diff options
author | MITSUNARI Shigeo <herumi@nifty.com> | 2018-05-17 15:08:43 +0800 |
---|---|---|
committer | MITSUNARI Shigeo <herumi@nifty.com> | 2018-05-17 15:08:43 +0800 |
commit | b33f6fdaa09d89386b7fecc142df922d723b6f7d (patch) | |
tree | 344b978537fe914f5be45098b8b6ef530d3adf6c | |
parent | e280cc5443a8c9e404b10ca7dc1da51d5c251387 (diff) | |
download | tangerine-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.tar.gz tangerine-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.tar.zst tangerine-mcl-b33f6fdaa09d89386b7fecc142df922d723b6f7d.zip |
reduce exception
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | include/mcl/fp.hpp | 67 | ||||
-rw-r--r-- | include/mcl/op.hpp | 9 | ||||
-rw-r--r-- | sample/bench.cpp | 3 | ||||
-rw-r--r-- | src/conversion.hpp | 190 | ||||
-rw-r--r-- | src/fp.cpp | 82 | ||||
-rw-r--r-- | test/conversion_test.cpp | 57 | ||||
-rw-r--r-- | test/fp_util_test.cpp | 38 |
8 files changed, 368 insertions, 80 deletions
@@ -3,7 +3,7 @@ LIB_DIR=lib OBJ_DIR=obj EXE_DIR=bin SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp -TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp +TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp conversion_test.cpp TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c512_test.cpp she_c256_test.cpp she_c384_test.cpp TEST_SRC+=aggregate_sig_test.cpp TEST_SRC+=bls12_test.cpp diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp index 0fb347c..0bd04c6 100644 --- a/include/mcl/fp.hpp +++ b/include/mcl/fp.hpp @@ -92,6 +92,23 @@ void loadWord(std::string& s, InputStream& is) } } +template<class InputStream> +size_t loadWord(char *buf, size_t bufSize, InputStream& is) +{ + if (bufSize == 0) return 0; + char c; + if (!skipSpace(&c, is)) return 0; + size_t pos = 0; + buf[pos++] = c; + for (;;) { + if (!cybozu::readChar(&c, is)) break; + if (isSpace(c)) break; + if (pos == bufSize) return 0; + buf[pos++] = c; + } + return pos; +} + } // local } // mcl::fp @@ -243,46 +260,72 @@ public: if (isMont()) op_.fromMont(v_, v_); } template<class InputStream> - void load(InputStream& is, int ioMode = IoSerialize) + void load(InputStream& is, int ioMode, bool *pb) { bool isMinus = false; + *pb = false; if (ioMode & (IoArray | IoArrayRaw | IoSerialize)) { const size_t n = getByteSize(); v_[op_.N - 1] = 0; - if (cybozu::readSome(v_, n, is) != n) throw cybozu::Exception("FpT:load:can't read") << n; + if (cybozu::readSome(v_, n, is) != n) { + return; + } } else { - std::string str; - fp::local::loadWord(str, is); - fp::strToArray(&isMinus, v_, op_.N, str, ioMode); + char buf[1024]; + size_t n = fp::local::loadWord(buf, sizeof(buf), is); + if (n == 0 || !fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode)) { + return; + } + } + if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) { + return; } - if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) throw cybozu::Exception("FpT:load:large value"); if (isMinus) { neg(*this, *this); } if (!(ioMode & IoArrayRaw)) { toMont(); } + *pb = true; } template<class OutputStream> - void save(OutputStream& os, int ioMode = IoSerialize) const + void save(OutputStream& os, int ioMode, bool *pb) const { const size_t n = getByteSize(); if (ioMode & (IoArray | IoArrayRaw | IoSerialize)) { if (ioMode & IoArrayRaw) { - cybozu::write(os, v_, n); + cybozu::write(os, v_, n, pb); } else { fp::Block b; getBlock(b); - cybozu::write(os, b.p, n); + cybozu::write(os, b.p, n, pb); } return; } fp::Block b; getBlock(b); - std::string str; // use low 8-bit ioMode for Fp - fp::arrayToStr(str, b.p, b.n, ioMode & 255); - cybozu::write(os, str.c_str(), str.size()); + char buf[2048]; + size_t len = fp::arrayToStr(buf, sizeof(buf), b.p, b.n, ioMode & 255); + if (len == 0) { + *pb = false; + return; + } + cybozu::write(os, buf + sizeof(buf) - len, len, pb); + } + template<class OutputStream> + void save(OutputStream& os, int ioMode = IoSerialize) const + { + bool b; + save(os, ioMode, &b); + if (!b) throw cybozu::Exception("fp:save") << ioMode; + } + template<class InputStream> + void load(InputStream& is, int ioMode = IoSerialize) + { + bool b; + load(is, ioMode, &b); + if (!b) throw cybozu::Exception("fp:load") << ioMode; } /* throw exception if x >= p diff --git a/include/mcl/op.hpp b/include/mcl/op.hpp index 4e577a2..7132721 100644 --- a/include/mcl/op.hpp +++ b/include/mcl/op.hpp @@ -323,9 +323,14 @@ private: /* conevrt string to array according to ioMode, */ -void strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode); +bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode); +bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const char *buf, size_t bufSize, int ioMode); -void arrayToStr(std::string& str, const Unit *x, size_t n, int ioMode); +/* + return retavl is written size if success else 0 + REMARK : the top of string is buf + bufSize - retval +*/ +size_t arrayToStr(char *buf, size_t bufSize, const Unit *x, size_t n, int ioMode); inline const char* getIoSeparator(int ioMode) { diff --git a/sample/bench.cpp b/sample/bench.cpp index 67f5da5..14997f8 100644 --- a/sample/bench.cpp +++ b/sample/bench.cpp @@ -146,9 +146,10 @@ void benchToStr16() }; Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13"); for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[128]; std::string str; Fp x(tbl[i]); - CYBOZU_BENCH("fp::toStr16", mcl::fp::toStr16, str, x.getUnit(), x.getUnitSize(), 16); + CYBOZU_BENCH("fp::arrayToHex", mcl::fp::arrayToHex, buf, sizeof(buf), x.getUnit(), x.getUnitSize(), true); mpz_class y(tbl[i]); CYBOZU_BENCH("gmp:getStr ", mcl::gmp::getStr, str, y, 16); } diff --git a/src/conversion.hpp b/src/conversion.hpp index 2383efd..9292a72 100644 --- a/src/conversion.hpp +++ b/src/conversion.hpp @@ -14,11 +14,13 @@ namespace mcl { namespace fp { /* - convert x[0..n) to hex string + convert little endian x[0, xn) to buf + return written size if success else 0 + data is buf[bufSize - retval, bufSize) start "0x" if withPrefix */ template<class T> -void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false) +size_t arrayToHex(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix = false) { size_t fullN = 0; if (n > 1) { @@ -33,23 +35,28 @@ void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false) const size_t topLen = cybozu::getHexLength(v); const size_t startPos = withPrefix ? 2 : 0; const size_t lenT = sizeof(T) * 2; - str.resize(startPos + fullN * lenT + topLen); + const size_t totalSize = startPos + fullN * lenT + topLen; + if (totalSize > bufSize) return 0; + char *const top = buf + bufSize - totalSize; if (withPrefix) { - str[0] = '0'; - str[1] = 'x'; + top[0] = '0'; + top[1] = 'x'; } - cybozu::itohex(&str[startPos], topLen, v, false); + cybozu::itohex(&top[startPos], topLen, v, false); for (size_t i = 0; i < fullN; i++) { - cybozu::itohex(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false); + cybozu::itohex(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false); } + return totalSize; } /* - convert x[0..n) to bin string + convert little endian x[0, xn) to buf + return written size if success else 0 + data is buf[bufSize - retval, bufSize) start "0b" if withPrefix */ template<class T> -void toStr2(std::string& str, const T *x, size_t n, bool withPrefix) +size_t arrayToBin(char *buf, size_t bufSize, const T *x, size_t n, bool withPrefix) { size_t fullN = 0; if (n > 1) { @@ -64,15 +71,18 @@ void toStr2(std::string& str, const T *x, size_t n, bool withPrefix) const size_t topLen = cybozu::getBinLength(v); const size_t startPos = withPrefix ? 2 : 0; const size_t lenT = sizeof(T) * 8; - str.resize(startPos + fullN * lenT + topLen); + const size_t totalSize = startPos + fullN * lenT + topLen; + if (totalSize > bufSize) return 0; + char *const top = buf + bufSize - totalSize; if (withPrefix) { - str[0] = '0'; - str[1] = 'b'; + top[0] = '0'; + top[1] = 'b'; } - cybozu::itobin(&str[startPos], topLen, v); + cybozu::itobin(&top[startPos], topLen, v); for (size_t i = 0; i < fullN; i++) { - cybozu::itobin(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]); + cybozu::itobin(&top[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]); } + return totalSize; } /* @@ -101,5 +111,155 @@ void fromStr16(T *x, size_t xn, const char *str, size_t strLen) for (size_t i = requireSize; i < xn; i++) x[i] = 0; } +namespace local { -} } // mcl::fp +/* + q = x[] / x + @retval r = x[] % x + @note accept q == x +*/ +inline uint32_t divU32(uint32_t *q, const uint32_t *x, size_t xn, uint32_t y) +{ + if (xn == 0) return 0; + uint32_t r = 0; + for (int i = (int)xn - 1; i >= 0; i--) { + uint64_t t = (uint64_t(r) << 32) | x[i]; + q[i] = uint32_t(t / y); + r = uint32_t(t % y); + } + return r; +} + +/* + z[0, xn) = x[0, xn) * y + return z[xn] + @note accept z == x +*/ +inline uint32_t mulU32(uint32_t *z, const uint32_t *x, size_t xn, uint32_t y) +{ + uint32_t H = 0; + for (size_t i = 0; i < xn; i++) { + uint32_t t = H; + uint64_t v = uint64_t(x[i]) * y; + uint32_t L = uint32_t(v); + H = uint32_t(v >> 32); + z[i] = t + L; + if (z[i] < t) { + H++; + } + } + return H; +} + +/* + x[0, xn) += y + return 1 if overflow else 0 +*/ +inline uint32_t addU32(uint32_t *x, size_t xn, uint32_t y) +{ + uint32_t t = x[0] + y; + x[0] = t; + if (t >= y) return 0; + for (size_t i = 1; i < xn; i++) { + t = x[i] + 1; + x[i] = t; + if (t != 0) return 0; + } + return 1; +} + +inline uint32_t decToU32(const char *p, size_t size, bool *pb) +{ + assert(0 < size && size <= 9); + uint32_t x = 0; + for (size_t i = 0; i < size; i++) { + char c = p[i]; + if (c < '0' || c > '9') { + *pb = false; + return 0; + } + x = x * 10 + uint32_t(c - '0'); + } + *pb = true; + return x; +} + +} // mcl::fp::local + +/* + little endian x[0, xn) to buf + return written size if success else 0 + data is buf[bufSize - retval, bufSize) +*/ +template<class UT> +inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn) +{ + const size_t maxN = 64; + uint32_t t[maxN]; + if (sizeof(UT) == 8) { + xn *= 2; + } + if (xn > maxN) return 0; + memcpy(t, x, xn * sizeof(t[0])); + + const size_t width = 9; + const uint32_t i1e9 = 1000000000U; + size_t pos = 0; + for (;;) { + uint32_t r = local::divU32(t, t, xn, i1e9); + while (xn > 0 && t[xn - 1] == 0) xn--; + size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r); + if (len == 0) return 0; + assert(0 < len && len <= width); + if (xn == 0) return pos + len; + // fill (width - len) '0' + for (size_t j = 0; j < width - len; j++) { + buf[bufSize - pos - width + j] = '0'; + } + pos += width; + } +} + +/* + convert buf[0, bufSize) to x[0, num) + return written num if success else 0 +*/ +template<class UT> +inline size_t convertDecToArray(UT *_x, size_t xSize, const char *buf, size_t bufSize) +{ + assert(sizeof(UT) == 4 || sizeof(UT) == 8); + const size_t width = 9; + const uint32_t i1e9 = 1000000000U; + if (xSize == 0) return 0; + if (sizeof(UT) == 8) { + xSize *= 2; + } + uint32_t *x = reinterpret_cast<uint32_t*>(_x); + size_t xn = 1; + x[0] = 0; + while (bufSize > 0) { + size_t n = bufSize % width; + if (n == 0) n = width; + bool b; + uint32_t v = local::decToU32(buf, n, &b); + if (!b) return 0; + uint32_t H = local::mulU32(x, x, xn, i1e9); + if (H > 0) { + if (xn == xSize) return 0; + x[xn++] = H; + } + H = local::addU32(x, xn, v); + if (H > 0) { + if (xn == xSize) return 0; + x[xn++] = H; + } + buf += n; + bufSize -= n; + } + if (sizeof(UT) == 8 && (xn & 1)) { + x[xn++] = 0; + } + return xn / (sizeof(UT) / 4); +} + +} } // mcp::fp @@ -63,35 +63,39 @@ inline Unit getUnitAsLE(const void *p) #endif } -const char *verifyStr(bool *isMinus, int *base, const std::string& str) +bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *buf, size_t bufSize) { - const char *p = str.c_str(); - if (*p == '-') { + if (bufSize == 0) return false; + size_t pos = 0; + if (*buf == '-') { + if (bufSize == 1) return false; *isMinus = true; - p++; + buf++; + pos++; } else { *isMinus = false; } - if (p[0] == '0') { - if (p[1] == 'x') { + if (buf[0] == '0') { + if (bufSize > 1 && buf[1] == 'x') { if (*base == 0 || *base == 16 || *base == (16 | IoPrefix)) { *base = 16; - p += 2; + pos += 2; } else { - throw cybozu::Exception("fp:verifyStr:0x conflicts with") << *base; + return false; } - } else if (p[1] == 'b') { + } else if (bufSize > 1 && buf[1] == 'b') { if (*base == 0 || *base == 2 || *base == (2 | IoPrefix)) { *base = 2; - p += 2; + pos += 2; } else { - throw cybozu::Exception("fp:verifyStr:0b conflicts with") << *base; + return false; } } } if (*base == 0) *base = 10; - if (*p == '\0') throw cybozu::Exception("fp:verifyStr:str is empty"); - return p; + if (pos == bufSize) return false; + *readSize = pos; + return true; } const char *ModeToStr(Mode mode) @@ -442,13 +446,17 @@ void Op::init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclM { // set mp and p bool isMinus = false; int base = 0; - const char *pstr = verifyStr(&isMinus, &base, mstr); - if (isMinus) throw cybozu::Exception("Op:init:mstr is minus") << mstr; + size_t readSize; + if (!parsePrefix(&readSize, &isMinus, &base, mstr.c_str(), mstr.size())) { + throw cybozu::Exception("fp:parsePrefix"); + } + const char *pstr = mstr.c_str() + readSize; if (!gmp::setStr(mp, pstr, base)) { throw cybozu::Exception("Op:init:bad str") << mstr; } - if (mp == 0) throw cybozu::Exception("Op:init:mstr is zero") << mstr; + if (isMinus) throw cybozu::Exception("Op:init:mstr is minus") << mstr; } + if (mp == 0) throw cybozu::Exception("Op:init:mstr is zero") << mstr; gmp::getArray(p, (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize, mp); bitSize = gmp::getBitSize(mp); pmod4 = gmp::getUnit(mp, 0) % 4; @@ -571,27 +579,20 @@ void Op::init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclM } } -void arrayToStr(std::string& str, const Unit *x, size_t n, int ioMode) +size_t arrayToStr(char *buf, size_t bufSize, const Unit *x, size_t n, int ioMode) { int base = ioMode & ~IoPrefix; bool withPrefix = (ioMode & IoPrefix) != 0; switch (base) { case 0: case 10: - { - mpz_class t; - gmp::setArray(t, x, n); - gmp::getStr(str, t, 10); - } - return; + return mcl::fp::arrayToDec(buf, bufSize, x, n); case 16: - mcl::fp::toStr16(str, x, n, withPrefix); - return; + return mcl::fp::arrayToHex(buf, bufSize, x, n, withPrefix); case 2: - mcl::fp::toStr2(str, x, n, withPrefix); - return; + return mcl::fp::arrayToBin(buf, bufSize, x, n, withPrefix); default: - throw cybozu::Exception("fp:arrayToStr:bad base") << base; + return 0; } } @@ -639,17 +640,22 @@ int detectIoMode(int ioMode, const std::ios_base& ios) return ioMode; } -void strToArray(bool *pIsMinus, Unit *x, size_t xN, const std::string& str, int ioMode) +bool strToArray(bool *pIsMinus, Unit *x, size_t xN, const char *buf, size_t bufSize, int ioMode) { assert(!(ioMode & (IoArray | IoArrayRaw | IoSerialize))); // use low 8-bit ioMode for Fp ioMode &= 0xff; - const char *p = verifyStr(pIsMinus, &ioMode, str); + size_t readSize; + if (!parsePrefix(&readSize, pIsMinus, &ioMode, buf, bufSize)) return false; +#if 0 +#else mpz_class mx; - if (!gmp::setStr(mx, p, ioMode)) { - throw cybozu::Exception("fp:strToArray:bad format") << ioMode << str; + if (!gmp::setStr(mx, std::string(buf + readSize, bufSize - readSize), ioMode)) { + return false; } gmp::getArray(x, xN, mx); +#endif + return true; } void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode) @@ -704,11 +710,7 @@ uint64_t getUint64(bool *pb, const fp::Block& b) if (pb) *pb = true; return v; } - if (!pb) { - std::string str; - arrayToStr(str, b.p, b.n, 10); - throw cybozu::Exception("fp::getUint64:large value") << str; - } + if (!pb) throw cybozu::Exception("fp::getUint64:large value"); *pb = false; return 0; } @@ -743,11 +745,7 @@ int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op) } } } - if (!pb) { - std::string str; - arrayToStr(str, b.p, b.n, 10); - throw cybozu::Exception("fp::getInt64:large value") << str << isNegative; - } + if (!pb) throw cybozu::Exception("fp::getInt64:large value"); *pb = false; return 0; } diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp new file mode 100644 index 0000000..3f1f959 --- /dev/null +++ b/test/conversion_test.cpp @@ -0,0 +1,57 @@ +#include <cybozu/test.hpp> +#include "../src/conversion.hpp" + +CYBOZU_TEST_AUTO(arrayToDec) +{ + const struct { + uint32_t x[5]; + size_t xn; + const char *s; + } tbl[] = { + { { 0, 0, 0, 0, 0 }, 1, "0" }, + { { 9, 0, 0, 0, 0 }, 1, "9" }, + { { 123456789, 0, 0, 0, 0 }, 1, "123456789" }, + { { 2147483647, 0, 0, 0, 0 }, 1, "2147483647" }, + { { 0xffffffff, 0, 0, 0, 0 }, 1, "4294967295" }, + { { 0x540be400, 0x2, 0, 0, 0 }, 2, "10000000000" }, + { { 0xffffffff, 0xffffffff, 0, 0, 0 }, 2, "18446744073709551615" }, + { { 0x89e80001, 0x8ac72304, 0, 0, 0 }, 2, "10000000000000000001" }, + { { 0xc582ca00, 0x8ac72304, 0, 0, 0 }, 2, "10000000001000000000" }, + { { 0, 0, 1, 0, 0 }, 3, "18446744073709551616" }, + { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }, 4, "340282366920938463463374607431768211455" }, + { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 5, "1461501637330902918203684832716283019655932542975" }, + { { 0x3b9aca00, 0x5e3f3700, 0x1cbfa532, 0x04f6433a, 0xd83ff078 }, 5, "1234567901234560000000000000000000000001000000000" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t bufSize = 128; + char buf[bufSize] = {}; + const char *str = tbl[i].s; + const uint32_t *x = tbl[i].x; + const size_t strLen = strlen(str); + size_t n = mcl::fp::arrayToDec(buf, bufSize, x, tbl[i].xn); + CYBOZU_TEST_EQUAL(n, strLen); + CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n); + const size_t maxN = 32; + uint32_t xx[maxN] = {}; + size_t xn = mcl::fp::convertDecToArray(xx, maxN, str, strLen); + CYBOZU_TEST_EQUAL(xn, tbl[i].xn); + CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn); + } + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t bufSize = 128; + char buf[bufSize] = {}; + const char *str = tbl[i].s; + const size_t strLen = strlen(str); + uint64_t x[8] = {}; + size_t xn = (tbl[i].xn + 1) / 2; + memcpy(x, tbl[i].x, tbl[i].xn * sizeof(uint32_t)); + size_t n = mcl::fp::arrayToDec(buf, bufSize, x, xn); + CYBOZU_TEST_EQUAL(n, strLen); + CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n); + const size_t maxN = 32; + uint64_t xx[maxN] = {}; + size_t xxn = mcl::fp::convertDecToArray(xx, maxN, str, strLen); + CYBOZU_TEST_EQUAL(xxn, xn); + CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn); + } +} diff --git a/test/fp_util_test.cpp b/test/fp_util_test.cpp index fbbe166..72e6c7d 100644 --- a/test/fp_util_test.cpp +++ b/test/fp_util_test.cpp @@ -4,7 +4,7 @@ #include <mcl/gmp_util.hpp> #include <mcl/fp.hpp> -CYBOZU_TEST_AUTO(toStr16) +CYBOZU_TEST_AUTO(arrayToHex) { const struct { uint32_t x[4]; @@ -18,15 +18,39 @@ CYBOZU_TEST_AUTO(toStr16) { { 1, 2, 0xffffffff, 0x123abc }, 4, "123abcffffffff0000000200000001" }, }; for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { - std::string str; - mcl::fp::toStr16(str, tbl[i].x, tbl[i].n, false); - CYBOZU_TEST_EQUAL(str, tbl[i].str); - mcl::fp::toStr16(str, tbl[i].x, tbl[i].n, true); - CYBOZU_TEST_EQUAL(str, std::string("0x") + tbl[i].str); + char buf[64]; + size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, false); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n); + n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, true); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0x") + tbl[i].str).c_str(), n); } } -// CYBOZU_TEST_AUTO(toStr2) // QQQ +CYBOZU_TEST_AUTO(arrayToBin) +{ + const struct { + uint32_t x[4]; + size_t n; + const char *str; + } tbl[] = { + { { 0, 0, 0, 0 }, 0, "0" }, + { { 0x123, 0, 0, 0 }, 1, "100100011" }, + { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "10101010101110111100110000010010001101000101011001111000" }, + { { 0, 0x12, 0x234a, 0 }, 3, "100011010010100000000000000000000000000001001000000000000000000000000000000000" }, + { { 1, 2, 0xffffffff, 0x123abc }, 4, "100100011101010111100111111111111111111111111111111110000000000000000000000000000001000000000000000000000000000000001" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[512]; + size_t n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, false); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n); + n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, true); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0b") + tbl[i].str).c_str(), n); + } +} // CYBOZU_TEST_AUTO(verifyStr) // QQQ CYBOZU_TEST_AUTO(fromStr16) |