aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@oath.com>2019-06-14 21:39:34 +0000
committerHenning Baldersheim <balder@oath.com>2019-06-14 21:39:34 +0000
commit76f910b9387e486418957ee7aa4a2ea5ea1a762d (patch)
tree87590a002e1bcd8fe9aaed9798e1e6e774f525cf /vespalib
parentd8c31e9bb2254244d521dfba6fbefd18e2fa7c46 (diff)
Use std::from_chars in stream.
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/stllike/asciistream_test.cpp16
-rw-r--r--vespalib/src/vespa/vespalib/stllike/asciistream.cpp106
2 files changed, 51 insertions, 71 deletions
diff --git a/vespalib/src/tests/stllike/asciistream_test.cpp b/vespalib/src/tests/stllike/asciistream_test.cpp
index b1ba70e6ae2..6e628d7e52c 100644
--- a/vespalib/src/tests/stllike/asciistream_test.cpp
+++ b/vespalib/src/tests/stllike/asciistream_test.cpp
@@ -72,16 +72,16 @@ AsciistreamTest::testIllegalNumbers()
{
asciistream is("777777777777");
uint16_t s(0);
- EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "An unsigned short can not represent '777777777777'");
+ EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "strToInt value '777777777777' is outside of range");
EXPECT_EQUAL(12u, is.size());
uint32_t i(0);
- EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "An unsigned int can not represent '777777777777'");
+ EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "strToInt value '777777777777' is outside of range");
EXPECT_EQUAL(12u, is.size());
int16_t si(0);
- EXPECT_EXCEPTION(is >> si, IllegalArgumentException, "A short can not represent '777777777777'");
+ EXPECT_EXCEPTION(is >> si, IllegalArgumentException, "strToInt value '777777777777' is outside of range");
EXPECT_EQUAL(12u, is.size());
int32_t ii(0);
- EXPECT_EXCEPTION(is >> ii, IllegalArgumentException, "An int can not represent '777777777777'");
+ EXPECT_EXCEPTION(is >> ii, IllegalArgumentException, "strToInt value '777777777777' is outside of range");
EXPECT_EQUAL(12u, is.size());
is << "777777777777";
EXPECT_EQUAL(24u, is.size());
@@ -95,10 +95,10 @@ AsciistreamTest::testIllegalNumbers()
{
asciistream is("-77");
uint16_t s(0);
- EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "An unsigned short can not represent '-77'");
+ EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "Illegal strToInt value '-77'");
EXPECT_EQUAL(3u, is.size());
uint32_t i(0);
- EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "An unsigned int can not represent '-77'");
+ EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "Illegal strToInt value '-77'");
EXPECT_EQUAL(3u, is.size());
}
{
@@ -131,12 +131,12 @@ AsciistreamTest::testIllegalNumbers()
EXPECT_TRUE(is.empty());
{
uint32_t l(0);
- EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "Failed decoding a unsigned long long from ''.");
+ EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "buffer underflow at pos 0.");
EXPECT_TRUE(is.empty());
}
{
int32_t l(0);
- EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "Failed decoding a long long from ''.");
+ EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "buffer underflow at pos 0");
EXPECT_TRUE(is.empty());
}
{
diff --git a/vespalib/src/vespa/vespalib/stllike/asciistream.cpp b/vespalib/src/vespa/vespalib/stllike/asciistream.cpp
index 7d585cf1cf6..739eb2f6d78 100644
--- a/vespalib/src/vespa/vespalib/stllike/asciistream.cpp
+++ b/vespalib/src/vespa/vespalib/stllike/asciistream.cpp
@@ -10,7 +10,8 @@
#include <limits>
#include <stdexcept>
#include <cassert>
-#include <math.h>
+#include <cmath>
+#include <charconv>
#include <vespa/log/log.h>
LOG_SETUP(".vespalib.stllike.asciistream");
@@ -77,9 +78,7 @@ asciistream::asciistream(stringref buf) :
}
}
-asciistream::~asciistream()
-{
-}
+asciistream::~asciistream() = default;
asciistream::asciistream(const asciistream & rhs) :
_rPos(0),
@@ -145,10 +144,11 @@ namespace {
int getValue(double & val, const char *buf) __attribute__((noinline));
int getValue(float & val, const char *buf) __attribute__((noinline));
-int getValue(unsigned long long & val, const char *buf) __attribute__((noinline));
-int getValue(long long & val, const char *buf) __attribute__((noinline));
void throwInputError(int e, const char * t, const char * buf) __attribute__((noinline));
+void throwInputError(std::errc e, const char * t, const char * buf) __attribute__((noinline));
void throwUnderflow(size_t pos) __attribute__((noinline));
+template <typename T>
+T strToInt(T & v, const char *begin, const char *end) __attribute__((noinline));
void throwInputError(int e, const char * t, const char * buf)
{
@@ -163,6 +163,16 @@ void throwInputError(int e, const char * t, const char * buf)
}
}
+void throwInputError(std::errc e, const char * t, const char * buf) {
+ if (e == std::errc::invalid_argument) {
+ throw IllegalArgumentException("Illegal " + string(t) + " value '" + string(buf) + "'.", VESPA_STRLOC);
+ } else if (e == std::errc::result_out_of_range) {
+ throw IllegalArgumentException(string(t) + " value '" + string(buf) + "' is outside of range.", VESPA_STRLOC);
+ } else {
+ throw IllegalArgumentException("Unknown error decoding an " + string(t) + " from '" + string(buf) + "'.", VESPA_STRLOC);
+ }
+}
+
void throwUnderflow(size_t pos)
{
throw IllegalArgumentException(make_string("buffer underflow at pos %ld.", pos), VESPA_STRLOC);
@@ -190,26 +200,28 @@ int getValue(float & val, const char *buf)
return ebuf - buf;
}
-int getValue(unsigned long long & val, const char *buf)
+template <typename T>
+T strToInt(T & v, const char *begin, const char *end)
{
- char *ebuf;
- errno = 0;
- val = strtoull(buf, &ebuf, 0);
- if ((errno != 0) || (buf == ebuf)) {
- throwInputError(errno, "unsigned long long", buf);
- }
- return ebuf - buf;
-}
+ const char * curr = begin;
+ for (;(curr < end) && std::isspace(*curr); curr++);
-int getValue(long long & val, const char *buf)
-{
- char *ebuf;
- errno = 0;
- val = strtoll(buf, &ebuf, 0);
- if ((errno != 0) || (buf == ebuf)) {
- throwInputError(errno, "long long", buf);
+ std::from_chars_result err;
+ if (((end - curr) > 2) && (curr[0] == '0') && ((curr[1] | 0x20) == 'x')) {
+ err = std::from_chars(curr+2, end, v, 16);
+ } else {
+ err = std::from_chars(curr, end, v, 10);
}
- return ebuf - buf;
+ if (err.ec == std::errc::invalid_argument) {
+ if (err.ptr >= end) {
+ throwUnderflow(err.ptr - begin);
+ }
+ throwInputError(err.ec, "strToInt", begin);
+ } else if (err.ec == std::errc::result_out_of_range) {
+ throwInputError(err.ec, "strToInt", begin);
+ }
+
+ return err.ptr - curr;
}
}
@@ -260,81 +272,49 @@ asciistream & asciistream::operator >> (unsigned char & v)
asciistream & asciistream::operator >> (unsigned short & v)
{
- unsigned long long l(0);
- size_t r = getValue(l, &_rbuf[_rPos]);
- if (l > std::numeric_limits<unsigned short>::max()) {
- throw IllegalArgumentException(make_string("An unsigned short can not represent '%lld'.", l), VESPA_STRLOC);
- }
- _rPos += r;
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (unsigned int & v)
{
- unsigned long long l(0);
- size_t r = getValue(l, &_rbuf[_rPos]);
- if (l > std::numeric_limits<unsigned int>::max()) {
- throw IllegalArgumentException(make_string("An unsigned int can not represent '%lld'.", l), VESPA_STRLOC);
- }
- _rPos += r;
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (unsigned long & v)
{
- unsigned long long l(0);
- _rPos += getValue(l, &_rbuf[_rPos]);
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (unsigned long long & v)
{
- unsigned long long l(0);
- _rPos += getValue(l, &_rbuf[_rPos]);
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (short & v)
{
- long long l(0);
- size_t r = getValue(l, &_rbuf[_rPos]);
- if ((l < std::numeric_limits<short>::min()) || (l > std::numeric_limits<short>::max())) {
- throw IllegalArgumentException(make_string("A short can not represent '%lld'.", l), VESPA_STRLOC);
- }
- _rPos += r;
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (int & v)
{
- long long l(0);
- size_t r = getValue(l, &_rbuf[_rPos]);
- if ((l < std::numeric_limits<int>::min()) || (l > std::numeric_limits<int>::max())) {
- throw IllegalArgumentException(make_string("An int can not represent '%lld'.", l), VESPA_STRLOC);
- }
- _rPos += r;
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (long & v)
{
- long long l(0);
- _rPos += getValue(l, &_rbuf[_rPos]);
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}
asciistream & asciistream::operator >> (long long & v)
{
- long long l(0);
- _rPos += getValue(l, &_rbuf[_rPos]);
- v = l;
+ _rPos += strToInt(v, &_rbuf[_rPos], &_rbuf[length()]);
return *this;
}