2018-01-10 17:18:31 +08:00
|
|
|
#pragma once
|
2017-08-14 23:41:23 +08:00
|
|
|
|
2017-08-15 01:28:01 +08:00
|
|
|
#include <algorithm> // copy
|
|
|
|
#include <cstddef> // size_t
|
|
|
|
#include <ios> // streamsize
|
|
|
|
#include <iterator> // back_inserter
|
|
|
|
#include <memory> // shared_ptr, make_shared
|
|
|
|
#include <ostream> // basic_ostream
|
|
|
|
#include <string> // basic_string
|
|
|
|
#include <vector> // vector
|
2017-08-14 23:41:23 +08:00
|
|
|
|
|
|
|
namespace nlohmann
|
|
|
|
{
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
/// abstract output adapter interface
|
|
|
|
template<typename CharType> struct output_adapter_protocol
|
|
|
|
{
|
|
|
|
virtual void write_character(CharType c) = 0;
|
|
|
|
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
2018-09-15 09:08:50 +08:00
|
|
|
virtual void write_characters_at(std::size_t position, const CharType* s, std::size_t length) = 0;
|
|
|
|
virtual std::size_t reserve_characters(std::size_t length) = 0;
|
2017-08-14 23:41:23 +08:00
|
|
|
virtual ~output_adapter_protocol() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// a type to simplify interfaces
|
|
|
|
template<typename CharType>
|
|
|
|
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
|
|
|
|
|
|
|
|
/// output adapter for byte vectors
|
|
|
|
template<typename CharType>
|
|
|
|
class output_vector_adapter : public output_adapter_protocol<CharType>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
|
|
|
|
|
|
|
|
void write_character(CharType c) override
|
|
|
|
{
|
|
|
|
v.push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_characters(const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
std::copy(s, s + length, std::back_inserter(v));
|
|
|
|
}
|
|
|
|
|
2018-09-15 09:08:50 +08:00
|
|
|
void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
std::copy(s, s + length, std::begin(v) + position);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t reserve_characters(std::size_t length) override
|
|
|
|
{
|
|
|
|
const auto position = v.size();
|
|
|
|
std::fill_n(std::back_inserter(v), length, static_cast<CharType>(0x00));
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
2017-08-14 23:41:23 +08:00
|
|
|
private:
|
|
|
|
std::vector<CharType>& v;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// output adapter for output streams
|
|
|
|
template<typename CharType>
|
|
|
|
class output_stream_adapter : public output_adapter_protocol<CharType>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
|
|
|
|
|
|
|
|
void write_character(CharType c) override
|
|
|
|
{
|
|
|
|
stream.put(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_characters(const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
stream.write(s, static_cast<std::streamsize>(length));
|
|
|
|
}
|
|
|
|
|
2018-09-15 09:08:50 +08:00
|
|
|
void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
const auto orig_offset = stream.tellp();
|
|
|
|
stream.seekp(static_cast<typename std::basic_ostream<CharType>::pos_type>(position));
|
|
|
|
stream.write(s, static_cast<std::streamsize>(length));
|
|
|
|
stream.seekp(orig_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t reserve_characters(std::size_t length) override
|
|
|
|
{
|
|
|
|
const auto position = stream.tellp();
|
|
|
|
std::vector<CharType> empty(length, static_cast<CharType>(0));
|
|
|
|
stream.write(empty.data(), length);
|
|
|
|
return static_cast<std::size_t>(position);
|
|
|
|
}
|
|
|
|
|
2017-08-14 23:41:23 +08:00
|
|
|
private:
|
|
|
|
std::basic_ostream<CharType>& stream;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// output adapter for basic_string
|
2018-03-10 22:19:28 +08:00
|
|
|
template<typename CharType, typename StringType = std::basic_string<CharType>>
|
2017-08-14 23:41:23 +08:00
|
|
|
class output_string_adapter : public output_adapter_protocol<CharType>
|
|
|
|
{
|
|
|
|
public:
|
2018-03-10 22:19:28 +08:00
|
|
|
explicit output_string_adapter(StringType& s) : str(s) {}
|
2017-08-14 23:41:23 +08:00
|
|
|
|
|
|
|
void write_character(CharType c) override
|
|
|
|
{
|
|
|
|
str.push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_characters(const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
str.append(s, length);
|
|
|
|
}
|
|
|
|
|
2018-09-15 09:08:50 +08:00
|
|
|
void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override
|
|
|
|
{
|
|
|
|
std::copy(s, s + length, std::begin(str) + position);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t reserve_characters(std::size_t length) override
|
|
|
|
{
|
|
|
|
const auto position = str.size();
|
|
|
|
std::fill_n(std::back_inserter(str), length, static_cast<CharType>(0x00));
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-14 23:41:23 +08:00
|
|
|
private:
|
2018-03-10 22:19:28 +08:00
|
|
|
StringType& str;
|
2017-08-14 23:41:23 +08:00
|
|
|
};
|
|
|
|
|
2018-03-10 22:19:28 +08:00
|
|
|
template<typename CharType, typename StringType = std::basic_string<CharType>>
|
2017-08-14 23:41:23 +08:00
|
|
|
class output_adapter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
output_adapter(std::vector<CharType>& vec)
|
|
|
|
: oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
|
|
|
|
|
|
|
|
output_adapter(std::basic_ostream<CharType>& s)
|
|
|
|
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
|
|
|
|
|
2018-03-10 22:19:28 +08:00
|
|
|
output_adapter(StringType& s)
|
2018-03-11 04:58:16 +08:00
|
|
|
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
|
2017-08-14 23:41:23 +08:00
|
|
|
|
|
|
|
operator output_adapter_t<CharType>()
|
|
|
|
{
|
|
|
|
return oa;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
output_adapter_t<CharType> oa = nullptr;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|