Blender  V2.93
BLI_dynstr.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Dynamically sized string ADT
19  */
20 
25 #include <stdio.h>
26 #include <stdlib.h> /* malloc */
27 #include <string.h>
28 
29 #include "BLI_dynstr.h"
30 #include "BLI_memarena.h"
31 #include "BLI_string.h"
32 #include "BLI_utildefines.h"
33 #include "MEM_guardedalloc.h"
34 
35 #ifdef _WIN32
36 # ifndef vsnprintf
37 # define vsnprintf _vsnprintf
38 # endif
39 #endif
40 
41 #ifndef va_copy
42 # ifdef __va_copy
43 # define va_copy(a, b) __va_copy(a, b)
44 # else /* !__va_copy */
45 # define va_copy(a, b) ((a) = (b))
46 # endif /* __va_copy */
47 #endif /* va_copy */
48 
49 /***/
50 
51 typedef struct DynStrElem DynStrElem;
52 struct DynStrElem {
54 
55  char *str;
56 };
57 
58 struct DynStr {
60  int curlen;
62 };
63 
64 /***/
65 
72 {
73  DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
74  ds->elems = ds->last = NULL;
75  ds->curlen = 0;
76  ds->memarena = NULL;
77 
78  return ds;
79 }
80 
87 {
88  DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
89  ds->elems = ds->last = NULL;
90  ds->curlen = 0;
92 
93  return ds;
94 }
95 
96 BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size)
97 {
98  return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size);
99 }
100 
107 void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
108 {
109  DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
110  int cstrlen = strlen(cstr);
111 
112  dse->str = dynstr_alloc(ds, cstrlen + 1);
113  memcpy(dse->str, cstr, cstrlen + 1);
114  dse->next = NULL;
115 
116  if (!ds->last) {
117  ds->last = ds->elems = dse;
118  }
119  else {
120  ds->last = ds->last->next = dse;
121  }
122 
123  ds->curlen += cstrlen;
124 }
125 
133 void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len)
134 {
135  DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
136  int cstrlen = BLI_strnlen(cstr, len);
137 
138  dse->str = dynstr_alloc(ds, cstrlen + 1);
139  memcpy(dse->str, cstr, cstrlen);
140  dse->str[cstrlen] = '\0';
141  dse->next = NULL;
142 
143  if (!ds->last) {
144  ds->last = ds->elems = dse;
145  }
146  else {
147  ds->last = ds->last->next = dse;
148  }
149 
150  ds->curlen += cstrlen;
151 }
152 
153 void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, va_list args)
154 {
155  char *message, fixedmessage[256];
156  int len = sizeof(fixedmessage);
157  const int maxlen = 65536;
158  int retval;
159 
160  while (1) {
161  va_list args_cpy;
162  if (len == sizeof(fixedmessage)) {
163  message = fixedmessage;
164  }
165  else {
166  message = MEM_callocN(sizeof(char) * len, "BLI_dynstr_appendf");
167  }
168 
169  /* cant reuse the same args, so work on a copy */
170  va_copy(args_cpy, args);
171  retval = vsnprintf(message, len, format, args_cpy);
172  va_end(args_cpy);
173 
174  if (retval == -1) {
175  /* -1 means not enough space, but on windows it may also mean
176  * there is a formatting error, so we impose a maximum length */
177  if (message != fixedmessage) {
178  MEM_freeN(message);
179  }
180  message = NULL;
181 
182  len *= 2;
183  if (len > maxlen) {
184  fprintf(stderr, "BLI_dynstr_append text too long or format error.\n");
185  break;
186  }
187  }
188  else if (retval >= len) {
189  /* in C99 the actual length required is returned */
190  if (message != fixedmessage) {
191  MEM_freeN(message);
192  }
193  message = NULL;
194 
195  /* retval doesn't include \0 terminator */
196  len = retval + 1;
197  }
198  else {
199  break;
200  }
201  }
202 
203  if (message) {
204  BLI_dynstr_append(ds, message);
205 
206  if (message != fixedmessage) {
207  MEM_freeN(message);
208  }
209  }
210 }
211 
218 void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format, ...)
219 {
220  va_list args;
221  char *message, fixedmessage[256];
222  int len = sizeof(fixedmessage);
223  const int maxlen = 65536;
224  int retval;
225 
226  /* note that it's tempting to just call BLI_dynstr_vappendf here
227  * and avoid code duplication, that crashes on some system because
228  * va_start/va_end have to be called for each vsnprintf call */
229 
230  while (1) {
231  if (len == sizeof(fixedmessage)) {
232  message = fixedmessage;
233  }
234  else {
235  message = MEM_callocN(sizeof(char) * (len), "BLI_dynstr_appendf");
236  }
237 
238  va_start(args, format);
239  retval = vsnprintf(message, len, format, args);
240  va_end(args);
241 
242  if (retval == -1) {
243  /* -1 means not enough space, but on windows it may also mean
244  * there is a formatting error, so we impose a maximum length */
245  if (message != fixedmessage) {
246  MEM_freeN(message);
247  }
248  message = NULL;
249 
250  len *= 2;
251  if (len > maxlen) {
252  fprintf(stderr, "BLI_dynstr_append text too long or format error.\n");
253  break;
254  }
255  }
256  else if (retval >= len) {
257  /* in C99 the actual length required is returned */
258  if (message != fixedmessage) {
259  MEM_freeN(message);
260  }
261  message = NULL;
262 
263  /* retval doesn't include \0 terminator */
264  len = retval + 1;
265  }
266  else {
267  break;
268  }
269  }
270 
271  if (message) {
272  BLI_dynstr_append(ds, message);
273 
274  if (message != fixedmessage) {
275  MEM_freeN(message);
276  }
277  }
278 }
279 
287 {
288  return ds->curlen;
289 }
290 
299 void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict rets)
300 {
301  char *s;
302  DynStrElem *dse;
303 
304  for (s = rets, dse = ds->elems; dse; dse = dse->next) {
305  int slen = strlen(dse->str);
306 
307  memcpy(s, dse->str, slen);
308 
309  s += slen;
310  }
311  BLI_assert((s - rets) == ds->curlen);
312  rets[ds->curlen] = '\0';
313 }
314 
324 {
325  char *rets = MEM_mallocN(ds->curlen + 1, "dynstr_cstring");
326  BLI_dynstr_get_cstring_ex(ds, rets);
327  return rets;
328 }
329 
336 {
337  if (ds->memarena) {
339  }
340  else {
341  for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) {
342  dse_next = dse->next;
343 
344  free(dse->str);
345  free(dse);
346  }
347  }
348 
349  ds->elems = ds->last = NULL;
350  ds->curlen = 0;
351 }
352 
359 {
360  if (ds->memarena) {
362  }
363  else {
364  BLI_dynstr_clear(ds);
365  }
366 
367  MEM_freeN(ds);
368 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...)
Definition: BLI_dynstr.c:218
void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict rets)
Definition: BLI_dynstr.c:299
void BLI_dynstr_free(DynStr *ds)
Definition: BLI_dynstr.c:358
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len)
Definition: BLI_dynstr.c:133
char * BLI_dynstr_get_cstring(DynStr *ds)
Definition: BLI_dynstr.c:323
#define va_copy(a, b)
Definition: BLI_dynstr.c:45
void BLI_dynstr_clear(DynStr *ds)
Definition: BLI_dynstr.c:335
BLI_INLINE void * dynstr_alloc(DynStr *__restrict ds, size_t size)
Definition: BLI_dynstr.c:96
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
Definition: BLI_dynstr.c:107
int BLI_dynstr_get_len(DynStr *ds)
Definition: BLI_dynstr.c:286
void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format, va_list args)
Definition: BLI_dynstr.c:153
DynStr * BLI_dynstr_new_memarena(void)
Definition: BLI_dynstr.c:86
DynStr * BLI_dynstr_new(void)
Definition: BLI_dynstr.c:71
A dynamically sized string ADT.
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:185
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:878
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
DynStrElem * next
Definition: BLI_dynstr.c:53
char * str
Definition: BLI_dynstr.c:55
MemArena * memarena
Definition: BLI_dynstr.c:61
DynStrElem * last
Definition: BLI_dynstr.c:59
int curlen
Definition: BLI_dynstr.c:60
DynStrElem * elems
Definition: BLI_dynstr.c:59
uint len