FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
avstring.c
Go to the documentation of this file.
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 "avstring.h"
31 #include "bprint.h"
32 
33 int av_strstart(const char *str, const char *pfx, const char **ptr)
34 {
35  while (*pfx && *pfx == *str) {
36  pfx++;
37  str++;
38  }
39  if (!*pfx && ptr)
40  *ptr = str;
41  return !*pfx;
42 }
43 
44 int av_stristart(const char *str, const char *pfx, const char **ptr)
45 {
46  while (*pfx && av_toupper((unsigned)*pfx) == av_toupper((unsigned)*str)) {
47  pfx++;
48  str++;
49  }
50  if (!*pfx && ptr)
51  *ptr = str;
52  return !*pfx;
53 }
54 
55 char *av_stristr(const char *s1, const char *s2)
56 {
57  if (!*s2)
58  return (char*)(intptr_t)s1;
59 
60  do
61  if (av_stristart(s1, s2, NULL))
62  return (char*)(intptr_t)s1;
63  while (*s1++);
64 
65  return NULL;
66 }
67 
68 char *av_strnstr(const char *haystack, const char *needle, size_t hay_length)
69 {
70  size_t needle_len = strlen(needle);
71  if (!needle_len)
72  return (char*)haystack;
73  while (hay_length >= needle_len) {
74  hay_length--;
75  if (!memcmp(haystack, needle, needle_len))
76  return (char*)haystack;
77  haystack++;
78  }
79  return NULL;
80 }
81 
82 size_t av_strlcpy(char *dst, const char *src, size_t size)
83 {
84  size_t len = 0;
85  while (++len < size && *src)
86  *dst++ = *src++;
87  if (len <= size)
88  *dst = 0;
89  return len + strlen(src) - 1;
90 }
91 
92 size_t av_strlcat(char *dst, const char *src, size_t size)
93 {
94  size_t len = strlen(dst);
95  if (size <= len + 1)
96  return len + strlen(src);
97  return len + av_strlcpy(dst + len, src, size - len);
98 }
99 
100 size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...)
101 {
102  int len = strlen(dst);
103  va_list vl;
104 
105  va_start(vl, fmt);
106  len += vsnprintf(dst + len, size > len ? size - len : 0, fmt, vl);
107  va_end(vl);
108 
109  return len;
110 }
111 
112 char *av_asprintf(const char *fmt, ...)
113 {
114  char *p = NULL;
115  va_list va;
116  int len;
117 
118  va_start(va, fmt);
119  len = vsnprintf(NULL, 0, fmt, va);
120  va_end(va);
121  if (len < 0)
122  goto end;
123 
124  p = av_malloc(len + 1);
125  if (!p)
126  goto end;
127 
128  va_start(va, fmt);
129  len = vsnprintf(p, len + 1, fmt, va);
130  va_end(va);
131  if (len < 0)
132  av_freep(&p);
133 
134 end:
135  return p;
136 }
137 
138 char *av_d2str(double d)
139 {
140  char *str = av_malloc(16);
141  if (str)
142  snprintf(str, 16, "%f", d);
143  return str;
144 }
145 
146 #define WHITESPACES " \n\t"
147 
148 char *av_get_token(const char **buf, const char *term)
149 {
150  char *out = av_malloc(strlen(*buf) + 1);
151  char *ret = out, *end = out;
152  const char *p = *buf;
153  if (!out)
154  return NULL;
155  p += strspn(p, WHITESPACES);
156 
157  while (*p && !strspn(p, term)) {
158  char c = *p++;
159  if (c == '\\' && *p) {
160  *out++ = *p++;
161  end = out;
162  } else if (c == '\'') {
163  while (*p && *p != '\'')
164  *out++ = *p++;
165  if (*p) {
166  p++;
167  end = out;
168  }
169  } else {
170  *out++ = c;
171  }
172  }
173 
174  do
175  *out-- = 0;
176  while (out >= end && strspn(out, WHITESPACES));
177 
178  *buf = p;
179 
180  return ret;
181 }
182 
183 char *av_strtok(char *s, const char *delim, char **saveptr)
184 {
185  char *tok;
186 
187  if (!s && !(s = *saveptr))
188  return NULL;
189 
190  /* skip leading delimiters */
191  s += strspn(s, delim);
192 
193  /* s now points to the first non delimiter char, or to the end of the string */
194  if (!*s) {
195  *saveptr = NULL;
196  return NULL;
197  }
198  tok = s++;
199 
200  /* skip non delimiters */
201  s += strcspn(s, delim);
202  if (*s) {
203  *s = 0;
204  *saveptr = s+1;
205  } else {
206  *saveptr = NULL;
207  }
208 
209  return tok;
210 }
211 
212 int av_strcasecmp(const char *a, const char *b)
213 {
214  uint8_t c1, c2;
215  do {
216  c1 = av_tolower(*a++);
217  c2 = av_tolower(*b++);
218  } while (c1 && c1 == c2);
219  return c1 - c2;
220 }
221 
222 int av_strncasecmp(const char *a, const char *b, size_t n)
223 {
224  const char *end = a + n;
225  uint8_t c1, c2;
226  do {
227  c1 = av_tolower(*a++);
228  c2 = av_tolower(*b++);
229  } while (a < end && c1 && c1 == c2);
230  return c1 - c2;
231 }
232 
233 const char *av_basename(const char *path)
234 {
235  char *p = strrchr(path, '/');
236 
237 #if HAVE_DOS_PATHS
238  char *q = strrchr(path, '\\');
239  char *d = strchr(path, ':');
240 
241  p = FFMAX3(p, q, d);
242 #endif
243 
244  if (!p)
245  return path;
246 
247  return p + 1;
248 }
249 
250 const char *av_dirname(char *path)
251 {
252  char *p = strrchr(path, '/');
253 
254 #if HAVE_DOS_PATHS
255  char *q = strrchr(path, '\\');
256  char *d = strchr(path, ':');
257 
258  d = d ? d + 1 : d;
259 
260  p = FFMAX3(p, q, d);
261 #endif
262 
263  if (!p)
264  return ".";
265 
266  *p = '\0';
267 
268  return path;
269 }
270 
271 int av_escape(char **dst, const char *src, const char *special_chars,
272  enum AVEscapeMode mode, int flags)
273 {
274  AVBPrint dstbuf;
275 
277  av_bprint_escape(&dstbuf, src, special_chars, mode, flags);
278 
279  if (!av_bprint_is_complete(&dstbuf)) {
280  av_bprint_finalize(&dstbuf, NULL);
281  return AVERROR(ENOMEM);
282  } else {
283  av_bprint_finalize(&dstbuf, dst);
284  return dstbuf.len;
285  }
286 }
287 
288 int av_isdigit(int c)
289 {
290  return c >= '0' && c <= '9';
291 }
292 
293 int av_isgraph(int c)
294 {
295  return c > 32 && c < 127;
296 }
297 
298 int av_isspace(int c)
299 {
300  return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' ||
301  c == '\v';
302 }
303 
304 int av_isxdigit(int c)
305 {
306  c = av_tolower(c);
307  return av_isdigit(c) || (c >= 'a' && c <= 'f');
308 }
309 
310 int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
311  unsigned int flags)
312 {
313  const uint8_t *p = *bufp;
314  uint32_t top;
315  uint64_t code;
316  int ret = 0;
317 
318  if (p >= buf_end)
319  return 0;
320 
321  code = *p++;
322 
323  /* first sequence byte starts with 10, or is 1111-1110 or 1111-1111,
324  which is not admitted */
325  if ((code & 0xc0) == 0x80 || code >= 0xFE) {
326  ret = AVERROR(EILSEQ);
327  goto end;
328  }
329  top = (code & 128) >> 1;
330 
331  while (code & top) {
332  int tmp;
333  if (p >= buf_end) {
334  (*bufp) ++;
335  return AVERROR(EILSEQ); /* incomplete sequence */
336  }
337 
338  /* we assume the byte to be in the form 10xx-xxxx */
339  tmp = *p++ - 128; /* strip leading 1 */
340  if (tmp>>6) {
341  (*bufp) ++;
342  return AVERROR(EILSEQ);
343  }
344  code = (code<<6) + tmp;
345  top <<= 5;
346  }
347  code &= (top << 1) - 1;
348 
349  if (code >= 1<<31) {
350  ret = AVERROR(EILSEQ); /* out-of-range value */
351  goto end;
352  }
353 
354  *codep = code;
355 
356  if (code > 0x10FFFF &&
358  ret = AVERROR(EILSEQ);
359  if (code < 0x20 && code != 0x9 && code != 0xA && code != 0xD &&
361  ret = AVERROR(EILSEQ);
362  if (code >= 0xD800 && code <= 0xDFFF &&
364  ret = AVERROR(EILSEQ);
365  if ((code == 0xFFFE || code == 0xFFFF) &&
367  ret = AVERROR(EILSEQ);
368 
369 end:
370  *bufp = p;
371  return ret;
372 }
373 
374 #ifdef TEST
375 
376 int main(void)
377 {
378  int i;
379  static const char * const strings[] = {
380  "''",
381  "",
382  ":",
383  "\\",
384  "'",
385  " '' :",
386  " '' '' :",
387  "foo '' :",
388  "'foo'",
389  "foo ",
390  " ' foo ' ",
391  "foo\\",
392  "foo': blah:blah",
393  "foo\\: blah:blah",
394  "foo\'",
395  "'foo : ' :blahblah",
396  "\\ :blah",
397  " foo",
398  " foo ",
399  " foo \\ ",
400  "foo ':blah",
401  " foo bar : blahblah",
402  "\\f\\o\\o",
403  "'foo : \\ \\ ' : blahblah",
404  "'\\fo\\o:': blahblah",
405  "\\'fo\\o\\:': foo ' :blahblah"
406  };
407 
408  printf("Testing av_get_token()\n");
409  for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) {
410  const char *p = strings[i];
411  char *q;
412  printf("|%s|", p);
413  q = av_get_token(&p, ":");
414  printf(" -> |%s|", q);
415  printf(" + |%s|\n", p);
416  av_free(q);
417  }
418 
419  return 0;
420 }
421 
422 #endif /* TEST */