Enable error and EOF check in class Fl_Image_Reader (#271)

This is part 1 and a prerequisite for the fix of issue #271.
It enables the user of this internal class (Fl_{BMP|GIF}_Image)
to test for read errors and EOF (end of file) while reading.

The method used to read data from memory got an optional third
argument 'const long datasize = -1)' to limit the size of the
memory block of data provided to the image reader. Default is -1
which means "unlimited" (backwards compatibility).

Using only two arguments (w/o size limit) is deprecated and should
only be done if the data size is not available.
This commit is contained in:
Albrecht Schlosser 2021-09-25 19:33:22 +02:00
parent 0f12e96d13
commit bc0d18c1bb
2 changed files with 82 additions and 40 deletions

View File

@ -1,7 +1,7 @@
// //
// Internal (Image) Reader class for the Fast Light Tool Kit (FLTK). // Internal (Image) Reader class for the Fast Light Tool Kit (FLTK).
// //
// Copyright 2020 by Bill Spitzak and others. // Copyright 2020-2021 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@ -50,12 +50,15 @@ int Fl_Image_Reader::open(const char *filename) {
} }
// Initialize the reader for memory access, name is copied and stored // Initialize the reader for memory access, name is copied and stored
int Fl_Image_Reader::open(const char *imagename, const unsigned char *data) { int Fl_Image_Reader::open(const char *imagename, const unsigned char *data, const long datasize) {
if (imagename) if (imagename)
pName = fl_strdup(imagename); pName = fl_strdup(imagename);
if (data) { if (data) {
pStart = pData = data; pStart = pData = data;
pIsData = 1; pIsData = 1;
if (datasize > 0) {
pEnd = pStart + datasize;
}
return 0; return 0;
} else { } else {
return -1; return -1;
@ -73,60 +76,82 @@ Fl_Image_Reader::~Fl_Image_Reader() {
// Read a single byte from memory or a file // Read a single byte from memory or a file
uchar Fl_Image_Reader::read_byte() { uchar Fl_Image_Reader::read_byte() {
if (error()) // don't read after read error or EOF
return 0;
if (pIsFile) { if (pIsFile) {
return getc(pFile); int ret = getc(pFile);
if (ret < 0) {
if (feof(pFile))
pError = 1;
else if (ferror(pFile))
pError = 2;
else
pError = 3; // unknown error
return 0;
}
return ret;
} else if (pIsData) { } else if (pIsData) {
return *pData++; if (pData < pEnd)
} else { return *pData++;
pError = 1; // EOF
return 0; return 0;
} }
pError = 3; // undefined mode
return 0;
} }
// Read a 16-bit unsigned integer, LSB-first // Read a 16-bit unsigned integer, LSB-first
unsigned short Fl_Image_Reader::read_word() { unsigned short Fl_Image_Reader::read_word() {
unsigned char b0, b1; // Bytes from file unsigned char b0, b1; // Bytes from file or memory
if (pIsFile) { b0 = read_byte();
b0 = (uchar)getc(pFile); b1 = read_byte();
b1 = (uchar)getc(pFile); if (error())
return ((b1 << 8) | b0);
} else if (pIsData) {
b0 = *pData++;
b1 = *pData++;
return ((b1 << 8) | b0);
} else {
return 0; return 0;
} return ((b1 << 8) | b0);
} }
// Read a 32-bit unsigned integer, LSB-first // Read a 32-bit unsigned integer, LSB-first
unsigned int Fl_Image_Reader::read_dword() { unsigned int Fl_Image_Reader::read_dword() {
unsigned char b0, b1, b2, b3; // Bytes from file unsigned char b0, b1, b2, b3; // Bytes from file or memory
if (pIsFile) { b0 = read_byte();
b0 = (uchar)getc(pFile); b1 = read_byte();
b1 = (uchar)getc(pFile); b2 = read_byte();
b2 = (uchar)getc(pFile); b3 = read_byte();
b3 = (uchar)getc(pFile); if (error())
return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
} else if (pIsData) {
b0 = *pData++;
b1 = *pData++;
b2 = *pData++;
b3 = *pData++;
return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
} else {
return 0; return 0;
} return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
} }
// Read a 32-bit signed integer, LSB-first
// int Fl_Image_Reader::read_long() -- implementation in header file
// Move the current read position to a byte offset from the beginning // Move the current read position to a byte offset from the beginning
// of the file or the original start address in memory // of the file or the original start address in memory.
// This clears the error flag if the position is valid.
void Fl_Image_Reader::seek(unsigned int n) { void Fl_Image_Reader::seek(unsigned int n) {
if (pIsFile) { if (pIsFile) {
fseek(pFile, n , SEEK_SET); int ret = fseek(pFile, n , SEEK_SET);
if (ret < 0)
pError = 2; // read / position error
else
pError = 0;
return;
} else if (pIsData) { } else if (pIsData) {
pData = pStart + n; if (pStart + n <= pEnd)
pData = pStart + n;
else
pError = 2; // read / position error
return;
} }
// unknown mode (not initialized ?)
pError = 3;
}
// Get the current read position as a byte offset from the
// beginning of the file or the original start address in memory
long Fl_Image_Reader::tell() const {
if (pIsFile) {
return ftell(pFile);
} else if (pIsData) {
return long(pData - pStart);
}
return 0;
} }

View File

@ -1,7 +1,7 @@
// //
// Internal (Image) Reader class for the Fast Light Tool Kit (FLTK). // Internal (Image) Reader class for the Fast Light Tool Kit (FLTK).
// //
// Copyright 2020 by Bill Spitzak and others. // Copyright 2020-2021 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@ -37,7 +37,9 @@ public:
pIsFile(0), pIsData(0), pIsFile(0), pIsData(0),
pFile(0L), pData(0L), pFile(0L), pData(0L),
pStart(0L), pStart(0L),
pName(0L) pEnd((const unsigned char *)(-1L)),
pName(0L),
pError(0)
{} {}
// Initialize the reader to access the file system, filename is copied // Initialize the reader to access the file system, filename is copied
@ -45,7 +47,7 @@ public:
int open(const char *filename); int open(const char *filename);
// Initialize the reader for memory access, name is copied and stored // Initialize the reader for memory access, name is copied and stored
int open(const char *imagename, const unsigned char *data); int open(const char *imagename, const unsigned char *data, const long datasize = -1);
// Close and destroy the reader // Close and destroy the reader
~Fl_Image_Reader(); ~Fl_Image_Reader();
@ -68,6 +70,15 @@ public:
// of the file or the original start address in memory // of the file or the original start address in memory
void seek(unsigned int n); void seek(unsigned int n);
// Get the current file or memory offset from the beginning
// of the file or the original start address in memory
long tell() const;
// Get the current EOF or error status of the file or data block
int error() const {
return pError;
}
// return the name or filename for this reader // return the name or filename for this reader
const char *name() { return pName; } const char *name() { return pName; }
@ -83,8 +94,14 @@ private:
const unsigned char *pData; const unsigned char *pData;
// a pointer to the start of the image data // a pointer to the start of the image data
const unsigned char *pStart; const unsigned char *pStart;
// a pointer to the end of image data if reading from memory, otherwise undefined
// note: currently (const unsigned char *)(-1L) if end of memory is not available
// ... which means "unlimited"
const unsigned char *pEnd;
// a copy of the name associated with this reader // a copy of the name associated with this reader
char *pName; char *pName;
// a flag to store EOF or error status
int pError;
}; };
#endif // FL_IMAGE_READER_H #endif // FL_IMAGE_READER_H