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 | |
13 | namespace nlohmann |
14 | { |
15 | namespace detail |
16 | { |
17 | /// abstract output adapter interface |
18 | template<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 |
26 | template<typename CharType> |
27 | using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; |
28 | |
29 | /// output adapter for byte vectors |
30 | template<typename CharType> |
31 | class 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 |
54 | template<typename CharType> |
55 | class 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 |
78 | template<typename CharType, typename StringType = std::basic_string<CharType>> |
79 | class 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 | |
101 | template<typename CharType, typename StringType = std::basic_string<CharType>> |
102 | class 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 | |