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