qpdf/include/qpdf/QPDFLogger.hh

165 lines
6.4 KiB
C++

// Copyright (c) 2005-2024 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 <qpdf/DLL.h>
#include <qpdf/Pipeline.hh>
#include <iostream>
#include <memory>
class QPDFLogger
{
public:
QPDF_DLL
static std::shared_ptr<QPDFLogger> create();
// Return the default logger. In general, you should use the default logger. You can also create
// your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do
// so. One reason may be that 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<QPDFLogger> 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<Pipeline> getInfo(bool null_okay = false);
QPDF_DLL
void warn(char const*);
QPDF_DLL
void warn(std::string const&);
QPDF_DLL
std::shared_ptr<Pipeline> getWarn(bool null_okay = false);
QPDF_DLL
void error(char const*);
QPDF_DLL
void error(std::string const&);
QPDF_DLL
std::shared_ptr<Pipeline> getError(bool null_okay = false);
QPDF_DLL
std::shared_ptr<Pipeline> getSave(bool null_okay = false);
QPDF_DLL
std::shared_ptr<Pipeline> standardOutput();
QPDF_DLL
std::shared_ptr<Pipeline> standardError();
QPDF_DLL
std::shared_ptr<Pipeline> discard();
// Passing a null pointer resets to default
QPDF_DLL
void setInfo(std::shared_ptr<Pipeline>);
QPDF_DLL
void setWarn(std::shared_ptr<Pipeline>);
QPDF_DLL
void setError(std::shared_ptr<Pipeline>);
// See notes above about the save pipeline
QPDF_DLL
void setSave(std::shared_ptr<Pipeline>, 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<Pipeline> throwIfNull(std::shared_ptr<Pipeline>, bool null_okay);
class Members
{
friend class QPDFLogger;
public:
QPDF_DLL
~Members();
private:
Members();
Members(Members const&) = delete;
std::shared_ptr<Pipeline> p_discard;
std::shared_ptr<Pipeline> p_real_stdout;
std::shared_ptr<Pipeline> p_stdout;
std::shared_ptr<Pipeline> p_stderr;
std::shared_ptr<Pipeline> p_info;
std::shared_ptr<Pipeline> p_warn;
std::shared_ptr<Pipeline> p_error;
std::shared_ptr<Pipeline> p_save;
};
std::shared_ptr<Members> m;
};
#endif // QPDFLOGGER_HH