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