• 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 <stdarg.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 };
19 
iwxstr_new2(size_t siz)20 IWXSTR *iwxstr_new2(size_t siz) {
21   if (!siz) siz = IWXSTR_AUNIT;
22   IWXSTR *xstr = malloc(sizeof(*xstr));
23   if (!xstr) return 0;
24   xstr->ptr = malloc(siz);
25   if (!xstr->ptr) {
26     free(xstr);
27     return 0;
28   }
29   xstr->size = 0;
30   xstr->asize = siz;
31   xstr->ptr[0] = '\0';
32   return xstr;
33 }
34 
iwxstr_new(void)35 IWXSTR *iwxstr_new(void) {
36   return iwxstr_new2(IWXSTR_AUNIT);
37 }
38 
iwxstr_destroy(IWXSTR * xstr)39 void iwxstr_destroy(IWXSTR *xstr) {
40   if (!xstr) return;
41   free(xstr->ptr);
42   free(xstr);
43 }
44 
iwxstr_clear(IWXSTR * xstr)45 void iwxstr_clear(IWXSTR *xstr) {
46   assert(xstr);
47   xstr->size = 0;
48 }
49 
iwxstr_cat(IWXSTR * xstr,const void * buf,size_t size)50 iwrc iwxstr_cat(IWXSTR *xstr, const void *buf, size_t size) {
51   size_t nsize = xstr->size + size + 1;
52   if (xstr->asize < nsize) {
53     while (xstr->asize < nsize) {
54       xstr->asize <<= 1;
55       if (xstr->asize < nsize) {
56         xstr->asize = nsize;
57       }
58     }
59     char *ptr = realloc(xstr->ptr, xstr->asize);
60     if (!ptr) {
61       return IW_ERROR_ERRNO;
62     }
63     xstr->ptr = ptr;
64   }
65   memcpy(xstr->ptr + xstr->size, buf, size);
66   xstr->size += size;
67   xstr->ptr[xstr->size] = '\0';
68   return IW_OK;
69 }
70 
iwxstr_cat2(IWXSTR * xstr,const char * buf)71 iwrc iwxstr_cat2(IWXSTR *xstr, const char *buf) {
72   return buf ? iwxstr_cat(xstr, buf, strlen(buf)) : 0;
73 }
74 
iwxstr_unshift(IWXSTR * xstr,const void * buf,size_t size)75 iwrc iwxstr_unshift(IWXSTR *xstr, const void *buf, size_t size) {
76   size_t nsize = xstr->size + size + 1;
77   if (xstr->asize < nsize) {
78     while (xstr->asize < nsize) {
79       xstr->asize <<= 1;
80       if (xstr->asize < nsize) {
81         xstr->asize = nsize;
82       }
83     }
84     char *ptr = realloc(xstr->ptr, xstr->asize);
85     if (!ptr) {
86       return IW_ERROR_ERRNO;
87     }
88     xstr->ptr = ptr;
89   }
90   if (xstr->size) {
91     // shift to right
92     memmove(xstr->ptr + size, xstr->ptr, xstr->size);
93   }
94   memcpy(xstr->ptr, buf, size);
95   xstr->size += size;
96   xstr->ptr[xstr->size] = '\0';
97   return IW_OK;
98 }
99 
iwxstr_shift(IWXSTR * xstr,size_t shift_size)100 void iwxstr_shift(IWXSTR *xstr, size_t shift_size) {
101   if (shift_size == 0) {
102     return;
103   }
104   if (shift_size > xstr->size) {
105     shift_size = xstr->size;
106   }
107   if (xstr->size > shift_size) {
108     memmove(xstr->ptr, xstr->ptr + shift_size, xstr->size - shift_size);
109   }
110   xstr->size -= shift_size;
111   xstr->ptr[xstr->size] = '\0';
112 }
113 
iwxstr_vaprintf(IWXSTR * xstr,const char * format,va_list ap)114 static iwrc iwxstr_vaprintf(IWXSTR *xstr, const char *format, va_list ap) {
115   iwrc rc = 0;
116   while (*format) {
117     if (*format == '%') {
118       char cbuf[32];
119       cbuf[0] = '%';
120       size_t cblen = 1;
121       int lnum = 0;
122       ++format;
123       while (strchr("0123456789 .+-hlLzI", *format) && *format && cblen < sizeof(cbuf) - 1) {
124         if (*format == 'l' || *format == 'L') {
125           lnum++;
126         }
127         cbuf[cblen++] = *(format++);
128       }
129       cbuf[cblen++] = *format;
130       cbuf[cblen] = '\0';
131       int tlen;
132       char *tmp, tbuf[128];
133       switch (*format) {
134         case 's':
135           tmp = va_arg(ap, char *);
136           if (!tmp) tmp = "(null)";
137           rc = iwxstr_cat(xstr, tmp, strlen(tmp));
138           break;
139         case 'd':
140           if (lnum >= 2) { // -V1037
141             tlen = sprintf(tbuf, cbuf, va_arg(ap, long long));
142           } else if (lnum >= 1) {
143             tlen = sprintf(tbuf, cbuf, va_arg(ap, long));
144           } else {
145             tlen = sprintf(tbuf, cbuf, va_arg(ap, int));
146           }
147           rc = iwxstr_cat(xstr, tbuf, (size_t) tlen);
148           break;
149         case 'o':
150         case 'u':
151         case 'x':
152         case 'X':
153         case 'c':
154           if (lnum >= 2) {
155             tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long long));
156           } else if (lnum >= 1) {
157             tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long));
158           } else {
159             tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int));
160           }
161           rc = iwxstr_cat(xstr, tbuf, (size_t) tlen);
162           break;
163         case 'e':
164         case 'E':
165         case 'f':
166         case 'g':
167         case 'G':
168           if (lnum > 1) {
169             tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, long double));
170           } else {
171             tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, double));
172           }
173           if (tlen < 0 || tlen >= sizeof(tbuf)) {
174             tbuf[sizeof(tbuf) - 1] = '*';
175             tlen = sizeof(tbuf);
176           }
177           rc = iwxstr_cat(xstr, tbuf, (size_t) tlen);
178           break;
179         case '%':
180           rc = iwxstr_cat(xstr, "%", 1);
181           break;
182       }
183       RCBREAK(rc);
184     } else {
185       rc = iwxstr_cat(xstr, format, 1);
186       RCRET(rc);
187     }
188     format++;
189   }
190   return rc;
191 }
192 
iwxstr_printf(IWXSTR * xstr,const char * format,...)193 iwrc iwxstr_printf(IWXSTR *xstr, const char *format, ...) {
194   va_list ap;
195   va_start(ap, format);
196   iwrc rc  = iwxstr_vaprintf(xstr, format, ap);
197   va_end(ap);
198   return rc;
199 }
200 
iwxstr_ptr(IWXSTR * xstr)201 char *iwxstr_ptr(IWXSTR *xstr) {
202   return xstr->ptr;
203 }
204 
iwxstr_size(IWXSTR * xstr)205 size_t iwxstr_size(IWXSTR *xstr) {
206   return xstr->size;
207 }
208 
209