LCOV - code coverage report
Current view: top level - src/backend/utils/mb/conversion_procs/euc2004_sjis2004 - euc2004_sjis2004.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 40.4 % 183 74
Test Date: 2026-03-07 10:14:53 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  *    EUC_JIS_2004, SHIFT_JIS_2004
       4              :  *
       5              :  * Copyright (c) 2007-2026, 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            6 : PG_MODULE_MAGIC_EXT(
      18              :                     .name = "euc2004_sjis2004",
      19              :                     .version = PG_VERSION
      20              : );
      21              : 
      22            3 : PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004);
      23            6 : 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            3 : euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)
      44              : {
      45            3 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      46            3 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      47            3 :     int         len = PG_GETARG_INT32(4);
      48            3 :     bool        noError = PG_GETARG_BOOL(5);
      49              :     int         converted;
      50              : 
      51            3 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JIS_2004, PG_SHIFT_JIS_2004);
      52              : 
      53            3 :     converted = euc_jis_20042shift_jis_2004(src, dest, len, noError);
      54              : 
      55            3 :     PG_RETURN_INT32(converted);
      56              : }
      57              : 
      58              : Datum
      59          129 : shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)
      60              : {
      61          129 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      62          129 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      63          129 :     int         len = PG_GETARG_INT32(4);
      64          129 :     bool        noError = PG_GETARG_BOOL(5);
      65              :     int         converted;
      66              : 
      67          129 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SHIFT_JIS_2004, PG_EUC_JIS_2004);
      68              : 
      69          129 :     converted = shift_jis_20042euc_jis_2004(src, dest, len, noError);
      70              : 
      71           84 :     PG_RETURN_INT32(converted);
      72              : }
      73              : 
      74              : /*
      75              :  * EUC_JIS_2004 -> SHIFT_JIS_2004
      76              :  */
      77              : static int
      78            3 : euc_jis_20042shift_jis_2004(const unsigned char *euc, unsigned char *p, int len, bool noError)
      79              : {
      80            3 :     const unsigned char *start = euc;
      81              :     int         c1,
      82              :                 ku,
      83              :                 ten;
      84              :     int         l;
      85              : 
      86           12 :     while (len > 0)
      87              :     {
      88            9 :         c1 = *euc;
      89            9 :         if (!IS_HIGHBIT_SET(c1))
      90              :         {
      91              :             /* ASCII */
      92            9 :             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            9 :             *p++ = c1;
     100            9 :             euc++;
     101            9 :             len--;
     102            9 :             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            3 :     *p = '\0';
     215              : 
     216            3 :     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           63 : get_ten(int b, int *ku)
     226              : {
     227              :     int         ten;
     228              : 
     229           63 :     if (b >= 0x40 && b <= 0x7e)
     230              :     {
     231            0 :         ten = b - 0x3f;
     232            0 :         *ku = 1;
     233              :     }
     234           63 :     else if (b >= 0x80 && b <= 0x9e)
     235              :     {
     236            0 :         ten = b - 0x40;
     237            0 :         *ku = 1;
     238              :     }
     239           63 :     else if (b >= 0x9f && b <= 0xfc)
     240              :     {
     241           63 :         ten = b - 0x9e;
     242           63 :         *ku = 0;
     243              :     }
     244              :     else
     245              :     {
     246            0 :         ten = -1;               /* error */
     247            0 :         *ku = 0;                /* keep compiler quiet */
     248              :     }
     249           63 :     return ten;
     250              : }
     251              : 
     252              : /*
     253              :  * SHIFT_JIS_2004 ---> EUC_JIS_2004
     254              :  */
     255              : 
     256              : static int
     257          129 : shift_jis_20042euc_jis_2004(const unsigned char *sjis, unsigned char *p, int len, bool noError)
     258              : {
     259          129 :     const unsigned char *start = sjis;
     260              :     int         c1;
     261              :     int         ku,
     262              :                 ten,
     263              :                 kubun;
     264              :     int         plane;
     265              :     int         l;
     266              : 
     267          579 :     while (len > 0)
     268              :     {
     269          540 :         c1 = *sjis;
     270              : 
     271          540 :         if (!IS_HIGHBIT_SET(c1))
     272              :         {
     273              :             /* ASCII */
     274          423 :             if (c1 == 0)
     275              :             {
     276           36 :                 if (noError)
     277           18 :                     break;
     278           18 :                 report_invalid_encoding(PG_SHIFT_JIS_2004,
     279              :                                         (const char *) sjis, len);
     280              :             }
     281          387 :             *p++ = c1;
     282          387 :             sjis++;
     283          387 :             len--;
     284          387 :             continue;
     285              :         }
     286              : 
     287          117 :         l = pg_encoding_verifymbchar(PG_SHIFT_JIS_2004, (const char *) sjis, len);
     288              : 
     289          117 :         if (l < 0 || l > len)
     290              :         {
     291           54 :             if (noError)
     292           27 :                 break;
     293           27 :             report_invalid_encoding(PG_SHIFT_JIS_2004,
     294              :                                     (const char *) sjis, len);
     295              :         }
     296              : 
     297           63 :         if (c1 >= 0xa1 && c1 <= 0xdf && l == 1)
     298              :         {
     299              :             /* JIS X0201 (1 byte kana) */
     300            0 :             *p++ = SS2;
     301            0 :             *p++ = c1;
     302              :         }
     303           63 :         else if (l == 2)
     304              :         {
     305           63 :             int         c2 = sjis[1];
     306              : 
     307           63 :             plane = 1;
     308           63 :             ku = 1;
     309           63 :             ten = 1;
     310              : 
     311              :             /*
     312              :              * JIS X 0213
     313              :              */
     314           63 :             if (c1 >= 0x81 && c1 <= 0x9f) /* plane 1 1ku-62ku */
     315              :             {
     316           63 :                 ku = (c1 << 1) - 0x100;
     317           63 :                 ten = get_ten(c2, &kubun);
     318           63 :                 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           63 :                 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           63 :             if (plane == 2)
     393            0 :                 *p++ = SS3;
     394              : 
     395           63 :             *p++ = ku + 0xa0;
     396           63 :             *p++ = ten + 0xa0;
     397              :         }
     398           63 :         sjis += l;
     399           63 :         len -= l;
     400              :     }
     401           84 :     *p = '\0';
     402              : 
     403           84 :     return sjis - start;
     404              : }
        

Generated by: LCOV version 2.0-1