2016-01-05 19:23:43 -05:00
# include "STDInclude.hpp"
namespace Utils
{
2016-06-05 15:55:38 -04:00
std : : string Stream : : Reader : : ReadString ( )
{
std : : string str ;
while ( char byte = Stream : : Reader : : ReadByte ( ) )
{
str . append ( & byte , 1 ) ;
}
return str ;
}
const char * Stream : : Reader : : ReadCString ( )
{
return Stream : : Reader : : Allocator - > DuplicateString ( Stream : : Reader : : ReadString ( ) ) ;
}
char Stream : : Reader : : ReadByte ( )
{
if ( ( Stream : : Reader : : Position + 1 ) < = Stream : : Reader : : Buffer . size ( ) )
{
return Stream : : Reader : : Buffer [ Stream : : Reader : : Position + + ] ;
}
return 0 ;
}
void * Stream : : Reader : : Read ( size_t size , size_t count )
{
size_t bytes = size * count ;
if ( ( Stream : : Reader : : Position + bytes ) < = Stream : : Reader : : Buffer . size ( ) )
{
void * buffer = Stream : : Reader : : Allocator - > Allocate ( bytes ) ;
std : : memcpy ( buffer , Stream : : Reader : : Buffer . data ( ) + Stream : : Reader : : Position , bytes ) ;
Stream : : Reader : : Position + = bytes ;
return buffer ;
}
return nullptr ;
}
bool Stream : : Reader : : End ( )
{
return ( Stream : : Reader : : Buffer . size ( ) = = Stream : : Reader : : Position ) ;
}
void Stream : : Reader : : Seek ( unsigned int position )
{
if ( Stream : : Reader : : Buffer . size ( ) > = position )
{
Stream : : Reader : : Position = position ;
}
}
2016-01-05 19:23:43 -05:00
Stream : : Stream ( ) : CriticalSectionState ( 0 )
{
memset ( Stream : : BlockSize , 0 , sizeof ( Stream : : BlockSize ) ) ;
}
Stream : : Stream ( size_t size ) : Stream ( )
{
Stream : : Buffer . reserve ( size ) ;
}
Stream : : ~ Stream ( )
{
Stream : : Buffer . clear ( ) ;
if ( Stream : : CriticalSectionState ! = 0 )
{
MessageBoxA ( 0 , Utils : : VA ( " Invalid critical section state '%i' for stream destruction! " , Stream : : CriticalSectionState ) , " WARNING " , MB_ICONEXCLAMATION ) ;
}
} ;
size_t Stream : : Length ( )
{
return Stream : : Buffer . length ( ) ;
}
size_t Stream : : Capacity ( )
{
return Stream : : Buffer . capacity ( ) ;
}
2016-01-24 06:19:34 -05:00
char * Stream : : Save ( const void * _str , size_t size , size_t count )
2016-01-05 19:23:43 -05:00
{
return Stream : : Save ( Stream : : GetCurrentBlock ( ) , _str , size , count ) ;
}
char * Stream : : Save ( Game : : XFILE_BLOCK_TYPES stream , const void * _str , size_t size , size_t count )
{
//if (stream == XFILE_BLOCK_TEMP || stream == XFILE_BLOCK_VIRTUAL || stream == XFILE_BLOCK_PHYSICAL) // Only those seem to actually write data.
// As I'm not sure though, I'll still write the data
2016-05-16 11:17:25 -04:00
// Use IncreaseBlockSize to fill virtual streams
2016-01-05 19:23:43 -05:00
auto data = Stream : : Data ( ) ;
if ( Stream : : IsCriticalSection ( ) & & Stream : : Length ( ) + ( size * count ) > Stream : : Capacity ( ) )
{
MessageBoxA ( 0 , Utils : : VA ( " Potential stream reallocation during critical operation detected! Writing data of the length 0x%X exceeds the allocated stream size of 0x%X \n " , ( size * count ) , Stream : : Capacity ( ) ) , " ERROR " , MB_ICONERROR ) ;
__debugbreak ( ) ;
}
2016-01-24 06:19:34 -05:00
Stream : : Buffer . append ( static_cast < const char * > ( _str ) , size * count ) ;
2016-01-05 19:23:43 -05:00
if ( Stream : : Data ( ) ! = data & & Stream : : IsCriticalSection ( ) )
{
MessageBoxA ( 0 , " Stream reallocation during critical operations not permitted! \n Please increase the initial memory size or reallocate memory during non-critical sections! " , " ERROR " , MB_ICONERROR ) ;
__debugbreak ( ) ;
}
2016-05-16 11:17:25 -04:00
Stream : : IncreaseBlockSize ( stream , size * count ) ;
2016-01-05 19:23:43 -05:00
return Stream : : At ( ) - ( size * count ) ;
}
char * Stream : : Save ( Game : : XFILE_BLOCK_TYPES stream , int value , size_t count )
{
auto ret = Stream : : Length ( ) ;
2016-01-24 13:58:13 -05:00
for ( size_t i = 0 ; i < count ; + + i )
2016-01-05 19:23:43 -05:00
{
Stream : : Save ( stream , & value , 4 , 1 ) ;
}
return Stream : : Data ( ) + ret ;
}
char * Stream : : SaveString ( std : : string string )
{
return Stream : : SaveString ( string . data ( ) /*, string.size()*/ ) ;
}
char * Stream : : SaveString ( const char * string )
{
return Stream : : SaveString ( string , strlen ( string ) ) ;
}
char * Stream : : SaveString ( const char * string , size_t len )
{
auto ret = Stream : : Length ( ) ;
if ( string )
{
Stream : : Save ( string , len ) ;
}
Stream : : SaveNull ( ) ;
return Stream : : Data ( ) + ret ;
}
char * Stream : : SaveText ( std : : string string )
{
return Stream : : Save ( string . data ( ) , string . length ( ) ) ;
}
char * Stream : : SaveByte ( unsigned char byte , size_t count )
{
auto ret = Stream : : Length ( ) ;
2016-01-24 13:58:13 -05:00
for ( size_t i = 0 ; i < count ; + + i )
2016-01-05 19:23:43 -05:00
{
Stream : : Save ( & byte , 1 ) ;
}
return Stream : : Data ( ) + ret ;
}
char * Stream : : SaveNull ( size_t count )
{
return Stream : : SaveByte ( 0 , count ) ;
}
char * Stream : : SaveMax ( size_t count )
{
2016-01-24 06:19:34 -05:00
return Stream : : SaveByte ( static_cast < unsigned char > ( - 1 ) , count ) ;
2016-01-05 19:23:43 -05:00
}
void Stream : : Align ( Stream : : Alignment align )
{
uint32_t size = 2 < < align ;
// Not power of 2!
if ( ! size | | ( size & ( size - 1 ) ) ) return ;
- - size ;
Game : : XFILE_BLOCK_TYPES stream = Stream : : GetCurrentBlock ( ) ;
Stream : : BlockSize [ stream ] = ~ size & ( Stream : : GetBlockSize ( stream ) + size ) ;
}
bool Stream : : PushBlock ( Game : : XFILE_BLOCK_TYPES stream )
{
Stream : : StreamStack . push_back ( stream ) ;
return Stream : : IsValidBlock ( stream ) ;
}
bool Stream : : PopBlock ( )
{
2016-02-12 09:06:06 -05:00
if ( ! Stream : : StreamStack . empty ( ) )
2016-01-05 19:23:43 -05:00
{
Stream : : StreamStack . pop_back ( ) ;
return true ;
}
return false ;
}
bool Stream : : IsValidBlock ( Game : : XFILE_BLOCK_TYPES stream )
{
return ( stream < Game : : MAX_XFILE_COUNT & & stream > = Game : : XFILE_BLOCK_TEMP ) ;
}
void Stream : : IncreaseBlockSize ( Game : : XFILE_BLOCK_TYPES stream , unsigned int size )
{
if ( Stream : : IsValidBlock ( stream ) )
{
Stream : : BlockSize [ stream ] + = size ;
}
}
void Stream : : IncreaseBlockSize ( unsigned int size )
{
return IncreaseBlockSize ( Stream : : GetCurrentBlock ( ) , size ) ;
}
Game : : XFILE_BLOCK_TYPES Stream : : GetCurrentBlock ( )
{
2016-02-12 09:06:06 -05:00
if ( ! Stream : : StreamStack . empty ( ) )
2016-01-05 19:23:43 -05:00
{
2016-05-16 11:17:25 -04:00
return Stream : : StreamStack . back ( ) ;
2016-01-05 19:23:43 -05:00
}
return Game : : XFILE_BLOCK_INVALID ;
}
char * Stream : : At ( )
{
2016-01-24 06:19:34 -05:00
return reinterpret_cast < char * > ( Stream : : Data ( ) + Stream : : Length ( ) ) ;
2016-01-05 19:23:43 -05:00
}
char * Stream : : Data ( )
{
2016-01-24 06:19:34 -05:00
return const_cast < char * > ( Stream : : Buffer . data ( ) ) ;
2016-01-05 19:23:43 -05:00
}
unsigned int Stream : : GetBlockSize ( Game : : XFILE_BLOCK_TYPES stream )
{
if ( Stream : : IsValidBlock ( stream ) )
{
return Stream : : BlockSize [ stream ] ;
}
return 0 ;
}
DWORD Stream : : GetPackedOffset ( )
{
Game : : XFILE_BLOCK_TYPES block = Stream : : GetCurrentBlock ( ) ;
Stream : : Offset offset ;
offset . block = block ;
offset . offset = Stream : : GetBlockSize ( block ) ;
return offset . GetPackedOffset ( ) ;
}
void Stream : : ToBuffer ( std : : string & outBuffer )
{
outBuffer . clear ( ) ;
outBuffer . append ( Stream : : Data ( ) , Stream : : Length ( ) ) ;
}
std : : string Stream : : ToBuffer ( )
{
std : : string buffer ;
Stream : : ToBuffer ( buffer ) ;
return buffer ;
}
void Stream : : EnterCriticalSection ( )
{
+ + Stream : : CriticalSectionState ;
}
void Stream : : LeaveCriticalSection ( )
{
- - Stream : : CriticalSectionState ;
}
bool Stream : : IsCriticalSection ( )
{
if ( Stream : : CriticalSectionState < 0 )
{
MessageBoxA ( 0 , " CriticalSectionState in stream has been overrun! " , " ERROR " , MB_ICONERROR ) ;
__debugbreak ( ) ;
}
return ( Stream : : CriticalSectionState ! = 0 ) ;
}
}