transcode_stream.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2008 The FLWOR Foundation.
00003  * 
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  * 
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef ZORBA_TRANSCODE_STREAM_API_H
00018 #define ZORBA_TRANSCODE_STREAM_API_H
00019 
00020 #include <stdexcept>
00021 #include <streambuf>
00022 #include <string>
00023 
00024 #include <zorba/config.h>
00025 #include <zorba/internal/proxy.h>
00026 #include <zorba/internal/unique_ptr.h>
00027 
00028 namespace zorba {
00029 
00030 typedef internal::ztd::proxy<std::streambuf> proxy_streambuf;
00031 
00032 namespace transcode {
00033 
00034 ///////////////////////////////////////////////////////////////////////////////
00035 
00036 /**
00037  * A %transcode::streambuf is-a std::streambuf for transcoding character
00038  * encodings from/to UTF-8 on-the-fly.
00039  *
00040  * To use it, replace a stream's streambuf:
00041  * \code
00042  *  istream is;
00043  *  // ...
00044  *  transcode::streambuf tbuf( "ISO-8859-1", is.rdbuf() );
00045  *  is.ios::rdbuf( &tbuf );
00046  * \endcode
00047  * Note that the %transcode::streambuf must exist for as long as it's being used
00048  * by the stream.  If you are replacing the streabuf for a stream you did not
00049  * create, you should set it back to the original streambuf:
00050  * \code
00051  *  void f( ostream &os ) {
00052  *    transcode::streambuf tbuf( "ISO-8859-1", os.rdbuf() );
00053  *    try {
00054  *      os.ios::rdbuf( &tbuf );
00055  *      // ...
00056  *    }
00057  *    catch ( ... ) {
00058  *      os.ios::rdbuf( tbuf.orig_streambuf() );
00059  *      throw;
00060  *    }
00061  *  }
00062  * \endcode
00063  *
00064  * While %transcode::streambuf does support seeking, the positions are relative
00065  * to the original byte stream.
00066  */
00067 class ZORBA_DLL_PUBLIC streambuf : public std::streambuf {
00068 public:
00069   /**
00070    * Constructs a %transcode::streambuf.
00071    *
00072    * @param charset The name of the character encoding to convert from/to.
00073    * @param orig The original streambuf to read/write from/to.
00074    * @throws std::invalid_argument if either \a charset is not supported or
00075    * \a orig is null.
00076    */
00077   streambuf( char const *charset, std::streambuf *orig );
00078 
00079   /**
00080    * Destructs a %transcode::streambuf.
00081    */
00082   ~streambuf();
00083 
00084   /**
00085    * Gets the original streambuf.
00086    *
00087    * @return said streambuf.
00088    */
00089   std::streambuf* orig_streambuf() const {
00090     return proxy_buf_->original();
00091   }
00092 
00093 protected:
00094   void imbue( std::locale const& );
00095   pos_type seekoff( off_type, std::ios_base::seekdir, std::ios_base::openmode );
00096   pos_type seekpos( pos_type, std::ios_base::openmode );
00097   std::streambuf* setbuf( char_type*, std::streamsize );
00098   std::streamsize showmanyc();
00099   int sync();
00100   int_type overflow( int_type );
00101   int_type pbackfail( int_type );
00102   int_type uflow();
00103   int_type underflow();
00104   std::streamsize xsgetn( char_type*, std::streamsize );
00105   std::streamsize xsputn( char_type const*, std::streamsize );
00106 
00107 private:
00108   std::unique_ptr<proxy_streambuf> proxy_buf_;
00109 
00110   // forbid
00111   streambuf( streambuf const& );
00112   streambuf& operator=( streambuf const& );
00113 };
00114 
00115 ///////////////////////////////////////////////////////////////////////////////
00116 
00117 /**
00118  * A %transcode::stream is used to wrap a C++ standard I/O stream with a
00119  * transcode::streambuf so that transcoding and the management of the streambuf
00120  * happens automatically.
00121  *
00122  * @tparam StreamType The I/O stream class type to wrap. It must be a concrete
00123  * stream class.
00124  */
00125 template<class StreamType>
00126 class stream : public StreamType {
00127 public:
00128   /**
00129    * Constructs a %transcode::stream.
00130    *
00131    * @param charset The name of the character encoding to convert from/to.
00132    * @throws std::invalid_argument if \a charset is not supported.
00133    */
00134   stream( char const *charset ) :
00135     tbuf_( charset, this->rdbuf() )
00136   {
00137     init();
00138   }
00139 
00140   /**
00141    * Constructs a %stream.
00142    *
00143    * @tparam StreamArgType The type of the first argument of \a StreamType's
00144    * constructor.
00145    * @param charset The name of the character encoding to convert from/to.
00146    * @param stream_arg The argument to pass as the first argument to
00147    * \a StreamType's constructor.
00148    * @throws std::invalid_argument if \a charset is not supported.
00149    */
00150   template<typename StreamArgType>
00151   stream( char const *charset, StreamArgType stream_arg ) :
00152     StreamType( stream_arg ),
00153     tbuf_( charset, this->rdbuf() )
00154   {
00155     init();
00156   }
00157 
00158   /**
00159    * Constructs a %transcode::stream.
00160    *
00161    * @tparam StreamArgType The type of the first argument of \a StreamType's
00162    * constructor.
00163    * @param charset The name of the character encoding to convert from/to.
00164    * @param stream_arg The argument to pass as the first argument to
00165    * \a StreamType's constructor.
00166    * @param mode The open-mode to pass to \a StreamType's constructor.
00167    * @throws std::invalid_argument if \a charset is not supported.
00168    */
00169   template<typename StreamArgType>
00170   stream( char const *charset, StreamArgType stream_arg,
00171           std::ios_base::openmode mode ) :
00172     StreamType( stream_arg, mode ),
00173     tbuf_( charset, this->rdbuf() )
00174   {
00175     init();
00176   }
00177 
00178 private:
00179   streambuf tbuf_;
00180 
00181   void init() {
00182     this->std::ios::rdbuf( &tbuf_ );
00183   }
00184 };
00185 
00186 ///////////////////////////////////////////////////////////////////////////////
00187 
00188 /**
00189  * Checks whether it would be necessary to transcode from the given character
00190  * encoding to UTF-8.
00191  *
00192  * @param charset The name of the character encoding to check.
00193  * @return \c true only if it would be necessary to transcode from the given
00194  * character encoding to UTF-8.
00195  */
00196 ZORBA_DLL_PUBLIC
00197 bool is_necessary( char const *charset );
00198 
00199 /**
00200  * Checks whether the given character set is supported for transcoding.
00201  *
00202  * @param charset The name of the character encoding to check.
00203  * @return \c true only if the character encoding is supported.
00204  */
00205 ZORBA_DLL_PUBLIC
00206 bool is_supported( char const *charset );
00207 
00208 ///////////////////////////////////////////////////////////////////////////////
00209 
00210 } // namespace transcode
00211 } // namespace zorba
00212 #endif  /* ZORBA_TRANSCODE_STREAM_API_H */
00213 /* vim:set et sw=2 ts=2: */
blog comments powered by Disqus