Line data Source code
1 : // Author(s): Jan Friso Groote 2 : // Copyright: see the accompanying file COPYING or copy at 3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. 6 : // (See accompanying file LICENSE_1_0.txt or copy at 7 : // http://www.boost.org/LICENSE_1_0.txt) 8 : // 9 : 10 : #ifndef MCRL2_ATERMPP_ATERM_IO_H 11 : #define MCRL2_ATERMPP_ATERM_IO_H 12 : 13 : #include "mcrl2/atermpp/aterm_list.h" 14 : #include "mcrl2/atermpp/aterm_int.h" 15 : #include "mcrl2/utilities/type_traits.h" 16 : 17 : namespace atermpp 18 : { 19 : 20 : /// \brief A function that is applied to all terms. The resulting term should only use 21 : /// a subset of the original arguments (i.e. not introduce new terms). 22 : /// \details Typical usage is removing the index traits from function symbols that represent operators. 23 : using aterm_transformer = aterm_appl(const aterm_appl&); 24 : 25 : /// \brief The default transformer that maps each term to itself. 26 423426 : inline aterm_appl identity(const aterm_appl& x) { return x; } 27 : 28 : /// \brief The general aterm stream interface, which enables the use of a transformer to 29 : /// change the written/read terms. 30 : class aterm_stream 31 : { 32 : public: 33 : virtual ~aterm_stream(); 34 : 35 : /// \brief Sets the given transformer to be applied to following writes. 36 501 : void set_transformer(aterm_transformer transformer) { m_transformer = transformer; } 37 : 38 : /// \returns The currently assigned transformer function. 39 219 : aterm_transformer* get_transformer() const { return m_transformer; } 40 : 41 : protected: 42 : aterm_transformer* m_transformer = identity; 43 : }; 44 : 45 : /// \brief The interface for a class that writes aterm to a stream. 46 : /// Every written term is retrieved by the corresponding aterm_istream::get() call. 47 : class aterm_ostream : public aterm_stream 48 : { 49 : public: 50 : virtual ~aterm_ostream(); 51 : 52 : /// \brief Write the given term to the stream. 53 : virtual void put(const aterm& term) = 0; 54 : }; 55 : 56 : /// \brief The interface for a class that reads aterm from a stream. 57 : /// The default constructed term aterm() indicates the end of the stream. 58 : class aterm_istream : public aterm_stream 59 : { 60 : public: 61 : virtual ~aterm_istream(); 62 : 63 : /// \brief Reads an aterm from this stream. 64 : virtual void get(aterm& t) = 0; 65 : }; 66 : 67 : // These free functions provide input/output operators for these streams. 68 : 69 : /// \brief Sets the given transformer to be applied to following reads. 70 144 : inline aterm_istream& operator>>(aterm_istream& stream, aterm_transformer transformer) { stream.set_transformer(transformer); return stream; } 71 138 : inline aterm_ostream& operator<<(aterm_ostream& stream, aterm_transformer transformer) { stream.set_transformer(transformer); return stream; } 72 : 73 : /// \brief Write the given term to the stream. 74 17504 : inline aterm_ostream& operator<<(aterm_ostream& stream, const aterm& term) { stream.put(term); return stream; } 75 : 76 : /// \brief Read the given term from the stream, but for aterm_list we want to use a specific one that performs validation (defined below). 77 3713 : inline aterm_istream& operator>>(aterm_istream& stream, aterm& term) { stream.get(term); return stream; } 78 : 79 : // Utility functions 80 : 81 : /// \brief A helper class to restore the state of the aterm_{i,o}stream objects upon destruction. Currently, onlt 82 : /// preserves the transformer object. 83 : class aterm_stream_state 84 : { 85 : public: 86 219 : aterm_stream_state(aterm_stream& stream) 87 219 : : m_stream(stream) 88 : { 89 219 : m_transformer = stream.get_transformer(); 90 219 : } 91 : 92 219 : ~aterm_stream_state() 93 : { 94 219 : m_stream.set_transformer(m_transformer); 95 219 : } 96 : 97 : private: 98 : aterm_stream& m_stream; 99 : aterm_transformer* m_transformer; 100 : }; 101 : 102 : /// \brief Write any container (that is not an aterm itself) to the stream. 103 : template<typename T, 104 : typename std::enable_if_t<mcrl2::utilities::is_iterable_v<T>, int> = 0, 105 : typename std::enable_if_t<!std::is_base_of<aterm, T>::value, int> = 0> 106 360 : inline aterm_ostream& operator<<(aterm_ostream& stream, const T& container) 107 : { 108 : // Write the number of elements, followed by each element in the container. 109 360 : stream << aterm_int(std::distance(container.begin(), container.end())); 110 : 111 472 : for (const auto& element : container) 112 : { 113 112 : stream << element; 114 : } 115 : 116 360 : return stream; 117 : } 118 : 119 : /// \brief Read any container (that is not an aterm itself) from the stream. 120 : template<typename T, 121 : typename std::enable_if_t<mcrl2::utilities::is_iterable_v<T>, int> = 0, 122 : typename std::enable_if_t<!std::is_base_of<aterm, T>::value, int> = 0> 123 383 : inline aterm_istream& operator>>(aterm_istream& stream, T& container) 124 : { 125 : // Insert the next nof_elements into the container. 126 383 : aterm_int nof_elements; 127 383 : stream >> nof_elements; 128 : 129 383 : auto it = std::inserter(container, container.end()); 130 535 : for (std::size_t i = 0; i < nof_elements.value(); ++i) 131 : { 132 152 : typename T::value_type element; 133 152 : stream >> element; 134 152 : it = element; 135 : } 136 : 137 383 : return stream; 138 383 : } 139 : 140 : template<typename T> 141 12598 : inline aterm_ostream& operator<<(aterm_ostream&& stream, const T& t) { stream << t; return stream; } 142 : 143 : template<typename T> 144 9 : inline aterm_istream& operator>>(aterm_istream&& stream, T& t) { stream >> t; return stream; } 145 : 146 : /// \brief Sends the name of a function symbol to an ostream. 147 : /// \param out The out stream. 148 : /// \param f The function symbol to be output. 149 : /// \return The stream. 150 : inline 151 2 : std::ostream& operator<<(std::ostream& out, const function_symbol& f) 152 : { 153 2 : return out << f.name(); 154 : } 155 : 156 : /// \brief Prints the name of a function symbol as a string. 157 : /// \param f The function symbol. 158 : /// \return The string representation of r. 159 : inline const std::string& pp(const function_symbol& f) 160 : { 161 : return f.name(); 162 : } 163 : 164 : /// \brief Writes term t to a stream in binary aterm format. 165 : void write_term_to_binary_stream(const aterm& t, std::ostream& os); 166 : 167 : /// \brief Reads a term from a stream in binary aterm format. 168 : void read_term_from_binary_stream(std::istream& is, aterm& t); 169 : 170 : /// \brief Writes term t to a stream in textual format. 171 : void write_term_to_text_stream(const aterm& t, std::ostream& os); 172 : 173 : /// \brief Reads a term from a stream which contains the term in textual format. 174 : void read_term_from_text_stream(std::istream& is, aterm& t); 175 : 176 : /// \brief Reads an aterm from a string. The string can be in either binary or text format. 177 : aterm read_term_from_string(const std::string& s); 178 : 179 : /// \brief Reads an aterm_list from a string. The string can be in either binary or text format. 180 : /// \details If the input is not a string, an aterm is returned of the wrong type. 181 : /// \return The term corresponding to the string. 182 19 : inline aterm_list read_list_from_string(const std::string& s) 183 : { 184 19 : const aterm_list l = down_cast<aterm_list>(read_term_from_string(s)); 185 19 : assert(l.type_is_list()); 186 19 : return l; 187 : } 188 : 189 : /// \brief Reads an aterm_int from a string. The string can be in either binary or text format. 190 : /// \details If the input is not an int, an aterm is returned of the wrong type. 191 : /// \return The aterm_int corresponding to the string. 192 2 : inline aterm_int read_int_from_string(const std::string& s) 193 : { 194 2 : const aterm_int n = down_cast<aterm_int>(read_term_from_string(s)); 195 2 : assert(n.type_is_int()); 196 2 : return n; 197 : } 198 : 199 : /// \brief Reads an aterm_appl from a string. The string can be in either binary or text format. 200 : /// \details If the input is not an aterm_appl, an aterm is returned of the wrong type. 201 : /// \return The term corresponding to the string. 202 29 : inline aterm_appl read_appl_from_string(const std::string& s) 203 : { 204 29 : const aterm_appl a = down_cast<aterm_appl>(read_term_from_string(s)); 205 29 : assert(a.type_is_appl()); 206 29 : return a; 207 : } 208 : 209 : 210 : } // namespace atermpp 211 : 212 : #endif // MCRL2_ATERMPP_ATERM_IO_H