46
46
#endif
47
47
48
48
struct PyDecContextObject ;
49
+ struct DecCondMap ;
49
50
50
51
typedef struct {
51
52
PyTypeObject * PyDecContextManager_Type ;
@@ -82,6 +83,9 @@ typedef struct {
82
83
83
84
PyObject * SignalTuple ;
84
85
86
+ struct DecCondMap * signal_map ;
87
+ struct DecCondMap * cond_map ;
88
+
85
89
/* External C-API functions */
86
90
binaryfunc _py_long_multiply ;
87
91
binaryfunc _py_long_floor_divide ;
@@ -181,7 +185,7 @@ incr_false(void)
181
185
#define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
182
186
#define DEC_ERRORS (DEC_INVALID_SIGNALS|DEC_ERR_OCCURRED)
183
187
184
- typedef struct {
188
+ typedef struct DecCondMap {
185
189
const char * name ; /* condition or signal name */
186
190
const char * fqname ; /* fully qualified name */
187
191
uint32_t flag ; /* libmpdec flag */
@@ -193,7 +197,7 @@ typedef struct {
193
197
#define INEXACT 6
194
198
#define ROUNDED 7
195
199
#define SIGNAL_MAP_LEN 9
196
- static DecCondMap signal_map [] = {
200
+ static DecCondMap signal_map_template [] = {
197
201
{"InvalidOperation" , "decimal.InvalidOperation" , MPD_IEEE_Invalid_operation , NULL },
198
202
{"FloatOperation" , "decimal.FloatOperation" , MPD_Float_operation , NULL },
199
203
{"DivisionByZero" , "decimal.DivisionByZero" , MPD_Division_by_zero , NULL },
@@ -207,7 +211,7 @@ static DecCondMap signal_map[] = {
207
211
};
208
212
209
213
/* Exceptions that inherit from InvalidOperation */
210
- static DecCondMap cond_map [] = {
214
+ static DecCondMap cond_map_template [] = {
211
215
{"InvalidOperation" , "decimal.InvalidOperation" , MPD_Invalid_operation , NULL },
212
216
{"ConversionSyntax" , "decimal.ConversionSyntax" , MPD_Conversion_syntax , NULL },
213
217
{"DivisionImpossible" , "decimal.DivisionImpossible" , MPD_Division_impossible , NULL },
@@ -219,6 +223,21 @@ static DecCondMap cond_map[] = {
219
223
{NULL }
220
224
};
221
225
226
+ /* Return a duplicate of DecCondMap template */
227
+ static inline DecCondMap *
228
+ dec_cond_map_init (DecCondMap * template , Py_ssize_t size )
229
+ {
230
+ DecCondMap * cm ;
231
+ cm = PyMem_Malloc (size );
232
+ if (cm == NULL ) {
233
+ PyErr_NoMemory ();
234
+ return NULL ;
235
+ }
236
+
237
+ memcpy (cm , template , size );
238
+ return cm ;
239
+ }
240
+
222
241
static const char * dec_signal_string [MPD_NUM_FLAGS ] = {
223
242
"Clamped" ,
224
243
"InvalidOperation" ,
@@ -312,8 +331,9 @@ static PyObject *
312
331
flags_as_exception (uint32_t flags )
313
332
{
314
333
DecCondMap * cm ;
334
+ decimal_state * state = GLOBAL_STATE ();
315
335
316
- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
336
+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
317
337
if (flags & cm -> flag ) {
318
338
return cm -> ex ;
319
339
}
@@ -326,8 +346,9 @@ Py_LOCAL_INLINE(uint32_t)
326
346
exception_as_flag (PyObject * ex )
327
347
{
328
348
DecCondMap * cm ;
349
+ decimal_state * state = GLOBAL_STATE ();
329
350
330
- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
351
+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
331
352
if (cm -> ex == ex ) {
332
353
return cm -> flag ;
333
354
}
@@ -342,20 +363,21 @@ flags_as_list(uint32_t flags)
342
363
{
343
364
PyObject * list ;
344
365
DecCondMap * cm ;
366
+ decimal_state * state = GLOBAL_STATE ();
345
367
346
368
list = PyList_New (0 );
347
369
if (list == NULL ) {
348
370
return NULL ;
349
371
}
350
372
351
- for (cm = cond_map ; cm -> name != NULL ; cm ++ ) {
373
+ for (cm = state -> cond_map ; cm -> name != NULL ; cm ++ ) {
352
374
if (flags & cm -> flag ) {
353
375
if (PyList_Append (list , cm -> ex ) < 0 ) {
354
376
goto error ;
355
377
}
356
378
}
357
379
}
358
- for (cm = signal_map + 1 ; cm -> name != NULL ; cm ++ ) {
380
+ for (cm = state -> signal_map + 1 ; cm -> name != NULL ; cm ++ ) {
359
381
if (flags & cm -> flag ) {
360
382
if (PyList_Append (list , cm -> ex ) < 0 ) {
361
383
goto error ;
@@ -375,13 +397,14 @@ signals_as_list(uint32_t flags)
375
397
{
376
398
PyObject * list ;
377
399
DecCondMap * cm ;
400
+ decimal_state * state = GLOBAL_STATE ();
378
401
379
402
list = PyList_New (0 );
380
403
if (list == NULL ) {
381
404
return NULL ;
382
405
}
383
406
384
- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
407
+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
385
408
if (flags & cm -> flag ) {
386
409
if (PyList_Append (list , cm -> ex ) < 0 ) {
387
410
Py_DECREF (list );
@@ -421,13 +444,14 @@ flags_as_dict(uint32_t flags)
421
444
{
422
445
DecCondMap * cm ;
423
446
PyObject * dict ;
447
+ decimal_state * state = GLOBAL_STATE ();
424
448
425
449
dict = PyDict_New ();
426
450
if (dict == NULL ) {
427
451
return NULL ;
428
452
}
429
453
430
- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
454
+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
431
455
PyObject * b = flags & cm -> flag ? Py_True : Py_False ;
432
456
if (PyDict_SetItem (dict , cm -> ex , b ) < 0 ) {
433
457
Py_DECREF (dict );
@@ -445,6 +469,7 @@ dict_as_flags(PyObject *val)
445
469
DecCondMap * cm ;
446
470
uint32_t flags = 0 ;
447
471
int x ;
472
+ decimal_state * state = GLOBAL_STATE ();
448
473
449
474
if (!PyDict_Check (val )) {
450
475
PyErr_SetString (PyExc_TypeError ,
@@ -458,7 +483,7 @@ dict_as_flags(PyObject *val)
458
483
return DEC_INVALID_SIGNALS ;
459
484
}
460
485
461
- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
486
+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
462
487
b = PyDict_GetItemWithError (val , cm -> ex );
463
488
if (b == NULL ) {
464
489
if (PyErr_Occurred ()) {
@@ -652,7 +677,8 @@ signaldict_repr(PyObject *self)
652
677
653
678
assert (SIGNAL_MAP_LEN == 9 );
654
679
655
- for (cm = signal_map , i = 0 ; cm -> name != NULL ; cm ++ , i ++ ) {
680
+ decimal_state * state = GLOBAL_STATE ();
681
+ for (cm = state -> signal_map , i = 0 ; cm -> name != NULL ; cm ++ , i ++ ) {
656
682
n [i ] = cm -> fqname ;
657
683
b [i ] = SdFlags (self )& cm -> flag ? "True" : "False" ;
658
684
}
@@ -5922,10 +5948,12 @@ PyInit__decimal(void)
5922
5948
ASSIGN_PTR (state -> SignalTuple , PyTuple_New (SIGNAL_MAP_LEN ));
5923
5949
5924
5950
/* Add exceptions that correspond to IEEE signals */
5951
+ ASSIGN_PTR (state -> signal_map , dec_cond_map_init (signal_map_template ,
5952
+ sizeof (signal_map_template )));
5925
5953
for (i = SIGNAL_MAP_LEN - 1 ; i >= 0 ; i -- ) {
5926
5954
PyObject * base ;
5927
5955
5928
- cm = signal_map + i ;
5956
+ cm = state -> signal_map + i ;
5929
5957
5930
5958
switch (cm -> flag ) {
5931
5959
case MPD_Float_operation :
@@ -5936,13 +5964,13 @@ PyInit__decimal(void)
5936
5964
PyExc_ZeroDivisionError );
5937
5965
break ;
5938
5966
case MPD_Overflow :
5939
- base = PyTuple_Pack (2 , signal_map [INEXACT ].ex ,
5940
- signal_map [ROUNDED ].ex );
5967
+ base = PyTuple_Pack (2 , state -> signal_map [INEXACT ].ex ,
5968
+ state -> signal_map [ROUNDED ].ex );
5941
5969
break ;
5942
5970
case MPD_Underflow :
5943
- base = PyTuple_Pack (3 , signal_map [INEXACT ].ex ,
5944
- signal_map [ROUNDED ].ex ,
5945
- signal_map [SUBNORMAL ].ex );
5971
+ base = PyTuple_Pack (3 , state -> signal_map [INEXACT ].ex ,
5972
+ state -> signal_map [ROUNDED ].ex ,
5973
+ state -> signal_map [SUBNORMAL ].ex );
5946
5974
break ;
5947
5975
default :
5948
5976
base = PyTuple_Pack (1 , state -> DecimalException );
@@ -5968,16 +5996,18 @@ PyInit__decimal(void)
5968
5996
* several conditions, including InvalidOperation! Naming the
5969
5997
* signal IEEEInvalidOperation would prevent the confusion.
5970
5998
*/
5971
- cond_map [0 ].ex = signal_map [0 ].ex ;
5999
+ ASSIGN_PTR (state -> cond_map , dec_cond_map_init (cond_map_template ,
6000
+ sizeof (cond_map_template )));
6001
+ state -> cond_map [0 ].ex = state -> signal_map [0 ].ex ;
5972
6002
5973
6003
/* Add remaining exceptions, inherit from InvalidOperation */
5974
- for (cm = cond_map + 1 ; cm -> name != NULL ; cm ++ ) {
6004
+ for (cm = state -> cond_map + 1 ; cm -> name != NULL ; cm ++ ) {
5975
6005
PyObject * base ;
5976
6006
if (cm -> flag == MPD_Division_undefined ) {
5977
- base = PyTuple_Pack (2 , signal_map [0 ].ex , PyExc_ZeroDivisionError );
6007
+ base = PyTuple_Pack (2 , state -> signal_map [0 ].ex , PyExc_ZeroDivisionError );
5978
6008
}
5979
6009
else {
5980
- base = PyTuple_Pack (1 , signal_map [0 ].ex );
6010
+ base = PyTuple_Pack (1 , state -> signal_map [0 ].ex );
5981
6011
}
5982
6012
if (base == NULL ) {
5983
6013
goto error ; /* GCOV_NOT_REACHED */
@@ -6057,6 +6087,8 @@ PyInit__decimal(void)
6057
6087
Py_CLEAR (collections_abc ); /* GCOV_NOT_REACHED */
6058
6088
Py_CLEAR (MutableMapping ); /* GCOV_NOT_REACHED */
6059
6089
Py_CLEAR (state -> SignalTuple ); /* GCOV_NOT_REACHED */
6090
+ PyMem_Free (state -> signal_map ); /* GCOV_NOT_REACHED */
6091
+ PyMem_Free (state -> cond_map ); /* GCOV_NOT_REACHED */
6060
6092
Py_CLEAR (state -> DecimalTuple ); /* GCOV_NOT_REACHED */
6061
6093
Py_CLEAR (state -> default_context_template ); /* GCOV_NOT_REACHED */
6062
6094
#ifndef WITH_DECIMAL_CONTEXTVAR
0 commit comments