Skip to content

Commit

Permalink
0.4.0 - added some functions to work with strings
Browse files Browse the repository at this point in the history
  • Loading branch information
aster94 committed Sep 25, 2019
1 parent a892602 commit 22c3d6b
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 101 deletions.
273 changes: 188 additions & 85 deletions Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,125 +19,228 @@
template <class T1, class T2>
bool doEvery(T1 *start_time, T2 interval)
{
if (millis() > *start_time + interval)
{
*start_time = millis();
return true;
}
else
{
return false;
}
if (millis() > *start_time + interval)
{
*start_time = millis();
return true;
}
else
{
return false;
}
}

// Change the state of a group of pins
void pinModeGroup(uint8_t pins[], size_t len, uint8_t state)
{
for (uint8_t i = 0; i < len; i++)
{
pinMode(pins[i], state);
}
for (uint8_t i = 0; i < len; i++)
{
pinMode(pins[i], state);
}
}

// Write the state of a group of pins
void digitalWriteGroup(uint8_t pins[], size_t len, uint8_t state)
{
for (uint8_t i = 0; i < len; i++)
{
digitalWrite(pins[i], state);
}
for (uint8_t i = 0; i < len; i++)
{
digitalWrite(pins[i], state);
}
}

// Toggle the state of a pin
void digitalToggle(uint8_t pin)
{
digitalWrite(pin, !digitalRead(pin));
digitalWrite(pin, !digitalRead(pin));
}

// Toggle the state of a group of pins
void digitalToggleGroup(uint8_t pins[], size_t len)
{
for (uint8_t i = 0; i < len; i++)
{
digitalWrite(pins[i], !digitalRead(pins[i]));
}
for (uint8_t i = 0; i < len; i++)
{
digitalWrite(pins[i], !digitalRead(pins[i]));
}
}

// Echo between two serial ports, bi or mono directional
void echo(UniversalSerial *one, UniversalSerial *two, bool mono_directional = false)
{
if (one->available())
{
two->write(one->read());
}
if (mono_directional == false)
{
if (two->available())
{
one->write(two->read());
}
}
if (one->available())
{
two->write(one->read());
}
if (mono_directional == false)
{
if (two->available())
{
one->write(two->read());
}
}
}

// Print an array of any kind
template <class T>
void printArray(T array, size_t len, char delimiter[] = "\n", uint8_t formatter = DEC, bool invert = false, bool index = false, UniversalSerial *_port = &Serial)
{
if (len >= 65535)
{
_port->println("ARRAY TOO BIG");
}

if (invert == false)
{
for (uint16_t i = 0; i < len; i++)
{
if (index)
{
_port->print(i);
_port->print(": ");
}
_port->print(array[i], formatter);
if (i < len - 1)
{
_port->print(delimiter);
}
}
}
else
{
for (uint16_t i = len; i > 0; i--)
{
if (index)
{
_port->print(i - 1);
_port->print(": ");
}
_port->print(array[i - 1], formatter);
if (i > 1)
{
_port->print(delimiter);
}
}
}
_port->println();
if (len >= 65535)
{
_port->println("ARRAY TOO BIG");
}

if (invert == false)
{
for (uint16_t i = 0; i < len; i++)
{
if (index)
{
_port->print(i);
_port->print(": ");
}
_port->print(array[i], formatter);
if (i < len - 1)
{
_port->print(delimiter);
}
}
}
else
{
for (uint16_t i = len; i > 0; i--)
{
if (index)
{
_port->print(i - 1);
_port->print(": ");
}
_port->print(array[i - 1], formatter);
if (i > 1)
{
_port->print(delimiter);
}
}
}
_port->println();
}

// The following functions are useful to work with char array
// without loosing hours debugging memory leak

/**
* @brief Split a char array in sub strings
*
* @param dest_arr the 2D array where to save the substrings
* @param len_dest_arr a value where to store the number of substrings
* @param str the string to split
* @param the chars used as delimiters
* @return char** same as dest_arr
*/
char **stringSplit(char ***dest_arr, size_t *len_dest_arr, const char *str, const char *delimiters)
{
int str_len = strlen(str) + 1; // add null terminator
char str_copy[str_len]; // we work on a copy
strcpy(str_copy, str);

(*dest_arr) = (char **)malloc(sizeof(char *) * str_len); // over size

uint8_t counter = 0; // limited to 255 sub strings
char *token = strtok(str_copy, delimiters); // split until first token
while (token != nullptr)
{
(*dest_arr)[counter] = (char *)malloc(strlen(token) + 1); // add null terminator
strcpy((*dest_arr)[counter], token); // copy token to dest_array
token = strtok(NULL, delimiters); // continue splitting
counter++;
}

(*dest_arr) = (char **)realloc((*dest_arr), sizeof(char *) * counter); // reallocate the right amount of memory
*len_dest_arr = counter; // save size
return (*dest_arr);
}


/**
* @brief Check if a string ends with a given string
*
* @param The char* to to check
* @param The characters looked for
* @return true if char* ends with the given char
* @return false if char* don't ends with the given char
*/
bool stringEndWith(char *str, const char *suffix)
{
size_t strLen = strlen(str);
size_t suffixLen = strlen(suffix);
if (suffixLen <= strLen)
{
return strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
}
return 0;
}

/**
* @brief Check if a string start with a given string
*
* @param The char* to to check
* @param The characters looked for
* @return true if char* starts with the given char
* @return false if char* don't starts with the given char
*/
bool stringStartWith(char *str, const char *prefix)
{
size_t strLen = strlen(str);
size_t prefixLen = strlen(prefix);
if (prefixLen <= strLen)
{
return strncmp(str, prefix, prefixLen) == 0;
}
return 0;
}

// Split a cstring into token and get one of them
char *splitString(char str[], uint8_t index, char delimiter[] = " ")

/**
* @brief Cut a given string from start to end
*
* @param The char array to cut
* @param The starting point, accept also negative value
* @param The ending point, accept also negative value
* @return The resulting char array
*/
char* stringCut(const char* str, int8_t start, int8_t end)
{
uint8_t counter = 0;
char *token = strtok(str, delimiter);
while (token != NULL)
{
if (counter == index)
{
return token;
}
token = strtok(NULL, delimiter);
counter++;
}
return NULL;
//print << "Cutting: \"" << str << "\" from: " << (int) start << " to " << (int)end << "\n";
uint8_t len = strlen(str);
int8_t offset = start;

//print << "str len: " << (int)len << "\n";

if (end < 0) // start from the back
{
end = len + end;
//print << "new end: " << (int)end << "\n";
}
if (start <0) // start from the back
{
start = len + start;
//print << "new start: " << (int)start << "\n";
offset = start;
}
if (start > end || start == end) // return an empty char
{
//print << "what?\n";
return '\0';
}
if (end > len) // cut until the end
{
//print << "out\n";
end = len;
}

char* cutted = (char*) malloc (sizeof(char*) * (end-start)); // allocate the right amount of memory
strncpy(cutted,str+start,end-offset); // make the cut
cutted[end-start] = '\0'; // add null-terminator

return cutted;
}

#endif // Utilities_h
60 changes: 47 additions & 13 deletions examples/basic/basic.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
void setup()
{
Serial.begin(115200);
delay(1000);
delay(100);

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

// Print that group
// Print this group
printArray(group, LEN(group));

// Set their pinMode
Expand All @@ -33,17 +33,7 @@ void setup()
delay(500);
}

// Create a string
char str[] = "hello, this is a test";

// Split it and get the 4th part (starting from 0)
char *substring = splitString(str, 4, " ,");

// Print it
Serial.print("substring: ");
Serial.println(substring); // this will output "test"

// A more complex array for printArray
// Another array for printArray
int array[] = {1, 11, 89, 34, 9};

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

// If you have more then one serial (like Serial2 or SoftwareSerial) you can make an echo between them
//echo(&Serial, &Serial2);

// Now some examples of string manipulation

// The string we want to cute
const char *long_text = "This is a very\n\
long text that you want\n\
to divide in lines";

// Some values that we need to initialize
char **lines = nullptr;
size_t number_of_lines;

// Finally we can split the string
lines = stringSplit(&lines, &number_of_lines, long_text, "\n");

// Print it line by line
for (uint8_t n = 0; n < number_of_lines; n++)
{
Serial.println(lines[n]);
}

// Assign part of it to a new variable
char *second_line = lines[1];

// This way we delete the variable lines and the memory it was occupy
free(lines);

// Check if a string start with another
if (stringStartWith(second_line, "long"))
{
Serial.println("Yes it is!");
}

// Cut/substring a piece of text
second_line = stringCut(second_line, 0, -5);

Serial.print("2° line after cut: ");
Serial.println(second_line);

// Check if a string ends with another
if (!stringEndWith(second_line, "want"))
{
Serial.println("Too late, \"want\" was cutted!");
}
}

unsigned long task1, task2;
Expand Down
Loading

0 comments on commit 22c3d6b

Please sign in to comment.