| 333 | */ |
| 334 | |
| 335 | int decimal2string(const decimal_t *from, char *to, int *to_len, |
| 336 | decimal_digits_t fixed_precision, |
| 337 | decimal_digits_t fixed_decimals, |
| 338 | char filler) |
| 339 | { |
| 340 | /* {intg_len, frac_len} output widths; {intg, frac} places in input */ |
| 341 | int len, frac= from->frac, i, intg_len, frac_len, fill, intg; |
| 342 | decimal_digits_t intg_tmp; |
| 343 | /* number digits before decimal point */ |
| 344 | int fixed_intg= (fixed_precision ? |
| 345 | (fixed_precision - fixed_decimals) : 0); |
| 346 | int error=E_DEC_OK; |
| 347 | char *s=to; |
| 348 | dec1 *buf, *buf0=from->buf, tmp; |
| 349 | |
| 350 | DBUG_ASSERT(*to_len >= 2+ (int) from->sign); |
| 351 | |
| 352 | /* removing leading zeroes */ |
| 353 | buf0= remove_leading_zeroes(from, &intg_tmp); |
| 354 | intg= (int) intg_tmp; /* intg can be negative later */ |
| 355 | if (unlikely(intg+frac==0)) |
| 356 | { |
| 357 | intg=1; |
| 358 | tmp=0; |
| 359 | buf0=&tmp; |
| 360 | } |
| 361 | |
| 362 | if (!(intg_len= fixed_precision ? fixed_intg : intg)) |
| 363 | intg_len= 1; |
| 364 | frac_len= fixed_precision ? fixed_decimals : frac; |
| 365 | len= from->sign + intg_len + MY_TEST(frac) + frac_len; |
| 366 | if (fixed_precision) |
| 367 | { |
| 368 | if (frac > fixed_decimals) |
| 369 | { |
| 370 | error= E_DEC_TRUNCATED; |
| 371 | frac= fixed_decimals; |
| 372 | } |
| 373 | if (intg > fixed_intg) |
| 374 | { |
| 375 | error= E_DEC_OVERFLOW; |
| 376 | intg= fixed_intg; |
| 377 | } |
| 378 | } |
| 379 | else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */ |
| 380 | { |
| 381 | int j= len-*to_len; |
| 382 | error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW; |
| 383 | if (frac && j >= frac + 1) j--; |
| 384 | if (j > frac) |
| 385 | { |
| 386 | intg-= j-frac; |
| 387 | frac= 0; |
| 388 | } |
| 389 | else |
| 390 | frac-=j; |
| 391 | frac_len= frac; |
| 392 | len= from->sign + intg_len + MY_TEST(frac) + frac_len; |