// 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