blob: a8bc04cd0cdcc82ad8fcce53cc4c7103d653bdec [file] [log] [blame]
Hye-Shik Chang3e2a3062004-01-17 14:29:29 +00001/*
2 * codecentry.h: Common Codec Entry Routines
3 *
4 * Written by Hye-Shik Chang <perky@FreeBSD.org>
5 * $CJKCodecs: codecentry.h,v 1.5 2004/01/17 11:26:10 perky Exp $
6 */
7
8#ifdef HAVE_ENCODER_INIT
9#define ENCODER_INIT_FUNC(encoding) encoding##_encode_init
10#else
11#define ENCODER_INIT_FUNC(encoding) NULL
12#endif
13
14#ifdef HAVE_ENCODER_RESET
15#define ENCODER_RESET_FUNC(encoding) encoding##_encode_reset
16#else
17#define ENCODER_RESET_FUNC(encoding) NULL
18#endif
19
20#ifdef HAVE_DECODER_INIT
21#define DECODER_INIT_FUNC(encoding) encoding##_decode_init
22#else
23#define DECODER_INIT_FUNC(encoding) NULL
24#endif
25
26#ifdef HAVE_DECODER_RESET
27#define DECODER_RESET_FUNC(encoding) encoding##_decode_reset
28#else
29#define DECODER_RESET_FUNC(encoding) NULL
30#endif
31
32#ifdef STRICT_BUILD
33#define BEGIN_CODEC_REGISTRY(encoding) \
34 __BEGIN_CODEC_REGISTRY(encoding, init_codecs_##encoding##_strict)
35#else
36#define BEGIN_CODEC_REGISTRY(encoding) \
37 __BEGIN_CODEC_REGISTRY(encoding, init_codecs_##encoding)
38#endif
39
40#define __BEGIN_CODEC_REGISTRY(encoding, initname) \
41 static MultibyteCodec __codec = { \
42 #encoding STRICT_SUFX, \
43 encoding##_encode, \
44 ENCODER_INIT_FUNC(encoding), \
45 ENCODER_RESET_FUNC(encoding), \
46 encoding##_decode, \
47 DECODER_INIT_FUNC(encoding), \
48 DECODER_RESET_FUNC(encoding), \
49 }; \
50 \
51 static struct PyMethodDef __methods[] = { \
52 {NULL, NULL}, \
53 }; \
54 \
55 void \
56 initname(void) \
57 { \
58 PyObject *codec; \
59 PyObject *m = NULL, *mod = NULL, *o = NULL; \
60 \
61 m = Py_InitModule("_codecs_" #encoding STRICT_SUFX, __methods);
62
63#define MAPOPEN(locale) \
64 mod = PyImport_ImportModule("_codecs_mapdata_" #locale);\
65 if (mod == NULL) goto errorexit; \
66 if (
67#define IMPORTMAP_ENCDEC(charset) \
68 importmap(mod, "__map_" #charset, &charset##encmap, \
69 &charset##decmap) ||
70#define IMPORTMAP_ENC(charset) \
71 importmap(mod, "__map_" #charset, &charset##encmap, \
72 NULL) ||
73#define IMPORTMAP_DEC(charset) \
74 importmap(mod, "__map_" #charset, NULL, \
75 &charset##decmap) ||
76#define MAPCLOSE() \
77 0) goto errorexit; \
78 Py_DECREF(mod);
79
80#define END_CODEC_REGISTRY(encoding) \
81 mod = PyImport_ImportModule("_multibytecodec"); \
82 if (mod == NULL) goto errorexit; \
83 o = PyObject_GetAttrString(mod, "__create_codec"); \
84 if (o == NULL || !PyCallable_Check(o)) \
85 goto errorexit; \
86 \
87 codec = createcodec(o, &__codec); \
88 if (codec == NULL) \
89 goto errorexit; \
90 PyModule_AddObject(m, "codec", codec); \
91 Py_DECREF(o); Py_DECREF(mod); \
92 \
93 if (PyErr_Occurred()) \
94 Py_FatalError("can't initialize the _" #encoding \
95 STRICT_SUFX " module"); \
96 \
97 return; \
98 \
99errorexit: \
100 Py_XDECREF(m); \
101 Py_XDECREF(mod); \
102 Py_XDECREF(o); \
103}
104
105#define CODEC_REGISTRY(encoding) \
106 BEGIN_CODEC_REGISTRY(encoding) \
107 END_CODEC_REGISTRY(encoding)
108
109#ifdef USING_BINARY_PAIR_SEARCH
110static DBCHAR
111find_pairencmap(ucs2_t body, ucs2_t modifier,
112 struct pair_encodemap *haystack, int haystacksize)
113{
114 int pos, min, max;
115 ucs4_t value = body << 16 | modifier;
116
117 min = 0;
118 max = haystacksize;
119
120 for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
121 if (value < haystack[pos].uniseq) {
122 if (max == pos) break;
123 else max = pos;
124 } else if (value > haystack[pos].uniseq) {
125 if (min == pos) break;
126 else min = pos;
127 } else
128 break;
129
130 if (value == haystack[pos].uniseq)
131 return haystack[pos].code;
132 else
133 return DBCINV;
134}
135#endif
136
137#ifndef CODEC_WITHOUT_MAPS
138static int
139importmap(PyObject *mod, const char *symbol,
140 const struct unim_index **encmap, const struct dbcs_index **decmap)
141{
142 PyObject *o;
143
144 o = PyObject_GetAttrString(mod, (char*)symbol);
145 if (o == NULL)
146 return -1;
147 else if (!PyCObject_Check(o)) {
148 PyErr_SetString(PyExc_ValueError, "map data must be a CObject.");
149 return -1;
150 } else {
151 struct dbcs_map *map;
152 map = PyCObject_AsVoidPtr(o);
153 if (encmap != NULL)
154 *encmap = map->encmap;
155 if (decmap != NULL)
156 *decmap = map->decmap;
157 Py_DECREF(o);
158 }
159
160 return 0;
161}
162#endif
163
164static PyObject *
165createcodec(PyObject *cofunc, MultibyteCodec *codec)
166{
167 PyObject *args, *r;
168
169 args = PyTuple_New(1);
170 if (args == NULL) return NULL;
171 PyTuple_SET_ITEM(args, 0, PyCObject_FromVoidPtr(codec, NULL));
172
173 r = PyObject_CallObject(cofunc, args);
174 Py_DECREF(args);
175
176 return r;
177}