48
48
#define DEFAULT_MSTRING_SIZE 20
49
49
#endif
50
50
51
- // #define UNSAFE_MSTRING // Don't initialize the string and don't terminate strncpy
51
+ // #define UNSAFE_MSTRING // Don't initialize the string to "" or set a terminating nul
52
52
// #define USE_SPRINTF // Use sprintf instead of snprintf
53
53
// #define DJB2_HASH // 32-bit hash with Djb2 algorithm
54
54
// #define MSTRING_DEBUG // Debug string operations to diagnose memory leaks
@@ -98,26 +98,20 @@ class MString {
98
98
99
99
void debug (FSTR_P const f) {
100
100
#if ENABLED(MSTRING_DEBUG)
101
- SERIAL_ECHO (FTOP (f));
102
- SERIAL_CHAR (' :' );
103
- SERIAL_ECHO (uintptr_t (str));
104
- SERIAL_CHAR (' ' );
105
- SERIAL_ECHO (length ());
106
- SERIAL_CHAR (' ' );
107
- SERIAL_ECHOLN (str);
101
+ SERIAL_ECHOLN (f, ' :' , uintptr_t (str), ' ' , length (), ' ' , str);
108
102
#endif
109
103
}
110
104
111
105
void safety (const int n) { if (SAFE && n <= SIZE) str[n] = ' \0 ' ; }
112
106
113
107
// Chainable String Setters
114
108
MString& set () { str[0 ] = ' \0 ' ; debug (F (" clear" )); return *this ; }
115
- MString& set (char *s) { strncpy (str, s, SIZE); debug (F (" string" )); return *this ; }
109
+ MString& set (char *s) { strlcpy (str, s, SIZE + 1 ); debug (F (" string" )); return *this ; }
116
110
MString& set (const char *s) { return set (const_cast <char *>(s)); }
117
- MString& set_P (PGM_P const s) { strncpy_P (str, s, SIZE); debug (F (" pstring" )); return *this ; }
111
+ MString& set_P (PGM_P const s) { strlcpy_P (str, s, SIZE + 1 ); debug (F (" pstring" )); return *this ; }
118
112
MString& set (FSTR_P const f) { return set_P (FTOP (f)); }
119
113
MString& set (const bool &b) { return set (b ? F (" true" ) : F (" false" )); }
120
- MString& set (const char c) { str[0 ] = c; if ( 1 < SIZE) str[1 ] = ' \0 ' ; debug (F (" char" )); return *this ; }
114
+ MString& set (const char c) { str[0 ] = c; str[1 ] = ' \0 ' ; debug (F (" char" )); return *this ; }
121
115
MString& set (const int8_t &i) { SNPRINTF_P (str, SIZE, PSTR (" %d" ), i); debug (F (" int8_t" )); return *this ; }
122
116
MString& set (const short &i) { SNPRINTF_P (str, SIZE, PSTR (" %d" ), i); debug (F (" short" )); return *this ; }
123
117
MString& set (const int &i) { SNPRINTF_P (str, SIZE, PSTR (" %d" ), i); debug (F (" int" )); return *this ; }
@@ -134,11 +128,11 @@ class MString {
134
128
MString& set (const xyze_pos_t &v) { set (); return append (v); }
135
129
136
130
template <int S>
137
- MString& set (const MString<S> &m) { strncpy (str, &m, SIZE); debug (F (" MString" )); return *this ; }
131
+ MString& set (const MString<S> &m) { strlcpy (str, &m, SIZE + 1 ); debug (F (" MString" )); return *this ; }
138
132
139
- MString& setn (char *s, int len) { int c = _MIN (len, SIZE); strncpy (str, s, c); str[c] = ' \0 ' ; debug (F (" string" )); return *this ; }
133
+ MString& setn (char *s, int len) { int c = _MIN (len, SIZE); strlcpy (str, s, c + 1 ) ; debug (F (" string" )); return *this ; }
140
134
MString& setn (const char *s, int len) { return setn (const_cast <char *>(s), len); }
141
- MString& setn_P (PGM_P const s, int len) { int c = _MIN (len, SIZE); strncpy_P (str, s, c); str[c] = ' \0 ' ; debug (F (" pstring" )); return *this ; }
135
+ MString& setn_P (PGM_P const s, int len) { int c = _MIN (len, SIZE); strlcpy_P (str, s, c + 1 ) ; debug (F (" pstring" )); return *this ; }
142
136
MString& setn (FSTR_P const f, int len) { return setn_P (FTOP (f), len); }
143
137
144
138
// set(repchr_t('-', 10))
@@ -159,9 +153,9 @@ class MString {
159
153
160
154
// Chainable String appenders
161
155
MString& append () { debug (F (" nil" )); return *this ; } // for macros that might emit no output
162
- MString& append (char *s) { int sz = length (); if (sz < SIZE) strncpy (str + sz, s, SIZE - sz); debug (F (" string" )); return *this ; }
156
+ MString& append (char *s) { int sz = length (); if (sz < SIZE) strlcpy (str + sz, s, SIZE - sz + 1 ); debug (F (" string" )); return *this ; }
163
157
MString& append (const char *s) { return append (const_cast <char *>(s)); }
164
- MString& append_P (PGM_P const s) { int sz = length (); if (sz < SIZE) strncpy_P (str + sz, s, SIZE - sz); debug (F (" pstring" )); return *this ; }
158
+ MString& append_P (PGM_P const s) { int sz = length (); if (sz < SIZE) strlcpy_P (str + sz, s, SIZE - sz + 1 ); debug (F (" pstring" )); return *this ; }
165
159
MString& append (FSTR_P const f) { return append_P (FTOP (f)); }
166
160
MString& append (const bool &b) { return append (b ? F (" true" ) : F (" false" )); }
167
161
MString& append (const char c) { int sz = length (); if (sz < SIZE) { str[sz] = c; if (sz < SIZE - 1 ) str[sz + 1 ] = ' \0 ' ; } return *this ; }
@@ -195,15 +189,15 @@ class MString {
195
189
MString& append (const MString<S> &m) { return append (&m); }
196
190
197
191
// Append only if the given space is available
198
- MString& appendn (char *s, int len) { int sz = length (), c = _MIN (len, SIZE - sz); if (c > 0 ) { strncpy (str + sz, s, c); str[sz + c] = ' \0 ' ; } debug (F (" string" )); return *this ; }
192
+ MString& appendn (char *s, int len) { int sz = length (), c = _MIN (len, SIZE - sz); if (c > 0 ) { strlcpy (str + sz, s, c + 1 ) ; } debug (F (" string" )); return *this ; }
199
193
MString& appendn (const char *s, int len) { return appendn (const_cast <char *>(s), len); }
200
- MString& appendn_P (PGM_P const s, int len) { int sz = length (), c = _MIN (len, SIZE - sz); if (c > 0 ) { strncpy_P (str + sz, s, c); str[sz + c] = ' \0 ' ; } debug (F (" pstring" )); return *this ; }
194
+ MString& appendn_P (PGM_P const s, int len) { int sz = length (), c = _MIN (len, SIZE - sz); if (c > 0 ) { strlcpy_P (str + sz, s, c + 1 ) ; } debug (F (" pstring" )); return *this ; }
201
195
MString& appendn (FSTR_P const f, int len) { return appendn_P (FTOP (f), len); }
202
196
203
197
// append(repchr_t('-', 10))
204
198
MString& append (const repchr_t &s) {
205
199
const int sz = length (), c = _MIN (s.count , SIZE - sz);
206
- if (c > 0 ) { memset (str + sz, s.asc , c); safety ( sz + c) ; }
200
+ if (c > 0 ) { memset (str + sz, s.asc , c); str[ sz + c] = ' \0 ' ; }
207
201
debug (F (" repchr" ));
208
202
return *this ;
209
203
}
@@ -299,7 +293,7 @@ class MString {
299
293
}
300
294
301
295
void copyto (char * const dst) const { strcpy (dst, str); }
302
- void copyto (char * const dst, int len) const { strncpy (dst, str, len); }
296
+ void copyto (char * const dst, int len) const { strlcpy (dst, str, len + 1 ); }
303
297
304
298
MString& clear () { return set (); }
305
299
MString& eol () { return append (' \n ' ); }
@@ -318,6 +312,7 @@ class MString {
318
312
319
313
#pragma GCC diagnostic pop
320
314
315
+ // Temporary inline string typically used to compose a G-code command
321
316
#ifndef TS_SIZE
322
317
#define TS_SIZE 63
323
318
#endif
0 commit comments