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: output_vector_adapter(std::vector<CharType> & vec)34 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept 35 : v(vec) 36 {} 37 write_character(CharType c)38 void write_character(CharType c) override 39 { 40 v.push_back(c); 41 } 42 43 JSON_HEDLEY_NON_NULL(2) write_characters(const CharType * s,std::size_t length)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: output_stream_adapter(std::basic_ostream<CharType> & s)58 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept 59 : stream(s) 60 {} 61 write_character(CharType c)62 void write_character(CharType c) override 63 { 64 stream.put(c); 65 } 66 67 JSON_HEDLEY_NON_NULL(2) write_characters(const CharType * s,std::size_t length)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: output_string_adapter(StringType & s)82 explicit output_string_adapter(StringType& s) noexcept 83 : str(s) 84 {} 85 write_character(CharType c)86 void write_character(CharType c) override 87 { 88 str.push_back(c); 89 } 90 91 JSON_HEDLEY_NON_NULL(2) write_characters(const CharType * s,std::size_t length)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: output_adapter(std::vector<CharType> & vec)105 output_adapter(std::vector<CharType>& vec) 106 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {} 107 output_adapter(std::basic_ostream<CharType> & s)108 output_adapter(std::basic_ostream<CharType>& s) 109 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} 110 output_adapter(StringType & s)111 output_adapter(StringType& s) 112 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} 113 operator output_adapter_t<CharType>()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