// --------------------------------------------------------------------------- // Effectors for stream I/O // --------------------------------------------------------------------------- // Last modified on: // April 26th, 2003. (started on April 4th, 2003.) // // Author: // Chusslove Illich (Часлав Илић) // // Legal: // Copyright (C) 2003 by Chusslove Illich. You can use, redistribute and // modify this software under the terms of GNU General Public Licence, // version 2. // --------------------------------------------------------------------------- #ifndef HUEY_FORMIO_H #define HUEY_FORMIO_H #include #include #include #include #define WL extern "C++" { namespace huey { // ----------------------------------------------------------------------- // Output format for general data. template class fgen; template std::ostream& operator<< (std::ostream&, const fgen&); template class fgen { public: // Output data with given width and alignment (0 for right, 1 for // left aligned). fgen (const T& data, uint width, uint alignment = 0); friend std::ostream& operator<< <> (std::ostream& os, const fgen& of); private: const T& data_; uint width_; uint alignment_; }; template fgen::fgen (const T& data, uint width, uint alignment) : data_(data), width_(width), alignment_(alignment) {} template std::ostream& operator<< (std::ostream& os, const fgen& of) { std::_Ios_Fmtflags preFlags = os.flags(); uint preWidth = os.width(); os.width(of.width_); if (of.alignment_ == 0) os.setf(std::ios::right); else //if (of.alignment_ == 1) os.setf(std::ios::left); os << of.data_; os.flags(preFlags); os.width(preWidth); return os; } // ----------------------------------------------------------------------- // Output format for real-type data. template class freal; template std::ostream& operator<< (std::ostream&, const freal&); template class freal { public: // Output data with given precision, width and alignment (0 for right, // 1 for left aligned). freal (const T& data, uint precision, uint width = 0, WL uint alignment = 0); friend std::ostream& operator<< <> (std::ostream& os, const freal& of); private: const T& data_; uint precision_; uint width_; uint alignment_; }; template freal::freal (const T& data, uint precision, uint width, WL uint alignment) : data_(data), precision_(precision), width_(width), alignment_(alignment) {} template std::ostream& operator<< (std::ostream& os, const freal& of) { std::ostringstream oss; oss.precision(of.precision_); oss.setf(std::ios::fixed); if (of.precision_ > 0) oss.setf(std::ios::showpoint); oss << of.data_; os << fgen(oss.str(), of.width_, of.alignment_); return os; } // ----------------------------------------------------------------------- // Input quoted string-like data. // Note: Input type must have operator `=' defined for `const char*' type. // Quote settings class defaultQuotes { public: // Set default quote, same for start and end. static void set (const std::string& quote); // Set default start and end quotes. static void set (const std::string& startQuote, WL const std::string& endQuote); // Get current default start quote static const std::string& getStart (); // Get current default end quote static const std::string& getEnd (); private: static std::string start_; static std::string end_; }; // Exception for invalid input. class excInvalidStreamInput : public std::logic_error { public: excInvalidStreamInput (const std::string& data, WL const std::string& input = "") WL : std::logic_error("excInvalidStreamInput"), WL data_(data), input_(input) {} virtual ~excInvalidStreamInput() throw() {}; virtual const std::string& getData () const { return data_; } virtual const std::string& getInput () const { return input_; } private: std::string data_; std::string input_; }; template class quoted; template std::istream& operator>> (std::istream&, const quoted&); // Effector. template class quoted { public: // Input default qouted string quoted (T& data); // Also, specify quote type. quoted (T& data, const std::string& quote); // Specify both start an end quotes. quoted (T& data, const std::string& startQuote, WL const std::string& endQuote); friend std::istream& operator>> <> (std::istream& is, const quoted& q); private: T& data_; std::string startQuote_; std::string endQuote_; }; template quoted::quoted (T& data) : data_(data), startQuote_(defaultQuotes::getStart()), WL endQuote_(defaultQuotes::getEnd()) {} template quoted::quoted (T& data, const std::string& quote) : data_(data), startQuote_(quote), endQuote_(quote) {} template quoted::quoted (T& data, const std::string& startQuote, WL const std::string& endQuote) : data_(data), startQuote_(startQuote), endQuote_(endQuote) {} template std::istream& operator>> (std::istream& is, const quoted& q) { std::string s; is >> s; if (not is) throw excInvalidStreamInput("eof"); if (s.find(q.startQuote_) == 0) { bool isEndQuote = false; while (is and not isEndQuote) { isEndQuote = s.rfind(q.endQuote_) WL == s.length() - q.endQuote_.length(); if (not isEndQuote) { char c; is.read(&c, 1); if (is) s += c; } } if (not is) throw excInvalidStreamInput("eof"); s.erase(0, q.startQuote_.length()); s.erase(s.length() - q.endQuote_.length(), q.endQuote_.length()); } q.data_ = s.c_str(); return is; } // ----------------------------------------------------------------------- // Assure that input data is valid, and that input stream remains valid // after extraction. // // Consider data to be next non-delimited string, eg. `100qwerty' will be // invalid when reading int type (without effector, only `100' would be // parsed as int). // // This effector should be typically used for reading numerical data. template class iassure { public: iassure (T& data); friend std::istream& operator>> <> (std::istream& is, const iassure& ia); private: T& data_; }; template iassure::iassure (T& data) : data_(data) {} template std::istream& operator>> (std::istream& is, const iassure& ia) { std::string s; is >> s; if (not is) throw excInvalidStreamInput("eof"); std::istringstream iss(s); iss >> ia.data_; if (not iss) throw excInvalidStreamInput("data", s); char c; iss >> c; if (iss) throw excInvalidStreamInput("tail", s); return is; } // ----------------------------------------------------------------------- } // namespace huey } // extern "C++" #endif