Coverage Report

Created: 2025-06-22 06:27

/src/qpdf/libqpdf/QPDFLogger.cc
Line
Count
Source (jump to first uncovered line)
1
#include <qpdf/QPDFLogger.hh>
2
3
#include <qpdf/Pl_Discard.hh>
4
#include <qpdf/Pl_OStream.hh>
5
#include <qpdf/QUtil.hh>
6
#include <iostream>
7
#include <stdexcept>
8
9
namespace
10
{
11
    class Pl_Track: public Pipeline
12
    {
13
      public:
14
        Pl_Track(char const* identifier, Pipeline* next) :
15
1
            Pipeline(identifier, next)
16
1
        {
17
1
            if (!next) {
18
0
                throw std::logic_error("Attempt to create Pl_Track with nullptr as next");
19
0
            }
20
1
        }
21
22
        void
23
        write(unsigned char const* data, size_t len) final
24
0
        {
25
0
            used = true;
26
0
            next()->write(data, len);
27
0
        }
28
29
        void
30
        finish() final
31
1
        {
32
1
            next()->finish();
33
1
        }
34
35
        bool
36
        getUsed() const
37
0
        {
38
0
            return used;
39
0
        }
40
41
      private:
42
        bool used{false};
43
    };
44
}; // namespace
45
46
QPDFLogger::Members::Members() :
47
1
    p_discard(new Pl_Discard()),
48
1
    p_real_stdout(new Pl_OStream("standard output", std::cout)),
49
1
    p_stdout(new Pl_Track("track stdout", p_real_stdout.get())),
50
1
    p_stderr(new Pl_OStream("standard error", std::cerr)),
51
1
    p_info(p_stdout),
52
1
    p_warn(nullptr),
53
1
    p_error(p_stderr),
54
1
    p_save(nullptr)
55
1
{
56
1
}
57
58
QPDFLogger::Members::~Members()
59
1
{
60
1
    p_stdout->finish();
61
1
    p_stderr->finish();
62
1
}
63
64
QPDFLogger::QPDFLogger() :
65
1
    m(new Members())
66
1
{
67
1
}
68
69
std::shared_ptr<QPDFLogger>
70
QPDFLogger::create()
71
1
{
72
1
    return std::shared_ptr<QPDFLogger>(new QPDFLogger);
73
1
}
74
75
std::shared_ptr<QPDFLogger>
76
QPDFLogger::defaultLogger()
77
35.9k
{
78
35.9k
    static auto l = create();
79
35.9k
    return l;
80
35.9k
}
81
82
void
83
QPDFLogger::info(char const* s)
84
0
{
85
0
    getInfo(false)->writeCStr(s);
86
0
}
87
88
void
89
QPDFLogger::info(std::string const& s)
90
0
{
91
0
    getInfo(false)->writeString(s);
92
0
}
93
94
std::shared_ptr<Pipeline>
95
QPDFLogger::getInfo(bool null_okay)
96
0
{
97
0
    return throwIfNull(m->p_info, null_okay);
98
0
}
99
100
void
101
QPDFLogger::warn(char const* s)
102
16
{
103
16
    getWarn(false)->writeCStr(s);
104
16
}
105
106
void
107
QPDFLogger::warn(std::string const& s)
108
0
{
109
0
    getWarn(false)->writeString(s);
110
0
}
111
112
std::shared_ptr<Pipeline>
113
QPDFLogger::getWarn(bool null_okay)
114
594k
{
115
594k
    if (m->p_warn) {
116
0
        return m->p_warn;
117
0
    }
118
594k
    return getError(null_okay);
119
594k
}
120
121
void
122
QPDFLogger::error(char const* s)
123
0
{
124
0
    getError(false)->writeCStr(s);
125
0
}
126
127
void
128
QPDFLogger::error(std::string const& s)
129
0
{
130
0
    getError(false)->writeString(s);
131
0
}
132
133
std::shared_ptr<Pipeline>
134
QPDFLogger::getError(bool null_okay)
135
610k
{
136
610k
    return throwIfNull(m->p_error, null_okay);
137
610k
}
138
139
std::shared_ptr<Pipeline>
140
QPDFLogger::getSave(bool null_okay)
141
0
{
142
0
    return throwIfNull(m->p_save, null_okay);
143
0
}
144
145
std::shared_ptr<Pipeline>
146
QPDFLogger::standardOutput()
147
0
{
148
0
    return m->p_stdout;
149
0
}
150
151
std::shared_ptr<Pipeline>
152
QPDFLogger::standardError()
153
0
{
154
0
    return m->p_stderr;
155
0
}
156
157
std::shared_ptr<Pipeline>
158
QPDFLogger::discard()
159
0
{
160
0
    return m->p_discard;
161
0
}
162
163
void
164
QPDFLogger::setInfo(std::shared_ptr<Pipeline> p)
165
0
{
166
0
    if (p == nullptr) {
167
0
        if (m->p_save == m->p_stdout) {
168
0
            p = m->p_stderr;
169
0
        } else {
170
0
            p = m->p_stdout;
171
0
        }
172
0
    }
173
0
    m->p_info = p;
174
0
}
175
176
void
177
QPDFLogger::setWarn(std::shared_ptr<Pipeline> p)
178
0
{
179
0
    m->p_warn = p;
180
0
}
181
182
void
183
QPDFLogger::setError(std::shared_ptr<Pipeline> p)
184
0
{
185
0
    if (p == nullptr) {
186
0
        p = m->p_stderr;
187
0
    }
188
0
    m->p_error = p;
189
0
}
190
191
void
192
QPDFLogger::setSave(std::shared_ptr<Pipeline> p, bool only_if_not_set)
193
0
{
194
0
    if (only_if_not_set && (m->p_save != nullptr)) {
195
0
        return;
196
0
    }
197
0
    if (m->p_save == p) {
198
0
        return;
199
0
    }
200
0
    if (p == m->p_stdout) {
201
0
        auto pt = dynamic_cast<Pl_Track*>(p.get());
202
0
        if (pt->getUsed()) {
203
0
            throw std::logic_error(
204
0
                "QPDFLogger: called setSave on standard output after standard"
205
0
                " output has already been used");
206
0
        }
207
0
        if (m->p_info == m->p_stdout) {
208
0
            m->p_info = m->p_stderr;
209
0
        }
210
0
        QUtil::binary_stdout();
211
0
    }
212
0
    m->p_save = p;
213
0
}
214
215
void
216
QPDFLogger::saveToStandardOutput(bool only_if_not_set)
217
0
{
218
0
    setSave(standardOutput(), only_if_not_set);
219
0
}
220
221
void
222
QPDFLogger::setOutputStreams(std::ostream* out_stream, std::ostream* err_stream)
223
0
{
224
0
    if (out_stream == &std::cout) {
225
0
        out_stream = nullptr;
226
0
    }
227
0
    if (err_stream == &std::cerr) {
228
0
        err_stream = nullptr;
229
0
    }
230
0
    std::shared_ptr<Pipeline> new_out;
231
0
    std::shared_ptr<Pipeline> new_err;
232
233
0
    if (out_stream == nullptr) {
234
0
        if (m->p_save == m->p_stdout) {
235
0
            new_out = m->p_stderr;
236
0
        } else {
237
0
            new_out = m->p_stdout;
238
0
        }
239
0
    } else {
240
0
        new_out = std::make_shared<Pl_OStream>("output", *out_stream);
241
0
    }
242
0
    if (err_stream == nullptr) {
243
0
        new_err = m->p_stderr;
244
0
    } else {
245
0
        new_err = std::make_shared<Pl_OStream>("error output", *err_stream);
246
0
    }
247
0
    m->p_info = new_out;
248
0
    m->p_warn = nullptr;
249
0
    m->p_error = new_err;
250
0
}
251
252
std::shared_ptr<Pipeline>
253
QPDFLogger::throwIfNull(std::shared_ptr<Pipeline> p, bool null_okay)
254
610k
{
255
610k
    if (!(null_okay || p)) {
256
0
        throw std::logic_error("QPDFLogger: requested a null pipeline without null_okay == true");
257
0
    }
258
610k
    return p;
259
610k
}