|
Blender
V2.59
|
00001 /* 00002 * $Id: BLI_dynstr.c 35246 2011-02-27 20:37:56Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * Dynamically sized string ADT 00029 */ 00030 00036 #include <stdarg.h> 00037 #include <string.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 #include "BLI_blenlib.h" 00041 #include "BLI_dynstr.h" 00042 00043 #ifdef _WIN32 00044 #ifndef vsnprintf 00045 #define vsnprintf _vsnprintf 00046 #endif 00047 #endif 00048 00049 #ifndef va_copy 00050 # ifdef __va_copy 00051 # define va_copy(a,b) __va_copy(a,b) 00052 # else /* !__va_copy */ 00053 # define va_copy(a,b) ((a)=(b)) 00054 # endif /* __va_copy */ 00055 #endif /* va_copy */ 00056 00057 /***/ 00058 00059 typedef struct DynStrElem DynStrElem; 00060 struct DynStrElem { 00061 DynStrElem *next; 00062 00063 char *str; 00064 }; 00065 00066 struct DynStr { 00067 DynStrElem *elems, *last; 00068 int curlen; 00069 }; 00070 00071 /***/ 00072 00073 DynStr *BLI_dynstr_new(void) { 00074 DynStr *ds= MEM_mallocN(sizeof(*ds), "DynStr"); 00075 ds->elems= ds->last= NULL; 00076 ds->curlen= 0; 00077 00078 return ds; 00079 } 00080 00081 void BLI_dynstr_append(DynStr *ds, const char *cstr) { 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 DynStrElem *dse= malloc(sizeof(*dse)); 00099 int cstrlen= BLI_strnlen(cstr, len); 00100 00101 dse->str= malloc(cstrlen+1); 00102 memcpy(dse->str, cstr, cstrlen); 00103 dse->str[cstrlen] = '\0'; 00104 dse->next= NULL; 00105 00106 if (!ds->last) 00107 ds->last= ds->elems= dse; 00108 else 00109 ds->last= ds->last->next= dse; 00110 00111 ds->curlen+= cstrlen; 00112 } 00113 00114 void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) 00115 { 00116 char *message, fixedmessage[256]; 00117 int len= sizeof(fixedmessage); 00118 const int maxlen= 65536; 00119 int retval; 00120 00121 while(1) { 00122 va_list args_cpy; 00123 if(len == sizeof(fixedmessage)) 00124 message= fixedmessage; 00125 else 00126 message= MEM_callocN(sizeof(char) * len, "BLI_dynstr_appendf"); 00127 00128 /* cant reuse the same args, so work on a copy */ 00129 va_copy(args_cpy, args); 00130 retval= vsnprintf(message, len, format, args_cpy); 00131 va_end(args_cpy); 00132 00133 if(retval == -1) { 00134 /* -1 means not enough space, but on windows it may also mean 00135 * there is a formatting error, so we impose a maximum length */ 00136 if(message != fixedmessage) 00137 MEM_freeN(message); 00138 message= NULL; 00139 00140 len *= 2; 00141 if(len > maxlen) { 00142 fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); 00143 break; 00144 } 00145 } 00146 else if(retval >= len) { 00147 /* in C99 the actual length required is returned */ 00148 if(message != fixedmessage) 00149 MEM_freeN(message); 00150 message= NULL; 00151 00152 /* retval doesnt include \0 terminator */ 00153 len= retval + 1; 00154 } 00155 else 00156 break; 00157 } 00158 00159 if(message) { 00160 BLI_dynstr_append(ds, message); 00161 00162 if(message != fixedmessage) 00163 MEM_freeN(message); 00164 } 00165 } 00166 00167 void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) 00168 { 00169 va_list args; 00170 char *message, fixedmessage[256]; 00171 int len= sizeof(fixedmessage); 00172 const int maxlen= 65536; 00173 int retval; 00174 00175 /* note that it's tempting to just call BLI_dynstr_vappendf here 00176 * and avoid code duplication, that crashes on some system because 00177 * va_start/va_end have to be called for each vsnprintf call */ 00178 00179 while(1) { 00180 if(len == sizeof(fixedmessage)) 00181 message= fixedmessage; 00182 else 00183 message= MEM_callocN(sizeof(char)*(len), "BLI_dynstr_appendf"); 00184 00185 va_start(args, format); 00186 retval= vsnprintf(message, len, format, args); 00187 va_end(args); 00188 00189 if(retval == -1) { 00190 /* -1 means not enough space, but on windows it may also mean 00191 * there is a formatting error, so we impose a maximum length */ 00192 if(message != fixedmessage) 00193 MEM_freeN(message); 00194 message= NULL; 00195 00196 len *= 2; 00197 if(len > maxlen) { 00198 fprintf(stderr, "BLI_dynstr_append text too long or format error.\n"); 00199 break; 00200 } 00201 } 00202 else if(retval >= len) { 00203 /* in C99 the actual length required is returned */ 00204 if(message != fixedmessage) 00205 MEM_freeN(message); 00206 message= NULL; 00207 00208 /* retval doesnt include \0 terminator */ 00209 len= retval + 1; 00210 } 00211 else 00212 break; 00213 } 00214 00215 if(message) { 00216 BLI_dynstr_append(ds, message); 00217 00218 if(message != fixedmessage) 00219 MEM_freeN(message); 00220 } 00221 } 00222 00223 int BLI_dynstr_get_len(DynStr *ds) { 00224 return ds->curlen; 00225 } 00226 00227 char *BLI_dynstr_get_cstring(DynStr *ds) { 00228 char *s, *rets= MEM_mallocN(ds->curlen+1, "dynstr_cstring"); 00229 DynStrElem *dse; 00230 00231 for (s= rets, dse= ds->elems; dse; dse= dse->next) { 00232 int slen= strlen(dse->str); 00233 00234 memcpy(s, dse->str, slen); 00235 00236 s+= slen; 00237 } 00238 rets[ds->curlen]= '\0'; 00239 00240 return rets; 00241 } 00242 00243 void BLI_dynstr_free(DynStr *ds) { 00244 DynStrElem *dse; 00245 00246 for (dse= ds->elems; dse; ) { 00247 DynStrElem *n= dse->next; 00248 00249 free(dse->str); 00250 free(dse); 00251 00252 dse= n; 00253 } 00254 00255 MEM_freeN(ds); 00256 }