FFmpeg
 All Data Structures 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 #ifdef TEST
289 
290 int main(void)
291 {
292  int i;
293  const char *strings[] = {
294  "''",
295  "",
296  ":",
297  "\\",
298  "'",
299  " '' :",
300  " '' '' :",
301  "foo '' :",
302  "'foo'",
303  "foo ",
304  " ' foo ' ",
305  "foo\\",
306  "foo': blah:blah",
307  "foo\\: blah:blah",
308  "foo\'",
309  "'foo : ' :blahblah",
310  "\\ :blah",
311  " foo",
312  " foo ",
313  " foo \\ ",
314  "foo ':blah",
315  " foo bar : blahblah",
316  "\\f\\o\\o",
317  "'foo : \\ \\ ' : blahblah",
318  "'\\fo\\o:': blahblah",
319  "\\'fo\\o\\:': foo ' :blahblah"
320  };
321 
322  printf("Testing av_get_token()\n");
323  for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) {
324  const char *p = strings[i];
325  char *q;
326  printf("|%s|", p);
327  q = av_get_token(&p, ":");
328  printf(" -> |%s|", q);
329  printf(" + |%s|\n", p);
330  av_free(q);
331  }
332 
333  return 0;
334 }
335 
336 #endif /* TEST */