inputStream.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLR_COMMON_INPUTSTREAM_H_
00016 #define _DLR_COMMON_INPUTSTREAM_H_
00017 
00018 #include<iostream>
00019 
00020 namespace dlr {
00021 
00022   namespace common {
00023     
00032     class InputStream
00033     {
00034     public:
00035       /* ============ Typedefs "inherited" from std::istream ============ */
00037       typedef std::istream::char_type char_type;
00038 
00039 
00040       /* ================== New typedefs and constants ================== */
00041     
00048       typedef unsigned int FormatFlag;
00049 
00050     
00054       static const FormatFlag NO_FLAG         = 0x00;
00055 
00056     
00062       static const FormatFlag SKIP_WHITESPACE = 0x01;
00063 
00064     
00071       static const FormatFlag SLOPPY_EXPECT   = 0x02;
00072 
00073     
00089       InputStream(std::istream& inputStream, FormatFlag flags=NO_FLAG)
00090         : m_istream(inputStream),
00091           m_skipWhiteSpace((flags & SKIP_WHITESPACE) != 0),
00092           m_sloppyExpect((flags & SLOPPY_EXPECT) != 0) {}
00093 
00094 
00098       ~InputStream() {}
00099 
00100       /* =================== Conversion operators =================== */
00101 
00108       operator void*() const {
00109         return m_istream;
00110       }
00111 
00112 
00119       operator std::istream&() const {
00120         return m_istream;
00121       }
00122 
00123       /* ============ Operators "inherited" from std::istream ============ */
00124 
00134       template <class Type>
00135       InputStream&
00136       operator>>(Type& typeInstance) {
00137         m_istream >> typeInstance;
00138         return *this;
00139       }
00140 
00141 
00142       /* ======== Member functions "inherited" from std::istream ======== */
00143 
00151       bool
00152       bad() {
00153         return m_istream.bad();
00154       }
00155 
00156     
00164       void
00165       clear(std::istream::iostate state=std::istream::goodbit) {
00166         m_istream.clear(state);
00167       }
00168 
00169 
00177       bool
00178       eof() {
00179         return m_istream.eof();
00180       }
00181 
00182     
00190       bool
00191       fail() {
00192         return m_istream.fail();
00193       }
00194 
00195     
00203       std::istream::int_type
00204       get() {
00205         return m_istream.get();
00206       }
00207 
00208 
00222       InputStream
00223       getline(char_type* inputBuffer, std::streamsize numberOfCharacters) {
00224         return m_istream.getline(inputBuffer, numberOfCharacters);
00225       }
00226     
00227     
00235       std::istream::int_type
00236       peek() {
00237         return m_istream.peek();
00238       }
00239 
00240     
00241       /* =================== New member functions =================== */
00242 
00252       InputStream&
00253       expect(std::istream::char_type inputChar) {
00254         std::istream::char_type readChar = 0;
00255         *this >> readChar;
00256         if(readChar != inputChar) {
00257           this->clear(std::ios_base::failbit);
00258         }
00259         return *this;
00260       }
00261 
00262 
00272       InputStream&
00273       expect(const std::string& inputString) {
00274         return this->expect(inputString.c_str(), inputString.size());
00275       }
00276 
00277 
00301       InputStream&
00302       expect(const char* inputCString, size_t stringSize=0) {
00303         // We need an area into which to read.
00304         std::istream::char_type inputBuffer[s_chunkSize + 1];
00305 
00306         // Remove leading white space, if required.
00307         if(m_skipWhiteSpace) {
00308           this->skipWhiteSpace();
00309         }
00310       
00311         // inputString might be very long, so we keep count of how much
00312         // we've read.
00313         size_t readCount = 0;
00314 
00315         // If the caller hasn't specified how long the string is, we
00316         // find out using strlen().
00317         if(stringSize == 0) {
00318           stringSize = strlen(inputCString);        
00319         }
00320       
00321         while(readCount < stringSize) {
00322           // Figure out how much to read.
00323           size_t thisChunkCount = stringSize - readCount;
00324 
00325           // But be sure not to overflow the buffer.
00326           if(thisChunkCount > s_chunkSize) {
00327             thisChunkCount = s_chunkSize;
00328           }
00329 
00330           // Read the appropriate number of characters.
00331           m_istream.read(inputBuffer,
00332                          static_cast<std::streamsize>(thisChunkCount));
00333 
00334           // Now evaluate what we've read.
00335           bool matchFlag = true;
00336           if(!m_sloppyExpect) {
00337             // We use memcmp() instead of strncmp() because the caller
00338             // might conceivably expect a string with a '\0' in the middle.
00339             matchFlag = (
00340               std::memcmp(reinterpret_cast<const void*>(inputCString
00341                                                         + readCount),
00342                           reinterpret_cast<const void*>(inputBuffer),
00343                           thisChunkCount * sizeof(char)) == 0);
00344           }
00345 
00346           // Quit if it wasn't what we expected.
00347           if(!matchFlag) {
00348             this->clear(std::ios_base::failbit);
00349             break;
00350           }
00351         
00352           // Increment our count of how many characters read.
00353           readCount += thisChunkCount;
00354         }
00355         return *this;
00356       }
00357     
00358 
00362       void
00363       skipWhiteSpace() {
00364         std::istream::char_type inputChar;
00365         m_istream >> inputChar;
00366         m_istream.putback(inputChar);
00367       }
00368 
00369     
00370     private:
00371       static const size_t s_chunkSize = 1024;
00372       std::istream& m_istream;
00373       bool m_skipWhiteSpace;
00374       bool m_sloppyExpect;
00375     };
00376 
00377   } // namespace common
00378   
00379 } // namespace dlr
00380 
00381 
00382 /* ======= Declarations to maintain compatibility with legacy code. ======= */
00383 
00384 namespace dlr {
00385 
00386   using common::InputStream;
00387   
00388 } // namespace dlr
00389 
00390 #endif // #ifndef _DLR_COMMON_INPUTSTREAM_H_

Generated on Mon Jul 9 20:34:03 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2