Mercurial > hg > th-libs
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: |