LCOV - code coverage report
Current view: top level - src/backend/utils/mb/conversion_procs/euc_tw_and_big5 - euc_tw_and_big5.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 57.6 % 276 159
Test Date: 2026-02-27 06:14:34 Functions: 100.0 % 19 19
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  *    EUC_TW, BIG5 and MULE_INTERNAL
       4              :  *
       5              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       6              :  * Portions Copyright (c) 1994, Regents of the University of California
       7              :  *
       8              :  * IDENTIFICATION
       9              :  *    src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c
      10              :  *
      11              :  *-------------------------------------------------------------------------
      12              :  */
      13              : 
      14              : #include "postgres.h"
      15              : #include "fmgr.h"
      16              : #include "mb/pg_wchar.h"
      17              : 
      18            6 : PG_MODULE_MAGIC_EXT(
      19              :                     .name = "euc_tw_and_big5",
      20              :                     .version = PG_VERSION
      21              : );
      22              : 
      23            3 : PG_FUNCTION_INFO_V1(euc_tw_to_big5);
      24            3 : PG_FUNCTION_INFO_V1(big5_to_euc_tw);
      25            3 : PG_FUNCTION_INFO_V1(euc_tw_to_mic);
      26            3 : PG_FUNCTION_INFO_V1(mic_to_euc_tw);
      27            6 : PG_FUNCTION_INFO_V1(big5_to_mic);
      28            6 : PG_FUNCTION_INFO_V1(mic_to_big5);
      29              : 
      30              : /* ----------
      31              :  * conv_proc(
      32              :  *      INTEGER,    -- source encoding id
      33              :  *      INTEGER,    -- destination encoding id
      34              :  *      CSTRING,    -- source string (null terminated C string)
      35              :  *      CSTRING,    -- destination string (null terminated C string)
      36              :  *      INTEGER,    -- source string length
      37              :  *      BOOL        -- if true, don't throw an error if conversion fails
      38              :  * ) returns INTEGER;
      39              :  *
      40              :  * Returns the number of bytes successfully converted.
      41              :  * ----------
      42              :  */
      43              : 
      44              : static int  euc_tw2big5(const unsigned char *euc, unsigned char *p, int len, bool noError);
      45              : static int  big52euc_tw(const unsigned char *big5, unsigned char *p, int len, bool noError);
      46              : static int  big52mic(const unsigned char *big5, unsigned char *p, int len, bool noError);
      47              : static int  mic2big5(const unsigned char *mic, unsigned char *p, int len, bool noError);
      48              : static int  euc_tw2mic(const unsigned char *euc, unsigned char *p, int len, bool noError);
      49              : static int  mic2euc_tw(const unsigned char *mic, unsigned char *p, int len, bool noError);
      50              : 
      51              : Datum
      52            3 : euc_tw_to_big5(PG_FUNCTION_ARGS)
      53              : {
      54            3 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      55            3 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      56            3 :     int         len = PG_GETARG_INT32(4);
      57            3 :     bool        noError = PG_GETARG_BOOL(5);
      58              :     int         converted;
      59              : 
      60            3 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_BIG5);
      61              : 
      62            3 :     converted = euc_tw2big5(src, dest, len, noError);
      63              : 
      64            3 :     PG_RETURN_INT32(converted);
      65              : }
      66              : 
      67              : Datum
      68            3 : big5_to_euc_tw(PG_FUNCTION_ARGS)
      69              : {
      70            3 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      71            3 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      72            3 :     int         len = PG_GETARG_INT32(4);
      73            3 :     bool        noError = PG_GETARG_BOOL(5);
      74              :     int         converted;
      75              : 
      76            3 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_EUC_TW);
      77              : 
      78            3 :     converted = big52euc_tw(src, dest, len, noError);
      79              : 
      80            3 :     PG_RETURN_INT32(converted);
      81              : }
      82              : 
      83              : Datum
      84            3 : euc_tw_to_mic(PG_FUNCTION_ARGS)
      85              : {
      86            3 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      87            3 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      88            3 :     int         len = PG_GETARG_INT32(4);
      89            3 :     bool        noError = PG_GETARG_BOOL(5);
      90              :     int         converted;
      91              : 
      92            3 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_MULE_INTERNAL);
      93              : 
      94            3 :     converted = euc_tw2mic(src, dest, len, noError);
      95              : 
      96            3 :     PG_RETURN_INT32(converted);
      97              : }
      98              : 
      99              : Datum
     100            3 : mic_to_euc_tw(PG_FUNCTION_ARGS)
     101              : {
     102            3 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     103            3 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     104            3 :     int         len = PG_GETARG_INT32(4);
     105            3 :     bool        noError = PG_GETARG_BOOL(5);
     106              :     int         converted;
     107              : 
     108            3 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_TW);
     109              : 
     110            3 :     converted = mic2euc_tw(src, dest, len, noError);
     111              : 
     112            3 :     PG_RETURN_INT32(converted);
     113              : }
     114              : 
     115              : Datum
     116           66 : big5_to_mic(PG_FUNCTION_ARGS)
     117              : {
     118           66 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     119           66 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     120           66 :     int         len = PG_GETARG_INT32(4);
     121           66 :     bool        noError = PG_GETARG_BOOL(5);
     122              :     int         converted;
     123              : 
     124           66 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_MULE_INTERNAL);
     125              : 
     126           66 :     converted = big52mic(src, dest, len, noError);
     127              : 
     128           48 :     PG_RETURN_INT32(converted);
     129              : }
     130              : 
     131              : Datum
     132          165 : mic_to_big5(PG_FUNCTION_ARGS)
     133              : {
     134          165 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     135          165 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     136          165 :     int         len = PG_GETARG_INT32(4);
     137          165 :     bool        noError = PG_GETARG_BOOL(5);
     138              :     int         converted;
     139              : 
     140          165 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_BIG5);
     141              : 
     142          165 :     converted = mic2big5(src, dest, len, noError);
     143              : 
     144           93 :     PG_RETURN_INT32(converted);
     145              : }
     146              : 
     147              : 
     148              : /*
     149              :  * EUC_TW ---> Big5
     150              :  */
     151              : static int
     152            3 : euc_tw2big5(const unsigned char *euc, unsigned char *p, int len, bool noError)
     153              : {
     154            3 :     const unsigned char *start = euc;
     155              :     unsigned char c1;
     156              :     unsigned short big5buf,
     157              :                 cnsBuf;
     158              :     unsigned char lc;
     159              :     int         l;
     160              : 
     161           12 :     while (len > 0)
     162              :     {
     163            9 :         c1 = *euc;
     164            9 :         if (IS_HIGHBIT_SET(c1))
     165              :         {
     166              :             /* Verify and decode the next EUC_TW input character */
     167            0 :             l = pg_encoding_verifymbchar(PG_EUC_TW, (const char *) euc, len);
     168            0 :             if (l < 0)
     169              :             {
     170            0 :                 if (noError)
     171            0 :                     break;
     172            0 :                 report_invalid_encoding(PG_EUC_TW,
     173              :                                         (const char *) euc, len);
     174              :             }
     175            0 :             if (c1 == SS2)
     176              :             {
     177            0 :                 c1 = euc[1];    /* plane No. */
     178            0 :                 if (c1 == 0xa1)
     179            0 :                     lc = LC_CNS11643_1;
     180            0 :                 else if (c1 == 0xa2)
     181            0 :                     lc = LC_CNS11643_2;
     182              :                 else
     183            0 :                     lc = c1 - 0xa3 + LC_CNS11643_3;
     184            0 :                 cnsBuf = (euc[2] << 8) | euc[3];
     185              :             }
     186              :             else
     187              :             {                   /* CNS11643-1 */
     188            0 :                 lc = LC_CNS11643_1;
     189            0 :                 cnsBuf = (c1 << 8) | euc[1];
     190              :             }
     191              : 
     192              :             /* Write it out in Big5 */
     193            0 :             big5buf = CNStoBIG5(cnsBuf, lc);
     194            0 :             if (big5buf == 0)
     195              :             {
     196            0 :                 if (noError)
     197            0 :                     break;
     198            0 :                 report_untranslatable_char(PG_EUC_TW, PG_BIG5,
     199              :                                            (const char *) euc, len);
     200              :             }
     201            0 :             *p++ = (big5buf >> 8) & 0x00ff;
     202            0 :             *p++ = big5buf & 0x00ff;
     203              : 
     204            0 :             euc += l;
     205            0 :             len -= l;
     206              :         }
     207              :         else
     208              :         {                       /* should be ASCII */
     209            9 :             if (c1 == 0)
     210              :             {
     211            0 :                 if (noError)
     212            0 :                     break;
     213            0 :                 report_invalid_encoding(PG_EUC_TW,
     214              :                                         (const char *) euc, len);
     215              :             }
     216            9 :             *p++ = c1;
     217            9 :             euc++;
     218            9 :             len--;
     219              :         }
     220              :     }
     221            3 :     *p = '\0';
     222              : 
     223            3 :     return euc - start;
     224              : }
     225              : 
     226              : /*
     227              :  * Big5 ---> EUC_TW
     228              :  */
     229              : static int
     230            3 : big52euc_tw(const unsigned char *big5, unsigned char *p, int len, bool noError)
     231              : {
     232            3 :     const unsigned char *start = big5;
     233              :     unsigned short c1;
     234              :     unsigned short big5buf,
     235              :                 cnsBuf;
     236              :     unsigned char lc;
     237              :     int         l;
     238              : 
     239           12 :     while (len > 0)
     240              :     {
     241              :         /* Verify and decode the next Big5 input character */
     242            9 :         c1 = *big5;
     243            9 :         if (IS_HIGHBIT_SET(c1))
     244              :         {
     245            0 :             l = pg_encoding_verifymbchar(PG_BIG5, (const char *) big5, len);
     246            0 :             if (l < 0)
     247              :             {
     248            0 :                 if (noError)
     249            0 :                     break;
     250            0 :                 report_invalid_encoding(PG_BIG5,
     251              :                                         (const char *) big5, len);
     252              :             }
     253            0 :             big5buf = (c1 << 8) | big5[1];
     254            0 :             cnsBuf = BIG5toCNS(big5buf, &lc);
     255              : 
     256            0 :             if (lc == LC_CNS11643_1)
     257              :             {
     258            0 :                 *p++ = (cnsBuf >> 8) & 0x00ff;
     259            0 :                 *p++ = cnsBuf & 0x00ff;
     260              :             }
     261            0 :             else if (lc == LC_CNS11643_2)
     262              :             {
     263            0 :                 *p++ = SS2;
     264            0 :                 *p++ = 0xa2;
     265            0 :                 *p++ = (cnsBuf >> 8) & 0x00ff;
     266            0 :                 *p++ = cnsBuf & 0x00ff;
     267              :             }
     268            0 :             else if (lc >= LC_CNS11643_3 && lc <= LC_CNS11643_7)
     269              :             {
     270            0 :                 *p++ = SS2;
     271            0 :                 *p++ = lc - LC_CNS11643_3 + 0xa3;
     272            0 :                 *p++ = (cnsBuf >> 8) & 0x00ff;
     273            0 :                 *p++ = cnsBuf & 0x00ff;
     274              :             }
     275              :             else
     276              :             {
     277            0 :                 if (noError)
     278            0 :                     break;
     279            0 :                 report_untranslatable_char(PG_BIG5, PG_EUC_TW,
     280              :                                            (const char *) big5, len);
     281              :             }
     282              : 
     283            0 :             big5 += l;
     284            0 :             len -= l;
     285              :         }
     286              :         else
     287              :         {
     288              :             /* ASCII */
     289            9 :             if (c1 == 0)
     290              :             {
     291            0 :                 if (noError)
     292            0 :                     break;
     293            0 :                 report_invalid_encoding(PG_BIG5,
     294              :                                         (const char *) big5, len);
     295              :             }
     296            9 :             *p++ = c1;
     297            9 :             big5++;
     298            9 :             len--;
     299            9 :             continue;
     300              :         }
     301              :     }
     302            3 :     *p = '\0';
     303              : 
     304            3 :     return big5 - start;
     305              : }
     306              : 
     307              : /*
     308              :  * EUC_TW ---> MIC
     309              :  */
     310              : static int
     311            3 : euc_tw2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
     312              : {
     313            3 :     const unsigned char *start = euc;
     314              :     int         c1;
     315              :     int         l;
     316              : 
     317           12 :     while (len > 0)
     318              :     {
     319            9 :         c1 = *euc;
     320            9 :         if (IS_HIGHBIT_SET(c1))
     321              :         {
     322            0 :             l = pg_encoding_verifymbchar(PG_EUC_TW, (const char *) euc, len);
     323            0 :             if (l < 0)
     324              :             {
     325            0 :                 if (noError)
     326            0 :                     break;
     327            0 :                 report_invalid_encoding(PG_EUC_TW,
     328              :                                         (const char *) euc, len);
     329              :             }
     330            0 :             if (c1 == SS2)
     331              :             {
     332            0 :                 c1 = euc[1];    /* plane No. */
     333            0 :                 if (c1 == 0xa1)
     334            0 :                     *p++ = LC_CNS11643_1;
     335            0 :                 else if (c1 == 0xa2)
     336            0 :                     *p++ = LC_CNS11643_2;
     337              :                 else
     338              :                 {
     339              :                     /* other planes are MULE private charsets */
     340            0 :                     *p++ = LCPRV2_B;
     341            0 :                     *p++ = c1 - 0xa3 + LC_CNS11643_3;
     342              :                 }
     343            0 :                 *p++ = euc[2];
     344            0 :                 *p++ = euc[3];
     345              :             }
     346              :             else
     347              :             {                   /* CNS11643-1 */
     348            0 :                 *p++ = LC_CNS11643_1;
     349            0 :                 *p++ = c1;
     350            0 :                 *p++ = euc[1];
     351              :             }
     352            0 :             euc += l;
     353            0 :             len -= l;
     354              :         }
     355              :         else
     356              :         {                       /* should be ASCII */
     357            9 :             if (c1 == 0)
     358              :             {
     359            0 :                 if (noError)
     360            0 :                     break;
     361            0 :                 report_invalid_encoding(PG_EUC_TW,
     362              :                                         (const char *) euc, len);
     363              :             }
     364            9 :             *p++ = c1;
     365            9 :             euc++;
     366            9 :             len--;
     367              :         }
     368              :     }
     369            3 :     *p = '\0';
     370              : 
     371            3 :     return euc - start;
     372              : }
     373              : 
     374              : /*
     375              :  * MIC ---> EUC_TW
     376              :  */
     377              : static int
     378            3 : mic2euc_tw(const unsigned char *mic, unsigned char *p, int len, bool noError)
     379              : {
     380            3 :     const unsigned char *start = mic;
     381              :     int         c1;
     382              :     int         l;
     383              : 
     384           12 :     while (len > 0)
     385              :     {
     386            9 :         c1 = *mic;
     387            9 :         if (!IS_HIGHBIT_SET(c1))
     388              :         {
     389              :             /* ASCII */
     390            9 :             if (c1 == 0)
     391              :             {
     392            0 :                 if (noError)
     393            0 :                     break;
     394            0 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     395              :                                         (const char *) mic, len);
     396              :             }
     397            9 :             *p++ = c1;
     398            9 :             mic++;
     399            9 :             len--;
     400            9 :             continue;
     401              :         }
     402            0 :         l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
     403            0 :         if (l < 0)
     404              :         {
     405            0 :             if (noError)
     406            0 :                 break;
     407            0 :             report_invalid_encoding(PG_MULE_INTERNAL,
     408              :                                     (const char *) mic, len);
     409              :         }
     410            0 :         if (c1 == LC_CNS11643_1)
     411              :         {
     412            0 :             *p++ = mic[1];
     413            0 :             *p++ = mic[2];
     414              :         }
     415            0 :         else if (c1 == LC_CNS11643_2)
     416              :         {
     417            0 :             *p++ = SS2;
     418            0 :             *p++ = 0xa2;
     419            0 :             *p++ = mic[1];
     420            0 :             *p++ = mic[2];
     421              :         }
     422            0 :         else if (c1 == LCPRV2_B &&
     423            0 :                  mic[1] >= LC_CNS11643_3 && mic[1] <= LC_CNS11643_7)
     424              :         {
     425            0 :             *p++ = SS2;
     426            0 :             *p++ = mic[1] - LC_CNS11643_3 + 0xa3;
     427            0 :             *p++ = mic[2];
     428            0 :             *p++ = mic[3];
     429              :         }
     430              :         else
     431              :         {
     432            0 :             if (noError)
     433            0 :                 break;
     434            0 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_TW,
     435              :                                        (const char *) mic, len);
     436              :         }
     437            0 :         mic += l;
     438            0 :         len -= l;
     439              :     }
     440            3 :     *p = '\0';
     441              : 
     442            3 :     return mic - start;
     443              : }
     444              : 
     445              : /*
     446              :  * Big5 ---> MIC
     447              :  */
     448              : static int
     449           66 : big52mic(const unsigned char *big5, unsigned char *p, int len, bool noError)
     450              : {
     451           66 :     const unsigned char *start = big5;
     452              :     unsigned short c1;
     453              :     unsigned short big5buf,
     454              :                 cnsBuf;
     455              :     unsigned char lc;
     456              :     int         l;
     457              : 
     458          300 :     while (len > 0)
     459              :     {
     460          270 :         c1 = *big5;
     461          270 :         if (!IS_HIGHBIT_SET(c1))
     462              :         {
     463              :             /* ASCII */
     464          216 :             if (c1 == 0)
     465              :             {
     466           18 :                 if (noError)
     467            9 :                     break;
     468            9 :                 report_invalid_encoding(PG_BIG5,
     469              :                                         (const char *) big5, len);
     470              :             }
     471          198 :             *p++ = c1;
     472          198 :             big5++;
     473          198 :             len--;
     474          198 :             continue;
     475              :         }
     476           54 :         l = pg_encoding_verifymbchar(PG_BIG5, (const char *) big5, len);
     477           54 :         if (l < 0)
     478              :         {
     479           18 :             if (noError)
     480            9 :                 break;
     481            9 :             report_invalid_encoding(PG_BIG5,
     482              :                                     (const char *) big5, len);
     483              :         }
     484           36 :         big5buf = (c1 << 8) | big5[1];
     485           36 :         cnsBuf = BIG5toCNS(big5buf, &lc);
     486           36 :         if (lc != 0)
     487              :         {
     488              :             /* Planes 3 and 4 are MULE private charsets */
     489           36 :             if (lc == LC_CNS11643_3 || lc == LC_CNS11643_4)
     490            0 :                 *p++ = LCPRV2_B;
     491           36 :             *p++ = lc;          /* Plane No. */
     492           36 :             *p++ = (cnsBuf >> 8) & 0x00ff;
     493           36 :             *p++ = cnsBuf & 0x00ff;
     494              :         }
     495              :         else
     496              :         {
     497            0 :             if (noError)
     498            0 :                 break;
     499            0 :             report_untranslatable_char(PG_BIG5, PG_MULE_INTERNAL,
     500              :                                        (const char *) big5, len);
     501              :         }
     502           36 :         big5 += l;
     503           36 :         len -= l;
     504              :     }
     505           48 :     *p = '\0';
     506              : 
     507           48 :     return big5 - start;
     508              : }
     509              : 
     510              : /*
     511              :  * MIC ---> Big5
     512              :  */
     513              : static int
     514          165 : mic2big5(const unsigned char *mic, unsigned char *p, int len, bool noError)
     515              : {
     516          165 :     const unsigned char *start = mic;
     517              :     unsigned short c1;
     518              :     unsigned short big5buf,
     519              :                 cnsBuf;
     520              :     int         l;
     521              : 
     522          291 :     while (len > 0)
     523              :     {
     524          270 :         c1 = *mic;
     525          270 :         if (!IS_HIGHBIT_SET(c1))
     526              :         {
     527              :             /* ASCII */
     528          117 :             if (c1 == 0)
     529              :             {
     530            0 :                 if (noError)
     531            0 :                     break;
     532            0 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     533              :                                         (const char *) mic, len);
     534              :             }
     535          117 :             *p++ = c1;
     536          117 :             mic++;
     537          117 :             len--;
     538          117 :             continue;
     539              :         }
     540          153 :         l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
     541          153 :         if (l < 0)
     542              :         {
     543           72 :             if (noError)
     544           36 :                 break;
     545           36 :             report_invalid_encoding(PG_MULE_INTERNAL,
     546              :                                     (const char *) mic, len);
     547              :         }
     548           81 :         if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == LCPRV2_B)
     549              :         {
     550            9 :             if (c1 == LCPRV2_B)
     551              :             {
     552            0 :                 c1 = mic[1];    /* get plane no. */
     553            0 :                 cnsBuf = (mic[2] << 8) | mic[3];
     554              :             }
     555              :             else
     556              :             {
     557            9 :                 cnsBuf = (mic[1] << 8) | mic[2];
     558              :             }
     559            9 :             big5buf = CNStoBIG5(cnsBuf, c1);
     560            9 :             if (big5buf == 0)
     561              :             {
     562            0 :                 if (noError)
     563            0 :                     break;
     564            0 :                 report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
     565              :                                            (const char *) mic, len);
     566              :             }
     567            9 :             *p++ = (big5buf >> 8) & 0x00ff;
     568            9 :             *p++ = big5buf & 0x00ff;
     569              :         }
     570              :         else
     571              :         {
     572           72 :             if (noError)
     573           36 :                 break;
     574           36 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
     575              :                                        (const char *) mic, len);
     576              :         }
     577            9 :         mic += l;
     578            9 :         len -= l;
     579              :     }
     580           93 :     *p = '\0';
     581              : 
     582           93 :     return mic - start;
     583              : }
        

Generated by: LCOV version 2.0-1