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