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