@@ -171,18 +171,26 @@ _PyLong_New(Py_ssize_t size)
171171PyLongObject *
172172_PyLong_FromDigits (int negative , Py_ssize_t digit_count , digit * digits )
173173{
174- assert (digit_count >= 0 );
175- if (digit_count == 0 ) {
176- return (PyLongObject * )_PyLong_GetZero ();
177- }
178- PyLongObject * result = _PyLong_New (digit_count );
179- if (result == NULL ) {
180- PyErr_NoMemory ();
174+ PyLongWriter * writer = PyLongWriter_Create ();
175+ if (writer == NULL ) {
181176 return NULL ;
182177 }
183- _PyLong_SetSignAndDigitCount (result , negative ?-1 :1 , digit_count );
184- memcpy (result -> long_value .ob_digit , digits , digit_count * sizeof (digit ));
185- return result ;
178+
179+ if (negative ) {
180+ PyLongWriter_SetSign (writer , -1 );
181+ }
182+
183+ Py_digit * writer_digits = PyLongWriter_AllocDigits (writer , digit_count );
184+ if (writer_digits == NULL ) {
185+ goto error ;
186+ }
187+ memcpy (writer_digits , digits , digit_count * sizeof (digit ));
188+
189+ return (PyLongObject * )PyLongWriter_Finish (writer );
190+
191+ error :
192+ PyLongWriter_Discard (writer );
193+ return NULL ;
186194}
187195
188196PyObject *
@@ -6729,3 +6737,70 @@ PyUnstable_Long_ReleaseExport(PyUnstable_Long_DigitArray *array)
67296737 array -> ndigits = 0 ;
67306738 array -> digits = NULL ;
67316739}
6740+
6741+
6742+ /* --- PyLongWriter API --------------------------------------------------- */
6743+
6744+ struct PyLongWriter {
6745+ PyLongObject * obj ;
6746+ int sign ;
6747+ };
6748+
6749+ PyLongWriter * PyLongWriter_Create (void )
6750+ {
6751+ PyLongWriter * writer = PyMem_Malloc (sizeof (PyLongWriter ));
6752+ if (writer == NULL ) {
6753+ PyErr_NoMemory ();
6754+ return NULL ;
6755+ }
6756+ writer -> obj = NULL ;
6757+ writer -> sign = 1 ;
6758+ return writer ;
6759+ }
6760+
6761+ Py_digit * PyLongWriter_AllocDigits (PyLongWriter * writer , size_t ndigits )
6762+ {
6763+ Py_CLEAR (writer -> obj );
6764+
6765+ if (ndigits > (size_t )PY_SSIZE_T_MAX ) {
6766+ PyErr_NoMemory ();
6767+ return NULL ;
6768+ }
6769+
6770+ writer -> obj = _PyLong_New (ndigits );
6771+ if (writer -> obj == NULL ) {
6772+ return NULL ;
6773+ }
6774+
6775+ return writer -> obj -> long_value .ob_digit ;
6776+ }
6777+
6778+ void PyLongWriter_SetSign (PyLongWriter * writer , int sign )
6779+ {
6780+ writer -> sign = sign ;
6781+ }
6782+
6783+ PyObject * PyLongWriter_Finish (PyLongWriter * writer )
6784+ {
6785+ if (writer -> obj ) {
6786+ assert (Py_REFCNT (writer -> obj ) == 1 );
6787+
6788+ if (writer -> sign < 0 && _PyLong_IsPositive (writer -> obj )) {
6789+ _PyLong_FlipSign (writer -> obj );
6790+ }
6791+
6792+ writer -> obj = maybe_small_long (long_normalize (writer -> obj ));
6793+ }
6794+ else {
6795+ writer -> obj = (PyLongObject * )Py_NewRef (_PyLong_GetZero ());
6796+ }
6797+
6798+ PyObject * res = (PyObject * )writer -> obj ;
6799+ PyMem_Free (writer );
6800+ return res ;
6801+ }
6802+
6803+ void PyLongWriter_Discard (PyLongWriter * writer )
6804+ {
6805+ PyMem_Free (writer );
6806+ }
0 commit comments