Skip to content

Commit 22c3d6b

Browse files
committed
0.4.0 - added some functions to work with strings
1 parent a892602 commit 22c3d6b

File tree

4 files changed

+241
-101
lines changed

4 files changed

+241
-101
lines changed

Utilities.h

Lines changed: 188 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,125 +19,228 @@
1919
template <class T1, class T2>
2020
bool doEvery(T1 *start_time, T2 interval)
2121
{
22-
if (millis() > *start_time + interval)
23-
{
24-
*start_time = millis();
25-
return true;
26-
}
27-
else
28-
{
29-
return false;
30-
}
22+
if (millis() > *start_time + interval)
23+
{
24+
*start_time = millis();
25+
return true;
26+
}
27+
else
28+
{
29+
return false;
30+
}
3131
}
3232

3333
// Change the state of a group of pins
3434
void pinModeGroup(uint8_t pins[], size_t len, uint8_t state)
3535
{
36-
for (uint8_t i = 0; i < len; i++)
37-
{
38-
pinMode(pins[i], state);
39-
}
36+
for (uint8_t i = 0; i < len; i++)
37+
{
38+
pinMode(pins[i], state);
39+
}
4040
}
4141

4242
// Write the state of a group of pins
4343
void digitalWriteGroup(uint8_t pins[], size_t len, uint8_t state)
4444
{
45-
for (uint8_t i = 0; i < len; i++)
46-
{
47-
digitalWrite(pins[i], state);
48-
}
45+
for (uint8_t i = 0; i < len; i++)
46+
{
47+
digitalWrite(pins[i], state);
48+
}
4949
}
5050

5151
// Toggle the state of a pin
5252
void digitalToggle(uint8_t pin)
5353
{
54-
digitalWrite(pin, !digitalRead(pin));
54+
digitalWrite(pin, !digitalRead(pin));
5555
}
5656

5757
// Toggle the state of a group of pins
5858
void digitalToggleGroup(uint8_t pins[], size_t len)
5959
{
60-
for (uint8_t i = 0; i < len; i++)
61-
{
62-
digitalWrite(pins[i], !digitalRead(pins[i]));
63-
}
60+
for (uint8_t i = 0; i < len; i++)
61+
{
62+
digitalWrite(pins[i], !digitalRead(pins[i]));
63+
}
6464
}
6565

6666
// Echo between two serial ports, bi or mono directional
6767
void echo(UniversalSerial *one, UniversalSerial *two, bool mono_directional = false)
6868
{
69-
if (one->available())
70-
{
71-
two->write(one->read());
72-
}
73-
if (mono_directional == false)
74-
{
75-
if (two->available())
76-
{
77-
one->write(two->read());
78-
}
79-
}
69+
if (one->available())
70+
{
71+
two->write(one->read());
72+
}
73+
if (mono_directional == false)
74+
{
75+
if (two->available())
76+
{
77+
one->write(two->read());
78+
}
79+
}
8080
}
8181

8282
// Print an array of any kind
8383
template <class T>
8484
void printArray(T array, size_t len, char delimiter[] = "\n", uint8_t formatter = DEC, bool invert = false, bool index = false, UniversalSerial *_port = &Serial)
8585
{
86-
if (len >= 65535)
87-
{
88-
_port->println("ARRAY TOO BIG");
89-
}
90-
91-
if (invert == false)
92-
{
93-
for (uint16_t i = 0; i < len; i++)
94-
{
95-
if (index)
96-
{
97-
_port->print(i);
98-
_port->print(": ");
99-
}
100-
_port->print(array[i], formatter);
101-
if (i < len - 1)
102-
{
103-
_port->print(delimiter);
104-
}
105-
}
106-
}
107-
else
108-
{
109-
for (uint16_t i = len; i > 0; i--)
110-
{
111-
if (index)
112-
{
113-
_port->print(i - 1);
114-
_port->print(": ");
115-
}
116-
_port->print(array[i - 1], formatter);
117-
if (i > 1)
118-
{
119-
_port->print(delimiter);
120-
}
121-
}
122-
}
123-
_port->println();
86+
if (len >= 65535)
87+
{
88+
_port->println("ARRAY TOO BIG");
89+
}
90+
91+
if (invert == false)
92+
{
93+
for (uint16_t i = 0; i < len; i++)
94+
{
95+
if (index)
96+
{
97+
_port->print(i);
98+
_port->print(": ");
99+
}
100+
_port->print(array[i], formatter);
101+
if (i < len - 1)
102+
{
103+
_port->print(delimiter);
104+
}
105+
}
106+
}
107+
else
108+
{
109+
for (uint16_t i = len; i > 0; i--)
110+
{
111+
if (index)
112+
{
113+
_port->print(i - 1);
114+
_port->print(": ");
115+
}
116+
_port->print(array[i - 1], formatter);
117+
if (i > 1)
118+
{
119+
_port->print(delimiter);
120+
}
121+
}
122+
}
123+
_port->println();
124+
}
125+
126+
// The following functions are useful to work with char array
127+
// without loosing hours debugging memory leak
128+
129+
/**
130+
* @brief Split a char array in sub strings
131+
*
132+
* @param dest_arr the 2D array where to save the substrings
133+
* @param len_dest_arr a value where to store the number of substrings
134+
* @param str the string to split
135+
* @param the chars used as delimiters
136+
* @return char** same as dest_arr
137+
*/
138+
char **stringSplit(char ***dest_arr, size_t *len_dest_arr, const char *str, const char *delimiters)
139+
{
140+
int str_len = strlen(str) + 1; // add null terminator
141+
char str_copy[str_len]; // we work on a copy
142+
strcpy(str_copy, str);
143+
144+
(*dest_arr) = (char **)malloc(sizeof(char *) * str_len); // over size
145+
146+
uint8_t counter = 0; // limited to 255 sub strings
147+
char *token = strtok(str_copy, delimiters); // split until first token
148+
while (token != nullptr)
149+
{
150+
(*dest_arr)[counter] = (char *)malloc(strlen(token) + 1); // add null terminator
151+
strcpy((*dest_arr)[counter], token); // copy token to dest_array
152+
token = strtok(NULL, delimiters); // continue splitting
153+
counter++;
154+
}
155+
156+
(*dest_arr) = (char **)realloc((*dest_arr), sizeof(char *) * counter); // reallocate the right amount of memory
157+
*len_dest_arr = counter; // save size
158+
return (*dest_arr);
159+
}
160+
161+
162+
/**
163+
* @brief Check if a string ends with a given string
164+
*
165+
* @param The char* to to check
166+
* @param The characters looked for
167+
* @return true if char* ends with the given char
168+
* @return false if char* don't ends with the given char
169+
*/
170+
bool stringEndWith(char *str, const char *suffix)
171+
{
172+
size_t strLen = strlen(str);
173+
size_t suffixLen = strlen(suffix);
174+
if (suffixLen <= strLen)
175+
{
176+
return strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
177+
}
178+
return 0;
179+
}
180+
181+
/**
182+
* @brief Check if a string start with a given string
183+
*
184+
* @param The char* to to check
185+
* @param The characters looked for
186+
* @return true if char* starts with the given char
187+
* @return false if char* don't starts with the given char
188+
*/
189+
bool stringStartWith(char *str, const char *prefix)
190+
{
191+
size_t strLen = strlen(str);
192+
size_t prefixLen = strlen(prefix);
193+
if (prefixLen <= strLen)
194+
{
195+
return strncmp(str, prefix, prefixLen) == 0;
196+
}
197+
return 0;
124198
}
125199

126-
// Split a cstring into token and get one of them
127-
char *splitString(char str[], uint8_t index, char delimiter[] = " ")
200+
201+
/**
202+
* @brief Cut a given string from start to end
203+
*
204+
* @param The char array to cut
205+
* @param The starting point, accept also negative value
206+
* @param The ending point, accept also negative value
207+
* @return The resulting char array
208+
*/
209+
char* stringCut(const char* str, int8_t start, int8_t end)
128210
{
129-
uint8_t counter = 0;
130-
char *token = strtok(str, delimiter);
131-
while (token != NULL)
132-
{
133-
if (counter == index)
134-
{
135-
return token;
136-
}
137-
token = strtok(NULL, delimiter);
138-
counter++;
139-
}
140-
return NULL;
211+
//print << "Cutting: \"" << str << "\" from: " << (int) start << " to " << (int)end << "\n";
212+
uint8_t len = strlen(str);
213+
int8_t offset = start;
214+
215+
//print << "str len: " << (int)len << "\n";
216+
217+
if (end < 0) // start from the back
218+
{
219+
end = len + end;
220+
//print << "new end: " << (int)end << "\n";
221+
}
222+
if (start <0) // start from the back
223+
{
224+
start = len + start;
225+
//print << "new start: " << (int)start << "\n";
226+
offset = start;
227+
}
228+
if (start > end || start == end) // return an empty char
229+
{
230+
//print << "what?\n";
231+
return '\0';
232+
}
233+
if (end > len) // cut until the end
234+
{
235+
//print << "out\n";
236+
end = len;
237+
}
238+
239+
char* cutted = (char*) malloc (sizeof(char*) * (end-start)); // allocate the right amount of memory
240+
strncpy(cutted,str+start,end-offset); // make the cut
241+
cutted[end-start] = '\0'; // add null-terminator
242+
243+
return cutted;
141244
}
142245

143246
#endif // Utilities_h

examples/basic/basic.ino

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
void setup()
44
{
55
Serial.begin(115200);
6-
delay(1000);
6+
delay(100);
77

88
// Create a group of pins
99
byte group[] = {LED_BUILTIN, 12, 11, 10, 9, 8};
1010

11-
// Print that group
11+
// Print this group
1212
printArray(group, LEN(group));
1313

1414
// Set their pinMode
@@ -33,17 +33,7 @@ void setup()
3333
delay(500);
3434
}
3535

36-
// Create a string
37-
char str[] = "hello, this is a test";
38-
39-
// Split it and get the 4th part (starting from 0)
40-
char *substring = splitString(str, 4, " ,");
41-
42-
// Print it
43-
Serial.print("substring: ");
44-
Serial.println(substring); // this will output "test"
45-
46-
// A more complex array for printArray
36+
// Another array for printArray
4737
int array[] = {1, 11, 89, 34, 9};
4838

4939
// Print the array as decimal values with a ", " between the items and invert them (from the last to the first)
@@ -57,6 +47,50 @@ void setup()
5747

5848
// If you have more then one serial (like Serial2 or SoftwareSerial) you can make an echo between them
5949
//echo(&Serial, &Serial2);
50+
51+
// Now some examples of string manipulation
52+
53+
// The string we want to cute
54+
const char *long_text = "This is a very\n\
55+
long text that you want\n\
56+
to divide in lines";
57+
58+
// Some values that we need to initialize
59+
char **lines = nullptr;
60+
size_t number_of_lines;
61+
62+
// Finally we can split the string
63+
lines = stringSplit(&lines, &number_of_lines, long_text, "\n");
64+
65+
// Print it line by line
66+
for (uint8_t n = 0; n < number_of_lines; n++)
67+
{
68+
Serial.println(lines[n]);
69+
}
70+
71+
// Assign part of it to a new variable
72+
char *second_line = lines[1];
73+
74+
// This way we delete the variable lines and the memory it was occupy
75+
free(lines);
76+
77+
// Check if a string start with another
78+
if (stringStartWith(second_line, "long"))
79+
{
80+
Serial.println("Yes it is!");
81+
}
82+
83+
// Cut/substring a piece of text
84+
second_line = stringCut(second_line, 0, -5);
85+
86+
Serial.print("2° line after cut: ");
87+
Serial.println(second_line);
88+
89+
// Check if a string ends with another
90+
if (!stringEndWith(second_line, "want"))
91+
{
92+
Serial.println("Too late, \"want\" was cutted!");
93+
}
6094
}
6195

6296
unsigned long task1, task2;

0 commit comments

Comments
 (0)