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