2017-04-17 11:33:19 +00:00
/*
* * files . h
* * Implements classes for reading from files or memory blocks
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 1998 - 2008 Randy Heit
* * Copyright 2005 - 2008 Christoph Oelckers
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
2016-03-01 15:47:10 +00:00
# ifndef FILES_H
# define FILES_H
# include <stdio.h>
2018-03-10 17:45:11 +00:00
# include <functional>
2016-03-01 15:47:10 +00:00
# include "doomtype.h"
# include "m_swap.h"
2018-03-11 12:26:30 +00:00
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
2018-03-11 11:33:46 +00:00
enum
2016-03-01 15:47:10 +00:00
{
2018-03-11 11:33:46 +00:00
METHOD_STORED = 0 ,
METHOD_SHRINK = 1 ,
METHOD_IMPLODE = 6 ,
METHOD_DEFLATE = 8 ,
METHOD_BZIP2 = 12 ,
METHOD_LZMA = 14 ,
METHOD_PPMD = 98 ,
METHOD_LZSS = 1337 , // not used in Zips - this is for Console Doom compression
METHOD_ZLIB = 1338 , // Zlib stream with header, used by compressed nodes.
2016-03-01 15:47:10 +00:00
} ;
2018-03-11 11:33:46 +00:00
class FileReaderInterface
2016-03-01 15:47:10 +00:00
{
public :
2018-03-11 11:33:46 +00:00
long Length = - 1 ;
virtual ~ FileReaderInterface ( ) { }
virtual long Tell ( ) const = 0 ;
virtual long Seek ( long offset , int origin ) = 0 ;
virtual long Read ( void * buffer , long len ) = 0 ;
virtual char * Gets ( char * strbuf , int len ) = 0 ;
virtual const char * GetBuffer ( ) const { return nullptr ; }
2016-03-01 15:47:10 +00:00
long GetLength ( ) const { return Length ; }
2018-03-10 12:46:35 +00:00
} ;
2018-03-11 12:26:30 +00:00
class DecompressorBase : public FileReaderInterface
{
public :
// These do not work but need to be defined to satisfy the FileReaderInterface.
// They will just error out when called.
long Tell ( ) const override ;
long Seek ( long offset , int origin ) override ;
char * Gets ( char * strbuf , int len ) override ;
} ;
2018-03-11 11:33:46 +00:00
class MemoryReader : public FileReaderInterface
2016-03-01 15:47:10 +00:00
{
protected :
2018-03-11 11:33:46 +00:00
const char * bufptr = nullptr ;
long FilePos = 0 ;
2016-03-01 15:47:10 +00:00
2018-03-11 11:33:46 +00:00
MemoryReader ( )
{ }
2016-09-21 07:01:12 +00:00
public :
2018-03-11 11:33:46 +00:00
MemoryReader ( const char * buffer , long length )
2016-09-21 07:01:12 +00:00
{
2018-03-11 11:33:46 +00:00
bufptr = buffer ;
Length = length ;
FilePos = 0 ;
2016-09-21 07:01:12 +00:00
}
2018-03-11 11:33:46 +00:00
long Tell ( ) const override ;
long Seek ( long offset , int origin ) override ;
long Read ( void * buffer , long len ) override ;
char * Gets ( char * strbuf , int len ) override ;
virtual const char * GetBuffer ( ) const override { return bufptr ; }
2016-09-21 07:01:12 +00:00
} ;
2018-03-11 12:26:30 +00:00
struct FResourceLump ;
2018-03-10 12:46:35 +00:00
2018-03-11 17:32:00 +00:00
class FileReader
2018-03-10 12:46:35 +00:00
{
2018-03-11 12:26:30 +00:00
friend struct FResourceLump ; // needs access to the private constructor.
2018-03-11 11:33:46 +00:00
FileReaderInterface * mReader = nullptr ;
2018-03-10 12:46:35 +00:00
2018-03-11 17:32:00 +00:00
FileReader ( const FileReader & r ) = delete ;
FileReader & operator = ( const FileReader & r ) = delete ;
2018-03-11 11:33:46 +00:00
2018-03-11 17:32:00 +00:00
explicit FileReader ( FileReaderInterface * r )
2018-03-11 12:26:30 +00:00
{
mReader = r ;
}
2018-03-10 12:46:35 +00:00
public :
enum ESeek
{
SeekSet = SEEK_SET ,
SeekCur = SEEK_CUR ,
SeekEnd = SEEK_END
} ;
typedef ptrdiff_t Size ; // let's not use 'long' here.
2018-03-11 17:32:00 +00:00
FileReader ( ) { }
2018-03-10 17:45:11 +00:00
2018-03-11 17:32:00 +00:00
FileReader ( FileReader & & r )
2018-03-10 12:46:35 +00:00
{
mReader = r . mReader ;
r . mReader = nullptr ;
}
2018-03-11 17:32:00 +00:00
FileReader & operator = ( FileReader & & r )
2018-03-10 17:45:11 +00:00
{
Close ( ) ;
mReader = r . mReader ;
r . mReader = nullptr ;
return * this ;
}
2018-03-11 17:32:00 +00:00
~ FileReader ( )
2018-03-10 17:45:11 +00:00
{
Close ( ) ;
}
2018-03-10 18:22:26 +00:00
bool isOpen ( ) const
{
return mReader ! = nullptr ;
}
2018-03-10 17:45:11 +00:00
void Close ( )
2018-03-10 12:46:35 +00:00
{
if ( mReader ! = nullptr ) delete mReader ;
mReader = nullptr ;
}
2018-03-11 11:33:46 +00:00
bool OpenFile ( const char * filename , Size start = 0 , Size length = - 1 ) ;
2018-03-11 17:32:00 +00:00
bool OpenFilePart ( FileReader & parent , Size start , Size length ) ;
2018-03-10 12:46:35 +00:00
bool OpenMemory ( const void * mem , Size length ) ; // read directly from the buffer
bool OpenMemoryArray ( const void * mem , Size length ) ; // read from a copy of the buffer.
2018-03-10 17:45:11 +00:00
bool OpenMemoryArray ( std : : function < bool ( TArray < uint8_t > & ) > getter ) ; // read contents to a buffer and return a reader to it
2018-03-11 17:32:00 +00:00
bool OpenDecompressor ( FileReader & parent , Size length , int method , bool seekable ) ; // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
2018-03-10 12:46:35 +00:00
Size Tell ( ) const
{
return mReader - > Tell ( ) ;
}
Size Seek ( Size offset , ESeek origin )
{
return mReader - > Seek ( ( long ) offset , origin ) ;
}
Size Read ( void * buffer , Size len )
{
return mReader - > Read ( buffer , ( long ) len ) ;
}
2018-11-10 10:56:18 +00:00
TArray < uint8_t > Read ( size_t len )
{
TArray < uint8_t > buffer ( ( int ) len , true ) ;
Size length = mReader - > Read ( & buffer [ 0 ] , ( long ) len ) ;
buffer . Clamp ( ( int ) length ) ;
return buffer ;
}
2018-11-02 09:20:12 +00:00
TArray < uint8_t > Read ( )
{
TArray < uint8_t > buffer ( mReader - > Length , true ) ;
Size length = mReader - > Read ( & buffer [ 0 ] , mReader - > Length ) ;
if ( length < mReader - > Length ) buffer . Clear ( ) ;
return buffer ;
}
2018-03-10 12:46:35 +00:00
char * Gets ( char * strbuf , Size len )
{
return mReader - > Gets ( strbuf , ( int ) len ) ;
}
2018-03-11 11:33:46 +00:00
const char * GetBuffer ( )
{
return mReader - > GetBuffer ( ) ;
}
Size GetLength ( ) const
{
2018-03-10 12:46:35 +00:00
return mReader - > GetLength ( ) ;
}
2018-03-11 17:20:49 +00:00
uint8_t ReadUInt8 ( )
2018-03-10 12:46:35 +00:00
{
2018-03-20 17:29:54 +00:00
uint8_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 1 ) ;
return v ;
2018-03-10 12:46:35 +00:00
}
2018-03-11 17:20:49 +00:00
int8_t ReadInt8 ( )
2018-03-10 12:46:35 +00:00
{
2018-03-20 17:29:54 +00:00
int8_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 1 ) ;
return v ;
2018-03-10 12:46:35 +00:00
}
2018-03-11 17:20:49 +00:00
uint16_t ReadUInt16 ( )
2018-03-10 12:46:35 +00:00
{
2018-03-20 17:29:54 +00:00
uint16_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 2 ) ;
return LittleShort ( v ) ;
2018-03-10 12:46:35 +00:00
}
2018-03-11 17:20:49 +00:00
int16_t ReadInt16 ( )
2018-03-10 12:46:35 +00:00
{
2018-03-20 17:29:54 +00:00
uint16_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 2 ) ;
return LittleShort ( v ) ;
2018-03-10 12:46:35 +00:00
}
2018-03-11 17:20:49 +00:00
uint32_t ReadUInt32 ( )
2018-03-10 12:46:35 +00:00
{
2018-03-20 17:29:54 +00:00
uint32_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 4 ) ;
return LittleLong ( v ) ;
2018-03-10 12:46:35 +00:00
}
2018-03-11 17:20:49 +00:00
int32_t ReadInt32 ( )
2018-03-11 11:33:46 +00:00
{
2018-03-20 17:29:54 +00:00
uint32_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 4 ) ;
return LittleLong ( v ) ;
2018-03-11 11:33:46 +00:00
}
2018-03-11 17:20:49 +00:00
uint32_t ReadUInt32BE ( )
{
2018-03-20 17:29:54 +00:00
uint32_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 4 ) ;
return BigLong ( v ) ;
}
int32_t ReadInt32BE ( )
{
2018-03-20 17:29:54 +00:00
uint32_t v = 0 ;
2018-03-11 17:20:49 +00:00
Read ( & v , 4 ) ;
return BigLong ( v ) ;
}
2018-03-10 12:46:35 +00:00
friend class FWadCollection ;
} ;
2018-03-11 11:33:46 +00:00
class FileWriter
{
protected :
bool OpenDirect ( const char * filename ) ;
FileWriter ( )
{
File = NULL ;
}
public :
virtual ~ FileWriter ( )
{
if ( File ! = NULL ) fclose ( File ) ;
}
static FileWriter * Open ( const char * filename ) ;
virtual size_t Write ( const void * buffer , size_t len ) ;
virtual long Tell ( ) ;
virtual long Seek ( long offset , int mode ) ;
size_t Printf ( const char * fmt , . . . ) GCCPRINTF ( 2 , 3 ) ;
protected :
FILE * File ;
protected :
bool CloseOnDestruct ;
} ;
class BufferWriter : public FileWriter
{
protected :
TArray < unsigned char > mBuffer ;
public :
BufferWriter ( ) { }
virtual size_t Write ( const void * buffer , size_t len ) override ;
TArray < unsigned char > * GetBuffer ( ) { return & mBuffer ; }
} ;
2016-03-01 15:47:10 +00:00
# endif