Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CAT/CATStreamSub.cpp Source File

CATStreamSub.cpp

Go to the documentation of this file.
00001 /// \file CATStreamSub.cpp
00002 /// \brief Sub-stream class
00003 /// \ingroup CAT
00004 ///
00005 /// Copyright (c) 2003-2007 by Michael Ellison.
00006 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00007 ///
00008 // $Author: mikeellison $
00009 // $Date: 2008-01-21 08:33:12 -0600 (Mon, 21 Jan 2008) $
00010 // $Revision:   $
00011 // $NoKeywords: $
00012 
00013 #include "CATStreamSub.h"
00014 CATStreamSub::CATStreamSub( CATInt64 offset, CATInt64 length, CATStream* parent) : 
00015 CATStream()
00016 {
00017    CATASSERT(parent != 0, "Sub streams with no parent aren't worth much....");
00018    CATASSERT(parent->IsOpen(), "The parent stream must be open, too...");
00019 
00020    fParent = parent;
00021    fOffset = offset;
00022    fLength = length;
00023    fCurPos = 0;
00024 }
00025 
00026 //---------------------------------------------------------------------------
00027 // Destructor will clean up the RAM, but it'll
00028 // assert in debug mode if you do this.
00029 //
00030 // Please call Close() before destroying a stream if you
00031 // have opened it previously.
00032 // \sa Close()
00033 //---------------------------------------------------------------------------
00034 CATStreamSub::~CATStreamSub()
00035 {
00036    CATASSERT(fSubCount == 0, "You have substreams left open on a substream!");
00037 }
00038 
00039 //---------------------------------------------------------------------------
00040 // Open() should not be called on substreams. They are always open.
00041 //---------------------------------------------------------------------------
00042 CATResult CATStreamSub::Open(const CATWChar* name, OPEN_MODE mode)
00043 {   
00044    CATASSERT(false, "Substreams are always open.");
00045    return CATRESULT(CAT_ERR_OPENING_SUBSTREAM);
00046 }
00047 
00048 //---------------------------------------------------------------------------
00049 // Close() should not be called on substreams. 
00050 //
00051 // When you are done with a substream, release it by calling
00052 // CATStream::ReleaseSubStream() with its parent.
00053 // \sa Open()
00054 //---------------------------------------------------------------------------
00055 CATResult CATStreamSub::Close()
00056 {
00057    CATASSERT(false, "Close() should not be called on substreams.");
00058    return CATRESULT(CAT_ERR_CLOSING_SUBSTREAM);
00059 }
00060 
00061 //---------------------------------------------------------------------------
00062 // IsOpen() returns true if the stream has been opened, and false otherwise.
00063 //
00064 // Substreams should always be open.
00065 //
00066 // \return bool - true if stream is open.
00067 // \sa Open(), Close()
00068 //---------------------------------------------------------------------------
00069 bool CATStreamSub::IsOpen()
00070 {
00071    return (fParent != 0);
00072 }
00073 
00074 
00075 //---------------------------------------------------------------------------
00076 // Read() reads the requested amount of data into a buffer.
00077 //
00078 // Will read up to, but not necessarily, [length] bytes.
00079 // On return, length is set to the number of bytes actually read.
00080 // buffer *must* be large enough for max value of length.
00081 // 
00082 // \param buffer - target buffer for read
00083 // \param length - min(length of buffer, desired read length).
00084 //        Set to amount read on return.
00085 // \return CATResult - CAT_SUCCESS on success
00086 // \sa Write()
00087 //---------------------------------------------------------------------------
00088 CATResult CATStreamSub::Read(void* buffer, CATUInt32& length)
00089 {
00090    CATASSERT(this->fParent != 0, "Can't read with a null parent.");
00091    if (this->fParent == 0)
00092    {
00093       return CATRESULT(CAT_ERR_SUBSTREAM_NO_PARENT);
00094    }
00095    
00096    if (this->fLength != -1)
00097    {
00098       if (length + fCurPos > this->fLength)
00099       {
00100          length = (CATUInt32)(fLength - fCurPos);
00101       }
00102    }
00103 
00104    CATResult result = fParent->ReadAbs(buffer,length,fCurPos + this->fOffset);
00105    fCurPos += length;
00106    return result;
00107 }
00108 
00109 //---------------------------------------------------------------------------
00110 // Write() writes the requested amount of data from a buffer.
00111 //
00112 // Incomplete writes are treated as an error.
00113 // 
00114 // \param buffer - source buffer to write from.
00115 // \param length - length of data to write
00116 // \return CATResult - CAT_SUCCESS on success
00117 // \sa Read()
00118 //---------------------------------------------------------------------------
00119 CATResult CATStreamSub::Write(const void* buffer, CATUInt32 length)
00120 {
00121    CATASSERT(this->fParent != 0, "Can't read with a null parent.");
00122    if (this->fParent == 0)
00123    {
00124       return CATRESULT(CAT_ERR_SUBSTREAM_NO_PARENT);
00125    }
00126    
00127    // If length was specified, then truncate write to our stream section.
00128    if (this->fLength != -1)
00129    {
00130       if (length + fCurPos > this->fLength)
00131       {
00132          CATTRACE("Warning! Attempt to write beyond specified end of substream! Write truncated...");
00133          if (fCurPos < fLength)
00134          {
00135             length = (CATUInt32)(fLength - fCurPos);
00136          }
00137          else
00138          {
00139             return CATRESULT(CAT_ERR_WRITE_PAST_SPECIFIED_END);
00140          }
00141       }
00142    }
00143 
00144    CATResult result = fParent->WriteAbs(buffer,length,fCurPos + this->fOffset);
00145    
00146    // Only add our position on success.
00147    if (CATSUCCEEDED(result))
00148       fCurPos += length;
00149       
00150    return result;
00151 }
00152 
00153 //---------------------------------------------------------------------------
00154 // Size() returns the size of the object in filesize.
00155 //
00156 // This should be cached and optimized later.
00157 //
00158 // This may not be supported on all stream types.
00159 // \param filesize - 64-bit length of file.
00160 // \return CATResult - CAT_SUCCESS on success
00161 //---------------------------------------------------------------------------
00162 CATResult CATStreamSub::Size(CATInt64& filesize)
00163 {
00164    CATResult result = CAT_SUCCESS;
00165    CATASSERT(this->fParent != 0, "Can't read with a null parent.");
00166    if (this->fParent == 0)
00167    {
00168       return CATRESULT(CAT_ERR_SUBSTREAM_NO_PARENT);
00169    }
00170 
00171    if (this->fLength == -1)
00172    {
00173       this->fParent->Size(filesize);
00174       filesize -= this->fOffset;
00175    }
00176    else
00177    {
00178       filesize = this->fLength;
00179    }
00180       
00181    return result;
00182 }
00183 
00184 //---------------------------------------------------------------------------
00185 // Substreams must be seekable.
00186 //---------------------------------------------------------------------------
00187 bool CATStreamSub::IsSeekable()
00188 {
00189    return true;
00190 }
00191 
00192 //---------------------------------------------------------------------------
00193 // SeekRelative() seeks from current position to a
00194 // relative location.
00195 //
00196 // \param offset - signed offset from current position
00197 // \return CATResult - CAT_SUCCESS on success.
00198 // \sa IsSeekable(), SeekAbsolute(), SeekFromEnd()
00199 //---------------------------------------------------------------------------
00200 CATResult CATStreamSub::SeekRelative(CATInt32  offset)
00201 {         
00202    CATResult result = CAT_SUCCESS;
00203    CATASSERT(this->fParent != 0, "Can't read with a null parent.");
00204    if (this->fParent == 0)
00205    {
00206       return CATRESULT(CAT_ERR_SUBSTREAM_NO_PARENT);
00207    }
00208 
00209    if (offset + fCurPos < 0)
00210    {
00211       fCurPos = 0;
00212       return CATRESULTFILE(CAT_ERR_FILE_SEEK,"SubStream");
00213    }
00214 
00215    if (fLength != -1)
00216    {
00217       if (fCurPos + offset > fLength)
00218       {
00219          fCurPos = fLength;
00220          return CATRESULT(CAT_ERR_SEEK_PAST_SPECIFIED_END);
00221       }
00222    }
00223 
00224    fCurPos += offset;
00225 
00226    return CAT_SUCCESS;   
00227 }
00228 
00229 
00230 //---------------------------------------------------------------------------
00231 // SeekAbsolute() seeks from the start of the file
00232 // to an absolute position.
00233 //
00234 // \param position - unsigned absolute position to seek to.
00235 // \return CATResult - CAT_SUCCESS on success.
00236 // \sa IsSeekable(), SeekRelative(), SeekFromEnd()
00237 //---------------------------------------------------------------------------
00238 CATResult CATStreamSub::SeekAbsolute(CATInt64 position)
00239 {
00240    CATResult result = CAT_SUCCESS;
00241    CATASSERT(this->fParent != 0, "Can't read with a null parent.");
00242    if (this->fParent == 0)
00243    {
00244       return CATRESULT(CAT_ERR_SUBSTREAM_NO_PARENT);
00245    }
00246 
00247    if (position < 0)
00248    {
00249       fCurPos = 0;
00250       return CATRESULTFILE(CAT_ERR_FILE_SEEK,"SubStream");
00251    }
00252 
00253    if (fLength != -1)
00254    {
00255       if (position > fLength)
00256       {
00257          fCurPos = fLength;
00258          return CATRESULT(CAT_ERR_SEEK_PAST_SPECIFIED_END);
00259       }
00260    }
00261 
00262    fCurPos = position;
00263 
00264    return CAT_SUCCESS;   
00265 }
00266 
00267 //---------------------------------------------------------------------------
00268 // SeekFromEnd() seeks from the end of the file.
00269 //
00270 // \param offset - signed offset from end of stream
00271 // \return CATResult - CAT_SUCCESS on success.
00272 // \sa IsSeekable(), SeekRelative(), SeekAbsolute()
00273 //---------------------------------------------------------------------------
00274 CATResult CATStreamSub::SeekFromEnd(CATInt32 offset)
00275 {
00276    CATResult result = CAT_SUCCESS;
00277    CATInt64 position = 0;
00278    if (CATFAILED(result = this->Size(position)))
00279    {
00280       return result;
00281    }
00282    return this->SeekAbsolute(position - offset);
00283 }
00284 
00285 
00286 //---------------------------------------------------------------------------
00287 // GetPosition() returns the current position in the stream
00288 // in position.
00289 //
00290 // \param position - current position - set on successful return.
00291 // \return CATResult - CAT_SUCCESS on success.
00292 // \sa IsSeekable(), Size()
00293 //---------------------------------------------------------------------------
00294 CATResult CATStreamSub::GetPosition(CATInt64& position)
00295 {
00296    position = this->fCurPos;
00297    return CAT_SUCCESS;
00298 }
00299 
00300 
00301 
00302 //---------------------------------------------------------------------------
00303 CATString CATStreamSub::GetName() const
00304 {
00305    if (fParent == 0)
00306    {
00307       return L"NULLSTREAM";
00308    }
00309    return this->fParent->GetName();
00310 }
00311 
00312 
00313 
00314 //---------------------------------------------------------------------------
00315 // ReadAbs() reads from the specified location, but does
00316 // not change the current stream position.
00317 //
00318 // ReadAbs() is mainly for use in substreams, and may not be
00319 // available from all stream types.  If you're not implementing
00320 // it, then please return an error from your derived class.
00321 //
00322 // \param buffer - target buffer for read
00323 // \param length - min(length of buffer, desired read length).
00324 //                 set to amount read on return.
00325 // \param position - position within stream to read.
00326 //  \return CATResult - CAT_SUCCESS on success.
00327 //---------------------------------------------------------------------------
00328 CATResult CATStreamSub::ReadAbs(void *buffer, CATUInt32& length, CATInt64 position)
00329 {
00330    CATResult result = CAT_SUCCESS;
00331    CATInt64 orgPos = 0;
00332 
00333    if (CATFAILED(result = this->GetPosition(orgPos)))
00334    {
00335       return result;
00336    }
00337    
00338    // On errors, at least try to restore the old position.
00339    if (CATFAILED(result = this->SeekAbsolute(position)))
00340    {
00341       this->SeekAbsolute(orgPos);
00342       return result;
00343    }
00344 
00345    if (CATFAILED(result = this->Read(buffer,length)))
00346    {
00347       this->SeekAbsolute(orgPos);
00348       return result;
00349    }
00350 
00351    return this->SeekAbsolute(orgPos);
00352 }
00353 
00354 //---------------------------------------------------------------------------
00355 // WriteAbs() Writes from the specified location, but does
00356 // not change the current stream position.
00357 //
00358 // WriteAbs() is mainly for use in substreams, and may not be
00359 // available from all stream types.  If you're not implementing
00360 // it, then please return an error from your derived class.
00361 //
00362 // \param buffer - target buffer for Write
00363 // \param length - length of data to write        
00364 // \param position - position within stream to read.
00365 //  \return CATResult - CAT_SUCCESS on success.
00366 //---------------------------------------------------------------------------
00367 CATResult CATStreamSub::WriteAbs(const void *buffer, CATUInt32 length, CATInt64 position)
00368 {
00369    CATResult result = CAT_SUCCESS;
00370    CATInt64 orgPos = 0;
00371 
00372    if (CATFAILED(result = this->GetPosition(orgPos)))
00373    {
00374       return result;
00375    }
00376    
00377    // On errors, at least try to restore the old position.
00378    if (CATFAILED(result = this->SeekAbsolute(position)))
00379    {
00380       this->SeekAbsolute(orgPos);
00381       return result;
00382    }
00383 
00384    if (CATFAILED(result = this->Write(buffer,length)))
00385    {
00386       this->SeekAbsolute(orgPos);
00387       return result;
00388    }
00389 
00390    return this->SeekAbsolute(orgPos);
00391 }
00392 

Generated on Mon Feb 11 04:09:48 2008 for Game Accessibility Suite by doxygen 1.5.4