size_t charset_decompose ( charset_t ch, char * src, size_t inlen, char * dst, size_t outlen) { char *buffer; ucs2_t u[MAXPATHLEN]; size_t len; size_t ilen; if ((size_t)(-1) == (len = convert_string_allocate_internal(ch, CH_UCS2, src, inlen, &buffer)) ) return len; ilen=sizeof(u); if ( (size_t)-1 == (ilen = decompose_w((ucs2_t *)buffer, len, u, &ilen)) ) { free (buffer); return (size_t)(-1); } if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, (char*)u, ilen, dst, outlen)) ) { free (buffer); return (size_t)(-1); } free(buffer); return (len); }
size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen) { size_t i_len, o_len; ucs2_t *u; ucs2_t buffer[MAXPATHLEN]; ucs2_t buffer2[MAXPATHLEN]; /* convert from_set to UCS2 */ if ((size_t)-1 == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, (char*) buffer, sizeof(buffer))) ) { LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from)); return (size_t) -1; } /* Do pre/decomposition */ i_len = sizeof(buffer2); u = buffer2; if (charsets[to] && (charsets[to]->flags & CHARSET_DECOMPOSED) ) { if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) ) return (size_t)-1; } else if (!charsets[from] || (charsets[from]->flags & CHARSET_DECOMPOSED)) { if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) ) return (size_t)-1; } else { u = buffer; i_len = o_len; } /* Convert UCS2 to to_set */ if ((size_t)(-1) == ( o_len = convert_string_internal( CH_UCS2, to, (char*) u, i_len, dest, destlen)) ) { LOG(log_error, logtype_default, "Conversion failed (CH_UCS2 to %s):%s", charset_name(to), strerror(errno)); return (size_t) -1; } return o_len; }
size_t charset_strlower(charset_t ch, const char *src, size_t srclen, char *dest, size_t destlen) { size_t size; char *buffer; size = convert_string_allocate_internal(ch, CH_UCS2, src, srclen, (char **) &buffer); if (size == (size_t)-1) { SAFE_FREE(buffer); return size; } if (!strlower_w((ucs2_t *)buffer) && (dest == src)) { free(buffer); return srclen; } size = convert_string_internal(CH_UCS2, ch, buffer, size, dest, destlen); free(buffer); return size; }
size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen, BOOL allow_bad_conv) { /* * NB. We deliberately don't do a strlen here if srclen == -1. * This is very expensive over millions of calls and is taken * care of in the slow path in convert_string_internal. JRA. */ #ifdef DEVELOPER SMB_ASSERT(destlen != (size_t)-1); #endif if (srclen == 0) return 0; if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t slen = srclen; size_t dlen = destlen; unsigned char lastp = '\0'; size_t retval = 0; /* If all characters are ascii, fast path here. */ while (slen && dlen) { if ((lastp = *p) <= 0x7f) { *q++ = *p++; if (slen != (size_t)-1) { slen--; } dlen--; retval++; if (!lastp) break; } else { #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS goto general_case; #else return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv); #endif } } if (!dlen) { /* Even if we fast path we should note if we ran out of room. */ if (((slen != (size_t)-1) && slen) || ((slen == (size_t)-1) && lastp)) { errno = E2BIG; } } return retval; } else if (from == CH_UTF16LE && to != CH_UTF16LE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; size_t slen = srclen; size_t dlen = destlen; unsigned char lastp = '\0'; /* If all characters are ascii, fast path here. */ while (((slen == (size_t)-1) || (slen >= 2)) && dlen) { if (((lastp = *p) <= 0x7f) && (p[1] == 0)) { *q++ = *p; if (slen != (size_t)-1) { slen -= 2; } p += 2; dlen--; retval++; if (!lastp) break; } else { #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS goto general_case; #else return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv); #endif } } if (!dlen) { /* Even if we fast path we should note if we ran out of room. */ if (((slen != (size_t)-1) && slen) || ((slen == (size_t)-1) && lastp)) { errno = E2BIG; } } return retval; } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; size_t slen = srclen; size_t dlen = destlen; unsigned char lastp = '\0'; /* If all characters are ascii, fast path here. */ while (slen && (dlen >= 2)) { if ((lastp = *p) <= 0x7F) { *q++ = *p++; *q++ = '\0'; if (slen != (size_t)-1) { slen--; } dlen -= 2; retval += 2; if (!lastp) break; } else { #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS goto general_case; #else return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv); #endif } } if (!dlen) { /* Even if we fast path we should note if we ran out of room. */ if (((slen != (size_t)-1) && slen) || ((slen == (size_t)-1) && lastp)) { errno = E2BIG; } } return retval; } #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS general_case: #endif return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv); }