summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp')
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp266
1 files changed, 266 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp
new file mode 100644
index 00000000..1a8fc0a9
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/number_parsers.hpp
@@ -0,0 +1,266 @@
+// Copyright 2013 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_DETAIL_NUMBERPARSERS_HPP
+#define JSONCONS_DETAIL_NUMBERPARSERS_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <type_traits>
+#include <algorithm>
+#include <exception>
+#include <jsoncons/jsoncons_config.hpp>
+
+namespace jsoncons { namespace detail {
+
+struct to_integer_result
+{
+ int64_t value;
+ bool overflow;
+};
+
+// Precondition: s satisfies
+
+// digit
+// digit1-digits
+// - digit
+// - digit1-digits
+
+template <class CharT>
+to_integer_result to_integer(const CharT* s, size_t length)
+{
+ JSONCONS_ASSERT(length > 0);
+
+ int64_t n = 0;
+ bool overflow = false;
+ const CharT* end = s + length;
+ if (*s == '-')
+ {
+ static const int64_t min_value = (std::numeric_limits<int64_t>::min)();
+ static const int64_t min_value_div_10 = min_value / 10;
+ ++s;
+ for (; s < end; ++s)
+ {
+ int64_t x = *s - '0';
+ if (n < min_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n < min_value + x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n -= x;
+ }
+ }
+ else
+ {
+ static const int64_t max_value = (std::numeric_limits<int64_t>::max)();
+ static const int64_t max_value_div_10 = max_value / 10;
+ for (; s < end; ++s)
+ {
+ int64_t x = *s - '0';
+ if (n > max_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n += x;
+ }
+ }
+
+ return to_integer_result({ n,overflow });
+}
+
+struct to_uinteger_result
+{
+ uint64_t value;
+ bool overflow;
+};
+
+// Precondition: s satisfies
+
+// digit
+// digit1-digits
+// - digit
+// - digit1-digits
+
+template <class CharT>
+to_uinteger_result to_uinteger(const CharT* s, size_t length)
+{
+ JSONCONS_ASSERT(length > 0);
+
+ static const uint64_t max_value = (std::numeric_limits<uint64_t>::max)();
+ static const uint64_t max_value_div_10 = max_value / 10;
+ uint64_t n = 0;
+ bool overflow = false;
+
+ const CharT* end = s + length;
+ for (; s < end; ++s)
+ {
+ uint64_t x = *s - '0';
+ if (n > max_value_div_10)
+ {
+ overflow = true;
+ break;
+ }
+ n = n * 10;
+ if (n > max_value - x)
+ {
+ overflow = true;
+ break;
+ }
+
+ n += x;
+ }
+ return to_uinteger_result{ n,overflow };
+}
+
+#if defined(JSONCONS_HAS_MSC__STRTOD_L)
+
+class string_to_double
+{
+private:
+ _locale_t locale_;
+public:
+ string_to_double()
+ {
+ locale_ = _create_locale(LC_NUMERIC, "C");
+ }
+ ~string_to_double()
+ {
+ _free_locale(locale_);
+ }
+
+ char get_decimal_point() const
+ {
+ return '.';
+ }
+
+ double operator()(const char* s, size_t) const
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ double val = _strtod_l(begin, &end, locale_);
+ if (begin == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("Invalid float value"));
+ }
+ return val;
+ }
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double&) = delete;
+ string_to_double& operator=(const string_to_double&) = delete;
+};
+
+#elif defined(JSONCONS_HAS_STRTOLD_L)
+
+class string_to_double
+{
+private:
+ locale_t locale_;
+public:
+ string_to_double()
+ {
+ locale_ = newlocale(LC_ALL_MASK, "C", (locale_t) 0);
+ }
+ ~string_to_double()
+ {
+ freelocale(locale_);
+ }
+
+ char get_decimal_point() const
+ {
+ return '.';
+ }
+
+ double operator()(const char* s, size_t length) const
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ double val = strtold_l(begin, &end, locale_);
+ if (begin == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("Invalid float value"));
+ }
+ return val;
+ }
+
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double& fr) = delete;
+ string_to_double& operator=(const string_to_double& fr) = delete;
+};
+
+#else
+class string_to_double
+{
+private:
+ std::vector<char> buffer_;
+ char decimal_point_;
+public:
+ string_to_double()
+ : buffer_()
+ {
+ struct lconv * lc = localeconv();
+ if (lc != nullptr && lc->decimal_point[0] != 0)
+ {
+ decimal_point_ = lc->decimal_point[0];
+ }
+ else
+ {
+ decimal_point_ = '.';
+ }
+ buffer_.reserve(100);
+ }
+
+ char get_decimal_point() const
+ {
+ return decimal_point_;
+ }
+
+ double operator()(const char* s, size_t /*length*/) const
+ {
+ char *end = nullptr;
+ double val = strtod(s, &end);
+ if (s == end)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("string_to_double failed"));
+ }
+ return val;
+ }
+
+private:
+ // noncopyable and nonmoveable
+ string_to_double(const string_to_double& fr) = delete;
+ string_to_double& operator=(const string_to_double& fr) = delete;
+};
+#endif
+
+}}
+
+#endif