fmt-conversion.h: fix pixfmt.h #include; fixes latest Libav
[mplayer.git] / bstr.c
blobfbd416aee06c39f79001883ce4d6f695464bd04c
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <string.h>
20 #include <assert.h>
21 #include <ctype.h>
22 #include <stdarg.h>
24 #include <libavutil/common.h>
26 #include "talloc.h"
28 #include "bstr.h"
30 int bstrcmp(struct bstr str1, struct bstr str2)
32 int ret = memcmp(str1.start, str2.start, FFMIN(str1.len, str2.len));
34 if (!ret) {
35 if (str1.len == str2.len)
36 return 0;
37 else if (str1.len > str2.len)
38 return 1;
39 else
40 return -1;
42 return ret;
45 int bstrcasecmp(struct bstr str1, struct bstr str2)
47 int ret = strncasecmp(str1.start, str2.start, FFMIN(str1.len, str2.len));
49 if (!ret) {
50 if (str1.len == str2.len)
51 return 0;
52 else if (str1.len > str2.len)
53 return 1;
54 else
55 return -1;
57 return ret;
60 int bstrchr(struct bstr str, int c)
62 for (int i = 0; i < str.len; i++)
63 if (str.start[i] == c)
64 return i;
65 return -1;
68 int bstrrchr(struct bstr str, int c)
70 for (int i = str.len - 1; i >= 0; i--)
71 if (str.start[i] == c)
72 return i;
73 return -1;
76 int bstrcspn(struct bstr str, const char *reject)
78 int i;
79 for (i = 0; i < str.len; i++)
80 if (strchr(reject, str.start[i]))
81 break;
82 return i;
85 int bstr_find(struct bstr haystack, struct bstr needle)
87 for (int i = 0; i < haystack.len; i++)
88 if (bstr_startswith(bstr_splice(haystack, i, haystack.len), needle))
89 return i;
90 return -1;
93 struct bstr bstr_lstrip(struct bstr str)
95 while (str.len && isspace(*str.start)) {
96 str.start++;
97 str.len--;
99 return str;
102 struct bstr bstr_strip(struct bstr str)
104 str = bstr_lstrip(str);
105 while (str.len && isspace(str.start[str.len - 1]))
106 str.len--;
107 return str;
110 struct bstr bstr_split(struct bstr str, const char *sep, struct bstr *rest)
112 int start;
113 for (start = 0; start < str.len; start++)
114 if (!strchr(sep, str.start[start]))
115 break;
116 str = bstr_cut(str, start);
117 int end = bstrcspn(str, sep);
118 if (rest) {
119 *rest = bstr_cut(str, end);
121 return bstr_splice(str, 0, end);
125 struct bstr bstr_splice(struct bstr str, int start, int end)
127 if (start < 0)
128 start += str.len;
129 if (end < 0)
130 end += str.len;
131 end = FFMIN(end, str.len);
132 start = FFMAX(start, 0);
133 end = FFMAX(end, start);
134 str.start += start;
135 str.len = end - start;
136 return str;
139 long long bstrtoll(struct bstr str, struct bstr *rest, int base)
141 str = bstr_lstrip(str);
142 char buf[51];
143 int len = FFMIN(str.len, 50);
144 memcpy(buf, str.start, len);
145 buf[len] = 0;
146 char *endptr;
147 long long r = strtoll(buf, &endptr, base);
148 if (rest)
149 *rest = bstr_cut(str, endptr - buf);
150 return r;
153 double bstrtod(struct bstr str, struct bstr *rest)
155 str = bstr_lstrip(str);
156 char buf[101];
157 int len = FFMIN(str.len, 100);
158 memcpy(buf, str.start, len);
159 buf[len] = 0;
160 char *endptr;
161 double r = strtod(buf, &endptr);
162 if (rest)
163 *rest = bstr_cut(str, endptr - buf);
164 return r;
167 struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str)
169 if (str.len == 0)
170 return NULL;
171 int count = 0;
172 for (int i = 0; i < str.len; i++)
173 if (str.start[i] == '\n')
174 count++;
175 if (str.start[str.len - 1] != '\n')
176 count++;
177 struct bstr *r = talloc_array_ptrtype(talloc_ctx, r, count);
178 unsigned char *p = str.start;
179 for (int i = 0; i < count - 1; i++) {
180 r[i].start = p;
181 while (*p++ != '\n');
182 r[i].len = p - r[i].start;
184 r[count - 1].start = p;
185 r[count - 1].len = str.start + str.len - p;
186 return r;
189 struct bstr bstr_getline(struct bstr str, struct bstr *rest)
191 int pos = bstrchr(str, '\n');
192 if (pos < 0)
193 pos = str.len;
194 if (rest)
195 *rest = bstr_cut(str, pos + 1);
196 return bstr_splice(str, 0, pos + 1);
199 bool bstr_eatstart(struct bstr *s, struct bstr prefix)
201 if (!bstr_startswith(*s, prefix))
202 return false;
203 *s = bstr_cut(*s, prefix.len);
204 return true;
207 void bstr_lower(struct bstr str)
209 for (int i = 0; i < str.len; i++)
210 str.start[i] = tolower(str.start[i]);
213 int bstr_sscanf(struct bstr str, const char *format, ...)
215 char *ptr = bstrdup0(NULL, str);
216 va_list va;
217 va_start(va, format);
218 int ret = vsscanf(ptr, format, va);
219 va_end(va);
220 talloc_free(ptr);
221 return ret;
224 int bstr_parse_utf8_code_length(unsigned char b)
226 if (b < 128)
227 return 1;
228 int bytes = 7 - av_log2(b ^ 255);
229 return (bytes >= 2 && bytes <= 4) ? bytes : -1;
232 int bstr_decode_utf8(struct bstr s, struct bstr *out_next)
234 if (s.len == 0)
235 return -1;
236 unsigned int codepoint = s.start[0];
237 s.start++; s.len--;
238 if (codepoint >= 128) {
239 int bytes = bstr_parse_utf8_code_length(codepoint);
240 if (bytes < 0 || s.len < bytes - 1)
241 return -1;
242 codepoint &= 127 >> bytes;
243 for (int n = 1; n < bytes; n++) {
244 int tmp = s.start[0];
245 if ((tmp & 0xC0) != 0x80)
246 return -1;
247 codepoint = (codepoint << 6) | (tmp & ~0xC0);
248 s.start++; s.len--;
251 if (out_next)
252 *out_next = s;
253 return codepoint;