diff options
author | Xavier Roche <xroche@users.noreply.github.com> | 2012-05-06 15:37:51 +0000 |
---|---|---|
committer | Xavier Roche <xroche@users.noreply.github.com> | 2012-05-06 15:37:51 +0000 |
commit | 39021d22d2bce1e55e2dd80811313433d8d38f9c (patch) | |
tree | d6394f6cf20daa007f851e5feb168733cdf2ee9c /src | |
parent | bbaccf7ba1676bd65c957102995396aae02c352a (diff) |
iconv fixes
Diffstat (limited to 'src')
-rw-r--r-- | src/htscharset.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/src/htscharset.c b/src/htscharset.c index 4deba12..4c97228 100644 --- a/src/htscharset.c +++ b/src/htscharset.c @@ -313,7 +313,7 @@ char *hts_convertStringSystemToUTF8(const char *s, size_t size) { char *hts_convertStringToUTF8(const char *s, size_t size, const char *charset) { /* Empty string ? */ if (size == 0) { - return strndup(s, size); + return strdup(""); } /* Already UTF-8 ? */ if (strcasecmp(charset, "utf-8") == 0 || strcasecmp(charset, "utf8") == 0) { @@ -328,29 +328,48 @@ char *hts_convertStringToUTF8(const char *s, size_t size, const char *charset) { size_t outbufCapa = 0; char *outbuf = NULL; size_t outbytesleft = 0; - while(inbytesleft != 0) { - const size_t ret = iconv(cp, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + size_t finalSize; + + /* Initial size to around the string size */ + for(outbufCapa = 16 ; outbufCapa < size + 1 ; outbufCapa *= 2) ; + outbuf = malloc(outbufCapa); + + /* Convert */ + while(outbuf != NULL && inbytesleft != 0) { + const size_t offset = outbufCapa - outbytesleft; + char *outbufCurrent = outbuf + offset; + const size_t ret = iconv(cp, &inbuf, &inbytesleft, &outbufCurrent, &outbytesleft); if (ret == (size_t) -1) { if (errno == E2BIG) { const size_t used = outbufCapa - outbytesleft; - if (outbufCapa == 0) { - outbufCapa = 16; - } else { - outbufCapa *= 2; - } + outbufCapa *= 2; outbuf = realloc(outbuf, outbufCapa); if (outbuf == NULL) { break; } outbytesleft = outbufCapa - used; + } else { + free(outbuf); + outbuf = NULL; + break; } } } + /* Final size ? */ + finalSize = outbufCapa - outbytesleft; + + /* Terminating \0 */ + if (outbuf != NULL && finalSize + 1 >= outbufCapa) { + outbuf = realloc(outbuf, finalSize + 1); + } + if (outbuf != NULL) + outbuf[finalSize] = '\0'; + /* Close codepage */ iconv_close(cp); - /* Return resulr (may be NULL) */ + /* Return result (may be NULL) */ return outbuf; } } |