LCOV - code coverage report
Current view: top level - src/backend/utils/mb - wchar.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 184 818 22.5 %
Date: 2019-06-19 16:07:09 Functions: 27 77 35.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * conversion functions between pg_wchar and multibyte streams.
       3             :  * Tatsuo Ishii
       4             :  * src/backend/utils/mb/wchar.c
       5             :  *
       6             :  */
       7             : /* can be used in either frontend or backend */
       8             : #ifdef FRONTEND
       9             : #include "postgres_fe.h"
      10             : #else
      11             : #include "postgres.h"
      12             : #endif
      13             : 
      14             : #include "mb/pg_wchar.h"
      15             : 
      16             : 
      17             : /*
      18             :  * Operations on multi-byte encodings are driven by a table of helper
      19             :  * functions.
      20             :  *
      21             :  * To add an encoding support, define mblen(), dsplen() and verifier() for
      22             :  * the encoding.  For server-encodings, also define mb2wchar() and wchar2mb()
      23             :  * conversion functions.
      24             :  *
      25             :  * These functions generally assume that their input is validly formed.
      26             :  * The "verifier" functions, further down in the file, have to be more
      27             :  * paranoid.
      28             :  *
      29             :  * We expect that mblen() does not need to examine more than the first byte
      30             :  * of the character to discover the correct length.  GB18030 is an exception
      31             :  * to that rule, though, as it also looks at second byte.  But even that
      32             :  * behaves in a predictable way, if you only pass the first byte: it will
      33             :  * treat 4-byte encoded characters as two 2-byte encoded characters, which is
      34             :  * good enough for all current uses.
      35             :  *
      36             :  * Note: for the display output of psql to work properly, the return values
      37             :  * of the dsplen functions must conform to the Unicode standard. In particular
      38             :  * the NUL character is zero width and control characters are generally
      39             :  * width -1. It is recommended that non-ASCII encodings refer their ASCII
      40             :  * subset to the ASCII routines to ensure consistency.
      41             :  */
      42             : 
      43             : /*
      44             :  * SQL/ASCII
      45             :  */
      46             : static int
      47           8 : pg_ascii2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
      48             : {
      49           8 :     int         cnt = 0;
      50             : 
      51         884 :     while (len > 0 && *from)
      52             :     {
      53         868 :         *to++ = *from++;
      54         868 :         len--;
      55         868 :         cnt++;
      56             :     }
      57           8 :     *to = 0;
      58           8 :     return cnt;
      59             : }
      60             : 
      61             : static int
      62          16 : pg_ascii_mblen(const unsigned char *s)
      63             : {
      64          16 :     return 1;
      65             : }
      66             : 
      67             : static int
      68           0 : pg_ascii_dsplen(const unsigned char *s)
      69             : {
      70           0 :     if (*s == '\0')
      71           0 :         return 0;
      72           0 :     if (*s < 0x20 || *s == 0x7f)
      73           0 :         return -1;
      74             : 
      75           0 :     return 1;
      76             : }
      77             : 
      78             : /*
      79             :  * EUC
      80             :  */
      81             : static int
      82           0 : pg_euc2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
      83             : {
      84           0 :     int         cnt = 0;
      85             : 
      86           0 :     while (len > 0 && *from)
      87             :     {
      88           0 :         if (*from == SS2 && len >= 2)    /* JIS X 0201 (so called "1 byte
      89             :                                          * KANA") */
      90             :         {
      91           0 :             from++;
      92           0 :             *to = (SS2 << 8) | *from++;
      93           0 :             len -= 2;
      94             :         }
      95           0 :         else if (*from == SS3 && len >= 3)   /* JIS X 0212 KANJI */
      96             :         {
      97           0 :             from++;
      98           0 :             *to = (SS3 << 16) | (*from++ << 8);
      99           0 :             *to |= *from++;
     100           0 :             len -= 3;
     101             :         }
     102           0 :         else if (IS_HIGHBIT_SET(*from) && len >= 2) /* JIS X 0208 KANJI */
     103             :         {
     104           0 :             *to = *from++ << 8;
     105           0 :             *to |= *from++;
     106           0 :             len -= 2;
     107             :         }
     108             :         else                    /* must be ASCII */
     109             :         {
     110           0 :             *to = *from++;
     111           0 :             len--;
     112             :         }
     113           0 :         to++;
     114           0 :         cnt++;
     115             :     }
     116           0 :     *to = 0;
     117           0 :     return cnt;
     118             : }
     119             : 
     120             : static inline int
     121           0 : pg_euc_mblen(const unsigned char *s)
     122             : {
     123             :     int         len;
     124             : 
     125           0 :     if (*s == SS2)
     126           0 :         len = 2;
     127           0 :     else if (*s == SS3)
     128           0 :         len = 3;
     129           0 :     else if (IS_HIGHBIT_SET(*s))
     130           0 :         len = 2;
     131             :     else
     132           0 :         len = 1;
     133           0 :     return len;
     134             : }
     135             : 
     136             : static inline int
     137           0 : pg_euc_dsplen(const unsigned char *s)
     138             : {
     139             :     int         len;
     140             : 
     141           0 :     if (*s == SS2)
     142           0 :         len = 2;
     143           0 :     else if (*s == SS3)
     144           0 :         len = 2;
     145           0 :     else if (IS_HIGHBIT_SET(*s))
     146           0 :         len = 2;
     147             :     else
     148           0 :         len = pg_ascii_dsplen(s);
     149           0 :     return len;
     150             : }
     151             : 
     152             : /*
     153             :  * EUC_JP
     154             :  */
     155             : static int
     156           0 : pg_eucjp2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     157             : {
     158           0 :     return pg_euc2wchar_with_len(from, to, len);
     159             : }
     160             : 
     161             : static int
     162           0 : pg_eucjp_mblen(const unsigned char *s)
     163             : {
     164           0 :     return pg_euc_mblen(s);
     165             : }
     166             : 
     167             : static int
     168           0 : pg_eucjp_dsplen(const unsigned char *s)
     169             : {
     170             :     int         len;
     171             : 
     172           0 :     if (*s == SS2)
     173           0 :         len = 1;
     174           0 :     else if (*s == SS3)
     175           0 :         len = 2;
     176           0 :     else if (IS_HIGHBIT_SET(*s))
     177           0 :         len = 2;
     178             :     else
     179           0 :         len = pg_ascii_dsplen(s);
     180           0 :     return len;
     181             : }
     182             : 
     183             : /*
     184             :  * EUC_KR
     185             :  */
     186             : static int
     187           0 : pg_euckr2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     188             : {
     189           0 :     return pg_euc2wchar_with_len(from, to, len);
     190             : }
     191             : 
     192             : static int
     193           0 : pg_euckr_mblen(const unsigned char *s)
     194             : {
     195           0 :     return pg_euc_mblen(s);
     196             : }
     197             : 
     198             : static int
     199           0 : pg_euckr_dsplen(const unsigned char *s)
     200             : {
     201           0 :     return pg_euc_dsplen(s);
     202             : }
     203             : 
     204             : /*
     205             :  * EUC_CN
     206             :  *
     207             :  */
     208             : static int
     209           0 : pg_euccn2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     210             : {
     211           0 :     int         cnt = 0;
     212             : 
     213           0 :     while (len > 0 && *from)
     214             :     {
     215           0 :         if (*from == SS2 && len >= 3)    /* code set 2 (unused?) */
     216             :         {
     217           0 :             from++;
     218           0 :             *to = (SS2 << 16) | (*from++ << 8);
     219           0 :             *to |= *from++;
     220           0 :             len -= 3;
     221             :         }
     222           0 :         else if (*from == SS3 && len >= 3)   /* code set 3 (unused ?) */
     223             :         {
     224           0 :             from++;
     225           0 :             *to = (SS3 << 16) | (*from++ << 8);
     226           0 :             *to |= *from++;
     227           0 :             len -= 3;
     228             :         }
     229           0 :         else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 1 */
     230             :         {
     231           0 :             *to = *from++ << 8;
     232           0 :             *to |= *from++;
     233           0 :             len -= 2;
     234             :         }
     235             :         else
     236             :         {
     237           0 :             *to = *from++;
     238           0 :             len--;
     239             :         }
     240           0 :         to++;
     241           0 :         cnt++;
     242             :     }
     243           0 :     *to = 0;
     244           0 :     return cnt;
     245             : }
     246             : 
     247             : static int
     248           0 : pg_euccn_mblen(const unsigned char *s)
     249             : {
     250             :     int         len;
     251             : 
     252           0 :     if (IS_HIGHBIT_SET(*s))
     253           0 :         len = 2;
     254             :     else
     255           0 :         len = 1;
     256           0 :     return len;
     257             : }
     258             : 
     259             : static int
     260           0 : pg_euccn_dsplen(const unsigned char *s)
     261             : {
     262             :     int         len;
     263             : 
     264           0 :     if (IS_HIGHBIT_SET(*s))
     265           0 :         len = 2;
     266             :     else
     267           0 :         len = pg_ascii_dsplen(s);
     268           0 :     return len;
     269             : }
     270             : 
     271             : /*
     272             :  * EUC_TW
     273             :  *
     274             :  */
     275             : static int
     276           0 : pg_euctw2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     277             : {
     278           0 :     int         cnt = 0;
     279             : 
     280           0 :     while (len > 0 && *from)
     281             :     {
     282           0 :         if (*from == SS2 && len >= 4)    /* code set 2 */
     283             :         {
     284           0 :             from++;
     285           0 :             *to = (((uint32) SS2) << 24) | (*from++ << 16);
     286           0 :             *to |= *from++ << 8;
     287           0 :             *to |= *from++;
     288           0 :             len -= 4;
     289             :         }
     290           0 :         else if (*from == SS3 && len >= 3)   /* code set 3 (unused?) */
     291             :         {
     292           0 :             from++;
     293           0 :             *to = (SS3 << 16) | (*from++ << 8);
     294           0 :             *to |= *from++;
     295           0 :             len -= 3;
     296             :         }
     297           0 :         else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 2 */
     298             :         {
     299           0 :             *to = *from++ << 8;
     300           0 :             *to |= *from++;
     301           0 :             len -= 2;
     302             :         }
     303             :         else
     304             :         {
     305           0 :             *to = *from++;
     306           0 :             len--;
     307             :         }
     308           0 :         to++;
     309           0 :         cnt++;
     310             :     }
     311           0 :     *to = 0;
     312           0 :     return cnt;
     313             : }
     314             : 
     315             : static int
     316           0 : pg_euctw_mblen(const unsigned char *s)
     317             : {
     318             :     int         len;
     319             : 
     320           0 :     if (*s == SS2)
     321           0 :         len = 4;
     322           0 :     else if (*s == SS3)
     323           0 :         len = 3;
     324           0 :     else if (IS_HIGHBIT_SET(*s))
     325           0 :         len = 2;
     326             :     else
     327           0 :         len = 1;
     328           0 :     return len;
     329             : }
     330             : 
     331             : static int
     332           0 : pg_euctw_dsplen(const unsigned char *s)
     333             : {
     334             :     int         len;
     335             : 
     336           0 :     if (*s == SS2)
     337           0 :         len = 2;
     338           0 :     else if (*s == SS3)
     339           0 :         len = 2;
     340           0 :     else if (IS_HIGHBIT_SET(*s))
     341           0 :         len = 2;
     342             :     else
     343           0 :         len = pg_ascii_dsplen(s);
     344           0 :     return len;
     345             : }
     346             : 
     347             : /*
     348             :  * Convert pg_wchar to EUC_* encoding.
     349             :  * caller must allocate enough space for "to", including a trailing zero!
     350             :  * len: length of from.
     351             :  * "from" not necessarily null terminated.
     352             :  */
     353             : static int
     354           0 : pg_wchar2euc_with_len(const pg_wchar *from, unsigned char *to, int len)
     355             : {
     356           0 :     int         cnt = 0;
     357             : 
     358           0 :     while (len > 0 && *from)
     359             :     {
     360             :         unsigned char c;
     361             : 
     362           0 :         if ((c = (*from >> 24)))
     363             :         {
     364           0 :             *to++ = c;
     365           0 :             *to++ = (*from >> 16) & 0xff;
     366           0 :             *to++ = (*from >> 8) & 0xff;
     367           0 :             *to++ = *from & 0xff;
     368           0 :             cnt += 4;
     369             :         }
     370           0 :         else if ((c = (*from >> 16)))
     371             :         {
     372           0 :             *to++ = c;
     373           0 :             *to++ = (*from >> 8) & 0xff;
     374           0 :             *to++ = *from & 0xff;
     375           0 :             cnt += 3;
     376             :         }
     377           0 :         else if ((c = (*from >> 8)))
     378             :         {
     379           0 :             *to++ = c;
     380           0 :             *to++ = *from & 0xff;
     381           0 :             cnt += 2;
     382             :         }
     383             :         else
     384             :         {
     385           0 :             *to++ = *from;
     386           0 :             cnt++;
     387             :         }
     388           0 :         from++;
     389           0 :         len--;
     390             :     }
     391           0 :     *to = 0;
     392           0 :     return cnt;
     393             : }
     394             : 
     395             : 
     396             : /*
     397             :  * JOHAB
     398             :  */
     399             : static int
     400           0 : pg_johab_mblen(const unsigned char *s)
     401             : {
     402           0 :     return pg_euc_mblen(s);
     403             : }
     404             : 
     405             : static int
     406           0 : pg_johab_dsplen(const unsigned char *s)
     407             : {
     408           0 :     return pg_euc_dsplen(s);
     409             : }
     410             : 
     411             : /*
     412             :  * convert UTF8 string to pg_wchar (UCS-4)
     413             :  * caller must allocate enough space for "to", including a trailing zero!
     414             :  * len: length of from.
     415             :  * "from" not necessarily null terminated.
     416             :  */
     417             : static int
     418      618942 : pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     419             : {
     420      618942 :     int         cnt = 0;
     421             :     uint32      c1,
     422             :                 c2,
     423             :                 c3,
     424             :                 c4;
     425             : 
     426    42187028 :     while (len > 0 && *from)
     427             :     {
     428    40949144 :         if ((*from & 0x80) == 0)
     429             :         {
     430    40949144 :             *to = *from++;
     431    40949144 :             len--;
     432             :         }
     433           0 :         else if ((*from & 0xe0) == 0xc0)
     434             :         {
     435           0 :             if (len < 2)
     436           0 :                 break;          /* drop trailing incomplete char */
     437           0 :             c1 = *from++ & 0x1f;
     438           0 :             c2 = *from++ & 0x3f;
     439           0 :             *to = (c1 << 6) | c2;
     440           0 :             len -= 2;
     441             :         }
     442           0 :         else if ((*from & 0xf0) == 0xe0)
     443             :         {
     444           0 :             if (len < 3)
     445           0 :                 break;          /* drop trailing incomplete char */
     446           0 :             c1 = *from++ & 0x0f;
     447           0 :             c2 = *from++ & 0x3f;
     448           0 :             c3 = *from++ & 0x3f;
     449           0 :             *to = (c1 << 12) | (c2 << 6) | c3;
     450           0 :             len -= 3;
     451             :         }
     452           0 :         else if ((*from & 0xf8) == 0xf0)
     453             :         {
     454           0 :             if (len < 4)
     455           0 :                 break;          /* drop trailing incomplete char */
     456           0 :             c1 = *from++ & 0x07;
     457           0 :             c2 = *from++ & 0x3f;
     458           0 :             c3 = *from++ & 0x3f;
     459           0 :             c4 = *from++ & 0x3f;
     460           0 :             *to = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
     461           0 :             len -= 4;
     462             :         }
     463             :         else
     464             :         {
     465             :             /* treat a bogus char as length 1; not ours to raise error */
     466           0 :             *to = *from++;
     467           0 :             len--;
     468             :         }
     469    40949144 :         to++;
     470    40949144 :         cnt++;
     471             :     }
     472      618942 :     *to = 0;
     473      618942 :     return cnt;
     474             : }
     475             : 
     476             : 
     477             : /*
     478             :  * Map a Unicode code point to UTF-8.  utf8string must have 4 bytes of
     479             :  * space allocated.
     480             :  */
     481             : unsigned char *
     482    15184618 : unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
     483             : {
     484    15184618 :     if (c <= 0x7F)
     485             :     {
     486    15184536 :         utf8string[0] = c;
     487             :     }
     488          82 :     else if (c <= 0x7FF)
     489             :     {
     490          26 :         utf8string[0] = 0xC0 | ((c >> 6) & 0x1F);
     491          26 :         utf8string[1] = 0x80 | (c & 0x3F);
     492             :     }
     493          56 :     else if (c <= 0xFFFF)
     494             :     {
     495          16 :         utf8string[0] = 0xE0 | ((c >> 12) & 0x0F);
     496          16 :         utf8string[1] = 0x80 | ((c >> 6) & 0x3F);
     497          16 :         utf8string[2] = 0x80 | (c & 0x3F);
     498             :     }
     499             :     else
     500             :     {
     501          40 :         utf8string[0] = 0xF0 | ((c >> 18) & 0x07);
     502          40 :         utf8string[1] = 0x80 | ((c >> 12) & 0x3F);
     503          40 :         utf8string[2] = 0x80 | ((c >> 6) & 0x3F);
     504          40 :         utf8string[3] = 0x80 | (c & 0x3F);
     505             :     }
     506             : 
     507    15184618 :     return utf8string;
     508             : }
     509             : 
     510             : /*
     511             :  * Trivial conversion from pg_wchar to UTF-8.
     512             :  * caller should allocate enough space for "to"
     513             :  * len: length of from.
     514             :  * "from" not necessarily null terminated.
     515             :  */
     516             : static int
     517     1008020 : pg_wchar2utf_with_len(const pg_wchar *from, unsigned char *to, int len)
     518             : {
     519     1008020 :     int         cnt = 0;
     520             : 
     521    17200428 :     while (len > 0 && *from)
     522             :     {
     523             :         int         char_len;
     524             : 
     525    15184388 :         unicode_to_utf8(*from, to);
     526    15184388 :         char_len = pg_utf_mblen(to);
     527    15184388 :         cnt += char_len;
     528    15184388 :         to += char_len;
     529    15184388 :         from++;
     530    15184388 :         len--;
     531             :     }
     532     1008020 :     *to = 0;
     533     1008020 :     return cnt;
     534             : }
     535             : 
     536             : /*
     537             :  * Return the byte length of a UTF8 character pointed to by s
     538             :  *
     539             :  * Note: in the current implementation we do not support UTF8 sequences
     540             :  * of more than 4 bytes; hence do NOT return a value larger than 4.
     541             :  * We return "1" for any leading byte that is either flat-out illegal or
     542             :  * indicates a length larger than we support.
     543             :  *
     544             :  * pg_utf2wchar_with_len(), utf8_to_unicode(), pg_utf8_islegal(), and perhaps
     545             :  * other places would need to be fixed to change this.
     546             :  */
     547             : int
     548   138442888 : pg_utf_mblen(const unsigned char *s)
     549             : {
     550             :     int         len;
     551             : 
     552   138442888 :     if ((*s & 0x80) == 0)
     553   138414948 :         len = 1;
     554       27940 :     else if ((*s & 0xe0) == 0xc0)
     555       12384 :         len = 2;
     556       15556 :     else if ((*s & 0xf0) == 0xe0)
     557       15508 :         len = 3;
     558          48 :     else if ((*s & 0xf8) == 0xf0)
     559          48 :         len = 4;
     560             : #ifdef NOT_USED
     561             :     else if ((*s & 0xfc) == 0xf8)
     562             :         len = 5;
     563             :     else if ((*s & 0xfe) == 0xfc)
     564             :         len = 6;
     565             : #endif
     566             :     else
     567           0 :         len = 1;
     568   138442888 :     return len;
     569             : }
     570             : 
     571             : /*
     572             :  * This is an implementation of wcwidth() and wcswidth() as defined in
     573             :  * "The Single UNIX Specification, Version 2, The Open Group, 1997"
     574             :  * <http://www.UNIX-systems.org/online.html>
     575             :  *
     576             :  * Markus Kuhn -- 2001-09-08 -- public domain
     577             :  *
     578             :  * customised for PostgreSQL
     579             :  *
     580             :  * original available at : http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
     581             :  */
     582             : 
     583             : struct mbinterval
     584             : {
     585             :     unsigned short first;
     586             :     unsigned short last;
     587             : };
     588             : 
     589             : /* auxiliary function for binary search in interval table */
     590             : static int
     591        4232 : mbbisearch(pg_wchar ucs, const struct mbinterval *table, int max)
     592             : {
     593        4232 :     int         min = 0;
     594             :     int         mid;
     595             : 
     596        4232 :     if (ucs < table[0].first || ucs > table[max].last)
     597        4232 :         return 0;
     598           0 :     while (max >= min)
     599             :     {
     600           0 :         mid = (min + max) / 2;
     601           0 :         if (ucs > table[mid].last)
     602           0 :             min = mid + 1;
     603           0 :         else if (ucs < table[mid].first)
     604           0 :             max = mid - 1;
     605             :         else
     606           0 :             return 1;
     607             :     }
     608             : 
     609           0 :     return 0;
     610             : }
     611             : 
     612             : 
     613             : /* The following functions define the column width of an ISO 10646
     614             :  * character as follows:
     615             :  *
     616             :  *    - The null character (U+0000) has a column width of 0.
     617             :  *
     618             :  *    - Other C0/C1 control characters and DEL will lead to a return
     619             :  *      value of -1.
     620             :  *
     621             :  *    - Non-spacing and enclosing combining characters (general
     622             :  *      category code Mn or Me in the Unicode database) have a
     623             :  *      column width of 0.
     624             :  *
     625             :  *    - Other format characters (general category code Cf in the Unicode
     626             :  *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
     627             :  *
     628             :  *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
     629             :  *      have a column width of 0.
     630             :  *
     631             :  *    - Spacing characters in the East Asian Wide (W) or East Asian
     632             :  *      FullWidth (F) category as defined in Unicode Technical
     633             :  *      Report #11 have a column width of 2.
     634             :  *
     635             :  *    - All remaining characters (including all printable
     636             :  *      ISO 8859-1 and WGL4 characters, Unicode control characters,
     637             :  *      etc.) have a column width of 1.
     638             :  *
     639             :  * This implementation assumes that wchar_t characters are encoded
     640             :  * in ISO 10646.
     641             :  */
     642             : 
     643             : static int
     644        4356 : ucs_wcwidth(pg_wchar ucs)
     645             : {
     646             :     /* sorted list of non-overlapping intervals of non-spacing characters */
     647             :     static const struct mbinterval combining[] = {
     648             :         {0x0300, 0x034E}, {0x0360, 0x0362}, {0x0483, 0x0486},
     649             :         {0x0488, 0x0489}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
     650             :         {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
     651             :         {0x05C4, 0x05C4}, {0x064B, 0x0655}, {0x0670, 0x0670},
     652             :         {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
     653             :         {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
     654             :         {0x07A6, 0x07B0}, {0x0901, 0x0902}, {0x093C, 0x093C},
     655             :         {0x0941, 0x0948}, {0x094D, 0x094D}, {0x0951, 0x0954},
     656             :         {0x0962, 0x0963}, {0x0981, 0x0981}, {0x09BC, 0x09BC},
     657             :         {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, {0x09E2, 0x09E3},
     658             :         {0x0A02, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42},
     659             :         {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A70, 0x0A71},
     660             :         {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5},
     661             :         {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, {0x0B01, 0x0B01},
     662             :         {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43},
     663             :         {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B82, 0x0B82},
     664             :         {0x0BC0, 0x0BC0}, {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40},
     665             :         {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
     666             :         {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
     667             :         {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA},
     668             :         {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31},
     669             :         {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1},
     670             :         {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, {0x0EC8, 0x0ECD},
     671             :         {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
     672             :         {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, {0x0F80, 0x0F84},
     673             :         {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, {0x0F99, 0x0FBC},
     674             :         {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, {0x1032, 0x1032},
     675             :         {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059},
     676             :         {0x1160, 0x11FF}, {0x17B7, 0x17BD}, {0x17C6, 0x17C6},
     677             :         {0x17C9, 0x17D3}, {0x180B, 0x180E}, {0x18A9, 0x18A9},
     678             :         {0x200B, 0x200F}, {0x202A, 0x202E}, {0x206A, 0x206F},
     679             :         {0x20D0, 0x20E3}, {0x302A, 0x302F}, {0x3099, 0x309A},
     680             :         {0xFB1E, 0xFB1E}, {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF},
     681             :         {0xFFF9, 0xFFFB}
     682             :     };
     683             : 
     684             :     /* test for 8-bit control characters */
     685        4356 :     if (ucs == 0)
     686           0 :         return 0;
     687             : 
     688        4356 :     if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0) || ucs > 0x0010ffff)
     689         124 :         return -1;
     690             : 
     691             :     /* binary search in table of non-spacing characters */
     692        4232 :     if (mbbisearch(ucs, combining,
     693             :                    sizeof(combining) / sizeof(struct mbinterval) - 1))
     694           0 :         return 0;
     695             : 
     696             :     /*
     697             :      * if we arrive here, ucs is not a combining or C0/C1 control character
     698             :      */
     699             : 
     700        4232 :     return 1 +
     701        4232 :         (ucs >= 0x1100 &&
     702           0 :          (ucs <= 0x115f ||       /* Hangul Jamo init. consonants */
     703           0 :           (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
     704           0 :            ucs != 0x303f) ||    /* CJK ... Yi */
     705           0 :           (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
     706           0 :           (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility
     707             :                                                  * Ideographs */
     708           0 :           (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
     709           0 :           (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
     710           0 :           (ucs >= 0xffe0 && ucs <= 0xffe6) ||
     711           0 :           (ucs >= 0x20000 && ucs <= 0x2ffff)));
     712             : }
     713             : 
     714             : /*
     715             :  * Convert a UTF-8 character to a Unicode code point.
     716             :  * This is a one-character version of pg_utf2wchar_with_len.
     717             :  *
     718             :  * No error checks here, c must point to a long-enough string.
     719             :  */
     720             : pg_wchar
     721        4374 : utf8_to_unicode(const unsigned char *c)
     722             : {
     723        4374 :     if ((*c & 0x80) == 0)
     724        4370 :         return (pg_wchar) c[0];
     725           4 :     else if ((*c & 0xe0) == 0xc0)
     726           8 :         return (pg_wchar) (((c[0] & 0x1f) << 6) |
     727           4 :                            (c[1] & 0x3f));
     728           0 :     else if ((*c & 0xf0) == 0xe0)
     729           0 :         return (pg_wchar) (((c[0] & 0x0f) << 12) |
     730           0 :                            ((c[1] & 0x3f) << 6) |
     731           0 :                            (c[2] & 0x3f));
     732           0 :     else if ((*c & 0xf8) == 0xf0)
     733           0 :         return (pg_wchar) (((c[0] & 0x07) << 18) |
     734           0 :                            ((c[1] & 0x3f) << 12) |
     735           0 :                            ((c[2] & 0x3f) << 6) |
     736           0 :                            (c[3] & 0x3f));
     737             :     else
     738             :         /* that is an invalid code on purpose */
     739           0 :         return 0xffffffff;
     740             : }
     741             : 
     742             : static int
     743        4356 : pg_utf_dsplen(const unsigned char *s)
     744             : {
     745        4356 :     return ucs_wcwidth(utf8_to_unicode(s));
     746             : }
     747             : 
     748             : /*
     749             :  * convert mule internal code to pg_wchar
     750             :  * caller should allocate enough space for "to"
     751             :  * len: length of from.
     752             :  * "from" not necessarily null terminated.
     753             :  */
     754             : static int
     755           0 : pg_mule2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     756             : {
     757           0 :     int         cnt = 0;
     758             : 
     759           0 :     while (len > 0 && *from)
     760             :     {
     761           0 :         if (IS_LC1(*from) && len >= 2)
     762             :         {
     763           0 :             *to = *from++ << 16;
     764           0 :             *to |= *from++;
     765           0 :             len -= 2;
     766             :         }
     767           0 :         else if (IS_LCPRV1(*from) && len >= 3)
     768             :         {
     769           0 :             from++;
     770           0 :             *to = *from++ << 16;
     771           0 :             *to |= *from++;
     772           0 :             len -= 3;
     773             :         }
     774           0 :         else if (IS_LC2(*from) && len >= 3)
     775             :         {
     776           0 :             *to = *from++ << 16;
     777           0 :             *to |= *from++ << 8;
     778           0 :             *to |= *from++;
     779           0 :             len -= 3;
     780             :         }
     781           0 :         else if (IS_LCPRV2(*from) && len >= 4)
     782             :         {
     783           0 :             from++;
     784           0 :             *to = *from++ << 16;
     785           0 :             *to |= *from++ << 8;
     786           0 :             *to |= *from++;
     787           0 :             len -= 4;
     788             :         }
     789             :         else
     790             :         {                       /* assume ASCII */
     791           0 :             *to = (unsigned char) *from++;
     792           0 :             len--;
     793             :         }
     794           0 :         to++;
     795           0 :         cnt++;
     796             :     }
     797           0 :     *to = 0;
     798           0 :     return cnt;
     799             : }
     800             : 
     801             : /*
     802             :  * convert pg_wchar to mule internal code
     803             :  * caller should allocate enough space for "to"
     804             :  * len: length of from.
     805             :  * "from" not necessarily null terminated.
     806             :  */
     807             : static int
     808           0 : pg_wchar2mule_with_len(const pg_wchar *from, unsigned char *to, int len)
     809             : {
     810           0 :     int         cnt = 0;
     811             : 
     812           0 :     while (len > 0 && *from)
     813             :     {
     814             :         unsigned char lb;
     815             : 
     816           0 :         lb = (*from >> 16) & 0xff;
     817           0 :         if (IS_LC1(lb))
     818             :         {
     819           0 :             *to++ = lb;
     820           0 :             *to++ = *from & 0xff;
     821           0 :             cnt += 2;
     822             :         }
     823           0 :         else if (IS_LC2(lb))
     824             :         {
     825           0 :             *to++ = lb;
     826           0 :             *to++ = (*from >> 8) & 0xff;
     827           0 :             *to++ = *from & 0xff;
     828           0 :             cnt += 3;
     829             :         }
     830           0 :         else if (IS_LCPRV1_A_RANGE(lb))
     831             :         {
     832           0 :             *to++ = LCPRV1_A;
     833           0 :             *to++ = lb;
     834           0 :             *to++ = *from & 0xff;
     835           0 :             cnt += 3;
     836             :         }
     837           0 :         else if (IS_LCPRV1_B_RANGE(lb))
     838             :         {
     839           0 :             *to++ = LCPRV1_B;
     840           0 :             *to++ = lb;
     841           0 :             *to++ = *from & 0xff;
     842           0 :             cnt += 3;
     843             :         }
     844           0 :         else if (IS_LCPRV2_A_RANGE(lb))
     845             :         {
     846           0 :             *to++ = LCPRV2_A;
     847           0 :             *to++ = lb;
     848           0 :             *to++ = (*from >> 8) & 0xff;
     849           0 :             *to++ = *from & 0xff;
     850           0 :             cnt += 4;
     851             :         }
     852           0 :         else if (IS_LCPRV2_B_RANGE(lb))
     853             :         {
     854           0 :             *to++ = LCPRV2_B;
     855           0 :             *to++ = lb;
     856           0 :             *to++ = (*from >> 8) & 0xff;
     857           0 :             *to++ = *from & 0xff;
     858           0 :             cnt += 4;
     859             :         }
     860             :         else
     861             :         {
     862           0 :             *to++ = *from & 0xff;
     863           0 :             cnt += 1;
     864             :         }
     865           0 :         from++;
     866           0 :         len--;
     867             :     }
     868           0 :     *to = 0;
     869           0 :     return cnt;
     870             : }
     871             : 
     872             : int
     873           0 : pg_mule_mblen(const unsigned char *s)
     874             : {
     875             :     int         len;
     876             : 
     877           0 :     if (IS_LC1(*s))
     878           0 :         len = 2;
     879           0 :     else if (IS_LCPRV1(*s))
     880           0 :         len = 3;
     881           0 :     else if (IS_LC2(*s))
     882           0 :         len = 3;
     883           0 :     else if (IS_LCPRV2(*s))
     884           0 :         len = 4;
     885             :     else
     886           0 :         len = 1;                /* assume ASCII */
     887           0 :     return len;
     888             : }
     889             : 
     890             : static int
     891           0 : pg_mule_dsplen(const unsigned char *s)
     892             : {
     893             :     int         len;
     894             : 
     895             :     /*
     896             :      * Note: it's not really appropriate to assume that all multibyte charsets
     897             :      * are double-wide on screen.  But this seems an okay approximation for
     898             :      * the MULE charsets we currently support.
     899             :      */
     900             : 
     901           0 :     if (IS_LC1(*s))
     902           0 :         len = 1;
     903           0 :     else if (IS_LCPRV1(*s))
     904           0 :         len = 1;
     905           0 :     else if (IS_LC2(*s))
     906           0 :         len = 2;
     907           0 :     else if (IS_LCPRV2(*s))
     908           0 :         len = 2;
     909             :     else
     910           0 :         len = 1;                /* assume ASCII */
     911             : 
     912           0 :     return len;
     913             : }
     914             : 
     915             : /*
     916             :  * ISO8859-1
     917             :  */
     918             : static int
     919         342 : pg_latin12wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
     920             : {
     921         342 :     int         cnt = 0;
     922             : 
     923       12198 :     while (len > 0 && *from)
     924             :     {
     925       11514 :         *to++ = *from++;
     926       11514 :         len--;
     927       11514 :         cnt++;
     928             :     }
     929         342 :     *to = 0;
     930         342 :     return cnt;
     931             : }
     932             : 
     933             : /*
     934             :  * Trivial conversion from pg_wchar to single byte encoding. Just ignores
     935             :  * high bits.
     936             :  * caller should allocate enough space for "to"
     937             :  * len: length of from.
     938             :  * "from" not necessarily null terminated.
     939             :  */
     940             : static int
     941          46 : pg_wchar2single_with_len(const pg_wchar *from, unsigned char *to, int len)
     942             : {
     943          46 :     int         cnt = 0;
     944             : 
     945         230 :     while (len > 0 && *from)
     946             :     {
     947         138 :         *to++ = *from++;
     948         138 :         len--;
     949         138 :         cnt++;
     950             :     }
     951          46 :     *to = 0;
     952          46 :     return cnt;
     953             : }
     954             : 
     955             : static int
     956           0 : pg_latin1_mblen(const unsigned char *s)
     957             : {
     958           0 :     return 1;
     959             : }
     960             : 
     961             : static int
     962           0 : pg_latin1_dsplen(const unsigned char *s)
     963             : {
     964           0 :     return pg_ascii_dsplen(s);
     965             : }
     966             : 
     967             : /*
     968             :  * SJIS
     969             :  */
     970             : static int
     971           0 : pg_sjis_mblen(const unsigned char *s)
     972             : {
     973             :     int         len;
     974             : 
     975           0 :     if (*s >= 0xa1 && *s <= 0xdf)
     976           0 :         len = 1;                /* 1 byte kana? */
     977           0 :     else if (IS_HIGHBIT_SET(*s))
     978           0 :         len = 2;                /* kanji? */
     979             :     else
     980           0 :         len = 1;                /* should be ASCII */
     981           0 :     return len;
     982             : }
     983             : 
     984             : static int
     985           0 : pg_sjis_dsplen(const unsigned char *s)
     986             : {
     987             :     int         len;
     988             : 
     989           0 :     if (*s >= 0xa1 && *s <= 0xdf)
     990           0 :         len = 1;                /* 1 byte kana? */
     991           0 :     else if (IS_HIGHBIT_SET(*s))
     992           0 :         len = 2;                /* kanji? */
     993             :     else
     994           0 :         len = pg_ascii_dsplen(s);   /* should be ASCII */
     995           0 :     return len;
     996             : }
     997             : 
     998             : /*
     999             :  * Big5
    1000             :  */
    1001             : static int
    1002           0 : pg_big5_mblen(const unsigned char *s)
    1003             : {
    1004             :     int         len;
    1005             : 
    1006           0 :     if (IS_HIGHBIT_SET(*s))
    1007           0 :         len = 2;                /* kanji? */
    1008             :     else
    1009           0 :         len = 1;                /* should be ASCII */
    1010           0 :     return len;
    1011             : }
    1012             : 
    1013             : static int
    1014           0 : pg_big5_dsplen(const unsigned char *s)
    1015             : {
    1016             :     int         len;
    1017             : 
    1018           0 :     if (IS_HIGHBIT_SET(*s))
    1019           0 :         len = 2;                /* kanji? */
    1020             :     else
    1021           0 :         len = pg_ascii_dsplen(s);   /* should be ASCII */
    1022           0 :     return len;
    1023             : }
    1024             : 
    1025             : /*
    1026             :  * GBK
    1027             :  */
    1028             : static int
    1029           0 : pg_gbk_mblen(const unsigned char *s)
    1030             : {
    1031             :     int         len;
    1032             : 
    1033           0 :     if (IS_HIGHBIT_SET(*s))
    1034           0 :         len = 2;                /* kanji? */
    1035             :     else
    1036           0 :         len = 1;                /* should be ASCII */
    1037           0 :     return len;
    1038             : }
    1039             : 
    1040             : static int
    1041           0 : pg_gbk_dsplen(const unsigned char *s)
    1042             : {
    1043             :     int         len;
    1044             : 
    1045           0 :     if (IS_HIGHBIT_SET(*s))
    1046           0 :         len = 2;                /* kanji? */
    1047             :     else
    1048           0 :         len = pg_ascii_dsplen(s);   /* should be ASCII */
    1049           0 :     return len;
    1050             : }
    1051             : 
    1052             : /*
    1053             :  * UHC
    1054             :  */
    1055             : static int
    1056           0 : pg_uhc_mblen(const unsigned char *s)
    1057             : {
    1058             :     int         len;
    1059             : 
    1060           0 :     if (IS_HIGHBIT_SET(*s))
    1061           0 :         len = 2;                /* 2byte? */
    1062             :     else
    1063           0 :         len = 1;                /* should be ASCII */
    1064           0 :     return len;
    1065             : }
    1066             : 
    1067             : static int
    1068           0 : pg_uhc_dsplen(const unsigned char *s)
    1069             : {
    1070             :     int         len;
    1071             : 
    1072           0 :     if (IS_HIGHBIT_SET(*s))
    1073           0 :         len = 2;                /* 2byte? */
    1074             :     else
    1075           0 :         len = pg_ascii_dsplen(s);   /* should be ASCII */
    1076           0 :     return len;
    1077             : }
    1078             : 
    1079             : /*
    1080             :  * GB18030
    1081             :  *  Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp>
    1082             :  */
    1083             : 
    1084             : /*
    1085             :  * Unlike all other mblen() functions, this also looks at the second byte of
    1086             :  * the input.  However, if you only pass the first byte of a multi-byte
    1087             :  * string, and \0 as the second byte, this still works in a predictable way:
    1088             :  * a 4-byte character will be reported as two 2-byte characters.  That's
    1089             :  * enough for all current uses, as a client-only encoding.  It works that
    1090             :  * way, because in any valid 4-byte GB18030-encoded character, the third and
    1091             :  * fourth byte look like a 2-byte encoded character, when looked at
    1092             :  * separately.
    1093             :  */
    1094             : static int
    1095           0 : pg_gb18030_mblen(const unsigned char *s)
    1096             : {
    1097             :     int         len;
    1098             : 
    1099           0 :     if (!IS_HIGHBIT_SET(*s))
    1100           0 :         len = 1;                /* ASCII */
    1101           0 :     else if (*(s + 1) >= 0x30 && *(s + 1) <= 0x39)
    1102           0 :         len = 4;
    1103             :     else
    1104           0 :         len = 2;
    1105           0 :     return len;
    1106             : }
    1107             : 
    1108             : static int
    1109           0 : pg_gb18030_dsplen(const unsigned char *s)
    1110             : {
    1111             :     int         len;
    1112             : 
    1113           0 :     if (IS_HIGHBIT_SET(*s))
    1114           0 :         len = 2;
    1115             :     else
    1116           0 :         len = pg_ascii_dsplen(s);   /* ASCII */
    1117           0 :     return len;
    1118             : }
    1119             : 
    1120             : /*
    1121             :  *-------------------------------------------------------------------
    1122             :  * multibyte sequence validators
    1123             :  *
    1124             :  * These functions accept "s", a pointer to the first byte of a string,
    1125             :  * and "len", the remaining length of the string.  If there is a validly
    1126             :  * encoded character beginning at *s, return its length in bytes; else
    1127             :  * return -1.
    1128             :  *
    1129             :  * The functions can assume that len > 0 and that *s != '\0', but they must
    1130             :  * test for and reject zeroes in any additional bytes of a multibyte character.
    1131             :  *
    1132             :  * Note that this definition allows the function for a single-byte
    1133             :  * encoding to be just "return 1".
    1134             :  *-------------------------------------------------------------------
    1135             :  */
    1136             : 
    1137             : static int
    1138           2 : pg_ascii_verifier(const unsigned char *s, int len)
    1139             : {
    1140           2 :     return 1;
    1141             : }
    1142             : 
    1143             : #define IS_EUC_RANGE_VALID(c)   ((c) >= 0xa1 && (c) <= 0xfe)
    1144             : 
    1145             : static int
    1146           0 : pg_eucjp_verifier(const unsigned char *s, int len)
    1147             : {
    1148             :     int         l;
    1149             :     unsigned char c1,
    1150             :                 c2;
    1151             : 
    1152           0 :     c1 = *s++;
    1153             : 
    1154           0 :     switch (c1)
    1155             :     {
    1156             :         case SS2:               /* JIS X 0201 */
    1157           0 :             l = 2;
    1158           0 :             if (l > len)
    1159           0 :                 return -1;
    1160           0 :             c2 = *s++;
    1161           0 :             if (c2 < 0xa1 || c2 > 0xdf)
    1162           0 :                 return -1;
    1163           0 :             break;
    1164             : 
    1165             :         case SS3:               /* JIS X 0212 */
    1166           0 :             l = 3;
    1167           0 :             if (l > len)
    1168           0 :                 return -1;
    1169           0 :             c2 = *s++;
    1170           0 :             if (!IS_EUC_RANGE_VALID(c2))
    1171           0 :                 return -1;
    1172           0 :             c2 = *s++;
    1173           0 :             if (!IS_EUC_RANGE_VALID(c2))
    1174           0 :                 return -1;
    1175           0 :             break;
    1176             : 
    1177             :         default:
    1178           0 :             if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
    1179             :             {
    1180           0 :                 l = 2;
    1181           0 :                 if (l > len)
    1182           0 :                     return -1;
    1183           0 :                 if (!IS_EUC_RANGE_VALID(c1))
    1184           0 :                     return -1;
    1185           0 :                 c2 = *s++;
    1186           0 :                 if (!IS_EUC_RANGE_VALID(c2))
    1187           0 :                     return -1;
    1188             :             }
    1189             :             else
    1190             :                 /* must be ASCII */
    1191             :             {
    1192           0 :                 l = 1;
    1193             :             }
    1194           0 :             break;
    1195             :     }
    1196             : 
    1197           0 :     return l;
    1198             : }
    1199             : 
    1200             : static int
    1201           0 : pg_euckr_verifier(const unsigned char *s, int len)
    1202             : {
    1203             :     int         l;
    1204             :     unsigned char c1,
    1205             :                 c2;
    1206             : 
    1207           0 :     c1 = *s++;
    1208             : 
    1209           0 :     if (IS_HIGHBIT_SET(c1))
    1210             :     {
    1211           0 :         l = 2;
    1212           0 :         if (l > len)
    1213           0 :             return -1;
    1214           0 :         if (!IS_EUC_RANGE_VALID(c1))
    1215           0 :             return -1;
    1216           0 :         c2 = *s++;
    1217           0 :         if (!IS_EUC_RANGE_VALID(c2))
    1218           0 :             return -1;
    1219             :     }
    1220             :     else
    1221             :         /* must be ASCII */
    1222             :     {
    1223           0 :         l = 1;
    1224             :     }
    1225             : 
    1226           0 :     return l;
    1227             : }
    1228             : 
    1229             : /* EUC-CN byte sequences are exactly same as EUC-KR */
    1230             : #define pg_euccn_verifier   pg_euckr_verifier
    1231             : 
    1232             : static int
    1233           0 : pg_euctw_verifier(const unsigned char *s, int len)
    1234             : {
    1235             :     int         l;
    1236             :     unsigned char c1,
    1237             :                 c2;
    1238             : 
    1239           0 :     c1 = *s++;
    1240             : 
    1241           0 :     switch (c1)
    1242             :     {
    1243             :         case SS2:               /* CNS 11643 Plane 1-7 */
    1244           0 :             l = 4;
    1245           0 :             if (l > len)
    1246           0 :                 return -1;
    1247           0 :             c2 = *s++;
    1248           0 :             if (c2 < 0xa1 || c2 > 0xa7)
    1249           0 :                 return -1;
    1250           0 :             c2 = *s++;
    1251           0 :             if (!IS_EUC_RANGE_VALID(c2))
    1252           0 :                 return -1;
    1253           0 :             c2 = *s++;
    1254           0 :             if (!IS_EUC_RANGE_VALID(c2))
    1255           0 :                 return -1;
    1256           0 :             break;
    1257             : 
    1258             :         case SS3:               /* unused */
    1259           0 :             return -1;
    1260             : 
    1261             :         default:
    1262           0 :             if (IS_HIGHBIT_SET(c1)) /* CNS 11643 Plane 1 */
    1263             :             {
    1264           0 :                 l = 2;
    1265           0 :                 if (l > len)
    1266           0 :                     return -1;
    1267             :                 /* no further range check on c1? */
    1268           0 :                 c2 = *s++;
    1269           0 :                 if (!IS_EUC_RANGE_VALID(c2))
    1270           0 :                     return -1;
    1271             :             }
    1272             :             else
    1273             :                 /* must be ASCII */
    1274             :             {
    1275           0 :                 l = 1;
    1276             :             }
    1277           0 :             break;
    1278             :     }
    1279           0 :     return l;
    1280             : }
    1281             : 
    1282             : static int
    1283           0 : pg_johab_verifier(const unsigned char *s, int len)
    1284             : {
    1285             :     int         l,
    1286             :                 mbl;
    1287             :     unsigned char c;
    1288             : 
    1289           0 :     l = mbl = pg_johab_mblen(s);
    1290             : 
    1291           0 :     if (len < l)
    1292           0 :         return -1;
    1293             : 
    1294           0 :     if (!IS_HIGHBIT_SET(*s))
    1295           0 :         return mbl;
    1296             : 
    1297           0 :     while (--l > 0)
    1298             :     {
    1299           0 :         c = *++s;
    1300           0 :         if (!IS_EUC_RANGE_VALID(c))
    1301           0 :             return -1;
    1302             :     }
    1303           0 :     return mbl;
    1304             : }
    1305             : 
    1306             : static int
    1307           0 : pg_mule_verifier(const unsigned char *s, int len)
    1308             : {
    1309             :     int         l,
    1310             :                 mbl;
    1311             :     unsigned char c;
    1312             : 
    1313           0 :     l = mbl = pg_mule_mblen(s);
    1314             : 
    1315           0 :     if (len < l)
    1316           0 :         return -1;
    1317             : 
    1318           0 :     while (--l > 0)
    1319             :     {
    1320           0 :         c = *++s;
    1321           0 :         if (!IS_HIGHBIT_SET(c))
    1322           0 :             return -1;
    1323             :     }
    1324           0 :     return mbl;
    1325             : }
    1326             : 
    1327             : static int
    1328          56 : pg_latin1_verifier(const unsigned char *s, int len)
    1329             : {
    1330          56 :     return 1;
    1331             : }
    1332             : 
    1333             : static int
    1334           0 : pg_sjis_verifier(const unsigned char *s, int len)
    1335             : {
    1336             :     int         l,
    1337             :                 mbl;
    1338             :     unsigned char c1,
    1339             :                 c2;
    1340             : 
    1341           0 :     l = mbl = pg_sjis_mblen(s);
    1342             : 
    1343           0 :     if (len < l)
    1344           0 :         return -1;
    1345             : 
    1346           0 :     if (l == 1)                 /* pg_sjis_mblen already verified it */
    1347           0 :         return mbl;
    1348             : 
    1349           0 :     c1 = *s++;
    1350           0 :     c2 = *s;
    1351           0 :     if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
    1352           0 :         return -1;
    1353           0 :     return mbl;
    1354             : }
    1355             : 
    1356             : static int
    1357           0 : pg_big5_verifier(const unsigned char *s, int len)
    1358             : {
    1359             :     int         l,
    1360             :                 mbl;
    1361             : 
    1362           0 :     l = mbl = pg_big5_mblen(s);
    1363             : 
    1364           0 :     if (len < l)
    1365           0 :         return -1;
    1366             : 
    1367           0 :     while (--l > 0)
    1368             :     {
    1369           0 :         if (*++s == '\0')
    1370           0 :             return -1;
    1371             :     }
    1372             : 
    1373           0 :     return mbl;
    1374             : }
    1375             : 
    1376             : static int
    1377           0 : pg_gbk_verifier(const unsigned char *s, int len)
    1378             : {
    1379             :     int         l,
    1380             :                 mbl;
    1381             : 
    1382           0 :     l = mbl = pg_gbk_mblen(s);
    1383             : 
    1384           0 :     if (len < l)
    1385           0 :         return -1;
    1386             : 
    1387           0 :     while (--l > 0)
    1388             :     {
    1389           0 :         if (*++s == '\0')
    1390           0 :             return -1;
    1391             :     }
    1392             : 
    1393           0 :     return mbl;
    1394             : }
    1395             : 
    1396             : static int
    1397           0 : pg_uhc_verifier(const unsigned char *s, int len)
    1398             : {
    1399             :     int         l,
    1400             :                 mbl;
    1401             : 
    1402           0 :     l = mbl = pg_uhc_mblen(s);
    1403             : 
    1404           0 :     if (len < l)
    1405           0 :         return -1;
    1406             : 
    1407           0 :     while (--l > 0)
    1408             :     {
    1409           0 :         if (*++s == '\0')
    1410           0 :             return -1;
    1411             :     }
    1412             : 
    1413           0 :     return mbl;
    1414             : }
    1415             : 
    1416             : static int
    1417           0 : pg_gb18030_verifier(const unsigned char *s, int len)
    1418             : {
    1419             :     int         l;
    1420             : 
    1421           0 :     if (!IS_HIGHBIT_SET(*s))
    1422           0 :         l = 1;                  /* ASCII */
    1423           0 :     else if (len >= 4 && *(s + 1) >= 0x30 && *(s + 1) <= 0x39)
    1424             :     {
    1425             :         /* Should be 4-byte, validate remaining bytes */
    1426           0 :         if (*s >= 0x81 && *s <= 0xfe &&
    1427           0 :             *(s + 2) >= 0x81 && *(s + 2) <= 0xfe &&
    1428           0 :             *(s + 3) >= 0x30 && *(s + 3) <= 0x39)
    1429           0 :             l = 4;
    1430             :         else
    1431           0 :             l = -1;
    1432             :     }
    1433           0 :     else if (len >= 2 && *s >= 0x81 && *s <= 0xfe)
    1434             :     {
    1435             :         /* Should be 2-byte, validate */
    1436           0 :         if ((*(s + 1) >= 0x40 && *(s + 1) <= 0x7e) ||
    1437           0 :             (*(s + 1) >= 0x80 && *(s + 1) <= 0xfe))
    1438           0 :             l = 2;
    1439             :         else
    1440           0 :             l = -1;
    1441             :     }
    1442             :     else
    1443           0 :         l = -1;
    1444           0 :     return l;
    1445             : }
    1446             : 
    1447             : static int
    1448       13972 : pg_utf8_verifier(const unsigned char *s, int len)
    1449             : {
    1450       13972 :     int         l = pg_utf_mblen(s);
    1451             : 
    1452       13972 :     if (len < l)
    1453           0 :         return -1;
    1454             : 
    1455       13972 :     if (!pg_utf8_islegal(s, l))
    1456           0 :         return -1;
    1457             : 
    1458       13972 :     return l;
    1459             : }
    1460             : 
    1461             : /*
    1462             :  * Check for validity of a single UTF-8 encoded character
    1463             :  *
    1464             :  * This directly implements the rules in RFC3629.  The bizarre-looking
    1465             :  * restrictions on the second byte are meant to ensure that there isn't
    1466             :  * more than one encoding of a given Unicode character point; that is,
    1467             :  * you may not use a longer-than-necessary byte sequence with high order
    1468             :  * zero bits to represent a character that would fit in fewer bytes.
    1469             :  * To do otherwise is to create security hazards (eg, create an apparent
    1470             :  * non-ASCII character that decodes to plain ASCII).
    1471             :  *
    1472             :  * length is assumed to have been obtained by pg_utf_mblen(), and the
    1473             :  * caller must have checked that that many bytes are present in the buffer.
    1474             :  */
    1475             : bool
    1476       14448 : pg_utf8_islegal(const unsigned char *source, int length)
    1477             : {
    1478             :     unsigned char a;
    1479             : 
    1480       14448 :     switch (length)
    1481             :     {
    1482             :         default:
    1483             :             /* reject lengths 5 and 6 for now */
    1484           0 :             return false;
    1485             :         case 4:
    1486           8 :             a = source[3];
    1487           8 :             if (a < 0x80 || a > 0xBF)
    1488           0 :                 return false;
    1489             :             /* FALL THRU */
    1490             :         case 3:
    1491        7756 :             a = source[2];
    1492        7756 :             if (a < 0x80 || a > 0xBF)
    1493           0 :                 return false;
    1494             :             /* FALL THRU */
    1495             :         case 2:
    1496       13978 :             a = source[1];
    1497       13978 :             switch (*source)
    1498             :             {
    1499             :                 case 0xE0:
    1500           0 :                     if (a < 0xA0 || a > 0xBF)
    1501           0 :                         return false;
    1502           0 :                     break;
    1503             :                 case 0xED:
    1504           0 :                     if (a < 0x80 || a > 0x9F)
    1505           0 :                         return false;
    1506           0 :                     break;
    1507             :                 case 0xF0:
    1508           8 :                     if (a < 0x90 || a > 0xBF)
    1509           0 :                         return false;
    1510           8 :                     break;
    1511             :                 case 0xF4:
    1512           0 :                     if (a < 0x80 || a > 0x8F)
    1513           0 :                         return false;
    1514           0 :                     break;
    1515             :                 default:
    1516       13970 :                     if (a < 0x80 || a > 0xBF)
    1517           0 :                         return false;
    1518       13970 :                     break;
    1519             :             }
    1520             :             /* FALL THRU */
    1521             :         case 1:
    1522       14448 :             a = *source;
    1523       14448 :             if (a >= 0x80 && a < 0xC2)
    1524           0 :                 return false;
    1525       14448 :             if (a > 0xF4)
    1526           0 :                 return false;
    1527       14448 :             break;
    1528             :     }
    1529       14448 :     return true;
    1530             : }
    1531             : 
    1532             : #ifndef FRONTEND
    1533             : 
    1534             : /*
    1535             :  * Generic character incrementer function.
    1536             :  *
    1537             :  * Not knowing anything about the properties of the encoding in use, we just
    1538             :  * keep incrementing the last byte until we get a validly-encoded result,
    1539             :  * or we run out of values to try.  We don't bother to try incrementing
    1540             :  * higher-order bytes, so there's no growth in runtime for wider characters.
    1541             :  * (If we did try to do that, we'd need to consider the likelihood that 255
    1542             :  * is not a valid final byte in the encoding.)
    1543             :  */
    1544             : static bool
    1545          58 : pg_generic_charinc(unsigned char *charptr, int len)
    1546             : {
    1547          58 :     unsigned char *lastbyte = charptr + len - 1;
    1548             :     mbverifier  mbverify;
    1549             : 
    1550             :     /* We can just invoke the character verifier directly. */
    1551          58 :     mbverify = pg_wchar_table[GetDatabaseEncoding()].mbverify;
    1552             : 
    1553         116 :     while (*lastbyte < (unsigned char) 255)
    1554             :     {
    1555          58 :         (*lastbyte)++;
    1556          58 :         if ((*mbverify) (charptr, len) == len)
    1557          58 :             return true;
    1558             :     }
    1559             : 
    1560           0 :     return false;
    1561             : }
    1562             : 
    1563             : /*
    1564             :  * UTF-8 character incrementer function.
    1565             :  *
    1566             :  * For a one-byte character less than 0x7F, we just increment the byte.
    1567             :  *
    1568             :  * For a multibyte character, every byte but the first must fall between 0x80
    1569             :  * and 0xBF; and the first byte must be between 0xC0 and 0xF4.  We increment
    1570             :  * the last byte that's not already at its maximum value.  If we can't find a
    1571             :  * byte that's less than the maximum allowable value, we simply fail.  We also
    1572             :  * need some special-case logic to skip regions used for surrogate pair
    1573             :  * handling, as those should not occur in valid UTF-8.
    1574             :  *
    1575             :  * Note that we don't reset lower-order bytes back to their minimums, since
    1576             :  * we can't afford to make an exhaustive search (see make_greater_string).
    1577             :  */
    1578             : static bool
    1579        1334 : pg_utf8_increment(unsigned char *charptr, int length)
    1580             : {
    1581             :     unsigned char a;
    1582             :     unsigned char limit;
    1583             : 
    1584        1334 :     switch (length)
    1585             :     {
    1586             :         default:
    1587             :             /* reject lengths 5 and 6 for now */
    1588           0 :             return false;
    1589             :         case 4:
    1590           0 :             a = charptr[3];
    1591           0 :             if (a < 0xBF)
    1592             :             {
    1593           0 :                 charptr[3]++;
    1594           0 :                 break;
    1595             :             }
    1596             :             /* FALL THRU */
    1597             :         case 3:
    1598           0 :             a = charptr[2];
    1599           0 :             if (a < 0xBF)
    1600             :             {
    1601           0 :                 charptr[2]++;
    1602           0 :                 break;
    1603             :             }
    1604             :             /* FALL THRU */
    1605             :         case 2:
    1606           0 :             a = charptr[1];
    1607           0 :             switch (*charptr)
    1608             :             {
    1609             :                 case 0xED:
    1610           0 :                     limit = 0x9F;
    1611           0 :                     break;
    1612             :                 case 0xF4:
    1613           0 :                     limit = 0x8F;
    1614           0 :                     break;
    1615             :                 default:
    1616           0 :                     limit = 0xBF;
    1617           0 :                     break;
    1618             :             }
    1619           0 :             if (a < limit)
    1620             :             {
    1621           0 :                 charptr[1]++;
    1622           0 :                 break;
    1623             :             }
    1624             :             /* FALL THRU */
    1625             :         case 1:
    1626        1334 :             a = *charptr;
    1627        1334 :             if (a == 0x7F || a == 0xDF || a == 0xEF || a == 0xF4)
    1628           0 :                 return false;
    1629        1334 :             charptr[0]++;
    1630        1334 :             break;
    1631             :     }
    1632             : 
    1633        1334 :     return true;
    1634             : }
    1635             : 
    1636             : /*
    1637             :  * EUC-JP character incrementer function.
    1638             :  *
    1639             :  * If the sequence starts with SS2 (0x8e), it must be a two-byte sequence
    1640             :  * representing JIS X 0201 characters with the second byte ranging between
    1641             :  * 0xa1 and 0xdf.  We just increment the last byte if it's less than 0xdf,
    1642             :  * and otherwise rewrite the whole sequence to 0xa1 0xa1.
    1643             :  *
    1644             :  * If the sequence starts with SS3 (0x8f), it must be a three-byte sequence
    1645             :  * in which the last two bytes range between 0xa1 and 0xfe.  The last byte
    1646             :  * is incremented if possible, otherwise the second-to-last byte.
    1647             :  *
    1648             :  * If the sequence starts with a value other than the above and its MSB
    1649             :  * is set, it must be a two-byte sequence representing JIS X 0208 characters
    1650             :  * with both bytes ranging between 0xa1 and 0xfe.  The last byte is
    1651             :  * incremented if possible, otherwise the second-to-last byte.
    1652             :  *
    1653             :  * Otherwise, the sequence is a single-byte ASCII character. It is
    1654             :  * incremented up to 0x7f.
    1655             :  */
    1656             : static bool
    1657           0 : pg_eucjp_increment(unsigned char *charptr, int length)
    1658             : {
    1659             :     unsigned char c1,
    1660             :                 c2;
    1661             :     int         i;
    1662             : 
    1663           0 :     c1 = *charptr;
    1664             : 
    1665           0 :     switch (c1)
    1666             :     {
    1667             :         case SS2:               /* JIS X 0201 */
    1668           0 :             if (length != 2)
    1669           0 :                 return false;
    1670             : 
    1671           0 :             c2 = charptr[1];
    1672             : 
    1673           0 :             if (c2 >= 0xdf)
    1674           0 :                 charptr[0] = charptr[1] = 0xa1;
    1675           0 :             else if (c2 < 0xa1)
    1676           0 :                 charptr[1] = 0xa1;
    1677             :             else
    1678           0 :                 charptr[1]++;
    1679           0 :             break;
    1680             : 
    1681             :         case SS3:               /* JIS X 0212 */
    1682           0 :             if (length != 3)
    1683           0 :                 return false;
    1684             : 
    1685           0 :             for (i = 2; i > 0; i--)
    1686             :             {
    1687           0 :                 c2 = charptr[i];
    1688           0 :                 if (c2 < 0xa1)
    1689             :                 {
    1690           0 :                     charptr[i] = 0xa1;
    1691           0 :                     return true;
    1692             :                 }
    1693           0 :                 else if (c2 < 0xfe)
    1694             :                 {
    1695           0 :                     charptr[i]++;
    1696           0 :                     return true;
    1697             :                 }
    1698             :             }
    1699             : 
    1700             :             /* Out of 3-byte code region */
    1701           0 :             return false;
    1702             : 
    1703             :         default:
    1704           0 :             if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
    1705             :             {
    1706           0 :                 if (length != 2)
    1707           0 :                     return false;
    1708             : 
    1709           0 :                 for (i = 1; i >= 0; i--)
    1710             :                 {
    1711           0 :                     c2 = charptr[i];
    1712           0 :                     if (c2 < 0xa1)
    1713             :                     {
    1714           0 :                         charptr[i] = 0xa1;
    1715           0 :                         return true;
    1716             :                     }
    1717           0 :                     else if (c2 < 0xfe)
    1718             :                     {
    1719           0 :                         charptr[i]++;
    1720           0 :                         return true;
    1721             :                     }
    1722             :                 }
    1723             : 
    1724             :                 /* Out of 2 byte code region */
    1725           0 :                 return false;
    1726             :             }
    1727             :             else
    1728             :             {                   /* ASCII, single byte */
    1729           0 :                 if (c1 > 0x7e)
    1730           0 :                     return false;
    1731           0 :                 (*charptr)++;
    1732             :             }
    1733           0 :             break;
    1734             :     }
    1735             : 
    1736           0 :     return true;
    1737             : }
    1738             : #endif                          /* !FRONTEND */
    1739             : 
    1740             : 
    1741             : /*
    1742             :  *-------------------------------------------------------------------
    1743             :  * encoding info table
    1744             :  * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
    1745             :  *-------------------------------------------------------------------
    1746             :  */
    1747             : const pg_wchar_tbl pg_wchar_table[] = {
    1748             :     {pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifier, 1}, /* PG_SQL_ASCII */
    1749             :     {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3},    /* PG_EUC_JP */
    1750             :     {pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifier, 2},    /* PG_EUC_CN */
    1751             :     {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifier, 3},    /* PG_EUC_KR */
    1752             :     {pg_euctw2wchar_with_len, pg_wchar2euc_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifier, 4},    /* PG_EUC_TW */
    1753             :     {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3},    /* PG_EUC_JIS_2004 */
    1754             :     {pg_utf2wchar_with_len, pg_wchar2utf_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifier, 4},   /* PG_UTF8 */
    1755             :     {pg_mule2wchar_with_len, pg_wchar2mule_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifier, 4},   /* PG_MULE_INTERNAL */
    1756             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN1 */
    1757             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN2 */
    1758             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN3 */
    1759             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN4 */
    1760             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN5 */
    1761             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN6 */
    1762             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN7 */
    1763             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN8 */
    1764             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN9 */
    1765             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN10 */
    1766             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1256 */
    1767             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1258 */
    1768             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN866 */
    1769             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN874 */
    1770             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8R */
    1771             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1251 */
    1772             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1252 */
    1773             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-5 */
    1774             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-6 */
    1775             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-7 */
    1776             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-8 */
    1777             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1250 */
    1778             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1253 */
    1779             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1254 */
    1780             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1255 */
    1781             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1257 */
    1782             :     {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8U */
    1783             :     {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}, /* PG_SJIS */
    1784             :     {0, 0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifier, 2}, /* PG_BIG5 */
    1785             :     {0, 0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifier, 2},    /* PG_GBK */
    1786             :     {0, 0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifier, 2},    /* PG_UHC */
    1787             :     {0, 0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifier, 4},    /* PG_GB18030 */
    1788             :     {0, 0, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifier, 3},  /* PG_JOHAB */
    1789             :     {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}  /* PG_SHIFT_JIS_2004 */
    1790             : };
    1791             : 
    1792             : /* returns the byte length of a word for mule internal code */
    1793             : int
    1794           0 : pg_mic_mblen(const unsigned char *mbstr)
    1795             : {
    1796           0 :     return pg_mule_mblen(mbstr);
    1797             : }
    1798             : 
    1799             : /*
    1800             :  * Returns the byte length of a multibyte character.
    1801             :  */
    1802             : int
    1803       12096 : pg_encoding_mblen(int encoding, const char *mbstr)
    1804             : {
    1805       12096 :     return (PG_VALID_ENCODING(encoding) ?
    1806       24192 :             pg_wchar_table[encoding].mblen((const unsigned char *) mbstr) :
    1807           0 :             pg_wchar_table[PG_SQL_ASCII].mblen((const unsigned char *) mbstr));
    1808             : }
    1809             : 
    1810             : /*
    1811             :  * Returns the display length of a multibyte character.
    1812             :  */
    1813             : int
    1814           0 : pg_encoding_dsplen(int encoding, const char *mbstr)
    1815             : {
    1816           0 :     return (PG_VALID_ENCODING(encoding) ?
    1817           0 :             pg_wchar_table[encoding].dsplen((const unsigned char *) mbstr) :
    1818           0 :             pg_wchar_table[PG_SQL_ASCII].dsplen((const unsigned char *) mbstr));
    1819             : }
    1820             : 
    1821             : /*
    1822             :  * Verify the first multibyte character of the given string.
    1823             :  * Return its byte length if good, -1 if bad.  (See comments above for
    1824             :  * full details of the mbverify API.)
    1825             :  */
    1826             : int
    1827           0 : pg_encoding_verifymb(int encoding, const char *mbstr, int len)
    1828             : {
    1829           0 :     return (PG_VALID_ENCODING(encoding) ?
    1830           0 :             pg_wchar_table[encoding].mbverify((const unsigned char *) mbstr, len) :
    1831           0 :             pg_wchar_table[PG_SQL_ASCII].mbverify((const unsigned char *) mbstr, len));
    1832             : }
    1833             : 
    1834             : /*
    1835             :  * fetch maximum length of a given encoding
    1836             :  */
    1837             : int
    1838     3410464 : pg_encoding_max_length(int encoding)
    1839             : {
    1840             :     Assert(PG_VALID_ENCODING(encoding));
    1841             : 
    1842     3410464 :     return pg_wchar_table[encoding].maxmblen;
    1843             : }
    1844             : 
    1845             : #ifndef FRONTEND
    1846             : 
    1847             : /*
    1848             :  * fetch maximum length of the encoding for the current database
    1849             :  */
    1850             : int
    1851     9720566 : pg_database_encoding_max_length(void)
    1852             : {
    1853     9720566 :     return pg_wchar_table[GetDatabaseEncoding()].maxmblen;
    1854             : }
    1855             : 
    1856             : /*
    1857             :  * get the character incrementer for the encoding for the current database
    1858             :  */
    1859             : mbcharacter_incrementer
    1860        1392 : pg_database_encoding_character_incrementer(void)
    1861             : {
    1862             :     /*
    1863             :      * Eventually it might be best to add a field to pg_wchar_table[], but for
    1864             :      * now we just use a switch.
    1865             :      */
    1866        1392 :     switch (GetDatabaseEncoding())
    1867             :     {
    1868             :         case PG_UTF8:
    1869        1334 :             return pg_utf8_increment;
    1870             : 
    1871             :         case PG_EUC_JP:
    1872           0 :             return pg_eucjp_increment;
    1873             : 
    1874             :         default:
    1875          58 :             return pg_generic_charinc;
    1876             :     }
    1877             : }
    1878             : 
    1879             : /*
    1880             :  * Verify mbstr to make sure that it is validly encoded in the current
    1881             :  * database encoding.  Otherwise same as pg_verify_mbstr().
    1882             :  */
    1883             : bool
    1884        4444 : pg_verifymbstr(const char *mbstr, int len, bool noError)
    1885             : {
    1886             :     return
    1887        4444 :         pg_verify_mbstr_len(GetDatabaseEncoding(), mbstr, len, noError) >= 0;
    1888             : }
    1889             : 
    1890             : /*
    1891             :  * Verify mbstr to make sure that it is validly encoded in the specified
    1892             :  * encoding.
    1893             :  */
    1894             : bool
    1895     2815002 : pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
    1896             : {
    1897     2815002 :     return pg_verify_mbstr_len(encoding, mbstr, len, noError) >= 0;
    1898             : }
    1899             : 
    1900             : /*
    1901             :  * Verify mbstr to make sure that it is validly encoded in the specified
    1902             :  * encoding.
    1903             :  *
    1904             :  * mbstr is not necessarily zero terminated; length of mbstr is
    1905             :  * specified by len.
    1906             :  *
    1907             :  * If OK, return length of string in the encoding.
    1908             :  * If a problem is found, return -1 when noError is
    1909             :  * true; when noError is false, ereport() a descriptive message.
    1910             :  */
    1911             : int
    1912     2820606 : pg_verify_mbstr_len(int encoding, const char *mbstr, int len, bool noError)
    1913             : {
    1914             :     mbverifier  mbverify;
    1915             :     int         mb_len;
    1916             : 
    1917             :     Assert(PG_VALID_ENCODING(encoding));
    1918             : 
    1919             :     /*
    1920             :      * In single-byte encodings, we need only reject nulls (\0).
    1921             :      */
    1922     2820606 :     if (pg_encoding_max_length(encoding) <= 1)
    1923             :     {
    1924       38884 :         const char *nullpos = memchr(mbstr, 0, len);
    1925             : 
    1926       38884 :         if (nullpos == NULL)
    1927       38884 :             return len;
    1928           0 :         if (noError)
    1929           0 :             return -1;
    1930           0 :         report_invalid_encoding(encoding, nullpos, 1);
    1931             :     }
    1932             : 
    1933             :     /* fetch function pointer just once */
    1934     2781722 :     mbverify = pg_wchar_table[encoding].mbverify;
    1935             : 
    1936     2781722 :     mb_len = 0;
    1937             : 
    1938   176185790 :     while (len > 0)
    1939             :     {
    1940             :         int         l;
    1941             : 
    1942             :         /* fast path for ASCII-subset characters */
    1943   170622348 :         if (!IS_HIGHBIT_SET(*mbstr))
    1944             :         {
    1945   170608376 :             if (*mbstr != '\0')
    1946             :             {
    1947   170608374 :                 mb_len++;
    1948   170608374 :                 mbstr++;
    1949   170608374 :                 len--;
    1950   170608374 :                 continue;
    1951             :             }
    1952           2 :             if (noError)
    1953           0 :                 return -1;
    1954           2 :             report_invalid_encoding(encoding, mbstr, len);
    1955             :         }
    1956             : 
    1957       13972 :         l = (*mbverify) ((const unsigned char *) mbstr, len);
    1958             : 
    1959       13972 :         if (l < 0)
    1960             :         {
    1961           0 :             if (noError)
    1962           0 :                 return -1;
    1963           0 :             report_invalid_encoding(encoding, mbstr, len);
    1964             :         }
    1965             : 
    1966       13972 :         mbstr += l;
    1967       13972 :         len -= l;
    1968       13972 :         mb_len++;
    1969             :     }
    1970     2781720 :     return mb_len;
    1971             : }
    1972             : 
    1973             : /*
    1974             :  * check_encoding_conversion_args: check arguments of a conversion function
    1975             :  *
    1976             :  * "expected" arguments can be either an encoding ID or -1 to indicate that
    1977             :  * the caller will check whether it accepts the ID.
    1978             :  *
    1979             :  * Note: the errors here are not really user-facing, so elog instead of
    1980             :  * ereport seems sufficient.  Also, we trust that the "expected" encoding
    1981             :  * arguments are valid encoding IDs, but we don't trust the actuals.
    1982             :  */
    1983             : void
    1984         802 : check_encoding_conversion_args(int src_encoding,
    1985             :                                int dest_encoding,
    1986             :                                int len,
    1987             :                                int expected_src_encoding,
    1988             :                                int expected_dest_encoding)
    1989             : {
    1990         802 :     if (!PG_VALID_ENCODING(src_encoding))
    1991           0 :         elog(ERROR, "invalid source encoding ID: %d", src_encoding);
    1992         802 :     if (src_encoding != expected_src_encoding && expected_src_encoding >= 0)
    1993           0 :         elog(ERROR, "expected source encoding \"%s\", but got \"%s\"",
    1994             :              pg_enc2name_tbl[expected_src_encoding].name,
    1995             :              pg_enc2name_tbl[src_encoding].name);
    1996         802 :     if (!PG_VALID_ENCODING(dest_encoding))
    1997           0 :         elog(ERROR, "invalid destination encoding ID: %d", dest_encoding);
    1998         802 :     if (dest_encoding != expected_dest_encoding && expected_dest_encoding >= 0)
    1999           0 :         elog(ERROR, "expected destination encoding \"%s\", but got \"%s\"",
    2000             :              pg_enc2name_tbl[expected_dest_encoding].name,
    2001             :              pg_enc2name_tbl[dest_encoding].name);
    2002         802 :     if (len < 0)
    2003           0 :         elog(ERROR, "encoding conversion length must not be negative");
    2004         802 : }
    2005             : 
    2006             : /*
    2007             :  * report_invalid_encoding: complain about invalid multibyte character
    2008             :  *
    2009             :  * note: len is remaining length of string, not length of character;
    2010             :  * len must be greater than zero, as we always examine the first byte.
    2011             :  */
    2012             : void
    2013           2 : report_invalid_encoding(int encoding, const char *mbstr, int len)
    2014             : {
    2015           2 :     int         l = pg_encoding_mblen(encoding, mbstr);
    2016             :     char        buf[8 * 5 + 1];
    2017           2 :     char       *p = buf;
    2018             :     int         j,
    2019             :                 jlimit;
    2020             : 
    2021           2 :     jlimit = Min(l, len);
    2022           2 :     jlimit = Min(jlimit, 8);    /* prevent buffer overrun */
    2023             : 
    2024           4 :     for (j = 0; j < jlimit; j++)
    2025             :     {
    2026           2 :         p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
    2027           2 :         if (j < jlimit - 1)
    2028           0 :             p += sprintf(p, " ");
    2029             :     }
    2030             : 
    2031           2 :     ereport(ERROR,
    2032             :             (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
    2033             :              errmsg("invalid byte sequence for encoding \"%s\": %s",
    2034             :                     pg_enc2name_tbl[encoding].name,
    2035             :                     buf)));
    2036             : }
    2037             : 
    2038             : /*
    2039             :  * report_untranslatable_char: complain about untranslatable character
    2040             :  *
    2041             :  * note: len is remaining length of string, not length of character;
    2042             :  * len must be greater than zero, as we always examine the first byte.
    2043             :  */
    2044             : void
    2045           0 : report_untranslatable_char(int src_encoding, int dest_encoding,
    2046             :                            const char *mbstr, int len)
    2047             : {
    2048           0 :     int         l = pg_encoding_mblen(src_encoding, mbstr);
    2049             :     char        buf[8 * 5 + 1];
    2050           0 :     char       *p = buf;
    2051             :     int         j,
    2052             :                 jlimit;
    2053             : 
    2054           0 :     jlimit = Min(l, len);
    2055           0 :     jlimit = Min(jlimit, 8);    /* prevent buffer overrun */
    2056             : 
    2057           0 :     for (j = 0; j < jlimit; j++)
    2058             :     {
    2059           0 :         p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
    2060           0 :         if (j < jlimit - 1)
    2061           0 :             p += sprintf(p, " ");
    2062             :     }
    2063             : 
    2064           0 :     ereport(ERROR,
    2065             :             (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
    2066             :              errmsg("character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"",
    2067             :                     buf,
    2068             :                     pg_enc2name_tbl[src_encoding].name,
    2069             :                     pg_enc2name_tbl[dest_encoding].name)));
    2070             : }
    2071             : 
    2072             : #endif                          /* !FRONTEND */

Generated by: LCOV version 1.13