// Copyright (c) 2005-2023 Jay Berkenbilt // // This file is part of qpdf. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software distributed under the License // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express // or implied. See the License for the specific language governing permissions and limitations under // the License. // // Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic // License. At your option, you may continue to consider qpdf to be licensed under those terms. // Please see the manual for additional information. #ifndef QPDFLOGGER_HH #define QPDFLOGGER_HH #include #include #include #include class QPDFLogger { public: QPDF_DLL static std::shared_ptr create(); // Return the default logger. In general, you should use the default logger. You can also create // your own loggers and use them QPDF and QPDFJob objects, but there are few reasons to do so. // One reason may if you are using multiple QPDF or QPDFJob objects in different threads and // want to capture output and errors to different streams. (Note that a single QPDF or QPDFJob // can't be safely used from multiple threads, but it is safe to use separate QPDF and QPDFJob // objects on separate threads.) Another possible reason would be if you are writing an // application that uses the qpdf library directly and qpdf is also used by a downstream library // or if you are using qpdf from a library and don't want to interfere with potential uses of // qpdf by other libraries or applications. QPDF_DLL static std::shared_ptr defaultLogger(); // Defaults: // // info -- if save is standard output, standard error, else standard output // warn -- whatever error points to // error -- standard error // save -- undefined unless set // // "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is // used for warnings. "error" is used for errors. "save" is used for saving output -- see below. // // On deletion, finish() is called for the standard output and standard error pipelines, which // flushes output. If you supply any custom pipelines, you must call finish() on them yourself. // Note that calling finish is not needed for string, stdio, or ostream pipelines. // // NOTES ABOUT THE SAVE PIPELINE // // The save pipeline is used by QPDFJob when some kind of binary output is being saved. This // includes saving attachments and stream data and also includes when the output file is // standard output. If you want to grab that output, you can call setSave. See // examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c. // // You should never set the save pipeline to the same destination as something else. Doing so // will corrupt your save output. If you want to save to standard output, use the method // saveToStandardOutput(). In addition to setting the save pipeline, that does the following // extra things: // // * If standard output has been used, a logic error is thrown // * If info is set to standard output at the time of the set save call, it is switched to // standard error. // // This is not a guarantee. You can still mess this up in ways that are not checked. Here are a // few examples: // // * Don't set any pipeline to standard output *after* passing it to setSave() // * Don't use a separate mechanism to write stdout/stderr other than // QPDFLogger::standardOutput() // * Don't set anything to the same custom pipeline that save is set to. // // Just be sure that if you change pipelines around, you should avoid having the save pipeline // also be used for any other purpose. The special case for saving to standard output allows you // to call saveToStandardOutput() early without having to worry about the info pipeline. QPDF_DLL void info(char const*); QPDF_DLL void info(std::string const&); QPDF_DLL std::shared_ptr getInfo(bool null_okay = false); QPDF_DLL void warn(char const*); QPDF_DLL void warn(std::string const&); QPDF_DLL std::shared_ptr getWarn(bool null_okay = false); QPDF_DLL void error(char const*); QPDF_DLL void error(std::string const&); QPDF_DLL std::shared_ptr getError(bool null_okay = false); QPDF_DLL std::shared_ptr getSave(bool null_okay = false); QPDF_DLL std::shared_ptr standardOutput(); QPDF_DLL std::shared_ptr standardError(); QPDF_DLL std::shared_ptr discard(); // Passing a null pointer resets to default QPDF_DLL void setInfo(std::shared_ptr); QPDF_DLL void setWarn(std::shared_ptr); QPDF_DLL void setError(std::shared_ptr); // See notes above about the save pipeline QPDF_DLL void setSave(std::shared_ptr, bool only_if_not_set); QPDF_DLL void saveToStandardOutput(bool only_if_not_set); // Shortcut for logic to reset output to new output/error streams. out_stream is used for info, // err_stream is used for error, and warning is cleared so that it follows error. QPDF_DLL void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); private: QPDFLogger(); std::shared_ptr throwIfNull(std::shared_ptr, bool null_okay); class Members { friend class QPDFLogger; public: QPDF_DLL ~Members(); private: Members(); Members(Members const&) = delete; std::shared_ptr p_discard; std::shared_ptr p_real_stdout; std::shared_ptr p_stdout; std::shared_ptr p_stderr; std::shared_ptr p_info; std::shared_ptr p_warn; std::shared_ptr p_error; std::shared_ptr p_save; }; std::shared_ptr m; }; #endif // QPDFLOGGER_HH