4646#endif
4747
4848struct PyDecContextObject ;
49+ struct DecCondMap ;
4950
5051typedef struct {
5152 PyTypeObject * PyDecContextManager_Type ;
@@ -82,6 +83,9 @@ typedef struct {
8283
8384 PyObject * SignalTuple ;
8485
86+ struct DecCondMap * signal_map ;
87+ struct DecCondMap * cond_map ;
88+
8589 /* External C-API functions */
8690 binaryfunc _py_long_multiply ;
8791 binaryfunc _py_long_floor_divide ;
@@ -181,7 +185,7 @@ incr_false(void)
181185#define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
182186#define DEC_ERRORS (DEC_INVALID_SIGNALS|DEC_ERR_OCCURRED)
183187
184- typedef struct {
188+ typedef struct DecCondMap {
185189 const char * name ; /* condition or signal name */
186190 const char * fqname ; /* fully qualified name */
187191 uint32_t flag ; /* libmpdec flag */
@@ -193,7 +197,7 @@ typedef struct {
193197#define INEXACT 6
194198#define ROUNDED 7
195199#define SIGNAL_MAP_LEN 9
196- static DecCondMap signal_map [] = {
200+ static DecCondMap signal_map_template [] = {
197201 {"InvalidOperation" , "decimal.InvalidOperation" , MPD_IEEE_Invalid_operation , NULL },
198202 {"FloatOperation" , "decimal.FloatOperation" , MPD_Float_operation , NULL },
199203 {"DivisionByZero" , "decimal.DivisionByZero" , MPD_Division_by_zero , NULL },
@@ -207,7 +211,7 @@ static DecCondMap signal_map[] = {
207211};
208212
209213/* Exceptions that inherit from InvalidOperation */
210- static DecCondMap cond_map [] = {
214+ static DecCondMap cond_map_template [] = {
211215 {"InvalidOperation" , "decimal.InvalidOperation" , MPD_Invalid_operation , NULL },
212216 {"ConversionSyntax" , "decimal.ConversionSyntax" , MPD_Conversion_syntax , NULL },
213217 {"DivisionImpossible" , "decimal.DivisionImpossible" , MPD_Division_impossible , NULL },
@@ -219,6 +223,21 @@ static DecCondMap cond_map[] = {
219223 {NULL }
220224};
221225
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+
222241static const char * dec_signal_string [MPD_NUM_FLAGS ] = {
223242 "Clamped" ,
224243 "InvalidOperation" ,
@@ -312,8 +331,9 @@ static PyObject *
312331flags_as_exception (uint32_t flags )
313332{
314333 DecCondMap * cm ;
334+ decimal_state * state = GLOBAL_STATE ();
315335
316- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
336+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
317337 if (flags & cm -> flag ) {
318338 return cm -> ex ;
319339 }
@@ -326,8 +346,9 @@ Py_LOCAL_INLINE(uint32_t)
326346exception_as_flag (PyObject * ex )
327347{
328348 DecCondMap * cm ;
349+ decimal_state * state = GLOBAL_STATE ();
329350
330- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
351+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
331352 if (cm -> ex == ex ) {
332353 return cm -> flag ;
333354 }
@@ -342,20 +363,21 @@ flags_as_list(uint32_t flags)
342363{
343364 PyObject * list ;
344365 DecCondMap * cm ;
366+ decimal_state * state = GLOBAL_STATE ();
345367
346368 list = PyList_New (0 );
347369 if (list == NULL ) {
348370 return NULL ;
349371 }
350372
351- for (cm = cond_map ; cm -> name != NULL ; cm ++ ) {
373+ for (cm = state -> cond_map ; cm -> name != NULL ; cm ++ ) {
352374 if (flags & cm -> flag ) {
353375 if (PyList_Append (list , cm -> ex ) < 0 ) {
354376 goto error ;
355377 }
356378 }
357379 }
358- for (cm = signal_map + 1 ; cm -> name != NULL ; cm ++ ) {
380+ for (cm = state -> signal_map + 1 ; cm -> name != NULL ; cm ++ ) {
359381 if (flags & cm -> flag ) {
360382 if (PyList_Append (list , cm -> ex ) < 0 ) {
361383 goto error ;
@@ -375,13 +397,14 @@ signals_as_list(uint32_t flags)
375397{
376398 PyObject * list ;
377399 DecCondMap * cm ;
400+ decimal_state * state = GLOBAL_STATE ();
378401
379402 list = PyList_New (0 );
380403 if (list == NULL ) {
381404 return NULL ;
382405 }
383406
384- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
407+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
385408 if (flags & cm -> flag ) {
386409 if (PyList_Append (list , cm -> ex ) < 0 ) {
387410 Py_DECREF (list );
@@ -421,13 +444,14 @@ flags_as_dict(uint32_t flags)
421444{
422445 DecCondMap * cm ;
423446 PyObject * dict ;
447+ decimal_state * state = GLOBAL_STATE ();
424448
425449 dict = PyDict_New ();
426450 if (dict == NULL ) {
427451 return NULL ;
428452 }
429453
430- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
454+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
431455 PyObject * b = flags & cm -> flag ? Py_True : Py_False ;
432456 if (PyDict_SetItem (dict , cm -> ex , b ) < 0 ) {
433457 Py_DECREF (dict );
@@ -445,6 +469,7 @@ dict_as_flags(PyObject *val)
445469 DecCondMap * cm ;
446470 uint32_t flags = 0 ;
447471 int x ;
472+ decimal_state * state = GLOBAL_STATE ();
448473
449474 if (!PyDict_Check (val )) {
450475 PyErr_SetString (PyExc_TypeError ,
@@ -458,7 +483,7 @@ dict_as_flags(PyObject *val)
458483 return DEC_INVALID_SIGNALS ;
459484 }
460485
461- for (cm = signal_map ; cm -> name != NULL ; cm ++ ) {
486+ for (cm = state -> signal_map ; cm -> name != NULL ; cm ++ ) {
462487 b = PyDict_GetItemWithError (val , cm -> ex );
463488 if (b == NULL ) {
464489 if (PyErr_Occurred ()) {
@@ -652,7 +677,8 @@ signaldict_repr(PyObject *self)
652677
653678 assert (SIGNAL_MAP_LEN == 9 );
654679
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 ++ ) {
656682 n [i ] = cm -> fqname ;
657683 b [i ] = SdFlags (self )& cm -> flag ? "True" : "False" ;
658684 }
@@ -5922,10 +5948,12 @@ PyInit__decimal(void)
59225948 ASSIGN_PTR (state -> SignalTuple , PyTuple_New (SIGNAL_MAP_LEN ));
59235949
59245950 /* 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 )));
59255953 for (i = SIGNAL_MAP_LEN - 1 ; i >= 0 ; i -- ) {
59265954 PyObject * base ;
59275955
5928- cm = signal_map + i ;
5956+ cm = state -> signal_map + i ;
59295957
59305958 switch (cm -> flag ) {
59315959 case MPD_Float_operation :
@@ -5936,13 +5964,13 @@ PyInit__decimal(void)
59365964 PyExc_ZeroDivisionError );
59375965 break ;
59385966 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 );
59415969 break ;
59425970 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 );
59465974 break ;
59475975 default :
59485976 base = PyTuple_Pack (1 , state -> DecimalException );
@@ -5968,16 +5996,18 @@ PyInit__decimal(void)
59685996 * several conditions, including InvalidOperation! Naming the
59695997 * signal IEEEInvalidOperation would prevent the confusion.
59705998 */
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 ;
59726002
59736003 /* 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 ++ ) {
59756005 PyObject * base ;
59766006 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 );
59786008 }
59796009 else {
5980- base = PyTuple_Pack (1 , signal_map [0 ].ex );
6010+ base = PyTuple_Pack (1 , state -> signal_map [0 ].ex );
59816011 }
59826012 if (base == NULL ) {
59836013 goto error ; /* GCOV_NOT_REACHED */
@@ -6057,6 +6087,8 @@ PyInit__decimal(void)
60576087 Py_CLEAR (collections_abc ); /* GCOV_NOT_REACHED */
60586088 Py_CLEAR (MutableMapping ); /* GCOV_NOT_REACHED */
60596089 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 */
60606092 Py_CLEAR (state -> DecimalTuple ); /* GCOV_NOT_REACHED */
60616093 Py_CLEAR (state -> default_context_template ); /* GCOV_NOT_REACHED */
60626094#ifndef WITH_DECIMAL_CONTEXTVAR
0 commit comments