Merging changes from trunk r58091-58323.
[blender.git] / source / blender / blenlib / intern / string.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program 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.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * 
27  */
28
29 /** \file blender/blenlib/intern/string.c
30  *  \ingroup bli
31  */
32
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <ctype.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_dynstr.h"
42 #include "BLI_string.h"
43
44 #include "BLI_utildefines.h"
45
46 #ifdef __GNUC__
47 #  pragma GCC diagnostic error "-Wsign-conversion"
48 #endif
49
50 // #define DEBUG_STRSIZE
51
52 /**
53  * Duplicates the first \a len bytes of cstring \a str
54  * into a newly mallocN'd string and returns it. \a str
55  * is assumed to be at least len bytes long.
56  *
57  * \param str The string to be duplicated
58  * \param len The number of bytes to duplicate
59  * \retval Returns the duplicated string
60  */
61 char *BLI_strdupn(const char *str, const size_t len)
62 {
63         char *n = MEM_mallocN(len + 1, "strdup");
64         memcpy(n, str, len);
65         n[len] = '\0';
66         
67         return n;
68 }
69
70 /**
71  * Duplicates the cstring \a str into a newly mallocN'd
72  * string and returns it.
73  *
74  * \param str The string to be duplicated
75  * \retval Returns the duplicated string
76  */
77 char *BLI_strdup(const char *str)
78 {
79         return BLI_strdupn(str, strlen(str));
80 }
81
82 /**
83  * Appends the two strings, and returns new mallocN'ed string
84  * \param str1 first string for copy
85  * \param str2 second string for append
86  * \retval Returns dst
87  */
88 char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
89 {
90         size_t len;
91         char *n;
92         
93         len = strlen(str1) + strlen(str2);
94         n = MEM_mallocN(len + 1, "strdupcat");
95         strcpy(n, str1);
96         strcat(n, str2);
97         
98         return n;
99 }
100
101 /**
102  * Like strncpy but ensures dst is always
103  * '\0' terminated.
104  *
105  * \param dst Destination for copy
106  * \param src Source string to copy
107  * \param maxncpy Maximum number of characters to copy (generally
108  * the size of dst)
109  * \retval Returns dst
110  */
111 char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
112 {
113         size_t srclen = BLI_strnlen(src, maxncpy - 1);
114         BLI_assert(maxncpy != 0);
115
116 #ifdef DEBUG_STRSIZE
117         memset(dst, 0xff, sizeof(*dst) * maxncpy);
118 #endif
119
120         memcpy(dst, src, srclen);
121         dst[srclen] = '\0';
122         return dst;
123 }
124
125 /**
126  * Like strncpy but ensures dst is always
127  * '\0' terminated.
128  *
129  * \note This is a duplicate of #BLI_strncpy that returns bytes copied.
130  * And is a drop in replacement for 'snprintf(str, sizeof(str), "%s", arg);'
131  *
132  * \param dst Destination for copy
133  * \param src Source string to copy
134  * \param maxncpy Maximum number of characters to copy (generally
135  * the size of dst)
136  * \retval The number of bytes copied (The only difference from BLI_strncpy).
137  */
138 size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
139 {
140         size_t srclen = BLI_strnlen(src, maxncpy - 1);
141         BLI_assert(maxncpy != 0);
142
143 #ifdef DEBUG_STRSIZE
144         memset(dst, 0xff, sizeof(*dst) * maxncpy);
145 #endif
146
147         memcpy(dst, src, srclen);
148         dst[srclen] = '\0';
149         return srclen;
150 }
151
152 size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
153 {
154         size_t srclen = strlen(src);
155         memcpy(dst, src, srclen + 1);
156         return srclen;
157 }
158
159 /**
160  * Portable replacement for #vsnprintf
161  */
162 size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
163 {
164         size_t n;
165
166         BLI_assert(buffer != NULL);
167         BLI_assert(maxncpy > 0);
168         BLI_assert(format != NULL);
169
170         n = (size_t)vsnprintf(buffer, maxncpy, format, arg);
171
172         if (n != -1 && n < maxncpy) {
173                 buffer[n] = '\0';
174         }
175         else {
176                 buffer[maxncpy - 1] = '\0';
177         }
178
179         return n;
180 }
181
182 /**
183  * Portable replacement for #snprintf
184  */
185 size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
186 {
187         size_t n;
188         va_list arg;
189
190 #ifdef DEBUG_STRSIZE
191         memset(dst, 0xff, sizeof(*dst) * maxncpy);
192 #endif
193
194         va_start(arg, format);
195         n = BLI_vsnprintf(dst, maxncpy, format, arg);
196         va_end(arg);
197
198         return n;
199 }
200
201 /**
202  * Print formatted string into a newly #MEM_mallocN'd string
203  * and return it.
204  */
205 char *BLI_sprintfN(const char *__restrict format, ...)
206 {
207         DynStr *ds;
208         va_list arg;
209         char *n;
210
211         BLI_assert(format != NULL);
212
213         va_start(arg, format);
214
215         ds = BLI_dynstr_new();
216         BLI_dynstr_vappendf(ds, format, arg);
217         n = BLI_dynstr_get_cstring(ds);
218         BLI_dynstr_free(ds);
219
220         va_end(arg);
221
222         return n;
223 }
224
225
226 /* match pythons string escaping, assume double quotes - (")
227  * TODO: should be used to create RNA animation paths.
228  * TODO: support more fancy string escaping. current code is primitive
229  *    this basically is an ascii version of PyUnicode_EncodeUnicodeEscape()
230  *    which is a useful reference. */
231 size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
232 {
233         size_t len = 0;
234
235         BLI_assert(maxncpy != 0);
236
237         while (len < maxncpy) {
238                 switch (*src) {
239                         case '\0':
240                                 goto escape_finish;
241                         case '\\':
242                         case '"':
243
244                         /* less common but should also be support */
245                         case '\t':
246                         case '\n':
247                         case '\r':
248                                 if (len + 1 < maxncpy) {
249                                         *dst++ = '\\';
250                                         len++;
251                                 }
252                                 else {
253                                         /* not enough space to escape */
254                                         break;
255                                 }
256                         /* intentionally pass through */
257                         default:
258                                 *dst = *src;
259                 }
260                 dst++;
261                 src++;
262                 len++;
263         }
264
265 escape_finish:
266
267         *dst = '\0';
268
269         return len;
270 }
271
272 /**
273  * Makes a copy of the text within the "" that appear after some text 'blahblah'
274  * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples"
275  *
276  * - str: is the entire string to chop
277  * - prefix: is the part of the string to leave out
278  *
279  * Assume that the strings returned must be freed afterwards, and that the inputs will contain
280  * data we want...
281  *
282  * \return the offset and a length so as to avoid doing an allocation.
283  */
284 char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
285 {
286         size_t prefixLen = strlen(prefix);
287         char *startMatch, *endMatch;
288         
289         /* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */
290         startMatch = strstr(str, prefix) + prefixLen + 1;
291         if (startMatch) {
292                 /* get the end point (i.e. where the next occurance of " is after the starting point) */
293                 endMatch = strchr(startMatch, '"'); /* "  NOTE: this comment here is just so that my text editor still shows the functions ok... */
294                 
295                 if (endMatch)
296                         /* return the slice indicated */
297                         return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch));
298         }
299         return BLI_strdupn("", 0);
300 }
301
302 /**
303  * Returns a copy of the cstring \a str into a newly mallocN'd
304  * string with all instances of oldText replaced with newText,
305  * and returns it.
306  *
307  * \note A rather wasteful string-replacement utility, though this shall do for now...
308  * Feel free to replace this with an even safe + nicer alternative
309  *
310  * \param str The string to replace occurrences of oldText in
311  * \param oldText The text in the string to find and replace
312  * \param newText The text in the string to find and replace
313  * \retval Returns the duplicated string
314  */
315 char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText)
316 {
317         DynStr *ds = NULL;
318         size_t lenOld = strlen(oldText);
319         char *match;
320         
321         /* sanity checks */
322         if ((str == NULL) || (str[0] == 0))
323                 return NULL;
324         else if ((oldText == NULL) || (newText == NULL) || (oldText[0] == 0))
325                 return BLI_strdup(str);
326         
327         /* while we can still find a match for the old substring that we're searching for, 
328          * keep dicing and replacing
329          */
330         while ( (match = strstr(str, oldText)) ) {
331                 /* the assembly buffer only gets created when we actually need to rebuild the string */
332                 if (ds == NULL)
333                         ds = BLI_dynstr_new();
334                         
335                 /* if the match position does not match the current position in the string, 
336                  * copy the text up to this position and advance the current position in the string
337                  */
338                 if (str != match) {
339                         /* replace the token at the 'match' position with \0 so that the copied string will be ok,
340                          * add the segment of the string from str to match to the buffer, then restore the value at match
341                          */
342                         match[0] = 0;
343                         BLI_dynstr_append(ds, str);
344                         match[0] = oldText[0];
345                         
346                         /* now our current position should be set on the start of the match */
347                         str = match;
348                 }
349                 
350                 /* add the replacement text to the accumulation buffer */
351                 BLI_dynstr_append(ds, newText);
352                 
353                 /* advance the current position of the string up to the end of the replaced segment */
354                 str += lenOld;
355         }
356         
357         /* finish off and return a new string that has had all occurrences of */
358         if (ds) {
359                 char *newStr;
360                 
361                 /* add what's left of the string to the assembly buffer 
362                  *      - we've been adjusting str to point at the end of the replaced segments
363                  */
364                 if (str != NULL)
365                         BLI_dynstr_append(ds, str);
366                 
367                 /* convert to new c-string (MEM_malloc'd), and free the buffer */
368                 newStr = BLI_dynstr_get_cstring(ds);
369                 BLI_dynstr_free(ds);
370                 
371                 return newStr;
372         }
373         else {
374                 /* just create a new copy of the entire string - we avoid going through the assembly buffer 
375                  * for what should be a bit more efficiency...
376                  */
377                 return BLI_strdup(str);
378         }
379
380
381 /**
382  * Compare two strings without regard to case.
383  *
384  * \retval True if the strings are equal, false otherwise.
385  */
386 int BLI_strcaseeq(const char *a, const char *b) 
387 {
388         return (BLI_strcasecmp(a, b) == 0);
389 }
390
391 /**
392  * Portable replacement for #strcasestr (not available in MSVC)
393  */
394 char *BLI_strcasestr(const char *s, const char *find)
395 {
396         register char c, sc;
397         register size_t len;
398         
399         if ((c = *find++) != 0) {
400                 c = tolower(c);
401                 len = strlen(find);
402                 do {
403                         do {
404                                 if ((sc = *s++) == 0)
405                                         return (NULL);
406                                 sc = tolower(sc);
407                         } while (sc != c);
408                 } while (BLI_strncasecmp(s, find, len) != 0);
409                 s--;
410         }
411         return ((char *) s);
412 }
413
414
415 int BLI_strcasecmp(const char *s1, const char *s2)
416 {
417         register int i;
418         register char c1, c2;
419
420         for (i = 0;; i++) {
421                 c1 = tolower(s1[i]);
422                 c2 = tolower(s2[i]);
423
424                 if (c1 < c2) {
425                         return -1;
426                 }
427                 else if (c1 > c2) {
428                         return 1;
429                 }
430                 else if (c1 == 0) {
431                         break;
432                 }
433         }
434
435         return 0;
436 }
437
438 int BLI_strncasecmp(const char *s1, const char *s2, size_t len)
439 {
440         register size_t i;
441         register char c1, c2;
442
443         for (i = 0; i < len; i++) {
444                 c1 = tolower(s1[i]);
445                 c2 = tolower(s2[i]);
446
447                 if (c1 < c2) {
448                         return -1;
449                 }
450                 else if (c1 > c2) {
451                         return 1;
452                 }
453                 else if (c1 == 0) {
454                         break;
455                 }
456         }
457
458         return 0;
459 }
460
461 /* compare number on the left size of the string */
462 static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker)
463 {
464         const char *p1 = s1, *p2 = s2;
465         int numdigit, numzero1, numzero2;
466
467         /* count and skip leading zeros */
468         for (numzero1 = 0; *p1 && (*p1 == '0'); numzero1++)
469                 p1++;
470         for (numzero2 = 0; *p2 && (*p2 == '0'); numzero2++)
471                 p2++;
472
473         /* find number of consecutive digits */
474         for (numdigit = 0; ; numdigit++) {
475                 if (isdigit(*(p1 + numdigit)) && isdigit(*(p2 + numdigit)))
476                         continue;
477                 else if (isdigit(*(p1 + numdigit)))
478                         return 1; /* s2 is bigger */
479                 else if (isdigit(*(p2 + numdigit)))
480                         return -1; /* s1 is bigger */
481                 else
482                         break;
483         }
484
485         /* same number of digits, compare size of number */
486         if (numdigit > 0) {
487                 int compare = (int)strncmp(p1, p2, (size_t)numdigit);
488
489                 if (compare != 0)
490                         return compare;
491         }
492
493         /* use number of leading zeros as tie breaker if still equal */
494         if (*tiebreaker == 0) {
495                 if (numzero1 > numzero2)
496                         *tiebreaker = 1;
497                 else if (numzero1 < numzero2)
498                         *tiebreaker = -1;
499         }
500
501         return 0;
502 }
503
504 /* natural string compare, keeping numbers in order */
505 int BLI_natstrcmp(const char *s1, const char *s2)
506 {
507         register int d1 = 0, d2 = 0;
508         register char c1, c2;
509         int tiebreaker = 0;
510
511         /* if both chars are numeric, to a left_number_strcmp().
512          * then increase string deltas as long they are 
513          * numeric, else do a tolower and char compare */
514
515         while (1) {
516                 c1 = tolower(s1[d1]);
517                 c2 = tolower(s2[d2]);
518                 
519                 if (isdigit(c1) && isdigit(c2) ) {
520                         int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker);
521                         
522                         if (numcompare != 0)
523                                 return numcompare;
524
525                         d1++;
526                         while (isdigit(s1[d1]) )
527                                 d1++;
528                         d2++;
529                         while (isdigit(s2[d2]) )
530                                 d2++;
531                         
532                         c1 = tolower(s1[d1]);
533                         c2 = tolower(s2[d2]);
534                 }
535         
536                 /* first check for '.' so "foo.bar" comes before "foo 1.bar" */
537                 if (c1 == '.' && c2 != '.')
538                         return -1;
539                 if (c1 != '.' && c2 == '.')
540                         return 1;
541                 else if (c1 < c2) {
542                         return -1;
543                 }
544                 else if (c1 > c2) {
545                         return 1;
546                 }
547                 else if (c1 == 0) {
548                         break;
549                 }
550                 d1++;
551                 d2++;
552         }
553         return tiebreaker;
554 }
555
556 void BLI_timestr(double _time, char *str, size_t maxlen)
557 {
558         /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
559         int  hr = ( (int)  _time) / (60 * 60);
560         int min = (((int)  _time) / 60 ) % 60;
561         int sec = ( (int)  _time) % 60;
562         int hun = ( (int) (_time   * 100.0)) % 100;
563
564         if (hr) {
565                 BLI_snprintf(str, maxlen, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun);
566         }
567         else {
568                 BLI_snprintf(str, maxlen, "%.2d:%.2d.%.2d", min, sec, hun);
569         }
570 }
571
572 /* determine the length of a fixed-size string */
573 size_t BLI_strnlen(const char *s, const size_t maxlen)
574 {
575         size_t len;
576
577         for (len = 0; len < maxlen; len++, s++) {
578                 if (!*s)
579                         break;
580         }
581         return len;
582 }
583
584 void BLI_ascii_strtolower(char *str, const size_t len)
585 {
586         size_t i;
587
588         for (i = 0; i < len; i++)
589                 if (str[i] >= 'A' && str[i] <= 'Z')
590                         str[i] += 'a' - 'A';
591 }
592
593 void BLI_ascii_strtoupper(char *str, const size_t len)
594 {
595         size_t i;
596
597         for (i = 0; i < len; i++)
598                 if (str[i] >= 'a' && str[i] <= 'z')
599                         str[i] -= 'a' - 'A';
600 }
601
602 /**
603  * Strip trailing zeros from a float, eg:
604  *   0.0000 -> 0.0
605  *   2.0010 -> 2.001
606  *
607  * \param str
608  * \param pad
609  * \return The number of zeto's stripped.
610  */
611 int BLI_str_rstrip_float_zero(char *str, const char pad)
612 {
613         char *p = strchr(str, '.');
614         int totstrip = 0;
615         if (p) {
616                 char *end_p;
617                 p++;  /* position at first decimal place */
618                 end_p = p + (strlen(p) - 1);  /* position at last character */
619                 if (end_p > p) {
620                         while (end_p != p && *end_p == '0') {
621                                 *end_p = pad;
622                                 end_p--;
623                         }
624                 }
625         }
626
627         return totstrip;
628 }