75template <
size_t SIZE = 64>
class StrN {
78 char mInlineData[SIZE] = {0};
79 StringHolderPtr mHeapData;
86 template <
size_t M>
StrN(
const StrN<M> &other) { copy(other); }
87 StrN(
const char *str) {
88 size_t len = strlen(str);
90 if (len + 1 <= SIZE) {
91 memcpy(mInlineData, str, len + 1);
94 mHeapData = StringHolderPtr::New(str);
97 StrN(
const StrN &other) { copy(other); }
98 void copy(
const char *str) {
99 size_t len = strlen(str);
101 if (len + 1 <= SIZE) {
102 memcpy(mInlineData, str, len + 1);
105 if (mHeapData && !mHeapData->isShared()) {
107 mHeapData->copy(str, len);
111 mHeapData = StringHolderPtr::New(str);
114 StrN &operator=(
const StrN &other) {
118 template <
size_t M>
StrN &operator=(
const StrN<M> &other) {
124 bool operator==(
const StrN &other)
const {
125 return strcmp(c_str(), other.c_str()) == 0;
128 bool operator!=(
const StrN &other)
const {
129 return strcmp(c_str(), other.c_str()) != 0;
132 void copy(
const char* str,
size_t len) {
134 if (len + 1 <= SIZE) {
135 memcpy(mInlineData, str, len + 1);
138 mHeapData = StringHolderPtr::New(str, len);
142 template <
size_t M>
void copy(
const StrN<M> &other) {
143 size_t len = other.size();
144 if (len + 1 <= SIZE) {
145 memcpy(mInlineData, other.c_str(), len + 1);
148 if (other.mHeapData) {
149 mHeapData = other.mHeapData;
151 mHeapData = StringHolderPtr::New(other.c_str());
157 size_t capacity()
const {
158 return mHeapData ? mHeapData->capacity() : SIZE;
161 size_t write(
int n) {
163 StringFormatter::append(n, &dst);
164 return write(dst.c_str(), dst.size());
167 size_t write(
const uint8_t *data,
size_t n) {
168 const char *str =
reinterpret_cast<const char *
>(data);
169 return write(str, n);
172 size_t write(
const char *str,
size_t n) {
173 size_t newLen = mLength + n;
174 if (mHeapData && !mHeapData->isShared()) {
175 if (!mHeapData->hasCapacity(newLen)) {
176 mHeapData->grow(newLen * 3 / 2);
178 memcpy(mHeapData->data() + mLength, str, n);
180 mHeapData->data()[mLength] =
'\0';
183 if (newLen + 1 <= SIZE) {
184 memcpy(mInlineData + mLength, str, n);
186 mInlineData[mLength] =
'\0';
190 StringHolderPtr newData = StringHolderPtr::New(newLen);
192 memcpy(newData->data(), c_str(), mLength);
193 memcpy(newData->data() + mLength, str, n);
194 newData->data()[newLen] =
'\0';
202 size_t write(
char c) {
return write(&c, 1); }
204 size_t write(uint8_t c) {
205 const char *str =
reinterpret_cast<const char *
>(&c);
206 return write(str, 1);
213 size_t size()
const {
return mLength; }
214 size_t length()
const {
return mLength; }
215 const char *c_str()
const {
216 return mHeapData ? mHeapData->data() : mInlineData;
219 char *c_str_mutable() {
220 return mHeapData ? mHeapData->data() : mInlineData;
223 char &operator[](
size_t index) {
224 if (index >= mLength) {
225 static char dummy =
'\0';
228 return c_str_mutable()[index];
231 const char &operator[](
size_t index)
const {
232 if (index >= mLength) {
233 static char dummy =
'\0';
236 return c_str()[index];
239 bool empty()
const {
return mLength == 0; }
244 bool operator<(
const StrN &other)
const {
245 return strcmp(c_str(), other.c_str()) < 0;
248 template<
size_t M>
bool operator<(
const StrN<M> &other)
const {
249 return strcmp(c_str(), other.c_str()) < 0;
252 void reserve(
size_t newCapacity) {
254 if (newCapacity <= mLength) {
259 if (newCapacity + 1 <= SIZE) {
264 if (mHeapData && !mHeapData->isShared() && mHeapData->hasCapacity(newCapacity)) {
269 StringHolderPtr newData = StringHolderPtr::New(newCapacity);
272 memcpy(newData->data(), c_str(), mLength);
273 newData->data()[mLength] =
'\0';
278 void clear(
bool freeMemory =
false) {
280 if (freeMemory && mHeapData) {
287 int16_t find(
const char &value)
const {
288 for (
size_t i = 0; i < mLength; ++i) {
289 if (c_str()[i] == value) {
296 StrN substring(
size_t start,
size_t end)
const {
297 if (start >= mLength) {
307 out.copy(c_str() + start, end - start);
316 size_t end = mLength;
317 while (start < mLength && StringFormatter::isSpace(c_str()[start])) {
320 while (end > start && StringFormatter::isSpace(c_str()[end - 1])) {
323 return substring(start, end);
326 float toFloat()
const {
327 return StringFormatter::parseFloat(c_str(), mLength);
333 StringHolderPtr mData;