memStream.cpp

Engine/source/core/stream/memStream.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "core/stream/memStream.h"
 26
 27
 28MemStream::MemStream( U32 growSize,
 29                      bool allowRead,
 30                      bool allowWrite )
 31   :  mGrowSize( growSize ),
 32      mBufferSize( 0 ),
 33      mStreamSize( 0 ),
 34      mBufferBase( NULL ),
 35      mInstCaps( 0 ),
 36      mCurrentPosition( 0 )
 37{
 38   AssertFatal( allowRead || allowWrite, "Either write or read must be allowed" );
 39
 40   if ( allowRead )
 41      mInstCaps |= Stream::StreamRead;
 42   if ( allowWrite )
 43      mInstCaps |= Stream::StreamWrite;
 44
 45   mOwnsMemory = true;
 46   setStatus( mGrowSize > 0 ? Ok : EOS );
 47}
 48
 49MemStream::MemStream( U32 bufferSize,
 50                      void *buffer,
 51                      bool allowRead,
 52                      bool allowWrite)
 53 : mGrowSize( 0 ),
 54   mBufferSize( bufferSize ),
 55   mStreamSize( bufferSize ),
 56   mBufferBase( buffer ),
 57   mInstCaps( 0 ),
 58   mOwnsMemory( false ),
 59   mCurrentPosition( 0 )
 60{
 61   AssertFatal( bufferSize > 0,  "Invalid buffer size");
 62   AssertFatal( allowRead || allowWrite, "Either write or read must be allowed");
 63
 64   if ( allowRead )
 65      mInstCaps |= Stream::StreamRead;
 66   if ( allowWrite )
 67      mInstCaps |= Stream::StreamWrite;
 68
 69   if ( !buffer )
 70   {
 71      mOwnsMemory = true;
 72      mBufferBase = dMalloc( mBufferSize );
 73   }
 74
 75   setStatus( Ok );
 76}
 77
 78MemStream::~MemStream()
 79{
 80   if ( mOwnsMemory )
 81      dFree( mBufferBase );
 82
 83   mBufferBase     = NULL;
 84   mCurrentPosition = 0;
 85
 86   setStatus( Closed );
 87}
 88
 89U32 MemStream::getStreamSize()
 90{
 91   AssertFatal( getStatus() != Closed, "Stream not open, size undefined" );
 92
 93   return mStreamSize;
 94}
 95
 96bool MemStream::hasCapability(const Capability in_cap) const
 97{
 98   // Closed streams can't do anything
 99   //
100   if (getStatus() == Closed)
101      return false;
102
103   U32 totalCaps = U32(Stream::StreamPosition) | mInstCaps;
104
105   return (U32(in_cap) & totalCaps) != 0;
106}
107
108U32 MemStream::getPosition() const
109{
110   AssertFatal(getStatus() != Closed, "Position of a closed stream is undefined");
111
112   return mCurrentPosition;
113}
114
115bool MemStream::setPosition(const U32 in_newPosition)
116{
117   AssertFatal(getStatus() != Closed, "SetPosition of a closed stream is not allowed");
118   AssertFatal(in_newPosition <= mStreamSize, "Invalid position");
119
120   mCurrentPosition = in_newPosition;
121   if (mCurrentPosition > mStreamSize) {
122      // Never gets here in debug version, this is for the release builds...
123      //
124      setStatus(UnknownError);
125      return false;
126   } else if (mCurrentPosition == mStreamSize) {
127      setStatus(EOS);
128   } else {
129      setStatus(Ok);
130   }
131
132   return true;
133}
134
135bool MemStream::_read(const U32 in_numBytes, void *out_pBuffer)
136{
137   AssertFatal(getStatus() != Closed, "Attempted read from a closed stream");
138
139   if (in_numBytes == 0)
140      return true;
141
142   AssertFatal(out_pBuffer != NULL, "Invalid output buffer");
143
144   if (hasCapability(StreamRead) == false) {
145      AssertWarn(false, "Reading is disallowed on this stream");
146      setStatus(IllegalCall);
147      return false;
148   }
149
150   bool success     = true;
151   U32  actualBytes = in_numBytes;
152   if ((mCurrentPosition + in_numBytes) > mStreamSize) {
153      success = false;
154      actualBytes = mStreamSize - mCurrentPosition;
155   }
156
157   // Obtain a current pointer, and do the copy
158   const void* pCurrent = (const void*)((const U8*)mBufferBase + mCurrentPosition);
159   dMemcpy(out_pBuffer, pCurrent, actualBytes);
160
161   // Advance the stream position
162   mCurrentPosition += actualBytes;
163
164   if (!success)
165      setStatus(EOS);
166   else
167      setStatus(Ok);
168
169   return success;
170}
171
172bool MemStream::_write(const U32 in_numBytes, const void *in_pBuffer)
173{
174   AssertFatal(getStatus() != Closed, "Attempted write to a closed stream");
175
176   if (in_numBytes == 0)
177      return true;
178
179   if (hasCapability(StreamWrite) == false) 
180   {
181      AssertWarn(0, "Writing is disallowed on this stream");
182      setStatus(IllegalCall);
183      return false;
184   }
185
186   bool success     = true;
187   U32  actualBytes = in_numBytes;
188   if ((mCurrentPosition + in_numBytes) > mBufferSize) 
189   {
190      if ( mGrowSize > 0 ) 
191      {
192         U32 growSize = (mCurrentPosition + in_numBytes) - mBufferSize;
193         mBufferSize += growSize + ( mGrowSize - ( growSize % mGrowSize ) );
194         mBufferBase = dRealloc( mBufferBase, mBufferSize );
195      } 
196      else
197      {
198         success = false;
199         actualBytes = mBufferSize - mCurrentPosition;
200      }
201   }
202
203   AssertFatal(in_pBuffer != NULL, "Invalid input buffer");
204
205   // Obtain a current pointer, and do the copy
206   void* pCurrent = (void*)((U8*)mBufferBase + mCurrentPosition);
207   dMemcpy(pCurrent, in_pBuffer, actualBytes);
208
209   // Advance the stream position
210   mCurrentPosition += actualBytes;
211   if (mCurrentPosition > mStreamSize)
212      mStreamSize = mCurrentPosition;
213
214   if (mCurrentPosition == mStreamSize)
215      setStatus(EOS);
216   else
217      setStatus(Ok);
218
219   return success;
220}
221
222void *MemStream::takeBuffer()
223{
224   void *buffer = mBufferBase;
225   
226   mBufferBase = NULL;
227   mBufferSize = 0;
228   mStreamSize = 0;
229   mCurrentPosition = 0;
230
231   setStatus(EOS);
232
233   return buffer;
234}
235