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