I would like to offer the SafeString library,
https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html,
I have developed, for inclusion in the Arduino core as an
alternative to the current String class (WString.cpp)
The current string processing options in Arduino are C character arrays (using strcat, srtcpy etc), which are a major source of program crashes, and the Arduino standard String class (contained in WString.cpp/.h files) which leads to program failure due to memory fragmentation and excessive memory usage, and is slower and contains bugs.
Both Sparkfun and Adafruit advise
against using the Arduino String class.
Sparkfun's
comment on the String class is “The String method (capital
'S') in Arduino uses a large amount of memory and tends to cause
problems in larger scale projects. ‘S’trings should be strongly
avoided in libraries.
Adafruit's comment on the String class is “In
most usages, lots of other little String objects are used
temporarily as you perform these (String) operations, forcing
the new string allocation to a new area of the heap and leaving
a big hole where the previous one was (memory fragmentation). “
SafeStrings have the following features:-
SafeStrings are easy to debug.
SafeStrings provide detailed error messages, including the name
of SafeString in question, to help you get your program running
correctly.
SafeStrings are safe and robust. SafeStrings never cause
reboots and are always in a valid usable state, even if your
code passes null pointers or '\0' arguments or exceeds the
available capacity of the SafeString.
SafeString programs run forever. SafeStrings completely
avoid memory fragmentation which will eventually cause your
program to fail and never makes extra copies when passed as
arguments.
SafeStrings are faster. SafeStrings do not create multiple copies or short
lived objects nor do they do unnecessary copying of the data.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/4c1834b8-5007-5b0c-a218-073ff7fae6f1%40forward.com.au.
>> whether it works across all platforms I believe it does, nothing fancy here. >>it might be nice if it had the same syntax and class name as the existing class. Unfortunately the syntax, while very similar, is not identical. A number of changes were necessary to make SafeStrings user proof. The differences are detailed in the tutorial https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html The most noticeable ones are:- To create a SafeString you need to use a macro, either at the global or method local level. createSafeString(msgStr, 5); // a SafeString called msgStr with space for 5 chars createSafeString(msgStr, 10, "A0"); // space for 10 chars and initialize with "A0" createSafeString macro creates the char array, of the requested size, and wraps it in a SafeString object, msgStr e.g. it expands to char msgStr_SAFEBUFFER[10+1]; // add 1 for terminating '\0' SafeString msgStr(sizeof(msgStr _SAFEBUFFER),msgStr _SAFEBUFFER,"A0","msgStr"); // adds the object name, msgStr, for error messages and debugging testStr1 = "a" + 10; // is not supported because it would create temporary objects. Use instead testStr1 = "a"; testStr1 += 10; concat() returns a SafeString& (not a bool) so you can chain concats e.g. testStr1.concat('a').concat(10); str[2] = .. is not supported because the '\0' error cannot be caught. In SafeStrings use setCharAt( ) instead. In WString str[2] = '\0'; results in str having an invalid internal state, i.e. str.length() != strlen(str.c_str()) SafeStrings are ALWAYS valid. If an operation fails the SafeString is left unchanged and an error message is output (if setOutput( ) has been called) String to number conversions actually check for a valid number and return false if invalid. The converted number is returned in the arg. e.g. createSafeString(str, 7, " 5.3.6 "); float f = 0.0; bool rtn = str.toFloat(f); will return false and leave f unchanged In WString f = str.toFloat() returns 5.3 and if it returns 0.0 you cannot tell if the string was '0.0' or '0.0a' or 'abc' IndexOf type methods return a size_t type, i.e. always >= 0, so tests for char found idx need to be changed to idx < str.length() // char found In WString -1 (int) is returned for the idx if the char not found void test(SafeString s); is not supported because to support it would require creating a complete copy the string. Arguments must be references, SafeString& If you try to call that method, then you get the compiler error message SafeString(const SafeString& other ); // You must declare SafeStrings function arguments as a reference, SafeString&, e.g. void test(SafeString& strIn) Extra SafeString methods:- stoken() indexes a SafeString into tokens via delimiters, nextToken() tokenizes and removes one token at a time prefix() and -= operator adds to the front of a SafeString, non-blocking read(Stream&) and readUntil(Stream&) SafeString implements the Print interface so you can add append text by calling the well know print methods on a SafeString object. This gives you all the print formatting options. SafeString::setOutput(Print&); enables detailed error messages and says where to send them. The debug() method dumps the SafeString to the set output. SafeString::setVerbose(false); suppresses printing the SaftString's contents in error msgs and debug() output commenting out the setOutput( ) statement turns off all error messages and debug. Error checks are still performed and the SafeStrings are still always valid, just no messages. Commenting out a define in SafeString.h removes all the error message code, but not the error checks, for small footprint. I think String should be retained but deprecated and something like SafeString be included in the core as the preferred alternative.
SafeStrings are safe and robust. SafeStrings never cause reboots and are always in a valid usable state
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/9d5b76d9-77f9-7634-8e12-153a24850b27%40pjrc.com.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/b18b973d-eb64-349c-2f9d-d392659e7cce%40forward.com.au.
This is not valid code.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/CAMy-CpSEmORy36h17MZiNXBKzyqdp8QogRU5H4QhvhNwEXihhA%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/c59d496c-d788-bcbf-7f62-3dddbcbbbfea%40pjrc.com.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/faaa93c5-43a5-f3c5-2bee-3a6fd9cd0bf7%40forward.com.au.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/b3857d72-93ab-6546-df40-c10dc82bce5f%40forward.com.au.
To unsubscribe from this group and stop receiving emails from it, send an email to devel...@arduino.cc.
I think that the issue is not in SafeString:- myMessage returns a reference to a stack variable in your SafeString example- myMessage returns a value in your String exampleThese are definitely not the same things. The bug is in your example ;-) , not in SafeStrin.
// createSafeString(str, 40, "test");// expands in the pre-processor to// char str_SAFEBUFFER[40+1];// SafeString str(sizeof(str_SAFEBUFFER),str_SAFEBUFFER,"test","str”);
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
To view this discussion on the web visit https://groups.google.com/a/arduino.cc/d/msgid/developers/2C94D3C3-7CF1-47FF-946C-40C2D50CB283%40me.com.
| char buff[150]; |
| |
V2.0.1 of the SafeString library has been released and is available from the Arduino Library manager. The tutorial at https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html, has been updated.
V2 adds wrapping of existing char* and char[] data in SafeStrings
so they can be safely worked on and the changes reflected directly
in the underlying char[], thus avoiding the need to pass
SafeString references as arguments and to more easily integrate
with third party libraries.
V2 also add typing short cuts for the macros, cSF() for
createSafeString(), cSFA() for createSafeStringFromCharArray() ,
cSFP() for createSafeStringFromCharPtr and cSFPS() for
createSafeStringFromCharPtrWithSize()
The SafeString_OBD.ino example parses OBD data, supplied from a third party library, and illustrates cSFA(), cSFP() and cSFPS( ). Wrapping a char* in a SafeString makes it easy to process char* args. Wrapping a char* with specified capacity, or wrapping a char[], makes it easy to build results using SafeStrings
The SafeString_ReadFrom_WriteTo.ino example
shows how to setup method 'static' SafeStrings variables.
The library and tutorial include multiple examples sketches for
parsing commands from c-strings, Arduino Monitor or telnet,
including processing of backspaces and auto processing after a
short typing timeout.
Because the createSafeStringFrom..() macros wrap existing
c-string
data, it is possible, but not advisable, to intermix calls to
SafeString methods and unsafe c-string methods, like strcat( ).
However typically you would do all your processing using
SafeString
methods, either in a method or within a code block { } However if
you do intermix SafeString method calls with c-string
methods, the wrapped SafeStrings remain valid and safe.
Before executing each method of a wrapped SafeString:-
a) the
underlying c-string is re-terminate to the SafeString capacity()
and
b) strlen called to resynchronize the SafeString length to
the length of the underlying c-string.
Suggestions, criticisms and bug reports welcome.