Coverage Report

Created: 2026-01-17 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpdf/libqpdf/qpdf/JSON_writer.hh
Line
Count
Source
1
#ifndef JSON_WRITER_HH
2
#define JSON_WRITER_HH
3
4
#include <qpdf/JSON.hh>
5
#include <qpdf/Pipeline.hh>
6
#include <qpdf/Pl_Base64.hh>
7
#include <qpdf/Pl_Concatenate.hh>
8
9
#include <string_view>
10
11
// Writer is a small utility class to aid writing JSON to a pipeline. Methods are designed to allow
12
// chaining of calls.
13
//
14
// Some uses of the class have a significant performance impact. The class is intended purely for
15
// internal use to allow it to be adapted as needed to maintain performance.
16
class JSON::Writer
17
{
18
  public:
19
    Writer(Pipeline* p, size_t depth) :
20
0
        p(p),
21
0
        indent(2 * depth)
22
0
    {
23
0
    }
24
25
    Writer&
26
    write(char const* data, size_t len)
27
0
    {
28
0
        p->write(reinterpret_cast<unsigned char const*>(data), len);
29
0
        return *this;
30
0
    }
31
32
    Writer&
33
    writeBase64(std::string_view sv)
34
0
    {
35
0
        auto encoded = Pl_Base64::encode(sv);
36
0
        p->write(reinterpret_cast<unsigned char const*>(encoded.data()), encoded.size());
37
0
        return *this;
38
0
    }
39
40
    Writer&
41
    writeNext()
42
0
    {
43
0
        auto n = indent;
44
0
        if (first) {
45
0
            first = false;
46
0
            write(&spaces[1], n % n_spaces + 1);
47
0
        } else {
48
0
            write(&spaces[0], n % n_spaces + 2);
49
0
        }
50
0
        while (n >= n_spaces) {
51
0
            write(&spaces[2], n_spaces);
52
0
            n -= n_spaces;
53
0
        }
54
0
        return *this;
55
0
    }
56
57
    Writer&
58
    writeStart(char const& c)
59
0
    {
60
0
        write(&c, 1);
61
0
        first = true;
62
0
        indent += 2;
63
0
        return *this;
64
0
    }
65
66
    Writer&
67
    writeEnd(char const& c)
68
0
    {
69
0
        if (indent > 1) {
70
0
            indent -= 2;
71
0
        }
72
0
        if (!first) {
73
0
            first = true;
74
0
            writeNext();
75
0
        }
76
0
        first = false;
77
0
        write(&c, 1);
78
0
        return *this;
79
0
    }
80
81
    Writer&
82
    operator<<(std::string_view sv)
83
0
    {
84
0
        p->write(reinterpret_cast<unsigned char const*>(sv.data()), sv.size());
85
0
        return *this;
86
0
    }
87
88
    Writer&
89
    operator<<(char const* s)
90
0
    {
91
0
        *this << std::string_view{s};
92
0
        return *this;
93
0
    }
94
95
    Writer&
96
    operator<<(bool val)
97
0
    {
98
0
        *this << (val ? "true" : "false");
99
0
        return *this;
100
0
    }
101
102
    Writer&
103
    operator<<(int val)
104
0
    {
105
0
        *this << std::to_string(val);
106
0
        return *this;
107
0
    }
108
109
    Writer&
110
    operator<<(size_t val)
111
0
    {
112
0
        *this << std::to_string(val);
113
0
        return *this;
114
0
    }
115
116
    Writer&
117
    operator<<(JSON&& j)
118
0
    {
119
0
        j.write(p, indent / 2);
120
0
        return *this;
121
0
    }
122
123
    static std::string encode_string(std::string const& utf8);
124
125
  private:
126
    Pipeline* p;
127
    bool first{true};
128
    size_t indent;
129
130
    static constexpr std::string_view spaces =
131
        ",\n                                                  ";
132
    static constexpr auto n_spaces = spaces.size() - 2;
133
};
134
135
#endif // JSON_WRITER_HH