Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 * 00027 */ 00028 00034 #include <string.h> 00035 #include <stdlib.h> 00036 #include <stdarg.h> 00037 #include <ctype.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_dynstr.h" 00042 #include "BLI_string.h" 00043 00044 char *BLI_strdupn(const char *str, const size_t len) 00045 { 00046 char *n= MEM_mallocN(len+1, "strdup"); 00047 memcpy(n, str, len); 00048 n[len]= '\0'; 00049 00050 return n; 00051 } 00052 char *BLI_strdup(const char *str) 00053 { 00054 return BLI_strdupn(str, strlen(str)); 00055 } 00056 00057 char *BLI_strdupcat(const char *str1, const char *str2) 00058 { 00059 size_t len; 00060 char *n; 00061 00062 len= strlen(str1)+strlen(str2); 00063 n= MEM_mallocN(len+1, "strdupcat"); 00064 strcpy(n, str1); 00065 strcat(n, str2); 00066 00067 return n; 00068 } 00069 00070 char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) 00071 { 00072 size_t srclen= strlen(src); 00073 size_t cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen; 00074 00075 memcpy(dst, src, cpylen); 00076 dst[cpylen]= '\0'; 00077 00078 return dst; 00079 } 00080 00081 size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) 00082 { 00083 size_t n; 00084 va_list arg; 00085 00086 va_start(arg, format); 00087 n = vsnprintf(buffer, count, format, arg); 00088 00089 if (n != -1 && n < count) { 00090 buffer[n] = '\0'; 00091 } 00092 else { 00093 buffer[count-1] = '\0'; 00094 } 00095 00096 va_end(arg); 00097 return n; 00098 } 00099 00100 char *BLI_sprintfN(const char *format, ...) 00101 { 00102 DynStr *ds; 00103 va_list arg; 00104 char *n; 00105 00106 va_start(arg, format); 00107 00108 ds= BLI_dynstr_new(); 00109 BLI_dynstr_vappendf(ds, format, arg); 00110 n= BLI_dynstr_get_cstring(ds); 00111 BLI_dynstr_free(ds); 00112 00113 va_end(arg); 00114 00115 return n; 00116 } 00117 00118 00119 /* match pythons string escaping, assume double quotes - (") 00120 * TODO: should be used to create RNA animation paths. 00121 * TODO: support more fancy string escaping. current code is primitive 00122 * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() 00123 * which is a useful reference. */ 00124 size_t BLI_strescape(char *dst, const char *src, const size_t maxlen) 00125 { 00126 size_t len= 0; 00127 while(len < maxlen) { 00128 switch(*src) { 00129 case '\0': 00130 goto escape_finish; 00131 case '\\': 00132 case '"': 00133 00134 /* less common but should also be support */ 00135 case '\t': 00136 case '\n': 00137 case '\r': 00138 if(len + 1 < maxlen) { 00139 *dst++ = '\\'; 00140 len++; 00141 } 00142 else { 00143 /* not enough space to escape */ 00144 break; 00145 } 00146 /* intentionally pass through */ 00147 default: 00148 *dst = *src; 00149 } 00150 dst++; 00151 src++; 00152 len++; 00153 } 00154 00155 escape_finish: 00156 00157 *dst= '\0'; 00158 00159 return len; 00160 } 00161 00162 00163 /* Makes a copy of the text within the "" that appear after some text 'blahblah' 00164 * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" 00165 * 00166 * - str: is the entire string to chop 00167 * - prefix: is the part of the string to leave out 00168 * 00169 * Assume that the strings returned must be freed afterwards, and that the inputs will contain 00170 * data we want... 00171 */ 00172 char *BLI_getQuotedStr (const char *str, const char *prefix) 00173 { 00174 size_t prefixLen = strlen(prefix); 00175 char *startMatch, *endMatch; 00176 00177 /* get the starting point (i.e. where prefix starts, and add prefixLen+1 to it to get be after the first " */ 00178 startMatch= strstr(str, prefix) + prefixLen + 1; 00179 00180 /* get the end point (i.e. where the next occurance of " is after the starting point) */ 00181 endMatch= strchr(startMatch, '"'); // " NOTE: this comment here is just so that my text editor still shows the functions ok... 00182 00183 /* return the slice indicated */ 00184 return BLI_strdupn(startMatch, (size_t)(endMatch-startMatch)); 00185 } 00186 00187 /* Replaces all occurances of oldText with newText in str, returning a new string that doesn't 00188 * contain the 'replaced' occurances. 00189 */ 00190 // A rather wasteful string-replacement utility, though this shall do for now... 00191 // Feel free to replace this with an even safe + nicer alternative 00192 char *BLI_replacestr(char *str, const char *oldText, const char *newText) 00193 { 00194 DynStr *ds= NULL; 00195 size_t lenOld= strlen(oldText); 00196 char *match; 00197 00198 /* sanity checks */ 00199 if ((str == NULL) || (str[0]==0)) 00200 return NULL; 00201 else if ((oldText == NULL) || (newText == NULL) || (oldText[0]==0)) 00202 return BLI_strdup(str); 00203 00204 /* while we can still find a match for the old substring that we're searching for, 00205 * keep dicing and replacing 00206 */ 00207 while ( (match = strstr(str, oldText)) ) { 00208 /* the assembly buffer only gets created when we actually need to rebuild the string */ 00209 if (ds == NULL) 00210 ds= BLI_dynstr_new(); 00211 00212 /* if the match position does not match the current position in the string, 00213 * copy the text up to this position and advance the current position in the string 00214 */ 00215 if (str != match) { 00216 /* replace the token at the 'match' position with \0 so that the copied string will be ok, 00217 * add the segment of the string from str to match to the buffer, then restore the value at match 00218 */ 00219 match[0]= 0; 00220 BLI_dynstr_append(ds, str); 00221 match[0]= oldText[0]; 00222 00223 /* now our current position should be set on the start of the match */ 00224 str= match; 00225 } 00226 00227 /* add the replacement text to the accumulation buffer */ 00228 BLI_dynstr_append(ds, newText); 00229 00230 /* advance the current position of the string up to the end of the replaced segment */ 00231 str += lenOld; 00232 } 00233 00234 /* finish off and return a new string that has had all occurances of */ 00235 if (ds) { 00236 char *newStr; 00237 00238 /* add what's left of the string to the assembly buffer 00239 * - we've been adjusting str to point at the end of the replaced segments 00240 */ 00241 if (str != NULL) 00242 BLI_dynstr_append(ds, str); 00243 00244 /* convert to new c-string (MEM_malloc'd), and free the buffer */ 00245 newStr= BLI_dynstr_get_cstring(ds); 00246 BLI_dynstr_free(ds); 00247 00248 return newStr; 00249 } 00250 else { 00251 /* just create a new copy of the entire string - we avoid going through the assembly buffer 00252 * for what should be a bit more efficiency... 00253 */ 00254 return BLI_strdup(str); 00255 } 00256 } 00257 00258 int BLI_strcaseeq(const char *a, const char *b) 00259 { 00260 return (BLI_strcasecmp(a, b)==0); 00261 } 00262 00263 /* strcasestr not available in MSVC */ 00264 char *BLI_strcasestr(const char *s, const char *find) 00265 { 00266 register char c, sc; 00267 register size_t len; 00268 00269 if ((c = *find++) != 0) { 00270 c= tolower(c); 00271 len = strlen(find); 00272 do { 00273 do { 00274 if ((sc = *s++) == 0) 00275 return (NULL); 00276 sc= tolower(sc); 00277 } while (sc != c); 00278 } while (BLI_strncasecmp(s, find, len) != 0); 00279 s--; 00280 } 00281 return ((char *) s); 00282 } 00283 00284 00285 int BLI_strcasecmp(const char *s1, const char *s2) 00286 { 00287 int i; 00288 00289 for (i=0; ; i++) { 00290 char c1 = tolower(s1[i]); 00291 char c2 = tolower(s2[i]); 00292 00293 if (c1<c2) { 00294 return -1; 00295 } else if (c1>c2) { 00296 return 1; 00297 } else if (c1==0) { 00298 break; 00299 } 00300 } 00301 00302 return 0; 00303 } 00304 00305 int BLI_strncasecmp(const char *s1, const char *s2, size_t len) 00306 { 00307 int i; 00308 00309 for (i=0; i<len; i++) { 00310 char c1 = tolower(s1[i]); 00311 char c2 = tolower(s2[i]); 00312 00313 if (c1<c2) { 00314 return -1; 00315 } else if (c1>c2) { 00316 return 1; 00317 } else if (c1==0) { 00318 break; 00319 } 00320 } 00321 00322 return 0; 00323 } 00324 00325 /* natural string compare, keeping numbers in order */ 00326 int BLI_natstrcmp(const char *s1, const char *s2) 00327 { 00328 int d1= 0, d2= 0; 00329 00330 /* if both chars are numeric, to a strtol(). 00331 then increase string deltas as long they are 00332 numeric, else do a tolower and char compare */ 00333 00334 while(1) { 00335 char c1 = tolower(s1[d1]); 00336 char c2 = tolower(s2[d2]); 00337 00338 if( isdigit(c1) && isdigit(c2) ) { 00339 int val1, val2; 00340 00341 val1= (int)strtol(s1+d1, (char **)NULL, 10); 00342 val2= (int)strtol(s2+d2, (char **)NULL, 10); 00343 00344 if (val1<val2) { 00345 return -1; 00346 } else if (val1>val2) { 00347 return 1; 00348 } 00349 d1++; 00350 while( isdigit(s1[d1]) ) 00351 d1++; 00352 d2++; 00353 while( isdigit(s2[d2]) ) 00354 d2++; 00355 00356 c1 = tolower(s1[d1]); 00357 c2 = tolower(s2[d2]); 00358 } 00359 00360 /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ 00361 if(c1=='.' && c2!='.') 00362 return -1; 00363 if(c1!='.' && c2=='.') 00364 return 1; 00365 else if (c1<c2) { 00366 return -1; 00367 } else if (c1>c2) { 00368 return 1; 00369 } else if (c1==0) { 00370 break; 00371 } 00372 d1++; 00373 d2++; 00374 } 00375 return 0; 00376 } 00377 00378 void BLI_timestr(double _time, char *str) 00379 { 00380 /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */ 00381 int hr= ( (int) _time) / (60*60); 00382 int min= (((int) _time) / 60 ) % 60; 00383 int sec= ( (int) (_time)) % 60; 00384 int hun= ( (int) (_time * 100.0)) % 100; 00385 00386 if (hr) { 00387 sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun); 00388 } else { 00389 sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun); 00390 } 00391 00392 str[11]=0; 00393 } 00394 00395 /* determine the length of a fixed-size string */ 00396 size_t BLI_strnlen(const char *str, size_t maxlen) 00397 { 00398 const char *end = memchr(str, '\0', maxlen); 00399 return end ? (size_t) (end - str) : maxlen; 00400 } 00401 00402 void BLI_ascii_strtolower(char *str, int len) 00403 { 00404 int i; 00405 00406 for(i=0; i<len; i++) 00407 if(str[i] >= 'A' && str[i] <= 'Z') 00408 str[i] += 'a' - 'A'; 00409 } 00410 00411 void BLI_ascii_strtoupper(char *str, int len) 00412 { 00413 int i; 00414 00415 for(i=0; i<len; i++) 00416 if(str[i] >= 'a' && str[i] <= 'z') 00417 str[i] -= 'a' - 'A'; 00418 } 00419