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) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 159 276 57.6 %
Date: 2024-12-03 09:15:01 Functions: 19 19 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14