// // rarrayio.h - I/O routines for tuntime arrays. Documentation in rarraydoc.pdf // // Copyright (c) 2013-2020 Ramses van Zon // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #ifndef RARRAYIO_H #define RARRAYIO_H #if __cplusplus >= 201103L #ifndef RARRAY_H #include #endif #include #include #include #include #include #include // //#include "rarraymacros.h" #ifdef RA_BOUNDSCHECK #include #define RA_CHECKORSAY(a, b) if (not(a)) throw std::out_of_range(std::string(b) + " in function " + std::string(__PRETTY_FUNCTION__)) #else #define RA_CHECKORSAY(a, b) #endif #if not defined(RA_INLINE) # if defined(__INTEL_COMPILER) # define RA_INLINE __forceinline # elif defined(__GNUC__) # define RA_INLINE __attribute__((always_inline)) inline # else # define RA_INLINE inline # endif #endif #define RA_INLINEF RA_INLINE #define RA_INLINE_ inline //end of #include "rarraymacros.h" namespace ra { template RA_INLINE_ std::istream& operator>>(std::istream &i, ra::rarray& r); template RA_INLINE_ std::ostream& operator<<(std::ostream &o, const ra::rarray& r); template RA_INLINE_ std::ostream& text_output(std::ostream &o, const rarray& r); template RA_INLINE_ std::ostream& text_output(std::ostream &o, const rarray& r); template struct Deref { static RA_INLINEF T& access(typename PointerArray::type p, const size_type* indices); }; template struct Deref // R=1 is special { static RA_INLINEF T& access(typename PointerArray::type p, const size_type* indices); }; template struct StringToValue { static RA_INLINE_ void get(const std::string& input, T& output); }; template<> struct StringToValue { static RA_INLINE_ void get(const std::string& input, std::string& output); }; enum class token { UNKNOWN=0, BRACEOPEN, BRACECLOSE, COMMA, DATASTRING, END }; inline char toch(const token& Token) { switch (Token) { case ra::token::BRACEOPEN: return '{'; case ra::token::BRACECLOSE: return '}'; case ra::token::COMMA: return ','; case ra::token::DATASTRING: return '$'; case ra::token::END: return '.'; default: return '?'; } } RA_INLINE_ std::list> parse_shape(std::istream & in, int R, size_type* shape); template RA_INLINE_ void parse_strings(const std::list> & tokens, const size_type* shape, typename PointerArray::type p); } // end namespace ra template RA_INLINE_ std::ostream& ra::operator<<(std::ostream &o, const ra::rarray& r) { if (R>1) { return ra::text_output(o,r); } else if (R==1) { if (not r.is_clear()) { o << "{"; for (ra::size_type i=0; i0) o << ","; o << r.data()[i]; } o << "}"; } } return o; } template RA_INLINE_ std::ostream& ra::text_output(std::ostream &o, const ra::rarray& r) { if (not r.is_clear()) { o << "{\n"; // new newline for (size_type i=0; i0) o << ",\n"; // new newline o << r.at(i); } o << "\n}"; // new newline } else { for (int i=0; i RA_INLINE_ std::ostream& ra::text_output(std::ostream &o, const ra::rarray& r) { if (not r.is_clear()) { o << '{'; for (size_type i=0; i RA_INLINE_ void ra::StringToValue::get(const std::string& input, T& output) { std::stringstream str(input); // use streaming operators by default str >> output; // won't work with strings as they get truncated at first whitespace } RA_INLINE_ void ra::StringToValue::get(const std::string& input, std::string& output) { output = input; } template RA_INLINEF T& ra::Deref::access(typename PointerArray::type p, const size_type* indices) { return Deref::access(p[indices[0]-1], indices+1); } template RA_INLINEF T& ra::Deref::access(typename PointerArray::type p, const size_type* indices) { return p[indices[0]-1]; } static char get_but_eat_newline(std::istream & in) { char ch1='\n'; while (ch1=='\n' && ! in.eof()) in >> ch1; // eats white space unless noskipws is set return ch1; } static char get_but_eat_whitespace(std::istream & in) { char ch1; in >> ch1; return ch1; } RA_INLINE_ std::list> ra::parse_shape(std::istream & in, int R, ra::size_type* shape) { if (shape == nullptr) { throw std::istream::failure("Parse call error"); } std::list> result; size_t init_file_ptr = in.tellg(); try { size_type current_shape[R]; for (int i=0; i=0) { if (current_depth==R-1) { char lastchar; std::string word = ""; do { if (word=="") { lastchar = get_but_eat_newline(in); } else { lastchar = in.get(); } if (lastchar != ',' and lastchar != '}') { word += lastchar; } if (word == "#") { word=""; std::string skipstr; do { skipstr += (lastchar = in.get()); } while (lastchar!=':'); int skip = atoi(skipstr.c_str());//// for (int i=0; i RA_INLINE_ void ra::parse_strings(const std::list> & tokens, const ra::size_type* shape, typename ra::PointerArray::type p) { size_type index[R]; int current_depth = -1; for (auto& tokenpair: tokens) { switch (tokenpair.first) { case ra::token::BRACEOPEN: current_depth++; index[current_depth]=1; break; case ra::token::BRACECLOSE: current_depth--; break; case ra::token::COMMA: index[current_depth]++; break; case ra::token::DATASTRING: StringToValue::get(tokenpair.second, Deref::access(p, index)); break; case ra::token::END: break; default: throw std::istream::failure("Parsing error"); break; } if (tokenpair.first == ra::token::END) break; } } template RA_INLINE_ std::istream& ra::operator>>(std::istream &in, ra::rarray& r) { ra::size_type extent[R] = {0}; auto X = ra::parse_shape(in, R, extent); if (ra::mul(extent,R) <= r.size()) r.reshape(extent, ra::RESIZE::ALLOWED); else r = rarray(extent); ra::parse_strings(X, extent, r.ptr_array()); return in; } // //#include "rarraydelmacros.h" #undef RA_CHECKORSAY #undef RA_INLINE #undef RA_INLINEF #undef RA_INLINE_ //end of #include "rarraydelmacros.h" #else #error "This file requires C++11 or newer support." #endif #endif