/src/mpg123/src/libmpg123/stringbuf.c
Line | Count | Source |
1 | | /* |
2 | | stringbuf: mimicking a bit of C++ to more safely handle strings |
3 | | |
4 | | copyright 2006-20 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 |
8 | | */ |
9 | | |
10 | | #include "mpg123lib_intern.h" |
11 | | #include "config.h" |
12 | | #include "mpg123.h" |
13 | | #include "../compat/compat.h" |
14 | | #include <string.h> |
15 | | #include "../common/debug.h" |
16 | | |
17 | | mpg123_string* attribute_align_arg mpg123_new_string(const char *val) |
18 | 0 | { |
19 | 0 | mpg123_string *sb = malloc(sizeof(mpg123_string)); |
20 | 0 | if(!sb) |
21 | 0 | return NULL; |
22 | 0 | mpg123_init_string(sb); |
23 | 0 | mpg123_set_string(sb, val); |
24 | 0 | return sb; |
25 | 0 | } |
26 | | |
27 | | void attribute_align_arg mpg123_delete_string(mpg123_string* sb) |
28 | 0 | { |
29 | 0 | if(!sb) |
30 | 0 | return; |
31 | 0 | mpg123_free_string(sb); |
32 | 0 | free(sb); |
33 | 0 | } |
34 | | |
35 | | void attribute_align_arg mpg123_init_string(mpg123_string* sb) |
36 | 169k | { |
37 | | /* Handing in NULL here is a fatal mistake and rightfully so. */ |
38 | 169k | sb->p = NULL; |
39 | 169k | sb->size = 0; |
40 | 169k | sb->fill = 0; |
41 | 169k | } |
42 | | |
43 | | void attribute_align_arg mpg123_free_string(mpg123_string* sb) |
44 | 75.7k | { |
45 | 75.7k | if(!sb) |
46 | 0 | return; |
47 | 75.7k | if(sb->p != NULL) free(sb->p); |
48 | 75.7k | mpg123_init_string(sb); |
49 | 75.7k | } |
50 | | |
51 | | int attribute_align_arg mpg123_grow_string(mpg123_string* sb, size_t new) |
52 | 49.4k | { |
53 | 49.4k | if(!sb) |
54 | 0 | return 0; |
55 | 49.4k | if(sb->size < new) return mpg123_resize_string(sb, new); |
56 | 286 | else return 1; |
57 | 49.4k | } |
58 | | |
59 | | int attribute_align_arg mpg123_resize_string(mpg123_string* sb, size_t new) |
60 | 49.1k | { |
61 | 49.1k | if(!sb) |
62 | 0 | return 0; |
63 | 49.1k | debug3("resizing string pointer %p from %lu to %lu", (void*) sb->p, (unsigned long)sb->size, (unsigned long)new); |
64 | 49.1k | if(new == 0) |
65 | 0 | { |
66 | 0 | if(sb->size && sb->p != NULL) free(sb->p); |
67 | 0 | mpg123_init_string(sb); |
68 | 0 | return 1; |
69 | 0 | } |
70 | 49.1k | if(sb->size != new) |
71 | 49.1k | { |
72 | 49.1k | char* t; |
73 | 49.1k | debug("really!"); |
74 | 49.1k | t = (char*) INT123_safe_realloc(sb->p, new*sizeof(char)); |
75 | 49.1k | debug1("INT123_safe_realloc returned %p", (void*) t); |
76 | 49.1k | if(t != NULL) |
77 | 49.1k | { |
78 | 49.1k | sb->p = t; |
79 | 49.1k | sb->size = new; |
80 | 49.1k | if(sb->size < sb->fill) |
81 | 0 | { |
82 | | // Cut short the existing data, properly. |
83 | 0 | sb->fill = sb->size; |
84 | 0 | sb->p[sb->fill-1] = 0; |
85 | 0 | } |
86 | 49.1k | return 1; |
87 | 49.1k | } |
88 | 0 | else return 0; |
89 | 49.1k | } |
90 | 0 | else return 1; /* success */ |
91 | 49.1k | } |
92 | | |
93 | | int attribute_align_arg mpg123_copy_string(mpg123_string* from, mpg123_string* to) |
94 | 0 | { |
95 | 0 | size_t fill; |
96 | 0 | char *text; |
97 | |
|
98 | 0 | debug2("called copy_string with %p -> %p", (void*)from, (void*)to); |
99 | 0 | if(to == NULL) |
100 | 0 | return 0; |
101 | 0 | if(from == NULL) |
102 | 0 | { |
103 | 0 | fill = 0; |
104 | 0 | text = NULL; |
105 | 0 | } |
106 | 0 | else |
107 | 0 | { |
108 | 0 | fill = from->fill; |
109 | 0 | text = from->p; |
110 | 0 | } |
111 | |
|
112 | 0 | if(mpg123_resize_string(to, fill)) |
113 | 0 | { |
114 | 0 | if(fill) /* Avoid memcpy(NULL, NULL, 0) */ |
115 | 0 | memcpy(to->p, text, fill); |
116 | 0 | to->fill = fill; |
117 | 0 | return 1; |
118 | 0 | } |
119 | 0 | else return 0; |
120 | 0 | } |
121 | | |
122 | | int attribute_align_arg mpg123_move_string(mpg123_string *from, mpg123_string *to) |
123 | 14.7k | { |
124 | 14.7k | if(to) |
125 | 14.7k | mpg123_free_string(to); |
126 | 0 | else |
127 | 0 | mpg123_free_string(from); |
128 | 14.7k | if(from && to) |
129 | 14.7k | *to = *from; |
130 | 14.7k | if(from) |
131 | 14.7k | mpg123_init_string(from); |
132 | 14.7k | return (from && to) ? 1 : 0; |
133 | 14.7k | } |
134 | | |
135 | | int attribute_align_arg mpg123_add_string(mpg123_string* sb, const char* stuff) |
136 | 0 | { |
137 | 0 | debug1("adding %s", stuff); |
138 | 0 | return mpg123_add_substring(sb, stuff, 0, stuff ? strlen(stuff) : 0); |
139 | 0 | } |
140 | | |
141 | | int attribute_align_arg mpg123_add_substring(mpg123_string *sb, const char *stuff, size_t from, size_t count) |
142 | 0 | { |
143 | 0 | debug("adding a substring"); |
144 | 0 | if(!sb || !stuff) |
145 | 0 | return 0; |
146 | 0 | if(sb->fill) /* includes zero byte... */ |
147 | 0 | { |
148 | 0 | if( (SIZE_MAX - sb->fill >= count) /* Avoid overflow. */ |
149 | 0 | && (sb->size >= sb->fill+count || mpg123_grow_string(sb, sb->fill+count)) ) |
150 | 0 | { |
151 | 0 | memcpy(sb->p+sb->fill-1, stuff+from, count); |
152 | 0 | sb->fill += count; |
153 | 0 | sb->p[sb->fill-1] = 0; /* Terminate! */ |
154 | 0 | } |
155 | 0 | else return 0; |
156 | 0 | } |
157 | 0 | else |
158 | 0 | { |
159 | 0 | if( count < SIZE_MAX && mpg123_grow_string(sb, count+1) ) |
160 | 0 | { |
161 | 0 | memcpy(sb->p, stuff+from, count); |
162 | 0 | sb->fill = count+1; |
163 | 0 | sb->p[sb->fill-1] = 0; /* Terminate! */ |
164 | 0 | } |
165 | 0 | else return 0; |
166 | 0 | } |
167 | 0 | return 1; |
168 | 0 | } |
169 | | |
170 | | int attribute_align_arg mpg123_set_substring(mpg123_string* sb, const char* stuff, size_t from, size_t count) |
171 | 0 | { |
172 | 0 | if(!sb) |
173 | 0 | return 0; |
174 | 0 | sb->fill = 0; |
175 | 0 | return mpg123_add_substring(sb, stuff, from, count); |
176 | 0 | } |
177 | | |
178 | | int attribute_align_arg mpg123_set_string(mpg123_string* sb, const char* stuff) |
179 | 0 | { |
180 | 0 | if(!sb) |
181 | 0 | return 0; |
182 | 0 | sb->fill = 0; |
183 | 0 | return mpg123_add_string(sb, stuff); |
184 | 0 | } |
185 | | |
186 | | size_t attribute_align_arg mpg123_strlen(mpg123_string *sb, int utf8) |
187 | 0 | { |
188 | 0 | size_t i; |
189 | 0 | size_t bytelen; |
190 | | |
191 | | /* 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. */ |
192 | 0 | if(!sb || sb->fill < 2 || sb->p[0] == 0) return 0; |
193 | | |
194 | | /* Find the first non-null character from the back. |
195 | | We already established that the first character is non-null |
196 | | That at fill-2 has to be null, though. */ |
197 | 0 | for(i=sb->fill-2; i>0; --i) |
198 | 0 | if(sb->p[i] != 0) break; |
199 | | |
200 | | /* For simple byte strings, we are done now. */ |
201 | 0 | bytelen = i+1; |
202 | |
|
203 | 0 | if(!utf8) return bytelen; |
204 | 0 | else |
205 | 0 | { |
206 | | /* Work out the actual count of UTF8 bytes. |
207 | | This employs no particular encoding error checking. */ |
208 | 0 | size_t len = 0; |
209 | 0 | for(i=0; i<bytelen; ++i) |
210 | 0 | { |
211 | | /* Every byte that is not a continuation byte ( 0xc0 == 10xx xxxx ) stands for a character. */ |
212 | 0 | if((sb->p[i] & 0xc0) != 0x80) len++; |
213 | 0 | } |
214 | 0 | return len; |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | int attribute_align_arg mpg123_chomp_string(mpg123_string *sb) |
219 | 0 | { |
220 | 0 | if(!sb || !sb->fill) return 0; |
221 | | |
222 | | /* Ensure that it is zero-terminated. */ |
223 | 0 | char *c = sb->p+sb->fill-1; |
224 | 0 | *c = 0; |
225 | 0 | for(; c >= sb->p; --c) |
226 | 0 | { |
227 | | /* Stop at the first proper character. */ |
228 | 0 | if(*c && *c != '\r' && *c != '\n') break; |
229 | 0 | else *c = 0; |
230 | 0 | } |
231 | | // We at least got a trailing zero. |
232 | 0 | sb->fill = (size_t)(c - sb->p + 1) + 1; |
233 | |
|
234 | 0 | return 1; |
235 | 0 | } |
236 | | |
237 | | int attribute_align_arg mpg123_same_string(mpg123_string *a, mpg123_string *b) |
238 | 3.13k | { |
239 | 3.13k | if(!a || !b) |
240 | 0 | return 0; |
241 | 3.13k | if(a->fill != b->fill) |
242 | 1.12k | return 0; |
243 | 2.00k | if(memcmp(a->p, b->p, a->fill)) |
244 | 1.04k | return 0; |
245 | 956 | return 1; |
246 | 2.00k | } |