• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iwxstr.h"
2 #include "iwlog.h"
3 
4 #include <stdlib.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <errno.h>
8 
9 // Default IWXSTR initial size
10 #ifndef IWXSTR_AUNIT
11 #define IWXSTR_AUNIT 16
12 #endif
13 
14 struct _IWXSTR {
15   char  *ptr;     /**< Data buffer */
16   size_t size;    /**< Actual data size */
17   size_t asize;   /**< Allocated buffer size */
18   void   (*user_data_free_fn)(void*);
19   void  *user_data;
20 };
21 
iwxstr_new2(size_t siz)22 IWXSTR* iwxstr_new2(size_t siz) {
23   if (!siz) {
24     siz = IWXSTR_AUNIT;
25   }
26   IWXSTR *xstr = malloc(sizeof(*xstr));
27   if (!xstr) {
28     return 0;
29   }
30   xstr->ptr = malloc(siz);
31   if (!xstr->ptr) {
32     free(xstr);
33     return 0;
34   }
35   xstr->user_data = 0;
36   xstr->user_data_free_fn = 0;
37   xstr->size = 0;
38   xstr->asize = siz;
39   xstr->ptr[0] = '\0';
40   return xstr;
41 }
42 
iwxstr_new(void)43 IWXSTR* iwxstr_new(void) {
44   return iwxstr_new2(IWXSTR_AUNIT);
45 }
46 
iwxstr_new_clone(const IWXSTR * xstr)47 IWXSTR* iwxstr_new_clone(const IWXSTR *xstr) {
48   IWXSTR *ret = malloc(sizeof(*ret));
49   if (!ret) {
50     return 0;
51   }
52   ret->user_data = 0;
53   ret->user_data_free_fn = 0;
54   ret->size = xstr->size;
55   ret->asize = xstr->asize;
56   ret->ptr = malloc(xstr->asize);
57   if (!ret->ptr) {
58     free(ret);
59     return 0;
60   }
61   if (xstr->size) {
62     memcpy(ret->ptr, xstr->ptr, xstr->size);
63   }
64   return ret;
65 }
66 
iwxstr_wrap(char * buf,size_t size,size_t asize)67 IWXSTR* iwxstr_wrap(char *buf, size_t size, size_t asize) {
68   IWXSTR *xstr = malloc(sizeof(*xstr));
69   if (!xstr) {
70     return 0;
71   }
72   xstr->user_data = 0;
73   xstr->user_data_free_fn = 0;
74   xstr->size = size;
75   xstr->asize = asize;
76   xstr->ptr = buf;
77 
78   if (size >= asize) {
79     xstr->ptr = realloc(buf, size + 1);
80     if (!xstr->ptr) {
81       free(xstr);
82       return 0;
83     }
84     xstr->asize = size + 1;
85   }
86   xstr->ptr[size] = '\0';
87   return xstr;
88 }
89 
iwxstr_destroy(IWXSTR * xstr)90 void iwxstr_destroy(IWXSTR *xstr) {
91   if (!xstr) {
92     return;
93   }
94   if (xstr->user_data_free_fn) {
95     xstr->user_data_free_fn(xstr->user_data);
96   }
97   free(xstr->ptr);
98   free(xstr);
99 }
100 
iwxstr_destroy_keep_ptr(IWXSTR * xstr)101 char* iwxstr_destroy_keep_ptr(IWXSTR *xstr) {
102   if (!xstr) {
103     return 0;
104   }
105   char *ptr = xstr->ptr;
106   if (xstr->user_data_free_fn) {
107     xstr->user_data_free_fn(xstr->user_data);
108   }
109   free(xstr);
110   return ptr;
111 }
112 
iwxstr_clear(IWXSTR * xstr)113 void iwxstr_clear(IWXSTR *xstr) {
114   assert(xstr);
115   xstr->size = 0;
116   xstr->ptr[0] = '\0';
117 }
118 
iwxstr_cat(IWXSTR * xstr,const void * buf,size_t size)119 iwrc iwxstr_cat(IWXSTR *xstr, const void *buf, size_t size) {
120   size_t nsize = xstr->size + size + 1;
121   if (xstr->asize < nsize) {
122     while (xstr->asize < nsize) {
123       xstr->asize <<= 1;
124       if (xstr->asize < nsize) {
125         xstr->asize = nsize;
126       }
127     }
128     char *ptr = realloc(xstr->ptr, xstr->asize);
129     if (!ptr) {
130       return IW_ERROR_ALLOC;
131     }
132     xstr->ptr = ptr;
133   }
134   memcpy(xstr->ptr + xstr->size, buf, size);
135   xstr->size += size;
136   xstr->ptr[xstr->size] = '\0';
137   return IW_OK;
138 }
139 
iwxstr_set_size(IWXSTR * xstr,size_t size)140 iwrc iwxstr_set_size(IWXSTR *xstr, size_t size) {
141   size_t nsize = size + 1;
142   if (xstr->asize < nsize) {
143     while (xstr->asize < nsize) {
144       xstr->asize <<= 1;
145       if (xstr->asize < nsize) {
146         xstr->asize = nsize;
147       }
148     }
149     char *ptr = realloc(xstr->ptr, xstr->asize);
150     if (!ptr) {
151       return IW_ERROR_ALLOC;
152     }
153     xstr->ptr = ptr;
154   }
155   xstr->size = size;
156   return IW_OK;
157 }
158 
iwxstr_cat2(IWXSTR * xstr,const char * buf)159 iwrc iwxstr_cat2(IWXSTR *xstr, const char *buf) {
160   return buf ? iwxstr_cat(xstr, buf, strlen(buf)) : 0;
161 }
162 
iwxstr_unshift(IWXSTR * xstr,const void * buf,size_t size)163 iwrc iwxstr_unshift(IWXSTR *xstr, const void *buf, size_t size) {
164   size_t nsize = xstr->size + size + 1;
165   if (xstr->asize < nsize) {
166     while (xstr->asize < nsize) {
167       xstr->asize <<= 1;
168       if (xstr->asize < nsize) {
169         xstr->asize = nsize;
170       }
171     }
172     char *ptr = realloc(xstr->ptr, xstr->asize);
173     if (!ptr) {
174       return IW_ERROR_ALLOC;
175     }
176     xstr->ptr = ptr;
177   }
178   if (xstr->size) {
179     // shift to right
180     memmove(xstr->ptr + size, xstr->ptr, xstr->size);
181   }
182   memcpy(xstr->ptr, buf, size);
183   xstr->size += size;
184   xstr->ptr[xstr->size] = '\0';
185   return IW_OK;
186 }
187 
iwxstr_shift(IWXSTR * xstr,size_t shift_size)188 void iwxstr_shift(IWXSTR *xstr, size_t shift_size) {
189   if (shift_size == 0) {
190     return;
191   }
192   if (shift_size > xstr->size) {
193     shift_size = xstr->size;
194   }
195   if (xstr->size > shift_size) {
196     memmove(xstr->ptr, xstr->ptr + shift_size, xstr->size - shift_size);
197   }
198   xstr->size -= shift_size;
199   xstr->ptr[xstr->size] = '\0';
200 }
201 
iwxstr_pop(IWXSTR * xstr,size_t pop_size)202 void iwxstr_pop(IWXSTR *xstr, size_t pop_size) {
203   if (pop_size == 0) {
204     return;
205   }
206   if (pop_size > xstr->size) {
207     pop_size = xstr->size;
208   }
209   xstr->size -= pop_size;
210   xstr->ptr[xstr->size] = '\0';
211 }
212 
iwxstr_insert(IWXSTR * xstr,size_t pos,const void * buf,size_t size)213 iwrc iwxstr_insert(IWXSTR *xstr, size_t pos, const void *buf, size_t size) {
214   if (pos > xstr->size) {
215     return IW_ERROR_OUT_OF_BOUNDS;
216   }
217   if (size == 0) {
218     return 0;
219   }
220   size_t nsize = xstr->size + size + 1;
221   if (xstr->asize < nsize) {
222     while (xstr->asize < nsize) {
223       xstr->asize <<= 1;
224       if (xstr->asize < nsize) {
225         xstr->asize = nsize;
226       }
227     }
228     char *ptr = realloc(xstr->ptr, xstr->asize);
229     if (!ptr) {
230       return IW_ERROR_ALLOC;
231     }
232     xstr->ptr = ptr;
233   }
234   memmove(xstr->ptr + pos + size, xstr->ptr + pos, xstr->size - pos + 1 /* \0 */);
235   memcpy(xstr->ptr + pos, buf, size);
236   xstr->size += size;
237   return IW_OK;
238 }
239 
iwxstr_insert_vaprintf(IWXSTR * xstr,size_t pos,const char * format,va_list va)240 iwrc iwxstr_insert_vaprintf(IWXSTR *xstr, size_t pos, const char *format, va_list va) {
241   iwrc rc = 0;
242   char buf[1024];
243   va_list cva;
244   va_copy(cva, va);
245   char *wp = buf;
246   int len = vsnprintf(wp, sizeof(buf), format, va);
247   if (len >= sizeof(buf)) {
248     RCA(wp = malloc(len + 1), finish);
249     len = vsnprintf(wp, len + 1, format, cva);
250     if (len < 0) {
251       rc = IW_ERROR_FAIL;
252       goto finish;
253     }
254   }
255   rc = iwxstr_insert(xstr, pos, wp, len);
256 
257 finish:
258   va_end(cva);
259   if (wp != buf) {
260     free(wp);
261   }
262   return rc;
263 }
264 
iwxstr_insert_printf(IWXSTR * xstr,size_t pos,const char * format,...)265 iwrc iwxstr_insert_printf(IWXSTR *xstr, size_t pos, const char *format, ...) {
266   va_list ap;
267   va_start(ap, format);
268   iwrc rc = iwxstr_insert_vaprintf(xstr, pos, format, ap);
269   va_end(ap);
270   return rc;
271 }
272 
iwxstr_vaprintf(IWXSTR * xstr,const char * format,va_list va)273 iwrc iwxstr_vaprintf(IWXSTR *xstr, const char *format, va_list va) {
274   iwrc rc = 0;
275   char buf[1024];
276   va_list cva;
277   va_copy(cva, va);
278   char *wp = buf;
279   int len = vsnprintf(wp, sizeof(buf), format, va);
280   if (len >= sizeof(buf)) {
281     RCA(wp = malloc(len + 1), finish);
282     len = vsnprintf(wp, len + 1, format, cva);
283     if (len < 0) {
284       rc = IW_ERROR_FAIL;
285       goto finish;
286     }
287   }
288   rc = iwxstr_cat(xstr, wp, len);
289 
290 finish:
291   va_end(cva);
292   if (wp != buf) {
293     free(wp);
294   }
295   return rc;
296 }
297 
iwxstr_printf(IWXSTR * xstr,const char * format,...)298 iwrc iwxstr_printf(IWXSTR *xstr, const char *format, ...) {
299   va_list ap;
300   va_start(ap, format);
301   iwrc rc = iwxstr_vaprintf(xstr, format, ap);
302   va_end(ap);
303   return rc;
304 }
305 
iwxstr_new_printf(const char * format,...)306 IWXSTR* iwxstr_new_printf(const char *format, ...) {
307   IWXSTR *xstr = iwxstr_new();
308   if (!xstr) {
309     return 0;
310   }
311   va_list ap;
312   va_start(ap, format);
313   iwrc rc = iwxstr_vaprintf(xstr, format, ap);
314   va_end(ap);
315   if (rc) {
316     iwxstr_destroy(xstr);
317     return 0;
318   }
319   return xstr;
320 }
321 
iwxstr_ptr(IWXSTR * xstr)322 char* iwxstr_ptr(IWXSTR *xstr) {
323   return xstr->ptr;
324 }
325 
iwxstr_size(IWXSTR * xstr)326 size_t iwxstr_size(IWXSTR *xstr) {
327   return xstr->size;
328 }
329 
iwxstr_asize(IWXSTR * xstr)330 size_t iwxstr_asize(IWXSTR *xstr) {
331   return xstr->asize;
332 }
333 
iwxstr_user_data_set(IWXSTR * xstr,void * data,void (* free_fn)(void *))334 void iwxstr_user_data_set(IWXSTR *xstr, void *data, void (*free_fn)(void*)) {
335   if (xstr->user_data_free_fn) {
336     xstr->user_data_free_fn(xstr->user_data);
337   }
338   xstr->user_data = data;
339   xstr->user_data_free_fn = free_fn;
340 }
341 
iwxstr_user_data_get(IWXSTR * xstr)342 void* iwxstr_user_data_get(IWXSTR *xstr) {
343   return xstr->user_data;
344 }
345 
iwxstr_user_data_detach(IWXSTR * xstr)346 void* iwxstr_user_data_detach(IWXSTR *xstr) {
347   xstr->user_data_free_fn = 0;
348   return xstr->user_data;
349 }
350