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 20devel Lines: 32.3 % 133 43
Test Date: 2026-07-25 22:15:46 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 8.5 % 94 8

             Branch data     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