diff options
Diffstat (limited to 'include/jsoncons/text_source_adaptor.hpp')
-rw-r--r-- | include/jsoncons/text_source_adaptor.hpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/include/jsoncons/text_source_adaptor.hpp b/include/jsoncons/text_source_adaptor.hpp new file mode 100644 index 0000000..491e8a6 --- /dev/null +++ b/include/jsoncons/text_source_adaptor.hpp @@ -0,0 +1,144 @@ +// Copyright 2021 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_TEXT_SOURCE_ADAPTOR_HPP +#define JSONCONS_TEXT_SOURCE_ADAPTOR_HPP + +#include <cstddef> +#include <string> +#include <vector> +#include <stdexcept> +#include <system_error> +#include <memory> // std::allocator_traits +#include <vector> // std::vector +#include <jsoncons/unicode_traits.hpp> +#include <jsoncons/json_error.hpp> // json_errc +#include <jsoncons/source.hpp> +#include <jsoncons/json_exception.hpp> + +namespace jsoncons { + + // unicode_source_adaptor + + template<class Source,class Allocator> + class unicode_source_adaptor + { + public: + using value_type = typename Source::value_type; + using source_type = Source; + private: + source_type source_; + bool bof_; + + + public: + template <class Sourceable> + unicode_source_adaptor(Sourceable&& source) + : source_(std::forward<Sourceable>(source)), + bof_(true) + { + } + + bool is_error() const + { + return source_.is_error(); + } + + bool eof() const + { + return source_.eof(); + } + + span<const value_type> read_buffer(std::error_code& ec) + { + if (source_.eof()) + { + return span<const value_type>(); + } + + auto s = source_.read_buffer(); + const value_type* data = s.data(); + std::size_t length = s.size(); + + if (bof_ && length > 0) + { + auto r = unicode_traits::detect_encoding_from_bom(data, length); + if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected)) + { + ec = json_errc::illegal_unicode_character; + return; + } + length -= (r.ptr - data); + data = r.ptr; + bof_ = false; + } + return span<const value_type>(data, length); + } + }; + + // json_source_adaptor + + template<class Source,class Allocator> + class json_source_adaptor + { + public: + using value_type = typename Source::value_type; + using value_type = typename Source::value_type; + using source_type = Source; + private: + source_type source_; + bool bof_; + + public: + + template <class Sourceable> + json_source_adaptor(Sourceable&& source) + : source_(std::forward<Sourceable>(source)), + bof_(true) + { + } + + bool is_error() const + { + return source_.is_error(); + } + + bool eof() const + { + return source_.eof(); + } + + span<const value_type> read_buffer(std::error_code& ec) + { + if (source_.eof()) + { + return span<const value_type>(); + } + + auto s = source_.read_buffer(); + const value_type* data = s.data(); + std::size_t length = s.size(); + + if (bof_ && length > 0) + { + auto r = unicode_traits::detect_json_encoding(data, length); + if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected)) + { + ec = json_errc::illegal_unicode_character; + return span<const value_type>(); + } + length -= (r.ptr - data); + data = r.ptr; + bof_ = false; + } + return span<const value_type>(data, length); + } + }; + +} // namespace jsoncons + +#endif + |