[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:40:58 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=83cd2ef
The following commit has been merged in the master branch:
commit 83cd2efab9ee070b96c04b248c46526b6321814f
Author: Andreas Huggel <ahuggel at gmx.net>
Date: Sun Dec 27 09:56:29 2009 +0000
#579: Implemented mmap for Windows directly in FileIo and made that class use the Pimpl idiom (#510) to de-clutter the interface. Unrelated: Added EXV_MIN/MAX macros, allow iconv config in commercial version.
---
config/config.h.in | 4 +-
msvc/exiv2lib/exiv2lib.vcproj | 15 --
msvc/include/exv_msvc.h | 22 +-
msvc/include/sys/mman.h | 57 -----
msvc/include/sys/socket.h | 7 -
msvc/include/sys/types.h | 8 -
msvc/include/winposix_export.h | 39 ----
msvc/src/mmap.cpp | 196 -----------------
samples/mmap-test.cpp | 2 +-
src/basicio.cpp | 478 +++++++++++++++++++++++++----------------
src/basicio.hpp | 50 +----
src/tiffcomposite.cpp | 6 +-
src/types.hpp | 4 +
13 files changed, 318 insertions(+), 570 deletions(-)
diff --git a/config/config.h.in b/config/config.h.in
index 8eaa194..8260fc6 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -25,11 +25,11 @@
native language is requested. */
#undef ENABLE_NLS
+#endif /* !EXV_COMMERCIAL_VERSION */
+
/* Define to 1 if you have the `iconv' function. */
#undef HAVE_ICONV
-#endif /* !EXV_COMMERCIAL_VERSION */
-
/* Define to `const' or to empty, depending on the second argument of `iconv'. */
#undef ICONV_CONST
diff --git a/msvc/exiv2lib/exiv2lib.vcproj b/msvc/exiv2lib/exiv2lib.vcproj
index 6061289..200440d 100644
--- a/msvc/exiv2lib/exiv2lib.vcproj
+++ b/msvc/exiv2lib/exiv2lib.vcproj
@@ -573,21 +573,6 @@ copy/y ..\..\..\zlib-1.2.3\projects
isualc6\Win32_DLL_Release\zlib1.dll $(OutDi
<File
RelativePath="..\include\exv_msvc.h">
</File>
- <File
- RelativePath="..\src\mmap.cpp">
- </File>
- <File
- RelativePath="..\include\sys\mman.h">
- </File>
- <File
- RelativePath="..\include\sys\socket.h">
- </File>
- <File
- RelativePath="..\include\sys ypes.h">
- </File>
- <File
- RelativePath="..\include\winposix_export.h">
- </File>
</Filter>
</Files>
<Globals>
diff --git a/msvc/include/exv_msvc.h b/msvc/include/exv_msvc.h
index 82dd414..b9544e5 100644
--- a/msvc/include/exv_msvc.h
+++ b/msvc/include/exv_msvc.h
@@ -43,14 +43,11 @@ typedef int pid_t;
native language is requested. */
# undef EXV_ENABLE_NLS
+#endif /* !EXV_COMMERCIAL_VERSION */
+
/* Define to 1 if you have the `iconv' function. */
# undef EXV_HAVE_ICONV
-/* Define to 1 to enable conversion of UCS2 encoded Windows tags to UTF-8. */
-# undef EXV_HAVE_PRINTUCS2
-
-#endif /* !EXV_COMMERCIAL_VERSION */
-
/* Define as 1 if you have the `zlib' library. (0 to omit zlib) [png support] */
#define HAVE_LIBZ 1
@@ -72,16 +69,11 @@ typedef int pid_t;
/* Windows unicode path support */
#define EXV_UNICODE_PATH
-/* Define to 1 if you have the "sys/mman.h header file (and supporting code of course) */
-/* At this time (between 0.18.1 and 0.19) this is used by TIFF files to avoid reading */
-/* the total file into memory returning in a 6x improvement in exiv2 on 2mb tiff files */
-#define EXV_HAVE_SYS_MMAN_H 1
-#ifdef EXV_HAVE_SYS_MMAN_H
-#if EXV_HAVE_SYS_MMAN_H
-#define EXV_HAVE_MMAP 1
-#define EXV_HAVE_MUNMAP 1
-#endif
-#endif
+/* Define to 1 if you have the `mmap' function. */
+/* #undef EXV_HAVE_MMAP */
+
+/* Define to 1 if you have the `munmap' function. */
+/* #undef EXV_HAVE_MUNMAP */
/* Shared library support */
#ifdef EXV_HAVE_DLL
diff --git a/msvc/include/sys/mman.h b/msvc/include/sys/mman.h
deleted file mode 100644
index 6c9b315..0000000
--- a/msvc/include/sys/mman.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- This file is part of the KDE libraries
- Copyright (C) 2004 Jaroslaw Staniek <js at iidea.pl>
-
- These sources are based on ftp://g.oswego.edu/pub/misc/malloc.c
- file by Doug Lea, released to the public domain.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License version 2 as published by the Free Software Foundation.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#ifndef KDEWIN_SYS_MMAN_H
-#define KDEWIN_SYS_MMAN_H
-
-// include everywhere
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PROT_NONE 0
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define PROT_EXEC 4
-
-/* These values don't really matter in windows mmap emulation */
-#define MAP_FILE 0
-#define MAP_SHARED 1
-#define MAP_PRIVATE 2
-#define MAP_TYPE 0xF
-#define MAP_FIXED 0x10
-#define MAP_ANONYMOUS 0x20
-#define MAP_ANON MAP_ANONYMOUS
-
-#define MAP_FAILED ((void *)-1)
-
-KDEWIN32_EXPORT void *mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);
-KDEWIN32_EXPORT int munmap(void *start, size_t length);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // KDEWIN_SYS_MMAN_H
diff --git a/msvc/include/sys/socket.h b/msvc/include/sys/socket.h
deleted file mode 100644
index 8d48c23..0000000
--- a/msvc/include/sys/socket.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _sys_socket_h_
-#define _sys_socket_h_
-
-// rmills
-// minimum to enable mmap.cpp to compile without change
-
-#endif
diff --git a/msvc/include/sys/types.h b/msvc/include/sys/types.h
deleted file mode 100644
index 39ad7de..0000000
--- a/msvc/include/sys/types.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _types_h_
-#define _types_h_
-// rmills
-// minimum required by exiv2
-//
-#include "winposix_export.h"
-#endif
-
diff --git a/msvc/include/winposix_export.h b/msvc/include/winposix_export.h
deleted file mode 100644
index abcc368..0000000
--- a/msvc/include/winposix_export.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _WINPOSIX_EXPORT_H_
-#define _WINPOSIX_EXPORT_H_
-
-// rmills
-// msvc/include/winposix_export.h
-//
-// I'm very appreciative and respectful of the work of Jaroslaw Staniek <js at iidea.pl>
-// in the KDE libraries where I found msvc/src/mmap.cpp and msvc/mman.h
-//
-// http://websvn.kde.org/trunk/KDE/kdelibs/win/include/msvc/sys/mman.h?revision=517357&view=markup&pathrev=519502
-// http://websvn.kde.org/trunk/KDE/kdelibs/win/src/mmap.c?revision=519502&view=markup&pathrev=519502
-
-// I have commented 2 essential tiny changes in mmap.cpp to make it compile with MSVC
-// I've also added a dummy sys/socket.h and sys/types.h file to keep everybody happy!
-//
-// the contents of this file are the minimum required to enable exiv2 to compile link and execute the mmap.cpp code
-//
-
-#ifndef ENOTSUP
-#define ENOTSUP 911
-#endif
-
-#ifndef off_t
-#define off_t size_t
-#endif
-
-#ifndef KDEWIN32_EXPORT
-#define KDEWIN32_EXPORT
-#endif
-
-// give MSVC 7.1 (VS 2003 .Net) encouragement to ignore _set_errno !
-#if _MSC_VER < 1400
-#ifndef _set_errno
-#define _set_errno(x)
-#endif
-#endif
-
-#endif
-
diff --git a/msvc/src/mmap.cpp b/msvc/src/mmap.cpp
deleted file mode 100644
index f85a502..0000000
--- a/msvc/src/mmap.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- This file is part of the KDE libraries
- Copyright (c) 2006 Christian Ehrlicher <ch.ehrlicher at gmx.de>
-
- These sources are based on ftp://g.oswego.edu/pub/misc/malloc.c
- file by Doug Lea, released to the public domain.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License version 2 as published by the Free Software Foundation.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include <winposix_export.h>
-#include <windows.h>
-
-#include <assert.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <io.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-
-#ifndef SECTION_MAP_EXECUTE_EXPLICIT
-//not defined in the February 2003 version of the Platform SDK
-#define SECTION_MAP_EXECUTE_EXPLICIT 0x0020
-#endif
-
-#ifndef FILE_MAP_EXECUTE
-//not defined in the February 2003 version of the Platform SDK
-#define FILE_MAP_EXECUTE SECTION_MAP_EXECUTE_EXPLICIT
-#endif
-
-#define MUNMAP_FAILURE (-1)
-
-#define USE_MALLOC_LOCK 1
-
-struct mmapInfos {
- HANDLE hFile; // the duplicated fd
- HANDLE hMap; // handle returned by CreateFileMapping
- void* start; // ptr returned by MapViewOfFile
-};
-
-CRITICAL_SECTION cs;
-
-// rmills - only change is to add long to the following 2 lines
-static long g_curMMapInfos = 0;
-static long g_maxMMapInfos = -1;
-static struct mmapInfos *g_mmapInfos = NULL;
-#define NEW_MMAP_STRUCT_CNT 10
-
-static int mapProtFlags(int flags, DWORD *dwAccess)
-{
- if ( ( flags & PROT_READ ) == PROT_READ ) {
- if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
- *dwAccess = FILE_MAP_WRITE;
- if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
- return PAGE_EXECUTE_READWRITE;
- }
- return PAGE_READWRITE;
- }
- if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
- *dwAccess = FILE_MAP_EXECUTE;
- return PAGE_EXECUTE_READ;
- }
- *dwAccess = FILE_MAP_READ;
- return PAGE_READONLY;
- }
- if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
- *dwAccess = FILE_MAP_COPY;
- return PAGE_WRITECOPY;
- }
- if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
- *dwAccess = FILE_MAP_EXECUTE;
- return PAGE_EXECUTE_READ;
- }
- *dwAccess = 0;
- return 0;
-}
-
-void *mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
-{
- struct mmapInfos mmi;
- DWORD dwAccess;
- DWORD flProtect;
- HANDLE hfd;
-
- if ( g_maxMMapInfos == -1 ) {
- g_maxMMapInfos = 0;
- InitializeCriticalSection( &cs );
- }
-
- flProtect = mapProtFlags( flags, &dwAccess );
- if ( flProtect == 0 ) {
- _set_errno( EINVAL );
- return MAP_FAILED;
- }
- // we don't support this atm
- if ( prot == MAP_FIXED ) {
- _set_errno( ENOTSUP );
- return MAP_FAILED;
- }
-
- if ( fd == -1 ) {
- _set_errno( EBADF );
- return MAP_FAILED;
- }
-
- hfd = (HANDLE)_get_osfhandle( fd );
- if ( hfd == INVALID_HANDLE_VALUE )
- return MAP_FAILED;
-
- if ( !DuplicateHandle( GetCurrentProcess(), hfd, GetCurrentProcess(),
- &mmi.hFile, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
-#ifdef _DEBUG
- DWORD dwLastErr = GetLastError();
-#endif
- return MAP_FAILED;
- }
- mmi.hMap = CreateFileMapping( mmi.hFile, NULL, flProtect,
- 0, length, NULL );
- if ( mmi.hMap == 0 ) {
- _set_errno( EACCES );
- return MAP_FAILED;
- }
-
- mmi.start = MapViewOfFile( mmi.hMap, dwAccess, 0, offset, 0 );
- if ( mmi.start == 0 ) {
- DWORD dwLastErr = GetLastError();
- if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
- _set_errno( EINVAL );
- else
- _set_errno( EACCES );
- return MAP_FAILED;
- }
- EnterCriticalSection( &cs );
- if ( g_mmapInfos == NULL ) {
- g_maxMMapInfos = NEW_MMAP_STRUCT_CNT;
- g_mmapInfos = ( struct mmapInfos* )calloc( g_maxMMapInfos,
- sizeof( struct mmapInfos ) );
- }
- if( g_curMMapInfos == g_maxMMapInfos) {
- g_maxMMapInfos += NEW_MMAP_STRUCT_CNT;
- g_mmapInfos = ( struct mmapInfos* )realloc( g_mmapInfos,
- g_maxMMapInfos * sizeof( struct mmapInfos ) );
- }
- memcpy( &g_mmapInfos[g_curMMapInfos], &mmi, sizeof( struct mmapInfos) );
- g_curMMapInfos++;
-
- LeaveCriticalSection( &cs );
-
- return mmi.start;
-}
-
-int munmap(void *start, size_t length)
-{
- int i, j;
-
- for( i = 0; i < g_curMMapInfos; i++ ) {
- if( g_mmapInfos[i].start == start )
- break;
- }
- if( i == g_curMMapInfos ) {
- _set_errno( EINVAL );
- return -1;
- }
-
- UnmapViewOfFile( g_mmapInfos[i].start );
- CloseHandle( g_mmapInfos[i].hMap );
- CloseHandle( g_mmapInfos[i].hFile );
-
- EnterCriticalSection( &cs );
- for( j = i + 1; j < g_curMMapInfos; j++ ) {
- memcpy( &g_mmapInfos[ j - 1 ], &g_mmapInfos[ j ],
- sizeof( struct mmapInfos ) );
- }
- g_curMMapInfos--;
-
- if( g_curMMapInfos == 0 ) {
- free( g_mmapInfos );
- g_mmapInfos = NULL;
- g_maxMMapInfos = 0;
- }
- LeaveCriticalSection( &cs );
-
- return 0;
-}
diff --git a/samples/mmap-test.cpp b/samples/mmap-test.cpp
index ad99b9c..61257b6 100644
--- a/samples/mmap-test.cpp
+++ b/samples/mmap-test.cpp
@@ -25,7 +25,7 @@ try {
throw Error(10, path, "rb", strError());
}
// Map it to memory
- const byte* pData = file.mmap();
+ const Exiv2::byte* pData = file.mmap();
long size = file.size();
DataBuf buf(size);
// Read from the memory mapped region
diff --git a/src/basicio.cpp b/src/basicio.cpp
index 2fb785f..bd5b2c2 100644
--- a/src/basicio.cpp
+++ b/src/basicio.cpp
@@ -61,7 +61,13 @@ EXIV2_RCSID("@(#) $Id$")
# include <unistd.h> // for getpid, stat
#endif
+// MSVC doesn't provide mode_t
+#ifdef _MSC_VER
+typedef unsigned short mode_t;
+#endif
+
#if defined WIN32 && !defined __CYGWIN__
+# include <windows.h>
# include <io.h>
#endif
@@ -73,137 +79,298 @@ namespace Exiv2 {
{
}
- FileIo::FileIo(const std::string& path)
+ //! Internal Pimpl structure of class FileIo.
+ class FileIo::Impl {
+ public:
+ Impl(const std::string& path); //!< Constructor
+#ifdef EXV_UNICODE_PATH
+ Impl(const std::wstring& wpath); //!< Constructor
+#endif
+ // Enumeration
+ enum OpMode { opRead, opWrite, opSeek };
+#ifdef EXV_UNICODE_PATH
+ enum WpMode { wpStandard, wpUnicode };
+#endif
+ // DATA
+ std::string path_;
+#ifdef EXV_UNICODE_PATH
+ std::wstring wpath_;
+ WpMode wpMode_;
+#endif
+ std::string openMode_;
+ FILE *fp_;
+ OpMode opMode_;
+
+#if defined WIN32 && !defined __CYGWIN__
+ HANDLE hFile_; // Duplicated fd
+ HANDLE hMap_; // Handle from CreateFileMapping
+#endif
+ byte* pMappedArea_;
+ size_t mappedLength_;
+ bool isMalloced_; //!< Is the mapped area allocated?
+ bool isWriteable_; //!< Can the mapped area be written to?
+ // TYPES
+ //! Simple struct stat wrapper for internal use
+ struct StructStat {
+ StructStat() : st_mode(0), st_size(0) {}
+ mode_t st_mode; //!< Permissions
+ off_t st_size; //!< Size
+ };
+
+ // METHODS
+ /*!
+ @brief Switch to a new access mode, reopening the file if needed.
+ Optimized to only reopen the file when it is really necessary.
+ @param opMode The mode to switch to.
+ @return 0 if successful
+ */
+ int switchMode(OpMode opMode);
+ //! stat wrapper for internal use
+ int stat(StructStat& buf) const;
+
+ private:
+ // NOT IMPLEMENTED
+ Impl(const Impl& rhs); //!< Copy constructor
+ Impl& operator=(const Impl& rhs); //!< Assignment
+
+ }; // class FileIo::Impl
+
+ FileIo::Impl::Impl(const std::string& path)
: path_(path),
#ifdef EXV_UNICODE_PATH
wpMode_(wpStandard),
#endif
fp_(0), opMode_(opSeek),
+#if defined WIN32 && !defined __CYGWIN__
+ hFile_(0), hMap_(0),
+#endif
pMappedArea_(0), mappedLength_(0), isMalloced_(false), isWriteable_(false)
{
}
#ifdef EXV_UNICODE_PATH
- FileIo::FileIo(const std::wstring& wpath)
+ FileIo::Impl::Impl(const std::wstring& wpath)
: wpath_(wpath),
wpMode_(wpUnicode),
fp_(0), opMode_(opSeek),
+#if defined WIN32 && !defined __CYGWIN__
+ hFile_(0), hMap_(0),
+#endif
pMappedArea_(0), mappedLength_(0), isMalloced_(false), isWriteable_(false)
{
}
#endif
+ int FileIo::Impl::switchMode(OpMode opMode)
+ {
+ assert(fp_ != 0);
+ if (opMode_ == opMode) return 0;
+ OpMode oldOpMode = opMode_;
+ opMode_ = opMode;
+
+ bool reopen = true;
+ switch(opMode) {
+ case opRead:
+ // Flush if current mode allows reading, else reopen (in mode "r+b"
+ // as in this case we know that we can write to the file)
+ if (openMode_[0] == 'r' || openMode_[1] == '+') reopen = false;
+ break;
+ case opWrite:
+ // Flush if current mode allows writing, else reopen
+ if (openMode_[0] != 'r' || openMode_[1] == '+') reopen = false;
+ break;
+ case opSeek:
+ reopen = false;
+ break;
+ }
+
+ if (!reopen) {
+ // Don't do anything when switching _from_ opSeek mode; we
+ // flush when switching _to_ opSeek.
+ if (oldOpMode == opSeek) return 0;
+
+ // Flush. On msvcrt fflush does not do the job
+ std::fseek(fp_, 0, SEEK_CUR);
+ return 0;
+ }
+
+ // Reopen the file
+ long offset = std::ftell(fp_);
+ if (offset == -1) return -1;
+ // 'Manual' open("r+b") to avoid munmap()
+ if (fp_ != 0) {
+ std::fclose(fp_);
+ fp_= 0;
+ }
+ openMode_ = "r+b";
+ opMode_ = opSeek;
+ fp_ = std::fopen(path_.c_str(), openMode_.c_str());
+ if (!fp_) return 1;
+ return std::fseek(fp_, offset, SEEK_SET);
+ } // FileIo::Impl::switchMode
+
+ int FileIo::Impl::stat(StructStat& buf) const
+ {
+ int ret = 0;
+#ifdef EXV_UNICODE_PATH
+ if (wpMode_ == wpUnicode) {
+ struct _stat st;
+ ret = ::_wstat(wpath_.c_str(), &st);
+ if (0 == ret) {
+ buf.st_size = st.st_size;
+ buf.st_mode = st.st_mode;
+ }
+ }
+ else
+#endif
+ {
+ struct stat st;
+ ret = ::stat(path_.c_str(), &st);
+ if (0 == ret) {
+ buf.st_size = st.st_size;
+ buf.st_mode = st.st_mode;
+ }
+ }
+ return ret;
+ } // FileIo::Impl::stat
+
+ FileIo::FileIo(const std::string& path)
+ : p_(new Impl(path))
+ {
+ }
+
+#ifdef EXV_UNICODE_PATH
+ FileIo::FileIo(const std::wstring& wpath)
+ : p_(new Impl(wpath))
+ {
+ }
+
+#endif
FileIo::~FileIo()
{
close();
+ delete p_;
}
int FileIo::munmap()
{
int rc = 0;
- if (pMappedArea_ != 0) {
+ if (p_->pMappedArea_ != 0) {
#if defined EXV_HAVE_MMAP && defined EXV_HAVE_MUNMAP
- if (::munmap(pMappedArea_, mappedLength_) != 0) {
+ if (::munmap(p_->pMappedArea_, p_->mappedLength_) != 0) {
rc = 1;
}
+#elif defined WIN32 && !defined __CYGWIN__
+ UnmapViewOfFile(p_->pMappedArea_);
+ CloseHandle(p_->hMap_);
+ p_->hMap_ = 0;
+ CloseHandle(p_->hFile_);
+ p_->hFile_ = 0;
#else
- if (isWriteable_) {
- write(pMappedArea_, mappedLength_);
+ if (p_->isWriteable_) {
+ write(p_->pMappedArea_, p_->mappedLength_);
}
- if (isMalloced_) {
- delete[] pMappedArea_;
- isMalloced_ = false;
+ if (p_->isMalloced_) {
+ delete[] p_->pMappedArea_;
+ p_->isMalloced_ = false;
}
#endif
}
- if (isWriteable_) {
- if (fp_ != 0) switchMode(opRead);
- isWriteable_ = false;
+ if (p_->isWriteable_) {
+ if (p_->fp_ != 0) p_->switchMode(Impl::opRead);
+ p_->isWriteable_ = false;
}
- pMappedArea_ = 0;
- mappedLength_ = 0;
+ p_->pMappedArea_ = 0;
+ p_->mappedLength_ = 0;
return rc;
}
byte* FileIo::mmap(bool isWriteable)
{
- assert(fp_ != 0);
+ assert(p_->fp_ != 0);
if (munmap() != 0) {
- throw Error(2, path_, strError(), "munmap");
+ throw Error(2, p_->path_, strError(), "munmap");
}
- mappedLength_ = size();
- isWriteable_ = isWriteable;
+ p_->mappedLength_ = size();
+ p_->isWriteable_ = isWriteable;
+ if (p_->isWriteable_ && p_->switchMode(Impl::opWrite) != 0) return 0;
#if defined EXV_HAVE_MMAP && defined EXV_HAVE_MUNMAP
int prot = PROT_READ;
- if (isWriteable_) {
+ if (p_->isWriteable_) {
prot |= PROT_WRITE;
- if (switchMode(opWrite) != 0) return 0;
}
- void* rc = ::mmap(0, mappedLength_, prot, MAP_SHARED, fileno(fp_), 0);
+ void* rc = ::mmap(0, p_->mappedLength_, prot, MAP_SHARED, fileno(p_->fp_), 0);
if (MAP_FAILED == rc) {
- throw Error(2, path_, strError(), "mmap");
+ throw Error(2, p_->path_, strError(), "mmap");
+ }
+ p_->pMappedArea_ = static_cast<byte*>(rc);
+
+#elif defined WIN32 && !defined __CYGWIN__
+ // Windows implementation
+
+ // TODO: An attempt to map a file with a length of 0 (zero) fails with
+ // an error code of ERROR_FILE_INVALID.
+ // Applications should test for files with a length of 0 (zero) and
+ // reject those files.
+
+ DWORD dwAccess = FILE_MAP_READ;
+ DWORD flProtect = PAGE_READONLY;
+ if (isWriteable) {
+ dwAccess = FILE_MAP_WRITE;
+ flProtect = PAGE_READWRITE;
+ }
+ HANDLE hPh = GetCurrentProcess();
+ HANDLE hFd = (HANDLE)_get_osfhandle(fileno(p_->fp_));
+ if (hFd == INVALID_HANDLE_VALUE) {
+ throw Error(2, p_->path_, "MSG1", "_get_osfhandle");
}
- pMappedArea_ = static_cast<byte*>(rc);
+ if (!DuplicateHandle(hPh, hFd, hPh, &p_->hFile_, 0, false, DUPLICATE_SAME_ACCESS)) {
+ throw Error(2, p_->path_, "MSG2", "DuplicateHandle");
+ }
+ p_->hMap_ = CreateFileMapping(p_->hFile_, 0, flProtect, 0, p_->mappedLength_, 0);
+ if (p_->hMap_ == 0 ) {
+ throw Error(2, p_->path_, "MSG3", "CreateFileMapping");
+ }
+ void* rc = MapViewOfFile(p_->hMap_, dwAccess, 0, 0, 0);
+ if (rc == 0) {
+ throw Error(2, p_->path_, "MSG4", "CreateFileMapping");
+ }
+ p_->pMappedArea_ = static_cast<byte*>(rc);
#else
// Workaround for platforms without mmap: Read the file into memory
- DataBuf buf(static_cast<long>(mappedLength_));
+ DataBuf buf(static_cast<long>(p_->mappedLength_));
read(buf.pData_, buf.size_);
- if (error() || eof()) throw Error(2, path_, strError(), "FileIo::mmap");
- pMappedArea_ = buf.release().first;
- isMalloced_ = true;
-#endif
- return pMappedArea_;
- }
-
- int FileIo::stat(StructStat& buf) const
- {
- int ret = 0;
-#ifdef EXV_UNICODE_PATH
- if (wpMode_ == wpUnicode) {
- struct _stat st;
- ret = ::_wstat(wpath_.c_str(), &st);
- if (0 == ret) {
- buf.st_size = st.st_size;
- buf.st_mode = st.st_mode;
- }
- }
- else
+ if (error() || eof()) throw Error(2, p_->path_, strError(), "FileIo::mmap");
+ p_->pMappedArea_ = buf.release().first;
+ p_->isMalloced_ = true;
#endif
- {
- struct stat st;
- ret = ::stat(path_.c_str(), &st);
- if (0 == ret) {
- buf.st_size = st.st_size;
- buf.st_mode = st.st_mode;
- }
- }
- return ret;
+ return p_->pMappedArea_;
}
BasicIo::AutoPtr FileIo::temporary() const
{
BasicIo::AutoPtr basicIo;
- StructStat buf;
- int ret = stat(buf);
+ Impl::StructStat buf;
+ int ret = p_->stat(buf);
// If file is > 1MB then use a file, otherwise use memory buffer
if (ret != 0 || buf.st_size > 1048576) {
pid_t pid = ::getpid();
std::auto_ptr<FileIo> fileIo;
#ifdef EXV_UNICODE_PATH
- if (wpMode_ == wpUnicode) {
- std::wstring tmpname = wpath_ + s2ws(toString(pid));
+ if (p_->wpMode_ == Impl::wpUnicode) {
+ std::wstring tmpname = p_->wpath_ + s2ws(toString(pid));
fileIo = std::auto_ptr<FileIo>(new FileIo(tmpname));
}
else
#endif
{
- std::string tmpname = path_ + toString(pid);
+ std::string tmpname = p_->path_ + toString(pid);
fileIo = std::auto_ptr<FileIo>(new FileIo(tmpname));
}
if (fileIo->open("w+b") != 0) {
- throw Error(10, path_, "w+b", strError());
+ throw Error(10, p_->path_, "w+b", strError());
}
basicIo = fileIo;
}
@@ -214,74 +381,26 @@ namespace Exiv2 {
return basicIo;
}
- int FileIo::switchMode(OpMode opMode)
- {
- assert(fp_ != 0);
- if (opMode_ == opMode) return 0;
- OpMode oldOpMode = opMode_;
- opMode_ = opMode;
-
- bool reopen = true;
- switch(opMode) {
- case opRead:
- // Flush if current mode allows reading, else reopen (in mode "r+b"
- // as in this case we know that we can write to the file)
- if (openMode_[0] == 'r' || openMode_[1] == '+') reopen = false;
- break;
- case opWrite:
- // Flush if current mode allows writing, else reopen
- if (openMode_[0] != 'r' || openMode_[1] == '+') reopen = false;
- break;
- case opSeek:
- reopen = false;
- break;
- }
-
- if (!reopen) {
- // Don't do anything when switching _from_ opSeek mode; we
- // flush when switching _to_ opSeek.
- if (oldOpMode == opSeek) return 0;
-
- // Flush. On msvcrt fflush does not do the job
- std::fseek(fp_, 0, SEEK_CUR);
- return 0;
- }
-
- // Reopen the file
- long offset = std::ftell(fp_);
- if (offset == -1) return -1;
- // 'Manual' open("r+b") to avoid munmap()
- if (fp_ != 0) {
- std::fclose(fp_);
- fp_= 0;
- }
- openMode_ = "r+b";
- opMode_ = opSeek;
- fp_ = std::fopen(path_.c_str(), openMode_.c_str());
- if (!fp_) return 1;
- return std::fseek(fp_, offset, SEEK_SET);
- }
-
long FileIo::write(const byte* data, long wcount)
{
- assert(fp_ != 0);
- if (switchMode(opWrite) != 0) return 0;
- return (long)std::fwrite(data, 1, wcount, fp_);
+ assert(p_->fp_ != 0);
+ if (p_->switchMode(Impl::opWrite) != 0) return 0;
+ return (long)std::fwrite(data, 1, wcount, p_->fp_);
}
long FileIo::write(BasicIo& src)
{
- assert(fp_ != 0);
+ assert(p_->fp_ != 0);
if (static_cast<BasicIo*>(this) == &src) return 0;
if (!src.isopen()) return 0;
- if (switchMode(opWrite) != 0) return 0;
+ if (p_->switchMode(Impl::opWrite) != 0) return 0;
byte buf[4096];
long readCount = 0;
long writeCount = 0;
long writeTotal = 0;
while ((readCount = src.read(buf, sizeof(buf)))) {
- writeTotal += writeCount = (long)std::fwrite(buf, 1, readCount, fp_);
+ writeTotal += writeCount = (long)std::fwrite(buf, 1, readCount, p_->fp_);
if (writeCount != readCount) {
// try to reset back to where write stopped
src.seek(writeCount-readCount, BasicIo::cur);
@@ -294,8 +413,8 @@ namespace Exiv2 {
void FileIo::transfer(BasicIo& src)
{
- const bool wasOpen = (fp_ != 0);
- const std::string lastMode(openMode_);
+ const bool wasOpen = (p_->fp_ != 0);
+ const std::string lastMode(p_->openMode_);
FileIo *fileIo = dynamic_cast<FileIo*>(&src);
if (fileIo) {
@@ -305,15 +424,15 @@ namespace Exiv2 {
if (open("w+b") != 0) {
// Remove the (temporary) file
#ifdef EXV_UNICODE_PATH
- if (fileIo->wpMode_ == wpUnicode) {
- ::_wremove(fileIo->wpath_.c_str());
+ if (fileIo->p_->wpMode_ == Impl::wpUnicode) {
+ ::_wremove(fileIo->p_->wpath_.c_str());
}
else
#endif
{
- ::remove(fileIo->path_.c_str());
+ ::remove(fileIo->p_->path_.c_str());
}
- throw Error(10, path_, "w+b", strError());
+ throw Error(10, p_->path_, "w+b", strError());
}
close();
@@ -322,13 +441,13 @@ namespace Exiv2 {
char* pf = 0;
#ifdef EXV_UNICODE_PATH
wchar_t* wpf = 0;
- if (wpMode_ == wpUnicode) {
- wpf = const_cast<wchar_t*>(wpath_.c_str());
+ if (p_->wpMode_ == Impl::wpUnicode) {
+ wpf = const_cast<wchar_t*>(p_->wpath_.c_str());
}
else
#endif
{
- pf = const_cast<char*>(path_.c_str());
+ pf = const_cast<char*>(p_->path_.c_str());
}
// Get the permissions of the file, or linked-to file, on platforms which have lstat
@@ -346,13 +465,13 @@ namespace Exiv2 {
}
origStMode = buf1.st_mode;
DataBuf lbuf; // So that the allocated memory is freed. Must have same scope as pf
- // In case path_ is a symlink, get the path of the linked-to file
+ // In case p_->path_ is a symlink, get the path of the linked-to file
if (statOk && S_ISLNK(buf1.st_mode)) {
lbuf.alloc(buf1.st_size + 1);
memset(lbuf.pData_, 0x0, lbuf.size_);
pf = reinterpret_cast<char*>(lbuf.pData_);
- if (::readlink(path_.c_str(), pf, lbuf.size_ - 1) == -1) {
- throw Error(2, path_, strError(), "readlink");
+ if (::readlink(p_->path_.c_str(), pf, lbuf.size_ - 1) == -1) {
+ throw Error(2, p_->path_, strError(), "readlink");
}
// We need the permissions of the file, not the symlink
if (::stat(pf, &buf1) == -1) {
@@ -364,8 +483,8 @@ namespace Exiv2 {
origStMode = buf1.st_mode;
}
#else // EXV_HAVE_LSTAT
- StructStat buf1;
- if (stat(buf1) == -1) {
+ Impl::StructStat buf1;
+ if (p_->stat(buf1) == -1) {
statOk = false;
}
origStMode = buf1.st_mode;
@@ -373,14 +492,14 @@ namespace Exiv2 {
// MSVCRT rename that does not overwrite existing files
#ifdef EXV_UNICODE_PATH
- if (wpMode_ == wpUnicode) {
+ if (p_->wpMode_ == Impl::wpUnicode) {
if (fileExists(wpf) && ::_wremove(wpf) != 0) {
throw Error(2, wpf, strError(), "::_wremove");
}
- if (::_wrename(fileIo->wpath_.c_str(), wpf) == -1) {
- throw Error(17, ws2s(fileIo->wpath_), wpf, strError());
+ if (::_wrename(fileIo->p_->wpath_.c_str(), wpf) == -1) {
+ throw Error(17, ws2s(fileIo->p_->wpath_), wpf, strError());
}
- ::_wremove(fileIo->wpath_.c_str());
+ ::_wremove(fileIo->p_->wpath_.c_str());
// Check permissions of new file
struct _stat buf2;
if (statOk && ::_wstat(wpf, &buf2) == -1) {
@@ -397,17 +516,17 @@ namespace Exiv2 {
#endif
}
}
- } // if (wpMode_ == wpUnicode)
+ } // if (p_->wpMode_ == Impl::wpUnicode)
else
#endif // EXV_UNICODE_PATH
{
if (fileExists(pf) && ::remove(pf) != 0) {
throw Error(2, pf, strError(), "::remove");
}
- if (::rename(fileIo->path_.c_str(), pf) == -1) {
- throw Error(17, fileIo->path_, pf, strError());
+ if (::rename(fileIo->p_->path_.c_str(), pf) == -1) {
+ throw Error(17, fileIo->p_->path_, pf, strError());
}
- ::remove(fileIo->path_.c_str());
+ ::remove(fileIo->p_->path_.c_str());
// Check permissions of new file
struct stat buf2;
if (statOk && ::stat(pf, &buf2) == -1) {
@@ -429,7 +548,7 @@ namespace Exiv2 {
else {
// Generic handling, reopen both to reset to start
if (open("w+b") != 0) {
- throw Error(10, path_, "w+b", strError());
+ throw Error(10, p_->path_, "w+b", strError());
}
if (src.open() != 0) {
throw Error(9, src.path(), strError());
@@ -440,24 +559,24 @@ namespace Exiv2 {
if (wasOpen) {
if (open(lastMode) != 0) {
- throw Error(10, path_, lastMode, strError());
+ throw Error(10, p_->path_, lastMode, strError());
}
}
else close();
- if (error() || src.error()) throw Error(18, path_, strError());
+ if (error() || src.error()) throw Error(18, p_->path_, strError());
}
int FileIo::putb(byte data)
{
- assert(fp_ != 0);
- if (switchMode(opWrite) != 0) return EOF;
- return putc(data, fp_);
+ assert(p_->fp_ != 0);
+ if (p_->switchMode(Impl::opWrite) != 0) return EOF;
+ return putc(data, p_->fp_);
}
int FileIo::seek(long offset, Position pos)
{
- assert(fp_ != 0);
+ assert(p_->fp_ != 0);
int fileSeek = 0;
switch (pos) {
@@ -466,30 +585,29 @@ namespace Exiv2 {
case BasicIo::end: fileSeek = SEEK_END; break;
}
- if (switchMode(opSeek) != 0) return 1;
- return std::fseek(fp_, offset, fileSeek);
+ if (p_->switchMode(Impl::opSeek) != 0) return 1;
+ return std::fseek(p_->fp_, offset, fileSeek);
}
long FileIo::tell() const
{
- assert(fp_ != 0);
- return std::ftell(fp_);
+ assert(p_->fp_ != 0);
+ return std::ftell(p_->fp_);
}
-
long FileIo::size() const
{
// Flush and commit only if the file is open for writing
- if (fp_ != 0 && (openMode_[0] != 'r' || openMode_[1] == '+')) {
- std::fflush(fp_);
+ if (p_->fp_ != 0 && (p_->openMode_[0] != 'r' || p_->openMode_[1] == '+')) {
+ std::fflush(p_->fp_);
#if defined WIN32 && !defined __CYGWIN__
// This is required on msvcrt before stat after writing to a file
- _commit(_fileno(fp_));
+ _commit(_fileno(p_->fp_));
#endif
}
- StructStat buf;
- int ret = stat(buf);
+ Impl::StructStat buf;
+ int ret = p_->stat(buf);
if (ret != 0) return -1;
return buf.st_size;
@@ -504,40 +622,40 @@ namespace Exiv2 {
int FileIo::open(const std::string& mode)
{
close();
- openMode_ = mode;
- opMode_ = opSeek;
+ p_->openMode_ = mode;
+ p_->opMode_ = Impl::opSeek;
#ifdef EXV_UNICODE_PATH
- if (wpMode_ == wpUnicode) {
- fp_ = ::_wfopen(wpath_.c_str(), s2ws(mode).c_str());
+ if (p_->wpMode_ == Impl::wpUnicode) {
+ p_->fp_ = ::_wfopen(p_->wpath_.c_str(), s2ws(mode).c_str());
}
else
#endif
{
- fp_ = ::fopen(path_.c_str(), mode.c_str());
+ p_->fp_ = ::fopen(p_->path_.c_str(), mode.c_str());
}
- if (!fp_) return 1;
+ if (!p_->fp_) return 1;
return 0;
}
bool FileIo::isopen() const
{
- return fp_ != 0;
+ return p_->fp_ != 0;
}
int FileIo::close()
{
int rc = 0;
if (munmap() != 0) rc = 2;
- if (fp_ != 0) {
- if (std::fclose(fp_) != 0) rc |= 1;
- fp_= 0;
+ if (p_->fp_ != 0) {
+ if (std::fclose(p_->fp_) != 0) rc |= 1;
+ p_->fp_= 0;
}
return rc;
}
DataBuf FileIo::read(long rcount)
{
- assert(fp_ != 0);
+ assert(p_->fp_ != 0);
DataBuf buf(rcount);
long readCount = read(buf.pData_, buf.size_);
buf.size_ = readCount;
@@ -546,46 +664,46 @@ namespace Exiv2 {
long FileIo::read(byte* buf, long rcount)
{
- assert(fp_ != 0);
- if (switchMode(opRead) != 0) return 0;
- return (long)std::fread(buf, 1, rcount, fp_);
+ assert(p_->fp_ != 0);
+ if (p_->switchMode(Impl::opRead) != 0) return 0;
+ return (long)std::fread(buf, 1, rcount, p_->fp_);
}
int FileIo::getb()
{
- assert(fp_ != 0);
- if (switchMode(opRead) != 0) return EOF;
- return getc(fp_);
+ assert(p_->fp_ != 0);
+ if (p_->switchMode(Impl::opRead) != 0) return EOF;
+ return getc(p_->fp_);
}
int FileIo::error() const
{
- return fp_ != 0 ? ferror(fp_) : 0;
+ return p_->fp_ != 0 ? ferror(p_->fp_) : 0;
}
bool FileIo::eof() const
{
- assert(fp_ != 0);
- return feof(fp_) != 0;
+ assert(p_->fp_ != 0);
+ return feof(p_->fp_) != 0;
}
std::string FileIo::path() const
{
#ifdef EXV_UNICODE_PATH
- if (wpMode_ == wpUnicode) {
- return ws2s(wpath_);
+ if (p_->wpMode_ == Impl::wpUnicode) {
+ return ws2s(p_->wpath_);
}
#endif
- return path_;
+ return p_->path_;
}
#ifdef EXV_UNICODE_PATH
std::wstring FileIo::wpath() const
{
- if (wpMode_ == wpStandard) {
- return s2ws(path_);
+ if (p_->wpMode_ == Impl::wpStandard) {
+ return s2ws(p_->path_);
}
- return wpath_;
+ return p_->wpath_;
}
#endif
@@ -627,7 +745,7 @@ namespace Exiv2 {
if (!isMalloced_) {
// Minimum size for 1st block is 32kB
- long size = std::max(32768 * (1 + need / 32768), size_);
+ long size = EXV_MAX(32768 * (1 + need / 32768), size_);
byte* data = (byte*)std::malloc(size);
std::memcpy(data, data_, size_);
data_ = data;
@@ -773,7 +891,7 @@ namespace Exiv2 {
long MemIo::read(byte* buf, long rcount)
{
long avail = size_ - idx_;
- long allow = std::min(rcount, avail);
+ long allow = EXV_MIN(rcount, avail);
std::memcpy(buf, &data_[idx_], allow);
idx_ += allow;
if (rcount > avail) eof_ = true;
diff --git a/src/basicio.hpp b/src/basicio.hpp
index 7c6d57d..6fe87b0 100644
--- a/src/basicio.hpp
+++ b/src/basicio.hpp
@@ -35,15 +35,6 @@
// + standard includes
#include <string>
-#include <memory>
-#include <cstdio>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-// MSVC doesn't provide mode_t
-#ifdef _MSC_VER
-typedef unsigned short mode_t;
-#endif
// *****************************************************************************
// namespace extensions
@@ -505,44 +496,9 @@ namespace Exiv2 {
//! Assignment operator
FileIo& operator=(const FileIo& rhs);
- // Enumeration
- enum OpMode { opRead, opWrite, opSeek };
-#ifdef EXV_UNICODE_PATH
- enum WpMode { wpStandard, wpUnicode };
-#endif
- // DATA
- std::string path_;
-#ifdef EXV_UNICODE_PATH
- std::wstring wpath_;
- WpMode wpMode_;
-#endif
- std::string openMode_;
- FILE *fp_;
- OpMode opMode_;
-
- byte* pMappedArea_;
- size_t mappedLength_;
- bool isMalloced_; //!< Is the mapped area allocated?
- bool isWriteable_; //!< Can the mapped area be written to?
-
- // TYPES
- //! Simple struct stat wrapper for internal use
- struct StructStat {
- StructStat() : st_mode(0), st_size(0) {}
- mode_t st_mode; //!< Permissions
- off_t st_size; //!< Size
- };
-
- // METHODS
- /*!
- @brief Switch to a new access mode, reopening the file if needed.
- Optimized to only reopen the file when it is really necessary.
- @param opMode The mode to switch to.
- @return 0 if successful
- */
- EXV_DLLLOCAL int switchMode(OpMode opMode);
- //! stat wrapper for internal use
- EXV_DLLLOCAL int stat(StructStat& buf) const;
+ // Pimpl idiom
+ class Impl;
+ Impl* p_;
}; // class FileIo
diff --git a/src/tiffcomposite.cpp b/src/tiffcomposite.cpp
index e4a173f..8ee15d0 100644
--- a/src/tiffcomposite.cpp
+++ b/src/tiffcomposite.cpp
@@ -635,7 +635,7 @@ namespace Exiv2 {
assert(def != 0);
uint16_t tag = static_cast<uint16_t>(idx / cfg()->tagStep());
- int32_t sz = std::min(def->size(tag, cfg()->group_), TiffEntryBase::doSize() - idx);
+ int32_t sz = EXV_MIN(def->size(tag, cfg()->group_), TiffEntryBase::doSize() - idx);
TiffComponent::AutoPtr tc = TiffCreator::create(tag, cfg()->group_);
TiffBinaryElement* tp = dynamic_cast<TiffBinaryElement*>(tc.get());
// The assertion typically fails if a component is not configured in
@@ -1674,13 +1674,13 @@ namespace Exiv2 {
uint32_t idx = 0;
for (Components::const_iterator i = elements_.begin(); i != elements_.end(); ++i) {
- idx = std::max(idx, (*i)->tag() * cfg()->tagStep());
+ idx = EXV_MAX(idx, (*i)->tag() * cfg()->tagStep());
idx += (*i)->size();
}
if (cfg()->hasFillers_ && def()) {
const ArrayDef* lastDef = def() + defSize() - 1;
uint16_t lastTag = static_cast<uint16_t>(lastDef->idx_ / cfg()->tagStep());
- idx = std::max(idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
+ idx = EXV_MAX(idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
}
return idx;
diff --git a/src/types.hpp b/src/types.hpp
index f10e5f5..3e1575c 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -73,6 +73,10 @@ typedef __int32 int32_t;
*/
#define EXV_CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+// Simple min and max macros
+#define EXV_MIN(a,b) ((a) < (b) ? (a) : (b))
+#define EXV_MAX(a,b) ((a) > (b) ? (a) : (b))
+
// *****************************************************************************
// forward declarations
struct tm;
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list