17db96d56Sopenharmony_ci/*
27db96d56Sopenharmony_ci * cjkcodecs.h: common header for cjkcodecs
37db96d56Sopenharmony_ci *
47db96d56Sopenharmony_ci * Written by Hye-Shik Chang <perky@FreeBSD.org>
57db96d56Sopenharmony_ci */
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci#ifndef _CJKCODECS_H_
87db96d56Sopenharmony_ci#define _CJKCODECS_H_
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
117db96d56Sopenharmony_ci#include "Python.h"
127db96d56Sopenharmony_ci#include "multibytecodec.h"
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci/* a unicode "undefined" code point */
167db96d56Sopenharmony_ci#define UNIINV  0xFFFE
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci/* internal-use DBCS code points which aren't used by any charsets */
197db96d56Sopenharmony_ci#define NOCHAR  0xFFFF
207db96d56Sopenharmony_ci#define MULTIC  0xFFFE
217db96d56Sopenharmony_ci#define DBCINV  0xFFFD
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ci/* shorter macros to save source size of mapping tables */
247db96d56Sopenharmony_ci#define U UNIINV
257db96d56Sopenharmony_ci#define N NOCHAR
267db96d56Sopenharmony_ci#define M MULTIC
277db96d56Sopenharmony_ci#define D DBCINV
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_cistruct dbcs_index {
307db96d56Sopenharmony_ci    const ucs2_t *map;
317db96d56Sopenharmony_ci    unsigned char bottom, top;
327db96d56Sopenharmony_ci};
337db96d56Sopenharmony_citypedef struct dbcs_index decode_map;
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_cistruct widedbcs_index {
367db96d56Sopenharmony_ci    const Py_UCS4 *map;
377db96d56Sopenharmony_ci    unsigned char bottom, top;
387db96d56Sopenharmony_ci};
397db96d56Sopenharmony_citypedef struct widedbcs_index widedecode_map;
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_cistruct unim_index {
427db96d56Sopenharmony_ci    const DBCHAR *map;
437db96d56Sopenharmony_ci    unsigned char bottom, top;
447db96d56Sopenharmony_ci};
457db96d56Sopenharmony_citypedef struct unim_index encode_map;
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_cistruct unim_index_bytebased {
487db96d56Sopenharmony_ci    const unsigned char *map;
497db96d56Sopenharmony_ci    unsigned char bottom, top;
507db96d56Sopenharmony_ci};
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_cistruct dbcs_map {
537db96d56Sopenharmony_ci    const char *charset;
547db96d56Sopenharmony_ci    const struct unim_index *encmap;
557db96d56Sopenharmony_ci    const struct dbcs_index *decmap;
567db96d56Sopenharmony_ci};
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_cistruct pair_encodemap {
597db96d56Sopenharmony_ci    Py_UCS4 uniseq;
607db96d56Sopenharmony_ci    DBCHAR code;
617db96d56Sopenharmony_ci};
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_cistatic const MultibyteCodec *codec_list;
647db96d56Sopenharmony_cistatic const struct dbcs_map *mapping_list;
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci#define CODEC_INIT(encoding)                                            \
677db96d56Sopenharmony_ci    static int encoding##_codec_init(const void *config)
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci#define ENCODER_INIT(encoding)                                          \
707db96d56Sopenharmony_ci    static int encoding##_encode_init(                                  \
717db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config)
727db96d56Sopenharmony_ci#define ENCODER(encoding)                                               \
737db96d56Sopenharmony_ci    static Py_ssize_t encoding##_encode(                                \
747db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config,                \
757db96d56Sopenharmony_ci        int kind, const void *data,                                     \
767db96d56Sopenharmony_ci        Py_ssize_t *inpos, Py_ssize_t inlen,                            \
777db96d56Sopenharmony_ci        unsigned char **outbuf, Py_ssize_t outleft, int flags)
787db96d56Sopenharmony_ci#define ENCODER_RESET(encoding)                                         \
797db96d56Sopenharmony_ci    static Py_ssize_t encoding##_encode_reset(                          \
807db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config,                \
817db96d56Sopenharmony_ci        unsigned char **outbuf, Py_ssize_t outleft)
827db96d56Sopenharmony_ci
837db96d56Sopenharmony_ci#define DECODER_INIT(encoding)                                          \
847db96d56Sopenharmony_ci    static int encoding##_decode_init(                                  \
857db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config)
867db96d56Sopenharmony_ci#define DECODER(encoding)                                               \
877db96d56Sopenharmony_ci    static Py_ssize_t encoding##_decode(                                \
887db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config,                \
897db96d56Sopenharmony_ci        const unsigned char **inbuf, Py_ssize_t inleft,                 \
907db96d56Sopenharmony_ci        _PyUnicodeWriter *writer)
917db96d56Sopenharmony_ci#define DECODER_RESET(encoding)                                         \
927db96d56Sopenharmony_ci    static Py_ssize_t encoding##_decode_reset(                          \
937db96d56Sopenharmony_ci        MultibyteCodec_State *state, const void *config)
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci#define NEXT_IN(i)                              \
967db96d56Sopenharmony_ci    do {                                        \
977db96d56Sopenharmony_ci        (*inbuf) += (i);                        \
987db96d56Sopenharmony_ci        (inleft) -= (i);                        \
997db96d56Sopenharmony_ci    } while (0)
1007db96d56Sopenharmony_ci#define NEXT_INCHAR(i)                          \
1017db96d56Sopenharmony_ci    do {                                        \
1027db96d56Sopenharmony_ci        (*inpos) += (i);                        \
1037db96d56Sopenharmony_ci    } while (0)
1047db96d56Sopenharmony_ci#define NEXT_OUT(o)                             \
1057db96d56Sopenharmony_ci    do {                                        \
1067db96d56Sopenharmony_ci        (*outbuf) += (o);                       \
1077db96d56Sopenharmony_ci        (outleft) -= (o);                       \
1087db96d56Sopenharmony_ci    } while (0)
1097db96d56Sopenharmony_ci#define NEXT(i, o)                              \
1107db96d56Sopenharmony_ci    do {                                        \
1117db96d56Sopenharmony_ci        NEXT_INCHAR(i);                         \
1127db96d56Sopenharmony_ci        NEXT_OUT(o);                            \
1137db96d56Sopenharmony_ci    } while (0)
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci#define REQUIRE_INBUF(n)                        \
1167db96d56Sopenharmony_ci    do {                                        \
1177db96d56Sopenharmony_ci        if (inleft < (n))                       \
1187db96d56Sopenharmony_ci            return MBERR_TOOFEW;                \
1197db96d56Sopenharmony_ci    } while (0)
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci#define REQUIRE_OUTBUF(n)                       \
1227db96d56Sopenharmony_ci    do {                                        \
1237db96d56Sopenharmony_ci        if (outleft < (n))                      \
1247db96d56Sopenharmony_ci            return MBERR_TOOSMALL;              \
1257db96d56Sopenharmony_ci    } while (0)
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ci#define INBYTE1 ((*inbuf)[0])
1287db96d56Sopenharmony_ci#define INBYTE2 ((*inbuf)[1])
1297db96d56Sopenharmony_ci#define INBYTE3 ((*inbuf)[2])
1307db96d56Sopenharmony_ci#define INBYTE4 ((*inbuf)[3])
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci#define INCHAR1 (PyUnicode_READ(kind, data, *inpos))
1337db96d56Sopenharmony_ci#define INCHAR2 (PyUnicode_READ(kind, data, *inpos + 1))
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci#define OUTCHAR(c)                                                         \
1367db96d56Sopenharmony_ci    do {                                                                   \
1377db96d56Sopenharmony_ci        if (_PyUnicodeWriter_WriteChar(writer, (c)) < 0)                   \
1387db96d56Sopenharmony_ci            return MBERR_EXCEPTION;                                         \
1397db96d56Sopenharmony_ci    } while (0)
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci#define OUTCHAR2(c1, c2)                                                   \
1427db96d56Sopenharmony_ci    do {                                                                   \
1437db96d56Sopenharmony_ci        Py_UCS4 _c1 = (c1);                                                \
1447db96d56Sopenharmony_ci        Py_UCS4 _c2 = (c2);                                                \
1457db96d56Sopenharmony_ci        if (_PyUnicodeWriter_Prepare(writer, 2, Py_MAX(_c1, c2)) < 0)      \
1467db96d56Sopenharmony_ci            return MBERR_EXCEPTION;                                        \
1477db96d56Sopenharmony_ci        PyUnicode_WRITE(writer->kind, writer->data, writer->pos, _c1);     \
1487db96d56Sopenharmony_ci        PyUnicode_WRITE(writer->kind, writer->data, writer->pos + 1, _c2); \
1497db96d56Sopenharmony_ci        writer->pos += 2;                                                  \
1507db96d56Sopenharmony_ci    } while (0)
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci#define OUTBYTEI(c, i)                     \
1537db96d56Sopenharmony_ci    do {                                   \
1547db96d56Sopenharmony_ci        assert((unsigned char)(c) == (c)); \
1557db96d56Sopenharmony_ci        ((*outbuf)[i]) = (c);              \
1567db96d56Sopenharmony_ci    } while (0)
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ci#define OUTBYTE1(c) OUTBYTEI(c, 0)
1597db96d56Sopenharmony_ci#define OUTBYTE2(c) OUTBYTEI(c, 1)
1607db96d56Sopenharmony_ci#define OUTBYTE3(c) OUTBYTEI(c, 2)
1617db96d56Sopenharmony_ci#define OUTBYTE4(c) OUTBYTEI(c, 3)
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci#define WRITEBYTE1(c1)              \
1647db96d56Sopenharmony_ci    do {                            \
1657db96d56Sopenharmony_ci        REQUIRE_OUTBUF(1);          \
1667db96d56Sopenharmony_ci        OUTBYTE1(c1);               \
1677db96d56Sopenharmony_ci    } while (0)
1687db96d56Sopenharmony_ci#define WRITEBYTE2(c1, c2)          \
1697db96d56Sopenharmony_ci    do {                            \
1707db96d56Sopenharmony_ci        REQUIRE_OUTBUF(2);          \
1717db96d56Sopenharmony_ci        OUTBYTE1(c1);               \
1727db96d56Sopenharmony_ci        OUTBYTE2(c2);               \
1737db96d56Sopenharmony_ci    } while (0)
1747db96d56Sopenharmony_ci#define WRITEBYTE3(c1, c2, c3)      \
1757db96d56Sopenharmony_ci    do {                            \
1767db96d56Sopenharmony_ci        REQUIRE_OUTBUF(3);          \
1777db96d56Sopenharmony_ci        OUTBYTE1(c1);               \
1787db96d56Sopenharmony_ci        OUTBYTE2(c2);               \
1797db96d56Sopenharmony_ci        OUTBYTE3(c3);               \
1807db96d56Sopenharmony_ci    } while (0)
1817db96d56Sopenharmony_ci#define WRITEBYTE4(c1, c2, c3, c4)  \
1827db96d56Sopenharmony_ci    do {                            \
1837db96d56Sopenharmony_ci        REQUIRE_OUTBUF(4);          \
1847db96d56Sopenharmony_ci        OUTBYTE1(c1);               \
1857db96d56Sopenharmony_ci        OUTBYTE2(c2);               \
1867db96d56Sopenharmony_ci        OUTBYTE3(c3);               \
1877db96d56Sopenharmony_ci        OUTBYTE4(c4);               \
1887db96d56Sopenharmony_ci    } while (0)
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci#define _TRYMAP_ENC(m, assi, val)                               \
1917db96d56Sopenharmony_ci    ((m)->map != NULL && (val) >= (m)->bottom &&                \
1927db96d56Sopenharmony_ci        (val)<= (m)->top && ((assi) = (m)->map[(val) -          \
1937db96d56Sopenharmony_ci        (m)->bottom]) != NOCHAR)
1947db96d56Sopenharmony_ci#define TRYMAP_ENC(charset, assi, uni)                     \
1957db96d56Sopenharmony_ci    _TRYMAP_ENC(&charset##_encmap[(uni) >> 8], assi, (uni) & 0xff)
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci#define _TRYMAP_DEC(m, assi, val)                             \
1987db96d56Sopenharmony_ci    ((m)->map != NULL &&                                        \
1997db96d56Sopenharmony_ci     (val) >= (m)->bottom &&                                    \
2007db96d56Sopenharmony_ci     (val)<= (m)->top &&                                        \
2017db96d56Sopenharmony_ci     ((assi) = (m)->map[(val) - (m)->bottom]) != UNIINV)
2027db96d56Sopenharmony_ci#define TRYMAP_DEC(charset, assi, c1, c2)                     \
2037db96d56Sopenharmony_ci    _TRYMAP_DEC(&charset##_decmap[c1], assi, c2)
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci#define BEGIN_MAPPINGS_LIST static const struct dbcs_map _mapping_list[] = {
2067db96d56Sopenharmony_ci#define MAPPING_ENCONLY(enc) {#enc, (void*)enc##_encmap, NULL},
2077db96d56Sopenharmony_ci#define MAPPING_DECONLY(enc) {#enc, NULL, (void*)enc##_decmap},
2087db96d56Sopenharmony_ci#define MAPPING_ENCDEC(enc) {#enc, (void*)enc##_encmap, (void*)enc##_decmap},
2097db96d56Sopenharmony_ci#define END_MAPPINGS_LIST                               \
2107db96d56Sopenharmony_ci    {"", NULL, NULL} };                                 \
2117db96d56Sopenharmony_ci    static const struct dbcs_map *mapping_list =        \
2127db96d56Sopenharmony_ci        (const struct dbcs_map *)_mapping_list;
2137db96d56Sopenharmony_ci
2147db96d56Sopenharmony_ci#define BEGIN_CODECS_LIST static const MultibyteCodec _codec_list[] = {
2157db96d56Sopenharmony_ci#define _STATEFUL_METHODS(enc)          \
2167db96d56Sopenharmony_ci    enc##_encode,                       \
2177db96d56Sopenharmony_ci    enc##_encode_init,                  \
2187db96d56Sopenharmony_ci    enc##_encode_reset,                 \
2197db96d56Sopenharmony_ci    enc##_decode,                       \
2207db96d56Sopenharmony_ci    enc##_decode_init,                  \
2217db96d56Sopenharmony_ci    enc##_decode_reset,
2227db96d56Sopenharmony_ci#define _STATELESS_METHODS(enc)         \
2237db96d56Sopenharmony_ci    enc##_encode, NULL, NULL,           \
2247db96d56Sopenharmony_ci    enc##_decode, NULL, NULL,
2257db96d56Sopenharmony_ci#define CODEC_STATEFUL(enc) {           \
2267db96d56Sopenharmony_ci    #enc, NULL, NULL,                   \
2277db96d56Sopenharmony_ci    _STATEFUL_METHODS(enc)              \
2287db96d56Sopenharmony_ci},
2297db96d56Sopenharmony_ci#define CODEC_STATELESS(enc) {          \
2307db96d56Sopenharmony_ci    #enc, NULL, NULL,                   \
2317db96d56Sopenharmony_ci    _STATELESS_METHODS(enc)             \
2327db96d56Sopenharmony_ci},
2337db96d56Sopenharmony_ci#define CODEC_STATELESS_WINIT(enc) {    \
2347db96d56Sopenharmony_ci    #enc, NULL,                         \
2357db96d56Sopenharmony_ci    enc##_codec_init,                   \
2367db96d56Sopenharmony_ci    _STATELESS_METHODS(enc)             \
2377db96d56Sopenharmony_ci},
2387db96d56Sopenharmony_ci#define END_CODECS_LIST                                 \
2397db96d56Sopenharmony_ci    {"", NULL,} };                                      \
2407db96d56Sopenharmony_ci    static const MultibyteCodec *codec_list =           \
2417db96d56Sopenharmony_ci        (const MultibyteCodec *)_codec_list;
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_cistatic PyObject *
2467db96d56Sopenharmony_cigetmultibytecodec(void)
2477db96d56Sopenharmony_ci{
2487db96d56Sopenharmony_ci    PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec");
2497db96d56Sopenharmony_ci    if (mod == NULL) {
2507db96d56Sopenharmony_ci        return NULL;
2517db96d56Sopenharmony_ci    }
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci    PyObject *cofunc = PyObject_GetAttrString(mod, "__create_codec");
2547db96d56Sopenharmony_ci    Py_DECREF(mod);
2557db96d56Sopenharmony_ci    return cofunc;
2567db96d56Sopenharmony_ci}
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_cistatic PyObject *
2597db96d56Sopenharmony_cigetcodec(PyObject *self, PyObject *encoding)
2607db96d56Sopenharmony_ci{
2617db96d56Sopenharmony_ci    PyObject *codecobj, *r, *cofunc;
2627db96d56Sopenharmony_ci    const MultibyteCodec *codec;
2637db96d56Sopenharmony_ci    const char *enc;
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci    if (!PyUnicode_Check(encoding)) {
2667db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError,
2677db96d56Sopenharmony_ci                        "encoding name must be a string.");
2687db96d56Sopenharmony_ci        return NULL;
2697db96d56Sopenharmony_ci    }
2707db96d56Sopenharmony_ci    enc = PyUnicode_AsUTF8(encoding);
2717db96d56Sopenharmony_ci    if (enc == NULL)
2727db96d56Sopenharmony_ci        return NULL;
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_ci    cofunc = getmultibytecodec();
2757db96d56Sopenharmony_ci    if (cofunc == NULL)
2767db96d56Sopenharmony_ci        return NULL;
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci    for (codec = codec_list; codec->encoding[0]; codec++)
2797db96d56Sopenharmony_ci        if (strcmp(codec->encoding, enc) == 0)
2807db96d56Sopenharmony_ci            break;
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci    if (codec->encoding[0] == '\0') {
2837db96d56Sopenharmony_ci        PyErr_SetString(PyExc_LookupError,
2847db96d56Sopenharmony_ci                        "no such codec is supported.");
2857db96d56Sopenharmony_ci        return NULL;
2867db96d56Sopenharmony_ci    }
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_ci    codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
2897db96d56Sopenharmony_ci    if (codecobj == NULL)
2907db96d56Sopenharmony_ci        return NULL;
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci    r = PyObject_CallOneArg(cofunc, codecobj);
2937db96d56Sopenharmony_ci    Py_DECREF(codecobj);
2947db96d56Sopenharmony_ci    Py_DECREF(cofunc);
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci    return r;
2977db96d56Sopenharmony_ci}
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_cistatic int
3017db96d56Sopenharmony_ciregister_maps(PyObject *module)
3027db96d56Sopenharmony_ci{
3037db96d56Sopenharmony_ci    const struct dbcs_map *h;
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci    for (h = mapping_list; h->charset[0] != '\0'; h++) {
3067db96d56Sopenharmony_ci        char mhname[256] = "__map_";
3077db96d56Sopenharmony_ci        strcpy(mhname + sizeof("__map_") - 1, h->charset);
3087db96d56Sopenharmony_ci
3097db96d56Sopenharmony_ci        PyObject *capsule = PyCapsule_New((void *)h,
3107db96d56Sopenharmony_ci                                          PyMultibyteCodec_CAPSULE_NAME, NULL);
3117db96d56Sopenharmony_ci        if (capsule == NULL) {
3127db96d56Sopenharmony_ci            return -1;
3137db96d56Sopenharmony_ci        }
3147db96d56Sopenharmony_ci        if (PyModule_AddObject(module, mhname, capsule) < 0) {
3157db96d56Sopenharmony_ci            Py_DECREF(capsule);
3167db96d56Sopenharmony_ci            return -1;
3177db96d56Sopenharmony_ci        }
3187db96d56Sopenharmony_ci    }
3197db96d56Sopenharmony_ci    return 0;
3207db96d56Sopenharmony_ci}
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci#ifdef USING_BINARY_PAIR_SEARCH
3237db96d56Sopenharmony_cistatic DBCHAR
3247db96d56Sopenharmony_cifind_pairencmap(ucs2_t body, ucs2_t modifier,
3257db96d56Sopenharmony_ci                const struct pair_encodemap *haystack, int haystacksize)
3267db96d56Sopenharmony_ci{
3277db96d56Sopenharmony_ci    int pos, min, max;
3287db96d56Sopenharmony_ci    Py_UCS4 value = body << 16 | modifier;
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci    min = 0;
3317db96d56Sopenharmony_ci    max = haystacksize;
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci    for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
3347db96d56Sopenharmony_ci        if (value < haystack[pos].uniseq) {
3357db96d56Sopenharmony_ci            if (max != pos) {
3367db96d56Sopenharmony_ci                max = pos;
3377db96d56Sopenharmony_ci                continue;
3387db96d56Sopenharmony_ci            }
3397db96d56Sopenharmony_ci        }
3407db96d56Sopenharmony_ci        else if (value > haystack[pos].uniseq) {
3417db96d56Sopenharmony_ci            if (min != pos) {
3427db96d56Sopenharmony_ci                min = pos;
3437db96d56Sopenharmony_ci                continue;
3447db96d56Sopenharmony_ci            }
3457db96d56Sopenharmony_ci        }
3467db96d56Sopenharmony_ci        break;
3477db96d56Sopenharmony_ci    }
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci    if (value == haystack[pos].uniseq) {
3507db96d56Sopenharmony_ci        return haystack[pos].code;
3517db96d56Sopenharmony_ci    }
3527db96d56Sopenharmony_ci    return DBCINV;
3537db96d56Sopenharmony_ci}
3547db96d56Sopenharmony_ci#endif
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci#ifdef USING_IMPORTED_MAPS
3577db96d56Sopenharmony_ci#define IMPORT_MAP(locale, charset, encmap, decmap) \
3587db96d56Sopenharmony_ci    importmap("_codecs_" #locale, "__map_" #charset, \
3597db96d56Sopenharmony_ci              (const void**)encmap, (const void**)decmap)
3607db96d56Sopenharmony_ci
3617db96d56Sopenharmony_cistatic int
3627db96d56Sopenharmony_ciimportmap(const char *modname, const char *symbol,
3637db96d56Sopenharmony_ci          const void **encmap, const void **decmap)
3647db96d56Sopenharmony_ci{
3657db96d56Sopenharmony_ci    PyObject *o, *mod;
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ci    mod = PyImport_ImportModule(modname);
3687db96d56Sopenharmony_ci    if (mod == NULL)
3697db96d56Sopenharmony_ci        return -1;
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ci    o = PyObject_GetAttrString(mod, symbol);
3727db96d56Sopenharmony_ci    if (o == NULL)
3737db96d56Sopenharmony_ci        goto errorexit;
3747db96d56Sopenharmony_ci    else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
3757db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
3767db96d56Sopenharmony_ci                        "map data must be a Capsule.");
3777db96d56Sopenharmony_ci        goto errorexit;
3787db96d56Sopenharmony_ci    }
3797db96d56Sopenharmony_ci    else {
3807db96d56Sopenharmony_ci        struct dbcs_map *map;
3817db96d56Sopenharmony_ci        map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
3827db96d56Sopenharmony_ci        if (encmap != NULL)
3837db96d56Sopenharmony_ci            *encmap = map->encmap;
3847db96d56Sopenharmony_ci        if (decmap != NULL)
3857db96d56Sopenharmony_ci            *decmap = map->decmap;
3867db96d56Sopenharmony_ci        Py_DECREF(o);
3877db96d56Sopenharmony_ci    }
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ci    Py_DECREF(mod);
3907db96d56Sopenharmony_ci    return 0;
3917db96d56Sopenharmony_ci
3927db96d56Sopenharmony_cierrorexit:
3937db96d56Sopenharmony_ci    Py_DECREF(mod);
3947db96d56Sopenharmony_ci    return -1;
3957db96d56Sopenharmony_ci}
3967db96d56Sopenharmony_ci#endif
3977db96d56Sopenharmony_ci
3987db96d56Sopenharmony_cistatic int
3997db96d56Sopenharmony_ci_cjk_exec(PyObject *module)
4007db96d56Sopenharmony_ci{
4017db96d56Sopenharmony_ci    return register_maps(module);
4027db96d56Sopenharmony_ci}
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_cistatic struct PyMethodDef _cjk_methods[] = {
4067db96d56Sopenharmony_ci    {"getcodec", (PyCFunction)getcodec, METH_O, ""},
4077db96d56Sopenharmony_ci    {NULL, NULL},
4087db96d56Sopenharmony_ci};
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_cistatic PyModuleDef_Slot _cjk_slots[] = {
4117db96d56Sopenharmony_ci    {Py_mod_exec, _cjk_exec},
4127db96d56Sopenharmony_ci    {0, NULL}
4137db96d56Sopenharmony_ci};
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_ci#define I_AM_A_MODULE_FOR(loc)                                          \
4167db96d56Sopenharmony_ci    static struct PyModuleDef _cjk_module = {                           \
4177db96d56Sopenharmony_ci        PyModuleDef_HEAD_INIT,                                          \
4187db96d56Sopenharmony_ci        .m_name = "_codecs_"#loc,                                       \
4197db96d56Sopenharmony_ci        .m_size = 0,                                                    \
4207db96d56Sopenharmony_ci        .m_methods = _cjk_methods,                                      \
4217db96d56Sopenharmony_ci        .m_slots = _cjk_slots,                                          \
4227db96d56Sopenharmony_ci    };                                                                  \
4237db96d56Sopenharmony_ci                                                                        \
4247db96d56Sopenharmony_ci    PyMODINIT_FUNC                                                      \
4257db96d56Sopenharmony_ci    PyInit__codecs_##loc(void)                                          \
4267db96d56Sopenharmony_ci    {                                                                   \
4277db96d56Sopenharmony_ci        return PyModuleDef_Init(&_cjk_module);                          \
4287db96d56Sopenharmony_ci    }
4297db96d56Sopenharmony_ci
4307db96d56Sopenharmony_ci#endif
431