2015-08-13 12:56:50 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
2015-10-06 23:31:21 +00:00
|
|
|
#if defined(CIRCUIT_OS)
|
|
|
|
#include <kstdlib.h>
|
|
|
|
#else
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
// itoa is not ANSI C
|
|
|
|
/**
|
|
|
|
* C++ version 0.4 char* style "itoa":
|
|
|
|
* Written by Lukás Chmela
|
|
|
|
* Released under GPLv3.
|
|
|
|
*/
|
|
|
|
static inline char* itoa(int value, char* result, int base) {
|
|
|
|
// check that the base if valid
|
|
|
|
if (base < 2 || base > 36) { *result = '\0'; return result; }
|
|
|
|
|
|
|
|
char* ptr = result, *ptr1 = result, tmp_char;
|
|
|
|
int tmp_value;
|
|
|
|
|
|
|
|
do {
|
|
|
|
tmp_value = value;
|
|
|
|
value /= base;
|
|
|
|
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
|
|
|
|
} while ( value );
|
|
|
|
|
|
|
|
// Apply negative sign
|
|
|
|
if (tmp_value < 0) *ptr++ = '-';
|
|
|
|
*ptr-- = '\0';
|
|
|
|
while(ptr1 < ptr) {
|
|
|
|
tmp_char = *ptr;
|
|
|
|
*ptr--= *ptr1;
|
|
|
|
*ptr1++ = tmp_char;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-06 15:49:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define KER_STRING_AVAILABLE
|
2015-08-13 12:56:50 +00:00
|
|
|
|
|
|
|
namespace ker
|
|
|
|
{
|
|
|
|
class String
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
uint8_t *mText;
|
|
|
|
size_t mLength;
|
|
|
|
public:
|
|
|
|
String() :
|
|
|
|
mText(nullptr),
|
|
|
|
mLength(0)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-08-13 15:23:11 +00:00
|
|
|
String(const String &other) :
|
|
|
|
String(other.mText, other.mLength)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
String(String &&other) :
|
|
|
|
mText(other.mText),
|
|
|
|
mLength(other.mLength)
|
|
|
|
{
|
|
|
|
other.mText = nullptr;
|
|
|
|
other.mLength = 0;
|
2015-08-14 15:12:08 +00:00
|
|
|
}
|
2015-08-13 15:23:11 +00:00
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
String(const char *text) :
|
|
|
|
mText(nullptr),
|
|
|
|
mLength(0)
|
2015-08-13 15:23:11 +00:00
|
|
|
{
|
2015-08-13 18:12:09 +00:00
|
|
|
this->copyFrom(reinterpret_cast<const uint8_t*>(text), strlen(text));
|
2015-08-13 12:56:50 +00:00
|
|
|
}
|
|
|
|
|
2015-10-06 23:31:21 +00:00
|
|
|
String(const char *bytes, size_t length) :
|
|
|
|
String(reinterpret_cast<const uint8_t *>(bytes), length)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
String(const uint8_t *bytes, size_t length) :
|
2015-08-13 18:12:09 +00:00
|
|
|
mText(nullptr),
|
2015-08-13 12:56:50 +00:00
|
|
|
mLength(length)
|
|
|
|
{
|
2015-08-13 18:12:09 +00:00
|
|
|
this->copyFrom(bytes, length);
|
2015-08-13 12:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~String()
|
|
|
|
{
|
2015-08-13 15:23:11 +00:00
|
|
|
if(this->mText != nullptr) {
|
2015-08-17 13:38:19 +00:00
|
|
|
free(this->mText);
|
2015-08-13 15:23:11 +00:00
|
|
|
}
|
2015-08-13 12:56:50 +00:00
|
|
|
}
|
|
|
|
|
2015-10-06 23:31:21 +00:00
|
|
|
uint8_t at(size_t index) const
|
|
|
|
{
|
|
|
|
return this->mText[index];
|
|
|
|
}
|
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
size_t length() const
|
|
|
|
{
|
|
|
|
return this->mLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool equals(const String &other) const
|
|
|
|
{
|
|
|
|
if(this->mLength != other.mLength) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-08-13 18:12:09 +00:00
|
|
|
return memcmp(this->mText, other.mText, this->mLength) == 0;
|
2015-08-13 12:56:50 +00:00
|
|
|
}
|
|
|
|
|
2015-08-21 15:32:48 +00:00
|
|
|
bool equals(const char *other) const
|
|
|
|
{
|
|
|
|
return strcmp(this->str(), other) == 0;
|
|
|
|
}
|
|
|
|
|
2015-08-14 15:12:08 +00:00
|
|
|
String append(const String &other) const
|
|
|
|
{
|
|
|
|
uint8_t *data = (uint8_t*)malloc(this->mLength + other.mLength);
|
|
|
|
memcpy(&data[0], this->mText, this->mLength);
|
|
|
|
memcpy(&data[this->mLength], other.mText, other.mLength);
|
|
|
|
String cat(data, this->mLength + other.mLength);
|
|
|
|
free(data);
|
|
|
|
return cat;
|
|
|
|
}
|
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
const uint8_t *text() const
|
|
|
|
{
|
|
|
|
static const uint8_t empty[] = { 0 };
|
|
|
|
if(this->mText != nullptr) {
|
|
|
|
return this->mText;
|
|
|
|
} else {
|
|
|
|
return empty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *str() const
|
|
|
|
{
|
|
|
|
return (char*)this->text();
|
|
|
|
}
|
|
|
|
|
|
|
|
operator const uint8_t *() const
|
|
|
|
{
|
|
|
|
return this->text();
|
|
|
|
}
|
|
|
|
|
|
|
|
operator const char *() const
|
|
|
|
{
|
|
|
|
return this->str();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t & operator [](size_t index)
|
|
|
|
{
|
|
|
|
return this->mText[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t & operator [](size_t index) const
|
|
|
|
{
|
|
|
|
return this->mText[index];
|
|
|
|
}
|
|
|
|
|
2015-08-16 21:40:34 +00:00
|
|
|
String & operator = (const String &other)
|
|
|
|
{
|
|
|
|
this->copyFrom(other.mText, other.mLength);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
bool operator ==(const String &other) const
|
|
|
|
{
|
|
|
|
return this->equals(other);
|
|
|
|
}
|
|
|
|
|
2015-08-21 15:32:48 +00:00
|
|
|
bool operator ==(const char *other) const
|
|
|
|
{
|
|
|
|
return this->equals(other);
|
|
|
|
}
|
|
|
|
|
2015-08-13 12:56:50 +00:00
|
|
|
bool operator !=(const String &other) const
|
|
|
|
{
|
|
|
|
return !this->equals(other);
|
|
|
|
}
|
2015-08-16 21:40:34 +00:00
|
|
|
|
2015-08-21 15:32:48 +00:00
|
|
|
bool operator !=(const char *other) const
|
|
|
|
{
|
|
|
|
return !this->equals(other);
|
|
|
|
}
|
|
|
|
|
2015-08-16 21:40:34 +00:00
|
|
|
String operator +(const String &other) const
|
|
|
|
{
|
|
|
|
return this->append(other);
|
|
|
|
}
|
|
|
|
|
2015-08-13 18:12:09 +00:00
|
|
|
private:
|
|
|
|
void copyFrom(const uint8_t *bytes, size_t length)
|
|
|
|
{
|
|
|
|
if(this->mText != nullptr) {
|
2015-08-17 18:04:14 +00:00
|
|
|
free(this->mText);
|
|
|
|
}
|
2015-08-13 18:12:09 +00:00
|
|
|
this->mText = (uint8_t*)malloc(length + 1);
|
|
|
|
memcpy(this->mText, bytes, length);
|
|
|
|
this->mLength = length;
|
|
|
|
this->mText[this->mLength] = 0; // last byte is always 0
|
|
|
|
}
|
2015-08-16 21:40:34 +00:00
|
|
|
public:
|
|
|
|
static String concat(const String &lhs, const String &rhs)
|
|
|
|
{
|
|
|
|
return lhs.append(rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static String fromNumber(int32_t number, int radix = 10)
|
|
|
|
{
|
|
|
|
static char buffer[64];
|
|
|
|
itoa(number, buffer, radix);
|
|
|
|
return String(buffer);
|
|
|
|
}
|
2015-10-06 15:49:36 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-10-07 01:43:23 +00:00
|
|
|
static String from(const T &);
|
2015-08-13 12:56:50 +00:00
|
|
|
};
|
2015-08-14 15:12:08 +00:00
|
|
|
|
|
|
|
|
2015-10-06 15:49:36 +00:00
|
|
|
static inline String operator + (const char *lhs, const String &rhs)
|
2015-08-14 15:12:08 +00:00
|
|
|
{
|
|
|
|
return String::concat(lhs, rhs);
|
|
|
|
}
|
|
|
|
|
2015-10-06 15:49:36 +00:00
|
|
|
static inline String operator + (const String &lhs, const char *rhs)
|
2015-08-14 15:12:08 +00:00
|
|
|
{
|
|
|
|
return String::concat(lhs, rhs);
|
|
|
|
}
|
2015-08-13 12:56:50 +00:00
|
|
|
};
|