LCOV - code coverage report
Current view: | top level - Modules/cjkcodecs - cjkcodecs.h (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 10 | 76 | 13.2 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 2 | 6 | 33.3 %
|  |  | Branches: | 4 | 42 | 9.5 %

               Branch data     Line data    Source code
           1                 :            : /*
           2                 :            :  * cjkcodecs.h: common header for cjkcodecs
           3                 :            :  *
           4                 :            :  * Written by Hye-Shik Chang <perky@FreeBSD.org>
           5                 :            :  */
           6                 :            :
           7                 :            : #ifndef _CJKCODECS_H_
           8                 :            : #define _CJKCODECS_H_
           9                 :            :
          10                 :            : #define PY_SSIZE_T_CLEAN
          11                 :            : #include "Python.h"
          12                 :            : #include "multibytecodec.h"
          13                 :            :
          14                 :            :
          15                 :            : /* a unicode "undefined" code point */
          16                 :            : #define UNIINV  0xFFFE
          17                 :            :
          18                 :            : /* internal-use DBCS code points which aren't used by any charsets */
          19                 :            : #define NOCHAR  0xFFFF
          20                 :            : #define MULTIC  0xFFFE
          21                 :            : #define DBCINV  0xFFFD
          22                 :            :
          23                 :            : /* shorter macros to save source size of mapping tables */
          24                 :            : #define U UNIINV
          25                 :            : #define N NOCHAR
          26                 :            : #define M MULTIC
          27                 :            : #define D DBCINV
          28                 :            :
          29                 :            : struct dbcs_index {
          30                 :            :     const ucs2_t *map;
          31                 :            :     unsigned char bottom, top;
          32                 :            : };
          33                 :            : typedef struct dbcs_index decode_map;
          34                 :            :
          35                 :            : struct widedbcs_index {
          36                 :            :     const Py_UCS4 *map;
          37                 :            :     unsigned char bottom, top;
          38                 :            : };
          39                 :            : typedef struct widedbcs_index widedecode_map;
          40                 :            :
          41                 :            : struct unim_index {
          42                 :            :     const DBCHAR *map;
          43                 :            :     unsigned char bottom, top;
          44                 :            : };
          45                 :            : typedef struct unim_index encode_map;
          46                 :            :
          47                 :            : struct unim_index_bytebased {
          48                 :            :     const unsigned char *map;
          49                 :            :     unsigned char bottom, top;
          50                 :            : };
          51                 :            :
          52                 :            : struct dbcs_map {
          53                 :            :     const char *charset;
          54                 :            :     const struct unim_index *encmap;
          55                 :            :     const struct dbcs_index *decmap;
          56                 :            : };
          57                 :            :
          58                 :            : struct pair_encodemap {
          59                 :            :     Py_UCS4 uniseq;
          60                 :            :     DBCHAR code;
          61                 :            : };
          62                 :            :
          63                 :            : static const MultibyteCodec *codec_list;
          64                 :            : static const struct dbcs_map *mapping_list;
          65                 :            :
          66                 :            : #define CODEC_INIT(encoding)                                            \
          67                 :            :     static int encoding##_codec_init(const void *config)
          68                 :            :
          69                 :            : #define ENCODER_INIT(encoding)                                          \
          70                 :            :     static int encoding##_encode_init(                                  \
          71                 :            :         MultibyteCodec_State *state, const void *config)
          72                 :            : #define ENCODER(encoding)                                               \
          73                 :            :     static Py_ssize_t encoding##_encode(                                \
          74                 :            :         MultibyteCodec_State *state, const void *config,                \
          75                 :            :         int kind, const void *data,                                     \
          76                 :            :         Py_ssize_t *inpos, Py_ssize_t inlen,                            \
          77                 :            :         unsigned char **outbuf, Py_ssize_t outleft, int flags)
          78                 :            : #define ENCODER_RESET(encoding)                                         \
          79                 :            :     static Py_ssize_t encoding##_encode_reset(                          \
          80                 :            :         MultibyteCodec_State *state, const void *config,                \
          81                 :            :         unsigned char **outbuf, Py_ssize_t outleft)
          82                 :            :
          83                 :            : #define DECODER_INIT(encoding)                                          \
          84                 :            :     static int encoding##_decode_init(                                  \
          85                 :            :         MultibyteCodec_State *state, const void *config)
          86                 :            : #define DECODER(encoding)                                               \
          87                 :            :     static Py_ssize_t encoding##_decode(                                \
          88                 :            :         MultibyteCodec_State *state, const void *config,                \
          89                 :            :         const unsigned char **inbuf, Py_ssize_t inleft,                 \
          90                 :            :         _PyUnicodeWriter *writer)
          91                 :            : #define DECODER_RESET(encoding)                                         \
          92                 :            :     static Py_ssize_t encoding##_decode_reset(                          \
          93                 :            :         MultibyteCodec_State *state, const void *config)
          94                 :            :
          95                 :            : #define NEXT_IN(i)                              \
          96                 :            :     do {                                        \
          97                 :            :         (*inbuf) += (i);                        \
          98                 :            :         (inleft) -= (i);                        \
          99                 :            :     } while (0)
         100                 :            : #define NEXT_INCHAR(i)                          \
         101                 :            :     do {                                        \
         102                 :            :         (*inpos) += (i);                        \
         103                 :            :     } while (0)
         104                 :            : #define NEXT_OUT(o)                             \
         105                 :            :     do {                                        \
         106                 :            :         (*outbuf) += (o);                       \
         107                 :            :         (outleft) -= (o);                       \
         108                 :            :     } while (0)
         109                 :            : #define NEXT(i, o)                              \
         110                 :            :     do {                                        \
         111                 :            :         NEXT_INCHAR(i);                         \
         112                 :            :         NEXT_OUT(o);                            \
         113                 :            :     } while (0)
         114                 :            :
         115                 :            : #define REQUIRE_INBUF(n)                        \
         116                 :            :     do {                                        \
         117                 :            :         if (inleft < (n))                       \
         118                 :            :             return MBERR_TOOFEW;                \
         119                 :            :     } while (0)
         120                 :            :
         121                 :            : #define REQUIRE_OUTBUF(n)                       \
         122                 :            :     do {                                        \
         123                 :            :         if (outleft < (n))                      \
         124                 :            :             return MBERR_TOOSMALL;              \
         125                 :            :     } while (0)
         126                 :            :
         127                 :            : #define INBYTE1 ((*inbuf)[0])
         128                 :            : #define INBYTE2 ((*inbuf)[1])
         129                 :            : #define INBYTE3 ((*inbuf)[2])
         130                 :            : #define INBYTE4 ((*inbuf)[3])
         131                 :            :
         132                 :            : #define INCHAR1 (PyUnicode_READ(kind, data, *inpos))
         133                 :            : #define INCHAR2 (PyUnicode_READ(kind, data, *inpos + 1))
         134                 :            :
         135                 :            : #define OUTCHAR(c)                                                         \
         136                 :            :     do {                                                                   \
         137                 :            :         if (_PyUnicodeWriter_WriteChar(writer, (c)) < 0)                   \
         138                 :            :             return MBERR_EXCEPTION;                                         \
         139                 :            :     } while (0)
         140                 :            :
         141                 :            : #define OUTCHAR2(c1, c2)                                                   \
         142                 :            :     do {                                                                   \
         143                 :            :         Py_UCS4 _c1 = (c1);                                                \
         144                 :            :         Py_UCS4 _c2 = (c2);                                                \
         145                 :            :         if (_PyUnicodeWriter_Prepare(writer, 2, Py_MAX(_c1, c2)) < 0)      \
         146                 :            :             return MBERR_EXCEPTION;                                        \
         147                 :            :         PyUnicode_WRITE(writer->kind, writer->data, writer->pos, _c1);     \
         148                 :            :         PyUnicode_WRITE(writer->kind, writer->data, writer->pos + 1, _c2); \
         149                 :            :         writer->pos += 2;                                                  \
         150                 :            :     } while (0)
         151                 :            :
         152                 :            : #define OUTBYTEI(c, i)                     \
         153                 :            :     do {                                   \
         154                 :            :         assert((unsigned char)(c) == (c)); \
         155                 :            :         ((*outbuf)[i]) = (c);              \
         156                 :            :     } while (0)
         157                 :            :
         158                 :            : #define OUTBYTE1(c) OUTBYTEI(c, 0)
         159                 :            : #define OUTBYTE2(c) OUTBYTEI(c, 1)
         160                 :            : #define OUTBYTE3(c) OUTBYTEI(c, 2)
         161                 :            : #define OUTBYTE4(c) OUTBYTEI(c, 3)
         162                 :            :
         163                 :            : #define WRITEBYTE1(c1)              \
         164                 :            :     do {                            \
         165                 :            :         REQUIRE_OUTBUF(1);          \
         166                 :            :         OUTBYTE1(c1);               \
         167                 :            :     } while (0)
         168                 :            : #define WRITEBYTE2(c1, c2)          \
         169                 :            :     do {                            \
         170                 :            :         REQUIRE_OUTBUF(2);          \
         171                 :            :         OUTBYTE1(c1);               \
         172                 :            :         OUTBYTE2(c2);               \
         173                 :            :     } while (0)
         174                 :            : #define WRITEBYTE3(c1, c2, c3)      \
         175                 :            :     do {                            \
         176                 :            :         REQUIRE_OUTBUF(3);          \
         177                 :            :         OUTBYTE1(c1);               \
         178                 :            :         OUTBYTE2(c2);               \
         179                 :            :         OUTBYTE3(c3);               \
         180                 :            :     } while (0)
         181                 :            : #define WRITEBYTE4(c1, c2, c3, c4)  \
         182                 :            :     do {                            \
         183                 :            :         REQUIRE_OUTBUF(4);          \
         184                 :            :         OUTBYTE1(c1);               \
         185                 :            :         OUTBYTE2(c2);               \
         186                 :            :         OUTBYTE3(c3);               \
         187                 :            :         OUTBYTE4(c4);               \
         188                 :            :     } while (0)
         189                 :            :
         190                 :            : #define _TRYMAP_ENC(m, assi, val)                               \
         191                 :            :     ((m)->map != NULL && (val) >= (m)->bottom &&                \
         192                 :            :         (val)<= (m)->top && ((assi) = (m)->map[(val) -          \
         193                 :            :         (m)->bottom]) != NOCHAR)
         194                 :            : #define TRYMAP_ENC(charset, assi, uni)                     \
         195                 :            :     _TRYMAP_ENC(&charset##_encmap[(uni) >> 8], assi, (uni) & 0xff)
         196                 :            :
         197                 :            : #define _TRYMAP_DEC(m, assi, val)                             \
         198                 :            :     ((m)->map != NULL &&                                        \
         199                 :            :      (val) >= (m)->bottom &&                                    \
         200                 :            :      (val)<= (m)->top &&                                        \
         201                 :            :      ((assi) = (m)->map[(val) - (m)->bottom]) != UNIINV)
         202                 :            : #define TRYMAP_DEC(charset, assi, c1, c2)                     \
         203                 :            :     _TRYMAP_DEC(&charset##_decmap[c1], assi, c2)
         204                 :            :
         205                 :            : #define BEGIN_MAPPINGS_LIST static const struct dbcs_map _mapping_list[] = {
         206                 :            : #define MAPPING_ENCONLY(enc) {#enc, (void*)enc##_encmap, NULL},
         207                 :            : #define MAPPING_DECONLY(enc) {#enc, NULL, (void*)enc##_decmap},
         208                 :            : #define MAPPING_ENCDEC(enc) {#enc, (void*)enc##_encmap, (void*)enc##_decmap},
         209                 :            : #define END_MAPPINGS_LIST                               \
         210                 :            :     {"", NULL, NULL} };                                 \
         211                 :            :     static const struct dbcs_map *mapping_list =        \
         212                 :            :         (const struct dbcs_map *)_mapping_list;
         213                 :            :
         214                 :            : #define BEGIN_CODECS_LIST static const MultibyteCodec _codec_list[] = {
         215                 :            : #define _STATEFUL_METHODS(enc)          \
         216                 :            :     enc##_encode,                       \
         217                 :            :     enc##_encode_init,                  \
         218                 :            :     enc##_encode_reset,                 \
         219                 :            :     enc##_decode,                       \
         220                 :            :     enc##_decode_init,                  \
         221                 :            :     enc##_decode_reset,
         222                 :            : #define _STATELESS_METHODS(enc)         \
         223                 :            :     enc##_encode, NULL, NULL,           \
         224                 :            :     enc##_decode, NULL, NULL,
         225                 :            : #define CODEC_STATEFUL(enc) {           \
         226                 :            :     #enc, NULL, NULL,                   \
         227                 :            :     _STATEFUL_METHODS(enc)              \
         228                 :            : },
         229                 :            : #define CODEC_STATELESS(enc) {          \
         230                 :            :     #enc, NULL, NULL,                   \
         231                 :            :     _STATELESS_METHODS(enc)             \
         232                 :            : },
         233                 :            : #define CODEC_STATELESS_WINIT(enc) {    \
         234                 :            :     #enc, NULL,                         \
         235                 :            :     enc##_codec_init,                   \
         236                 :            :     _STATELESS_METHODS(enc)             \
         237                 :            : },
         238                 :            : #define END_CODECS_LIST                                 \
         239                 :            :     {"", NULL,} };                                      \
         240                 :            :     static const MultibyteCodec *codec_list =           \
         241                 :            :         (const MultibyteCodec *)_codec_list;
         242                 :            :
         243                 :            :
         244                 :            :
         245                 :            : static PyObject *
         246                 :          0 : getmultibytecodec(void)
         247                 :            : {
         248                 :          0 :     return _PyImport_GetModuleAttrString("_multibytecodec", "__create_codec");
         249                 :            : }
         250                 :            :
         251                 :            : static PyObject *
         252                 :          0 : getcodec(PyObject *self, PyObject *encoding)
         253                 :            : {
         254                 :            :     PyObject *codecobj, *r, *cofunc;
         255                 :            :     const MultibyteCodec *codec;
         256                 :            :     const char *enc;
         257                 :            :
         258         [ #  # ]:          0 :     if (!PyUnicode_Check(encoding)) {
         259                 :          0 :         PyErr_SetString(PyExc_TypeError,
         260                 :            :                         "encoding name must be a string.");
         261                 :          0 :         return NULL;
         262                 :            :     }
         263                 :          0 :     enc = PyUnicode_AsUTF8(encoding);
         264         [ #  # ]:          0 :     if (enc == NULL)
         265                 :          0 :         return NULL;
         266                 :            :
         267                 :          0 :     cofunc = getmultibytecodec();
         268         [ #  # ]:          0 :     if (cofunc == NULL)
         269                 :          0 :         return NULL;
         270                 :            :
         271         [ #  # ]:          0 :     for (codec = codec_list; codec->encoding[0]; codec++)
         272         [ #  # ]:          0 :         if (strcmp(codec->encoding, enc) == 0)
         273                 :          0 :             break;
         274                 :            :
         275         [ #  # ]:          0 :     if (codec->encoding[0] == '\0') {
         276                 :          0 :         PyErr_SetString(PyExc_LookupError,
         277                 :            :                         "no such codec is supported.");
         278                 :          0 :         return NULL;
         279                 :            :     }
         280                 :            :
         281                 :          0 :     codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
         282         [ #  # ]:          0 :     if (codecobj == NULL)
         283                 :          0 :         return NULL;
         284                 :            :
         285                 :          0 :     r = PyObject_CallOneArg(cofunc, codecobj);
         286                 :          0 :     Py_DECREF(codecobj);
         287                 :          0 :     Py_DECREF(cofunc);
         288                 :            :
         289                 :          0 :     return r;
         290                 :            : }
         291                 :            :
         292                 :            :
         293                 :            : static int
         294                 :          6 : register_maps(PyObject *module)
         295                 :            : {
         296                 :            :     const struct dbcs_map *h;
         297                 :            :
         298         [ +  + ]:         29 :     for (h = mapping_list; h->charset[0] != '\0'; h++) {
         299                 :         23 :         char mhname[256] = "__map_";
         300                 :         23 :         strcpy(mhname + sizeof("__map_") - 1, h->charset);
         301                 :            :
         302                 :         23 :         PyObject *capsule = PyCapsule_New((void *)h,
         303                 :            :                                           PyMultibyteCodec_CAPSULE_NAME, NULL);
         304         [ -  + ]:         23 :         if (capsule == NULL) {
         305                 :          0 :             return -1;
         306                 :            :         }
         307         [ -  + ]:         23 :         if (PyModule_AddObject(module, mhname, capsule) < 0) {
         308                 :          0 :             Py_DECREF(capsule);
         309                 :          0 :             return -1;
         310                 :            :         }
         311                 :            :     }
         312                 :          6 :     return 0;
         313                 :            : }
         314                 :            :
         315                 :            : #ifdef USING_BINARY_PAIR_SEARCH
         316                 :            : static DBCHAR
         317                 :          0 : find_pairencmap(ucs2_t body, ucs2_t modifier,
         318                 :            :                 const struct pair_encodemap *haystack, int haystacksize)
         319                 :            : {
         320                 :            :     int pos, min, max;
         321                 :          0 :     Py_UCS4 value = body << 16 | modifier;
         322                 :            :
         323                 :          0 :     min = 0;
         324                 :          0 :     max = haystacksize;
         325                 :            :
         326         [ #  # ]:          0 :     for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
         327         [ #  # ]:          0 :         if (value < haystack[pos].uniseq) {
         328         [ #  # ]:          0 :             if (max != pos) {
         329                 :          0 :                 max = pos;
         330                 :          0 :                 continue;
         331                 :            :             }
         332                 :            :         }
         333         [ #  # ]:          0 :         else if (value > haystack[pos].uniseq) {
         334         [ #  # ]:          0 :             if (min != pos) {
         335                 :          0 :                 min = pos;
         336                 :          0 :                 continue;
         337                 :            :             }
         338                 :            :         }
         339                 :          0 :         break;
         340                 :            :     }
         341                 :            :
         342         [ #  # ]:          0 :     if (value == haystack[pos].uniseq) {
         343                 :          0 :         return haystack[pos].code;
         344                 :            :     }
         345                 :          0 :     return DBCINV;
         346                 :            : }
         347                 :            : #endif
         348                 :            :
         349                 :            : #ifdef USING_IMPORTED_MAPS
         350                 :            : #define IMPORT_MAP(locale, charset, encmap, decmap) \
         351                 :            :     importmap("_codecs_" #locale, "__map_" #charset, \
         352                 :            :               (const void**)encmap, (const void**)decmap)
         353                 :            :
         354                 :            : static int
         355                 :          0 : importmap(const char *modname, const char *symbol,
         356                 :            :           const void **encmap, const void **decmap)
         357                 :            : {
         358                 :            :     PyObject *o, *mod;
         359                 :            :
         360                 :          0 :     mod = PyImport_ImportModule(modname);
         361         [ #  # ]:          0 :     if (mod == NULL)
         362                 :          0 :         return -1;
         363                 :            :
         364                 :          0 :     o = PyObject_GetAttrString(mod, symbol);
         365         [ #  # ]:          0 :     if (o == NULL)
         366                 :          0 :         goto errorexit;
         367         [ #  # ]:          0 :     else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
         368                 :          0 :         PyErr_SetString(PyExc_ValueError,
         369                 :            :                         "map data must be a Capsule.");
         370                 :          0 :         goto errorexit;
         371                 :            :     }
         372                 :            :     else {
         373                 :            :         struct dbcs_map *map;
         374                 :          0 :         map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
         375         [ #  # ]:          0 :         if (encmap != NULL)
         376                 :          0 :             *encmap = map->encmap;
         377         [ #  # ]:          0 :         if (decmap != NULL)
         378                 :          0 :             *decmap = map->decmap;
         379                 :          0 :         Py_DECREF(o);
         380                 :            :     }
         381                 :            :
         382                 :          0 :     Py_DECREF(mod);
         383                 :          0 :     return 0;
         384                 :            :
         385                 :          0 : errorexit:
         386                 :          0 :     Py_DECREF(mod);
         387                 :          0 :     return -1;
         388                 :            : }
         389                 :            : #endif
         390                 :            :
         391                 :            : static int
         392                 :          6 : _cjk_exec(PyObject *module)
         393                 :            : {
         394                 :          6 :     return register_maps(module);
         395                 :            : }
         396                 :            :
         397                 :            :
         398                 :            : static struct PyMethodDef _cjk_methods[] = {
         399                 :            :     {"getcodec", (PyCFunction)getcodec, METH_O, ""},
         400                 :            :     {NULL, NULL},
         401                 :            : };
         402                 :            :
         403                 :            : static PyModuleDef_Slot _cjk_slots[] = {
         404                 :            :     {Py_mod_exec, _cjk_exec},
         405                 :            :     {0, NULL}
         406                 :            : };
         407                 :            :
         408                 :            : #define I_AM_A_MODULE_FOR(loc)                                          \
         409                 :            :     static struct PyModuleDef _cjk_module = {                           \
         410                 :            :         PyModuleDef_HEAD_INIT,                                          \
         411                 :            :         .m_name = "_codecs_"#loc,                                       \
         412                 :            :         .m_size = 0,                                                    \
         413                 :            :         .m_methods = _cjk_methods,                                      \
         414                 :            :         .m_slots = _cjk_slots,                                          \
         415                 :            :     };                                                                  \
         416                 :            :                                                                         \
         417                 :            :     PyMODINIT_FUNC                                                      \
         418                 :            :     PyInit__codecs_##loc(void)                                          \
         419                 :            :     {                                                                   \
         420                 :            :         return PyModuleDef_Init(&_cjk_module);                          \
         421                 :            :     }
         422                 :            :
         423                 :            : #endif

Generated by: LCOV version 1.14