Coverage Report

Created: 2026-04-29 06:21

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
30.8k
        p(p),
21
30.8k
        indent(2 * depth)
22
30.8k
    {
23
30.8k
    }
24
25
    Writer&
26
    write(char const* data, size_t len)
27
2.58M
    {
28
2.58M
        p->write(reinterpret_cast<unsigned char const*>(data), len);
29
2.58M
        return *this;
30
2.58M
    }
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
1.94M
    {
43
1.94M
        auto n = indent;
44
1.94M
        if (first) {
45
362k
            first = false;
46
362k
            write(&spaces[1], n % n_spaces + 1);
47
1.58M
        } else {
48
1.58M
            write(&spaces[0], n % n_spaces + 2);
49
1.58M
        }
50
2.17M
        while (n >= n_spaces) {
51
228k
            write(&spaces[2], n_spaces);
52
228k
            n -= n_spaces;
53
228k
        }
54
1.94M
        return *this;
55
1.94M
    }
56
57
    Writer&
58
    writeStart(char const& c)
59
205k
    {
60
205k
        write(&c, 1);
61
205k
        first = true;
62
205k
        indent += 2;
63
205k
        return *this;
64
205k
    }
65
66
    Writer&
67
    writeEnd(char const& c)
68
205k
    {
69
205k
        if (indent > 1) {
70
205k
            indent -= 2;
71
205k
        }
72
205k
        if (!first) {
73
181k
            first = true;
74
181k
            writeNext();
75
181k
        }
76
205k
        first = false;
77
205k
        write(&c, 1);
78
205k
        return *this;
79
205k
    }
80
81
    Writer&
82
    operator<<(std::string_view sv)
83
5.30M
    {
84
5.30M
        p->write(reinterpret_cast<unsigned char const*>(sv.data()), sv.size());
85
5.30M
        return *this;
86
5.30M
    }
87
88
    Writer&
89
    operator<<(char const* s)
90
3.39M
    {
91
3.39M
        *this << std::string_view{s};
92
3.39M
        return *this;
93
3.39M
    }
94
95
    Writer&
96
    operator<<(bool val)
97
7.99k
    {
98
7.99k
        *this << (val ? "true" : "false");
99
7.99k
        return *this;
100
7.99k
    }
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