]> pd.if.org Git - pdclib.old/blob - functions/uchar/c16rtomb.c
PDCLIB-2 PDCLIB-9 Add single character unicode conversion functions (C11)
[pdclib.old] / functions / uchar / c16rtomb.c
1 /* c16rtomb(\r
2     char        *restrict   s, \r
3     char16_t                c16,\r
4     mbstate_t   *restrict   ps);\r
5 \r
6    This file is part of the Public Domain C Library (PDCLib).\r
7    Permission is granted to use, modify, and / or redistribute at will.\r
8 */\r
9 \r
10 #ifndef REGTEST\r
11 #include <uchar.h>\r
12 #include <errno.h>\r
13 #include <stdint.h>\r
14 #include <assert.h>\r
15 #include <stdlib.h>\r
16 #include <_PDCLIB_encoding.h>\r
17 #include <_PDCLIB_locale.h>\r
18 \r
19 size_t c16rtomb_l(\r
20     char        *restrict   s, \r
21     char16_t                c16,\r
22     mbstate_t   *restrict   ps,\r
23     locale_t     restrict   l\r
24 )\r
25 {\r
26     const char16_t *restrict psrc = &c16;\r
27 \r
28     if(!l->_Codec->__c16stombs) {\r
29         // Codec doesn't support direct conversion - translate via UCS-4\r
30         if(ps->_Surrogate == 0) {\r
31             // No pending surrogate\r
32             if((c16 & 0xF800) == 0xD800) {\r
33                 // Surrogate range\r
34                 if((c16 & 0x0400) == 0) {\r
35                     // 0xD800 -> 0xDBFF leading surrogate\r
36                     ps->_Surrogate = c16;\r
37 \r
38                     // Need more data\r
39                     // Return 0 - we haven't output anything yet\r
40 \r
41                     /* STD: ISO/IEC 9899:2011 is very implcifit about this being\r
42                      *      the correct return value. N1040, from which the \r
43                      *      function was adopted, is explicit about 0 being a \r
44                      *      valid return.\r
45                      */\r
46                     return (size_t) 0;\r
47                 } else {\r
48                     // 0xDC00 -> 0xDFFF trailing surrogate\r
49                     errno = EILSEQ;\r
50                     return (size_t) -1;\r
51                 }\r
52             } else {\r
53                 // BMP range - UTF16 == UCS-4, pass through to c32rtomb_l\r
54                 return c32rtomb_l(s, c16, ps, l);\r
55             }\r
56         } else {\r
57             // We have a stored surrogate\r
58             if((c16 & 0xFC00) == 0xDC00) {\r
59                 // Trailing surrogate\r
60                 char32_t c32 = (ps->_Surrogate & 0x3FF) << 10 | (c16 & 0x3FF);\r
61                 return c32rtomb_l(s, c32, ps, l);\r
62             } else {\r
63                 // Not a trailing surrogate - encoding error\r
64                 errno = EILSEQ;\r
65                 return (size_t) -1;\r
66             }\r
67 \r
68         }\r
69     } else {\r
70         // Codec supports direct conversion\r
71         size_t srcsz  = 1;\r
72         size_t dstsz  = MB_CUR_MAX;\r
73         size_t dstrem = dstsz;\r
74 \r
75         if(l->_Codec->__c16stombs(&s, &dstrem, &psrc, &srcsz, ps)) {\r
76             // Successful conversion\r
77             return dstsz - dstrem;\r
78         } else {\r
79             errno = EILSEQ;\r
80             return (size_t) -1;\r
81         }\r
82     }\r
83 }\r
84 \r
85 size_t c16rtomb(\r
86     char        *restrict   s, \r
87     char16_t                c16,\r
88     mbstate_t   *restrict   ps\r
89 )\r
90 {\r
91     return c16rtomb_l(s, c16, ps, _PDCLIB_threadlocale());\r
92 }\r
93 \r
94 #endif\r
95 \r
96 #ifdef TEST\r
97 #include <_PDCLIB_test.h>\r
98 \r
99 int main( void )\r
100 {\r
101     TESTCASE( NO_TESTDRIVER );\r
102     return TEST_RESULTS;\r
103 }\r
104 #endif\r