Commit 0a243c8c authored by Adam Reichold's avatar Adam Reichold Committed by Albert Astals Cid

Add a GooFile class to encapsulate file read access using offsets

Bug #62735
parent 70e6af47
......@@ -27,6 +27,8 @@ check_include_files(unistd.h HAVE_UNISTD_H)
check_function_exists(fseek64 HAVE_FSEEK64)
check_function_exists(fseeko HAVE_FSEEKO)
check_function_exists(ftell64 HAVE_FTELL64)
check_function_exists(pread64 HAVE_PREAD64)
check_function_exists(lseek64 HAVE_LSEEK64)
check_function_exists(gmtime_r HAVE_GMTIME_R)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_function_exists(localtime_r HAVE_LOCALTIME_R)
......
......@@ -46,6 +46,12 @@
/* Define to 1 if you have the `ftell64' function. */
#cmakedefine HAVE_FTELL64 1
/* Define to 1 if you have the `pread64' function. */
#cmakedefine HAVE_PREAD64 1
/* Define to 1 if you have the `lseek64' function. */
#cmakedefine HAVE_LSEEK64 1
/* Defines if gettimeofday is available on your system */
#cmakedefine HAVE_GETTIMEOFDAY 1
......
......@@ -264,6 +264,7 @@ AC_CHECK_FUNCS(ftell64, xpdf_cv_func_ftell64=yes, xpdf_cv_func_ftell64=no)
if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then
AC_DEFINE(HAVE_FSEEK64)
fi
AC_CHECK_FUNCS(pread64 lseek64)
dnl Test for zlib
AC_ARG_ENABLE([zlib],
......
......@@ -21,6 +21,7 @@
// Copyright (C) 2008, 2010, 2012 Hib Eris <hib@hiberis.nl>
// Copyright (C) 2009, 2012 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -584,6 +585,85 @@ Goffset GoffsetMax() {
#endif
}
//------------------------------------------------------------------------
// GooFile
//------------------------------------------------------------------------
#ifdef _WIN32
int GooFile::read(char *buf, int n, Goffset offset) const {
DWORD m;
LARGE_INTEGER largeInteger = {0};
largeInteger.QuadPart = offset;
OVERLAPPED overlapped = {0};
overlapped.Offset = largeInteger.LowPart;
overlapped.OffsetHigh = largeInteger.HighPart;
return FALSE == ReadFile(handle, buf, n, &m, &overlapped) ? -1 : m;
}
Goffset GooFile::size() const {
LARGE_INTEGER size = {-1,-1};
GetFileSizeEx(handle, &size);
return size.QuadPart;
}
GooFile* GooFile::open(const GooString *fileName) {
HANDLE handle = CreateFile(fileName->getCString(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
}
GooFile* GooFile::open(const wchar_t *fileName) {
HANDLE handle = CreateFileW(fileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
}
#else
int GooFile::read(char *buf, int n, Goffset offset) const {
#ifdef HAVE_PREAD64
return pread64(fd, buf, n, offset);
#else
return pread(fd, buf, n, offset);
#endif
}
Goffset GooFile::size() const {
#ifdef HAVE_LSEEK64
return lseek64(fd, 0, SEEK_END);
#else
return lseek(fd, 0, SEEK_END);
#endif
}
GooFile* GooFile::open(const GooString *fileName) {
#ifdef VMS
int fd = ::open(fileName->getCString(), Q_RDONLY, "ctx=stm");
#else
int fd = ::open(fileName->getCString(), O_RDONLY);
#endif
return fd < 0 ? NULL : new GooFile(fd);
}
#endif // _WIN32
//------------------------------------------------------------------------
// GDir and GDirEntry
//------------------------------------------------------------------------
......
......@@ -18,6 +18,7 @@
// Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2009, 2011, 2012 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -121,6 +122,35 @@ extern Goffset Gftell(FILE *f);
// Largest offset supported by Gfseek/Gftell
extern Goffset GoffsetMax();
//------------------------------------------------------------------------
// GooFile
//------------------------------------------------------------------------
class GooFile
{
public:
int read(char *buf, int n, Goffset offset) const;
Goffset size() const;
static GooFile *open(const GooString *fileName);
#ifdef _WIN32
static GooFile *open(const wchar_t *fileName);
~GooFile() { CloseHandle(handle); }
private:
GooFile(HANDLE handleA): handle(handleA) {}
HANDLE handle;
#else
~GooFile() { close(fd); }
private:
GooFile(int fdA) : fd(fdA) {}
int fd;
#endif // _WIN32
};
//------------------------------------------------------------------------
// GDir and GDirEntry
//------------------------------------------------------------------------
......
......@@ -6,6 +6,7 @@
// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
// Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2012 Mark Brand <mabrand@mabrand.nl>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
TODO: instead of a fixed mapping defined in displayFontTab, it could
scan the whole fonts directory, parse TTF files and build font
......@@ -408,9 +409,7 @@ void GlobalParams::setupBaseFonts(char * dir)
{
const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR;
GooString *fileName = NULL;
struct stat buf;
FILE *file;
int size = 0;
GooFile *file;
if (baseFontsInitialized)
return;
......@@ -453,15 +452,9 @@ void GlobalParams::setupBaseFonts(char * dir)
fileName = new GooString(dataRoot);
fileName->append("/cidfmap");
if (stat(fileName->getCString(), &buf) == 0) {
size = buf.st_size;
}
// try to open file
#ifdef VMS
file = fopen(fileName->getCString(), "rb", "ctx=stm");
#else
file = fopen(fileName->getCString(), "rb");
#endif
file = GooFile::open(fileName);
if (file != NULL) {
Parser *parser;
......@@ -470,7 +463,7 @@ void GlobalParams::setupBaseFonts(char * dir)
obj1.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj1)),
new FileStream(file, 0, gFalse, file->size(), &obj1)),
gTrue);
obj1.free();
parser->getObj(&obj1);
......@@ -498,7 +491,7 @@ void GlobalParams::setupBaseFonts(char * dir)
parser->getObj(&obj1);
}
}
fclose(file);
delete file;
delete parser;
}
}
......
......@@ -29,6 +29,7 @@
// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -55,6 +56,7 @@
#include <sys/stat.h>
#include "goo/gstrtod.h"
#include "goo/GooString.h"
#include "goo/gfile.h"
#include "poppler-config.h"
#include "GlobalParams.h"
#include "Page.h"
......@@ -129,7 +131,6 @@ PDFDoc::PDFDoc()
PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
GooString *userPassword, void *guiDataA) {
Object obj;
Goffset size = 0;
#ifdef _WIN32
int n, i;
#endif
......@@ -147,17 +148,8 @@ PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
fileNameU[n] = L'\0';
#endif
struct stat buf;
if (stat(fileName->getCString(), &buf) == 0) {
size = buf.st_size;
}
// try to open file
#ifdef VMS
file = fopen(fileName->getCString(), "rb", "ctx=stm");
#else
file = fopen(fileName->getCString(), "rb");
#endif
file = GooFile::open(fileName);
if (file == NULL) {
// fopen() has failed.
// Keep a copy of the errno returned by fopen so that it can be
......@@ -170,7 +162,7 @@ PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
// create stream
obj.initNull();
str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
str = new FileStream(file, 0, gFalse, file->size(), &obj);
ok = setup(ownerPassword, userPassword);
}
......@@ -194,26 +186,17 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GooString *ownerPassword,
fileNameU[i] = fileNameA[i];
}
fileNameU[fileNameLen] = L'\0';
// try to open file
// NB: _wfopen is only available in NT
struct _stat buf;
int size = 0;
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (_wstat(fileNameU, &buf) == 0) {
size = buf.st_size;
}
file = _wfopen(fileNameU, L"rb");
file = GooFile::open(fileNameU);
} else {
if (_stat(fileName->getCString(), &buf) == 0) {
size = buf.st_size;
}
file = fopen(fileName->getCString(), "rb");
file = GooFile::open(fileName);
}
if (!size || !file) {
if (!file) {
error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
errCode = errOpenFile;
return;
......@@ -221,7 +204,7 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GooString *ownerPassword,
// create stream
obj.initNull();
str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
str = new FileStream(file, 0, gFalse, file->size(), &obj);
ok = setup(ownerPassword, userPassword);
}
......@@ -343,7 +326,7 @@ PDFDoc::~PDFDoc() {
delete str;
}
if (file) {
fclose(file);
delete file;
}
if (fileName) {
delete fileName;
......
......@@ -25,6 +25,7 @@
// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -49,6 +50,7 @@
#include "Stream.h"
class GooString;
class GooFile;
class BaseStream;
class OutputDev;
class Links;
......@@ -307,7 +309,7 @@ private:
#ifdef _WIN32
wchar_t *fileNameU;
#endif
FILE *file;
GooFile *file;
BaseStream *str;
void *guiData;
int pdfMajorVersion;
......
......@@ -28,6 +28,7 @@
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2012 Even Rouault <even.rouault@mines-paris.org>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -749,31 +750,15 @@ GBool StreamPredictor::getNextLine() {
return gTrue;
}
//------------------------------------------------------------------------
// UniqueFileStream
//------------------------------------------------------------------------
UniqueFileStream::UniqueFileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
Goffset lengthA, Object *dictA):
FileStream(fA, fileNameA, startA, limitedA, lengthA, dictA) {
f = fopen(fileName, "rb");
}
UniqueFileStream::~UniqueFileStream() {
close();
fclose(f);
}
//------------------------------------------------------------------------
// FileStream
//------------------------------------------------------------------------
FileStream::FileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
FileStream::FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
Goffset lengthA, Object *dictA):
BaseStream(dictA, lengthA) {
f = fA;
fileName = fileNameA;
start = startA;
file = fileA;
offset = start = startA;
limited = limitedA;
length = lengthA;
bufPtr = bufEnd = buf;
......@@ -787,17 +772,17 @@ FileStream::~FileStream() {
}
BaseStream *FileStream::copy() {
return new UniqueFileStream(f, fileName, start, limited, length, &dict);
return new FileStream(file, start, limited, length, &dict);
}
Stream *FileStream::makeSubStream(Goffset startA, GBool limitedA,
Goffset lengthA, Object *dictA) {
return new FileStream(f, fileName, startA, limitedA, lengthA, dictA);
return new FileStream(file, startA, limitedA, lengthA, dictA);
}
void FileStream::reset() {
savePos = Gftell(f);
Gfseek(f, start, SEEK_SET);
savePos = offset;
offset = start;
saved = gTrue;
bufPtr = bufEnd = buf;
bufPos = start;
......@@ -805,7 +790,7 @@ void FileStream::reset() {
void FileStream::close() {
if (saved) {
Gfseek(f, savePos, SEEK_SET);
offset = savePos;
saved = gFalse;
}
}
......@@ -823,7 +808,8 @@ GBool FileStream::fillBuf() {
} else {
n = fileStreamBufSize;
}
n = fread(buf, 1, n, f);
n = file->read(buf, n, offset);
offset += n;
bufEnd = buf + n;
if (bufPtr >= bufEnd) {
return gFalse;
......@@ -835,15 +821,13 @@ void FileStream::setPos(Goffset pos, int dir) {
Goffset size;
if (dir >= 0) {
Gfseek(f, pos, SEEK_SET);
bufPos = pos;
offset = bufPos = pos;
} else {
Gfseek(f, 0, SEEK_END);
size = Gftell(f);
size = file->size();
if (pos > size)
pos = size;
Gfseek(f, -pos, SEEK_END);
bufPos = Gftell(f);
offset = size - pos;
bufPos = offset;
}
bufPtr = bufEnd = buf;
}
......
......@@ -24,6 +24,7 @@
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Peter Breitenlohner <peb@mppmu.mpg.de>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -43,6 +44,7 @@
#include "Object.h"
#include "goo/GooMutex.h"
class GooFile;
class BaseStream;
class CachedFile;
......@@ -443,7 +445,7 @@ private:
class FileStream: public BaseStream {
public:
FileStream(FILE *fA, char *fileName, Goffset startA, GBool limitedA,
FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
Goffset lengthA, Object *dictA);
virtual ~FileStream();
virtual BaseStream *copy();
......@@ -491,10 +493,9 @@ private:
return n;
}
protected:
FILE *f;
char *fileName;
private:
GooFile* file;
Goffset offset;
Goffset start;
GBool limited;
char buf[fileStreamBufSize];
......@@ -505,14 +506,6 @@ private:
GBool saved;
};
class UniqueFileStream: public FileStream {
public:
UniqueFileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
Goffset lengthA, Object *dictA);
virtual ~UniqueFileStream();
};
//------------------------------------------------------------------------
// CachedFileStream
//------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment