]> pd.if.org Git - pdclib/blob - functions/uchar/c16rtomb.c
PDCLIB-2 c16rtomb: did not support NULL destination buffer mode (count output characters)
[pdclib] / 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     char buf[s ? 0 : MB_CUR_MAX];\r
28     s =      s ? s : buf;\r
29 \r
30     if(!l->_Codec->__c16stombs) {\r
31         // Codec doesn't support direct conversion - translate via UCS-4\r
32         if(ps->_Surrogate == 0) {\r
33             // No pending surrogate\r
34             if((c16 & 0xF800) == 0xD800) {\r
35                 // Surrogate range\r
36                 if((c16 & 0x0400) == 0) {\r
37                     // 0xD800 -> 0xDBFF leading surrogate\r
38                     ps->_Surrogate = c16;\r
39 \r
40                     // Need more data\r
41                     // Return 0 - we haven't output anything yet\r
42 \r
43                     /* STD: ISO/IEC 9899:2011 is very implcifit about this being\r
44                      *      the correct return value. N1040, from which the \r
45                      *      function was adopted, is explicit about 0 being a \r
46                      *      valid return.\r
47                      */\r
48                     return (size_t) 0;\r
49                 } else {\r
50                     // 0xDC00 -> 0xDFFF trailing surrogate\r
51                     errno = EILSEQ;\r
52                     return (size_t) -1;\r
53                 }\r
54             } else {\r
55                 // BMP range - UTF16 == UCS-4, pass through to c32rtomb_l\r
56                 return c32rtomb_l(s, c16, ps, l);\r
57             }\r
58         } else {\r
59             // We have a stored surrogate\r
60             if((c16 & 0xFC00) == 0xDC00) {\r
61                 // Trailing surrogate\r
62                 char32_t c32 = (ps->_Surrogate & 0x3FF) << 10 | (c16 & 0x3FF);\r
63                 ps->_Surrogate = 0;\r
64                 return c32rtomb_l(s, c32, ps, l);\r
65             } else {\r
66                 // Not a trailing surrogate - encoding error\r
67                 errno = EILSEQ;\r
68                 return (size_t) -1;\r
69             }\r
70 \r
71         }\r
72     } else {\r
73         // Codec supports direct conversion\r
74         size_t srcsz  = 1;\r
75         size_t dstsz  = MB_CUR_MAX;\r
76         size_t dstrem = dstsz;\r
77 \r
78         if(l->_Codec->__c16stombs(&s, &dstrem, &psrc, &srcsz, ps)) {\r
79             // Successful conversion\r
80             return dstsz - dstrem;\r
81         } else {\r
82             errno = EILSEQ;\r
83             return (size_t) -1;\r
84         }\r
85     }\r
86 }\r
87 \r
88 size_t c16rtomb(\r
89     char        *restrict   s, \r
90     char16_t                c16,\r
91     mbstate_t   *restrict   ps\r
92 )\r
93 {\r
94     return c16rtomb_l(s, c16, ps, _PDCLIB_threadlocale());\r
95 }\r
96 \r
97 #endif\r
98 \r
99 #ifdef TEST\r
100 #include <_PDCLIB_test.h>\r
101 \r
102 int main( void )\r
103 {\r
104     TESTCASE( NO_TESTDRIVER );\r
105     return TEST_RESULTS;\r
106 }\r
107 #endif\r