cvc5-cvc5-1.2.0.src.options.managed_streams.h Maven / Gradle / Ivy
The newest version!
/******************************************************************************
* Top contributors (to current version):
* Gereon Kremer
*
* This file is part of the cvc5 project.
*
* Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
* in the top-level source directory and their institutional affiliations.
* All rights reserved. See the file COPYING in the top-level source
* directory for licensing information.
* ****************************************************************************
*
* Wrappers to handle memory management of streams.
*
* This file contains wrappers to handle special cases of managing memory
* related to streams stored in options.
*/
#include "cvc5_public.h"
#ifndef CVC5__OPTIONS__MANAGED_STREAMS_H
#define CVC5__OPTIONS__MANAGED_STREAMS_H
#include
#include
namespace cvc5::internal {
namespace detail {
/*
* Open a file as an output stream and return it as a pointer. The caller
* assumes the ownership of the returned pointer.
*/
std::unique_ptr openOStream(const std::string& filename);
/*
* Open a file as an input stream and return it as a pointer. The caller
* assumes the ownership of the returned pointer.
*/
std::unique_ptr openIStream(const std::string& filename);
} // namespace detail
/**
* Implements memory management for streams, both input and output. It is
* intended to be subclassed, where a subclass can provide a default value and
* special cases. Usually, users should use one of these subclasses.
* The template argument type should be either std::istream or std::ostream,
* indicating whether the type wraps an input or output stream.
*/
template
class ManagedStream
{
public:
ManagedStream(Stream* nonowned, std::string description)
: d_nonowned(nonowned), d_description(std::move(description)) {}
virtual ~ManagedStream() {}
/**
* Open the stream from the given value. First check the special cases and
* then fall back to using `std::ofstream` or `std::ifstream`.
*/
void open(const std::string& value)
{
if (specialCases(value)) return;
if constexpr (std::is_same::value)
{
d_nonowned = nullptr;
d_owned = detail::openOStream(value);
d_description = value;
}
else if constexpr (std::is_same::value)
{
d_nonowned = nullptr;
d_owned = detail::openIStream(value);
d_description = value;
}
}
Stream& operator*() const { return *getPtr(); }
Stream* operator->() const { return getPtr(); }
operator Stream&() const { return *getPtr(); }
operator Stream*() const { return getPtr(); }
const std::string& description() const { return d_description; }
protected:
Stream* d_nonowned;
std::shared_ptr d_owned;
std::string d_description = "";
private:
/**
* Check if there is a special case for this value. If so, the implementation
* should set d_stream appropriately and return true to skip the default
* methods for opening a stream.
*/
virtual bool specialCases(const std::string& value) = 0;
/** Return the pointer, either from d_nonowned or d_owned. */
Stream* getPtr() const
{
if (d_nonowned != nullptr) return d_nonowned;
return d_owned.get();
}
};
template
std::ostream& operator<<(std::ostream& os, const ManagedStream& ms)
{
return os << ms.description();
}
/**
* Managed error output. It recognizes "stderr" and "--" as special valued for
* std::cerr.
*/
class ManagedErr : public ManagedStream
{
public:
ManagedErr();
private:
bool specialCases(const std::string& value) override final;
};
/**
* Managed standard input. It recognizes "stdin" and "--" as special valued for
* std::cin.
*/
class ManagedIn : public ManagedStream
{
public:
ManagedIn();
private:
bool specialCases(const std::string& value) override final;
};
/**
* Managed standard output. It recognizes "stdout" and "--" as special valued
* for std::cout.
*/
class ManagedOut : public ManagedStream
{
public:
ManagedOut();
private:
bool specialCases(const std::string& value) override final;
};
} // namespace cvc5::internal
#endif /* CVC5__OPTIONS__MANAGED_STREAMS_H */