From 598f78bd1f3c59cfdca91a590bd95298b7d28d9e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Apr 2009 16:03:19 +0200 Subject: charcnv: Import push_codepoint(). --- source3/lib/charcnv.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'source3') diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 374079c8ae..eb794d8347 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -1861,3 +1861,64 @@ codepoint_t next_codepoint(const char *str, size_t *size) /* no other length is valid */ return INVALID_CODEPOINT; } + +/* + push a single codepoint into a CH_UNIX string the target string must + be able to hold the full character, which is guaranteed if it is at + least 5 bytes in size. The caller may pass less than 5 bytes if they + are sure the character will fit (for example, you can assume that + uppercase/lowercase of a character will not add more than 1 byte) + + return the number of bytes occupied by the CH_UNIX character, or + -1 on failure +*/ +_PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c) +{ + smb_iconv_t descriptor; + uint8_t buf[4]; + size_t ilen, olen; + const char *inbuf; + + if (c < 128) { + *str = c; + return 1; + } + + lazy_initialize_conv(); + + descriptor = conv_handles[CH_UNIX][CH_UTF16LE]; + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + return -1; + } + + if (c < 0x10000) { + ilen = 2; + olen = 5; + inbuf = (char *)buf; + SSVAL(buf, 0, c); + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; + } + + c -= 0x10000; + + buf[0] = (c>>10) & 0xFF; + buf[1] = (c>>18) | 0xd8; + buf[2] = c & 0xFF; + buf[3] = ((c>>8) & 0x3) | 0xdc; + + ilen = 4; + olen = 5; + inbuf = (char *)buf; + + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; +} + + -- cgit