comparison th_string.c @ 228:ca9cd98dbcff

Initial work on printf() style function family implementation.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Feb 2016 13:59:51 +0200
parents 128c8cb80205
children 38a0719359ef
comparison
equal deleted inserted replaced
227:5f9de1d542ee 228:ca9cd98dbcff
106 106
107 return th_strdup_trim_do(src, len, flags); 107 return th_strdup_trim_do(src, len, flags);
108 } 108 }
109 109
110 110
111 /* Simple implementations of printf() type functions
112 */
113 static int th_vput_itoa(void *ctx, int (*vputch)(void *ctx, const char ch), int val, int radix, char padMode, int width, BOOL unsig, BOOL upcase, BOOL sign)
114 {
115 char buf[64];
116 size_t pos = 0;
117 BOOL neg = FALSE;
118 int ret = 0;
119
120 if (radix > 16)
121 return 0;
122
123 if (val < 0)
124 {
125 neg = TRUE;
126 val = -val;
127 }
128
129 do
130 {
131 int digit = val % radix;
132 if (digit < 10)
133 buf[pos] = '0' + digit;
134 else
135 buf[pos] = (upcase ? 'A' : 'a') + digit - 10;
136 val /= radix;
137 pos++;
138 }
139 while (val > 0 && pos < sizeof(buf) - 1);
140 buf[pos] = 0;
141
142 if (!unsig)
143 {
144 char ch = sign ? (neg ? '-' : '+') : (neg ? '-' : 0);
145 if (ch && (ret = vputch(ctx, ch)) == EOF)
146 goto out;
147 }
148
149 int nwidth = width - pos;
150
151 if (nwidth > 0 && padMode != '-')
152 {
153 while (nwidth--)
154 if ((ret = vputch(ctx, padMode)) == EOF)
155 goto out;
156 }
157
158 while (pos--)
159 {
160 if ((ret = vputch(ctx, buf[pos])) == EOF)
161 goto out;
162 }
163
164 if (nwidth > 0 && padMode == '-')
165 {
166 while (nwidth--)
167 if ((ret = vputch(ctx, ' ')) == EOF)
168 goto out;
169 }
170
171 out:
172 return ret;
173 }
174
175
176 static int th_vput_str(void *ctx, int (*vputch)(void *ctx, const char ch), const char *str, char padMode, int width)
177 {
178 int nwidth = width - strlen(str);
179 int ret = 0;
180
181 if (nwidth > 0 && padMode != '-')
182 {
183 while (nwidth--)
184 if ((ret = vputch(ctx, padMode)) == EOF)
185 goto out;
186 }
187
188 while (*str)
189 {
190 if ((ret = vputch(ctx, *str++)) == EOF)
191 goto out;
192 }
193
194 if (nwidth > 0 && padMode == '-')
195 {
196 while (nwidth--)
197 if ((ret = vputch(ctx, ' ')) == EOF)
198 goto out;
199 }
200
201 out:
202 return ret;
203 }
204
205
206 int th_vprintf_do(void *ctx, int (*vputch)(void *ctx, const char ch), const char *fmt, va_list ap)
207 {
208 int ret;
209
210 while (*fmt)
211 {
212 if (*fmt != '%')
213 {
214 if ((ret = vputch(ctx, *fmt)) == EOF)
215 return ret;
216 }
217 else
218 {
219 char padMode = ' ', padChar = 0;
220 BOOL sign = FALSE;
221 int width = 0;
222
223 fmt++;
224
225 if (*fmt == '+')
226 {
227 sign = TRUE;
228 fmt++;
229 }
230
231 if (*fmt == '0' || *fmt == '-' || *fmt == '\'')
232 {
233 padMode = *fmt++;
234 if (padMode == '\'')
235 {
236 padChar = *fmt++;
237 if (*fmt != '\'')
238 goto out;
239 fmt++;
240 }
241
242 if (*fmt == 0)
243 goto out;
244 }
245
246 while (th_isdigit(*fmt))
247 width = width * 10 + (*fmt++ - '0');
248
249 switch (*fmt)
250 {
251 case '%':
252 vputch(ctx, *fmt);
253 break;
254
255 case 0:
256 goto out;
257
258 case 'u':
259 case 'd':
260 if (padMode != '0' && padMode != '-' && padMode != ' ')
261 goto out;
262
263 if ((ret = th_vput_itoa(ctx, vputch, va_arg(ap, unsigned int), 10, padMode, width, *fmt == 'u', FALSE, sign)) == EOF)
264 goto out;
265 break;
266
267 case 'x':
268 case 'X':
269 if (padMode != '0' && padMode != '-' && padMode != ' ')
270 goto out;
271
272 if ((ret = th_vput_itoa(ctx, vputch, va_arg(ap, unsigned int), 16, padMode, width, TRUE, *fmt == 'X', FALSE)) == EOF)
273 goto out;
274 break;
275
276 case 'f':
277 goto out;
278
279 case 's':
280 if (padMode != '-' && padMode != ' ')
281 goto out;
282
283 if ((ret = th_vput_str(ctx, vputch, va_arg(ap, char *), padMode, width)) == EOF)
284 goto out;
285 break;
286
287 default:
288 vputch(ctx, *fmt);
289 break;
290 }
291 }
292 fmt++;
293 }
294 out:
295 return ret;
296 }
297
298
299 typedef struct
300 {
301 char *buf;
302 size_t size, pos;
303 } th_pbuf_ctx;
304
305
306 static int th_pbuf_vputch(void *pctx, const char ch)
307 {
308 th_pbuf_ctx *ctx = (th_pbuf_ctx *) pctx;
309 if (ctx->pos < ctx->size)
310 ctx->buf[ctx->pos] = ch;
311 ctx->pos++;
312 return ch;
313 }
314
315
316 int th_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
317 {
318 #ifdef TH_USE_INTERNAL_SPRINTF
319 th_pbuf_ctx ctx;
320 ctx.buf = buf;
321 ctx.size = size;
322 ctx.pos = 0;
323
324 return th_vprintf_do((void *) &ctx, th_pbuf_vputch, fmt, ap);
325 #else
326 return vsnpintf(buf, size, fmt, ap);
327 #endif
328 }
329
330
331 int th_snprintf(char *buf, size_t size, const char *fmt, ...)
332 {
333 int n;
334 va_list ap;
335 va_start(ap, fmt);
336 #ifdef TH_USE_INTERNAL_SPRINTF
337 n = th_vsnprintf(buf, size, fmt, ap);
338 #else
339 n = vsnprintf(buf, size, fmt, ap);
340 #endif
341 va_end(ap);
342 return n;
343 }
344
345
346 static int th_stdio_vputch(void *ctx, const char ch)
347 {
348 return fputc(ch, (FILE *) ctx);
349 }
350
351
352 int th_vfprintf(FILE *fh, const char *fmt, va_list ap)
353 {
354 #ifdef TH_USE_INTERNAL_SPRINTF
355 return th_vprintf_do((void *) fh, th_stdio_vputch, fmt, ap);
356 #else
357 return vfprintf(fh, fmt, ap);
358 #endif
359 }
360
361
362 int th_fprintf(FILE *fh, const char *fmt, ...)
363 {
364 int ret;
365 va_list ap;
366 va_start(ap, fmt);
367 #ifdef TH_USE_INTERNAL_SPRINTF
368 ret = th_vprintf_do((void *) fh, th_stdio_vputch, fmt, ap);
369 #else
370 ret = fprintf(fh, fmt, ap);
371 #endif
372 va_end(ap);
373 return ret;
374 }
375
376
111 /* Simulate a sprintf() that allocates memory 377 /* Simulate a sprintf() that allocates memory
112 */ 378 */
113 char *th_strdup_vprintf(const char *fmt, va_list args) 379 char *th_strdup_vprintf(const char *fmt, va_list args)
114 { 380 {
115 int size = 64; 381 int size = 64;
121 while (1) 387 while (1)
122 { 388 {
123 int n; 389 int n;
124 va_list ap; 390 va_list ap;
125 va_copy(ap, args); 391 va_copy(ap, args);
392 #ifdef TH_USE_INTERNAL_SPRINTF
393 n = th_vsnprintf(buf, size, fmt, ap);
394 #else
126 n = vsnprintf(buf, size, fmt, ap); 395 n = vsnprintf(buf, size, fmt, ap);
396 #endif
127 va_end(ap); 397 va_end(ap);
128 398
129 if (n > -1 && n < size) 399 if (n > -1 && n < size)
130 return buf; 400 return buf;
131 if (n > -1) 401 if (n > -1)
230 return NULL; 500 return NULL;
231 501
232 const size_t 502 const size_t
233 slen = strlen(str), 503 slen = strlen(str),
234 nlen = strlen(needle); 504 nlen = strlen(needle);
235 505
236 if (slen < nlen) 506 if (slen < nlen)
237 return NULL; 507 return NULL;
238 508
239 if (th_strcasecmp(str - nlen - 1, needle) == 0) 509 if (th_strcasecmp(str - nlen - 1, needle) == 0)
240 return str - nlen - 1; 510 return str - nlen - 1;