#ifndef _utl_ReadStream_h_ #define _utl_ReadStream_h_ #include #include #include #include #include #include namespace utl { /* \brief Read simple structured data from stream sources The only requirement for reading a colon-structured data is that is is described by some type T with the operator>> implemented. Example: File contains columns: int time, double pressure, bool flag The structure is described by the following class: \code struct Data { int fTime; double fPressure; bool fFlag; }; inline std::istream& operator>>(std::istream& is, Data& d) { return is >> d.fTime >> std::ws >> d.fPressure >> std::ws >> d.fFlag; } \endcode Having that, the whole file is read as \code ifstream file("foo.txt"); vector v; ReadStream(file).GetLines(v); \endcode By default, the GetLines() method does whitespace and comment stripping before the string is passed to the boost::lexical_cast (which uses operator>>). If not desired, this white-space compression and comment stripping can be switched off by adding 'false' to the GetLines() call. The following types of input is stripped:
  • empty lines or lines with only white-space characters (this is done even when 'false' is passed)
  • shell-like comments: all the rest of the line after '#' is discarded
  • C-like comments: all characters between inclusive '&47;*' and '*&47;' are removed
  • C++-like comments: all characters after and including '//' are discarded
If your file contain more columns which you don't want to parse, issue is.setstate(ios_base::eofbit) after you've read all the needed columns. boost::lexical_cast namely checks for the state of the stream after operator>> is called and requires the EOF state to be set. \author Darko Veberic \version $Id$ */ class ReadStream : public SafeBoolCast { public: ReadStream() : fStream(0) { } ReadStream(std::istream& is) : fStream(&is) { } void SetStream(std::istream& is) { fStream = &is; } std::istream& GetStream() const { ThrowOnZeroDereference::Examine(fStream); return *fStream; } void Clear() { fStream = 0; } template bool Get(T& t) { ThrowOnZeroDereference::Examine(fStream); return (GetStream() >> t); } template bool GetLine(T& t) { ThrowOnZeroDereference::Examine(fStream); std::string line; if (!std::getline(*fStream, line)) return false; t = boost::lexical_cast(line); return true; } template void GetLines(std::vector& v, const bool filterComments = true) { ThrowOnZeroDereference::Examine(fStream); std::string line; while (std::getline(*fStream, line)) { if (filterComments) line = FilterComments(line); if (!line.empty()) v.push_back(boost::lexical_cast(line)); } } bool BoolCast() const { return fStream && *fStream; } private: ReadStream(const ReadStream&); ReadStream& operator=(const ReadStream&); static std::string FilterComments(const std::string& line); std::istream* fStream; }; } #endif