2017-01-16 11:42:50 -05:00
# include "STDInclude.hpp"
namespace Utils
{
std : : string Stream : : Reader : : readString ( )
{
std : : string str ;
while ( char byte = this - > readByte ( ) )
{
2017-04-16 08:29:35 -04:00
str . push_back ( byte ) ;
2017-01-16 11:42:50 -05:00
}
return str ;
}
const char * Stream : : Reader : : readCString ( )
{
return this - > allocator - > duplicateString ( this - > readString ( ) ) ;
}
char Stream : : Reader : : readByte ( )
{
if ( ( this - > position + 1 ) < = this - > buffer . size ( ) )
{
return this - > buffer [ this - > position + + ] ;
}
2017-03-16 15:40:32 -04:00
throw std : : runtime_error ( " Reading past the buffer " ) ;
2017-01-16 11:42:50 -05:00
}
void * Stream : : Reader : : read ( size_t size , size_t count )
{
size_t bytes = size * count ;
if ( ( this - > position + bytes ) < = this - > buffer . size ( ) )
{
void * _buffer = this - > allocator - > allocate ( bytes ) ;
std : : memcpy ( _buffer , this - > buffer . data ( ) + this - > position , bytes ) ;
this - > position + = bytes ;
return _buffer ;
}
2017-03-16 15:40:32 -04:00
throw std : : runtime_error ( " Reading past the buffer " ) ;
2017-01-16 11:42:50 -05:00
}
bool Stream : : Reader : : end ( )
{
return ( this - > buffer . size ( ) = = this - > position ) ;
}
void Stream : : Reader : : seek ( unsigned int _position )
{
if ( this - > buffer . size ( ) > = _position )
{
this - > position = _position ;
}
}
2017-04-15 10:48:43 -04:00
void Stream : : Reader : : seekRelative ( unsigned int _position )
{
return this - > seek ( _position + this - > position ) ;
}
2016-12-25 09:17:31 -05:00
void * Stream : : Reader : : readPointer ( )
{
void * pointer = this - > read < void * > ( ) ;
if ( ! this - > hasPointer ( pointer ) )
{
2017-01-20 16:41:03 -05:00
this - > pointerMap [ pointer ] = nullptr ;
2016-12-25 09:17:31 -05:00
}
return pointer ;
}
2017-01-16 11:42:50 -05:00
void Stream : : Reader : : mapPointer ( void * oldPointer , void * newPointer )
{
if ( this - > hasPointer ( oldPointer ) )
{
this - > pointerMap [ oldPointer ] = newPointer ;
}
}
2016-12-25 09:17:31 -05:00
bool Stream : : Reader : : hasPointer ( void * pointer )
{
return this - > pointerMap . find ( pointer ) ! = this - > pointerMap . end ( ) ;
2017-01-16 11:42:50 -05:00
}
2017-04-18 13:28:00 -04:00
Stream : : Stream ( ) : ptrAssertion ( false ) , criticalSectionState ( 0 )
2017-01-16 11:42:50 -05:00
{
memset ( this - > blockSize , 0 , sizeof ( this - > blockSize ) ) ;
# ifdef WRITE_LOGS
this - > structLevel = 0 ;
Utils : : IO : : WriteFile ( " userraw/logs/zb_writes.log " , " " , false ) ;
# endif
}
Stream : : Stream ( size_t size ) : Stream ( )
{
this - > buffer . reserve ( size ) ;
}
Stream : : ~ Stream ( )
{
this - > buffer . clear ( ) ;
if ( this - > criticalSectionState ! = 0 )
{
2017-01-20 16:41:03 -05:00
MessageBoxA ( nullptr , Utils : : String : : VA ( " Invalid critical section state '%i' for stream destruction! " , this - > criticalSectionState ) , " WARNING " , MB_ICONEXCLAMATION ) ;
2017-01-16 11:42:50 -05:00
}
} ;
size_t Stream : : length ( )
{
return this - > buffer . length ( ) ;
}
size_t Stream : : capacity ( )
{
return this - > buffer . capacity ( ) ;
}
2017-04-18 13:28:00 -04:00
void Stream : : assertPointer ( const void * pointer , size_t length )
{
if ( ! this - > ptrAssertion ) return ;
for ( auto & entry : this - > ptrList )
{
unsigned int ePtr = reinterpret_cast < unsigned int > ( entry . first ) ;
unsigned int tPtr = reinterpret_cast < unsigned int > ( pointer ) ;
if ( Utils : : HasIntercection ( ePtr , entry . second , tPtr , length ) )
{
MessageBoxA ( nullptr , " Duplicate data written! " , " ERROR " , MB_ICONERROR ) ;
__debugbreak ( ) ;
}
}
this - > ptrList . push_back ( { pointer , length } ) ;
}
2017-01-16 11:42:50 -05:00
char * Stream : : save ( const void * _str , size_t size , size_t count )
{
return this - > save ( this - > getCurrentBlock ( ) , _str , size , count ) ;
}
char * Stream : : save ( Game : : XFILE_BLOCK_TYPES stream , const void * _str , size_t size , size_t count )
{
// Only those seem to actually write data.
// everything else is allocated at runtime but XFILE_BLOCK_RUNTIME is the only one that actually allocates anything
// clearly half of this stuff is unused
if ( stream = = Game : : XFILE_BLOCK_RUNTIME )
{
this - > increaseBlockSize ( stream , size * count ) ;
return this - > at ( ) ;
}
auto data = this - > data ( ) ;
if ( this - > isCriticalSection ( ) & & this - > length ( ) + ( size * count ) > this - > capacity ( ) )
{
2017-01-20 16:41:03 -05:00
MessageBoxA ( nullptr , Utils : : String : : 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 ) , this - > capacity ( ) ) , " ERROR " , MB_ICONERROR ) ;
2017-01-16 11:42:50 -05:00
__debugbreak ( ) ;
}
this - > buffer . append ( static_cast < const char * > ( _str ) , size * count ) ;
if ( this - > data ( ) ! = data & & this - > isCriticalSection ( ) )
{
2017-01-20 16:41:03 -05:00
MessageBoxA ( nullptr , " Stream reallocation during critical operations not permitted! \n Please increase the initial memory size or reallocate memory during non-critical sections! " , " ERROR " , MB_ICONERROR ) ;
2017-01-16 11:42:50 -05:00
__debugbreak ( ) ;
}
this - > increaseBlockSize ( stream , size * count ) ;
2017-04-18 13:28:00 -04:00
this - > assertPointer ( _str , size * count ) ;
2017-01-16 11:42:50 -05:00
return this - > at ( ) - ( size * count ) ;
}
char * Stream : : save ( Game : : XFILE_BLOCK_TYPES stream , int value , size_t count )
{
auto ret = this - > length ( ) ;
for ( size_t i = 0 ; i < count ; + + i )
{
this - > save ( stream , & value , 4 , 1 ) ;
}
return this - > data ( ) + ret ;
}
char * Stream : : saveString ( std : : string string )
{
return this - > saveString ( string . data ( ) /*, string.size()*/ ) ;
}
char * Stream : : saveString ( const char * string )
{
return this - > saveString ( string , strlen ( string ) ) ;
}
char * Stream : : saveString ( const char * string , size_t len )
{
auto ret = this - > length ( ) ;
if ( string )
{
this - > save ( string , len ) ;
}
this - > saveNull ( ) ;
return this - > data ( ) + ret ;
}
char * Stream : : saveText ( std : : string string )
{
return this - > save ( string . data ( ) , string . length ( ) ) ;
}
char * Stream : : saveByte ( unsigned char byte , size_t count )
{
auto ret = this - > length ( ) ;
for ( size_t i = 0 ; i < count ; + + i )
{
this - > save ( & byte , 1 ) ;
}
return this - > data ( ) + ret ;
}
char * Stream : : saveNull ( size_t count )
{
return this - > saveByte ( 0 , count ) ;
}
char * Stream : : saveMax ( size_t count )
{
return this - > saveByte ( static_cast < unsigned char > ( - 1 ) , count ) ;
}
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 = this - > getCurrentBlock ( ) ;
this - > blockSize [ stream ] = ~ size & ( this - > getBlockSize ( stream ) + size ) ;
}
bool Stream : : pushBlock ( Game : : XFILE_BLOCK_TYPES stream )
{
this - > streamStack . push_back ( stream ) ;
return this - > isValidBlock ( stream ) ;
}
bool Stream : : popBlock ( )
{
if ( ! this - > streamStack . empty ( ) )
{
this - > streamStack . pop_back ( ) ;
return true ;
}
return false ;
}
2017-03-20 16:07:55 -04:00
bool Stream : : hasBlock ( )
{
return ! this - > streamStack . empty ( ) ;
}
2017-01-16 11:42:50 -05:00
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 ( this - > isValidBlock ( stream ) )
{
this - > blockSize [ stream ] + = size ;
}
# ifdef WRITE_LOGS
std : : string data = fmt : : sprintf ( " %*s%d \n " , this - > structLevel , " " , size ) ;
if ( stream = = Game : : XFILE_BLOCK_RUNTIME ) data = fmt : : sprintf ( " %*s(%d) \n " , this - > structLevel , " " , size ) ;
Utils : : IO : : WriteFile ( " userraw/logs/zb_writes.log " , data , true ) ;
# endif
}
void Stream : : increaseBlockSize ( unsigned int size )
{
return this - > increaseBlockSize ( this - > getCurrentBlock ( ) , size ) ;
}
Game : : XFILE_BLOCK_TYPES Stream : : getCurrentBlock ( )
{
if ( ! this - > streamStack . empty ( ) )
{
return this - > streamStack . back ( ) ;
}
return Game : : XFILE_BLOCK_INVALID ;
}
char * Stream : : at ( )
{
return reinterpret_cast < char * > ( this - > data ( ) + this - > length ( ) ) ;
}
char * Stream : : data ( )
{
return const_cast < char * > ( this - > buffer . data ( ) ) ;
}
unsigned int Stream : : getBlockSize ( Game : : XFILE_BLOCK_TYPES stream )
{
if ( this - > isValidBlock ( stream ) )
{
return this - > blockSize [ stream ] ;
}
return 0 ;
}
DWORD Stream : : getPackedOffset ( )
{
Game : : XFILE_BLOCK_TYPES block = this - > getCurrentBlock ( ) ;
Stream : : Offset offset ;
offset . block = block ;
offset . offset = this - > getBlockSize ( block ) ;
return offset . getPackedOffset ( ) ;
}
void Stream : : toBuffer ( std : : string & outBuffer )
{
outBuffer . clear ( ) ;
outBuffer . append ( this - > data ( ) , this - > length ( ) ) ;
}
std : : string Stream : : toBuffer ( )
{
std : : string _buffer ;
this - > toBuffer ( _buffer ) ;
return _buffer ;
}
void Stream : : enterCriticalSection ( )
{
+ + this - > criticalSectionState ;
}
void Stream : : leaveCriticalSection ( )
{
- - this - > criticalSectionState ;
}
bool Stream : : isCriticalSection ( )
{
if ( this - > criticalSectionState < 0 )
{
2017-01-20 16:41:03 -05:00
MessageBoxA ( nullptr , " CriticalSectionState in stream has been overrun! " , " ERROR " , MB_ICONERROR ) ;
2017-01-16 11:42:50 -05:00
__debugbreak ( ) ;
}
return ( this - > criticalSectionState ! = 0 ) ;
}
# ifdef WRITE_LOGS
void Stream : : enterStruct ( const char * structName )
{
if ( this - > structLevel > = 0 )
{
Utils : : IO : : WriteFile ( " userraw/logs/zb_writes.log " , fmt : : sprintf ( " %*s%s \n " , this - > structLevel + + , " " , structName ) , true ) ;
}
}
void Stream : : leaveStruct ( )
{
if ( - - this - > structLevel < 0 )
{
Components : : Logger : : Print ( " Stream::leaveStruct underflow! All following writes will not be logged! \n " ) ;
return ;
}
Utils : : IO : : WriteFile ( " userraw/logs/zb_writes.log " , fmt : : sprintf ( " %*s----- \n " , this - > structLevel , " " ) , true ) ;
}
# endif
}