| 484 | typedef char * iconv_ibp; |
| 485 | #endif |
| 486 | char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv, |
| 487 | size_t bom_len, size_t *outsz_p) |
| 488 | { |
| 489 | size_t outsz, outalloc; |
| 490 | char *out, *outpos; |
| 491 | iconv_ibp cp; |
| 492 | |
| 493 | outsz = insz; |
| 494 | outalloc = st_add(outsz, 1 + bom_len); /* for terminating NUL */ |
| 495 | out = xmalloc(outalloc); |
| 496 | outpos = out + bom_len; |
| 497 | cp = (iconv_ibp)in; |
| 498 | |
| 499 | while (1) { |
| 500 | size_t cnt = iconv(conv, &cp, &insz, &outpos, &outsz); |
| 501 | |
| 502 | if (cnt == (size_t) -1) { |
| 503 | size_t sofar; |
| 504 | if (errno != E2BIG) { |
| 505 | free(out); |
| 506 | return NULL; |
| 507 | } |
| 508 | /* insz has remaining number of bytes. |
| 509 | * since we started outsz the same as insz, |
| 510 | * it is likely that insz is not enough for |
| 511 | * converting the rest. |
| 512 | */ |
| 513 | sofar = outpos - out; |
| 514 | outalloc = st_add3(sofar, st_mult(insz, 2), 32); |
| 515 | out = xrealloc(out, outalloc); |
| 516 | outpos = out + sofar; |
| 517 | outsz = outalloc - sofar - 1; |
| 518 | #ifdef ICONV_RESTART_RESET |
| 519 | /* |
| 520 | * If iconv(3) messes up piecemeal conversions |
| 521 | * then restore the original pointers, sizes, |
| 522 | * and converter state, then retry converting |
| 523 | * the full string using the reallocated buffer. |
| 524 | */ |
| 525 | insz += cp - (iconv_ibp)in; /* Restore insz */ |
| 526 | cp = (iconv_ibp)in; /* original start value */ |
| 527 | outpos = out + bom_len; /* original start value */ |
| 528 | outsz = outalloc - bom_len - 1; /* new len */ |
| 529 | iconv(conv, NULL, NULL, NULL, NULL); /* reset iconv machinery */ |
| 530 | #endif |
| 531 | } |
| 532 | else { |
| 533 | *outpos = '\0'; |
| 534 | if (outsz_p) |
| 535 | *outsz_p = outpos - out; |
| 536 | break; |
| 537 | } |
| 538 | } |
| 539 | return out; |
| 540 | } |
| 541 | |
| 542 | static const char *fallback_encoding(const char *name) |
| 543 | { |
no test coverage detected