#endif
typedef struct {
- /* Reads at most *_P_insz bytes from *_P_inbuf and writes the result into
- * *_P_outbuf, writing at most *_P_outsz characters. Updates *_P_outbuf,
- * *_P_outsz, *_P_inbuf, *_P_outsz with the resulting state
+ /* Reads at most *_P_insz code units from *_P_inbuf and writes the result
+ * into *_P_outbuf, writing at most *_P_outsz code units. Updates
+ * *_P_outbuf, *_P_outsz, *_P_inbuf, *_P_outsz with the resulting state
+ *
+ * If _P_outbuf is NULL, then the input must be processed but no output
+ * generated. _P_outsz may be processed as normal.
*
* Returns true if the conversion completed successfully (i.e. one of
* _P_outsize or _P_insize reached zero and no coding errors were
* encountered), else return false.
*/
- _PDCLIB_bool (*__mbtoc32)(
+
+ /* UCS-4 variants. Mandatory. */
+
+ _PDCLIB_bool (*__mbstoc32s)(
_PDCLIB_char32_t **_PDCLIB_restrict _P_outbuf,
_PDCLIB_size_t *_PDCLIB_restrict _P_outsz,
const char **_PDCLIB_restrict _P_inbuf,
_PDCLIB_mbstate_t *_PDCLIB_restrict _P_ps
);
- _PDCLIB_bool (*__c32tomb)(
+ _PDCLIB_bool (*__c32stombs)(
char **_PDCLIB_restrict _P_outbuf,
_PDCLIB_size_t *_PDCLIB_restrict _P_outsz,
const _PDCLIB_char32_t **_PDCLIB_restrict _P_inbuf,
_PDCLIB_size_t *_PDCLIB_restrict _P_insz,
_PDCLIB_mbstate_t *_PDCLIB_restrict _P_ps
);
+
+ /* UTF-16 variants; same as above except optional.
+ *
+ * If not provided, _PDCLib will internally synthesize on top of the UCS-4
+ * variants above, albeit at a performance cost.
+ */
+
+ _PDCLIB_bool (*__mbstoc16s)(
+ _PDCLIB_char16_t **_PDCLIB_restrict _P_outbuf,
+ _PDCLIB_size_t *_PDCLIB_restrict _P_outsz,
+ const char **_PDCLIB_restrict _P_inbuf,
+ _PDCLIB_size_t *_PDCLIB_restrict _P_insz,
+ _PDCLIB_mbstate_t *_PDCLIB_restrict _P_ps
+ );
+
+ _PDCLIB_bool (*__c16stombs)(
+ char **_PDCLIB_restrict _P_outbuf,
+ _PDCLIB_size_t *_PDCLIB_restrict _P_outsz,
+ const _PDCLIB_char16_t **_PDCLIB_restrict _P_inbuf,
+ _PDCLIB_size_t *_PDCLIB_restrict _P_insz,
+ _PDCLIB_mbstate_t *_PDCLIB_restrict _P_ps
+ );
} _PDCLIB_charcodec;
#endif
goto end_conversion; \
} while(0)
-#define OUT32(_c) do { \
- (*((*p_outbuf)++)) = (_c); \
- (*p_outsz)--; \
- _PDCLIB_UNDEFINED(accum); \
- state = DecStart; \
+#define OUT32(_c) do { \
+ if(p_outbuf) \
+ (*((*p_outbuf)++)) = (_c); \
+ (*p_outsz)--; \
+ _PDCLIB_UNDEFINED(accum); \
+ state = DecStart; \
} while(0)
#define CHECK_CONTINUATION \
do { if((c & 0xC0) != 0x80) return false; } while(0)
{
START_CONVERSION
while(*p_outsz) {
- char *c8 = *p_outbuf;
+ unsigned char outc;
switch(state) {
case Enc3R:
- *c8 = 0x80 | ((accum >> 12) & 0x3F);
+ outc = 0x80 | ((accum >> 12) & 0x3F);
state = Enc2R;
break;
case Enc2R:
- *c8 = 0x80 | ((accum >> 6) & 0x3F);
+ outc = 0x80 | ((accum >> 6) & 0x3F);
state = Enc1R;
break;
case Enc1R:
- *c8 = 0x80 | (accum & 0x3F);
+ outc = 0x80 | (accum & 0x3F);
state = EncStart;
_PDCLIB_UNDEFINED(accum);
break;
(*p_insz)--;
if(accum <= 0x7F) {
- *c8 = accum;
+ outc = accum;
state = EncStart;
_PDCLIB_UNDEFINED(accum);
} else if(accum <= 0x7FF) {
- *c8 = 0xC0 | (accum >> 6);
+ outc = 0xC0 | (accum >> 6);
state = Enc1R;
} else if(accum <= 0xFFFF) {
- *c8 = 0xE0 | (accum >> 12);
+ outc = 0xE0 | (accum >> 12);
state = Enc2R;
} else if(accum <= 0x10FFFF) {
- *c8 = 0xF0 | (accum >> 18);
+ outc = 0xF0 | (accum >> 18);
state = Enc3R;
} else {
FINISH(false);
break;
}
-
- (*p_outbuf)++;
+ if(p_outbuf) {
+ **p_outbuf = outc;
+ (*p_outbuf)++;
+ }
(*p_outsz)--;
}
END_CONVERSION;
}
+
+_PDCLIB_charcodec _PDCLIB_utf8_codec = {
+ .__mbstoc32s = utf8toc32,
+ .__c32stombs = c32toutf8,
+};
+
#endif
#ifdef TEST