string_util.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 This software was developed in the APRIL Robotics Lab under the
4 direction of Edwin Olson, ebolson@umich.edu. This software may be
5 available under alternative licensing terms; contact the address above.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 The views and conclusions contained in the software and documentation are those
24 of the authors and should not be interpreted as representing official policies,
25 either expressed or implied, of the Regents of The University of Michigan.
26 */
27 
28 #include <assert.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 
35 #include "string_util.h"
36 #include "zarray.h"
37 
39 {
40  char *s;
41  size_t alloc;
42  size_t size; // as if strlen() was called; not counting terminating \0
43 };
44 
45 #define MIN_PRINTF_ALLOC 16
46 
47 char *sprintf_alloc(const char *fmt, ...)
48 {
49  assert(fmt != NULL);
50 
51  va_list args;
52 
53  va_start(args,fmt);
54  char *buf = vsprintf_alloc(fmt, args);
55  va_end(args);
56 
57  return buf;
58 }
59 
60 char *vsprintf_alloc(const char *fmt, va_list orig_args)
61 {
62  assert(fmt != NULL);
63 
64  int size = MIN_PRINTF_ALLOC;
65  char *buf = malloc(size * sizeof(char));
66 
67  int returnsize;
68  va_list args;
69 
70  va_copy(args, orig_args);
71  returnsize = vsnprintf(buf, size, fmt, args);
72  va_end(args);
73 
74  // it was successful
75  if (returnsize < size) {
76  return buf;
77  }
78 
79  // otherwise, we should try again
80  free(buf);
81  size = returnsize + 1;
82  buf = malloc(size * sizeof(char));
83 
84  va_copy(args, orig_args);
85  returnsize = vsnprintf(buf, size, fmt, args);
86  va_end(args);
87 
88  assert(returnsize <= size);
89  return buf;
90 }
91 
92 char *_str_concat_private(const char *first, ...)
93 {
94  size_t len = 0;
95 
96  // get the total length (for the allocation)
97  {
98  va_list args;
99  va_start(args, first);
100  const char *arg = first;
101  while(arg != NULL) {
102  len += strlen(arg);
103  arg = va_arg(args, const char *);
104  }
105  va_end(args);
106  }
107 
108  // write the string
109  char *str = malloc(len*sizeof(char) + 1);
110  char *ptr = str;
111  {
112  va_list args;
113  va_start(args, first);
114  const char *arg = first;
115  while(arg != NULL) {
116  while(*arg)
117  *ptr++ = *arg++;
118  arg = va_arg(args, const char *);
119  }
120  *ptr = '\0';
121  va_end(args);
122  }
123 
124  return str;
125 }
126 
127 // Returns the index of the first character that differs:
128 int str_diff_idx(const char * a, const char * b)
129 {
130  assert(a != NULL);
131  assert(b != NULL);
132 
133  size_t i = 0;
134 
135  size_t lena = strlen(a);
136  size_t lenb = strlen(b);
137 
138  size_t minlen = lena < lenb ? lena : lenb;
139 
140  for (; i < minlen; i++)
141  if (a[i] != b[i])
142  break;
143 
144  return i;
145 }
146 
147 
148 zarray_t *str_split(const char *str, const char *delim)
149 {
150  assert(str != NULL);
151  assert(delim != NULL);
152 
153  zarray_t *parts = zarray_create(sizeof(char*));
155 
156  size_t delim_len = strlen(delim);
157  size_t len = strlen(str);
158  size_t pos = 0;
159 
160  while (pos < len) {
161  if (str_starts_with(&str[pos], delim) && delim_len > 0) {
162  pos += delim_len;
163  // never add empty strings (repeated tokens)
164  if (string_buffer_size(sb) > 0) {
165  char *part = string_buffer_to_string(sb);
166  zarray_add(parts, &part);
167  }
169  } else {
170  string_buffer_append(sb, str[pos]);
171  pos++;
172  }
173  }
174 
175  if (string_buffer_size(sb) > 0) {
176  char *part = string_buffer_to_string(sb);
177  zarray_add(parts, &part);
178  }
179 
181  return parts;
182 }
183 
184 // split on one or more spaces.
185 zarray_t *str_split_spaces(const char *str)
186 {
187  zarray_t *parts = zarray_create(sizeof(char*));
188  size_t len = strlen(str);
189  size_t pos = 0;
190 
191  while (pos < len) {
192 
193  while (pos < len && str[pos] == ' ')
194  pos++;
195 
196  // produce a token?
197  if (pos < len) {
198  // yes!
199  size_t off0 = pos;
200  while (pos < len && str[pos] != ' ')
201  pos++;
202  size_t off1 = pos;
203 
204  size_t len_off = off1 - off0;
205  char *tok = malloc(len_off + 1);
206  memcpy(tok, &str[off0], len_off);
207  tok[len_off] = 0;
208  zarray_add(parts, &tok);
209  }
210  }
211 
212  return parts;
213 }
214 
216 {
217  if (!za)
218  return;
219 
220  zarray_vmap(za, free);
221  zarray_destroy(za);
222 }
223 
224 char *str_trim(char *str)
225 {
226  assert(str != NULL);
227 
228  return str_lstrip(str_rstrip(str));
229 }
230 
231 char *str_lstrip(char *str)
232 {
233  assert(str != NULL);
234 
235  char *ptr = str;
236  char *end = str + strlen(str);
237  for(; ptr != end && isspace(*ptr); ptr++);
238  // shift the string to the left so the original pointer still works
239  memmove(str, ptr, strlen(ptr)+1);
240  return str;
241 }
242 
243 char *str_rstrip(char *str)
244 {
245  assert(str != NULL);
246 
247  char *ptr = str + strlen(str) - 1;
248  for(; ptr+1 != str && isspace(*ptr); ptr--);
249  *(ptr+1) = '\0';
250  return str;
251 }
252 
253 int str_indexof(const char *haystack, const char *needle)
254 {
255  assert(haystack != NULL);
256  assert(needle != NULL);
257 
258  // use signed types for hlen/nlen because hlen - nlen can be negative.
259  int hlen = (int) strlen(haystack);
260  int nlen = (int) strlen(needle);
261 
262  if (nlen > hlen) return -1;
263 
264  for (int i = 0; i <= hlen - nlen; i++) {
265  if (!strncmp(&haystack[i], needle, nlen))
266  return i;
267  }
268 
269  return -1;
270 }
271 
272 int str_last_indexof(const char *haystack, const char *needle)
273 {
274  assert(haystack != NULL);
275  assert(needle != NULL);
276 
277  // use signed types for hlen/nlen because hlen - nlen can be negative.
278  int hlen = (int) strlen(haystack);
279  int nlen = (int) strlen(needle);
280 
281  int last_index = -1;
282  for (int i = 0; i <= hlen - nlen; i++) {
283  if (!strncmp(&haystack[i], needle, nlen))
284  last_index = i;
285  }
286 
287  return last_index;
288 }
289 
290 // in-place modification.
291 char *str_tolowercase(char *s)
292 {
293  assert(s != NULL);
294 
295  size_t slen = strlen(s);
296  for (size_t i = 0; i < slen; i++) {
297  if (s[i] >= 'A' && s[i] <= 'Z')
298  s[i] = s[i] + 'a' - 'A';
299  }
300 
301  return s;
302 }
303 
304 char *str_touppercase(char *s)
305 {
306  assert(s != NULL);
307 
308  size_t slen = strlen(s);
309  for (size_t i = 0; i < slen; i++) {
310  if (s[i] >= 'a' && s[i] <= 'z')
311  s[i] = s[i] - ('a' - 'A');
312  }
313 
314  return s;
315 }
316 
318 {
319  string_buffer_t *sb = (string_buffer_t*) calloc(1, sizeof(string_buffer_t));
320  assert(sb != NULL);
321  sb->alloc = 32;
322  sb->s = calloc(sb->alloc, 1);
323  return sb;
324 }
325 
327 {
328  if (sb == NULL)
329  return;
330 
331  if (sb->s)
332  free(sb->s);
333 
334  memset(sb, 0, sizeof(string_buffer_t));
335  free(sb);
336 }
337 
339 {
340  assert(sb != NULL);
341 
342  if (sb->size+2 >= sb->alloc) {
343  sb->alloc *= 2;
344  sb->s = realloc(sb->s, sb->alloc);
345  }
346 
347  sb->s[sb->size++] = c;
348  sb->s[sb->size] = 0;
349 }
350 
352  assert(sb != NULL);
353  if (sb->size == 0)
354  return 0;
355 
356  char back = sb->s[--sb->size];
357  sb->s[sb->size] = 0;
358  return back;
359 }
360 
361 void string_buffer_appendf(string_buffer_t *sb, const char *fmt, ...)
362 {
363  assert(sb != NULL);
364  assert(fmt != NULL);
365 
366  int size = MIN_PRINTF_ALLOC;
367  char *buf = malloc(size * sizeof(char));
368 
369  int returnsize;
370  va_list args;
371 
372  va_start(args,fmt);
373  returnsize = vsnprintf(buf, size, fmt, args);
374  va_end(args);
375 
376  if (returnsize >= size) {
377  // otherwise, we should try again
378  free(buf);
379  size = returnsize + 1;
380  buf = malloc(size * sizeof(char));
381 
382  va_start(args, fmt);
383  returnsize = vsnprintf(buf, size, fmt, args);
384  va_end(args);
385 
386  assert(returnsize <= size);
387  }
388 
390  free(buf);
391 }
392 
394 {
395  assert(sb != NULL);
396  assert(str != NULL);
397 
398  size_t len = strlen(str);
399 
400  while (sb->size+len + 1 >= sb->alloc) {
401  sb->alloc *= 2;
402  sb->s = realloc(sb->s, sb->alloc);
403  }
404 
405  memcpy(&sb->s[sb->size], str, len);
406  sb->size += len;
407  sb->s[sb->size] = 0;
408 }
409 
410 bool string_buffer_ends_with(string_buffer_t *sb, const char *str)
411 {
412  assert(sb != NULL);
413  assert(str != NULL);
414 
415  return str_ends_with(sb->s, str);
416 }
417 
419 {
420  assert(sb != NULL);
421 
422  return strdup(sb->s);
423 }
424 
425 // returns length of string (not counting \0)
427 {
428  assert(sb != NULL);
429 
430  return sb->size;
431 }
432 
434 {
435  assert(sb != NULL);
436 
437  sb->s[0] = 0;
438  sb->size = 0;
439 }
440 
442 {
443  assert(str != NULL);
444 
445  string_feeder_t *sf = (string_feeder_t*) calloc(1, sizeof(string_feeder_t));
446  sf->s = strdup(str);
447  sf->len = strlen(sf->s);
448  sf->line = 1;
449  sf->col = 0;
450  sf->pos = 0;
451  return sf;
452 }
453 
455 {
456  assert(sf != NULL);
457  return sf->line;
458 }
459 
461 {
462  assert(sf != NULL);
463  return sf->col;
464 }
465 
467 {
468  if (sf == NULL)
469  return;
470 
471  free(sf->s);
472  memset(sf, 0, sizeof(string_feeder_t));
473  free(sf);
474 }
475 
477 {
478  assert(sf != NULL);
479 
480  return sf->s[sf->pos] != 0 && sf->pos <= sf->len;
481 }
482 
484 {
485  assert(sf != NULL);
486  assert(sf->pos <= sf->len);
487 
488  char c = sf->s[sf->pos++];
489  if (c == '\n') {
490  sf->line++;
491  sf->col = 0;
492  } else {
493  sf->col++;
494  }
495 
496  return c;
497 }
498 
500 {
501  assert(sf != NULL);
502  assert(sf->pos <= sf->len);
503 
504  if (sf->pos + length > sf->len)
505  length = sf->len - sf->pos;
506 
507  char *substr = calloc(length+1, sizeof(char));
508  for (size_t i = 0 ; i < length ; i++)
509  substr[i] = string_feeder_next(sf);
510  return substr;
511 }
512 
514 {
515  assert(sf != NULL);
516  assert(sf->pos <= sf->len);
517 
518  return sf->s[sf->pos];
519 }
520 
522 {
523  assert(sf != NULL);
524  assert(sf->pos <= sf->len);
525 
526  if (sf->pos + length > sf->len)
527  length = sf->len - sf->pos;
528 
529  char *substr = calloc(length+1, sizeof(char));
530  memcpy(substr, &sf->s[sf->pos], length*sizeof(char));
531  return substr;
532 }
533 
534 bool string_feeder_starts_with(string_feeder_t *sf, const char *str)
535 {
536  assert(sf != NULL);
537  assert(str != NULL);
538  assert(sf->pos <= sf->len);
539 
540  return str_starts_with(&sf->s[sf->pos], str);
541 }
542 
543 void string_feeder_require(string_feeder_t *sf, const char *str)
544 {
545  assert(sf != NULL);
546  assert(str != NULL);
547  assert(sf->pos <= sf->len);
548 
549  size_t len = strlen(str);
550 
551  for (size_t i = 0; i < len; i++) {
552  char c = string_feeder_next(sf);
553  assert(c == str[i]);
554  (void)c;
555  }
556 }
557 
559 bool str_ends_with(const char *haystack, const char *needle)
560 {
561  assert(haystack != NULL);
562  assert(needle != NULL);
563 
564  size_t lens = strlen(haystack);
565  size_t lenneedle = strlen(needle);
566 
567  if (lenneedle > lens)
568  return false;
569 
570  return !strncmp(&haystack[lens - lenneedle], needle, lenneedle);
571 }
572 
573 #ifndef _MSC_VER
574 inline
575 #endif
576 bool str_starts_with(const char *haystack, const char *needle)
577 {
578  assert(haystack != NULL);
579  assert(needle != NULL);
580 
581  // haystack[pos] doesn't have to be compared to zero; if it were
582  // zero, it either doesn't match needle (in which case the loop
583  // terminates) or it matches needle[pos] (in which case the loop
584  // terminates).
585  int pos = 0;
586  while (haystack[pos] == needle[pos] && needle[pos] != 0)
587  pos++;
588 
589  return (needle[pos] == 0);
590 }
591 
592 bool str_starts_with_any(const char *haystack, const char **needles, int num_needles)
593 {
594  assert(haystack != NULL);
595  assert(needles != NULL);
596  assert(num_needles >= 0);
597 
598  for (int i = 0; i < num_needles; i++) {
599  assert(needles[i] != NULL);
600  if (str_starts_with(haystack, needles[i]))
601  return true;
602  }
603 
604  return false;
605 }
606 
607 bool str_matches_any(const char *haystack, const char **needles, int num_needles)
608 {
609  assert(haystack != NULL);
610  assert(needles != NULL);
611  assert(num_needles >= 0);
612 
613  for (int i = 0; i < num_needles; i++) {
614  assert(needles[i] != NULL);
615  if (!strcmp(haystack, needles[i]))
616  return true;
617  }
618 
619  return false;
620 }
621 
622 char *str_substring(const char *str, size_t startidx, size_t endidx)
623 {
624  assert(str != NULL);
625  assert(startidx <= strlen(str)+1);
626  assert(endidx >= startidx);
627  assert(endidx <= strlen(str)+1);
628 
629  size_t blen = endidx - startidx; // not counting \0
630  char *b = malloc(blen + 1);
631  memcpy(b, &str[startidx], blen);
632  b[blen] = 0;
633  return b;
634 }
635 
636 char *str_replace(const char *haystack, const char *needle, const char *replacement)
637 {
638  assert(haystack != NULL);
639  assert(needle != NULL);
640  assert(replacement != NULL);
641 
643  size_t haystack_len = strlen(haystack);
644  size_t needle_len = strlen(needle);
645 
646  size_t pos = 0;
647  while (pos < haystack_len) {
648  if (needle_len > 0 && str_starts_with(&haystack[pos], needle)) {
649  string_buffer_append_string(sb, replacement);
650  pos += needle_len;
651  } else {
652  string_buffer_append(sb, haystack[pos]);
653  pos++;
654  }
655  }
656  if (needle_len == 0 && haystack_len == 0)
657  string_buffer_append_string(sb, replacement);
658 
659  char *res = string_buffer_to_string(sb);
661  return res;
662 }
663 
664 char *str_replace_many(const char *_haystack, ...)
665 {
666  va_list ap;
667  va_start(ap, _haystack);
668 
669  char *haystack = strdup(_haystack);
670 
671  while (true) {
672  char *needle = va_arg(ap, char*);
673  if (!needle)
674  break;
675 
676  char *replacement = va_arg(ap, char*);
677  char *tmp = str_replace(haystack, needle, replacement);
678  free(haystack);
679  haystack = tmp;
680  }
681 
682  va_end(ap);
683 
684  return haystack;
685 }
686 
687 static void buffer_appendf(char **_buf, int *bufpos, void *fmt, ...)
688 {
689  char *buf = *_buf;
690  va_list ap;
691 
692  int salloc = 128;
693  char *s = malloc(salloc);
694 
695  va_start(ap, fmt);
696  int slen = vsnprintf(s, salloc, fmt, ap);
697  va_end(ap);
698 
699  if (slen >= salloc) {
700  s = realloc(s, slen + 1);
701  va_start(ap, fmt);
702  vsprintf((char*) s, fmt, ap);
703  va_end(ap);
704  }
705 
706  buf = realloc(buf, *bufpos + slen + 1);
707  *_buf = buf;
708 
709  memcpy(&buf[*bufpos], s, slen + 1); // get trailing \0
710  (*bufpos) += slen;
711 
712  free(s);
713 }
714 
715 static int is_variable_character(char c)
716 {
717  if (c >= 'a' && c <= 'z')
718  return 1;
719 
720  if (c >= 'A' && c <= 'Z')
721  return 1;
722 
723  if (c >= '0' && c <= '9')
724  return 1;
725 
726  if (c == '_')
727  return 1;
728 
729  return 0;
730 }
731 
732 char *str_expand_envs(const char *in)
733 {
734  size_t inlen = strlen(in);
735  size_t inpos = 0;
736 
737  char *out = NULL;
738  int outpos = 0;
739 
740  while (inpos < inlen) {
741 
742  if (in[inpos] != '$') {
743  buffer_appendf(&out, &outpos, "%c", in[inpos]);
744  inpos++;
745  continue;
746 
747  } else {
748  inpos++; // consume '$'
749 
750  char *varname = NULL;
751  int varnamepos = 0;
752 
753  while (inpos < inlen && is_variable_character(in[inpos])) {
754  buffer_appendf(&varname, &varnamepos, "%c", in[inpos]);
755  inpos++;
756  }
757 
758  char *env = getenv(varname);
759  if (env)
760  buffer_appendf(&out, &outpos, "%s", env);
761 
762  free(varname);
763  }
764  }
765 
766  return out;
767 }
str_split
zarray_t * str_split(const char *str, const char *delim)
Definition: string_util.c:148
zarray_create
static zarray_t * zarray_create(size_t el_sz)
Definition: zarray.h:57
str_last_indexof
int str_last_indexof(const char *haystack, const char *needle)
Definition: string_util.c:272
string_feeder_peek_length
char * string_feeder_peek_length(string_feeder_t *sf, size_t length)
Definition: string_util.c:521
str_indexof
int str_indexof(const char *haystack, const char *needle)
Definition: string_util.c:253
string_feeder_get_column
int string_feeder_get_column(string_feeder_t *sf)
Definition: string_util.c:460
zarray_destroy
static void zarray_destroy(zarray_t *za)
Definition: zarray.h:70
MIN_PRINTF_ALLOC
#define MIN_PRINTF_ALLOC
Definition: string_util.c:45
str_touppercase
char * str_touppercase(char *s)
Definition: string_util.c:304
string_feeder::len
size_t len
Definition: string_util.h:48
zarray
Definition: zarray.h:43
string_buffer_create
string_buffer_t * string_buffer_create()
Definition: string_util.c:317
string_buffer
Definition: string_util.c:38
str_substring
char * str_substring(const char *str, size_t startidx, size_t endidx)
Definition: string_util.c:622
is_variable_character
static int is_variable_character(char c)
Definition: string_util.c:715
string_feeder_destroy
void string_feeder_destroy(string_feeder_t *sf)
Definition: string_util.c:466
sprintf_alloc
char * sprintf_alloc(const char *fmt,...)
Definition: string_util.c:47
str_split_spaces
zarray_t * str_split_spaces(const char *str)
Definition: string_util.c:185
str_lstrip
char * str_lstrip(char *str)
Definition: string_util.c:231
string_feeder
Definition: string_util.h:45
string_buffer::s
char * s
Definition: string_util.c:40
str_ends_with
bool str_ends_with(const char *haystack, const char *needle)
Definition: string_util.c:559
string_buffer_append
void string_buffer_append(string_buffer_t *sb, char c)
Definition: string_util.c:338
string_buffer_append_string
void string_buffer_append_string(string_buffer_t *sb, const char *str)
Definition: string_util.c:393
str_starts_with_any
bool str_starts_with_any(const char *haystack, const char **needles, int num_needles)
Definition: string_util.c:592
string_feeder::pos
size_t pos
Definition: string_util.h:49
string_buffer_ends_with
bool string_buffer_ends_with(string_buffer_t *sb, const char *str)
Definition: string_util.c:410
string_buffer::size
size_t size
Definition: string_util.c:42
string_buffer_destroy
void string_buffer_destroy(string_buffer_t *sb)
Definition: string_util.c:326
string_feeder_peek
char string_feeder_peek(string_feeder_t *sf)
Definition: string_util.c:513
str_diff_idx
int str_diff_idx(const char *a, const char *b)
Definition: string_util.c:128
_str_concat_private
char * _str_concat_private(const char *first,...)
Definition: string_util.c:92
string_feeder_starts_with
bool string_feeder_starts_with(string_feeder_t *sf, const char *str)
Definition: string_util.c:534
string_buffer_to_string
char * string_buffer_to_string(string_buffer_t *sb)
Definition: string_util.c:418
str_rstrip
char * str_rstrip(char *str)
Definition: string_util.c:243
zarray_add
static void zarray_add(zarray_t *za, const void *p)
Definition: zarray.h:179
string_buffer::alloc
size_t alloc
Definition: string_util.c:41
string_feeder::line
int line
Definition: string_util.h:51
string_feeder::s
char * s
Definition: string_util.h:47
string_buffer_appendf
void string_buffer_appendf(string_buffer_t *sb, const char *fmt,...)
Definition: string_util.c:361
str_trim
char * str_trim(char *str)
Definition: string_util.c:224
str_matches_any
bool str_matches_any(const char *haystack, const char **needles, int num_needles)
Definition: string_util.c:607
str_split_destroy
void str_split_destroy(zarray_t *za)
Definition: string_util.c:215
string_feeder_get_line
int string_feeder_get_line(string_feeder_t *sf)
Definition: string_util.c:454
string_feeder::col
int col
Definition: string_util.h:51
string_buffer_size
size_t string_buffer_size(string_buffer_t *sb)
Definition: string_util.c:426
string_util.h
string_feeder_next_length
char * string_feeder_next_length(string_feeder_t *sf, size_t length)
Definition: string_util.c:499
zarray.h
str_expand_envs
char * str_expand_envs(const char *in)
Definition: string_util.c:732
string_feeder_has_next
bool string_feeder_has_next(string_feeder_t *sf)
Definition: string_util.c:476
str_tolowercase
char * str_tolowercase(char *s)
Definition: string_util.c:291
zarray_vmap
void zarray_vmap(zarray_t *za, void(*f)(void *))
Definition: zarray.c:44
string_buffer_pop_back
char string_buffer_pop_back(string_buffer_t *sb)
Definition: string_util.c:351
str_replace
char * str_replace(const char *haystack, const char *needle, const char *replacement)
Definition: string_util.c:636
string_buffer_reset
void string_buffer_reset(string_buffer_t *sb)
Definition: string_util.c:433
vsprintf_alloc
char * vsprintf_alloc(const char *fmt, va_list orig_args)
Definition: string_util.c:60
string_feeder_create
string_feeder_t * string_feeder_create(const char *str)
Definition: string_util.c:441
string_feeder_require
void string_feeder_require(string_feeder_t *sf, const char *str)
Definition: string_util.c:543
buffer_appendf
static void buffer_appendf(char **_buf, int *bufpos, void *fmt,...)
Definition: string_util.c:687
str_replace_many
char * str_replace_many(const char *_haystack,...)
Definition: string_util.c:664
string_feeder_next
char string_feeder_next(string_feeder_t *sf)
Definition: string_util.c:483
str_starts_with
bool str_starts_with(const char *haystack, const char *needle)
Definition: string_util.c:576


apriltag
Author(s): Edwin Olson , Max Krogius
autogenerated on Sun Apr 20 2025 02:08:19