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