@@ -1720,6 +1720,185 @@ 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
+ typedef struct PyLongExport {
1766
+ int64_t value;
1767
+ uint8_t negative;
1768
+ Py_ssize_t ndigits;
1769
+ const void *digits;
1770
+ Py_uintptr_t _reserved;
1771
+ } PyLongExport;
1772
+
1773
+ typedef struct PyLongWriter PyLongWriter;
1774
+
1775
+ static inline const PyLongLayout*
1776
+ PyLong_GetNativeLayout (void )
1777
+ {
1778
+ static const PyLongLayout PyLong_LAYOUT = {
1779
+ PyLong_SHIFT,
1780
+ sizeof (digit),
1781
+ -1 , // least significant first
1782
+ PY_LITTLE_ENDIAN ? -1 : 1 ,
1783
+ };
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
+ memset (export_long, 0 , sizeof (*export_long));
1793
+ PyErr_Format (PyExc_TypeError, " expected int, got %s" ,
1794
+ Py_TYPE (obj)->tp_name );
1795
+ return -1 ;
1796
+ }
1797
+
1798
+ // Fast-path: try to convert to a int64_t
1799
+ PyLongObject *self = (PyLongObject*)obj;
1800
+ int overflow;
1801
+ #if SIZEOF_LONG == 8
1802
+ long value = PyLong_AsLongAndOverflow (obj, &overflow);
1803
+ #else
1804
+ // Windows has 32-bit long, so use 64-bit long long instead
1805
+ long long value = PyLong_AsLongLongAndOverflow (obj, &overflow);
1806
+ #endif
1807
+ Py_BUILD_ASSERT (sizeof (value) == sizeof (int64_t ));
1808
+ // the function cannot fail since obj is a PyLongObject
1809
+ assert (!(value == -1 && PyErr_Occurred ()));
1810
+
1811
+ if (!overflow) {
1812
+ export_long->value = value;
1813
+ export_long->negative = 0 ;
1814
+ export_long->ndigits = 0 ;
1815
+ export_long->digits = 0 ;
1816
+ export_long->_reserved = 0 ;
1817
+ }
1818
+ else {
1819
+ export_long->value = 0 ;
1820
+ export_long->negative = _PyLong_Sign (obj) < 0 ;
1821
+ export_long->ndigits = _PyLong_DigitCount (self);
1822
+ if (export_long->ndigits == 0 ) {
1823
+ export_long->ndigits = 1 ;
1824
+ }
1825
+ export_long->digits = _PyLong_GetDigits (self);
1826
+ export_long->_reserved = (Py_uintptr_t)Py_NewRef (obj);
1827
+ }
1828
+ return 0 ;
1829
+ }
1830
+
1831
+ static inline void
1832
+ PyLong_FreeExport (PyLongExport *export_long)
1833
+ {
1834
+ PyObject *obj = (PyObject*)export_long->_reserved ;
1835
+
1836
+ if (obj) {
1837
+ export_long->_reserved = 0 ;
1838
+ Py_DECREF (obj);
1839
+ }
1840
+ }
1841
+
1842
+ static inline PyLongWriter*
1843
+ PyLongWriter_Create (int negative, Py_ssize_t ndigits, void **digits)
1844
+ {
1845
+ if (ndigits <= 0 ) {
1846
+ PyErr_SetString (PyExc_ValueError, " ndigits must be positive" );
1847
+ return NULL ;
1848
+ }
1849
+ assert (digits != NULL );
1850
+
1851
+ PyLongObject *obj = _PyLong_New (ndigits);
1852
+ if (obj == NULL ) {
1853
+ return NULL ;
1854
+ }
1855
+ _PyLong_SetSignAndDigitCount (obj, negative?-1 :1 , ndigits);
1856
+
1857
+ *digits = _PyLong_GetDigits (obj);
1858
+ return (PyLongWriter*)obj;
1859
+ }
1860
+
1861
+ static inline void
1862
+ PyLongWriter_Discard (PyLongWriter *writer)
1863
+ {
1864
+ PyLongObject *obj = (PyLongObject *)writer;
1865
+
1866
+ assert (Py_REFCNT (obj) == 1 );
1867
+ Py_DECREF (obj);
1868
+ }
1869
+
1870
+ static inline PyObject*
1871
+ PyLongWriter_Finish (PyLongWriter *writer)
1872
+ {
1873
+ PyObject *obj = (PyObject *)writer;
1874
+ PyLongObject *self = (PyLongObject*)obj;
1875
+ Py_ssize_t j = _PyLong_DigitCount (self);
1876
+ Py_ssize_t i = j;
1877
+ int sign = _PyLong_Sign (obj);
1878
+
1879
+ assert (Py_REFCNT (obj) == 1 );
1880
+
1881
+ // Normalize and get singleton if possible
1882
+ while (i > 0 && _PyLong_GetDigits (self)[i-1 ] == 0 ) {
1883
+ --i;
1884
+ }
1885
+ if (i != j) {
1886
+ if (i == 0 ) {
1887
+ sign = 0 ;
1888
+ }
1889
+ _PyLong_SetSignAndDigitCount (self, sign, i);
1890
+ }
1891
+ if (i <= 1 ) {
1892
+ long val = sign * (long )(_PyLong_GetDigits (self)[0 ]);
1893
+ Py_DECREF (obj);
1894
+ return PyLong_FromLong (val);
1895
+ }
1896
+
1897
+ return obj;
1898
+ }
1899
+ #endif
1900
+
1901
+
1723
1902
#ifdef __cplusplus
1724
1903
}
1725
1904
#endif
0 commit comments