LCOV - code coverage report
Current view: top level - monetdb5/modules/atoms - str.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 679 916 74.1 %
Date: 2021-10-13 02:24:04 Functions: 69 81 85.2 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  *  N.J. Nes, M.L. Kersten
      11             :  * The String Module
      12             :  * Strings can be created in many ways. Already in the built-in
      13             :  * operations each atom can be cast to a string using the str(atom)
      14             :  * mil command.  The string module gives the possibility of
      15             :  * construction string as a substring of the a given string (s). There
      16             :  * are two such construction functions.  The first is the substring
      17             :  * from some position (offset) until the end of the string. The second
      18             :  * start again on the given offset position but only copies count
      19             :  * number of bytes. The functions fail when the position and count
      20             :  * fall out of bounds. A negative position indicates that the position
      21             :  * is computed from the end of the source string.
      22             :  *
      23             :  * The strings can be compared using the "=" and "!=" operators.
      24             :  *
      25             :  * The operator "+" concatenates a string and an atom. The atom will
      26             :  * be converted to a string using the atom to string c function. The
      27             :  * string and the result of the conversion are concatenated to form a
      28             :  * new string. This string is returned.
      29             :  *
      30             :  * The length function returns the length of the string. The length is
      31             :  * the number of characters in the string. The maximum string length
      32             :  * handled by the kernel is 32-bits long.
      33             :  *
      34             :  * chrAt() returns the character at position index in the string
      35             :  * s. The function will fail when the index is out of range. The range
      36             :  * is from 0 to length(s)-1.
      37             :  *
      38             :  * The startsWith and endsWith functions test if the string s starts
      39             :  * with or ends with the given prefix or suffix.
      40             :  *
      41             :  * The toLower and toUpper functions cast the string to lower or upper
      42             :  * case characters.
      43             :  *
      44             :  * The search(str,chr) function searches for the first occurrence of a
      45             :  * character from the begining of the string. The search(chr,str)
      46             :  * searches for the last occurrence (or first from the end of the
      47             :  * string). The last search function locates the position of first
      48             :  * occurrence of the string s2 in string s. All search functions
      49             :  * return -1 when the search failed.  Otherwise the position is
      50             :  * returned.
      51             :  *
      52             :  * All string functions fail when an incorrect string (NULL pointer)
      53             :  * is given.  In the current implementation, a fail is signaled by
      54             :  * returning nil, since this facilitates the use of the string module
      55             :  * in bulk operations.
      56             :  *
      57             :  * All functions in the module have now been converted to
      58             :  * Unicode. Internally, we use UTF-8 to store strings as Unicode in
      59             :  * zero-terminated byte-sequences.
      60             :  */
      61             : #include "monetdb_config.h"
      62             : #include "str.h"
      63             : #include <string.h>
      64             : 
      65             : /*
      66             :  * UTF-8 Handling
      67             :  * UTF-8 is a way to store Unicode strings in zero-terminated byte
      68             :  * sequences, which you can e.g. strcmp() with old 8-bit Latin-1
      69             :  * strcmp() functions and which then gives the same results as doing
      70             :  * the strcmp() on equivalent Latin-1 and ASCII character strings
      71             :  * stored in simple one-byte sequences.  These characteristics make
      72             :  * UTF-8 an attractive format for upgrading an ASCII-oriented computer
      73             :  * program towards one that supports Unicode. That is why we use UTF-8
      74             :  * in MonetDB.
      75             :  *
      76             :  * For MonetDB, UTF-8 mostly has no consequences, as strings stored in
      77             :  * BATs are regarded as data, and it does not matter for the database
      78             :  * kernel whether the zero-terminated byte sequence it is processing
      79             :  * has UTF-8 or Latin-1 semantics. This module is the only place where
      80             :  * explicit string functionality is located. We {\bf do} have to adapt
      81             :  * the behavior of the length(), search(), substring() and the
      82             :  * like commands to the fact that one (Unicode) character is now
      83             :  * stored in a variable number of bytes (possibly > 1).
      84             :  *
      85             :  * One of the things that become more complex in Unicode are
      86             :  * uppercase/lowercase conversions. The below tables are the simple
      87             :  * one-to-one Unicode case mappings. We do not support the special
      88             :  * casing mappings (e.g. from one to two letters).
      89             :  *
      90             :  * References:
      91             :  * simple casing:       http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
      92             :  * complex casing: http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt
      93             :  *
      94             :  * The Unicode case conversion implementation in MonetDB fills a
      95             :  * mapping BAT of int,int combinations, in which we perform
      96             :  * high-performance hash-lookup (all code inlined).
      97             :  */
      98             : 
      99             : /* These tables were generated from the Unicode 13.0.0 spec. */
     100             : struct UTF8_lower_upper {
     101             :         unsigned int from, to;
     102             : } UTF8_toUpper[] = { /* code points with non-null uppercase conversion */
     103             :         { 0x0061, 0x0041, },
     104             :         { 0x0062, 0x0042, },
     105             :         { 0x0063, 0x0043, },
     106             :         { 0x0064, 0x0044, },
     107             :         { 0x0065, 0x0045, },
     108             :         { 0x0066, 0x0046, },
     109             :         { 0x0067, 0x0047, },
     110             :         { 0x0068, 0x0048, },
     111             :         { 0x0069, 0x0049, },
     112             :         { 0x006A, 0x004A, },
     113             :         { 0x006B, 0x004B, },
     114             :         { 0x006C, 0x004C, },
     115             :         { 0x006D, 0x004D, },
     116             :         { 0x006E, 0x004E, },
     117             :         { 0x006F, 0x004F, },
     118             :         { 0x0070, 0x0050, },
     119             :         { 0x0071, 0x0051, },
     120             :         { 0x0072, 0x0052, },
     121             :         { 0x0073, 0x0053, },
     122             :         { 0x0074, 0x0054, },
     123             :         { 0x0075, 0x0055, },
     124             :         { 0x0076, 0x0056, },
     125             :         { 0x0077, 0x0057, },
     126             :         { 0x0078, 0x0058, },
     127             :         { 0x0079, 0x0059, },
     128             :         { 0x007A, 0x005A, },
     129             :         { 0x00B5, 0x039C, },
     130             :         { 0x00E0, 0x00C0, },
     131             :         { 0x00E1, 0x00C1, },
     132             :         { 0x00E2, 0x00C2, },
     133             :         { 0x00E3, 0x00C3, },
     134             :         { 0x00E4, 0x00C4, },
     135             :         { 0x00E5, 0x00C5, },
     136             :         { 0x00E6, 0x00C6, },
     137             :         { 0x00E7, 0x00C7, },
     138             :         { 0x00E8, 0x00C8, },
     139             :         { 0x00E9, 0x00C9, },
     140             :         { 0x00EA, 0x00CA, },
     141             :         { 0x00EB, 0x00CB, },
     142             :         { 0x00EC, 0x00CC, },
     143             :         { 0x00ED, 0x00CD, },
     144             :         { 0x00EE, 0x00CE, },
     145             :         { 0x00EF, 0x00CF, },
     146             :         { 0x00F0, 0x00D0, },
     147             :         { 0x00F1, 0x00D1, },
     148             :         { 0x00F2, 0x00D2, },
     149             :         { 0x00F3, 0x00D3, },
     150             :         { 0x00F4, 0x00D4, },
     151             :         { 0x00F5, 0x00D5, },
     152             :         { 0x00F6, 0x00D6, },
     153             :         { 0x00F8, 0x00D8, },
     154             :         { 0x00F9, 0x00D9, },
     155             :         { 0x00FA, 0x00DA, },
     156             :         { 0x00FB, 0x00DB, },
     157             :         { 0x00FC, 0x00DC, },
     158             :         { 0x00FD, 0x00DD, },
     159             :         { 0x00FE, 0x00DE, },
     160             :         { 0x00FF, 0x0178, },
     161             :         { 0x0101, 0x0100, },
     162             :         { 0x0103, 0x0102, },
     163             :         { 0x0105, 0x0104, },
     164             :         { 0x0107, 0x0106, },
     165             :         { 0x0109, 0x0108, },
     166             :         { 0x010B, 0x010A, },
     167             :         { 0x010D, 0x010C, },
     168             :         { 0x010F, 0x010E, },
     169             :         { 0x0111, 0x0110, },
     170             :         { 0x0113, 0x0112, },
     171             :         { 0x0115, 0x0114, },
     172             :         { 0x0117, 0x0116, },
     173             :         { 0x0119, 0x0118, },
     174             :         { 0x011B, 0x011A, },
     175             :         { 0x011D, 0x011C, },
     176             :         { 0x011F, 0x011E, },
     177             :         { 0x0121, 0x0120, },
     178             :         { 0x0123, 0x0122, },
     179             :         { 0x0125, 0x0124, },
     180             :         { 0x0127, 0x0126, },
     181             :         { 0x0129, 0x0128, },
     182             :         { 0x012B, 0x012A, },
     183             :         { 0x012D, 0x012C, },
     184             :         { 0x012F, 0x012E, },
     185             :         { 0x0131, 0x0049, },
     186             :         { 0x0133, 0x0132, },
     187             :         { 0x0135, 0x0134, },
     188             :         { 0x0137, 0x0136, },
     189             :         { 0x013A, 0x0139, },
     190             :         { 0x013C, 0x013B, },
     191             :         { 0x013E, 0x013D, },
     192             :         { 0x0140, 0x013F, },
     193             :         { 0x0142, 0x0141, },
     194             :         { 0x0144, 0x0143, },
     195             :         { 0x0146, 0x0145, },
     196             :         { 0x0148, 0x0147, },
     197             :         { 0x014B, 0x014A, },
     198             :         { 0x014D, 0x014C, },
     199             :         { 0x014F, 0x014E, },
     200             :         { 0x0151, 0x0150, },
     201             :         { 0x0153, 0x0152, },
     202             :         { 0x0155, 0x0154, },
     203             :         { 0x0157, 0x0156, },
     204             :         { 0x0159, 0x0158, },
     205             :         { 0x015B, 0x015A, },
     206             :         { 0x015D, 0x015C, },
     207             :         { 0x015F, 0x015E, },
     208             :         { 0x0161, 0x0160, },
     209             :         { 0x0163, 0x0162, },
     210             :         { 0x0165, 0x0164, },
     211             :         { 0x0167, 0x0166, },
     212             :         { 0x0169, 0x0168, },
     213             :         { 0x016B, 0x016A, },
     214             :         { 0x016D, 0x016C, },
     215             :         { 0x016F, 0x016E, },
     216             :         { 0x0171, 0x0170, },
     217             :         { 0x0173, 0x0172, },
     218             :         { 0x0175, 0x0174, },
     219             :         { 0x0177, 0x0176, },
     220             :         { 0x017A, 0x0179, },
     221             :         { 0x017C, 0x017B, },
     222             :         { 0x017E, 0x017D, },
     223             :         { 0x017F, 0x0053, },
     224             :         { 0x0180, 0x0243, },
     225             :         { 0x0183, 0x0182, },
     226             :         { 0x0185, 0x0184, },
     227             :         { 0x0188, 0x0187, },
     228             :         { 0x018C, 0x018B, },
     229             :         { 0x0192, 0x0191, },
     230             :         { 0x0195, 0x01F6, },
     231             :         { 0x0199, 0x0198, },
     232             :         { 0x019A, 0x023D, },
     233             :         { 0x019E, 0x0220, },
     234             :         { 0x01A1, 0x01A0, },
     235             :         { 0x01A3, 0x01A2, },
     236             :         { 0x01A5, 0x01A4, },
     237             :         { 0x01A8, 0x01A7, },
     238             :         { 0x01AD, 0x01AC, },
     239             :         { 0x01B0, 0x01AF, },
     240             :         { 0x01B4, 0x01B3, },
     241             :         { 0x01B6, 0x01B5, },
     242             :         { 0x01B9, 0x01B8, },
     243             :         { 0x01BD, 0x01BC, },
     244             :         { 0x01BF, 0x01F7, },
     245             :         { 0x01C5, 0x01C4, },
     246             :         { 0x01C6, 0x01C4, },
     247             :         { 0x01C8, 0x01C7, },
     248             :         { 0x01C9, 0x01C7, },
     249             :         { 0x01CB, 0x01CA, },
     250             :         { 0x01CC, 0x01CA, },
     251             :         { 0x01CE, 0x01CD, },
     252             :         { 0x01D0, 0x01CF, },
     253             :         { 0x01D2, 0x01D1, },
     254             :         { 0x01D4, 0x01D3, },
     255             :         { 0x01D6, 0x01D5, },
     256             :         { 0x01D8, 0x01D7, },
     257             :         { 0x01DA, 0x01D9, },
     258             :         { 0x01DC, 0x01DB, },
     259             :         { 0x01DD, 0x018E, },
     260             :         { 0x01DF, 0x01DE, },
     261             :         { 0x01E1, 0x01E0, },
     262             :         { 0x01E3, 0x01E2, },
     263             :         { 0x01E5, 0x01E4, },
     264             :         { 0x01E7, 0x01E6, },
     265             :         { 0x01E9, 0x01E8, },
     266             :         { 0x01EB, 0x01EA, },
     267             :         { 0x01ED, 0x01EC, },
     268             :         { 0x01EF, 0x01EE, },
     269             :         { 0x01F2, 0x01F1, },
     270             :         { 0x01F3, 0x01F1, },
     271             :         { 0x01F5, 0x01F4, },
     272             :         { 0x01F9, 0x01F8, },
     273             :         { 0x01FB, 0x01FA, },
     274             :         { 0x01FD, 0x01FC, },
     275             :         { 0x01FF, 0x01FE, },
     276             :         { 0x0201, 0x0200, },
     277             :         { 0x0203, 0x0202, },
     278             :         { 0x0205, 0x0204, },
     279             :         { 0x0207, 0x0206, },
     280             :         { 0x0209, 0x0208, },
     281             :         { 0x020B, 0x020A, },
     282             :         { 0x020D, 0x020C, },
     283             :         { 0x020F, 0x020E, },
     284             :         { 0x0211, 0x0210, },
     285             :         { 0x0213, 0x0212, },
     286             :         { 0x0215, 0x0214, },
     287             :         { 0x0217, 0x0216, },
     288             :         { 0x0219, 0x0218, },
     289             :         { 0x021B, 0x021A, },
     290             :         { 0x021D, 0x021C, },
     291             :         { 0x021F, 0x021E, },
     292             :         { 0x0223, 0x0222, },
     293             :         { 0x0225, 0x0224, },
     294             :         { 0x0227, 0x0226, },
     295             :         { 0x0229, 0x0228, },
     296             :         { 0x022B, 0x022A, },
     297             :         { 0x022D, 0x022C, },
     298             :         { 0x022F, 0x022E, },
     299             :         { 0x0231, 0x0230, },
     300             :         { 0x0233, 0x0232, },
     301             :         { 0x023C, 0x023B, },
     302             :         { 0x023F, 0x2C7E, },
     303             :         { 0x0240, 0x2C7F, },
     304             :         { 0x0242, 0x0241, },
     305             :         { 0x0247, 0x0246, },
     306             :         { 0x0249, 0x0248, },
     307             :         { 0x024B, 0x024A, },
     308             :         { 0x024D, 0x024C, },
     309             :         { 0x024F, 0x024E, },
     310             :         { 0x0250, 0x2C6F, },
     311             :         { 0x0251, 0x2C6D, },
     312             :         { 0x0252, 0x2C70, },
     313             :         { 0x0253, 0x0181, },
     314             :         { 0x0254, 0x0186, },
     315             :         { 0x0256, 0x0189, },
     316             :         { 0x0257, 0x018A, },
     317             :         { 0x0259, 0x018F, },
     318             :         { 0x025B, 0x0190, },
     319             :         { 0x025C, 0xA7AB, },
     320             :         { 0x0260, 0x0193, },
     321             :         { 0x0261, 0xA7AC, },
     322             :         { 0x0263, 0x0194, },
     323             :         { 0x0265, 0xA78D, },
     324             :         { 0x0266, 0xA7AA, },
     325             :         { 0x0268, 0x0197, },
     326             :         { 0x0269, 0x0196, },
     327             :         { 0x026A, 0xA7AE, },
     328             :         { 0x026B, 0x2C62, },
     329             :         { 0x026C, 0xA7AD, },
     330             :         { 0x026F, 0x019C, },
     331             :         { 0x0271, 0x2C6E, },
     332             :         { 0x0272, 0x019D, },
     333             :         { 0x0275, 0x019F, },
     334             :         { 0x027D, 0x2C64, },
     335             :         { 0x0280, 0x01A6, },
     336             :         { 0x0282, 0xA7C5, },
     337             :         { 0x0283, 0x01A9, },
     338             :         { 0x0287, 0xA7B1, },
     339             :         { 0x0288, 0x01AE, },
     340             :         { 0x0289, 0x0244, },
     341             :         { 0x028A, 0x01B1, },
     342             :         { 0x028B, 0x01B2, },
     343             :         { 0x028C, 0x0245, },
     344             :         { 0x0292, 0x01B7, },
     345             :         { 0x029D, 0xA7B2, },
     346             :         { 0x029E, 0xA7B0, },
     347             :         { 0x0345, 0x0399, },
     348             :         { 0x0371, 0x0370, },
     349             :         { 0x0373, 0x0372, },
     350             :         { 0x0377, 0x0376, },
     351             :         { 0x037B, 0x03FD, },
     352             :         { 0x037C, 0x03FE, },
     353             :         { 0x037D, 0x03FF, },
     354             :         { 0x03AC, 0x0386, },
     355             :         { 0x03AD, 0x0388, },
     356             :         { 0x03AE, 0x0389, },
     357             :         { 0x03AF, 0x038A, },
     358             :         { 0x03B1, 0x0391, },
     359             :         { 0x03B2, 0x0392, },
     360             :         { 0x03B3, 0x0393, },
     361             :         { 0x03B4, 0x0394, },
     362             :         { 0x03B5, 0x0395, },
     363             :         { 0x03B6, 0x0396, },
     364             :         { 0x03B7, 0x0397, },
     365             :         { 0x03B8, 0x0398, },
     366             :         { 0x03B9, 0x0399, },
     367             :         { 0x03BA, 0x039A, },
     368             :         { 0x03BB, 0x039B, },
     369             :         { 0x03BC, 0x039C, },
     370             :         { 0x03BD, 0x039D, },
     371             :         { 0x03BE, 0x039E, },
     372             :         { 0x03BF, 0x039F, },
     373             :         { 0x03C0, 0x03A0, },
     374             :         { 0x03C1, 0x03A1, },
     375             :         { 0x03C2, 0x03A3, },
     376             :         { 0x03C3, 0x03A3, },
     377             :         { 0x03C4, 0x03A4, },
     378             :         { 0x03C5, 0x03A5, },
     379             :         { 0x03C6, 0x03A6, },
     380             :         { 0x03C7, 0x03A7, },
     381             :         { 0x03C8, 0x03A8, },
     382             :         { 0x03C9, 0x03A9, },
     383             :         { 0x03CA, 0x03AA, },
     384             :         { 0x03CB, 0x03AB, },
     385             :         { 0x03CC, 0x038C, },
     386             :         { 0x03CD, 0x038E, },
     387             :         { 0x03CE, 0x038F, },
     388             :         { 0x03D0, 0x0392, },
     389             :         { 0x03D1, 0x0398, },
     390             :         { 0x03D5, 0x03A6, },
     391             :         { 0x03D6, 0x03A0, },
     392             :         { 0x03D7, 0x03CF, },
     393             :         { 0x03D9, 0x03D8, },
     394             :         { 0x03DB, 0x03DA, },
     395             :         { 0x03DD, 0x03DC, },
     396             :         { 0x03DF, 0x03DE, },
     397             :         { 0x03E1, 0x03E0, },
     398             :         { 0x03E3, 0x03E2, },
     399             :         { 0x03E5, 0x03E4, },
     400             :         { 0x03E7, 0x03E6, },
     401             :         { 0x03E9, 0x03E8, },
     402             :         { 0x03EB, 0x03EA, },
     403             :         { 0x03ED, 0x03EC, },
     404             :         { 0x03EF, 0x03EE, },
     405             :         { 0x03F0, 0x039A, },
     406             :         { 0x03F1, 0x03A1, },
     407             :         { 0x03F2, 0x03F9, },
     408             :         { 0x03F3, 0x037F, },
     409             :         { 0x03F5, 0x0395, },
     410             :         { 0x03F8, 0x03F7, },
     411             :         { 0x03FB, 0x03FA, },
     412             :         { 0x0430, 0x0410, },
     413             :         { 0x0431, 0x0411, },
     414             :         { 0x0432, 0x0412, },
     415             :         { 0x0433, 0x0413, },
     416             :         { 0x0434, 0x0414, },
     417             :         { 0x0435, 0x0415, },
     418             :         { 0x0436, 0x0416, },
     419             :         { 0x0437, 0x0417, },
     420             :         { 0x0438, 0x0418, },
     421             :         { 0x0439, 0x0419, },
     422             :         { 0x043A, 0x041A, },
     423             :         { 0x043B, 0x041B, },
     424             :         { 0x043C, 0x041C, },
     425             :         { 0x043D, 0x041D, },
     426             :         { 0x043E, 0x041E, },
     427             :         { 0x043F, 0x041F, },
     428             :         { 0x0440, 0x0420, },
     429             :         { 0x0441, 0x0421, },
     430             :         { 0x0442, 0x0422, },
     431             :         { 0x0443, 0x0423, },
     432             :         { 0x0444, 0x0424, },
     433             :         { 0x0445, 0x0425, },
     434             :         { 0x0446, 0x0426, },
     435             :         { 0x0447, 0x0427, },
     436             :         { 0x0448, 0x0428, },
     437             :         { 0x0449, 0x0429, },
     438             :         { 0x044A, 0x042A, },
     439             :         { 0x044B, 0x042B, },
     440             :         { 0x044C, 0x042C, },
     441             :         { 0x044D, 0x042D, },
     442             :         { 0x044E, 0x042E, },
     443             :         { 0x044F, 0x042F, },
     444             :         { 0x0450, 0x0400, },
     445             :         { 0x0451, 0x0401, },
     446             :         { 0x0452, 0x0402, },
     447             :         { 0x0453, 0x0403, },
     448             :         { 0x0454, 0x0404, },
     449             :         { 0x0455, 0x0405, },
     450             :         { 0x0456, 0x0406, },
     451             :         { 0x0457, 0x0407, },
     452             :         { 0x0458, 0x0408, },
     453             :         { 0x0459, 0x0409, },
     454             :         { 0x045A, 0x040A, },
     455             :         { 0x045B, 0x040B, },
     456             :         { 0x045C, 0x040C, },
     457             :         { 0x045D, 0x040D, },
     458             :         { 0x045E, 0x040E, },
     459             :         { 0x045F, 0x040F, },
     460             :         { 0x0461, 0x0460, },
     461             :         { 0x0463, 0x0462, },
     462             :         { 0x0465, 0x0464, },
     463             :         { 0x0467, 0x0466, },
     464             :         { 0x0469, 0x0468, },
     465             :         { 0x046B, 0x046A, },
     466             :         { 0x046D, 0x046C, },
     467             :         { 0x046F, 0x046E, },
     468             :         { 0x0471, 0x0470, },
     469             :         { 0x0473, 0x0472, },
     470             :         { 0x0475, 0x0474, },
     471             :         { 0x0477, 0x0476, },
     472             :         { 0x0479, 0x0478, },
     473             :         { 0x047B, 0x047A, },
     474             :         { 0x047D, 0x047C, },
     475             :         { 0x047F, 0x047E, },
     476             :         { 0x0481, 0x0480, },
     477             :         { 0x048B, 0x048A, },
     478             :         { 0x048D, 0x048C, },
     479             :         { 0x048F, 0x048E, },
     480             :         { 0x0491, 0x0490, },
     481             :         { 0x0493, 0x0492, },
     482             :         { 0x0495, 0x0494, },
     483             :         { 0x0497, 0x0496, },
     484             :         { 0x0499, 0x0498, },
     485             :         { 0x049B, 0x049A, },
     486             :         { 0x049D, 0x049C, },
     487             :         { 0x049F, 0x049E, },
     488             :         { 0x04A1, 0x04A0, },
     489             :         { 0x04A3, 0x04A2, },
     490             :         { 0x04A5, 0x04A4, },
     491             :         { 0x04A7, 0x04A6, },
     492             :         { 0x04A9, 0x04A8, },
     493             :         { 0x04AB, 0x04AA, },
     494             :         { 0x04AD, 0x04AC, },
     495             :         { 0x04AF, 0x04AE, },
     496             :         { 0x04B1, 0x04B0, },
     497             :         { 0x04B3, 0x04B2, },
     498             :         { 0x04B5, 0x04B4, },
     499             :         { 0x04B7, 0x04B6, },
     500             :         { 0x04B9, 0x04B8, },
     501             :         { 0x04BB, 0x04BA, },
     502             :         { 0x04BD, 0x04BC, },
     503             :         { 0x04BF, 0x04BE, },
     504             :         { 0x04C2, 0x04C1, },
     505             :         { 0x04C4, 0x04C3, },
     506             :         { 0x04C6, 0x04C5, },
     507             :         { 0x04C8, 0x04C7, },
     508             :         { 0x04CA, 0x04C9, },
     509             :         { 0x04CC, 0x04CB, },
     510             :         { 0x04CE, 0x04CD, },
     511             :         { 0x04CF, 0x04C0, },
     512             :         { 0x04D1, 0x04D0, },
     513             :         { 0x04D3, 0x04D2, },
     514             :         { 0x04D5, 0x04D4, },
     515             :         { 0x04D7, 0x04D6, },
     516             :         { 0x04D9, 0x04D8, },
     517             :         { 0x04DB, 0x04DA, },
     518             :         { 0x04DD, 0x04DC, },
     519             :         { 0x04DF, 0x04DE, },
     520             :         { 0x04E1, 0x04E0, },
     521             :         { 0x04E3, 0x04E2, },
     522             :         { 0x04E5, 0x04E4, },
     523             :         { 0x04E7, 0x04E6, },
     524             :         { 0x04E9, 0x04E8, },
     525             :         { 0x04EB, 0x04EA, },
     526             :         { 0x04ED, 0x04EC, },
     527             :         { 0x04EF, 0x04EE, },
     528             :         { 0x04F1, 0x04F0, },
     529             :         { 0x04F3, 0x04F2, },
     530             :         { 0x04F5, 0x04F4, },
     531             :         { 0x04F7, 0x04F6, },
     532             :         { 0x04F9, 0x04F8, },
     533             :         { 0x04FB, 0x04FA, },
     534             :         { 0x04FD, 0x04FC, },
     535             :         { 0x04FF, 0x04FE, },
     536             :         { 0x0501, 0x0500, },
     537             :         { 0x0503, 0x0502, },
     538             :         { 0x0505, 0x0504, },
     539             :         { 0x0507, 0x0506, },
     540             :         { 0x0509, 0x0508, },
     541             :         { 0x050B, 0x050A, },
     542             :         { 0x050D, 0x050C, },
     543             :         { 0x050F, 0x050E, },
     544             :         { 0x0511, 0x0510, },
     545             :         { 0x0513, 0x0512, },
     546             :         { 0x0515, 0x0514, },
     547             :         { 0x0517, 0x0516, },
     548             :         { 0x0519, 0x0518, },
     549             :         { 0x051B, 0x051A, },
     550             :         { 0x051D, 0x051C, },
     551             :         { 0x051F, 0x051E, },
     552             :         { 0x0521, 0x0520, },
     553             :         { 0x0523, 0x0522, },
     554             :         { 0x0525, 0x0524, },
     555             :         { 0x0527, 0x0526, },
     556             :         { 0x0529, 0x0528, },
     557             :         { 0x052B, 0x052A, },
     558             :         { 0x052D, 0x052C, },
     559             :         { 0x052F, 0x052E, },
     560             :         { 0x0561, 0x0531, },
     561             :         { 0x0562, 0x0532, },
     562             :         { 0x0563, 0x0533, },
     563             :         { 0x0564, 0x0534, },
     564             :         { 0x0565, 0x0535, },
     565             :         { 0x0566, 0x0536, },
     566             :         { 0x0567, 0x0537, },
     567             :         { 0x0568, 0x0538, },
     568             :         { 0x0569, 0x0539, },
     569             :         { 0x056A, 0x053A, },
     570             :         { 0x056B, 0x053B, },
     571             :         { 0x056C, 0x053C, },
     572             :         { 0x056D, 0x053D, },
     573             :         { 0x056E, 0x053E, },
     574             :         { 0x056F, 0x053F, },
     575             :         { 0x0570, 0x0540, },
     576             :         { 0x0571, 0x0541, },
     577             :         { 0x0572, 0x0542, },
     578             :         { 0x0573, 0x0543, },
     579             :         { 0x0574, 0x0544, },
     580             :         { 0x0575, 0x0545, },
     581             :         { 0x0576, 0x0546, },
     582             :         { 0x0577, 0x0547, },
     583             :         { 0x0578, 0x0548, },
     584             :         { 0x0579, 0x0549, },
     585             :         { 0x057A, 0x054A, },
     586             :         { 0x057B, 0x054B, },
     587             :         { 0x057C, 0x054C, },
     588             :         { 0x057D, 0x054D, },
     589             :         { 0x057E, 0x054E, },
     590             :         { 0x057F, 0x054F, },
     591             :         { 0x0580, 0x0550, },
     592             :         { 0x0581, 0x0551, },
     593             :         { 0x0582, 0x0552, },
     594             :         { 0x0583, 0x0553, },
     595             :         { 0x0584, 0x0554, },
     596             :         { 0x0585, 0x0555, },
     597             :         { 0x0586, 0x0556, },
     598             :         { 0x10D0, 0x1C90, },
     599             :         { 0x10D1, 0x1C91, },
     600             :         { 0x10D2, 0x1C92, },
     601             :         { 0x10D3, 0x1C93, },
     602             :         { 0x10D4, 0x1C94, },
     603             :         { 0x10D5, 0x1C95, },
     604             :         { 0x10D6, 0x1C96, },
     605             :         { 0x10D7, 0x1C97, },
     606             :         { 0x10D8, 0x1C98, },
     607             :         { 0x10D9, 0x1C99, },
     608             :         { 0x10DA, 0x1C9A, },
     609             :         { 0x10DB, 0x1C9B, },
     610             :         { 0x10DC, 0x1C9C, },
     611             :         { 0x10DD, 0x1C9D, },
     612             :         { 0x10DE, 0x1C9E, },
     613             :         { 0x10DF, 0x1C9F, },
     614             :         { 0x10E0, 0x1CA0, },
     615             :         { 0x10E1, 0x1CA1, },
     616             :         { 0x10E2, 0x1CA2, },
     617             :         { 0x10E3, 0x1CA3, },
     618             :         { 0x10E4, 0x1CA4, },
     619             :         { 0x10E5, 0x1CA5, },
     620             :         { 0x10E6, 0x1CA6, },
     621             :         { 0x10E7, 0x1CA7, },
     622             :         { 0x10E8, 0x1CA8, },
     623             :         { 0x10E9, 0x1CA9, },
     624             :         { 0x10EA, 0x1CAA, },
     625             :         { 0x10EB, 0x1CAB, },
     626             :         { 0x10EC, 0x1CAC, },
     627             :         { 0x10ED, 0x1CAD, },
     628             :         { 0x10EE, 0x1CAE, },
     629             :         { 0x10EF, 0x1CAF, },
     630             :         { 0x10F0, 0x1CB0, },
     631             :         { 0x10F1, 0x1CB1, },
     632             :         { 0x10F2, 0x1CB2, },
     633             :         { 0x10F3, 0x1CB3, },
     634             :         { 0x10F4, 0x1CB4, },
     635             :         { 0x10F5, 0x1CB5, },
     636             :         { 0x10F6, 0x1CB6, },
     637             :         { 0x10F7, 0x1CB7, },
     638             :         { 0x10F8, 0x1CB8, },
     639             :         { 0x10F9, 0x1CB9, },
     640             :         { 0x10FA, 0x1CBA, },
     641             :         { 0x10FD, 0x1CBD, },
     642             :         { 0x10FE, 0x1CBE, },
     643             :         { 0x10FF, 0x1CBF, },
     644             :         { 0x13F8, 0x13F0, },
     645             :         { 0x13F9, 0x13F1, },
     646             :         { 0x13FA, 0x13F2, },
     647             :         { 0x13FB, 0x13F3, },
     648             :         { 0x13FC, 0x13F4, },
     649             :         { 0x13FD, 0x13F5, },
     650             :         { 0x1C80, 0x0412, },
     651             :         { 0x1C81, 0x0414, },
     652             :         { 0x1C82, 0x041E, },
     653             :         { 0x1C83, 0x0421, },
     654             :         { 0x1C84, 0x0422, },
     655             :         { 0x1C85, 0x0422, },
     656             :         { 0x1C86, 0x042A, },
     657             :         { 0x1C87, 0x0462, },
     658             :         { 0x1C88, 0xA64A, },
     659             :         { 0x1D79, 0xA77D, },
     660             :         { 0x1D7D, 0x2C63, },
     661             :         { 0x1D8E, 0xA7C6, },
     662             :         { 0x1E01, 0x1E00, },
     663             :         { 0x1E03, 0x1E02, },
     664             :         { 0x1E05, 0x1E04, },
     665             :         { 0x1E07, 0x1E06, },
     666             :         { 0x1E09, 0x1E08, },
     667             :         { 0x1E0B, 0x1E0A, },
     668             :         { 0x1E0D, 0x1E0C, },
     669             :         { 0x1E0F, 0x1E0E, },
     670             :         { 0x1E11, 0x1E10, },
     671             :         { 0x1E13, 0x1E12, },
     672             :         { 0x1E15, 0x1E14, },
     673             :         { 0x1E17, 0x1E16, },
     674             :         { 0x1E19, 0x1E18, },
     675             :         { 0x1E1B, 0x1E1A, },
     676             :         { 0x1E1D, 0x1E1C, },
     677             :         { 0x1E1F, 0x1E1E, },
     678             :         { 0x1E21, 0x1E20, },
     679             :         { 0x1E23, 0x1E22, },
     680             :         { 0x1E25, 0x1E24, },
     681             :         { 0x1E27, 0x1E26, },
     682             :         { 0x1E29, 0x1E28, },
     683             :         { 0x1E2B, 0x1E2A, },
     684             :         { 0x1E2D, 0x1E2C, },
     685             :         { 0x1E2F, 0x1E2E, },
     686             :         { 0x1E31, 0x1E30, },
     687             :         { 0x1E33, 0x1E32, },
     688             :         { 0x1E35, 0x1E34, },
     689             :         { 0x1E37, 0x1E36, },
     690             :         { 0x1E39, 0x1E38, },
     691             :         { 0x1E3B, 0x1E3A, },
     692             :         { 0x1E3D, 0x1E3C, },
     693             :         { 0x1E3F, 0x1E3E, },
     694             :         { 0x1E41, 0x1E40, },
     695             :         { 0x1E43, 0x1E42, },
     696             :         { 0x1E45, 0x1E44, },
     697             :         { 0x1E47, 0x1E46, },
     698             :         { 0x1E49, 0x1E48, },
     699             :         { 0x1E4B, 0x1E4A, },
     700             :         { 0x1E4D, 0x1E4C, },
     701             :         { 0x1E4F, 0x1E4E, },
     702             :         { 0x1E51, 0x1E50, },
     703             :         { 0x1E53, 0x1E52, },
     704             :         { 0x1E55, 0x1E54, },
     705             :         { 0x1E57, 0x1E56, },
     706             :         { 0x1E59, 0x1E58, },
     707             :         { 0x1E5B, 0x1E5A, },
     708             :         { 0x1E5D, 0x1E5C, },
     709             :         { 0x1E5F, 0x1E5E, },
     710             :         { 0x1E61, 0x1E60, },
     711             :         { 0x1E63, 0x1E62, },
     712             :         { 0x1E65, 0x1E64, },
     713             :         { 0x1E67, 0x1E66, },
     714             :         { 0x1E69, 0x1E68, },
     715             :         { 0x1E6B, 0x1E6A, },
     716             :         { 0x1E6D, 0x1E6C, },
     717             :         { 0x1E6F, 0x1E6E, },
     718             :         { 0x1E71, 0x1E70, },
     719             :         { 0x1E73, 0x1E72, },
     720             :         { 0x1E75, 0x1E74, },
     721             :         { 0x1E77, 0x1E76, },
     722             :         { 0x1E79, 0x1E78, },
     723             :         { 0x1E7B, 0x1E7A, },
     724             :         { 0x1E7D, 0x1E7C, },
     725             :         { 0x1E7F, 0x1E7E, },
     726             :         { 0x1E81, 0x1E80, },
     727             :         { 0x1E83, 0x1E82, },
     728             :         { 0x1E85, 0x1E84, },
     729             :         { 0x1E87, 0x1E86, },
     730             :         { 0x1E89, 0x1E88, },
     731             :         { 0x1E8B, 0x1E8A, },
     732             :         { 0x1E8D, 0x1E8C, },
     733             :         { 0x1E8F, 0x1E8E, },
     734             :         { 0x1E91, 0x1E90, },
     735             :         { 0x1E93, 0x1E92, },
     736             :         { 0x1E95, 0x1E94, },
     737             :         { 0x1E9B, 0x1E60, },
     738             :         { 0x1EA1, 0x1EA0, },
     739             :         { 0x1EA3, 0x1EA2, },
     740             :         { 0x1EA5, 0x1EA4, },
     741             :         { 0x1EA7, 0x1EA6, },
     742             :         { 0x1EA9, 0x1EA8, },
     743             :         { 0x1EAB, 0x1EAA, },
     744             :         { 0x1EAD, 0x1EAC, },
     745             :         { 0x1EAF, 0x1EAE, },
     746             :         { 0x1EB1, 0x1EB0, },
     747             :         { 0x1EB3, 0x1EB2, },
     748             :         { 0x1EB5, 0x1EB4, },
     749             :         { 0x1EB7, 0x1EB6, },
     750             :         { 0x1EB9, 0x1EB8, },
     751             :         { 0x1EBB, 0x1EBA, },
     752             :         { 0x1EBD, 0x1EBC, },
     753             :         { 0x1EBF, 0x1EBE, },
     754             :         { 0x1EC1, 0x1EC0, },
     755             :         { 0x1EC3, 0x1EC2, },
     756             :         { 0x1EC5, 0x1EC4, },
     757             :         { 0x1EC7, 0x1EC6, },
     758             :         { 0x1EC9, 0x1EC8, },
     759             :         { 0x1ECB, 0x1ECA, },
     760             :         { 0x1ECD, 0x1ECC, },
     761             :         { 0x1ECF, 0x1ECE, },
     762             :         { 0x1ED1, 0x1ED0, },
     763             :         { 0x1ED3, 0x1ED2, },
     764             :         { 0x1ED5, 0x1ED4, },
     765             :         { 0x1ED7, 0x1ED6, },
     766             :         { 0x1ED9, 0x1ED8, },
     767             :         { 0x1EDB, 0x1EDA, },
     768             :         { 0x1EDD, 0x1EDC, },
     769             :         { 0x1EDF, 0x1EDE, },
     770             :         { 0x1EE1, 0x1EE0, },
     771             :         { 0x1EE3, 0x1EE2, },
     772             :         { 0x1EE5, 0x1EE4, },
     773             :         { 0x1EE7, 0x1EE6, },
     774             :         { 0x1EE9, 0x1EE8, },
     775             :         { 0x1EEB, 0x1EEA, },
     776             :         { 0x1EED, 0x1EEC, },
     777             :         { 0x1EEF, 0x1EEE, },
     778             :         { 0x1EF1, 0x1EF0, },
     779             :         { 0x1EF3, 0x1EF2, },
     780             :         { 0x1EF5, 0x1EF4, },
     781             :         { 0x1EF7, 0x1EF6, },
     782             :         { 0x1EF9, 0x1EF8, },
     783             :         { 0x1EFB, 0x1EFA, },
     784             :         { 0x1EFD, 0x1EFC, },
     785             :         { 0x1EFF, 0x1EFE, },
     786             :         { 0x1F00, 0x1F08, },
     787             :         { 0x1F01, 0x1F09, },
     788             :         { 0x1F02, 0x1F0A, },
     789             :         { 0x1F03, 0x1F0B, },
     790             :         { 0x1F04, 0x1F0C, },
     791             :         { 0x1F05, 0x1F0D, },
     792             :         { 0x1F06, 0x1F0E, },
     793             :         { 0x1F07, 0x1F0F, },
     794             :         { 0x1F10, 0x1F18, },
     795             :         { 0x1F11, 0x1F19, },
     796             :         { 0x1F12, 0x1F1A, },
     797             :         { 0x1F13, 0x1F1B, },
     798             :         { 0x1F14, 0x1F1C, },
     799             :         { 0x1F15, 0x1F1D, },
     800             :         { 0x1F20, 0x1F28, },
     801             :         { 0x1F21, 0x1F29, },
     802             :         { 0x1F22, 0x1F2A, },
     803             :         { 0x1F23, 0x1F2B, },
     804             :         { 0x1F24, 0x1F2C, },
     805             :         { 0x1F25, 0x1F2D, },
     806             :         { 0x1F26, 0x1F2E, },
     807             :         { 0x1F27, 0x1F2F, },
     808             :         { 0x1F30, 0x1F38, },
     809             :         { 0x1F31, 0x1F39, },
     810             :         { 0x1F32, 0x1F3A, },
     811             :         { 0x1F33, 0x1F3B, },
     812             :         { 0x1F34, 0x1F3C, },
     813             :         { 0x1F35, 0x1F3D, },
     814             :         { 0x1F36, 0x1F3E, },
     815             :         { 0x1F37, 0x1F3F, },
     816             :         { 0x1F40, 0x1F48, },
     817             :         { 0x1F41, 0x1F49, },
     818             :         { 0x1F42, 0x1F4A, },
     819             :         { 0x1F43, 0x1F4B, },
     820             :         { 0x1F44, 0x1F4C, },
     821             :         { 0x1F45, 0x1F4D, },
     822             :         { 0x1F51, 0x1F59, },
     823             :         { 0x1F53, 0x1F5B, },
     824             :         { 0x1F55, 0x1F5D, },
     825             :         { 0x1F57, 0x1F5F, },
     826             :         { 0x1F60, 0x1F68, },
     827             :         { 0x1F61, 0x1F69, },
     828             :         { 0x1F62, 0x1F6A, },
     829             :         { 0x1F63, 0x1F6B, },
     830             :         { 0x1F64, 0x1F6C, },
     831             :         { 0x1F65, 0x1F6D, },
     832             :         { 0x1F66, 0x1F6E, },
     833             :         { 0x1F67, 0x1F6F, },
     834             :         { 0x1F70, 0x1FBA, },
     835             :         { 0x1F71, 0x1FBB, },
     836             :         { 0x1F72, 0x1FC8, },
     837             :         { 0x1F73, 0x1FC9, },
     838             :         { 0x1F74, 0x1FCA, },
     839             :         { 0x1F75, 0x1FCB, },
     840             :         { 0x1F76, 0x1FDA, },
     841             :         { 0x1F77, 0x1FDB, },
     842             :         { 0x1F78, 0x1FF8, },
     843             :         { 0x1F79, 0x1FF9, },
     844             :         { 0x1F7A, 0x1FEA, },
     845             :         { 0x1F7B, 0x1FEB, },
     846             :         { 0x1F7C, 0x1FFA, },
     847             :         { 0x1F7D, 0x1FFB, },
     848             :         { 0x1F80, 0x1F88, },
     849             :         { 0x1F81, 0x1F89, },
     850             :         { 0x1F82, 0x1F8A, },
     851             :         { 0x1F83, 0x1F8B, },
     852             :         { 0x1F84, 0x1F8C, },
     853             :         { 0x1F85, 0x1F8D, },
     854             :         { 0x1F86, 0x1F8E, },
     855             :         { 0x1F87, 0x1F8F, },
     856             :         { 0x1F90, 0x1F98, },
     857             :         { 0x1F91, 0x1F99, },
     858             :         { 0x1F92, 0x1F9A, },
     859             :         { 0x1F93, 0x1F9B, },
     860             :         { 0x1F94, 0x1F9C, },
     861             :         { 0x1F95, 0x1F9D, },
     862             :         { 0x1F96, 0x1F9E, },
     863             :         { 0x1F97, 0x1F9F, },
     864             :         { 0x1FA0, 0x1FA8, },
     865             :         { 0x1FA1, 0x1FA9, },
     866             :         { 0x1FA2, 0x1FAA, },
     867             :         { 0x1FA3, 0x1FAB, },
     868             :         { 0x1FA4, 0x1FAC, },
     869             :         { 0x1FA5, 0x1FAD, },
     870             :         { 0x1FA6, 0x1FAE, },
     871             :         { 0x1FA7, 0x1FAF, },
     872             :         { 0x1FB0, 0x1FB8, },
     873             :         { 0x1FB1, 0x1FB9, },
     874             :         { 0x1FB3, 0x1FBC, },
     875             :         { 0x1FBE, 0x0399, },
     876             :         { 0x1FC3, 0x1FCC, },
     877             :         { 0x1FD0, 0x1FD8, },
     878             :         { 0x1FD1, 0x1FD9, },
     879             :         { 0x1FE0, 0x1FE8, },
     880             :         { 0x1FE1, 0x1FE9, },
     881             :         { 0x1FE5, 0x1FEC, },
     882             :         { 0x1FF3, 0x1FFC, },
     883             :         { 0x214E, 0x2132, },
     884             :         { 0x2170, 0x2160, },
     885             :         { 0x2171, 0x2161, },
     886             :         { 0x2172, 0x2162, },
     887             :         { 0x2173, 0x2163, },
     888             :         { 0x2174, 0x2164, },
     889             :         { 0x2175, 0x2165, },
     890             :         { 0x2176, 0x2166, },
     891             :         { 0x2177, 0x2167, },
     892             :         { 0x2178, 0x2168, },
     893             :         { 0x2179, 0x2169, },
     894             :         { 0x217A, 0x216A, },
     895             :         { 0x217B, 0x216B, },
     896             :         { 0x217C, 0x216C, },
     897             :         { 0x217D, 0x216D, },
     898             :         { 0x217E, 0x216E, },
     899             :         { 0x217F, 0x216F, },
     900             :         { 0x2184, 0x2183, },
     901             :         { 0x24D0, 0x24B6, },
     902             :         { 0x24D1, 0x24B7, },
     903             :         { 0x24D2, 0x24B8, },
     904             :         { 0x24D3, 0x24B9, },
     905             :         { 0x24D4, 0x24BA, },
     906             :         { 0x24D5, 0x24BB, },
     907             :         { 0x24D6, 0x24BC, },
     908             :         { 0x24D7, 0x24BD, },
     909             :         { 0x24D8, 0x24BE, },
     910             :         { 0x24D9, 0x24BF, },
     911             :         { 0x24DA, 0x24C0, },
     912             :         { 0x24DB, 0x24C1, },
     913             :         { 0x24DC, 0x24C2, },
     914             :         { 0x24DD, 0x24C3, },
     915             :         { 0x24DE, 0x24C4, },
     916             :         { 0x24DF, 0x24C5, },
     917             :         { 0x24E0, 0x24C6, },
     918             :         { 0x24E1, 0x24C7, },
     919             :         { 0x24E2, 0x24C8, },
     920             :         { 0x24E3, 0x24C9, },
     921             :         { 0x24E4, 0x24CA, },
     922             :         { 0x24E5, 0x24CB, },
     923             :         { 0x24E6, 0x24CC, },
     924             :         { 0x24E7, 0x24CD, },
     925             :         { 0x24E8, 0x24CE, },
     926             :         { 0x24E9, 0x24CF, },
     927             :         { 0x2C30, 0x2C00, },
     928             :         { 0x2C31, 0x2C01, },
     929             :         { 0x2C32, 0x2C02, },
     930             :         { 0x2C33, 0x2C03, },
     931             :         { 0x2C34, 0x2C04, },
     932             :         { 0x2C35, 0x2C05, },
     933             :         { 0x2C36, 0x2C06, },
     934             :         { 0x2C37, 0x2C07, },
     935             :         { 0x2C38, 0x2C08, },
     936             :         { 0x2C39, 0x2C09, },
     937             :         { 0x2C3A, 0x2C0A, },
     938             :         { 0x2C3B, 0x2C0B, },
     939             :         { 0x2C3C, 0x2C0C, },
     940             :         { 0x2C3D, 0x2C0D, },
     941             :         { 0x2C3E, 0x2C0E, },
     942             :         { 0x2C3F, 0x2C0F, },
     943             :         { 0x2C40, 0x2C10, },
     944             :         { 0x2C41, 0x2C11, },
     945             :         { 0x2C42, 0x2C12, },
     946             :         { 0x2C43, 0x2C13, },
     947             :         { 0x2C44, 0x2C14, },
     948             :         { 0x2C45, 0x2C15, },
     949             :         { 0x2C46, 0x2C16, },
     950             :         { 0x2C47, 0x2C17, },
     951             :         { 0x2C48, 0x2C18, },
     952             :         { 0x2C49, 0x2C19, },
     953             :         { 0x2C4A, 0x2C1A, },
     954             :         { 0x2C4B, 0x2C1B, },
     955             :         { 0x2C4C, 0x2C1C, },
     956             :         { 0x2C4D, 0x2C1D, },
     957             :         { 0x2C4E, 0x2C1E, },
     958             :         { 0x2C4F, 0x2C1F, },
     959             :         { 0x2C50, 0x2C20, },
     960             :         { 0x2C51, 0x2C21, },
     961             :         { 0x2C52, 0x2C22, },
     962             :         { 0x2C53, 0x2C23, },
     963             :         { 0x2C54, 0x2C24, },
     964             :         { 0x2C55, 0x2C25, },
     965             :         { 0x2C56, 0x2C26, },
     966             :         { 0x2C57, 0x2C27, },
     967             :         { 0x2C58, 0x2C28, },
     968             :         { 0x2C59, 0x2C29, },
     969             :         { 0x2C5A, 0x2C2A, },
     970             :         { 0x2C5B, 0x2C2B, },
     971             :         { 0x2C5C, 0x2C2C, },
     972             :         { 0x2C5D, 0x2C2D, },
     973             :         { 0x2C5E, 0x2C2E, },
     974             :         { 0x2C61, 0x2C60, },
     975             :         { 0x2C65, 0x023A, },
     976             :         { 0x2C66, 0x023E, },
     977             :         { 0x2C68, 0x2C67, },
     978             :         { 0x2C6A, 0x2C69, },
     979             :         { 0x2C6C, 0x2C6B, },
     980             :         { 0x2C73, 0x2C72, },
     981             :         { 0x2C76, 0x2C75, },
     982             :         { 0x2C81, 0x2C80, },
     983             :         { 0x2C83, 0x2C82, },
     984             :         { 0x2C85, 0x2C84, },
     985             :         { 0x2C87, 0x2C86, },
     986             :         { 0x2C89, 0x2C88, },
     987             :         { 0x2C8B, 0x2C8A, },
     988             :         { 0x2C8D, 0x2C8C, },
     989             :         { 0x2C8F, 0x2C8E, },
     990             :         { 0x2C91, 0x2C90, },
     991             :         { 0x2C93, 0x2C92, },
     992             :         { 0x2C95, 0x2C94, },
     993             :         { 0x2C97, 0x2C96, },
     994             :         { 0x2C99, 0x2C98, },
     995             :         { 0x2C9B, 0x2C9A, },
     996             :         { 0x2C9D, 0x2C9C, },
     997             :         { 0x2C9F, 0x2C9E, },
     998             :         { 0x2CA1, 0x2CA0, },
     999             :         { 0x2CA3, 0x2CA2, },
    1000             :         { 0x2CA5, 0x2CA4, },
    1001             :         { 0x2CA7, 0x2CA6, },
    1002             :         { 0x2CA9, 0x2CA8, },
    1003             :         { 0x2CAB, 0x2CAA, },
    1004             :         { 0x2CAD, 0x2CAC, },
    1005             :         { 0x2CAF, 0x2CAE, },
    1006             :         { 0x2CB1, 0x2CB0, },
    1007             :         { 0x2CB3, 0x2CB2, },
    1008             :         { 0x2CB5, 0x2CB4, },
    1009             :         { 0x2CB7, 0x2CB6, },
    1010             :         { 0x2CB9, 0x2CB8, },
    1011             :         { 0x2CBB, 0x2CBA, },
    1012             :         { 0x2CBD, 0x2CBC, },
    1013             :         { 0x2CBF, 0x2CBE, },
    1014             :         { 0x2CC1, 0x2CC0, },
    1015             :         { 0x2CC3, 0x2CC2, },
    1016             :         { 0x2CC5, 0x2CC4, },
    1017             :         { 0x2CC7, 0x2CC6, },
    1018             :         { 0x2CC9, 0x2CC8, },
    1019             :         { 0x2CCB, 0x2CCA, },
    1020             :         { 0x2CCD, 0x2CCC, },
    1021             :         { 0x2CCF, 0x2CCE, },
    1022             :         { 0x2CD1, 0x2CD0, },
    1023             :         { 0x2CD3, 0x2CD2, },
    1024             :         { 0x2CD5, 0x2CD4, },
    1025             :         { 0x2CD7, 0x2CD6, },
    1026             :         { 0x2CD9, 0x2CD8, },
    1027             :         { 0x2CDB, 0x2CDA, },
    1028             :         { 0x2CDD, 0x2CDC, },
    1029             :         { 0x2CDF, 0x2CDE, },
    1030             :         { 0x2CE1, 0x2CE0, },
    1031             :         { 0x2CE3, 0x2CE2, },
    1032             :         { 0x2CEC, 0x2CEB, },
    1033             :         { 0x2CEE, 0x2CED, },
    1034             :         { 0x2CF3, 0x2CF2, },
    1035             :         { 0x2D00, 0x10A0, },
    1036             :         { 0x2D01, 0x10A1, },
    1037             :         { 0x2D02, 0x10A2, },
    1038             :         { 0x2D03, 0x10A3, },
    1039             :         { 0x2D04, 0x10A4, },
    1040             :         { 0x2D05, 0x10A5, },
    1041             :         { 0x2D06, 0x10A6, },
    1042             :         { 0x2D07, 0x10A7, },
    1043             :         { 0x2D08, 0x10A8, },
    1044             :         { 0x2D09, 0x10A9, },
    1045             :         { 0x2D0A, 0x10AA, },
    1046             :         { 0x2D0B, 0x10AB, },
    1047             :         { 0x2D0C, 0x10AC, },
    1048             :         { 0x2D0D, 0x10AD, },
    1049             :         { 0x2D0E, 0x10AE, },
    1050             :         { 0x2D0F, 0x10AF, },
    1051             :         { 0x2D10, 0x10B0, },
    1052             :         { 0x2D11, 0x10B1, },
    1053             :         { 0x2D12, 0x10B2, },
    1054             :         { 0x2D13, 0x10B3, },
    1055             :         { 0x2D14, 0x10B4, },
    1056             :         { 0x2D15, 0x10B5, },
    1057             :         { 0x2D16, 0x10B6, },
    1058             :         { 0x2D17, 0x10B7, },
    1059             :         { 0x2D18, 0x10B8, },
    1060             :         { 0x2D19, 0x10B9, },
    1061             :         { 0x2D1A, 0x10BA, },
    1062             :         { 0x2D1B, 0x10BB, },
    1063             :         { 0x2D1C, 0x10BC, },
    1064             :         { 0x2D1D, 0x10BD, },
    1065             :         { 0x2D1E, 0x10BE, },
    1066             :         { 0x2D1F, 0x10BF, },
    1067             :         { 0x2D20, 0x10C0, },
    1068             :         { 0x2D21, 0x10C1, },
    1069             :         { 0x2D22, 0x10C2, },
    1070             :         { 0x2D23, 0x10C3, },
    1071             :         { 0x2D24, 0x10C4, },
    1072             :         { 0x2D25, 0x10C5, },
    1073             :         { 0x2D27, 0x10C7, },
    1074             :         { 0x2D2D, 0x10CD, },
    1075             :         { 0xA641, 0xA640, },
    1076             :         { 0xA643, 0xA642, },
    1077             :         { 0xA645, 0xA644, },
    1078             :         { 0xA647, 0xA646, },
    1079             :         { 0xA649, 0xA648, },
    1080             :         { 0xA64B, 0xA64A, },
    1081             :         { 0xA64D, 0xA64C, },
    1082             :         { 0xA64F, 0xA64E, },
    1083             :         { 0xA651, 0xA650, },
    1084             :         { 0xA653, 0xA652, },
    1085             :         { 0xA655, 0xA654, },
    1086             :         { 0xA657, 0xA656, },
    1087             :         { 0xA659, 0xA658, },
    1088             :         { 0xA65B, 0xA65A, },
    1089             :         { 0xA65D, 0xA65C, },
    1090             :         { 0xA65F, 0xA65E, },
    1091             :         { 0xA661, 0xA660, },
    1092             :         { 0xA663, 0xA662, },
    1093             :         { 0xA665, 0xA664, },
    1094             :         { 0xA667, 0xA666, },
    1095             :         { 0xA669, 0xA668, },
    1096             :         { 0xA66B, 0xA66A, },
    1097             :         { 0xA66D, 0xA66C, },
    1098             :         { 0xA681, 0xA680, },
    1099             :         { 0xA683, 0xA682, },
    1100             :         { 0xA685, 0xA684, },
    1101             :         { 0xA687, 0xA686, },
    1102             :         { 0xA689, 0xA688, },
    1103             :         { 0xA68B, 0xA68A, },
    1104             :         { 0xA68D, 0xA68C, },
    1105             :         { 0xA68F, 0xA68E, },
    1106             :         { 0xA691, 0xA690, },
    1107             :         { 0xA693, 0xA692, },
    1108             :         { 0xA695, 0xA694, },
    1109             :         { 0xA697, 0xA696, },
    1110             :         { 0xA699, 0xA698, },
    1111             :         { 0xA69B, 0xA69A, },
    1112             :         { 0xA723, 0xA722, },
    1113             :         { 0xA725, 0xA724, },
    1114             :         { 0xA727, 0xA726, },
    1115             :         { 0xA729, 0xA728, },
    1116             :         { 0xA72B, 0xA72A, },
    1117             :         { 0xA72D, 0xA72C, },
    1118             :         { 0xA72F, 0xA72E, },
    1119             :         { 0xA733, 0xA732, },
    1120             :         { 0xA735, 0xA734, },
    1121             :         { 0xA737, 0xA736, },
    1122             :         { 0xA739, 0xA738, },
    1123             :         { 0xA73B, 0xA73A, },
    1124             :         { 0xA73D, 0xA73C, },
    1125             :         { 0xA73F, 0xA73E, },
    1126             :         { 0xA741, 0xA740, },
    1127             :         { 0xA743, 0xA742, },
    1128             :         { 0xA745, 0xA744, },
    1129             :         { 0xA747, 0xA746, },
    1130             :         { 0xA749, 0xA748, },
    1131             :         { 0xA74B, 0xA74A, },
    1132             :         { 0xA74D, 0xA74C, },
    1133             :         { 0xA74F, 0xA74E, },
    1134             :         { 0xA751, 0xA750, },
    1135             :         { 0xA753, 0xA752, },
    1136             :         { 0xA755, 0xA754, },
    1137             :         { 0xA757, 0xA756, },
    1138             :         { 0xA759, 0xA758, },
    1139             :         { 0xA75B, 0xA75A, },
    1140             :         { 0xA75D, 0xA75C, },
    1141             :         { 0xA75F, 0xA75E, },
    1142             :         { 0xA761, 0xA760, },
    1143             :         { 0xA763, 0xA762, },
    1144             :         { 0xA765, 0xA764, },
    1145             :         { 0xA767, 0xA766, },
    1146             :         { 0xA769, 0xA768, },
    1147             :         { 0xA76B, 0xA76A, },
    1148             :         { 0xA76D, 0xA76C, },
    1149             :         { 0xA76F, 0xA76E, },
    1150             :         { 0xA77A, 0xA779, },
    1151             :         { 0xA77C, 0xA77B, },
    1152             :         { 0xA77F, 0xA77E, },
    1153             :         { 0xA781, 0xA780, },
    1154             :         { 0xA783, 0xA782, },
    1155             :         { 0xA785, 0xA784, },
    1156             :         { 0xA787, 0xA786, },
    1157             :         { 0xA78C, 0xA78B, },
    1158             :         { 0xA791, 0xA790, },
    1159             :         { 0xA793, 0xA792, },
    1160             :         { 0xA794, 0xA7C4, },
    1161             :         { 0xA797, 0xA796, },
    1162             :         { 0xA799, 0xA798, },
    1163             :         { 0xA79B, 0xA79A, },
    1164             :         { 0xA79D, 0xA79C, },
    1165             :         { 0xA79F, 0xA79E, },
    1166             :         { 0xA7A1, 0xA7A0, },
    1167             :         { 0xA7A3, 0xA7A2, },
    1168             :         { 0xA7A5, 0xA7A4, },
    1169             :         { 0xA7A7, 0xA7A6, },
    1170             :         { 0xA7A9, 0xA7A8, },
    1171             :         { 0xA7B5, 0xA7B4, },
    1172             :         { 0xA7B7, 0xA7B6, },
    1173             :         { 0xA7B9, 0xA7B8, },
    1174             :         { 0xA7BB, 0xA7BA, },
    1175             :         { 0xA7BD, 0xA7BC, },
    1176             :         { 0xA7BF, 0xA7BE, },
    1177             :         { 0xA7C3, 0xA7C2, },
    1178             :         { 0xA7C8, 0xA7C7, },
    1179             :         { 0xA7CA, 0xA7C9, },
    1180             :         { 0xA7F6, 0xA7F5, },
    1181             :         { 0xAB53, 0xA7B3, },
    1182             :         { 0xAB70, 0x13A0, },
    1183             :         { 0xAB71, 0x13A1, },
    1184             :         { 0xAB72, 0x13A2, },
    1185             :         { 0xAB73, 0x13A3, },
    1186             :         { 0xAB74, 0x13A4, },
    1187             :         { 0xAB75, 0x13A5, },
    1188             :         { 0xAB76, 0x13A6, },
    1189             :         { 0xAB77, 0x13A7, },
    1190             :         { 0xAB78, 0x13A8, },
    1191             :         { 0xAB79, 0x13A9, },
    1192             :         { 0xAB7A, 0x13AA, },
    1193             :         { 0xAB7B, 0x13AB, },
    1194             :         { 0xAB7C, 0x13AC, },
    1195             :         { 0xAB7D, 0x13AD, },
    1196             :         { 0xAB7E, 0x13AE, },
    1197             :         { 0xAB7F, 0x13AF, },
    1198             :         { 0xAB80, 0x13B0, },
    1199             :         { 0xAB81, 0x13B1, },
    1200             :         { 0xAB82, 0x13B2, },
    1201             :         { 0xAB83, 0x13B3, },
    1202             :         { 0xAB84, 0x13B4, },
    1203             :         { 0xAB85, 0x13B5, },
    1204             :         { 0xAB86, 0x13B6, },
    1205             :         { 0xAB87, 0x13B7, },
    1206             :         { 0xAB88, 0x13B8, },
    1207             :         { 0xAB89, 0x13B9, },
    1208             :         { 0xAB8A, 0x13BA, },
    1209             :         { 0xAB8B, 0x13BB, },
    1210             :         { 0xAB8C, 0x13BC, },
    1211             :         { 0xAB8D, 0x13BD, },
    1212             :         { 0xAB8E, 0x13BE, },
    1213             :         { 0xAB8F, 0x13BF, },
    1214             :         { 0xAB90, 0x13C0, },
    1215             :         { 0xAB91, 0x13C1, },
    1216             :         { 0xAB92, 0x13C2, },
    1217             :         { 0xAB93, 0x13C3, },
    1218             :         { 0xAB94, 0x13C4, },
    1219             :         { 0xAB95, 0x13C5, },
    1220             :         { 0xAB96, 0x13C6, },
    1221             :         { 0xAB97, 0x13C7, },
    1222             :         { 0xAB98, 0x13C8, },
    1223             :         { 0xAB99, 0x13C9, },
    1224             :         { 0xAB9A, 0x13CA, },
    1225             :         { 0xAB9B, 0x13CB, },
    1226             :         { 0xAB9C, 0x13CC, },
    1227             :         { 0xAB9D, 0x13CD, },
    1228             :         { 0xAB9E, 0x13CE, },
    1229             :         { 0xAB9F, 0x13CF, },
    1230             :         { 0xABA0, 0x13D0, },
    1231             :         { 0xABA1, 0x13D1, },
    1232             :         { 0xABA2, 0x13D2, },
    1233             :         { 0xABA3, 0x13D3, },
    1234             :         { 0xABA4, 0x13D4, },
    1235             :         { 0xABA5, 0x13D5, },
    1236             :         { 0xABA6, 0x13D6, },
    1237             :         { 0xABA7, 0x13D7, },
    1238             :         { 0xABA8, 0x13D8, },
    1239             :         { 0xABA9, 0x13D9, },
    1240             :         { 0xABAA, 0x13DA, },
    1241             :         { 0xABAB, 0x13DB, },
    1242             :         { 0xABAC, 0x13DC, },
    1243             :         { 0xABAD, 0x13DD, },
    1244             :         { 0xABAE, 0x13DE, },
    1245             :         { 0xABAF, 0x13DF, },
    1246             :         { 0xABB0, 0x13E0, },
    1247             :         { 0xABB1, 0x13E1, },
    1248             :         { 0xABB2, 0x13E2, },
    1249             :         { 0xABB3, 0x13E3, },
    1250             :         { 0xABB4, 0x13E4, },
    1251             :         { 0xABB5, 0x13E5, },
    1252             :         { 0xABB6, 0x13E6, },
    1253             :         { 0xABB7, 0x13E7, },
    1254             :         { 0xABB8, 0x13E8, },
    1255             :         { 0xABB9, 0x13E9, },
    1256             :         { 0xABBA, 0x13EA, },
    1257             :         { 0xABBB, 0x13EB, },
    1258             :         { 0xABBC, 0x13EC, },
    1259             :         { 0xABBD, 0x13ED, },
    1260             :         { 0xABBE, 0x13EE, },
    1261             :         { 0xABBF, 0x13EF, },
    1262             :         { 0xFF41, 0xFF21, },
    1263             :         { 0xFF42, 0xFF22, },
    1264             :         { 0xFF43, 0xFF23, },
    1265             :         { 0xFF44, 0xFF24, },
    1266             :         { 0xFF45, 0xFF25, },
    1267             :         { 0xFF46, 0xFF26, },
    1268             :         { 0xFF47, 0xFF27, },
    1269             :         { 0xFF48, 0xFF28, },
    1270             :         { 0xFF49, 0xFF29, },
    1271             :         { 0xFF4A, 0xFF2A, },
    1272             :         { 0xFF4B, 0xFF2B, },
    1273             :         { 0xFF4C, 0xFF2C, },
    1274             :         { 0xFF4D, 0xFF2D, },
    1275             :         { 0xFF4E, 0xFF2E, },
    1276             :         { 0xFF4F, 0xFF2F, },
    1277             :         { 0xFF50, 0xFF30, },
    1278             :         { 0xFF51, 0xFF31, },
    1279             :         { 0xFF52, 0xFF32, },
    1280             :         { 0xFF53, 0xFF33, },
    1281             :         { 0xFF54, 0xFF34, },
    1282             :         { 0xFF55, 0xFF35, },
    1283             :         { 0xFF56, 0xFF36, },
    1284             :         { 0xFF57, 0xFF37, },
    1285             :         { 0xFF58, 0xFF38, },
    1286             :         { 0xFF59, 0xFF39, },
    1287             :         { 0xFF5A, 0xFF3A, },
    1288             :         { 0x10428, 0x10400, },
    1289             :         { 0x10429, 0x10401, },
    1290             :         { 0x1042A, 0x10402, },
    1291             :         { 0x1042B, 0x10403, },
    1292             :         { 0x1042C, 0x10404, },
    1293             :         { 0x1042D, 0x10405, },
    1294             :         { 0x1042E, 0x10406, },
    1295             :         { 0x1042F, 0x10407, },
    1296             :         { 0x10430, 0x10408, },
    1297             :         { 0x10431, 0x10409, },
    1298             :         { 0x10432, 0x1040A, },
    1299             :         { 0x10433, 0x1040B, },
    1300             :         { 0x10434, 0x1040C, },
    1301             :         { 0x10435, 0x1040D, },
    1302             :         { 0x10436, 0x1040E, },
    1303             :         { 0x10437, 0x1040F, },
    1304             :         { 0x10438, 0x10410, },
    1305             :         { 0x10439, 0x10411, },
    1306             :         { 0x1043A, 0x10412, },
    1307             :         { 0x1043B, 0x10413, },
    1308             :         { 0x1043C, 0x10414, },
    1309             :         { 0x1043D, 0x10415, },
    1310             :         { 0x1043E, 0x10416, },
    1311             :         { 0x1043F, 0x10417, },
    1312             :         { 0x10440, 0x10418, },
    1313             :         { 0x10441, 0x10419, },
    1314             :         { 0x10442, 0x1041A, },
    1315             :         { 0x10443, 0x1041B, },
    1316             :         { 0x10444, 0x1041C, },
    1317             :         { 0x10445, 0x1041D, },
    1318             :         { 0x10446, 0x1041E, },
    1319             :         { 0x10447, 0x1041F, },
    1320             :         { 0x10448, 0x10420, },
    1321             :         { 0x10449, 0x10421, },
    1322             :         { 0x1044A, 0x10422, },
    1323             :         { 0x1044B, 0x10423, },
    1324             :         { 0x1044C, 0x10424, },
    1325             :         { 0x1044D, 0x10425, },
    1326             :         { 0x1044E, 0x10426, },
    1327             :         { 0x1044F, 0x10427, },
    1328             :         { 0x104D8, 0x104B0, },
    1329             :         { 0x104D9, 0x104B1, },
    1330             :         { 0x104DA, 0x104B2, },
    1331             :         { 0x104DB, 0x104B3, },
    1332             :         { 0x104DC, 0x104B4, },
    1333             :         { 0x104DD, 0x104B5, },
    1334             :         { 0x104DE, 0x104B6, },
    1335             :         { 0x104DF, 0x104B7, },
    1336             :         { 0x104E0, 0x104B8, },
    1337             :         { 0x104E1, 0x104B9, },
    1338             :         { 0x104E2, 0x104BA, },
    1339             :         { 0x104E3, 0x104BB, },
    1340             :         { 0x104E4, 0x104BC, },
    1341             :         { 0x104E5, 0x104BD, },
    1342             :         { 0x104E6, 0x104BE, },
    1343             :         { 0x104E7, 0x104BF, },
    1344             :         { 0x104E8, 0x104C0, },
    1345             :         { 0x104E9, 0x104C1, },
    1346             :         { 0x104EA, 0x104C2, },
    1347             :         { 0x104EB, 0x104C3, },
    1348             :         { 0x104EC, 0x104C4, },
    1349             :         { 0x104ED, 0x104C5, },
    1350             :         { 0x104EE, 0x104C6, },
    1351             :         { 0x104EF, 0x104C7, },
    1352             :         { 0x104F0, 0x104C8, },
    1353             :         { 0x104F1, 0x104C9, },
    1354             :         { 0x104F2, 0x104CA, },
    1355             :         { 0x104F3, 0x104CB, },
    1356             :         { 0x104F4, 0x104CC, },
    1357             :         { 0x104F5, 0x104CD, },
    1358             :         { 0x104F6, 0x104CE, },
    1359             :         { 0x104F7, 0x104CF, },
    1360             :         { 0x104F8, 0x104D0, },
    1361             :         { 0x104F9, 0x104D1, },
    1362             :         { 0x104FA, 0x104D2, },
    1363             :         { 0x104FB, 0x104D3, },
    1364             :         { 0x10CC0, 0x10C80, },
    1365             :         { 0x10CC1, 0x10C81, },
    1366             :         { 0x10CC2, 0x10C82, },
    1367             :         { 0x10CC3, 0x10C83, },
    1368             :         { 0x10CC4, 0x10C84, },
    1369             :         { 0x10CC5, 0x10C85, },
    1370             :         { 0x10CC6, 0x10C86, },
    1371             :         { 0x10CC7, 0x10C87, },
    1372             :         { 0x10CC8, 0x10C88, },
    1373             :         { 0x10CC9, 0x10C89, },
    1374             :         { 0x10CCA, 0x10C8A, },
    1375             :         { 0x10CCB, 0x10C8B, },
    1376             :         { 0x10CCC, 0x10C8C, },
    1377             :         { 0x10CCD, 0x10C8D, },
    1378             :         { 0x10CCE, 0x10C8E, },
    1379             :         { 0x10CCF, 0x10C8F, },
    1380             :         { 0x10CD0, 0x10C90, },
    1381             :         { 0x10CD1, 0x10C91, },
    1382             :         { 0x10CD2, 0x10C92, },
    1383             :         { 0x10CD3, 0x10C93, },
    1384             :         { 0x10CD4, 0x10C94, },
    1385             :         { 0x10CD5, 0x10C95, },
    1386             :         { 0x10CD6, 0x10C96, },
    1387             :         { 0x10CD7, 0x10C97, },
    1388             :         { 0x10CD8, 0x10C98, },
    1389             :         { 0x10CD9, 0x10C99, },
    1390             :         { 0x10CDA, 0x10C9A, },
    1391             :         { 0x10CDB, 0x10C9B, },
    1392             :         { 0x10CDC, 0x10C9C, },
    1393             :         { 0x10CDD, 0x10C9D, },
    1394             :         { 0x10CDE, 0x10C9E, },
    1395             :         { 0x10CDF, 0x10C9F, },
    1396             :         { 0x10CE0, 0x10CA0, },
    1397             :         { 0x10CE1, 0x10CA1, },
    1398             :         { 0x10CE2, 0x10CA2, },
    1399             :         { 0x10CE3, 0x10CA3, },
    1400             :         { 0x10CE4, 0x10CA4, },
    1401             :         { 0x10CE5, 0x10CA5, },
    1402             :         { 0x10CE6, 0x10CA6, },
    1403             :         { 0x10CE7, 0x10CA7, },
    1404             :         { 0x10CE8, 0x10CA8, },
    1405             :         { 0x10CE9, 0x10CA9, },
    1406             :         { 0x10CEA, 0x10CAA, },
    1407             :         { 0x10CEB, 0x10CAB, },
    1408             :         { 0x10CEC, 0x10CAC, },
    1409             :         { 0x10CED, 0x10CAD, },
    1410             :         { 0x10CEE, 0x10CAE, },
    1411             :         { 0x10CEF, 0x10CAF, },
    1412             :         { 0x10CF0, 0x10CB0, },
    1413             :         { 0x10CF1, 0x10CB1, },
    1414             :         { 0x10CF2, 0x10CB2, },
    1415             :         { 0x118C0, 0x118A0, },
    1416             :         { 0x118C1, 0x118A1, },
    1417             :         { 0x118C2, 0x118A2, },
    1418             :         { 0x118C3, 0x118A3, },
    1419             :         { 0x118C4, 0x118A4, },
    1420             :         { 0x118C5, 0x118A5, },
    1421             :         { 0x118C6, 0x118A6, },
    1422             :         { 0x118C7, 0x118A7, },
    1423             :         { 0x118C8, 0x118A8, },
    1424             :         { 0x118C9, 0x118A9, },
    1425             :         { 0x118CA, 0x118AA, },
    1426             :         { 0x118CB, 0x118AB, },
    1427             :         { 0x118CC, 0x118AC, },
    1428             :         { 0x118CD, 0x118AD, },
    1429             :         { 0x118CE, 0x118AE, },
    1430             :         { 0x118CF, 0x118AF, },
    1431             :         { 0x118D0, 0x118B0, },
    1432             :         { 0x118D1, 0x118B1, },
    1433             :         { 0x118D2, 0x118B2, },
    1434             :         { 0x118D3, 0x118B3, },
    1435             :         { 0x118D4, 0x118B4, },
    1436             :         { 0x118D5, 0x118B5, },
    1437             :         { 0x118D6, 0x118B6, },
    1438             :         { 0x118D7, 0x118B7, },
    1439             :         { 0x118D8, 0x118B8, },
    1440             :         { 0x118D9, 0x118B9, },
    1441             :         { 0x118DA, 0x118BA, },
    1442             :         { 0x118DB, 0x118BB, },
    1443             :         { 0x118DC, 0x118BC, },
    1444             :         { 0x118DD, 0x118BD, },
    1445             :         { 0x118DE, 0x118BE, },
    1446             :         { 0x118DF, 0x118BF, },
    1447             :         { 0x16E60, 0x16E40, },
    1448             :         { 0x16E61, 0x16E41, },
    1449             :         { 0x16E62, 0x16E42, },
    1450             :         { 0x16E63, 0x16E43, },
    1451             :         { 0x16E64, 0x16E44, },
    1452             :         { 0x16E65, 0x16E45, },
    1453             :         { 0x16E66, 0x16E46, },
    1454             :         { 0x16E67, 0x16E47, },
    1455             :         { 0x16E68, 0x16E48, },
    1456             :         { 0x16E69, 0x16E49, },
    1457             :         { 0x16E6A, 0x16E4A, },
    1458             :         { 0x16E6B, 0x16E4B, },
    1459             :         { 0x16E6C, 0x16E4C, },
    1460             :         { 0x16E6D, 0x16E4D, },
    1461             :         { 0x16E6E, 0x16E4E, },
    1462             :         { 0x16E6F, 0x16E4F, },
    1463             :         { 0x16E70, 0x16E50, },
    1464             :         { 0x16E71, 0x16E51, },
    1465             :         { 0x16E72, 0x16E52, },
    1466             :         { 0x16E73, 0x16E53, },
    1467             :         { 0x16E74, 0x16E54, },
    1468             :         { 0x16E75, 0x16E55, },
    1469             :         { 0x16E76, 0x16E56, },
    1470             :         { 0x16E77, 0x16E57, },
    1471             :         { 0x16E78, 0x16E58, },
    1472             :         { 0x16E79, 0x16E59, },
    1473             :         { 0x16E7A, 0x16E5A, },
    1474             :         { 0x16E7B, 0x16E5B, },
    1475             :         { 0x16E7C, 0x16E5C, },
    1476             :         { 0x16E7D, 0x16E5D, },
    1477             :         { 0x16E7E, 0x16E5E, },
    1478             :         { 0x16E7F, 0x16E5F, },
    1479             :         { 0x1E922, 0x1E900, },
    1480             :         { 0x1E923, 0x1E901, },
    1481             :         { 0x1E924, 0x1E902, },
    1482             :         { 0x1E925, 0x1E903, },
    1483             :         { 0x1E926, 0x1E904, },
    1484             :         { 0x1E927, 0x1E905, },
    1485             :         { 0x1E928, 0x1E906, },
    1486             :         { 0x1E929, 0x1E907, },
    1487             :         { 0x1E92A, 0x1E908, },
    1488             :         { 0x1E92B, 0x1E909, },
    1489             :         { 0x1E92C, 0x1E90A, },
    1490             :         { 0x1E92D, 0x1E90B, },
    1491             :         { 0x1E92E, 0x1E90C, },
    1492             :         { 0x1E92F, 0x1E90D, },
    1493             :         { 0x1E930, 0x1E90E, },
    1494             :         { 0x1E931, 0x1E90F, },
    1495             :         { 0x1E932, 0x1E910, },
    1496             :         { 0x1E933, 0x1E911, },
    1497             :         { 0x1E934, 0x1E912, },
    1498             :         { 0x1E935, 0x1E913, },
    1499             :         { 0x1E936, 0x1E914, },
    1500             :         { 0x1E937, 0x1E915, },
    1501             :         { 0x1E938, 0x1E916, },
    1502             :         { 0x1E939, 0x1E917, },
    1503             :         { 0x1E93A, 0x1E918, },
    1504             :         { 0x1E93B, 0x1E919, },
    1505             :         { 0x1E93C, 0x1E91A, },
    1506             :         { 0x1E93D, 0x1E91B, },
    1507             :         { 0x1E93E, 0x1E91C, },
    1508             :         { 0x1E93F, 0x1E91D, },
    1509             :         { 0x1E940, 0x1E91E, },
    1510             :         { 0x1E941, 0x1E91F, },
    1511             :         { 0x1E942, 0x1E920, },
    1512             :         { 0x1E943, 0x1E921, },
    1513             : }, UTF8_toLower[] = { /* code points with non-null lowercase conversion */
    1514             :         { 0x0041, 0x0061, },
    1515             :         { 0x0042, 0x0062, },
    1516             :         { 0x0043, 0x0063, },
    1517             :         { 0x0044, 0x0064, },
    1518             :         { 0x0045, 0x0065, },
    1519             :         { 0x0046, 0x0066, },
    1520             :         { 0x0047, 0x0067, },
    1521             :         { 0x0048, 0x0068, },
    1522             :         { 0x0049, 0x0069, },
    1523             :         { 0x004A, 0x006A, },
    1524             :         { 0x004B, 0x006B, },
    1525             :         { 0x004C, 0x006C, },
    1526             :         { 0x004D, 0x006D, },
    1527             :         { 0x004E, 0x006E, },
    1528             :         { 0x004F, 0x006F, },
    1529             :         { 0x0050, 0x0070, },
    1530             :         { 0x0051, 0x0071, },
    1531             :         { 0x0052, 0x0072, },
    1532             :         { 0x0053, 0x0073, },
    1533             :         { 0x0054, 0x0074, },
    1534             :         { 0x0055, 0x0075, },
    1535             :         { 0x0056, 0x0076, },
    1536             :         { 0x0057, 0x0077, },
    1537             :         { 0x0058, 0x0078, },
    1538             :         { 0x0059, 0x0079, },
    1539             :         { 0x005A, 0x007A, },
    1540             :         { 0x00C0, 0x00E0, },
    1541             :         { 0x00C1, 0x00E1, },
    1542             :         { 0x00C2, 0x00E2, },
    1543             :         { 0x00C3, 0x00E3, },
    1544             :         { 0x00C4, 0x00E4, },
    1545             :         { 0x00C5, 0x00E5, },
    1546             :         { 0x00C6, 0x00E6, },
    1547             :         { 0x00C7, 0x00E7, },
    1548             :         { 0x00C8, 0x00E8, },
    1549             :         { 0x00C9, 0x00E9, },
    1550             :         { 0x00CA, 0x00EA, },
    1551             :         { 0x00CB, 0x00EB, },
    1552             :         { 0x00CC, 0x00EC, },
    1553             :         { 0x00CD, 0x00ED, },
    1554             :         { 0x00CE, 0x00EE, },
    1555             :         { 0x00CF, 0x00EF, },
    1556             :         { 0x00D0, 0x00F0, },
    1557             :         { 0x00D1, 0x00F1, },
    1558             :         { 0x00D2, 0x00F2, },
    1559             :         { 0x00D3, 0x00F3, },
    1560             :         { 0x00D4, 0x00F4, },
    1561             :         { 0x00D5, 0x00F5, },
    1562             :         { 0x00D6, 0x00F6, },
    1563             :         { 0x00D8, 0x00F8, },
    1564             :         { 0x00D9, 0x00F9, },
    1565             :         { 0x00DA, 0x00FA, },
    1566             :         { 0x00DB, 0x00FB, },
    1567             :         { 0x00DC, 0x00FC, },
    1568             :         { 0x00DD, 0x00FD, },
    1569             :         { 0x00DE, 0x00FE, },
    1570             :         { 0x0100, 0x0101, },
    1571             :         { 0x0102, 0x0103, },
    1572             :         { 0x0104, 0x0105, },
    1573             :         { 0x0106, 0x0107, },
    1574             :         { 0x0108, 0x0109, },
    1575             :         { 0x010A, 0x010B, },
    1576             :         { 0x010C, 0x010D, },
    1577             :         { 0x010E, 0x010F, },
    1578             :         { 0x0110, 0x0111, },
    1579             :         { 0x0112, 0x0113, },
    1580             :         { 0x0114, 0x0115, },
    1581             :         { 0x0116, 0x0117, },
    1582             :         { 0x0118, 0x0119, },
    1583             :         { 0x011A, 0x011B, },
    1584             :         { 0x011C, 0x011D, },
    1585             :         { 0x011E, 0x011F, },
    1586             :         { 0x0120, 0x0121, },
    1587             :         { 0x0122, 0x0123, },
    1588             :         { 0x0124, 0x0125, },
    1589             :         { 0x0126, 0x0127, },
    1590             :         { 0x0128, 0x0129, },
    1591             :         { 0x012A, 0x012B, },
    1592             :         { 0x012C, 0x012D, },
    1593             :         { 0x012E, 0x012F, },
    1594             :         { 0x0130, 0x0069, },
    1595             :         { 0x0132, 0x0133, },
    1596             :         { 0x0134, 0x0135, },
    1597             :         { 0x0136, 0x0137, },
    1598             :         { 0x0139, 0x013A, },
    1599             :         { 0x013B, 0x013C, },
    1600             :         { 0x013D, 0x013E, },
    1601             :         { 0x013F, 0x0140, },
    1602             :         { 0x0141, 0x0142, },
    1603             :         { 0x0143, 0x0144, },
    1604             :         { 0x0145, 0x0146, },
    1605             :         { 0x0147, 0x0148, },
    1606             :         { 0x014A, 0x014B, },
    1607             :         { 0x014C, 0x014D, },
    1608             :         { 0x014E, 0x014F, },
    1609             :         { 0x0150, 0x0151, },
    1610             :         { 0x0152, 0x0153, },
    1611             :         { 0x0154, 0x0155, },
    1612             :         { 0x0156, 0x0157, },
    1613             :         { 0x0158, 0x0159, },
    1614             :         { 0x015A, 0x015B, },
    1615             :         { 0x015C, 0x015D, },
    1616             :         { 0x015E, 0x015F, },
    1617             :         { 0x0160, 0x0161, },
    1618             :         { 0x0162, 0x0163, },
    1619             :         { 0x0164, 0x0165, },
    1620             :         { 0x0166, 0x0167, },
    1621             :         { 0x0168, 0x0169, },
    1622             :         { 0x016A, 0x016B, },
    1623             :         { 0x016C, 0x016D, },
    1624             :         { 0x016E, 0x016F, },
    1625             :         { 0x0170, 0x0171, },
    1626             :         { 0x0172, 0x0173, },
    1627             :         { 0x0174, 0x0175, },
    1628             :         { 0x0176, 0x0177, },
    1629             :         { 0x0178, 0x00FF, },
    1630             :         { 0x0179, 0x017A, },
    1631             :         { 0x017B, 0x017C, },
    1632             :         { 0x017D, 0x017E, },
    1633             :         { 0x0181, 0x0253, },
    1634             :         { 0x0182, 0x0183, },
    1635             :         { 0x0184, 0x0185, },
    1636             :         { 0x0186, 0x0254, },
    1637             :         { 0x0187, 0x0188, },
    1638             :         { 0x0189, 0x0256, },
    1639             :         { 0x018A, 0x0257, },
    1640             :         { 0x018B, 0x018C, },
    1641             :         { 0x018E, 0x01DD, },
    1642             :         { 0x018F, 0x0259, },
    1643             :         { 0x0190, 0x025B, },
    1644             :         { 0x0191, 0x0192, },
    1645             :         { 0x0193, 0x0260, },
    1646             :         { 0x0194, 0x0263, },
    1647             :         { 0x0196, 0x0269, },
    1648             :         { 0x0197, 0x0268, },
    1649             :         { 0x0198, 0x0199, },
    1650             :         { 0x019C, 0x026F, },
    1651             :         { 0x019D, 0x0272, },
    1652             :         { 0x019F, 0x0275, },
    1653             :         { 0x01A0, 0x01A1, },
    1654             :         { 0x01A2, 0x01A3, },
    1655             :         { 0x01A4, 0x01A5, },
    1656             :         { 0x01A6, 0x0280, },
    1657             :         { 0x01A7, 0x01A8, },
    1658             :         { 0x01A9, 0x0283, },
    1659             :         { 0x01AC, 0x01AD, },
    1660             :         { 0x01AE, 0x0288, },
    1661             :         { 0x01AF, 0x01B0, },
    1662             :         { 0x01B1, 0x028A, },
    1663             :         { 0x01B2, 0x028B, },
    1664             :         { 0x01B3, 0x01B4, },
    1665             :         { 0x01B5, 0x01B6, },
    1666             :         { 0x01B7, 0x0292, },
    1667             :         { 0x01B8, 0x01B9, },
    1668             :         { 0x01BC, 0x01BD, },
    1669             :         { 0x01C4, 0x01C6, },
    1670             :         { 0x01C5, 0x01C6, },
    1671             :         { 0x01C7, 0x01C9, },
    1672             :         { 0x01C8, 0x01C9, },
    1673             :         { 0x01CA, 0x01CC, },
    1674             :         { 0x01CB, 0x01CC, },
    1675             :         { 0x01CD, 0x01CE, },
    1676             :         { 0x01CF, 0x01D0, },
    1677             :         { 0x01D1, 0x01D2, },
    1678             :         { 0x01D3, 0x01D4, },
    1679             :         { 0x01D5, 0x01D6, },
    1680             :         { 0x01D7, 0x01D8, },
    1681             :         { 0x01D9, 0x01DA, },
    1682             :         { 0x01DB, 0x01DC, },
    1683             :         { 0x01DE, 0x01DF, },
    1684             :         { 0x01E0, 0x01E1, },
    1685             :         { 0x01E2, 0x01E3, },
    1686             :         { 0x01E4, 0x01E5, },
    1687             :         { 0x01E6, 0x01E7, },
    1688             :         { 0x01E8, 0x01E9, },
    1689             :         { 0x01EA, 0x01EB, },
    1690             :         { 0x01EC, 0x01ED, },
    1691             :         { 0x01EE, 0x01EF, },
    1692             :         { 0x01F1, 0x01F3, },
    1693             :         { 0x01F2, 0x01F3, },
    1694             :         { 0x01F4, 0x01F5, },
    1695             :         { 0x01F6, 0x0195, },
    1696             :         { 0x01F7, 0x01BF, },
    1697             :         { 0x01F8, 0x01F9, },
    1698             :         { 0x01FA, 0x01FB, },
    1699             :         { 0x01FC, 0x01FD, },
    1700             :         { 0x01FE, 0x01FF, },
    1701             :         { 0x0200, 0x0201, },
    1702             :         { 0x0202, 0x0203, },
    1703             :         { 0x0204, 0x0205, },
    1704             :         { 0x0206, 0x0207, },
    1705             :         { 0x0208, 0x0209, },
    1706             :         { 0x020A, 0x020B, },
    1707             :         { 0x020C, 0x020D, },
    1708             :         { 0x020E, 0x020F, },
    1709             :         { 0x0210, 0x0211, },
    1710             :         { 0x0212, 0x0213, },
    1711             :         { 0x0214, 0x0215, },
    1712             :         { 0x0216, 0x0217, },
    1713             :         { 0x0218, 0x0219, },
    1714             :         { 0x021A, 0x021B, },
    1715             :         { 0x021C, 0x021D, },
    1716             :         { 0x021E, 0x021F, },
    1717             :         { 0x0220, 0x019E, },
    1718             :         { 0x0222, 0x0223, },
    1719             :         { 0x0224, 0x0225, },
    1720             :         { 0x0226, 0x0227, },
    1721             :         { 0x0228, 0x0229, },
    1722             :         { 0x022A, 0x022B, },
    1723             :         { 0x022C, 0x022D, },
    1724             :         { 0x022E, 0x022F, },
    1725             :         { 0x0230, 0x0231, },
    1726             :         { 0x0232, 0x0233, },
    1727             :         { 0x023A, 0x2C65, },
    1728             :         { 0x023B, 0x023C, },
    1729             :         { 0x023D, 0x019A, },
    1730             :         { 0x023E, 0x2C66, },
    1731             :         { 0x0241, 0x0242, },
    1732             :         { 0x0243, 0x0180, },
    1733             :         { 0x0244, 0x0289, },
    1734             :         { 0x0245, 0x028C, },
    1735             :         { 0x0246, 0x0247, },
    1736             :         { 0x0248, 0x0249, },
    1737             :         { 0x024A, 0x024B, },
    1738             :         { 0x024C, 0x024D, },
    1739             :         { 0x024E, 0x024F, },
    1740             :         { 0x0370, 0x0371, },
    1741             :         { 0x0372, 0x0373, },
    1742             :         { 0x0376, 0x0377, },
    1743             :         { 0x037F, 0x03F3, },
    1744             :         { 0x0386, 0x03AC, },
    1745             :         { 0x0388, 0x03AD, },
    1746             :         { 0x0389, 0x03AE, },
    1747             :         { 0x038A, 0x03AF, },
    1748             :         { 0x038C, 0x03CC, },
    1749             :         { 0x038E, 0x03CD, },
    1750             :         { 0x038F, 0x03CE, },
    1751             :         { 0x0391, 0x03B1, },
    1752             :         { 0x0392, 0x03B2, },
    1753             :         { 0x0393, 0x03B3, },
    1754             :         { 0x0394, 0x03B4, },
    1755             :         { 0x0395, 0x03B5, },
    1756             :         { 0x0396, 0x03B6, },
    1757             :         { 0x0397, 0x03B7, },
    1758             :         { 0x0398, 0x03B8, },
    1759             :         { 0x0399, 0x03B9, },
    1760             :         { 0x039A, 0x03BA, },
    1761             :         { 0x039B, 0x03BB, },
    1762             :         { 0x039C, 0x03BC, },
    1763             :         { 0x039D, 0x03BD, },
    1764             :         { 0x039E, 0x03BE, },
    1765             :         { 0x039F, 0x03BF, },
    1766             :         { 0x03A0, 0x03C0, },
    1767             :         { 0x03A1, 0x03C1, },
    1768             :         { 0x03A3, 0x03C3, },
    1769             :         { 0x03A4, 0x03C4, },
    1770             :         { 0x03A5, 0x03C5, },
    1771             :         { 0x03A6, 0x03C6, },
    1772             :         { 0x03A7, 0x03C7, },
    1773             :         { 0x03A8, 0x03C8, },
    1774             :         { 0x03A9, 0x03C9, },
    1775             :         { 0x03AA, 0x03CA, },
    1776             :         { 0x03AB, 0x03CB, },
    1777             :         { 0x03CF, 0x03D7, },
    1778             :         { 0x03D8, 0x03D9, },
    1779             :         { 0x03DA, 0x03DB, },
    1780             :         { 0x03DC, 0x03DD, },
    1781             :         { 0x03DE, 0x03DF, },
    1782             :         { 0x03E0, 0x03E1, },
    1783             :         { 0x03E2, 0x03E3, },
    1784             :         { 0x03E4, 0x03E5, },
    1785             :         { 0x03E6, 0x03E7, },
    1786             :         { 0x03E8, 0x03E9, },
    1787             :         { 0x03EA, 0x03EB, },
    1788             :         { 0x03EC, 0x03ED, },
    1789             :         { 0x03EE, 0x03EF, },
    1790             :         { 0x03F4, 0x03B8, },
    1791             :         { 0x03F7, 0x03F8, },
    1792             :         { 0x03F9, 0x03F2, },
    1793             :         { 0x03FA, 0x03FB, },
    1794             :         { 0x03FD, 0x037B, },
    1795             :         { 0x03FE, 0x037C, },
    1796             :         { 0x03FF, 0x037D, },
    1797             :         { 0x0400, 0x0450, },
    1798             :         { 0x0401, 0x0451, },
    1799             :         { 0x0402, 0x0452, },
    1800             :         { 0x0403, 0x0453, },
    1801             :         { 0x0404, 0x0454, },
    1802             :         { 0x0405, 0x0455, },
    1803             :         { 0x0406, 0x0456, },
    1804             :         { 0x0407, 0x0457, },
    1805             :         { 0x0408, 0x0458, },
    1806             :         { 0x0409, 0x0459, },
    1807             :         { 0x040A, 0x045A, },
    1808             :         { 0x040B, 0x045B, },
    1809             :         { 0x040C, 0x045C, },
    1810             :         { 0x040D, 0x045D, },
    1811             :         { 0x040E, 0x045E, },
    1812             :         { 0x040F, 0x045F, },
    1813             :         { 0x0410, 0x0430, },
    1814             :         { 0x0411, 0x0431, },
    1815             :         { 0x0412, 0x0432, },
    1816             :         { 0x0413, 0x0433, },
    1817             :         { 0x0414, 0x0434, },
    1818             :         { 0x0415, 0x0435, },
    1819             :         { 0x0416, 0x0436, },
    1820             :         { 0x0417, 0x0437, },
    1821             :         { 0x0418, 0x0438, },
    1822             :         { 0x0419, 0x0439, },
    1823             :         { 0x041A, 0x043A, },
    1824             :         { 0x041B, 0x043B, },
    1825             :         { 0x041C, 0x043C, },
    1826             :         { 0x041D, 0x043D, },
    1827             :         { 0x041E, 0x043E, },
    1828             :         { 0x041F, 0x043F, },
    1829             :         { 0x0420, 0x0440, },
    1830             :         { 0x0421, 0x0441, },
    1831             :         { 0x0422, 0x0442, },
    1832             :         { 0x0423, 0x0443, },
    1833             :         { 0x0424, 0x0444, },
    1834             :         { 0x0425, 0x0445, },
    1835             :         { 0x0426, 0x0446, },
    1836             :         { 0x0427, 0x0447, },
    1837             :         { 0x0428, 0x0448, },
    1838             :         { 0x0429, 0x0449, },
    1839             :         { 0x042A, 0x044A, },
    1840             :         { 0x042B, 0x044B, },
    1841             :         { 0x042C, 0x044C, },
    1842             :         { 0x042D, 0x044D, },
    1843             :         { 0x042E, 0x044E, },
    1844             :         { 0x042F, 0x044F, },
    1845             :         { 0x0460, 0x0461, },
    1846             :         { 0x0462, 0x0463, },
    1847             :         { 0x0464, 0x0465, },
    1848             :         { 0x0466, 0x0467, },
    1849             :         { 0x0468, 0x0469, },
    1850             :         { 0x046A, 0x046B, },
    1851             :         { 0x046C, 0x046D, },
    1852             :         { 0x046E, 0x046F, },
    1853             :         { 0x0470, 0x0471, },
    1854             :         { 0x0472, 0x0473, },
    1855             :         { 0x0474, 0x0475, },
    1856             :         { 0x0476, 0x0477, },
    1857             :         { 0x0478, 0x0479, },
    1858             :         { 0x047A, 0x047B, },
    1859             :         { 0x047C, 0x047D, },
    1860             :         { 0x047E, 0x047F, },
    1861             :         { 0x0480, 0x0481, },
    1862             :         { 0x048A, 0x048B, },
    1863             :         { 0x048C, 0x048D, },
    1864             :         { 0x048E, 0x048F, },
    1865             :         { 0x0490, 0x0491, },
    1866             :         { 0x0492, 0x0493, },
    1867             :         { 0x0494, 0x0495, },
    1868             :         { 0x0496, 0x0497, },
    1869             :         { 0x0498, 0x0499, },
    1870             :         { 0x049A, 0x049B, },
    1871             :         { 0x049C, 0x049D, },
    1872             :         { 0x049E, 0x049F, },
    1873             :         { 0x04A0, 0x04A1, },
    1874             :         { 0x04A2, 0x04A3, },
    1875             :         { 0x04A4, 0x04A5, },
    1876             :         { 0x04A6, 0x04A7, },
    1877             :         { 0x04A8, 0x04A9, },
    1878             :         { 0x04AA, 0x04AB, },
    1879             :         { 0x04AC, 0x04AD, },
    1880             :         { 0x04AE, 0x04AF, },
    1881             :         { 0x04B0, 0x04B1, },
    1882             :         { 0x04B2, 0x04B3, },
    1883             :         { 0x04B4, 0x04B5, },
    1884             :         { 0x04B6, 0x04B7, },
    1885             :         { 0x04B8, 0x04B9, },
    1886             :         { 0x04BA, 0x04BB, },
    1887             :         { 0x04BC, 0x04BD, },
    1888             :         { 0x04BE, 0x04BF, },
    1889             :         { 0x04C0, 0x04CF, },
    1890             :         { 0x04C1, 0x04C2, },
    1891             :         { 0x04C3, 0x04C4, },
    1892             :         { 0x04C5, 0x04C6, },
    1893             :         { 0x04C7, 0x04C8, },
    1894             :         { 0x04C9, 0x04CA, },
    1895             :         { 0x04CB, 0x04CC, },
    1896             :         { 0x04CD, 0x04CE, },
    1897             :         { 0x04D0, 0x04D1, },
    1898             :         { 0x04D2, 0x04D3, },
    1899             :         { 0x04D4, 0x04D5, },
    1900             :         { 0x04D6, 0x04D7, },
    1901             :         { 0x04D8, 0x04D9, },
    1902             :         { 0x04DA, 0x04DB, },
    1903             :         { 0x04DC, 0x04DD, },
    1904             :         { 0x04DE, 0x04DF, },
    1905             :         { 0x04E0, 0x04E1, },
    1906             :         { 0x04E2, 0x04E3, },
    1907             :         { 0x04E4, 0x04E5, },
    1908             :         { 0x04E6, 0x04E7, },
    1909             :         { 0x04E8, 0x04E9, },
    1910             :         { 0x04EA, 0x04EB, },
    1911             :         { 0x04EC, 0x04ED, },
    1912             :         { 0x04EE, 0x04EF, },
    1913             :         { 0x04F0, 0x04F1, },
    1914             :         { 0x04F2, 0x04F3, },
    1915             :         { 0x04F4, 0x04F5, },
    1916             :         { 0x04F6, 0x04F7, },
    1917             :         { 0x04F8, 0x04F9, },
    1918             :         { 0x04FA, 0x04FB, },
    1919             :         { 0x04FC, 0x04FD, },
    1920             :         { 0x04FE, 0x04FF, },
    1921             :         { 0x0500, 0x0501, },
    1922             :         { 0x0502, 0x0503, },
    1923             :         { 0x0504, 0x0505, },
    1924             :         { 0x0506, 0x0507, },
    1925             :         { 0x0508, 0x0509, },
    1926             :         { 0x050A, 0x050B, },
    1927             :         { 0x050C, 0x050D, },
    1928             :         { 0x050E, 0x050F, },
    1929             :         { 0x0510, 0x0511, },
    1930             :         { 0x0512, 0x0513, },
    1931             :         { 0x0514, 0x0515, },
    1932             :         { 0x0516, 0x0517, },
    1933             :         { 0x0518, 0x0519, },
    1934             :         { 0x051A, 0x051B, },
    1935             :         { 0x051C, 0x051D, },
    1936             :         { 0x051E, 0x051F, },
    1937             :         { 0x0520, 0x0521, },
    1938             :         { 0x0522, 0x0523, },
    1939             :         { 0x0524, 0x0525, },
    1940             :         { 0x0526, 0x0527, },
    1941             :         { 0x0528, 0x0529, },
    1942             :         { 0x052A, 0x052B, },
    1943             :         { 0x052C, 0x052D, },
    1944             :         { 0x052E, 0x052F, },
    1945             :         { 0x0531, 0x0561, },
    1946             :         { 0x0532, 0x0562, },
    1947             :         { 0x0533, 0x0563, },
    1948             :         { 0x0534, 0x0564, },
    1949             :         { 0x0535, 0x0565, },
    1950             :         { 0x0536, 0x0566, },
    1951             :         { 0x0537, 0x0567, },
    1952             :         { 0x0538, 0x0568, },
    1953             :         { 0x0539, 0x0569, },
    1954             :         { 0x053A, 0x056A, },
    1955             :         { 0x053B, 0x056B, },
    1956             :         { 0x053C, 0x056C, },
    1957             :         { 0x053D, 0x056D, },
    1958             :         { 0x053E, 0x056E, },
    1959             :         { 0x053F, 0x056F, },
    1960             :         { 0x0540, 0x0570, },
    1961             :         { 0x0541, 0x0571, },
    1962             :         { 0x0542, 0x0572, },
    1963             :         { 0x0543, 0x0573, },
    1964             :         { 0x0544, 0x0574, },
    1965             :         { 0x0545, 0x0575, },
    1966             :         { 0x0546, 0x0576, },
    1967             :         { 0x0547, 0x0577, },
    1968             :         { 0x0548, 0x0578, },
    1969             :         { 0x0549, 0x0579, },
    1970             :         { 0x054A, 0x057A, },
    1971             :         { 0x054B, 0x057B, },
    1972             :         { 0x054C, 0x057C, },
    1973             :         { 0x054D, 0x057D, },
    1974             :         { 0x054E, 0x057E, },
    1975             :         { 0x054F, 0x057F, },
    1976             :         { 0x0550, 0x0580, },
    1977             :         { 0x0551, 0x0581, },
    1978             :         { 0x0552, 0x0582, },
    1979             :         { 0x0553, 0x0583, },
    1980             :         { 0x0554, 0x0584, },
    1981             :         { 0x0555, 0x0585, },
    1982             :         { 0x0556, 0x0586, },
    1983             :         { 0x10A0, 0x2D00, },
    1984             :         { 0x10A1, 0x2D01, },
    1985             :         { 0x10A2, 0x2D02, },
    1986             :         { 0x10A3, 0x2D03, },
    1987             :         { 0x10A4, 0x2D04, },
    1988             :         { 0x10A5, 0x2D05, },
    1989             :         { 0x10A6, 0x2D06, },
    1990             :         { 0x10A7, 0x2D07, },
    1991             :         { 0x10A8, 0x2D08, },
    1992             :         { 0x10A9, 0x2D09, },
    1993             :         { 0x10AA, 0x2D0A, },
    1994             :         { 0x10AB, 0x2D0B, },
    1995             :         { 0x10AC, 0x2D0C, },
    1996             :         { 0x10AD, 0x2D0D, },
    1997             :         { 0x10AE, 0x2D0E, },
    1998             :         { 0x10AF, 0x2D0F, },
    1999             :         { 0x10B0, 0x2D10, },
    2000             :         { 0x10B1, 0x2D11, },
    2001             :         { 0x10B2, 0x2D12, },
    2002             :         { 0x10B3, 0x2D13, },
    2003             :         { 0x10B4, 0x2D14, },
    2004             :         { 0x10B5, 0x2D15, },
    2005             :         { 0x10B6, 0x2D16, },
    2006             :         { 0x10B7, 0x2D17, },
    2007             :         { 0x10B8, 0x2D18, },
    2008             :         { 0x10B9, 0x2D19, },
    2009             :         { 0x10BA, 0x2D1A, },
    2010             :         { 0x10BB, 0x2D1B, },
    2011             :         { 0x10BC, 0x2D1C, },
    2012             :         { 0x10BD, 0x2D1D, },
    2013             :         { 0x10BE, 0x2D1E, },
    2014             :         { 0x10BF, 0x2D1F, },
    2015             :         { 0x10C0, 0x2D20, },
    2016             :         { 0x10C1, 0x2D21, },
    2017             :         { 0x10C2, 0x2D22, },
    2018             :         { 0x10C3, 0x2D23, },
    2019             :         { 0x10C4, 0x2D24, },
    2020             :         { 0x10C5, 0x2D25, },
    2021             :         { 0x10C7, 0x2D27, },
    2022             :         { 0x10CD, 0x2D2D, },
    2023             :         { 0x13A0, 0xAB70, },
    2024             :         { 0x13A1, 0xAB71, },
    2025             :         { 0x13A2, 0xAB72, },
    2026             :         { 0x13A3, 0xAB73, },
    2027             :         { 0x13A4, 0xAB74, },
    2028             :         { 0x13A5, 0xAB75, },
    2029             :         { 0x13A6, 0xAB76, },
    2030             :         { 0x13A7, 0xAB77, },
    2031             :         { 0x13A8, 0xAB78, },
    2032             :         { 0x13A9, 0xAB79, },
    2033             :         { 0x13AA, 0xAB7A, },
    2034             :         { 0x13AB, 0xAB7B, },
    2035             :         { 0x13AC, 0xAB7C, },
    2036             :         { 0x13AD, 0xAB7D, },
    2037             :         { 0x13AE, 0xAB7E, },
    2038             :         { 0x13AF, 0xAB7F, },
    2039             :         { 0x13B0, 0xAB80, },
    2040             :         { 0x13B1, 0xAB81, },
    2041             :         { 0x13B2, 0xAB82, },
    2042             :         { 0x13B3, 0xAB83, },
    2043             :         { 0x13B4, 0xAB84, },
    2044             :         { 0x13B5, 0xAB85, },
    2045             :         { 0x13B6, 0xAB86, },
    2046             :         { 0x13B7, 0xAB87, },
    2047             :         { 0x13B8, 0xAB88, },
    2048             :         { 0x13B9, 0xAB89, },
    2049             :         { 0x13BA, 0xAB8A, },
    2050             :         { 0x13BB, 0xAB8B, },
    2051             :         { 0x13BC, 0xAB8C, },
    2052             :         { 0x13BD, 0xAB8D, },
    2053             :         { 0x13BE, 0xAB8E, },
    2054             :         { 0x13BF, 0xAB8F, },
    2055             :         { 0x13C0, 0xAB90, },
    2056             :         { 0x13C1, 0xAB91, },
    2057             :         { 0x13C2, 0xAB92, },
    2058             :         { 0x13C3, 0xAB93, },
    2059             :         { 0x13C4, 0xAB94, },
    2060             :         { 0x13C5, 0xAB95, },
    2061             :         { 0x13C6, 0xAB96, },
    2062             :         { 0x13C7, 0xAB97, },
    2063             :         { 0x13C8, 0xAB98, },
    2064             :         { 0x13C9, 0xAB99, },
    2065             :         { 0x13CA, 0xAB9A, },
    2066             :         { 0x13CB, 0xAB9B, },
    2067             :         { 0x13CC, 0xAB9C, },
    2068             :         { 0x13CD, 0xAB9D, },
    2069             :         { 0x13CE, 0xAB9E, },
    2070             :         { 0x13CF, 0xAB9F, },
    2071             :         { 0x13D0, 0xABA0, },
    2072             :         { 0x13D1, 0xABA1, },
    2073             :         { 0x13D2, 0xABA2, },
    2074             :         { 0x13D3, 0xABA3, },
    2075             :         { 0x13D4, 0xABA4, },
    2076             :         { 0x13D5, 0xABA5, },
    2077             :         { 0x13D6, 0xABA6, },
    2078             :         { 0x13D7, 0xABA7, },
    2079             :         { 0x13D8, 0xABA8, },
    2080             :         { 0x13D9, 0xABA9, },
    2081             :         { 0x13DA, 0xABAA, },
    2082             :         { 0x13DB, 0xABAB, },
    2083             :         { 0x13DC, 0xABAC, },
    2084             :         { 0x13DD, 0xABAD, },
    2085             :         { 0x13DE, 0xABAE, },
    2086             :         { 0x13DF, 0xABAF, },
    2087             :         { 0x13E0, 0xABB0, },
    2088             :         { 0x13E1, 0xABB1, },
    2089             :         { 0x13E2, 0xABB2, },
    2090             :         { 0x13E3, 0xABB3, },
    2091             :         { 0x13E4, 0xABB4, },
    2092             :         { 0x13E5, 0xABB5, },
    2093             :         { 0x13E6, 0xABB6, },
    2094             :         { 0x13E7, 0xABB7, },
    2095             :         { 0x13E8, 0xABB8, },
    2096             :         { 0x13E9, 0xABB9, },
    2097             :         { 0x13EA, 0xABBA, },
    2098             :         { 0x13EB, 0xABBB, },
    2099             :         { 0x13EC, 0xABBC, },
    2100             :         { 0x13ED, 0xABBD, },
    2101             :         { 0x13EE, 0xABBE, },
    2102             :         { 0x13EF, 0xABBF, },
    2103             :         { 0x13F0, 0x13F8, },
    2104             :         { 0x13F1, 0x13F9, },
    2105             :         { 0x13F2, 0x13FA, },
    2106             :         { 0x13F3, 0x13FB, },
    2107             :         { 0x13F4, 0x13FC, },
    2108             :         { 0x13F5, 0x13FD, },
    2109             :         { 0x1C90, 0x10D0, },
    2110             :         { 0x1C91, 0x10D1, },
    2111             :         { 0x1C92, 0x10D2, },
    2112             :         { 0x1C93, 0x10D3, },
    2113             :         { 0x1C94, 0x10D4, },
    2114             :         { 0x1C95, 0x10D5, },
    2115             :         { 0x1C96, 0x10D6, },
    2116             :         { 0x1C97, 0x10D7, },
    2117             :         { 0x1C98, 0x10D8, },
    2118             :         { 0x1C99, 0x10D9, },
    2119             :         { 0x1C9A, 0x10DA, },
    2120             :         { 0x1C9B, 0x10DB, },
    2121             :         { 0x1C9C, 0x10DC, },
    2122             :         { 0x1C9D, 0x10DD, },
    2123             :         { 0x1C9E, 0x10DE, },
    2124             :         { 0x1C9F, 0x10DF, },
    2125             :         { 0x1CA0, 0x10E0, },
    2126             :         { 0x1CA1, 0x10E1, },
    2127             :         { 0x1CA2, 0x10E2, },
    2128             :         { 0x1CA3, 0x10E3, },
    2129             :         { 0x1CA4, 0x10E4, },
    2130             :         { 0x1CA5, 0x10E5, },
    2131             :         { 0x1CA6, 0x10E6, },
    2132             :         { 0x1CA7, 0x10E7, },
    2133             :         { 0x1CA8, 0x10E8, },
    2134             :         { 0x1CA9, 0x10E9, },
    2135             :         { 0x1CAA, 0x10EA, },
    2136             :         { 0x1CAB, 0x10EB, },
    2137             :         { 0x1CAC, 0x10EC, },
    2138             :         { 0x1CAD, 0x10ED, },
    2139             :         { 0x1CAE, 0x10EE, },
    2140             :         { 0x1CAF, 0x10EF, },
    2141             :         { 0x1CB0, 0x10F0, },
    2142             :         { 0x1CB1, 0x10F1, },
    2143             :         { 0x1CB2, 0x10F2, },
    2144             :         { 0x1CB3, 0x10F3, },
    2145             :         { 0x1CB4, 0x10F4, },
    2146             :         { 0x1CB5, 0x10F5, },
    2147             :         { 0x1CB6, 0x10F6, },
    2148             :         { 0x1CB7, 0x10F7, },
    2149             :         { 0x1CB8, 0x10F8, },
    2150             :         { 0x1CB9, 0x10F9, },
    2151             :         { 0x1CBA, 0x10FA, },
    2152             :         { 0x1CBD, 0x10FD, },
    2153             :         { 0x1CBE, 0x10FE, },
    2154             :         { 0x1CBF, 0x10FF, },
    2155             :         { 0x1E00, 0x1E01, },
    2156             :         { 0x1E02, 0x1E03, },
    2157             :         { 0x1E04, 0x1E05, },
    2158             :         { 0x1E06, 0x1E07, },
    2159             :         { 0x1E08, 0x1E09, },
    2160             :         { 0x1E0A, 0x1E0B, },
    2161             :         { 0x1E0C, 0x1E0D, },
    2162             :         { 0x1E0E, 0x1E0F, },
    2163             :         { 0x1E10, 0x1E11, },
    2164             :         { 0x1E12, 0x1E13, },
    2165             :         { 0x1E14, 0x1E15, },
    2166             :         { 0x1E16, 0x1E17, },
    2167             :         { 0x1E18, 0x1E19, },
    2168             :         { 0x1E1A, 0x1E1B, },
    2169             :         { 0x1E1C, 0x1E1D, },
    2170             :         { 0x1E1E, 0x1E1F, },
    2171             :         { 0x1E20, 0x1E21, },
    2172             :         { 0x1E22, 0x1E23, },
    2173             :         { 0x1E24, 0x1E25, },
    2174             :         { 0x1E26, 0x1E27, },
    2175             :         { 0x1E28, 0x1E29, },
    2176             :         { 0x1E2A, 0x1E2B, },
    2177             :         { 0x1E2C, 0x1E2D, },
    2178             :         { 0x1E2E, 0x1E2F, },
    2179             :         { 0x1E30, 0x1E31, },
    2180             :         { 0x1E32, 0x1E33, },
    2181             :         { 0x1E34, 0x1E35, },
    2182             :         { 0x1E36, 0x1E37, },
    2183             :         { 0x1E38, 0x1E39, },
    2184             :         { 0x1E3A, 0x1E3B, },
    2185             :         { 0x1E3C, 0x1E3D, },
    2186             :         { 0x1E3E, 0x1E3F, },
    2187             :         { 0x1E40, 0x1E41, },
    2188             :         { 0x1E42, 0x1E43, },
    2189             :         { 0x1E44, 0x1E45, },
    2190             :         { 0x1E46, 0x1E47, },
    2191             :         { 0x1E48, 0x1E49, },
    2192             :         { 0x1E4A, 0x1E4B, },
    2193             :         { 0x1E4C, 0x1E4D, },
    2194             :         { 0x1E4E, 0x1E4F, },
    2195             :         { 0x1E50, 0x1E51, },
    2196             :         { 0x1E52, 0x1E53, },
    2197             :         { 0x1E54, 0x1E55, },
    2198             :         { 0x1E56, 0x1E57, },
    2199             :         { 0x1E58, 0x1E59, },
    2200             :         { 0x1E5A, 0x1E5B, },
    2201             :         { 0x1E5C, 0x1E5D, },
    2202             :         { 0x1E5E, 0x1E5F, },
    2203             :         { 0x1E60, 0x1E61, },
    2204             :         { 0x1E62, 0x1E63, },
    2205             :         { 0x1E64, 0x1E65, },
    2206             :         { 0x1E66, 0x1E67, },
    2207             :         { 0x1E68, 0x1E69, },
    2208             :         { 0x1E6A, 0x1E6B, },
    2209             :         { 0x1E6C, 0x1E6D, },
    2210             :         { 0x1E6E, 0x1E6F, },
    2211             :         { 0x1E70, 0x1E71, },
    2212             :         { 0x1E72, 0x1E73, },
    2213             :         { 0x1E74, 0x1E75, },
    2214             :         { 0x1E76, 0x1E77, },
    2215             :         { 0x1E78, 0x1E79, },
    2216             :         { 0x1E7A, 0x1E7B, },
    2217             :         { 0x1E7C, 0x1E7D, },
    2218             :         { 0x1E7E, 0x1E7F, },
    2219             :         { 0x1E80, 0x1E81, },
    2220             :         { 0x1E82, 0x1E83, },
    2221             :         { 0x1E84, 0x1E85, },
    2222             :         { 0x1E86, 0x1E87, },
    2223             :         { 0x1E88, 0x1E89, },
    2224             :         { 0x1E8A, 0x1E8B, },
    2225             :         { 0x1E8C, 0x1E8D, },
    2226             :         { 0x1E8E, 0x1E8F, },
    2227             :         { 0x1E90, 0x1E91, },
    2228             :         { 0x1E92, 0x1E93, },
    2229             :         { 0x1E94, 0x1E95, },
    2230             :         { 0x1E9E, 0x00DF, },
    2231             :         { 0x1EA0, 0x1EA1, },
    2232             :         { 0x1EA2, 0x1EA3, },
    2233             :         { 0x1EA4, 0x1EA5, },
    2234             :         { 0x1EA6, 0x1EA7, },
    2235             :         { 0x1EA8, 0x1EA9, },
    2236             :         { 0x1EAA, 0x1EAB, },
    2237             :         { 0x1EAC, 0x1EAD, },
    2238             :         { 0x1EAE, 0x1EAF, },
    2239             :         { 0x1EB0, 0x1EB1, },
    2240             :         { 0x1EB2, 0x1EB3, },
    2241             :         { 0x1EB4, 0x1EB5, },
    2242             :         { 0x1EB6, 0x1EB7, },
    2243             :         { 0x1EB8, 0x1EB9, },
    2244             :         { 0x1EBA, 0x1EBB, },
    2245             :         { 0x1EBC, 0x1EBD, },
    2246             :         { 0x1EBE, 0x1EBF, },
    2247             :         { 0x1EC0, 0x1EC1, },
    2248             :         { 0x1EC2, 0x1EC3, },
    2249             :         { 0x1EC4, 0x1EC5, },
    2250             :         { 0x1EC6, 0x1EC7, },
    2251             :         { 0x1EC8, 0x1EC9, },
    2252             :         { 0x1ECA, 0x1ECB, },
    2253             :         { 0x1ECC, 0x1ECD, },
    2254             :         { 0x1ECE, 0x1ECF, },
    2255             :         { 0x1ED0, 0x1ED1, },
    2256             :         { 0x1ED2, 0x1ED3, },
    2257             :         { 0x1ED4, 0x1ED5, },
    2258             :         { 0x1ED6, 0x1ED7, },
    2259             :         { 0x1ED8, 0x1ED9, },
    2260             :         { 0x1EDA, 0x1EDB, },
    2261             :         { 0x1EDC, 0x1EDD, },
    2262             :         { 0x1EDE, 0x1EDF, },
    2263             :         { 0x1EE0, 0x1EE1, },
    2264             :         { 0x1EE2, 0x1EE3, },
    2265             :         { 0x1EE4, 0x1EE5, },
    2266             :         { 0x1EE6, 0x1EE7, },
    2267             :         { 0x1EE8, 0x1EE9, },
    2268             :         { 0x1EEA, 0x1EEB, },
    2269             :         { 0x1EEC, 0x1EED, },
    2270             :         { 0x1EEE, 0x1EEF, },
    2271             :         { 0x1EF0, 0x1EF1, },
    2272             :         { 0x1EF2, 0x1EF3, },
    2273             :         { 0x1EF4, 0x1EF5, },
    2274             :         { 0x1EF6, 0x1EF7, },
    2275             :         { 0x1EF8, 0x1EF9, },
    2276             :         { 0x1EFA, 0x1EFB, },
    2277             :         { 0x1EFC, 0x1EFD, },
    2278             :         { 0x1EFE, 0x1EFF, },
    2279             :         { 0x1F08, 0x1F00, },
    2280             :         { 0x1F09, 0x1F01, },
    2281             :         { 0x1F0A, 0x1F02, },
    2282             :         { 0x1F0B, 0x1F03, },
    2283             :         { 0x1F0C, 0x1F04, },
    2284             :         { 0x1F0D, 0x1F05, },
    2285             :         { 0x1F0E, 0x1F06, },
    2286             :         { 0x1F0F, 0x1F07, },
    2287             :         { 0x1F18, 0x1F10, },
    2288             :         { 0x1F19, 0x1F11, },
    2289             :         { 0x1F1A, 0x1F12, },
    2290             :         { 0x1F1B, 0x1F13, },
    2291             :         { 0x1F1C, 0x1F14, },
    2292             :         { 0x1F1D, 0x1F15, },
    2293             :         { 0x1F28, 0x1F20, },
    2294             :         { 0x1F29, 0x1F21, },
    2295             :         { 0x1F2A, 0x1F22, },
    2296             :         { 0x1F2B, 0x1F23, },
    2297             :         { 0x1F2C, 0x1F24, },
    2298             :         { 0x1F2D, 0x1F25, },
    2299             :         { 0x1F2E, 0x1F26, },
    2300             :         { 0x1F2F, 0x1F27, },
    2301             :         { 0x1F38, 0x1F30, },
    2302             :         { 0x1F39, 0x1F31, },
    2303             :         { 0x1F3A, 0x1F32, },
    2304             :         { 0x1F3B, 0x1F33, },
    2305             :         { 0x1F3C, 0x1F34, },
    2306             :         { 0x1F3D, 0x1F35, },
    2307             :         { 0x1F3E, 0x1F36, },
    2308             :         { 0x1F3F, 0x1F37, },
    2309             :         { 0x1F48, 0x1F40, },
    2310             :         { 0x1F49, 0x1F41, },
    2311             :         { 0x1F4A, 0x1F42, },
    2312             :         { 0x1F4B, 0x1F43, },
    2313             :         { 0x1F4C, 0x1F44, },
    2314             :         { 0x1F4D, 0x1F45, },
    2315             :         { 0x1F59, 0x1F51, },
    2316             :         { 0x1F5B, 0x1F53, },
    2317             :         { 0x1F5D, 0x1F55, },
    2318             :         { 0x1F5F, 0x1F57, },
    2319             :         { 0x1F68, 0x1F60, },
    2320             :         { 0x1F69, 0x1F61, },
    2321             :         { 0x1F6A, 0x1F62, },
    2322             :         { 0x1F6B, 0x1F63, },
    2323             :         { 0x1F6C, 0x1F64, },
    2324             :         { 0x1F6D, 0x1F65, },
    2325             :         { 0x1F6E, 0x1F66, },
    2326             :         { 0x1F6F, 0x1F67, },
    2327             :         { 0x1F88, 0x1F80, },
    2328             :         { 0x1F89, 0x1F81, },
    2329             :         { 0x1F8A, 0x1F82, },
    2330             :         { 0x1F8B, 0x1F83, },
    2331             :         { 0x1F8C, 0x1F84, },
    2332             :         { 0x1F8D, 0x1F85, },
    2333             :         { 0x1F8E, 0x1F86, },
    2334             :         { 0x1F8F, 0x1F87, },
    2335             :         { 0x1F98, 0x1F90, },
    2336             :         { 0x1F99, 0x1F91, },
    2337             :         { 0x1F9A, 0x1F92, },
    2338             :         { 0x1F9B, 0x1F93, },
    2339             :         { 0x1F9C, 0x1F94, },
    2340             :         { 0x1F9D, 0x1F95, },
    2341             :         { 0x1F9E, 0x1F96, },
    2342             :         { 0x1F9F, 0x1F97, },
    2343             :         { 0x1FA8, 0x1FA0, },
    2344             :         { 0x1FA9, 0x1FA1, },
    2345             :         { 0x1FAA, 0x1FA2, },
    2346             :         { 0x1FAB, 0x1FA3, },
    2347             :         { 0x1FAC, 0x1FA4, },
    2348             :         { 0x1FAD, 0x1FA5, },
    2349             :         { 0x1FAE, 0x1FA6, },
    2350             :         { 0x1FAF, 0x1FA7, },
    2351             :         { 0x1FB8, 0x1FB0, },
    2352             :         { 0x1FB9, 0x1FB1, },
    2353             :         { 0x1FBA, 0x1F70, },
    2354             :         { 0x1FBB, 0x1F71, },
    2355             :         { 0x1FBC, 0x1FB3, },
    2356             :         { 0x1FC8, 0x1F72, },
    2357             :         { 0x1FC9, 0x1F73, },
    2358             :         { 0x1FCA, 0x1F74, },
    2359             :         { 0x1FCB, 0x1F75, },
    2360             :         { 0x1FCC, 0x1FC3, },
    2361             :         { 0x1FD8, 0x1FD0, },
    2362             :         { 0x1FD9, 0x1FD1, },
    2363             :         { 0x1FDA, 0x1F76, },
    2364             :         { 0x1FDB, 0x1F77, },
    2365             :         { 0x1FE8, 0x1FE0, },
    2366             :         { 0x1FE9, 0x1FE1, },
    2367             :         { 0x1FEA, 0x1F7A, },
    2368             :         { 0x1FEB, 0x1F7B, },
    2369             :         { 0x1FEC, 0x1FE5, },
    2370             :         { 0x1FF8, 0x1F78, },
    2371             :         { 0x1FF9, 0x1F79, },
    2372             :         { 0x1FFA, 0x1F7C, },
    2373             :         { 0x1FFB, 0x1F7D, },
    2374             :         { 0x1FFC, 0x1FF3, },
    2375             :         { 0x2126, 0x03C9, },
    2376             :         { 0x212A, 0x006B, },
    2377             :         { 0x212B, 0x00E5, },
    2378             :         { 0x2132, 0x214E, },
    2379             :         { 0x2160, 0x2170, },
    2380             :         { 0x2161, 0x2171, },
    2381             :         { 0x2162, 0x2172, },
    2382             :         { 0x2163, 0x2173, },
    2383             :         { 0x2164, 0x2174, },
    2384             :         { 0x2165, 0x2175, },
    2385             :         { 0x2166, 0x2176, },
    2386             :         { 0x2167, 0x2177, },
    2387             :         { 0x2168, 0x2178, },
    2388             :         { 0x2169, 0x2179, },
    2389             :         { 0x216A, 0x217A, },
    2390             :         { 0x216B, 0x217B, },
    2391             :         { 0x216C, 0x217C, },
    2392             :         { 0x216D, 0x217D, },
    2393             :         { 0x216E, 0x217E, },
    2394             :         { 0x216F, 0x217F, },
    2395             :         { 0x2183, 0x2184, },
    2396             :         { 0x24B6, 0x24D0, },
    2397             :         { 0x24B7, 0x24D1, },
    2398             :         { 0x24B8, 0x24D2, },
    2399             :         { 0x24B9, 0x24D3, },
    2400             :         { 0x24BA, 0x24D4, },
    2401             :         { 0x24BB, 0x24D5, },
    2402             :         { 0x24BC, 0x24D6, },
    2403             :         { 0x24BD, 0x24D7, },
    2404             :         { 0x24BE, 0x24D8, },
    2405             :         { 0x24BF, 0x24D9, },
    2406             :         { 0x24C0, 0x24DA, },
    2407             :         { 0x24C1, 0x24DB, },
    2408             :         { 0x24C2, 0x24DC, },
    2409             :         { 0x24C3, 0x24DD, },
    2410             :         { 0x24C4, 0x24DE, },
    2411             :         { 0x24C5, 0x24DF, },
    2412             :         { 0x24C6, 0x24E0, },
    2413             :         { 0x24C7, 0x24E1, },
    2414             :         { 0x24C8, 0x24E2, },
    2415             :         { 0x24C9, 0x24E3, },
    2416             :         { 0x24CA, 0x24E4, },
    2417             :         { 0x24CB, 0x24E5, },
    2418             :         { 0x24CC, 0x24E6, },
    2419             :         { 0x24CD, 0x24E7, },
    2420             :         { 0x24CE, 0x24E8, },
    2421             :         { 0x24CF, 0x24E9, },
    2422             :         { 0x2C00, 0x2C30, },
    2423             :         { 0x2C01, 0x2C31, },
    2424             :         { 0x2C02, 0x2C32, },
    2425             :         { 0x2C03, 0x2C33, },
    2426             :         { 0x2C04, 0x2C34, },
    2427             :         { 0x2C05, 0x2C35, },
    2428             :         { 0x2C06, 0x2C36, },
    2429             :         { 0x2C07, 0x2C37, },
    2430             :         { 0x2C08, 0x2C38, },
    2431             :         { 0x2C09, 0x2C39, },
    2432             :         { 0x2C0A, 0x2C3A, },
    2433             :         { 0x2C0B, 0x2C3B, },
    2434             :         { 0x2C0C, 0x2C3C, },
    2435             :         { 0x2C0D, 0x2C3D, },
    2436             :         { 0x2C0E, 0x2C3E, },
    2437             :         { 0x2C0F, 0x2C3F, },
    2438             :         { 0x2C10, 0x2C40, },
    2439             :         { 0x2C11, 0x2C41, },
    2440             :         { 0x2C12, 0x2C42, },
    2441             :         { 0x2C13, 0x2C43, },
    2442             :         { 0x2C14, 0x2C44, },
    2443             :         { 0x2C15, 0x2C45, },
    2444             :         { 0x2C16, 0x2C46, },
    2445             :         { 0x2C17, 0x2C47, },
    2446             :         { 0x2C18, 0x2C48, },
    2447             :         { 0x2C19, 0x2C49, },
    2448             :         { 0x2C1A, 0x2C4A, },
    2449             :         { 0x2C1B, 0x2C4B, },
    2450             :         { 0x2C1C, 0x2C4C, },
    2451             :         { 0x2C1D, 0x2C4D, },
    2452             :         { 0x2C1E, 0x2C4E, },
    2453             :         { 0x2C1F, 0x2C4F, },
    2454             :         { 0x2C20, 0x2C50, },
    2455             :         { 0x2C21, 0x2C51, },
    2456             :         { 0x2C22, 0x2C52, },
    2457             :         { 0x2C23, 0x2C53, },
    2458             :         { 0x2C24, 0x2C54, },
    2459             :         { 0x2C25, 0x2C55, },
    2460             :         { 0x2C26, 0x2C56, },
    2461             :         { 0x2C27, 0x2C57, },
    2462             :         { 0x2C28, 0x2C58, },
    2463             :         { 0x2C29, 0x2C59, },
    2464             :         { 0x2C2A, 0x2C5A, },
    2465             :         { 0x2C2B, 0x2C5B, },
    2466             :         { 0x2C2C, 0x2C5C, },
    2467             :         { 0x2C2D, 0x2C5D, },
    2468             :         { 0x2C2E, 0x2C5E, },
    2469             :         { 0x2C60, 0x2C61, },
    2470             :         { 0x2C62, 0x026B, },
    2471             :         { 0x2C63, 0x1D7D, },
    2472             :         { 0x2C64, 0x027D, },
    2473             :         { 0x2C67, 0x2C68, },
    2474             :         { 0x2C69, 0x2C6A, },
    2475             :         { 0x2C6B, 0x2C6C, },
    2476             :         { 0x2C6D, 0x0251, },
    2477             :         { 0x2C6E, 0x0271, },
    2478             :         { 0x2C6F, 0x0250, },
    2479             :         { 0x2C70, 0x0252, },
    2480             :         { 0x2C72, 0x2C73, },
    2481             :         { 0x2C75, 0x2C76, },
    2482             :         { 0x2C7E, 0x023F, },
    2483             :         { 0x2C7F, 0x0240, },
    2484             :         { 0x2C80, 0x2C81, },
    2485             :         { 0x2C82, 0x2C83, },
    2486             :         { 0x2C84, 0x2C85, },
    2487             :         { 0x2C86, 0x2C87, },
    2488             :         { 0x2C88, 0x2C89, },
    2489             :         { 0x2C8A, 0x2C8B, },
    2490             :         { 0x2C8C, 0x2C8D, },
    2491             :         { 0x2C8E, 0x2C8F, },
    2492             :         { 0x2C90, 0x2C91, },
    2493             :         { 0x2C92, 0x2C93, },
    2494             :         { 0x2C94, 0x2C95, },
    2495             :         { 0x2C96, 0x2C97, },
    2496             :         { 0x2C98, 0x2C99, },
    2497             :         { 0x2C9A, 0x2C9B, },
    2498             :         { 0x2C9C, 0x2C9D, },
    2499             :         { 0x2C9E, 0x2C9F, },
    2500             :         { 0x2CA0, 0x2CA1, },
    2501             :         { 0x2CA2, 0x2CA3, },
    2502             :         { 0x2CA4, 0x2CA5, },
    2503             :         { 0x2CA6, 0x2CA7, },
    2504             :         { 0x2CA8, 0x2CA9, },
    2505             :         { 0x2CAA, 0x2CAB, },
    2506             :         { 0x2CAC, 0x2CAD, },
    2507             :         { 0x2CAE, 0x2CAF, },
    2508             :         { 0x2CB0, 0x2CB1, },
    2509             :         { 0x2CB2, 0x2CB3, },
    2510             :         { 0x2CB4, 0x2CB5, },
    2511             :         { 0x2CB6, 0x2CB7, },
    2512             :         { 0x2CB8, 0x2CB9, },
    2513             :         { 0x2CBA, 0x2CBB, },
    2514             :         { 0x2CBC, 0x2CBD, },
    2515             :         { 0x2CBE, 0x2CBF, },
    2516             :         { 0x2CC0, 0x2CC1, },
    2517             :         { 0x2CC2, 0x2CC3, },
    2518             :         { 0x2CC4, 0x2CC5, },
    2519             :         { 0x2CC6, 0x2CC7, },
    2520             :         { 0x2CC8, 0x2CC9, },
    2521             :         { 0x2CCA, 0x2CCB, },
    2522             :         { 0x2CCC, 0x2CCD, },
    2523             :         { 0x2CCE, 0x2CCF, },
    2524             :         { 0x2CD0, 0x2CD1, },
    2525             :         { 0x2CD2, 0x2CD3, },
    2526             :         { 0x2CD4, 0x2CD5, },
    2527             :         { 0x2CD6, 0x2CD7, },
    2528             :         { 0x2CD8, 0x2CD9, },
    2529             :         { 0x2CDA, 0x2CDB, },
    2530             :         { 0x2CDC, 0x2CDD, },
    2531             :         { 0x2CDE, 0x2CDF, },
    2532             :         { 0x2CE0, 0x2CE1, },
    2533             :         { 0x2CE2, 0x2CE3, },
    2534             :         { 0x2CEB, 0x2CEC, },
    2535             :         { 0x2CED, 0x2CEE, },
    2536             :         { 0x2CF2, 0x2CF3, },
    2537             :         { 0xA640, 0xA641, },
    2538             :         { 0xA642, 0xA643, },
    2539             :         { 0xA644, 0xA645, },
    2540             :         { 0xA646, 0xA647, },
    2541             :         { 0xA648, 0xA649, },
    2542             :         { 0xA64A, 0xA64B, },
    2543             :         { 0xA64C, 0xA64D, },
    2544             :         { 0xA64E, 0xA64F, },
    2545             :         { 0xA650, 0xA651, },
    2546             :         { 0xA652, 0xA653, },
    2547             :         { 0xA654, 0xA655, },
    2548             :         { 0xA656, 0xA657, },
    2549             :         { 0xA658, 0xA659, },
    2550             :         { 0xA65A, 0xA65B, },
    2551             :         { 0xA65C, 0xA65D, },
    2552             :         { 0xA65E, 0xA65F, },
    2553             :         { 0xA660, 0xA661, },
    2554             :         { 0xA662, 0xA663, },
    2555             :         { 0xA664, 0xA665, },
    2556             :         { 0xA666, 0xA667, },
    2557             :         { 0xA668, 0xA669, },
    2558             :         { 0xA66A, 0xA66B, },
    2559             :         { 0xA66C, 0xA66D, },
    2560             :         { 0xA680, 0xA681, },
    2561             :         { 0xA682, 0xA683, },
    2562             :         { 0xA684, 0xA685, },
    2563             :         { 0xA686, 0xA687, },
    2564             :         { 0xA688, 0xA689, },
    2565             :         { 0xA68A, 0xA68B, },
    2566             :         { 0xA68C, 0xA68D, },
    2567             :         { 0xA68E, 0xA68F, },
    2568             :         { 0xA690, 0xA691, },
    2569             :         { 0xA692, 0xA693, },
    2570             :         { 0xA694, 0xA695, },
    2571             :         { 0xA696, 0xA697, },
    2572             :         { 0xA698, 0xA699, },
    2573             :         { 0xA69A, 0xA69B, },
    2574             :         { 0xA722, 0xA723, },
    2575             :         { 0xA724, 0xA725, },
    2576             :         { 0xA726, 0xA727, },
    2577             :         { 0xA728, 0xA729, },
    2578             :         { 0xA72A, 0xA72B, },
    2579             :         { 0xA72C, 0xA72D, },
    2580             :         { 0xA72E, 0xA72F, },
    2581             :         { 0xA732, 0xA733, },
    2582             :         { 0xA734, 0xA735, },
    2583             :         { 0xA736, 0xA737, },
    2584             :         { 0xA738, 0xA739, },
    2585             :         { 0xA73A, 0xA73B, },
    2586             :         { 0xA73C, 0xA73D, },
    2587             :         { 0xA73E, 0xA73F, },
    2588             :         { 0xA740, 0xA741, },
    2589             :         { 0xA742, 0xA743, },
    2590             :         { 0xA744, 0xA745, },
    2591             :         { 0xA746, 0xA747, },
    2592             :         { 0xA748, 0xA749, },
    2593             :         { 0xA74A, 0xA74B, },
    2594             :         { 0xA74C, 0xA74D, },
    2595             :         { 0xA74E, 0xA74F, },
    2596             :         { 0xA750, 0xA751, },
    2597             :         { 0xA752, 0xA753, },
    2598             :         { 0xA754, 0xA755, },
    2599             :         { 0xA756, 0xA757, },
    2600             :         { 0xA758, 0xA759, },
    2601             :         { 0xA75A, 0xA75B, },
    2602             :         { 0xA75C, 0xA75D, },
    2603             :         { 0xA75E, 0xA75F, },
    2604             :         { 0xA760, 0xA761, },
    2605             :         { 0xA762, 0xA763, },
    2606             :         { 0xA764, 0xA765, },
    2607             :         { 0xA766, 0xA767, },
    2608             :         { 0xA768, 0xA769, },
    2609             :         { 0xA76A, 0xA76B, },
    2610             :         { 0xA76C, 0xA76D, },
    2611             :         { 0xA76E, 0xA76F, },
    2612             :         { 0xA779, 0xA77A, },
    2613             :         { 0xA77B, 0xA77C, },
    2614             :         { 0xA77D, 0x1D79, },
    2615             :         { 0xA77E, 0xA77F, },
    2616             :         { 0xA780, 0xA781, },
    2617             :         { 0xA782, 0xA783, },
    2618             :         { 0xA784, 0xA785, },
    2619             :         { 0xA786, 0xA787, },
    2620             :         { 0xA78B, 0xA78C, },
    2621             :         { 0xA78D, 0x0265, },
    2622             :         { 0xA790, 0xA791, },
    2623             :         { 0xA792, 0xA793, },
    2624             :         { 0xA796, 0xA797, },
    2625             :         { 0xA798, 0xA799, },
    2626             :         { 0xA79A, 0xA79B, },
    2627             :         { 0xA79C, 0xA79D, },
    2628             :         { 0xA79E, 0xA79F, },
    2629             :         { 0xA7A0, 0xA7A1, },
    2630             :         { 0xA7A2, 0xA7A3, },
    2631             :         { 0xA7A4, 0xA7A5, },
    2632             :         { 0xA7A6, 0xA7A7, },
    2633             :         { 0xA7A8, 0xA7A9, },
    2634             :         { 0xA7AA, 0x0266, },
    2635             :         { 0xA7AB, 0x025C, },
    2636             :         { 0xA7AC, 0x0261, },
    2637             :         { 0xA7AD, 0x026C, },
    2638             :         { 0xA7AE, 0x026A, },
    2639             :         { 0xA7B0, 0x029E, },
    2640             :         { 0xA7B1, 0x0287, },
    2641             :         { 0xA7B2, 0x029D, },
    2642             :         { 0xA7B3, 0xAB53, },
    2643             :         { 0xA7B4, 0xA7B5, },
    2644             :         { 0xA7B6, 0xA7B7, },
    2645             :         { 0xA7B8, 0xA7B9, },
    2646             :         { 0xA7BA, 0xA7BB, },
    2647             :         { 0xA7BC, 0xA7BD, },
    2648             :         { 0xA7BE, 0xA7BF, },
    2649             :         { 0xA7C2, 0xA7C3, },
    2650             :         { 0xA7C4, 0xA794, },
    2651             :         { 0xA7C5, 0x0282, },
    2652             :         { 0xA7C6, 0x1D8E, },
    2653             :         { 0xA7C7, 0xA7C8, },
    2654             :         { 0xA7C9, 0xA7CA, },
    2655             :         { 0xA7F5, 0xA7F6, },
    2656             :         { 0xFF21, 0xFF41, },
    2657             :         { 0xFF22, 0xFF42, },
    2658             :         { 0xFF23, 0xFF43, },
    2659             :         { 0xFF24, 0xFF44, },
    2660             :         { 0xFF25, 0xFF45, },
    2661             :         { 0xFF26, 0xFF46, },
    2662             :         { 0xFF27, 0xFF47, },
    2663             :         { 0xFF28, 0xFF48, },
    2664             :         { 0xFF29, 0xFF49, },
    2665             :         { 0xFF2A, 0xFF4A, },
    2666             :         { 0xFF2B, 0xFF4B, },
    2667             :         { 0xFF2C, 0xFF4C, },
    2668             :         { 0xFF2D, 0xFF4D, },
    2669             :         { 0xFF2E, 0xFF4E, },
    2670             :         { 0xFF2F, 0xFF4F, },
    2671             :         { 0xFF30, 0xFF50, },
    2672             :         { 0xFF31, 0xFF51, },
    2673             :         { 0xFF32, 0xFF52, },
    2674             :         { 0xFF33, 0xFF53, },
    2675             :         { 0xFF34, 0xFF54, },
    2676             :         { 0xFF35, 0xFF55, },
    2677             :         { 0xFF36, 0xFF56, },
    2678             :         { 0xFF37, 0xFF57, },
    2679             :         { 0xFF38, 0xFF58, },
    2680             :         { 0xFF39, 0xFF59, },
    2681             :         { 0xFF3A, 0xFF5A, },
    2682             :         { 0x10400, 0x10428, },
    2683             :         { 0x10401, 0x10429, },
    2684             :         { 0x10402, 0x1042A, },
    2685             :         { 0x10403, 0x1042B, },
    2686             :         { 0x10404, 0x1042C, },
    2687             :         { 0x10405, 0x1042D, },
    2688             :         { 0x10406, 0x1042E, },
    2689             :         { 0x10407, 0x1042F, },
    2690             :         { 0x10408, 0x10430, },
    2691             :         { 0x10409, 0x10431, },
    2692             :         { 0x1040A, 0x10432, },
    2693             :         { 0x1040B, 0x10433, },
    2694             :         { 0x1040C, 0x10434, },
    2695             :         { 0x1040D, 0x10435, },
    2696             :         { 0x1040E, 0x10436, },
    2697             :         { 0x1040F, 0x10437, },
    2698             :         { 0x10410, 0x10438, },
    2699             :         { 0x10411, 0x10439, },
    2700             :         { 0x10412, 0x1043A, },
    2701             :         { 0x10413, 0x1043B, },
    2702             :         { 0x10414, 0x1043C, },
    2703             :         { 0x10415, 0x1043D, },
    2704             :         { 0x10416, 0x1043E, },
    2705             :         { 0x10417, 0x1043F, },
    2706             :         { 0x10418, 0x10440, },
    2707             :         { 0x10419, 0x10441, },
    2708             :         { 0x1041A, 0x10442, },
    2709             :         { 0x1041B, 0x10443, },
    2710             :         { 0x1041C, 0x10444, },
    2711             :         { 0x1041D, 0x10445, },
    2712             :         { 0x1041E, 0x10446, },
    2713             :         { 0x1041F, 0x10447, },
    2714             :         { 0x10420, 0x10448, },
    2715             :         { 0x10421, 0x10449, },
    2716             :         { 0x10422, 0x1044A, },
    2717             :         { 0x10423, 0x1044B, },
    2718             :         { 0x10424, 0x1044C, },
    2719             :         { 0x10425, 0x1044D, },
    2720             :         { 0x10426, 0x1044E, },
    2721             :         { 0x10427, 0x1044F, },
    2722             :         { 0x104B0, 0x104D8, },
    2723             :         { 0x104B1, 0x104D9, },
    2724             :         { 0x104B2, 0x104DA, },
    2725             :         { 0x104B3, 0x104DB, },
    2726             :         { 0x104B4, 0x104DC, },
    2727             :         { 0x104B5, 0x104DD, },
    2728             :         { 0x104B6, 0x104DE, },
    2729             :         { 0x104B7, 0x104DF, },
    2730             :         { 0x104B8, 0x104E0, },
    2731             :         { 0x104B9, 0x104E1, },
    2732             :         { 0x104BA, 0x104E2, },
    2733             :         { 0x104BB, 0x104E3, },
    2734             :         { 0x104BC, 0x104E4, },
    2735             :         { 0x104BD, 0x104E5, },
    2736             :         { 0x104BE, 0x104E6, },
    2737             :         { 0x104BF, 0x104E7, },
    2738             :         { 0x104C0, 0x104E8, },
    2739             :         { 0x104C1, 0x104E9, },
    2740             :         { 0x104C2, 0x104EA, },
    2741             :         { 0x104C3, 0x104EB, },
    2742             :         { 0x104C4, 0x104EC, },
    2743             :         { 0x104C5, 0x104ED, },
    2744             :         { 0x104C6, 0x104EE, },
    2745             :         { 0x104C7, 0x104EF, },
    2746             :         { 0x104C8, 0x104F0, },
    2747             :         { 0x104C9, 0x104F1, },
    2748             :         { 0x104CA, 0x104F2, },
    2749             :         { 0x104CB, 0x104F3, },
    2750             :         { 0x104CC, 0x104F4, },
    2751             :         { 0x104CD, 0x104F5, },
    2752             :         { 0x104CE, 0x104F6, },
    2753             :         { 0x104CF, 0x104F7, },
    2754             :         { 0x104D0, 0x104F8, },
    2755             :         { 0x104D1, 0x104F9, },
    2756             :         { 0x104D2, 0x104FA, },
    2757             :         { 0x104D3, 0x104FB, },
    2758             :         { 0x10C80, 0x10CC0, },
    2759             :         { 0x10C81, 0x10CC1, },
    2760             :         { 0x10C82, 0x10CC2, },
    2761             :         { 0x10C83, 0x10CC3, },
    2762             :         { 0x10C84, 0x10CC4, },
    2763             :         { 0x10C85, 0x10CC5, },
    2764             :         { 0x10C86, 0x10CC6, },
    2765             :         { 0x10C87, 0x10CC7, },
    2766             :         { 0x10C88, 0x10CC8, },
    2767             :         { 0x10C89, 0x10CC9, },
    2768             :         { 0x10C8A, 0x10CCA, },
    2769             :         { 0x10C8B, 0x10CCB, },
    2770             :         { 0x10C8C, 0x10CCC, },
    2771             :         { 0x10C8D, 0x10CCD, },
    2772             :         { 0x10C8E, 0x10CCE, },
    2773             :         { 0x10C8F, 0x10CCF, },
    2774             :         { 0x10C90, 0x10CD0, },
    2775             :         { 0x10C91, 0x10CD1, },
    2776             :         { 0x10C92, 0x10CD2, },
    2777             :         { 0x10C93, 0x10CD3, },
    2778             :         { 0x10C94, 0x10CD4, },
    2779             :         { 0x10C95, 0x10CD5, },
    2780             :         { 0x10C96, 0x10CD6, },
    2781             :         { 0x10C97, 0x10CD7, },
    2782             :         { 0x10C98, 0x10CD8, },
    2783             :         { 0x10C99, 0x10CD9, },
    2784             :         { 0x10C9A, 0x10CDA, },
    2785             :         { 0x10C9B, 0x10CDB, },
    2786             :         { 0x10C9C, 0x10CDC, },
    2787             :         { 0x10C9D, 0x10CDD, },
    2788             :         { 0x10C9E, 0x10CDE, },
    2789             :         { 0x10C9F, 0x10CDF, },
    2790             :         { 0x10CA0, 0x10CE0, },
    2791             :         { 0x10CA1, 0x10CE1, },
    2792             :         { 0x10CA2, 0x10CE2, },
    2793             :         { 0x10CA3, 0x10CE3, },
    2794             :         { 0x10CA4, 0x10CE4, },
    2795             :         { 0x10CA5, 0x10CE5, },
    2796             :         { 0x10CA6, 0x10CE6, },
    2797             :         { 0x10CA7, 0x10CE7, },
    2798             :         { 0x10CA8, 0x10CE8, },
    2799             :         { 0x10CA9, 0x10CE9, },
    2800             :         { 0x10CAA, 0x10CEA, },
    2801             :         { 0x10CAB, 0x10CEB, },
    2802             :         { 0x10CAC, 0x10CEC, },
    2803             :         { 0x10CAD, 0x10CED, },
    2804             :         { 0x10CAE, 0x10CEE, },
    2805             :         { 0x10CAF, 0x10CEF, },
    2806             :         { 0x10CB0, 0x10CF0, },
    2807             :         { 0x10CB1, 0x10CF1, },
    2808             :         { 0x10CB2, 0x10CF2, },
    2809             :         { 0x118A0, 0x118C0, },
    2810             :         { 0x118A1, 0x118C1, },
    2811             :         { 0x118A2, 0x118C2, },
    2812             :         { 0x118A3, 0x118C3, },
    2813             :         { 0x118A4, 0x118C4, },
    2814             :         { 0x118A5, 0x118C5, },
    2815             :         { 0x118A6, 0x118C6, },
    2816             :         { 0x118A7, 0x118C7, },
    2817             :         { 0x118A8, 0x118C8, },
    2818             :         { 0x118A9, 0x118C9, },
    2819             :         { 0x118AA, 0x118CA, },
    2820             :         { 0x118AB, 0x118CB, },
    2821             :         { 0x118AC, 0x118CC, },
    2822             :         { 0x118AD, 0x118CD, },
    2823             :         { 0x118AE, 0x118CE, },
    2824             :         { 0x118AF, 0x118CF, },
    2825             :         { 0x118B0, 0x118D0, },
    2826             :         { 0x118B1, 0x118D1, },
    2827             :         { 0x118B2, 0x118D2, },
    2828             :         { 0x118B3, 0x118D3, },
    2829             :         { 0x118B4, 0x118D4, },
    2830             :         { 0x118B5, 0x118D5, },
    2831             :         { 0x118B6, 0x118D6, },
    2832             :         { 0x118B7, 0x118D7, },
    2833             :         { 0x118B8, 0x118D8, },
    2834             :         { 0x118B9, 0x118D9, },
    2835             :         { 0x118BA, 0x118DA, },
    2836             :         { 0x118BB, 0x118DB, },
    2837             :         { 0x118BC, 0x118DC, },
    2838             :         { 0x118BD, 0x118DD, },
    2839             :         { 0x118BE, 0x118DE, },
    2840             :         { 0x118BF, 0x118DF, },
    2841             :         { 0x16E40, 0x16E60, },
    2842             :         { 0x16E41, 0x16E61, },
    2843             :         { 0x16E42, 0x16E62, },
    2844             :         { 0x16E43, 0x16E63, },
    2845             :         { 0x16E44, 0x16E64, },
    2846             :         { 0x16E45, 0x16E65, },
    2847             :         { 0x16E46, 0x16E66, },
    2848             :         { 0x16E47, 0x16E67, },
    2849             :         { 0x16E48, 0x16E68, },
    2850             :         { 0x16E49, 0x16E69, },
    2851             :         { 0x16E4A, 0x16E6A, },
    2852             :         { 0x16E4B, 0x16E6B, },
    2853             :         { 0x16E4C, 0x16E6C, },
    2854             :         { 0x16E4D, 0x16E6D, },
    2855             :         { 0x16E4E, 0x16E6E, },
    2856             :         { 0x16E4F, 0x16E6F, },
    2857             :         { 0x16E50, 0x16E70, },
    2858             :         { 0x16E51, 0x16E71, },
    2859             :         { 0x16E52, 0x16E72, },
    2860             :         { 0x16E53, 0x16E73, },
    2861             :         { 0x16E54, 0x16E74, },
    2862             :         { 0x16E55, 0x16E75, },
    2863             :         { 0x16E56, 0x16E76, },
    2864             :         { 0x16E57, 0x16E77, },
    2865             :         { 0x16E58, 0x16E78, },
    2866             :         { 0x16E59, 0x16E79, },
    2867             :         { 0x16E5A, 0x16E7A, },
    2868             :         { 0x16E5B, 0x16E7B, },
    2869             :         { 0x16E5C, 0x16E7C, },
    2870             :         { 0x16E5D, 0x16E7D, },
    2871             :         { 0x16E5E, 0x16E7E, },
    2872             :         { 0x16E5F, 0x16E7F, },
    2873             :         { 0x1E900, 0x1E922, },
    2874             :         { 0x1E901, 0x1E923, },
    2875             :         { 0x1E902, 0x1E924, },
    2876             :         { 0x1E903, 0x1E925, },
    2877             :         { 0x1E904, 0x1E926, },
    2878             :         { 0x1E905, 0x1E927, },
    2879             :         { 0x1E906, 0x1E928, },
    2880             :         { 0x1E907, 0x1E929, },
    2881             :         { 0x1E908, 0x1E92A, },
    2882             :         { 0x1E909, 0x1E92B, },
    2883             :         { 0x1E90A, 0x1E92C, },
    2884             :         { 0x1E90B, 0x1E92D, },
    2885             :         { 0x1E90C, 0x1E92E, },
    2886             :         { 0x1E90D, 0x1E92F, },
    2887             :         { 0x1E90E, 0x1E930, },
    2888             :         { 0x1E90F, 0x1E931, },
    2889             :         { 0x1E910, 0x1E932, },
    2890             :         { 0x1E911, 0x1E933, },
    2891             :         { 0x1E912, 0x1E934, },
    2892             :         { 0x1E913, 0x1E935, },
    2893             :         { 0x1E914, 0x1E936, },
    2894             :         { 0x1E915, 0x1E937, },
    2895             :         { 0x1E916, 0x1E938, },
    2896             :         { 0x1E917, 0x1E939, },
    2897             :         { 0x1E918, 0x1E93A, },
    2898             :         { 0x1E919, 0x1E93B, },
    2899             :         { 0x1E91A, 0x1E93C, },
    2900             :         { 0x1E91B, 0x1E93D, },
    2901             :         { 0x1E91C, 0x1E93E, },
    2902             :         { 0x1E91D, 0x1E93F, },
    2903             :         { 0x1E91E, 0x1E940, },
    2904             :         { 0x1E91F, 0x1E941, },
    2905             :         { 0x1E920, 0x1E942, },
    2906             :         { 0x1E921, 0x1E943, },
    2907             : };
    2908             : 
    2909             : static BAT *UTF8_toUpperFrom = NULL, *UTF8_toUpperTo = NULL,
    2910             :         *UTF8_toLowerFrom = NULL, *UTF8_toLowerTo = NULL;
    2911             : 
    2912             : static str
    2913         266 : STRprelude(void *ret)
    2914             : {
    2915             :         (void) ret;
    2916         266 :         if (UTF8_toUpperFrom == NULL) {
    2917             :                 size_t i;
    2918             : 
    2919         266 :                 UTF8_toUpperFrom = COLnew(0, TYPE_int, sizeof(UTF8_toUpper) / sizeof(UTF8_toUpper[0]), TRANSIENT);
    2920         266 :                 UTF8_toUpperTo = COLnew(0, TYPE_int, sizeof(UTF8_toUpper) / sizeof(UTF8_toUpper[0]), TRANSIENT);
    2921         266 :                 UTF8_toLowerFrom = COLnew(0, TYPE_int, sizeof(UTF8_toLower) / sizeof(UTF8_toLower[0]), TRANSIENT);
    2922         266 :                 UTF8_toLowerTo = COLnew(0, TYPE_int, sizeof(UTF8_toLower) / sizeof(UTF8_toLower[0]), TRANSIENT);
    2923         266 :                 if (UTF8_toUpperFrom == NULL || UTF8_toUpperTo == NULL ||
    2924         266 :                         UTF8_toLowerFrom == NULL || UTF8_toLowerTo == NULL) {
    2925           0 :                         goto bailout;
    2926             :                 }
    2927             : 
    2928         266 :                 int *fp = (int *) Tloc(UTF8_toUpperFrom, 0);
    2929         266 :                 int *tp = (int *) Tloc(UTF8_toUpperTo, 0);
    2930      375326 :                 for (i = 0; i < sizeof(UTF8_toUpper) / sizeof(UTF8_toUpper[0]); i++) {
    2931      375060 :                         fp[i] = UTF8_toUpper[i].from;
    2932      375060 :                         tp[i] = UTF8_toUpper[i].to;
    2933             :                 }
    2934         266 :                 UTF8_toUpperFrom->tkey = true;
    2935         266 :                 UTF8_toUpperFrom->tsorted = true;
    2936         266 :                 UTF8_toUpperFrom->trevsorted = false;
    2937         266 :                 UTF8_toUpperFrom->tnil = false;
    2938         266 :                 UTF8_toUpperFrom->tnonil = true;
    2939         266 :                 BATsetcount(UTF8_toUpperFrom, i);
    2940         266 :                 UTF8_toUpperTo->tkey = false;
    2941         266 :                 UTF8_toUpperTo->tsorted = false;
    2942         266 :                 UTF8_toUpperTo->trevsorted = false;
    2943         266 :                 UTF8_toUpperTo->tnil = false;
    2944         266 :                 UTF8_toUpperTo->tnonil = true;
    2945         266 :                 BATsetcount(UTF8_toUpperTo, i);
    2946             : 
    2947         266 :                 fp = (int *) Tloc(UTF8_toLowerFrom, 0);
    2948         266 :                 tp = (int *) Tloc(UTF8_toLowerTo, 0);
    2949      370804 :                 for (i = 0; i < sizeof(UTF8_toLower) / sizeof(UTF8_toLower[0]); i++) {
    2950      370538 :                         fp[i] = UTF8_toLower[i].from;
    2951      370538 :                         tp[i] = UTF8_toLower[i].to;
    2952             :                 }
    2953         266 :                 UTF8_toLowerFrom->tkey = true;
    2954         266 :                 UTF8_toLowerFrom->tsorted = true;
    2955         266 :                 UTF8_toLowerFrom->trevsorted = false;
    2956         266 :                 UTF8_toLowerFrom->tnil = false;
    2957         266 :                 UTF8_toLowerFrom->tnonil = true;
    2958         266 :                 BATsetcount(UTF8_toLowerFrom, i);
    2959         266 :                 UTF8_toLowerTo->tkey = false;
    2960         266 :                 UTF8_toLowerTo->tsorted = false;
    2961         266 :                 UTF8_toLowerTo->trevsorted = false;
    2962         266 :                 UTF8_toLowerTo->tnil = false;
    2963         266 :                 UTF8_toLowerTo->tnonil = true;
    2964         266 :                 BATsetcount(UTF8_toLowerTo, i);
    2965             : 
    2966         532 :                 if (BBPrename(UTF8_toUpperFrom->batCacheid, "monet_unicode_upper_from") != 0 ||
    2967         532 :                         BBPrename(UTF8_toUpperTo->batCacheid, "monet_unicode_upper_to") != 0 ||
    2968         532 :                         BBPrename(UTF8_toLowerFrom->batCacheid, "monet_unicode_lower_from") != 0 ||
    2969         266 :                         BBPrename(UTF8_toLowerTo->batCacheid, "monet_unicode_lower_to") != 0) {
    2970           0 :                         goto bailout;
    2971             :                 }
    2972         266 :                 BBP_pid(UTF8_toUpperFrom->batCacheid) = 0;
    2973         266 :                 BBP_pid(UTF8_toUpperTo->batCacheid) = 0;
    2974         266 :                 BBP_pid(UTF8_toLowerFrom->batCacheid) = 0;
    2975         266 :                 BBP_pid(UTF8_toLowerTo->batCacheid) = 0;
    2976             :         }
    2977             :         return MAL_SUCCEED;
    2978             : 
    2979           0 :   bailout:
    2980           0 :         BBPreclaim(UTF8_toUpperFrom);
    2981           0 :         BBPreclaim(UTF8_toUpperTo);
    2982           0 :         BBPreclaim(UTF8_toLowerFrom);
    2983           0 :         BBPreclaim(UTF8_toLowerTo);
    2984           0 :         UTF8_toUpperFrom = NULL;
    2985           0 :         UTF8_toUpperTo = NULL;
    2986           0 :         UTF8_toLowerFrom = NULL;
    2987           0 :         UTF8_toLowerTo = NULL;
    2988           0 :         throw(MAL, "str.prelude", GDK_EXCEPTION);
    2989             : }
    2990             : 
    2991             : static str
    2992         264 : STRepilogue(void *ret)
    2993             : {
    2994             :         (void) ret;
    2995         264 :         if (UTF8_toUpperFrom)
    2996         264 :                 BBPunfix(UTF8_toUpperFrom->batCacheid);
    2997         264 :         if (UTF8_toUpperTo)
    2998         264 :                 BBPunfix(UTF8_toUpperTo->batCacheid);
    2999         264 :         if (UTF8_toLowerFrom)
    3000         264 :                 BBPunfix(UTF8_toLowerFrom->batCacheid);
    3001         264 :         if (UTF8_toLowerTo)
    3002         264 :                 BBPunfix(UTF8_toLowerTo->batCacheid);
    3003         264 :         UTF8_toUpperFrom = NULL;
    3004         264 :         UTF8_toUpperTo = NULL;
    3005         264 :         UTF8_toLowerFrom = NULL;
    3006         264 :         UTF8_toLowerTo = NULL;
    3007         264 :         return MAL_SUCCEED;
    3008             : }
    3009             : 
    3010             : /* Get the last char in (X2), and #bytes it takes, but do not decrease
    3011             :  * the pos in (X2).  See gdk_atoms.c for UTF-8 encoding */
    3012             : #define UTF8_LASTCHAR(X1, SZ, X2, SZ2)                          \
    3013             :         do {                                                                                    \
    3014             :                 if (((X2)[SZ2-1] & 0x80) == 0) {                    \
    3015             :                         (X1) = (X2)[SZ2-1];                                             \
    3016             :                         (SZ) = 1;                                                               \
    3017             :                 } else if (((X2)[SZ2-2] & 0xE0) == 0xC0) {  \
    3018             :                         (X1)  = ((X2)[SZ2-2] & 0x1F) << 6;            \
    3019             :                         (X1) |= ((X2)[SZ2-1] & 0x3F);                       \
    3020             :                         (SZ) = 2;                                                               \
    3021             :                 } else if (((X2)[SZ2-3] & 0xF0) == 0xE0) {  \
    3022             :                         (X1)  = ((X2)[SZ2-3] & 0x0F) << 12;           \
    3023             :                         (X1) |= ((X2)[SZ2-2] & 0x3F) << 6;            \
    3024             :                         (X1) |= ((X2)[SZ2-1] & 0x3F);                       \
    3025             :                         (SZ) = 3;                                                               \
    3026             :                 } else if (((X2)[SZ2-4] & 0xF8) == 0xF0) {  \
    3027             :                         (X1)  = ((X2)[SZ2-4] & 0x07) << 18;           \
    3028             :                         (X1) |= ((X2)[SZ2-3] & 0x3F) << 12;           \
    3029             :                         (X1) |= ((X2)[SZ2-2] & 0x3F) << 6;            \
    3030             :                         (X1) |= ((X2)[SZ2-1] & 0x3F);                       \
    3031             :                         (SZ) = 4;                                                               \
    3032             :                 } else {                                                                        \
    3033             :                         (X1) = int_nil;                                                 \
    3034             :                         (SZ) = 0;                                                               \
    3035             :                 }                                                                                       \
    3036             :         } while (0)
    3037             : 
    3038             : /* Get the first char in (X2), and #bytes it takes, but do not
    3039             :  * increase the pos in (X2) */
    3040             : #define UTF8_NEXTCHAR(X1, SZ, X2)                               \
    3041             :         do {                                                                            \
    3042             :                 if (((X2)[0] & 0x80) == 0) {                        \
    3043             :                         (X1) = (X2)[0];                                         \
    3044             :                         (SZ) = 1;                                                       \
    3045             :                 } else if (((X2)[0] & 0xE0) == 0xC0) {      \
    3046             :                         (X1)  = ((X2)[0] & 0x1F) << 6;                \
    3047             :                         (X1) |= ((X2)[1] & 0x3F);                   \
    3048             :                         (SZ) = 2;                                                       \
    3049             :                 } else if (((X2)[0] & 0xF0) == 0xE0) {      \
    3050             :                         (X1)  = ((X2)[0] & 0x0F) << 12;               \
    3051             :                         (X1) |= ((X2)[1] & 0x3F) << 6;                \
    3052             :                         (X1) |= ((X2)[2] & 0x3F);                   \
    3053             :                         (SZ) = 3;                                                       \
    3054             :                 } else if (((X2)[0] & 0xF8) == 0xF0) {      \
    3055             :                         (X1)  = ((X2)[0] & 0x07) << 18;               \
    3056             :                         (X1) |= ((X2)[1] & 0x3F) << 12;               \
    3057             :                         (X1) |= ((X2)[2] & 0x3F) << 6;                \
    3058             :                         (X1) |= ((X2)[3] & 0x3F);                   \
    3059             :                         (SZ) = 4;                                                       \
    3060             :                 } else {                                                                \
    3061             :                         (X1) = int_nil;                                         \
    3062             :                         (SZ) = 0;                                                       \
    3063             :                 }                                                                               \
    3064             :         } while (0)
    3065             : 
    3066             : #define UTF8_GETCHAR(X1, X2)                                                                                    \
    3067             :         do {                                                                                                                            \
    3068             :                 if ((*(X2) & 0x80) == 0) {                                                                          \
    3069             :                         (X1) = *(X2)++;                                                                                         \
    3070             :                 } else if ((*(X2) & 0xE0) == 0xC0) {                                                        \
    3071             :                         (X1)  = (*(X2)++ & 0x1F) << 6;                                                                \
    3072             :                         (X1) |= (*(X2)++ & 0x3F);                                                                   \
    3073             :                 } else if ((*(X2) & 0xF0) == 0xE0) {                                                        \
    3074             :                         (X1)  = (*(X2)++ & 0x0F) << 12;                                                               \
    3075             :                         (X1) |= (*(X2)++ & 0x3F) << 6;                                                                \
    3076             :                         (X1) |= (*(X2)++ & 0x3F);                                                                   \
    3077             :                 } else if ((*(X2) & 0xF8) == 0xF0) {                                                        \
    3078             :                         (X1)  = (*(X2)++ & 0x07) << 18;                                                               \
    3079             :                         (X1) |= (*(X2)++ & 0x3F) << 12;                                                               \
    3080             :                         (X1) |= (*(X2)++ & 0x3F) << 6;                                                                \
    3081             :                         (X1) |= (*(X2)++ & 0x3F);                                                                   \
    3082             :                         if ((X1) > 0x10FFFF || ((X1) & 0x1FF800) == 0xD800)                      \
    3083             :                                 goto illegal;                                                                                   \
    3084             :                 } else {                                                                                                                \
    3085             :                         (X1) = int_nil;                                                                                         \
    3086             :                 }                                                                                                                               \
    3087             :         } while (0)
    3088             : 
    3089             : #define UTF8_PUTCHAR(X1, X2)                                                                                    \
    3090             :         do {                                                                                                                            \
    3091             :                 if ((X1) < 0 || (X1) > 0x10FFFF || ((X1) & 0x1FF800) == 0xD800) { \
    3092             :                         goto illegal;                                                                                           \
    3093             :                 } else if ((X1) <= 0x7F) {                                                                           \
    3094             :                         *(X2)++ = (X1);                                                                                         \
    3095             :                 } else if ((X1) <= 0x7FF) {                                                                          \
    3096             :                         *(X2)++ = 0xC0 | ((X1) >> 6);                                                             \
    3097             :                         *(X2)++ = 0x80 | ((X1) & 0x3F);                                                             \
    3098             :                 } else if ((X1) <= 0xFFFF) {                                                                 \
    3099             :                         *(X2)++ = 0xE0 | ((X1) >> 12);                                                            \
    3100             :                         *(X2)++ = 0x80 | (((X1) >> 6) & 0x3F);                                                \
    3101             :                         *(X2)++ = 0x80 | ((X1) & 0x3F);                                                             \
    3102             :                 } else {                                                                                                                \
    3103             :                         *(X2)++ = 0xF0 | ((X1) >> 18);                                                            \
    3104             :                         *(X2)++ = 0x80 | (((X1) >> 12) & 0x3F);                                               \
    3105             :                         *(X2)++ = 0x80 | (((X1) >> 6) & 0x3F);                                                \
    3106             :                         *(X2)++ = 0x80 | ((X1) & 0x3F);                                                             \
    3107             :                 }                                                                                                                               \
    3108             :         } while (0)
    3109             : 
    3110             : #define UTF8_CHARLEN(UC) \
    3111             :         ((UC) <= 0x7F ? 1 : (UC) <= 0x7FF ? 2 : (UC) <= 0xFFFF ? 3 : 4)
    3112             : //      (1 + ((UC) > 0x7F) + ((UC) > 0x7FF) + ((UC) > 0xFFFF))
    3113             : 
    3114             : static inline int
    3115          30 : UTF8_strpos(const char *s, const char *end)
    3116             : {
    3117             :         int pos = 0;
    3118             : 
    3119          30 :         UTF8_assert(s);
    3120             : 
    3121          30 :         if (s > end) {
    3122             :                 return -1;
    3123             :         }
    3124         113 :         while (s < end) {
    3125             :                 /* just count leading bytes of encoded code points; only works
    3126             :                  * for correctly encoded UTF-8 */
    3127          83 :                 pos += (*s++ & 0xC0) != 0x80;
    3128             :         }
    3129             :         return pos;
    3130             : }
    3131             : 
    3132             : static inline str
    3133     6614058 : UTF8_strtail(const char *s, int pos)
    3134             : {
    3135     6614058 :         UTF8_assert(s);
    3136    92206304 :         while (*s) {
    3137    91465260 :                 if ((*s & 0xC0) != 0x80) {
    3138    91465206 :                         if (pos <= 0)
    3139             :                                 break;
    3140    85165430 :                         pos--;
    3141             :                 }
    3142    85165484 :                 s++;
    3143             :         }
    3144     7040820 :         return (str) s;
    3145             : }
    3146             : 
    3147             : static inline str
    3148         214 : UTF8_strncpy(char *restrict dst, const char *restrict s, int n)
    3149             : {
    3150         214 :         UTF8_assert(s);
    3151        1445 :         while (*s && n) {
    3152        1231 :                 if ((*s & 0xF8) == 0xF0) {
    3153             :                         /* 4 byte UTF-8 sequence */
    3154           0 :                         *dst++ = *s++;
    3155           0 :                         *dst++ = *s++;
    3156           0 :                         *dst++ = *s++;
    3157           0 :                         *dst++ = *s++;
    3158        1231 :                 } else if ((*s & 0xF0) == 0xE0) {
    3159             :                         /* 3 byte UTF-8 sequence */
    3160           6 :                         *dst++ = *s++;
    3161           6 :                         *dst++ = *s++;
    3162           6 :                         *dst++ = *s++;
    3163        1225 :                 } else if ((*s & 0xE0) == 0xC0) {
    3164             :                         /* 2 byte UTF-8 sequence */
    3165           0 :                         *dst++ = *s++;
    3166           0 :                         *dst++ = *s++;
    3167             :                 } else {
    3168             :                         /* 1 byte UTF-8 "sequence" */
    3169        1225 :                         *dst++ = *s++;
    3170             :                 }
    3171        1231 :                 n--;
    3172             :         }
    3173         214 :         *dst = '\0';
    3174         214 :         return dst;
    3175             : }
    3176             : 
    3177             : static inline str
    3178           9 : UTF8_offset(char *restrict s, int n)
    3179             : {
    3180           9 :         UTF8_assert(s);
    3181          33 :         while (*s && n) {
    3182          24 :                 if ((*s & 0xF8) == 0xF0) {
    3183             :                         /* 4 byte UTF-8 sequence */
    3184           0 :                         s += 4;
    3185          24 :                 } else if ((*s & 0xF0) == 0xE0) {
    3186             :                         /* 3 byte UTF-8 sequence */
    3187           8 :                         s += 3;
    3188          16 :                 } else if ((*s & 0xE0) == 0xC0) {
    3189             :                         /* 2 byte UTF-8 sequence */
    3190           0 :                         s += 2;
    3191             :                 } else {
    3192             :                         /* 1 byte UTF-8 "sequence" */
    3193          16 :                         s++;
    3194             :                 }
    3195          24 :                 n--;
    3196             :         }
    3197           9 :         return s;
    3198             : }
    3199             : 
    3200             : str
    3201      109944 : str_case_hash_lock(bool upper)
    3202             : {
    3203      109944 :         BAT *b = upper ? UTF8_toUpperFrom : UTF8_toLowerFrom;
    3204             : 
    3205      109944 :         if (BAThash(b) != GDK_SUCCEED)
    3206           0 :                 throw(MAL, "str.str_case_hash_lock", GDK_EXCEPTION);
    3207      109944 :         MT_rwlock_rdlock(&b->thashlock);
    3208      109944 :         return MAL_SUCCEED;
    3209             : }
    3210             : 
    3211             : void
    3212         126 : str_case_hash_unlock(bool upper)
    3213             : {
    3214         126 :         BAT *b = upper ? UTF8_toUpperFrom : UTF8_toLowerFrom;
    3215      109944 :         MT_rwlock_rdunlock(&b->thashlock);
    3216         126 : }
    3217             : 
    3218             : static inline str
    3219      370016 : convertCase(BAT *from, BAT *to, str *buf, size_t *buflen, const char *src, const char *malfunc)
    3220             : {
    3221      370016 :         size_t len = strlen(src);
    3222             :         char *dst;
    3223      370016 :         const char *end = src + len;
    3224      370016 :         bool lower_to_upper = from == UTF8_toUpperFrom;
    3225      370016 :         const Hash *h = from->thash;
    3226      370016 :         const int *restrict fromb = (const int *restrict) from->theap->base;
    3227      370016 :         const int *restrict tob = (const int *restrict) to->theap->base;
    3228      370016 :         size_t nextlen = len + 1;
    3229             : 
    3230             :         /* the from and to bats are not views */
    3231      370016 :         assert(from->tbaseoff == 0);
    3232      370016 :         assert(to->tbaseoff == 0);
    3233      370016 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nextlen, malfunc);
    3234      370016 :         dst = *buf;
    3235     4892791 :         while (src < end) {
    3236             :                 int c;
    3237             : 
    3238     4522770 :                 UTF8_GETCHAR(c, src);
    3239     4522770 :                 if (c < 192) { /* the first 191 characters in unicode are trivial to convert */
    3240             :                         /* for ASCII characters we don't need to do a hash lookup */
    3241     4522746 :                         if (lower_to_upper) {
    3242     3188564 :                                 if ('a' <= c && c <= 'z')
    3243     2497549 :                                         c += 'A' - 'a';
    3244             :                         } else {
    3245     1334182 :                                 if ('A' <= c && c <= 'Z')
    3246     1294392 :                                         c += 'a' - 'A';
    3247             :                         }
    3248             :                 } else {
    3249             :                         /* use hash, even though BAT is sorted */
    3250          46 :                         for (BUN hb = HASHget(h, hash_int(h, &c));
    3251             :                                         hb != BUN_NONE;
    3252          19 :                                         hb = HASHgetlink(h, hb)) {
    3253          21 :                                 if (c == fromb[hb]) {
    3254           2 :                                         c = tob[hb];
    3255           2 :                                         break;
    3256             :                                 }
    3257             :                         }
    3258             :                 }
    3259     4522770 :                 if (dst + UTF8_CHARLEN(c) > *buf + len) {
    3260             :                         /* doesn't fit, so allocate more space;
    3261             :                          * also allocate enough for the rest of the
    3262             :                          * source */
    3263           0 :                         size_t off = dst - *buf;
    3264           0 :                         size_t nextlen = (len += 4 + (end - src)) + 1;
    3265             : 
    3266           0 :                         CHECK_STR_BUFFER_LENGTH(buf, buflen, nextlen, malfunc);
    3267           5 :                         dst = *buf + off;
    3268             :                 }
    3269     4522775 :                 UTF8_PUTCHAR(c, dst);
    3270             :         }
    3271      370021 :         *dst = 0;
    3272      370021 :         return MAL_SUCCEED;
    3273             : illegal:
    3274           0 :         throw(MAL, malfunc, SQLSTATE(42000) "Illegal Unicode code point");
    3275             : }
    3276             : 
    3277             : /*
    3278             :  * Here you find the wrappers around the version 4 library code
    3279             :  * It also contains the direct implementation of the string
    3280             :  * matching support routines.
    3281             :  */
    3282             : #include "mal_exception.h"
    3283             : 
    3284             : /*
    3285             :  * The SQL like function return a boolean
    3286             :  */
    3287             : static bool
    3288           0 : STRlike(const char *s, const char *pat, const char *esc)
    3289             : {
    3290             :         const char *t, *p;
    3291             : 
    3292             :         t = s;
    3293           0 :         for (p = pat; *p && *t; p++) {
    3294           0 :                 if (esc && *p == *esc) {
    3295           0 :                         p++;
    3296           0 :                         if (*p != *t)
    3297             :                                 return false;
    3298           0 :                         t++;
    3299           0 :                 } else if (*p == '_')
    3300           0 :                         t++;
    3301           0 :                 else if (*p == '%') {
    3302           0 :                         p++;
    3303           0 :                         while (*p == '%')
    3304           0 :                                 p++;
    3305           0 :                         if (*p == 0)
    3306             :                                 return true;    /* tail is acceptable */
    3307           0 :                         for (; *p && *t; t++)
    3308           0 :                                 if (STRlike(t, p, esc))
    3309             :                                         return true;
    3310           0 :                         if (*p == 0 && *t == 0)
    3311             :                                 return true;
    3312           0 :                         return false;
    3313           0 :                 } else if (*p == *t)
    3314           0 :                         t++;
    3315             :                 else
    3316             :                         return false;
    3317             :         }
    3318           0 :         if (*p == '%' && *(p + 1) == 0)
    3319             :                 return true;
    3320           0 :         return *t == 0 && *p == 0;
    3321             : }
    3322             : 
    3323             : static str
    3324           0 : STRlikewrap3(bit *ret, const str *s, const str *pat, const str *esc)
    3325             : {
    3326           0 :         if (strNil(*s) || strNil(*pat) || strNil(*esc))
    3327           0 :                 *ret = bit_nil;
    3328             :         else
    3329           0 :                 *ret = (bit) STRlike(*s, *pat, *esc);
    3330           0 :         return MAL_SUCCEED;
    3331             : }
    3332             : 
    3333             : static str
    3334           0 : STRlikewrap(bit *ret, const str *s, const str *pat)
    3335             : {
    3336           0 :         if (strNil(*s) || strNil(*pat))
    3337           0 :                 *ret = bit_nil;
    3338             :         else
    3339           0 :                 *ret = (bit) STRlike(*s, *pat, NULL);
    3340           0 :         return MAL_SUCCEED;
    3341             : }
    3342             : 
    3343             : static str
    3344           0 : STRtostr(str *res, const str *src)
    3345             : {
    3346           0 :         if( *src == 0)
    3347           0 :                 *res= GDKstrdup(str_nil);
    3348             :         else
    3349           0 :                 *res = GDKstrdup(*src);
    3350           0 :         if (*res == NULL)
    3351           0 :                 throw(MAL, "str.str", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3352             :         return MAL_SUCCEED;
    3353             : }
    3354             : 
    3355             : static str
    3356          97 : STRLength(int *res, const str *arg1)
    3357             : {
    3358          97 :         str s = *arg1;
    3359             : 
    3360          97 :         *res = strNil(s) ? int_nil : UTF8_strlen(s);
    3361          97 :         return MAL_SUCCEED;
    3362             : }
    3363             : 
    3364             : 
    3365             : 
    3366             : static str
    3367           1 : STRBytes(int *res, const str *arg1)
    3368             : {
    3369           1 :         str s = *arg1;
    3370             : 
    3371           1 :         *res = strNil(s) ? int_nil : str_strlen(s);
    3372           1 :         return MAL_SUCCEED;
    3373             : }
    3374             : 
    3375             : str
    3376          26 : str_tail(str *buf, size_t *buflen, str s, int off)
    3377             : {
    3378          26 :         if (off < 0) {
    3379           1 :                 off += UTF8_strlen(s);
    3380             :                 if (off < 0)
    3381             :                         off = 0;
    3382             :         }
    3383          26 :         str tail = UTF8_strtail(s, off);
    3384          26 :         size_t nextlen = strlen(tail) + 1;
    3385          26 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nextlen, "str.tail");
    3386          26 :         strcpy(*buf, tail);
    3387          26 :         return MAL_SUCCEED;
    3388             : }
    3389             : 
    3390             : static str
    3391           1 : STRTail(str *res, const str *arg1, const int *offset)
    3392             : {
    3393           1 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3394           1 :         int off = *offset;
    3395             : 
    3396           1 :         if (strNil(s) || is_int_nil(off)) {
    3397           0 :                 *res = GDKstrdup(str_nil);
    3398             :         } else {
    3399           1 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3400             : 
    3401           1 :                 *res = NULL;
    3402           1 :                 if (!(buf = GDKmalloc(buflen)))
    3403           0 :                         throw(MAL, "str.tail", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3404           1 :                 if ((msg = str_tail(&buf, &buflen, s, off)) != MAL_SUCCEED) {
    3405           0 :                         GDKfree(buf);
    3406           0 :                         return msg;
    3407             :                 }
    3408           1 :                 *res = GDKstrdup(buf);
    3409             :         }
    3410             : 
    3411           1 :         GDKfree(buf);
    3412           1 :         if (!*res)
    3413           0 :                 msg = createException(MAL, "str.tail", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3414             :         return msg;
    3415             : }
    3416             : 
    3417             : str
    3418     3663642 : str_Sub_String(str *buf, size_t *buflen, str s, int off, int l)
    3419             : {
    3420             :         size_t len;
    3421             : 
    3422     3663642 :         if (off < 0) {
    3423           4 :                 off += UTF8_strlen(s);
    3424           4 :                 if (off < 0) {
    3425           3 :                         l += off;
    3426             :                         off = 0;
    3427             :                 }
    3428             :         }
    3429             :         /* here, off >= 0 */
    3430     3663642 :         if (l < 0) {
    3431           6 :                 strcpy(*buf, "");
    3432           6 :                 return MAL_SUCCEED;
    3433             :         }
    3434     3663636 :         s = UTF8_strtail(s, off);
    3435     3732317 :         len = (size_t)(UTF8_strtail(s, l) - s + 1);
    3436     3781573 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, len, "str.substring");
    3437     3781573 :         strcpy_len(*buf, s, len);
    3438     3830053 :         return MAL_SUCCEED;
    3439             : }
    3440             : 
    3441             : static str
    3442           4 : STRSubString(str *res, const str *arg1, const int *offset, const int *length)
    3443             : {
    3444           4 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3445           4 :         int off = *offset, len = *length;
    3446             : 
    3447           4 :         if (strNil(s) || is_int_nil(off) || is_int_nil(len)) {
    3448           1 :                 *res = GDKstrdup(str_nil);
    3449             :         } else {
    3450           3 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3451             : 
    3452           3 :                 *res = NULL;
    3453           3 :                 if (!(buf = GDKmalloc(buflen)))
    3454           0 :                         throw(MAL, "str.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3455           3 :                 if ((msg = str_Sub_String(&buf, &buflen, s, off, len)) != MAL_SUCCEED) {
    3456           0 :                         GDKfree(buf);
    3457           0 :                         return msg;
    3458             :                 }
    3459           3 :                 *res = GDKstrdup(buf);
    3460             :         }
    3461             : 
    3462           4 :         GDKfree(buf);
    3463           4 :         if (!*res)
    3464           0 :                 msg = createException(MAL, "str.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3465             :         return msg;
    3466             : }
    3467             : 
    3468             : str
    3469           2 : str_from_wchr(str *buf, size_t *buflen, int c)
    3470             : {
    3471           2 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, 5, "str.unicode");
    3472           2 :         str s = *buf;
    3473           2 :         UTF8_PUTCHAR(c, s);
    3474           2 :         *s = 0;
    3475           2 :         return MAL_SUCCEED;
    3476             : illegal:
    3477           0 :         throw(MAL, "str.unicode", SQLSTATE(42000) "Illegal Unicode code point");
    3478             : }
    3479             : 
    3480             : static str
    3481           0 : STRFromWChr(str *res, const int *c)
    3482             : {
    3483           0 :         str buf = NULL, msg = MAL_SUCCEED;
    3484           0 :         int cc = *c;
    3485             : 
    3486           0 :         if (is_int_nil(cc)) {
    3487           0 :                 *res = GDKstrdup(str_nil);
    3488             :         } else {
    3489           0 :                 size_t buflen = MAX(strlen(str_nil) + 1, 8);
    3490             : 
    3491           0 :                 *res = NULL;
    3492           0 :                 if (!(buf = GDKmalloc(buflen)))
    3493           0 :                         throw(MAL, "str.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3494           0 :                 if ((msg = str_from_wchr(&buf, &buflen, cc)) != MAL_SUCCEED) {
    3495           0 :                         GDKfree(buf);
    3496           0 :                         return msg;
    3497             :                 }
    3498           0 :                 *res = GDKstrdup(buf);
    3499             :         }
    3500             : 
    3501           0 :         GDKfree(buf);
    3502           0 :         if (!*res)
    3503           0 :                 msg = createException(MAL, "str.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3504             :         return msg;
    3505             : }
    3506             : 
    3507             : /* return the Unicode code point of arg1 at position at */
    3508             : str
    3509          29 : str_wchr_at(int *res, str s, int at)
    3510             : {
    3511             :         /* 64bit: should have lng arg */
    3512          29 :         if (strNil(s) || is_int_nil(at) || at < 0) {
    3513           2 :                 *res = int_nil;
    3514           2 :                 return MAL_SUCCEED;
    3515             :         }
    3516          27 :         s = UTF8_strtail(s, at);
    3517          27 :         if (s == NULL || *s == 0) {
    3518           6 :                 *res = int_nil;
    3519           6 :                 return MAL_SUCCEED;
    3520             :         }
    3521          21 :         UTF8_GETCHAR(*res, s);
    3522             :         return MAL_SUCCEED;
    3523             : illegal:
    3524           0 :         throw(MAL, "str.unicodeAt", SQLSTATE(42000) "Illegal Unicode code point");
    3525             : }
    3526             : 
    3527             : static str
    3528           0 : STRWChrAt(int *res, const str *arg1, const int *at)
    3529             : {
    3530           0 :         return str_wchr_at(res, *arg1, *at);
    3531             : }
    3532             : 
    3533             : /* returns whether arg1 starts with arg2 */
    3534             : bit
    3535           2 : str_is_prefix(str s, str prefix)
    3536             : {
    3537           2 :         return strncmp(s, prefix, strlen(prefix)) == 0;
    3538             : }
    3539             : 
    3540             : static str
    3541           2 : STRPrefix(bit *res, const str *arg1, const str *arg2)
    3542             : {
    3543           2 :         str s = *arg1, prefix = *arg2;
    3544             : 
    3545           4 :         *res = (strNil(s) || strNil(prefix)) ? bit_nil : str_is_prefix(s, prefix);
    3546           2 :         return MAL_SUCCEED;
    3547             : }
    3548             : 
    3549             : bit
    3550           0 : str_is_suffix(str s, str suffix)
    3551             : {
    3552           0 :         size_t sl = strlen(s), sul = strlen(suffix);
    3553             : 
    3554           0 :         if (sl < sul)
    3555             :                 return 0;
    3556             :         else
    3557           0 :                 return strcmp(s + sl - sul, suffix) == 0;
    3558             : }
    3559             : 
    3560             : /* returns whether arg1 ends with arg2 */
    3561             : static str
    3562           0 : STRSuffix(bit *res, const str *arg1, const str *arg2)
    3563             : {
    3564           0 :         str s = *arg1, suffix = *arg2;
    3565             : 
    3566           0 :         *res = (strNil(s) || strNil(suffix)) ? bit_nil : str_is_suffix(s, suffix);
    3567           0 :         return MAL_SUCCEED;
    3568             : }
    3569             : 
    3570             : str
    3571      168107 : str_lower(str *buf, size_t *buflen, str s)
    3572             : {
    3573      168107 :         return convertCase(UTF8_toLowerFrom, UTF8_toLowerTo, buf, buflen, s, "str.lower");
    3574             : }
    3575             : 
    3576             : static str
    3577        4977 : STRLower(str *res, const str *arg1)
    3578             : {
    3579        4977 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3580             : 
    3581        4977 :         if (strNil(s)) {
    3582          66 :                 *res = GDKstrdup(str_nil);
    3583             :         } else {
    3584        4911 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3585             : 
    3586        4911 :                 *res = NULL;
    3587        4911 :                 if (!(buf = GDKmalloc(buflen)))
    3588           0 :                         throw(MAL, "str.lower", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3589        4911 :                 if ((msg = str_case_hash_lock(false))) {
    3590           0 :                         GDKfree(buf);
    3591           0 :                         return msg;
    3592             :                 }
    3593        4911 :                 msg = str_lower(&buf, &buflen, s);
    3594             :                 str_case_hash_unlock(false);
    3595        4911 :                 if (msg != MAL_SUCCEED) {
    3596           0 :                         GDKfree(buf);
    3597           0 :                         return msg;
    3598             :                 }
    3599        4911 :                 *res = GDKstrdup(buf);
    3600             :         }
    3601             : 
    3602        4977 :         GDKfree(buf);
    3603        4977 :         if (!*res)
    3604           0 :                 msg = createException(MAL, "str.lower", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3605             :         return msg;
    3606             : }
    3607             : 
    3608             : str
    3609      201914 : str_upper(str *buf, size_t *buflen, str s)
    3610             : {
    3611      201914 :         return convertCase(UTF8_toUpperFrom, UTF8_toUpperTo, buf, buflen, s, "str.upper");
    3612             : }
    3613             : 
    3614             : static str
    3615      104908 : STRUpper(str *res, const str *arg1)
    3616             : {
    3617      104908 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3618             : 
    3619      104908 :         if (strNil(s)) {
    3620           1 :                 *res = GDKstrdup(str_nil);
    3621             :         } else {
    3622      104907 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3623             : 
    3624      104907 :                 *res = NULL;
    3625      104907 :                 if (!(buf = GDKmalloc(buflen)))
    3626           0 :                         throw(MAL, "str.upper", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3627      104907 :                 if ((msg = str_case_hash_lock(true))) {
    3628           0 :                         GDKfree(buf);
    3629           0 :                         return msg;
    3630             :                 }
    3631      104907 :                 msg = str_upper(&buf, &buflen, s);
    3632             :                 str_case_hash_unlock(true);
    3633      104907 :                 if (msg != MAL_SUCCEED) {
    3634           0 :                         GDKfree(buf);
    3635           0 :                         return msg;
    3636             :                 }
    3637      104907 :                 *res = GDKstrdup(buf);
    3638             :         }
    3639             : 
    3640      104908 :         GDKfree(buf);
    3641      104908 :         if (!*res)
    3642           0 :                 msg = createException(MAL, "str.upper", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3643             :         return msg;
    3644             : }
    3645             : 
    3646             : int
    3647          44 : str_search(str s, str s2)
    3648             : {
    3649             :         /* 64bit: should return lng */
    3650          44 :         if ((s2 = strstr(s, s2)) != NULL)
    3651          30 :                 return UTF8_strpos(s, s2);
    3652             :         else
    3653             :                 return -1;
    3654             : }
    3655             : 
    3656             : /* find first occurrence of needle in haystack */
    3657             : static str
    3658           0 : STRstrSearch(int *res, const str *haystack, const str *needle)
    3659             : {
    3660           0 :         str s = *haystack, s2 = *needle;
    3661             : 
    3662           0 :         *res = (strNil(s) || strNil(s2)) ? int_nil : str_search(s, s2);
    3663           0 :         return MAL_SUCCEED;
    3664             : }
    3665             : 
    3666             : int
    3667           0 : str_reverse_str_search(str s, str s2)
    3668             : {
    3669             :         /* 64bit: should return lng */
    3670           0 :         size_t len = strlen(s), slen = strlen(s2);
    3671             :         int res = -1; /* changed if found */
    3672             : 
    3673           0 :         if (len >= slen) {
    3674           0 :                 const char *p = s + len - slen;
    3675             :                 do {
    3676           0 :                         if (strncmp(p, s2, slen) == 0) {
    3677           0 :                                 res = UTF8_strpos(s, p);
    3678           0 :                                 break;
    3679             :                         }
    3680           0 :                 } while (p-- > s);
    3681             :         }
    3682           0 :         return res;
    3683             : }
    3684             : 
    3685             : /* find last occurrence of arg2 in arg1 */
    3686             : static str
    3687           0 : STRReverseStrSearch(int *res, const str *arg1, const str *arg2)
    3688             : {
    3689           0 :         str s = *arg1, s2 = *arg2;
    3690             : 
    3691           0 :         *res = (strNil(s) || strNil(s2)) ? int_nil : str_reverse_str_search(s, s2);
    3692           0 :         return MAL_SUCCEED;
    3693             : }
    3694             : 
    3695             : str
    3696          35 : str_splitpart(str *buf, size_t *buflen, str s, str s2, int f)
    3697             : {
    3698             :         size_t len;
    3699             :         char *p = NULL;
    3700             : 
    3701          35 :         if (f <= 0)
    3702           4 :                 throw(MAL, "str.splitpart", SQLSTATE(42000) "field position must be greater than zero");
    3703             : 
    3704          31 :         len = strlen(s2);
    3705          31 :         if (len) {
    3706          38 :                 while ((p = strstr(s, s2)) != NULL && f > 1) {
    3707          11 :                         s = p + len;
    3708          11 :                         f--;
    3709             :                 }
    3710             :         }
    3711             : 
    3712          31 :         if (f != 1) {
    3713          12 :                 strcpy(*buf, "");
    3714          12 :                 return MAL_SUCCEED;
    3715             :         }
    3716             : 
    3717          19 :         if (p == NULL) {
    3718           9 :                 len = strlen(s);
    3719             :         } else {
    3720          10 :                 len = (size_t) (p - s);
    3721             :         }
    3722             : 
    3723          19 :         len++;
    3724          19 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, len, "str.splitpart");
    3725          19 :         strcpy_len(*buf, s, len);
    3726          19 :         return MAL_SUCCEED;
    3727             : }
    3728             : 
    3729             : static str
    3730          21 : STRsplitpart(str *res, str *haystack, str *needle, int *field)
    3731             : {
    3732          21 :         str buf = NULL, msg = MAL_SUCCEED, s = *haystack, s2 = *needle;
    3733          21 :         int f = *field;
    3734             : 
    3735          42 :         if (strNil(s) || strNil(s2) || is_int_nil(f)) {
    3736           0 :                 *res = GDKstrdup(str_nil);
    3737             :         } else {
    3738          21 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3739             : 
    3740          21 :                 *res = NULL;
    3741          21 :                 if (!(buf = GDKmalloc(buflen)))
    3742           4 :                         throw(MAL, "str.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3743          21 :                 if ((msg = str_splitpart(&buf, &buflen, s, s2, f)) != MAL_SUCCEED) {
    3744           4 :                         GDKfree(buf);
    3745           4 :                         return msg;
    3746             :                 }
    3747          17 :                 *res = GDKstrdup(buf);
    3748             :         }
    3749             : 
    3750          17 :         GDKfree(buf);
    3751          17 :         if (!*res)
    3752           0 :                 msg = createException(MAL, "str.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3753             :         return msg;
    3754             : }
    3755             : 
    3756             : /* returns number of bytes to remove from left to strip the codepoints in rm */
    3757             : static size_t
    3758         324 : lstrip(const char *s, size_t len, const int *rm, size_t nrm)
    3759             : {
    3760             :         int c;
    3761             :         size_t i, n, skip = 0;
    3762             : 
    3763         431 :         while (len > 0) {
    3764         419 :                 UTF8_NEXTCHAR(c, n, s);
    3765         419 :                 assert(n > 0 && n <= len);
    3766        6966 :                 for (i = 0; i < nrm; i++) {
    3767        6654 :                         if (rm[i] == c) {
    3768         107 :                                 s += n;
    3769         107 :                                 skip += n;
    3770         107 :                                 len -= n;
    3771         107 :                                 break;
    3772             :                         }
    3773             :                 }
    3774         419 :                 if (i == nrm)
    3775             :                         break;
    3776             :         }
    3777         324 :         return skip;
    3778             : }
    3779             : 
    3780             : /* returns the resulting length of s after stripping codepoints in rm
    3781             :  * from the right */
    3782             : static size_t
    3783         398 : rstrip(const char *s, size_t len, const int *rm, size_t nrm)
    3784             : {
    3785             :         int c;
    3786             :         size_t i, n;
    3787             : 
    3788         544 :         while (len > 0) {
    3789         534 :                 UTF8_LASTCHAR(c, n, s, len);
    3790         534 :                 assert(n > 0 && n <= len);
    3791        8938 :                 for (i = 0; i < nrm; i++) {
    3792        8550 :                         if (rm[i] == c) {
    3793         146 :                                 len -= n;
    3794         146 :                                 break;
    3795             :                         }
    3796             :                 }
    3797         534 :                 if (i == nrm)
    3798             :                         break;
    3799             :         }
    3800         398 :         return len;
    3801             : }
    3802             : 
    3803             : const int whitespace[] = {
    3804             :         ' ',                                            /* space */
    3805             :         '\t',                                           /* tab (character tabulation) */
    3806             :         '\n',                                           /* line feed */
    3807             :         '\r',                                           /* carriage return */
    3808             :         '\f',                                           /* form feed */
    3809             :         '\v',                                           /* vertical tab (line tabulation) */
    3810             : /* below the code points that have the Unicode Zs (space separator) property */
    3811             :         0x00A0,                                         /* no-break space */
    3812             :         0x1680,                                         /* ogham space mark */
    3813             :         0x2000,                                         /* en quad */
    3814             :         0x2001,                                         /* em quad */
    3815             :         0x2002,                                         /* en space */
    3816             :         0x2003,                                         /* em space */
    3817             :         0x2004,                                         /* three-per-em space */
    3818             :         0x2005,                                         /* four-per-em space */
    3819             :         0x2006,                                         /* six-per-em space */
    3820             :         0x2007,                                         /* figure space */
    3821             :         0x2008,                                         /* punctuation space */
    3822             :         0x2009,                                         /* thin space */
    3823             :         0x200A,                                         /* hair space */
    3824             :         0x202F,                                         /* narrow no-break space */
    3825             :         0x205F,                                         /* medium mathematical space */
    3826             :         0x3000,                                         /* ideographic space */
    3827             : };
    3828             : #define NSPACES         (sizeof(whitespace) / sizeof(whitespace[0]))
    3829             : 
    3830             : str
    3831         279 : str_strip(str *buf, size_t *buflen, str s)
    3832             : {
    3833         279 :         size_t len = strlen(s);
    3834         279 :         size_t n = lstrip(s, len, whitespace, NSPACES);
    3835         279 :         s += n;
    3836         279 :         len -= n;
    3837         279 :         n = rstrip(s, len, whitespace, NSPACES);
    3838             : 
    3839         279 :         n++;
    3840         279 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, n, "str.strip");
    3841         279 :         strcpy_len(*buf, s, n);
    3842         279 :         return MAL_SUCCEED;
    3843             : }
    3844             : 
    3845             : /* remove all whitespace from either side of arg1 */
    3846             : static str
    3847           6 : STRStrip(str *res, const str *arg1)
    3848             : {
    3849           6 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3850             : 
    3851           6 :         if (strNil(s)) {
    3852           0 :                 *res = GDKstrdup(str_nil);
    3853             :         } else {
    3854           6 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3855             : 
    3856           6 :                 *res = NULL;
    3857           6 :                 if (!(buf = GDKmalloc(buflen)))
    3858           0 :                         throw(MAL, "str.strip", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3859           6 :                 if ((msg = str_strip(&buf, &buflen, s)) != MAL_SUCCEED) {
    3860           0 :                         GDKfree(buf);
    3861           0 :                         return msg;
    3862             :                 }
    3863           6 :                 *res = GDKstrdup(buf);
    3864             :         }
    3865             : 
    3866           6 :         GDKfree(buf);
    3867           6 :         if (!*res)
    3868           0 :                 msg = createException(MAL, "str.strip", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3869             :         return msg;
    3870             : }
    3871             : 
    3872             : str
    3873          23 : str_ltrim(str *buf, size_t *buflen, str s)
    3874             : {
    3875          23 :         size_t len = strlen(s);
    3876          23 :         size_t n = lstrip(s, len, whitespace, NSPACES);
    3877          23 :         size_t nallocate = len - n + 1;
    3878             : 
    3879          23 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nallocate, "str.ltrim");
    3880          23 :         strcpy_len(*buf, s + n, nallocate);
    3881          23 :         return MAL_SUCCEED;
    3882             : }
    3883             : 
    3884             : /* remove all whitespace from the start (left) of arg1 */
    3885             : static str
    3886          15 : STRLtrim(str *res, const str *arg1)
    3887             : {
    3888          15 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3889             : 
    3890          15 :         if (strNil(s)) {
    3891           0 :                 *res = GDKstrdup(str_nil);
    3892             :         } else {
    3893          15 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3894             : 
    3895          15 :                 *res = NULL;
    3896          15 :                 if (!(buf = GDKmalloc(buflen)))
    3897           0 :                         throw(MAL, "str.ltrim", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3898          15 :                 if ((msg = str_ltrim(&buf, &buflen, s)) != MAL_SUCCEED) {
    3899           0 :                         GDKfree(buf);
    3900           0 :                         return msg;
    3901             :                 }
    3902          15 :                 *res = GDKstrdup(buf);
    3903             :         }
    3904             : 
    3905          15 :         GDKfree(buf);
    3906          15 :         if (!*res)
    3907           0 :                 msg = createException(MAL, "str.ltrim", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3908             :         return msg;
    3909             : }
    3910             : 
    3911             : str
    3912          96 : str_rtrim(str *buf, size_t *buflen, str s)
    3913             : {
    3914          96 :         size_t len = strlen(s);
    3915          96 :         size_t n = rstrip(s, len, whitespace, NSPACES);
    3916             : 
    3917          96 :         n++;
    3918          96 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, n, "str.rtrim");
    3919          96 :         strcpy_len(*buf, s, n);
    3920          96 :         return MAL_SUCCEED;
    3921             : }
    3922             : 
    3923             : /* remove all whitespace from the end (right) of arg1 */
    3924             : static str
    3925           4 : STRRtrim(str *res, const str *arg1)
    3926             : {
    3927           4 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    3928             : 
    3929           4 :         if (strNil(s)) {
    3930           0 :                 *res = GDKstrdup(str_nil);
    3931             :         } else {
    3932           4 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3933             : 
    3934           4 :                 *res = NULL;
    3935           4 :                 if (!(buf = GDKmalloc(buflen)))
    3936           0 :                         throw(MAL, "str.rtrim", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3937           4 :                 if ((msg = str_rtrim(&buf, &buflen, s)) != MAL_SUCCEED) {
    3938           0 :                         GDKfree(buf);
    3939           0 :                         return msg;
    3940             :                 }
    3941           4 :                 *res = GDKstrdup(buf);
    3942             :         }
    3943             : 
    3944           4 :         GDKfree(buf);
    3945           4 :         if (!*res)
    3946           0 :                 msg = createException(MAL, "str.rtrim", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3947             :         return msg;
    3948             : }
    3949             : 
    3950             : /* return a list of codepoints in s */
    3951             : static str
    3952          33 : trimchars(str *buf, size_t *buflen, size_t *n, const char *s, size_t len_s, const char *malfunc)
    3953             : {
    3954          33 :         size_t len = 0, nlen = len_s * sizeof(int);
    3955             :         int c, *cbuf;
    3956             : 
    3957          33 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nlen, malfunc);
    3958          33 :         cbuf = *(int**)buf;
    3959             : 
    3960         179 :         while (*s) {
    3961         146 :                 UTF8_GETCHAR(c, s);
    3962         146 :                 assert(!is_int_nil(c));
    3963         146 :                 cbuf[len++] = c;
    3964             :         }
    3965          33 :         *n = len;
    3966          33 :         return MAL_SUCCEED;
    3967             : illegal:
    3968           0 :         throw(MAL, malfunc, SQLSTATE(42000) "Illegal Unicode code point");
    3969             : }
    3970             : 
    3971             : str
    3972          13 : str_strip2(str *buf, size_t *buflen, str s, str s2)
    3973             : {
    3974             :         str msg = MAL_SUCCEED;
    3975             :         size_t len, n, n2, n3;
    3976             : 
    3977          13 :         if ((n2 = strlen(s2)) == 0) {
    3978           1 :                 len = strlen(s) + 1;
    3979           1 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, len, "str.strip2");
    3980           1 :                 strcpy(*buf, s);
    3981           1 :                 return MAL_SUCCEED;
    3982             :         } else {
    3983          12 :                 if ((msg = trimchars(buf, buflen, &n3, s2, n2, "str.strip2")) != MAL_SUCCEED)
    3984             :                         return msg;
    3985          12 :                 len = strlen(s);
    3986          12 :                 n = lstrip(s, len, *(int**)buf, n3);
    3987          12 :                 s += n;
    3988          12 :                 len -= n;
    3989          12 :                 n = rstrip(s, len, *(int**)buf, n3);
    3990             : 
    3991          12 :                 n++;
    3992          12 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, n, "str.strip2");
    3993          12 :                 strcpy_len(*buf, s, n);
    3994          12 :                 return MAL_SUCCEED;
    3995             :         }
    3996             : }
    3997             : 
    3998             : /* remove the longest string containing only characters from arg2 from
    3999             :  * either side of arg1 */
    4000             : static str
    4001           7 : STRStrip2(str *res, const str *arg1, const str *arg2)
    4002             : {
    4003           7 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2;
    4004             : 
    4005          14 :         if (strNil(s) || strNil(s2)) {
    4006           0 :                 *res = GDKstrdup(str_nil);
    4007             :         } else {
    4008           7 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH * sizeof(int);
    4009             : 
    4010           7 :                 *res = NULL;
    4011           7 :                 if (!(buf = GDKmalloc(buflen)))
    4012           0 :                         throw(MAL, "str.strip2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4013           7 :                 if ((msg = str_strip2(&buf, &buflen, s, s2)) != MAL_SUCCEED) {
    4014           0 :                         GDKfree(buf);
    4015           0 :                         return msg;
    4016             :                 }
    4017           7 :                 *res = GDKstrdup(buf);
    4018             :         }
    4019             : 
    4020           7 :         GDKfree(buf);
    4021           7 :         if (!*res)
    4022           0 :                 msg = createException(MAL, "str.strip2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4023             :         return msg;
    4024             : }
    4025             : 
    4026             : str
    4027          11 : str_ltrim2(str *buf, size_t *buflen, str s, str s2)
    4028             : {
    4029             :         str msg = MAL_SUCCEED;
    4030             :         size_t len, n, n2, n3, nallocate;
    4031             : 
    4032          11 :         if ((n2 = strlen(s2)) == 0) {
    4033           1 :                 len = strlen(s) + 1;
    4034           1 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, len, "str.ltrim2");
    4035           1 :                 strcpy(*buf, s);
    4036           1 :                 return MAL_SUCCEED;
    4037             :         } else {
    4038          10 :                 if ((msg = trimchars(buf, buflen, &n3, s2, n2, "str.ltrim2")) != MAL_SUCCEED)
    4039             :                         return msg;
    4040          10 :                 len = strlen(s);
    4041          10 :                 n = lstrip(s, len, *(int**)buf, n3);
    4042          10 :                 nallocate = len - n + 1;
    4043             : 
    4044          10 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, nallocate, "str.ltrim2");
    4045          10 :                 strcpy_len(*buf, s + n, nallocate);
    4046          10 :                 return MAL_SUCCEED;
    4047             :         }
    4048             : }
    4049             : 
    4050             : /* remove the longest string containing only characters from arg2 from
    4051             :  * the start (left) of arg1 */
    4052             : static str
    4053           5 : STRLtrim2(str *res, const str *arg1, const str *arg2)
    4054             : {
    4055           5 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2;
    4056             : 
    4057          10 :         if (strNil(s) || strNil(s2)) {
    4058           0 :                 *res = GDKstrdup(str_nil);
    4059             :         } else {
    4060           5 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH * sizeof(int);
    4061             : 
    4062           5 :                 *res = NULL;
    4063           5 :                 if (!(buf = GDKmalloc(buflen)))
    4064           0 :                         throw(MAL, "str.ltrim2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4065           5 :                 if ((msg = str_ltrim2(&buf, &buflen, s, s2)) != MAL_SUCCEED) {
    4066           0 :                         GDKfree(buf);
    4067           0 :                         return msg;
    4068             :                 }
    4069           5 :                 *res = GDKstrdup(buf);
    4070             :         }
    4071             : 
    4072           5 :         GDKfree(buf);
    4073           5 :         if (!*res)
    4074           0 :                 msg = createException(MAL, "str.ltrim2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4075             :         return msg;
    4076             : }
    4077             : 
    4078             : str
    4079          13 : str_rtrim2(str *buf, size_t *buflen, str s, str s2)
    4080             : {
    4081             :         str msg = MAL_SUCCEED;
    4082             :         size_t len, n, n2, n3;
    4083             : 
    4084          13 :         if ((n2 = strlen(s2)) == 0) {
    4085           2 :                 len = strlen(s) + 1;
    4086           2 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, len, "str.rtrim2");
    4087           2 :                 strcpy(*buf, s);
    4088           2 :                 return MAL_SUCCEED;
    4089             :         } else {
    4090          11 :                 if ((msg = trimchars(buf, buflen, &n3, s2, n2, "str.ltrim2")) != MAL_SUCCEED)
    4091             :                         return msg;
    4092          11 :                 len = strlen(s);
    4093          11 :                 n = rstrip(s, len, *(int**)buf, n3);
    4094          11 :                 n++;
    4095             : 
    4096          11 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, n, "str.rtrim2");
    4097          11 :                 strcpy_len(*buf, s, n);
    4098          11 :                 return MAL_SUCCEED;
    4099             :         }
    4100             : }
    4101             : 
    4102             : /* remove the longest string containing only characters from arg2 from
    4103             :  * the end (right) of arg1 */
    4104             : static str
    4105           7 : STRRtrim2(str *res, const str *arg1, const str *arg2)
    4106             : {
    4107           7 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2;
    4108             : 
    4109          14 :         if (strNil(s) || strNil(s2)) {
    4110           0 :                 *res = GDKstrdup(str_nil);
    4111             :         } else {
    4112           7 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH * sizeof(int);
    4113             : 
    4114           7 :                 *res = NULL;
    4115           7 :                 if (!(buf = GDKmalloc(buflen)))
    4116           0 :                         throw(MAL, "str.rtrim2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4117           7 :                 if ((msg = str_rtrim2(&buf, &buflen, s, s2)) != MAL_SUCCEED) {
    4118           0 :                         GDKfree(buf);
    4119           0 :                         return msg;
    4120             :                 }
    4121           7 :                 *res = GDKstrdup(buf);
    4122             :         }
    4123             : 
    4124           7 :         GDKfree(buf);
    4125           7 :         if (!*res)
    4126           0 :                 msg = createException(MAL, "str.rtrim2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4127             :         return msg;
    4128             : }
    4129             : 
    4130             : static str
    4131          56 : pad(str *buf, size_t *buflen, const char *s, const char *pad, int len, int left, const char *malfunc)
    4132             : {
    4133             :         size_t slen, padlen, repeats, residual, i, nlen;
    4134             :         char *res;
    4135             : 
    4136             :         if (len < 0)
    4137             :                 len = 0;
    4138             : 
    4139          56 :         slen = (size_t) UTF8_strlen(s);
    4140          56 :         if (slen > (size_t) len) {
    4141             :                 /* truncate */
    4142          20 :                 pad = UTF8_strtail(s, len);
    4143          20 :                 slen = pad - s + 1;
    4144             : 
    4145          20 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, slen, malfunc);
    4146          20 :                 strcpy_len(*buf, s, slen);
    4147          20 :                 return MAL_SUCCEED;
    4148             :         }
    4149             : 
    4150          36 :         padlen = (size_t) UTF8_strlen(pad);
    4151          36 :         if (slen == (size_t) len || padlen == 0) {
    4152             :                 /* nothing to do (no padding if there is no pad string) */
    4153           0 :                 slen = strlen(s) + 1;
    4154           0 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, slen, malfunc);
    4155           0 :                 strcpy(*buf, s);
    4156           0 :                 return MAL_SUCCEED;
    4157             :         }
    4158             : 
    4159          36 :         repeats = ((size_t) len - slen) / padlen;
    4160          36 :         residual = ((size_t) len - slen) % padlen;
    4161          36 :         if (residual > 0)
    4162          18 :                 residual = (size_t) (UTF8_strtail(pad, (int) residual) - pad);
    4163          36 :         padlen = strlen(pad);
    4164          36 :         slen = strlen(s);
    4165             : 
    4166          36 :         nlen = slen + repeats * padlen + residual + 1;
    4167          36 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nlen, malfunc);
    4168          36 :         res = *buf;
    4169          36 :         if (left) {
    4170          81 :                 for (i = 0; i < repeats; i++)
    4171          63 :                         memcpy(res + i * padlen, pad, padlen);
    4172          18 :                 if (residual > 0)
    4173           9 :                         memcpy(res + repeats * padlen, pad, residual);
    4174          18 :                 if (slen > 0)
    4175          18 :                         memcpy(res + repeats * padlen + residual, s, slen);
    4176             :         } else {
    4177          18 :                 if (slen > 0)
    4178          18 :                         memcpy(res, s, slen);
    4179          81 :                 for (i = 0; i < repeats; i++)
    4180          63 :                         memcpy(res + slen + i * padlen, pad, padlen);
    4181          18 :                 if (residual > 0)
    4182           9 :                         memcpy(res + slen + repeats * padlen, pad, residual);
    4183             :         }
    4184          36 :         res[repeats * padlen + residual + slen] = 0;
    4185          36 :         return MAL_SUCCEED;
    4186             : }
    4187             : 
    4188             : str
    4189           4 : str_lpad(str *buf, size_t *buflen, str s, int len)
    4190             : {
    4191           7 :         return pad(buf, buflen, s, " ", len, 1, "str.lpad");
    4192             : }
    4193             : 
    4194             : /* Fill up 'arg1' to length 'len' by prepending whitespaces.
    4195             :  * If 'arg1' is already longer than 'len', then it's truncated on the right
    4196             :  * (NB: this is the PostgreSQL definition).
    4197             :  *
    4198             :  * Example: lpad('hi', 5)
    4199             :  * Result: '   hi'
    4200             :  */
    4201             : static str
    4202           3 : STRLpad(str *res, const str *arg1, const int *len)
    4203             : {
    4204           3 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4205           3 :         int l = *len;
    4206             : 
    4207           3 :         if (strNil(s) || is_int_nil(l)) {
    4208           0 :                 *res = GDKstrdup(str_nil);
    4209             :         } else {
    4210           3 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4211             : 
    4212           3 :                 *res = NULL;
    4213           3 :                 if (!(buf = GDKmalloc(buflen)))
    4214           0 :                         throw(MAL, "str.lpad", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4215           3 :                 if ((msg = str_lpad(&buf, &buflen, s, l)) != MAL_SUCCEED) {
    4216           0 :                         GDKfree(buf);
    4217           0 :                         return msg;
    4218             :                 }
    4219           3 :                 *res = GDKstrdup(buf);
    4220             :         }
    4221             : 
    4222           3 :         GDKfree(buf);
    4223           3 :         if (!*res)
    4224           0 :                 msg = createException(MAL, "str.lpad", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4225             :         return msg;
    4226             : }
    4227             : 
    4228             : str
    4229           4 : str_rpad(str *buf, size_t *buflen, str s, int len)
    4230             : {
    4231           7 :         return pad(buf, buflen, s, " ", len, 0, "str.lpad");
    4232             : }
    4233             : 
    4234             : /* Fill up 'arg1' to length 'len' by appending whitespaces.
    4235             :  * If 'arg1' is already longer than 'len', then it's truncated (on the right)
    4236             :  * (NB: this is the PostgreSQL definition).
    4237             :  *
    4238             :  * Example: rpad('hi', 5)
    4239             :  * Result: 'hi   '
    4240             :  */
    4241             : static str
    4242           3 : STRRpad(str *res, const str *arg1, const int *len)
    4243             : {
    4244           3 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4245           3 :         int l = *len;
    4246             : 
    4247           3 :         if (strNil(s) || is_int_nil(l)) {
    4248           0 :                 *res = GDKstrdup(str_nil);
    4249             :         } else {
    4250           3 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4251             : 
    4252           3 :                 *res = NULL;
    4253           3 :                 if (!(buf = GDKmalloc(buflen)))
    4254           0 :                         throw(MAL, "str.rpad", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4255           3 :                 if ((msg = str_rpad(&buf, &buflen, s, l)) != MAL_SUCCEED) {
    4256           0 :                         GDKfree(buf);
    4257           0 :                         return msg;
    4258             :                 }
    4259           3 :                 *res = GDKstrdup(buf);
    4260             :         }
    4261             : 
    4262           3 :         GDKfree(buf);
    4263           3 :         if (!*res)
    4264           0 :                 msg = createException(MAL, "str.rpad", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4265             :         return msg;
    4266             : }
    4267             : 
    4268             : str
    4269          16 : str_lpad3(str *buf, size_t *buflen, str s, int len, str s2)
    4270             : {
    4271          21 :         return pad(buf, buflen, s, s2, len, 1, "str.lpad2");
    4272             : }
    4273             : 
    4274             : /* Fill up 'arg1' to length 'len' by prepending characters from 'arg2'
    4275             :  * If 'arg1' is already longer than 'len', then it's truncated on the right
    4276             :  * (NB: this is the PostgreSQL definition).
    4277             :  *
    4278             :  * Example: lpad('hi', 5, 'xy')
    4279             :  * Result: xyxhi
    4280             :  */
    4281             : static str
    4282           5 : STRLpad3(str *res, const str *arg1, const int *len, const str *arg2)
    4283             : {
    4284           5 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2;
    4285           5 :         int l = *len;
    4286             : 
    4287          10 :         if (strNil(s) || strNil(s2) || is_int_nil(l)) {
    4288           0 :                 *res = GDKstrdup(str_nil);
    4289             :         } else {
    4290           5 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4291             : 
    4292           5 :                 *res = NULL;
    4293           5 :                 if (!(buf = GDKmalloc(buflen)))
    4294           0 :                         throw(MAL, "str.lpad2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4295           5 :                 if ((msg = str_lpad3(&buf, &buflen, s, l, s2)) != MAL_SUCCEED) {
    4296           0 :                         GDKfree(buf);
    4297           0 :                         return msg;
    4298             :                 }
    4299           5 :                 *res = GDKstrdup(buf);
    4300             :         }
    4301             : 
    4302           5 :         GDKfree(buf);
    4303           5 :         if (!*res)
    4304           0 :                 msg = createException(MAL, "str.lpad2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4305             :         return msg;
    4306             : }
    4307             : 
    4308             : str
    4309          16 : str_rpad3(str *buf, size_t *buflen, str s, int len, str s2)
    4310             : {
    4311          21 :         return pad(buf, buflen, s, s2, len, 0, "str.rpad2");
    4312             : }
    4313             : 
    4314             : /* Fill up 'arg1' to length 'len' by appending characters from 'arg2'
    4315             :  * If 'arg1' is already longer than 'len', then it's truncated (on the right)
    4316             :  * (NB: this is the PostgreSQL definition).
    4317             :  *
    4318             :  * Example: rpad('hi', 5, 'xy')
    4319             :  * Result: hixyx
    4320             :  */
    4321             : static str
    4322           5 : STRRpad3(str *res, const str *arg1, const int *len, const str *arg2)
    4323             : {
    4324           5 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2;
    4325           5 :         int l = *len;
    4326             : 
    4327          10 :         if (strNil(s) || strNil(s2) || is_int_nil(l)) {
    4328           0 :                 *res = GDKstrdup(str_nil);
    4329             :         } else {
    4330           5 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4331             : 
    4332           5 :                 *res = NULL;
    4333           5 :                 if (!(buf = GDKmalloc(buflen)))
    4334           0 :                         throw(MAL, "str.rpad2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4335           5 :                 if ((msg = str_rpad3(&buf, &buflen, s, l, s2)) != MAL_SUCCEED) {
    4336           0 :                         GDKfree(buf);
    4337           0 :                         return msg;
    4338             :                 }
    4339           5 :                 *res = GDKstrdup(buf);
    4340             :         }
    4341             : 
    4342           5 :         GDKfree(buf);
    4343           5 :         if (!*res)
    4344           0 :                 msg = createException(MAL, "str.rpad2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4345             :         return msg;
    4346             : }
    4347             : 
    4348             : str
    4349       82390 : str_substitute(str *buf, size_t *buflen, str s, str src, str dst, bit repeat)
    4350             : {
    4351       82390 :         size_t lsrc = strlen(src), ldst = strlen(dst), n, l = strlen(s);
    4352             :         char *b, *fnd;
    4353             :         const char *pfnd;
    4354             : 
    4355       82390 :         if (!lsrc || !l) { /* s/src is an empty string, there's nothing to substitute */
    4356         277 :                 l++;
    4357         277 :                 CHECK_STR_BUFFER_LENGTH(buf, buflen, l, "str.substitute");
    4358         277 :                 strcpy(*buf, s);
    4359         277 :                 return MAL_SUCCEED;
    4360             :         }
    4361             : 
    4362       82113 :         n = l + ldst;
    4363       82113 :         if (repeat && ldst > lsrc)
    4364       36146 :                 n = (ldst * l) / lsrc;  /* max length */
    4365             : 
    4366       82113 :         n++;
    4367       82113 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, n, "str.substitute");
    4368       82113 :         b = *buf;
    4369             :         pfnd = s;
    4370             :         do {
    4371       88767 :                 fnd = strstr(pfnd, src);
    4372       88767 :                 if (fnd == NULL)
    4373             :                         break;
    4374        6654 :                 n = fnd - pfnd;
    4375        6654 :                 if (n > 0) {
    4376        5769 :                         strcpy_len(b, pfnd, n + 1);
    4377        5769 :                         b += n;
    4378             :                 }
    4379        6654 :                 if (ldst > 0) {
    4380         587 :                         strcpy_len(b, dst, ldst + 1);
    4381         587 :                         b += ldst;
    4382             :                 }
    4383        6654 :                 if (*fnd == 0)
    4384             :                         break;
    4385        6654 :                 pfnd = fnd + lsrc;
    4386        6654 :         } while (repeat);
    4387       82113 :         strcpy(b, pfnd);
    4388       82113 :         return MAL_SUCCEED;
    4389             : }
    4390             : 
    4391             : static str
    4392        5450 : STRSubstitute(str *res, const str *arg1, const str *arg2, const str *arg3, const bit *g)
    4393             : {
    4394        5450 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1, s2 = *arg2, s3 = *arg3;
    4395             : 
    4396       16349 :         if (strNil(s) || strNil(s2) || strNil(s3)) {
    4397           2 :                 *res = GDKstrdup(str_nil);
    4398             :         } else {
    4399        5448 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4400             : 
    4401        5448 :                 *res = NULL;
    4402        5448 :                 if (!(buf = GDKmalloc(buflen)))
    4403           0 :                         throw(MAL, "str.substitute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4404        5448 :                 if ((msg = str_substitute(&buf, &buflen, s, s2, s3, *g)) != MAL_SUCCEED) {
    4405           0 :                         GDKfree(buf);
    4406           0 :                         return msg;
    4407             :                 }
    4408        5448 :                 *res = GDKstrdup(buf);
    4409             :         }
    4410             : 
    4411        5450 :         GDKfree(buf);
    4412        5450 :         if (!*res)
    4413           0 :                 msg = createException(MAL, "str.substitute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4414             :         return msg;
    4415             : }
    4416             : 
    4417             : static str
    4418           7 : STRascii(int *ret, const str *s)
    4419             : {
    4420           7 :         return str_wchr_at(ret, *s, 0);
    4421             : }
    4422             : 
    4423             : str
    4424          14 : str_substring_tail(str *buf, size_t *buflen, str s, int start)
    4425             : {
    4426             :         if( start <1) start =1;
    4427          20 :         start--;
    4428          20 :         return str_tail(buf, buflen, s, start);
    4429             : }
    4430             : 
    4431             : static str
    4432           6 : STRsubstringTail(str *res, const str *arg1, const int *start)
    4433             : {
    4434           6 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4435           6 :         int st = *start;
    4436             : 
    4437           6 :         if (strNil(s) || is_int_nil(st)) {
    4438           0 :                 *res = GDKstrdup(str_nil);
    4439             :         } else {
    4440           6 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4441             : 
    4442           6 :                 *res = NULL;
    4443           6 :                 if (!(buf = GDKmalloc(buflen)))
    4444           0 :                         throw(MAL, "str.substringTail", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4445           6 :                 if ((msg = str_substring_tail(&buf, &buflen, s, st)) != MAL_SUCCEED) {
    4446           0 :                         GDKfree(buf);
    4447           0 :                         return msg;
    4448             :                 }
    4449           6 :                 *res = GDKstrdup(buf);
    4450             :         }
    4451             : 
    4452           6 :         GDKfree(buf);
    4453           6 :         if (!*res)
    4454           0 :                 msg = createException(MAL, "str.substringTail", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4455             :         return msg;
    4456             : }
    4457             : 
    4458             : str
    4459     3553624 : str_sub_string(str *buf, size_t *buflen, str s, int start, int l)
    4460             : {
    4461             :         if( start <1) start =1;
    4462     3553640 :         start--;
    4463     3553640 :         return str_Sub_String(buf, buflen, s, start, l);
    4464             : }
    4465             : 
    4466             : static str
    4467          19 : STRsubstring(str *res, const str *arg1, const int *start, const int *ll)
    4468             : {
    4469          19 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4470          19 :         int st = *start, l = *ll;
    4471             : 
    4472          19 :         if (strNil(s) || is_int_nil(st) || is_int_nil(l)) {
    4473           3 :                 *res = GDKstrdup(str_nil);
    4474             :         } else {
    4475          16 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4476             : 
    4477          16 :                 *res = NULL;
    4478          16 :                 if (!(buf = GDKmalloc(buflen)))
    4479           0 :                         throw(MAL, "str.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4480          16 :                 if ((msg = str_sub_string(&buf, &buflen, s, st, l)) != MAL_SUCCEED) {
    4481           0 :                         GDKfree(buf);
    4482           0 :                         return msg;
    4483             :                 }
    4484          16 :                 *res = GDKstrdup(buf);
    4485             :         }
    4486             : 
    4487          19 :         GDKfree(buf);
    4488          19 :         if (!*res)
    4489           0 :                 msg = createException(MAL, "str.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4490             :         return msg;
    4491             : }
    4492             : 
    4493             : static str
    4494           4 : STRprefix(str *res, const str *arg1, const int *ll)
    4495             : {
    4496           4 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4497           4 :         int l = *ll;
    4498             : 
    4499           4 :         if (strNil(s) || is_int_nil(l)) {
    4500           0 :                 *res = GDKstrdup(str_nil);
    4501             :         } else {
    4502           4 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4503             : 
    4504           4 :                 *res = NULL;
    4505           4 :                 if (!(buf = GDKmalloc(buflen)))
    4506           0 :                         throw(MAL, "str.prefix", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4507           4 :                 if ((msg = str_Sub_String(&buf, &buflen, s, 0, l)) != MAL_SUCCEED) {
    4508           0 :                         GDKfree(buf);
    4509           0 :                         return msg;
    4510             :                 }
    4511           4 :                 *res = GDKstrdup(buf);
    4512             :         }
    4513             : 
    4514           4 :         GDKfree(buf);
    4515           4 :         if (!*res)
    4516           0 :                 msg = createException(MAL, "str.prefix", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4517             :         return msg;
    4518             : }
    4519             : 
    4520             : str
    4521           6 : str_suffix(str *buf, size_t *buflen, str s, int l)
    4522             : {
    4523           6 :         int start = (int) (strlen(s) - l);
    4524           6 :         return str_Sub_String(buf, buflen, s, start, l);
    4525             : }
    4526             : 
    4527             : static str
    4528           2 : STRsuffix(str *res, const str *arg1, const int *ll)
    4529             : {
    4530           2 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4531           2 :         int l = *ll;
    4532             : 
    4533           2 :         if (strNil(s) || is_int_nil(l)) {
    4534           0 :                 *res = GDKstrdup(str_nil);
    4535             :         } else {
    4536           2 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4537             : 
    4538           2 :                 *res = NULL;
    4539           2 :                 if (!(buf = GDKmalloc(buflen)))
    4540           0 :                         throw(MAL, "str.suffix", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4541           2 :                 if ((msg = str_suffix(&buf, &buflen, s, l)) != MAL_SUCCEED) {
    4542           0 :                         GDKfree(buf);
    4543           0 :                         return msg;
    4544             :                 }
    4545           2 :                 *res = GDKstrdup(buf);
    4546             :         }
    4547             : 
    4548           2 :         GDKfree(buf);
    4549           2 :         if (!*res)
    4550           0 :                 msg = createException(MAL, "str.suffix", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4551             :         return msg;
    4552             : }
    4553             : 
    4554             : int
    4555          36 : str_locate2(str needle, str haystack, int start)
    4556             : {
    4557             :         int off, res;
    4558             :         char *s;
    4559             : 
    4560          36 :         off = start <= 0 ? 1 : start;
    4561          36 :         s = UTF8_strtail(haystack, off - 1);
    4562          36 :         res = str_search(s, needle);
    4563          36 :         return res >= 0 ? res + off : 0;
    4564             : }
    4565             : 
    4566             : static str
    4567          70 : STRlocate3(int *ret, const str *needle, const str *haystack, const int *start)
    4568             : {
    4569          70 :         str s = *needle, s2 = *haystack;
    4570          70 :         int st = *start;
    4571             : 
    4572         140 :         *ret = (strNil(s) || strNil(s2) || is_int_nil(st)) ? int_nil : str_locate2(s, s2, st);
    4573          70 :         return MAL_SUCCEED;
    4574             : }
    4575             : 
    4576             : static str
    4577          11 : STRlocate(int *ret, const str *needle, const str *haystack)
    4578             : {
    4579          11 :         str s = *needle, s2 = *haystack;
    4580             : 
    4581          19 :         *ret = (strNil(s) || strNil(s2)) ? int_nil : str_locate2(s, s2, 1);
    4582          11 :         return MAL_SUCCEED;
    4583             : }
    4584             : 
    4585             : str
    4586         221 : str_insert(str *buf, size_t *buflen, str s, int strt, int l, str s2)
    4587             : {
    4588             :         str v;
    4589         221 :         int l1 = UTF8_strlen(s);
    4590             :         size_t nextlen;
    4591             : 
    4592         221 :         if (l < 0)
    4593           0 :                 throw(MAL, "str.insert", SQLSTATE(42000) "The number of characters for insert function must be non negative");
    4594         221 :         if (strt < 0) {
    4595           0 :                 if (-strt <= l1)
    4596           0 :                         strt = l1 + strt;
    4597             :                 else
    4598             :                         strt = 0;
    4599             :         }
    4600             :         if (strt > l1)
    4601             :                 strt = l1;
    4602             : 
    4603         221 :         nextlen = strlen(s) + strlen(s2) + 1;
    4604         221 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nextlen, "str.insert");
    4605         221 :         v = *buf;
    4606         221 :         if (strt > 0)
    4607         214 :                 v = UTF8_strncpy(v, s, strt);
    4608         221 :         strcpy(v, s2);
    4609         221 :         if (strt + l < l1)
    4610           9 :                 strcat(v, UTF8_offset((char *)s, strt + l));
    4611             :         return MAL_SUCCEED;
    4612             : }
    4613             : 
    4614             : static str
    4615         223 : STRinsert(str *res, const str *input, const int *start, const int *nchars, const str *input2)
    4616             : {
    4617         223 :         str buf = NULL, msg = MAL_SUCCEED, s = *input, s2 = *input2;
    4618         223 :         int st = *start, n = *nchars;
    4619             : 
    4620         445 :         if (strNil(s) || is_int_nil(st) || is_int_nil(n) || strNil(s2)) {
    4621           2 :                 *res = GDKstrdup(str_nil);
    4622             :         } else {
    4623         221 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4624             : 
    4625         221 :                 *res = NULL;
    4626         221 :                 if (!(buf = GDKmalloc(buflen)))
    4627           0 :                         throw(MAL, "str.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4628         221 :                 if ((msg = str_insert(&buf, &buflen, s, st, n, s2)) != MAL_SUCCEED) {
    4629           0 :                         GDKfree(buf);
    4630           0 :                         return msg;
    4631             :                 }
    4632         221 :                 *res = GDKstrdup(buf);
    4633             :         }
    4634             : 
    4635         223 :         GDKfree(buf);
    4636         223 :         if (!*res)
    4637           0 :                 msg = createException(MAL, "str.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4638             :         return msg;
    4639             : }
    4640             : 
    4641             : static str
    4642        5450 : STRreplace(str *ret, const str *s1, const str *s2, const str *s3)
    4643             : {
    4644        5450 :         bit flag= TRUE;
    4645        5450 :         return STRSubstitute(ret,s1,s2,s3,&flag);
    4646             : }
    4647             : 
    4648             : str
    4649          12 : str_repeat(str *buf, size_t *buflen, str s, int c)
    4650             : {
    4651          12 :         size_t l = strlen(s), nextlen;
    4652             : 
    4653          12 :         if (l >= INT_MAX)
    4654           0 :                 throw(MAL, "str.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4655          12 :         nextlen = (size_t) c * l + 1;
    4656             : 
    4657          12 :         CHECK_STR_BUFFER_LENGTH(buf, buflen, nextlen, "str.repeat");
    4658          12 :         str t = *buf;
    4659          12 :         *t = 0;
    4660      160031 :         for (int i = c; i>0; i--, t += l)
    4661      160019 :                 strcpy(t, s);
    4662             :         return MAL_SUCCEED;
    4663             : }
    4664             : 
    4665             : static str
    4666           9 : STRrepeat(str *res, const str *arg1, const int *c)
    4667             : {
    4668           9 :         str buf = NULL, msg = MAL_SUCCEED, s = *arg1;
    4669           9 :         int cc = *c;
    4670             : 
    4671           9 :         if (strNil(s) || is_int_nil(cc) || cc < 0) {
    4672           1 :                 *res = GDKstrdup(str_nil);
    4673             :         } else {
    4674           8 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4675             : 
    4676           8 :                 *res = NULL;
    4677           8 :                 if (!(buf = GDKmalloc(buflen)))
    4678           0 :                         throw(MAL, "str.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4679           8 :                 if ((msg = str_repeat(&buf, &buflen, s, cc)) != MAL_SUCCEED) {
    4680           0 :                         GDKfree(buf);
    4681           0 :                         return msg;
    4682             :                 }
    4683           8 :                 *res = GDKstrdup(buf);
    4684             :         }
    4685             : 
    4686           9 :         GDKfree(buf);
    4687           9 :         if (!*res)
    4688           0 :                 msg = createException(MAL, "str.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4689             :         return msg;
    4690             : }
    4691             : 
    4692             : static str
    4693           0 : STRspace(str *res, const int *ll)
    4694             : {
    4695           0 :         str buf = NULL, msg = MAL_SUCCEED;
    4696           0 :         int l = *ll;
    4697             : 
    4698           0 :         if (is_int_nil(l) || l < 0) {
    4699           0 :                 *res = GDKstrdup(str_nil);
    4700             :         } else {
    4701           0 :                 char space[] = " ", *s= space;
    4702           0 :                 size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4703             : 
    4704           0 :                 *res = NULL;
    4705           0 :                 if (!(buf = GDKmalloc(buflen)))
    4706           0 :                         throw(MAL, "str.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4707           0 :                 if ((msg = str_repeat(&buf, &buflen, s, l)) != MAL_SUCCEED) {
    4708           0 :                         GDKfree(buf);
    4709           0 :                         return msg;
    4710             :                 }
    4711           0 :                 *res = GDKstrdup(buf);
    4712             :         }
    4713             : 
    4714           0 :         GDKfree(buf);
    4715           0 :         if (!*res)
    4716           0 :                 msg = createException(MAL, "str.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4717             :         return msg;
    4718             : }
    4719             : 
    4720             : #include "mel.h"
    4721             : mel_func str_init_funcs[] = {
    4722             :  command("str", "str", STRtostr, false, "Noop routine.", args(1,2, arg("",str),arg("s",str))),
    4723             :  command("str", "string", STRTail, false, "Return the tail s[offset..n]\nof a string s[0..n].", args(1,3, arg("",str),arg("s",str),arg("offset",int))),
    4724             :  command("str", "string3", STRSubString, false, "Return substring s[offset..offset+count] of a string s[0..n]", args(1,4, arg("",str),arg("s",str),arg("offset",int),arg("count",int))),
    4725             :  command("str", "length", STRLength, false, "Return the length of a string.", args(1,2, arg("",int),arg("s",str))),
    4726             :  command("str", "nbytes", STRBytes, false, "Return the string length in bytes.", args(1,2, arg("",int),arg("s",str))),
    4727             :  command("str", "unicodeAt", STRWChrAt, false, "get a unicode character\n(as an int) from a string position.", args(1,3, arg("",int),arg("s",str),arg("index",int))),
    4728             :  command("str", "unicode", STRFromWChr, false, "convert a unicode to a character.", args(1,2, arg("",str),arg("wchar",int))),
    4729             :  command("str", "startsWith", STRPrefix, false, "Prefix check.", args(1,3, arg("",bit),arg("s",str),arg("prefix",str))),
    4730             :  command("str", "endsWith", STRSuffix, false, "Suffix check.", args(1,3, arg("",bit),arg("s",str),arg("suffix",str))),
    4731             :  command("str", "toLower", STRLower, false, "Convert a string to lower case.", args(1,2, arg("",str),arg("s",str))),
    4732             :  command("str", "toUpper", STRUpper, false, "Convert a string to upper case.", args(1,2, arg("",str),arg("s",str))),
    4733             :  command("str", "search", STRstrSearch, false, "Search for a substring. Returns\nposition, -1 if not found.", args(1,3, arg("",int),arg("s",str),arg("c",str))),
    4734             :  command("str", "r_search", STRReverseStrSearch, false, "Reverse search for a substring. Returns\nposition, -1 if not found.", args(1,3, arg("",int),arg("s",str),arg("c",str))),
    4735             :  command("str", "splitpart", STRsplitpart, false, "Split string on delimiter. Returns\ngiven field (counting from one.)", args(1,4, arg("",str),arg("s",str),arg("needle",str),arg("field",int))),
    4736             :  command("str", "trim", STRStrip, false, "Strip whitespaces around a string.", args(1,2, arg("",str),arg("s",str))),
    4737             :  command("str", "ltrim", STRLtrim, false, "Strip whitespaces from start of a string.", args(1,2, arg("",str),arg("s",str))),
    4738             :  command("str", "rtrim", STRRtrim, false, "Strip whitespaces from end of a string.", args(1,2, arg("",str),arg("s",str))),
    4739             :  command("str", "trim2", STRStrip2, false, "Remove the longest string containing only characters from the second string around the first string.", args(1,3, arg("",str),arg("s",str),arg("s2",str))),
    4740             :  command("str", "ltrim2", STRLtrim2, false, "Remove the longest string containing only characters from the second string from the start of the first string.", args(1,3, arg("",str),arg("s",str),arg("s2",str))),
    4741             :  command("str", "rtrim2", STRRtrim2, false, "Remove the longest string containing only characters from the second string from the end of the first string.", args(1,3, arg("",str),arg("s",str),arg("s2",str))),
    4742             :  command("str", "lpad", STRLpad, false, "Fill up a string to the given length prepending the whitespace character.", args(1,3, arg("",str),arg("s",str),arg("len",int))),
    4743             :  command("str", "rpad", STRRpad, false, "Fill up a string to the given length appending the whitespace character.", args(1,3, arg("",str),arg("s",str),arg("len",int))),
    4744             :  command("str", "lpad3", STRLpad3, false, "Fill up the first string to the given length prepending characters of the second string.", args(1,4, arg("",str),arg("s",str),arg("len",int),arg("s2",str))),
    4745             :  command("str", "rpad3", STRRpad3, false, "Fill up the first string to the given length appending characters of the second string.", args(1,4, arg("",str),arg("s",str),arg("len",int),arg("s2",str))),
    4746             :  command("str", "substitute", STRSubstitute, false, "Substitute first occurrence of 'src' by\n'dst'.  Iff repeated = true this is\nrepeated while 'src' can be found in the\nresult string. In order to prevent\nrecursion and result strings of unlimited\nsize, repeating is only done iff src is\nnot a substring of dst.", args(1,5, arg("",str),arg("s",str),arg("src",str),arg("dst",str),arg("rep",bit))),
    4747             :  command("str", "like", STRlikewrap, false, "SQL pattern match function", args(1,3, arg("",bit),arg("s",str),arg("pat",str))),
    4748             :  command("str", "like3", STRlikewrap3, false, "SQL pattern match function", args(1,4, arg("",bit),arg("s",str),arg("pat",str),arg("esc",str))),
    4749             :  command("str", "ascii", STRascii, false, "Return unicode of head of string", args(1,2, arg("",int),arg("s",str))),
    4750             :  command("str", "substring", STRsubstringTail, false, "Extract the tail of a string", args(1,3, arg("",str),arg("s",str),arg("start",int))),
    4751             :  command("str", "substring3", STRsubstring, false, "Extract a substring from str starting at start, for length len", args(1,4, arg("",str),arg("s",str),arg("start",int),arg("len",int))),
    4752             :  command("str", "prefix", STRprefix, false, "Extract the prefix of a given length", args(1,3, arg("",str),arg("s",str),arg("l",int))),
    4753             :  command("str", "suffix", STRsuffix, false, "Extract the suffix of a given length", args(1,3, arg("",str),arg("s",str),arg("l",int))),
    4754             :  command("str", "stringleft", STRprefix, false, "", args(1,3, arg("",str),arg("s",str),arg("l",int))),
    4755             :  command("str", "stringright", STRsuffix, false, "", args(1,3, arg("",str),arg("s",str),arg("l",int))),
    4756             :  command("str", "locate", STRlocate, false, "Locate the start position of a string", args(1,3, arg("",int),arg("s1",str),arg("s2",str))),
    4757             :  command("str", "locate3", STRlocate3, false, "Locate the start position of a string", args(1,4, arg("",int),arg("s1",str),arg("s2",str),arg("start",int))),
    4758             :  command("str", "insert", STRinsert, false, "Insert a string into another", args(1,5, arg("",str),arg("s",str),arg("start",int),arg("l",int),arg("s2",str))),
    4759             :  command("str", "replace", STRreplace, false, "Insert a string into another", args(1,4, arg("",str),arg("s",str),arg("pat",str),arg("s2",str))),
    4760             :  command("str", "repeat", STRrepeat, false, "", args(1,3, arg("",str),arg("s2",str),arg("c",int))),
    4761             :  command("str", "space", STRspace, false, "", args(1,2, arg("",str),arg("l",int))),
    4762             :  command("str", "prelude", STRprelude, false, "", args(1,1, arg("",void))),
    4763             :  command("str", "epilogue", STRepilogue, false, "", args(1,1, arg("",void))),
    4764             :  { .imp=NULL }
    4765             : };
    4766             : #include "mal_import.h"
    4767             : #ifdef _MSC_VER
    4768             : #undef read
    4769             : #pragma section(".CRT$XCU",read)
    4770             : #endif
    4771         259 : LIB_STARTUP_FUNC(init_str_mal)
    4772         259 : { mal_module("str", NULL, str_init_funcs); }

Generated by: LCOV version 1.14