LCOV - code coverage report
Current view: top level - src/backend/utils/mb/conversion_procs/euc2004_sjis2004 - euc2004_sjis2004.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 39 146 26.7 %
Date: 2019-11-21 13:06:38 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  *    EUC_JIS_2004, SHIFT_JIS_2004
       4             :  *
       5             :  * Copyright (c) 2007-2019, PostgreSQL Global Development Group
       6             :  *
       7             :  * IDENTIFICATION
       8             :  *    src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c
       9             :  *
      10             :  *-------------------------------------------------------------------------
      11             :  */
      12             : 
      13             : #include "postgres.h"
      14             : #include "fmgr.h"
      15             : #include "mb/pg_wchar.h"
      16             : 
      17           4 : PG_MODULE_MAGIC;
      18             : 
      19           4 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
      20           4 : PG_FUNCTION_INFO_V1(shift_jis_2004_to_euc_jis_2004);
      21             : 
      22             : static void euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len);
      23             : static void shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len);
      24             : 
      25             : /* ----------
      26             :  * conv_proc(
      27             :  *      INTEGER,    -- source encoding id
      28             :  *      INTEGER,    -- destination encoding id
      29             :  *      CSTRING,    -- source string (null terminated C string)
      30             :  *      CSTRING,    -- destination string (null terminated C string)
      31             :  *      INTEGER     -- source string length
      32             :  * ) returns VOID;
      33             :  * ----------
      34             :  */
      35             : 
      36             : Datum
      37           4 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
      38             : {
      39           4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      40           4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      41           4 :     int         len = PG_GETARG_INT32(4);
      42             : 
      43           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
      44             : 
      45           4 :     euc_jis_20042shift_jis_2004(src, dest, len);
      46             : 
      47           4 :     PG_RETURN_VOID();
      48             : }
      49             : 
      50             : Datum
      51           4 : shift_jis_2004_to_euc_jis_2004(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             : 
      57           4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
      58             : 
      59           4 :     shift_jis_20042euc_jis_2004(src, dest, len);
      60             : 
      61           4 :     PG_RETURN_VOID();
      62             : }
      63             : 
      64             : /*
      65             :  * EUC_JIS_2004 -> SHIFT_JIS_2004
      66             :  */
      67             : static void
      68           4 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len)
      69             : {
      70             :     int         c1,
      71             :                 ku,
      72             :                 ten;
      73             :     int         l;
      74             : 
      75          20 :     while (len > 0)
      76             :     {
      77          12 :         c1 = *euc;
      78          12 :         if (!IS_HIGHBIT_SET(c1))
      79             :         {
      80             :             /* ASCII */
      81          12 :             if (c1 == 0)
      82           0 :                 report_invalid_encoding(PG_EUC_JIS_2004,
      83             :                                         (const char *) euc, len);
      84          12 :             *p++ = c1;
      85          12 :             euc++;
      86          12 :             len--;
      87          12 :             continue;
      88             :         }
      89             : 
      90           0 :         l = pg_encoding_verifymb(PG_EUC_JIS_2004, (const char *) euc, len);
      91             : 
      92           0 :         if (l < 0)
      93           0 :             report_invalid_encoding(PG_EUC_JIS_2004,
      94             :                                     (const char *) euc, len);
      95             : 
      96           0 :         if (c1 == SS2 && l == 2)    /* JIS X 0201 kana? */
      97             :         {
      98           0 :             *p++ = euc[1];
      99             :         }
     100           0 :         else if (c1 == SS3 && l == 3)   /* JIS X 0213 plane 2? */
     101             :         {
     102           0 :             ku = euc[1] - 0xa0;
     103           0 :             ten = euc[2] - 0xa0;
     104             : 
     105           0 :             switch (ku)
     106             :             {
     107             :                 case 1:
     108             :                 case 3:
     109             :                 case 4:
     110             :                 case 5:
     111             :                 case 8:
     112             :                 case 12:
     113             :                 case 13:
     114             :                 case 14:
     115             :                 case 15:
     116           0 :                     *p++ = ((ku + 0x1df) >> 1) - (ku >> 3) * 3;
     117           0 :                     break;
     118             :                 default:
     119           0 :                     if (ku >= 78 && ku <= 94)
     120             :                     {
     121           0 :                         *p++ = (ku + 0x19b) >> 1;
     122             :                     }
     123             :                     else
     124           0 :                         report_invalid_encoding(PG_EUC_JIS_2004,
     125             :                                                 (const char *) euc, len);
     126             :             }
     127             : 
     128           0 :             if (ku % 2)
     129             :             {
     130           0 :                 if (ten >= 1 && ten <= 63)
     131           0 :                     *p++ = ten + 0x3f;
     132           0 :                 else if (ten >= 64 && ten <= 94)
     133           0 :                     *p++ = ten + 0x40;
     134             :                 else
     135           0 :                     report_invalid_encoding(PG_EUC_JIS_2004,
     136             :                                             (const char *) euc, len);
     137             :             }
     138             :             else
     139           0 :                 *p++ = ten + 0x9e;
     140             :         }
     141             : 
     142           0 :         else if (l == 2)        /* JIS X 0213 plane 1? */
     143             :         {
     144           0 :             ku = c1 - 0xa0;
     145           0 :             ten = euc[1] - 0xa0;
     146             : 
     147           0 :             if (ku >= 1 && ku <= 62)
     148           0 :                 *p++ = (ku + 0x101) >> 1;
     149           0 :             else if (ku >= 63 && ku <= 94)
     150           0 :                 *p++ = (ku + 0x181) >> 1;
     151             :             else
     152           0 :                 report_invalid_encoding(PG_EUC_JIS_2004,
     153             :                                         (const char *) euc, len);
     154             : 
     155           0 :             if (ku % 2)
     156             :             {
     157           0 :                 if (ten >= 1 && ten <= 63)
     158           0 :                     *p++ = ten + 0x3f;
     159           0 :                 else if (ten >= 64 && ten <= 94)
     160           0 :                     *p++ = ten + 0x40;
     161             :                 else
     162           0 :                     report_invalid_encoding(PG_EUC_JIS_2004,
     163             :                                             (const char *) euc, len);
     164             :             }
     165             :             else
     166           0 :                 *p++ = ten + 0x9e;
     167             :         }
     168             :         else
     169           0 :             report_invalid_encoding(PG_EUC_JIS_2004,
     170             :                                     (const char *) euc, len);
     171             : 
     172           0 :         euc += l;
     173           0 :         len -= l;
     174             :     }
     175           4 :     *p = '\0';
     176           4 : }
     177             : 
     178             : /*
     179             :  * returns SHIFT_JIS_2004 "ku" code indicated by second byte
     180             :  * *ku = 0: "ku" = even
     181             :  * *ku = 1: "ku" = odd
     182             :  */
     183             : static int
     184           0 : get_ten(int b, int *ku)
     185             : {
     186             :     int         ten;
     187             : 
     188           0 :     if (b >= 0x40 && b <= 0x7e)
     189             :     {
     190           0 :         ten = b - 0x3f;
     191           0 :         *ku = 1;
     192             :     }
     193           0 :     else if (b >= 0x80 && b <= 0x9e)
     194             :     {
     195           0 :         ten = b - 0x40;
     196           0 :         *ku = 1;
     197             :     }
     198           0 :     else if (b >= 0x9f && b <= 0xfc)
     199             :     {
     200           0 :         ten = b - 0x9e;
     201           0 :         *ku = 0;
     202             :     }
     203             :     else
     204             :     {
     205           0 :         ten = -1;               /* error */
     206           0 :         *ku = 0;                /* keep compiler quiet */
     207             :     }
     208           0 :     return ten;
     209             : }
     210             : 
     211             : /*
     212             :  * SHIFT_JIS_2004 ---> EUC_JIS_2004
     213             :  */
     214             : 
     215             : static void
     216           4 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len)
     217             : {
     218             :     int         c1;
     219             :     int         ku,
     220             :                 ten,
     221             :                 kubun;
     222             :     int         plane;
     223             :     int         l;
     224             : 
     225          20 :     while (len > 0)
     226             :     {
     227          12 :         c1 = *sjis;
     228             : 
     229          12 :         if (!IS_HIGHBIT_SET(c1))
     230             :         {
     231             :             /* ASCII */
     232          12 :             if (c1 == 0)
     233           0 :                 report_invalid_encoding(PG_SHIFT_JIS_2004,
     234             :                                         (const char *) sjis, len);
     235          12 :             *p++ = c1;
     236          12 :             sjis++;
     237          12 :             len--;
     238          12 :             continue;
     239             :         }
     240             : 
     241           0 :         l = pg_encoding_verifymb(PG_SHIFT_JIS_2004, (const char *) sjis, len);
     242             : 
     243           0 :         if (l < 0 || l > len)
     244           0 :             report_invalid_encoding(PG_SHIFT_JIS_2004,
     245             :                                     (const char *) sjis, len);
     246             : 
     247           0 :         if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
     248             :         {
     249             :             /* JIS X0201 (1 byte kana) */
     250           0 :             *p++ = SS2;
     251           0 :             *p++ = c1;
     252             :         }
     253           0 :         else if (l == 2)
     254             :         {
     255           0 :             int         c2 = sjis[1];
     256             : 
     257           0 :             plane = 1;
     258           0 :             ku = 1;
     259           0 :             ten = 1;
     260             : 
     261             :             /*
     262             :              * JIS X 0213
     263             :              */
     264           0 :             if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
     265             :             {
     266           0 :                 ku = (c1 << 1) - 0x100;
     267           0 :                 ten = get_ten(c2, &kubun);
     268           0 :                 if (ten < 0)
     269           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     270             :                                             (const char *) sjis, len);
     271           0 :                 ku -= kubun;
     272             :             }
     273           0 :             else if (c1 >= 0xe0 && c1 <= 0xef)    /* plane 1 62ku-94ku */
     274             :             {
     275           0 :                 ku = (c1 << 1) - 0x180;
     276           0 :                 ten = get_ten(c2, &kubun);
     277           0 :                 if (ten < 0)
     278           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     279             : 
     280             :                                             (const char *) sjis, len);
     281           0 :                 ku -= kubun;
     282             :             }
     283           0 :             else if (c1 >= 0xf0 && c1 <= 0xf3)    /* plane 2
     284             :                                                  * 1,3,4,5,8,12,13,14,15 ku */
     285             :             {
     286           0 :                 plane = 2;
     287           0 :                 ten = get_ten(c2, &kubun);
     288           0 :                 if (ten < 0)
     289           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     290             :                                             (const char *) sjis, len);
     291           0 :                 switch (c1)
     292             :                 {
     293             :                     case 0xf0:
     294           0 :                         ku = kubun == 0 ? 8 : 1;
     295           0 :                         break;
     296             :                     case 0xf1:
     297           0 :                         ku = kubun == 0 ? 4 : 3;
     298           0 :                         break;
     299             :                     case 0xf2:
     300           0 :                         ku = kubun == 0 ? 12 : 5;
     301           0 :                         break;
     302             :                     default:
     303           0 :                         ku = kubun == 0 ? 14 : 13;
     304           0 :                         break;
     305             :                 }
     306           0 :             }
     307           0 :             else if (c1 >= 0xf4 && c1 <= 0xfc)    /* plane 2 78-94ku */
     308             :             {
     309           0 :                 plane = 2;
     310           0 :                 ten = get_ten(c2, &kubun);
     311           0 :                 if (ten < 0)
     312           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     313             :                                             (const char *) sjis, len);
     314           0 :                 if (c1 == 0xf4 && kubun == 1)
     315           0 :                     ku = 15;
     316             :                 else
     317           0 :                     ku = (c1 << 1) - 0x19a - kubun;
     318             :             }
     319             :             else
     320           0 :                 report_invalid_encoding(PG_SHIFT_JIS_2004,
     321             :                                         (const char *) sjis, len);
     322             : 
     323           0 :             if (plane == 2)
     324           0 :                 *p++ = SS3;
     325             : 
     326           0 :             *p++ = ku + 0xa0;
     327           0 :             *p++ = ten + 0xa0;
     328             :         }
     329           0 :         sjis += l;
     330           0 :         len -= l;
     331             :     }
     332           4 :     *p = '\0';
     333           4 : }

Generated by: LCOV version 1.13