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

Generated on Tue Nov 24 23:57:55 2009 for dlrCommon Utility Library by  doxygen 1.5.8