[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