@@ -1720,6 +1720,187 @@ static inline int PyLong_AsUInt64(PyObject *obj, uint64_t *pvalue)
1720
1720
#endif
1721
1721
1722
1722
1723
+ // gh-102471 added import and export API for integers to 3.14.0a2.
1724
+ #if PY_VERSION_HEX < 0x030E00A2 && PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
1725
+ // Helpers to access PyLongObject internals.
1726
+ static inline void
1727
+ _PyLong_SetSignAndDigitCount (PyLongObject *op, int sign, Py_ssize_t size)
1728
+ {
1729
+ #if PY_VERSION_HEX >= 0x030C0000
1730
+ op->long_value .lv_tag = (uintptr_t )(1 - sign) | ((uintptr_t )(size) << 3 );
1731
+ #elif PY_VERSION_HEX >= 0x030900A4
1732
+ Py_SET_SIZE (op, sign*size);
1733
+ #else
1734
+ Py_SIZE (op) = sign*size;
1735
+ #endif
1736
+ }
1737
+
1738
+ static inline Py_ssize_t
1739
+ _PyLong_DigitCount (const PyLongObject *op)
1740
+ {
1741
+ #if PY_VERSION_HEX >= 0x030C0000
1742
+ return (Py_ssize_t)(op->long_value .lv_tag >> 3 );
1743
+ #else
1744
+ return _PyLong_Sign ((PyObject*)op) < 0 ? -Py_SIZE (op) : Py_SIZE (op);
1745
+ #endif
1746
+ }
1747
+
1748
+ static inline digit*
1749
+ _PyLong_GetDigits (const PyLongObject *op)
1750
+ {
1751
+ #if PY_VERSION_HEX >= 0x030C0000
1752
+ return (digit*)(op->long_value .ob_digit );
1753
+ #else
1754
+ return (digit*)(op->ob_digit );
1755
+ #endif
1756
+ }
1757
+
1758
+ typedef struct PyLongLayout {
1759
+ uint8_t bits_per_digit;
1760
+ uint8_t digit_size;
1761
+ int8_t digits_order;
1762
+ int8_t digit_endianness;
1763
+ } PyLongLayout;
1764
+
1765
+ static const PyLongLayout PyLong_LAYOUT = {
1766
+ PyLong_SHIFT,
1767
+ sizeof (digit),
1768
+ -1 , // least significant first
1769
+ PY_LITTLE_ENDIAN ? -1 : 1 ,
1770
+ };
1771
+
1772
+ typedef struct PyLongExport {
1773
+ int64_t value;
1774
+ uint8_t negative;
1775
+ Py_ssize_t ndigits;
1776
+ const void *digits;
1777
+ Py_uintptr_t _reserved;
1778
+ } PyLongExport;
1779
+
1780
+ typedef struct PyLongWriter PyLongWriter;
1781
+
1782
+ static inline const PyLongLayout*
1783
+ PyLong_GetNativeLayout (void )
1784
+ {
1785
+ return &PyLong_LAYOUT;
1786
+ }
1787
+
1788
+ static inline int
1789
+ PyLong_Export (PyObject *obj, PyLongExport *export_long)
1790
+ {
1791
+ if (!PyLong_Check (obj)) {
1792
+ PyErr_Format (PyExc_TypeError, " expected int, got %s" ,
1793
+ Py_TYPE (obj)->tp_name );
1794
+ return -1 ;
1795
+ }
1796
+
1797
+ // Fast-path: try to convert to a int64_t
1798
+ PyLongObject *self = (PyLongObject*)obj;
1799
+ int overflow;
1800
+ #if SIZEOF_LONG == 8
1801
+ long value = PyLong_AsLongAndOverflow (obj, &overflow);
1802
+ #else
1803
+ // Windows has 32-bit long, so use 64-bit long long instead
1804
+ long long value = PyLong_AsLongLongAndOverflow (obj, &overflow);
1805
+ #endif
1806
+ Py_BUILD_ASSERT (sizeof (value) == sizeof (int64_t ));
1807
+ // the function cannot fail since obj is a PyLongObject
1808
+ assert (!(value == -1 && PyErr_Occurred ()));
1809
+
1810
+ if (!overflow) {
1811
+ export_long->value = value;
1812
+ export_long->negative = 0 ;
1813
+ export_long->ndigits = 0 ;
1814
+ export_long->digits = 0 ;
1815
+ export_long->_reserved = 0 ;
1816
+ }
1817
+ else {
1818
+ export_long->value = 0 ;
1819
+ export_long->negative = _PyLong_Sign (obj) < 0 ;
1820
+ export_long->ndigits = _PyLong_DigitCount (self);
1821
+ if (export_long->ndigits == 0 ) {
1822
+ export_long->ndigits = 1 ;
1823
+ }
1824
+ export_long->digits = _PyLong_GetDigits (self);
1825
+ export_long->_reserved = (Py_uintptr_t)Py_NewRef (obj);
1826
+ }
1827
+ return 0 ;
1828
+ }
1829
+
1830
+ static inline void
1831
+ PyLong_FreeExport (PyLongExport *export_long)
1832
+ {
1833
+ PyObject *obj = (PyObject*)export_long->_reserved ;
1834
+
1835
+ if (obj) {
1836
+ export_long->_reserved = 0 ;
1837
+ Py_DECREF (obj);
1838
+ }
1839
+ }
1840
+
1841
+ static inline PyLongWriter*
1842
+ PyLongWriter_Create (int negative, Py_ssize_t ndigits, void **digits)
1843
+ {
1844
+ if (ndigits < 0 ) {
1845
+ PyErr_SetString (PyExc_ValueError, " ndigits must be positive" );
1846
+ return NULL ;
1847
+ }
1848
+ assert (digits != NULL );
1849
+
1850
+ PyLongObject *obj = _PyLong_New (ndigits);
1851
+ if (obj == NULL ) {
1852
+ return NULL ;
1853
+ }
1854
+ if (ndigits == 0 ) {
1855
+ assert (_PyLong_GetDigits (obj)[0 ] == 0 );
1856
+ }
1857
+ _PyLong_SetSignAndDigitCount (obj, negative?-1 :1 , ndigits);
1858
+
1859
+ *digits = _PyLong_GetDigits (obj);
1860
+ return (PyLongWriter*)obj;
1861
+ }
1862
+
1863
+ static inline void
1864
+ PyLongWriter_Discard (PyLongWriter *writer)
1865
+ {
1866
+ PyLongObject *obj = (PyLongObject *)writer;
1867
+
1868
+ assert (Py_REFCNT (obj) == 1 );
1869
+ Py_DECREF (obj);
1870
+ }
1871
+
1872
+ static inline PyObject*
1873
+ PyLongWriter_Finish (PyLongWriter *writer)
1874
+ {
1875
+ PyObject *obj = (PyObject *)writer;
1876
+ PyLongObject *self = (PyLongObject*)obj;
1877
+ Py_ssize_t j = _PyLong_DigitCount (self);
1878
+ Py_ssize_t i = j;
1879
+ int sign = _PyLong_Sign (obj);
1880
+
1881
+ assert (Py_REFCNT (obj) == 1 );
1882
+
1883
+ // Normalize and get singleton if possible
1884
+ while (i > 0 && _PyLong_GetDigits (self)[i-1 ] == 0 ) {
1885
+ --i;
1886
+ }
1887
+ if (i != j) {
1888
+ if (i == 0 ) {
1889
+ sign = 0 ;
1890
+ }
1891
+ _PyLong_SetSignAndDigitCount (self, sign, i);
1892
+ }
1893
+ if (i <= 1 ) {
1894
+ long val = sign*(long )(_PyLong_GetDigits (self)[0 ]);
1895
+ Py_DECREF (obj);
1896
+ return PyLong_FromLong (val);
1897
+ }
1898
+
1899
+ return obj;
1900
+ }
1901
+ #endif
1902
+
1903
+
1723
1904
#ifdef __cplusplus
1724
1905
}
1725
1906
#endif
0 commit comments