comparison th_string.c @ 299:0311f139fcf6

Refactor how various printf modifier flags etc. are handled. Still needs work and refining.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 22 Feb 2016 18:31:11 +0200
parents 86fe17a2ed81
children 11cba47777ec
comparison
equal deleted inserted replaced
298:86fe17a2ed81 299:0311f139fcf6
122 122
123 123
124 // 124 //
125 // Simple implementations of printf() type functions 125 // Simple implementations of printf() type functions
126 // 126 //
127 static int th_printf_vput_pad(th_printf_ctx *ctx, th_printf_vputch vputch, int nwidth, const char padChar) 127 static int th_printf_pad_pre(th_printf_ctx *ctx, th_printf_vputch vputch,
128 { 128 int f_width, const int f_flags)
129 while (nwidth--) 129 {
130 { 130 if (f_width > 0 && (f_flags & TH_PF_LEFT) == 0)
131 int ret; 131 {
132 if ((ret = vputch(ctx, padChar)) == EOF) 132 char pad = (f_flags & TH_PF_ZERO) ? '0' : ' ';
133 return ret; 133 while (f_width--)
134 {
135 int ret;
136 if ((ret = vputch(ctx, pad)) == EOF)
137 return ret;
138 }
134 } 139 }
135 return 0; 140 return 0;
136 } 141 }
137 142
138 143
144 static int th_printf_pad_post(th_printf_ctx *ctx, th_printf_vputch vputch,
145 int f_width, const int f_flags)
146 {
147 if (f_width > 0 && (f_flags & TH_PF_LEFT))
148 {
149 char pad = ' ';
150 while (f_width--)
151 {
152 int ret;
153 if ((ret = vputch(ctx, pad)) == EOF)
154 return ret;
155 }
156 }
157 return 0;
158 }
159
160
139 static int th_printf_vput_int(th_printf_ctx *ctx, th_printf_vputch vputch, 161 static int th_printf_vput_int(th_printf_ctx *ctx, th_printf_vputch vputch,
140 int pval, const int radix, const char padMode, const char padChar, 162 int pval, const int radix, const int f_flags,
141 const int f_width, const BOOL unsig, const BOOL upcase, const BOOL f_sign) 163 const int f_width, const BOOL unsig, const BOOL upcase)
142 { 164 {
143 char buf[64]; 165 char buf[64];
144 size_t pos = 0; 166 size_t pos = 0;
145 BOOL neg = FALSE; 167 BOOL neg = FALSE;
146 int ret = 0; 168 int ret = 0;
175 return EOF; 197 return EOF;
176 198
177 // Do we want a sign prefix? Not for unsigned values 199 // Do we want a sign prefix? Not for unsigned values
178 if (!unsig) 200 if (!unsig)
179 { 201 {
180 char ch = f_sign ? (neg ? '-' : '+') : (neg ? '-' : 0); 202 char ch = (f_flags & TH_PF_SIGN) ? (neg ? '-' : '+') : (neg ? '-' : ((f_flags & TH_PF_SPACE) ? ' ' : 0));
181 if (ch && (ret = vputch(ctx, ch)) == EOF) 203 if (ch && (ret = vputch(ctx, ch)) == EOF)
182 goto out; 204 goto out;
183 } 205 }
184 206
185 // Calculate necessary padding, if any 207 // Calculate necessary padding, if any
186 int nwidth = f_width - pos; 208 int nwidth = f_width - pos;
187 209
188 // Prefix padding? 210 // Prefix padding?
189 if (padMode != '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, padMode)) == EOF) 211 if ((ret = th_printf_pad_pre(ctx, vputch, nwidth, f_flags)) == EOF)
190 goto out; 212 goto out;
191 213
192 // Output the value 214 // Output the value
193 while (pos--) 215 while (pos--)
194 { 216 {
195 if ((ret = vputch(ctx, buf[pos])) == EOF) 217 if ((ret = vputch(ctx, buf[pos])) == EOF)
196 goto out; 218 goto out;
197 } 219 }
198 220
199 // Postfix padding? 221 // Postfix padding?
200 if (padMode == '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, ' ')) == EOF) 222 if ((ret = th_printf_pad_post(ctx, vputch, nwidth, f_flags)) == EOF)
201 goto out; 223 goto out;
202 224
203 out: 225 out:
204 return ret; 226 return ret;
205 } 227 }
206 228
207 229
208 static int th_printf_vput_str(th_printf_ctx *ctx, th_printf_vputch vputch, 230 static int th_printf_vput_str(th_printf_ctx *ctx, th_printf_vputch vputch,
209 const char *str, const char padMode, const char padChar, 231 const char *str, const int f_flags, const int f_width, const int f_prec)
210 const int f_width, const int f_prec)
211 { 232 {
212 int nwidth, ret = 0; 233 int nwidth, ret = 0;
213 234
214 // Check for null strings 235 // Check for null strings
215 if (str == NULL) 236 if (str == NULL)
216 str = "(null)"; 237 str = "(null)";
217 238
218 nwidth = f_width - strlen(str); 239 nwidth = f_width - strlen(str);
219 240
220 // Prefix padding? 241 // Prefix padding?
221 if (padMode != '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, padMode)) == EOF) 242 if ((ret = th_printf_pad_pre(ctx, vputch, nwidth, f_flags)) == EOF)
222 goto out; 243 goto out;
223 244
224 while (*str) 245 while (*str)
225 { 246 {
226 if ((ret = vputch(ctx, *str++)) == EOF) 247 if ((ret = vputch(ctx, *str++)) == EOF)
227 goto out; 248 goto out;
228 } 249 }
229 250
230 // Postfix padding? 251 // Postfix padding?
231 if (padMode == '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, ' ')) == EOF) 252 if ((ret = th_printf_pad_post(ctx, vputch, nwidth, f_flags)) == EOF)
232 goto out; 253 goto out;
233 254
234 out: 255 out:
235 return ret; 256 return ret;
236 } 257 }
247 if ((ret = vputch(ctx, *fmt)) == EOF) 268 if ((ret = vputch(ctx, *fmt)) == EOF)
248 goto out; 269 goto out;
249 } 270 }
250 else 271 else
251 { 272 {
252 char padMode = ' ', padChar = 0; 273 int f_width = 0, f_prec = 1, f_flags = 0;
253 int f_width = 0, f_prec = -1; 274 BOOL end = FALSE;
254 BOOL f_sign = FALSE;
255 275
256 fmt++; 276 fmt++;
257 277
258 // Check for field sign 278 // Check for flags
259 if (*fmt == '+') 279 while (!end)
260 { 280 {
261 f_sign = TRUE; 281 switch (*fmt)
262 fmt++;
263 }
264
265 // Check for padding
266 if (*fmt == '0' || *fmt == '-' || *fmt == '\'')
267 {
268 padMode = *fmt++;
269 if (padMode == '\'')
270 { 282 {
271 padChar = *fmt++; 283 case '#':
272 if (*fmt != '\'') 284 f_flags |= TH_PF_ALT;
273 return -101; 285 break;
274 fmt++; 286
287 case '+':
288 f_flags |= TH_PF_SIGN;
289 break;
290
291 case '0':
292 f_flags |= TH_PF_ZERO;
293 break;
294
295 case '-':
296 f_flags |= TH_PF_LEFT;
297 break;
298
299 case ' ':
300 f_flags |= TH_PF_SPACE;
301 break;
302
303 case '\'':
304 f_flags |= TH_PF_GROUP;
305 break;
306
307 default:
308 end = TRUE;
309 break;
275 } 310 }
276 311 if (!end) fmt++;
277 if (*fmt == 0)
278 return -102;
279 } 312 }
280 313
281 // Get field width 314 // Get field width
282 while (th_isdigit(*fmt)) 315 while (th_isdigit(*fmt))
283 f_width = f_width * 10 + (*fmt++ - '0'); 316 f_width = f_width * 10 + (*fmt++ - '0');
284 317
285 // Check for field precision 318 // Check for field precision
286 if (*fmt == '.') 319 if (*fmt == '.')
287 { 320 {
288 fmt++; 321 fmt++;
289 if (!th_isdigit(*fmt))
290 return -103;
291
292 // If no digit after '.', precision is to be 0 322 // If no digit after '.', precision is to be 0
293 f_prec = 0; 323 f_prec = 0;
294 while (th_isdigit(*fmt)) 324 while (th_isdigit(*fmt))
295 f_prec = f_prec * 10 + (*fmt++ - '0'); 325 f_prec = f_prec * 10 + (*fmt++ - '0');
326
327 f_flags &= ~ TH_PF_ZERO;
296 } 328 }
297 329
298 // Check for length modifiers (NOT SUPPORTED CURRENTLY) 330 // Check for length modifiers (NOT SUPPORTED CURRENTLY)
299 switch (*fmt) 331 switch (*fmt)
300 { 332 {
311 { 343 {
312 case 0: 344 case 0:
313 return -104; 345 return -104;
314 346
315 case 'c': 347 case 'c':
316 if (padMode != ' ' || f_width > 0 || f_prec >= 0 || f_sign) 348 if ((ret = th_printf_pad_pre(ctx, vputch, f_width - 1, f_flags)) == EOF)
317 return -105; 349 goto out;
318
319 if ((ret = vputch(ctx, va_arg(ap, int))) == EOF) 350 if ((ret = vputch(ctx, va_arg(ap, int))) == EOF)
320 goto out; 351 goto out;
321 break; 352 if ((ret = th_printf_pad_post(ctx, vputch, f_width - 1, f_flags)) == EOF)
322
323 case 'u':
324 case 'd':
325 if ((padMode != '0' && padMode != '-' && padMode != ' ') || f_prec >= 0)
326 return -105;
327
328 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
329 10, padMode, padChar, f_width, *fmt == 'u', FALSE, f_sign)) == EOF)
330 goto out; 353 goto out;
331 break; 354 break;
332 355
356 case 'o':
357 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
358 8, f_flags, f_width, FALSE, FALSE)) == EOF)
359 goto out;
360 break;
361
362 case 'u':
363 case 'i':
364 case 'd':
365 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
366 10, f_flags, f_width, *fmt == 'u', FALSE)) == EOF)
367 goto out;
368 break;
369
333 case 'x': 370 case 'x':
334 case 'X': 371 case 'X':
335 if ((padMode != '0' && padMode != '-' && padMode != ' ') || f_prec >= 0)
336 return -106;
337
338 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int), 372 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
339 16, padMode, padChar, f_width, TRUE, *fmt == 'X', FALSE)) == EOF) 373 16, f_flags, f_width, TRUE, *fmt == 'X')) == EOF)
340 goto out; 374 goto out;
341 break; 375 break;
342 376
377 case 'p':
378 if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, void *),
379 16, f_flags, f_width, TRUE, FALSE)) == EOF)
380 goto out;
381 break;
382
343 case 'f': 383 case 'f':
344 goto out; 384 case 'F':
385 return -112;
345 break; 386 break;
346 387
347 case 's': 388 case 's':
348 if ((padMode != '-' && padMode != ' ') || f_sign) 389 if ((ret = th_printf_vput_str(ctx, vputch, va_arg(ap, char *),
349 return -108; 390 f_flags, f_width, f_prec)) == EOF)
350
351 if ((ret = th_printf_vput_str(ctx, vputch, va_arg(ap, char *), padMode, padChar, f_width, f_prec)) == EOF)
352 goto out; 391 goto out;
353 break; 392 break;
354 393
355 //case '%': 394 //case '%':
356 default: 395 default: