LCOV - code coverage report
Current view: top level - src/backend/utils/mb/conversion_procs/euc_jp_and_sjis - euc_jp_and_sjis.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 32.3 % 133 43
Test Date: 2026-04-18 18:16:24 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  *    EUC_JP and SJIS
       4              :  *
       5              :  * Portions Copyright (c) 1996-2026, 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_jp_and_sjis/euc_jp_and_sjis.c
      10              :  *
      11              :  *-------------------------------------------------------------------------
      12              :  */
      13              : 
      14              : #include "postgres.h"
      15              : #include "fmgr.h"
      16              : #include "mb/pg_wchar.h"
      17              : 
      18              : /*
      19              :  * SJIS alternative code.
      20              :  * this code is used if a mapping EUC -> SJIS is not defined.
      21              :  */
      22              : #define PGSJISALTCODE 0x81ac
      23              : #define PGEUCALTCODE 0xa2ae
      24              : 
      25              : /*
      26              :  * conversion table between SJIS UDC (IBM kanji) and EUC_JP
      27              :  */
      28              : #include "sjis.map"
      29              : 
      30            4 : PG_MODULE_MAGIC_EXT(
      31              :                     .name = "euc_jp_and_sjis",
      32              :                     .version = PG_VERSION
      33              : );
      34              : 
      35            4 : PG_FUNCTION_INFO_V1(euc_jp_to_sjis);
      36            4 : PG_FUNCTION_INFO_V1(sjis_to_euc_jp);
      37              : 
      38              : /* ----------
      39              :  * conv_proc(
      40              :  *      INTEGER,    -- source encoding id
      41              :  *      INTEGER,    -- destination encoding id
      42              :  *      CSTRING,    -- source string (null terminated C string)
      43              :  *      CSTRING,    -- destination string (null terminated C string)
      44              :  *      INTEGER,    -- source string length
      45              :  *      BOOL        -- if true, don't throw an error if conversion fails
      46              :  * ) returns INTEGER;
      47              :  *
      48              :  * Returns the number of bytes successfully converted.
      49              :  * ----------
      50              :  */
      51              : 
      52              : static int  euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len, bool noError);
      53              : static int  sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len, bool noError);
      54              : 
      55              : Datum
      56            4 : euc_jp_to_sjis(PG_FUNCTION_ARGS)
      57              : {
      58            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      59            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      60            4 :     int         len = PG_GETARG_INT32(4);
      61            4 :     bool        noError = PG_GETARG_BOOL(5);
      62              :     int         converted;
      63              : 
      64            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_EUC_JP, PG_SJIS);
      65              : 
      66            4 :     converted = euc_jp2sjis(src, dest, len, noError);
      67              : 
      68            4 :     PG_RETURN_INT32(converted);
      69              : }
      70              : 
      71              : Datum
      72            4 : sjis_to_euc_jp(PG_FUNCTION_ARGS)
      73              : {
      74            4 :     unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
      75            4 :     unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
      76            4 :     int         len = PG_GETARG_INT32(4);
      77            4 :     bool        noError = PG_GETARG_BOOL(5);
      78              :     int         converted;
      79              : 
      80            4 :     CHECK_ENCODING_CONVERSION_ARGS(PG_SJIS, PG_EUC_JP);
      81              : 
      82            4 :     converted = sjis2euc_jp(src, dest, len, noError);
      83              : 
      84            4 :     PG_RETURN_INT32(converted);
      85              : }
      86              : 
      87              : /*
      88              :  * EUC_JP -> SJIS
      89              :  */
      90              : static int
      91            4 : euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len, bool noError)
      92              : {
      93            4 :     const unsigned char *start = euc;
      94              :     int         c1,
      95              :                 c2,
      96              :                 k;
      97              :     int         l;
      98              : 
      99           16 :     while (len > 0)
     100              :     {
     101           12 :         c1 = *euc;
     102           12 :         if (!IS_HIGHBIT_SET(c1))
     103              :         {
     104              :             /* ASCII */
     105           12 :             if (c1 == 0)
     106              :             {
     107            0 :                 if (noError)
     108            0 :                     break;
     109            0 :                 report_invalid_encoding(PG_EUC_JP,
     110              :                                         (const char *) euc, len);
     111              :             }
     112           12 :             *p++ = c1;
     113           12 :             euc++;
     114           12 :             len--;
     115           12 :             continue;
     116              :         }
     117            0 :         l = pg_encoding_verifymbchar(PG_EUC_JP, (const char *) euc, len);
     118            0 :         if (l < 0)
     119              :         {
     120            0 :             if (noError)
     121            0 :                 break;
     122            0 :             report_invalid_encoding(PG_EUC_JP,
     123              :                                     (const char *) euc, len);
     124              :         }
     125            0 :         if (c1 == SS2)
     126              :         {
     127              :             /* hankaku kana? */
     128            0 :             *p++ = euc[1];
     129              :         }
     130            0 :         else if (c1 == SS3)
     131              :         {
     132              :             /* JIS X0212 kanji? */
     133            0 :             c1 = euc[1];
     134            0 :             c2 = euc[2];
     135            0 :             k = c1 << 8 | c2;
     136            0 :             if (k >= 0xf5a1)
     137              :             {
     138              :                 /* UDC2 */
     139            0 :                 c1 -= 0x54;
     140            0 :                 *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x74;
     141            0 :                 *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
     142              :             }
     143              :             else
     144              :             {
     145              :                 int         i,
     146              :                             k2;
     147              : 
     148              :                 /* IBM kanji */
     149            0 :                 for (i = 0;; i++)
     150              :                 {
     151            0 :                     k2 = ibmkanji[i].euc & 0xffff;
     152            0 :                     if (k2 == 0xffff)
     153              :                     {
     154            0 :                         *p++ = PGSJISALTCODE >> 8;
     155            0 :                         *p++ = PGSJISALTCODE & 0xff;
     156            0 :                         break;
     157              :                     }
     158            0 :                     if (k2 == k)
     159              :                     {
     160            0 :                         k = ibmkanji[i].sjis;
     161            0 :                         *p++ = k >> 8;
     162            0 :                         *p++ = k & 0xff;
     163            0 :                         break;
     164              :                     }
     165              :                 }
     166              :             }
     167              :         }
     168              :         else
     169              :         {
     170              :             /* JIS X0208 kanji? */
     171            0 :             c2 = euc[1];
     172            0 :             k = (c1 << 8) | (c2 & 0xff);
     173            0 :             if (k >= 0xf5a1)
     174              :             {
     175              :                 /* UDC1 */
     176            0 :                 c1 -= 0x54;
     177            0 :                 *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1) + 0x6f;
     178              :             }
     179              :             else
     180            0 :                 *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1);
     181            0 :             *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
     182              :         }
     183            0 :         euc += l;
     184            0 :         len -= l;
     185              :     }
     186            4 :     *p = '\0';
     187              : 
     188            4 :     return euc - start;
     189              : }
     190              : 
     191              : /*
     192              :  * SJIS ---> EUC_JP
     193              :  */
     194              : static int
     195            4 : sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len, bool noError)
     196              : {
     197            4 :     const unsigned char *start = sjis;
     198              :     int         c1,
     199              :                 c2,
     200              :                 i,
     201              :                 k,
     202              :                 k2;
     203              :     int         l;
     204              : 
     205           16 :     while (len > 0)
     206              :     {
     207           12 :         c1 = *sjis;
     208           12 :         if (!IS_HIGHBIT_SET(c1))
     209              :         {
     210              :             /* ASCII */
     211           12 :             if (c1 == 0)
     212              :             {
     213            0 :                 if (noError)
     214            0 :                     break;
     215            0 :                 report_invalid_encoding(PG_SJIS,
     216              :                                         (const char *) sjis, len);
     217              :             }
     218           12 :             *p++ = c1;
     219           12 :             sjis++;
     220           12 :             len--;
     221           12 :             continue;
     222              :         }
     223            0 :         l = pg_encoding_verifymbchar(PG_SJIS, (const char *) sjis, len);
     224            0 :         if (l < 0)
     225              :         {
     226            0 :             if (noError)
     227            0 :                 break;
     228            0 :             report_invalid_encoding(PG_SJIS,
     229              :                                     (const char *) sjis, len);
     230              :         }
     231            0 :         if (c1 >= 0xa1 && c1 <= 0xdf)
     232              :         {
     233              :             /* JIS X0201 (1 byte kana) */
     234            0 :             *p++ = SS2;
     235            0 :             *p++ = c1;
     236              :         }
     237              :         else
     238              :         {
     239              :             /*
     240              :              * JIS X0208, X0212, user defined extended characters
     241              :              */
     242            0 :             c2 = sjis[1];
     243            0 :             k = (c1 << 8) + c2;
     244            0 :             if (k >= 0xed40 && k < 0xf040)
     245              :             {
     246              :                 /* NEC selection IBM kanji */
     247            0 :                 for (i = 0;; i++)
     248              :                 {
     249            0 :                     k2 = ibmkanji[i].nec;
     250            0 :                     if (k2 == 0xffff)
     251            0 :                         break;
     252            0 :                     if (k2 == k)
     253              :                     {
     254            0 :                         k = ibmkanji[i].sjis;
     255            0 :                         c1 = (k >> 8) & 0xff;
     256            0 :                         c2 = k & 0xff;
     257              :                     }
     258              :                 }
     259              :             }
     260              : 
     261            0 :             if (k < 0xeb3f)
     262              :             {
     263              :                 /* JIS X0208 */
     264            0 :                 *p++ = ((c1 & 0x3f) << 1) + 0x9f + (c2 > 0x9e);
     265            0 :                 *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
     266              :             }
     267            0 :             else if ((k >= 0xeb40 && k < 0xf040) || (k >= 0xfc4c && k <= 0xfcfc))
     268              :             {
     269              :                 /* NEC selection IBM kanji - Other undecided justice */
     270            0 :                 *p++ = PGEUCALTCODE >> 8;
     271            0 :                 *p++ = PGEUCALTCODE & 0xff;
     272              :             }
     273            0 :             else if (k >= 0xf040 && k < 0xf540)
     274              :             {
     275              :                 /*
     276              :                  * UDC1 mapping to X0208 85 ku - 94 ku JIS code 0x7521 -
     277              :                  * 0x7e7e EUC 0xf5a1 - 0xfefe
     278              :                  */
     279            0 :                 c1 -= 0x6f;
     280            0 :                 *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
     281            0 :                 *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
     282              :             }
     283            0 :             else if (k >= 0xf540 && k < 0xfa40)
     284              :             {
     285              :                 /*
     286              :                  * UDC2 mapping to X0212 85 ku - 94 ku JIS code 0x7521 -
     287              :                  * 0x7e7e EUC 0x8ff5a1 - 0x8ffefe
     288              :                  */
     289            0 :                 *p++ = SS3;
     290            0 :                 c1 -= 0x74;
     291            0 :                 *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
     292            0 :                 *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
     293              :             }
     294            0 :             else if (k >= 0xfa40)
     295              :             {
     296              :                 /*
     297              :                  * mapping IBM kanji to X0208 and X0212
     298              :                  *
     299              :                  */
     300            0 :                 for (i = 0;; i++)
     301              :                 {
     302            0 :                     k2 = ibmkanji[i].sjis;
     303            0 :                     if (k2 == 0xffff)
     304            0 :                         break;
     305            0 :                     if (k2 == k)
     306              :                     {
     307            0 :                         k = ibmkanji[i].euc;
     308            0 :                         if (k >= 0x8f0000)
     309              :                         {
     310            0 :                             *p++ = SS3;
     311            0 :                             *p++ = 0x80 | ((k & 0xff00) >> 8);
     312            0 :                             *p++ = 0x80 | (k & 0xff);
     313              :                         }
     314              :                         else
     315              :                         {
     316            0 :                             *p++ = 0x80 | (k >> 8);
     317            0 :                             *p++ = 0x80 | (k & 0xff);
     318              :                         }
     319              :                     }
     320              :                 }
     321              :             }
     322              :         }
     323            0 :         sjis += l;
     324            0 :         len -= l;
     325              :     }
     326            4 :     *p = '\0';
     327              : 
     328            4 :     return sjis - start;
     329              : }
        

Generated by: LCOV version 2.0-1