Commit 9e90007a4a490dd1335b63079fc3e2a74420911f

Authored by m-holger
1 parent b1b789df

Add new private class JSON::Writer

Create a simple utility class for writing JSON to a pipeline.
include/qpdf/JSON.hh
... ... @@ -290,8 +290,11 @@ class JSON
290 290 QPDF_DLL
291 291 qpdf_offset_t getEnd() const;
292 292  
  293 + // The following class does not form part of the public API and is for internal use only.
  294 +
  295 + class Writer;
  296 +
293 297 private:
294   - static std::string encode_string(std::string const& utf8);
295 298 static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter);
296 299  
297 300 enum value_type_e {
... ...
libqpdf/JSON.cc
1 1 #include <qpdf/JSON.hh>
2 2  
  3 +#include <qpdf/JSON_writer.hh>
  4 +
3 5 #include <qpdf/BufferInputSource.hh>
4 6 #include <qpdf/Pl_Base64.hh>
5 7 #include <qpdf/Pl_Concatenate.hh>
... ... @@ -119,7 +121,7 @@ JSON::JSON_array::write(Pipeline* p, size_t depth) const
119 121 JSON::JSON_string::JSON_string(std::string const& utf8) :
120 122 JSON_value(vt_string),
121 123 utf8(utf8),
122   - encoded(encode_string(utf8))
  124 + encoded(Writer::encode_string(utf8))
123 125 {
124 126 }
125 127  
... ... @@ -211,7 +213,7 @@ JSON::unparse() const
211 213 }
212 214  
213 215 std::string
214   -JSON::encode_string(std::string const& str)
  216 +JSON::Writer::encode_string(std::string const& str)
215 217 {
216 218 static auto constexpr hexchars = "0123456789abcdef";
217 219  
... ... @@ -279,7 +281,7 @@ JSON
279 281 JSON::addDictionaryMember(std::string const& key, JSON const& val)
280 282 {
281 283 if (auto* obj = m ? dynamic_cast<JSON_dictionary*>(m->value.get()) : nullptr) {
282   - return obj->members[encode_string(key)] = val.m ? val : makeNull();
  284 + return obj->members[Writer::encode_string(key)] = val.m ? val : makeNull();
283 285 } else {
284 286 throw std::runtime_error("JSON::addDictionaryMember called on non-dictionary");
285 287 }
... ...
libqpdf/qpdf/JSON_writer.hh 0 → 100644
  1 +#ifndef JSON_WRITER_HH
  2 +#define JSON_WRITER_HH
  3 +
  4 +#include <qpdf/JSON.hh>
  5 +#include <qpdf/Pipeline.hh>
  6 +
  7 +#include <string_view>
  8 +
  9 +// Writer is a small utility class to aid writing JSON to a pipeline. Methods are designed to allow
  10 +// chaining of calls.
  11 +//
  12 +// Some uses of the class have a significant performance impact. The class is intended purely for
  13 +// internal use to allow it to be adapted as needed to maintain performance.
  14 +class JSON::Writer
  15 +{
  16 + public:
  17 + Writer(Pipeline* p, size_t depth) :
  18 + p(p),
  19 + indent(2 * depth)
  20 + {
  21 + }
  22 +
  23 + Writer&
  24 + write(char const* data, size_t len)
  25 + {
  26 + p->write(reinterpret_cast<unsigned char const*>(data), len);
  27 + return *this;
  28 + }
  29 +
  30 + Writer&
  31 + writeNext()
  32 + {
  33 + auto n = indent;
  34 + if (first) {
  35 + first = false;
  36 + write(&spaces[1], n % n_spaces + 1);
  37 + } else {
  38 + write(&spaces[0], n % n_spaces + 2);
  39 + }
  40 + while (n >= n_spaces) {
  41 + write(&spaces[2], n_spaces);
  42 + n -= n_spaces;
  43 + }
  44 + return *this;
  45 + }
  46 +
  47 + Writer&
  48 + writeStart(char const& c)
  49 + {
  50 + write(&c, 1);
  51 + first = true;
  52 + indent += 2;
  53 + return *this;
  54 + }
  55 +
  56 + Writer&
  57 + writeEnd(char const& c)
  58 + {
  59 + if (indent > 1) {
  60 + indent -= 2;
  61 + }
  62 + if (!first) {
  63 + first = true;
  64 + writeNext();
  65 + }
  66 + first = false;
  67 + write(&c, 1);
  68 + return *this;
  69 + }
  70 +
  71 + Writer&
  72 + operator<<(std::string_view sv)
  73 + {
  74 + p->write(reinterpret_cast<unsigned char const*>(sv.data()), sv.size());
  75 + return *this;
  76 + }
  77 +
  78 + Writer&
  79 + operator<<(char const* s)
  80 + {
  81 + *this << std::string_view{s};
  82 + return *this;
  83 + }
  84 +
  85 + Writer&
  86 + operator<<(bool val)
  87 + {
  88 + *this << (val ? "true" : "false");
  89 + return *this;
  90 + }
  91 +
  92 + Writer&
  93 + operator<<(int val)
  94 + {
  95 + *this << std::to_string(val);
  96 + return *this;
  97 + }
  98 +
  99 + Writer&
  100 + operator<<(size_t val)
  101 + {
  102 + *this << std::to_string(val);
  103 + return *this;
  104 + }
  105 +
  106 + Writer&
  107 + operator<<(JSON&& j)
  108 + {
  109 + j.write(p, indent / 2);
  110 + return *this;
  111 + }
  112 +
  113 + static std::string encode_string(std::string const& utf8);
  114 +
  115 + private:
  116 + Pipeline* p;
  117 + bool first{true};
  118 + size_t indent;
  119 +
  120 + static constexpr std::string_view spaces =
  121 + ",\n ";
  122 + static constexpr auto n_spaces = spaces.size() - 2;
  123 +};
  124 +
  125 +#endif // JSON_WRITER_HH
... ...