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 13devel Lines: 98 170 57.6 %
Date: 2019-11-16 00:06:57 Functions: 17 17 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-2019, 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           4 : 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           4 : PG_FUNCTION_INFO_V1(big5_to_mic);
      27           4 : 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             :  * ) returns VOID;
      37             :  * ----------
      38             :  */
      39             : 
      40             : static void big52mic(const unsigned char *big5, unsigned char *p, int len);
      41             : static void mic2big5(const unsigned char *mic, unsigned char *p, int len);
      42             : static void euc_tw2mic(const unsigned char *euc, unsigned char *p, int len);
      43             : static void mic2euc_tw(const unsigned char *mic, unsigned char *p, int len);
      44             : 
      45             : Datum
      46           4 : euc_tw_to_big5(PG_FUNCTION_ARGS)
      47             : {
      48           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      49           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      50           4 :     int         len = PG_GETARG_INT32(4);
      51             :     unsigned char *buf;
      52             : 
      53           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_BIG5);
      54             : 
      55           4 :     buf = palloc(len * ENCODING_GROWTH_RATE + 1);
      56           4 :     euc_tw2mic(src, buf, len);
      57           4 :     mic2big5(buf, dest, strlen((char *) buf));
      58           4 :     pfree(buf);
      59             : 
      60           4 :     PG_RETURN_VOID();
      61             : }
      62             : 
      63             : Datum
      64           4 : big5_to_euc_tw(PG_FUNCTION_ARGS)
      65             : {
      66           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      67           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      68           4 :     int         len = PG_GETARG_INT32(4);
      69             :     unsigned char *buf;
      70             : 
      71           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_EUC_TW);
      72             : 
      73           4 :     buf = palloc(len * ENCODING_GROWTH_RATE + 1);
      74           4 :     big52mic(src, buf, len);
      75           4 :     mic2euc_tw(buf, dest, strlen((char *) buf));
      76           4 :     pfree(buf);
      77             : 
      78           4 :     PG_RETURN_VOID();
      79             : }
      80             : 
      81             : Datum
      82           4 : euc_tw_to_mic(PG_FUNCTION_ARGS)
      83             : {
      84           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      85           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      86           4 :     int         len = PG_GETARG_INT32(4);
      87             : 
      88           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_TW, PG_MULE_INTERNAL);
      89             : 
      90           4 :     euc_tw2mic(src, dest, len);
      91             : 
      92           4 :     PG_RETURN_VOID();
      93             : }
      94             : 
      95             : Datum
      96           4 : mic_to_euc_tw(PG_FUNCTION_ARGS)
      97             : {
      98           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      99           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     100           4 :     int         len = PG_GETARG_INT32(4);
     101             : 
     102           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_EUC_TW);
     103             : 
     104           4 :     mic2euc_tw(src, dest, len);
     105             : 
     106           4 :     PG_RETURN_VOID();
     107             : }
     108             : 
     109             : Datum
     110           4 : big5_to_mic(PG_FUNCTION_ARGS)
     111             : {
     112           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     113           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     114           4 :     int         len = PG_GETARG_INT32(4);
     115             : 
     116           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_BIG5, PG_MULE_INTERNAL);
     117             : 
     118           4 :     big52mic(src, dest, len);
     119             : 
     120           4 :     PG_RETURN_VOID();
     121             : }
     122             : 
     123             : Datum
     124           4 : mic_to_big5(PG_FUNCTION_ARGS)
     125             : {
     126           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
     127           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
     128           4 :     int         len = PG_GETARG_INT32(4);
     129             : 
     130           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_BIG5);
     131             : 
     132           4 :     mic2big5(src, dest, len);
     133             : 
     134           4 :     PG_RETURN_VOID();
     135             : }
     136             : 
     137             : /*
     138             :  * EUC_TW ---> MIC
     139             :  */
     140             : static void
     141           8 : euc_tw2mic(const unsigned char *euc, unsigned char *p, int len)
     142             : {
     143             :     int         c1;
     144             :     int         l;
     145             : 
     146          40 :     while (len > 0)
     147             :     {
     148          24 :         c1 = *euc;
     149          24 :         if (IS_HIGHBIT_SET(c1))
     150             :         {
     151           0 :             l = pg_encoding_verifymb(PG_EUC_TW, (const char *) euc, len);
     152           0 :             if (l < 0)
     153           0 :                 report_invalid_encoding(PG_EUC_TW,
     154             :                                         (const char *) euc, len);
     155           0 :             if (c1 == SS2)
     156             :             {
     157           0 :                 c1 = euc[1];    /* plane No. */
     158           0 :                 if (c1 == 0xa1)
     159           0 :                     *p++ = LC_CNS11643_1;
     160           0 :                 else if (c1 == 0xa2)
     161           0 :                     *p++ = LC_CNS11643_2;
     162             :                 else
     163             :                 {
     164             :                     /* other planes are MULE private charsets */
     165           0 :                     *p++ = LCPRV2_B;
     166           0 :                     *p++ = c1 - 0xa3 + LC_CNS11643_3;
     167             :                 }
     168           0 :                 *p++ = euc[2];
     169           0 :                 *p++ = euc[3];
     170             :             }
     171             :             else
     172             :             {                   /* CNS11643-1 */
     173           0 :                 *p++ = LC_CNS11643_1;
     174           0 :                 *p++ = c1;
     175           0 :                 *p++ = euc[1];
     176             :             }
     177           0 :             euc += l;
     178           0 :             len -= l;
     179             :         }
     180             :         else
     181             :         {                       /* should be ASCII */
     182          24 :             if (c1 == 0)
     183           0 :                 report_invalid_encoding(PG_EUC_TW,
     184             :                                         (const char *) euc, len);
     185          24 :             *p++ = c1;
     186          24 :             euc++;
     187          24 :             len--;
     188             :         }
     189             :     }
     190           8 :     *p = '\0';
     191           8 : }
     192             : 
     193             : /*
     194             :  * MIC ---> EUC_TW
     195             :  */
     196             : static void
     197           8 : mic2euc_tw(const unsigned char *mic, unsigned char *p, int len)
     198             : {
     199             :     int         c1;
     200             :     int         l;
     201             : 
     202          40 :     while (len > 0)
     203             :     {
     204          24 :         c1 = *mic;
     205          24 :         if (!IS_HIGHBIT_SET(c1))
     206             :         {
     207             :             /* ASCII */
     208          24 :             if (c1 == 0)
     209           0 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     210             :                                         (const char *) mic, len);
     211          24 :             *p++ = c1;
     212          24 :             mic++;
     213          24 :             len--;
     214          24 :             continue;
     215             :         }
     216           0 :         l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
     217           0 :         if (l < 0)
     218           0 :             report_invalid_encoding(PG_MULE_INTERNAL,
     219             :                                     (const char *) mic, len);
     220           0 :         if (c1 == LC_CNS11643_1)
     221             :         {
     222           0 :             *p++ = mic[1];
     223           0 :             *p++ = mic[2];
     224             :         }
     225           0 :         else if (c1 == LC_CNS11643_2)
     226             :         {
     227           0 :             *p++ = SS2;
     228           0 :             *p++ = 0xa2;
     229           0 :             *p++ = mic[1];
     230           0 :             *p++ = mic[2];
     231             :         }
     232           0 :         else if (c1 == LCPRV2_B &&
     233           0 :                  mic[1] >= LC_CNS11643_3 && mic[1] <= LC_CNS11643_7)
     234             :         {
     235           0 :             *p++ = SS2;
     236           0 :             *p++ = mic[1] - LC_CNS11643_3 + 0xa3;
     237           0 :             *p++ = mic[2];
     238           0 :             *p++ = mic[3];
     239             :         }
     240             :         else
     241           0 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_TW,
     242             :                                        (const char *) mic, len);
     243           0 :         mic += l;
     244           0 :         len -= l;
     245             :     }
     246           8 :     *p = '\0';
     247           8 : }
     248             : 
     249             : /*
     250             :  * Big5 ---> MIC
     251             :  */
     252             : static void
     253           8 : big52mic(const unsigned char *big5, unsigned char *p, int len)
     254             : {
     255             :     unsigned short c1;
     256             :     unsigned short big5buf,
     257             :                 cnsBuf;
     258             :     unsigned char lc;
     259             :     int         l;
     260             : 
     261          40 :     while (len > 0)
     262             :     {
     263          24 :         c1 = *big5;
     264          24 :         if (!IS_HIGHBIT_SET(c1))
     265             :         {
     266             :             /* ASCII */
     267          24 :             if (c1 == 0)
     268           0 :                 report_invalid_encoding(PG_BIG5,
     269             :                                         (const char *) big5, len);
     270          24 :             *p++ = c1;
     271          24 :             big5++;
     272          24 :             len--;
     273          24 :             continue;
     274             :         }
     275           0 :         l = pg_encoding_verifymb(PG_BIG5, (const char *) big5, len);
     276           0 :         if (l < 0)
     277           0 :             report_invalid_encoding(PG_BIG5,
     278             :                                     (const char *) big5, len);
     279           0 :         big5buf = (c1 << 8) | big5[1];
     280           0 :         cnsBuf = BIG5toCNS(big5buf, &lc);
     281           0 :         if (lc != 0)
     282             :         {
     283             :             /* Planes 3 and 4 are MULE private charsets */
     284           0 :             if (lc == LC_CNS11643_3 || lc == LC_CNS11643_4)
     285           0 :                 *p++ = LCPRV2_B;
     286           0 :             *p++ = lc;          /* Plane No. */
     287           0 :             *p++ = (cnsBuf >> 8) & 0x00ff;
     288           0 :             *p++ = cnsBuf & 0x00ff;
     289             :         }
     290             :         else
     291           0 :             report_untranslatable_char(PG_BIG5, PG_MULE_INTERNAL,
     292             :                                        (const char *) big5, len);
     293           0 :         big5 += l;
     294           0 :         len -= l;
     295             :     }
     296           8 :     *p = '\0';
     297           8 : }
     298             : 
     299             : /*
     300             :  * MIC ---> Big5
     301             :  */
     302             : static void
     303           8 : mic2big5(const unsigned char *mic, unsigned char *p, int len)
     304             : {
     305             :     unsigned short c1;
     306             :     unsigned short big5buf,
     307             :                 cnsBuf;
     308             :     int         l;
     309             : 
     310          40 :     while (len > 0)
     311             :     {
     312          24 :         c1 = *mic;
     313          24 :         if (!IS_HIGHBIT_SET(c1))
     314             :         {
     315             :             /* ASCII */
     316          24 :             if (c1 == 0)
     317           0 :                 report_invalid_encoding(PG_MULE_INTERNAL,
     318             :                                         (const char *) mic, len);
     319          24 :             *p++ = c1;
     320          24 :             mic++;
     321          24 :             len--;
     322          24 :             continue;
     323             :         }
     324           0 :         l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
     325           0 :         if (l < 0)
     326           0 :             report_invalid_encoding(PG_MULE_INTERNAL,
     327             :                                     (const char *) mic, len);
     328           0 :         if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == LCPRV2_B)
     329             :         {
     330           0 :             if (c1 == LCPRV2_B)
     331             :             {
     332           0 :                 c1 = mic[1];    /* get plane no. */
     333           0 :                 cnsBuf = (mic[2] << 8) | mic[3];
     334             :             }
     335             :             else
     336             :             {
     337           0 :                 cnsBuf = (mic[1] << 8) | mic[2];
     338             :             }
     339           0 :             big5buf = CNStoBIG5(cnsBuf, c1);
     340           0 :             if (big5buf == 0)
     341           0 :                 report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
     342             :                                            (const char *) mic, len);
     343           0 :             *p++ = (big5buf >> 8) & 0x00ff;
     344           0 :             *p++ = big5buf & 0x00ff;
     345             :         }
     346             :         else
     347           0 :             report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
     348             :                                        (const char *) mic, len);
     349           0 :         mic += l;
     350           0 :         len -= l;
     351             :     }
     352           8 :     *p = '\0';
     353           8 : }

Generated by: LCOV version 1.13