Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52868 views
1
/*
2
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
3
* Copyright (c) 2007 Mans Rullgard
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include <stdarg.h>
23
#include <stdint.h>
24
#include <stdio.h>
25
#include <string.h>
26
27
#include "config.h"
28
#include "common.h"
29
#include "mem.h"
30
#include "avassert.h"
31
#include "avstring.h"
32
#include "bprint.h"
33
34
int av_strstart(const char *str, const char *pfx, const char **ptr)
35
{
36
while (*pfx && *pfx == *str) {
37
pfx++;
38
str++;
39
}
40
if (!*pfx && ptr)
41
*ptr = str;
42
return !*pfx;
43
}
44
45
int av_stristart(const char *str, const char *pfx, const char **ptr)
46
{
47
while (*pfx && av_toupper((unsigned)*pfx) == av_toupper((unsigned)*str)) {
48
pfx++;
49
str++;
50
}
51
if (!*pfx && ptr)
52
*ptr = str;
53
return !*pfx;
54
}
55
56
char *av_stristr(const char *s1, const char *s2)
57
{
58
if (!*s2)
59
return (char*)(intptr_t)s1;
60
61
do
62
if (av_stristart(s1, s2, NULL))
63
return (char*)(intptr_t)s1;
64
while (*s1++);
65
66
return NULL;
67
}
68
69
char *av_strnstr(const char *haystack, const char *needle, size_t hay_length)
70
{
71
size_t needle_len = strlen(needle);
72
if (!needle_len)
73
return (char*)haystack;
74
while (hay_length >= needle_len) {
75
hay_length--;
76
if (!memcmp(haystack, needle, needle_len))
77
return (char*)haystack;
78
haystack++;
79
}
80
return NULL;
81
}
82
83
size_t av_strlcpy(char *dst, const char *src, size_t size)
84
{
85
size_t len = 0;
86
while (++len < size && *src)
87
*dst++ = *src++;
88
if (len <= size)
89
*dst = 0;
90
return len + strlen(src) - 1;
91
}
92
93
size_t av_strlcat(char *dst, const char *src, size_t size)
94
{
95
size_t len = strlen(dst);
96
if (size <= len + 1)
97
return len + strlen(src);
98
return len + av_strlcpy(dst + len, src, size - len);
99
}
100
101
size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...)
102
{
103
size_t len = strlen(dst);
104
va_list vl;
105
106
va_start(vl, fmt);
107
len += vsnprintf(dst + len, size > len ? size - len : 0, fmt, vl);
108
va_end(vl);
109
110
return len;
111
}
112
113
char *av_asprintf(const char *fmt, ...)
114
{
115
char *p = NULL;
116
va_list va;
117
int len;
118
119
va_start(va, fmt);
120
len = vsnprintf(NULL, 0, fmt, va);
121
va_end(va);
122
if (len < 0)
123
goto end;
124
125
p = av_malloc(len + 1);
126
if (!p)
127
goto end;
128
129
va_start(va, fmt);
130
len = vsnprintf(p, len + 1, fmt, va);
131
va_end(va);
132
if (len < 0)
133
av_freep(&p);
134
135
end:
136
return p;
137
}
138
139
char *av_d2str(double d)
140
{
141
char *str = av_malloc(16);
142
if (str)
143
snprintf(str, 16, "%f", d);
144
return str;
145
}
146
147
#define WHITESPACES " \n\t"
148
149
char *av_get_token(const char **buf, const char *term)
150
{
151
char *out = av_malloc(strlen(*buf) + 1);
152
char *ret = out, *end = out;
153
const char *p = *buf;
154
if (!out)
155
return NULL;
156
p += strspn(p, WHITESPACES);
157
158
while (*p && !strspn(p, term)) {
159
char c = *p++;
160
if (c == '\\' && *p) {
161
*out++ = *p++;
162
end = out;
163
} else if (c == '\'') {
164
while (*p && *p != '\'')
165
*out++ = *p++;
166
if (*p) {
167
p++;
168
end = out;
169
}
170
} else {
171
*out++ = c;
172
}
173
}
174
175
do
176
*out-- = 0;
177
while (out >= end && strspn(out, WHITESPACES));
178
179
*buf = p;
180
181
return ret;
182
}
183
184
char *av_strtok(char *s, const char *delim, char **saveptr)
185
{
186
char *tok;
187
188
if (!s && !(s = *saveptr))
189
return NULL;
190
191
/* skip leading delimiters */
192
s += strspn(s, delim);
193
194
/* s now points to the first non delimiter char, or to the end of the string */
195
if (!*s) {
196
*saveptr = NULL;
197
return NULL;
198
}
199
tok = s++;
200
201
/* skip non delimiters */
202
s += strcspn(s, delim);
203
if (*s) {
204
*s = 0;
205
*saveptr = s+1;
206
} else {
207
*saveptr = NULL;
208
}
209
210
return tok;
211
}
212
213
int av_strcasecmp(const char *a, const char *b)
214
{
215
uint8_t c1, c2;
216
do {
217
c1 = av_tolower(*a++);
218
c2 = av_tolower(*b++);
219
} while (c1 && c1 == c2);
220
return c1 - c2;
221
}
222
223
int av_strncasecmp(const char *a, const char *b, size_t n)
224
{
225
const char *end = a + n;
226
uint8_t c1, c2;
227
do {
228
c1 = av_tolower(*a++);
229
c2 = av_tolower(*b++);
230
} while (a < end && c1 && c1 == c2);
231
return c1 - c2;
232
}
233
234
const char *av_basename(const char *path)
235
{
236
char *p = strrchr(path, '/');
237
238
#if HAVE_DOS_PATHS
239
char *q = strrchr(path, '\\');
240
char *d = strchr(path, ':');
241
242
p = FFMAX3(p, q, d);
243
#endif
244
245
if (!p)
246
return path;
247
248
return p + 1;
249
}
250
251
const char *av_dirname(char *path)
252
{
253
char *p = strrchr(path, '/');
254
255
#if HAVE_DOS_PATHS
256
char *q = strrchr(path, '\\');
257
char *d = strchr(path, ':');
258
259
d = d ? d + 1 : d;
260
261
p = FFMAX3(p, q, d);
262
#endif
263
264
if (!p)
265
return ".";
266
267
*p = '\0';
268
269
return path;
270
}
271
272
char *av_append_path_component(const char *path, const char *component)
273
{
274
size_t p_len, c_len;
275
char *fullpath;
276
277
if (!path)
278
return av_strdup(component);
279
if (!component)
280
return av_strdup(path);
281
282
p_len = strlen(path);
283
c_len = strlen(component);
284
if (p_len > SIZE_MAX - c_len || p_len + c_len > SIZE_MAX - 2)
285
return NULL;
286
fullpath = av_malloc(p_len + c_len + 2);
287
if (fullpath) {
288
if (p_len) {
289
av_strlcpy(fullpath, path, p_len + 1);
290
if (c_len) {
291
if (fullpath[p_len - 1] != '/' && component[0] != '/')
292
fullpath[p_len++] = '/';
293
else if (fullpath[p_len - 1] == '/' && component[0] == '/')
294
p_len--;
295
}
296
}
297
av_strlcpy(&fullpath[p_len], component, c_len + 1);
298
fullpath[p_len + c_len] = 0;
299
}
300
return fullpath;
301
}
302
303
int av_escape(char **dst, const char *src, const char *special_chars,
304
enum AVEscapeMode mode, int flags)
305
{
306
AVBPrint dstbuf;
307
308
av_bprint_init(&dstbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
309
av_bprint_escape(&dstbuf, src, special_chars, mode, flags);
310
311
if (!av_bprint_is_complete(&dstbuf)) {
312
av_bprint_finalize(&dstbuf, NULL);
313
return AVERROR(ENOMEM);
314
} else {
315
av_bprint_finalize(&dstbuf, dst);
316
return dstbuf.len;
317
}
318
}
319
320
int av_match_name(const char *name, const char *names)
321
{
322
const char *p;
323
int len, namelen;
324
325
if (!name || !names)
326
return 0;
327
328
namelen = strlen(name);
329
while (*names) {
330
int negate = '-' == *names;
331
p = strchr(names, ',');
332
if (!p)
333
p = names + strlen(names);
334
names += negate;
335
len = FFMAX(p - names, namelen);
336
if (!av_strncasecmp(name, names, len) || !strncmp("ALL", names, FFMAX(3, p - names)))
337
return !negate;
338
names = p + (*p == ',');
339
}
340
return 0;
341
}
342
343
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
344
unsigned int flags)
345
{
346
const uint8_t *p = *bufp;
347
uint32_t top;
348
uint64_t code;
349
int ret = 0, tail_len;
350
uint32_t overlong_encoding_mins[6] = {
351
0x00000000, 0x00000080, 0x00000800, 0x00010000, 0x00200000, 0x04000000,
352
};
353
354
if (p >= buf_end)
355
return 0;
356
357
code = *p++;
358
359
/* first sequence byte starts with 10, or is 1111-1110 or 1111-1111,
360
which is not admitted */
361
if ((code & 0xc0) == 0x80 || code >= 0xFE) {
362
ret = AVERROR(EILSEQ);
363
goto end;
364
}
365
top = (code & 128) >> 1;
366
367
tail_len = 0;
368
while (code & top) {
369
int tmp;
370
tail_len++;
371
if (p >= buf_end) {
372
(*bufp) ++;
373
return AVERROR(EILSEQ); /* incomplete sequence */
374
}
375
376
/* we assume the byte to be in the form 10xx-xxxx */
377
tmp = *p++ - 128; /* strip leading 1 */
378
if (tmp>>6) {
379
(*bufp) ++;
380
return AVERROR(EILSEQ);
381
}
382
code = (code<<6) + tmp;
383
top <<= 5;
384
}
385
code &= (top << 1) - 1;
386
387
/* check for overlong encodings */
388
av_assert0(tail_len <= 5);
389
if (code < overlong_encoding_mins[tail_len]) {
390
ret = AVERROR(EILSEQ);
391
goto end;
392
}
393
394
if (code >= 1U<<31) {
395
ret = AVERROR(EILSEQ); /* out-of-range value */
396
goto end;
397
}
398
399
*codep = code;
400
401
if (code > 0x10FFFF &&
402
!(flags & AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES))
403
ret = AVERROR(EILSEQ);
404
if (code < 0x20 && code != 0x9 && code != 0xA && code != 0xD &&
405
flags & AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES)
406
ret = AVERROR(EILSEQ);
407
if (code >= 0xD800 && code <= 0xDFFF &&
408
!(flags & AV_UTF8_FLAG_ACCEPT_SURROGATES))
409
ret = AVERROR(EILSEQ);
410
if ((code == 0xFFFE || code == 0xFFFF) &&
411
!(flags & AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS))
412
ret = AVERROR(EILSEQ);
413
414
end:
415
*bufp = p;
416
return ret;
417
}
418
419
int av_match_list(const char *name, const char *list, char separator)
420
{
421
const char *p, *q;
422
423
for (p = name; p && *p; ) {
424
for (q = list; q && *q; ) {
425
int k;
426
for (k = 0; p[k] == q[k] || (p[k]*q[k] == 0 && p[k]+q[k] == separator); k++)
427
if (k && (!p[k] || p[k] == separator))
428
return 1;
429
q = strchr(q, separator);
430
q += !!q;
431
}
432
p = strchr(p, separator);
433
p += !!p;
434
}
435
436
return 0;
437
}
438
439
#ifdef TEST
440
441
int main(void)
442
{
443
int i;
444
char *fullpath;
445
static const char * const strings[] = {
446
"''",
447
"",
448
":",
449
"\\",
450
"'",
451
" '' :",
452
" '' '' :",
453
"foo '' :",
454
"'foo'",
455
"foo ",
456
" ' foo ' ",
457
"foo\\",
458
"foo': blah:blah",
459
"foo\\: blah:blah",
460
"foo\'",
461
"'foo : ' :blahblah",
462
"\\ :blah",
463
" foo",
464
" foo ",
465
" foo \\ ",
466
"foo ':blah",
467
" foo bar : blahblah",
468
"\\f\\o\\o",
469
"'foo : \\ \\ ' : blahblah",
470
"'\\fo\\o:': blahblah",
471
"\\'fo\\o\\:': foo ' :blahblah"
472
};
473
474
printf("Testing av_get_token()\n");
475
for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) {
476
const char *p = strings[i];
477
char *q;
478
printf("|%s|", p);
479
q = av_get_token(&p, ":");
480
printf(" -> |%s|", q);
481
printf(" + |%s|\n", p);
482
av_free(q);
483
}
484
485
printf("Testing av_append_path_component()\n");
486
#define TEST_APPEND_PATH_COMPONENT(path, component, expected) \
487
fullpath = av_append_path_component((path), (component)); \
488
printf("%s = %s\n", fullpath ? fullpath : "(null)", expected); \
489
av_free(fullpath);
490
TEST_APPEND_PATH_COMPONENT(NULL, NULL, "(null)")
491
TEST_APPEND_PATH_COMPONENT("path", NULL, "path");
492
TEST_APPEND_PATH_COMPONENT(NULL, "comp", "comp");
493
TEST_APPEND_PATH_COMPONENT("path", "comp", "path/comp");
494
TEST_APPEND_PATH_COMPONENT("path/", "comp", "path/comp");
495
TEST_APPEND_PATH_COMPONENT("path", "/comp", "path/comp");
496
TEST_APPEND_PATH_COMPONENT("path/", "/comp", "path/comp");
497
TEST_APPEND_PATH_COMPONENT("path/path2/", "/comp/comp2", "path/path2/comp/comp2");
498
return 0;
499
}
500
501
#endif /* TEST */
502
503