Spinning Topp Logo BlackTopp Studios
inc
memorystream.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _resourcememorystream_cpp
41 #define _resourcememorystream_cpp
42 
43 #include "Resource/memorystream.h"
44 #include "stringtool.h"
45 #include "exception.h"
46 
47 #include <cstring>
48 #include <cassert>
49 #include <algorithm>
50 
51 namespace Mezzanine
52 {
53  namespace Resource
54  {
55  ///////////////////////////////////////////////////////////////////////////////
56  // MemoryStreamBuffer Methods
57 
59  BufferStart(NULL),
60  /*BufferReadPos(NULL),
61  BufferWritePos(NULL),// */
62  BufferEnd(NULL),
63  FreeBuffer(true)
64  { }
65 
67  { this->DestroyBuffer(); }
68 
69  std::streampos MemoryStreamBuffer::CheckStreamPosition(const std::streampos Position)
70  {
71  std::streampos BufferSize = this->BufferEnd - this->BufferStart;
72  if( Position < 0 ) {
73  return 0;
74  }
75  if( Position > BufferSize ) {
76  return BufferSize;
77  }
78  return Position;
79  }
80 
81  std::streamoff MemoryStreamBuffer::CheckStreamOffset(const std::streamoff CursorOffset, const std::streamoff Adjust)
82  {
83  std::streampos BufferSize = this->BufferEnd - this->BufferStart;
84  if( CursorOffset + Adjust < 0 ) {
85  return -CursorOffset;
86  }
87  if( CursorOffset + Adjust > BufferSize ) {
88  return BufferSize - CursorOffset;
89  }
90  return Adjust;
91  }
92 
93  std::streampos MemoryStreamBuffer::GetReadPosition() const
94  { return static_cast<std::streampos>( this->gptr() - this->eback() ); }
95 
96  std::streampos MemoryStreamBuffer::GetWritePosition() const
97  { return static_cast<std::streampos>( this->pptr() - this->pbase() ); }
98 
99  ///////////////////////////////////////////////////////////////////////////////
100  // Locales
101 
102  void MemoryStreamBuffer::imbue(const std::locale& loc)
103  { }
104 
105  ///////////////////////////////////////////////////////////////////////////////
106  // Buffer Management and Positioning
107 
108  std::streambuf* MemoryStreamBuffer::setbuf(char* s, std::streamsize n)
109  {
110  if( s != NULL && n > 0 ) {
111  this->DestroyBuffer();
112 
113  this->BufferStart = s;
114  this->BufferEnd = this->BufferStart + n;
115  /*this->BufferReadPos = this->BufferStart;
116  this->BufferWritePos = this->BufferStart;// */
117  this->setg(this->BufferStart,this->BufferStart,this->BufferEnd);
118  this->setp(this->BufferStart,this->BufferEnd);// */
119  return this;
120  }
121  return NULL;
122  }
123 
124  std::streampos MemoryStreamBuffer::seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which)
125  {
126  std::streampos BufferSize = this->BufferEnd - this->BufferStart;
127  // Read
128  if( which & std::ios_base::in ) {
129  std::streampos ReadPosition = this->GetReadPosition();
130  switch( way )
131  {
132  case std::ios_base::beg: this->gbump( this->CheckStreamPosition( off ) - ReadPosition ); break;
133  case std::ios_base::end: this->gbump( this->CheckStreamPosition( BufferSize + off ) - ReadPosition ); break;
134  case std::ios_base::cur:
135  default: this->gbump( this->CheckStreamOffset(ReadPosition,off) ); break;
136  }
137  }
138  // Write
139  if( which & std::ios_base::out ) {
140  std::streampos WritePosition = this->GetWritePosition();
141  switch( way )
142  {
143  case std::ios_base::beg: this->pbump( this->CheckStreamPosition( off ) - WritePosition ); break;
144  case std::ios_base::end: this->pbump( this->CheckStreamPosition( BufferSize + off ) - WritePosition ); break;
145  case std::ios_base::cur:
146  default: this->pbump( this->CheckStreamOffset(WritePosition,off) ); break;
147  }
148  }
149  return ( which & std::ios_base::in ? this->GetReadPosition() : this->GetWritePosition() );
150  }
151 
152  std::streampos MemoryStreamBuffer::seekpos(std::streampos sp, std::ios_base::openmode which)
153  {
154  // Read
155  if( which & std::ios_base::in ) {
156  std::streampos ReadPosition = this->GetReadPosition();
157  this->gbump( this->CheckStreamPosition( sp ) - ReadPosition );
158  }
159  // Write
160  if( which & std::ios_base::out ) {
161  std::streampos WritePosition = this->GetWritePosition();
162  this->pbump( this->CheckStreamPosition( sp ) - WritePosition );
163  }
164  return ( which & std::ios_base::in ? this->GetReadPosition() : this->GetWritePosition() );
165  }
166 
168  { return 0; }
169 
170  ///////////////////////////////////////////////////////////////////////////////
171  // Input Functions (get/read)
172 
174  {
175  if( this->BufferStart != NULL ) {
176  assert( std::less_equal<Char8*>()(this->gptr(),this->egptr()) );
177  //return this->BufferEnd - this->BufferReadPos;
178  return this->egptr() - this->gptr();
179  }
180  return 0;
181  }
182 
183  std::streamsize MemoryStreamBuffer::xsgetn(char* s, std::streamsize n)
184  {
185  if( this->OpenMode & std::ios_base::in ) {
186  return std::streambuf::xsgetn(s,n);
187  }
188  return 0;
189  }
190 
192  {
193  if( this->gptr() == this->egptr() ) {
194  //if( this->BufferReadPos == this->BufferEnd ) {
195  return traits_type::eof();
196  }
197 
198  return traits_type::to_int_type( *(this->egptr()) );
199  }
200 
202  {
203  return std::streambuf::uflow();
204  }
205 
207  {
208  //if( this->BufferReadPos == this->BufferStart || ( c != traits_type::eof() && c != ( this->BufferReadPos - 1 ) ) ) {
209  if( this->gptr() == this->eback() || ( c != traits_type::eof() && c != *( this->gptr() - 1 ) ) ) {
210  return traits_type::eof();
211  }
212 
213  //return traits_type::to_int_type( *(--this->BufferReadPos) );
214  this->gbump(-1);
215  return this->sgetc();
216  }
217 
218  ///////////////////////////////////////////////////////////////////////////////
219  // Output Functions (put/write)
220 
221  std::streamsize MemoryStreamBuffer::xsputn(const char* s, std::streamsize n)
222  {
223  if( this->OpenMode & std::ios_base::out ) {
224  return std::streambuf::xsputn(s,n);
225  }
226  return 0;
227  }
228 
230  {
231  //if( this->pptr() == this->epptr() )
232  return traits_type::eof();
233  }
234 
235  ///////////////////////////////////////////////////////////////////////////////
236  // Utility
237 
239  {
240  if( Size > 0 ) {
241  this->setbuf( new Char8[Size], Size );
242  this->FreeBuffer = true;
243  }
244  }
245 
246  void MemoryStreamBuffer::SetBuffer(char* Buffer, const Whole BufferSize, const Boole FreeBuf)
247  {
248  if( this->setbuf(Buffer,BufferSize) ) {
249  this->ConfigureBuffer(0);
250  this->FreeBuffer = FreeBuf;
251  }
252  }
253 
254  void MemoryStreamBuffer::CopyBuffer(const char* Buffer, const Whole BufferSize)
255  {
256  char* NewBuf = new char[BufferSize];
257  memcpy(NewBuf,Buffer,BufferSize);
258  this->SetBuffer(NewBuf,BufferSize,true);
259  }
260 
262  {
263  // Gonna use the std api for consistency, but could return raw members as well
264  return this->eback();
265  }
266 
268  {
269  // Gonna use the std api for consistency, but could return raw members as well
270  return this->egptr();
271  }
272 
273  std::streamsize MemoryStreamBuffer::GetBufferSize() const
274  {
275  return this->egptr() - this->eback();
276  }
277 
278  void MemoryStreamBuffer::ConfigureBuffer(const std::streampos Pos, std::ios_base::openmode Mode)
279  {
280  if( this->BufferStart != NULL ) {
281  if( Mode & std::ios_base::in ) {
282  //this->BufferReadPos = this->BufferStart + Pos;
283  this->setg(this->BufferStart,this->BufferStart + Pos,this->BufferEnd);
284  }
285  if( Mode & std::ios_base::out ) {
286  //this->BufferWritePos = this->BufferStart + Pos;
287  this->setp(this->BufferStart,this->BufferEnd);
288  }
289  this->OpenMode = Mode;
290  this->seekpos(Pos,Mode);
291  }
292  }
293 
295  {
296  if( this->BufferStart != NULL && this->FreeBuffer ) {
297  delete[] this->BufferStart;
298  this->BufferStart = NULL;
299  /*this->BufferReadPos = NULL;
300  this->BufferWritePos = NULL;// */
301  this->BufferEnd = NULL;
302  }
303  }
304 
306  { this->FreeBuffer = FreeBuf; }
307 
309  { return this->FreeBuffer; }
310 
311  ///////////////////////////////////////////////////////////////////////////////
312  // MemoryStream Methods
313 
315  IOStream(&this->Buffer)
316  { /*this->init(&this->Buffer);*/ }
317 
318  MemoryStream::MemoryStream(const Whole BufferSize, const Whole Mode) :
319  IOStream(&this->Buffer)
320  { /*this->init(&this->Buffer);*/ this->CreateBuffer(BufferSize,Mode); }
321 
322  MemoryStream::MemoryStream(const void* Buffer, const Whole BufferSize, const Whole Mode) :
323  IOStream(&this->Buffer)
324  { /*this->init(&this->Buffer);*/ this->CopyBuffer(Buffer,BufferSize,Mode); }
325 
326  MemoryStream::MemoryStream(void* Buffer, const Whole BufferSize, const Boole FreeAfter, const Whole Mode) :
327  IOStream(&this->Buffer)
328  { /*this->init(&this->Buffer);*/ this->SetBuffer(Buffer,BufferSize,FreeAfter,Mode); }
329 
331  { }
332 
333  ///////////////////////////////////////////////////////////////////////////////
334  // Utility
335 
336  void MemoryStream::CreateBuffer(const Whole Size, const Whole Mode)
337  { this->Buffer.CreateBuffer(Size); this->Buffer.ConfigureBuffer(0,static_cast<std::ios_base::openmode>(Mode)); }
338 
339  void MemoryStream::SetBuffer(void* Buffer, const Whole BufferSize, const Boole FreeBuf, const Whole Mode)
340  { this->Buffer.SetBuffer(static_cast<char*>(Buffer),BufferSize,FreeBuf); this->Buffer.ConfigureBuffer(0,static_cast<std::ios_base::openmode>(Mode)); }
341 
342  void MemoryStream::CopyBuffer(const void* Buffer, const Whole BufferSize, const Whole Mode)
343  { this->Buffer.CopyBuffer(static_cast<const char*>(Buffer),BufferSize); this->Buffer.ConfigureBuffer(0,static_cast<std::ios_base::openmode>(Mode)); }
344 
346  { return this->Buffer.GetBufferStart(); }
347 
349  { return this->Buffer.GetBufferEnd(); }
350 
351  void MemoryStream::SetFreeBuffer(const Boole FreeBuf)
352  { this->Buffer.SetFreeBuffer(FreeBuf); }
353 
355  { return this->Buffer.GetFreeBuffer(); }
356 
357  ///////////////////////////////////////////////////////////////////////////////
358  // Stream Base Operations
359 
361  { return this->Buffer.GetBufferSize(); }
362  }//Resource
363 }//Mezzanine
364 
365 #endif
void CreateBuffer(const Whole Size, const Whole Mode=Resource::SF_Read|Resource::SF_Write)
Creates a new memory buffer to stream to/from.
std::streamoff CheckStreamOffset(const std::streamoff CursorOffset, const std::streamoff Adjust)
Verifies an offset in this stream is valid for a read or write cursor.
virtual int overflow(int c=traits_type::eof())
Writes a character at the current write position without advancing the write position.
Char8 * BufferStart
A pointer to the start of this memory buffer.
Definition: memorystream.h:61
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
virtual ~MemoryStream()
Class destructor.
virtual std::streampos seekpos(std::streampos sp, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out)
Moves the read and/or write pointers to the specified position in the stream.
void SetFreeBuffer(const Boole FreeBuf)
Sets if this should delete it's internal buffer when it is destroyed.
virtual std::streambuf * setbuf(char *s, std::streamsize n)
Sets the buffer to be streamed from.
Whole OpenMode
A bitfield describing the settings this buffer was opened with.
Definition: memorystream.h:73
Boole GetFreeBuffer() const
Gets if this should delete it's internal buffer when it is destroyed.
MemoryStream()
Blank constructor.
void CopyBuffer(const void *Buffer, const Whole BufferSize, const Whole Mode=Resource::SF_Read|Resource::SF_Write)
Copies a pre-existing buffer to this buffer for streaming.
void DestroyBuffer()
Convenience method for deleting the existing buffer being streamed.
Char8 * GetBufferStart() const
Gets the start of this buffer.
std::streampos GetReadPosition() const
Gets the current position of the read cursor.
Base class for streams that support both read and write operations.
Definition: datastream.h:263
This implements the exception hiearchy for Mezzanine.
virtual int pbackfail(int c=traits_type::eof())
Reverse the last character extraction operation by decrementing the read position and placing the spe...
void SetFreeBuffer(const Boole FreeBuf)
Sets if this should delete it's internal buffer when it is destroyed.
char Char8
A datatype to represent one character.
Definition: datatypes.h:169
std::streampos GetWritePosition() const
Gets the current position of the write cursor.
virtual ~MemoryStreamBuffer()
Class destructor.
void CopyBuffer(const char *Buffer, const Whole BufferSize)
Copies a pre-existing buffer to this buffer for streaming.
virtual std::streamsize showmanyc()
Gets the number of characters remaining that can be safely extracted from this buffer.
void ConfigureBuffer(const std::streampos Pos, std::ios_base::openmode Mode=std::ios_base::in|std::ios_base::out)
Sets the get and put pointers for the streambuffer and assigns the current position to the specified ...
Char8 * GetBufferEnd() const
Gets the end of this buffer.
virtual StreamSize GetSize() const
Boole GetFreeBuffer() const
Gets if this should delete it's internal buffer when it is destroyed.
Declaration of MemoryStream.
void SetBuffer(char *Buffer, const Whole BufferSize, const Boole FreeBuf)
Wraps an external buffer for streaming.
virtual int uflow()
Gets the value at the current read position and then increments the read position.
std::streampos CheckStreamPosition(const std::streampos Position)
Verifies a position in this stream is valid.
void SetBuffer(void *Buffer, const Whole BufferSize, const Boole FreeBuf, const Whole Mode=Resource::SF_Read|Resource::SF_Write)
Wraps an external buffer for streaming.
virtual int sync()
Syncs this stream buffer with it's source.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
virtual std::streamsize xsgetn(char *s, std::streamsize n)
Gets a number of characters starting at the read position and populates an array with them...
std::streamsize StreamSize
Convenience define for the stream size datatype.
Definition: datastream.h:61
std::streamsize GetBufferSize() const
Gets the size of the current buffer being streamed to/from.
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Writes a number of characters from a provided buffer to the stream.
Char8 * GetBufferEnd() const
Gets the end of this buffer.
virtual std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out)
Moves the read and/or write pointers in the stream.
Char8 * BufferEnd
A pointer to one passed the last element in the range of this buffer.
Definition: memorystream.h:70
MemoryStreamBuffer Buffer
The buffer object being streamed to/from.
Definition: memorystream.h:227
virtual void imbue(const std::locale &loc)
Notifies this class that a new locale is being imbued to this streambuf.
Char8 * GetBufferStart() const
Gets the start of this buffer.
void CreateBuffer(const Whole Size)
Convenience method for creating a new buffer to be used by this stream.
virtual int underflow()
Gets the value at the current read position without incrementing the read position.
Boole FreeBuffer
Stores whether or not the memory allocated will be free'd when this buffer is deleted.
Definition: memorystream.h:76