]> pd.if.org Git - pdclib.old/blob - internals/_PDCLIB_encoding.h
11e2ac5ee27c81e99903d007363dcae4553c5f27
[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 #ifdef _PDCLIB_WCHAR_IS_UCS2
20 /* Must be cauued with bufsize >= 1, in != NULL, out != NULL, ps != NULL
21  *
22  * Converts a wchar to a UCS4 (char32_t) value. Returns
23  *   1, 2   : Valid character (converted to UCS-4)
24  *   -1     : Encoding error
25  *   -2     : Partial character (only lead surrogate in buffer)
26  */
27 static inline int _PDCLIB_wcrtoc32(
28             _PDCLIB_char32_t    *_PDCLIB_restrict   out, 
29     const   _PDCLIB_wchar_t     *_PDCLIB_restrict   in,
30             _PDCLIB_size_t                          bufsize,
31             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps  
32 )
33 {
34     if(ps->_Surrogate) {
35         // We already have a lead surrogate
36         if(*in & ~0x3FF != 0xDC00) {
37             // Encoding error
38             return -1;
39         } else {
40             // Decode and reset state
41             *out = (ps->_Surrogate & 0x3FF) << 10 | (*in & 0x3FF);
42             ps->_Surrogate = 0;
43             return 1;
44         }
45     } if(*in & ~0x3FF == 0xD800) {
46         // Lead surrogate
47         if(bufsize >= 2) {
48             // Buffer big enough
49             if(in[1] & ~0x3FF != 0xDC00) {
50                 // Encoding error
51                 return -1;
52             } else {
53                 *out = (in[0] & 0x3FF) << 10 | (in[1] & 0x3FF);
54                 return 2;
55             }
56         } else {
57             // Buffer too small - update state
58             ps->_Surrogate = *in;
59             return -2;
60         }
61     } else {
62         // BMP character
63         *out = *in;
64         return 1;
65     }
66 }
67
68 static inline _PDCLIB_size_t _PDCLIB_c32rtowc(
69             _PDCLIB_wchar_t     *_PDCLIB_restrict   out,
70     const   _PDCLIB_char32_t    *_PDCLIB_restrict   in,
71             _PDCLIB_size_t                          bufsize,
72             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps
73 )
74 {
75     if(ps->_Surrogate) {
76         *out = ps->_Surrogate;
77         ps->_Surrogate = 0;
78         return 0;
79     }
80
81     if(*in <= 0xFFFF) {
82         // BMP character
83         *out = *in;
84         return 1;
85     } else {
86         // Supplementary plane character
87         *out = 0xD800 | (*in & 0x3FF);
88         if(bufsize >= 2) {
89             out[1] = 0xDC00 | (*in >> 10);
90             return 2;
91         } else {
92             ps->_Surrogate = 0xDC00 | (*in >> 10);
93             return 1;
94         }
95     }
96 }
97 #else
98 /* Dummy implementation for when wc == c32 */
99 static inline _PDCLIB_size_t _PDCLIB_wcrtoc32(
100             _PDCLIB_char32_t    *_PDCLIB_restrict   out, 
101     const   _PDCLIB_wchar_t     *_PDCLIB_restrict   in,
102             _PDCLIB_size_t                          bufsize,
103             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps  
104 )
105 {
106     *out = *in;
107     return 1;
108 }
109
110 static inline _PDCLIB_size_t _PDCLIB_c32rtowc(
111             _PDCLIB_wchar_t     *_PDCLIB_restrict   out,
112     const   _PDCLIB_char32_t    *_PDCLIB_restrict   in,
113             _PDCLIB_size_t                          bufsize,
114             _PDCLIB_mbstate_t   *_PDCLIB_restrict   ps
115 )
116 {
117     *out = *in;
118     return 1;
119 }
120 #endif
121
122 typedef struct {
123     /* Reads at most *_P_insz bytes from *_P_inbuf and writes the result into 
124      * *_P_outbuf, writing at most *_P_outsz characters. Updates *_P_outbuf,
125      * *_P_outsz, *_P_inbuf, *_P_outsz with the resulting state
126      *
127      * Returns true if the conversion completed successfully (i.e. one of 
128      * _P_outsize or _P_insize reached zero and no coding errors were 
129      * encountered), else return false.
130      */
131     _PDCLIB_bool (*__mbtoc32)(
132         _PDCLIB_char32_t       **_PDCLIB_restrict   _P_outbuf,
133         _PDCLIB_size_t          *_PDCLIB_restrict   _P_outsz,
134         const char             **_PDCLIB_restrict   _P_inbuf,
135         _PDCLIB_size_t          *_PDCLIB_restrict   _P_insz,
136         _PDCLIB_mbstate_t       *_PDCLIB_restrict   _P_ps
137     );
138
139     _PDCLIB_bool (*__c32tomb)(
140         char                   **_PDCLIB_restrict  _P_outbuf,
141         _PDCLIB_size_t          *_PDCLIB_restrict  _P_outsz,
142         const _PDCLIB_char32_t **_PDCLIB_restrict  _P_inbuf,
143         _PDCLIB_size_t          *_PDCLIB_restrict  _P_insz,
144         _PDCLIB_mbstate_t       *_PDCLIB_restrict  _P_ps
145     );
146 } _PDCLIB_charcodec;
147
148 #endif