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 * Dynamically sized string ADT 00027 */ 00028 00034 #include <stdarg.h> 00035 #include <string.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 #include "BLI_blenlib.h" 00039 #include "BLI_dynstr.h" 00040 00041 #ifdef _WIN32 00042 #ifndef vsnprintf 00043 #define vsnprintf _vsnprintf 00044 #endif 00045 #endif 00046 00047 #ifndef va_copy 00048 # ifdef __va_copy 00049 # define va_copy(a,b) __va_copy(a,b) 00050 # else /* !__va_copy */ 00051 # define va_copy(a,b) ((a)=(b)) 00052 # endif /* __va_copy */ 00053 #endif /* va_copy */ 00054 00055 /***/ 00056 00057 typedef struct DynStrElem DynStrElem; 00058 struct DynStrElem { 00059 DynStrElem *next; 00060 00061 char *str; 00062 }; 00063 00064 struct DynStr { 00065 DynStrElem *elems, *last; 00066 int curlen; 00067 }; 00068 00069 /***/ 00070 00071 DynStr *BLI_dynstr_new(void) 00072 { 00073 DynStr *ds= MEM_mallocN(sizeof(*ds), "DynStr"); 00074 ds->elems= ds->last= NULL; 00075 ds->curlen= 0; 00076 00077 return ds; 00078 } 00079 00080 void BLI_dynstr_append(DynStr *ds, const char *cstr) 00081 { 00082 DynStrElem *dse= malloc(sizeof(*dse)); 00083 int cstrlen= strlen(cstr); 00084 00085 dse->str= malloc(cstrlen+1); 00086 memcpy(dse->str, cstr, cstrlen+1); 00087 dse->next= NULL; 00088 00089 if (!ds->last) 00090 ds->last= ds->elems= dse; 00091 else 00092 ds->last= ds->last->next= dse; 00093 00094 ds->curlen+= cstrlen; 00095 } 00096 00097 void BLI_dynstr_nappend(DynStr *ds, const char *cstr, int len) 00098 { 00099 DynStrElem *dse= malloc(sizeof(*dse)); 00100 int cstrlen= BLI_strnlen(cstr, len); 00101 00102 dse->str= malloc(cstrlen+1); 00103 memcpy(dse->str, cstr, cstrlen); 00104 dse->str[cstrlen] = '\0'; 00105 dse->next= NULL; 00106 00107 if (!ds->last) 00108 ds->last= ds->elems= dse; 00109 else 00110 ds->last= ds->last->next= dse; 00111 00112 ds->curlen+= cstrlen; 00113 } 00114 00115 void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) 00116 { 00117 char *message, fixedmessage[256]; 00118 int len= sizeof(fixedmessage); 00119 const int maxlen= 65536; 00120 int retval; 00121 00122 while(1) { 00123 va_list args_cpy; 00124 if(len == sizeof(fixedmessage)) 00125 message= fixedmessage; 00126 else 00127 message= MEM_callocN(sizeof(char) * len, "BLI_dynstr_appendf"); 00128 00129 /* cant reuse the same args, so work on a copy */ 00130 va_copy(args_cpy, args); 00131 retval= vsnprintf(message, len, format, args_cpy); 00132 va_end(args_cpy); 00133 00134 if(retval == -1) { 00135 /* -1 means not enough space, but on windows it may also mean 00136 * there is a formatting error, so we impose a maximum length */ 00137 if(message != fixedmessage) 00138 MEM_freeN(message); 00139 message= NULL; 00140 00141 len *= 2; 00142 if(len > maxlen) { 00143 fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); 00144 break; 00145 } 00146 } 00147 else if(retval >= len) { 00148 /* in C99 the actual length required is returned */ 00149 if(message != fixedmessage) 00150 MEM_freeN(message); 00151 message= NULL; 00152 00153 /* retval doesnt include \0 terminator */ 00154 len= retval + 1; 00155 } 00156 else 00157 break; 00158 } 00159 00160 if(message) { 00161 BLI_dynstr_append(ds, message); 00162 00163 if(message != fixedmessage) 00164 MEM_freeN(message); 00165 } 00166 } 00167 00168 void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) 00169 { 00170 va_list args; 00171 char *message, fixedmessage[256]; 00172 int len= sizeof(fixedmessage); 00173 const int maxlen= 65536; 00174 int retval; 00175 00176 /* note that it's tempting to just call BLI_dynstr_vappendf here 00177 * and avoid code duplication, that crashes on some system because 00178 * va_start/va_end have to be called for each vsnprintf call */ 00179 00180 while(1) { 00181 if(len == sizeof(fixedmessage)) 00182 message= fixedmessage; 00183 else 00184 message= MEM_callocN(sizeof(char)*(len), "BLI_dynstr_appendf"); 00185 00186 va_start(args, format); 00187 retval= vsnprintf(message, len, format, args); 00188 va_end(args); 00189 00190 if(retval == -1) { 00191 /* -1 means not enough space, but on windows it may also mean 00192 * there is a formatting error, so we impose a maximum length */ 00193 if(message != fixedmessage) 00194 MEM_freeN(message); 00195 message= NULL; 00196 00197 len *= 2; 00198 if(len > maxlen) { 00199 fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); 00200 break; 00201 } 00202 } 00203 else if(retval >= len) { 00204 /* in C99 the actual length required is returned */ 00205 if(message != fixedmessage) 00206 MEM_freeN(message); 00207 message= NULL; 00208 00209 /* retval doesnt include \0 terminator */ 00210 len= retval + 1; 00211 } 00212 else 00213 break; 00214 } 00215 00216 if(message) { 00217 BLI_dynstr_append(ds, message); 00218 00219 if(message != fixedmessage) 00220 MEM_freeN(message); 00221 } 00222 } 00223 00224 int BLI_dynstr_get_len(DynStr *ds) 00225 { 00226 return ds->curlen; 00227 } 00228 00229 void BLI_dynstr_get_cstring_ex(DynStr *ds, char *rets) 00230 { 00231 char *s; 00232 DynStrElem *dse; 00233 00234 for (s= rets, dse= ds->elems; dse; dse= dse->next) { 00235 int slen= strlen(dse->str); 00236 00237 memcpy(s, dse->str, slen); 00238 00239 s+= slen; 00240 } 00241 rets[ds->curlen]= '\0'; 00242 } 00243 00244 char *BLI_dynstr_get_cstring(DynStr *ds) 00245 { 00246 char *rets= MEM_mallocN(ds->curlen+1, "dynstr_cstring"); 00247 BLI_dynstr_get_cstring_ex(ds, rets); 00248 return rets; 00249 } 00250 00251 void BLI_dynstr_free(DynStr *ds) 00252 { 00253 DynStrElem *dse; 00254 00255 for (dse= ds->elems; dse; ) { 00256 DynStrElem *n= dse->next; 00257 00258 free(dse->str); 00259 free(dse); 00260 00261 dse= n; 00262 } 00263 00264 MEM_freeN(ds); 00265 }