Blender V2.61 - r43446

string.c

Go to the documentation of this file.
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