Blender  V2.93
string.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <ctype.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "BLI_dynstr.h"
35 #include "BLI_string.h"
36 
37 #include "BLI_utildefines.h"
38 
39 #ifdef __GNUC__
40 # pragma GCC diagnostic error "-Wsign-conversion"
41 #endif
42 
43 // #define DEBUG_STRSIZE
44 
54 char *BLI_strdupn(const char *str, const size_t len)
55 {
56  char *n = MEM_mallocN(len + 1, "strdup");
57  memcpy(n, str, len);
58  n[len] = '\0';
59 
60  return n;
61 }
62 
70 char *BLI_strdup(const char *str)
71 {
72  return BLI_strdupn(str, strlen(str));
73 }
74 
81 char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
82 {
83  /* include the NULL terminator of str2 only */
84  const size_t str1_len = strlen(str1);
85  const size_t str2_len = strlen(str2) + 1;
86  char *str, *s;
87 
88  str = MEM_mallocN(str1_len + str2_len, "strdupcat");
89  s = str;
90 
91  memcpy(s, str1, str1_len); /* NOLINT: bugprone-not-null-terminated-result */
92  s += str1_len;
93  memcpy(s, str2, str2_len);
94 
95  return str;
96 }
97 
108 char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
109 {
110  size_t srclen = BLI_strnlen(src, maxncpy - 1);
111  BLI_assert(maxncpy != 0);
112 
113 #ifdef DEBUG_STRSIZE
114  memset(dst, 0xff, sizeof(*dst) * maxncpy);
115 #endif
116 
117  memcpy(dst, src, srclen);
118  dst[srclen] = '\0';
119  return dst;
120 }
121 
132 char *BLI_strncpy_ensure_pad(char *__restrict dst,
133  const char *__restrict src,
134  const char pad,
135  size_t maxncpy)
136 {
137  BLI_assert(maxncpy != 0);
138 
139 #ifdef DEBUG_STRSIZE
140  memset(dst, 0xff, sizeof(*dst) * maxncpy);
141 #endif
142 
143  if (src[0] == '\0') {
144  dst[0] = '\0';
145  }
146  else {
147  /* Add heading/trailing wildcards if needed. */
148  size_t idx = 0;
149  size_t srclen;
150 
151  if (src[idx] != pad) {
152  dst[idx++] = pad;
153  maxncpy--;
154  }
155  maxncpy--; /* trailing '\0' */
156 
157  srclen = BLI_strnlen(src, maxncpy);
158  if ((src[srclen - 1] != pad) && (srclen == maxncpy)) {
159  srclen--;
160  }
161 
162  memcpy(&dst[idx], src, srclen);
163  idx += srclen;
164 
165  if (dst[idx - 1] != pad) {
166  dst[idx++] = pad;
167  }
168  dst[idx] = '\0';
169  }
170 
171  return dst;
172 }
173 
187 size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
188 {
189  size_t srclen = BLI_strnlen(src, maxncpy - 1);
190  BLI_assert(maxncpy != 0);
191 
192 #ifdef DEBUG_STRSIZE
193  memset(dst, 0xff, sizeof(*dst) * maxncpy);
194 #endif
195 
196  memcpy(dst, src, srclen);
197  dst[srclen] = '\0';
198  return srclen;
199 }
200 
201 size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
202 {
203  size_t srclen = strlen(src);
204  memcpy(dst, src, srclen + 1);
205  return srclen;
206 }
207 
211 size_t BLI_vsnprintf(char *__restrict buffer,
212  size_t maxncpy,
213  const char *__restrict format,
214  va_list arg)
215 {
216  size_t n;
217 
218  BLI_assert(buffer != NULL);
219  BLI_assert(maxncpy > 0);
220  BLI_assert(format != NULL);
221 
222  n = (size_t)vsnprintf(buffer, maxncpy, format, arg);
223 
224  if (n != -1 && n < maxncpy) {
225  buffer[n] = '\0';
226  }
227  else {
228  buffer[maxncpy - 1] = '\0';
229  }
230 
231  return n;
232 }
233 
237 size_t BLI_vsnprintf_rlen(char *__restrict buffer,
238  size_t maxncpy,
239  const char *__restrict format,
240  va_list arg)
241 {
242  size_t n;
243 
244  BLI_assert(buffer != NULL);
245  BLI_assert(maxncpy > 0);
246  BLI_assert(format != NULL);
247 
248  n = (size_t)vsnprintf(buffer, maxncpy, format, arg);
249 
250  if (n != -1 && n < maxncpy) {
251  /* pass */
252  }
253  else {
254  n = maxncpy - 1;
255  }
256  buffer[n] = '\0';
257 
258  return n;
259 }
260 
264 size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
265 {
266  size_t n;
267  va_list arg;
268 
269 #ifdef DEBUG_STRSIZE
270  memset(dst, 0xff, sizeof(*dst) * maxncpy);
271 #endif
272 
273  va_start(arg, format);
274  n = BLI_vsnprintf(dst, maxncpy, format, arg);
275  va_end(arg);
276 
277  return n;
278 }
279 
283 size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
284 {
285  size_t n;
286  va_list arg;
287 
288 #ifdef DEBUG_STRSIZE
289  memset(dst, 0xff, sizeof(*dst) * maxncpy);
290 #endif
291 
292  va_start(arg, format);
293  n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg);
294  va_end(arg);
295 
296  return n;
297 }
298 
303 char *BLI_sprintfN(const char *__restrict format, ...)
304 {
305  DynStr *ds;
306  va_list arg;
307  char *n;
308 
309  va_start(arg, format);
310 
311  ds = BLI_dynstr_new();
312  BLI_dynstr_vappendf(ds, format, arg);
313  n = BLI_dynstr_get_cstring(ds);
314  BLI_dynstr_free(ds);
315 
316  va_end(arg);
317 
318  return n;
319 }
320 
333 size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy)
334 {
335 
336  BLI_assert(dst_maxncpy != 0);
337 
338  size_t len = 0;
339  for (; (len < dst_maxncpy) && (*src != '\0'); dst++, src++, len++) {
340  char c = *src;
341  if (ELEM(c, '\\', '"') || /* Use as-is. */
342  ((c == '\t') && ((void)(c = 't'), true)) || /* Tab. */
343  ((c == '\n') && ((void)(c = 'n'), true)) || /* Newline. */
344  ((c == '\r') && ((void)(c = 'r'), true)) || /* Carriage return. */
345  ((c == '\a') && ((void)(c = 'a'), true)) || /* Bell. */
346  ((c == '\b') && ((void)(c = 'b'), true)) || /* Backspace. */
347  ((c == '\f') && ((void)(c = 'f'), true))) /* Form-feed. */
348  {
349  if (UNLIKELY(len + 1 >= dst_maxncpy)) {
350  /* Not enough space to escape. */
351  break;
352  }
353  *dst++ = '\\';
354  len++;
355  }
356  *dst = c;
357  }
358  *dst = '\0';
359 
360  return len;
361 }
362 
375 size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy)
376 {
377  size_t len = 0;
378  for (size_t i = 0; i < src_maxncpy && (*src != '\0'); i++, src++) {
379  char c = *src;
380  if (c == '\\') {
381  char c_next = *(src + 1);
382  if (((c_next == '"') && ((void)(c = '"'), true)) || /* Quote. */
383  ((c_next == '\\') && ((void)(c = '\\'), true)) || /* Backslash. */
384  ((c_next == 't') && ((void)(c = '\t'), true)) || /* Tab. */
385  ((c_next == 'n') && ((void)(c = '\n'), true)) || /* Newline. */
386  ((c_next == 'r') && ((void)(c = '\r'), true)) || /* Carriage return. */
387  ((c_next == 'a') && ((void)(c = '\a'), true)) || /* Bell. */
388  ((c_next == 'b') && ((void)(c = '\b'), true)) || /* Backspace. */
389  ((c_next == 'f') && ((void)(c = '\f'), true))) /* Form-feed. */
390  {
391  i++;
392  src++;
393  }
394  }
395 
396  dst[len++] = c;
397  }
398  dst[len] = 0;
399  return len;
400 }
401 
410 const char *BLI_str_escape_find_quote(const char *str)
411 {
412  bool escape = false;
413  while (*str && (*str != '"' || escape)) {
414  /* A pair of back-slashes represents a single back-slash,
415  * only use a single back-slash for escaping. */
416  escape = (escape == false) && (*str == '\\');
417  str++;
418  }
419  return (*str == '"') ? str : NULL;
420 }
421 
432 char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
433 {
434  const char *start_match, *end_match;
435 
436  /* get the starting point (i.e. where prefix starts, and add prefix_len+1
437  * to it to get be after the first " */
438  start_match = strstr(str, prefix);
439  if (start_match) {
440  const size_t prefix_len = strlen(prefix);
441  start_match += prefix_len + 1;
442  /* get the end point (i.e. where the next occurrence of " is after the starting point) */
443  end_match = BLI_str_escape_find_quote(start_match);
444  if (end_match) {
445  const size_t escaped_len = (size_t)(end_match - start_match);
446  char *result = MEM_mallocN(sizeof(char) * (escaped_len + 1), __func__);
447  const size_t unescaped_len = BLI_str_unescape(result, start_match, escaped_len);
448  if (unescaped_len != escaped_len) {
449  result = MEM_reallocN(result, sizeof(char) * (unescaped_len + 1));
450  }
451  return result;
452  }
453  }
454  return NULL;
455 }
456 
470 char *BLI_str_replaceN(const char *__restrict str,
471  const char *__restrict substr_old,
472  const char *__restrict substr_new)
473 {
474  DynStr *ds = NULL;
475  size_t len_old = strlen(substr_old);
476  const char *match;
477 
478  BLI_assert(substr_old[0] != '\0');
479 
480  /* While we can still find a match for the old sub-string that we're searching for,
481  * keep dicing and replacing. */
482  while ((match = strstr(str, substr_old))) {
483  /* the assembly buffer only gets created when we actually need to rebuild the string */
484  if (ds == NULL) {
485  ds = BLI_dynstr_new();
486  }
487 
488  /* If the match position does not match the current position in the string,
489  * copy the text up to this position and advance the current position in the string. */
490  if (str != match) {
491  /* Add the segment of the string from `str` to match to the buffer,
492  * then restore the value at match. */
493  BLI_dynstr_nappend(ds, str, (match - str));
494 
495  /* now our current position should be set on the start of the match */
496  str = match;
497  }
498 
499  /* Add the replacement text to the accumulation buffer. */
500  BLI_dynstr_append(ds, substr_new);
501 
502  /* Advance the current position of the string up to the end of the replaced segment. */
503  str += len_old;
504  }
505 
506  /* Finish off and return a new string that has had all occurrences of. */
507  if (ds) {
508  char *str_new;
509 
510  /* Add what's left of the string to the assembly buffer
511  * - we've been adjusting `str` to point at the end of the replaced segments. */
512  BLI_dynstr_append(ds, str);
513 
514  /* Convert to new c-string (MEM_malloc'd), and free the buffer. */
515  str_new = BLI_dynstr_get_cstring(ds);
516  BLI_dynstr_free(ds);
517 
518  return str_new;
519  }
520  /* Just create a new copy of the entire string - we avoid going through the assembly buffer
521  * for what should be a bit more efficiency. */
522  return BLI_strdup(str);
523 }
524 
532 void BLI_str_replace_char(char *str, char src, char dst)
533 {
534  while (*str) {
535  if (*str == src) {
536  *str = dst;
537  }
538  str++;
539  }
540 }
541 
549 bool BLI_str_replace_table_exact(char *string,
550  const size_t string_len,
551  const char *replace_table[][2],
552  int replace_table_len)
553 {
554  for (int i = 0; i < replace_table_len; i++) {
555  if (STREQ(string, replace_table[i][0])) {
556  BLI_strncpy(string, replace_table[i][1], string_len);
557  return true;
558  }
559  }
560  return false;
561 }
562 
570 int BLI_strcaseeq(const char *a, const char *b)
571 {
572  return (BLI_strcasecmp(a, b) == 0);
573 }
574 
578 char *BLI_strcasestr(const char *s, const char *find)
579 {
580  char c, sc;
581  size_t len;
582 
583  if ((c = *find++) != 0) {
584  c = tolower(c);
585  len = strlen(find);
586  do {
587  do {
588  if ((sc = *s++) == 0) {
589  return NULL;
590  }
591  sc = tolower(sc);
592  } while (sc != c);
593  } while (BLI_strncasecmp(s, find, len) != 0);
594  s--;
595  }
596  return ((char *)s);
597 }
598 
600 {
601  return (str_len / 2) + 1;
602 }
603 
604 bool BLI_string_has_word_prefix(const char *haystack, const char *needle, size_t needle_len)
605 {
606  const char *match = BLI_strncasestr(haystack, needle, needle_len);
607  if (match) {
608  if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) {
609  return true;
610  }
611  return BLI_string_has_word_prefix(match + 1, needle, needle_len);
612  }
613  return false;
614 }
615 
616 bool BLI_string_all_words_matched(const char *name,
617  const char *str,
618  int (*words)[2],
619  const int words_len)
620 {
621  int index;
622  for (index = 0; index < words_len; index++) {
623  if (!BLI_string_has_word_prefix(name, str + words[index][0], (size_t)words[index][1])) {
624  break;
625  }
626  }
627  const bool all_words_matched = (index == words_len);
628 
629  return all_words_matched;
630 }
631 
635 char *BLI_strncasestr(const char *s, const char *find, size_t len)
636 {
637  char c, sc;
638 
639  if ((c = *find++) != 0) {
640  c = tolower(c);
641  if (len > 1) {
642  do {
643  do {
644  if ((sc = *s++) == 0) {
645  return NULL;
646  }
647  sc = tolower(sc);
648  } while (sc != c);
649  } while (BLI_strncasecmp(s, find, len - 1) != 0);
650  }
651  else {
652  {
653  do {
654  if ((sc = *s++) == 0) {
655  return NULL;
656  }
657  sc = tolower(sc);
658  } while (sc != c);
659  }
660  }
661  s--;
662  }
663  return ((char *)s);
664 }
665 
666 int BLI_strcasecmp(const char *s1, const char *s2)
667 {
668  int i;
669  char c1, c2;
670 
671  for (i = 0;; i++) {
672  c1 = tolower(s1[i]);
673  c2 = tolower(s2[i]);
674 
675  if (c1 < c2) {
676  return -1;
677  }
678  if (c1 > c2) {
679  return 1;
680  }
681  if (c1 == 0) {
682  break;
683  }
684  }
685 
686  return 0;
687 }
688 
689 int BLI_strncasecmp(const char *s1, const char *s2, size_t len)
690 {
691  size_t i;
692  char c1, c2;
693 
694  for (i = 0; i < len; i++) {
695  c1 = tolower(s1[i]);
696  c2 = tolower(s2[i]);
697 
698  if (c1 < c2) {
699  return -1;
700  }
701  if (c1 > c2) {
702  return 1;
703  }
704  if (c1 == 0) {
705  break;
706  }
707  }
708 
709  return 0;
710 }
711 
712 /* compare number on the left size of the string */
713 static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker)
714 {
715  const char *p1 = s1, *p2 = s2;
716  int numdigit, numzero1, numzero2;
717 
718  /* count and skip leading zeros */
719  for (numzero1 = 0; *p1 == '0'; numzero1++) {
720  p1++;
721  }
722  for (numzero2 = 0; *p2 == '0'; numzero2++) {
723  p2++;
724  }
725 
726  /* find number of consecutive digits */
727  for (numdigit = 0;; numdigit++) {
728  if (isdigit(*(p1 + numdigit)) && isdigit(*(p2 + numdigit))) {
729  continue;
730  }
731  if (isdigit(*(p1 + numdigit))) {
732  return 1; /* s2 is bigger */
733  }
734  if (isdigit(*(p2 + numdigit))) {
735  return -1; /* s1 is bigger */
736  }
737  break;
738  }
739 
740  /* same number of digits, compare size of number */
741  if (numdigit > 0) {
742  int compare = (int)strncmp(p1, p2, (size_t)numdigit);
743 
744  if (compare != 0) {
745  return compare;
746  }
747  }
748 
749  /* use number of leading zeros as tie breaker if still equal */
750  if (*tiebreaker == 0) {
751  if (numzero1 > numzero2) {
752  *tiebreaker = 1;
753  }
754  else if (numzero1 < numzero2) {
755  *tiebreaker = -1;
756  }
757  }
758 
759  return 0;
760 }
761 
766 int BLI_strcasecmp_natural(const char *s1, const char *s2)
767 {
768  int d1 = 0, d2 = 0;
769  char c1, c2;
770  int tiebreaker = 0;
771 
772  /* if both chars are numeric, to a left_number_strcmp().
773  * then increase string deltas as long they are
774  * numeric, else do a tolower and char compare */
775 
776  while (1) {
777  if (isdigit(s1[d1]) && isdigit(s2[d2])) {
778  int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker);
779 
780  if (numcompare != 0) {
781  return numcompare;
782  }
783 
784  /* Some wasted work here, left_number_strcmp already consumes at least some digits. */
785  d1++;
786  while (isdigit(s1[d1])) {
787  d1++;
788  }
789  d2++;
790  while (isdigit(s2[d2])) {
791  d2++;
792  }
793  }
794 
795  /* Test for end of strings first so that shorter strings are ordered in front. */
796  if (ELEM(0, s1[d1], s2[d2])) {
797  break;
798  }
799 
800  c1 = tolower(s1[d1]);
801  c2 = tolower(s2[d2]);
802 
803  if (c1 == c2) {
804  /* Continue iteration */
805  }
806  /* Check for '.' so "foo.bar" comes before "foo 1.bar". */
807  else if (c1 == '.') {
808  return -1;
809  }
810  else if (c2 == '.') {
811  return 1;
812  }
813  else if (c1 < c2) {
814  return -1;
815  }
816  else if (c1 > c2) {
817  return 1;
818  }
819 
820  d1++;
821  d2++;
822  }
823 
824  if (tiebreaker) {
825  return tiebreaker;
826  }
827 
828  /* we might still have a different string because of lower/upper case, in
829  * that case fall back to regular string comparison */
830  return strcmp(s1, s2);
831 }
832 
837 int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad)
838 {
839  size_t str1_len, str2_len;
840 
841  while (*str1 == pad) {
842  str1++;
843  }
844  while (*str2 == pad) {
845  str2++;
846  }
847 
848  str1_len = strlen(str1);
849  str2_len = strlen(str2);
850 
851  while (str1_len && (str1[str1_len - 1] == pad)) {
852  str1_len--;
853  }
854  while (str2_len && (str2[str2_len - 1] == pad)) {
855  str2_len--;
856  }
857 
858  if (str1_len == str2_len) {
859  return strncmp(str1, str2, str2_len);
860  }
861  if (str1_len > str2_len) {
862  int ret = strncmp(str1, str2, str2_len);
863  if (ret == 0) {
864  ret = 1;
865  }
866  return ret;
867  }
868  {
869  int ret = strncmp(str1, str2, str1_len);
870  if (ret == 0) {
871  ret = -1;
872  }
873  return ret;
874  }
875 }
876 
877 /* determine the length of a fixed-size string */
878 size_t BLI_strnlen(const char *s, const size_t maxlen)
879 {
880  size_t len;
881 
882  for (len = 0; len < maxlen; len++, s++) {
883  if (!*s) {
884  break;
885  }
886  }
887  return len;
888 }
889 
890 void BLI_str_tolower_ascii(char *str, const size_t len)
891 {
892  size_t i;
893 
894  for (i = 0; (i < len) && str[i]; i++) {
895  if (str[i] >= 'A' && str[i] <= 'Z') {
896  str[i] += 'a' - 'A';
897  }
898  }
899 }
900 
901 void BLI_str_toupper_ascii(char *str, const size_t len)
902 {
903  size_t i;
904 
905  for (i = 0; (i < len) && str[i]; i++) {
906  if (str[i] >= 'a' && str[i] <= 'z') {
907  str[i] -= 'a' - 'A';
908  }
909  }
910 }
911 
915 void BLI_str_rstrip(char *str)
916 {
917  for (int i = (int)strlen(str) - 1; i >= 0; i--) {
918  if (isspace(str[i])) {
919  str[i] = '\0';
920  }
921  else {
922  break;
923  }
924  }
925 }
926 
936 int BLI_str_rstrip_float_zero(char *str, const char pad)
937 {
938  char *p = strchr(str, '.');
939  int totstrip = 0;
940  if (p) {
941  char *end_p;
942  p++; /* position at first decimal place */
943  end_p = p + (strlen(p) - 1); /* position at last character */
944  if (end_p > p) {
945  while (end_p != p && *end_p == '0') {
946  *end_p = pad;
947  end_p--;
948  totstrip++;
949  }
950  }
951  }
952 
953  return totstrip;
954 }
955 
964 int BLI_str_index_in_array_n(const char *__restrict str,
965  const char **__restrict str_array,
966  const int str_array_len)
967 {
968  int index;
969  const char **str_iter = str_array;
970 
971  for (index = 0; index < str_array_len; str_iter++, index++) {
972  if (STREQ(str, *str_iter)) {
973  return index;
974  }
975  }
976  return -1;
977 }
978 
986 int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array)
987 {
988  int index;
989  const char **str_iter = str_array;
990 
991  for (index = 0; *str_iter; str_iter++, index++) {
992  if (STREQ(str, *str_iter)) {
993  return index;
994  }
995  }
996  return -1;
997 }
998 
1006 bool BLI_str_startswith(const char *__restrict str, const char *__restrict start)
1007 {
1008  for (; *str && *start; str++, start++) {
1009  if (*str != *start) {
1010  return false;
1011  }
1012  }
1013 
1014  return (*start == '\0');
1015 }
1016 
1017 bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength)
1018 {
1019  size_t elength = strlen(end);
1020 
1021  if (elength < slength) {
1022  const char *iter = &str[slength - elength];
1023  while (*iter) {
1024  if (*iter++ != *end++) {
1025  return false;
1026  }
1027  }
1028  return true;
1029  }
1030  return false;
1031 }
1032 
1040 bool BLI_str_endswith(const char *__restrict str, const char *__restrict end)
1041 {
1042  const size_t slength = strlen(str);
1043  return BLI_strn_endswith(str, end, slength);
1044 }
1045 
1056 size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf)
1057 {
1058  return BLI_str_partition_ex(str, NULL, delim, sep, suf, false);
1059 }
1060 
1071 size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf)
1072 {
1073  return BLI_str_partition_ex(str, NULL, delim, sep, suf, true);
1074 }
1075 
1088 size_t BLI_str_partition_ex(const char *str,
1089  const char *end,
1090  const char delim[],
1091  const char **sep,
1092  const char **suf,
1093  const bool from_right)
1094 {
1095  const char *d;
1096  char *(*func)(const char *str, int c) = from_right ? strrchr : strchr;
1097 
1098  BLI_assert(end == NULL || end > str);
1099 
1100  *sep = *suf = NULL;
1101 
1102  for (d = delim; *d != '\0'; d++) {
1103  const char *tmp;
1104 
1105  if (end) {
1106  if (from_right) {
1107  for (tmp = end - 1; (tmp >= str) && (*tmp != *d); tmp--) {
1108  /* pass */
1109  }
1110  if (tmp < str) {
1111  tmp = NULL;
1112  }
1113  }
1114  else {
1115  tmp = func(str, *d);
1116  if (tmp >= end) {
1117  tmp = NULL;
1118  }
1119  }
1120  }
1121  else {
1122  tmp = func(str, *d);
1123  }
1124 
1125  if (tmp && (from_right ? (*sep < tmp) : (!*sep || *sep > tmp))) {
1126  *sep = tmp;
1127  }
1128  }
1129 
1130  if (*sep) {
1131  *suf = *sep + 1;
1132  return (size_t)(*sep - str);
1133  }
1134 
1135  return end ? (size_t)(end - str) : strlen(str);
1136 }
1137 
1138 static size_t BLI_str_format_int_grouped_ex(char src[16], char dst[16], int num_len)
1139 {
1140  char *p_src = src;
1141  char *p_dst = dst;
1142 
1143  const char separator = ',';
1144  int commas;
1145 
1146  if (*p_src == '-') {
1147  *p_dst++ = *p_src++;
1148  num_len--;
1149  }
1150 
1151  for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) {
1152  *p_dst++ = *p_src++;
1153  if (commas == 1) {
1154  *p_dst++ = separator;
1155  }
1156  }
1157  *--p_dst = '\0';
1158 
1159  return (size_t)(p_dst - dst);
1160 }
1161 
1170 size_t BLI_str_format_int_grouped(char dst[16], int num)
1171 {
1172  char src[16];
1173  int num_len = sprintf(src, "%d", num);
1174 
1175  return BLI_str_format_int_grouped_ex(src, dst, num_len);
1176 }
1177 
1186 size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num)
1187 {
1188  /* NOTE: Buffer to hold maximum unsigned int64, which is 1.8e+19. but
1189  * we also need space for commas and null-terminator. */
1190  char src[27];
1191  int num_len = sprintf(src, "%" PRIu64 "", num);
1192 
1193  return BLI_str_format_int_grouped_ex(src, dst, num_len);
1194 }
1195 
1206 void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10)
1207 {
1208  double bytes_converted = bytes;
1209  int order = 0;
1210  int decimals;
1211  const int base = base_10 ? 1000 : 1024;
1212  const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"};
1213  const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
1214  const int tot_units = ARRAY_SIZE(units_base_2);
1215 
1216  BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch");
1217 
1218  while ((fabs(bytes_converted) >= base) && ((order + 1) < tot_units)) {
1219  bytes_converted /= base;
1220  order++;
1221  }
1222  decimals = MAX2(order - 1, 0);
1223 
1224  /* Format value first, stripping away floating zeroes. */
1225  const size_t dst_len = 15;
1226  size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted);
1227  len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0');
1228  dst[len++] = ' ';
1229  BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len);
1230 }
1231 
1243  const char *str, const size_t len, const char delim, int r_words[][2], int words_max)
1244 {
1245  int n = 0, i;
1246  bool charsearch = true;
1247 
1248  /* Skip leading spaces */
1249  for (i = 0; (i < len) && (str[i] != '\0'); i++) {
1250  if (str[i] != delim) {
1251  break;
1252  }
1253  }
1254 
1255  for (; (i < len) && (str[i] != '\0') && (n < words_max); i++) {
1256  if ((str[i] != delim) && (charsearch == true)) {
1257  r_words[n][0] = i;
1258  charsearch = false;
1259  }
1260  else {
1261  if ((str[i] == delim) && (charsearch == false)) {
1262  r_words[n][1] = i - r_words[n][0];
1263  n++;
1264  charsearch = true;
1265  }
1266  }
1267  }
1268 
1269  if (charsearch == false) {
1270  r_words[n][1] = i - r_words[n][0];
1271  n++;
1272  }
1273 
1274  return n;
1275 }
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:86
#define BLI_assert(a)
Definition: BLI_assert.h:58
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL()
Definition: BLI_dynstr.c:133
void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, va_list args) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:107
#define ARRAY_SIZE(arr)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define str(s)
#define PRIu64
Definition: inttypes.h:135
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
return ret
unsigned __int64 uint64_t
Definition: stdint.h:93
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array)
Definition: string.c:986
void BLI_str_replace_char(char *str, char src, char dst)
Definition: string.c:532
char * BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
Definition: string.c:432
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...)
Definition: string.c:283
size_t BLI_strnlen(const char *s, const size_t maxlen)
Definition: string.c:878
bool BLI_str_replace_table_exact(char *string, const size_t string_len, const char *replace_table[][2], int replace_table_len)
Definition: string.c:549
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...)
Definition: string.c:264
static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker)
Definition: string.c:713
int BLI_strcasecmp(const char *s1, const char *s2)
Definition: string.c:666
size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf)
Definition: string.c:1056
bool BLI_string_has_word_prefix(const char *haystack, const char *needle, size_t needle_len)
Definition: string.c:604
int BLI_string_max_possible_word_count(const int str_len)
Definition: string.c:599
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
Definition: string.c:108
bool BLI_string_all_words_matched(const char *name, const char *str, int(*words)[2], const int words_len)
Definition: string.c:616
char * BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy)
Definition: string.c:132
void BLI_str_rstrip(char *str)
Definition: string.c:915
size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
Definition: string.c:237
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
Definition: string.c:187
int BLI_string_find_split_words(const char *str, const size_t len, const char delim, int r_words[][2], int words_max)
Definition: string.c:1242
size_t BLI_str_format_int_grouped(char dst[16], int num)
Definition: string.c:1170
char * BLI_strdup(const char *str)
Definition: string.c:70
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
Definition: string.c:201
int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad)
Definition: string.c:837
int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len)
Definition: string.c:964
char * BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
Definition: string.c:81
int BLI_strcasecmp_natural(const char *s1, const char *s2)
Definition: string.c:766
int BLI_strncasecmp(const char *s1, const char *s2, size_t len)
Definition: string.c:689
char * BLI_strncasestr(const char *s, const char *find, size_t len)
Definition: string.c:635
char * BLI_strdupn(const char *str, const size_t len)
Definition: string.c:54
const char * BLI_str_escape_find_quote(const char *str)
Definition: string.c:410
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy)
Definition: string.c:333
void BLI_str_tolower_ascii(char *str, const size_t len)
Definition: string.c:890
size_t BLI_str_partition_ex(const char *str, const char *end, const char delim[], const char **sep, const char **suf, const bool from_right)
Definition: string.c:1088
size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf)
Definition: string.c:1071
size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
Definition: string.c:211
bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength)
Definition: string.c:1017
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10)
Definition: string.c:1206
size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy)
Definition: string.c:375
size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num)
Definition: string.c:1186
char * BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new)
Definition: string.c:470
void BLI_str_toupper_ascii(char *str, const size_t len)
Definition: string.c:901
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end)
Definition: string.c:1040
char * BLI_strcasestr(const char *s, const char *find)
Definition: string.c:578
int BLI_str_rstrip_float_zero(char *str, const char pad)
Definition: string.c:936
char * BLI_sprintfN(const char *__restrict format,...)
Definition: string.c:303
bool BLI_str_startswith(const char *__restrict str, const char *__restrict start)
Definition: string.c:1006
static size_t BLI_str_format_int_grouped_ex(char src[16], char dst[16], int num_len)
Definition: string.c:1138
int BLI_strcaseeq(const char *a, const char *b)
Definition: string.c:570
ccl_device_inline float2 fabs(const float2 &a)
uint len