From 5a91b271f6076f5c2972dfa4fcc41b800bba77b7 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 7 Nov 2001 18:14:46 +0000 Subject: add convert_string_allocate() function (This used to be commit 8b494b0be323c983b7ea3d1dcf1f61216396caec) --- source3/lib/charcnv.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 5 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index ebf316d9dd..2929233388 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -26,6 +26,8 @@ static pstring cvtbuf; static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; +static int initialized; + /**************************************************************************** return the name of a charset to give to iconv() ****************************************************************************/ @@ -92,15 +94,14 @@ size_t convert_string(charset_t from, charset_t to, { size_t i_len, o_len; size_t retval; - const char* inbuf = (const char*)src; + char* inbuf = (char*)src; char* outbuf = (char*)dest; - static int initialised; smb_iconv_t descriptor; if (srclen == -1) srclen = strlen(src)+1; - if (!initialised) { - initialised = 1; + if (!initialized) { + initialized = 1; load_case_tables(); init_iconv(); } @@ -118,7 +119,8 @@ size_t convert_string(charset_t from, charset_t to, o_len=destlen; retval=smb_iconv(descriptor,&inbuf, &i_len, &outbuf, &o_len); if(retval==-1) - { char *reason="unknown error"; + { + char *reason="unknown error"; switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; break; case E2BIG: reason="No more room"; @@ -139,6 +141,85 @@ size_t convert_string(charset_t from, charset_t to, return destlen-o_len; } +/* you must provide source lenght -1 is not accepted as lenght. + this function will return the size in bytes of the converted string + or -1 in case of error. + */ +size_t convert_string_allocate(charset_t from, charset_t to, + void const *src, size_t srclen, void **dest) +{ + size_t i_len, o_len, destlen; + size_t retval; + char* inbuf = (char *)src; + char *outbuf, *ob; + smb_iconv_t descriptor; + + *dest = NULL; + + if (src == NULL || srclen == -1) return -1; + + if (!initialized) { + initialized = 1; + load_case_tables(); + init_iconv(); + } + + descriptor = conv_handles[from][to]; + + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + /* conversion not supported, return -1*/ + return -1; + } + + destlen = MAX(srclen, 1024); + outbuf = NULL; +convert: + destlen = destlen * 2; + ob = (char *)realloc(outbuf, destlen); + if (!ob) { + DEBUG(0, ("convert_string_allocate: realloc failed!\n")); + free(outbuf); + return -1; + } + else outbuf = ob; + i_len = srclen; + o_len = destlen; + retval = smb_iconv(descriptor, + &inbuf, &i_len, + &outbuf, &o_len); + if(retval == -1) + { + char *reason="unknown error"; + switch(errno) + { + case EINVAL: + reason="Incomplete multibyte sequence"; + break; + case E2BIG: + goto convert; + break; + case EILSEQ: + reason="Illegal myltibyte sequence"; + break; + } + DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); + /* smb_panic(reason); */ + return -1; + } + + destlen = destlen - o_len; + *dest = (char *)malloc(destlen); + if (!*dest) { + DEBUG(0, ("convert_string_allocate: out of memory!\n")); + free(outbuf); + return -1; + } + memcpy(*dest, outbuf, destlen); + free(outbuf); + + return destlen; +} + int unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) { int size; -- cgit