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