]> pd.if.org Git - pdclib.old/blob - internals/_PDCLIB_encoding.h
PDCLIB-2 PDCLIB-12: If the internal character conversion routines are called
[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 "_PDCLIB_int.h"
10
11 #ifndef __cplusplus
12 typedef _PDCLIB_int16_t         _PDCLIB_char16_t;
13 typedef _PDCLIB_int32_t         _PDCLIB_char32_t;
14 #else
15 typedef char16_t                _PDCLIB_char16_t;
16 typedef char32_t                _PDCLIB_char32_t;
17 #endif
18
19 /* -------------------------------------------------------------------------- */
20 /* mbstate_t                                                                  */
21 /* -------------------------------------------------------------------------- */
22
23 typedef struct _PDCLIB_mbstate_t {
24     union {
25         /* Is this the best way to represent this? Is this big enough? */
26         _PDCLIB_uint64_t _St64[15];
27         _PDCLIB_uint32_t _St32[31];
28         _PDCLIB_uint16_t _St16[62];
29         unsigned char    _StUC[124];
30         signed   char    _StSC[124];
31                  char    _StC [124];
32     };
33
34     union {
35         /* c16/related functions: Surrogate storage
36          *
37          * If zero, no surrogate pending. If nonzero, surrogate.
38          */
39         _PDCLIB_uint16_t     _Surrogate;
40
41         /* Reserved for potential mbtoutf8/etc functions */
42         unsigned char        _U8[4];
43     };
44 } _PDCLIB_mbstate_t;
45
46 #ifdef _PDCLIB_WCHAR_IS_UCS2
47 /* Must be cauued with bufsize >= 1, in != NULL, out != NULL, ps != NULL
48  *
49  * Converts a wchar to a UCS4 (char32_t) value. Returns
50  *   1, 2   : Valid character (converted to UCS-4)
51  *   -1     : Encoding error
52  *   -2     : Partial character (only lead surrogate in buffer)
53  */
54 static inline int _PDCLIB_wcrtoc32(
55             _PDCLIB_char32_t    *_PDCLIB_restrict   out, 
56     const   _PDCLIB_wchar_t     *_PDCLIB_restrict   in,
57             _PDCLIB_size_t                          bufsize,
58             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps  
59 )
60 {
61     if(ps->_Surrogate) {
62         // We already have a lead surrogate
63         if(*in & ~0x3FF != 0xDC00) {
64             // Encoding error
65             return -1;
66         } else {
67             // Decode and reset state
68             *out = (ps->_Surrogate & 0x3FF) << 10 | (*in & 0x3FF);
69             ps->_Surrogate = 0;
70             return 1;
71         }
72     } if(*in & ~0x3FF == 0xD800) {
73         // Lead surrogate
74         if(bufsize >= 2) {
75             // Buffer big enough
76             if(in[1] & ~0x3FF != 0xDC00) {
77                 // Encoding error
78                 return -1;
79             } else {
80                 *out = (in[0] & 0x3FF) << 10 | (in[1] & 0x3FF);
81                 return 2;
82             }
83         } else {
84             // Buffer too small - update state
85             ps->_Surrogate = *in;
86             return -2;
87         }
88     } else {
89         // BMP character
90         *out = *in;
91         return 1;
92     }
93 }
94
95 static inline _PDCLIB_size_t _PDCLIB_c32rtowc(
96             _PDCLIB_wchar_t     *_PDCLIB_restrict   out,
97     const   _PDCLIB_char32_t    *_PDCLIB_restrict   in,
98             _PDCLIB_size_t                          bufsize,
99             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps
100 )
101 {
102     if(ps->_Surrogate) {
103         *out = ps->_Surrogate;
104         ps->_Surrogate = 0;
105         return 0;
106     }
107
108     if(*in <= 0xFFFF) {
109         // BMP character
110         *out = *in;
111         return 1;
112     } else {
113         // Supplementary plane character
114         *out = 0xD800 | (*in & 0x3FF);
115         if(bufsize >= 2) {
116             out[1] = 0xDC00 | (*in >> 10);
117             return 2;
118         } else {
119             ps->_Surrogate = 0xDC00 | (*in >> 10);
120             return 1;
121         }
122     }
123 }
124 #else
125 /* Dummy implementation for when wc == c32 */
126 static inline _PDCLIB_size_t _PDCLIB_wcrtoc32(
127             _PDCLIB_char32_t    *_PDCLIB_restrict   out, 
128     const   _PDCLIB_wchar_t     *_PDCLIB_restrict   in,
129             _PDCLIB_size_t                          bufsize,
130             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps  
131 )
132 {
133     *out = *in;
134     return 1;
135 }
136
137 static inline _PDCLIB_size_t _PDCLIB_c32rtowc(
138             _PDCLIB_wchar_t     *_PDCLIB_restrict   out,
139     const   _PDCLIB_char32_t    *_PDCLIB_restrict   in,
140             _PDCLIB_size_t                          bufsize,
141             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps
142 )
143 {
144     *out = *in;
145     return 1;
146 }
147 #endif
148
149 typedef struct {
150     /* Reads at most *_P_insz code units from *_P_inbuf and writes the result 
151      * into *_P_outbuf, writing at most *_P_outsz code units. Updates 
152      * *_P_outbuf, *_P_outsz, *_P_inbuf, *_P_outsz with the resulting state
153      *
154      * If _P_outbuf is NULL, then the input must be processed but no output 
155      * generated. _P_outsz may be processed as normal.
156      *
157      * Returns true if the conversion completed successfully (i.e. one of 
158      * _P_outsize or _P_insize reached zero and no coding errors were 
159      * encountered), else return false.
160      */
161
162     /* UCS-4 variants. Mandatory. */
163
164     _PDCLIB_bool (*__mbstoc32s)(
165         _PDCLIB_char32_t       **_PDCLIB_restrict   _P_outbuf,
166         _PDCLIB_size_t          *_PDCLIB_restrict   _P_outsz,
167         const char             **_PDCLIB_restrict   _P_inbuf,
168         _PDCLIB_size_t          *_PDCLIB_restrict   _P_insz,
169         _PDCLIB_mbstate_t       *_PDCLIB_restrict   _P_ps
170     );
171
172     _PDCLIB_bool (*__c32stombs)(
173         char                   **_PDCLIB_restrict  _P_outbuf,
174         _PDCLIB_size_t          *_PDCLIB_restrict  _P_outsz,
175         const _PDCLIB_char32_t **_PDCLIB_restrict  _P_inbuf,
176         _PDCLIB_size_t          *_PDCLIB_restrict  _P_insz,
177         _PDCLIB_mbstate_t       *_PDCLIB_restrict  _P_ps
178     );
179
180     /* UTF-16 variants; same as above except optional. 
181      *
182      * If not provided, _PDCLib will internally synthesize on top of the UCS-4
183      * variants above, albeit at a performance cost.
184      */
185
186     _PDCLIB_bool (*__mbstoc16s)(
187         _PDCLIB_char16_t       **_PDCLIB_restrict   _P_outbuf,
188         _PDCLIB_size_t          *_PDCLIB_restrict   _P_outsz,
189         const char             **_PDCLIB_restrict   _P_inbuf,
190         _PDCLIB_size_t          *_PDCLIB_restrict   _P_insz,
191         _PDCLIB_mbstate_t       *_PDCLIB_restrict   _P_ps
192     );
193
194     _PDCLIB_bool (*__c16stombs)(
195         char                   **_PDCLIB_restrict  _P_outbuf,
196         _PDCLIB_size_t          *_PDCLIB_restrict  _P_outsz,
197         const _PDCLIB_char16_t **_PDCLIB_restrict  _P_inbuf,
198         _PDCLIB_size_t          *_PDCLIB_restrict  _P_insz,
199         _PDCLIB_mbstate_t       *_PDCLIB_restrict  _P_ps
200     );
201 } _PDCLIB_charcodec;
202
203 #endif