blob: 050f06206ef8dea8824dd5c8b44ba40469827a0b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
* Copyright 2020 Robert Mustacchi
*/
/*
* C11 c16rtomb(3C) support.
*
* Convert a series of char16_t values into a series of multi-byte characters.
* We may be given a surrogate value, so we need to potentially store that in
* the interim.
*/
#include <uchar.h>
#include <errno.h>
#include "mblocal.h"
#include "unicode.h"
static mbstate_t c16rtomb_state;
size_t
c16rtomb(char *restrict str, char16_t c16, mbstate_t *restrict ps)
{
char32_t c32;
_CHAR16State *c16s;
if (ps == NULL) {
ps = &c16rtomb_state;
}
if (str == NULL) {
c16 = L'\0';
}
c16s = (_CHAR16State *)ps;
if (c16s->c16_surrogate != 0) {
if (c16 > UNICODE_SUR_MAX || c16 < UNICODE_SUR_MIN ||
(c16 & UNICODE_SUR_LOWER) != UNICODE_SUR_LOWER) {
errno = EILSEQ;
return ((size_t)-1);
}
c32 = UNICODE_SUR_UVALUE(c16s->c16_surrogate) |
UNICODE_SUR_LVALUE(c16);
c32 += UNICODE_SUP_START;
c16s->c16_surrogate = 0;
} else if (c16 >= UNICODE_SUR_MIN && c16 <= UNICODE_SUR_MAX) {
/*
* The lower surrogate pair mask (dc00) overlaps the upper mask
* (d800), hence why we do a binary and with the upper mask.
*/
if ((c16 & UNICODE_SUR_LOWER) != UNICODE_SUR_UPPER) {
errno = EILSEQ;
return ((size_t)-1);
}
c16s->c16_surrogate = c16;
return (0);
} else {
c32 = c16;
}
/*
* Call c32rtomb() and not wcrtomb() so that way all of the unicode code
* point validation is performed.
*/
return (c32rtomb(str, c32, ps));
}
|