diff options
author | Matthias Klose <doko@ubuntu.com> | 2012-06-30 16:26:26 (GMT) |
---|---|---|
committer | Matthias Klose <doko@ubuntu.com> | 2012-06-30 16:26:26 (GMT) |
commit | fe39bd12f8a37f3bfcbbcc52fba49841053e1682 (patch) | |
tree | 6eb163bfdfca3310623b3494d9b5e4dd8864c376 | |
parent | 5884449539510313c826d69835829c7957c7154a (diff) | |
parent | 3746aee9059567b5199051a5147aecbecb6a5acf (diff) | |
download | cpython-fe39bd12f8a37f3bfcbbcc52fba49841053e1682.zip cpython-fe39bd12f8a37f3bfcbbcc52fba49841053e1682.tar.gz cpython-fe39bd12f8a37f3bfcbbcc52fba49841053e1682.tar.bz2 |
- merge branches
-rw-r--r-- | Lib/test/test_zipfile.py | 18 | ||||
-rw-r--r-- | Modules/_decimal/_decimal.c | 38 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/basearith.c | 27 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/basearith.h | 6 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.c | 526 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.h | 10 | ||||
-rw-r--r-- | setup.py | 2 |
7 files changed, 428 insertions, 199 deletions
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 0772236..2e52c68 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -1134,6 +1134,24 @@ class OtherTests(unittest.TestCase): 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 index a85023a..60fc696 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -3203,7 +3203,8 @@ static PyObject * 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 @@ dec_as_long(PyObject *dec, PyObject *context, int round) return NULL; } - maxsize = mpd_sizeinbase(x, PyLong_BASE); - if (maxsize > PY_SSIZE_T_MAX) { - mpd_del(x); - PyErr_NoMemory(); - return NULL; - } - pylong = _PyLong_New(maxsize); - if (pylong == NULL) { - mpd_del(x); - return NULL; - } - status = 0; + ob_digit = NULL; #if PYLONG_BITS_IN_DIGIT == 30 - n = mpd_qexport_u32(pylong->ob_digit, maxsize, PyLong_BASE, x, &status); + n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status); #elif PYLONG_BITS_IN_DIGIT == 15 - n = mpd_qexport_u16(pylong->ob_digit, maxsize, PyLong_BASE, x, &status); + n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status); #else - #error "PYLONG_BITS_IN_DIGIT should be 15 or 30" + #error "PYLONG_BITS_IN_DIGIT should be 15 or 30" #endif - if (dec_addstatus(context, status)) { - Py_DECREF((PyObject *) pylong); + + if (n == SIZE_MAX) { + PyErr_NoMemory(); + mpd_del(x); + return NULL; + } + + 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 index e9d5024..dd21a7a 100644 --- a/Modules/_decimal/libmpdec/basearith.c +++ b/Modules/_decimal/libmpdec/basearith.c @@ -583,8 +583,30 @@ _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b) 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_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, _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 index 94de862..5004b2c 100644 --- a/Modules/_decimal/libmpdec/basearith.h +++ b/Modules/_decimal/libmpdec/basearith.h @@ -49,8 +49,10 @@ void _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v, 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 index 7efe656..b5f7808 100644 --- 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 @@ finish: /* Base conversions */ /******************************************************************************/ -/* - * Returns the space needed to represent an integer mpd_t in base 'base'. - * The result is undefined for non-integers. - * - * Max space needed: - * - * base^n >= 10^(digits+exp) - * n >= log10(10^(digits+exp))/log10(base) = (digits+exp) / log10(base) - */ +/* Space needed to represent an integer mpd_t in base 'base'. */ size_t -mpd_sizeinbase(mpd_t *a, uint32_t base) +mpd_sizeinbase(const mpd_t *a, uint32_t base) { - size_t x; + double x; + size_t digits; assert(mpd_isinteger(a)); + assert(base >= 2); + if (mpd_iszero(a)) { return 1; } - x = a->digits+a->exp; + digits = a->digits+a->exp; + assert(digits > 0); #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) { + /* ceil(2711437152599294 / log10(2)) + 4 == 2**53 */ + if (digits > 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 + + x = (double)digits / log10(base); + return (x > SIZE_MAX-1) ? SIZE_MAX : (size_t)x + 1; } -/* - * Returns the space needed to import a base 'base' integer of length 'srclen'. - */ -static inline mpd_ssize_t +/* Space needed to import a base 'base' integer of length 'srclen'. */ +static 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; + + assert(srclen > 0); + assert(base >= 2); + +#if SIZE_MAX == UINT64_MAX 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; + + 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 inline size_t -_to_base_u16(uint16_t *w, size_t wlen, mpd_uint_t wbase, - mpd_uint_t *u, mpd_ssize_t ulen) +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 { - 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 */ + 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 && n < wlen); - - /* proper termination condition */ - assert(u[ulen-1] == 0); + } while (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) +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 m = 1; + mpd_ssize_t n = 0; mpd_uint_t carry; assert(wlen > 0 && ulen > 0); + assert(ubase <= (1U<<16)); - 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; + 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; + } } - /* proper termination condition */ - assert(ulen == SIZE_MAX); + return n; } -/* target base wbase <= source base ubase */ -static inline size_t -_baseconv_to_smaller(uint32_t *w, size_t wlen, mpd_uint_t wbase, +/* 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 { - w[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase); + 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 && n < wlen); - - /* proper termination condition */ - assert(u[ulen-1] == 0); + } while (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, +#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) { - mpd_ssize_t m = 1; + size_t n = 0; mpd_uint_t carry; assert(wlen > 0 && ulen > 0); + assert(ubase < wbase); - 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; + (*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; + } } - /* proper termination condition */ - assert(ulen == SIZE_MAX); + 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; +} /* - * Converts an integer mpd_t to a multiprecision integer with - * base <= UINT16_MAX+1. The least significant word of the result - * is rdata[0]. + * Convert an integer mpd_t to a multiprecision integer with base <= 2**16. + * 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_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; + if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) { + goto malloc_error; } } - n = _to_base_u16(rdata, rlen, rbase, tsrc->data, tsrc->len); + n = _baseconv_to_u16(rdata, rlen, rbase, tsrc.data, tsrc.len); + if (n == SIZE_MAX) { + goto malloc_error; + } + - mpd_del(tsrc); +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_qimport_u16(mpd_t *result, { 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) { - mpd_seterror(result, MPD_Invalid_operation, status); - return; - } - if (srclen > MPD_SIZE_MAX/(sizeof *usrc)) { + rlen = _mpd_importsize(srclen, srcbase); + if (rlen == MPD_SSIZE_MAX) { 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 @@ mpd_qimport_u16(mpd_t *result, 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,58 +8073,66 @@ mpd_qimport_u32(mpd_t *result, 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) { - mpd_seterror(result, MPD_Invalid_operation, status); - return; - } - if (srclen > MPD_SIZE_MAX/(sizeof *usrc)) { + rlen = _mpd_importsize(srclen, srcbase); + if (rlen == MPD_SSIZE_MAX) { mpd_seterror(result, MPD_Invalid_operation, status); return; } - if ((usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc)) == NULL) { - mpd_seterror(result, MPD_Malloc_error, status); - 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; + return; } #ifdef CONFIG_64 - _baseconv_to_larger(result->data, rlen, MPD_RADIX, - usrc, srclen, srcbase); + n = _coeff_from_smaller_base(result, rlen, MPD_RADIX, + srcdata, srclen, srcbase, + status); #else - if (srcbase <= MPD_RADIX) { - _baseconv_to_larger(result->data, rlen, MPD_RADIX, - usrc, srclen, srcbase); + 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 { - _baseconv_to_smaller(result->data, rlen, MPD_RADIX, - usrc, (mpd_ssize_t)srclen, srcbase); + 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; + } + 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 index f3f32ac..d131c71 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.h +++ b/Modules/_decimal/libmpdec/mpdecimal.h @@ -511,16 +511,16 @@ void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t 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 @@ size_t mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t base, 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); @@ -1818,7 +1818,7 @@ class PyBuildExt(build_ext): 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'] |