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