2 stringbuf: mimicking a bit of C++ to more safely handle strings
4 copyright 2006-17 by the mpg123 project
5 - free software under the terms of the LGPL 2.1
6 see COPYING and AUTHORS files in distribution or http://mpg123.org
7 initially written by Thomas Orgis
10 #include "mpg123lib_intern.h"
17 void attribute_align_arg
mpg123_init_string(mpg123_string
* sb
)
19 /* Handing in NULL here is a fatal mistake and rightfully so. */
25 void attribute_align_arg
mpg123_free_string(mpg123_string
* sb
)
29 if(sb
->p
!= NULL
) free(sb
->p
);
30 mpg123_init_string(sb
);
33 int attribute_align_arg
mpg123_grow_string(mpg123_string
* sb
, size_t new)
37 if(sb
->size
< new) return mpg123_resize_string(sb
, new);
41 int attribute_align_arg
mpg123_resize_string(mpg123_string
* sb
, size_t new)
45 debug3("resizing string pointer %p from %lu to %lu", (void*) sb
->p
, (unsigned long)sb
->size
, (unsigned long)new);
48 if(sb
->size
&& sb
->p
!= NULL
) free(sb
->p
);
49 mpg123_init_string(sb
);
56 t
= (char*) safe_realloc(sb
->p
, new*sizeof(char));
57 debug1("safe_realloc returned %p", (void*) t
);
66 else return 1; /* success */
69 int attribute_align_arg
mpg123_copy_string(mpg123_string
* from
, mpg123_string
* to
)
74 debug2("called copy_string with %p -> %p", (void*)from
, (void*)to
);
88 if(mpg123_resize_string(to
, fill
))
90 if(fill
) /* Avoid memcpy(NULL, NULL, 0) */
91 memcpy(to
->p
, text
, fill
);
98 int attribute_align_arg
mpg123_add_string(mpg123_string
* sb
, const char* stuff
)
100 debug1("adding %s", stuff
);
101 return mpg123_add_substring(sb
, stuff
, 0, stuff
? strlen(stuff
) : 0);
104 int attribute_align_arg
mpg123_add_substring(mpg123_string
*sb
, const char *stuff
, size_t from
, size_t count
)
106 debug("adding a substring");
109 if(sb
->fill
) /* includes zero byte... */
111 if( (SIZE_MAX
- sb
->fill
>= count
) /* Avoid overflow. */
112 && (sb
->size
>= sb
->fill
+count
|| mpg123_grow_string(sb
, sb
->fill
+count
)) )
114 memcpy(sb
->p
+sb
->fill
-1, stuff
+from
, count
);
116 sb
->p
[sb
->fill
-1] = 0; /* Terminate! */
122 if( count
< SIZE_MAX
&& mpg123_grow_string(sb
, count
+1) )
124 memcpy(sb
->p
, stuff
+from
, count
);
126 sb
->p
[sb
->fill
-1] = 0; /* Terminate! */
133 int attribute_align_arg
mpg123_set_substring(mpg123_string
* sb
, const char* stuff
, size_t from
, size_t count
)
138 return mpg123_add_substring(sb
, stuff
, from
, count
);
141 int attribute_align_arg
mpg123_set_string(mpg123_string
* sb
, const char* stuff
)
146 return mpg123_add_string(sb
, stuff
);
149 size_t attribute_align_arg
mpg123_strlen(mpg123_string
*sb
, int utf8
)
154 /* Notions of empty string. If there's only a single character, it has to be the trailing zero, and if the first is the trailing zero anyway, we got empty. */
155 if(!sb
|| sb
->fill
< 2 || sb
->p
[0] == 0) return 0;
157 /* Find the first non-null character from the back.
158 We already established that the first character is non-null
159 That at fill-2 has to be null, though. */
160 for(i
=sb
->fill
-2; i
>0; --i
)
161 if(sb
->p
[i
] != 0) break;
163 /* For simple byte strings, we are done now. */
166 if(!utf8
) return bytelen
;
169 /* Work out the actual count of UTF8 bytes.
170 This employs no particular encoding error checking. */
172 for(i
=0; i
<bytelen
; ++i
)
174 /* Every byte that is not a continuation byte ( 0xc0 == 10xx xxxx ) stands for a character. */
175 if((sb
->p
[i
] & 0xc0) != 0x80) len
++;
181 int attribute_align_arg
mpg123_chomp_string(mpg123_string
*sb
)
184 if(!sb
|| !sb
->fill
) return 0;
186 /* Ensure that it is zero-terminated. */
187 sb
->p
[sb
->fill
-1] = 0;
188 for(i
=sb
->fill
-2; i
>=0; --i
)
191 /* Stop at the first proper character. */
192 if(*c
&& *c
!= '\r' && *c
!= '\n') break;
195 /* initial fill at least 1, so i at least -1,
196 +2 means nothing happened for fill=1 .
197 With i=0, we got one non-null character, fill shall be 2
198 to accomodate the trailing zero. */
199 sb
->fill
= (size_t)i
+2;