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

Generated by: LCOV version 1.14