[poppler] config.h.cmake configure.ac ConfigureChecks.cmake goo/gfile.cc goo/gfile.h poppler/GlobalParamsWin.cc poppler/PDFDoc.cc poppler/PDFDoc.h poppler/Stream.cc poppler/Stream.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Thu Apr 4 15:00:39 PDT 2013
ConfigureChecks.cmake | 2 +
config.h.cmake | 6 +++
configure.ac | 1
goo/gfile.cc | 80 +++++++++++++++++++++++++++++++++++++++++++++
goo/gfile.h | 30 ++++++++++++++++
poppler/GlobalParamsWin.cc | 19 +++-------
poppler/PDFDoc.cc | 37 +++++---------------
poppler/PDFDoc.h | 4 +-
poppler/Stream.cc | 46 ++++++++-----------------
poppler/Stream.h | 17 ++-------
10 files changed, 158 insertions(+), 84 deletions(-)
New commits:
commit 0a243c8c14d09a40f25338999c3ca06273277b45
Author: Adam Reichold <adamreichold at myopera.com>
Date: Fri Apr 5 00:00:07 2013 +0200
Add a GooFile class to encapsulate file read access using offsets
Bug #62735
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 6e547ed..9f67b43 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -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)
diff --git a/config.h.cmake b/config.h.cmake
index cde219f..c3b30db 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -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
diff --git a/configure.ac b/configure.ac
index fc77b22..cd4645b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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],
diff --git a/goo/gfile.cc b/goo/gfile.cc
index 7630e20..c46fd86 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -21,6 +21,7 @@
// Copyright (C) 2008, 2010, 2012 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2009, 2012 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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
@@ -585,6 +586,85 @@ Goffset GoffsetMax() {
}
//------------------------------------------------------------------------
+// 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
//------------------------------------------------------------------------
diff --git a/goo/gfile.h b/goo/gfile.h
index 6787a6e..0caee71 100644
--- a/goo/gfile.h
+++ b/goo/gfile.h
@@ -18,6 +18,7 @@
// Copyright (C) 2006 Kristian Høgsberg <krh at redhat.com>
// Copyright (C) 2009, 2011, 2012 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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
@@ -122,6 +123,35 @@ extern Goffset Gftell(FILE *f);
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
//------------------------------------------------------------------------
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index e83c079..084b49b 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -6,6 +6,7 @@
// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
// Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2012 Mark Brand <mabrand at mabrand.nl>
+ // Copyright (C) 2013 Adam Reichold <adamreichold at 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;
}
}
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 46ecea5..52d694f 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -29,6 +29,7 @@
// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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;
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index cc9d2db..da9bf5b 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -25,6 +25,7 @@
// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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;
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 6ffd5d3..d5d26ec 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -28,6 +28,7 @@
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2012 Even Rouault <even.rouault at mines-paris.org>
// Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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
@@ -750,30 +751,14 @@ GBool StreamPredictor::getNextLine() {
}
//------------------------------------------------------------------------
-// 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;
}
diff --git a/poppler/Stream.h b/poppler/Stream.h
index dfcd530..5347d66 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -24,6 +24,7 @@
// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2013 Peter Breitenlohner <peb at mppmu.mpg.de>
+// Copyright (C) 2013 Adam Reichold <adamreichold at 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
//------------------------------------------------------------------------
More information about the poppler
mailing list