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 17devel Lines: 74 183 40.4 %
Date: 2024-04-26 20:11:02 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  *    EUC_JIS_2004, SHIFT_JIS_2004
       4             :  *
       5             :  * Copyright (c) 2007-2024, 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          12 : PG_MODULE_MAGIC;
      18             : 
      19           6 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
      20          12 : PG_FUNCTION_INFO_V1(shift_jis_2004_to_euc_jis_2004);
      21             : 
      22             : static int  euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError);
      23             : static int  shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError);
      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             :  *      BOOL        -- if true, don't throw an error if conversion fails
      33             :  * ) returns INTEGER;
      34             :  *
      35             :  * Returns the number of bytes successfully converted.
      36             :  * ----------
      37             :  */
      38             : 
      39             : Datum
      40           6 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
      41             : {
      42           6 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      43           6 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      44           6 :     int         len = PG_GETARG_INT32(4);
      45           6 :     bool        noError = PG_GETARG_BOOL(5);
      46             :     int         converted;
      47             : 
      48           6 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
      49             : 
      50           6 :     converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
      51             : 
      52           6 :     PG_RETURN_INT32(converted);
      53             : }
      54             : 
      55             : Datum
      56         258 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
      57             : {
      58         258 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      59         258 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      60         258 :     int         len = PG_GETARG_INT32(4);
      61         258 :     bool        noError = PG_GETARG_BOOL(5);
      62             :     int         converted;
      63             : 
      64         258 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
      65             : 
      66         258 :     converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
      67             : 
      68         168 :     PG_RETURN_INT32(converted);
      69             : }
      70             : 
      71             : /*
      72             :  * EUC_JIS_2004 -> SHIFT_JIS_2004
      73             :  */
      74             : static int
      75           6 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
      76             : {
      77           6 :     const unsigned char *start = euc;
      78             :     int         c1,
      79             :                 ku,
      80             :                 ten;
      81             :     int         l;
      82             : 
      83          24 :     while (len > 0)
      84             :     {
      85          18 :         c1 = *euc;
      86          18 :         if (!IS_HIGHBIT_SET(c1))
      87             :         {
      88             :             /* ASCII */
      89          18 :             if (c1 == 0)
      90             :             {
      91           0 :                 if (noError)
      92           0 :                     break;
      93           0 :                 report_invalid_encoding(PG_EUC_JIS_2004,
      94             :                                         (const char *) euc, len);
      95             :             }
      96          18 :             *p++ = c1;
      97          18 :             euc++;
      98          18 :             len--;
      99          18 :             continue;
     100             :         }
     101             : 
     102           0 :         l = pg_encoding_verifymbchar(PG_EUC_JIS_2004, (const char *) euc, len);
     103             : 
     104           0 :         if (l < 0)
     105             :         {
     106           0 :             if (noError)
     107           0 :                 break;
     108           0 :             report_invalid_encoding(PG_EUC_JIS_2004,
     109             :                                     (const char *) euc, len);
     110             :         }
     111             : 
     112           0 :         if (c1 == SS2 && l == 2)    /* JIS X 0201 kana? */
     113             :         {
     114           0 :             *p++ = euc[1];
     115             :         }
     116           0 :         else if (c1 == SS3 && l == 3)   /* JIS X 0213 plane 2? */
     117             :         {
     118           0 :             ku = euc[1] - 0xa0;
     119           0 :             ten = euc[2] - 0xa0;
     120             : 
     121           0 :             switch (ku)
     122             :             {
     123           0 :                 case 1:
     124             :                 case 3:
     125             :                 case 4:
     126             :                 case 5:
     127             :                 case 8:
     128             :                 case 12:
     129             :                 case 13:
     130             :                 case 14:
     131             :                 case 15:
     132           0 :                     *p++ = ((ku + 0x1df) >> 1) - (ku >> 3) * 3;
     133           0 :                     break;
     134           0 :                 default:
     135           0 :                     if (ku >= 78 && ku <= 94)
     136             :                     {
     137           0 :                         *p++ = (ku + 0x19b) >> 1;
     138             :                     }
     139             :                     else
     140             :                     {
     141           0 :                         if (noError)
     142           0 :                             break;
     143           0 :                         report_invalid_encoding(PG_EUC_JIS_2004,
     144             :                                                 (const char *) euc, len);
     145             :                     }
     146             :             }
     147             : 
     148           0 :             if (ku % 2)
     149             :             {
     150           0 :                 if (ten >= 1 && ten <= 63)
     151           0 :                     *p++ = ten + 0x3f;
     152           0 :                 else if (ten >= 64 && ten <= 94)
     153           0 :                     *p++ = ten + 0x40;
     154             :                 else
     155             :                 {
     156           0 :                     if (noError)
     157           0 :                         break;
     158           0 :                     report_invalid_encoding(PG_EUC_JIS_2004,
     159             :                                             (const char *) euc, len);
     160             :                 }
     161             :             }
     162             :             else
     163           0 :                 *p++ = ten + 0x9e;
     164             :         }
     165             : 
     166           0 :         else if (l == 2)        /* JIS X 0213 plane 1? */
     167             :         {
     168           0 :             ku = c1 - 0xa0;
     169           0 :             ten = euc[1] - 0xa0;
     170             : 
     171           0 :             if (ku >= 1 && ku <= 62)
     172           0 :                 *p++ = (ku + 0x101) >> 1;
     173           0 :             else if (ku >= 63 && ku <= 94)
     174           0 :                 *p++ = (ku + 0x181) >> 1;
     175             :             else
     176             :             {
     177           0 :                 if (noError)
     178           0 :                     break;
     179           0 :                 report_invalid_encoding(PG_EUC_JIS_2004,
     180             :                                         (const char *) euc, len);
     181             :             }
     182             : 
     183           0 :             if (ku % 2)
     184             :             {
     185           0 :                 if (ten >= 1 && ten <= 63)
     186           0 :                     *p++ = ten + 0x3f;
     187           0 :                 else if (ten >= 64 && ten <= 94)
     188           0 :                     *p++ = ten + 0x40;
     189             :                 else
     190             :                 {
     191           0 :                     if (noError)
     192           0 :                         break;
     193           0 :                     report_invalid_encoding(PG_EUC_JIS_2004,
     194             :                                             (const char *) euc, len);
     195             :                 }
     196             :             }
     197             :             else
     198           0 :                 *p++ = ten + 0x9e;
     199             :         }
     200             :         else
     201             :         {
     202           0 :             if (noError)
     203           0 :                 break;
     204           0 :             report_invalid_encoding(PG_EUC_JIS_2004,
     205             :                                     (const char *) euc, len);
     206             :         }
     207             : 
     208           0 :         euc += l;
     209           0 :         len -= l;
     210             :     }
     211           6 :     *p = '\0';
     212             : 
     213           6 :     return euc - start;
     214             : }
     215             : 
     216             : /*
     217             :  * returns SHIFT_JIS_2004 "ku" code indicated by second byte
     218             :  * *ku = 0: "ku" = even
     219             :  * *ku = 1: "ku" = odd
     220             :  */
     221             : static int
     222         126 : get_ten(int b, int *ku)
     223             : {
     224             :     int         ten;
     225             : 
     226         126 :     if (b >= 0x40 && b <= 0x7e)
     227             :     {
     228           0 :         ten = b - 0x3f;
     229           0 :         *ku = 1;
     230             :     }
     231         126 :     else if (b >= 0x80 && b <= 0x9e)
     232             :     {
     233           0 :         ten = b - 0x40;
     234           0 :         *ku = 1;
     235             :     }
     236         126 :     else if (b >= 0x9f && b <= 0xfc)
     237             :     {
     238         126 :         ten = b - 0x9e;
     239         126 :         *ku = 0;
     240             :     }
     241             :     else
     242             :     {
     243           0 :         ten = -1;               /* error */
     244           0 :         *ku = 0;                /* keep compiler quiet */
     245             :     }
     246         126 :     return ten;
     247             : }
     248             : 
     249             : /*
     250             :  * SHIFT_JIS_2004 ---> EUC_JIS_2004
     251             :  */
     252             : 
     253             : static int
     254         258 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
     255             : {
     256         258 :     const unsigned char *start = sjis;
     257             :     int         c1;
     258             :     int         ku,
     259             :                 ten,
     260             :                 kubun;
     261             :     int         plane;
     262             :     int         l;
     263             : 
     264        1158 :     while (len > 0)
     265             :     {
     266        1080 :         c1 = *sjis;
     267             : 
     268        1080 :         if (!IS_HIGHBIT_SET(c1))
     269             :         {
     270             :             /* ASCII */
     271         846 :             if (c1 == 0)
     272             :             {
     273          72 :                 if (noError)
     274          36 :                     break;
     275          36 :                 report_invalid_encoding(PG_SHIFT_JIS_2004,
     276             :                                         (const char *) sjis, len);
     277             :             }
     278         774 :             *p++ = c1;
     279         774 :             sjis++;
     280         774 :             len--;
     281         774 :             continue;
     282             :         }
     283             : 
     284         234 :         l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
     285             : 
     286         234 :         if (l < 0 || l > len)
     287             :         {
     288         108 :             if (noError)
     289          54 :                 break;
     290          54 :             report_invalid_encoding(PG_SHIFT_JIS_2004,
     291             :                                     (const char *) sjis, len);
     292             :         }
     293             : 
     294         126 :         if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
     295             :         {
     296             :             /* JIS X0201 (1 byte kana) */
     297           0 :             *p++ = SS2;
     298           0 :             *p++ = c1;
     299             :         }
     300         126 :         else if (l == 2)
     301             :         {
     302         126 :             int         c2 = sjis[1];
     303             : 
     304         126 :             plane = 1;
     305         126 :             ku = 1;
     306         126 :             ten = 1;
     307             : 
     308             :             /*
     309             :              * JIS X 0213
     310             :              */
     311         126 :             if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
     312             :             {
     313         126 :                 ku = (c1 << 1) - 0x100;
     314         126 :                 ten = get_ten(c2, &kubun);
     315         126 :                 if (ten < 0)
     316             :                 {
     317           0 :                     if (noError)
     318           0 :                         break;
     319           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     320             :                                             (const char *) sjis, len);
     321             :                 }
     322         126 :                 ku -= kubun;
     323             :             }
     324           0 :             else if (c1 >= 0xe0 && c1 <= 0xef)    /* plane 1 62ku-94ku */
     325             :             {
     326           0 :                 ku = (c1 << 1) - 0x180;
     327           0 :                 ten = get_ten(c2, &kubun);
     328           0 :                 if (ten < 0)
     329             :                 {
     330           0 :                     if (noError)
     331           0 :                         break;
     332           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     333             :                                             (const char *) sjis, len);
     334             :                 }
     335           0 :                 ku -= kubun;
     336             :             }
     337           0 :             else if (c1 >= 0xf0 && c1 <= 0xf3)    /* plane 2
     338             :                                                  * 1,3,4,5,8,12,13,14,15 ku */
     339             :             {
     340           0 :                 plane = 2;
     341           0 :                 ten = get_ten(c2, &kubun);
     342           0 :                 if (ten < 0)
     343             :                 {
     344           0 :                     if (noError)
     345           0 :                         break;
     346           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     347             :                                             (const char *) sjis, len);
     348             :                 }
     349           0 :                 switch (c1)
     350             :                 {
     351           0 :                     case 0xf0:
     352           0 :                         ku = kubun == 0 ? 8 : 1;
     353           0 :                         break;
     354           0 :                     case 0xf1:
     355           0 :                         ku = kubun == 0 ? 4 : 3;
     356           0 :                         break;
     357           0 :                     case 0xf2:
     358           0 :                         ku = kubun == 0 ? 12 : 5;
     359           0 :                         break;
     360           0 :                     default:
     361           0 :                         ku = kubun == 0 ? 14 : 13;
     362           0 :                         break;
     363             :                 }
     364             :             }
     365           0 :             else if (c1 >= 0xf4 && c1 <= 0xfc)    /* plane 2 78-94ku */
     366             :             {
     367           0 :                 plane = 2;
     368           0 :                 ten = get_ten(c2, &kubun);
     369           0 :                 if (ten < 0)
     370             :                 {
     371           0 :                     if (noError)
     372           0 :                         break;
     373           0 :                     report_invalid_encoding(PG_SHIFT_JIS_2004,
     374             :                                             (const char *) sjis, len);
     375             :                 }
     376           0 :                 if (c1 == 0xf4 && kubun == 1)
     377           0 :                     ku = 15;
     378             :                 else
     379           0 :                     ku = (c1 << 1) - 0x19a - kubun;
     380             :             }
     381             :             else
     382             :             {
     383           0 :                 if (noError)
     384           0 :                     break;
     385           0 :                 report_invalid_encoding(PG_SHIFT_JIS_2004,
     386             :                                         (const char *) sjis, len);
     387             :             }
     388             : 
     389         126 :             if (plane == 2)
     390           0 :                 *p++ = SS3;
     391             : 
     392         126 :             *p++ = ku + 0xa0;
     393         126 :             *p++ = ten + 0xa0;
     394             :         }
     395         126 :         sjis += l;
     396         126 :         len -= l;
     397             :     }
     398         168 :     *p = '\0';
     399             : 
     400         168 :     return sjis - start;
     401             : }

Generated by: LCOV version 1.14