Open Broadcaster Software
Free, open source software for live streaming and recording
dstr.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Hugh Bailey <obs.jim@gmail.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #pragma once
18 
19 #include <string.h>
20 #include <stdarg.h>
21 #include "c99defs.h"
22 #include "bmem.h"
23 
24 /*
25  * Dynamic string
26  *
27  * Helper struct/functions for dynamically sizing string buffers.
28  */
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 struct strref;
35 
36 struct dstr {
37  char *array;
38  size_t len; /* number of characters, excluding null terminator */
39  size_t capacity;
40 };
41 
42 #ifndef _MSC_VER
43 #define PRINTFATTR(f, a) __attribute__((__format__(__printf__, f, a)))
44 #else
45 #define PRINTFATTR(f, a)
46 #endif
47 
48 EXPORT int astrcmpi(const char *str1, const char *str2);
49 EXPORT int wstrcmpi(const wchar_t *str1, const wchar_t *str2);
50 EXPORT int astrcmp_n(const char *str1, const char *str2, size_t n);
51 EXPORT int wstrcmp_n(const wchar_t *str1, const wchar_t *str2, size_t n);
52 EXPORT int astrcmpi_n(const char *str1, const char *str2, size_t n);
53 EXPORT int wstrcmpi_n(const wchar_t *str1, const wchar_t *str2, size_t n);
54 
55 EXPORT char *astrstri(const char *str, const char *find);
56 EXPORT wchar_t *wstrstri(const wchar_t *str, const wchar_t *find);
57 
58 EXPORT char *strdepad(char *str);
59 EXPORT wchar_t *wcsdepad(wchar_t *str);
60 
61 EXPORT char **strlist_split(const char *str, char split_ch, bool include_empty);
62 EXPORT void strlist_free(char **strlist);
63 
64 static inline void dstr_init(struct dstr *dst);
65 static inline void dstr_init_move(struct dstr *dst, struct dstr *src);
66 static inline void dstr_init_move_array(struct dstr *dst, char *str);
67 static inline void dstr_init_copy(struct dstr *dst, const char *src);
68 static inline void dstr_init_copy_dstr(struct dstr *dst,
69  const struct dstr *src);
70 EXPORT void dstr_init_copy_strref(struct dstr *dst, const struct strref *src);
71 
72 static inline void dstr_free(struct dstr *dst);
73 static inline void dstr_array_free(struct dstr *array, const size_t count);
74 
75 static inline void dstr_move(struct dstr *dst, struct dstr *src);
76 static inline void dstr_move_array(struct dstr *dst, char *str);
77 
78 EXPORT void dstr_copy(struct dstr *dst, const char *array);
79 static inline void dstr_copy_dstr(struct dstr *dst, const struct dstr *src);
80 EXPORT void dstr_copy_strref(struct dstr *dst, const struct strref *src);
81 
82 EXPORT void dstr_ncopy(struct dstr *dst, const char *array,
83  const size_t len);
84 EXPORT void dstr_ncopy_dstr(struct dstr *dst, const struct dstr *src,
85  const size_t len);
86 
87 static inline void dstr_resize(struct dstr *dst, const size_t num);
88 static inline void dstr_reserve(struct dstr *dst, const size_t num);
89 
90 static inline bool dstr_is_empty(const struct dstr *str);
91 
92 static inline void dstr_cat(struct dstr *dst, const char *array);
93 EXPORT void dstr_cat_dstr(struct dstr *dst, const struct dstr *str);
94 EXPORT void dstr_cat_strref(struct dstr *dst, const struct strref *str);
95 
96 static inline void dstr_cat_ch(struct dstr *dst, char ch);
97 
98 EXPORT void dstr_ncat(struct dstr *dst, const char *array, const size_t len);
99 EXPORT void dstr_ncat_dstr(struct dstr *dst, const struct dstr *str,
100  const size_t len);
101 
102 EXPORT void dstr_insert(struct dstr *dst, const size_t idx,
103  const char *array);
104 EXPORT void dstr_insert_dstr(struct dstr *dst, const size_t idx,
105  const struct dstr *str);
106 EXPORT void dstr_insert_ch(struct dstr *dst, const size_t idx,
107  const char ch);
108 
109 EXPORT void dstr_remove(struct dstr *dst, const size_t idx, const size_t count);
110 
111 PRINTFATTR(2, 3)
112 EXPORT void dstr_printf(struct dstr *dst, const char *format, ...);
113 PRINTFATTR(2, 3)
114 EXPORT void dstr_catf(struct dstr *dst, const char *format, ...);
115 
116 EXPORT void dstr_vprintf(struct dstr *dst, const char *format, va_list args);
117 EXPORT void dstr_vcatf(struct dstr *dst, const char *format, va_list args);
118 
119 EXPORT void dstr_safe_printf(struct dstr *dst, const char *format,
120  const char *val1, const char *val2, const char *val3,
121  const char *val4);
122 
123 static inline const char *dstr_find_i(const struct dstr *str,
124  const char *find);
125 static inline const char *dstr_find(const struct dstr *str,
126  const char *find);
127 
128 EXPORT void dstr_replace(struct dstr *str, const char *find,
129  const char *replace);
130 
131 static inline int dstr_cmp(const struct dstr *str1, const char *str2);
132 static inline int dstr_cmpi(const struct dstr *str1, const char *str2);
133 static inline int dstr_ncmp(const struct dstr *str1, const char *str2,
134  const size_t n);
135 static inline int dstr_ncmpi(const struct dstr *str1, const char *str2,
136  const size_t n);
137 
138 EXPORT void dstr_depad(struct dstr *dst);
139 
140 EXPORT void dstr_left(struct dstr *dst, const struct dstr *str,
141  const size_t pos);
142 EXPORT void dstr_mid(struct dstr *dst, const struct dstr *str,
143  const size_t start, const size_t count);
144 EXPORT void dstr_right(struct dstr *dst, const struct dstr *str,
145  const size_t pos);
146 
147 static inline char dstr_end(const struct dstr *str);
148 
149 EXPORT void dstr_from_mbs(struct dstr *dst, const char *mbstr);
150 EXPORT char *dstr_to_mbs(const struct dstr *str);
151 EXPORT void dstr_from_wcs(struct dstr *dst, const wchar_t *wstr);
152 EXPORT wchar_t *dstr_to_wcs(const struct dstr *str);
153 
154 EXPORT void dstr_to_upper(struct dstr *str);
155 EXPORT void dstr_to_lower(struct dstr *str);
156 
157 #undef PRINTFATTR
158 
159 /* ------------------------------------------------------------------------- */
160 
161 static inline void dstr_init(struct dstr *dst)
162 {
163  dst->array = NULL;
164  dst->len = 0;
165  dst->capacity = 0;
166 }
167 
168 static inline void dstr_init_move_array(struct dstr *dst, char *str)
169 {
170  dst->array = str;
171  dst->len = (!str) ? 0 : strlen(str);
172  dst->capacity = dst->len + 1;
173 }
174 
175 static inline void dstr_init_move(struct dstr *dst, struct dstr *src)
176 {
177  *dst = *src;
178  dstr_init(src);
179 }
180 
181 static inline void dstr_init_copy(struct dstr *dst, const char *str)
182 {
183  dstr_init(dst);
184  dstr_copy(dst, str);
185 }
186 
187 static inline void dstr_init_copy_dstr(struct dstr *dst, const struct dstr *src)
188 {
189  dstr_init(dst);
190  dstr_copy_dstr(dst, src);
191 }
192 
193 static inline void dstr_free(struct dstr *dst)
194 {
195  bfree(dst->array);
196  dst->array = NULL;
197  dst->len = 0;
198  dst->capacity = 0;
199 }
200 
201 static inline void dstr_array_free(struct dstr *array, const size_t count)
202 {
203  size_t i;
204  for (i = 0; i < count; i++)
205  dstr_free(array+i);
206 }
207 
208 static inline void dstr_move_array(struct dstr *dst, char *str)
209 {
210  dstr_free(dst);
211  dst->array = str;
212  dst->len = (!str) ? 0 : strlen(str);
213  dst->capacity = dst->len + 1;
214 }
215 
216 static inline void dstr_move(struct dstr *dst, struct dstr *src)
217 {
218  dstr_free(dst);
219  dstr_init_move(dst, src);
220 }
221 
222 static inline void dstr_ensure_capacity(struct dstr *dst, const size_t new_size)
223 {
224  size_t new_cap;
225  if (new_size <= dst->capacity)
226  return;
227 
228  new_cap = (!dst->capacity) ? new_size : dst->capacity*2;
229  if (new_size > new_cap)
230  new_cap = new_size;
231  dst->array = (char*)brealloc(dst->array, new_cap);
232  dst->capacity = new_cap;
233 }
234 
235 static inline void dstr_copy_dstr(struct dstr *dst, const struct dstr *src)
236 {
237  if (dst->array)
238  dstr_free(dst);
239 
240  if (src->len) {
241  dstr_ensure_capacity(dst, src->len + 1);
242  memcpy(dst->array, src->array, src->len + 1);
243  dst->len = src->len;
244  }
245 }
246 
247 static inline void dstr_reserve(struct dstr *dst, const size_t capacity)
248 {
249  if (capacity == 0 || capacity <= dst->len)
250  return;
251 
252  dst->array = (char*)brealloc(dst->array, capacity);
253  dst->capacity = capacity;
254 }
255 
256 static inline void dstr_resize(struct dstr *dst, const size_t num)
257 {
258  if (!num) {
259  dstr_free(dst);
260  return;
261  }
262 
263  dstr_ensure_capacity(dst, num + 1);
264  dst->array[num] = 0;
265  dst->len = num;
266 }
267 
268 static inline bool dstr_is_empty(const struct dstr *str)
269 {
270  if (!str->array || !str->len)
271  return true;
272  if (!*str->array)
273  return true;
274 
275  return false;
276 }
277 
278 static inline void dstr_cat(struct dstr *dst, const char *array)
279 {
280  size_t len;
281  if (!array || !*array)
282  return;
283 
284  len = strlen(array);
285  dstr_ncat(dst, array, len);
286 }
287 
288 static inline void dstr_cat_ch(struct dstr *dst, char ch)
289 {
290  dstr_ensure_capacity(dst, ++dst->len + 1);
291  dst->array[dst->len-1] = ch;
292  dst->array[dst->len] = 0;
293 }
294 
295 static inline const char *dstr_find_i(const struct dstr *str, const char *find)
296 {
297  return astrstri(str->array, find);
298 }
299 
300 static inline const char *dstr_find(const struct dstr *str, const char *find)
301 {
302  return strstr(str->array, find);
303 }
304 
305 static inline int dstr_cmp(const struct dstr *str1, const char *str2)
306 {
307  return strcmp(str1->array, str2);
308 }
309 
310 static inline int dstr_cmpi(const struct dstr *str1, const char *str2)
311 {
312  return astrcmpi(str1->array, str2);
313 }
314 
315 static inline int dstr_ncmp(const struct dstr *str1, const char *str2,
316  const size_t n)
317 {
318  return astrcmp_n(str1->array, str2, n);
319 }
320 
321 static inline int dstr_ncmpi(const struct dstr *str1, const char *str2,
322  const size_t n)
323 {
324  return astrcmpi_n(str1->array, str2, n);
325 }
326 
327 static inline char dstr_end(const struct dstr *str)
328 {
329  if (dstr_is_empty(str))
330  return 0;
331 
332  return str->array[str->len - 1];
333 }
334 
335 #ifdef __cplusplus
336 }
337 #endif
EXPORT void dstr_ncopy_dstr(struct dstr *dst, const struct dstr *src, const size_t len)
EXPORT int wstrcmpi(const wchar_t *str1, const wchar_t *str2)
EXPORT int astrcmpi(const char *str1, const char *str2)
EXPORT void dstr_depad(struct dstr *dst)
EXPORT void dstr_ncopy(struct dstr *dst, const char *array, const size_t len)
EXPORT void dstr_mid(struct dstr *dst, const struct dstr *str, const size_t start, const size_t count)
EXPORT void dstr_to_upper(struct dstr *str)
EXPORT int astrcmp_n(const char *str1, const char *str2, size_t n)
EXPORT void dstr_replace(struct dstr *str, const char *find, const char *replace)
EXPORT void * brealloc(void *ptr, size_t size)
EXPORT char * dstr_to_mbs(const struct dstr *str)
EXPORT wchar_t * dstr_to_wcs(const struct dstr *str)
EXPORT void dstr_copy_strref(struct dstr *dst, const struct strref *src)
EXPORT wchar_t * wcsdepad(wchar_t *str)
EXPORT char ** strlist_split(const char *str, char split_ch, bool include_empty)
EXPORT int wstrcmp_n(const wchar_t *str1, const wchar_t *str2, size_t n)
EXPORT void dstr_ncat(struct dstr *dst, const char *array, const size_t len)
EXPORT void dstr_vcatf(struct dstr *dst, const char *format, va_list args)
EXPORT void dstr_init_copy_strref(struct dstr *dst, const struct strref *src)
EXPORT void dstr_insert_ch(struct dstr *dst, const size_t idx, const char ch)
EXPORT void dstr_insert(struct dstr *dst, const size_t idx, const char *array)
EXPORT void dstr_cat_dstr(struct dstr *dst, const struct dstr *str)
#define EXPORT
Definition: c99defs.h:53
EXPORT wchar_t * wstrstri(const wchar_t *str, const wchar_t *find)
EXPORT void dstr_copy(struct dstr *dst, const char *array)
EXPORT void dstr_to_lower(struct dstr *str)
EXPORT void dstr_safe_printf(struct dstr *dst, const char *format, const char *val1, const char *val2, const char *val3, const char *val4)
char * array
Definition: dstr.h:37
EXPORT void dstr_insert_dstr(struct dstr *dst, const size_t idx, const struct dstr *str)
EXPORT void dstr_vprintf(struct dstr *dst, const char *format, va_list args)
Definition: dstr.h:36
EXPORT char * astrstri(const char *str, const char *find)
EXPORT void dstr_cat_strref(struct dstr *dst, const struct strref *str)
EXPORT void dstr_printf(struct dstr *dst, const char *format,...)
size_t capacity
Definition: dstr.h:39
EXPORT int wstrcmpi_n(const wchar_t *str1, const wchar_t *str2, size_t n)
EXPORT void dstr_remove(struct dstr *dst, const size_t idx, const size_t count)
EXPORT void dstr_catf(struct dstr *dst, const char *format,...)
EXPORT void dstr_from_wcs(struct dstr *dst, const wchar_t *wstr)
EXPORT void dstr_right(struct dstr *dst, const struct dstr *str, const size_t pos)
#define PRINTFATTR(f, a)
Definition: dstr.h:43
EXPORT void strlist_free(char **strlist)
EXPORT void dstr_from_mbs(struct dstr *dst, const char *mbstr)
EXPORT int astrcmpi_n(const char *str1, const char *str2, size_t n)
size_t len
Definition: dstr.h:38
EXPORT char * strdepad(char *str)
EXPORT void bfree(void *ptr)
EXPORT void dstr_ncat_dstr(struct dstr *dst, const struct dstr *str, const size_t len)
EXPORT void dstr_left(struct dstr *dst, const struct dstr *str, const size_t pos)
Definition: lexer.h:30