summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp')
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp
new file mode 100644
index 00000000..27c90fa1
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons/jsoncons_io.hpp
@@ -0,0 +1,358 @@
+// 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_JSONCONS_IO_HPP
+#define JSONCONS_JSONCONS_IO_HPP
+
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <ostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <cstdarg>
+#include <limits> // std::numeric_limits
+#include "jsoncons_config.hpp"
+#include "ovectorstream.hpp"
+
+namespace jsoncons
+{
+
+template <typename CharT>
+class buffered_ostream
+{
+ static const size_t default_buffer_length = 16384;
+
+ std::basic_ostream<CharT>* os_;
+ std::vector<CharT> buffer_;
+ CharT * const begin_buffer_;
+ const CharT* const end_buffer_;
+ CharT* p_;
+public:
+ buffered_ostream(std::basic_ostream<CharT>& os)
+ : os_(std::addressof(os)), buffer_(default_buffer_length), begin_buffer_(buffer_.data()), end_buffer_(buffer_.data()+default_buffer_length), p_(buffer_.data())
+ {
+ }
+ ~buffered_ostream()
+ {
+ os_->write(begin_buffer_, (p_ - begin_buffer_));
+ os_->flush();
+ }
+
+ void flush()
+ {
+ os_->write(begin_buffer_, (p_ - begin_buffer_));
+ p_ = begin_buffer_;
+ os_->flush();
+ }
+
+ void write(const CharT* s, size_t length)
+ {
+ size_t diff = end_buffer_ - p_;
+ if (diff >= length)
+ {
+ std::memcpy(p_, s, length*sizeof(CharT));
+ p_ += length;
+ }
+ else
+ {
+ os_->write(begin_buffer_, (p_ - begin_buffer_));
+ os_->write(s, length);
+ p_ = begin_buffer_;
+ }
+ }
+
+ void write(const std::basic_string<CharT>& s)
+ {
+ write(s.data(),s.length());
+ }
+
+ void put(CharT c)
+ {
+ if (p_ < end_buffer_)
+ {
+ *p_++ = c;
+ }
+ else
+ {
+ os_->write(begin_buffer_, (p_-begin_buffer_));
+ p_ = begin_buffer_;
+ *p_++ = c;
+ }
+ }
+
+};
+
+#ifdef _MSC_VER
+
+template <typename CharT>
+class float_printer
+{
+ uint8_t precision_;
+public:
+ float_printer(int precision)
+ : precision_(precision)
+ {
+ }
+
+ void print(double val, uint8_t precision, buffered_ostream<CharT>& os)
+ {
+ char buf[_CVTBUFSIZE];
+ int decimal_point = 0;
+ int sign = 0;
+
+ int prec = (precision == 0) ? precision_ : precision;
+
+ int err = _ecvt_s(buf, _CVTBUFSIZE, val, prec, &decimal_point, &sign);
+ if (err != 0)
+ {
+ throw std::runtime_error("Failed attempting double to string conversion");
+ }
+ char* s = buf;
+ char* se = s + prec;
+
+ int i, k;
+ int j;
+
+ if (sign)
+ {
+ os.put('-');
+ }
+ if (decimal_point <= -4 || decimal_point > se - s + 5)
+ {
+ os.put(*s++);
+ if (s < se)
+ {
+ os.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+
+ while(s < se)
+ {
+ os.put(*s++);
+ }
+ }
+ os.put('e');
+ /* sprintf(b, "%+.2d", decimal_point - 1); */
+ if (--decimal_point < 0) {
+ os.put('-');
+ decimal_point = -decimal_point;
+ }
+ else
+ os.put('+');
+ for(j = 2, k = 10; 10*k <= decimal_point; j++, k *= 10);
+ for(;;)
+ {
+ i = decimal_point / k;
+ os.put(i + '0');
+ if (--j <= 0)
+ break;
+ decimal_point -= i*k;
+ decimal_point *= 10;
+ }
+ }
+ else if (decimal_point <= 0)
+ {
+ os.put('0');
+ os.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ for(; decimal_point < 0; decimal_point++)
+ {
+ os.put('0');
+ }
+ while(s < se)
+ {
+ os.put(*s++);
+ }
+ }
+ else {
+ while(s < se)
+ {
+ os.put(*s++);
+ if ((--decimal_point == 0) && s < se)
+ {
+ os.put('.');
+ while ((se-1) > s && *(se-1) == '0')
+ {
+ --se;
+ }
+ }
+ }
+ for(; decimal_point > 0; decimal_point--)
+ {
+ os.put('0');
+ }
+ }
+ }
+};
+
+#else
+
+template <typename CharT>
+class float_printer
+{
+ jsoncons::basic_ovectorstream<CharT> vs_;
+ uint8_t precision_;
+public:
+ float_printer(uint8_t precision)
+ : vs_(255), precision_(precision)
+ {
+ vs_.set_locale(std::locale::classic());
+ vs_.precision(precision);
+ }
+
+ void print(double val, uint8_t precision, buffered_ostream<CharT>& os)
+ {
+ vs_.reset();
+ vs_.precision(precision == 0 ? precision_ : precision);
+ vs_ << val;
+
+ const CharT* s = vs_.data();
+ const CharT* se = s + vs_.length();
+
+ bool dot = false;
+ while (s < se)
+ {
+ if (*s == '.')
+ {
+ dot = true;
+ }
+ else if (*s == 'e')
+ {
+ if (!dot)
+ {
+ os.put('.');
+ os.put('0');
+ dot = true;
+ }
+ }
+ os.put(*s);
+ ++s;
+ }
+ if (!dot)
+ {
+ os.put('.');
+ os.put('0');
+ }
+ }
+};
+
+#endif
+
+// string_to_float only requires narrow char
+#ifdef _MSC_VER
+class float_reader
+{
+private:
+ _locale_t locale_;
+public:
+ float_reader()
+ {
+ locale_ = _create_locale(LC_NUMERIC, "C");
+ }
+ ~float_reader()
+ {
+ _free_locale(locale_);
+ }
+
+ double read(const char* s, size_t length)
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ double val = _strtod_l(begin, &end, locale_);
+ if (begin == end)
+ {
+ throw std::invalid_argument("Invalid float value");
+ }
+ return val;
+ }
+
+ float_reader(const float_reader& fr) = delete;
+ float_reader& operator=(const float_reader& fr) = delete;
+};
+
+#else
+class float_reader
+{
+private:
+ std::vector<char> buffer_;
+ std::string decimal_point_;
+ bool is_dot_;
+public:
+ float_reader()
+ : buffer_()
+ {
+ struct lconv * lc = localeconv();
+ if (lc != nullptr)
+ {
+ decimal_point_ = std::string(lc->decimal_point);
+ }
+ else
+ {
+ decimal_point_ = std::string(".");
+ }
+ buffer_.reserve(100);
+ is_dot_ = decimal_point_ == ".";
+ }
+
+ double read(const char* s, size_t length)
+ {
+ double val;
+ if (is_dot_)
+ {
+ const char *begin = s;
+ char *end = nullptr;
+ val = strtod(begin, &end);
+ if (begin == end)
+ {
+ throw std::invalid_argument("Invalid float value");
+ }
+ }
+ else
+ {
+ buffer_.clear();
+ size_t j = 0;
+ const char* pe = s + length;
+ for (const char* p = s; p < pe; ++p)
+ {
+ if (*p == '.')
+ {
+ buffer_.insert(buffer_.begin() + j, decimal_point_.begin(), decimal_point_.end());
+ j += decimal_point_.length();
+ }
+ else
+ {
+ buffer_.push_back(*p);
+ ++j;
+ }
+ }
+ const char *begin = buffer_.data();
+ char *end = nullptr;
+ val = strtod(begin, &end);
+ if (begin == end)
+ {
+ throw std::invalid_argument("Invalid float value");
+ }
+ }
+ return val;
+ }
+
+ float_reader(const float_reader& fr) = delete;
+ float_reader& operator=(const float_reader& fr) = delete;
+};
+#endif
+
+}
+
+#endif