/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 | 47.0k | { |
78 | 47.0k | static auto l = create(); |
79 | 47.0k | return l; |
80 | 47.0k | } |
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 | 61 | { |
103 | 61 | getWarn(false)->writeCStr(s); |
104 | 61 | } |
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 | 747k | { |
115 | 747k | if (m->p_warn) { |
116 | 0 | return m->p_warn; |
117 | 0 | } |
118 | 747k | return getError(null_okay); |
119 | 747k | } |
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 | 771k | { |
136 | 771k | return throwIfNull(m->p_error, null_okay); |
137 | 771k | } |
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 | 771k | { |
255 | 771k | if (!(null_okay || p)) { |
256 | 0 | throw std::logic_error("QPDFLogger: requested a null pipeline without null_okay == true"); |
257 | 0 | } |
258 | 771k | return p; |
259 | 771k | } |