]> pd.if.org Git - pdclib.old/blob - internals/_PDCLIB_encoding.h
PDCLIB-2 PDCLIB-9 wcrtomb
[pdclib.old] / internals / _PDCLIB_encoding.h
1 /* Encoding support <_PDCLIB_encoding.h>
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #ifndef __PDCLIB_ENCODING_H
8 #define __PDCLIB_ENCODING_H __PDCLIB_ENCODING_H
9 #include <uchar.h>
10
11 /* Must be cauued with bufsize >= 1, in != NULL, out != NULL, ps != NULL
12  *
13  * Converts a UTF-16 (char16_t) to a UCS4 (char32_t) value. Returns
14  *   1, 2   : Valid character (converted to UCS-4)
15  *   -1     : Encoding error
16  *   -2     : Partial character (only lead surrogate in buffer)
17  */
18 static inline int _PDCLIB_c16rtoc32(
19             _PDCLIB_char32_t    *_PDCLIB_restrict   out, 
20     const   _PDCLIB_char16_t    *_PDCLIB_restrict   in,
21             _PDCLIB_size_t                          bufsize,
22             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps  
23 )
24 {
25     if(ps->_Surrogate) {
26         // We already have a lead surrogate
27         if((*in & ~0x3FF) != 0xDC00) {
28             // Encoding error
29             return -1;
30         } else {
31             // Decode and reset state
32             *out = (ps->_Surrogate & 0x3FF) << 10 | (*in & 0x3FF);
33             ps->_Surrogate = 0;
34             return 1;
35         }
36     } if((*in & ~0x3FF) == 0xD800) {
37         // Lead surrogate
38         if(bufsize >= 2) {
39             // Buffer big enough
40             if((in[1] & ~0x3FF) != 0xDC00) {
41                 // Encoding error
42                 return -1;
43             } else {
44                 *out = (in[0] & 0x3FF) << 10 | (in[1] & 0x3FF);
45                 return 2;
46             }
47         } else {
48             // Buffer too small - update state
49             ps->_Surrogate = *in;
50             return -2;
51         }
52     } else {
53         // BMP character
54         *out = *in;
55         return 1;
56     }
57 }
58
59 static inline _PDCLIB_size_t _PDCLIB_c32rtoc16(
60             _PDCLIB_wchar_t     *_PDCLIB_restrict   out,
61     const   _PDCLIB_char32_t    *_PDCLIB_restrict   in,
62             _PDCLIB_size_t                          bufsize,
63             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps
64 )
65 {
66     if(ps->_Surrogate) {
67         *out = ps->_Surrogate;
68         ps->_Surrogate = 0;
69         return 0;
70     }
71
72     if(*in <= 0xFFFF) {
73         // BMP character
74         *out = *in;
75         return 1;
76     } else {
77         // Supplementary plane character
78         *out = 0xD800 | (*in & 0x3FF);
79         if(bufsize >= 2) {
80             out[1] = 0xDC00 | (*in >> 10);
81             return 2;
82         } else {
83             ps->_Surrogate = 0xDC00 | (*in >> 10);
84             return 1;
85         }
86     }
87 }
88
89 struct _PDCLIB_charcodec {
90     /* Reads at most *_P_insz code units from *_P_inbuf and writes the result 
91      * into *_P_outbuf, writing at most *_P_outsz code units. Updates 
92      * *_P_outbuf, *_P_outsz, *_P_inbuf, *_P_outsz with the resulting state
93      *
94      * If _P_outbuf is NULL, then the input must be processed but no output 
95      * generated. _P_outsz may be processed as normal.
96      *
97      * Returns true if the conversion completed successfully (i.e. one of 
98      * _P_outsize or _P_insize reached zero and no coding errors were 
99      * encountered), else return false.
100      */
101
102     /* UCS-4 variants. Mandatory. */
103
104     _PDCLIB_bool (*__mbstoc32s)(
105         _PDCLIB_char32_t       *_PDCLIB_restrict *_PDCLIB_restrict   _P_outbuf,
106         _PDCLIB_size_t                           *_PDCLIB_restrict   _P_outsz,
107         const char             *_PDCLIB_restrict *_PDCLIB_restrict   _P_inbuf,
108         _PDCLIB_size_t                           *_PDCLIB_restrict   _P_insz,
109         _PDCLIB_mbstate_t                        *_PDCLIB_restrict   _P_ps
110     );
111
112     _PDCLIB_bool (*__c32stombs)(
113         char                   *_PDCLIB_restrict *_PDCLIB_restrict  _P_outbuf,
114         _PDCLIB_size_t                           *_PDCLIB_restrict  _P_outsz,
115         const _PDCLIB_char32_t *_PDCLIB_restrict *_PDCLIB_restrict  _P_inbuf,
116         _PDCLIB_size_t                           *_PDCLIB_restrict  _P_insz,
117         _PDCLIB_mbstate_t                        *_PDCLIB_restrict  _P_ps
118     );
119
120     /* UTF-16 variants; same as above except optional. 
121      *
122      * If not provided, _PDCLib will internally synthesize on top of the UCS-4
123      * variants above, albeit at a performance cost.
124      */
125
126     _PDCLIB_bool (*__mbstoc16s)(
127         _PDCLIB_char16_t       *_PDCLIB_restrict *_PDCLIB_restrict   _P_outbuf,
128         _PDCLIB_size_t                           *_PDCLIB_restrict   _P_outsz,
129         const char             *_PDCLIB_restrict *_PDCLIB_restrict   _P_inbuf,
130         _PDCLIB_size_t                           *_PDCLIB_restrict   _P_insz,
131         _PDCLIB_mbstate_t                        *_PDCLIB_restrict   _P_ps
132     );
133
134     _PDCLIB_bool (*__c16stombs)(
135         char                   *_PDCLIB_restrict *_PDCLIB_restrict  _P_outbuf,
136         _PDCLIB_size_t                           *_PDCLIB_restrict  _P_outsz,
137         const _PDCLIB_char16_t *_PDCLIB_restrict *_PDCLIB_restrict  _P_inbuf,
138         _PDCLIB_size_t                           *_PDCLIB_restrict  _P_insz,
139         _PDCLIB_mbstate_t                        *_PDCLIB_restrict  _P_ps
140     );
141
142     size_t __mb_max;
143 };
144
145 /* mbstate _PendState values */
146 enum {
147     /* Nothing pending; _PendChar ignored */
148     _PendClear = 0, 
149
150     /* Process the character stored in _PendChar before reading the buffer 
151      * passed for the conversion
152      */
153     _PendPrefix = 1,
154 };
155
156 /* XXX Defining these here is temporary - will move to xlocale in future */
157 size_t mbrtoc16_l(
158         char16_t    *_PDCLIB_restrict   pc16,
159         const char  *_PDCLIB_restrict   s, 
160         size_t                          n,
161         mbstate_t   *_PDCLIB_restrict   ps,
162 _PDCLIB_locale_t     _PDCLIB_restrict   l);
163
164 size_t c16rtomb_l(
165         char        *_PDCLIB_restrict   s, 
166         char16_t                        c16, 
167         mbstate_t   *_PDCLIB_restrict   ps,
168 _PDCLIB_locale_t     _PDCLIB_restrict   l);
169
170 size_t mbrtoc32_l(
171         char32_t    *_PDCLIB_restrict   pc32,
172         const char  *_PDCLIB_restrict   s, 
173         size_t                          n,
174         mbstate_t   *_PDCLIB_restrict   ps,
175 _PDCLIB_locale_t     _PDCLIB_restrict   l);
176
177 size_t c32rtomb_l(
178         char        *_PDCLIB_restrict   s, 
179         char32_t                        c32,
180         mbstate_t   *_PDCLIB_restrict   ps,
181 _PDCLIB_locale_t     _PDCLIB_restrict   l);
182
183 #define _PDCLIB_WCHAR_ENCODING_UTF16 16
184 #define _PDCLIB_WCHAR_ENCODING_UCS4  32
185
186 #if !defined(_PDCLIB_WCHAR_ENCODING)
187     #define _PDCLIB_WCHAR_ENCODING 0
188 #endif
189
190 #if _PDCLIB_WCHAR_ENCODING == _PDCLIB_WCHAR_ENCODING_UTF16
191     #define _PDCLIB_mbrtocwc_l mbrtoc16_l
192     #define _PDCLIB_mbrtocwc   mbrtoc16
193     #define _PDCLIB_cwcrtomb_l c16rtomb_l
194     #define _PDCLIB_cwcrtomb   c16rtomb
195 #elif _PDCLIB_WCHAR_ENCODING == _PDCLIB_WCHAR_ENCODING_UCS4
196     #define _PDCLIB_mbrtocwc_l mbrtoc32_l
197     #define _PDCLIB_mbrtocwc   mbrtoc32
198     #define _PDCLIB_cwcrtomb_l c32rtomb_l
199     #define _PDCLIB_cwcrtomb   c32rtomb
200 #else
201     #error _PDCLIB_WCHAR_ENCODING not defined correctly
202     #error Define to one of _PDCLIB_WCHAR_ENCODING_UCS4 or _PDCLIB_WCHAR_ENCODING_UTF16
203 #endif
204
205 #endif