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+=(const 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)
- Return values:
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 –
- Return values:
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:
str – String to find
ignoreCase – Whether search is case-sensitive or not
- Return values:
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:
str – String to find
ignoreCase – Whether search is case-sensitive or not
- Return values:
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:
str – String to search for
ignoreCase – Whether search is case-sensitive or not
- Return values:
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:
str – String to search for
ignoreCase – Whether search is case-sensitive or not
- Return values:
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
- Return values:
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
- Return values:
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
- Return values:
bool – false on memory error
-
String popFront()
Pop first item from array (at index 0)
- Return values:
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
- Return values:
bool – false on memory error
-
inline void clear()
Empty the array.
-
unsigned count() const
Get quantity of strings in array.
- Return values:
unsigned – Quantity of strings
-
String join(const String &separator = ",") const
Get contents of array as delimited string.
- Parameters:
separator – What to join elements with
- Return values:
String – e.g. CStringArray(F(“a\0b\0c”)).join() returns “a,b,c”
-
bool reserve(size_t size)
Pre-allocate String memory.
On failure, the String is left unchanged. reserve(0), if successful, will validate an invalid string (i.e., “if (s)” will be true afterwards)
- Parameters:
size –
- Return values:
bool – true on success, false on failure
-
inline const char *c_str() const
Get a constant (un-modifiable) pointer to String content.
- Return values:
const – char* Always valid, even for a null string
-
bool endsWith(char suffix) const
Compare the end of a String.
- Parameters:
suffix –
- Return values:
bool – true on match
-
bool endsWith(const String &suffix) const
Compare the end of a String.
- Parameters:
suffix –
- Return values:
bool – true on match
-
size_t getBytes(unsigned char *buf, size_t bufsize, size_t index = 0) const
Read contents of a String into a buffer.
Note
Returned data always nul terminated so buffer size needs to take this into account
- Parameters:
buf – buffer to write data
bufsize – size of buffer in bytes
index – offset to start
- Return values:
unsigned – number of bytes copied, excluding nul terminator
-
inline bool startsWith(const String &prefix) const
Compare the start of a String Comparison is case-sensitive, must match exactly.
- Parameters:
prefix –
- Return values:
bool – true on match
-
bool startsWith(const String &prefix, size_t offset) const
Compare a string portion.
mis-named as does not necessarily compare from start
Note
Comparison is case-sensitive, must match exactly
- Parameters:
prefix –
offset – Index to start comparison at
- Return values:
bool – true on match
-
inline void toCharArray(char *buf, size_t bufsize, size_t index = 0) const
Read contents of String into a buffer.
See also
See
getBytes()
-
class Iterator
-
template<typename T>