Skip to content

Commit

Permalink
support input from different encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
Nomango committed Sep 27, 2022
1 parent 1b774ab commit 68d452d
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 105 deletions.
16 changes: 8 additions & 8 deletions examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ int main(int argc, char** argv)
User u = { 1001, "中文" };

const auto str = json::dump<wchar_t>(u, {
json::serializer<wchar_t>::with_indent(2),
json::serializer<wchar_t>::with_escaping_unicode(false),
json::serializer<wchar_t>::with_source_encoding<encoding::auto_utf>(),
json::serializer<wchar_t>::with_target_encoding<encoding::auto_utf>(),
json::serializer_type<wchar_t>::with_indent(2),
json::serializer_type<wchar_t>::with_unicode_escaping(false),
json::serializer_type<wchar_t>::with_source_encoding<encoding::auto_utf>(),
json::serializer_type<wchar_t>::with_target_encoding<encoding::auto_utf>(),
});
std::wcout << str << std::endl;

u = json::parse("{\"id\": 1002,\"name\":\"Jack\"}", {
json::parser::with_error_handler(nullptr),
json::parser::with_source_encoding<encoding::auto_utf>(),
json::parser::with_target_encoding<encoding::auto_utf>(),
u = json::parse(L"{\"id\": 1002,\"name\":\"Jack中文\"}", {
json::parser_type<wchar_t>::with_error_handler(nullptr),
json::parser_type<wchar_t>::with_source_encoding<encoding::auto_utf>(),
json::parser_type<wchar_t>::with_target_encoding<encoding::auto_utf>(),
});

json::dump(std::wcout, u);
Expand Down
110 changes: 58 additions & 52 deletions include/configor/configor_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,23 @@

#include <functional> // std::function
#include <initializer_list> // std::initializer_list
#include <ios> // std::noskipws
#include <istream> // std::basic_istream
#include <streambuf> // std::basic_streambuf
#include <type_traits> // std::char_traits

namespace configor
{

namespace detail
{

template <typename _ValTy>
template <typename _ValTy, typename _SourceCharTy>
class basic_parser
{
public:
using value_type = _ValTy;
using integer_type = typename _ValTy::integer_type;
using float_type = typename _ValTy::float_type;
using char_type = typename _ValTy::char_type;
using string_type = typename _ValTy::string_type;
using istream_type = std::basic_istream<char_type>;

basic_parser(istream_type& is)
using value_type = _ValTy;
using source_char_type = _SourceCharTy;
using target_char_type = typename value_type::char_type;

basic_parser(std::basic_istream<source_char_type>& is)
: is_(nullptr)
, err_handler_(nullptr)
, source_decoder_(nullptr)
Expand Down Expand Up @@ -83,21 +77,21 @@ class basic_parser
template <template <class> class _Encoding>
inline void set_source_encoding()
{
source_decoder_ = _Encoding<char_type>::decode;
source_decoder_ = _Encoding<source_char_type>::decode;
}

template <template <class> class _Encoding>
inline void set_target_encoding()
{
target_encoder_ = _Encoding<char_type>::encode;
target_encoder_ = _Encoding<target_char_type>::encode;
}

protected:
virtual token_type scan() = 0;

virtual void get_integer(integer_type& out) = 0;
virtual void get_float(float_type& out) = 0;
virtual void get_string(string_type& out) = 0;
virtual void get_integer(typename value_type::integer_type& out) = 0;
virtual void get_float(typename value_type::float_type& out) = 0;
virtual void get_string(typename value_type::string_type& out) = 0;

virtual void do_parse(value_type& c, token_type last_token, bool read_next = true)
{
Expand Down Expand Up @@ -222,10 +216,10 @@ class basic_parser
}

protected:
std::basic_istream<char_type> is_;
error_handler* err_handler_;
encoding::decoder<char_type> source_decoder_;
encoding::encoder<char_type> target_encoder_;
std::basic_istream<source_char_type> is_;
error_handler* err_handler_;
encoding::decoder<source_char_type> source_decoder_;
encoding::encoder<target_char_type> target_encoder_;
};

//
Expand All @@ -236,79 +230,91 @@ template <typename _Args>
class parsable
{
public:
using value_type = typename _Args::value_type;
using char_type = typename value_type::char_type;
using string_type = typename value_type::string_type;
using value_type = typename _Args::value_type;

template <typename _SourceCharTy = typename value_type::char_type>
using parser_type = typename _Args::template parser_type<value_type, _SourceCharTy>;

template <typename _CharTy>
using default_encoding = typename _Args::template default_encoding<_CharTy>;
using parser = parser_type<>;

using parser = typename _Args::template parser_type<value_type>;
using parser_option = std::function<void(parser&)>;
template <typename _SourceCharTy>
using parser_option = std::function<void(parser_type<_SourceCharTy>&)>;

// parse from stream
static void parse(value_type& c, std::basic_istream<char_type>& is,
std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static void parse(value_type& c, std::basic_istream<_SourceCharTy>& is,
std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
parser p{ is };
p.template set_source_encoding<default_encoding>();
p.template set_target_encoding<default_encoding>();
parser_type<_SourceCharTy> p{ is };
p.template set_source_encoding<typename _Args::default_encoding>();
p.template set_target_encoding<typename _Args::default_encoding>();
for (const auto& option : options)
{
option(p);
}
p.parse(c);
}

static value_type parse(std::basic_istream<char_type>& is, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static value_type parse(std::basic_istream<_SourceCharTy>& is,
std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
value_type c;
parse(c, is, options);
return c;
}

// parse from string
static void parse(value_type& c, const string_type& str, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static void parse(value_type& c, const typename _Args::template string_type<_SourceCharTy>& str,
std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_string_istreambuf<char_type> buf{ str };
std::basic_istream<char_type> is{ &buf };
detail::fast_string_istreambuf<_SourceCharTy> buf{ str };
std::basic_istream<_SourceCharTy> is{ &buf };
parse(c, is, options);
}

static value_type parse(const string_type& str, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static value_type parse(const typename _Args::template string_type<_SourceCharTy>& str,
std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_string_istreambuf<char_type> buf{ str };
std::basic_istream<char_type> is{ &buf };
detail::fast_string_istreambuf<_SourceCharTy> buf{ str };
std::basic_istream<_SourceCharTy> is{ &buf };
return parse(is, options);
}

// parse from c-style string
static void parse(value_type& c, const char_type* str, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static void parse(value_type& c, const _SourceCharTy* str,
std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_buffer_istreambuf<char_type> buf{ str };
std::basic_istream<char_type> is{ &buf };
detail::fast_buffer_istreambuf<_SourceCharTy> buf{ str };
std::basic_istream<_SourceCharTy> is{ &buf };
parse(c, is, options);
}

static value_type parse(const char_type* str, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy>
static value_type parse(const _SourceCharTy* str, std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_buffer_istreambuf<char_type> buf{ str };
std::basic_istream<char_type> is{ &buf };
detail::fast_buffer_istreambuf<_SourceCharTy> buf{ str };
std::basic_istream<_SourceCharTy> is{ &buf };
return parse(is, options);
}

// parse from c-style file
static void parse(value_type& c, std::FILE* file, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy = typename value_type::char_type>
static void parse(value_type& c, std::FILE* file, std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_cfile_istreambuf<char_type> buf{ file };
std::basic_istream<char_type> is{ &buf };
detail::fast_cfile_istreambuf<_SourceCharTy> buf{ file };
std::basic_istream<_SourceCharTy> is{ &buf };
parse(c, is, options);
}

static value_type parse(std::FILE* file, std::initializer_list<parser_option> options = {})
template <typename _SourceCharTy = typename value_type::char_type>
static value_type parse(std::FILE* file, std::initializer_list<parser_option<_SourceCharTy>> options = {})
{
detail::fast_cfile_istreambuf<char_type> buf{ file };
std::basic_istream<char_type> is{ &buf };
detail::fast_cfile_istreambuf<_SourceCharTy> buf{ file };
std::basic_istream<_SourceCharTy> is{ &buf };
return parse(is, options);
}
};
Expand Down
22 changes: 10 additions & 12 deletions include/configor/configor_serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
#include "configor_token.hpp"
#include "configor_value.hpp"

#include <functional> // std::function
#include <ios> // std::streamsize
#include <ostream> // std::basic_ostream
#include <type_traits> // std::char_traits
#include <functional> // std::function
#include <ios> // std::streamsize
#include <ostream> // std::basic_ostream

namespace configor
{
Expand Down Expand Up @@ -212,23 +211,22 @@ class serializable
public:
using value_type = typename _Args::value_type;

template <typename _CharTy>
using default_encoding = typename _Args::template default_encoding<_CharTy>;

template <typename _TargetCharTy = typename value_type::char_type>
using serializer = typename _Args::template serializer_type<value_type, _TargetCharTy>;
using serializer_type = typename _Args::template serializer_type<value_type, _TargetCharTy>;

using serializer = serializer_type<>;

template <typename _TargetCharTy>
using serializer_option = std::function<void(serializer<_TargetCharTy>&)>;
using serializer_option = std::function<void(serializer_type<_TargetCharTy>&)>;

// dump to stream
template <typename _TargetCharTy>
static void dump(std::basic_ostream<_TargetCharTy>& os, const value_type& v,
std::initializer_list<serializer_option<_TargetCharTy>> options = {})
{
serializer<_TargetCharTy> s{ os };
s.template set_source_encoding<default_encoding>();
s.template set_target_encoding<default_encoding>();
serializer_type<_TargetCharTy> s{ os };
s.template set_source_encoding<typename _Args::default_encoding>();
s.template set_target_encoding<typename _Args::default_encoding>();
for (const auto& option : options)
{
option(s);
Expand Down
Loading

0 comments on commit 68d452d

Please sign in to comment.