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

Generated by: LCOV version 1.14