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 "options/managed_streams.h" 17 : : 18 : : #include <cerrno> 19 : : #include <cstring> 20 : : #include <fstream> 21 : : #include <iostream> 22 : : #include <sstream> 23 : : 24 : : #include "options/option_exception.h" 25 : : 26 : : namespace cvc5::internal { 27 : : 28 : 364 : std::string cvc5_errno_failreason() 29 : : { 30 : : #if HAVE_STRERROR_R 31 : : #if STRERROR_R_CHAR_P 32 : : if (errno != 0) 33 : : { 34 : : // GNU version of strerror_r: *might* use the given buffer, 35 : : // or might not. It returns a pointer to buf, or not. 36 : : char buf[80]; 37 : : return std::string(strerror_r(errno, buf, sizeof buf)); 38 : : } 39 : : else 40 : : { 41 : : return "unknown reason"; 42 : : } 43 : : #else /* STRERROR_R_CHAR_P */ 44 : : if (errno != 0) 45 : : { 46 : : // XSI version of strerror_r: always uses the given buffer. 47 : : // Returns an error code. 48 : : char buf[80]; 49 : : if (strerror_r(errno, buf, sizeof buf) == 0) 50 : : { 51 : : return std::string(buf); 52 : : } 53 : : else 54 : : { 55 : : // some error occurred while getting the error string 56 : : return "unknown reason"; 57 : : } 58 : : } 59 : : else 60 : : { 61 : : return "unknown reason"; 62 : : } 63 : : #endif /* STRERROR_R_CHAR_P */ 64 : : #else /* HAVE_STRERROR_R */ 65 : 364 : return "unknown reason"; 66 : : #endif /* HAVE_STRERROR_R */ 67 : : } 68 : : 69 : : namespace detail { 70 : : 71 : 293 : std::unique_ptr<std::ostream> openOStream(const std::string& filename) 72 : : { 73 : 293 : errno = 0; 74 : 293 : std::unique_ptr<std::ostream> res = std::make_unique<std::ofstream>(filename); 75 [ + - ][ + - ]: 293 : if (!res || !*res) [ + - ] 76 : : { 77 : 293 : std::stringstream ss; 78 : 293 : ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason(); 79 : 293 : throw OptionException(ss.str()); 80 : 293 : } 81 : 0 : return res; 82 : 293 : } 83 : 71 : std::unique_ptr<std::istream> openIStream(const std::string& filename) 84 : : { 85 : 71 : errno = 0; 86 : 71 : std::unique_ptr<std::istream> res = std::make_unique<std::ifstream>(filename); 87 [ + - ][ + - ]: 71 : if (!res || !*res) [ + - ] 88 : : { 89 : 71 : std::stringstream ss; 90 : 71 : ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason(); 91 : 71 : throw OptionException(ss.str()); 92 : 71 : } 93 : 0 : return res; 94 : 71 : } 95 : : } // namespace detail 96 : : 97 : 78628 : ManagedErr::ManagedErr() : ManagedStream(&std::cerr, "stderr") {} 98 : 158 : bool ManagedErr::specialCases(const std::string& value) 99 : : { 100 [ + - ][ - + ]: 158 : if (value == "stderr" || value == "--") [ - + ] 101 : : { 102 : 0 : d_nonowned = &std::cerr; 103 : 0 : d_owned.reset(); 104 : 0 : d_description = "stderr"; 105 : 0 : return true; 106 : : } 107 [ + + ]: 158 : else if (value == "stdout") 108 : : { 109 : 2 : d_nonowned = &std::cout; 110 : 2 : d_owned.reset(); 111 : 2 : d_description = "stdout"; 112 : 2 : return true; 113 : : } 114 : 156 : return false; 115 : : } 116 : : 117 : 78542 : ManagedIn::ManagedIn() : ManagedStream(&std::cin, "stdin") {} 118 : 72 : bool ManagedIn::specialCases(const std::string& value) 119 : : { 120 [ + + ][ - + ]: 72 : if (value == "stdin" || value == "--") [ + + ] 121 : : { 122 : 1 : d_nonowned = &std::cin; 123 : 1 : d_owned.reset(); 124 : 1 : d_description = "stdin"; 125 : 1 : return true; 126 : : } 127 : 71 : return false; 128 : : } 129 : : 130 : 157078 : ManagedOut::ManagedOut() : ManagedStream(&std::cout, "stdout") {} 131 : 138 : bool ManagedOut::specialCases(const std::string& value) 132 : : { 133 [ + - ][ - + ]: 138 : if (value == "stdout" || value == "--") [ - + ] 134 : : { 135 : 0 : d_nonowned = &std::cout; 136 : 0 : d_owned.reset(); 137 : 0 : d_description = "stdout"; 138 : 0 : return true; 139 : : } 140 [ + + ]: 138 : else if (value == "stderr") 141 : : { 142 : 1 : d_nonowned = &std::cerr; 143 : 1 : d_owned.reset(); 144 : 1 : d_description = "stderr"; 145 : 1 : return true; 146 : : } 147 : 137 : return false; 148 : : } 149 : : 150 : : } // namespace cvc5::internal