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-03-22 06:16:09 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            8 : PG_MODULE_MAGIC_EXT(
      19              :                     .name = "euc_tw_and_big5",
      20              :                     .version = PG_VERSION
      21              : );
      22              : 
      23            4 : PG_FUNCTION_INFO_V1(euc_tw_to_big5);
      24            4 : PG_FUNCTION_INFO_V1(big5_to_euc_tw);
      25            4 : PG_FUNCTION_INFO_V1(euc_tw_to_mic);
      26            4 : PG_FUNCTION_INFO_V1(mic_to_euc_tw);
      27            8 : PG_FUNCTION_INFO_V1(big5_to_mic);
      28            8 : 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            4 : euc_tw_to_big5(PG_FUNCTION_ARGS)
      53              : {
      54            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      55            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      56            4 :     int         len = PG_GETARG_INT32(4);
      57            4 :     bool        noError = PG_GETARG_BOOL(5);
      58              :     int         converted;
      59              : 
      60            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_BIG5);
      61              : 
      62            4 :     converted = euc_tw2big5(src, dest, len, noError);
      63              : 
      64            4 :     PG_RETURN_INT32(converted);
      65              : }
      66              : 
      67              : Datum
      68            4 : big5_to_euc_tw(PG_FUNCTION_ARGS)
      69              : {
      70            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      71            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      72            4 :     int         len = PG_GETARG_INT32(4);
      73            4 :     bool        noError = PG_GETARG_BOOL(5);
      74              :     int         converted;
      75              : 
      76            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_EUC_TW);
      77              : 
      78            4 :     converted = big52euc_tw(src, dest, len, noError);
      79              : 
      80            4 :     PG_RETURN_INT32(converted);
      81              : }
      82              : 
      83              : Datum
      84            4 : euc_tw_to_mic(PG_FUNCTION_ARGS)
      85              : {
      86            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      87            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      88            4 :     int         len = PG_GETARG_INT32(4);
      89            4 :     bool        noError = PG_GETARG_BOOL(5);
      90              :     int         converted;
      91              : 
      92            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_MULE_INTERNAL);
      93              : 
      94            4 :     converted = euc_tw2mic(src, dest, len, noError);
      95              : 
      96            4 :     PG_RETURN_INT32(converted);
      97              : }
      98              : 
      99              : Datum
     100            4 : mic_to_euc_tw(PG_FUNCTION_ARGS)
     101              : {
     102            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     103            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     104            4 :     int         len = PG_GETARG_INT32(4);
     105            4 :     bool        noError = PG_GETARG_BOOL(5);
     106              :     int         converted;
     107              : 
     108            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_TW);
     109              : 
     110            4 :     converted = mic2euc_tw(src, dest, len, noError);
     111              : 
     112            4 :     PG_RETURN_INT32(converted);
     113              : }
     114              : 
     115              : Datum
     116           88 : big5_to_mic(PG_FUNCTION_ARGS)
     117              : {
     118           88 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     119           88 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     120           88 :     int         len = PG_GETARG_INT32(4);
     121           88 :     bool        noError = PG_GETARG_BOOL(5);
     122              :     int         converted;
     123              : 
     124           88 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_MULE_INTERNAL);
     125              : 
     126           88 :     converted = big52mic(src, dest, len, noError);
     127              : 
     128           64 :     PG_RETURN_INT32(converted);
     129              : }
     130              : 
     131              : Datum
     132          220 : mic_to_big5(PG_FUNCTION_ARGS)
     133              : {
     134          220 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     135          220 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     136          220 :     int         len = PG_GETARG_INT32(4);
     137          220 :     bool        noError = PG_GETARG_BOOL(5);
     138              :     int         converted;
     139              : 
     140          220 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_BIG5);
     141              : 
     142          220 :     converted = mic2big5(src, dest, len, noError);
     143              : 
     144          124 :     PG_RETURN_INT32(converted);
     145              : }
     146              : 
     147              : 
     148              : /*
     149              :  * EUC_TW ---> Big5
     150              :  */
     151              : static int
     152            4 : euc_tw2big5(const unsigned char *euc, unsigned char *p, int len, bool noError)
     153              : {
     154            4 :     const unsigned char *start = euc;
     155              :     unsigned char c1;
     156              :     unsigned short big5buf,
     157              :                 cnsBuf;
     158              :     unsigned char lc;
     159              :     int         l;
     160              : 
     161           16 :     while (len > 0)
     162              :     {
     163           12 :         c1 = *euc;
     164           12 :         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           12 :             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           12 :             *p++ = c1;
     217           12 :             euc++;
     218           12 :             len--;
     219              :         }
     220              :     }
     221            4 :     *p = '\0';
     222              : 
     223            4 :     return euc - start;
     224              : }
     225              : 
     226              : /*
     227              :  * Big5 ---> EUC_TW
     228              :  */
     229              : static int
     230            4 : big52euc_tw(const unsigned char *big5, unsigned char *p, int len, bool noError)
     231              : {
     232            4 :     const unsigned char *start = big5;
     233              :     unsigned short c1;
     234              :     unsigned short big5buf,
     235              :                 cnsBuf;
     236              :     unsigned char lc;
     237              :     int         l;
     238              : 
     239           16 :     while (len > 0)
     240              :     {
     241              :         /* Verify and decode the next Big5 input character */
     242           12 :         c1 = *big5;
     243           12 :         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           12 :             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           12 :             *p++ = c1;
     297           12 :             big5++;
     298           12 :             len--;
     299           12 :             continue;
     300              :         }
     301              :     }
     302            4 :     *p = '\0';
     303              : 
     304            4 :     return big5 - start;
     305              : }
     306              : 
     307              : /*
     308              :  * EUC_TW ---> MIC
     309              :  */
     310              : static int
     311            4 : euc_tw2mic(const unsigned char *euc, unsigned char *p, int len, bool noError)
     312              : {
     313            4 :     const unsigned char *start = euc;
     314              :     int         c1;
     315              :     int         l;
     316              : 
     317           16 :     while (len > 0)
     318              :     {
     319           12 :         c1 = *euc;
     320           12 :         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           12 :             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           12 :             *p++ = c1;
     365           12 :             euc++;
     366           12 :             len--;
     367              :         }
     368              :     }
     369            4 :     *p = '\0';
     370              : 
     371            4 :     return euc - start;
     372              : }
     373              : 
     374              : /*
     375              :  * MIC ---> EUC_TW
     376              :  */
     377              : static int
     378            4 : mic2euc_tw(const unsigned char *mic, unsigned char *p, int len, bool noError)
     379              : {
     380            4 :     const unsigned char *start = mic;
     381              :     int         c1;
     382              :     int         l;
     383              : 
     384           16 :     while (len > 0)
     385              :     {
     386           12 :         c1 = *mic;
     387           12 :         if (!IS_HIGHBIT_SET(c1))
     388              :         {
     389              :             /* ASCII */
     390           12 :             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           12 :             *p++ = c1;
     398           12 :             mic++;
     399           12 :             len--;
     400           12 :             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            4 :     *p = '\0';
     441              : 
     442            4 :     return mic - start;
     443              : }
     444              : 
     445              : /*
     446              :  * Big5 ---> MIC
     447              :  */
     448              : static int
     449           88 : big52mic(const unsigned char *big5, unsigned char *p, int len, bool noError)
     450              : {
     451           88 :     const unsigned char *start = big5;
     452              :     unsigned short c1;
     453              :     unsigned short big5buf,
     454              :                 cnsBuf;
     455              :     unsigned char lc;
     456              :     int         l;
     457              : 
     458          400 :     while (len > 0)
     459              :     {
     460          360 :         c1 = *big5;
     461          360 :         if (!IS_HIGHBIT_SET(c1))
     462              :         {
     463              :             /* ASCII */
     464          288 :             if (c1 == 0)
     465              :             {
     466           24 :                 if (noError)
     467           12 :                     break;
     468           12 :                 report_invalid_encoding(PG_BIG5,
     469              :                                         (const char *) big5, len);
     470              :             }
     471          264 :             *p++ = c1;
     472          264 :             big5++;
     473          264 :             len--;
     474          264 :             continue;
     475              :         }
     476           72 :         l = pg_encoding_verifymbchar(PG_BIG5, (const char *) big5, len);
     477           72 :         if (l < 0)
     478              :         {
     479           24 :             if (noError)
     480           12 :                 break;
     481           12 :             report_invalid_encoding(PG_BIG5,
     482              :                                     (const char *) big5, len);
     483              :         }
     484           48 :         big5buf = (c1 << 8) | big5[1];
     485           48 :         cnsBuf = BIG5toCNS(big5buf, &lc);
     486           48 :         if (lc != 0)
     487              :         {
     488              :             /* Planes 3 and 4 are MULE private charsets */
     489           48 :             if (lc == LC_CNS11643_3 || lc == LC_CNS11643_4)
     490            0 :                 *p++ = LCPRV2_B;
     491           48 :             *p++ = lc;          /* Plane No. */
     492           48 :             *p++ = (cnsBuf >> 8) & 0x00ff;
     493           48 :             *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           48 :         big5 += l;
     503           48 :         len -= l;
     504              :     }
     505           64 :     *p = '\0';
     506              : 
     507           64 :     return big5 - start;
     508              : }
     509              : 
     510              : /*
     511              :  * MIC ---> Big5
     512              :  */
     513              : static int
     514          220 : mic2big5(const unsigned char *mic, unsigned char *p, int len, bool noError)
     515              : {
     516          220 :     const unsigned char *start = mic;
     517              :     unsigned short c1;
     518              :     unsigned short big5buf,
     519              :                 cnsBuf;
     520              :     int         l;
     521              : 
     522          388 :     while (len > 0)
     523              :     {
     524          360 :         c1 = *mic;
     525          360 :         if (!IS_HIGHBIT_SET(c1))
     526              :         {
     527              :             /* ASCII */
     528          156 :             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          156 :             *p++ = c1;
     536          156 :             mic++;
     537          156 :             len--;
     538          156 :             continue;
     539              :         }
     540          204 :         l = pg_encoding_verifymbchar(PG_MULE_INTERNAL, (const char *) mic, len);
     541          204 :         if (l < 0)
     542              :         {
     543           96 :             if (noError)
     544           48 :                 break;
     545           48 :             report_invalid_encoding(PG_MULE_INTERNAL,
     546              :                                     (const char *) mic, len);
     547              :         }
     548          108 :         if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == LCPRV2_B)
     549              :         {
     550           12 :             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           12 :                 cnsBuf = (mic[1] << 8) | mic[2];
     558              :             }
     559           12 :             big5buf = CNStoBIG5(cnsBuf, c1);
     560           12 :             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           12 :             *p++ = (big5buf >> 8) & 0x00ff;
     568           12 :             *p++ = big5buf & 0x00ff;
     569              :         }
     570              :         else
     571              :         {
     572           96 :             if (noError)
     573           48 :                 break;
     574           48 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
     575              :                                        (const char *) mic, len);
     576              :         }
     577           12 :         mic += l;
     578           12 :         len -= l;
     579              :     }
     580          124 :     *p = '\0';
     581              : 
     582          124 :     return mic - start;
     583              : }
        

Generated by: LCOV version 2.0-1