memStream.cpp
Engine/source/core/stream/memStream.cpp
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