summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp')
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp374
1 files changed, 374 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp b/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp
new file mode 100644
index 00000000..58779280
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons/detail/number_printers.hpp
@@ -0,0 +1,374 @@
+// 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_NUMBERPRINTERS_HPP
+#define JSONCONS_DETAIL_NUMBERPRINTERS_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <locale>
+#include <limits>
+#include <algorithm>
+#include <exception>
+#include <jsoncons/jsoncons_config.hpp>
+#include <jsoncons/detail/obufferedstream.hpp>
+
+namespace jsoncons { namespace detail {
+
+// print_integer
+
+template<class Writer>
+void print_integer(int64_t value, Writer& os)
+{
+ typedef typename Writer::char_type char_type;
+
+ char_type buf[255];
+ uint64_t u = (value < 0) ? static_cast<uint64_t>(-value) : static_cast<uint64_t>(value);
+ char_type* p = buf;
+ do
+ {
+ *p++ = static_cast<char_type>(48 + u%10);
+ }
+ while (u /= 10);
+ if (value < 0)
+ {
+ os.put('-');
+ }
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+// print_uinteger
+
+template<class Writer>
+void print_uinteger(uint64_t value, Writer& os)
+{
+ typedef typename Writer::char_type char_type;
+
+ char_type buf[255];
+ char_type* p = buf;
+ do
+ {
+ *p++ = static_cast<char_type>(48 + value % 10);
+ } while (value /= 10);
+ while (--p >= buf)
+ {
+ os.put(*p);
+ }
+}
+
+// print_double
+
+#if defined(JSONCONS_HAS__ECVT_S)
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ char buf[_CVTBUFSIZE];
+ int decimal_point = 0;
+ int sign = 0;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ int err = _ecvt_s(buf, _CVTBUFSIZE, val, prec, &decimal_point, &sign);
+ if (err != 0)
+ {
+ JSONCONS_THROW(json_exception_impl<std::runtime_error>("Failed attempting double to string conversion"));
+ }
+ //std::cout << "prec:" << prec << ", buf:" << buf << std::endl;
+ char* s = buf;
+ char* se = s + prec;
+
+ int i, k;
+ int j;
+
+ if (sign)
+ {
+ writer.put('-');
+ }
+ if (decimal_point <= -4 || decimal_point > se - s + 5)
+ {
+ writer.put(*s++);
+ if (s < se)
+ {
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+
+ while(s < se)
+ {
+ writer.put(*s++);
+ }
+ }
+ writer.put('e');
+ /* sprintf(b, "%+.2d", decimal_point - 1); */
+ if (--decimal_point < 0) {
+ writer.put('-');
+ decimal_point = -decimal_point;
+ }
+ else
+ writer.put('+');
+ for(j = 2, k = 10; 10*k <= decimal_point; j++, k *= 10);
+ for(;;)
+ {
+ i = decimal_point / k;
+ writer.put(static_cast<char_type>(i) + '0');
+ if (--j <= 0)
+ break;
+ decimal_point -= i*k;
+ decimal_point *= 10;
+ }
+ }
+ else if (decimal_point <= 0)
+ {
+ writer.put('0');
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ for(; decimal_point < 0; decimal_point++)
+ {
+ writer.put('0');
+ }
+ while(s < se)
+ {
+ writer.put(*s++);
+ }
+ }
+ else {
+ while(s < se)
+ {
+ writer.put(*s++);
+ if ((--decimal_point == 0) && s < se)
+ {
+ writer.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ }
+ }
+ for(; decimal_point > 0; decimal_point--)
+ {
+ writer.put('0');
+ }
+ }
+ }
+};
+
+#elif defined(JSONCONS_NO_LOCALECONV)
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+ basic_obufferedstream<char> os_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ os_.imbue(std::locale::classic());
+ os_.precision(precision);
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ os_.clear_sequence();
+ os_.precision(prec);
+ os_ << val;
+
+ //std::cout << "precision_override_:" << (int)precision_override_ << ", precision:" << (int)precision << ", buf:" << os_.data() << std::endl;
+
+ const char_type* sbeg = os_.data();
+ const char_type* send = sbeg + os_.length();
+ const char_type* pexp = send;
+
+ if (sbeg != send)
+ {
+ bool dot = false;
+ for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp)
+ {
+ }
+
+ const char_type* qend = pexp;
+ while (qend >= sbeg+2 && *(qend-1) == '0' && *(qend-2) != '.')
+ {
+ --qend;
+ }
+ if (pexp == send)
+ {
+ qend = ((qend >= sbeg+2) && *(qend-2) == '.') ? qend : send;
+ }
+
+ for (const char_type* q = sbeg; q < qend; ++q)
+ {
+ if (*q == '.')
+ {
+ dot = true;
+ }
+ writer.put(*q);
+ }
+ if (!dot)
+ {
+ writer.put('.');
+ writer.put('0');
+ dot = true;
+ }
+ for (const char_type* q = pexp; q < send; ++q)
+ {
+ writer.put(*q);
+ }
+ }
+ }
+};
+#else
+
+class print_double
+{
+private:
+ uint8_t precision_override_;
+ char decimal_point_;
+public:
+ print_double(uint8_t precision)
+ : precision_override_(precision)
+ {
+ struct lconv * lc = localeconv();
+ if (lc != nullptr && lc->decimal_point[0] != 0)
+ {
+ decimal_point_ = lc->decimal_point[0];
+ }
+ else
+ {
+ decimal_point_ = '.';
+ }
+ }
+
+ template <class Writer>
+ void operator()(double val, uint8_t precision, Writer& writer)
+ {
+ typedef typename Writer::char_type char_type;
+
+ int prec;
+ if (precision_override_ != 0)
+ {
+ prec = precision_override_;
+ }
+ else if (precision != 0)
+ {
+ prec = precision;
+ }
+ else
+ {
+ prec = std::numeric_limits<double>::digits10;
+ }
+
+ char number_buffer[100];
+ int length = snprintf(number_buffer, 100, "%1.*g", prec, val);
+ if (length < 0)
+ {
+ JSONCONS_THROW(json_exception_impl<std::invalid_argument>("print_double failed."));
+ }
+
+ const char* sbeg = number_buffer;
+ const char* send = sbeg + length;
+ const char* pexp = send;
+
+ if (sbeg != send)
+ {
+ bool dot = false;
+ for (pexp = sbeg; *pexp != 'e' && *pexp != 'E' && pexp < send; ++pexp)
+ {
+ }
+
+ for (const char* q = sbeg; q < pexp; ++q)
+ {
+ switch (*q)
+ {
+ case '-':case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
+ writer.put(*q);
+ break;
+ default:
+ if (*q == decimal_point_)
+ {
+ dot = true;
+ writer.put('.');
+ }
+ break;
+ }
+ }
+ if (!dot)
+ {
+ writer.put('.');
+ writer.put('0');
+ dot = true;
+ }
+ for (const char* q = pexp; q < send; ++q)
+ {
+ writer.put(*q);
+ }
+ }
+ }
+};
+
+#endif
+
+}}
+
+#endif