CStringArray

Introduction

This is a class to manage a double NUL-terminated list of strings, such as "one\0two\0three\0".

It’s similar in operation to Vector<String>, but more memory-efficient as all the data is stored in a single String object. (CStringArray is a subclass of String.)

You can see some examples in Sming/Core/DateTime.cpp and Sming/Core/Data/WebConstants.cpp.

Background

Each value in the sequence is terminated by a NUL character \0. For clarity, placing one string per line is suggested:

// ["one", "two", "three"]
CStringArray csa = F(
   "one\0"
   "two\0"
   "three\0"
);

Note use of the F() macro. Assignments require a length because of the NUL characters, so this won’t work as expected:

// ["one"]
CStringArray csa =
   "one\0"
   "two\0"
   "three\0";

When assigning sequences, the final NUL separator may be omitted (it will be added automatically):

// ["one", "two", "three"]
CStringArray csa = F(
   "one\0"
   "two\0"
   "three"
);

Sequences may contain empty values, so this example contains four values:

// ["one", "two", "three", ""]
CStringArray csa = F(
   "one\0"
   "two\0"
   "three\0"
   "\0"
);

Adding strings

Elements can be added using standard concatenation operators:

CStringArray arr;
arr += "string1";
arr += 12;
arr += 5.4;
arr += F("data");

Be mindful that each call may require a heap re-allocation, so consider estimating or calculating the required space and using String::reserve():

CStringArray arr;
arr.reserve(250);
// now add content

Use with FlashString

You can use a single FlashString containing these values and load them all at the same time into a CStringArray:

DEFINE_FSTR_LOCAL(fstr_list,
   "a\0"
   "b\0"
   "c\0"
   "d\0"
   "e\0"
);

CStringArray list(fstr_list);
for(unsigned i = 0; i < list.count(); ++i) {
   debug_i("list[%u] = '%s'", i, list[i]);
}

Note

The entire FlashString is loaded into RAM so better suited for occasional lookups or if instantiated outside of a loop.

You may find FSTR::Array, FSTR::Vector or FSTR::Map more appropriate. See FlashString for details.

Iterator support

Looping by index is slow because the array must be scanned from the start for each access. Iterators are simpler to use and much more efficient:

for(auto s: list) {
   debug_i("'%s'", s);
}

For more complex operations:

CStringArray::Iterator pos;
for(auto it = list.begin(); it != list.end(); ++it) {
   debug_i("list[%u] = '%s' @ %u", it.index(), *it, it.offset());
   // Can use direct comparison with const char* or String
   if(it == "c") {
      pos = it; // Note position
   }
}

if(pos) {
   debug_i("Item '%s' found at index %u, offset %u", pos.str(), pos.index(), pos.offset());
} else {
   debug_i("Item not found");
}

Pushing and popping

CStringArray can be used as a simple FIFO or stack using push/pop methods. Behaviour is similar to STL deque, except pop methods also return a value.

STACK:

CStringArray csa;
csa.pushBack("first value");
csa.pushBack("second value");
String popStack = csa.popBack(); // "second value"

FIFO:

CStringArray csa;
csa.pushBack("first value");
csa.pushBack("second value");
String deque = csa.popFront(); // "first value"

Note that popping values does not perform any memory de-allocation.

Comparison with Vector<String>

Advantages

More memory efficient Uses only a single heap allocation (assuming content is passed to constructor) Useful for simple lookups, e.g. mapping enumerated values to strings

Disadvantages

Slower. Items must be iterated using multiple strlen() calls Ordering and insertions / deletions not supported

API Documentation

class CStringArray : private String

Class to manage a double null-terminated list of strings, such as “one\0two\0three\0”.

Concatenation operators

template<typename T>
inline CStringArray &operator+=(T value)

Append numbers, etc. to the array.

Parameters

value – char, int, float, etc. as supported by String

Public Functions

bool add(const char *str, int length = -1)

Append a new string (or array of strings) to the end of the array.

Note

If str contains any NUL characters it will be handled as an array

Parameters
  • str

  • length – Length of new string in array (default is length of str)

Returns

bool – false on memory allocation error

inline bool add(const String &str)

Append a new string (or array of strings) to the end of the array.

Note

If str contains any NUL characters it will be handled as an array

Parameters

str

Returns

bool – false on memory allocation error

int indexOf(const char *str, bool ignoreCase = true) const

Find the given string and return its index.

Note

Comparison is not case-sensitive

Parameters
  • strString to find

  • ignoreCase – Whether search is case-sensitive or not

Returns

int – index of given string, -1 if not found

inline int indexOf(const String &str, bool ignoreCase = true) const

Find the given string and return its index.

Note

Comparison is not case-sensitive

Parameters
  • strString to find

  • ignoreCase – Whether search is case-sensitive or not

Returns

int – index of given string, -1 if not found

inline bool contains(const char *str, bool ignoreCase = true) const

Check if array contains a string.

Note

Search is not case-sensitive

Parameters
  • strString to search for

  • ignoreCase – Whether search is case-sensitive or not

Returns

bool – True if string exists in array

inline bool contains(const String &str, bool ignoreCase = true) const

Check if array contains a string.

Note

Search is not case-sensitive

Parameters
  • strString to search for

  • ignoreCase – Whether search is case-sensitive or not

Returns

bool – True if string exists in array

const char *getValue(unsigned index) const

Get string at the given position.

Parameters

index – 0-based index of string to obtain

Returns

const – char* nullptr if index is not valid

inline const char *operator[](unsigned index) const

Get string at the given position.

Parameters

index – 0-based index of string to obtain

Returns

const – char* nullptr if index is not valid

inline const char *front() const

Get first value in array, null if empty.

bool pushFront(const char *str)

Insert item at start of array.

Parameters

str – Item to insert

Returns

bool – false on memory error

String popFront()

Pop first item from array (at index 0)

Returns

String – null if array is empty

const char *back() const

Get last item in array, null if empty.

inline bool pushBack(const char *str)

Add item to end of array.

Parameters

str – Item to add

Returns

bool – false on memory error

String popBack()

Pop last item from array.

Returns

String – null if array is empty

inline void clear()

Empty the array.

unsigned count() const

Get quantity of strings in array.

Returns

unsigned – Quantity of strings

class Iterator