[Python-checkins] cpython (merge default -> default): - merge branches

matthias.klose python-checkins at python.org
Sat Jun 30 18:27:53 CEST 2012


http://hg.python.org/cpython/rev/3fae2a4443ff
changeset:   77880:3fae2a4443ff
parent:      77879:e6e99d449bdc
parent:      77878:dbc94178703f
user:        Matthias Klose <doko at ubuntu.com>
date:        Sat Jun 30 18:26:26 2012 +0200
summary:
  - merge branches

files:
  Lib/test/test_zipfile.py              |   18 +
  Modules/_decimal/_decimal.c           |   38 +-
  Modules/_decimal/libmpdec/basearith.c |   27 +-
  Modules/_decimal/libmpdec/basearith.h |    6 +-
  Modules/_decimal/libmpdec/mpdecimal.c |  694 ++++++++-----
  Modules/_decimal/libmpdec/mpdecimal.h |   10 +-
  setup.py                              |    2 +-
  7 files changed, 512 insertions(+), 283 deletions(-)


diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -1134,6 +1134,24 @@
         with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
             self.assertEqual(zipfr.comment, comment2)
 
+        # check that comments are correctly modified in append mode
+        with zipfile.ZipFile(TESTFN,mode="w") as zipf:
+            zipf.comment = b"original comment"
+            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+        with zipfile.ZipFile(TESTFN,mode="a") as zipf:
+            zipf.comment = b"an updated comment"
+        with zipfile.ZipFile(TESTFN,mode="r") as zipf:
+            self.assertEqual(zipf.comment, b"an updated comment")
+
+        # check that comments are correctly shortened in append mode
+        with zipfile.ZipFile(TESTFN,mode="w") as zipf:
+            zipf.comment = b"original comment that's longer"
+            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+        with zipfile.ZipFile(TESTFN,mode="a") as zipf:
+            zipf.comment = b"shorter comment"
+        with zipfile.ZipFile(TESTFN,mode="r") as zipf:
+            self.assertEqual(zipf.comment, b"shorter comment")
+
     def test_unicode_comment(self):
         with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf:
             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -3203,7 +3203,8 @@
 dec_as_long(PyObject *dec, PyObject *context, int round)
 {
     PyLongObject *pylong;
-    size_t maxsize, n;
+    digit *ob_digit;
+    size_t n;
     Py_ssize_t i;
     mpd_t *x;
     mpd_context_t workctx;
@@ -3234,32 +3235,33 @@
         return NULL;
     }
 
-    maxsize = mpd_sizeinbase(x, PyLong_BASE);
-    if (maxsize > PY_SSIZE_T_MAX) {
-        mpd_del(x);
+    status = 0;
+    ob_digit = NULL;
+#if PYLONG_BITS_IN_DIGIT == 30
+    n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status);
+#elif PYLONG_BITS_IN_DIGIT == 15
+    n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status);
+#else
+    #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
+#endif
+
+    if (n == SIZE_MAX) {
         PyErr_NoMemory();
-        return NULL;
-    }
-    pylong = _PyLong_New(maxsize);
-    if (pylong == NULL) {
         mpd_del(x);
         return NULL;
     }
 
-    status = 0;
-#if PYLONG_BITS_IN_DIGIT == 30
-    n = mpd_qexport_u32(pylong->ob_digit, maxsize, PyLong_BASE, x, &status);
-#elif PYLONG_BITS_IN_DIGIT == 15
-    n = mpd_qexport_u16(pylong->ob_digit, maxsize, PyLong_BASE, x, &status);
-#else
-  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
-#endif
-    if (dec_addstatus(context, status)) {
-        Py_DECREF((PyObject *) pylong);
+    assert(n > 0);
+    pylong = _PyLong_New(n);
+    if (pylong == NULL) {
+        mpd_free(ob_digit);
         mpd_del(x);
         return NULL;
     }
 
+    memcpy(pylong->ob_digit, ob_digit, n * sizeof(digit));
+    mpd_free(ob_digit);
+
     i = n;
     while ((i > 0) && (pylong->ob_digit[i-1] == 0)) {
         i--;
diff --git a/Modules/_decimal/libmpdec/basearith.c b/Modules/_decimal/libmpdec/basearith.c
--- a/Modules/_decimal/libmpdec/basearith.c
+++ b/Modules/_decimal/libmpdec/basearith.c
@@ -583,8 +583,30 @@
     return carry;
 }
 
+/* w := product of u (len n) and v (single word). Return carry. */
+mpd_uint_t
+_mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
+{
+    mpd_uint_t hi, lo;
+    mpd_uint_t carry = 0;
+    mpd_size_t i;
+
+    assert(n > 0);
+
+    for (i=0; i < n; i++) {
+
+        _mpd_mul_words(&hi, &lo, u[i], v);
+        lo = carry + lo;
+        if (lo < carry) hi++;
+
+        _mpd_div_words_r(&carry, &w[i], hi, lo);
+    }
+
+    return carry;
+}
+
 /* w := product of u (len n) and v (single word) */
-void
+mpd_uint_t
 _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                 mpd_uint_t v, mpd_uint_t b)
 {
@@ -602,7 +624,8 @@
 
         _mpd_div_words(&carry, &w[i], hi, lo, b);
     }
-    w[i] = carry;
+
+    return carry;
 }
 
 /*
diff --git a/Modules/_decimal/libmpdec/basearith.h b/Modules/_decimal/libmpdec/basearith.h
--- a/Modules/_decimal/libmpdec/basearith.h
+++ b/Modules/_decimal/libmpdec/basearith.h
@@ -49,8 +49,10 @@
                   mpd_size_t m, mpd_size_t n);
 void _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                    mpd_uint_t v);
-void _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
-                     mpd_uint_t v, mpd_uint_t b);
+mpd_uint_t _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
+                           mpd_uint_t v);
+mpd_uint_t _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
+                           mpd_uint_t v, mpd_uint_t b);
 mpd_uint_t _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
                          mpd_uint_t v);
 mpd_uint_t _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c
--- a/Modules/_decimal/libmpdec/mpdecimal.c
+++ b/Modules/_decimal/libmpdec/mpdecimal.c
@@ -36,7 +36,6 @@
 #include "bits.h"
 #include "convolute.h"
 #include "crt.h"
-#include "errno.h"
 #include "memory.h"
 #include "typearith.h"
 #include "umodarith.h"
@@ -52,9 +51,6 @@
   #endif
 #endif
 
-#if defined(__x86_64__) && defined(__GLIBC__) && !defined(__INTEL_COMPILER)
-  #define USE_80BIT_LONG_DOUBLE
-#endif
 
 #if defined(_MSC_VER)
   #define ALWAYS_INLINE __forceinline
@@ -7567,270 +7563,449 @@
 /*                              Base conversions                              */
 /******************************************************************************/
 
+/* Space needed to represent an integer mpd_t in base 'base'. */
+size_t
+mpd_sizeinbase(const mpd_t *a, uint32_t base)
+{
+    double x;
+    size_t digits;
+
+    assert(mpd_isinteger(a));
+    assert(base >= 2);
+
+    if (mpd_iszero(a)) {
+        return 1;
+    }
+
+    digits = a->digits+a->exp;
+    assert(digits > 0);
+
+#ifdef CONFIG_64
+    /* ceil(2711437152599294 / log10(2)) + 4 == 2**53 */
+    if (digits > 2711437152599294ULL) {
+        return SIZE_MAX;
+    }
+#endif
+
+    x = (double)digits / log10(base);
+    return (x > SIZE_MAX-1) ? SIZE_MAX : (size_t)x + 1;
+}
+
+/* Space needed to import a base 'base' integer of length 'srclen'. */
+static mpd_ssize_t
+_mpd_importsize(size_t srclen, uint32_t base)
+{
+    double x;
+
+    assert(srclen > 0);
+    assert(base >= 2);
+
+#if SIZE_MAX == UINT64_MAX
+    if (srclen > (1ULL<<53)) {
+        return MPD_SSIZE_MAX;
+    }
+#endif
+
+    x = (double)srclen * (log10(base)/MPD_RDIGITS);
+    return (x >= MPD_MAXIMPORT) ? MPD_SSIZE_MAX : (mpd_ssize_t)x + 1;
+}
+
+static uint8_t
+mpd_resize_u16(uint16_t **w, size_t nmemb)
+{
+    uint8_t err = 0;
+    *w = mpd_realloc(*w, nmemb, sizeof **w, &err);
+    return !err;
+}
+
+static uint8_t
+mpd_resize_u32(uint32_t **w, size_t nmemb)
+{
+    uint8_t err = 0;
+    *w = mpd_realloc(*w, nmemb, sizeof **w, &err);
+    return !err;
+}
+
+static size_t
+_baseconv_to_u16(uint16_t **w, size_t wlen, mpd_uint_t wbase,
+                 mpd_uint_t *u, mpd_ssize_t ulen)
+{
+    size_t n = 0;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(wbase <= (1U<<16));
+
+    do {
+        if (n >= wlen) {
+            if (!mpd_resize_u16(w, n+1)) {
+                return SIZE_MAX;
+            }
+            wlen = n+1;
+        }
+        (*w)[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);
+        /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */
+        ulen = _mpd_real_size(u, ulen);
+
+    } while (u[ulen-1] != 0);
+
+    return n;
+}
+
+static size_t
+_coeff_from_u16(mpd_t *w, mpd_ssize_t wlen,
+                const mpd_uint_t *u, size_t ulen, uint32_t ubase,
+                uint32_t *status)
+{
+    mpd_ssize_t n = 0;
+    mpd_uint_t carry;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(ubase <= (1U<<16));
+
+    w->data[n++] = u[--ulen];
+    while (--ulen != SIZE_MAX) {
+        carry = _mpd_shortmul_c(w->data, w->data, n, ubase);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_qresize(w, n+1, status)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            w->data[n++] = carry;
+        }
+        carry = _mpd_shortadd(w->data, n, u[ulen]);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_qresize(w, n+1, status)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            w->data[n++] = carry;
+        }
+    }
+
+    return n;
+}
+
+/* target base wbase < source base ubase */
+static size_t
+_baseconv_to_smaller(uint32_t **w, size_t wlen, uint32_t wbase,
+                     mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase)
+{
+    size_t n = 0;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(wbase < ubase);
+
+    do {
+        if (n >= wlen) {
+            if (!mpd_resize_u32(w, n+1)) {
+                return SIZE_MAX;
+            }
+            wlen = n+1;
+        }
+        (*w)[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
+        /* ulen will be at least 1. u[ulen-1] can only be zero if ulen == 1 */
+        ulen = _mpd_real_size(u, ulen);
+
+    } while (u[ulen-1] != 0);
+
+    return n;
+}
+
+#ifdef CONFIG_32
+/* target base 'wbase' == source base 'ubase' */
+static size_t
+_copy_equal_base(uint32_t **w, size_t wlen,
+                 const uint32_t *u, size_t ulen)
+{
+    if (wlen < ulen) {
+        if (!mpd_resize_u32(w, ulen)) {
+            return SIZE_MAX;
+        }
+    }
+
+    memcpy(*w, u, ulen * (sizeof **w));
+    return ulen;
+}
+
+/* target base 'wbase' > source base 'ubase' */
+static size_t
+_baseconv_to_larger(uint32_t **w, size_t wlen, mpd_uint_t wbase,
+                    const mpd_uint_t *u, size_t ulen, mpd_uint_t ubase)
+{
+    size_t n = 0;
+    mpd_uint_t carry;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(ubase < wbase);
+
+    (*w)[n++] = u[--ulen];
+    while (--ulen != SIZE_MAX) {
+        carry = _mpd_shortmul_b(*w, *w, n, ubase, wbase);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_resize_u32(w, n+1)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            (*w)[n++] = carry;
+        }
+        carry = _mpd_shortadd_b(*w, n, u[ulen], wbase);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_resize_u32(w, n+1)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            (*w)[n++] = carry;
+        }
+    }
+
+    return n;
+}
+
+/* target base wbase < source base ubase */
+static size_t
+_coeff_from_larger_base(mpd_t *w, size_t wlen, mpd_uint_t wbase,
+                        mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase,
+                        uint32_t *status)
+{
+    size_t n = 0;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(wbase < ubase);
+
+    do {
+        if (n >= wlen) {
+            if (!mpd_qresize(w, n+1, status)) {
+                return SIZE_MAX;
+            }
+            wlen = n+1;
+        }
+        w->data[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
+        /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */
+        ulen = _mpd_real_size(u, ulen);
+
+    } while (u[ulen-1] != 0);
+
+    return n;
+}
+#endif
+
+/* target base 'wbase' > source base 'ubase' */
+static size_t
+_coeff_from_smaller_base(mpd_t *w, mpd_ssize_t wlen, mpd_uint_t wbase,
+                         const uint32_t *u, size_t ulen, mpd_uint_t ubase,
+                         uint32_t *status)
+{
+    mpd_ssize_t n = 0;
+    mpd_uint_t carry;
+
+    assert(wlen > 0 && ulen > 0);
+    assert(wbase > ubase);
+
+    w->data[n++] = u[--ulen];
+    while (--ulen != SIZE_MAX) {
+        carry = _mpd_shortmul_b(w->data, w->data, n, ubase, wbase);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_qresize(w, n+1, status)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            w->data[n++] = carry;
+        }
+        carry = _mpd_shortadd_b(w->data, n, u[ulen], wbase);
+        if (carry) {
+            if (n >= wlen) {
+                if (!mpd_qresize(w, n+1, status)) {
+                    return SIZE_MAX;
+                }
+                wlen = n+1;
+            }
+            w->data[n++] = carry;
+        }
+    }
+
+    return n;
+}
+
 /*
- * Returns the space needed to represent an integer mpd_t in base 'base'.
- * The result is undefined for non-integers.
+ * Convert an integer mpd_t to a multiprecision integer with base <= 2**16.
+ * The least significant word of the result is (*rdata)[0].
  *
- * Max space needed:
+ * If rdata is NULL, space is allocated by the function and rlen is irrelevant.
+ * In case of an error any allocated storage is freed and rdata is set back to
+ * NULL.
  *
- *   base^n >= 10^(digits+exp)
- *   n >= log10(10^(digits+exp))/log10(base) = (digits+exp) / log10(base)
+ * If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation
+ * functions and rlen MUST be correct. If necessary, the function will resize
+ * rdata. In case of an error the caller must free rdata.
+ *
+ * Return value: In case of success, the exact length of rdata, SIZE_MAX
+ * otherwise.
  */
 size_t
-mpd_sizeinbase(mpd_t *a, uint32_t base)
-{
-    size_t x;
-
-    assert(mpd_isinteger(a));
-    if (mpd_iszero(a)) {
-        return 1;
-    }
-
-    x = a->digits+a->exp;
-
-#ifdef CONFIG_64
-  #ifdef USE_80BIT_LONG_DOUBLE
-    return (long double)x / log10(base) + 3;
-  #else
-    /* x > floor(((1ULL<<53)-3) * log10(2)) */
-    if (x > 2711437152599294ULL) {
-        return SIZE_MAX;
-    }
-    return (size_t)((double)x / log10(base) + 3);
-  #endif
-#else /* CONFIG_32 */
-{
-    double y =  x / log10(base) + 3;
-    return (y > SIZE_MAX) ? SIZE_MAX : (size_t)y;
-}
-#endif
-}
-
-/*
- * Returns the space needed to import a base 'base' integer of length 'srclen'.
- */
-static inline mpd_ssize_t
-_mpd_importsize(size_t srclen, uint32_t base)
-{
-#if SIZE_MAX == UINT64_MAX
-  #ifdef USE_80BIT_LONG_DOUBLE
-    long double x = (long double)srclen * (log10(base)/MPD_RDIGITS) + 3;
-  #else
-    double x;
-    if (srclen > (1ULL<<53)) {
-        return MPD_SSIZE_MAX;
-    }
-    x = (double)srclen * (log10(base)/MPD_RDIGITS) + 3;
-  #endif
-#else
-    double x = srclen * (log10(base)/MPD_RDIGITS) + 3;
-#endif
-    return (x > MPD_MAXIMPORT) ? MPD_SSIZE_MAX : (mpd_ssize_t)x;
-}
-
-
-static inline size_t
-_to_base_u16(uint16_t *w, size_t wlen, mpd_uint_t wbase,
-             mpd_uint_t *u, mpd_ssize_t ulen)
-{
-    size_t n = 0;
-
-    assert(wlen > 0 && ulen > 0);
-
-    do {
-        w[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);
-        /* ulen will be at least 1. u[ulen-1] can only be zero if ulen == 1 */
-        ulen = _mpd_real_size(u, ulen);
-
-    } while (u[ulen-1] != 0 && n < wlen);
-
-    /* proper termination condition */
-    assert(u[ulen-1] == 0);
-
-    return n;
-}
-
-static inline void
-_from_base_u16(mpd_uint_t *w, mpd_ssize_t wlen,
-               const mpd_uint_t *u, size_t ulen, uint32_t ubase)
-{
-    mpd_ssize_t m = 1;
-    mpd_uint_t carry;
-
-    assert(wlen > 0 && ulen > 0);
-
-    w[0] = u[--ulen];
-    while (--ulen != SIZE_MAX && m < wlen) {
-        _mpd_shortmul(w, w, m, ubase);
-        m = _mpd_real_size(w, m+1);
-        carry = _mpd_shortadd(w, m, u[ulen]);
-        if (carry) w[m++] = carry;
-    }
-
-    /* proper termination condition */
-    assert(ulen == SIZE_MAX);
-}
-
-/* target base wbase <= source base ubase */
-static inline size_t
-_baseconv_to_smaller(uint32_t *w, size_t wlen, mpd_uint_t wbase,
-                     mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase)
-{
-    size_t n = 0;
-
-    assert(wlen > 0 && ulen > 0);
-
-    do {
-        w[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
-        /* ulen will be at least 1. u[ulen-1] can only be zero if ulen == 1 */
-        ulen = _mpd_real_size(u, ulen);
-
-    } while (u[ulen-1] != 0 && n < wlen);
-
-    /* proper termination condition */
-    assert(u[ulen-1] == 0);
-
-    return n;
-}
-
-/* target base wbase >= source base ubase */
-static inline void
-_baseconv_to_larger(mpd_uint_t *w, mpd_ssize_t wlen, mpd_uint_t wbase,
-                    const mpd_uint_t *u, size_t ulen, mpd_uint_t ubase)
-{
-    mpd_ssize_t m = 1;
-    mpd_uint_t carry;
-
-    assert(wlen > 0 && ulen > 0);
-
-    w[0] = u[--ulen];
-    while (--ulen != SIZE_MAX && m < wlen) {
-        _mpd_shortmul_b(w, w, m, ubase, wbase);
-        m = _mpd_real_size(w, m+1);
-        carry = _mpd_shortadd_b(w, m, u[ulen], wbase);
-        if (carry) w[m++] = carry;
-    }
-
-    /* proper termination condition */
-    assert(ulen == SIZE_MAX);
-}
-
-
-/*
- * Converts an integer mpd_t to a multiprecision integer with
- * base <= UINT16_MAX+1. The least significant word of the result
- * is rdata[0].
- */
-size_t
-mpd_qexport_u16(uint16_t *rdata, size_t rlen, uint32_t rbase,
+mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,
                 const mpd_t *src, uint32_t *status)
 {
-    mpd_t *tsrc;
+    MPD_NEW_STATIC(tsrc,0,0,0,0);
+    int alloc = 0; /* rdata == NULL */
     size_t n;
 
     assert(rbase <= (1U<<16));
-    assert(rlen <= SIZE_MAX/(sizeof *rdata));
 
     if (mpd_isspecial(src) || !_mpd_isint(src)) {
         *status |= MPD_Invalid_operation;
         return SIZE_MAX;
     }
 
-    memset(rdata, 0, rlen * (sizeof *rdata));
+    if (*rdata == NULL) {
+        rlen = mpd_sizeinbase(src, rbase);
+        if (rlen == SIZE_MAX) {
+            *status |= MPD_Invalid_operation;
+            return SIZE_MAX;
+        }
+        *rdata = mpd_alloc(rlen, sizeof **rdata);
+        if (*rdata == NULL) {
+            goto malloc_error;
+        }
+        alloc = 1;
+    }
 
     if (mpd_iszero(src)) {
+        **rdata = 0;
         return 1;
     }
 
-    if ((tsrc = mpd_qnew()) == NULL) {
-        *status |= MPD_Malloc_error;
-        return SIZE_MAX;
-    }
-
     if (src->exp >= 0) {
-        if (!mpd_qshiftl(tsrc, src, src->exp, status)) {
-            mpd_del(tsrc);
-            return SIZE_MAX;
+        if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {
+            goto malloc_error;
         }
     }
     else {
-        if (mpd_qshiftr(tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
-            mpd_del(tsrc);
-            return SIZE_MAX;
-        }
-    }
-
-    n = _to_base_u16(rdata, rlen, rbase, tsrc->data, tsrc->len);
-
-    mpd_del(tsrc);
+        if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
+            goto malloc_error;
+        }
+    }
+
+    n = _baseconv_to_u16(rdata, rlen, rbase, tsrc.data, tsrc.len);
+    if (n == SIZE_MAX) {
+        goto malloc_error;
+    }
+
+
+out:
+    mpd_del(&tsrc);
     return n;
+
+malloc_error:
+    if (alloc) {
+        mpd_free(*rdata);
+        *rdata = NULL;
+    }
+    n = SIZE_MAX;
+    *status |= MPD_Malloc_error;
+    goto out;
 }
 
 /*
- * Converts an integer mpd_t to a multiprecision integer with
- * base <= UINT32_MAX. The least significant word of the result
- * is rdata[0].
+ * Convert an integer mpd_t to a multiprecision integer with base<=UINT32_MAX.
+ * The least significant word of the result is (*rdata)[0].
+ *
+ * If rdata is NULL, space is allocated by the function and rlen is irrelevant.
+ * In case of an error any allocated storage is freed and rdata is set back to
+ * NULL.
+ *
+ * If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation
+ * functions and rlen MUST be correct. If necessary, the function will resize
+ * rdata. In case of an error the caller must free rdata.
+ *
+ * Return value: In case of success, the exact length of rdata, SIZE_MAX
+ * otherwise.
  */
 size_t
-mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t rbase,
+mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t rbase,
                 const mpd_t *src, uint32_t *status)
 {
-    mpd_t *tsrc;
+    MPD_NEW_STATIC(tsrc,0,0,0,0);
+    int alloc = 0; /* rdata == NULL */
     size_t n;
 
     if (mpd_isspecial(src) || !_mpd_isint(src)) {
         *status |= MPD_Invalid_operation;
         return SIZE_MAX;
     }
-#if MPD_SIZE_MAX < SIZE_MAX
-    if (rlen > MPD_SSIZE_MAX) {
-        *status |= MPD_Invalid_operation;
-        return SIZE_MAX;
-    }
-#endif
-
-    assert(rlen <= SIZE_MAX/(sizeof *rdata));
-    memset(rdata, 0, rlen * (sizeof *rdata));
+
+    if (*rdata == NULL) {
+        rlen = mpd_sizeinbase(src, rbase);
+        if (rlen == SIZE_MAX) {
+            *status |= MPD_Invalid_operation;
+            return SIZE_MAX;
+        }
+        *rdata = mpd_alloc(rlen, sizeof **rdata);
+        if (*rdata == NULL) {
+            goto malloc_error;
+        }
+        alloc = 1;
+    }
 
     if (mpd_iszero(src)) {
+        **rdata = 0;
         return 1;
     }
 
-    if ((tsrc = mpd_qnew()) == NULL) {
-        *status |= MPD_Malloc_error;
-        return SIZE_MAX;
-    }
-
     if (src->exp >= 0) {
-        if (!mpd_qshiftl(tsrc, src, src->exp, status)) {
-            mpd_del(tsrc);
-            return SIZE_MAX;
+        if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {
+            goto malloc_error;
         }
     }
     else {
-        if (mpd_qshiftr(tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
-            mpd_del(tsrc);
-            return SIZE_MAX;
+        if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
+            goto malloc_error;
         }
     }
 
 #ifdef CONFIG_64
     n = _baseconv_to_smaller(rdata, rlen, rbase,
-                             tsrc->data, tsrc->len, MPD_RADIX);
+                             tsrc.data, tsrc.len, MPD_RADIX);
 #else
-    if (rbase <= MPD_RADIX) {
+    if (rbase == MPD_RADIX) {
+        n = _copy_equal_base(rdata, rlen, tsrc.data, tsrc.len);
+    }
+    else if (rbase < MPD_RADIX) {
         n = _baseconv_to_smaller(rdata, rlen, rbase,
-                                 tsrc->data, tsrc->len, MPD_RADIX);
+                                 tsrc.data, tsrc.len, MPD_RADIX);
     }
     else {
-        _baseconv_to_larger(rdata, (mpd_ssize_t)rlen, rbase,
-                            tsrc->data, tsrc->len, MPD_RADIX);
-        n = _mpd_real_size(rdata, (mpd_ssize_t)rlen);
+        n = _baseconv_to_larger(rdata, rlen, rbase,
+                                tsrc.data, tsrc.len, MPD_RADIX);
     }
 #endif
 
-    mpd_del(tsrc);
+    if (n == SIZE_MAX) {
+        goto malloc_error;
+    }
+
+
+out:
+    mpd_del(&tsrc);
     return n;
+
+malloc_error:
+    if (alloc) {
+        mpd_free(*rdata);
+        *rdata = NULL;
+    }
+    n = SIZE_MAX;
+    *status |= MPD_Malloc_error;
+    goto out;
 }
 
 
@@ -7846,20 +8021,19 @@
 {
     mpd_uint_t *usrc; /* uint16_t src copied to an mpd_uint_t array */
     mpd_ssize_t rlen; /* length of the result */
-    size_t n = 0;
+    size_t n;
 
     assert(srclen > 0);
     assert(srcbase <= (1U<<16));
 
-    if ((rlen = _mpd_importsize(srclen, srcbase)) == MPD_SSIZE_MAX) {
+    rlen = _mpd_importsize(srclen, srcbase);
+    if (rlen == MPD_SSIZE_MAX) {
         mpd_seterror(result, MPD_Invalid_operation, status);
         return;
     }
-    if (srclen > MPD_SIZE_MAX/(sizeof *usrc)) {
-        mpd_seterror(result, MPD_Invalid_operation, status);
-        return;
-    }
-    if ((usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc)) == NULL) {
+
+    usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);
+    if (usrc == NULL) {
         mpd_seterror(result, MPD_Malloc_error, status);
         return;
     }
@@ -7867,16 +8041,18 @@
         usrc[n] = srcdata[n];
     }
 
-    /* result->data is initialized to zero */
     if (!mpd_qresize_zero(result, rlen, status)) {
         goto finish;
     }
 
-    _from_base_u16(result->data, rlen, usrc, srclen, srcbase);
+    n = _coeff_from_u16(result, rlen, usrc, srclen, srcbase, status);
+    if (n == SIZE_MAX) {
+        goto finish;
+    }
 
     mpd_set_flags(result, srcsign);
     result->exp = 0;
-    result->len = _mpd_real_size(result->data, rlen);
+    result->len = n;
     mpd_setdigits(result);
 
     mpd_qresize(result, result->len, status);
@@ -7897,59 +8073,67 @@
                 uint8_t srcsign, uint32_t srcbase,
                 const mpd_context_t *ctx, uint32_t *status)
 {
-    mpd_uint_t *usrc; /* uint32_t src copied to an mpd_uint_t array */
     mpd_ssize_t rlen; /* length of the result */
-    size_t n = 0;
+    size_t n;
 
     assert(srclen > 0);
 
-    if ((rlen = _mpd_importsize(srclen, srcbase)) == MPD_SSIZE_MAX) {
+    rlen = _mpd_importsize(srclen, srcbase);
+    if (rlen == MPD_SSIZE_MAX) {
         mpd_seterror(result, MPD_Invalid_operation, status);
         return;
     }
-    if (srclen > MPD_SIZE_MAX/(sizeof *usrc)) {
-        mpd_seterror(result, MPD_Invalid_operation, status);
+
+    if (!mpd_qresize_zero(result, rlen, status)) {
         return;
     }
-    if ((usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc)) == NULL) {
-        mpd_seterror(result, MPD_Malloc_error, status);
+
+#ifdef CONFIG_64
+    n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,
+                                 srcdata, srclen, srcbase,
+                                 status);
+#else
+    if (srcbase == MPD_RADIX) {
+        if (!mpd_qresize_zero(result, srclen, status)) {
+            return;
+        }
+        memcpy(result->data, srcdata, srclen * (sizeof *srcdata));
+        n = srclen;
+    }
+    else if (srcbase < MPD_RADIX) {
+        n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,
+                                     srcdata, srclen, srcbase,
+                                     status);
+    }
+    else {
+        mpd_uint_t *usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);
+        if (usrc == NULL) {
+            mpd_seterror(result, MPD_Malloc_error, status);
+            return;
+        }
+        for (n = 0; n < srclen; n++) {
+            usrc[n] = srcdata[n];
+        }
+
+        n = _coeff_from_larger_base(result, rlen, MPD_RADIX,
+                                    usrc, (mpd_ssize_t)srclen, srcbase,
+                                    status);
+        mpd_free(usrc);
+    }
+#endif
+
+    if (n == SIZE_MAX) {
         return;
     }
-    for (n = 0; n < srclen; n++) {
-        usrc[n] = srcdata[n];
-    }
-
-    /* result->data is initialized to zero */
-    if (!mpd_qresize_zero(result, rlen, status)) {
-        goto finish;
-    }
-
-#ifdef CONFIG_64
-    _baseconv_to_larger(result->data, rlen, MPD_RADIX,
-                        usrc, srclen, srcbase);
-#else
-    if (srcbase <= MPD_RADIX) {
-        _baseconv_to_larger(result->data, rlen, MPD_RADIX,
-                            usrc, srclen, srcbase);
-    }
-    else {
-        _baseconv_to_smaller(result->data, rlen, MPD_RADIX,
-                             usrc, (mpd_ssize_t)srclen, srcbase);
-    }
-#endif
 
     mpd_set_flags(result, srcsign);
     result->exp = 0;
-    result->len = _mpd_real_size(result->data, rlen);
+    result->len = n;
     mpd_setdigits(result);
 
     mpd_qresize(result, result->len, status);
     mpd_qfinalize(result, ctx, status);
-
-
-finish:
-    mpd_free(usrc);
-}
-
-
-
+}
+
+
+
diff --git a/Modules/_decimal/libmpdec/mpdecimal.h b/Modules/_decimal/libmpdec/mpdecimal.h
--- a/Modules/_decimal/libmpdec/mpdecimal.h
+++ b/Modules/_decimal/libmpdec/mpdecimal.h
@@ -511,16 +511,16 @@
 void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 
 
-size_t mpd_sizeinbase(mpd_t *a, uint32_t base);
+size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
 void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
                      uint8_t srcsign, uint32_t srcbase,
                      const mpd_context_t *ctx, uint32_t *status);
 void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
                      uint8_t srcsign, uint32_t srcbase,
                      const mpd_context_t *ctx, uint32_t *status);
-size_t mpd_qexport_u16(uint16_t *rdata, size_t rlen, uint32_t base,
+size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
                        const mpd_t *src, uint32_t *status);
-size_t mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t base,
+size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
                        const mpd_t *src, uint32_t *status);
 
 
@@ -531,8 +531,8 @@
 char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
 void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
 void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
-size_t mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
-size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
 void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
 int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
 int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1818,7 +1818,7 @@
 
     def _decimal_ext(self):
         extra_compile_args = []
-        undef_macros=['NDEBUG']
+        undef_macros = ['NDEBUG']
         if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
             include_dirs = []
             libraries = ['mpdec']

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list