3 * various string, file, list operations.
8 * ***** BEGIN GPL LICENSE BLOCK *****
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
25 * All rights reserved.
27 * The Original Code is: all of this file.
29 * Contributor(s): none yet.
31 * ***** END GPL LICENSE BLOCK *****
35 /** \file blender/blenlib/intern/string.c
45 #include "MEM_guardedalloc.h"
47 #include "BLI_dynstr.h"
48 #include "BLI_string.h"
50 char *BLI_strdupn(const char *str, const size_t len) {
51 char *n= MEM_mallocN(len+1, "strdup");
57 char *BLI_strdup(const char *str) {
58 return BLI_strdupn(str, strlen(str));
61 char *BLI_strdupcat(const char *str1, const char *str2)
66 len= strlen(str1)+strlen(str2);
67 n= MEM_mallocN(len+1, "strdupcat");
74 char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) {
75 size_t srclen= strlen(src);
76 size_t cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
78 memcpy(dst, src, cpylen);
84 size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
89 va_start(arg, format);
90 n = vsnprintf(buffer, count, format, arg);
92 if (n != -1 && n < count) {
95 buffer[count-1] = '\0';
102 char *BLI_sprintfN(const char *format, ...)
108 va_start(arg, format);
110 ds= BLI_dynstr_new();
111 BLI_dynstr_vappendf(ds, format, arg);
112 n= BLI_dynstr_get_cstring(ds);
120 /* Makes a copy of the text within the "" that appear after some text 'blahblah'
121 * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples"
123 * - str: is the entire string to chop
124 * - prefix: is the part of the string to leave out
126 * Assume that the strings returned must be freed afterwards, and that the inputs will contain
129 char *BLI_getQuotedStr (const char *str, const char *prefix)
131 size_t prefixLen = strlen(prefix);
132 char *startMatch, *endMatch;
134 /* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */
135 startMatch= strstr(str, prefix) + prefixLen + 1;
137 /* get the end point (i.e. where the next occurance of " is after the starting point) */
138 endMatch= strchr(startMatch, '"'); // " NOTE: this comment here is just so that my text editor still shows the functions ok...
140 /* return the slice indicated */
141 return BLI_strdupn(startMatch, (size_t)(endMatch-startMatch));
144 /* Replaces all occurances of oldText with newText in str, returning a new string that doesn't
145 * contain the 'replaced' occurances.
147 // A rather wasteful string-replacement utility, though this shall do for now...
148 // Feel free to replace this with an even safe + nicer alternative
149 char *BLI_replacestr(char *str, const char *oldText, const char *newText)
152 size_t lenOld= strlen(oldText);
156 if ((str == NULL) || (str[0]==0))
158 else if ((oldText == NULL) || (newText == NULL) || (oldText[0]==0))
159 return BLI_strdup(str);
161 /* while we can still find a match for the old substring that we're searching for,
162 * keep dicing and replacing
164 while ( (match = strstr(str, oldText)) ) {
165 /* the assembly buffer only gets created when we actually need to rebuild the string */
167 ds= BLI_dynstr_new();
169 /* if the match position does not match the current position in the string,
170 * copy the text up to this position and advance the current position in the string
173 /* replace the token at the 'match' position with \0 so that the copied string will be ok,
174 * add the segment of the string from str to match to the buffer, then restore the value at match
177 BLI_dynstr_append(ds, str);
178 match[0]= oldText[0];
180 /* now our current position should be set on the start of the match */
184 /* add the replacement text to the accumulation buffer */
185 BLI_dynstr_append(ds, newText);
187 /* advance the current position of the string up to the end of the replaced segment */
191 /* finish off and return a new string that has had all occurances of */
195 /* add what's left of the string to the assembly buffer
196 * - we've been adjusting str to point at the end of the replaced segments
199 BLI_dynstr_append(ds, str);
201 /* convert to new c-string (MEM_malloc'd), and free the buffer */
202 newStr= BLI_dynstr_get_cstring(ds);
208 /* just create a new copy of the entire string - we avoid going through the assembly buffer
209 * for what should be a bit more efficiency...
211 return BLI_strdup(str);
215 int BLI_streq(const char *a, const char *b)
217 return (strcmp(a, b)==0);
220 int BLI_strcaseeq(const char *a, const char *b)
222 return (BLI_strcasecmp(a, b)==0);
225 /* strcasestr not available in MSVC */
226 char *BLI_strcasestr(const char *s, const char *find)
231 if ((c = *find++) != 0) {
236 if ((sc = *s++) == 0)
240 } while (BLI_strncasecmp(s, find, len) != 0);
247 int BLI_strcasecmp(const char *s1, const char *s2) {
251 char c1 = tolower(s1[i]);
252 char c2 = tolower(s2[i]);
266 int BLI_strncasecmp(const char *s1, const char *s2, size_t len) {
269 for (i=0; i<len; i++) {
270 char c1 = tolower(s1[i]);
271 char c2 = tolower(s2[i]);
285 /* natural string compare, keeping numbers in order */
286 int BLI_natstrcmp(const char *s1, const char *s2)
290 /* if both chars are numeric, to a strtol().
291 then increase string deltas as long they are
292 numeric, else do a tolower and char compare */
295 char c1 = tolower(s1[d1]);
296 char c2 = tolower(s2[d2]);
298 if( isdigit(c1) && isdigit(c2) ) {
301 val1= (int)strtol(s1+d1, (char **)NULL, 10);
302 val2= (int)strtol(s2+d2, (char **)NULL, 10);
306 } else if (val1>val2) {
310 while( isdigit(s1[d1]) )
313 while( isdigit(s2[d2]) )
316 c1 = tolower(s1[d1]);
317 c2 = tolower(s2[d2]);
320 /* first check for '.' so "foo.bar" comes before "foo 1.bar" */
321 if(c1=='.' && c2!='.')
323 if(c1!='.' && c2=='.')
338 void BLI_timestr(double _time, char *str)
340 /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
341 int hr= ( (int) _time) / (60*60);
342 int min= (((int) _time) / 60 ) % 60;
343 int sec= ( (int) (_time)) % 60;
344 int hun= ( (int) (_time * 100.0)) % 100;
347 sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
349 sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
355 /* determine the length of a fixed-size string */
356 size_t BLI_strnlen(const char *str, size_t maxlen)
358 const char *end = memchr(str, '\0', maxlen);
359 return end ? (size_t) (end - str) : maxlen;
362 /* from libswish3, originally called u8_isvalid(),
363 * modified to return the index of the bad character (byte index not utf).
364 * http://svn.swish-e.org/libswish3/trunk/src/libswish3/utf8.c r3044 - campbell */
366 /* based on the valid_utf8 routine from the PCRE library by Philip Hazel
368 length is in bytes, since without knowing whether the string is valid
369 it's hard to know how many characters there are! */
371 static const char trailingBytesForUTF8[256] = {
372 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
373 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
374 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
375 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
376 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
377 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
378 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
379 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
382 int BLI_utf8_invalid_byte(const char *str, int length)
384 const unsigned char *p, *pend = (unsigned char*)str + length;
388 for (p = (unsigned char*)str; p < pend; p++) {
392 if ((c & 0xc0) != 0xc0)
394 ab = trailingBytesForUTF8[c];
400 /* Check top bits in the second byte */
401 if ((*p & 0xc0) != 0x80)
404 /* Check for overlong sequences for each different length */
406 /* Check for xx00 000x */
408 if ((c & 0x3e) == 0) goto utf8_error;
409 continue; /* We know there aren't any more bytes to check */
411 /* Check for 1110 0000, xx0x xxxx */
413 if (c == 0xe0 && (*p & 0x20) == 0) goto utf8_error;
416 /* Check for 1111 0000, xx00 xxxx */
418 if (c == 0xf0 && (*p & 0x30) == 0) goto utf8_error;
421 /* Check for 1111 1000, xx00 0xxx */
423 if (c == 0xf8 && (*p & 0x38) == 0) goto utf8_error;
426 /* Check for leading 0xfe or 0xff,
427 and then for 1111 1100, xx00 00xx */
429 if (c == 0xfe || c == 0xff ||
430 (c == 0xfc && (*p & 0x3c) == 0)) goto utf8_error;
434 /* Check for valid bytes after the 2nd, if any; all must start 10 */
436 if ((*(p+1) & 0xc0) != 0x80) goto utf8_error;
437 p++; /* do this after so we get usable offset - campbell */
445 return (int)((char *)p - (char *)str) - 1;
448 int BLI_utf8_invalid_strip(char *str, int length)
450 int bad_char, tot= 0;
452 while((bad_char= BLI_utf8_invalid_byte(str, length)) != -1) {
457 /* last character bad, strip it */
463 /* strip, keep looking */
464 memmove(str, str + 1, length);
472 void BLI_ascii_strtolower(char *str, int len)
477 if(str[i] >= 'A' && str[i] <= 'Z')
481 void BLI_ascii_strtoupper(char *str, int len)
486 if(str[i] >= 'a' && str[i] <= 'z')