]> pd.if.org Git - pdclib/blob - functions/uchar/c16rtomb.c
bce172bd00ff070a5095d33747ff273d56b8021b
[pdclib] / functions / uchar / c16rtomb.c
1 /* c16rtomb( char *, char16_t, mbstate_t * )\r
2 \r
3    This file is part of the Public Domain C Library (PDCLib).\r
4    Permission is granted to use, modify, and / or redistribute at will.\r
5 */\r
6 \r
7 #ifndef REGTEST\r
8 #include <uchar.h>\r
9 #include <errno.h>\r
10 #include <stdint.h>\r
11 #include <assert.h>\r
12 #include <stdlib.h>\r
13 #include "_PDCLIB_encoding.h"\r
14 #include "_PDCLIB_locale.h"\r
15 \r
16 size_t c16rtomb_l(\r
17     char        *restrict   s, \r
18     char16_t                c16,\r
19     mbstate_t   *restrict   ps,\r
20     locale_t     restrict   l\r
21 )\r
22 {\r
23     const char16_t *restrict psrc = &c16;\r
24     char buf[s ? 0 : MB_CUR_MAX];\r
25     s =      s ? s : buf;\r
26 \r
27     if(!l->_Codec->__c16stombs) {\r
28         // Codec doesn't support direct conversion - translate via UCS-4\r
29         if(ps->_Surrogate == 0) {\r
30             // No pending surrogate\r
31             if((c16 & 0xF800) == 0xD800) {\r
32                 // Surrogate range\r
33                 if((c16 & 0x0400) == 0) {\r
34                     // 0xD800 -> 0xDBFF leading surrogate\r
35                     ps->_Surrogate = c16;\r
36 \r
37                     // Need more data\r
38                     // Return 0 - we haven't output anything yet\r
39 \r
40                     /* STD: ISO/IEC 9899:2011 is very implcifit about this being\r
41                      *      the correct return value. N1040, from which the \r
42                      *      function was adopted, is explicit about 0 being a \r
43                      *      valid return.\r
44                      */\r
45                     return (size_t) 0;\r
46                 } else {\r
47                     // 0xDC00 -> 0xDFFF trailing surrogate\r
48                     errno = EILSEQ;\r
49                     return (size_t) -1;\r
50                 }\r
51             } else {\r
52                 // BMP range - UTF16 == UCS-4, pass through to c32rtomb_l\r
53                 return c32rtomb_l(s, c16, ps, l);\r
54             }\r
55         } else {\r
56             // We have a stored surrogate\r
57             if((c16 & 0xFC00) == 0xDC00) {\r
58                 // Trailing surrogate\r
59                 char32_t c32 = (ps->_Surrogate & 0x3FF) << 10 | (c16 & 0x3FF);\r
60                 ps->_Surrogate = 0;\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