FDO API Reference Feature Data Objects

ObjectStreamReader.h

Go to the documentation of this file.
00001 #ifndef FDO_IO_OBJECTSTREAMREADER_H
00002 #define FDO_IO_OBJECTSTREAMREADER_H
00003 // 
00004 
00005 //
00006 // Copyright (C) 2004-2006  Autodesk, Inc.
00007 // 
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of version 2.1 of the GNU Lesser
00010 // General Public License as published by the Free Software Foundation.
00011 // 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // Lesser General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU Lesser General Public
00018 // License along with this library; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 //
00021 
00022 #include <FdoCommon.h>
00023 #include <Common/IStreamReaderTmpl.h>
00024 
00025 /// \brief
00026 /// FdoIoObjectStreamReader is the template for all
00027 /// readers on FdoIoStream. Readers for various sized objects
00028 /// or primitive types can be based on this class.
00029 template <typename T> class FdoIoObjectStreamReader : public FdoIStreamReaderTmpl<T> 
00030 {
00031 public:
00032     /// \brief
00033     /// Gets the stream length
00034     /// 
00035     /// \return
00036     /// Returns the size of the data source in number of items 
00037     /// 
00038     FDO_API_COMMON virtual FdoInt64   GetLength()
00039     {
00040         FdoInt64 byteCount = mStream->GetLength();
00041 
00042     /// Return the number of objects (floor if #bytes/object size)
00043     /// Partial objects at end of stream are ignored.
00044         return( byteCount / sizeof(T) );
00045     }
00046 
00047  
00048     /// \brief
00049     /// Skips a number of items
00050     /// 
00051     /// \param offset 
00052     /// Input number of items to skip
00053     /// 
00054     FDO_API_COMMON virtual void       Skip(const FdoInt32 offset)
00055     {
00056         mStream->Skip( offset * sizeof(T) );
00057     }
00058   
00059     /// \brief
00060     /// Gets the current stream position. Position is 
00061     /// measured by number of items from the stream start
00062     /// 
00063     /// \return
00064     /// Returns the current index in the stream
00065     /// 
00066     FDO_API_COMMON virtual FdoInt64   GetIndex()
00067     {
00068         FdoInt64 byteIndex = mStream->GetIndex();
00069 
00070         if ( (byteIndex % sizeof(T)) != 0 )
00071             throw FdoException::Create(
00072                 FdoException::NLSGetMessage(
00073                     FDO_NLSID(FDO_36_STREAMINDEXALIGN),
00074                     "%1$s: Current byte position %2$d does not align with size of item being read ($3$d)",
00075                     "FdoIoObjectStreamReader::GetIndex",
00076                     byteIndex,
00077                     sizeof(T)
00078                 )
00079             );
00080 
00081         return( byteIndex / sizeof(T) );
00082     }
00083 
00084 
00085     /// \brief
00086     /// Reset the current index to the stream start. Allows re-reading.
00087     /// 
00088     FDO_API_COMMON virtual void       Reset()
00089     {
00090         mStream->Reset();
00091     }
00092 
00093     /// \brief
00094     /// Reads in the next block of items. Use ReadNext( buffer) to read in 
00095     /// the entire stream. The caller is responsible to allocate a buffer large 
00096     /// enough to store data.
00097     /// 
00098     /// \param buffer 
00099     /// Output array holding data read in.
00100     /// \param offset 
00101     /// Input index in the array indicating the beginning of the output buffer. 
00102     /// If zero, then the buffer is reused. If the end of the buffer, then read in 
00103     /// appending mode. Throws "out-of-bounds" exception if not in this range.
00104     /// \param count 
00105     /// Input number of items to be read in. If -1 read the entire stream.
00106     /// Throws "out-of-bounds"  exception if not a positive value or -1.
00107     /// 
00108     /// \return
00109     /// Returns the number of items actually read in. When 0 (zero) then the 
00110     /// end-of-stream was reached.
00111     /// 
00112     FDO_API_COMMON virtual FdoInt32   ReadNext( T* buffer, 
00113                                       const FdoInt32 offset = 0,
00114                                       const FdoInt32 count = -1)
00115     {
00116         FdoInt32 objectsRead = 0;
00117         FdoInt32 totalObjectsRead = 0;
00118         FdoInt32 bytesRead = 0;
00119 
00120         if ( offset < 0 ) 
00121             throw FdoException::Create(
00122                 FdoException::NLSGetMessage(
00123                     FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)
00124                 )
00125             );
00126 
00127         if ( count < -1 ) 
00128             throw FdoException::Create(
00129                 FdoException::NLSGetMessage(
00130                     FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)
00131                 )
00132             );
00133 
00134         if ( count == -1 ) {
00135             for ( ; ; ) {
00136                 objectsRead = ReadNext( buffer, offset + totalObjectsRead, mBlockSize );
00137                 if ( objectsRead == 0 )
00138                     break;
00139                 totalObjectsRead += objectsRead;
00140             }
00141 
00142             return(totalObjectsRead);
00143         }
00144         else {
00145             FdoInt32 lCount = count;
00146 
00147     /// If the stream provides context information then calculate
00148     /// how many items are left to read.
00149             if ( mStream->HasContext() ) {
00150                 FdoInt64 length = GetLength();
00151 
00152                 if ( length > -1 ) {
00153                     FdoInt64 pos = GetIndex();
00154                     FdoInt64 remaining = ( length - pos ) / sizeof(T);
00155     /// Items that will be read is lessor of items to read
00156     /// and items remaining. This ensures that we don't
00157     /// read any partial item at the end of the stream.
00158                     lCount = lCount < remaining ? lCount : (FdoInt32) remaining;
00159                 }
00160             }
00161 
00162             bytesRead =  (FdoInt32) mStream->Read( &buffer[offset], lCount * sizeof(T));
00163 
00164             return( bytesRead / sizeof(T) );
00165         }
00166     }
00167     /// \param buffer 
00168     /// Output array holding data read in.
00169     /// \param offset 
00170     /// Input index in the array indicating the beginning of the output buffer. 
00171     /// If zero, then the buffer is reused. If the end of the buffer, then read in 
00172     /// appending mode. Throws "out-of-bounds" exception if not in this range.
00173     /// \param count 
00174     /// Input number of items to be read in. If -1 read the entire stream.
00175     /// Throws "out-of-bounds"  exception if not a positive value or -1.
00176     /// 
00177     /// \return
00178     /// Returns the number of items actually read in. When 0 (zero) then the 
00179     /// end-of-stream was reached.
00180     /// 
00181     
00182     /// \brief
00183     /// Reads in the next block of items. Use ReadNext( buffer) to read in 
00184     /// the entire stream. The caller is responsible to create/dispose the FdoArray.
00185     /// 
00186     /// \param buffer 
00187     /// Input array holding data read in.
00188     /// \param offset 
00189     /// Input index in the array indicating the beginning of the output buffer. 
00190     /// If zero, then the buffer is reused. If the end of the buffer, then read in 
00191     /// appending mode. Throws "out-of-bounds" exception if not in this range.
00192     /// \param count 
00193     /// Input number of items to be read in. If -1 read the entire stream.
00194     /// Throws "out-of-bounds"  exception if not a positive value or -1.
00195     /// 
00196     /// \return
00197     /// Returns the number of items actually read in. When 0 (zero) then the 
00198     /// end-of-stream was reached.
00199     /// 
00200     FDO_API_COMMON virtual FdoInt32       ReadNext(  FdoArray<T> * &buffer, 
00201                                         const FdoInt32 offset = 0,
00202                                         const FdoInt32 count = -1 )
00203     {
00204         FdoInt32 lCount = count;
00205 
00206         FdoInt32 lCount2 = 0;
00207         FdoInt64 byteRemaining = 0;
00208         FdoInt64 remaining = 0;
00209 
00210         if ( offset < 0 ) 
00211             throw FdoException::Create(
00212                 FdoException::NLSGetMessage(
00213                     FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)
00214                 )
00215             );
00216 
00217         if ( count < -1 ) 
00218             throw FdoException::Create(
00219                 FdoException::NLSGetMessage(
00220                     FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)
00221                 )
00222             );
00223 
00224         if ( count == -1 ) {
00225             byteRemaining = mStream->GetLength() - mStream->GetIndex();
00226             remaining = byteRemaining / sizeof(T);
00227 
00228             if ( remaining > LONG_MAX ) 
00229                 throw FdoException::Create(
00230                     FdoException::NLSGetMessage(
00231                         FDO_NLSID(FDO_46_REMAININGSTREAMSIZE),
00232                         "%1$s: Cannot read remainder of stream, there are more than %$2d items remaining.",
00233                         "FdoIoObjectStreamReader::ReadNext(FdoArray<T>,FdoInt32,FdoInt32)",
00234                         LONG_MAX
00235                     )
00236                 );
00237 
00238             lCount = (FdoInt32) remaining;
00239         }
00240         T* tmpBuffer = buffer->GetData();
00241 
00242         lCount2 = ReadNext( tmpBuffer, offset, lCount );
00243 
00244         return(lCount2);
00245     }
00246 
00247 protected:
00248 /// \cond DOXYGEN-IGNORE
00249     FdoIoObjectStreamReader() {}
00250 
00251     FdoIoObjectStreamReader( FdoIoStream* stream ) 
00252     {
00253         FDO_SAFE_ADDREF(stream);
00254         mStream = stream;
00255     }
00256 
00257     ~FdoIoObjectStreamReader()
00258     {
00259     }
00260 /// \endcond
00261 
00262 private:
00263     FdoIoStreamP mStream;
00264     static const FdoInt32 mBlockSize = 4096;
00265 };
00266 
00267 #endif
00268 
00269 

Comments or suggestions? Send us feedback.