@@ -60,8 +60,20 @@ struct pair_encodemap {
60
60
DBCHAR code ;
61
61
};
62
62
63
- static const MultibyteCodec * codec_list ;
64
- static const struct dbcs_map * mapping_list ;
63
+ typedef struct {
64
+ int num_mappings ;
65
+ int num_codecs ;
66
+ struct dbcs_map * mapping_list ;
67
+ MultibyteCodec * codec_list ;
68
+ } cjkcodecs_module_state ;
69
+
70
+ static inline cjkcodecs_module_state *
71
+ get_module_state (PyObject * mod )
72
+ {
73
+ void * state = PyModule_GetState (mod );
74
+ assert (state != NULL );
75
+ return (cjkcodecs_module_state * )state ;
76
+ }
65
77
66
78
#define CODEC_INIT (encoding ) \
67
79
static int encoding##_codec_init(const void *config)
@@ -202,16 +214,40 @@ static const struct dbcs_map *mapping_list;
202
214
#define TRYMAP_DEC (charset , assi , c1 , c2 ) \
203
215
_TRYMAP_DEC(&charset##_decmap[c1], assi, c2)
204
216
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;
217
+ #define BEGIN_MAPPINGS_LIST (NUM ) \
218
+ static int \
219
+ add_mappings(cjkcodecs_module_state *st) \
220
+ { \
221
+ int idx = 0; \
222
+ st->num_mappings = NUM; \
223
+ st->mapping_list = PyMem_Calloc(NUM, sizeof(struct dbcs_map)); \
224
+ if (st->mapping_list == NULL) { \
225
+ return -1; \
226
+ }
227
+
228
+ #define MAPPING_ENCONLY (enc ) \
229
+ st->mapping_list[idx++] = (struct dbcs_map){#enc, (void*)enc##_encmap, NULL};
230
+ #define MAPPING_DECONLY (enc ) \
231
+ st->mapping_list[idx++] = (struct dbcs_map){#enc, NULL, (void*)enc##_decmap};
232
+ #define MAPPING_ENCDEC (enc ) \
233
+ st->mapping_list[idx++] = (struct dbcs_map){#enc, (void*)enc##_encmap, (void*)enc##_decmap};
234
+
235
+ #define END_MAPPINGS_LIST \
236
+ assert(st->num_mappings == idx); \
237
+ return 0; \
238
+ }
239
+
240
+ #define BEGIN_CODECS_LIST (NUM ) \
241
+ static int \
242
+ add_codecs(cjkcodecs_module_state *st) \
243
+ { \
244
+ int idx = 0; \
245
+ st->num_codecs = NUM; \
246
+ st->codec_list = PyMem_Calloc(NUM, sizeof(MultibyteCodec)); \
247
+ if (st->codec_list == NULL) { \
248
+ return -1; \
249
+ }
213
250
214
- #define BEGIN_CODECS_LIST static const MultibyteCodec _codec_list[] = {
215
251
#define _STATEFUL_METHODS (enc ) \
216
252
enc##_encode, \
217
253
enc##_encode_init, \
@@ -222,23 +258,18 @@ static const struct dbcs_map *mapping_list;
222
258
#define _STATELESS_METHODS (enc ) \
223
259
enc##_encode, NULL, NULL, \
224
260
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;
261
+
262
+ #define CODEC_STATEFUL (enc ) \
263
+ st->codec_list[idx++] = (MultibyteCodec){#enc, NULL, NULL, _STATEFUL_METHODS(enc)};
264
+ #define CODEC_STATELESS (enc ) \
265
+ st->codec_list[idx++] = (MultibyteCodec){#enc, NULL, NULL, _STATELESS_METHODS(enc)};
266
+ #define CODEC_STATELESS_WINIT (enc ) \
267
+ st->codec_list[idx++] = (MultibyteCodec){#enc, NULL, enc##_codec_init, _STATELESS_METHODS(enc)};
268
+
269
+ #define END_CODECS_LIST \
270
+ assert(st->num_codecs == idx); \
271
+ return 0; \
272
+ }
242
273
243
274
244
275
@@ -249,53 +280,70 @@ getmultibytecodec(void)
249
280
}
250
281
251
282
static PyObject *
252
- getcodec ( PyObject * self , PyObject * encoding )
283
+ _getcodec ( const MultibyteCodec * codec )
253
284
{
254
- PyObject * codecobj , * r , * cofunc ;
255
- const MultibyteCodec * codec ;
256
- const char * enc ;
257
-
258
- if (!PyUnicode_Check (encoding )) {
259
- PyErr_SetString (PyExc_TypeError ,
260
- "encoding name must be a string." );
285
+ PyObject * cofunc = getmultibytecodec ();
286
+ if (cofunc == NULL ) {
261
287
return NULL ;
262
288
}
263
- enc = PyUnicode_AsUTF8 (encoding );
264
- if (enc == NULL )
265
- return NULL ;
266
289
267
- cofunc = getmultibytecodec ();
268
- if (cofunc == NULL )
290
+ PyObject * codecobj = PyCapsule_New ((void * )codec ,
291
+ PyMultibyteCodec_CAPSULE_NAME ,
292
+ NULL );
293
+ if (codecobj == NULL ) {
294
+ Py_DECREF (cofunc );
269
295
return NULL ;
296
+ }
270
297
271
- for (codec = codec_list ; codec -> encoding [0 ]; codec ++ )
272
- if (strcmp (codec -> encoding , enc ) == 0 )
273
- break ;
298
+ PyObject * res = PyObject_CallOneArg (cofunc , codecobj );
299
+ Py_DECREF (codecobj );
300
+ Py_DECREF (cofunc );
301
+ return res ;
302
+ }
274
303
275
- if (codec -> encoding [0 ] == '\0' ) {
276
- PyErr_SetString (PyExc_LookupError ,
277
- "no such codec is supported." );
304
+ static PyObject *
305
+ getcodec (PyObject * self , PyObject * encoding )
306
+ {
307
+ if (!PyUnicode_Check (encoding )) {
308
+ PyErr_SetString (PyExc_TypeError ,
309
+ "encoding name must be a string." );
278
310
return NULL ;
279
311
}
280
-
281
- codecobj = PyCapsule_New ((void * )codec , PyMultibyteCodec_CAPSULE_NAME , NULL );
282
- if (codecobj == NULL )
312
+ const char * enc = PyUnicode_AsUTF8 (encoding );
313
+ if (enc == NULL ) {
283
314
return NULL ;
315
+ }
284
316
285
- r = PyObject_CallOneArg (cofunc , codecobj );
286
- Py_DECREF (codecobj );
287
- Py_DECREF (cofunc );
317
+ cjkcodecs_module_state * st = get_module_state (self );
318
+ for (int i = 0 ; i < st -> num_codecs ; i ++ ) {
319
+ const MultibyteCodec * codec = & st -> codec_list [i ];
320
+ if (strcmp (codec -> encoding , enc ) == 0 ) {
321
+ return _getcodec (codec );
322
+ }
323
+ }
288
324
289
- return r ;
325
+ PyErr_SetString (PyExc_LookupError ,
326
+ "no such codec is supported." );
327
+ return NULL ;
290
328
}
291
329
330
+ static int add_mappings (cjkcodecs_module_state * );
331
+ static int add_codecs (cjkcodecs_module_state * );
292
332
293
333
static int
294
334
register_maps (PyObject * module )
295
335
{
296
- const struct dbcs_map * h ;
336
+ // Init module state.
337
+ cjkcodecs_module_state * st = get_module_state (module );
338
+ if (add_mappings (st ) < 0 ) {
339
+ return -1 ;
340
+ }
341
+ if (add_codecs (st ) < 0 ) {
342
+ return -1 ;
343
+ }
297
344
298
- for (h = mapping_list ; h -> charset [0 ] != '\0' ; h ++ ) {
345
+ for (int i = 0 ; i < st -> num_mappings ; i ++ ) {
346
+ const struct dbcs_map * h = & st -> mapping_list [i ];
299
347
char mhname [256 ] = "__map_" ;
300
348
strcpy (mhname + sizeof ("__map_" ) - 1 , h -> charset );
301
349
@@ -394,6 +442,13 @@ _cjk_exec(PyObject *module)
394
442
return register_maps (module );
395
443
}
396
444
445
+ static void
446
+ _cjk_free (void * mod )
447
+ {
448
+ cjkcodecs_module_state * st = get_module_state ((PyObject * )mod );
449
+ PyMem_Free (st -> mapping_list );
450
+ PyMem_Free (st -> codec_list );
451
+ }
397
452
398
453
static struct PyMethodDef _cjk_methods [] = {
399
454
{"getcodec" , (PyCFunction )getcodec , METH_O , "" },
@@ -409,9 +464,10 @@ static PyModuleDef_Slot _cjk_slots[] = {
409
464
static struct PyModuleDef _cjk_module = { \
410
465
PyModuleDef_HEAD_INIT, \
411
466
.m_name = "_codecs_"#loc, \
412
- .m_size = 0, \
467
+ .m_size = sizeof(cjkcodecs_module_state), \
413
468
.m_methods = _cjk_methods, \
414
469
.m_slots = _cjk_slots, \
470
+ .m_free = _cjk_free, \
415
471
}; \
416
472
\
417
473
PyMODINIT_FUNC \
0 commit comments