charcnv: Import push_codepoint().
authorJelmer Vernooij <jelmer@samba.org>
Thu, 23 Apr 2009 14:03:19 +0000 (16:03 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Thu, 23 Apr 2009 15:50:18 +0000 (17:50 +0200)
source3/lib/charcnv.c

index 374079c8ae701b34c2a6404233fb45ded93da7fc..eb794d8347f21a967ec936527a5545c95289c8e4 100644 (file)
@@ -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;
+}
+
+