mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-27 08:14:34 +00:00
764792d8db
Tracy will now perform a number of checks when trying to read a dump file: 1. The file must have at least 4 bytes of data. 2. There should be a 4 byte header to indicate the file was saved by tracy. This is a breaking change in file format. 3. Old header-less files are still supported, but there's a new check for data validity. The first 4 bytes of file (as an uint32) must be less or equal to max LZ4 data packet size. This requires the first two bytes to be 00 00 or 00 01, which should catch most invalid files.
148 lines
3.6 KiB
C++
148 lines
3.6 KiB
C++
#ifndef __TRACYFILEREAD_HPP__
|
|
#define __TRACYFILEREAD_HPP__
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "TracyFileHeader.hpp"
|
|
#include "../common/tracy_lz4.hpp"
|
|
#include "../common/TracyForceInline.hpp"
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
struct NotTracyDump : public std::exception {};
|
|
|
|
class FileRead
|
|
{
|
|
public:
|
|
static FileRead* Open( const char* fn )
|
|
{
|
|
auto f = fopen( fn, "rb" );
|
|
return f ? new FileRead( f ) : nullptr;
|
|
}
|
|
|
|
~FileRead()
|
|
{
|
|
fclose( m_file );
|
|
LZ4_freeStreamDecode( m_stream );
|
|
}
|
|
|
|
tracy_force_inline void Read( void* ptr, size_t size )
|
|
{
|
|
if( size <= BufSize - m_offset )
|
|
{
|
|
ReadSmall( ptr, size );
|
|
}
|
|
else
|
|
{
|
|
ReadBig( ptr, size );
|
|
}
|
|
}
|
|
|
|
void Skip( size_t size )
|
|
{
|
|
if( size <= BufSize - m_offset )
|
|
{
|
|
m_offset += size;
|
|
}
|
|
else
|
|
{
|
|
char m_lz4buf[LZ4Size];
|
|
while( size > 0 )
|
|
{
|
|
if( m_offset == BufSize )
|
|
{
|
|
m_active = 1 - m_active;
|
|
m_offset = 0;
|
|
uint32_t sz;
|
|
fread( &sz, 1, sizeof( sz ), m_file );
|
|
fread( m_lz4buf, 1, sz, m_file );
|
|
m_lastBlock = LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize );
|
|
}
|
|
|
|
const auto sz = std::min( size, BufSize - m_offset );
|
|
m_offset += sz;
|
|
size -= sz;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool IsEOF()
|
|
{
|
|
if( m_lastBlock != BufSize && m_offset == m_lastBlock ) return true;
|
|
if( m_offset == BufSize )
|
|
{
|
|
if( fseek( m_file, 1, SEEK_CUR ) != 0 ) return true;
|
|
fseek( m_file, -1, SEEK_CUR );
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
FileRead( FILE* f )
|
|
: m_stream( LZ4_createStreamDecode() )
|
|
, m_file( f )
|
|
, m_offset( BufSize )
|
|
, m_active( 1 )
|
|
, m_lastBlock( 0 )
|
|
{
|
|
char hdr[4];
|
|
if( fread( hdr, 1, sizeof( hdr ), m_file ) != sizeof( hdr ) ) throw NotTracyDump();
|
|
if( memcmp( hdr, Lz4Header, sizeof( hdr ) ) != 0 )
|
|
{
|
|
fseek( m_file, 0, SEEK_SET );
|
|
uint32_t sz;
|
|
static_assert( sizeof( sz ) == sizeof( hdr ), "Size mismatch" );
|
|
memcpy( &sz, hdr, sizeof( sz ) );
|
|
if( sz > LZ4Size ) throw NotTracyDump();
|
|
}
|
|
}
|
|
|
|
tracy_force_inline void ReadSmall( void* ptr, size_t size )
|
|
{
|
|
memcpy( ptr, m_buf[m_active] + m_offset, size );
|
|
m_offset += size;
|
|
}
|
|
|
|
void ReadBig( void* ptr, size_t size )
|
|
{
|
|
char m_lz4buf[LZ4Size];
|
|
auto dst = (char*)ptr;
|
|
while( size > 0 )
|
|
{
|
|
if( m_offset == BufSize )
|
|
{
|
|
m_active = 1 - m_active;
|
|
m_offset = 0;
|
|
uint32_t sz;
|
|
fread( &sz, 1, sizeof( sz ), m_file );
|
|
fread( m_lz4buf, 1, sz, m_file );
|
|
m_lastBlock = LZ4_decompress_safe_continue( m_stream, m_lz4buf, m_buf[m_active], sz, BufSize );
|
|
}
|
|
|
|
const auto sz = std::min( size, BufSize - m_offset );
|
|
memcpy( dst, m_buf[m_active] + m_offset, sz );
|
|
m_offset += sz;
|
|
dst += sz;
|
|
size -= sz;
|
|
}
|
|
}
|
|
|
|
enum { BufSize = 64 * 1024 };
|
|
enum { LZ4Size = LZ4_COMPRESSBOUND( BufSize ) };
|
|
|
|
LZ4_streamDecode_t* m_stream;
|
|
FILE* m_file;
|
|
char m_buf[2][BufSize];
|
|
size_t m_offset;
|
|
uint8_t m_active;
|
|
int m_lastBlock;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|