lineend.h

Go to the documentation of this file.
00001 /**********************************************************************
00002 lineend.h - Stream buffer for filtering line endings, converting \r or \r\n -> \n
00003  
00004  Copyright (C) 1998 by James Kanze
00005  Copyright (C) 2007 by Chris Morley
00006  
00007 This file is part of the Open Babel project.
00008 For more information, see <http://openbabel.sourceforge.net/>
00009  
00010 This program is free software; you can redistribute it and/or modify
00011 it under the terms of the GNU General Public License as published by
00012 the Free Software Foundation version 2 of the License.
00013  
00014 This program is distributed in the hope that it will be useful, but
00015 WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 General Public License for more details.
00018 ***********************************************************************/
00019 
00020 #ifndef OB_LINEEND_H
00021 #define OB_LINEEND_H
00022 
00023 #include <streambuf>
00024 
00025 #ifndef OBCONV
00026 #define OBCONV
00027 #endif
00028 
00029 namespace OpenBabel
00030 {
00031 
00057   template< class Extractor >
00058   class FilteringInputStreambuf : public std::streambuf
00059   {
00060   public:
00061     FilteringInputStreambuf(
00062       std::streambuf*        source = NULL ,
00063       bool                   deleteWhenFinished = false 
00064       ) ;
00065     virtual                 ~FilteringInputStreambuf()
00066     {
00067       sync();
00068     };
00069     virtual int              overflow( int ) {return EOF;};
00070     virtual int              underflow() ;
00071     virtual int              sync() ;
00072 
00073     //Pass the random acess functions to the source rdbuf and synchronize
00074     virtual std::streampos   seekoff(std::streamoff off, std::ios_base::seekdir way,
00075       std::ios_base::openmode which = std::ios_base::in | std::ios_base::out )
00076     {
00077       std::streampos ret = mySource->pubseekoff(off, way, which);
00078 //      sync();
00079       return ret;
00080     };
00081 
00082     virtual std::streampos   seekpos(std::streampos sp, 
00083       std::ios_base::openmode which = std::ios_base::in | std::ios_base::out )
00084     {
00085       std::streampos ret = mySource->pubseekpos(sp, which);
00086 //      sync();
00087       return ret;
00088     };
00089 
00091     std::streambuf* GetSource()const
00092     {
00093       return mySource;
00094     };
00095 
00097     void SetSource(std::streambuf* newsource)
00098     {
00099       mySource = newsource;
00100       setg( &myBuffer , &myBuffer , &myBuffer + 1 ) ;
00101     }
00102 
00103 //    Extractor&   extractor() {return myExtractor;};
00104 
00105   private:
00106     std::streambuf*          mySource ;
00107     Extractor                myExtractor ;
00108     char                     myBuffer ;
00109     bool                     myDeleteWhenFinished ;
00110   } ;
00111 
00112 //*******************************************************
00113   template< class Extractor >
00114   FilteringInputStreambuf< Extractor >::FilteringInputStreambuf(
00115     std::streambuf*        source ,
00116     bool                   deleteWhenFinished) 
00117     : mySource(source), myDeleteWhenFinished(deleteWhenFinished)
00118   {
00119     setg( &myBuffer , &myBuffer , &myBuffer ) ;
00120   }
00121 
00123   template< class Extractor >
00124   int
00125   FilteringInputStreambuf< Extractor >::underflow()
00126   {
00127     int result( EOF ) ;
00128     if( gptr() < egptr() )
00129       result = *gptr() ;
00130     else if ( mySource != NULL )
00131     {
00132       result = myExtractor( *mySource ) ;
00133       if ( result != EOF )
00134       {
00135         if( result < 0 || result > UCHAR_MAX ) 
00136           std::cerr << "FilteringInputStreambuf error" << std::endl;
00137         myBuffer = result ;
00138         setg( &myBuffer , &myBuffer , &myBuffer + 1 ) ;
00139       }
00140     }
00141     return result ;
00142   }
00143 
00145   template< class Extractor >
00146   int
00147   FilteringInputStreambuf< Extractor >::sync()
00148   {
00149     int result( 0 ) ;
00150     if ( mySource != NULL )
00151     {
00152       if ( gptr() < egptr() )
00153       {
00154         result = mySource->sputbackc( *gptr() ) ;
00155         setg( NULL , NULL , NULL ) ;
00156       }
00157       if ( mySource->pubsync() == EOF )
00158           result = EOF ;
00159     }
00160     return result ;
00161   }
00162 
00163 //*********************************************
00166 class OBCONV LineEndingExtractor
00167 {
00168 public:
00169   int operator()( std::streambuf& src )
00170   {
00171     int ch( src.sbumpc() ) ;
00172     switch (ch)
00173     {
00174       case 13: //CR or CRLF
00175         if(src.sgetc() == 10)
00176           src.sbumpc(); //CRLF
00177         //fall through
00178       case 10: //LF
00179         return '\n';
00180         break;
00181       default:
00182         return ch;
00183     }
00184   }
00185   void finalize( std::streambuf& ) {}
00186 };
00187 
00188 } //namespace
00189 
00190 #endif //OB_LINEEND_H