1#pragma once
2
3#include <algorithm> // copy
4#include <cstddef> // size_t
5#include <ios> // streamsize
6#include <iterator> // back_inserter
7#include <memory> // shared_ptr, make_shared
8#include <ostream> // basic_ostream
9#include <string> // basic_string
10#include <vector> // vector
11#include <nlohmann/detail/macro_scope.hpp>
12
13namespace nlohmann
14{
15namespace detail
16{
17/// abstract output adapter interface
18template<typename CharType> struct output_adapter_protocol
19{
20 virtual void write_character(CharType c) = 0;
21 virtual void write_characters(const CharType* s, std::size_t length) = 0;
22 virtual ~output_adapter_protocol() = default;
23};
24
25/// a type to simplify interfaces
26template<typename CharType>
27using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
28
29/// output adapter for byte vectors
30template<typename CharType>
31class output_vector_adapter : public output_adapter_protocol<CharType>
32{
33 public:
34 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
35 : v(vec)
36 {}
37
38 void write_character(CharType c) override
39 {
40 v.push_back(c);
41 }
42
43 JSON_HEDLEY_NON_NULL(2)
44 void write_characters(const CharType* s, std::size_t length) override
45 {
46 std::copy(s, s + length, std::back_inserter(v));
47 }
48
49 private:
50 std::vector<CharType>& v;
51};
52
53/// output adapter for output streams
54template<typename CharType>
55class output_stream_adapter : public output_adapter_protocol<CharType>
56{
57 public:
58 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
59 : stream(s)
60 {}
61
62 void write_character(CharType c) override
63 {
64 stream.put(c);
65 }
66
67 JSON_HEDLEY_NON_NULL(2)
68 void write_characters(const CharType* s, std::size_t length) override
69 {
70 stream.write(s, static_cast<std::streamsize>(length));
71 }
72
73 private:
74 std::basic_ostream<CharType>& stream;
75};
76
77/// output adapter for basic_string
78template<typename CharType, typename StringType = std::basic_string<CharType>>
79class output_string_adapter : public output_adapter_protocol<CharType>
80{
81 public:
82 explicit output_string_adapter(StringType& s) noexcept
83 : str(s)
84 {}
85
86 void write_character(CharType c) override
87 {
88 str.push_back(c);
89 }
90
91 JSON_HEDLEY_NON_NULL(2)
92 void write_characters(const CharType* s, std::size_t length) override
93 {
94 str.append(s, length);
95 }
96
97 private:
98 StringType& str;
99};
100
101template<typename CharType, typename StringType = std::basic_string<CharType>>
102class output_adapter
103{
104 public:
105 output_adapter(std::vector<CharType>& vec)
106 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
107
108 output_adapter(std::basic_ostream<CharType>& s)
109 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
110
111 output_adapter(StringType& s)
112 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
113
114 operator output_adapter_t<CharType>()
115 {
116 return oa;
117 }
118
119 private:
120 output_adapter_t<CharType> oa = nullptr;
121};
122} // namespace detail
123} // namespace nlohmann
124