Added support for files larger than ~2GB.

This implements #786.

TinyXML reads the entire file into a pre-allocated buffer in memory. To
get the buffer size, it uses `fseek()` to seek to the end of the file,
and `ftell()` to get the current byte offset. But because `ftell()`
returns a 32-bit signed value, it can only represent byte offsets, hence
file sizes, up to about 2GB.

To get around this, `fseek` and `ftell` have been replaced by the
`TIXML_FSEEK` and `TIXML_FTELL` macros, respectively, which will resolve
to 64-bit versions of these functions on platforms that have them.
This commit is contained in:
John Senneker
2019-11-19 11:00:52 -05:00
parent ff61650517
commit bf59a2d4c8

View File

@@ -100,6 +100,20 @@ distribution.
#define TIXML_SSCANF sscanf #define TIXML_SSCANF sscanf
#endif #endif
#if defined(_WIN64)
#define TIXML_FSEEK _fseeki64
#define TIXML_FTELL _ftelli64
#elif defined(__APPLE__)
#define TIXML_FSEEK fseeko
#define TIXML_FTELL ftello
#elif defined(__x86_64__)
#define TIXML_FSEEK fseeko64
#define TIXML_FTELL ftello64
#else
#define TIXML_FSEEK fseek
#define TIXML_FTELL ftell
#endif
static const char LINE_FEED = static_cast<char>(0x0a); // all line endings are normalized to LF static const char LINE_FEED = static_cast<char>(0x0a); // all line endings are normalized to LF
static const char LF = LINE_FEED; static const char LF = LINE_FEED;
@@ -2280,15 +2294,15 @@ XMLError XMLDocument::LoadFile( FILE* fp )
{ {
Clear(); Clear();
fseek( fp, 0, SEEK_SET ); TIXML_FSEEK( fp, 0, SEEK_SET );
if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
return _errorID; return _errorID;
} }
fseek( fp, 0, SEEK_END ); TIXML_FSEEK( fp, 0, SEEK_END );
const long filelength = ftell( fp ); const long long filelength = TIXML_FTELL( fp );
fseek( fp, 0, SEEK_SET ); TIXML_FSEEK( fp, 0, SEEK_SET );
if ( filelength == -1L ) { if ( filelength == -1L ) {
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
return _errorID; return _errorID;