The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/unicode/u8_textprep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 /*
   22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   23  * Use is subject to license terms.
   24  */
   25 
   26 /*
   27  * Copyright 2022 MNX Cloud, Inc.
   28  */
   29 
   30 
   31 
   32 /*
   33  * UTF-8 text preparation functions (PSARC/2007/149, PSARC/2007/458).
   34  *
   35  * Man pages: u8_textprep_open(9F), u8_textprep_buf(9F), u8_textprep_close(9F),
   36  * u8_textprep_str(9F), u8_strcmp(9F), and u8_validate(9F). See also
   37  * the section 3C man pages.
   38  * Interface stability: Committed.
   39  */
   40 
   41 #include <sys/types.h>
   42 #include <sys/string.h>
   43 #include <sys/param.h>
   44 #include <sys/sysmacros.h>
   45 #include <sys/debug.h>
   46 #include <sys/kmem.h>
   47 #include <sys/sunddi.h>
   48 #include <sys/u8_textprep.h>
   49 #include <sys/byteorder.h>
   50 #include <sys/errno.h>
   51 #include <sys/u8_textprep_data.h>
   52 #include <sys/mod.h>
   53 
   54 /* The maximum possible number of bytes in a UTF-8 character. */
   55 #define U8_MB_CUR_MAX                   (4)
   56 
   57 /*
   58  * The maximum number of bytes needed for a UTF-8 character to cover
   59  * U+0000 - U+FFFF, i.e., the coding space of now deprecated UCS-2.
   60  */
   61 #define U8_MAX_BYTES_UCS2               (3)
   62 
   63 /* The maximum possible number of bytes in a Stream-Safe Text. */
   64 #define U8_STREAM_SAFE_TEXT_MAX         (128)
   65 
   66 /*
   67  * The maximum number of characters in a combining/conjoining sequence and
   68  * the actual upperbound limit of a combining/conjoining sequence.
   69  */
   70 #define U8_MAX_CHARS_A_SEQ              (32)
   71 #define U8_UPPER_LIMIT_IN_A_SEQ         (31)
   72 
   73 /* The combining class value for Starter. */
   74 #define U8_COMBINING_CLASS_STARTER      (0)
   75 
   76 /*
   77  * Some Hangul related macros at below.
   78  *
   79  * The first and the last of Hangul syllables, Hangul Jamo Leading consonants,
   80  * Vowels, and optional Trailing consonants in Unicode scalar values.
   81  *
   82  * Please be noted that the U8_HANGUL_JAMO_T_FIRST is 0x11A7 at below not
   83  * the actual U+11A8. This is due to that the trailing consonant is optional
   84  * and thus we are doing a pre-calculation of subtracting one.
   85  *
   86  * Each of 19 modern leading consonants has total 588 possible syllables since
   87  * Hangul has 21 modern vowels and 27 modern trailing consonants plus 1 for
   88  * no trailing consonant case, i.e., 21 x 28 = 588.
   89  *
   90  * We also have bunch of Hangul related macros at below. Please bear in mind
   91  * that the U8_HANGUL_JAMO_1ST_BYTE can be used to check whether it is
   92  * a Hangul Jamo or not but the value does not guarantee that it is a Hangul
   93  * Jamo; it just guarantee that it will be most likely.
   94  */
   95 #define U8_HANGUL_SYL_FIRST             (0xAC00U)
   96 #define U8_HANGUL_SYL_LAST              (0xD7A3U)
   97 
   98 #define U8_HANGUL_JAMO_L_FIRST          (0x1100U)
   99 #define U8_HANGUL_JAMO_L_LAST           (0x1112U)
  100 #define U8_HANGUL_JAMO_V_FIRST          (0x1161U)
  101 #define U8_HANGUL_JAMO_V_LAST           (0x1175U)
  102 #define U8_HANGUL_JAMO_T_FIRST          (0x11A7U)
  103 #define U8_HANGUL_JAMO_T_LAST           (0x11C2U)
  104 
  105 #define U8_HANGUL_V_COUNT               (21)
  106 #define U8_HANGUL_VT_COUNT              (588)
  107 #define U8_HANGUL_T_COUNT               (28)
  108 
  109 #define U8_HANGUL_JAMO_1ST_BYTE         (0xE1U)
  110 
  111 #define U8_SAVE_HANGUL_AS_UTF8(s, i, j, k, b) \
  112         (s)[(i)] = (uchar_t)(0xE0U | ((uint32_t)(b) & 0xF000U) >> 12); \
  113         (s)[(j)] = (uchar_t)(0x80U | ((uint32_t)(b) & 0x0FC0U) >> 6); \
  114         (s)[(k)] = (uchar_t)(0x80U | ((uint32_t)(b) & 0x003FU));
  115 
  116 #define U8_HANGUL_JAMO_L(u) \
  117         ((u) >= U8_HANGUL_JAMO_L_FIRST && (u) <= U8_HANGUL_JAMO_L_LAST)
  118 
  119 #define U8_HANGUL_JAMO_V(u) \
  120         ((u) >= U8_HANGUL_JAMO_V_FIRST && (u) <= U8_HANGUL_JAMO_V_LAST)
  121 
  122 #define U8_HANGUL_JAMO_T(u) \
  123         ((u) > U8_HANGUL_JAMO_T_FIRST && (u) <= U8_HANGUL_JAMO_T_LAST)
  124 
  125 #define U8_HANGUL_JAMO(u) \
  126         ((u) >= U8_HANGUL_JAMO_L_FIRST && (u) <= U8_HANGUL_JAMO_T_LAST)
  127 
  128 #define U8_HANGUL_SYLLABLE(u) \
  129         ((u) >= U8_HANGUL_SYL_FIRST && (u) <= U8_HANGUL_SYL_LAST)
  130 
  131 #define U8_HANGUL_COMPOSABLE_L_V(s, u) \
  132         ((s) == U8_STATE_HANGUL_L && U8_HANGUL_JAMO_V((u)))
  133 
  134 #define U8_HANGUL_COMPOSABLE_LV_T(s, u) \
  135         ((s) == U8_STATE_HANGUL_LV && U8_HANGUL_JAMO_T((u)))
  136 
  137 /* The types of decomposition mappings. */
  138 #define U8_DECOMP_BOTH                  (0xF5U)
  139 #define U8_DECOMP_CANONICAL             (0xF6U)
  140 
  141 /* The indicator for 16-bit table. */
  142 #define U8_16BIT_TABLE_INDICATOR        (0x8000U)
  143 
  144 /* The following are some convenience macros. */
  145 #define U8_PUT_3BYTES_INTO_UTF32(u, b1, b2, b3)  \
  146         (u) = ((((uint32_t)(b1) & 0x0F) << 12) | \
  147                 (((uint32_t)(b2) & 0x3F) << 6)  | \
  148                 ((uint32_t)(b3) & 0x3F));
  149 
  150 #define U8_SIMPLE_SWAP(a, b, t) \
  151         (t) = (a); \
  152         (a) = (b); \
  153         (b) = (t);
  154 
  155 #define U8_ASCII_TOUPPER(c) \
  156         (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c))
  157 
  158 #define U8_ASCII_TOLOWER(c) \
  159         (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
  160 
  161 #define U8_ISASCII(c)                   (((uchar_t)(c)) < 0x80U)
  162 /*
  163  * The following macro assumes that the two characters that are to be
  164  * swapped are adjacent to each other and 'a' comes before 'b'.
  165  *
  166  * If the assumptions are not met, then, the macro will fail.
  167  */
  168 #define U8_SWAP_COMB_MARKS(a, b) \
  169         for (k = 0; k < disp[(a)]; k++) \
  170                 u8t[k] = u8s[start[(a)] + k]; \
  171         for (k = 0; k < disp[(b)]; k++) \
  172                 u8s[start[(a)] + k] = u8s[start[(b)] + k]; \
  173         start[(b)] = start[(a)] + disp[(b)]; \
  174         for (k = 0; k < disp[(a)]; k++) \
  175                 u8s[start[(b)] + k] = u8t[k]; \
  176         U8_SIMPLE_SWAP(comb_class[(a)], comb_class[(b)], tc); \
  177         U8_SIMPLE_SWAP(disp[(a)], disp[(b)], tc);
  178 
  179 /* The possible states during normalization. */
  180 typedef enum {
  181         U8_STATE_START = 0,
  182         U8_STATE_HANGUL_L = 1,
  183         U8_STATE_HANGUL_LV = 2,
  184         U8_STATE_HANGUL_LVT = 3,
  185         U8_STATE_HANGUL_V = 4,
  186         U8_STATE_HANGUL_T = 5,
  187         U8_STATE_COMBINING_MARK = 6
  188 } u8_normalization_states_t;
  189 
  190 /*
  191  * The three vectors at below are used to check bytes of a given UTF-8
  192  * character are valid and not containing any malformed byte values.
  193  *
  194  * We used to have a quite relaxed UTF-8 binary representation but then there
  195  * was some security related issues and so the Unicode Consortium defined
  196  * and announced the UTF-8 Corrigendum at Unicode 3.1 and then refined it
  197  * one more time at the Unicode 3.2. The following three tables are based on
  198  * that.
  199  */
  200 
  201 #define U8_ILLEGAL_NEXT_BYTE_COMMON(c)  ((c) < 0x80 || (c) > 0xBF)
  202 
  203 #define I_                              U8_ILLEGAL_CHAR
  204 #define O_                              U8_OUT_OF_RANGE_CHAR
  205 
  206 static const int8_t u8_number_of_bytes[0x100] = {
  207         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  208         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  209         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  210         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  211         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  212         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  213         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  214         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
  215 
  216 /*      80  81  82  83  84  85  86  87  88  89  8A  8B  8C  8D  8E  8F  */
  217         I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
  218 
  219 /*      90  91  92  93  94  95  96  97  98  99  9A  9B  9C  9D  9E  9F  */
  220         I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
  221 
  222 /*      A0  A1  A2  A3  A4  A5  A6  A7  A8  A9  AA  AB  AC  AD  AE  AF  */
  223         I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
  224 
  225 /*      B0  B1  B2  B3  B4  B5  B6  B7  B8  B9  BA  BB  BC  BD  BE  BF  */
  226         I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_, I_,
  227 
  228 /*      C0  C1  C2  C3  C4  C5  C6  C7  C8  C9  CA  CB  CC  CD  CE  CF  */
  229         I_, I_, 2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
  230 
  231 /*      D0  D1  D2  D3  D4  D5  D6  D7  D8  D9  DA  DB  DC  DD  DE  DF  */
  232         2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
  233 
  234 /*      E0  E1  E2  E3  E4  E5  E6  E7  E8  E9  EA  EB  EC  ED  EE  EF  */
  235         3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
  236 
  237 /*      F0  F1  F2  F3  F4  F5  F6  F7  F8  F9  FA  FB  FC  FD  FE  FF  */
  238         4,  4,  4,  4,  4,  O_, O_, O_, O_, O_, O_, O_, O_, O_, O_, O_,
  239 };
  240 
  241 #undef  I_
  242 #undef  O_
  243 
  244 static const uint8_t u8_valid_min_2nd_byte[0x100] = {
  245         0,    0,    0,    0,    0,    0,    0,    0,
  246         0,    0,    0,    0,    0,    0,    0,    0,
  247         0,    0,    0,    0,    0,    0,    0,    0,
  248         0,    0,    0,    0,    0,    0,    0,    0,
  249         0,    0,    0,    0,    0,    0,    0,    0,
  250         0,    0,    0,    0,    0,    0,    0,    0,
  251         0,    0,    0,    0,    0,    0,    0,    0,
  252         0,    0,    0,    0,    0,    0,    0,    0,
  253         0,    0,    0,    0,    0,    0,    0,    0,
  254         0,    0,    0,    0,    0,    0,    0,    0,
  255         0,    0,    0,    0,    0,    0,    0,    0,
  256         0,    0,    0,    0,    0,    0,    0,    0,
  257         0,    0,    0,    0,    0,    0,    0,    0,
  258         0,    0,    0,    0,    0,    0,    0,    0,
  259         0,    0,    0,    0,    0,    0,    0,    0,
  260         0,    0,    0,    0,    0,    0,    0,    0,
  261         0,    0,    0,    0,    0,    0,    0,    0,
  262         0,    0,    0,    0,    0,    0,    0,    0,
  263         0,    0,    0,    0,    0,    0,    0,    0,
  264         0,    0,    0,    0,    0,    0,    0,    0,
  265         0,    0,    0,    0,    0,    0,    0,    0,
  266         0,    0,    0,    0,    0,    0,    0,    0,
  267         0,    0,    0,    0,    0,    0,    0,    0,
  268         0,    0,    0,    0,    0,    0,    0,    0,
  269 /*      C0    C1    C2    C3    C4    C5    C6    C7    */
  270         0,    0,    0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  271 /*      C8    C9    CA    CB    CC    CD    CE    CF    */
  272         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  273 /*      D0    D1    D2    D3    D4    D5    D6    D7    */
  274         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  275 /*      D8    D9    DA    DB    DC    DD    DE    DF    */
  276         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  277 /*      E0    E1    E2    E3    E4    E5    E6    E7    */
  278         0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  279 /*      E8    E9    EA    EB    EC    ED    EE    EF    */
  280         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  281 /*      F0    F1    F2    F3    F4    F5    F6    F7    */
  282         0x90, 0x80, 0x80, 0x80, 0x80, 0,    0,    0,
  283         0,    0,    0,    0,    0,    0,    0,    0,
  284 };
  285 
  286 static const uint8_t u8_valid_max_2nd_byte[0x100] = {
  287         0,    0,    0,    0,    0,    0,    0,    0,
  288         0,    0,    0,    0,    0,    0,    0,    0,
  289         0,    0,    0,    0,    0,    0,    0,    0,
  290         0,    0,    0,    0,    0,    0,    0,    0,
  291         0,    0,    0,    0,    0,    0,    0,    0,
  292         0,    0,    0,    0,    0,    0,    0,    0,
  293         0,    0,    0,    0,    0,    0,    0,    0,
  294         0,    0,    0,    0,    0,    0,    0,    0,
  295         0,    0,    0,    0,    0,    0,    0,    0,
  296         0,    0,    0,    0,    0,    0,    0,    0,
  297         0,    0,    0,    0,    0,    0,    0,    0,
  298         0,    0,    0,    0,    0,    0,    0,    0,
  299         0,    0,    0,    0,    0,    0,    0,    0,
  300         0,    0,    0,    0,    0,    0,    0,    0,
  301         0,    0,    0,    0,    0,    0,    0,    0,
  302         0,    0,    0,    0,    0,    0,    0,    0,
  303         0,    0,    0,    0,    0,    0,    0,    0,
  304         0,    0,    0,    0,    0,    0,    0,    0,
  305         0,    0,    0,    0,    0,    0,    0,    0,
  306         0,    0,    0,    0,    0,    0,    0,    0,
  307         0,    0,    0,    0,    0,    0,    0,    0,
  308         0,    0,    0,    0,    0,    0,    0,    0,
  309         0,    0,    0,    0,    0,    0,    0,    0,
  310         0,    0,    0,    0,    0,    0,    0,    0,
  311 /*      C0    C1    C2    C3    C4    C5    C6    C7    */
  312         0,    0,    0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
  313 /*      C8    C9    CA    CB    CC    CD    CE    CF    */
  314         0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
  315 /*      D0    D1    D2    D3    D4    D5    D6    D7    */
  316         0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
  317 /*      D8    D9    DA    DB    DC    DD    DE    DF    */
  318         0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
  319 /*      E0    E1    E2    E3    E4    E5    E6    E7    */
  320         0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
  321 /*      E8    E9    EA    EB    EC    ED    EE    EF    */
  322         0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x9f, 0xbf, 0xbf,
  323 /*      F0    F1    F2    F3    F4    F5    F6    F7    */
  324         0xbf, 0xbf, 0xbf, 0xbf, 0x8f, 0,    0,    0,
  325         0,    0,    0,    0,    0,    0,    0,    0,
  326 };
  327 
  328 
  329 /*
  330  * The u8_validate() validates on the given UTF-8 character string and
  331  * calculate the byte length. It is quite similar to mblen(3C) except that
  332  * this will validate against the list of characters if required and
  333  * specific to UTF-8 and Unicode.
  334  */
  335 int
  336 u8_validate(const char *u8str, size_t n, char **list, int flag, int *errnum)
  337 {
  338         uchar_t *ib;
  339         uchar_t *ibtail;
  340         uchar_t **p;
  341         uchar_t *s1;
  342         uchar_t *s2;
  343         uchar_t f;
  344         int sz;
  345         size_t i;
  346         int ret_val;
  347         boolean_t second;
  348         boolean_t no_need_to_validate_entire;
  349         boolean_t check_additional;
  350         boolean_t validate_ucs2_range_only;
  351 
  352         if (! u8str)
  353                 return (0);
  354 
  355         ib = (uchar_t *)u8str;
  356         ibtail = ib + n;
  357 
  358         ret_val = 0;
  359 
  360         no_need_to_validate_entire = ! (flag & U8_VALIDATE_ENTIRE);
  361         check_additional = flag & U8_VALIDATE_CHECK_ADDITIONAL;
  362         validate_ucs2_range_only = flag & U8_VALIDATE_UCS2_RANGE;
  363 
  364         while (ib < ibtail) {
  365                 /*
  366                  * The first byte of a UTF-8 character tells how many
  367                  * bytes will follow for the character. If the first byte
  368                  * is an illegal byte value or out of range value, we just
  369                  * return -1 with an appropriate error number.
  370                  */
  371                 sz = u8_number_of_bytes[*ib];
  372                 if (sz == U8_ILLEGAL_CHAR) {
  373                         *errnum = EILSEQ;
  374                         return (-1);
  375                 }
  376 
  377                 if (sz == U8_OUT_OF_RANGE_CHAR ||
  378                     (validate_ucs2_range_only && sz > U8_MAX_BYTES_UCS2)) {
  379                         *errnum = ERANGE;
  380                         return (-1);
  381                 }
  382 
  383                 /*
  384                  * If we don't have enough bytes to check on, that's also
  385                  * an error. As you can see, we give illegal byte sequence
  386                  * checking higher priority then EINVAL cases.
  387                  */
  388                 if ((ibtail - ib) < sz) {
  389                         *errnum = EINVAL;
  390                         return (-1);
  391                 }
  392 
  393                 if (sz == 1) {
  394                         ib++;
  395                         ret_val++;
  396                 } else {
  397                         /*
  398                          * Check on the multi-byte UTF-8 character. For more
  399                          * details on this, see comment added for the used
  400                          * data structures at the beginning of the file.
  401                          */
  402                         f = *ib++;
  403                         ret_val++;
  404                         second = B_TRUE;
  405                         for (i = 1; i < sz; i++) {
  406                                 if (second) {
  407                                         if (*ib < u8_valid_min_2nd_byte[f] ||
  408                                             *ib > u8_valid_max_2nd_byte[f]) {
  409                                                 *errnum = EILSEQ;
  410                                                 return (-1);
  411                                         }
  412                                         second = B_FALSE;
  413                                 } else if (U8_ILLEGAL_NEXT_BYTE_COMMON(*ib)) {
  414                                         *errnum = EILSEQ;
  415                                         return (-1);
  416                                 }
  417                                 ib++;
  418                                 ret_val++;
  419                         }
  420                 }
  421 
  422                 if (check_additional) {
  423                         for (p = (uchar_t **)list, i = 0; p[i]; i++) {
  424                                 s1 = ib - sz;
  425                                 s2 = p[i];
  426                                 while (s1 < ib) {
  427                                         if (*s1 != *s2 || *s2 == '\0')
  428                                                 break;
  429                                         s1++;
  430                                         s2++;
  431                                 }
  432 
  433                                 if (s1 >= ib && *s2 == '\0') {
  434                                         *errnum = EBADF;
  435                                         return (-1);
  436                                 }
  437                         }
  438                 }
  439 
  440                 if (no_need_to_validate_entire)
  441                         break;
  442         }
  443 
  444         return (ret_val);
  445 }
  446 
  447 /*
  448  * The do_case_conv() looks at the mapping tables and returns found
  449  * bytes if any. If not found, the input bytes are returned. The function
  450  * always terminate the return bytes with a null character assuming that
  451  * there are plenty of room to do so.
  452  *
  453  * The case conversions are simple case conversions mapping a character to
  454  * another character as specified in the Unicode data. The byte size of
  455  * the mapped character could be different from that of the input character.
  456  *
  457  * The return value is the byte length of the returned character excluding
  458  * the terminating null byte.
  459  */
  460 static size_t
  461 do_case_conv(int uv, uchar_t *u8s, uchar_t *s, int sz, boolean_t is_it_toupper)
  462 {
  463         size_t i;
  464         uint16_t b1 = 0;
  465         uint16_t b2 = 0;
  466         uint16_t b3 = 0;
  467         uint16_t b3_tbl;
  468         uint16_t b3_base;
  469         uint16_t b4 = 0;
  470         size_t start_id;
  471         size_t end_id;
  472 
  473         /*
  474          * At this point, the only possible values for sz are 2, 3, and 4.
  475          * The u8s should point to a vector that is well beyond the size of
  476          * 5 bytes.
  477          */
  478         if (sz == 2) {
  479                 b3 = u8s[0] = s[0];
  480                 b4 = u8s[1] = s[1];
  481         } else if (sz == 3) {
  482                 b2 = u8s[0] = s[0];
  483                 b3 = u8s[1] = s[1];
  484                 b4 = u8s[2] = s[2];
  485         } else if (sz == 4) {
  486                 b1 = u8s[0] = s[0];
  487                 b2 = u8s[1] = s[1];
  488                 b3 = u8s[2] = s[2];
  489                 b4 = u8s[3] = s[3];
  490         } else {
  491                 /* This is not possible but just in case as a fallback. */
  492                 if (is_it_toupper)
  493                         *u8s = U8_ASCII_TOUPPER(*s);
  494                 else
  495                         *u8s = U8_ASCII_TOLOWER(*s);
  496                 u8s[1] = '\0';
  497 
  498                 return (1);
  499         }
  500         u8s[sz] = '\0';
  501 
  502         /*
  503          * Let's find out if we have a corresponding character.
  504          */
  505         b1 = u8_common_b1_tbl[uv][b1];
  506         if (b1 == U8_TBL_ELEMENT_NOT_DEF)
  507                 return ((size_t)sz);
  508 
  509         b2 = u8_case_common_b2_tbl[uv][b1][b2];
  510         if (b2 == U8_TBL_ELEMENT_NOT_DEF)
  511                 return ((size_t)sz);
  512 
  513         if (is_it_toupper) {
  514                 b3_tbl = u8_toupper_b3_tbl[uv][b2][b3].tbl_id;
  515                 if (b3_tbl == U8_TBL_ELEMENT_NOT_DEF)
  516                         return ((size_t)sz);
  517 
  518                 start_id = u8_toupper_b4_tbl[uv][b3_tbl][b4];
  519                 end_id = u8_toupper_b4_tbl[uv][b3_tbl][b4 + 1];
  520 
  521                 /* Either there is no match or an error at the table. */
  522                 if (start_id >= end_id || (end_id - start_id) > U8_MB_CUR_MAX)
  523                         return ((size_t)sz);
  524 
  525                 b3_base = u8_toupper_b3_tbl[uv][b2][b3].base;
  526 
  527                 for (i = 0; start_id < end_id; start_id++)
  528                         u8s[i++] = u8_toupper_final_tbl[uv][b3_base + start_id];
  529         } else {
  530                 b3_tbl = u8_tolower_b3_tbl[uv][b2][b3].tbl_id;
  531                 if (b3_tbl == U8_TBL_ELEMENT_NOT_DEF)
  532                         return ((size_t)sz);
  533 
  534                 start_id = u8_tolower_b4_tbl[uv][b3_tbl][b4];
  535                 end_id = u8_tolower_b4_tbl[uv][b3_tbl][b4 + 1];
  536 
  537                 if (start_id >= end_id || (end_id - start_id) > U8_MB_CUR_MAX)
  538                         return ((size_t)sz);
  539 
  540                 b3_base = u8_tolower_b3_tbl[uv][b2][b3].base;
  541 
  542                 for (i = 0; start_id < end_id; start_id++)
  543                         u8s[i++] = u8_tolower_final_tbl[uv][b3_base + start_id];
  544         }
  545 
  546         /*
  547          * If i is still zero, that means there is no corresponding character.
  548          */
  549         if (i == 0)
  550                 return ((size_t)sz);
  551 
  552         u8s[i] = '\0';
  553 
  554         return (i);
  555 }
  556 
  557 /*
  558  * The do_case_compare() function compares the two input strings, s1 and s2,
  559  * one character at a time doing case conversions if applicable and return
  560  * the comparison result as like strcmp().
  561  *
  562  * Since, in empirical sense, most of text data are 7-bit ASCII characters,
  563  * we treat the 7-bit ASCII characters as a special case trying to yield
  564  * faster processing time.
  565  */
  566 static int
  567 do_case_compare(size_t uv, uchar_t *s1, uchar_t *s2, size_t n1,
  568     size_t n2, boolean_t is_it_toupper, int *errnum)
  569 {
  570         int f;
  571         int sz1;
  572         int sz2;
  573         size_t j;
  574         size_t i1;
  575         size_t i2;
  576         uchar_t u8s1[U8_MB_CUR_MAX + 1];
  577         uchar_t u8s2[U8_MB_CUR_MAX + 1];
  578 
  579         i1 = i2 = 0;
  580         while (i1 < n1 && i2 < n2) {
  581                 /*
  582                  * Find out what would be the byte length for this UTF-8
  583                  * character at string s1 and also find out if this is
  584                  * an illegal start byte or not and if so, issue a proper
  585                  * error number and yet treat this byte as a character.
  586                  */
  587                 sz1 = u8_number_of_bytes[*s1];
  588                 if (sz1 < 0) {
  589                         *errnum = EILSEQ;
  590                         sz1 = 1;
  591                 }
  592 
  593                 /*
  594                  * For 7-bit ASCII characters mainly, we do a quick case
  595                  * conversion right at here.
  596                  *
  597                  * If we don't have enough bytes for this character, issue
  598                  * an EINVAL error and use what are available.
  599                  *
  600                  * If we have enough bytes, find out if there is
  601                  * a corresponding uppercase character and if so, copy over
  602                  * the bytes for a comparison later. If there is no
  603                  * corresponding uppercase character, then, use what we have
  604                  * for the comparison.
  605                  */
  606                 if (sz1 == 1) {
  607                         if (is_it_toupper)
  608                                 u8s1[0] = U8_ASCII_TOUPPER(*s1);
  609                         else
  610                                 u8s1[0] = U8_ASCII_TOLOWER(*s1);
  611                         s1++;
  612                         u8s1[1] = '\0';
  613                 } else if ((i1 + sz1) > n1) {
  614                         *errnum = EINVAL;
  615                         for (j = 0; (i1 + j) < n1; )
  616                                 u8s1[j++] = *s1++;
  617                         u8s1[j] = '\0';
  618                 } else {
  619                         (void) do_case_conv(uv, u8s1, s1, sz1, is_it_toupper);
  620                         s1 += sz1;
  621                 }
  622 
  623                 /* Do the same for the string s2. */
  624                 sz2 = u8_number_of_bytes[*s2];
  625                 if (sz2 < 0) {
  626                         *errnum = EILSEQ;
  627                         sz2 = 1;
  628                 }
  629 
  630                 if (sz2 == 1) {
  631                         if (is_it_toupper)
  632                                 u8s2[0] = U8_ASCII_TOUPPER(*s2);
  633                         else
  634                                 u8s2[0] = U8_ASCII_TOLOWER(*s2);
  635                         s2++;
  636                         u8s2[1] = '\0';
  637                 } else if ((i2 + sz2) > n2) {
  638                         *errnum = EINVAL;
  639                         for (j = 0; (i2 + j) < n2; )
  640                                 u8s2[j++] = *s2++;
  641                         u8s2[j] = '\0';
  642                 } else {
  643                         (void) do_case_conv(uv, u8s2, s2, sz2, is_it_toupper);
  644                         s2 += sz2;
  645                 }
  646 
  647                 /* Now compare the two characters. */
  648                 if (sz1 == 1 && sz2 == 1) {
  649                         if (*u8s1 > *u8s2)
  650                                 return (1);
  651                         if (*u8s1 < *u8s2)
  652                                 return (-1);
  653                 } else {
  654                         f = strcmp((const char *)u8s1, (const char *)u8s2);
  655                         if (f != 0)
  656                                 return (f);
  657                 }
  658 
  659                 /*
  660                  * They were the same. Let's move on to the next
  661                  * characters then.
  662                  */
  663                 i1 += sz1;
  664                 i2 += sz2;
  665         }
  666 
  667         /*
  668          * We compared until the end of either or both strings.
  669          *
  670          * If we reached to or went over the ends for the both, that means
  671          * they are the same.
  672          *
  673          * If we reached only one of the two ends, that means the other string
  674          * has something which then the fact can be used to determine
  675          * the return value.
  676          */
  677         if (i1 >= n1) {
  678                 if (i2 >= n2)
  679                         return (0);
  680                 return (-1);
  681         }
  682         return (1);
  683 }
  684 
  685 /*
  686  * The combining_class() function checks on the given bytes and find out
  687  * the corresponding Unicode combining class value. The return value 0 means
  688  * it is a Starter. Any illegal UTF-8 character will also be treated as
  689  * a Starter.
  690  */
  691 static uchar_t
  692 combining_class(size_t uv, uchar_t *s, size_t sz)
  693 {
  694         uint16_t b1 = 0;
  695         uint16_t b2 = 0;
  696         uint16_t b3 = 0;
  697         uint16_t b4 = 0;
  698 
  699         if (sz == 1 || sz > 4)
  700                 return (0);
  701 
  702         if (sz == 2) {
  703                 b3 = s[0];
  704                 b4 = s[1];
  705         } else if (sz == 3) {
  706                 b2 = s[0];
  707                 b3 = s[1];
  708                 b4 = s[2];
  709         } else if (sz == 4) {
  710                 b1 = s[0];
  711                 b2 = s[1];
  712                 b3 = s[2];
  713                 b4 = s[3];
  714         }
  715 
  716         b1 = u8_common_b1_tbl[uv][b1];
  717         if (b1 == U8_TBL_ELEMENT_NOT_DEF)
  718                 return (0);
  719 
  720         b2 = u8_combining_class_b2_tbl[uv][b1][b2];
  721         if (b2 == U8_TBL_ELEMENT_NOT_DEF)
  722                 return (0);
  723 
  724         b3 = u8_combining_class_b3_tbl[uv][b2][b3];
  725         if (b3 == U8_TBL_ELEMENT_NOT_DEF)
  726                 return (0);
  727 
  728         return (u8_combining_class_b4_tbl[uv][b3][b4]);
  729 }
  730 
  731 /*
  732  * The do_decomp() function finds out a matching decomposition if any
  733  * and return. If there is no match, the input bytes are copied and returned.
  734  * The function also checks if there is a Hangul, decomposes it if necessary
  735  * and returns.
  736  *
  737  * To save time, a single byte 7-bit ASCII character should be handled by
  738  * the caller.
  739  *
  740  * The function returns the number of bytes returned sans always terminating
  741  * the null byte. It will also return a state that will tell if there was
  742  * a Hangul character decomposed which then will be used by the caller.
  743  */
  744 static size_t
  745 do_decomp(size_t uv, uchar_t *u8s, uchar_t *s, int sz,
  746     boolean_t canonical_decomposition, u8_normalization_states_t *state)
  747 {
  748         uint16_t b1 = 0;
  749         uint16_t b2 = 0;
  750         uint16_t b3 = 0;
  751         uint16_t b3_tbl;
  752         uint16_t b3_base;
  753         uint16_t b4 = 0;
  754         size_t start_id;
  755         size_t end_id;
  756         size_t i;
  757         uint32_t u1;
  758 
  759         if (sz == 2) {
  760                 b3 = u8s[0] = s[0];
  761                 b4 = u8s[1] = s[1];
  762                 u8s[2] = '\0';
  763         } else if (sz == 3) {
  764                 /* Convert it to a Unicode scalar value. */
  765                 U8_PUT_3BYTES_INTO_UTF32(u1, s[0], s[1], s[2]);
  766 
  767                 /*
  768                  * If this is a Hangul syllable, we decompose it into
  769                  * a leading consonant, a vowel, and an optional trailing
  770                  * consonant and then return.
  771                  */
  772                 if (U8_HANGUL_SYLLABLE(u1)) {
  773                         u1 -= U8_HANGUL_SYL_FIRST;
  774 
  775                         b1 = U8_HANGUL_JAMO_L_FIRST + u1 / U8_HANGUL_VT_COUNT;
  776                         b2 = U8_HANGUL_JAMO_V_FIRST + (u1 % U8_HANGUL_VT_COUNT)
  777                             / U8_HANGUL_T_COUNT;
  778                         b3 = u1 % U8_HANGUL_T_COUNT;
  779 
  780                         U8_SAVE_HANGUL_AS_UTF8(u8s, 0, 1, 2, b1);
  781                         U8_SAVE_HANGUL_AS_UTF8(u8s, 3, 4, 5, b2);
  782                         if (b3) {
  783                                 b3 += U8_HANGUL_JAMO_T_FIRST;
  784                                 U8_SAVE_HANGUL_AS_UTF8(u8s, 6, 7, 8, b3);
  785 
  786                                 u8s[9] = '\0';
  787                                 *state = U8_STATE_HANGUL_LVT;
  788                                 return (9);
  789                         }
  790 
  791                         u8s[6] = '\0';
  792                         *state = U8_STATE_HANGUL_LV;
  793                         return (6);
  794                 }
  795 
  796                 b2 = u8s[0] = s[0];
  797                 b3 = u8s[1] = s[1];
  798                 b4 = u8s[2] = s[2];
  799                 u8s[3] = '\0';
  800 
  801                 /*
  802                  * If this is a Hangul Jamo, we know there is nothing
  803                  * further that we can decompose.
  804                  */
  805                 if (U8_HANGUL_JAMO_L(u1)) {
  806                         *state = U8_STATE_HANGUL_L;
  807                         return (3);
  808                 }
  809 
  810                 if (U8_HANGUL_JAMO_V(u1)) {
  811                         if (*state == U8_STATE_HANGUL_L)
  812                                 *state = U8_STATE_HANGUL_LV;
  813                         else
  814                                 *state = U8_STATE_HANGUL_V;
  815                         return (3);
  816                 }
  817 
  818                 if (U8_HANGUL_JAMO_T(u1)) {
  819                         if (*state == U8_STATE_HANGUL_LV)
  820                                 *state = U8_STATE_HANGUL_LVT;
  821                         else
  822                                 *state = U8_STATE_HANGUL_T;
  823                         return (3);
  824                 }
  825         } else if (sz == 4) {
  826                 b1 = u8s[0] = s[0];
  827                 b2 = u8s[1] = s[1];
  828                 b3 = u8s[2] = s[2];
  829                 b4 = u8s[3] = s[3];
  830                 u8s[4] = '\0';
  831         } else {
  832                 /*
  833                  * This is a fallback and should not happen if the function
  834                  * was called properly.
  835                  */
  836                 u8s[0] = s[0];
  837                 u8s[1] = '\0';
  838                 *state = U8_STATE_START;
  839                 return (1);
  840         }
  841 
  842         /*
  843          * At this point, this routine does not know what it would get.
  844          * The caller should sort it out if the state isn't a Hangul one.
  845          */
  846         *state = U8_STATE_START;
  847 
  848         /* Try to find matching decomposition mapping byte sequence. */
  849         b1 = u8_common_b1_tbl[uv][b1];
  850         if (b1 == U8_TBL_ELEMENT_NOT_DEF)
  851                 return ((size_t)sz);
  852 
  853         b2 = u8_decomp_b2_tbl[uv][b1][b2];
  854         if (b2 == U8_TBL_ELEMENT_NOT_DEF)
  855                 return ((size_t)sz);
  856 
  857         b3_tbl = u8_decomp_b3_tbl[uv][b2][b3].tbl_id;
  858         if (b3_tbl == U8_TBL_ELEMENT_NOT_DEF)
  859                 return ((size_t)sz);
  860 
  861         /*
  862          * If b3_tbl is bigger than or equal to U8_16BIT_TABLE_INDICATOR
  863          * which is 0x8000, this means we couldn't fit the mappings into
  864          * the cardinality of a unsigned byte.
  865          */
  866         if (b3_tbl >= U8_16BIT_TABLE_INDICATOR) {
  867                 b3_tbl -= U8_16BIT_TABLE_INDICATOR;
  868                 start_id = u8_decomp_b4_16bit_tbl[uv][b3_tbl][b4];
  869                 end_id = u8_decomp_b4_16bit_tbl[uv][b3_tbl][b4 + 1];
  870         } else {
  871                 // cppcheck-suppress arrayIndexOutOfBoundsCond
  872                 start_id = u8_decomp_b4_tbl[uv][b3_tbl][b4];
  873                 // cppcheck-suppress arrayIndexOutOfBoundsCond
  874                 end_id = u8_decomp_b4_tbl[uv][b3_tbl][b4 + 1];
  875         }
  876 
  877         /* This also means there wasn't any matching decomposition. */
  878         if (start_id >= end_id)
  879                 return ((size_t)sz);
  880 
  881         /*
  882          * The final table for decomposition mappings has three types of
  883          * byte sequences depending on whether a mapping is for compatibility
  884          * decomposition, canonical decomposition, or both like the following:
  885          *
  886          * (1) Compatibility decomposition mappings:
  887          *
  888          *      +---+---+-...-+---+
  889          *      | B0| B1| ... | Bm|
  890          *      +---+---+-...-+---+
  891          *
  892          *      The first byte, B0, is always less than 0xF5 (U8_DECOMP_BOTH).
  893          *
  894          * (2) Canonical decomposition mappings:
  895          *
  896          *      +---+---+---+-...-+---+
  897          *      | T | b0| b1| ... | bn|
  898          *      +---+---+---+-...-+---+
  899          *
  900          *      where the first byte, T, is 0xF6 (U8_DECOMP_CANONICAL).
  901          *
  902          * (3) Both mappings:
  903          *
  904          *      +---+---+---+---+-...-+---+---+---+-...-+---+
  905          *      | T | D | b0| b1| ... | bn| B0| B1| ... | Bm|
  906          *      +---+---+---+---+-...-+---+---+---+-...-+---+
  907          *
  908          *      where T is 0xF5 (U8_DECOMP_BOTH) and D is a displacement
  909          *      byte, b0 to bn are canonical mapping bytes and B0 to Bm are
  910          *      compatibility mapping bytes.
  911          *
  912          * Note that compatibility decomposition means doing recursive
  913          * decompositions using both compatibility decomposition mappings and
  914          * canonical decomposition mappings. On the other hand, canonical
  915          * decomposition means doing recursive decompositions using only
  916          * canonical decomposition mappings. Since the table we have has gone
  917          * through the recursions already, we do not need to do so during
  918          * runtime, i.e., the table has been completely flattened out
  919          * already.
  920          */
  921 
  922         b3_base = u8_decomp_b3_tbl[uv][b2][b3].base;
  923 
  924         /* Get the type, T, of the byte sequence. */
  925         b1 = u8_decomp_final_tbl[uv][b3_base + start_id];
  926 
  927         /*
  928          * If necessary, adjust start_id, end_id, or both. Note that if
  929          * this is compatibility decomposition mapping, there is no
  930          * adjustment.
  931          */
  932         if (canonical_decomposition) {
  933                 /* Is the mapping only for compatibility decomposition? */
  934                 if (b1 < U8_DECOMP_BOTH)
  935                         return ((size_t)sz);
  936 
  937                 start_id++;
  938 
  939                 if (b1 == U8_DECOMP_BOTH) {
  940                         end_id = start_id +
  941                             u8_decomp_final_tbl[uv][b3_base + start_id];
  942                         start_id++;
  943                 }
  944         } else {
  945                 /*
  946                  * Unless this is a compatibility decomposition mapping,
  947                  * we adjust the start_id.
  948                  */
  949                 if (b1 == U8_DECOMP_BOTH) {
  950                         start_id++;
  951                         start_id += u8_decomp_final_tbl[uv][b3_base + start_id];
  952                 } else if (b1 == U8_DECOMP_CANONICAL) {
  953                         start_id++;
  954                 }
  955         }
  956 
  957         for (i = 0; start_id < end_id; start_id++)
  958                 u8s[i++] = u8_decomp_final_tbl[uv][b3_base + start_id];
  959         u8s[i] = '\0';
  960 
  961         return (i);
  962 }
  963 
  964 /*
  965  * The find_composition_start() function uses the character bytes given and
  966  * find out the matching composition mappings if any and return the address
  967  * to the composition mappings as explained in the do_composition().
  968  */
  969 static uchar_t *
  970 find_composition_start(size_t uv, uchar_t *s, size_t sz)
  971 {
  972         uint16_t b1 = 0;
  973         uint16_t b2 = 0;
  974         uint16_t b3 = 0;
  975         uint16_t b3_tbl;
  976         uint16_t b3_base;
  977         uint16_t b4 = 0;
  978         size_t start_id;
  979         size_t end_id;
  980 
  981         if (sz == 1) {
  982                 b4 = s[0];
  983         } else if (sz == 2) {
  984                 b3 = s[0];
  985                 b4 = s[1];
  986         } else if (sz == 3) {
  987                 b2 = s[0];
  988                 b3 = s[1];
  989                 b4 = s[2];
  990         } else if (sz == 4) {
  991                 b1 = s[0];
  992                 b2 = s[1];
  993                 b3 = s[2];
  994                 b4 = s[3];
  995         } else {
  996                 /*
  997                  * This is a fallback and should not happen if the function
  998                  * was called properly.
  999                  */
 1000                 return (NULL);
 1001         }
 1002 
 1003         b1 = u8_composition_b1_tbl[uv][b1];
 1004         if (b1 == U8_TBL_ELEMENT_NOT_DEF)
 1005                 return (NULL);
 1006 
 1007         b2 = u8_composition_b2_tbl[uv][b1][b2];
 1008         if (b2 == U8_TBL_ELEMENT_NOT_DEF)
 1009                 return (NULL);
 1010 
 1011         b3_tbl = u8_composition_b3_tbl[uv][b2][b3].tbl_id;
 1012         if (b3_tbl == U8_TBL_ELEMENT_NOT_DEF)
 1013                 return (NULL);
 1014 
 1015         if (b3_tbl >= U8_16BIT_TABLE_INDICATOR) {
 1016                 b3_tbl -= U8_16BIT_TABLE_INDICATOR;
 1017                 start_id = u8_composition_b4_16bit_tbl[uv][b3_tbl][b4];
 1018                 end_id = u8_composition_b4_16bit_tbl[uv][b3_tbl][b4 + 1];
 1019         } else {
 1020                 // cppcheck-suppress arrayIndexOutOfBoundsCond
 1021                 start_id = u8_composition_b4_tbl[uv][b3_tbl][b4];
 1022                 // cppcheck-suppress arrayIndexOutOfBoundsCond
 1023                 end_id = u8_composition_b4_tbl[uv][b3_tbl][b4 + 1];
 1024         }
 1025 
 1026         if (start_id >= end_id)
 1027                 return (NULL);
 1028 
 1029         b3_base = u8_composition_b3_tbl[uv][b2][b3].base;
 1030 
 1031         return ((uchar_t *)&(u8_composition_final_tbl[uv][b3_base + start_id]));
 1032 }
 1033 
 1034 /*
 1035  * The blocked() function checks on the combining class values of previous
 1036  * characters in this sequence and return whether it is blocked or not.
 1037  */
 1038 static boolean_t
 1039 blocked(uchar_t *comb_class, size_t last)
 1040 {
 1041         uchar_t my_comb_class;
 1042         size_t i;
 1043 
 1044         my_comb_class = comb_class[last];
 1045         for (i = 1; i < last; i++)
 1046                 if (comb_class[i] >= my_comb_class ||
 1047                     comb_class[i] == U8_COMBINING_CLASS_STARTER)
 1048                         return (B_TRUE);
 1049 
 1050         return (B_FALSE);
 1051 }
 1052 
 1053 /*
 1054  * The do_composition() reads the character string pointed by 's' and
 1055  * do necessary canonical composition and then copy over the result back to
 1056  * the 's'.
 1057  *
 1058  * The input argument 's' cannot contain more than 32 characters.
 1059  */
 1060 static size_t
 1061 do_composition(size_t uv, uchar_t *s, uchar_t *comb_class, uchar_t *start,
 1062     uchar_t *disp, size_t last, uchar_t **os, uchar_t *oslast)
 1063 {
 1064         uchar_t t[U8_STREAM_SAFE_TEXT_MAX + 1];
 1065         uchar_t tc[U8_MB_CUR_MAX] = { '\0' };
 1066         uint8_t saved_marks[U8_MAX_CHARS_A_SEQ];
 1067         size_t saved_marks_count;
 1068         uchar_t *p;
 1069         uchar_t *saved_p;
 1070         uchar_t *q;
 1071         size_t i;
 1072         size_t saved_i;
 1073         size_t j;
 1074         size_t k;
 1075         size_t l;
 1076         size_t C;
 1077         size_t saved_l;
 1078         size_t size;
 1079         uint32_t u1;
 1080         uint32_t u2;
 1081         boolean_t match_not_found = B_TRUE;
 1082 
 1083         /*
 1084          * This should never happen unless the callers are doing some strange
 1085          * and unexpected things.
 1086          *
 1087          * The "last" is the index pointing to the last character not last + 1.
 1088          */
 1089         if (last >= U8_MAX_CHARS_A_SEQ)
 1090                 last = U8_UPPER_LIMIT_IN_A_SEQ;
 1091 
 1092         for (i = l = 0; i <= last; i++) {
 1093                 /*
 1094                  * The last or any non-Starters at the beginning, we don't
 1095                  * have any chance to do composition and so we just copy them
 1096                  * to the temporary buffer.
 1097                  */
 1098                 if (i >= last || comb_class[i] != U8_COMBINING_CLASS_STARTER) {
 1099 SAVE_THE_CHAR:
 1100                         p = s + start[i];
 1101                         size = disp[i];
 1102                         for (k = 0; k < size; k++)
 1103                                 t[l++] = *p++;
 1104                         continue;
 1105                 }
 1106 
 1107                 /*
 1108                  * If this could be a start of Hangul Jamos, then, we try to
 1109                  * conjoin them.
 1110                  */
 1111                 if (s[start[i]] == U8_HANGUL_JAMO_1ST_BYTE) {
 1112                         U8_PUT_3BYTES_INTO_UTF32(u1, s[start[i]],
 1113                             s[start[i] + 1], s[start[i] + 2]);
 1114                         U8_PUT_3BYTES_INTO_UTF32(u2, s[start[i] + 3],
 1115                             s[start[i] + 4], s[start[i] + 5]);
 1116 
 1117                         if (U8_HANGUL_JAMO_L(u1) && U8_HANGUL_JAMO_V(u2)) {
 1118                                 u1 -= U8_HANGUL_JAMO_L_FIRST;
 1119                                 u2 -= U8_HANGUL_JAMO_V_FIRST;
 1120                                 u1 = U8_HANGUL_SYL_FIRST +
 1121                                     (u1 * U8_HANGUL_V_COUNT + u2) *
 1122                                     U8_HANGUL_T_COUNT;
 1123 
 1124                                 i += 2;
 1125                                 if (i <= last) {
 1126                                         U8_PUT_3BYTES_INTO_UTF32(u2,
 1127                                             s[start[i]], s[start[i] + 1],
 1128                                             s[start[i] + 2]);
 1129 
 1130                                         if (U8_HANGUL_JAMO_T(u2)) {
 1131                                                 u1 += u2 -
 1132                                                     U8_HANGUL_JAMO_T_FIRST;
 1133                                                 i++;
 1134                                         }
 1135                                 }
 1136 
 1137                                 U8_SAVE_HANGUL_AS_UTF8(t + l, 0, 1, 2, u1);
 1138                                 i--;
 1139                                 l += 3;
 1140                                 continue;
 1141                         }
 1142                 }
 1143 
 1144                 /*
 1145                  * Let's then find out if this Starter has composition
 1146                  * mapping.
 1147                  */
 1148                 p = find_composition_start(uv, s + start[i], disp[i]);
 1149                 if (p == NULL)
 1150                         goto SAVE_THE_CHAR;
 1151 
 1152                 /*
 1153                  * We have a Starter with composition mapping and the next
 1154                  * character is a non-Starter. Let's try to find out if
 1155                  * we can do composition.
 1156                  */
 1157 
 1158                 saved_p = p;
 1159                 saved_i = i;
 1160                 saved_l = l;
 1161                 saved_marks_count = 0;
 1162 
 1163 TRY_THE_NEXT_MARK:
 1164                 q = s + start[++i];
 1165                 size = disp[i];
 1166 
 1167                 /*
 1168                  * The next for() loop compares the non-Starter pointed by
 1169                  * 'q' with the possible (joinable) characters pointed by 'p'.
 1170                  *
 1171                  * The composition final table entry pointed by the 'p'
 1172                  * looks like the following:
 1173                  *
 1174                  * +---+---+---+-...-+---+---+---+---+-...-+---+---+
 1175                  * | C | b0| b2| ... | bn| F | B0| B1| ... | Bm| F |
 1176                  * +---+---+---+-...-+---+---+---+---+-...-+---+---+
 1177                  *
 1178                  * where C is the count byte indicating the number of
 1179                  * mapping pairs where each pair would be look like
 1180                  * (b0-bn F, B0-Bm F). The b0-bn are the bytes of the second
 1181                  * character of a canonical decomposition and the B0-Bm are
 1182                  * the bytes of a matching composite character. The F is
 1183                  * a filler byte after each character as the separator.
 1184                  */
 1185 
 1186                 match_not_found = B_TRUE;
 1187 
 1188                 for (C = *p++; C > 0; C--) {
 1189                         for (k = 0; k < size; p++, k++)
 1190                                 if (*p != q[k])
 1191                                         break;
 1192 
 1193                         /* Have we found it? */
 1194                         if (k >= size && *p == U8_TBL_ELEMENT_FILLER) {
 1195                                 match_not_found = B_FALSE;
 1196 
 1197                                 l = saved_l;
 1198 
 1199                                 while (*++p != U8_TBL_ELEMENT_FILLER)
 1200                                         t[l++] = *p;
 1201 
 1202                                 break;
 1203                         }
 1204 
 1205                         /* We didn't find; skip to the next pair. */
 1206                         if (*p != U8_TBL_ELEMENT_FILLER)
 1207                                 while (*++p != U8_TBL_ELEMENT_FILLER)
 1208                                         ;
 1209                         while (*++p != U8_TBL_ELEMENT_FILLER)
 1210                                 ;
 1211                         p++;
 1212                 }
 1213 
 1214                 /*
 1215                  * If there was no match, we will need to save the combining
 1216                  * mark for later appending. After that, if the next one
 1217                  * is a non-Starter and not blocked, then, we try once
 1218                  * again to do composition with the next non-Starter.
 1219                  *
 1220                  * If there was no match and this was a Starter, then,
 1221                  * this is a new start.
 1222                  *
 1223                  * If there was a match and a composition done and we have
 1224                  * more to check on, then, we retrieve a new composition final
 1225                  * table entry for the composite and then try to do the
 1226                  * composition again.
 1227                  */
 1228 
 1229                 if (match_not_found) {
 1230                         if (comb_class[i] == U8_COMBINING_CLASS_STARTER) {
 1231                                 i--;
 1232                                 goto SAVE_THE_CHAR;
 1233                         }
 1234 
 1235                         saved_marks[saved_marks_count++] = i;
 1236                 }
 1237 
 1238                 if (saved_l == l) {
 1239                         while (i < last) {
 1240                                 if (blocked(comb_class, i + 1))
 1241                                         saved_marks[saved_marks_count++] = ++i;
 1242                                 else
 1243                                         break;
 1244                         }
 1245                         if (i < last) {
 1246                                 p = saved_p;
 1247                                 goto TRY_THE_NEXT_MARK;
 1248                         }
 1249                 } else if (i < last) {
 1250                         p = find_composition_start(uv, t + saved_l,
 1251                             l - saved_l);
 1252                         if (p != NULL) {
 1253                                 saved_p = p;
 1254                                 goto TRY_THE_NEXT_MARK;
 1255                         }
 1256                 }
 1257 
 1258                 /*
 1259                  * There is no more composition possible.
 1260                  *
 1261                  * If there was no composition what so ever then we copy
 1262                  * over the original Starter and then append any non-Starters
 1263                  * remaining at the target string sequentially after that.
 1264                  */
 1265 
 1266                 if (saved_l == l) {
 1267                         p = s + start[saved_i];
 1268                         size = disp[saved_i];
 1269                         for (j = 0; j < size; j++)
 1270                                 t[l++] = *p++;
 1271                 }
 1272 
 1273                 for (k = 0; k < saved_marks_count; k++) {
 1274                         p = s + start[saved_marks[k]];
 1275                         size = disp[saved_marks[k]];
 1276                         for (j = 0; j < size; j++)
 1277                                 t[l++] = *p++;
 1278                 }
 1279         }
 1280 
 1281         /*
 1282          * If the last character is a Starter and if we have a character
 1283          * (possibly another Starter) that can be turned into a composite,
 1284          * we do so and we do so until there is no more of composition
 1285          * possible.
 1286          */
 1287         if (comb_class[last] == U8_COMBINING_CLASS_STARTER) {
 1288                 p = *os;
 1289                 saved_l = l - disp[last];
 1290 
 1291                 while (p < oslast) {
 1292                         int8_t number_of_bytes = u8_number_of_bytes[*p];
 1293 
 1294                         if (number_of_bytes <= 1)
 1295                                 break;
 1296                         size = number_of_bytes;
 1297                         if ((p + size) > oslast)
 1298                                 break;
 1299 
 1300                         saved_p = p;
 1301 
 1302                         for (i = 0; i < size; i++)
 1303                                 tc[i] = *p++;
 1304 
 1305                         q = find_composition_start(uv, t + saved_l,
 1306                             l - saved_l);
 1307                         if (q == NULL) {
 1308                                 p = saved_p;
 1309                                 break;
 1310                         }
 1311 
 1312                         match_not_found = B_TRUE;
 1313 
 1314                         for (C = *q++; C > 0; C--) {
 1315                                 for (k = 0; k < size; q++, k++)
 1316                                         if (*q != tc[k])
 1317                                                 break;
 1318 
 1319                                 if (k >= size && *q == U8_TBL_ELEMENT_FILLER) {
 1320                                         match_not_found = B_FALSE;
 1321 
 1322                                         l = saved_l;
 1323 
 1324                                         while (*++q != U8_TBL_ELEMENT_FILLER) {
 1325                                                 /*
 1326                                                  * This is practically
 1327                                                  * impossible but we don't
 1328                                                  * want to take any chances.
 1329                                                  */
 1330                                                 if (l >=
 1331                                                     U8_STREAM_SAFE_TEXT_MAX) {
 1332                                                         p = saved_p;
 1333                                                         goto SAFE_RETURN;
 1334                                                 }
 1335                                                 t[l++] = *q;
 1336                                         }
 1337 
 1338                                         break;
 1339                                 }
 1340 
 1341                                 if (*q != U8_TBL_ELEMENT_FILLER)
 1342                                         while (*++q != U8_TBL_ELEMENT_FILLER)
 1343                                                 ;
 1344                                 while (*++q != U8_TBL_ELEMENT_FILLER)
 1345                                         ;
 1346                                 q++;
 1347                         }
 1348 
 1349                         if (match_not_found) {
 1350                                 p = saved_p;
 1351                                 break;
 1352                         }
 1353                 }
 1354 SAFE_RETURN:
 1355                 *os = p;
 1356         }
 1357 
 1358         /*
 1359          * Now we copy over the temporary string to the target string.
 1360          * Since composition always reduces the number of characters or
 1361          * the number of characters stay, we don't need to worry about
 1362          * the buffer overflow here.
 1363          */
 1364         for (i = 0; i < l; i++)
 1365                 s[i] = t[i];
 1366         s[l] = '\0';
 1367 
 1368         return (l);
 1369 }
 1370 
 1371 /*
 1372  * The collect_a_seq() function checks on the given string s, collect
 1373  * a sequence of characters at u8s, and return the sequence. While it collects
 1374  * a sequence, it also applies case conversion, canonical or compatibility
 1375  * decomposition, canonical decomposition, or some or all of them and
 1376  * in that order.
 1377  *
 1378  * The collected sequence cannot be bigger than 32 characters since if
 1379  * it is having more than 31 characters, the sequence will be terminated
 1380  * with a U+034F COMBINING GRAPHEME JOINER (CGJ) character and turned into
 1381  * a Stream-Safe Text. The collected sequence is always terminated with
 1382  * a null byte and the return value is the byte length of the sequence
 1383  * including 0. The return value does not include the terminating
 1384  * null byte.
 1385  */
 1386 static size_t
 1387 collect_a_seq(size_t uv, uchar_t *u8s, uchar_t **source, uchar_t *slast,
 1388     boolean_t is_it_toupper,
 1389     boolean_t is_it_tolower,
 1390     boolean_t canonical_decomposition,
 1391     boolean_t compatibility_decomposition,
 1392     boolean_t canonical_composition,
 1393     int *errnum, u8_normalization_states_t *state)
 1394 {
 1395         uchar_t *s;
 1396         int sz;
 1397         int saved_sz;
 1398         size_t i;
 1399         size_t j;
 1400         size_t k;
 1401         size_t l;
 1402         uchar_t comb_class[U8_MAX_CHARS_A_SEQ];
 1403         uchar_t disp[U8_MAX_CHARS_A_SEQ];
 1404         uchar_t start[U8_MAX_CHARS_A_SEQ];
 1405         uchar_t u8t[U8_MB_CUR_MAX] = { '\0' };
 1406         uchar_t uts[U8_STREAM_SAFE_TEXT_MAX + 1];
 1407         uchar_t tc;
 1408         size_t last;
 1409         size_t saved_last;
 1410         uint32_t u1;
 1411 
 1412         /*
 1413          * Save the source string pointer which we will return a changed
 1414          * pointer if we do processing.
 1415          */
 1416         s = *source;
 1417 
 1418         /*
 1419          * The following is a fallback for just in case callers are not
 1420          * checking the string boundaries before the calling.
 1421          */
 1422         if (s >= slast) {
 1423                 u8s[0] = '\0';
 1424 
 1425                 return (0);
 1426         }
 1427 
 1428         /*
 1429          * As the first thing, let's collect a character and do case
 1430          * conversion if necessary.
 1431          */
 1432 
 1433         sz = u8_number_of_bytes[*s];
 1434 
 1435         if (sz < 0) {
 1436                 *errnum = EILSEQ;
 1437 
 1438                 u8s[0] = *s++;
 1439                 u8s[1] = '\0';
 1440 
 1441                 *source = s;
 1442 
 1443                 return (1);
 1444         }
 1445 
 1446         if (sz == 1) {
 1447                 if (is_it_toupper)
 1448                         u8s[0] = U8_ASCII_TOUPPER(*s);
 1449                 else if (is_it_tolower)
 1450                         u8s[0] = U8_ASCII_TOLOWER(*s);
 1451                 else
 1452                         u8s[0] = *s;
 1453                 s++;
 1454                 u8s[1] = '\0';
 1455         } else if ((s + sz) > slast) {
 1456                 *errnum = EINVAL;
 1457 
 1458                 for (i = 0; s < slast; )
 1459                         u8s[i++] = *s++;
 1460                 u8s[i] = '\0';
 1461 
 1462                 *source = s;
 1463 
 1464                 return (i);
 1465         } else {
 1466                 if (is_it_toupper || is_it_tolower) {
 1467                         i = do_case_conv(uv, u8s, s, sz, is_it_toupper);
 1468                         s += sz;
 1469                         sz = i;
 1470                 } else {
 1471                         for (i = 0; i < sz; )
 1472                                 u8s[i++] = *s++;
 1473                         u8s[i] = '\0';
 1474                 }
 1475         }
 1476 
 1477         /*
 1478          * And then canonical/compatibility decomposition followed by
 1479          * an optional canonical composition. Please be noted that
 1480          * canonical composition is done only when a decomposition is
 1481          * done.
 1482          */
 1483         if (canonical_decomposition || compatibility_decomposition) {
 1484                 if (sz == 1) {
 1485                         *state = U8_STATE_START;
 1486 
 1487                         saved_sz = 1;
 1488 
 1489                         comb_class[0] = 0;
 1490                         start[0] = 0;
 1491                         disp[0] = 1;
 1492 
 1493                         last = 1;
 1494                 } else {
 1495                         saved_sz = do_decomp(uv, u8s, u8s, sz,
 1496                             canonical_decomposition, state);
 1497 
 1498                         last = 0;
 1499 
 1500                         for (i = 0; i < saved_sz; ) {
 1501                                 sz = u8_number_of_bytes[u8s[i]];
 1502 
 1503                                 comb_class[last] = combining_class(uv,
 1504                                     u8s + i, sz);
 1505                                 start[last] = i;
 1506                                 disp[last] = sz;
 1507 
 1508                                 last++;
 1509                                 i += sz;
 1510                         }
 1511 
 1512                         /*
 1513                          * Decomposition yields various Hangul related
 1514                          * states but not on combining marks. We need to
 1515                          * find out at here by checking on the last
 1516                          * character.
 1517                          */
 1518                         if (*state == U8_STATE_START) {
 1519                                 if (comb_class[last - 1])
 1520                                         *state = U8_STATE_COMBINING_MARK;
 1521                         }
 1522                 }
 1523 
 1524                 saved_last = last;
 1525 
 1526                 while (s < slast) {
 1527                         sz = u8_number_of_bytes[*s];
 1528 
 1529                         /*
 1530                          * If this is an illegal character, an incomplete
 1531                          * character, or an 7-bit ASCII Starter character,
 1532                          * then we have collected a sequence; break and let
 1533                          * the next call deal with the two cases.
 1534                          *
 1535                          * Note that this is okay only if you are using this
 1536                          * function with a fixed length string, not on
 1537                          * a buffer with multiple calls of one chunk at a time.
 1538                          */
 1539                         if (sz <= 1) {
 1540                                 break;
 1541                         } else if ((s + sz) > slast) {
 1542                                 break;
 1543                         } else {
 1544                                 /*
 1545                                  * If the previous character was a Hangul Jamo
 1546                                  * and this character is a Hangul Jamo that
 1547                                  * can be conjoined, we collect the Jamo.
 1548                                  */
 1549                                 if (*s == U8_HANGUL_JAMO_1ST_BYTE) {
 1550                                         U8_PUT_3BYTES_INTO_UTF32(u1,
 1551                                             *s, *(s + 1), *(s + 2));
 1552 
 1553                                         if (U8_HANGUL_COMPOSABLE_L_V(*state,
 1554                                             u1)) {
 1555                                                 i = 0;
 1556                                                 *state = U8_STATE_HANGUL_LV;
 1557                                                 goto COLLECT_A_HANGUL;
 1558                                         }
 1559 
 1560                                         if (U8_HANGUL_COMPOSABLE_LV_T(*state,
 1561                                             u1)) {
 1562                                                 i = 0;
 1563                                                 *state = U8_STATE_HANGUL_LVT;
 1564                                                 goto COLLECT_A_HANGUL;
 1565                                         }
 1566                                 }
 1567 
 1568                                 /*
 1569                                  * Regardless of whatever it was, if this is
 1570                                  * a Starter, we don't collect the character
 1571                                  * since that's a new start and we will deal
 1572                                  * with it at the next time.
 1573                                  */
 1574                                 i = combining_class(uv, s, sz);
 1575                                 if (i == U8_COMBINING_CLASS_STARTER)
 1576                                         break;
 1577 
 1578                                 /*
 1579                                  * We know the current character is a combining
 1580                                  * mark. If the previous character wasn't
 1581                                  * a Starter (not Hangul) or a combining mark,
 1582                                  * then, we don't collect this combining mark.
 1583                                  */
 1584                                 if (*state != U8_STATE_START &&
 1585                                     *state != U8_STATE_COMBINING_MARK)
 1586                                         break;
 1587 
 1588                                 *state = U8_STATE_COMBINING_MARK;
 1589 COLLECT_A_HANGUL:
 1590                                 /*
 1591                                  * If we collected a Starter and combining
 1592                                  * marks up to 30, i.e., total 31 characters,
 1593                                  * then, we terminate this degenerately long
 1594                                  * combining sequence with a U+034F COMBINING
 1595                                  * GRAPHEME JOINER (CGJ) which is 0xCD 0x8F in
 1596                                  * UTF-8 and turn this into a Stream-Safe
 1597                                  * Text. This will be extremely rare but
 1598                                  * possible.
 1599                                  *
 1600                                  * The following will also guarantee that
 1601                                  * we are not writing more than 32 characters
 1602                                  * plus a NULL at u8s[].
 1603                                  */
 1604                                 if (last >= U8_UPPER_LIMIT_IN_A_SEQ) {
 1605 TURN_STREAM_SAFE:
 1606                                         *state = U8_STATE_START;
 1607                                         comb_class[last] = 0;
 1608                                         start[last] = saved_sz;
 1609                                         disp[last] = 2;
 1610                                         last++;
 1611 
 1612                                         u8s[saved_sz++] = 0xCD;
 1613                                         u8s[saved_sz++] = 0x8F;
 1614 
 1615                                         break;
 1616                                 }
 1617 
 1618                                 /*
 1619                                  * Some combining marks also do decompose into
 1620                                  * another combining mark or marks.
 1621                                  */
 1622                                 if (*state == U8_STATE_COMBINING_MARK) {
 1623                                         k = last;
 1624                                         l = sz;
 1625                                         i = do_decomp(uv, uts, s, sz,
 1626                                             canonical_decomposition, state);
 1627                                         for (j = 0; j < i; ) {
 1628                                                 sz = u8_number_of_bytes[uts[j]];
 1629 
 1630                                                 comb_class[last] =
 1631                                                     combining_class(uv,
 1632                                                     uts + j, sz);
 1633                                                 start[last] = saved_sz + j;
 1634                                                 disp[last] = sz;
 1635 
 1636                                                 last++;
 1637                                                 if (last >=
 1638                                                     U8_UPPER_LIMIT_IN_A_SEQ) {
 1639                                                         last = k;
 1640                                                         goto TURN_STREAM_SAFE;
 1641                                                 }
 1642                                                 j += sz;
 1643                                         }
 1644 
 1645                                         *state = U8_STATE_COMBINING_MARK;
 1646                                         sz = i;
 1647                                         s += l;
 1648 
 1649                                         for (i = 0; i < sz; i++)
 1650                                                 u8s[saved_sz++] = uts[i];
 1651                                 } else {
 1652                                         comb_class[last] = i;
 1653                                         start[last] = saved_sz;
 1654                                         disp[last] = sz;
 1655                                         last++;
 1656 
 1657                                         for (i = 0; i < sz; i++)
 1658                                                 u8s[saved_sz++] = *s++;
 1659                                 }
 1660 
 1661                                 /*
 1662                                  * If this is U+0345 COMBINING GREEK
 1663                                  * YPOGEGRAMMENI (0xCD 0x85 in UTF-8), a.k.a.,
 1664                                  * iota subscript, and need to be converted to
 1665                                  * uppercase letter, convert it to U+0399 GREEK
 1666                                  * CAPITAL LETTER IOTA (0xCE 0x99 in UTF-8),
 1667                                  * i.e., convert to capital adscript form as
 1668                                  * specified in the Unicode standard.
 1669                                  *
 1670                                  * This is the only special case of (ambiguous)
 1671                                  * case conversion at combining marks and
 1672                                  * probably the standard will never have
 1673                                  * anything similar like this in future.
 1674                                  */
 1675                                 if (is_it_toupper && sz >= 2 &&
 1676                                     u8s[saved_sz - 2] == 0xCD &&
 1677                                     u8s[saved_sz - 1] == 0x85) {
 1678                                         u8s[saved_sz - 2] = 0xCE;
 1679                                         u8s[saved_sz - 1] = 0x99;
 1680                                 }
 1681                         }
 1682                 }
 1683 
 1684                 /*
 1685                  * Let's try to ensure a canonical ordering for the collected
 1686                  * combining marks. We do this only if we have collected
 1687                  * at least one more non-Starter. (The decomposition mapping
 1688                  * data tables have fully (and recursively) expanded and
 1689                  * canonically ordered decompositions.)
 1690                  *
 1691                  * The U8_SWAP_COMB_MARKS() convenience macro has some
 1692                  * assumptions and we are meeting the assumptions.
 1693                  */
 1694                 last--;
 1695                 if (last >= saved_last) {
 1696                         for (i = 0; i < last; i++)
 1697                                 for (j = last; j > i; j--)
 1698                                         if (comb_class[j] &&
 1699                                             comb_class[j - 1] > comb_class[j]) {
 1700                                                 U8_SWAP_COMB_MARKS(j - 1, j);
 1701                                         }
 1702                 }
 1703 
 1704                 *source = s;
 1705 
 1706                 if (! canonical_composition) {
 1707                         u8s[saved_sz] = '\0';
 1708                         return (saved_sz);
 1709                 }
 1710 
 1711                 /*
 1712                  * Now do the canonical composition. Note that we do this
 1713                  * only after a canonical or compatibility decomposition to
 1714                  * finish up NFC or NFKC.
 1715                  */
 1716                 sz = do_composition(uv, u8s, comb_class, start, disp, last,
 1717                     &s, slast);
 1718         }
 1719 
 1720         *source = s;
 1721 
 1722         return ((size_t)sz);
 1723 }
 1724 
 1725 /*
 1726  * The do_norm_compare() function does string comparison based on Unicode
 1727  * simple case mappings and Unicode Normalization definitions.
 1728  *
 1729  * It does so by collecting a sequence of character at a time and comparing
 1730  * the collected sequences from the strings.
 1731  *
 1732  * The meanings on the return values are the same as the usual strcmp().
 1733  */
 1734 static int
 1735 do_norm_compare(size_t uv, uchar_t *s1, uchar_t *s2, size_t n1, size_t n2,
 1736     int flag, int *errnum)
 1737 {
 1738         int result;
 1739         size_t sz1;
 1740         size_t sz2;
 1741         uchar_t u8s1[U8_STREAM_SAFE_TEXT_MAX + 1];
 1742         uchar_t u8s2[U8_STREAM_SAFE_TEXT_MAX + 1];
 1743         uchar_t *s1last;
 1744         uchar_t *s2last;
 1745         boolean_t is_it_toupper;
 1746         boolean_t is_it_tolower;
 1747         boolean_t canonical_decomposition;
 1748         boolean_t compatibility_decomposition;
 1749         boolean_t canonical_composition;
 1750         u8_normalization_states_t state;
 1751 
 1752         s1last = s1 + n1;
 1753         s2last = s2 + n2;
 1754 
 1755         is_it_toupper = flag & U8_TEXTPREP_TOUPPER;
 1756         is_it_tolower = flag & U8_TEXTPREP_TOLOWER;
 1757         canonical_decomposition = flag & U8_CANON_DECOMP;
 1758         compatibility_decomposition = flag & U8_COMPAT_DECOMP;
 1759         canonical_composition = flag & U8_CANON_COMP;
 1760 
 1761         while (s1 < s1last && s2 < s2last) {
 1762                 /*
 1763                  * If the current character is a 7-bit ASCII and the last
 1764                  * character, or, if the current character and the next
 1765                  * character are both some 7-bit ASCII characters then
 1766                  * we treat the current character as a sequence.
 1767                  *
 1768                  * In any other cases, we need to call collect_a_seq().
 1769                  */
 1770 
 1771                 if (U8_ISASCII(*s1) && ((s1 + 1) >= s1last ||
 1772                     ((s1 + 1) < s1last && U8_ISASCII(*(s1 + 1))))) {
 1773                         if (is_it_toupper)
 1774                                 u8s1[0] = U8_ASCII_TOUPPER(*s1);
 1775                         else if (is_it_tolower)
 1776                                 u8s1[0] = U8_ASCII_TOLOWER(*s1);
 1777                         else
 1778                                 u8s1[0] = *s1;
 1779                         u8s1[1] = '\0';
 1780                         sz1 = 1;
 1781                         s1++;
 1782                 } else {
 1783                         state = U8_STATE_START;
 1784                         sz1 = collect_a_seq(uv, u8s1, &s1, s1last,
 1785                             is_it_toupper, is_it_tolower,
 1786                             canonical_decomposition,
 1787                             compatibility_decomposition,
 1788                             canonical_composition, errnum, &state);
 1789                 }
 1790 
 1791                 if (U8_ISASCII(*s2) && ((s2 + 1) >= s2last ||
 1792                     ((s2 + 1) < s2last && U8_ISASCII(*(s2 + 1))))) {
 1793                         if (is_it_toupper)
 1794                                 u8s2[0] = U8_ASCII_TOUPPER(*s2);
 1795                         else if (is_it_tolower)
 1796                                 u8s2[0] = U8_ASCII_TOLOWER(*s2);
 1797                         else
 1798                                 u8s2[0] = *s2;
 1799                         u8s2[1] = '\0';
 1800                         sz2 = 1;
 1801                         s2++;
 1802                 } else {
 1803                         state = U8_STATE_START;
 1804                         sz2 = collect_a_seq(uv, u8s2, &s2, s2last,
 1805                             is_it_toupper, is_it_tolower,
 1806                             canonical_decomposition,
 1807                             compatibility_decomposition,
 1808                             canonical_composition, errnum, &state);
 1809                 }
 1810 
 1811                 /*
 1812                  * Now compare the two characters. If they are the same,
 1813                  * we move on to the next character sequences.
 1814                  */
 1815                 if (sz1 == 1 && sz2 == 1) {
 1816                         if (*u8s1 > *u8s2)
 1817                                 return (1);
 1818                         if (*u8s1 < *u8s2)
 1819                                 return (-1);
 1820                 } else {
 1821                         result = strcmp((const char *)u8s1, (const char *)u8s2);
 1822                         if (result != 0)
 1823                                 return (result);
 1824                 }
 1825         }
 1826 
 1827         /*
 1828          * We compared until the end of either or both strings.
 1829          *
 1830          * If we reached to or went over the ends for the both, that means
 1831          * they are the same.
 1832          *
 1833          * If we reached only one end, that means the other string has
 1834          * something which then can be used to determine the return value.
 1835          */
 1836         if (s1 >= s1last) {
 1837                 if (s2 >= s2last)
 1838                         return (0);
 1839                 return (-1);
 1840         }
 1841         return (1);
 1842 }
 1843 
 1844 /*
 1845  * The u8_strcmp() function compares two UTF-8 strings quite similar to
 1846  * the strcmp(). For the comparison, however, Unicode Normalization specific
 1847  * equivalency and Unicode simple case conversion mappings based equivalency
 1848  * can be requested and checked against.
 1849  */
 1850 int
 1851 u8_strcmp(const char *s1, const char *s2, size_t n, int flag, size_t uv,
 1852     int *errnum)
 1853 {
 1854         int f;
 1855         size_t n1;
 1856         size_t n2;
 1857 
 1858         *errnum = 0;
 1859 
 1860         /*
 1861          * Check on the requested Unicode version, case conversion, and
 1862          * normalization flag values.
 1863          */
 1864 
 1865         if (uv > U8_UNICODE_LATEST) {
 1866                 *errnum = ERANGE;
 1867                 uv = U8_UNICODE_LATEST;
 1868         }
 1869 
 1870         if (flag == 0) {
 1871                 flag = U8_STRCMP_CS;
 1872         } else {
 1873                 f = flag & (U8_STRCMP_CS | U8_STRCMP_CI_UPPER |
 1874                     U8_STRCMP_CI_LOWER);
 1875                 if (f == 0) {
 1876                         flag |= U8_STRCMP_CS;
 1877                 } else if (f != U8_STRCMP_CS && f != U8_STRCMP_CI_UPPER &&
 1878                     f != U8_STRCMP_CI_LOWER) {
 1879                         *errnum = EBADF;
 1880                         flag = U8_STRCMP_CS;
 1881                 }
 1882 
 1883                 f = flag & (U8_CANON_DECOMP | U8_COMPAT_DECOMP | U8_CANON_COMP);
 1884                 if (f && f != U8_STRCMP_NFD && f != U8_STRCMP_NFC &&
 1885                     f != U8_STRCMP_NFKD && f != U8_STRCMP_NFKC) {
 1886                         *errnum = EBADF;
 1887                         flag = U8_STRCMP_CS;
 1888                 }
 1889         }
 1890 
 1891         if (flag == U8_STRCMP_CS) {
 1892                 return (n == 0 ? strcmp(s1, s2) : strncmp(s1, s2, n));
 1893         }
 1894 
 1895         n1 = strlen(s1);
 1896         n2 = strlen(s2);
 1897         if (n != 0) {
 1898                 if (n < n1)
 1899                         n1 = n;
 1900                 if (n < n2)
 1901                         n2 = n;
 1902         }
 1903 
 1904         /*
 1905          * Simple case conversion can be done much faster and so we do
 1906          * them separately here.
 1907          */
 1908         if (flag == U8_STRCMP_CI_UPPER) {
 1909                 return (do_case_compare(uv, (uchar_t *)s1, (uchar_t *)s2,
 1910                     n1, n2, B_TRUE, errnum));
 1911         } else if (flag == U8_STRCMP_CI_LOWER) {
 1912                 return (do_case_compare(uv, (uchar_t *)s1, (uchar_t *)s2,
 1913                     n1, n2, B_FALSE, errnum));
 1914         }
 1915 
 1916         return (do_norm_compare(uv, (uchar_t *)s1, (uchar_t *)s2, n1, n2,
 1917             flag, errnum));
 1918 }
 1919 
 1920 size_t
 1921 u8_textprep_str(char *inarray, size_t *inlen, char *outarray, size_t *outlen,
 1922     int flag, size_t unicode_version, int *errnum)
 1923 {
 1924         int f;
 1925         int sz;
 1926         uchar_t *ib;
 1927         uchar_t *ibtail;
 1928         uchar_t *ob;
 1929         uchar_t *obtail;
 1930         boolean_t do_not_ignore_null;
 1931         boolean_t do_not_ignore_invalid;
 1932         boolean_t is_it_toupper;
 1933         boolean_t is_it_tolower;
 1934         boolean_t canonical_decomposition;
 1935         boolean_t compatibility_decomposition;
 1936         boolean_t canonical_composition;
 1937         size_t ret_val;
 1938         size_t i;
 1939         size_t j;
 1940         uchar_t u8s[U8_STREAM_SAFE_TEXT_MAX + 1];
 1941         u8_normalization_states_t state;
 1942 
 1943         if (unicode_version > U8_UNICODE_LATEST) {
 1944                 *errnum = ERANGE;
 1945                 return ((size_t)-1);
 1946         }
 1947 
 1948         f = flag & (U8_TEXTPREP_TOUPPER | U8_TEXTPREP_TOLOWER);
 1949         if (f == (U8_TEXTPREP_TOUPPER | U8_TEXTPREP_TOLOWER)) {
 1950                 *errnum = EBADF;
 1951                 return ((size_t)-1);
 1952         }
 1953 
 1954         f = flag & (U8_CANON_DECOMP | U8_COMPAT_DECOMP | U8_CANON_COMP);
 1955         if (f && f != U8_TEXTPREP_NFD && f != U8_TEXTPREP_NFC &&
 1956             f != U8_TEXTPREP_NFKD && f != U8_TEXTPREP_NFKC) {
 1957                 *errnum = EBADF;
 1958                 return ((size_t)-1);
 1959         }
 1960 
 1961         if (inarray == NULL || *inlen == 0)
 1962                 return (0);
 1963 
 1964         if (outarray == NULL) {
 1965                 *errnum = E2BIG;
 1966                 return ((size_t)-1);
 1967         }
 1968 
 1969         ib = (uchar_t *)inarray;
 1970         ob = (uchar_t *)outarray;
 1971         ibtail = ib + *inlen;
 1972         obtail = ob + *outlen;
 1973 
 1974         do_not_ignore_null = !(flag & U8_TEXTPREP_IGNORE_NULL);
 1975         do_not_ignore_invalid = !(flag & U8_TEXTPREP_IGNORE_INVALID);
 1976         is_it_toupper = flag & U8_TEXTPREP_TOUPPER;
 1977         is_it_tolower = flag & U8_TEXTPREP_TOLOWER;
 1978 
 1979         ret_val = 0;
 1980 
 1981         /*
 1982          * If we don't have a normalization flag set, we do the simple case
 1983          * conversion based text preparation separately below. Text
 1984          * preparation involving Normalization will be done in the false task
 1985          * block, again, separately since it will take much more time and
 1986          * resource than doing simple case conversions.
 1987          */
 1988         if (f == 0) {
 1989                 while (ib < ibtail) {
 1990                         if (*ib == '\0' && do_not_ignore_null)
 1991                                 break;
 1992 
 1993                         sz = u8_number_of_bytes[*ib];
 1994 
 1995                         if (sz < 0) {
 1996                                 if (do_not_ignore_invalid) {
 1997                                         *errnum = EILSEQ;
 1998                                         ret_val = (size_t)-1;
 1999                                         break;
 2000                                 }
 2001 
 2002                                 sz = 1;
 2003                                 ret_val++;
 2004                         }
 2005 
 2006                         if (sz == 1) {
 2007                                 if (ob >= obtail) {
 2008                                         *errnum = E2BIG;
 2009                                         ret_val = (size_t)-1;
 2010                                         break;
 2011                                 }
 2012 
 2013                                 if (is_it_toupper)
 2014                                         *ob = U8_ASCII_TOUPPER(*ib);
 2015                                 else if (is_it_tolower)
 2016                                         *ob = U8_ASCII_TOLOWER(*ib);
 2017                                 else
 2018                                         *ob = *ib;
 2019                                 ib++;
 2020                                 ob++;
 2021                         } else if ((ib + sz) > ibtail) {
 2022                                 if (do_not_ignore_invalid) {
 2023                                         *errnum = EINVAL;
 2024                                         ret_val = (size_t)-1;
 2025                                         break;
 2026                                 }
 2027 
 2028                                 if ((obtail - ob) < (ibtail - ib)) {
 2029                                         *errnum = E2BIG;
 2030                                         ret_val = (size_t)-1;
 2031                                         break;
 2032                                 }
 2033 
 2034                                 /*
 2035                                  * We treat the remaining incomplete character
 2036                                  * bytes as a character.
 2037                                  */
 2038                                 ret_val++;
 2039 
 2040                                 while (ib < ibtail)
 2041                                         *ob++ = *ib++;
 2042                         } else {
 2043                                 if (is_it_toupper || is_it_tolower) {
 2044                                         i = do_case_conv(unicode_version, u8s,
 2045                                             ib, sz, is_it_toupper);
 2046 
 2047                                         if ((obtail - ob) < i) {
 2048                                                 *errnum = E2BIG;
 2049                                                 ret_val = (size_t)-1;
 2050                                                 break;
 2051                                         }
 2052 
 2053                                         ib += sz;
 2054 
 2055                                         for (sz = 0; sz < i; sz++)
 2056                                                 *ob++ = u8s[sz];
 2057                                 } else {
 2058                                         if ((obtail - ob) < sz) {
 2059                                                 *errnum = E2BIG;
 2060                                                 ret_val = (size_t)-1;
 2061                                                 break;
 2062                                         }
 2063 
 2064                                         for (i = 0; i < sz; i++)
 2065                                                 *ob++ = *ib++;
 2066                                 }
 2067                         }
 2068                 }
 2069         } else {
 2070                 canonical_decomposition = flag & U8_CANON_DECOMP;
 2071                 compatibility_decomposition = flag & U8_COMPAT_DECOMP;
 2072                 canonical_composition = flag & U8_CANON_COMP;
 2073 
 2074                 while (ib < ibtail) {
 2075                         if (*ib == '\0' && do_not_ignore_null)
 2076                                 break;
 2077 
 2078                         /*
 2079                          * If the current character is a 7-bit ASCII
 2080                          * character and it is the last character, or,
 2081                          * if the current character is a 7-bit ASCII
 2082                          * character and the next character is also a 7-bit
 2083                          * ASCII character, then, we copy over this
 2084                          * character without going through collect_a_seq().
 2085                          *
 2086                          * In any other cases, we need to look further with
 2087                          * the collect_a_seq() function.
 2088                          */
 2089                         if (U8_ISASCII(*ib) && ((ib + 1) >= ibtail ||
 2090                             ((ib + 1) < ibtail && U8_ISASCII(*(ib + 1))))) {
 2091                                 if (ob >= obtail) {
 2092                                         *errnum = E2BIG;
 2093                                         ret_val = (size_t)-1;
 2094                                         break;
 2095                                 }
 2096 
 2097                                 if (is_it_toupper)
 2098                                         *ob = U8_ASCII_TOUPPER(*ib);
 2099                                 else if (is_it_tolower)
 2100                                         *ob = U8_ASCII_TOLOWER(*ib);
 2101                                 else
 2102                                         *ob = *ib;
 2103                                 ib++;
 2104                                 ob++;
 2105                         } else {
 2106                                 *errnum = 0;
 2107                                 state = U8_STATE_START;
 2108 
 2109                                 j = collect_a_seq(unicode_version, u8s,
 2110                                     &ib, ibtail,
 2111                                     is_it_toupper,
 2112                                     is_it_tolower,
 2113                                     canonical_decomposition,
 2114                                     compatibility_decomposition,
 2115                                     canonical_composition,
 2116                                     errnum, &state);
 2117 
 2118                                 if (*errnum && do_not_ignore_invalid) {
 2119                                         ret_val = (size_t)-1;
 2120                                         break;
 2121                                 }
 2122 
 2123                                 if ((obtail - ob) < j) {
 2124                                         *errnum = E2BIG;
 2125                                         ret_val = (size_t)-1;
 2126                                         break;
 2127                                 }
 2128 
 2129                                 for (i = 0; i < j; i++)
 2130                                         *ob++ = u8s[i];
 2131                         }
 2132                 }
 2133         }
 2134 
 2135         *inlen = ibtail - ib;
 2136         *outlen = obtail - ob;
 2137 
 2138         return (ret_val);
 2139 }
 2140 
 2141 EXPORT_SYMBOL(u8_validate);
 2142 EXPORT_SYMBOL(u8_strcmp);
 2143 EXPORT_SYMBOL(u8_textprep_str);

Cache object: 0e2f409238348be1cdff0e95306db81b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.