Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * Wrappers to handle memory management of streams. 11 : : * 12 : : * This file contains wrappers to handle special cases of managing memory 13 : : * related to streams stored in options. 14 : : */ 15 : : 16 : : #include "cvc5_public.h" 17 : : 18 : : #ifndef CVC5__OPTIONS__MANAGED_STREAMS_H 19 : : #define CVC5__OPTIONS__MANAGED_STREAMS_H 20 : : 21 : : #include <memory> 22 : : #include <ostream> 23 : : 24 : : namespace cvc5::internal { 25 : : 26 : : namespace detail { 27 : : /* 28 : : * Open a file as an output stream and return it as a pointer. The caller 29 : : * assumes the ownership of the returned pointer. 30 : : */ 31 : : std::unique_ptr<std::ostream> openOStream(const std::string& filename); 32 : : /* 33 : : * Open a file as an input stream and return it as a pointer. The caller 34 : : * assumes the ownership of the returned pointer. 35 : : */ 36 : : std::unique_ptr<std::istream> openIStream(const std::string& filename); 37 : : } // namespace detail 38 : : 39 : : /** 40 : : * Implements memory management for streams, both input and output. It is 41 : : * intended to be subclassed, where a subclass can provide a default value and 42 : : * special cases. Usually, users should use one of these subclasses. 43 : : * The template argument type should be either std::istream or std::ostream, 44 : : * indicating whether the type wraps an input or output stream. 45 : : */ 46 : : template <typename Stream> 47 : : class ManagedStream 48 : : { 49 : : public: 50 : 572872 : ManagedStream(Stream* nonowned, std::string description) 51 : 572872 : : d_nonowned(nonowned), d_description(std::move(description)) {} 52 : 532488 : virtual ~ManagedStream() {} 53 : : 54 : : /** 55 : : * Open the stream from the given value. First check the special cases and 56 : : * then fall back to using `std::ofstream` or `std::ifstream`. 57 : : */ 58 : 368 : void open(const std::string& value) 59 : : { 60 [ + + ]: 368 : if (specialCases(value)) return; 61 : : if constexpr (std::is_same<Stream, std::ostream>::value) 62 : : { 63 : 293 : d_nonowned = nullptr; 64 : 293 : d_owned = detail::openOStream(value); 65 : 0 : d_description = value; 66 : : } 67 : : else if constexpr (std::is_same<Stream, std::istream>::value) 68 : : { 69 : 71 : d_nonowned = nullptr; 70 : 71 : d_owned = detail::openIStream(value); 71 : 0 : d_description = value; 72 : : } 73 : : } 74 : : 75 : 783693 : Stream& operator*() const { return *getPtr(); } 76 : : Stream* operator->() const { return getPtr(); } 77 : 2226 : operator Stream&() const { return *getPtr(); } 78 : 4 : operator Stream*() const { return getPtr(); } 79 : : 80 : 7006 : const std::string& description() const { return d_description; } 81 : : 82 : : protected: 83 : : Stream* d_nonowned; 84 : : std::shared_ptr<Stream> d_owned; 85 : : std::string d_description = "<null>"; 86 : : 87 : : private: 88 : : /** 89 : : * Check if there is a special case for this value. If so, the implementation 90 : : * should set d_stream appropriately and return true to skip the default 91 : : * methods for opening a stream. 92 : : */ 93 : : virtual bool specialCases(const std::string& value) = 0; 94 : : 95 : : /** Return the pointer, either from d_nonowned or d_owned. */ 96 : 785923 : Stream* getPtr() const 97 : : { 98 [ + - ]: 785923 : if (d_nonowned != nullptr) return d_nonowned; 99 : 0 : return d_owned.get(); 100 : : } 101 : : }; 102 : : 103 : : template <typename Stream> 104 : 7006 : std::ostream& operator<<(std::ostream& os, const ManagedStream<Stream>& ms) 105 : : { 106 : 7006 : return os << ms.description(); 107 : : } 108 : : 109 : : /** 110 : : * Managed error output. It recognizes "stderr" and "--" as special valued for 111 : : * std::cerr. 112 : : */ 113 : : class ManagedErr : public ManagedStream<std::ostream> 114 : : { 115 : : public: 116 : : ManagedErr(); 117 : : 118 : : private: 119 : : bool specialCases(const std::string& value) override final; 120 : : }; 121 : : 122 : : /** 123 : : * Managed standard input. It recognizes "stdin" and "--" as special valued for 124 : : * std::cin. 125 : : */ 126 : : class ManagedIn : public ManagedStream<std::istream> 127 : : { 128 : : public: 129 : : ManagedIn(); 130 : : 131 : : private: 132 : : bool specialCases(const std::string& value) override final; 133 : : }; 134 : : 135 : : /** 136 : : * Managed standard output. It recognizes "stdout" and "--" as special valued 137 : : * for std::cout. 138 : : */ 139 : : class ManagedOut : public ManagedStream<std::ostream> 140 : : { 141 : : public: 142 : : ManagedOut(); 143 : : 144 : : private: 145 : : bool specialCases(const std::string& value) override final; 146 : : }; 147 : : 148 : : } // namespace cvc5::internal 149 : : 150 : : #endif /* CVC5__OPTIONS__MANAGED_STREAMS_H */