An update:
After I finished writing SafeStrings, I was prompted to look at Arduino Strings more closely.
It turns out that by following a few guidelines you can successfully use Strings in your code.
On Uno and Mega2560 it turns out Strings are essentially bullet proof.
For other boards (with more memory) see the guide lines in my tutorial
Taming Arduino Strings
For the ESP32 / ESP8266 which uses Strings extensively in their Web support libraries, Taming Arduino Strings suggests a periodic automatic reboot and provides sample code to do that.
I am using that approach on a commercial project I am doing at the moment.
SafeStrings still has some advantages over Arduino Strings
Complete control over memory use
SafeStrings are a wrapper around a char [] that provides safety from buffer overruns and out of range indexing. Because SafeString uses a fixed char [], the memory usage is fixed when you create the SafeString and does not change. When you create global SafeStrings their memory usage is reported by the compiler so it is simpler to see how much SRAM your code is using. SafeStrings also use less memory because they don't need to convert “text” to a SafeString before using it in compare and indexOf functions.
Catches, flags and ignores Errors and prints a detailed message to help you fix the error
SafeString checks every one of its function calls for null pointers, buffer-overrun and out of range indexing. Function calls the would cause an error are ignored, ie the SafeString remains unchanged, and the error is flagged and a detailed error messge displayed that allows you to pin point the problem and fix it. SafeString also does not have the errors that are in Arduino String's code
Simple non-blocking Serial Readers
The Arduino String reader, Serial.readStringUntil () can block the loop waiting while waiting for data. While you can code non-blocking readers using Strings, the methods in the SafeString are simpler and have a number of advanced functions like tokenizing the input, non-blocking input timeouts, selectable echo of the input and a skipToDelimiter function to skip over un- wanted or partial input. The SafeString readers also count the number of chars read so you can check when an entire web response has been received.
Better number parsing methods
As noted above, the String toInt () method can give odd results. The SafeString toInt (int i), toLong (long l) etc, return true if the string is a valid number and updates the argument, otherwise they return false. The String toInt () method just returns 0 if the string is not a number and returns 5 for "5.9" and for "5a"
Easier to use with libraries
Third party libraries often return their text results as a char *. If you use Strings, you will be making a complete copy of the text when you assign the result to a String, using extra memory. On the other hand with SafeString, you can just wrap the char * in a SafeString without taking a copy and then safely parse and process the data.
More text manipulation functions
While Strings have startsWith, endsWith, indexOf, lastIndexOf, substring, replace and remove methods, SafeString has all of those methods plus a full set of print () methods to print to a SafeString and prefix (), startsWithIgnoreCase (), indexOfCharFrom () , removeBefore (), removeFrom (), removeLast (), stoken (), nextToken () and non-blocking readFrom (), writeTo (), read (), readUntil (), readUntilToken ()
The SafeString library also has a SafeStringStream class that lets you automate the testing of sketches that expect to process Stream data input.
There are also BufferedInput and BufferedOutput classes that provide larger input buffers and non-blocking Serial output. The non-blocking millisDelay timerclass and a loopTimer class are also included in the SafeString library.