summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format57
-rw-r--r--.gitignore61
-rw-r--r--.travis.yml34
-rw-r--r--AUTHORS14
-rw-r--r--COPYING32
-rw-r--r--ChangeLog339
-rw-r--r--ChangeLog-pre.1.99.222
-rw-r--r--ChangeLog-pre.1.99.321
-rw-r--r--ChangeLog-pre.1.99.412
-rw-r--r--ChangeLog-pre.1.99.522
-rw-r--r--ChangeLog-pre.1.99.637
-rw-r--r--INSTALL234
-rw-r--r--Makefile.am42
-rw-r--r--NEWS215
-rw-r--r--README15
-rw-r--r--TODO9
-rw-r--r--XMPCore/Makefile.am3
-rw-r--r--XMPCore/source/ExpatAdapter.cpp2
-rw-r--r--XMPCore/source/Makefile.am64
-rw-r--r--XMPCore/source/ParseRDF.cpp52
-rw-r--r--XMPCore/source/XMPCore_Impl.cpp1
-rw-r--r--XMPCore/source/XMPCore_Impl.hpp2
-rw-r--r--XMPCore/source/XMPIterator.cpp9
-rw-r--r--XMPCore/source/XMPMeta-GetSet.cpp2
-rw-r--r--XMPCore/source/XMPMeta-Serialize.cpp18
-rw-r--r--XMPCore/source/XMPMeta.cpp11
-rw-r--r--XMPCore/source/XMPMeta.hpp2
-rw-r--r--XMPCore/source/XMPUtils.cpp7
-rw-r--r--XMPFiles/Makefile.am3
-rw-r--r--XMPFiles/source/FileHandlers/AIFF_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/MP3_Handler.cpp4
-rw-r--r--XMPFiles/source/FileHandlers/Makefile.am73
-rw-r--r--XMPFiles/source/FileHandlers/P2_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/PSD_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/PSD_Handler.hpp2
-rw-r--r--XMPFiles/source/FileHandlers/UCF_Handler.hpp23
-rw-r--r--XMPFiles/source/FileHandlers/WAVE_Handler.cpp2
-rw-r--r--XMPFiles/source/FileHandlers/WEBP_Handler.cpp197
-rw-r--r--XMPFiles/source/FileHandlers/WEBP_Handler.hpp48
-rw-r--r--XMPFiles/source/FormatSupport/GIF_Support.cpp352
-rw-r--r--XMPFiles/source/FormatSupport/GIF_Support.hpp71
-rw-r--r--XMPFiles/source/FormatSupport/ID3_Support.cpp23
-rw-r--r--XMPFiles/source/FormatSupport/ID3_Support.hpp19
-rw-r--r--XMPFiles/source/FormatSupport/IFF/Chunk.cpp3
-rw-r--r--XMPFiles/source/FormatSupport/IFF/ChunkController.cpp4
-rw-r--r--XMPFiles/source/FormatSupport/IPTC_Support.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/Makefile.am82
-rw-r--r--XMPFiles/source/FormatSupport/P2_Support.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/P2_Support.hpp4
-rw-r--r--XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/ReconcileTIFF.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/Reconcile_Impl.cpp2
-rw-r--r--XMPFiles/source/FormatSupport/Reconcile_Impl.hpp2
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp1
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp4
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_Support.cpp10
-rw-r--r--XMPFiles/source/FormatSupport/TIFF_Support.hpp4
-rw-r--r--XMPFiles/source/FormatSupport/WAVE/iXMLMetadata.cpp4
-rw-r--r--XMPFiles/source/FormatSupport/WEBP_Support.cpp273
-rw-r--r--XMPFiles/source/FormatSupport/WEBP_Support.hpp174
-rw-r--r--XMPFiles/source/FormatSupport/XMPScanner.cpp22
-rw-r--r--XMPFiles/source/FormatSupport/XMPScanner.hpp2
-rw-r--r--XMPFiles/source/HandlerRegistry.cpp3
-rw-r--r--XMPFiles/source/Makefile.am57
-rw-r--r--XMPFiles/source/NativeMetadataSupport/Makefile.am51
-rw-r--r--XMPFiles/source/NativeMetadataSupport/ValueObject.h2
-rw-r--r--XMPFiles/source/PluginHandler/FileHandler.h2
-rw-r--r--XMPFiles/source/PluginHandler/Makefile.am61
-rw-r--r--XMPFiles/source/PluginHandler/XMPAtoms.h2
-rw-r--r--XMPFiles/source/XMPFiles_Impl.cpp3
-rw-r--r--XMPFiles/source/XMPFiles_Impl.hpp6
-rw-r--r--XMPFilesPlugins/Makefile.am4
-rw-r--r--XMPFilesPlugins/PDF_Handler/Makefile.am3
-rw-r--r--XMPFilesPlugins/PDF_Handler/README.exempi6
-rw-r--r--XMPFilesPlugins/api/Makefile.am2
-rw-r--r--XMPFilesPlugins/api/source/Makefile.am13
-rwxr-xr-xautogen.sh52
-rw-r--r--build/GNUmakefile.am37
-rw-r--r--configure.ac268
-rw-r--r--debian/changelog12
-rw-r--r--debian/compat1
-rw-r--r--debian/control32
-rw-r--r--debian/copyright36
-rw-r--r--debian/libexempi-dev.install3
-rw-r--r--debian/libexempi2.install1
-rwxr-xr-xdebian/rules7
-rw-r--r--exempi/Makefile.am79
-rw-r--r--exempi/doc/Doxyfile.in1869
-rw-r--r--exempi/doc/Makefile.am38
-rw-r--r--exempi/exempi-2.0.pc.in12
-rw-r--r--exempi/exempi.140
-rw-r--r--exempi/exempi.cpp1170
-rw-r--r--exempi/libexempi.sym67
-rw-r--r--exempi/main.cpp357
-rw-r--r--exempi/tests/Makefile.am110
-rw-r--r--exempi/tests/fdo18635.jpgbin0 -> 216859 bytes
-rw-r--r--exempi/tests/fdo83313.jpgbin0 -> 18340 bytes
-rw-r--r--exempi/tests/test-bgo.cpp74
-rw-r--r--exempi/tests/test-exempi-core.cpp231
-rw-r--r--exempi/tests/test-fdo83313.cpp74
-rw-r--r--exempi/tests/test-serialise.cpp102
-rw-r--r--exempi/tests/test-tiff-leak.cpp86
-rw-r--r--exempi/tests/test-webp.cpp119
-rw-r--r--exempi/tests/test-write-new-prop.cpp150
-rw-r--r--exempi/tests/test-xmpfiles-write.cpp120
-rw-r--r--exempi/tests/test-xmpfiles.cpp129
-rw-r--r--exempi/tests/test1.xmp255
-rw-r--r--exempi/tests/test3.cpp115
-rwxr-xr-xexempi/tests/testcore.sh29
-rw-r--r--exempi/tests/testcpp.cpp69
-rw-r--r--exempi/tests/testinit.cpp94
-rw-r--r--exempi/tests/utils.cpp119
-rw-r--r--exempi/tests/utils.h69
-rw-r--r--exempi/xmp++.hpp61
-rw-r--r--exempi/xmp.h742
-rw-r--r--exempi/xmpconsts.h69
-rw-r--r--exempi/xmperrors.h86
-rw-r--r--m4/ax_cflags_gcc_option.m4230
-rw-r--r--m4/ax_cxx_compile_stdcxx_11.m4133
-rw-r--r--m4/ax_ld_check_flag.m496
-rw-r--r--m4/ax_tls.m478
-rw-r--r--m4/boost.m41560
-rw-r--r--m4/shave.m440
-rw-r--r--public/Makefile.am38
-rw-r--r--public/include/Makefile.am50
-rw-r--r--public/include/XMP_Const.h4
-rw-r--r--public/include/XMP_IO.hpp2
-rw-r--r--public/include/XMP_UnixEndian.h32
-rw-r--r--public/include/client-glue/Makefile.am40
-rw-r--r--public/include/client-glue/WXMPFiles.hpp4
-rw-r--r--public/include/client-glue/WXMPMeta.hpp2
-rw-r--r--rpm/SLED10.spec54
-rw-r--r--samples/BlueSquares/BlueSquare.gifbin0 -> 3858 bytes
-rw-r--r--samples/BlueSquares/Makefile.am39
-rw-r--r--samples/Makefile.am39
-rw-r--r--samples/source/Makefile.am94
-rw-r--r--samples/source/ModifyingXMP.cpp1
-rw-r--r--samples/source/common/TagTree.cpp4
-rw-r--r--samples/source/common/XMPScanner.cpp18
-rw-r--r--samples/source/common/XMPScanner.hpp2
-rw-r--r--samples/source/common/globals.h9
-rw-r--r--samples/source/xmpcommand/Actions.h5
-rw-r--r--samples/source/xmpcommand/PrintUsage.cpp6
-rw-r--r--samples/source/xmpcommand/PrintUsage.h4
-rw-r--r--samples/testfiles/BlueSquare.gifbin0 -> 3858 bytes
-rw-r--r--samples/testfiles/BlueSquare.webpbin0 -> 4974 bytes
-rw-r--r--samples/testfiles/Makefile.am39
-rw-r--r--source/EndianUtils.hpp11
-rw-r--r--source/Host_IO-POSIX.cpp4
-rw-r--r--source/Makefile.am60
-rw-r--r--source/XIO.cpp8
-rw-r--r--source/XMLParserAdapter.hpp4
-rw-r--r--source/XMPFiles_IO.cpp2
-rw-r--r--source/XMP_LibUtils.hpp6
-rw-r--r--third-party/Makefile.am4
-rw-r--r--third-party/expat/Makefile.am3
-rw-r--r--third-party/expat/lib/expat.h3
-rw-r--r--third-party/zlib/Makefile.am3
-rw-r--r--third-party/zlib/zlib.h2
-rw-r--r--third-party/zuid/interfaces/Makefile.am50
160 files changed, 12545 insertions, 198 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..b4742c8
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,57 @@
+---
+Language: Cpp
+# BasedOnStyle: Mozilla
+AccessModifierOffset: -4
+ConstructorInitializerIndentWidth: 2
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AlwaysBreakTemplateDeclarations: true
+AlwaysBreakBeforeMultilineStrings: false
+BreakBeforeBinaryOperators: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: true
+BinPackParameters: true
+ColumnLimit: 80
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+DerivePointerAlignment: true
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: false
+IndentWrappedFunctionNames: false
+IndentFunctionDeclarationAfterType: false
+MaxEmptyLinesToKeep: 1
+KeepEmptyLinesAtTheStartOfBlocks: true
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakString: 1000
+PenaltyBreakFirstLessLess: 120
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+SpacesBeforeTrailingComments: 1
+Cpp11BracedListStyle: false
+Standard: Cpp11
+IndentWidth: 4
+TabWidth: 8
+UseTab: Never
+BreakBeforeBraces: Stroustrup
+SpacesInParentheses: false
+SpacesInAngles: false
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: true
+SpaceBeforeAssignmentOperators: true
+ContinuationIndentWidth: 4
+CommentPragmas: '^ IWYU pragma:'
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+SpaceBeforeParens: ControlStatements
+DisableFormat: false
+...
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..41ca6de
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,61 @@
+Makefile
+Makefile.in
+GNUmakefile
+GNUmakefile.in
+TAGS
+*~
+TAGS
+config.guess
+config.sub
+config.log
+config.status
+aclocal.m4
+autogen.err
+configure
+depcomp
+install-sh
+ltmain.sh
+missing
+autom4te.cache
+stamp-h1
+shave
+shave-libtool
+*.o
+*.lo
+*.la
+.libs
+.deps
+.git
+compile
+libtool
+test-driver
+*.plist/
+exempi/exempi-2.0.pc
+exempi/exempi
+exempi/tests/test.jpg
+exempi/tests/test.webp
+exempi/tests/testexempicore
+exempi/tests/testserialise
+exempi/tests/testwritenewprop
+exempi/tests/testtiffleak
+exempi/tests/testxmpfiles
+exempi/tests/testxmpfileswrite
+exempi/tests/test2
+exempi/tests/test3
+exempi/tests/testinit
+exempi/tests/testfdo18635
+exempi/tests/testfdo83313
+exempi/tests/testcpp
+exempi/tests/testwebp
+exempi/tests/test*.log
+exempi/tests/test*.trs
+exempi/doc/Doxyfile
+samples/source/dumpmainxmp
+samples/source/dumpxmp
+samples/source/xmpcoverage
+samples/source/xmpfilescoverage
+samples/source/customschema
+samples/source/modifyingxmp
+samples/source/readingxmp
+samples/source/xmpcommandtool
+samples/source/xmpcoverageLog.txt
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b04c954
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,34 @@
+dist: trusty
+language: cpp
+matrix:
+ include:
+ - compiler: gcc
+ env: COMPILER=g++
+ - compiler: gcc
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - libboost-test-dev
+ - g++-5
+ env: COMPILER=g++-5
+ - compiler: gcc
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - libboost-test-dev
+ - g++-6
+ env: COMPILER=g++-6
+ - compiler: clang
+ env: COMPILER=clang++
+addons:
+ apt:
+ packages:
+ - libboost-test-dev
+script:
+ - ./autogen.sh
+ - make
+ - make check \ No newline at end of file
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..482c2f5
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,14 @@
+The package is based on Adobe XMP SDK CS6
+
+Maintainer:
+Hubert Figuiere <hub@figuiere.net>
+
+Original XMP code by:
+Adobe Systems Incorporated (XMP SDK)
+
+Contributions by:
+Ian Jacobi
+Jason Kivlighn
+Michael Biebl <biebl@debian.org>
+Tim Mooney
+Misty De Meo
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..e7439c9
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,32 @@
+This package is based off Adobe XMP SDK CD6, distributed
+under the BSD license reproduced thereafter for convenience
+and available in BSD-License.txt
+
+This package is licensed under the same license.
+
+
+The BSD License
+
+Copyright (c) 1999 - 2010, Adobe Systems Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems Incorporated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..047887b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,339 @@
+2009-05-26 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FileHandlers/UCF_Handler.cpp (UCF_CheckFormat):
+ Mismatched new [] / delete. (Closes bug #21934)
+
+2009-05-15 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp:
+ Catch unhandled exceptions in xmp_files_can_put_xmp()
+ (Closes bug #20622)
+
+2009-03-11 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac:
+ * exempi/Makefile.am:
+ * m4/ax_ld_check_flag.m4:
+ Detect proper ldflags. (Closes bug #20554)
+
+ * configure.ac: Bump to version 2.1.1
+
+2009-03-11 Lars Holm Nielsen <lnielsen@eso.org>
+
+ * source/XMPFiles/FileHandlers/Makefile.am:
+ * source/XMPFiles/FormatSupport/Makefile.am:
+ * configure.ac:
+ Some files missing when building on Mac
+ (Closes bug #20554)
+
+2009-02-24 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp (xmp_set_property):
+ If the value is struct or array, if the property value
+ is the empty string pass NULL.
+ (Closes bug #16030)
+
+2009-02-22 Hubert Figuiere <hub@figuiere.net>
+
+ * source/common/XMLParserAdapter.hpp:
+ Remove an annoying warning.
+
+2009-02-20 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.in:
+ * m4/shave.m4:
+ * shave-libtool.in:
+ * shave.in:
+ Add shave to make the build output saner.
+
+2008-12-28 Michael Biebl <biebl@debian.org>
+
+ * tests/utils.cpp
+ * samples/source/XMPFilesCoverage.cpp
+ * source/common/XML_Node.cpp
+ Fix build on gcc 4.4
+
+2008-12-24 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FileHandlers/P2_Handler.cpp (SetStartTimecodeFromLegacyXML):
+ Don't compare string pointers. (Closes: #19312)
+
+=== 2.1.0 ===
+
+2008-12-24 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/test-bgo.cpp
+ * exempi/tests/test-xmpfiles.cpp
+ Remove serious warnings.
+
+2008-12-21 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/Makefile.am
+ * exempi/tests/test-bgo.cpp
+ * exempi/tests/test-exempi-core.cpp
+ * exempi/tests/test-serialise.cpp
+ * exempi/tests/test-tiff-leak.cpp
+ * exempi/tests/test-write-new-prop.cpp
+ * exempi/tests/test-xmpfiles-write.cpp
+ * exempi/tests/test-xmpfiles.cpp
+ * exempi/tests/test3.cpp
+ * exempi/tests/testinit.cpp
+ Migrated to use boost/test/minimal
+
+ * exempi/tests/test1.cpp
+ * exempi/tests/test2.cpp
+ Split out for the above change.
+
+2008-12-19 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/Makefile.am (EXTRA_DIST): Added libexempi.sym
+
+2008-11-26 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/Makefile.am (TESTS_ENVIRONMENT):
+ BOOST_TEST_CATCH_SYSTEM_ERRORS=no is set before running
+ the test. This avoid a failure because of system() on
+ boost 1.35 and later.
+ See https://svn.boost.org/trac/boost/ticket/1723
+
+2008-11-24 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FormatSupport/ReconcileTIFF.cpp (ImportSingleTIFF_ASCII):
+ Re-enable the conversion for UNIX. Disabled in the original SDK.
+
+ * exempi/tests/Makefile.am:
+ * exempi/tests/fdo18635.jpg:
+ * exempi/tests/test-bgo.cpp
+ Don't crash on not so valid Exif. (Closes #18635)
+ And test case.
+
+2008-11-18 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/libexempi.sym, exempi/Makefile.am (libexempi_la_LDFLAGS):
+ Use symbol file. (Closes #16139)
+
+ * samples/testfiles/BlueSquare.gif,
+ samples/testfiles/Makefile.am: Forgotten files.
+
+ * NEWS, configure.ac, exempi/Makefile.am,
+ exempi/tests/test2.cpp, exempi/tests/testcore.sh,
+ samples/Makefile.am, samples/source/Makefile.am,
+ source/XMPFiles/FileHandlers/Makefile.am,
+ source/XMPFiles/FormatSupport/Makefile.am,
+ source/XMPCore/Makefile.am, source/common/Makefile.am:
+ Fix the build system.
+ * source/XMPFiles/FileHandlers/AVCHD_Handler.cpp
+ source/XMPFiles/FileHandlers/MP3_Handler.cpp,
+ source/XMPFiles/FileHandlers/MP3_Handler.hpp,
+ source/XMPFiles/FileHandlers/P2_Handler.cpp,
+ source/XMPFiles/FileHandlers/SonyHDV_Handler.cpp,
+ source/XMPFiles/FileHandlers/WAV_Handler.cpp,
+ source/XMPFiles/FileHandlers/WAV_Handler.hpp,
+ source/XMPFiles/FileHandlers/XDCAMEX_Handler.cpp,
+ source/XMPFiles/FileHandlers/XDCAM_Handler.cpp,
+ source/XMPFiles/FormatSupport/ID3_Support.cpp,
+ source/XMPFiles/FormatSupport/ID3_Support.hpp,
+ source/XMPFiles/FormatSupport/RIFF_Support.cpp,
+ source/XMPFiles/FormatSupport/RIFF_Support.hpp,
+ source/XMPFiles/FormatSupport/ReconcileTIFF.cpp,
+ source/XMPFiles/FormatSupport/Reconcile_Impl.cpp,
+ source/XMPFiles/FormatSupport/Reconcile_Impl.hpp,
+ source/XMPFiles/FormatSupport/TIFF_Support.hpp:
+ Enable all the file formats that Adobe disabled on
+ purpose.
+ * samples/source/ModifyingXMP.cpp,
+ source/common/EndianUtils.hpp,
+ source/common/LargeFileAccess.hpp,
+ source/common/XML_Node.cpp:
+ Other misc merge fixes.
+
+ * Merge the XPM SDK 4.4.2
+
+2008-05-29 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp, exempi/Makefile.am: don't define
+ UNIX_ENV in the source code but use the CPPFLAGS.
+
+ * exempi/exempi.cpp (xmp_files_get_xmp): CHECK_PTR should
+ return false and not NULL.
+
+2008-04-06 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/xmp.h, exempi/exempi.cpp: add new API
+ xmp_namespace_prefix(), xmp_prefix_namespace_uri().
+ * exempi/tests/test1.cpp: corresponding test.
+ (Closes #14962)
+
+2008-04-04 Hubert Figuiere <hub@figuiere.net>
+
+ * Start 2.1.0
+
+=== 2.0.2 ===
+
+2008-08-12 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp (set_error): Use pthread for the TLS
+ if there is no compiler support.
+ (Closes #16598)
+
+ * configure.ac:
+ * m4/ax_tls.m4:
+ Check for TLS.
+
+=== 2.0.1 ===
+
+2008-04-28 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/test1.cpp: Check that errors are unset.
+
+2008-04-24 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp: RESET_ERROR is called
+ upon entry of any functions.
+ error code is local thread storage.
+
+2008-04-05 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FormatSupport/Reconcile_Impl.cpp,
+ configure.ac: Check for iconv constness. (Closes #14613)
+
+2008-04-04 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/xmp.h: no stdbool.h on Sun compilers
+ (Closes #14612)
+
+=== 2.0.0 ===
+
+2008-04-01 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: This is really 2.0.0
+
+ * exempi/tests/test1.cpp, exempi/tests/test1.xmp:
+ Add a test on "Rating:".
+
+2008-03-30 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FormatSupport/EndianUtils.hpp,
+ configure.ac: Fix the endian detection. (Closes #15263)
+
+2008-02-22 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPCore/XMPMeta.cpp,
+ source/XMPFiles/FormatSupport/GIF_Support.cpp,
+ source/XMPFiles/FormatSupport/ID3_Support.cpp,
+ source/XMPFiles/FormatSupport/PNG_Support.cpp,
+ source/XMPFiles/FormatSupport/PSIR_FileWriter.cpp,
+ source/XMPFiles/FormatSupport/PSIR_MemoryReader.cpp,
+ source/XMPFiles/FormatSupport/ReconcileIPTC.cpp,
+ source/XMPFiles/FormatSupport/TIFF_Support.hpp:
+ Add some missing includes. (Closes #14615)
+
+ * source/XMPFiles/FormatSupport/EndianUtils.hpp: endian
+ detection on Solaris. (Closes #14614)
+
+=== 1.99.9 ===
+
+2008-01-30 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/xmp.h (XMP_OPEN_OPNLYXMP): Bad API breakage fix (introduced
+ in 1.99.8)
+
+=== 1.99.8 ===
+
+2008-01-23 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FormatSupport/GIF_Support.cpp (ReadHeader): Fix
+ a nasty buffer overflow. Closes Debian #454297. Closes Gnome #484105
+ Patch by Michael Biebl <biebl@debian.org>
+ (ReadBlock): Fix another possible overflow similar to the one in
+ ReadHeader()
+
+2008-01-22 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/xmp.h: Fix a typo. (Closes #14200)
+
+2008-01-18 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/Makefile.am: Disable strict aliasing. This fix
+ some nasty warning.
+
+2008-01-13 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: Allow disabling unittest if you
+ don't have boost (Closes #13712)
+
+ * autogen.sh: Don't run autoheader. (Closes #14049)
+
+ * autogen.sh: re-order commands in autogens.sh
+
+=== 1.99.7 ===
+
+2008-01-12 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: Fix the soversion. A mix-up occured in the last
+ release.
+
+=== 1.99.6 ===
+
+2008-01-11 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/test2.cpp (test_tiff_leak): Ensure that the file is
+ writable.
+
+2007-12-22 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: make boost optional as it is only for
+ the unit tests. (Closes #13712)
+
+ * configure.ac, m4/boost.m4, exempi/test/Makefile.am:
+ Change the BOOST detection macros.
+ (Closes #13713)
+
+2007-12-20 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPCore/XMPUtils.cpp (ConvertFromInt64): Fix format
+ for long long int that was causing a failure on ppc (big endian).
+
+2007-12-19 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp, exempi/tests/test1.cpp,
+ exempi/tests/test1.xmp, exempi/xmp.h:
+ Add setter/getter for int32, int64, bool, float.
+
+ * exempi/xmpconsts.h, exempi/exempi.cpp: add ACR schema namespace
+
+ * public/include/TXMPMeta.hpp, public/include/client-glue/TXMPMeta.incl_cpp,
+ samples/source/XMPCoreCoverage.cpp,
+ source/XMPFiles/FormatSupport/ReconcileTIFF.cpp:
+ Some APIs use long and long long. Change that.
+
+ * source/XMPFiles/FormatSupport/TIFF_FileWriter.cpp, exempi/tests/*:
+ Fix a memory leak. See http://www.adobeforums.com/webx/.3bc42b73
+ And test case.
+
+ * exempi/tests/*, configure.ac: detect valgrind.
+ Add leak detection support.
+
+2007-12-17 Hubert Figuiere <hub@figuiere.net>
+
+ * autogen.sh: added for convenience for non-tarball builders.
+ (Closes #13707)
+
+2007-12-16 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/*: added new API for get/set datetime.
+
+ * exempi/tests/*: refactor the test preparation.
+
+2007-11-13 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/tests/*.c: Add a bunch of include deemed necessary
+ by suse factory.
+ * Add a bunch of include deemed necessary by suse factory.
+
+2007-11-08 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPFiles/FormatSupport/Makefile.am: add
+ -Wno-multichar to remove warnings.
+ QuickTime_Support.cpp is in the dist as a noinst_HEADER
+
diff --git a/ChangeLog-pre.1.99.2 b/ChangeLog-pre.1.99.2
new file mode 100644
index 0000000..72d7e18
--- /dev/null
+++ b/ChangeLog-pre.1.99.2
@@ -0,0 +1,22 @@
+2007-06-14 Jason Kivlighn <jkivlighn@gmail.com>
+
+ * source/XMPFiles/FileHandlers/TIFF_Handler.cpp (UpdateFile):
+ Fix a bug: store the tag as BYTE and not UNDEFINED
+ to comply with the spec.
+
+2007-06-06 Hubert Figuiere <hub@figuiere.net>
+
+ * Release 1.99.1
+
+ * exempi/exempi.cpp: Added more exception catching.
+
+ * exempi/xmpconsts.h: Added NS_CC namespace
+
+ * exempi/exempi.cpp (xmp_register_namespace): wrapped
+ the namespace registration. Actually needed to
+ set new API.
+
+2007-05-11 Hubert Figuiere <hub@figuiere.net>
+
+ * Initial version of exempi 1.99.0
+
diff --git a/ChangeLog-pre.1.99.3 b/ChangeLog-pre.1.99.3
new file mode 100644
index 0000000..261ea6f
--- /dev/null
+++ b/ChangeLog-pre.1.99.3
@@ -0,0 +1,21 @@
+2007-06-25 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp (xmp_copy): Added API.
+
+2007-06-24 Hubert Figuiere <hub@figuiere.net>
+
+ * Added xmp_set_property2(), xmp_set_array_item()
+ and xmp_get_error() to the public API.
+
+2007-06-23 Hubert Figuiere <hub@figuiere.net>
+
+ * Added xmp_get_property_and_bits() and all the
+ option bits for it.
+
+2007-06-21 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp (xmp_files_get_xmp): More
+ exception handling. Should be better for error
+ management and resource tracking: was causing XMP to
+ leak because the exception was not caught.
+
diff --git a/ChangeLog-pre.1.99.4 b/ChangeLog-pre.1.99.4
new file mode 100644
index 0000000..e4e3bdb
--- /dev/null
+++ b/ChangeLog-pre.1.99.4
@@ -0,0 +1,12 @@
+2007-06-29 Hubert Figuiere <hub@figuiere.net>
+
+ * rpm/SLED10.spec: Added .spec for SLED10 packaging
+ (only in git)
+
+2007-06-28 Hubert Figuiere <hub@figuiere.net>
+
+ * New API wrapped: xmp_serialize{,_and_format}() and the
+ corresponding option bits
+
+ * New API wrapped: xmp_get_array_item()
+
diff --git a/ChangeLog-pre.1.99.5 b/ChangeLog-pre.1.99.5
new file mode 100644
index 0000000..f422ab3
--- /dev/null
+++ b/ChangeLog-pre.1.99.5
@@ -0,0 +1,22 @@
+2007-08-14 Hubert Figuiere <hub@figuiere.net>
+
+ * New API xmp_delete_localized_text(), by Ian Jacobi.
+
+2007-08-13 Hubert Figuiere <hub@figuiere.net>
+
+ * source/XMPCore/, public/include/: new call DeleteLocalizedText()
+ by Ian Jacobi.
+
+ * New API xmp_append_array_item(), xmp_delete_property(),
+ xmp_has_property(), xmp_get_localized_text(),
+ xmp_set_localized_text() by Ian Jacobi.
+ * exempi.cpp (xmp_files_open_new): Handle exception properly
+ by Ian Jacobi.
+
+2007-08-12 Hubert Figuiere <hub@figuiere.net>
+
+ * Added GIF smart handler support by Ian Jacobi.
+
+ * source/XMPCore/XMPCore_Impl.hpp (kXMPCoreName): Add Exempi
+ name to clearly identify when Exempi is generating.
+
diff --git a/ChangeLog-pre.1.99.6 b/ChangeLog-pre.1.99.6
new file mode 100644
index 0000000..8cd8d93
--- /dev/null
+++ b/ChangeLog-pre.1.99.6
@@ -0,0 +1,37 @@
+2007-11-06 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: Lower requirement for libboost.
+
+2007-11-01 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/doc/*, exempi/Makefile.am, configure.ac: Documentation
+ generation with Doxygen (manual).
+
+2007-10-31 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp: CHECK_PTR macro to check the input pointers
+ in all the API functions.
+ More functions return true or false (instead of void).
+
+ * exempi/tests/*: update for new API.
+
+2007-10-30 Hubert Figuiere <hub@figuiere.net>
+
+ * ABI breakage: soversion is now 3
+
+ * exempi/{exempi.cpp,xmp.h}: xmp_get_property_and_bits() renamed
+ xmp_get_property(). xmp_set_property2() renamed
+ xmp_set_property(). More exception handling and refactor
+ set_error() use.
+
+ * exempi/tests/*: update for new API.
+
+2007-10-02 Hubert Figuiere <hub@figuiere.net>
+
+ * exempi/exempi.cpp (xmp_files_new): Catch
+ exceptions.
+
+2007-08-17 Hubert Figuiere <hub@figuiere.net>
+
+ * configure.ac: add AC_CONFIG_MACRO_DIR to configure.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..5458714
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..2fdee08
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,42 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = third-party source XMPCore XMPFiles samples exempi
+DIST_SUBDIRS = build third-party source XMPCore XMPFiles XMPFilesPlugins samples exempi public
+
+EXTRA_DIST = autogen.sh
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..c6ad8b6
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,215 @@
+2.4.0
+
+- Bug #89449: Upgrade XMPCore to Adobe XMP CC 2014.12.
+ - New flag to optimize layout on MPEG4 files.
+ - GoPro MPEG4 video files support.
+ - Improved JPEG support.
+ - iXML support in WAVE files.
+ - Several bugs and memory leaks fixes.
+ - Changes from Adobe XMP CC 2013.06.
+ - Pluggable file handlers (not exposed yet in Exempi)
+ - Support for Exif 2.3 properties
+ - New RIFF file handler
+ - Better Postscript support.
+ - Lot of bug fixes.
+- New API: added XMP_OPEN_OPTIMIZEFILELAYOUT for new SDK.
+- Now require (partial) C++11 support to compile (gcc 4.4.7 tested)
+- New: WebP format handler (contributed: Frankie Dintino, The Atlantic)
+
+Internal:
+
+- Exempi is now automatically build and the test run by Travis CI.
+
+2.3.0 - 2016/03/15
+
+- New: API xmp_datetime_compare().
+- New: API xmp_string_len() to get the length of the XmpString.
+- Bug #94065:
+ - New: API xmp_files_can_put_xmp_xmpstring() and xmp_files_can_put_xmp_cstr()
+ variants.
+ - New: API xmp_files_put_xmp_xmpstring() and xmp_files_put_xmp_cstr()
+ variants.
+ - New: API xmp_files_get_xmp_xmpstring() variant.
+ - Test: check the status of the PDF handler.
+- Bug #90380: Fix potential crash with corrupt TIFF file.
+- Bug #14612: Better Solaris compilation fix.
+- Fix header to pass -Wstrict-prototypes
+
+2.2.2 - 2014/08/31
+
+- Public header cleanup and documentation update.
+- Update Doxygen config.
+- Bug #73058: Add missing include for MacOS.
+- Bug #72810: Fix typo in date test in MP3 handler.
+- Bug #83313: Fix crash on invalid Exif (from Samsung)
+- Fix valgrind testing for xmpcore.sh
+- Fix delete / delete[] mismatch in ID3_Support.hpp
+
+2.2.1 - 2013/06/29
+
+- Bug #54011: Use POSIX API for files on MacOS. (Misty De Meo)
+- Bug #58175: Replace OS X FlatCarbon headers. (Misty De Meo)
+- Added a manpage for exempi(1).
+- Added the -n option to the command line for arbitrary namespaces.
+
+2.2.0 - 2012/02/21
+
+- New 'exempi' command line tool.
+- Upgrade XMPCore to Adobe XMP 5.1.2
+ - Quicktime support now works without Quicktime.
+ - Reconciliation with ID3v2.
+ - "Blessed" 64-bits support (we already had it in exempi).
+ - Slight change in the way XMP are written for MWG compliance.
+ - Fixed a serious bug with RIFF.
+ - Change in the way local text encoding is dealt with.
+ - Alternative languages behave slightly differently by changing
+ how the default language property is managed.
+ - Probably a bunch of bugs fixed that I don't know about.
+- Update unit tests.
+ - Refactor the fixtures.
+- Use automake silent rules instead of shave. (build only)
+- "make dist" generate a bzip2 archive as well. (build only)
+- Remove some obsolete warning flags. (build only)
+- Build xmpcommandtool
+- New: API xmp_files_get_format_info().
+- New: API xmp_files_check_file_format().
+- New: API xmp_files_get_file_info().
+- New: API XMP_PROP_ARRAY_INSERT_BEFORE, XMP_PROP_ARRAY_INSERT_AFTER array options.
+- New: C++ helpers in xmp++.hpp.
+
+Bug fixes:
+
+- Bug #37747: mismatch delete/delete[] and new/new[] (from Meego
+ https://bugs.meego.com/show_bug.cgi?id=14661)
+
+2.1.1 - 2009/06/30
+
+New features:
+
+- Added shave to the build system for sane output. (build only)
+
+Bug fixes:
+
+- Bug #16030: if the property is an array or struct allow "" to be passed
+ as a value.
+- Bug #19312: source/XMPFiles/FileHandlers/P2_Handler.cpp was using
+ an improper string comparison. (made rpmlint unhappy).
+- Bug #20554: Missing file on MacOS X.
+- Bug #20554: Detect ldflags properly.
+- Bug #20622: Catch unhandled exceptions in xmp_files_can_put_xmp().
+- Bug #21934: Mismatched new [] / delete.
+- Bug #22554: Fix a SIGFPE encountered on some invalid files. (Bug GNOME #586720)
+
+2.1.0
+
+- Upgrade XMPCore to Adobe XMP 4.4.2
+ - Handlers for additional file formats, including ASF (WMA, WMV), FLV;
+ MPEG4; SWF; folder-based video formats AVCHD, P2, SonyHDV, and XDCAM; UCF
+ - Additional schemas to support document histories, composed documents,
+ and temporal metadata
+- New: NS_PDF namespace for PDF.
+- New: API xmp_prefix_namespace_uri() and xmp_namespace_prefix(). Bug #14962.
+- Bug: make sure boost >1.35 does not fail test with system().
+- Bug: unit test now use boost/test/minimal.hpp to work with more boost
+ install. (known boost.test bug)
+- Bug: fix a typo in a CHECK_PTR call causing warnings on gcc < 4.
+- Bug: no longer define UNIX_ENV in exempi.cpp and let CPPFLAGS do it.
+- Bug #16139: the list of exported symbols was too large.
+- Bug #18635: fix crasher.
+
+2.0.2
+
+- Bug #16598: address the lack of TLS for some platforms.
+
+2.0.1
+
+- Bug #14612: no stdbool.h for Sun compilers.
+- Bug #14613: check for iconv() const-ness.
+- Make the error checking more robust.
+- Make error code thread-safe (ie local to the thread).
+
+2.0.0
+
+- Bug #14614, Bug #15263: endian detection in configure.
+- Bug #14615: missing includes for Solaris.
+
+1.99.9
+
+- Bug: fixed an API breakage introduced in 1.99.8
+
+1.99.8
+
+- Bug #14049: don't run autoheader.
+- Bug #13712: add --enable-unittest to disable tests.
+- Bug: Disable strict aliasing in XMPFiles due to bad casting.
+- Bug #14200: fix a typo.
+- Bug: fix a couple of buffer overflows in GIF support. Closes Debian #454297.
+ Closes Gnome #484105
+
+1.99.7
+
+- Bug: fix soversion.
+
+1.99.6
+
+- New: API xmp_get_property_date() / xmp_set_property_date() with tests.
+- New: API xmp_{get,set]_property_{float,bool,int32,int64}() with tests.
+- New: API add ACR schema namespaces.
+- Test: refactor a the tests preparation.
+- Test: add a test for multiple initializations.
+- Test: use valgrind is available.
+- Bug: fix configure to allow building on MacOS X. Closes bug #13596
+- Bug #13707: add autogen.sh
+- Bug #13713: fix boost macros to link boost.test statically (for 1.34).
+- Bug #13712: skip tests if no boost.
+
+1.99.5
+
+- ABI breakage: soversion is now 3
+- Change: API xmp_files_close(), xmp_files_put_xmp(), xmp_files_free(),
+ xmp_free(), xmp_iterator_free(), xmp_iterator_skip() now return bool.
+- Change: API xmp_get_property_and_bits() renamed xmp_get_property().
+- Change: API xmp_set_property2() renamed xmp_set_property().
+- Bug: all API should check about input and return an error if
+ passed NULL.
+- Bug: more exception handling and refactor set_error() use.
+- Bug: add AC_CONFIG_MACRO_DIR to configure.
+- Bug: Lower requirement for libboost to 1.33.0.
+- New: Doxygen API doc generation.
+
+1.99.4
+
+- New: GIF Files smart handlers
+- New: API xmp_append_array_item(), xmp_delete_property(),
+ xmp_has_property(), xmp_get_localized_text(),
+ xmp_set_localized_text()
+- New: API xmp_delete_localized_text()
+- New: Exempi will be visible in the "generator" string of the XMP packet.
+- Bug: xmp_files_open_new() will handle exceptions properly
+
+1.99.3
+
+- New: API xmp_serialize{,_and_format}() and the
+ corresponding option bits
+- New API xmp_get_array_item()
+
+1.99.2
+
+- New: API xmp_copy()
+- New: API xmp_set_property2(), xmp_set_array_item()
+ and xmp_get_error()
+- New: API xmp_get_property_and_bits()
+- Bug: xmp_files_get_xmp() handle exceptions properly.
+
+1.99.1
+
+- Bug: store the TIFF tag as BYTE and not UNDEFINED
+ to comply with the spec.
+- Bug: more exception catched.
+- New: added NS_CC namespace
+- New: API xmp_register_namespace()
+
+1.99.0
+
+Initial release of the 2.0 series. Based on Adobe XMP SDK 4.1.1
+
diff --git a/README b/README
new file mode 100644
index 0000000..e8dab58
--- /dev/null
+++ b/README
@@ -0,0 +1,15 @@
+exempi is a port of Adobe XMP SDK to work on UNIX and to be build with
+GNU automake.
+
+It includes XMPCore and XMPFiles, libexempi, a C-based API and exempi
+a command line tool.
+
+It require at least the gcc 4.4.7 C++ compiler or clang++.
+
+It is maintained by Hubert Figuiere <hub@figuiere.net>
+
+Contributors:
+ Frankie Dintino <fdintino@theatlantic.com>
+
+
+Homepage: http://libopenraw.freedesktop.org/wiki/Exempi
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..aa03630
--- /dev/null
+++ b/TODO
@@ -0,0 +1,9 @@
+Things to do:
+
+- allow providing your own IO
+- add handler for Ogg (need to be defined)
+- reconcile CC license from Ogg to XMP. Check for other media
+format like MP3
+- add support for QuickTime without having quicktime
+- bug gna #10110
+- add support for PDF (using PoDoFo?)
diff --git a/XMPCore/Makefile.am b/XMPCore/Makefile.am
new file mode 100644
index 0000000..525e2e5
--- /dev/null
+++ b/XMPCore/Makefile.am
@@ -0,0 +1,3 @@
+
+
+SUBDIRS=source
diff --git a/XMPCore/source/ExpatAdapter.cpp b/XMPCore/source/ExpatAdapter.cpp
index 5fe0181..38ad449 100644
--- a/XMPCore/source/ExpatAdapter.cpp
+++ b/XMPCore/source/ExpatAdapter.cpp
@@ -146,7 +146,7 @@ void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last /
#if BanAllEntityUsage
if ( this->isAborted ) {
- XMP_Error error(kXMPErr_BadXML, "DOCTYPE is not allowed" )
+ XMP_Error error(kXMPErr_BadXML, "DOCTYPE is not allowed" );
this->NotifyClient ( kXMPErrSev_Recoverable, error );
}
#endif
diff --git a/XMPCore/source/Makefile.am b/XMPCore/source/Makefile.am
new file mode 100644
index 0000000..309d255
--- /dev/null
+++ b/XMPCore/source/Makefile.am
@@ -0,0 +1,64 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+
+noinst_LTLIBRARIES = libXMPCore.la
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/public/include \
+ -Wall @XMPCORE_CPPFLAGS@
+
+noinst_HEADERS = \
+ XMPCore_Impl.hpp XMPIterator.hpp \
+ XMPMeta.hpp XMPUtils.hpp
+
+
+libXMPCore_la_SOURCES = ExpatAdapter.cpp \
+ WXMPIterator.cpp \
+ WXMPUtils.cpp \
+ XMPIterator.cpp \
+ XMPMeta-GetSet.cpp \
+ XMPMeta-Serialize.cpp \
+ XMPUtils-FileInfo.cpp \
+ ParseRDF.cpp \
+ WXMPMeta.cpp \
+ XMPCore_Impl.cpp \
+ XMPMeta.cpp \
+ XMPMeta-Parse.cpp \
+ XMPUtils.cpp
+
diff --git a/XMPCore/source/ParseRDF.cpp b/XMPCore/source/ParseRDF.cpp
index b163867..8ec0e87 100644
--- a/XMPCore/source/ParseRDF.cpp
+++ b/XMPCore/source/ParseRDF.cpp
@@ -315,16 +315,6 @@ GetRDFTermKind ( const XMP_VarString & name )
// =================================================================================================
static void
-RemoveChild ( XMP_Node * xmpParent, size_t index )
-{
- XMP_Node * child = xmpParent->children[index];
- xmpParent->children.erase ( xmpParent->children.begin() + index );
- delete child;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static void
RemoveQualifier ( XMP_Node * xmpParent, size_t index )
{
XMP_Node * qualifier = xmpParent->qualifiers[index];
@@ -359,20 +349,6 @@ IsCoreSyntaxTerm ( RDFTermKind term )
}
// -------------------------------------------------------------------------------------------------
-// IsSyntaxTerm
-// ------------
-//
-// 7.2.3 syntaxTerms
-// coreSyntaxTerms | rdf:Description | rdf:li
-
-static bool
-IsSyntaxTerm ( RDFTermKind term )
-{
- if ( (kRDFTerm_FirstSyntax <= term) && (term <= kRDFTerm_LastSyntax) ) return true;
- return false;
-}
-
-// -------------------------------------------------------------------------------------------------
// IsOldTerm
// ---------
//
@@ -387,20 +363,6 @@ IsOldTerm ( RDFTermKind term )
}
// -------------------------------------------------------------------------------------------------
-// IsNodeElementName
-// -----------------
-//
-// 7.2.5 nodeElementURIs
-// anyURI - ( coreSyntaxTerms | rdf:li | oldTerms )
-
-static bool
-IsNodeElementName ( RDFTermKind term )
-{
- if ( (term == kRDFTerm_li) || IsOldTerm ( term ) ) return false;
- return (! IsCoreSyntaxTerm ( term ));
-}
-
-// -------------------------------------------------------------------------------------------------
// IsPropertyElementName
// ---------------------
//
@@ -415,20 +377,6 @@ IsPropertyElementName ( RDFTermKind term )
}
// -------------------------------------------------------------------------------------------------
-// IsPropertyAttributeName
-// -----------------------
-//
-// 7.2.7 propertyAttributeURIs
-// anyURI - ( coreSyntaxTerms | rdf:Description | rdf:li | oldTerms )
-
-static bool
-IsPropertyAttributeName ( RDFTermKind term )
-{
- if ( (term == kRDFTerm_Description) || (term == kRDFTerm_li) || IsOldTerm ( term ) ) return false;
- return (! IsCoreSyntaxTerm ( term ));
-}
-
-// -------------------------------------------------------------------------------------------------
// IsNumberedArrayItemName
// -----------------------
//
diff --git a/XMPCore/source/XMPCore_Impl.cpp b/XMPCore/source/XMPCore_Impl.cpp
index daec535..86c30bd 100644
--- a/XMPCore/source/XMPCore_Impl.cpp
+++ b/XMPCore/source/XMPCore_Impl.cpp
@@ -645,6 +645,7 @@ ExpandXPath ( XMP_StringPtr schemaNS,
XMP_StringPtr qualName = 0 , nameEnd = 0;
XMP_VarString currStep;
+ qualName = nameEnd = NULL;
size_t resCount = 2; // Guess at the number of steps. At least 2, plus 1 for each '/' or '['.
for ( stepEnd = propPath; *stepEnd != 0; ++stepEnd ) {
if ( (*stepEnd == '/') || (*stepEnd == '[') ) ++resCount;
diff --git a/XMPCore/source/XMPCore_Impl.hpp b/XMPCore/source/XMPCore_Impl.hpp
index 52aa114..7ce2537 100644
--- a/XMPCore/source/XMPCore_Impl.hpp
+++ b/XMPCore/source/XMPCore_Impl.hpp
@@ -121,7 +121,7 @@ extern WXMP_Result void_wResult;
(XMP_API_VERSION_MINOR << 16) | \
(XMP_API_VERSION_MICRO << 8) )
- #define kXMPCoreName "XMP Core"
+ #define kXMPCoreName "Exempi + XMP Core"
#define kXMPCore_VersionMessage kXMPCoreName " " XMPCORE_API_VERSION_STRING
// =================================================================================================
// Support for call tracing
diff --git a/XMPCore/source/XMPIterator.cpp b/XMPCore/source/XMPIterator.cpp
index 275e32f..80cf6ca 100644
--- a/XMPCore/source/XMPIterator.cpp
+++ b/XMPCore/source/XMPIterator.cpp
@@ -367,7 +367,7 @@ XMPIterator::Terminate() RELEASE_NO_THROW
XMPIterator::XMPIterator ( const XMPMeta & xmpObj,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
- XMP_OptionBits options ) : info(IterInfo(options,&xmpObj)), clientRefs(0)
+ XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,&xmpObj))
{
if ( (options & kXMP_IterClassMask) != kXMP_IterProperties ) {
XMP_Throw ( "Unsupported iteration kind", kXMPErr_BadOptions );
@@ -485,11 +485,10 @@ XMPIterator::XMPIterator ( const XMPMeta & xmpObj,
//
// Constructor for iterations over global tables such as registered namespaces or aliases.
-XMPIterator::XMPIterator ( XMP_StringPtr schemaNS,
- XMP_StringPtr propName,
- XMP_OptionBits options ) : info(IterInfo(options,0)), clientRefs(0)
+XMPIterator::XMPIterator ( XMP_StringPtr /*schemaNS*/,
+ XMP_StringPtr /*propName*/,
+ XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,0))
{
- void * p; p = &schemaNS; p = &propName; p = &options; // Avoid unused param warnings.
XMP_Throw("Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented);
} // XMPIterator for global tables
diff --git a/XMPCore/source/XMPMeta-GetSet.cpp b/XMPCore/source/XMPMeta-GetSet.cpp
index 18c024c..c67965f 100644
--- a/XMPCore/source/XMPMeta-GetSet.cpp
+++ b/XMPCore/source/XMPMeta-GetSet.cpp
@@ -1081,7 +1081,6 @@ XMPMeta::DeleteLocalizedText ( XMP_StringPtr schemaNS,
XMP_Node * assocNode = 0;
size_t assocIndex;
- size_t assocIsXDefault = false;
if ( itemIsXDefault ) {
@@ -1100,7 +1099,6 @@ XMPMeta::DeleteLocalizedText ( XMP_StringPtr schemaNS,
if ( (qualNode->name == "xml:lang") && (qualNode->value == "x-default") ) {
assocNode = arrayNode->children[0];
assocIndex = 0;
- assocIsXDefault = true;
}
}
diff --git a/XMPCore/source/XMPMeta-Serialize.cpp b/XMPCore/source/XMPMeta-Serialize.cpp
index 39a5270..f31e65e 100644
--- a/XMPCore/source/XMPMeta-Serialize.cpp
+++ b/XMPCore/source/XMPMeta-Serialize.cpp
@@ -44,7 +44,7 @@ using namespace std;
static const char * kPacketHeader = "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>";
static const char * kPacketTrailer = "<?xpacket end=\"w\"?>"; // ! The w/r is at [size-4].
-static const char * kTXMP_SchemaGroup = "XMP_SchemaGroup";
+//static const char * kTXMP_SchemaGroup = "XMP_SchemaGroup";
static const char * kRDF_XMPMetaStart = "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"";
static const char * kRDF_XMPMetaEnd = "</x:xmpmeta>";
@@ -59,19 +59,19 @@ static const char * kRDF_StructStart = "<rdf:Description>";
static const char * kRDF_StructEnd = "</rdf:Description>";
static const char * kRDF_BagStart = "<rdf:Bag>";
-static const char * kRDF_BagEnd = "</rdf:Bag>";
+//static const char * kRDF_BagEnd = "</rdf:Bag>";
-static const char * kRDF_SeqStart = "<rdf:Seq>";
-static const char * kRDF_SeqEnd = "</rdf:Seq>";
+//static const char * kRDF_SeqStart = "<rdf:Seq>";
+//static const char * kRDF_SeqEnd = "</rdf:Seq>";
-static const char * kRDF_AltStart = "<rdf:Alt>";
-static const char * kRDF_AltEnd = "</rdf:Alt>";
+//static const char * kRDF_AltStart = "<rdf:Alt>";
+//static const char * kRDF_AltEnd = "</rdf:Alt>";
static const char * kRDF_ItemStart = "<rdf:li>";
-static const char * kRDF_ItemEnd = "</rdf:li>";
+//static const char * kRDF_ItemEnd = "</rdf:li>";
static const char * kRDF_ValueStart = "<rdf:value>";
-static const char * kRDF_ValueEnd = "</rdf:value>";
+//static const char * kRDF_ValueEnd = "</rdf:value>";
// =================================================================================================
@@ -1347,11 +1347,9 @@ XMPMeta::SerializeToBuffer ( XMP_VarString * rdfString,
} else {
std::string padStr ( " " ); padStr[0] = padStr[1] = padStr[2] = 0; // Assume big endian.
- UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32BE;
if ( charEncoding & _XMP_LittleEndian_Bit ) {
padStr[0] = ' '; padStr[1] = padStr[2] = padStr[3] = 0;
- Converter = UTF8_to_UTF32LE;
}
utf8Str.swap ( *rdfString );
diff --git a/XMPCore/source/XMPMeta.cpp b/XMPCore/source/XMPMeta.cpp
index b2f02b6..ae31063 100644
--- a/XMPCore/source/XMPMeta.cpp
+++ b/XMPCore/source/XMPMeta.cpp
@@ -686,7 +686,7 @@ RegisterStandardAliases()
// ============
-XMPMeta::XMPMeta() : tree(XMP_Node(0,"",0)), clientRefs(0), xmlParser(0)
+XMPMeta::XMPMeta() : clientRefs(0), tree(XMP_Node(0,"",0)), xmlParser(0)
{
#if XMP_TraceCTorDTor
printf ( "Default construct XMPMeta @ %.8X\n", this );
@@ -886,7 +886,9 @@ XMPMeta::Initialize()
XMP_Assert ( sizeof(XMP_Bool) == 1 );
XMP_Assert ( sizeof(XMP_OptionBits) == 4 ); // Check that option masking work on all 32 bits.
+#if XMP_DebugBuild
XMP_OptionBits flag = (XMP_OptionBits) (~0UL);
+#endif
XMP_Assert ( flag == (XMP_OptionBits)(-1L) );
XMP_Assert ( (flag ^ kXMP_PropHasLang) == 0xFFFFFFBFUL );
XMP_Assert ( (flag & ~kXMP_PropHasLang) == 0xFFFFFFBFUL );
@@ -1030,10 +1032,9 @@ XMPMeta::GetGlobalOptions()
// ----------------
/* class-static */ void
-XMPMeta::SetGlobalOptions ( XMP_OptionBits options )
+XMPMeta::SetGlobalOptions ( XMP_OptionBits /*options*/ )
{
- void * p; p = &options; // Avoid unused param warnings.
XMP_Throw("Unimplemented method XMPMeta::SetGlobalOptions", kXMPErr_Unimplemented);
} // SetGlobalOptions
@@ -1267,11 +1268,9 @@ XMPMeta::GetObjectOptions() const
// ----------------
void
-XMPMeta::SetObjectOptions ( XMP_OptionBits options )
+XMPMeta::SetObjectOptions ( XMP_OptionBits /*options*/ )
{
- void * p; p = &options; // Avoid unused param warnings.
XMP_Throw ( "Unimplemented method XMPMeta::SetObjectOptions", kXMPErr_Unimplemented );
-
} // SetObjectOptions
diff --git a/XMPCore/source/XMPMeta.hpp b/XMPCore/source/XMPMeta.hpp
index 34b71aa..a93554d 100644
--- a/XMPCore/source/XMPMeta.hpp
+++ b/XMPCore/source/XMPMeta.hpp
@@ -411,7 +411,7 @@ public:
private:
// ! These are hidden on purpose:
- XMPMeta ( const XMPMeta & /* original */ ) : tree(XMP_Node(0,"",0)), clientRefs(0), xmlParser(0)
+ XMPMeta ( const XMPMeta & /* original */ ) : clientRefs(0), tree(XMP_Node(0,"",0)), xmlParser(0)
{ XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); };
void operator= ( const XMPMeta & /* rhs */ )
{ XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); };
diff --git a/XMPCore/source/XMPUtils.cpp b/XMPCore/source/XMPUtils.cpp
index 8a8c4fc..c075389 100644
--- a/XMPCore/source/XMPUtils.cpp
+++ b/XMPCore/source/XMPUtils.cpp
@@ -1890,7 +1890,10 @@ static size_t MoveLargestProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, PropSize
printf ( " Move %s, %d bytes\n", propName, propSize );
#endif
- bool moved = MoveOneProperty ( stdXMP, extXMP, schemaURI, propName );
+#if XMP_DebugBuild
+ bool moved =
+#endif
+ MoveOneProperty ( stdXMP, extXMP, schemaURI, propName );
XMP_Assert ( moved );
propSizes.erase ( lastPos );
@@ -3025,9 +3028,11 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
// Adjust the standard XMP padding to be up to 2KB.
+#if XMP_DebugBuild
XMP_Assert ( (stdStr->size() > kTrailerLen) && (stdStr->size() <= kStdXMPLimit) );
const char * packetEnd = stdStr->c_str() + stdStr->size() - kTrailerLen;
XMP_Assert ( XMP_LitMatch ( packetEnd, kPacketTrailer ) );
+#endif
size_t extraPadding = kStdXMPLimit - stdStr->size(); // ! Do this before erasing the trailer.
if ( extraPadding > 2047 ) extraPadding = 2047;
diff --git a/XMPFiles/Makefile.am b/XMPFiles/Makefile.am
new file mode 100644
index 0000000..525e2e5
--- /dev/null
+++ b/XMPFiles/Makefile.am
@@ -0,0 +1,3 @@
+
+
+SUBDIRS=source
diff --git a/XMPFiles/source/FileHandlers/AIFF_Handler.cpp b/XMPFiles/source/FileHandlers/AIFF_Handler.cpp
index 8c9d604..6331a0b 100644
--- a/XMPFiles/source/FileHandlers/AIFF_Handler.cpp
+++ b/XMPFiles/source/FileHandlers/AIFF_Handler.cpp
@@ -132,7 +132,7 @@ const ChunkIdentifier AIFF_MetaHandler::kAIFCAnno[2] = { { kChunk_FORM, kType_AI
// ================================
AIFF_MetaHandler::AIFF_MetaHandler ( XMPFiles * _parent )
- : mChunkBehavior(NULL), mChunkController(NULL),
+ : mChunkController(NULL), mChunkBehavior(NULL),
mAiffMeta(), mXMPChunk(NULL),
mNameChunk(NULL), mAuthChunk(NULL),
mCprChunk(NULL), mAnnoChunk(NULL)
diff --git a/XMPFiles/source/FileHandlers/MP3_Handler.cpp b/XMPFiles/source/FileHandlers/MP3_Handler.cpp
index e9520f3..9295a2e 100644
--- a/XMPFiles/source/FileHandlers/MP3_Handler.cpp
+++ b/XMPFiles/source/FileHandlers/MP3_Handler.cpp
@@ -130,8 +130,8 @@ MP3_MetaHandler::MP3_MetaHandler ( XMPFiles * _parent )
this->newFramesSize = 0;
this->tagIsDirty = false;
this->mustShift = false;
- this->majorVersion = 2.3;
- this->minorVersion = 2.3;
+ this->majorVersion = 2;
+ this->minorVersion = 3;
this->hasID3Tag = false;
this->hasFooter = false;
this->extHeaderSize = 0;
diff --git a/XMPFiles/source/FileHandlers/Makefile.am b/XMPFiles/source/FileHandlers/Makefile.am
new file mode 100644
index 0000000..1198856
--- /dev/null
+++ b/XMPFiles/source/FileHandlers/Makefile.am
@@ -0,0 +1,73 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+
+noinst_LTLIBRARIES = libxmpfilehandlers.la
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/public/include \
+ -Wall @XMPCORE_CPPFLAGS@
+
+
+libxmpfilehandlers_la_SOURCES = \
+AIFF_Handler.cpp AIFF_Handler.hpp\
+ASF_Handler.cpp ASF_Handler.hpp\
+AVCHD_Handler.cpp AVCHD_Handler.hpp\
+Basic_Handler.cpp Basic_Handler.hpp\
+FLV_Handler.cpp FLV_Handler.hpp\
+InDesign_Handler.cpp InDesign_Handler.hpp\
+JPEG_Handler.cpp JPEG_Handler.hpp\
+MP3_Handler.cpp MP3_Handler.hpp\
+MPEG2_Handler.cpp MPEG2_Handler.hpp \
+MPEG4_Handler.cpp MPEG4_Handler.hpp \
+P2_Handler.cpp P2_Handler.hpp\
+PNG_Handler.cpp PNG_Handler.hpp\
+PostScript_Handler.cpp PostScript_Handler.hpp\
+PSD_Handler.cpp PSD_Handler.hpp\
+RIFF_Handler.cpp RIFF_Handler.hpp \
+Scanner_Handler.cpp Scanner_Handler.hpp\
+SonyHDV_Handler.cpp SonyHDV_Handler.hpp\
+SWF_Handler.cpp SWF_Handler.hpp\
+TIFF_Handler.cpp TIFF_Handler.hpp\
+Trivial_Handler.cpp Trivial_Handler.hpp\
+UCF_Handler.cpp UCF_Handler.hpp\
+XDCAMEX_Handler.cpp XDCAMEX_Handler.hpp\
+XDCAM_Handler.cpp XDCAM_Handler.hpp\
+WAVE_Handler.cpp WAVE_Handler.hpp \
+GIF_Handler.cpp GIF_Handler.hpp \
+WEBP_Handler.cpp WEB_Handler.hpp
+$(NULL)
+
diff --git a/XMPFiles/source/FileHandlers/P2_Handler.cpp b/XMPFiles/source/FileHandlers/P2_Handler.cpp
index 982744d..1b7ad09 100644
--- a/XMPFiles/source/FileHandlers/P2_Handler.cpp
+++ b/XMPFiles/source/FileHandlers/P2_Handler.cpp
@@ -720,7 +720,7 @@ void P2_MetaHandler::SetStartTimecodeFromLegacyXML ( XML_NodePtr legacyVideoCont
dmTimeFormat = "50Timecode";
this->AdjustTimeCode( p2StartTimecode, false );
- } else if ( p2FrameRate == "59.94p" ) {
+ } else if ( ( p2FrameRate == "59.94p" ) && ( p2DropFrameFlag != 0 ) ) {
if ( XMP_LitMatch ( p2DropFrameFlag, "true" ) ) {
dmTimeFormat = "5994DropTimecode";
diff --git a/XMPFiles/source/FileHandlers/PSD_Handler.cpp b/XMPFiles/source/FileHandlers/PSD_Handler.cpp
index cbcf4df..312e855 100644
--- a/XMPFiles/source/FileHandlers/PSD_Handler.cpp
+++ b/XMPFiles/source/FileHandlers/PSD_Handler.cpp
@@ -81,7 +81,7 @@ XMPFileHandler * PSD_MetaHandlerCTor ( XMPFiles * parent )
// PSD_MetaHandler::PSD_MetaHandler
// ================================
-PSD_MetaHandler::PSD_MetaHandler ( XMPFiles * _parent ) : iptcMgr(0), exifMgr(0), skipReconcile(false),imageWidth(0),imageHeight(0)
+PSD_MetaHandler::PSD_MetaHandler ( XMPFiles * _parent ) : skipReconcile(false), iptcMgr(0), exifMgr(0),imageWidth(0),imageHeight(0)
{
this->parent = _parent;
this->handlerFlags = kPSD_HandlerFlags;
diff --git a/XMPFiles/source/FileHandlers/PSD_Handler.hpp b/XMPFiles/source/FileHandlers/PSD_Handler.hpp
index 51dd4b9..4caec1b 100644
--- a/XMPFiles/source/FileHandlers/PSD_Handler.hpp
+++ b/XMPFiles/source/FileHandlers/PSD_Handler.hpp
@@ -58,7 +58,7 @@ public:
private:
- PSD_MetaHandler() : iptcMgr(0), exifMgr(0), skipReconcile(false) {}; // Hidden on purpose.
+ PSD_MetaHandler() : skipReconcile(false), iptcMgr(0), exifMgr(0) {} // Hidden on purpose.
PSIR_FileWriter psirMgr; // Don't need a pointer, the PSIR part is always file-based.
IPTC_Manager * iptcMgr; // Need to use pointers so we can properly select between read-only
diff --git a/XMPFiles/source/FileHandlers/UCF_Handler.hpp b/XMPFiles/source/FileHandlers/UCF_Handler.hpp
index 3140c23..eee46ef 100644
--- a/XMPFiles/source/FileHandlers/UCF_Handler.hpp
+++ b/XMPFiles/source/FileHandlers/UCF_Handler.hpp
@@ -237,8 +237,8 @@ private:
//TODO intergrate in clear()
void release() // avoid terminus free() since subject to a #define (mem-leak-check)
{
- if (filename) delete filename;
- if (extraField) delete extraField;
+ if (filename) delete [] filename;
+ if (extraField) delete [] extraField;
filename=0;
extraField=0;
}
@@ -277,10 +277,10 @@ private:
PutUns16LE(0x14, &fields[FileHeader::o_extractVersion] );
}
- FileHeader() : filename(0),filenameLen(0),extraField(0),extraFieldLen(0)
+ FileHeader() : filename(0),extraField(0),filenameLen(0),extraFieldLen(0)
{
clear();
- };
+ }
// reads entire *FileHeader* structure from file (starting at current position)
void read(XMP_IO* file)
@@ -379,9 +379,9 @@ private:
private:
void release() //*** needed or can go?
{
- if (filename) delete filename;
- if (extraField) delete extraField;
- if (comment) delete comment;
+ if (filename) delete [] filename;
+ if (extraField) delete [] extraField;
+ if (comment) delete [] comment;
filename=0; filenameLen=0;
extraField=0; extraFieldLen=0;
comment=0; commentLen=0;
@@ -547,7 +547,7 @@ private:
{
//// WRITE BACK REAL 64 BIT VALUES, CREATE EXTRA FIELD ///////////////
//may only wipe extra field after obtaining all Info from it
- if (extraField) delete extraField;
+ if (extraField) delete [] extraField;
extraFieldLen=0;
if ( ( sizeUncompressed > 0xffffffff ) ||
@@ -598,7 +598,7 @@ private:
void setXMPFilename()
{
- if (filename) delete filename;
+ if (filename) delete [] filename;
filenameLen = xmpFilenameLen;
filename = new char[xmpFilenameLen];
PutUns16LE(filenameLen, &fields[CDFileHeader::o_fileNameLength] );
@@ -630,8 +630,9 @@ private:
const static XMP_Uns32 SIG = 0x06054b50;
void UCFECD_Free()
{
- if(commentLen) delete comment;
+ if(commentLen) delete [] comment;
commentLen = 0;
+ comment = 0;
}
public:
const static XMP_Int32 o_Sig = 0;
@@ -678,7 +679,7 @@ private:
~EndOfCD()
{
- if (comment) delete comment;
+ if (comment) delete [] comment;
};
}; //class EndOfCD
diff --git a/XMPFiles/source/FileHandlers/WAVE_Handler.cpp b/XMPFiles/source/FileHandlers/WAVE_Handler.cpp
index 1695013..6f7f287 100644
--- a/XMPFiles/source/FileHandlers/WAVE_Handler.cpp
+++ b/XMPFiles/source/FileHandlers/WAVE_Handler.cpp
@@ -140,7 +140,7 @@ const ChunkIdentifier WAVE_MetaHandler::kRF64iXML[2] = { { kChunk_RF64, kType_WA
// ================================
WAVE_MetaHandler::WAVE_MetaHandler ( XMPFiles * _parent )
- : mChunkBehavior(NULL), mChunkController(NULL),
+ : mChunkController(NULL), mChunkBehavior(NULL),
mINFOMeta(), mBEXTMeta(), mCartMeta(), mDISPMeta(), miXMLMeta(),
mXMPChunk(NULL), mINFOChunk(NULL),
mBEXTChunk(NULL), mCartChunk(NULL), mDISPChunk(NULL), miXMLChunk(NULL)
diff --git a/XMPFiles/source/FileHandlers/WEBP_Handler.cpp b/XMPFiles/source/FileHandlers/WEBP_Handler.cpp
new file mode 100644
index 0000000..c0b1f09
--- /dev/null
+++ b/XMPFiles/source/FileHandlers/WEBP_Handler.cpp
@@ -0,0 +1,197 @@
+#include "public/include/XMP_Const.h"
+#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header.
+
+#include "XMPFiles/source/FileHandlers/WEBP_Handler.hpp"
+
+#include "XMPFiles/source/FormatSupport/IPTC_Support.hpp"
+#include "XMPFiles/source/FormatSupport/PSIR_Support.hpp"
+#include "XMPFiles/source/FormatSupport/ReconcileLegacy.hpp"
+#include "XMPFiles/source/FormatSupport/Reconcile_Impl.hpp"
+#include "XMPFiles/source/FormatSupport/TIFF_Support.hpp"
+#include "XMPFiles/source/FormatSupport/WEBP_Support.hpp"
+#include "source/XIO.hpp"
+
+using namespace std;
+
+/// File format handler for WEBP.
+
+XMPFileHandler* WEBP_MetaHandlerCTor(XMPFiles* parent)
+{
+ return new WEBP_MetaHandler(parent);
+}
+
+// Check that the file begins with "RIFF", a 4 byte length, then the chunkType
+// (WEBP).
+bool WEBP_CheckFormat(XMP_FileFormat format, XMP_StringPtr filePath,
+ XMP_IO* file, XMPFiles* parent)
+{
+ IgnoreParam(format);
+ IgnoreParam(parent);
+ XMP_Assert(format == kXMP_WEBPFile);
+
+ if (file->Length() < 12)
+ return false;
+ file->Rewind();
+
+ XMP_Uns8 chunkID[12];
+ file->ReadAll(chunkID, 12);
+ if (!CheckBytes(&chunkID[0], "RIFF", 4)) {
+ return false;
+ }
+ if (CheckBytes(&chunkID[8], "WEBP", 4) && format == kXMP_WEBPFile) {
+ return true;
+ }
+ return false;
+}
+
+WEBP_MetaHandler::WEBP_MetaHandler(XMPFiles* parent)
+ : exifMgr(0)
+{
+ this->parent = parent;
+ this->handlerFlags = kWEBP_HandlerFlags;
+ this->stdCharForm = kXMP_Char8Bit;
+
+ this->initialFileSize = 0;
+ this->mainChunk = 0;
+}
+
+WEBP_MetaHandler::~WEBP_MetaHandler()
+{
+ if (this->mainChunk) {
+ delete this->mainChunk;
+ }
+ if (this->exifMgr) {
+ delete this->exifMgr;
+ }
+ if (this->iptcMgr) {
+ delete this->iptcMgr;
+ }
+ if (this->psirMgr) {
+ delete this->psirMgr;
+ }
+}
+
+void WEBP_MetaHandler::CacheFileData()
+{
+ this->containsXMP = false; // assume for now
+
+ XMP_IO* file = this->parent->ioRef;
+ this->initialFileSize = file->Length();
+
+ file->Rewind();
+
+ XMP_Int64 filePos = 0;
+ while (filePos < this->initialFileSize) {
+ this->mainChunk = new WEBP::Container(this);
+ filePos = file->Offset();
+ }
+
+ // covered before => internal error if it occurs
+ XMP_Validate(file->Offset() == this->initialFileSize,
+ "WEBP_MetaHandler::CacheFileData: unknown data at end of file",
+ kXMPErr_InternalFailure);
+}
+
+void WEBP_MetaHandler::ProcessXMP()
+{
+ SXMPUtils::RemoveProperties(&this->xmpObj, 0, 0, kXMPUtil_DoAllProperties);
+
+ bool readOnly = false;
+ bool xmpOnly = false;
+ bool haveExif = false;
+ if (this->parent) {
+ readOnly =
+ !XMP_OptionIsSet(this->parent->openFlags, kXMPFiles_OpenForUpdate);
+ xmpOnly =
+ XMP_OptionIsSet(this->parent->openFlags, kXMPFiles_OpenOnlyXMP);
+ }
+ if (!xmpOnly) {
+ if (readOnly) {
+ this->exifMgr = new TIFF_MemoryReader();
+ }
+ else {
+ this->exifMgr = new TIFF_FileWriter();
+ }
+ this->psirMgr = new PSIR_MemoryReader();
+ this->iptcMgr = new IPTC_Reader();
+ if (this->parent) {
+ exifMgr->SetErrorCallback(&this->parent->errorCallback);
+ }
+ if (this->mainChunk) {
+ WEBP::Chunk* exifChunk = this->mainChunk->getExifChunk();
+ if (exifChunk != NULL) {
+ haveExif = true;
+ this->exifMgr->ParseMemoryStream(exifChunk->data.data() + 6,
+ exifChunk->data.size() - 6);
+ }
+ }
+ }
+
+ if (this->containsXMP) {
+ this->xmpObj.ParseFromBuffer(this->xmpPacket.c_str(),
+ (XMP_StringLen) this->xmpPacket.size());
+ }
+ if (haveExif) {
+ XMP_OptionBits options = k2XMP_FileHadExif;
+ if (this->containsXMP) {
+ options |= k2XMP_FileHadXMP;
+ }
+ TIFF_Manager& exif = *this->exifMgr;
+ PSIR_Manager& psir = *this->psirMgr;
+ IPTC_Manager& iptc = *this->iptcMgr;
+ ImportPhotoData(exif, iptc, psir, kDigestMatches, &this->xmpObj,
+ options);
+ // Assume that, since the file had EXIF data, some of it was mapped to
+ // XMP
+ this->containsXMP = true;
+ }
+ this->processedXMP = true;
+}
+
+void WEBP_MetaHandler::UpdateFile(bool doSafeUpdate)
+{
+ XMP_Validate(this->needsUpdate, "nothing to update",
+ kXMPErr_InternalFailure);
+
+ bool xmpOnly = false;
+ if (this->parent) {
+ xmpOnly =
+ XMP_OptionIsSet(this->parent->openFlags, kXMPFiles_OpenOnlyXMP);
+ }
+
+ if (!xmpOnly && this->exifMgr) {
+ WEBP::Chunk* exifChunk = this->mainChunk->getExifChunk();
+ if (exifChunk != NULL) {
+ ExportPhotoData(kXMP_TIFFFile, &this->xmpObj, this->exifMgr, 0, 0);
+ if (this->exifMgr->IsLegacyChanged()) {
+ XMP_Uns8* exifPtr;
+ XMP_Uns32 exifLen =
+ this->exifMgr->UpdateMemoryStream((void**)&exifPtr);
+ RawDataBlock exifData(&exifChunk->data[0], &exifChunk->data[6]);
+ exifData.insert(exifData.begin() + 6, &exifPtr[0],
+ &exifPtr[exifLen]);
+ exifChunk->data = exifData;
+ exifChunk->size = exifLen + 6;
+ exifChunk->needsRewrite = true;
+ }
+ }
+ }
+
+ this->packetInfo.charForm = stdCharForm;
+ this->packetInfo.writeable = true;
+ this->packetInfo.offset = kXMPFiles_UnknownOffset;
+ this->packetInfo.length = kXMPFiles_UnknownLength;
+
+ this->xmpObj.SerializeToBuffer(&this->xmpPacket, kXMP_OmitPacketWrapper);
+
+ this->mainChunk->write(this);
+ this->needsUpdate = false; // do last for safety
+}
+
+void WEBP_MetaHandler::WriteTempFile(XMP_IO* tempRef)
+{
+ IgnoreParam(tempRef);
+ XMP_Throw("WEBP_MetaHandler::WriteTempFile: Not supported (must go through "
+ "UpdateFile)",
+ kXMPErr_Unavailable);
+}
diff --git a/XMPFiles/source/FileHandlers/WEBP_Handler.hpp b/XMPFiles/source/FileHandlers/WEBP_Handler.hpp
new file mode 100644
index 0000000..c5041ea
--- /dev/null
+++ b/XMPFiles/source/FileHandlers/WEBP_Handler.hpp
@@ -0,0 +1,48 @@
+#ifndef __WEBP_Handler_hpp__
+#define __WEBP_Handler_hpp__ 1
+
+#include "public/include/XMP_Const.h"
+#include "public/include/XMP_Environment.h"
+
+#include "XMPFiles/source/FormatSupport/WEBP_Support.hpp"
+#include "XMPFiles/source/FormatSupport/TIFF_Support.hpp"
+#include "XMPFiles/source/FormatSupport/IPTC_Support.hpp"
+#include "XMPFiles/source/FormatSupport/PSIR_Support.hpp"
+
+#include "source/XIO.hpp"
+
+// File format handler for WEBP
+
+extern XMPFileHandler* WEBP_MetaHandlerCTor(XMPFiles* parent);
+
+extern bool WEBP_CheckFormat(XMP_FileFormat format, XMP_StringPtr filePath,
+ XMP_IO* fileRef, XMPFiles* parent);
+
+static const XMP_OptionBits kWEBP_HandlerFlags =
+ (kXMPFiles_CanInjectXMP | kXMPFiles_CanExpand | kXMPFiles_PrefersInPlace |
+ kXMPFiles_AllowsOnlyXMP | kXMPFiles_ReturnsRawPacket |
+ kXMPFiles_CanReconcile);
+
+class WEBP_MetaHandler
+ : public XMPFileHandler {
+public:
+ WEBP_MetaHandler(XMPFiles* parent);
+ ~WEBP_MetaHandler();
+
+ void CacheFileData();
+ void ProcessXMP();
+ void UpdateFile(bool doSafeUpdate);
+ void WriteTempFile(XMP_IO* tempRef);
+
+ WEBP::Container* mainChunk;
+ WEBP::XMPChunk* xmpChunk;
+ XMP_Int64 initialFileSize;
+ TIFF_Manager* exifMgr;
+ // The PSIR_Manager and IPTC_Manager aren't actually used, but they need
+ // to be instantiated and passed to the function that reconciles EXIF and
+ // XMP data.
+ PSIR_Manager* psirMgr;
+ IPTC_Manager* iptcMgr;
+};
+
+#endif /* __WEBP_Handler_hpp__ */
diff --git a/XMPFiles/source/FormatSupport/GIF_Support.cpp b/XMPFiles/source/FormatSupport/GIF_Support.cpp
new file mode 100644
index 0000000..4f2ac6c
--- /dev/null
+++ b/XMPFiles/source/FormatSupport/GIF_Support.cpp
@@ -0,0 +1,352 @@
+// =================================================================================================
+// ADOBE SYSTEMS INCORPORATED
+// Copyright 2002-2007 Adobe Systems Incorporated
+// All Rights Reserved
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+//
+// Derived from PNG_Support.cpp by Ian Jacobi
+// Ported to the CS6 version by Hubert Figuiere
+// =================================================================================================
+
+#include "GIF_Support.hpp"
+#include <string.h>
+
+#include "source/XIO.hpp"
+
+typedef std::basic_string<unsigned char> filebuffer;
+
+// Don't need CRC.
+
+namespace GIF_Support
+{
+ // This only really counts for extension blocks.
+ enum blockType {
+ bGraphicControl = 0xF9,
+ bComment = 0xFE,
+ bPlainText = 0x01,
+ bApplication = 0xFF,
+ // Hacky. Don't like the following, but there's no easy way.
+ bImage = 0x2C,
+ bExtension = 0x21,
+ bTerminator = 0x3B,
+ bHeader = 0x47
+ };
+
+ // =============================================================================================
+
+ long OpenGIF ( XMP_IO* fileRef, BlockState & inOutBlockState )
+ {
+ XMP_Uns64 pos = 0;
+ unsigned char name;
+ XMP_Uns32 len;
+ BlockData newBlock;
+
+ pos = fileRef->Seek ( 0, kXMP_SeekFromStart );
+ // header needs to be a block, mostly for our safe write.
+ pos = ReadHeader ( fileRef );
+ if (pos < 13)
+ return 0;
+
+ newBlock.pos = 0;
+ newBlock.len = pos;
+ newBlock.type = bHeader;
+ inOutBlockState.blocks.push_back(newBlock);
+
+ // read first and following blocks
+ while ( ReadBlock ( fileRef, inOutBlockState, &name, &len, pos) ) {}
+
+ return inOutBlockState.blocks.size();
+
+ }
+
+ // =============================================================================================
+
+ long ReadHeader ( XMP_IO* fileRef )
+ {
+ long bytesRead;
+ long headerSize;
+ long tableSize = 0;
+ long bytesPerColor = 0;
+ unsigned char buffer[768];
+
+ headerSize = 0;
+ bytesRead = fileRef->Read ( buffer, GIF_SIGNATURE_LEN );
+ if ( bytesRead != GIF_SIGNATURE_LEN ) return 0;
+ if ( memcmp ( buffer, GIF_SIGNATURE_DATA, GIF_SIGNATURE_LEN) != 0 ) return 0;
+ headerSize += bytesRead;
+ bytesRead = fileRef->Read ( buffer, 3 );
+ if ( bytesRead != 3 ) return 0;
+ if ( memcmp ( buffer, "87a", 3 ) != 0 && memcmp ( buffer, "89a", 3 ) != 0 ) return 0;
+ headerSize += bytesRead;
+ bytesRead = fileRef->Read ( buffer, 4 );
+ if ( bytesRead != 4 ) return 0;
+ headerSize += bytesRead;
+ bytesRead = fileRef->Read ( buffer, 3 );
+ if ( bytesRead != 3 ) return 0;
+ headerSize += bytesRead;
+ if ( buffer[0] & 0x80 ) tableSize = (1 << ((buffer[0] & 0x07) + 1)) * 3;
+ bytesRead = fileRef->Read ( buffer, tableSize );
+ if ( bytesRead != tableSize ) return 0;
+ headerSize += bytesRead;
+
+ return headerSize;
+ }
+
+ // =============================================================================================
+
+ bool ReadBlock ( XMP_IO* fileRef, BlockState & inOutBlockState, unsigned char * blockType, XMP_Uns32 * blockLength, XMP_Uns64 & inOutPosition )
+ {
+ try
+ {
+ XMP_Uns64 startPosition = inOutPosition;
+ long bytesRead;
+ long blockSize;
+ unsigned char buffer[768];
+
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ if ( buffer[0] == bImage )
+ {
+ // Image is a special case.
+ long tableSize = 0;
+ bytesRead = fileRef->Read ( buffer, 4 );
+ if ( bytesRead != 4 ) return false;
+ inOutPosition += 4;
+ bytesRead = fileRef->Read ( buffer, 4 );
+ if ( bytesRead != 4 ) return false;
+ inOutPosition += 4;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ if ( buffer[0] & 0x80 ) tableSize = (1 << ((buffer[0] & 0x07) + 1)) * 3;
+ bytesRead = fileRef->Read ( buffer, tableSize );
+ if ( bytesRead != tableSize ) return 0;
+ inOutPosition += tableSize;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ while ( tableSize != 0x00 )
+ {
+ bytesRead = fileRef->Read ( buffer, tableSize );
+ if ( bytesRead != tableSize ) return false;
+ inOutPosition += tableSize;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ }
+
+ BlockData newBlock;
+
+ newBlock.pos = startPosition;
+ newBlock.len = inOutPosition - startPosition;
+ newBlock.type = bImage;
+
+ inOutBlockState.blocks.push_back ( newBlock );
+ }
+ else if ( buffer[0] == bExtension )
+ {
+ unsigned char type;
+ long tableSize = 0;
+
+ BlockData newBlock;
+
+ newBlock.pos = startPosition;
+
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ type = buffer[0];
+ newBlock.type = type;
+
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ while ( tableSize != 0x00 )
+ {
+ bytesRead = fileRef->Read ( buffer, tableSize );
+ if ( bytesRead != tableSize ) return false;
+ inOutPosition += tableSize;
+ if ( inOutPosition - startPosition == 14 && type == bApplication )
+ {
+ // Check for XMP identifier...
+ CheckApplicationBlockHeader ( fileRef, inOutBlockState, newBlock, inOutPosition );
+
+ if ( newBlock.xmp == true )
+ {
+ newBlock.len = inOutPosition - startPosition;
+
+ inOutBlockState.blocks.push_back ( newBlock );
+
+ return true;
+ }
+ }
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ }
+
+ newBlock.len = inOutPosition - startPosition;
+
+ inOutBlockState.blocks.push_back ( newBlock );
+ }
+ else if ( buffer[0] == bTerminator )
+ {
+ BlockData newBlock;
+
+ newBlock.pos = startPosition;
+ newBlock.len = 1;
+ newBlock.type = buffer[0];
+
+ inOutBlockState.blocks.push_back ( newBlock );
+ }
+
+ } catch ( ... ) {
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+ // =============================================================================================
+
+ bool WriteXMPBlock ( XMP_IO* fileRef, XMP_Uns32 len, const char* inBuffer )
+ {
+ bool ret = false;
+ unsigned long datalen = (APPLICATION_HEADER_LEN + len + MAGIC_TRAILER_LEN);
+ unsigned char* buffer = new unsigned char[datalen];
+
+ try
+ {
+ size_t pos = 0;
+ memcpy(&buffer[pos], APPLICATION_HEADER_DATA, APPLICATION_HEADER_LEN);
+ pos += APPLICATION_HEADER_LEN;
+ memcpy(&buffer[pos], inBuffer, len);
+ pos += len;
+ memcpy(&buffer[pos], MAGIC_TRAILER_DATA, MAGIC_TRAILER_LEN);
+
+ fileRef->Write(buffer, datalen);
+
+ ret = true;
+ }
+ catch ( ... ) {}
+
+ delete [] buffer;
+
+ return ret;
+ }
+
+ // =============================================================================================
+
+ bool CopyBlock ( XMP_IO* sourceRef, XMP_IO* destRef, BlockData& block )
+ {
+ try
+ {
+ sourceRef->Seek ( block.pos, kXMP_SeekFromStart );
+ XIO::Copy (sourceRef, destRef, (block.len));
+
+ } catch ( ... ) {
+
+ return false;
+
+ }
+
+ return true;
+ }
+
+ // =============================================================================================
+
+ // Don't need CRC.
+
+ // =============================================================================================
+
+ unsigned long CheckApplicationBlockHeader ( XMP_IO* fileRef, BlockState& inOutBlockState, BlockData& inOutBlockData, XMP_Uns64& inOutPosition )
+ {
+ try
+ {
+ fileRef->Seek((inOutBlockData.pos), kXMP_SeekFromStart);
+
+ unsigned char buffer[256];
+ long bytesRead = fileRef->Read ( buffer, APPLICATION_HEADER_LEN );
+
+ if (bytesRead == APPLICATION_HEADER_LEN)
+ {
+ if (memcmp(buffer, APPLICATION_HEADER_DATA, APPLICATION_HEADER_LEN) == 0)
+ {
+ // We still have to go through all of the data...
+ long tableSize = 0;
+ long xmpSize;
+
+ inOutPosition = inOutBlockData.pos + APPLICATION_HEADER_LEN;
+ inOutBlockState.xmpPos = inOutPosition;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return 0;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ while ( tableSize != 0x00 )
+ {
+ bytesRead = fileRef->Read ( buffer, tableSize );
+ if ( bytesRead != tableSize ) return false;
+ inOutPosition += tableSize;
+ bytesRead = fileRef->Read ( buffer, 1 );
+ if ( bytesRead != 1 ) return false;
+ inOutPosition += 1;
+ tableSize = buffer[0];
+ }
+ inOutBlockState.xmpLen = inOutPosition - inOutBlockData.pos - APPLICATION_HEADER_LEN - MAGIC_TRAILER_LEN;
+ inOutBlockState.xmpBlock = inOutBlockData;
+ inOutBlockData.xmp = true;
+ }
+ }
+ }
+ catch ( ... ) {}
+
+ return 0;
+ }
+
+ bool ReadBuffer ( XMP_IO* fileRef, XMP_Uns64 & pos, XMP_Uns32 len, char * outBuffer )
+ {
+ try
+ {
+ if ( (fileRef == 0) || (outBuffer == 0) ) return false;
+
+ fileRef->Seek ( pos, kXMP_SeekFromStart );
+ long bytesRead = fileRef->Read ( outBuffer, len );
+ if ( XMP_Uns32(bytesRead) != len ) return false;
+
+ return true;
+ }
+ catch ( ... ) {}
+
+ return false;
+ }
+
+ bool WriteBuffer ( XMP_IO* fileRef, XMP_Uns64 & pos, XMP_Uns32 len, const char * inBuffer )
+ {
+ try
+ {
+ if ( (fileRef == 0) || (inBuffer == 0) ) return false;
+
+ fileRef->Seek ( pos, kXMP_SeekFromStart );
+ fileRef->Write( inBuffer, len );
+
+ return true;
+ }
+ catch ( ... ) {}
+
+ return false;
+ }
+
+} // namespace GIF_Support
diff --git a/XMPFiles/source/FormatSupport/GIF_Support.hpp b/XMPFiles/source/FormatSupport/GIF_Support.hpp
new file mode 100644
index 0000000..aa81b8a
--- /dev/null
+++ b/XMPFiles/source/FormatSupport/GIF_Support.hpp
@@ -0,0 +1,71 @@
+#ifndef __GIF_Support_hpp__
+#define __GIF_Support_hpp__ 1
+
+// =================================================================================================
+// ADOBE SYSTEMS INCORPORATED
+// Copyright 2002-2007 Adobe Systems Incorporated
+// All Rights Reserved
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it
+//
+// Derived from PNG_Support.hpp by Ian Jacobi
+// =================================================================================================
+
+#include "XMP_Environment.h" // ! This must be the first include.
+
+#include "XMPFiles/source/XMPFiles_Impl.hpp"
+
+#define GIF_SIGNATURE_LEN 3
+#define GIF_SIGNATURE_DATA "\x47\x49\x46"
+
+#define APPLICATION_HEADER_LEN 14
+#define APPLICATION_HEADER_DATA "\x21\xFF\x0B\x58\x4D\x50\x20\x44\x61\x74\x61\x58\x4D\x50"
+
+#define MAGIC_TRAILER_LEN 258
+#define MAGIC_TRAILER_DATA "\x01\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8\xF7\xF6\xF5\xF4\xF3\xF2\xF1\xF0\xEF\xEE\xED\xEC\xEB\xEA\xE9\xE8\xE7\xE6\xE5\xE4\xE3\xE2\xE1\xE0\xDF\xDE\xDD\xDC\xDB\xDA\xD9\xD8\xD7\xD6\xD5\xD4\xD3\xD2\xD1\xD0\xCF\xCE\xCD\xCC\xCB\xCA\xC9\xC8\xC7\xC6\xC5\xC4\xC3\xC2\xC1\xC0\xBF\xBE\xBD\xBC\xBB\xBA\xB9\xB8\xB7\xB6\xB5\xB4\xB3\xB2\xB1\xB0\xAF\xAE\xAD\xAC\xAB\xAA\xA9\xA8\xA7\xA6\xA5\xA4\xA3\xA2\xA1\xA0\x9F\x9E\x9D\x9C\x9B\x9A\x99\x98\x97\x96\x95\x94\x93\x92\x91\x90\x8F\x8E\x8D\x8C\x8B\x8A\x89\x88\x87\x86\x85\x84\x83\x82\x81\x80\x7F\x7E\x7D\x7C\x7B\x7A\x79\x78\x77\x76\x75\x74\x73\x72\x71\x70\x6F\x6E\x6D\x6C\x6B\x6A\x69\x68\x67\x66\x65\x64\x63\x62\x61\x60\x5F\x5E\x5D\x5C\x5B\x5A\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4F\x4E\x4D\x4C\x4B\x4A\x49\x48\x47\x46\x45\x44\x43\x42\x41\x40\x3F\x3E\x3D\x3C\x3B\x3A\x39\x38\x37\x36\x35\x34\x33\x32\x31\x30\x2F\x2E\x2D\x2C\x2B\x2A\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1F\x1E\x1D\x1C\x1B\x1A\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00"
+
+namespace GIF_Support
+{
+ class BlockData
+ {
+ public:
+ BlockData() : pos(0), len(0), type(0), xmp(false) {}
+ virtual ~BlockData() {}
+
+ XMP_Uns64 pos; // file offset of block
+ XMP_Uns32 len; // length of block data, including extension introducer and label
+ char type; // name/type of block
+ bool xmp; // application extension block with XMP ?
+ };
+
+ typedef std::vector<BlockData> BlockVector;
+ typedef BlockVector::iterator BlockIterator;
+
+ class BlockState
+ {
+ public:
+ BlockState() : xmpPos(0), xmpLen(0) {}
+ virtual ~BlockState() {}
+
+ XMP_Uns64 xmpPos;
+ XMP_Uns32 xmpLen;
+ BlockData xmpBlock;
+ BlockVector blocks; /* vector of blocks */
+ };
+
+ long OpenGIF ( XMP_IO* fileRef, BlockState& inOutBlockState );
+
+ long ReadHeader ( XMP_IO* fileRef );
+ bool ReadBlock ( XMP_IO* fileRef, BlockState& inOutBlockState, unsigned char* blockType, XMP_Uns32* blockLength, XMP_Uns64& inOutPosition );
+ bool WriteXMPBlock ( XMP_IO* fileRef, XMP_Uns32 len, const char* inBuffer );
+ bool CopyBlock ( XMP_IO* sourceRef, XMP_IO* destRef, BlockData& block );
+
+ unsigned long CheckApplicationBlockHeader ( XMP_IO* fileRef, BlockState& inOutBlockState, BlockData& inOutBlockData, XMP_Uns64& inOutPosition );
+
+ bool ReadBuffer ( XMP_IO* fileRef, XMP_Uns64& pos, XMP_Uns32 len, char* outBuffer );
+ bool WriteBuffer ( XMP_IO* fileRef, XMP_Uns64& pos, XMP_Uns32 len, const char* inBuffer );
+
+} // namespace GIF_Support
+
+#endif // __GIF_Support_hpp__
diff --git a/XMPFiles/source/FormatSupport/ID3_Support.cpp b/XMPFiles/source/FormatSupport/ID3_Support.cpp
index abe0923..528609c 100644
--- a/XMPFiles/source/FormatSupport/ID3_Support.cpp
+++ b/XMPFiles/source/FormatSupport/ID3_Support.cpp
@@ -20,6 +20,27 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#if !XMP_WinBuild
+ int stricmp ( const char * left, const char * right ) // Case insensitive ASCII compare.
+ {
+ char chL = *left; // ! Allow for 0 passes in the loop (one string is empty).
+ char chR = *right; // ! Return -1 for stricmp ( "a", "Z" ).
+
+ for ( ; (*left != 0) && (*right != 0); ++left, ++right ) {
+ chL = *left;
+ chR = *right;
+ if ( chL == chR ) continue;
+ if ( ('A' <= chL) && (chL <= 'Z') ) chL |= 0x20;
+ if ( ('A' <= chR) && (chR <= 'Z') ) chR |= 0x20;
+ if ( chL != chR ) break;
+ }
+
+ if ( chL == chR ) return 0;
+ if ( chL < chR ) return -1;
+ return 1;
+ }
+#endif
+
namespace ID3_Support {
// =================================================================================================
@@ -440,7 +461,7 @@ ID3v2Frame::ID3v2Frame ( XMP_Uns32 id ) : frameDefaults
void ID3v2Frame::release()
{
- if ( this->content != 0 ) delete this->content;
+ if ( this->content != 0 ) delete [] this->content;
this->content = 0;
this->contentSize = 0;
}
diff --git a/XMPFiles/source/FormatSupport/ID3_Support.hpp b/XMPFiles/source/FormatSupport/ID3_Support.hpp
index 299c27c..dda6bfc 100644
--- a/XMPFiles/source/FormatSupport/ID3_Support.hpp
+++ b/XMPFiles/source/FormatSupport/ID3_Support.hpp
@@ -18,24 +18,7 @@
#if XMP_WinBuild
#define stricmp _stricmp
#else
- static int stricmp ( const char * left, const char * right ) // Case insensitive ASCII compare.
- {
- char chL = *left; // ! Allow for 0 passes in the loop (one string is empty).
- char chR = *right; // ! Return -1 for stricmp ( "a", "Z" ).
-
- for ( ; (*left != 0) && (*right != 0); ++left, ++right ) {
- chL = *left;
- chR = *right;
- if ( chL == chR ) continue;
- if ( ('A' <= chL) && (chL <= 'Z') ) chL |= 0x20;
- if ( ('A' <= chR) && (chR <= 'Z') ) chR |= 0x20;
- if ( chL != chR ) break;
- }
-
- if ( chL == chR ) return 0;
- if ( chL < chR ) return -1;
- return 1;
- }
+ int stricmp ( const char * left, const char * right ); // Case insensitive ASCII compare.
#endif
// =================================================================================================
diff --git a/XMPFiles/source/FormatSupport/IFF/Chunk.cpp b/XMPFiles/source/FormatSupport/IFF/Chunk.cpp
index 9e1407f..e8acc9f 100644
--- a/XMPFiles/source/FormatSupport/IFF/Chunk.cpp
+++ b/XMPFiles/source/FormatSupport/IFF/Chunk.cpp
@@ -15,6 +15,7 @@
#include "source/XIO.hpp"
#include <cstdio>
+#include <cstdlib>
#include <typeinfo>
using namespace IFF_RIFF;
@@ -1207,7 +1208,7 @@ void Chunk::adjustSize( XMP_Int64 sizeChange )
mSize = mBufferSize;
// if the difference is odd, the corrected even size has be incremented by 1
- sizeChange += abs(sizeChange % 2);
+ sizeChange += std::abs(sizeChange % 2);
}
else // mChunkMode == CHUNK_NODE/CHUNK_UNKNOWN
{
diff --git a/XMPFiles/source/FormatSupport/IFF/ChunkController.cpp b/XMPFiles/source/FormatSupport/IFF/ChunkController.cpp
index fc7c2c6..29dec94 100644
--- a/XMPFiles/source/FormatSupport/IFF/ChunkController.cpp
+++ b/XMPFiles/source/FormatSupport/IFF/ChunkController.cpp
@@ -31,8 +31,8 @@ ChunkController::ChunkController( IChunkBehavior* chunkBehavior, XMP_Bool bigEnd
mChunkBehavior (chunkBehavior),
mFileSize (0),
mRoot (NULL),
- mTrailingGarbageSize (0),
- mTrailingGarbageOffset (0)
+ mTrailingGarbageOffset (0),
+ mTrailingGarbageSize (0)
{
if (bigEndian)
{
diff --git a/XMPFiles/source/FormatSupport/IPTC_Support.cpp b/XMPFiles/source/FormatSupport/IPTC_Support.cpp
index 3a3421c..3df7726 100644
--- a/XMPFiles/source/FormatSupport/IPTC_Support.cpp
+++ b/XMPFiles/source/FormatSupport/IPTC_Support.cpp
@@ -525,7 +525,7 @@ void IPTC_Writer::SetDataSet_UTF8 ( XMP_Uns8 dsNum, const void* utf8Ptr, XMP_Uns
}
}
- XMP_Uns8 * dataPtr = (XMP_Uns8*) malloc ( dataLen );
+ XMP_Uns8 * dataPtr = dataLen ? (XMP_Uns8*) malloc ( dataLen ) : NULL;
if ( dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
memcpy ( dataPtr, tempPtr, dataLen ); // AUDIT: Safe, malloc'ed dataLen bytes above.
diff --git a/XMPFiles/source/FormatSupport/Makefile.am b/XMPFiles/source/FormatSupport/Makefile.am
new file mode 100644
index 0000000..8916332
--- /dev/null
+++ b/XMPFiles/source/FormatSupport/Makefile.am
@@ -0,0 +1,82 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+noinst_LTLIBRARIES = libformatsupport.la
+noinst_HEADERS = IPTC_Support.hpp PSIR_Support.hpp\
+ Reconcile_Impl.hpp RIFF_Support.hpp XMPScanner.hpp\
+ ID3_Support.hpp PNG_Support.hpp QuickTime_Support.hpp\
+ ReconcileLegacy.hpp TIFF_Support.hpp GIF_Support.hpp
+
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions
+AM_CPPFLAGS = -I$(top_srcdir) \
+ -I$(top_srcdir)/public/include/ \
+ -Wall @XMPCORE_CPPFLAGS@
+
+libformatsupport_la_SOURCES = \
+ PackageFormat_Support.cpp PackageFormat_Support.hpp \
+ PostScript_Support.cpp PostScript_Support.hpp \
+ PSIR_FileWriter.cpp Reconcile_Impl.cpp \
+ ReconcileTIFF.cpp TIFF_MemoryReader.cpp \
+ IPTC_Support.cpp PSIR_MemoryReader.cpp ReconcileIPTC.cpp \
+ RIFF.cpp RIFF.hpp ID3_Support.cpp ID3_Support.hpp\
+ RIFF_Support.cpp TIFF_Support.cpp \
+ ISOBaseMedia_Support.hpp ISOBaseMedia_Support.cpp \
+ PNG_Support.cpp ReconcileLegacy.cpp \
+ GIF_Support.cpp \
+ SWF_Support.hpp SWF_Support.cpp\
+ XDCAM_Support.hpp XDCAM_Support.cpp\
+ TIFF_FileWriter.cpp XMPScanner.cpp \
+ MOOV_Support.cpp MOOV_Support.hpp \
+ QuickTime_Support.cpp \
+ ASF_Support.hpp ASF_Support.cpp \
+ MacScriptExtracts.h \
+ TimeConversionUtils.cpp TimeConversionUtils.hpp \
+ AIFF/AIFFBehavior.cpp AIFF/AIFFBehavior.h \
+ AIFF/AIFFMetadata.cpp AIFF/AIFFMetadata.h \
+ AIFF/AIFFReconcile.cpp AIFF/AIFFReconcile.h \
+ IFF/ChunkController.cpp IFF/Chunk.cpp IFF/ChunkPath.cpp IFF/IChunkBehavior.cpp IFF/IChunkContainer.h \
+ IFF/ChunkController.h IFF/Chunk.h IFF/ChunkPath.h IFF/IChunkBehavior.h IFF/IChunkData.h \
+ WAVE/BEXTMetadata.cpp WAVE/CartMetadata.h WAVE/DISPMetadata.cpp WAVE/INFOMetadata.h WAVE/WAVEBehavior.cpp WAVE/WAVEReconcile.h \
+ WAVE/BEXTMetadata.h WAVE/Cr8rMetadata.cpp WAVE/DISPMetadata.h WAVE/PrmLMetadata.cpp WAVE/WAVEBehavior.h \
+ WAVE/CartMetadata.cpp WAVE/Cr8rMetadata.h WAVE/INFOMetadata.cpp WAVE/PrmLMetadata.h WAVE/WAVEReconcile.cpp \
+ WAVE/iXMLMetadata.h WAVE/iXMLMetadata.cpp \
+ P2_Support.hpp P2_Support.cpp \
+ WEBP_Support.hpp WEBP_Support.cpp \
+ $(NULL)
+
+
diff --git a/XMPFiles/source/FormatSupport/P2_Support.cpp b/XMPFiles/source/FormatSupport/P2_Support.cpp
index a5336d5..fc5a334 100644
--- a/XMPFiles/source/FormatSupport/P2_Support.cpp
+++ b/XMPFiles/source/FormatSupport/P2_Support.cpp
@@ -25,7 +25,7 @@
#include <sstream>
P2_Clip::P2_Clip(const std::string & p2ClipMetadataFilePath)
- try :p2XMLParser(0),p2Root(0),headContentCached(false)
+ try :headContentCached(false),p2XMLParser(0),p2Root(0)
,p2ClipContent(0),filePath(p2ClipMetadataFilePath)
{
Host_IO::FileRef hostRef = Host_IO::Open ( p2ClipMetadataFilePath.c_str(), Host_IO::openReadOnly );
diff --git a/XMPFiles/source/FormatSupport/P2_Support.hpp b/XMPFiles/source/FormatSupport/P2_Support.hpp
index e16faea..8375d32 100644
--- a/XMPFiles/source/FormatSupport/P2_Support.hpp
+++ b/XMPFiles/source/FormatSupport/P2_Support.hpp
@@ -47,9 +47,9 @@ protected:
class ClipContent
{
public:
- ClipContent():clipId(0),scaleUnit(0),
+ ClipContent():clipTitle(0),clipId(0),scaleUnit(0),
duration(0),OffsetInShot(0),topClipId(0),nextClipId(0),
- prevClipId(0),shotId(0),clipMetadata(0),essenceList(0),clipTitle(0){}
+ prevClipId(0),shotId(0),clipMetadata(0),essenceList(0){}
std::string* clipTitle;
std::string* clipId;
std::string* scaleUnit;
diff --git a/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp b/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
index 5d06220..12adc58 100644
--- a/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
+++ b/XMPFiles/source/FormatSupport/PSIR_FileWriter.cpp
@@ -409,7 +409,7 @@ XMP_Uns32 PSIR_FileWriter::UpdateMemoryResources ( void** dataPtr )
newLength += this->otherRsrcs[i].rsrcLength;
}
- XMP_Uns8* newContent = (XMP_Uns8*) malloc ( newLength );
+ XMP_Uns8* newContent = newLength ? (XMP_Uns8*) malloc ( newLength ) : NULL;
if ( newContent == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
// Fill in the new image resource block.
diff --git a/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp b/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp
index f9e1165..ee58379 100644
--- a/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp
+++ b/XMPFiles/source/FormatSupport/ReconcileTIFF.cpp
@@ -506,7 +506,7 @@ ImportSingleTIFF_ASCII ( const TIFF_Manager::TagInfo & tagInfo,
if ( tagInfo.dataLen == 0 ) return; // Ignore empty tags.
const char * chPtr = (const char *)tagInfo.dataPtr;
- const bool hasNul = (chPtr[tagInfo.dataLen-1] == 0);
+ const bool hasNul = !tagInfo.dataLen || !chPtr || (chPtr[tagInfo.dataLen-1] == 0);
const bool isUTF8 = ReconcileUtils::IsUTF8 ( chPtr, tagInfo.dataLen );
if ( isUTF8 && hasNul ) {
diff --git a/XMPFiles/source/FormatSupport/Reconcile_Impl.cpp b/XMPFiles/source/FormatSupport/Reconcile_Impl.cpp
index ca0e1a0..7ff57c2 100644
--- a/XMPFiles/source/FormatSupport/Reconcile_Impl.cpp
+++ b/XMPFiles/source/FormatSupport/Reconcile_Impl.cpp
@@ -21,6 +21,8 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
+const char * ReconcileUtils::kHexDigits = "0123456789ABCDEF";
+
// =================================================================================================
/// \file Reconcile_Impl.cpp
/// \brief Implementation utilities for the photo metadata reconciliation support.
diff --git a/XMPFiles/source/FormatSupport/Reconcile_Impl.hpp b/XMPFiles/source/FormatSupport/Reconcile_Impl.hpp
index 4efcb3f..6fc357d 100644
--- a/XMPFiles/source/FormatSupport/Reconcile_Impl.hpp
+++ b/XMPFiles/source/FormatSupport/Reconcile_Impl.hpp
@@ -33,7 +33,7 @@ namespace ReconcileUtils {
// *** These ought to be with the Unicode conversions.
- static const char * kHexDigits = "0123456789ABCDEF";
+ extern const char * kHexDigits;
bool IsASCII ( const void * _textPtr, size_t textLen );
bool IsUTF8 ( const void * _textPtr, size_t textLen );
diff --git a/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp b/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp
index 20c6012..ec92c8e 100644
--- a/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp
+++ b/XMPFiles/source/FormatSupport/TIFF_FileWriter.cpp
@@ -585,6 +585,7 @@ void TIFF_FileWriter::ParseMemoryStream ( const void* data, XMP_Uns32 length, bo
} else {
if ( length > 100*1024*1024 ) XMP_Throw ( "Outrageous length for memory-based TIFF", kXMPErr_BadTIFF );
this->memStream = (XMP_Uns8*) malloc(length);
+ this->ownedStream = true;
if ( this->memStream == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
memcpy ( this->memStream, data, length ); // AUDIT: Safe, malloc'ed length bytes above.
this->ownedStream = true;
diff --git a/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp b/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp
index 31192c7..c1a0d44 100644
--- a/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp
+++ b/XMPFiles/source/FormatSupport/TIFF_MemoryReader.cpp
@@ -96,14 +96,14 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD )
#if ! (SUNOS_SPARC || XMP_IOS_ARM)
TweakedIFDEntry temp = ifdEntries[i];
++j; // ! So the insertion index becomes j.
- memcpy ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i.
+ memmove ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // FAILED -- AUDIT: Safe, moving less than i entries to a location before i.
ifdEntries[j] = temp;
#else
void * tempifdEntries = &ifdEntries[i];
TweakedIFDEntry temp;
memcpy ( &temp, tempifdEntries, sizeof(TweakedIFDEntry) );
++j; // ! So the insertion index becomes j.
- memcpy ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // AUDIT: Safe, moving less than i entries to a location before i.
+ memmove ( &ifdEntries[j+1], &ifdEntries[j], 12*(i-j) ); // FAILED -- AUDIT: Safe, moving less than i entries to a location before i.
tempifdEntries = &ifdEntries[j];
memcpy ( tempifdEntries, &temp, sizeof(TweakedIFDEntry) );
#endif
diff --git a/XMPFiles/source/FormatSupport/TIFF_Support.cpp b/XMPFiles/source/FormatSupport/TIFF_Support.cpp
index da2f9b6..08b0bc6 100644
--- a/XMPFiles/source/FormatSupport/TIFF_Support.cpp
+++ b/XMPFiles/source/FormatSupport/TIFF_Support.cpp
@@ -16,6 +16,10 @@
#include "source/UnicodeConversions.hpp"
+static const char * kTIFF_TypeNames[] = { "ShortOrLong", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL",
+ "SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL",
+ "FLOAT", "DOUBLE" };
+
// =================================================================================================
/// \file TIFF_Support.cpp
/// \brief Manager for parsing and serializing TIFF streams.
@@ -29,9 +33,9 @@
static bool sFirstCTor = true;
TIFF_Manager::TIFF_Manager()
- : bigEndian(false), nativeEndian(false), errorCallbackPtr( NULL ),
- GetUns16(0), GetUns32(0), GetFloat(0), GetDouble(0),
- PutUns16(0), PutUns32(0), PutFloat(0), PutDouble(0)
+ : GetUns16(0), GetUns32(0), GetFloat(0), GetDouble(0),
+ PutUns16(0), PutUns32(0), PutFloat(0), PutDouble(0),
+ bigEndian(false), nativeEndian(false), errorCallbackPtr( NULL )
{
if ( sFirstCTor ) {
diff --git a/XMPFiles/source/FormatSupport/TIFF_Support.hpp b/XMPFiles/source/FormatSupport/TIFF_Support.hpp
index 6d4860b..5ed5965 100644
--- a/XMPFiles/source/FormatSupport/TIFF_Support.hpp
+++ b/XMPFiles/source/FormatSupport/TIFF_Support.hpp
@@ -101,10 +101,6 @@ static const bool kTIFF_IsIntegerType[] = { 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0,
static const bool kTIFF_IsRationalType[] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 };
static const bool kTIFF_IsFloatType[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
-static const char * kTIFF_TypeNames[] = { "ShortOrLong", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL",
- "SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL",
- "FLOAT", "DOUBLE" };
-
enum { // Encodings for SetTag_EncodedString.
kTIFF_EncodeUndefined = 0,
kTIFF_EncodeASCII = 1,
diff --git a/XMPFiles/source/FormatSupport/WAVE/iXMLMetadata.cpp b/XMPFiles/source/FormatSupport/WAVE/iXMLMetadata.cpp
index 9b52c79..a153bc7 100644
--- a/XMPFiles/source/FormatSupport/WAVE/iXMLMetadata.cpp
+++ b/XMPFiles/source/FormatSupport/WAVE/iXMLMetadata.cpp
@@ -58,8 +58,8 @@ namespace IFF_RIFF {
static const char * trackFunctionTagName = "FUNCTION";
iXMLMetadata::iXMLMetadata()
- : mRootNode( NULL )
- , mExpatAdapter( NULL )
+ : mExpatAdapter( NULL )
+ , mRootNode( NULL )
, mErrorCallback( NULL )
, mExtraSpaceSize( 1024 ) {}
diff --git a/XMPFiles/source/FormatSupport/WEBP_Support.cpp b/XMPFiles/source/FormatSupport/WEBP_Support.cpp
new file mode 100644
index 0000000..2b007de
--- /dev/null
+++ b/XMPFiles/source/FormatSupport/WEBP_Support.cpp
@@ -0,0 +1,273 @@
+#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header.
+
+#include "public/include/XMP_Const.h"
+#include "public/include/XMP_IO.hpp"
+
+#include "XMPFiles/source/XMPFiles_Impl.hpp"
+#include "source/XIO.hpp"
+#include "source/XMPFiles_IO.hpp"
+
+#include "XMPFiles/source/FileHandlers/WEBP_Handler.hpp"
+#include "XMPFiles/source/FormatSupport/WEBP_Support.hpp"
+
+#include <stdexcept> // std::out_of_range
+#include <vector>
+
+using namespace WEBP;
+
+namespace WEBP {
+
+// Constructor for reading an existing chunk
+Chunk::Chunk(Container* parent, WEBP_MetaHandler* handler)
+{
+ this->needsRewrite = (parent) ? parent->needsRewrite : false;
+ this->parent = parent;
+
+ XMP_IO* file = handler->parent->ioRef;
+ this->pos = file->Offset();
+
+ this->tag = XIO::ReadUns32_LE(file);
+
+ this->size = XIO::ReadUns32_LE(file);
+
+ // Make sure the size is within expected bounds.
+ if ((this->pos + this->size + 8) > handler->initialFileSize) {
+ XMP_Throw("Bad RIFF chunk size", kXMPErr_BadFileFormat);
+ }
+
+ this->data.reserve((XMP_Int32) this->size);
+ this->data.assign((XMP_Int32) this->size, '\0');
+ file->ReadAll((void*)this->data.data(), (XMP_Int32) this->size);
+
+ // Account for padding
+ if (this->size & 1) {
+ file->Seek(1, kXMP_SeekFromCurrent);
+ }
+}
+
+// Constructor for creating a new chunk
+Chunk::Chunk(Container* parent, XMP_Uns32 tag)
+ : parent(parent), tag(tag)
+{
+ this->needsRewrite = true;
+}
+
+void Chunk::write(WEBP_MetaHandler* handler)
+{
+ XMP_IO* file = handler->parent->ioRef;
+ if (this->needsRewrite) {
+ this->pos = file->Offset();
+ XIO::WriteUns32_LE(file, this->tag);
+ XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
+ file->Write(this->data.data(), (XMP_Int32) this->size);
+ }
+ else {
+ file->Seek(this->pos + this->size + 8, kXMP_SeekFromStart);
+ }
+ if (this->size & 1) {
+ const XMP_Uns8 zero = 0;
+ file->Write(&zero, 1);
+ }
+}
+
+Chunk::~Chunk()
+{
+ // Do nothing
+}
+
+XMPChunk::XMPChunk(Container* parent)
+ : Chunk(parent, kChunk_XMP_)
+{
+ this->size = 0;
+}
+
+XMPChunk::XMPChunk(Container* parent, WEBP_MetaHandler* handler)
+ : Chunk(parent, handler)
+{
+ handler->packetInfo.offset = this->pos + 8;
+ handler->packetInfo.length = (XMP_Int32) this->data.size();
+
+ handler->xmpPacket.reserve(handler->packetInfo.length);
+ handler->xmpPacket.assign(handler->packetInfo.length, '\0');
+ handler->xmpPacket.insert(handler->xmpPacket.begin(), this->data.begin(),
+ this->data.end());
+
+ handler->containsXMP = true; // last, after all possible failure
+
+ // pointer for later processing
+ handler->xmpChunk = this;
+}
+
+void XMPChunk::write(WEBP_MetaHandler* handler)
+{
+ XMP_IO* file = handler->parent->ioRef;
+ this->size = handler->xmpPacket.size();
+ XIO::WriteUns32_LE(file, this->tag);
+ XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
+ file->Write(handler->xmpPacket.data(), (XMP_Int32) this->size);
+ if (this->size & 1) {
+ const XMP_Uns8 zero = 0;
+ file->Write(&zero, 1);
+ }
+}
+
+VP8XChunk::VP8XChunk(Container* parent)
+ : Chunk(parent, kChunk_VP8X)
+{
+ this->needsRewrite = true;
+ this->size = 10;
+ this->data.resize(this->size);
+ this->data.assign(this->size, 0);
+ XMP_Uns8* bitstream =
+ (XMP_Uns8*)parent->chunks[WEBP_CHUNK_IMAGE][0]->data.data();
+ XMP_Uns32 width = ((bitstream[7] << 8) | bitstream[6]) & 0x3fff;
+ XMP_Uns32 height = ((bitstream[9] << 8) | bitstream[8]) & 0x3fff;
+ this->width(width);
+ this->height(height);
+ parent->vp8x = this;
+}
+
+VP8XChunk::VP8XChunk(Container* parent, WEBP_MetaHandler* handler)
+ : Chunk(parent, handler)
+{
+ this->size = 10;
+ this->needsRewrite = true;
+ parent->vp8x = this;
+}
+
+XMP_Uns32 VP8XChunk::width()
+{
+ return GetLE24(&this->data[4]) + 1;
+}
+void VP8XChunk::width(XMP_Uns32 val)
+{
+ PutLE24(&this->data[4], val - 1);
+}
+XMP_Uns32 VP8XChunk::height()
+{
+ return GetLE24(&this->data[7]) + 1;
+}
+void VP8XChunk::height(XMP_Uns32 val)
+{
+ PutLE24(&this->data[7], val - 1);
+}
+bool VP8XChunk::xmp()
+{
+ XMP_Uns32 flags = GetLE32(&this->data[0]);
+ return (bool)((flags >> XMP_FLAG_BIT) & 1);
+}
+void VP8XChunk::xmp(bool hasXMP)
+{
+ XMP_Uns32 flags = GetLE32(&this->data[0]);
+ flags ^= (-hasXMP ^ flags) & (1 << XMP_FLAG_BIT);
+ PutLE32(&this->data[0], flags);
+}
+
+Container::Container(WEBP_MetaHandler* handler) : Chunk(NULL, handler)
+{
+ this->needsRewrite = false;
+
+ XMP_IO* file = handler->parent->ioRef;
+
+ file->Seek(12, kXMP_SeekFromStart);
+
+ XMP_Int64 size = handler->initialFileSize;
+
+ XMP_Uns32 peek = 0;
+
+ while (file->Offset() < size) {
+ peek = XIO::PeekUns32_LE(file);
+ switch (peek) {
+ case kChunk_XMP_:
+ this->addChunk(new XMPChunk(this, handler));
+ break;
+ case kChunk_VP8X:
+ this->addChunk(new VP8XChunk(this, handler));
+ break;
+ default:
+ this->addChunk(new Chunk(this, handler));
+ break;
+ }
+ }
+
+ if (this->chunks[WEBP_CHUNK_IMAGE].size() == 0) {
+ XMP_Throw("File has no image bitstream", kXMPErr_BadFileFormat);
+ }
+
+ if (this->chunks[WEBP_CHUNK_VP8X].size() == 0) {
+ // The file is either in Lossy or Lossless Simple File Format.
+ // For simplicity we will always convert it to the Extended File Format.
+ this->needsRewrite = true;
+ this->addChunk(new VP8XChunk(this));
+ }
+
+ if (this->chunks[WEBP_CHUNK_XMP].size() == 0) {
+ XMPChunk* xmpChunk = new XMPChunk(this);
+ this->addChunk(xmpChunk);
+ handler->xmpChunk = xmpChunk;
+ this->vp8x->xmp(true);
+ }
+}
+
+Chunk* Container::getExifChunk()
+{
+ if (this->chunks[WEBP::WEBP_CHUNK_EXIF].size() == 0) {
+ return NULL;
+ }
+ return this->chunks[WEBP::WEBP_CHUNK_EXIF][0];
+}
+
+void Container::addChunk(Chunk* chunk)
+{
+ ChunkId idx;
+
+ try {
+ idx = chunkMap.at(chunk->tag);
+ }
+ catch (const std::out_of_range& e) {
+ idx = WEBP_CHUNK_UNKNOWN;
+ }
+ this->chunks[idx].push_back(chunk);
+}
+
+void Container::write(WEBP_MetaHandler* handler)
+{
+ XMP_IO* file = handler->parent->ioRef;
+ file->Rewind();
+ XIO::WriteUns32_LE(file, this->tag);
+ XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
+ XIO::WriteUns32_LE(file, kChunk_WEBP);
+
+ size_t i, j;
+ std::vector<Chunk*> chunkVect;
+ for (i = 0; i < WEBP_CHUNK_NIL; i++) {
+ chunkVect = this->chunks[i];
+ for (j = 0; j < chunkVect.size(); j++) {
+ chunkVect.at(j)->write(handler);
+ }
+ }
+ XMP_Int64 lastOffset = file->Offset();
+ this->size = lastOffset - 8;
+ file->Seek(this->pos + 4, kXMP_SeekFromStart);
+ XIO::WriteUns32_LE(file, (XMP_Uns32) this->size);
+ file->Seek(lastOffset, kXMP_SeekFromStart);
+ if (lastOffset < handler->initialFileSize) {
+ file->Truncate(lastOffset);
+ }
+}
+
+Container::~Container()
+{
+ Chunk* chunk;
+ size_t i;
+ std::vector<Chunk*> chunkVect;
+ for (i = 0; i < WEBP_CHUNK_NIL; i++) {
+ chunkVect = this->chunks[i];
+ while (!chunkVect.empty()) {
+ chunk = chunkVect.back();
+ delete chunk;
+ chunkVect.pop_back();
+ }
+ }
+}
+}
diff --git a/XMPFiles/source/FormatSupport/WEBP_Support.hpp b/XMPFiles/source/FormatSupport/WEBP_Support.hpp
new file mode 100644
index 0000000..aebe781
--- /dev/null
+++ b/XMPFiles/source/FormatSupport/WEBP_Support.hpp
@@ -0,0 +1,174 @@
+#ifndef __WEBP_Support_hpp__
+#define __WEBP_Support_hpp__ 1
+
+#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header.
+
+#include "public/include/XMP_Const.h"
+#include "public/include/XMP_IO.hpp"
+
+#include "XMPFiles/source/XMPFiles_Impl.hpp"
+#include "source/Endian.h"
+#include "source/XMPFiles_IO.hpp"
+
+#include <array>
+#include <map>
+#include <vector>
+
+// forward declaration:
+class WEBP_MetaHandler;
+
+namespace WEBP {
+
+// Read 16, 24 or 32 bits stored in little-endian order.
+//
+// The inline functions provided in EndianUtils.hpp and XIO.hpp operate on
+// pointers to XMP_Uns32, and then flip the bytes if the desired endianness
+// differs from the host's. It seems to me that it is much simpler to read
+// the data into XMP_Uns8 (i.e. unsigned char) arrays and just use shift
+// operators (which operate on values rather than their representation
+// in memory) to convert between values and the bytes read from or written to
+// a file in a platform-independent way. And besides, WEBP stores dimensions
+// in 24 bit LE, and converting that to and from a 32 bit pointer, having to
+// account for the platform's endianness, would be a nightmare.
+static inline XMP_Uns32 GetLE16(const XMP_Uns8* const data)
+{
+ return (XMP_Uns32)(data[0] << 0) | (data[1] << 8);
+}
+
+static inline XMP_Uns32 GetLE24(const XMP_Uns8* const data)
+{
+ return GetLE16(data) | (data[2] << 16);
+}
+
+static inline XMP_Uns32 GetLE32(const XMP_Uns8* const data)
+{
+ return (XMP_Uns32)GetLE16(data) | (GetLE16(data + 2) << 16);
+}
+
+// Store 16, 24 or 32 bits in little-endian order.
+static inline void PutLE16(XMP_Uns8* const data, XMP_Uns32 val)
+{
+ assert(val < (1 << 16));
+ data[0] = (val >> 0);
+ data[1] = (val >> 8);
+}
+
+static inline void PutLE24(XMP_Uns8* const buf, XMP_Uns32 val)
+{
+ assert(val < (1 << 24));
+ PutLE16(buf, val & 0xffff);
+ buf[2] = (val >> 16);
+}
+
+static inline void PutLE32(XMP_Uns8* const data, XMP_Uns32 val)
+{
+ PutLE16(data, (XMP_Uns32)(val & 0xffff));
+ PutLE16(data + 2, (XMP_Uns32)(val >> 16));
+}
+
+#define WEBP_MKFOURCC(a, b, c, d) \
+ ((XMP_Uns32)(a) | (b) << 8 | (c) << 16 | (d) << 24)
+
+// VP8X Feature Flags.
+typedef enum FeatureFlagBits {
+ FRAGMENTS_FLAG_BIT, // Experimental, not enabled by default
+ ANIMATION_FLAG_BIT,
+ XMP_FLAG_BIT,
+ EXIF_FLAG_BIT,
+ ALPHA_FLAG_BIT,
+ ICCP_FLAG_BIT
+} FeatureFlagBits;
+
+typedef enum ChunkId {
+ WEBP_CHUNK_VP8X, // VP8X
+ WEBP_CHUNK_ICCP, // ICCP
+ WEBP_CHUNK_ANIM, // ANIM
+ WEBP_CHUNK_ANMF, // ANMF
+ WEBP_CHUNK_FRGM, // FRGM
+ WEBP_CHUNK_ALPHA, // ALPH
+ WEBP_CHUNK_IMAGE, // VP8/VP8L
+ WEBP_CHUNK_EXIF, // EXIF
+ WEBP_CHUNK_XMP, // XMP
+ WEBP_CHUNK_UNKNOWN, // Other chunks.
+ WEBP_CHUNK_NIL
+} ChunkId;
+
+const XMP_Uns32 kChunk_RIFF = WEBP_MKFOURCC('R', 'I', 'F', 'F');
+const XMP_Uns32 kChunk_WEBP = WEBP_MKFOURCC('W', 'E', 'B', 'P');
+const XMP_Uns32 kChunk_VP8_ = WEBP_MKFOURCC('V', 'P', '8', ' ');
+const XMP_Uns32 kChunk_VP8L = WEBP_MKFOURCC('V', 'P', '8', 'L');
+const XMP_Uns32 kChunk_VP8X = WEBP_MKFOURCC('V', 'P', '8', 'X');
+const XMP_Uns32 kChunk_XMP_ = WEBP_MKFOURCC('X', 'M', 'P', ' ');
+const XMP_Uns32 kChunk_ANIM = WEBP_MKFOURCC('A', 'N', 'I', 'M');
+const XMP_Uns32 kChunk_ICCP = WEBP_MKFOURCC('I', 'C', 'C', 'P');
+const XMP_Uns32 kChunk_EXIF = WEBP_MKFOURCC('E', 'X', 'I', 'F');
+const XMP_Uns32 kChunk_ANMF = WEBP_MKFOURCC('A', 'N', 'M', 'F');
+const XMP_Uns32 kChunk_FRGM = WEBP_MKFOURCC('F', 'R', 'G', 'M');
+const XMP_Uns32 kChunk_ALPH = WEBP_MKFOURCC('A', 'L', 'P', 'H');
+
+static std::map<XMP_Uns32, ChunkId> chunkMap = {
+ { kChunk_VP8X, WEBP_CHUNK_VP8X }, { kChunk_ICCP, WEBP_CHUNK_ICCP },
+ { kChunk_ANIM, WEBP_CHUNK_ANIM }, { kChunk_ANMF, WEBP_CHUNK_ANMF },
+ { kChunk_FRGM, WEBP_CHUNK_FRGM }, { kChunk_ALPH, WEBP_CHUNK_ALPHA },
+ { kChunk_VP8_, WEBP_CHUNK_IMAGE }, { kChunk_VP8L, WEBP_CHUNK_IMAGE },
+ { kChunk_EXIF, WEBP_CHUNK_EXIF }, { kChunk_XMP_, WEBP_CHUNK_XMP }
+};
+
+class Container;
+
+class Chunk {
+public:
+ Chunk(Container* parent, WEBP_MetaHandler* handler);
+ Chunk(Container* parent, XMP_Uns32 tag);
+ virtual ~Chunk();
+
+ virtual void write(WEBP_MetaHandler* handler);
+
+ Container* parent;
+ XMP_Uns32 tag;
+ RawDataBlock data;
+ XMP_Int64 pos;
+ XMP_Int64 size;
+ bool needsRewrite;
+};
+
+class XMPChunk
+ : public Chunk {
+public:
+ XMPChunk(Container* parent, WEBP_MetaHandler* handler);
+ XMPChunk(Container* parent);
+ void write(WEBP_MetaHandler* handler);
+};
+
+class VP8XChunk
+ : public Chunk {
+public:
+ VP8XChunk(Container* parent, WEBP_MetaHandler* handler);
+ VP8XChunk(Container* parent);
+ bool xmp();
+ void xmp(bool);
+ XMP_Uns32 width();
+ XMP_Uns32 height();
+ void width(XMP_Uns32);
+ void height(XMP_Uns32);
+};
+
+typedef std::array<std::vector<Chunk*>, WEBP_CHUNK_NIL> Chunks;
+
+class Container
+ : public Chunk {
+public:
+ Container(WEBP_MetaHandler* handler);
+ ~Container();
+
+ void write(WEBP_MetaHandler* handler);
+ void addChunk(Chunk*);
+ Chunk* getExifChunk();
+
+ Chunks chunks;
+ VP8XChunk* vp8x;
+};
+
+} // namespace WEBP
+
+#endif // __WEBP_Support_hpp__
diff --git a/XMPFiles/source/FormatSupport/XMPScanner.cpp b/XMPFiles/source/FormatSupport/XMPScanner.cpp
index 14552de..22726d0 100644
--- a/XMPFiles/source/FormatSupport/XMPScanner.cpp
+++ b/XMPFiles/source/FormatSupport/XMPScanner.cpp
@@ -989,7 +989,7 @@ XMPScanner::InternalSnip::InternalSnip ( XMP_Int64 offset, XMP_Int64 length )
XMPScanner::InternalSnip::InternalSnip ( const InternalSnip & rhs ) :
fInfo ( rhs.fInfo ),
- fMachine ( NULL )
+ fMachine ()
{
assert ( rhs.fMachine.get() == NULL ); // Don't copy a snip with a machine.
@@ -1257,13 +1257,13 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
} else {
// *** snipPos->fMachine.reset ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) ); VC++ lacks reset
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine> ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );
+ snipPos->fMachine = unique_ptr<PacketMachine> ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
PacketMachine * pm = new PacketMachine ( bufferOffset, bufferOrigin, bufferLength );
- auto_ptr<PacketMachine> ap ( pm );
- snipPos->fMachine = ap;
+ unique_ptr<PacketMachine> ap ( pm );
+ snipPos->fMachine = std::move(ap);
}
#endif
thisMachine = snipPos->fMachine.get();
@@ -1282,12 +1282,12 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
snipPos->fInfo.fState = eRawInputSnip;
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
+ snipPos->fMachine = unique_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
- auto_ptr<PacketMachine> ap ( 0 );
- snipPos->fMachine = ap;
+ unique_ptr<PacketMachine> ap;
+ snipPos->fMachine = std::move(ap);
}
#endif
bufferDone = true;
@@ -1375,12 +1375,12 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
// This packet ends exactly at the end of the current snip.
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
+ snipPos->fMachine = unique_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
- auto_ptr<PacketMachine> ap ( 0 );
- snipPos->fMachine = ap;
+ unique_ptr<PacketMachine> ap;
+ snipPos->fMachine = std::move(ap);
}
#endif
bufferDone = true;
@@ -1392,7 +1392,7 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
InternalSnipIterator tailPos = NextSnip ( snipPos );
- tailPos->fMachine = snipPos->fMachine; // auto_ptr assignment - taking ownership
+ tailPos->fMachine = std::move(snipPos->fMachine); // unique_ptr assignment - taking ownership
thisMachine->ResetMachine ();
snipPos = tailPos;
diff --git a/XMPFiles/source/FormatSupport/XMPScanner.hpp b/XMPFiles/source/FormatSupport/XMPScanner.hpp
index 1648692..841f2ec 100644
--- a/XMPFiles/source/FormatSupport/XMPScanner.hpp
+++ b/XMPFiles/source/FormatSupport/XMPScanner.hpp
@@ -156,7 +156,7 @@ private: // XMPScanner
public:
SnipInfo fInfo; // The public info about this snip.
- std::auto_ptr<PacketMachine> fMachine; // The state machine for "active" snips.
+ std::unique_ptr<PacketMachine> fMachine; // The state machine for "active" snips.
InternalSnip ( XMP_Int64 offset, XMP_Int64 length );
InternalSnip ( const InternalSnip & );
diff --git a/XMPFiles/source/HandlerRegistry.cpp b/XMPFiles/source/HandlerRegistry.cpp
index cc58d34..60547fc 100644
--- a/XMPFiles/source/HandlerRegistry.cpp
+++ b/XMPFiles/source/HandlerRegistry.cpp
@@ -40,6 +40,7 @@
#include "XMPFiles/source/FileHandlers/XDCAMEX_Handler.hpp"
#include "XMPFiles/source/FileHandlers/XDCAMFAM_Handler.hpp"
#include "XMPFiles/source/FileHandlers/XDCAMSAM_Handler.hpp"
+ #include "XMPFiles/source/FileHandlers/WEBP_Handler.hpp"
#endif
#if EnableMiscHandlers
@@ -144,6 +145,7 @@ void HandlerRegistry::initialize()
allOK &= this->registerNormalHandler ( kXMP_MP3File, kMP3_HandlerFlags, MP3_CheckFormat, MP3_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_WAVFile, kWAVE_HandlerFlags, WAVE_CheckFormat, WAVE_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_AVIFile, kRIFF_HandlerFlags, RIFF_CheckFormat, RIFF_MetaHandlerCTor );
+ allOK &= this->registerNormalHandler ( kXMP_WEBPFile, kWEBP_HandlerFlags, WEBP_CheckFormat, WEBP_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_SWFFile, kSWF_HandlerFlags, SWF_CheckFormat, SWF_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_MPEG4File, kMPEG4_HandlerFlags, MPEG4_CheckFormat, MPEG4_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_MOVFile, kMPEG4_HandlerFlags, MPEG4_CheckFormat, MPEG4_MetaHandlerCTor ); // ! Yes, MPEG-4 includes MOV.
@@ -155,6 +157,7 @@ void HandlerRegistry::initialize()
allOK &= this->registerNormalHandler ( kXMP_InDesignFile, kInDesign_HandlerFlags, InDesign_CheckFormat, InDesign_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_PNGFile, kPNG_HandlerFlags, PNG_CheckFormat, PNG_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_UCFFile, kUCF_HandlerFlags, UCF_CheckFormat, UCF_MetaHandlerCTor );
+ allOK &= this->registerNormalHandler ( kXMP_GIFFile, kGIF_HandlerFlags, GIF_CheckFormat, GIF_MetaHandlerCTor );
// ! EPS and PostScript have the same handler, EPS is a proper subset of PostScript.
allOK &= this->registerNormalHandler ( kXMP_EPSFile, kPostScript_HandlerFlags, PostScript_CheckFormat, PostScript_MetaHandlerCTor );
allOK &= this->registerNormalHandler ( kXMP_PostScriptFile, kPostScript_HandlerFlags, PostScript_CheckFormat, PostScript_MetaHandlerCTor );
diff --git a/XMPFiles/source/Makefile.am b/XMPFiles/source/Makefile.am
new file mode 100644
index 0000000..6d1a1d3
--- /dev/null
+++ b/XMPFiles/source/Makefile.am
@@ -0,0 +1,57 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SUBDIRS = FileHandlers FormatSupport NativeMetadataSupport PluginHandler
+
+noinst_LTLIBRARIES = libXMPFiles.la
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions -fno-strict-aliasing
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/public/include \
+ -I$(top_srcdir)/XMPFilesPlugins/api/source/ \
+ -Wall @XMPCORE_CPPFLAGS@
+
+noinst_HEADERS = XMPFiles.hpp XMPFiles_Impl.hpp HandlerRegistry.h
+
+libXMPFiles_la_SOURCES = WXMPFiles.cpp XMPFiles.cpp \
+ XMPFiles_Impl.cpp HandlerRegistry.cpp
+
+
+libXMPFiles_la_LIBADD = ./FileHandlers/libxmpfilehandlers.la \
+ ./FormatSupport/libformatsupport.la \
+ ./PluginHandler/libpluginhandler.la \
+ ./NativeMetadataSupport/libnativemetadata.la
+#libXMPFiles_la_LDFLAGS = -version-info @LIBXMPCORE_VERSION_INFO@
diff --git a/XMPFiles/source/NativeMetadataSupport/Makefile.am b/XMPFiles/source/NativeMetadataSupport/Makefile.am
new file mode 100644
index 0000000..2606720
--- /dev/null
+++ b/XMPFiles/source/NativeMetadataSupport/Makefile.am
@@ -0,0 +1,51 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+noinst_LTLIBRARIES = libnativemetadata.la
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions -fno-strict-aliasing
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/public/include \
+ -I$(top_srcdir)/XMPFilesPlugins/api/source/ \
+ -Wall @XMPCORE_CPPFLAGS@
+
+libnativemetadata_la_SOURCES = \
+ IMetadata.cpp IMetadata.h \
+ IReconcile.cpp IReconcile.h \
+ MetadataSet.cpp MetadataSet.h \
+ ValueObject.h \
+ $(NULL)
diff --git a/XMPFiles/source/NativeMetadataSupport/ValueObject.h b/XMPFiles/source/NativeMetadataSupport/ValueObject.h
index cd4b6d9..4ef2f50 100644
--- a/XMPFiles/source/NativeMetadataSupport/ValueObject.h
+++ b/XMPFiles/source/NativeMetadataSupport/ValueObject.h
@@ -10,6 +10,8 @@
#ifndef _ValueObject_h_
#define _ValueObject_h_
+#include <string.h>
+
#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header.
#include "public/include/XMP_Const.h"
diff --git a/XMPFiles/source/PluginHandler/FileHandler.h b/XMPFiles/source/PluginHandler/FileHandler.h
index ca43ced..96c344b 100644
--- a/XMPFiles/source/PluginHandler/FileHandler.h
+++ b/XMPFiles/source/PluginHandler/FileHandler.h
@@ -51,7 +51,7 @@ class FileHandler
public:
FileHandler(std::string & uid, XMP_OptionBits handlerFlags, FileHandlerType type, ModuleSharedPtr module):
- mVersion(0), mUID(uid), mHandlerFlags(handlerFlags), mOverwrite(false), mType(type), mModule(module),mSerializeOption(0) {}
+ mVersion(0), mUID(uid), mHandlerFlags(handlerFlags), mSerializeOption(0), mOverwrite(false), mType(type), mModule(module) {}
virtual ~FileHandler(){}
diff --git a/XMPFiles/source/PluginHandler/Makefile.am b/XMPFiles/source/PluginHandler/Makefile.am
new file mode 100644
index 0000000..0c0a6f6
--- /dev/null
+++ b/XMPFiles/source/PluginHandler/Makefile.am
@@ -0,0 +1,61 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+noinst_LTLIBRARIES = libpluginhandler.la
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions -fno-strict-aliasing
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/public/include \
+ -I$(top_srcdir)/XMPFilesPlugins/api/source/ \
+ -Wall @XMPCORE_CPPFLAGS@
+
+if MAC_ENV
+PLATFORM_UTILS=OS_Utils_Mac.cpp
+else
+PLATFORM_UTILS=OS_Utils_Linux.cpp
+endif
+
+libpluginhandler_la_SOURCES = FileHandler.h \
+ FileHandlerInstance.cpp FileHandlerInstance.h \
+ HostAPIImpl.cpp \
+ Module.cpp Module.h ModuleUtils.h \
+ PluginManager.cpp PluginManager.h \
+ XMPAtoms.cpp XMPAtoms.h \
+ $(PLATFORM_UTILS) \
+ $(NULL)
+
+EXTRA_DIST=OS_Utils_Linux.cpp OS_Utils_WIN.cpp OS_Utils_Mac.cpp
diff --git a/XMPFiles/source/PluginHandler/XMPAtoms.h b/XMPFiles/source/PluginHandler/XMPAtoms.h
index 4cacef0..3daad38 100644
--- a/XMPFiles/source/PluginHandler/XMPAtoms.h
+++ b/XMPFiles/source/PluginHandler/XMPAtoms.h
@@ -100,7 +100,7 @@ class ResourceParser
{
public:
ResourceParser(ModuleSharedPtr module)
- : mModule(module), mFlags(0), mSerializeOption(0), mType(0), mVersion(0.0), mOverwriteHandler(false) {}
+ : mModule(module), mType(0), mFlags(0), mSerializeOption(0), mVersion(0.0), mOverwriteHandler(false) {}
/**
* Initialize the XMPAtoms which will be used in parsing resource files.
diff --git a/XMPFiles/source/XMPFiles_Impl.cpp b/XMPFiles/source/XMPFiles_Impl.cpp
index 5914560..febb790 100644
--- a/XMPFiles/source/XMPFiles_Impl.cpp
+++ b/XMPFiles/source/XMPFiles_Impl.cpp
@@ -92,6 +92,7 @@ const FileExtMapping kFileExtMap[] =
{ "avi", kXMP_AVIFile },
{ "cin", kXMP_CINFile },
{ "wav", kXMP_WAVFile },
+ { "webp", kXMP_WEBPFile },
{ "mp3", kXMP_MP3File },
{ "mp4", kXMP_MPEG4File },
{ "m4v", kXMP_MPEG4File },
@@ -517,4 +518,4 @@ void XMPFileHandler::NotifyClient(GenericErrorCallback * errCBptr, XMP_ErrorSeve
throw error;
}
}
-// ================================================================================================= \ No newline at end of file
+// =================================================================================================
diff --git a/XMPFiles/source/XMPFiles_Impl.hpp b/XMPFiles/source/XMPFiles_Impl.hpp
index b70d88c..f8bc5ac 100644
--- a/XMPFiles/source/XMPFiles_Impl.hpp
+++ b/XMPFiles/source/XMPFiles_Impl.hpp
@@ -149,11 +149,11 @@ extern XMP_StringPtr voidStringPtr;
extern XMP_StringLen voidStringLen;
extern XMP_OptionBits voidOptionBits;
-static const XMP_Uns8 * kUTF8_PacketStart = (const XMP_Uns8 *) "<?xpacket begin=";
-static const XMP_Uns8 * kUTF8_PacketID = (const XMP_Uns8 *) "W5M0MpCehiHzreSzNTczkc9d";
+#define kUTF8_PacketStart (const XMP_Uns8 *)"<?xpacket begin="
+#define kUTF8_PacketID (const XMP_Uns8 *)"W5M0MpCehiHzreSzNTczkc9d"
static const size_t kUTF8_PacketHeaderLen = 51; // ! strlen ( "<?xpacket begin='xxx' id='W5M0MpCehiHzreSzNTczkc9d'" )
-static const XMP_Uns8 * kUTF8_PacketTrailer = (const XMP_Uns8 *) "<?xpacket end=\"w\"?>";
+#define kUTF8_PacketTrailer (const XMP_Uns8 *)"<?xpacket end=\"w\"?>"
static const size_t kUTF8_PacketTrailerLen = 19; // ! strlen ( kUTF8_PacketTrailer )
struct FileExtMapping {
diff --git a/XMPFilesPlugins/Makefile.am b/XMPFilesPlugins/Makefile.am
new file mode 100644
index 0000000..24fd3a6
--- /dev/null
+++ b/XMPFilesPlugins/Makefile.am
@@ -0,0 +1,4 @@
+
+
+
+SUBDIRS=api PDF_Handler
diff --git a/XMPFilesPlugins/PDF_Handler/Makefile.am b/XMPFilesPlugins/PDF_Handler/Makefile.am
new file mode 100644
index 0000000..310146c
--- /dev/null
+++ b/XMPFilesPlugins/PDF_Handler/Makefile.am
@@ -0,0 +1,3 @@
+
+
+EXTRA_DIST = README.exempi
diff --git a/XMPFilesPlugins/PDF_Handler/README.exempi b/XMPFilesPlugins/PDF_Handler/README.exempi
new file mode 100644
index 0000000..f5fceac
--- /dev/null
+++ b/XMPFilesPlugins/PDF_Handler/README.exempi
@@ -0,0 +1,6 @@
+This directory usually contains a proprietary PDF Handler
+written by Adobe. There is no source code.
+
+It has been omitted from the Exempi tarball.
+
+Check the source code repository. \ No newline at end of file
diff --git a/XMPFilesPlugins/api/Makefile.am b/XMPFilesPlugins/api/Makefile.am
new file mode 100644
index 0000000..57fb028
--- /dev/null
+++ b/XMPFilesPlugins/api/Makefile.am
@@ -0,0 +1,2 @@
+
+SUBDIRS=source
diff --git a/XMPFilesPlugins/api/source/Makefile.am b/XMPFilesPlugins/api/source/Makefile.am
new file mode 100644
index 0000000..ece8912
--- /dev/null
+++ b/XMPFilesPlugins/api/source/Makefile.am
@@ -0,0 +1,13 @@
+
+
+EXTRA_DIST = HostAPIAccess.cpp \
+ HostAPIAccess.h\
+ HostAPI.h\
+ PluginAPIImpl.cpp\
+ PluginBase.cpp\
+ PluginBase.h\
+ PluginConst.h\
+ PluginHandler.h\
+ PluginRegistry.cpp\
+ PluginRegistry.h\
+ $(NULL)
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..9bb10bc
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+#
+# part of libopenraw
+#
+
+
+topsrcdir=`dirname $0`
+if test x$topsrcdir = x ; then
+ topsrcdir=.
+fi
+
+builddir=`pwd`
+
+AUTOCONF=autoconf
+
+LIBTOOL=$(command -v glibtool)
+if [ -z "$LIBTOOL" ]; then
+ LIBTOOL=libtool
+fi
+
+LIBTOOLIZE=$(command -v glibtoolize)
+if [ -z "$LIBTOOLIZE" ]; then
+ LIBTOOLIZE=libtoolize
+fi
+
+
+AUTOMAKE=automake
+ACLOCAL=aclocal
+
+cd $topsrcdir
+
+rm -f autogen.err
+$LIBTOOLIZE --force
+$ACLOCAL -I m4 >> autogen.err 2>&1
+
+#autoheader --force
+$AUTOMAKE --add-missing --copy --foreign
+$AUTOCONF
+
+cd $builddir
+
+
+if [ "$NOCONFIGURE" = "" ]; then
+ if test -z "$*"; then
+ echo "I am going to run ./configure with --enable-maintainer-mode"
+ echo "If you wish to pass any to it, please specify them on "
+ echo "the $0 command line."
+ fi
+ echo "Running configure..."
+ $topsrcdir/configure --enable-maintainer-mode "$@"
+fi
diff --git a/build/GNUmakefile.am b/build/GNUmakefile.am
new file mode 100644
index 0000000..1cdb0f1
--- /dev/null
+++ b/build/GNUmakefile.am
@@ -0,0 +1,37 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+noinst_HEADERS=XMP_BuildInfo.h \ No newline at end of file
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..6f67259
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,268 @@
+dnl Copyright (C) 2007-2010 Hubert Figuiere
+dnl Small portions are:
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+AC_PREREQ(2.50)
+AC_INIT(exempi,2.4.0)
+AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects])
+AM_MAINTAINER_MODE
+m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
+AM_SILENT_RULES([yes])
+
+dnl ---------------------------------------------------------------------------
+dnl Advanced information about versioning:
+dnl * "Writing shared libraries" by Mike Hearn
+dnl http://plan99.net/~mike/writing-shared-libraries.html
+dnl * libtool.info chapter "Versioning"
+dnl * libtool.info chapter "Updating library version information"
+dnl ---------------------------------------------------------------------------
+dnl Versioning:
+dnl - CURRENT (Major): Increment if the interface has changes. AGE is always
+dnl *changed* at the same time.
+dnl - AGE (Micro): Increment if any interfaces have been added; set to 0
+dnl if any interfaces have been removed. Removal has
+dnl precedence over adding, so set to 0 if both happened.
+dnl It denotes upward compatibility.
+dnl - REVISION (Minor): Increment any time the source changes; set to
+dnl 0 if you incremented CURRENT.
+dnl
+dnl To summarize. Any interface *change* increment CURRENT. If that interface
+dnl change does not break upward compatibility (ie it is an addition),
+dnl increment AGE, Otherwise AGE is reset to 0. If CURRENT has changed,
+dnl REVISION is set to 0, otherwise REVISION is incremented.
+dnl ---------------------------------------------------------------------------
+dnl 1.99.0 is the revision 2 0 0
+dnl 1.99.1 is the revision 3 1 0
+dnl 1.99.2 is the revision 4 2 0
+dnl 1.99.3 is the revision 5 3 0
+dnl 1.99.4 is the revision 6 4 0
+dnl ABI breakage reset major to 3
+dnl 1.99.5 is the revision 3.0.0
+dnl 1.99.6 is the revision 3.1.0 WHICH IS WRONG!!!
+dnl 1.99.7 is the revision 4.1.0
+dnl 1.99.8 is the revision 4.1.1
+dnl 1.99.9 is the revision 4.1.1 (no library change have been made)
+dnl 2.0.0 is the revision 4.1.2
+dnl 2.0.1 is the revision 4.1.3
+dnl 2.0.2 is the revision 4.1.4
+dnl 2.1.0 is the revision 5.2.0
+dnl 2.1.1 is the revision 5.2.1
+dnl 2.2.0 is the revision 5.2.2 -- no public API change
+dnl 2.2.1 is the revision 5.2.3 -- no public API change
+dnl 2.2.2 is the revision 5.2.4 -- no public API change
+dnl 2.2.3 is the revision 5.2.5 -- no public API change
+dnl 2.3.0 is the revision 6.3.0
+dnl 2.4.0 is the revision 7.4.0
+AC_SUBST([EXEMPI_REVISION], [0])
+AC_SUBST([EXEMPI_AGE], [4])
+AC_SUBST([EXEMPI_CURRENT], [7])
+AC_SUBST([EXEMPI_CURRENT_MIN],
+ [`expr $EXEMPI_CURRENT - $EXEMPI_AGE`])
+AC_SUBST([EXEMPI_VERSION_INFO],
+ [$EXEMPI_CURRENT:$EXEMPI_REVISION:$EXEMPI_AGE])
+
+dnl the major version. used for package names, etc
+EXEMPI_MAJOR_VERSION=2.0
+AC_SUBST(EXEMPI_MAJOR_VERSION)
+
+dnl the path where includes are installed
+EXEMPI_INCLUDE_BASE=exempi-$EXEMPI_MAJOR_VERSION
+AC_SUBST(EXEMPI_INCLUDE_BASE)
+
+dnl --------------------------------------------------------------------
+dnl guess directory to install *.pc into
+dnl --------------------------------------------------------------------
+pkgconfigdir='${libdir}/pkgconfig'
+AC_SUBST(pkgconfigdir)
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AX_CXX_COMPILE_STDCXX_11(noext,mandatory)
+
+AC_C_BIGENDIAN
+AC_DEFINE(CHECKED_ENDIANNESS)
+AC_LANG(C++)
+
+AC_ARG_WITH(darwinports,[ --with-darwinports add /opt/local/... to CPP/LDFLAGS (Mac OSX)],[
+ if test "x$withval" != "xno"; then
+ CPPFLAGS="$CPPFLAGS -I/opt/local/include"
+ LDFLAGS="$LDFLAGS -L/opt/local/lib"
+ CC=g++
+ fi
+])
+AC_ARG_WITH(fink,[ --with-fink add /sw/... to CPP/LDFLAGS (Mac OSX)],[
+ if test "x$withval" != "xno"; then
+ CPPFLAGS="$CPPFLAGS -I/sw/include"
+ LDFLAGS="$LDFLAGS -L/sw/lib"
+ CC=g++
+ fi
+])
+
+
+AC_CHECK_HEADER(expat.h, ,
+ AC_MSG_ERROR([expat headers missing]))
+AC_CHECK_HEADER(iconv.h, ,
+ AC_MSG_ERROR([iconv headers missing]))
+AC_CHECK_HEADER(zlib.h, ,
+ AC_MSG_ERROR([zlib headers missing]))
+
+dnl Blatently copied from iconv.m4 to remove the crack about libtool
+dnl But check for constness of the iconv parameters.
+AC_MSG_CHECKING([for iconv declaration])
+AC_CACHE_VAL(am_cv_proto_iconv, [
+ AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+ am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+AC_MSG_RESULT([$]{ac_t:-
+ }[$]am_cv_proto_iconv)
+AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+ [Define as const if the declaration of iconv() needs const.])
+dnl end iconv checks
+
+
+dnl TLS.
+AX_TLS
+if test "$ac_cv_tls" != "none"; then
+ AC_DEFINE(HAVE_NATIVE_TLS, [1], [Define if compiler has native TLS.])
+fi
+dnl end TLS
+
+dnl check LD Flags
+dnl we need a valid symfile. Make one.
+cat >> _ac_foo.sym << _ACEOF
+foo
+_ACEOF
+AX_LD_CHECK_FLAG([-Wl,--retain-symbols-file=_ac_foo.sym],[],[],[
+dnl success
+cv_support_symfile=yes
+],[
+dnl fail
+cv_support_symfile=no
+])
+rm -f _ac_foo.sym
+AM_CONDITIONAL(HAVE_SYMBOLS_FILE, test x$cv_support_symfile = "xyes")
+
+
+AC_ARG_ENABLE(unittest,
+ AC_HELP_STRING([--enable-unittest=yes|no],
+ [enable the unittest. requires boost (default is yes)]),
+ ENABLE_UNITTEST=$enableval,
+ ENABLE_UNITTEST=yes)
+if test x$ENABLE_UNITTEST = xyes ; then
+ BOOST_REQUIRE([1.48.0])
+ BOOST_TEST([mt-s])
+else
+ ENABLE_UNITTEST=no
+fi
+
+
+case $build_vendor in
+ apple)
+ EXEMPI_PLATFORM_DEF=MAC_ENV
+ LDFLAGS="$LDFLAGS -framework CoreServices -stdlib=libc++"
+ CPPFLAGS="$CPPFLAGS -std=c++11 -stdlib=libc++"
+ ;;
+ *)
+ EXEMPI_PLATFORM_DEF=UNIX_ENV
+ ;;
+esac
+
+AC_SUBST(EXEMPI_PLATFORM_DEF)
+AM_CONDITIONAL(MAC_ENV, test x$EXEMPI_PLATFORM_DEF = xMAC_ENV)
+AM_CONDITIONAL(UNIX_ENV, test x$EXEMPI_PLATFORM_DEF = xUNIX_ENV)
+
+AM_CONDITIONAL(WITH_UNIT_TEST, test x$ENABLE_UNITTEST = xyes)
+
+dnl Check for valgrind (optional) for make check.
+dnl AC_CHECK_PROG(VALGRIND, valgrind, valgrind)
+AC_CHECK_HEADERS(valgrind/memcheck.h)
+if test "$VALGRIND" = ""; then
+ AC_MSG_WARN([Valgrind is missing. checks will run without])
+fi
+if test "$VALGRIND" != ""; then
+dnl due to stupid m4 I had to double the [ and ] in the regexp
+ vg_ver=`valgrind --version | sed -e 's/.*-\([[0-9]]\)\.[[0-9]].*/\1/'`
+ VALGRIND="$VALGRIND --tool=memcheck --leak-check=yes --num-callers=10 --error-exitcode=100"
+ if test "$vg_ver" != "3" ; then
+ VALGRIND="$VALGRIND --logfile-fd=-1"
+ fi
+fi
+AC_SUBST(VALGRIND)
+
+AC_ARG_ENABLE(asan,[ --enable-asan Turn on address sanitizer],[
+ AX_APPEND_COMPILE_FLAGS([-fsanitize=address -fno-omit-frame-pointer])
+]
+,
+[
+
+])
+
+XMPCORE_CPPFLAGS="-D$EXEMPI_PLATFORM_DEF=1 -DXMP_IMPL=1 -DXMP_ClientBuild=0 \
+ -DXMP_StaticBuild=1 -DBanAllEntityUsage \
+ -D_FILE_OFFSET_BITS=64 -DHAVE_EXPAT_CONFIG_H=1 -DXML_STATIC=1 \
+ -DDISABLE_QUICKTIME"
+AC_SUBST(XMPCORE_CPPFLAGS)
+
+AC_OUTPUT([
+Makefile
+third-party/Makefile
+third-party/zuid/interfaces/Makefile
+third-party/zlib/Makefile
+third-party/expat/Makefile
+source/Makefile
+XMPCore/Makefile
+XMPCore/source/Makefile
+XMPFiles/Makefile
+XMPFiles/source/Makefile
+XMPFiles/source/FileHandlers/Makefile
+XMPFiles/source/FormatSupport/Makefile
+XMPFiles/source/NativeMetadataSupport/Makefile
+XMPFiles/source/PluginHandler/Makefile
+XMPFilesPlugins/Makefile
+XMPFilesPlugins/api/Makefile
+XMPFilesPlugins/api/source/Makefile
+XMPFilesPlugins/PDF_Handler/Makefile
+samples/Makefile
+samples/source/Makefile
+samples/testfiles/Makefile
+build/GNUmakefile
+public/Makefile
+public/include/Makefile
+public/include/client-glue/Makefile
+exempi/Makefile
+exempi/doc/Makefile
+exempi/doc/Doxyfile
+exempi/tests/Makefile
+exempi/exempi-2.0.pc
+])
+
+
+echo "
+Defines:
+
+ EXEMPI_PLATFORM_DEF = $EXEMPI_PLATFORM_DEF
+ CPPFLAGS = $CPPFLAGS
+ LDFLAGS = $LDFLAGS
+ Thread Local Storage = $ac_cv_tls
+ Run unit test = $ENABLE_UNITTEST
+"
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..4f68d4d
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,12 @@
+exempi (1.99.2+git20070625) unstable; urgency=low
+
+ * New upstream version
+
+ -- Hubert Figuiere <hub@figuiere.net> Wed, 6 Jun 2007 22:15:52 -0400
+
+exempi (1.99.0+git20070526) unstable; urgency=low
+
+ * Initial release
+
+ -- Hubert Figuiere <hub@figuiere.net> Sat, 26 May 2007 16:35:34 -0400
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..d0bf923
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,32 @@
+Source: exempi
+Section: libs
+Priority: extra
+Maintainer: Hubert Figuiere <hub@figuiere.net>
+Build-Depends: debhelper (>> 5.0.0), cdbs (>= 0.4.30), libboost-dev (>= 1.33), libexpat1-dev
+Standards-Version: 3.7.2
+
+
+Package: libexempi-dev
+Section: libdevel
+Depends: libexempi3 (= ${Source-Version})
+Architecture: any
+Description: A library to parse XMP metadata (Development files)
+ Exempi is a library to parse XMP metadata as defined by the
+ specification.
+
+
+Package: libexempi3-dbg
+Architecture: any
+Depends: libexempi3 (= ${Source-Version})
+Description: A library to parse XMP metadata (Debug files)
+ Exempi is a library to parse XMP metadata as defined by the
+ specification.
+
+
+Package: libexempi3
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: A library to parse XMP metadata (Library)
+ Exempi is a library to parse XMP metadata as defined by the
+ specification.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..4c8eaba
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,36 @@
+This package was debianized by Hubert Figuiere <hub@figuiere.net> on
+Mon Mar 12 22:22:41 EDT 2007
+
+It was downloaded from Git
+
+Copyright:
+ Copyright (C) 2007 Hubert Figuiere <hub@figuiere.net>
+ Copyright (c) 1999 - 2007, Adobe Systems Incorporated
+
+License:
+
+Copyright (c) 1999 - 2007, Adobe Systems Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+* Neither the name of Adobe Systems Incorporated, nor the names of its contributors may be used to endorse or promote products derived from this software wit
+hout specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/debian/libexempi-dev.install b/debian/libexempi-dev.install
new file mode 100644
index 0000000..c7dd91c
--- /dev/null
+++ b/debian/libexempi-dev.install
@@ -0,0 +1,3 @@
+usr/include
+usr/lib/pkgconfig
+usr/lib/libexempi.{so,la,a} \ No newline at end of file
diff --git a/debian/libexempi2.install b/debian/libexempi2.install
new file mode 100644
index 0000000..5f36ae7
--- /dev/null
+++ b/debian/libexempi2.install
@@ -0,0 +1 @@
+usr/lib/libexempi.so.2*
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..726c479
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+
+DEB_DH_INSTALL_SOURCEDIR=debian/tmp
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+
diff --git a/exempi/Makefile.am b/exempi/Makefile.am
new file mode 100644
index 0000000..4a65f91
--- /dev/null
+++ b/exempi/Makefile.am
@@ -0,0 +1,79 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+SUBDIRS = tests
+DIST_SUBDIRS = tests doc
+
+exempidir = $(includedir)/@EXEMPI_INCLUDE_BASE@/exempi
+exempi_HEADERS = xmp.h xmpconsts.h xmperrors.h xmp++.hpp
+
+bin_PROGRAMS = exempi
+
+exempi_SOURCES = main.cpp
+exempi_CPPFLAGS = -I$(srcdir)/..
+exempi_LDADD = libexempi.la
+
+AM_CPPFLAGS = -I$(top_srcdir)/public/include -I$(top_srcdir)/XMPCore/source \
+ -I$(top_srcdir)/build/ -I$(top_srcdir) \
+ -I$(top_srcdir)/source/common/ \
+ -Wall -D@EXEMPI_PLATFORM_DEF@=1
+
+lib_LTLIBRARIES = libexempi.la
+
+pkgconfig_DATA = exempi-@EXEMPI_MAJOR_VERSION@.pc
+
+libexempi_la_SOURCES = exempi.cpp
+
+libexempi_la_LIBADD = $(top_builddir)/source/libxmpcommon.la \
+ $(top_builddir)/XMPCore/source/libXMPCore.la \
+ $(top_builddir)/XMPFiles/source/libXMPFiles.la \
+ $(top_builddir)/third-party/zuid/interfaces/libmd5.la \
+ -lexpat -lz -ldl
+
+if UNIX_ENV
+libexempi_la_LIBADD += -lrt
+endif
+
+libexempi_la_LDFLAGS = -version-info @EXEMPI_VERSION_INFO@
+
+if HAVE_SYMBOLS_FILE
+libexempi_la_LDFLAGS += -Wl,--retain-symbols-file=$(srcdir)/libexempi.sym
+endif
+
+dist_man1_MANS = exempi.1
+
+EXTRA_DIST = libexempi.sym
+
diff --git a/exempi/doc/Doxyfile.in b/exempi/doc/Doxyfile.in
new file mode 100644
index 0000000..21033dc
--- /dev/null
+++ b/exempi/doc/Doxyfile.in
@@ -0,0 +1,1869 @@
+# Doxyfile 1.8.3.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = @PACKAGE@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = .
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ..
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page (index.html).
+# This can be useful if you have a project on for instance GitHub and want reuse
+# the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search engine
+# library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
+# of to a relative location where the documentation can be found.
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS = *.h
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/exempi/doc/Makefile.am b/exempi/doc/Makefile.am
new file mode 100644
index 0000000..012eac6
--- /dev/null
+++ b/exempi/doc/Makefile.am
@@ -0,0 +1,38 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+EXTRA_DIST = Doxyfile.in
+
diff --git a/exempi/exempi-2.0.pc.in b/exempi/exempi-2.0.pc.in
new file mode 100644
index 0000000..e8d6745
--- /dev/null
+++ b/exempi/exempi-2.0.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+VERSION=@VERSION@
+
+Name: exempi
+Description: Library for easy parsing of XMP metadata.
+Requires:
+Version: @VERSION@
+Libs: -L${libdir} -lexempi
+Cflags: -I${includedir}/@EXEMPI_INCLUDE_BASE@ -I${includedir}
diff --git a/exempi/exempi.1 b/exempi/exempi.1
new file mode 100644
index 0000000..01bb741
--- /dev/null
+++ b/exempi/exempi.1
@@ -0,0 +1,40 @@
+.TH exempi 1 "February 10 2013"
+
+.SH NAME
+
+exempi - command line tool to manipulate XMP metadata
+
+.SH SYNTAX
+
+exempi { -h | [ -R ] [ -x ] [ { -w | -o <file> } ] [ { -g <prop_name> | -s <prop_name> -v <value> } ] } <files>
+
+.SH OPTIONS
+
+.IP "-h: show this help"
+.IP "-R: don't reconcile"
+.IP "-x: dump XML"
+.IP "-X: file(s) is XMP"
+.IP "-w: write in place. Only for -s. Not compatible with -o."
+.IP "-o <file>: file to write the output to."
+.IP "-n <ns> <prefix>: set the prefix for a namespace."
+.IP "-g <prop_name>: retrieve the value with prop_name."
+.IP "-s <prop_name> -v <value>: retrieve or get the value."
+.IP "<files> the files to read from."
+
+.SH SECURITY
+
+The source code hasn't been audited for security. The command line tool doesn't have a strong input sanity checking easier.
+.P
+Be careful not to run the tool as super-user. Be careful if you decide to use it in an online (web) application.
+.P
+Patches and suggestions welcome.
+
+.SH AUHTORS
+
+Exempi is written by Hubert Figuiere
+.P
+It contains the XMP SDK written by Adobe Systems Inc.
+
+.SH LICENSE
+
+Exempi is licensed under the BSD license.
diff --git a/exempi/exempi.cpp b/exempi/exempi.cpp
new file mode 100644
index 0000000..5392047
--- /dev/null
+++ b/exempi/exempi.cpp
@@ -0,0 +1,1170 @@
+/*
+ * exempi - exempi.cpp
+ *
+ * Copyright (C) 2007-2016 Hubert Figuière
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @brief this file implement the glue for XMP API
+ */
+
+#include "xmpconsts.h"
+#include "xmp.h"
+#include "xmperrors.h"
+
+#include <string>
+#include <iostream>
+#include <memory>
+
+#define XMP_INCLUDE_XMPFILES 1
+#define TXMP_STRING_TYPE std::string
+#include "XMP.hpp"
+#include "XMP.incl_cpp"
+#include "XMPUtils.hpp"
+
+#if HAVE_NATIVE_TLS
+
+static TLS int g_error = 0;
+
+static void set_error(int err)
+{
+ g_error = err;
+}
+
+#else
+
+#include <pthread.h>
+
+/* Portable thread local storage using pthreads */
+static pthread_key_t key = NULL;
+static pthread_once_t key_once = PTHREAD_ONCE_INIT;
+
+/* Destructor called when a thread exits - ensure to delete allocated int
+ * pointer */
+static void destroy_tls_key(void *ptr)
+{
+ int *err_ptr = static_cast<int *>(ptr);
+ delete err_ptr;
+}
+
+/* Create a key for use with pthreads local storage */
+static void create_tls_key()
+{
+ (void)pthread_key_create(&key, destroy_tls_key);
+}
+
+/* Obtain the latest xmp error for this specific thread - defaults to 0 */
+static int get_error_for_thread()
+{
+ int *err_ptr;
+
+ pthread_once(&key_once, create_tls_key);
+ err_ptr = (int *)pthread_getspecific(key);
+
+ if (err_ptr == NULL) {
+ return 0;
+ }
+
+ return *err_ptr;
+}
+
+/* set the current xmp error for this specific thread */
+static void set_error(int err)
+{
+ int *err_ptr;
+
+ // Ensure that create_thread_local_storage_key is only called
+ // once, by the first thread, to create the key.
+ pthread_once(&key_once, create_tls_key);
+
+ // Retrieve pointer to int for this thread.
+ err_ptr = (int *)pthread_getspecific(key);
+
+ // Allocate it, if it does not exists.
+ if (err_ptr == NULL) {
+ err_ptr = new int;
+ pthread_setspecific(key, err_ptr);
+ }
+
+ // Save the error for this thread.
+ *err_ptr = err;
+}
+
+#endif
+
+static void set_error(const XMP_Error &e)
+{
+ set_error(-e.GetID());
+ std::cerr << e.GetErrMsg() << std::endl;
+}
+
+#define RESET_ERROR set_error(0)
+
+// Hack: assign between XMP_DateTime and XmpDateTime
+#define ASSIGN(dst, src) \
+ (dst).year = (src).year; \
+ (dst).month = (src).month; \
+ (dst).day = (src).day; \
+ (dst).hour = (src).hour; \
+ (dst).minute = (src).minute; \
+ (dst).second = (src).second; \
+ (dst).tzSign = (src).tzSign; \
+ (dst).tzHour = (src).tzHour; \
+ (dst).tzMinute = (src).tzMinute; \
+ (dst).nanoSecond = (src).nanoSecond;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char NS_XMP_META[] = "adobe:ns:meta/";
+const char NS_RDF[] = kXMP_NS_RDF;
+const char NS_EXIF[] = kXMP_NS_EXIF;
+const char NS_TIFF[] = kXMP_NS_TIFF;
+const char NS_XAP[] = kXMP_NS_XMP;
+const char NS_XAP_RIGHTS[] = kXMP_NS_XMP_Rights;
+const char NS_DC[] = kXMP_NS_DC;
+const char NS_EXIF_AUX[] = kXMP_NS_EXIF_Aux;
+const char NS_CRS[] = kXMP_NS_CameraRaw;
+const char NS_LIGHTROOM[] = "http://ns.adobe.com/lightroom/1.0/";
+const char NS_CAMERA_RAW_SETTINGS[] = kXMP_NS_CameraRaw;
+const char NS_CAMERA_RAW_SAVED_SETTINGS[] =
+ "http://ns.adobe.com/camera-raw-saved-settings/1.0/";
+const char NS_PHOTOSHOP[] = kXMP_NS_Photoshop;
+const char NS_IPTC4XMP[] = kXMP_NS_IPTCCore;
+const char NS_TPG[] = kXMP_NS_XMP_PagedFile;
+const char NS_DIMENSIONS_TYPE[] = kXMP_NS_XMP_Dimensions;
+const char NS_CC[] = "http://creativecommons.org/ns#";
+const char NS_PDF[] = kXMP_NS_PDF;
+
+#define STRING(x) reinterpret_cast<std::string *>(x)
+
+#define CHECK_PTR(p, r) \
+ if (p == NULL) { \
+ set_error(XMPErr_BadObject); \
+ return r; \
+ }
+
+int xmp_get_error()
+{
+#if HAVE_NATIVE_TLS
+ return g_error;
+#else
+ return get_error_for_thread();
+#endif
+}
+
+bool xmp_init()
+{
+ RESET_ERROR;
+ try {
+ // no need to initialize anything else.
+ // XMP SDK 5.1.2 needs this because it has been lobotomized of local
+ // text
+ // conversion
+ // the one that was done in Exempi with libiconv.
+ return SXMPFiles::Initialize(kXMPFiles_IgnoreLocalText);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return false;
+}
+
+void xmp_terminate()
+{
+ RESET_ERROR;
+ SXMPFiles::Terminate();
+}
+
+bool xmp_register_namespace(const char *namespaceURI,
+ const char *suggestedPrefix,
+ XmpStringPtr registeredPrefix)
+{
+ RESET_ERROR;
+ try {
+ return SXMPMeta::RegisterNamespace(namespaceURI, suggestedPrefix,
+ STRING(registeredPrefix));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return false;
+}
+
+bool xmp_namespace_prefix(const char *ns, XmpStringPtr prefix)
+{
+ CHECK_PTR(ns, false);
+ RESET_ERROR;
+ try {
+ return SXMPMeta::GetNamespacePrefix(ns, STRING(prefix));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return false;
+}
+
+bool xmp_prefix_namespace_uri(const char *prefix, XmpStringPtr ns)
+{
+ CHECK_PTR(prefix, false);
+ RESET_ERROR;
+ try {
+ return SXMPMeta::GetNamespaceURI(prefix, STRING(ns));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return false;
+}
+
+XmpFilePtr xmp_files_new()
+{
+ RESET_ERROR;
+
+ try {
+ auto txf = std::unique_ptr<SXMPFiles>(new SXMPFiles());
+
+ return reinterpret_cast<XmpFilePtr>(txf.release());
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return NULL;
+}
+
+XmpFilePtr xmp_files_open_new(const char *path, XmpOpenFileOptions options)
+{
+ CHECK_PTR(path, NULL);
+ RESET_ERROR;
+
+ try {
+ auto txf = std::unique_ptr<SXMPFiles>(new SXMPFiles);
+
+ txf->OpenFile(path, XMP_FT_UNKNOWN, options);
+
+ return reinterpret_cast<XmpFilePtr>(txf.release());
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+
+ return NULL;
+}
+
+bool xmp_files_open(XmpFilePtr xf, const char *path, XmpOpenFileOptions options)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+ try {
+ return txf->OpenFile(path, XMP_FT_UNKNOWN, options);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return false;
+}
+
+bool xmp_files_close(XmpFilePtr xf, XmpCloseFileOptions options)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ try {
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+ txf->CloseFile(options);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+XmpPtr xmp_files_get_new_xmp(XmpFilePtr xf)
+{
+ CHECK_PTR(xf, NULL);
+ RESET_ERROR;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+
+ bool result = false;
+ try {
+ auto xmp = std::unique_ptr<SXMPMeta>(new SXMPMeta);
+ result = txf->GetXMP(xmp.get());
+ if (result) {
+ return reinterpret_cast<XmpPtr>(xmp.release());
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return NULL;
+}
+
+bool xmp_files_get_xmp(XmpFilePtr xf, XmpPtr xmp)
+{
+ CHECK_PTR(xf, false);
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+ bool result = false;
+ try {
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+
+ result = txf->GetXMP(reinterpret_cast<SXMPMeta *>(xmp));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return result;
+}
+
+bool xmp_files_get_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet,
+ XmpPacketInfo* packet_info)
+{
+ CHECK_PTR(xf, false);
+ CHECK_PTR(xmp_packet, false);
+ RESET_ERROR;
+ bool result = false;
+ try {
+ SXMPFiles *txf = reinterpret_cast<SXMPFiles*>(xf);
+
+ XMP_PacketInfo xmp_packet_info;
+ result = txf->GetXMP(NULL,
+ reinterpret_cast<std::string*>(xmp_packet),
+ &xmp_packet_info);
+ if (packet_info) {
+ packet_info->offset = xmp_packet_info.offset;
+ packet_info->length = xmp_packet_info.length;
+ packet_info->padSize = xmp_packet_info.padSize;
+ packet_info->charForm = xmp_packet_info.charForm;
+ packet_info->writeable = xmp_packet_info.writeable;
+ packet_info->hasWrapper = xmp_packet_info.hasWrapper;
+ packet_info->pad = xmp_packet_info.pad;
+ }
+ }
+ catch(const XMP_Error & e) {
+ set_error(e);
+ }
+ return result;
+}
+
+
+bool xmp_files_can_put_xmp(XmpFilePtr xf, XmpPtr xmp)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+ bool result = false;
+
+ try {
+ result = txf->CanPutXMP(*reinterpret_cast<const SXMPMeta *>(xmp));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return result;
+}
+
+bool xmp_files_can_put_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ SXMPFiles *txf = reinterpret_cast<SXMPFiles*>(xf);
+ bool result = false;
+
+ try {
+ result = txf->CanPutXMP(*reinterpret_cast<const std::string*>(xmp_packet));
+ }
+ catch(const XMP_Error & e) {
+ set_error(e);
+ return false;
+ }
+ return result;
+}
+
+bool xmp_files_can_put_xmp_cstr(XmpFilePtr xf, const char* xmp_packet, size_t len)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ SXMPFiles *txf = reinterpret_cast<SXMPFiles*>(xf);
+ bool result = false;
+
+ try {
+ result = txf->CanPutXMP(xmp_packet, len);
+ }
+ catch(const XMP_Error & e) {
+ set_error(e);
+ return false;
+ }
+ return result;
+}
+
+bool xmp_files_put_xmp(XmpFilePtr xf, XmpPtr xmp)
+{
+ CHECK_PTR(xf, false);
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+
+ try {
+ txf->PutXMP(*reinterpret_cast<const SXMPMeta *>(xmp));
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_files_put_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet)
+{
+ CHECK_PTR(xf, false);
+ CHECK_PTR(xmp_packet, false);
+ RESET_ERROR;
+ SXMPFiles *txf = reinterpret_cast<SXMPFiles*>(xf);
+
+ try {
+ txf->PutXMP(*reinterpret_cast<const std::string*>(xmp_packet));
+ }
+ catch(const XMP_Error & e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_files_put_xmp_cstr(XmpFilePtr xf, const char* xmp_packet, size_t len)
+{
+ CHECK_PTR(xf, false);
+ CHECK_PTR(xmp_packet, false);
+ RESET_ERROR;
+ SXMPFiles *txf = reinterpret_cast<SXMPFiles*>(xf);
+
+ try {
+ txf->PutXMP(xmp_packet, len);
+ }
+ catch(const XMP_Error & e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_files_get_file_info(XmpFilePtr xf, XmpStringPtr filePath,
+ XmpOpenFileOptions *options,
+ XmpFileType *file_format,
+ XmpFileFormatOptions *handler_flags)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+
+ bool result = false;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+ try {
+ result = txf->GetFileInfo(STRING(filePath), (XMP_OptionBits *)options,
+ (XMP_FileFormat *)file_format,
+ (XMP_OptionBits *)handler_flags);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+
+ return result;
+}
+
+bool xmp_files_free(XmpFilePtr xf)
+{
+ CHECK_PTR(xf, false);
+ RESET_ERROR;
+ auto txf = reinterpret_cast<SXMPFiles *>(xf);
+ try {
+ delete txf;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_files_get_format_info(XmpFileType format,
+ XmpFileFormatOptions *options)
+{
+ RESET_ERROR;
+
+ bool result = false;
+ try {
+ result = SXMPFiles::GetFormatInfo(format, (XMP_OptionBits *)options);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return result;
+}
+
+XmpFileType xmp_files_check_file_format(const char *filePath)
+{
+ CHECK_PTR(filePath, XMP_FT_UNKNOWN);
+ RESET_ERROR;
+
+ XmpFileType file_type = XMP_FT_UNKNOWN;
+ try {
+ file_type = (XmpFileType)SXMPFiles::CheckFileFormat(filePath);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return XMP_FT_UNKNOWN;
+ }
+ return file_type;
+}
+
+XmpPtr xmp_new_empty()
+{
+ RESET_ERROR;
+ SXMPMeta *txmp = new SXMPMeta;
+ return (XmpPtr)txmp;
+}
+
+XmpPtr xmp_new(const char *buffer, size_t len)
+{
+ CHECK_PTR(buffer, NULL);
+ RESET_ERROR;
+
+ try {
+ auto txmp = std::unique_ptr<SXMPMeta>(new SXMPMeta(buffer, len));
+ return reinterpret_cast<XmpPtr>(txmp.release());
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return NULL;
+}
+
+XmpPtr xmp_copy(XmpPtr xmp)
+{
+ CHECK_PTR(xmp, NULL);
+ RESET_ERROR;
+
+ try {
+ auto txmp = std::unique_ptr<SXMPMeta>(new SXMPMeta(*(SXMPMeta *)xmp));
+ return reinterpret_cast<XmpPtr>(txmp.release());
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return NULL;
+}
+
+bool xmp_parse(XmpPtr xmp, const char *buffer, size_t len)
+{
+ CHECK_PTR(xmp, false);
+ CHECK_PTR(buffer, false);
+
+ SXMPMeta *txmp = (SXMPMeta *)xmp;
+ try {
+ txmp->ParseFromBuffer(buffer, len, kXMP_RequireXMPMeta);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_serialize(XmpPtr xmp, XmpStringPtr buffer, uint32_t options,
+ uint32_t padding)
+{
+ RESET_ERROR;
+ return xmp_serialize_and_format(xmp, buffer, options, padding, "\n", " ",
+ 0);
+}
+
+bool xmp_serialize_and_format(XmpPtr xmp, XmpStringPtr buffer, uint32_t options,
+ uint32_t padding, const char *newline,
+ const char *tab, int32_t indent)
+{
+ CHECK_PTR(xmp, false);
+ CHECK_PTR(buffer, false);
+ RESET_ERROR;
+
+ SXMPMeta *txmp = (SXMPMeta *)xmp;
+ try {
+ txmp->SerializeToBuffer(STRING(buffer), options, padding, newline, tab,
+ indent);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ return false;
+ }
+ return true;
+}
+
+bool xmp_free(XmpPtr xmp)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+ SXMPMeta *txmp = (SXMPMeta *)xmp;
+ delete txmp;
+ return true;
+}
+
+bool xmp_get_property(XmpPtr xmp, const char *schema, const char *name,
+ XmpStringPtr property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetProperty(schema, name, STRING(property), &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_property_date(XmpPtr xmp, const char *schema, const char *name,
+ XmpDateTime *property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ XMP_DateTime dt;
+ // memset((void*)&dt, 1, sizeof(XMP_DateTime));
+ ret = txmp->GetProperty_Date(schema, name, &dt, &optionBits);
+ ASSIGN((*property), dt);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_property_float(XmpPtr xmp, const char *schema, const char *name,
+ double *property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetProperty_Float(schema, name, property, &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_property_bool(XmpPtr xmp, const char *schema, const char *name,
+ bool *property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetProperty_Bool(schema, name, property, &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_property_int32(XmpPtr xmp, const char *schema, const char *name,
+ int32_t *property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ // the long converstion is needed until XMPCore is fixed it use proper
+ // types.
+ ret = txmp->GetProperty_Int(schema, name, property, &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_property_int64(XmpPtr xmp, const char *schema, const char *name,
+ int64_t *property, uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetProperty_Int64(schema, name, property, &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_get_array_item(XmpPtr xmp, const char *schema, const char *name,
+ int32_t index, XmpStringPtr property,
+ uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetArrayItem(schema, name, index, STRING(property),
+ &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ return ret;
+}
+
+bool xmp_set_property(XmpPtr xmp, const char *schema, const char *name,
+ const char *value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ // see bug #16030
+ // when it is a struct or an array, get prop return an empty string
+ // but it fail if passed an empty string
+ if ((optionBits & (XMP_PROP_VALUE_IS_STRUCT | XMP_PROP_VALUE_IS_ARRAY)) &&
+ (*value == 0)) {
+ value = NULL;
+ }
+ try {
+ txmp->SetProperty(schema, name, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_property_date(XmpPtr xmp, const char *schema, const char *name,
+ const XmpDateTime *value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ XMP_DateTime dt;
+ ASSIGN(dt, (*value));
+ txmp->SetProperty_Date(schema, name, dt, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_property_float(XmpPtr xmp, const char *schema, const char *name,
+ double value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetProperty_Float(schema, name, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_property_bool(XmpPtr xmp, const char *schema, const char *name,
+ bool value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetProperty_Bool(schema, name, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_property_int32(XmpPtr xmp, const char *schema, const char *name,
+ int32_t value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetProperty_Int(schema, name, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_property_int64(XmpPtr xmp, const char *schema, const char *name,
+ int64_t value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetProperty_Int64(schema, name, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_set_array_item(XmpPtr xmp, const char *schema, const char *name,
+ int32_t index, const char *value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetArrayItem(schema, name, index, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_append_array_item(XmpPtr xmp, const char *schema, const char *name,
+ uint32_t arrayOptions, const char *value,
+ uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->AppendArrayItem(schema, name, arrayOptions, value, optionBits);
+ ret = true;
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+ catch (...) {
+ }
+ return ret;
+}
+
+bool xmp_delete_property(XmpPtr xmp, const char *schema, const char *name)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = true;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->DeleteProperty(schema, name);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ ret = false;
+ }
+ catch (...) {
+ ret = false;
+ }
+ return ret;
+}
+
+bool xmp_has_property(XmpPtr xmp, const char *schema, const char *name)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = true;
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ try {
+ ret = txmp->DoesPropertyExist(schema, name);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ ret = false;
+ }
+ catch (...) {
+ ret = false;
+ }
+ return ret;
+}
+
+bool xmp_get_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang, const char *specificLang,
+ XmpStringPtr actualLang, XmpStringPtr itemValue,
+ uint32_t *propsBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = false;
+ try {
+ auto txmp = reinterpret_cast<const SXMPMeta *>(xmp);
+ XMP_OptionBits optionBits;
+ ret = txmp->GetLocalizedText(schema, name, genericLang, specificLang,
+ STRING(actualLang), STRING(itemValue),
+ &optionBits);
+ if (propsBits) {
+ *propsBits = optionBits;
+ }
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ ret = false;
+ }
+ return ret;
+}
+
+bool xmp_set_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang, const char *specificLang,
+ const char *value, uint32_t optionBits)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = true;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->SetLocalizedText(schema, name, genericLang, specificLang, value,
+ optionBits);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ ret = false;
+ }
+ catch (...) {
+ ret = false;
+ }
+ return ret;
+}
+
+bool xmp_delete_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang,
+ const char *specificLang)
+{
+ CHECK_PTR(xmp, false);
+ RESET_ERROR;
+
+ bool ret = true;
+ auto txmp = reinterpret_cast<SXMPMeta *>(xmp);
+ try {
+ txmp->DeleteLocalizedText(schema, name, genericLang, specificLang);
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ ret = false;
+ }
+ catch (...) {
+ ret = false;
+ }
+ return ret;
+}
+
+XmpStringPtr xmp_string_new()
+{
+ return (XmpStringPtr) new std::string;
+}
+
+void xmp_string_free(XmpStringPtr s)
+{
+ auto str = reinterpret_cast<std::string *>(s);
+ delete str;
+}
+
+const char *xmp_string_cstr(XmpStringPtr s)
+{
+ CHECK_PTR(s, NULL);
+ return reinterpret_cast<const std::string *>(s)->c_str();
+}
+
+size_t xmp_string_len(XmpStringPtr s)
+{
+ CHECK_PTR(s, 0);
+ return reinterpret_cast<const std::string *>(s)->size();
+}
+
+XmpIteratorPtr xmp_iterator_new(XmpPtr xmp, const char *schema,
+ const char *propName, XmpIterOptions options)
+{
+ CHECK_PTR(xmp, NULL);
+ RESET_ERROR;
+
+ try {
+ auto xiter = std::unique_ptr<SXMPIterator>(
+ new SXMPIterator(*(SXMPMeta *)xmp, schema, propName, options));
+
+ return reinterpret_cast<XmpIteratorPtr>(xiter.release());
+ }
+ catch (const XMP_Error &e) {
+ set_error(e);
+ }
+
+ return NULL;
+}
+
+bool xmp_iterator_free(XmpIteratorPtr iter)
+{
+ CHECK_PTR(iter, false);
+ RESET_ERROR;
+ auto titer = reinterpret_cast<SXMPIterator *>(iter);
+ delete titer;
+ return true;
+}
+
+bool xmp_iterator_next(XmpIteratorPtr iter, XmpStringPtr schema,
+ XmpStringPtr propName, XmpStringPtr propValue,
+ uint32_t *options)
+{
+ CHECK_PTR(iter, false);
+ RESET_ERROR;
+ auto titer = reinterpret_cast<SXMPIterator *>(iter);
+ return titer->Next(reinterpret_cast<std::string *>(schema),
+ reinterpret_cast<std::string *>(propName),
+ reinterpret_cast<std::string *>(propValue), options);
+}
+
+bool xmp_iterator_skip(XmpIteratorPtr iter, XmpIterSkipOptions options)
+{
+ CHECK_PTR(iter, false);
+ RESET_ERROR;
+ auto titer = reinterpret_cast<SXMPIterator *>(iter);
+ titer->Skip(options);
+ return true;
+}
+
+int xmp_datetime_compare(XmpDateTime *left, XmpDateTime *right)
+{
+ if (!left && !right) {
+ return 0;
+ }
+ if (!left) {
+ return -1;
+ }
+ if (!right) {
+ return 1;
+ }
+ XMP_DateTime _left;
+ ASSIGN(_left, *left);
+ XMP_DateTime _right;
+ ASSIGN(_right, *right);
+ return XMPUtils::CompareDateTime(_left, _right);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/exempi/libexempi.sym b/exempi/libexempi.sym
new file mode 100644
index 0000000..d75d5c0
--- /dev/null
+++ b/exempi/libexempi.sym
@@ -0,0 +1,67 @@
+xmp_append_array_item
+xmp_copy
+xmp_delete_localized_text
+xmp_delete_property
+xmp_files_can_put_xmp
+xmp_files_close
+xmp_files_free
+xmp_files_get_new_xmp
+xmp_files_get_xmp
+xmp_files_new
+xmp_files_open
+xmp_files_open_new
+xmp_files_put_xmp
+xmp_free
+xmp_get_array_item
+xmp_get_error
+xmp_get_localized_text
+xmp_get_property
+xmp_get_property_bool
+xmp_get_property_date
+xmp_get_property_float
+xmp_get_property_int32
+xmp_get_property_int64
+xmp_has_property
+xmp_init
+xmp_iterator_free
+xmp_iterator_new
+xmp_iterator_next
+xmp_iterator_skip
+xmp_namespace_prefix
+xmp_new
+xmp_new_empty
+xmp_parse
+xmp_prefix_namespace_uri
+xmp_register_namespace
+xmp_serialize
+xmp_serialize_and_format
+xmp_set_array_item
+xmp_set_localized_text
+xmp_set_property
+xmp_set_property_bool
+xmp_set_property_date
+xmp_set_property_float
+xmp_set_property_int32
+xmp_set_property_int64
+xmp_string_cstr
+xmp_string_free
+xmp_string_new
+xmp_terminate
+NS_CAMERA_RAW_SAVED_SETTINGS
+NS_CAMERA_RAW_SETTINGS
+NS_CC
+NS_CRS
+NS_DC
+NS_DIMENSIONS_TYPE
+NS_EXIF
+NS_EXIF_AUX
+NS_IPTC4XMP
+NS_LIGHTROOM
+NS_PDF
+NS_PHOTOSHOP
+NS_RDF
+NS_TIFF
+NS_TPG
+NS_XAP
+NS_XAP_RIGHTS
+NS_XMP_META
diff --git a/exempi/main.cpp b/exempi/main.cpp
new file mode 100644
index 0000000..4cca1ca
--- /dev/null
+++ b/exempi/main.cpp
@@ -0,0 +1,357 @@
+/* -*- tab-width:4; c-basic-offset:4; indent-tabs-mode:nil;
+ * c-file-style:"stroustrup" -*- */
+/*
+ * exempi - exempi.cpp
+ *
+ * Copyright (C) 2011-2013 Hubert Figuiere
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+#include <vector>
+
+#include <exempi/xmp.h>
+#include <exempi/xmp++.hpp>
+
+enum { ACTION_NONE = 0, ACTION_SET, ACTION_GET };
+
+static void process_file(const char *filename, bool no_reconcile,
+ bool is_an_xmp, bool dump_xml, bool write_in_place,
+ int action, const std::string &value_name,
+ const std::string &prop_value,
+ const std::string &output);
+
+/** fatal error in argument. Display and quit. */
+static void fatal_error(const char *error)
+{
+ fprintf(stderr, "ERROR: %s\n", error);
+ exit(128);
+}
+
+/** Print the usage, and quit. Exit code is 255.
+ */
+static void usage()
+{
+ fprintf(stderr, "Exempi version %s\n", VERSION);
+ fprintf(stderr, "exempi { -h | [ -R ] [ -x ] [ { -w | -o <file> } ] [ { -g "
+ "<prop_name> | -s <prop_name> -v <value> } ] } <files>\n");
+ fprintf(stderr, "\t-h: show this help\n");
+ fprintf(stderr, "\t-R: don't reconcile\n");
+ fprintf(stderr, "\t-x: dump XML packet.\n");
+ fprintf(stderr, "\t-X: file(s) is XMP\n");
+ fprintf(stderr,
+ "\t-w: write in place. Only for -s. Not compatible with -o.\n");
+ fprintf(stderr, "\t-o <file>: file to write the output to.\n");
+ fprintf(stderr, "\t-n <uri> <prefix>: create a new namespace.\n");
+ fprintf(stderr, "\t-g <prop_name>: retrieve the value with prop_name.\n");
+ fprintf(stderr,
+ "\t-s <prop_name> -v <value>: retrieve or get the value.\n");
+ fprintf(stderr, "\t<files> the files to read from.\n");
+
+ exit(255);
+}
+
+int main(int argc, char **argv)
+{
+ int ch;
+
+ int action = ACTION_NONE;
+ bool dont_reconcile = false;
+ bool write_in_place = false;
+ bool dump_xml = false;
+ bool is_an_xmp = false;
+ std::string output_file;
+ std::string value_name;
+ std::string prop_value;
+ std::vector<std::pair<std::string, std::string>> namespaces;
+
+ while ((ch = getopt(argc, argv, "hRo:wxXn:g:s:v:")) != -1) {
+ switch (ch) {
+
+ case 'R':
+ dont_reconcile = true;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 'w':
+ write_in_place = true;
+ break;
+ case 'x':
+ dump_xml = true;
+ break;
+ case 'X':
+ is_an_xmp = true;
+ break;
+ case 'g':
+ if (!value_name.empty()) {
+ usage();
+ }
+ action = ACTION_GET;
+ value_name = optarg;
+ break;
+ case 'n': {
+ std::string ns = optarg;
+ std::string prefix = argv[optind];
+ if (prefix[0] && prefix[0] != '-') {
+ namespaces.push_back(make_pair(ns, prefix));
+ optind++;
+ }
+ break;
+ }
+ case 's':
+ if (!value_name.empty()) {
+ usage();
+ }
+ action = ACTION_SET;
+ value_name = optarg;
+ break;
+ case 'v':
+ if (action != ACTION_SET || value_name.empty()) {
+ fatal_error("-v needs to come after -s");
+ }
+ prop_value = optarg;
+ break;
+ case 'h':
+ case '?':
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (optind == 1 || argc == 0) {
+ fatal_error("Missing input.");
+ return 1;
+ }
+
+ if (write_in_place && (!output_file.empty() || action != ACTION_SET)) {
+ fatal_error(
+ "Need to write in place and output file are mutually exclusive.");
+ return 1;
+ }
+
+ if (action == ACTION_SET && (!write_in_place && argc > 1)) {
+ fatal_error("Need to write in place for more than one file.");
+ return 1;
+ }
+
+ xmp_init();
+ if (!namespaces.empty()) {
+ for (std::vector<std::pair<std::string, std::string>>::const_iterator
+ iter = namespaces.begin();
+ iter != namespaces.end(); ++iter) {
+ xmp_register_namespace(iter->first.c_str(), iter->second.c_str(),
+ NULL);
+ }
+ }
+ while (argc) {
+
+ process_file(*argv, dont_reconcile, is_an_xmp, write_in_place, dump_xml,
+ action, value_name, prop_value, output_file);
+ argc--;
+ argv++;
+ }
+
+ xmp_terminate();
+ return 0;
+}
+
+static XmpPtr get_xmp_from_sidecar(const char *filename, bool is_an_xmp)
+{
+ struct stat s;
+
+ if (stat(filename, &s) == -1) {
+ perror("exempi:");
+ return NULL;
+ }
+
+ off_t size = s.st_size;
+ FILE *file = fopen(filename, "r");
+ if (!file) {
+ perror("exempi:");
+ return NULL;
+ }
+
+ char *buffer = (char *)malloc(size);
+ size_t len = fread(buffer, 1, size, file);
+
+ XmpPtr xmp = xmp_new_empty();
+ if (!xmp_parse(xmp, buffer, len)) {
+ xmp_free(xmp);
+ xmp = NULL;
+ }
+ free(buffer);
+ fclose(file);
+ return xmp;
+}
+
+/** Helper to get the XMP for the file */
+static XmpPtr get_xmp_from_file(const char *filename, bool no_reconcile,
+ bool is_an_xmp)
+{
+ if (is_an_xmp) {
+ return get_xmp_from_sidecar(filename, is_an_xmp);
+ }
+
+ xmp::ScopedPtr<XmpFilePtr> f(xmp_files_open_new(
+ filename, (XmpOpenFileOptions)(XMP_OPEN_READ |
+ (no_reconcile ? XMP_OPEN_ONLYXMP : 0))));
+ if (f) {
+ XmpPtr xmp = xmp_files_get_new_xmp(f);
+ xmp_files_close(f, XMP_CLOSE_NOOPTION);
+ return xmp;
+ }
+ return NULL;
+}
+
+/** dump the XMP xml to the output IO */
+static void dump_xmp(const char *filename, bool no_reconcile, bool is_an_xmp,
+ FILE *outio)
+{
+ printf("dump_xmp for file %s\n", filename);
+ xmp::ScopedPtr<XmpPtr> xmp(
+ get_xmp_from_file(filename, no_reconcile, is_an_xmp));
+
+ xmp::ScopedPtr<XmpStringPtr> output(xmp_string_new());
+
+ xmp_serialize_and_format(xmp, output, XMP_SERIAL_OMITPACKETWRAPPER, 0, "\n",
+ " ", 0);
+
+ fprintf(outio, "%s", xmp_string_cstr(output));
+}
+
+/** get an xmp prop and dump it to the output IO */
+static void get_xmp_prop(const char *filename, const std::string &value_name,
+ bool no_reconcile, bool is_an_xmp, FILE *outio)
+{
+ xmp::ScopedPtr<XmpPtr> xmp(
+ get_xmp_from_file(filename, no_reconcile, is_an_xmp));
+
+ std::string prefix;
+ size_t idx = value_name.find(':');
+ if (idx != std::string::npos) {
+ prefix = std::string(value_name, 0, idx);
+ }
+
+ xmp::ScopedPtr<XmpStringPtr> property(xmp_string_new());
+ xmp::ScopedPtr<XmpStringPtr> ns(xmp_string_new());
+ xmp_prefix_namespace_uri(prefix.c_str(), ns);
+ xmp_get_property(xmp, xmp_string_cstr(ns), value_name.c_str(), property,
+ NULL);
+ fprintf(outio, "%s\n", xmp_string_cstr(property));
+}
+
+static void set_xmp_prop(const char *filename, const std::string &value_name,
+ const std::string &prop_value, bool no_reconcile,
+ bool is_an_xmp, bool write_in_place, FILE *outio)
+{
+ xmp::ScopedPtr<XmpPtr> xmp(
+ get_xmp_from_file(filename, no_reconcile, is_an_xmp));
+
+ std::string prefix;
+ size_t idx = value_name.find(':');
+ if (idx != std::string::npos) {
+ prefix = std::string(value_name, 0, idx);
+ }
+
+ xmp::ScopedPtr<XmpStringPtr> ns(xmp_string_new());
+ xmp_prefix_namespace_uri(prefix.c_str(), ns);
+ if (!xmp_set_property(xmp, xmp_string_cstr(ns),
+ value_name.c_str() + idx + 1, prop_value.c_str(),
+ 0)) {
+ fprintf(stderr, "set error = %d\n", xmp_get_error());
+ }
+
+ if (write_in_place) {
+ xmp::ScopedPtr<XmpFilePtr> f(xmp_files_open_new(
+ filename,
+ (XmpOpenFileOptions)(XMP_OPEN_FORUPDATE |
+ (no_reconcile ? XMP_OPEN_ONLYXMP : 0))));
+
+ if (!xmp_files_can_put_xmp(f, xmp)) {
+ fprintf(stderr, "can put xmp error = %d\n", xmp_get_error());
+ }
+ if (!xmp_files_put_xmp(f, xmp)) {
+ fprintf(stderr, "put xmp error = %d\n", xmp_get_error());
+ }
+ if (!xmp_files_close(f, XMP_CLOSE_SAFEUPDATE)) {
+ fprintf(stderr, "close error = %d\n", xmp_get_error());
+ }
+ }
+}
+
+/** process a file with all the options */
+static void process_file(const char *filename, bool no_reconcile,
+ bool is_an_xmp, bool write_in_place, bool dump_xml,
+ int action, const std::string &value_name,
+ const std::string &prop_value,
+ const std::string &output)
+{
+ printf("processing file %s\n", filename);
+
+ FILE *outio = stdout;
+
+ bool needclose = false;
+ if (!output.empty()) {
+ outio = fopen(output.c_str(), "a+");
+ needclose = true;
+ }
+
+ switch (action) {
+ case ACTION_NONE:
+ if (dump_xml) {
+ dump_xmp(filename, no_reconcile, is_an_xmp, outio);
+ }
+ break;
+ case ACTION_SET:
+ set_xmp_prop(filename, value_name, prop_value, no_reconcile, is_an_xmp,
+ write_in_place, outio);
+ break;
+ case ACTION_GET:
+ get_xmp_prop(filename, value_name, no_reconcile, is_an_xmp, outio);
+ break;
+ default:
+ break;
+ }
+
+ if (needclose) {
+ fclose(outio);
+ }
+}
diff --git a/exempi/tests/Makefile.am b/exempi/tests/Makefile.am
new file mode 100644
index 0000000..92c94e9
--- /dev/null
+++ b/exempi/tests/Makefile.am
@@ -0,0 +1,110 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2011 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+
+AUTOMAKE_OPTIONS = parallel-tests
+TEST_EXTENSIONS = .sh
+
+if WITH_UNIT_TEST
+check_PROGRAMS = testexempicore testserialise testwritenewprop \
+ testtiffleak testxmpfiles testxmpfileswrite \
+ test3 testinit testfdo18635 testfdo83313 testcpp testwebp
+TESTS = testcore.sh testinit testexempicore testserialise testwritenewprop \
+ testtiffleak testxmpfiles testxmpfileswrite \
+ test3 testfdo18635 testfdo83313 testcpp testwebp
+TESTS_ENVIRONMENT = TEST_DIR=$(srcdir) BOOST_TEST_CATCH_SYSTEM_ERRORS=no VALGRIND="$(VALGRIND)"
+LOG_COMPILER = $(VALGRIND)
+endif
+check_SCRIPTS = testcore.sh
+
+check_DATA = test1.xmp fdo18635.jpg fdo83313.jpg
+
+noinst_HEADERS = utils.h
+
+EXTRA_DIST = $(check_DATA) $(check_SCRIPTS)
+CLEANFILES = test.jpg
+
+AM_CXXFLAGS = @BOOST_CPPFLAGS@
+AM_CPPFLAGS = -I$(srcdir)/.. -I$(top_srcdir)/public/include -I$(top_srcdir)
+
+testinit_SOURCES = testinit.cpp utils.cpp
+testinit_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testinit_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testexempicore_SOURCES = test-exempi-core.cpp utils.cpp
+testexempicore_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testexempicore_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testserialise_SOURCES = test-serialise.cpp utils.cpp
+testserialise_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testserialise_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testwritenewprop_SOURCES = test-write-new-prop.cpp utils.cpp
+testwritenewprop_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testwritenewprop_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testtiffleak_SOURCES = test-tiff-leak.cpp utils.cpp
+testtiffleak_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testtiffleak_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testxmpfiles_SOURCES = test-xmpfiles.cpp utils.cpp
+testxmpfiles_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testxmpfiles_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testxmpfileswrite_SOURCES = test-xmpfiles-write.cpp utils.cpp
+testxmpfileswrite_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testxmpfileswrite_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+test3_SOURCES = test3.cpp utils.cpp
+test3_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+test3_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testfdo18635_SOURCES = test-bgo.cpp utils.cpp
+testfdo18635_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testfdo18635_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testfdo83313_SOURCES = test-fdo83313.cpp utils.cpp
+testfdo83313_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testfdo83313_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testcpp_SOURCES = testcpp.cpp utils.cpp
+testcpp_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testcpp_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
+
+testwebp_SOURCES = test-webp.cpp utils.cpp
+testwebp_LDADD = ../libexempi.la @BOOST_UNIT_TEST_FRAMEWORK_LIBS@
+testwebp_LDFLAGS = -static @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@
diff --git a/exempi/tests/fdo18635.jpg b/exempi/tests/fdo18635.jpg
new file mode 100644
index 0000000..0f8f38f
--- /dev/null
+++ b/exempi/tests/fdo18635.jpg
Binary files differ
diff --git a/exempi/tests/fdo83313.jpg b/exempi/tests/fdo83313.jpg
new file mode 100644
index 0000000..59c5c43
--- /dev/null
+++ b/exempi/tests/fdo83313.jpg
Binary files differ
diff --git a/exempi/tests/test-bgo.cpp b/exempi/tests/test-bgo.cpp
new file mode 100644
index 0000000..1919780
--- /dev/null
+++ b/exempi/tests/test-bgo.cpp
@@ -0,0 +1,74 @@
+/*
+ * exempi - test-bgo.cpp
+ *
+ * Copyright (C) 2007-2008 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+int test_main(int argc, char* argv[])
+{
+ prepare_test(argc, argv, "fdo18635.jpg");
+
+ BOOST_CHECK(xmp_init());
+
+ XmpFilePtr xf = xmp_files_open_new(g_testfile.c_str(), XMP_OPEN_READ);
+
+ BOOST_CHECK(xf != NULL);
+ if (xf == NULL) {
+ return 1;
+ }
+
+ XmpPtr xmp = xmp_files_get_new_xmp(xf);
+
+ BOOST_CHECK(xmp != NULL);
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_free(xf));
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-exempi-core.cpp b/exempi/tests/test-exempi-core.cpp
new file mode 100644
index 0000000..c71f1b2
--- /dev/null
+++ b/exempi/tests/test-exempi-core.cpp
@@ -0,0 +1,231 @@
+/*
+ * exempi - test-exempi-core.cpp
+ *
+ * Copyright (C) 2007-2013 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+using boost::unit_test::test_suite;
+
+// void test_exempi()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "test1.xmp");
+
+ size_t len;
+ char *buffer;
+
+ FILE *f = fopen(g_testfile.c_str(), "rb");
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ exit(128);
+ }
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buffer = (char *)malloc(len + 1);
+ size_t rlen = fread(buffer, 1, len, f);
+
+ BOOST_CHECK(rlen == len);
+ BOOST_CHECK(len != 0);
+
+ BOOST_CHECK(xmp_init());
+
+ XmpPtr xmp = xmp_new_empty();
+
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+
+ BOOST_CHECK(xmp != NULL);
+
+ XmpStringPtr the_prop = xmp_string_new();
+ BOOST_CHECK(xmp_string_len(the_prop) == 0);
+
+ BOOST_CHECK(xmp_has_property(xmp, NS_TIFF, "Make"));
+ BOOST_CHECK(!xmp_has_property(xmp, NS_TIFF, "Foo"));
+
+ BOOST_CHECK(xmp_get_property(xmp, NS_TIFF, "Make", the_prop, NULL));
+ BOOST_CHECK(strcmp("Canon", xmp_string_cstr(the_prop)) == 0);
+ BOOST_CHECK(xmp_string_len(the_prop) == 5);
+
+ BOOST_CHECK(xmp_set_property(xmp, NS_TIFF, "Make", "Leica", 0));
+ BOOST_CHECK(xmp_get_property(xmp, NS_TIFF, "Make", the_prop, NULL));
+ BOOST_CHECK(strcmp("Leica", xmp_string_cstr(the_prop)) == 0);
+ BOOST_CHECK(xmp_string_len(the_prop) == 5);
+
+ uint32_t bits;
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_DC, "rights[1]/?xml:lang", the_prop, &bits));
+ BOOST_CHECK(bits == 0x20);
+ BOOST_CHECK(XMP_IS_PROP_QUALIFIER(bits));
+
+ BOOST_CHECK(xmp_get_property(xmp, NS_DC, "rights[1]", the_prop, &bits));
+ BOOST_CHECK(bits == 0x50);
+ BOOST_CHECK(XMP_HAS_PROP_QUALIFIERS(bits));
+
+ XmpStringPtr the_lang = xmp_string_new();
+ BOOST_CHECK(xmp_get_localized_text(xmp, NS_DC, "rights", NULL, "x-default",
+ the_lang, the_prop, &bits));
+ BOOST_CHECK(strcmp("x-default", xmp_string_cstr(the_lang)) == 0);
+ BOOST_CHECK(strcmp("2006, Hubert Figuiere", xmp_string_cstr(the_prop)) == 0);
+
+ // This will modify the default property.
+ BOOST_CHECK(
+ xmp_set_localized_text(xmp, NS_DC, "rights", "en", "en-CA", "Foo Bar", 0));
+ // Ask for the en_US alternative.
+ BOOST_CHECK(xmp_get_localized_text(xmp, NS_DC, "rights", "en", "en-US",
+ the_lang, the_prop, &bits));
+ // And we only got the "en-CA" as the only "en"
+ BOOST_CHECK(strcmp("en-US", xmp_string_cstr(the_lang)) != 0);
+ BOOST_CHECK(strcmp("en-CA", xmp_string_cstr(the_lang)) == 0);
+ // Check its value
+ BOOST_CHECK(strcmp("Foo Bar", xmp_string_cstr(the_prop)) == 0);
+ // The default property is supposed to have been changed too.
+ BOOST_CHECK(xmp_get_localized_text(xmp, NS_DC, "rights", NULL, "x-default",
+ the_lang, the_prop, &bits));
+ BOOST_CHECK(strcmp("Foo Bar", xmp_string_cstr(the_prop)) == 0);
+
+ // This should also remove the property x-default. (SDK 5.2.2)
+ BOOST_CHECK(xmp_delete_localized_text(xmp, NS_DC, "rights", "en", "en-CA"));
+
+ BOOST_CHECK(!xmp_has_property(xmp, NS_DC, "rights[1]"));
+ BOOST_CHECK(!xmp_has_property(xmp, NS_DC, "rights[2]"));
+
+ xmp_string_free(the_lang);
+
+ BOOST_CHECK(xmp_set_array_item(xmp, NS_DC, "creator", 2, "foo", 0));
+ BOOST_CHECK(xmp_get_array_item(xmp, NS_DC, "creator", 2, the_prop, &bits));
+ BOOST_CHECK(XMP_IS_PROP_SIMPLE(bits));
+ BOOST_CHECK(strcmp("foo", xmp_string_cstr(the_prop)) == 0);
+ BOOST_CHECK(xmp_append_array_item(xmp, NS_DC, "creator", 0, "bar", 0));
+
+ BOOST_CHECK(xmp_get_array_item(xmp, NS_DC, "creator", 3, the_prop, &bits));
+ BOOST_CHECK(XMP_IS_PROP_SIMPLE(bits));
+ BOOST_CHECK(strcmp("bar", xmp_string_cstr(the_prop)) == 0);
+
+ BOOST_CHECK(xmp_delete_property(xmp, NS_DC, "creator[3]"));
+ BOOST_CHECK(!xmp_has_property(xmp, NS_DC, "creator[3]"));
+
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_EXIF, "DateTimeOriginal", the_prop, NULL));
+ BOOST_CHECK(strcmp("2006-12-07T23:20:43-05:00", xmp_string_cstr(the_prop)) ==
+ 0);
+
+ BOOST_CHECK(xmp_get_property(xmp, NS_XAP, "Rating", the_prop, NULL));
+ BOOST_CHECK(strcmp("3", xmp_string_cstr(the_prop)) == 0);
+
+ xmp_string_free(the_prop);
+
+ // testing date time get
+ XmpDateTime the_dt;
+ bool ret;
+ BOOST_CHECK(ret = xmp_get_property_date(xmp, NS_EXIF, "DateTimeOriginal",
+ &the_dt, NULL));
+ BOOST_CHECK(the_dt.year == 2006);
+ BOOST_CHECK(the_dt.minute == 20);
+ BOOST_CHECK(the_dt.tzSign == XMP_TZ_WEST);
+
+ // testing compare
+ XmpDateTime the_other_dt;
+ BOOST_CHECK(ret = xmp_get_property_date(xmp, NS_EXIF, "DateTimeOriginal",
+ &the_other_dt, NULL));
+ BOOST_CHECK(xmp_datetime_compare(&the_dt, &the_other_dt) == 0);
+ the_other_dt.year++;
+ BOOST_CHECK(xmp_datetime_compare(&the_dt, &the_other_dt) < 0);
+ BOOST_CHECK(xmp_datetime_compare(&the_other_dt, &the_dt) > 0);
+ // NULL checks - this is Exempi API
+ BOOST_CHECK(xmp_datetime_compare(NULL, NULL) == 0);
+ BOOST_CHECK(xmp_datetime_compare(NULL, &the_other_dt) < 0);
+ BOOST_CHECK(xmp_datetime_compare(&the_other_dt, NULL) > 0);
+
+ // testing float get set
+ double float_value = 0.0;
+ BOOST_CHECK(xmp_get_property_float(xmp, NS_CAMERA_RAW_SETTINGS,
+ "SharpenRadius", &float_value, NULL));
+ BOOST_CHECK(float_value == 1.0);
+ BOOST_CHECK(xmp_set_property_float(xmp, NS_CAMERA_RAW_SETTINGS,
+ "SharpenRadius", 2.5, 0));
+ BOOST_CHECK(xmp_get_property_float(xmp, NS_CAMERA_RAW_SETTINGS,
+ "SharpenRadius", &float_value, NULL));
+ BOOST_CHECK(float_value == 2.5);
+
+ // testing bool get set
+ bool bool_value = true;
+ BOOST_CHECK(xmp_get_property_bool(xmp, NS_CAMERA_RAW_SETTINGS,
+ "AlreadyApplied", &bool_value, NULL));
+ BOOST_CHECK(!bool_value);
+ BOOST_CHECK(xmp_set_property_bool(xmp, NS_CAMERA_RAW_SETTINGS,
+ "AlreadyApplied", true, 0));
+ BOOST_CHECK(xmp_get_property_bool(xmp, NS_CAMERA_RAW_SETTINGS,
+ "AlreadyApplied", &bool_value, NULL));
+ BOOST_CHECK(bool_value);
+
+ // testing int get set
+ int32_t value = 0;
+ BOOST_CHECK(
+ xmp_get_property_int32(xmp, NS_EXIF, "MeteringMode", &value, NULL));
+ BOOST_CHECK(value == 5);
+ BOOST_CHECK(xmp_set_property_int32(xmp, NS_EXIF, "MeteringMode", 10, 0));
+ int64_t valuelarge = 0;
+ BOOST_CHECK(
+ xmp_get_property_int64(xmp, NS_EXIF, "MeteringMode", &valuelarge, NULL));
+ BOOST_CHECK(valuelarge == 10);
+ BOOST_CHECK(xmp_set_property_int64(xmp, NS_EXIF, "MeteringMode", 32, 0));
+
+ BOOST_CHECK(
+ xmp_get_property_int32(xmp, NS_EXIF, "MeteringMode", &value, NULL));
+ BOOST_CHECK(value == 32);
+
+ BOOST_CHECK(xmp_free(xmp));
+
+ free(buffer);
+ fclose(f);
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-fdo83313.cpp b/exempi/tests/test-fdo83313.cpp
new file mode 100644
index 0000000..38ff771
--- /dev/null
+++ b/exempi/tests/test-fdo83313.cpp
@@ -0,0 +1,74 @@
+/*
+ * exempi - test-bgo.cpp
+ *
+ * Copyright (C) 2007-2008 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+int test_main(int argc, char* argv[])
+{
+ prepare_test(argc, argv, "fdo83313.jpg");
+
+ BOOST_CHECK(xmp_init());
+
+ XmpFilePtr xf = xmp_files_open_new(g_testfile.c_str(), XMP_OPEN_READ);
+
+ BOOST_CHECK(xf != NULL);
+ if (xf == NULL) {
+ return 1;
+ }
+
+ XmpPtr xmp = xmp_files_get_new_xmp(xf);
+
+ BOOST_CHECK(xmp != NULL);
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_free(xf));
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-serialise.cpp b/exempi/tests/test-serialise.cpp
new file mode 100644
index 0000000..6175a16
--- /dev/null
+++ b/exempi/tests/test-serialise.cpp
@@ -0,0 +1,102 @@
+/*
+ * exempi - test-serialise.cpp
+ *
+ * Copyright (C) 2007-2008 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+using boost::unit_test::test_suite;
+
+// void test_serialize()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "test1.xmp");
+
+ size_t len;
+ char *buffer;
+ FILE *f = fopen(g_testfile.c_str(), "rb");
+
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buffer = (char *)malloc(len + 1);
+ size_t rlen = fread(buffer, 1, len, f);
+
+ BOOST_CHECK(rlen == len);
+ BOOST_CHECK(len != 0);
+ buffer[rlen] = 0;
+
+ BOOST_CHECK(xmp_init());
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ XmpPtr xmp = xmp_new_empty();
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ std::string b1(buffer);
+ std::string b2;
+ XmpStringPtr output = xmp_string_new();
+
+ BOOST_CHECK(xmp_serialize_and_format(
+ xmp, output, XMP_SERIAL_OMITPACKETWRAPPER, 0, "\n", " ", 0));
+ BOOST_CHECK(xmp_get_error() == 0);
+ b2 = xmp_string_cstr(output);
+ // find a way to compare that.
+ // BOOST_CHECK_EQUAL(b1, b2);
+
+ xmp_string_free(output);
+ BOOST_CHECK(xmp_free(xmp));
+
+ free(buffer);
+ fclose(f);
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-tiff-leak.cpp b/exempi/tests/test-tiff-leak.cpp
new file mode 100644
index 0000000..729cced
--- /dev/null
+++ b/exempi/tests/test-tiff-leak.cpp
@@ -0,0 +1,86 @@
+/*
+ * exempi - test-tiff-leak.cpp
+ *
+ * Copyright (C) 2007-2008,2010 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+
+/** See http://www.adobeforums.com/webx/.3bc42b73 for the orignal
+ * test case */
+// void test_tiff_leak()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "../../samples/testfiles/BlueSquare.jpg");
+
+ std::string orig_tiff_file =
+ g_src_testdir + "../../samples/testfiles/BlueSquare.tif";
+ BOOST_CHECK(copy_file(orig_tiff_file, "test.tif"));
+ BOOST_CHECK(chmod("test.tif", S_IRUSR | S_IWUSR) == 0);
+ BOOST_CHECK(xmp_init());
+
+ XmpFilePtr f = xmp_files_open_new("test.tif", XMP_OPEN_FORUPDATE);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 1;
+ }
+
+ XmpPtr xmp;
+
+ BOOST_CHECK(xmp = xmp_files_get_new_xmp(f));
+ BOOST_CHECK(xmp != NULL);
+
+ xmp_set_localized_text(xmp, NS_DC, "description", "en", "en-US", "foo", 0);
+ BOOST_CHECK(xmp_files_put_xmp(f, xmp));
+ BOOST_CHECK(xmp_files_close(f, XMP_CLOSE_NOOPTION));
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_free(f));
+ xmp_terminate();
+
+ BOOST_CHECK(unlink("test.tif") == 0);
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-webp.cpp b/exempi/tests/test-webp.cpp
new file mode 100644
index 0000000..47aa7dc
--- /dev/null
+++ b/exempi/tests/test-webp.cpp
@@ -0,0 +1,119 @@
+/*
+ * exempi - test-webp.cpp
+ *
+ * Copyright (C) 2007-2016 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+
+using boost::unit_test::test_suite;
+
+
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "../../samples/testfiles/BlueSquare.webp");
+
+ BOOST_CHECK(xmp_init());
+
+ BOOST_CHECK(xmp_files_check_file_format(g_testfile.c_str()) == XMP_FT_WEBP);
+ XmpFilePtr f = xmp_files_open_new(g_testfile.c_str(), XMP_OPEN_READ);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 1;
+ }
+
+ XmpPtr xmp = xmp_files_get_new_xmp(f);
+ BOOST_CHECK(xmp != NULL);
+
+ BOOST_CHECK(xmp_files_free(f));
+
+ BOOST_CHECK(copy_file(g_testfile, "test.webp"));
+ BOOST_CHECK(chmod("test.webp", S_IRUSR | S_IWUSR) == 0);
+
+ BOOST_CHECK(xmp_files_check_file_format("test.webp") == XMP_FT_WEBP);
+
+ f = xmp_files_open_new("test.webp", XMP_OPEN_FORUPDATE);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 2;
+ }
+
+ BOOST_CHECK(xmp_set_property(xmp, NS_PHOTOSHOP, "ICCProfile", "foo", 0));
+
+ BOOST_CHECK(xmp_files_can_put_xmp(f, xmp));
+ BOOST_CHECK(xmp_files_put_xmp(f, xmp));
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_close(f, XMP_CLOSE_SAFEUPDATE));
+ BOOST_CHECK(xmp_files_free(f));
+
+ f = xmp_files_open_new("test.webp", XMP_OPEN_READ);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 3;
+ }
+ xmp = xmp_files_get_new_xmp(f);
+ BOOST_CHECK(xmp != NULL);
+
+ XmpStringPtr the_prop = xmp_string_new();
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_PHOTOSHOP, "ICCProfile", the_prop, NULL));
+ BOOST_CHECK(strcmp("foo", xmp_string_cstr(the_prop)) == 0);
+
+ xmp_string_free(the_prop);
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_close(f, XMP_CLOSE_NOOPTION));
+ BOOST_CHECK(xmp_files_free(f));
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+
+ return 0;
+}
diff --git a/exempi/tests/test-write-new-prop.cpp b/exempi/tests/test-write-new-prop.cpp
new file mode 100644
index 0000000..524376e
--- /dev/null
+++ b/exempi/tests/test-write-new-prop.cpp
@@ -0,0 +1,150 @@
+/*
+ * exempi - test1.cpp
+ *
+ * Copyright (C) 2007-2008 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+using boost::unit_test::test_suite;
+
+// void test_write_new_property()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "test1.xmp");
+
+ size_t len;
+ char *buffer;
+
+ FILE *f = fopen(g_testfile.c_str(), "rb");
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ exit(128);
+ }
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buffer = (char *)malloc(len + 1);
+ size_t rlen = fread(buffer, 1, len, f);
+
+ BOOST_CHECK(rlen == len);
+ BOOST_CHECK(len != 0);
+
+ BOOST_CHECK(xmp_init());
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ XmpPtr xmp = xmp_new_empty();
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ BOOST_CHECK(xmp != NULL);
+
+ XmpStringPtr reg_prefix = xmp_string_new();
+ BOOST_CHECK(xmp_register_namespace(NS_CC, "cc", reg_prefix));
+ BOOST_CHECK(xmp_get_error() == 0);
+ BOOST_CHECK(strcmp("cc:", xmp_string_cstr(reg_prefix)) == 0);
+
+ BOOST_CHECK(xmp_prefix_namespace_uri("cc", reg_prefix));
+ BOOST_CHECK(xmp_get_error() == 0);
+ BOOST_CHECK(strcmp(NS_CC, xmp_string_cstr(reg_prefix)) == 0);
+
+ BOOST_CHECK(xmp_namespace_prefix(NS_CC, reg_prefix));
+ BOOST_CHECK(xmp_get_error() == 0);
+ BOOST_CHECK(strcmp("cc:", xmp_string_cstr(reg_prefix)) == 0);
+
+ xmp_string_free(reg_prefix);
+
+ BOOST_CHECK(xmp_set_property(xmp, NS_CC, "License", "Foo", 0));
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ XmpStringPtr the_prop = xmp_string_new();
+ BOOST_CHECK(xmp_get_property(xmp, NS_CC, "License", the_prop, NULL));
+ BOOST_CHECK(xmp_get_error() == 0);
+ BOOST_CHECK(strcmp("Foo", xmp_string_cstr(the_prop)) == 0);
+
+ XmpDateTime the_dt;
+ the_dt.year = 2005;
+ the_dt.month = 12;
+ the_dt.day = 25;
+ the_dt.hour = 12;
+ the_dt.minute = 42;
+ the_dt.second = 42;
+ the_dt.tzSign = XMP_TZ_UTC;
+ the_dt.tzHour = 0;
+ the_dt.tzMinute = 0;
+ the_dt.nanoSecond = 0;
+ BOOST_CHECK(
+ xmp_set_property_date(xmp, NS_EXIF, "DateTimeOriginal", &the_dt, 0));
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_EXIF, "DateTimeOriginal", the_prop, NULL));
+ BOOST_CHECK(xmp_get_error() == 0);
+ BOOST_CHECK(strcmp("2005-12-25T12:42:42", xmp_string_cstr(the_prop)) == 0);
+
+ XmpDateTime the_dt2;
+ BOOST_CHECK(
+ xmp_get_property_date(xmp, NS_EXIF, "DateTimeOriginal", &the_dt2, NULL));
+ BOOST_CHECK(xmp_get_error() == 0);
+
+ BOOST_CHECK(the_dt2.year == 2005);
+ BOOST_CHECK(the_dt2.minute == 42);
+ BOOST_CHECK(the_dt2.tzSign == XMP_TZ_UTC);
+
+ xmp_string_free(the_prop);
+
+ BOOST_CHECK(xmp_free(xmp));
+
+ free(buffer);
+ fclose(f);
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test-xmpfiles-write.cpp b/exempi/tests/test-xmpfiles-write.cpp
new file mode 100644
index 0000000..e44e242
--- /dev/null
+++ b/exempi/tests/test-xmpfiles-write.cpp
@@ -0,0 +1,120 @@
+/*
+ * exempi - test-xmpfile-write.cpp
+ *
+ * Copyright (C) 2007-2008,2010 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+
+using boost::unit_test::test_suite;
+
+// void test_xmpfiles_write()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "../../samples/testfiles/BlueSquare.jpg");
+
+ BOOST_CHECK(xmp_init());
+
+ BOOST_CHECK(xmp_files_check_file_format(g_testfile.c_str()) == XMP_FT_JPEG);
+ XmpFilePtr f = xmp_files_open_new(g_testfile.c_str(), XMP_OPEN_READ);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 1;
+ }
+
+ XmpPtr xmp = xmp_files_get_new_xmp(f);
+ BOOST_CHECK(xmp != NULL);
+
+ BOOST_CHECK(xmp_files_free(f));
+
+ BOOST_CHECK(copy_file(g_testfile, "test.jpg"));
+ BOOST_CHECK(chmod("test.jpg", S_IRUSR | S_IWUSR) == 0);
+
+ BOOST_CHECK(xmp_files_check_file_format("test.jpg") == XMP_FT_JPEG);
+
+ f = xmp_files_open_new("test.jpg", XMP_OPEN_FORUPDATE);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 2;
+ }
+
+ BOOST_CHECK(xmp_set_property(xmp, NS_PHOTOSHOP, "ICCProfile", "foo", 0));
+
+ BOOST_CHECK(xmp_files_can_put_xmp(f, xmp));
+ BOOST_CHECK(xmp_files_put_xmp(f, xmp));
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_close(f, XMP_CLOSE_SAFEUPDATE));
+ BOOST_CHECK(xmp_files_free(f));
+
+ f = xmp_files_open_new("test.jpg", XMP_OPEN_READ);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ return 3;
+ }
+ xmp = xmp_files_get_new_xmp(f);
+ BOOST_CHECK(xmp != NULL);
+
+ XmpStringPtr the_prop = xmp_string_new();
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_PHOTOSHOP, "ICCProfile", the_prop, NULL));
+ BOOST_CHECK(strcmp("foo", xmp_string_cstr(the_prop)) == 0);
+
+ xmp_string_free(the_prop);
+
+ BOOST_CHECK(xmp_free(xmp));
+ BOOST_CHECK(xmp_files_close(f, XMP_CLOSE_NOOPTION));
+ BOOST_CHECK(xmp_files_free(f));
+
+ // unlink("test.jpg");
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+
+ return 0;
+}
diff --git a/exempi/tests/test-xmpfiles.cpp b/exempi/tests/test-xmpfiles.cpp
new file mode 100644
index 0000000..9a2bfca
--- /dev/null
+++ b/exempi/tests/test-xmpfiles.cpp
@@ -0,0 +1,129 @@
+/*
+ * exempi - test-xmpfiles.cpp
+ *
+ * Copyright (C) 2007-2016 Hubert Figuière
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+
+using boost::unit_test::test_suite;
+
+// void test_xmpfiles()
+int test_main(int argc, char* argv[])
+{
+ prepare_test(argc, argv, "../../samples/testfiles/BlueSquare.jpg");
+
+ BOOST_CHECK(xmp_init());
+
+ XmpFilePtr f = xmp_files_open_new(g_testfile.c_str(), XMP_OPEN_READ);
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ exit(128);
+ }
+
+ BOOST_CHECK(xmp_files_check_file_format(g_testfile.c_str()) == XMP_FT_JPEG);
+
+ XmpStringPtr file_path = xmp_string_new();
+ XmpOpenFileOptions options;
+ XmpFileType file_format;
+ XmpFileFormatOptions handler_flags;
+ BOOST_CHECK(xmp_files_get_file_info(f, file_path, &options, &file_format,
+ &handler_flags));
+ BOOST_CHECK(options == XMP_OPEN_READ);
+ BOOST_CHECK(file_format == XMP_FT_JPEG);
+ // the value check might break at each SDK update. You have been warned.
+ BOOST_CHECK(handler_flags == 0x27f);
+ BOOST_CHECK(g_testfile == xmp_string_cstr(file_path));
+ xmp_string_free(file_path);
+
+ XmpPtr xmp = xmp_new_empty();
+
+ BOOST_CHECK(xmp != NULL);
+
+ BOOST_CHECK(xmp_files_get_xmp(f, xmp));
+
+ {
+ XmpStringPtr thestring = xmp_string_new();
+ XmpPacketInfo packet_info;
+ BOOST_CHECK(xmp_files_get_xmp_xmpstring(f, thestring, &packet_info));
+ BOOST_CHECK(packet_info.offset == 2189);
+ BOOST_CHECK(packet_info.length == 4782);
+ BOOST_CHECK(packet_info.padSize == 2049);
+ BOOST_CHECK(packet_info.hasWrapper);
+
+ const char *xmp_str = xmp_string_cstr(thestring);
+ BOOST_CHECK(xmp_str);
+ xmp_string_free(thestring);
+ }
+
+ XmpStringPtr the_prop = xmp_string_new();
+
+ BOOST_CHECK(
+ xmp_get_property(xmp, NS_PHOTOSHOP, "ICCProfile", the_prop, NULL));
+ BOOST_CHECK(strcmp("sRGB IEC61966-2.1", xmp_string_cstr(the_prop)) == 0);
+
+ xmp_string_free(the_prop);
+ BOOST_CHECK(xmp_free(xmp));
+
+ BOOST_CHECK(xmp_files_free(f));
+
+ XmpFileFormatOptions formatOptions;
+
+ // the value check might break at each SDK update. You have been warned.
+ BOOST_CHECK(xmp_files_get_format_info(XMP_FT_JPEG, &formatOptions));
+ BOOST_CHECK(formatOptions == 0x27f);
+ BOOST_CHECK(xmp_files_get_format_info(XMP_FT_GIF, &formatOptions));
+ BOOST_CHECK(formatOptions == 0x46b);
+ BOOST_CHECK(xmp_files_get_format_info(XMP_FT_PNG, &formatOptions));
+ BOOST_CHECK(formatOptions == 0x46b);
+ // PDF doesn't have a smart handler.
+ BOOST_CHECK(!xmp_files_get_format_info(XMP_FT_PDF, &formatOptions));
+
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/test1.xmp b/exempi/tests/test1.xmp
new file mode 100644
index 0000000..281f936
--- /dev/null
+++ b/exempi/tests/test1.xmp
@@ -0,0 +1,255 @@
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Public XMP Toolkit Core 3.5">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
+ <tiff:Make>Canon</tiff:Make>
+ <tiff:Model>Canon EOS 20D</tiff:Model>
+ <tiff:Orientation>1</tiff:Orientation>
+ <tiff:ImageWidth>3504</tiff:ImageWidth>
+ <tiff:ImageLength>2336</tiff:ImageLength>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:exif="http://ns.adobe.com/exif/1.0/">
+ <exif:ExifVersion>0221</exif:ExifVersion>
+ <exif:ExposureTime>15/1</exif:ExposureTime>
+ <exif:ShutterSpeedValue>-3906891/1000000</exif:ShutterSpeedValue>
+ <exif:FNumber>8/1</exif:FNumber>
+ <exif:ApertureValue>6/1</exif:ApertureValue>
+ <exif:ExposureProgram>1</exif:ExposureProgram>
+ <exif:DateTimeOriginal>2006-12-07T23:20:43-05:00</exif:DateTimeOriginal>
+ <exif:DateTimeDigitized>2006-12-07T23:20:43-05:00</exif:DateTimeDigitized>
+ <exif:ExposureBiasValue>0/2</exif:ExposureBiasValue>
+ <exif:MaxApertureValue>3625/1000</exif:MaxApertureValue>
+ <exif:MeteringMode>5</exif:MeteringMode>
+ <exif:FocalLength>32/1</exif:FocalLength>
+ <exif:CustomRendered>0</exif:CustomRendered>
+ <exif:ExposureMode>1</exif:ExposureMode>
+ <exif:WhiteBalance>0</exif:WhiteBalance>
+ <exif:SceneCaptureType>0</exif:SceneCaptureType>
+ <exif:FocalPlaneXResolution>3504000/885</exif:FocalPlaneXResolution>
+ <exif:FocalPlaneYResolution>2336000/590</exif:FocalPlaneYResolution>
+ <exif:FocalPlaneResolutionUnit>2</exif:FocalPlaneResolutionUnit>
+ <exif:ISOSpeedRatings>
+ <rdf:Seq>
+ <rdf:li>100</rdf:li>
+ </rdf:Seq>
+ </exif:ISOSpeedRatings>
+ <exif:Flash rdf:parseType="Resource">
+ <exif:Fired>False</exif:Fired>
+ <exif:Return>0</exif:Return>
+ <exif:Mode>2</exif:Mode>
+ <exif:Function>False</exif:Function>
+ <exif:RedEyeMode>False</exif:RedEyeMode>
+ </exif:Flash>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xap="http://ns.adobe.com/xap/1.0/">
+ <xap:ModifyDate>2006-12-07T23:20:43-05:00</xap:ModifyDate>
+ <xap:Rating>3</xap:Rating>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:creator>
+ <rdf:Seq>
+ <rdf:li>unknown</rdf:li>
+ </rdf:Seq>
+ </dc:creator>
+ <dc:rights>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">2006, Hubert Figuiere</rdf:li>
+ </rdf:Alt>
+ </dc:rights>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>night</rdf:li>
+ <rdf:li>ontario</rdf:li>
+ <rdf:li>ottawa</rdf:li>
+ <rdf:li>parliament of canada</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:aux="http://ns.adobe.com/exif/1.0/aux/">
+ <aux:SerialNumber>420103070</aux:SerialNumber>
+ <aux:LensInfo>24/1 85/1 0/0 0/0</aux:LensInfo>
+ <aux:Lens>24.0-85.0 mm</aux:Lens>
+ <aux:ImageNumber>176</aux:ImageNumber>
+ <aux:FlashCompensation>-2/1</aux:FlashCompensation>
+ <aux:OwnerName>unknown</aux:OwnerName>
+ <aux:Firmware>1.1.0</aux:Firmware>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/">
+ <crs:AlreadyApplied>False</crs:AlreadyApplied>
+ <crs:WhiteBalance>As Shot</crs:WhiteBalance>
+ <crs:Exposure>0.00</crs:Exposure>
+ <crs:Shadows>5</crs:Shadows>
+ <crs:Brightness>+50</crs:Brightness>
+ <crs:Contrast>+25</crs:Contrast>
+ <crs:Saturation>0</crs:Saturation>
+ <crs:Sharpness>25</crs:Sharpness>
+ <crs:LuminanceSmoothing>0</crs:LuminanceSmoothing>
+ <crs:ColorNoiseReduction>25</crs:ColorNoiseReduction>
+ <crs:ChromaticAberrationR>0</crs:ChromaticAberrationR>
+ <crs:ChromaticAberrationB>0</crs:ChromaticAberrationB>
+ <crs:VignetteAmount>0</crs:VignetteAmount>
+ <crs:ShadowTint>0</crs:ShadowTint>
+ <crs:RedHue>0</crs:RedHue>
+ <crs:RedSaturation>0</crs:RedSaturation>
+ <crs:GreenHue>0</crs:GreenHue>
+ <crs:GreenSaturation>0</crs:GreenSaturation>
+ <crs:BlueHue>0</crs:BlueHue>
+ <crs:BlueSaturation>0</crs:BlueSaturation>
+ <crs:FillLight>0</crs:FillLight>
+ <crs:Vibrance>0</crs:Vibrance>
+ <crs:HighlightRecovery>0</crs:HighlightRecovery>
+ <crs:Clarity>0</crs:Clarity>
+ <crs:Defringe>0</crs:Defringe>
+ <crs:HueAdjustmentRed>0</crs:HueAdjustmentRed>
+ <crs:HueAdjustmentOrange>0</crs:HueAdjustmentOrange>
+ <crs:HueAdjustmentYellow>0</crs:HueAdjustmentYellow>
+ <crs:HueAdjustmentGreen>0</crs:HueAdjustmentGreen>
+ <crs:HueAdjustmentAqua>0</crs:HueAdjustmentAqua>
+ <crs:HueAdjustmentBlue>0</crs:HueAdjustmentBlue>
+ <crs:HueAdjustmentPurple>0</crs:HueAdjustmentPurple>
+ <crs:HueAdjustmentMagenta>0</crs:HueAdjustmentMagenta>
+ <crs:SaturationAdjustmentRed>0</crs:SaturationAdjustmentRed>
+ <crs:SaturationAdjustmentOrange>0</crs:SaturationAdjustmentOrange>
+ <crs:SaturationAdjustmentYellow>0</crs:SaturationAdjustmentYellow>
+ <crs:SaturationAdjustmentGreen>0</crs:SaturationAdjustmentGreen>
+ <crs:SaturationAdjustmentAqua>0</crs:SaturationAdjustmentAqua>
+ <crs:SaturationAdjustmentBlue>0</crs:SaturationAdjustmentBlue>
+ <crs:SaturationAdjustmentPurple>0</crs:SaturationAdjustmentPurple>
+ <crs:SaturationAdjustmentMagenta>0</crs:SaturationAdjustmentMagenta>
+ <crs:LuminanceAdjustmentRed>0</crs:LuminanceAdjustmentRed>
+ <crs:LuminanceAdjustmentOrange>0</crs:LuminanceAdjustmentOrange>
+ <crs:LuminanceAdjustmentYellow>0</crs:LuminanceAdjustmentYellow>
+ <crs:LuminanceAdjustmentGreen>0</crs:LuminanceAdjustmentGreen>
+ <crs:LuminanceAdjustmentAqua>0</crs:LuminanceAdjustmentAqua>
+ <crs:LuminanceAdjustmentBlue>0</crs:LuminanceAdjustmentBlue>
+ <crs:LuminanceAdjustmentPurple>0</crs:LuminanceAdjustmentPurple>
+ <crs:LuminanceAdjustmentMagenta>0</crs:LuminanceAdjustmentMagenta>
+ <crs:SplitToningShadowHue>0</crs:SplitToningShadowHue>
+ <crs:SplitToningShadowSaturation>0</crs:SplitToningShadowSaturation>
+ <crs:SplitToningHighlightHue>0</crs:SplitToningHighlightHue>
+ <crs:SplitToningHighlightSaturation>0</crs:SplitToningHighlightSaturation>
+ <crs:SplitToningBalance>0</crs:SplitToningBalance>
+ <crs:ParametricShadows>0</crs:ParametricShadows>
+ <crs:ParametricDarks>0</crs:ParametricDarks>
+ <crs:ParametricLights>0</crs:ParametricLights>
+ <crs:ParametricHighlights>0</crs:ParametricHighlights>
+ <crs:ParametricShadowSplit>25</crs:ParametricShadowSplit>
+ <crs:ParametricMidtoneSplit>50</crs:ParametricMidtoneSplit>
+ <crs:ParametricHighlightSplit>75</crs:ParametricHighlightSplit>
+ <crs:SharpenRadius>+1.0</crs:SharpenRadius>
+ <crs:SharpenDetail>25</crs:SharpenDetail>
+ <crs:SharpenEdgeMasking>0</crs:SharpenEdgeMasking>
+ <crs:ConvertToGrayscale>False</crs:ConvertToGrayscale>
+ <crs:ToneCurveName>Medium Contrast</crs:ToneCurveName>
+ <crs:ToneCurve>
+ <rdf:Seq>
+ <rdf:li>0, 0</rdf:li>
+ <rdf:li>32, 22</rdf:li>
+ <rdf:li>64, 56</rdf:li>
+ <rdf:li>128, 128</rdf:li>
+ <rdf:li>192, 196</rdf:li>
+ <rdf:li>255, 255</rdf:li>
+ </rdf:Seq>
+ </crs:ToneCurve>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:crx="http://ns.adobe.com/lightroom-settings-experimental/1.0/">
+ <crx:ConvertToGrayscale>false</crx:ConvertToGrayscale>
+ <crx:SplitToningHighlightHue>0</crx:SplitToningHighlightHue>
+ <crx:Sharpness>25</crx:Sharpness>
+ <crx:CropBottom>1</crx:CropBottom>
+ <crx:GreenSaturation>0</crx:GreenSaturation>
+ <crx:Exposure>0</crx:Exposure>
+ <crx:LuminanceAdjustmentGreens>0</crx:LuminanceAdjustmentGreens>
+ <crx:SplitToningShadowHue>0</crx:SplitToningShadowHue>
+ <crx:BlueHue>0</crx:BlueHue>
+ <crx:GreenHue>0</crx:GreenHue>
+ <crx:FillLight>0</crx:FillLight>
+ <crx:HueAdjustmentCyans>0</crx:HueAdjustmentCyans>
+ <crx:SaturationAdjustmentGreens>0</crx:SaturationAdjustmentGreens>
+ <crx:Saturation>0</crx:Saturation>
+ <crx:SaturationAdjustmentBlues>0</crx:SaturationAdjustmentBlues>
+ <crx:VignetteMidpoint>50</crx:VignetteMidpoint>
+ <crx:ToneHighlightSplit>75</crx:ToneHighlightSplit>
+ <crx:ToneShadowSplit>25</crx:ToneShadowSplit>
+ <crx:Contrast>25</crx:Contrast>
+ <crx:WhiteBalance>As Shot</crx:WhiteBalance>
+ <crx:HueAdjustmentMagentas>0</crx:HueAdjustmentMagentas>
+ <crx:HighlightRecovery>0</crx:HighlightRecovery>
+ <crx:SaturationAdjustmentCyans>0</crx:SaturationAdjustmentCyans>
+ <crx:GrayMixerYellows>100</crx:GrayMixerYellows>
+ <crx:HueAdjustmentGreens>0</crx:HueAdjustmentGreens>
+ <crx:ToneShadows>0</crx:ToneShadows>
+ <crx:GrayMixerGreens>71</crx:GrayMixerGreens>
+ <crx:GrayMixerBlues>0</crx:GrayMixerBlues>
+ <crx:ColorNoiseReduction>25</crx:ColorNoiseReduction>
+ <crx:ShadowTint>0</crx:ShadowTint>
+ <crx:Shadows>5</crx:Shadows>
+ <crx:RedHue>0</crx:RedHue>
+ <crx:Brightness>50</crx:Brightness>
+ <crx:BlueSaturation>0</crx:BlueSaturation>
+ <crx:CropTop>0</crx:CropTop>
+ <crx:SaturationAdjustmentMagentas>0</crx:SaturationAdjustmentMagentas>
+ <crx:GrayMixerReds>29</crx:GrayMixerReds>
+ <crx:AutoBrightness>false</crx:AutoBrightness>
+ <crx:AutoTonality>false</crx:AutoTonality>
+ <crx:AutoExposure>false</crx:AutoExposure>
+ <crx:RedSaturation>0</crx:RedSaturation>
+ <crx:LuminanceAdjustmentMagentas>0</crx:LuminanceAdjustmentMagentas>
+ <crx:LuminanceAdjustmentBlues>0</crx:LuminanceAdjustmentBlues>
+ <crx:HueAdjustmentBlues>0</crx:HueAdjustmentBlues>
+ <crx:SaturationAdjustmentReds>0</crx:SaturationAdjustmentReds>
+ <crx:LuminanceAdjustmentYellows>0</crx:LuminanceAdjustmentYellows>
+ <crx:SplitToningShadowSaturation>0</crx:SplitToningShadowSaturation>
+ <crx:ChromaticAberrationR>0</crx:ChromaticAberrationR>
+ <crx:LuminanceAdjustmentCyans>0</crx:LuminanceAdjustmentCyans>
+ <crx:CropAngle>0</crx:CropAngle>
+ <crx:ChromaticAberrationB>0</crx:ChromaticAberrationB>
+ <crx:AutoShadows>false</crx:AutoShadows>
+ <crx:CropRight>1</crx:CropRight>
+ <crx:ToneLights>0</crx:ToneLights>
+ <crx:HueAdjustmentReds>0</crx:HueAdjustmentReds>
+ <crx:Vibrance>0</crx:Vibrance>
+ <crx:ToneDarks>0</crx:ToneDarks>
+ <crx:GrayMixerMagentas>29</crx:GrayMixerMagentas>
+ <crx:LuminanceSmoothing>0</crx:LuminanceSmoothing>
+ <crx:SplitToningHighlightSaturation>0</crx:SplitToningHighlightSaturation>
+ <crx:HueAdjustmentYellows>0</crx:HueAdjustmentYellows>
+ <crx:GrayMixerCyans>71</crx:GrayMixerCyans>
+ <crx:ToneMidtoneSplit>50</crx:ToneMidtoneSplit>
+ <crx:VignetteAmount>0</crx:VignetteAmount>
+ <crx:AutoContrast>false</crx:AutoContrast>
+ <crx:CropLeft>0</crx:CropLeft>
+ <crx:ToneHighlights>0</crx:ToneHighlights>
+ <crx:AutoGrayscaleWeights>true</crx:AutoGrayscaleWeights>
+ <crx:SaturationAdjustmentYellows>0</crx:SaturationAdjustmentYellows>
+ <crx:LuminanceAdjustmentReds>0</crx:LuminanceAdjustmentReds>
+ <crx:Tint>1</crx:Tint>
+ <crx:Temperature>4350</crx:Temperature>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:lr="http://ns.adobe.com/lightroom/1.0/">
+ <lr:hierarchicalKeywords>aGllcmFyY2hpY2FsS2V5d29yZHMgPSB7Cgl7CgkJZmxhdCA9IHsKCQkJIm5pZ2h0IiwKCQl9LAoJCXBhdGggPSB7CgkJCSJuaWdodCIsCgkJfSwKCQlwcmltYXJ5ID0gIm5pZ2h0IiwKCQl1dWlkID0gIkU1RDEwQTFELTU3QUYtMTFEQi04RTMzLTAwMEQ5MzVDODY5QSIsCgl9LAoJewoJCWZsYXQgPSB7CgkJCSJvbnRhcmlvIiwKCQkJIm90dGF3YSIsCgkJfSwKCQlwYXRoID0gewoJCQkib250YXJpbyIsCgkJCSJvdHRhd2EiLAoJCX0sCgkJcHJpbWFyeSA9ICJvdHRhd2EiLAoJCXV1aWQgPSAiQjgzMTc4RkItNTdBRi0xMURCLThFMzMtMDAwRDkzNUM4NjlBIiwKCX0sCgl7CgkJZmxhdCA9IHsKCQkJInBhcmxpYW1lbnQgb2YgY2FuYWRhIiwKCQkJIm9udGFyaW8iLAoJCQkib3R0YXdhIiwKCQl9LAoJCXBhdGggPSB7CgkJCSJvbnRhcmlvIiwKCQkJIm90dGF3YSIsCgkJCSJwYXJsaWFtZW50IG9mIGNhbmFkYSIsCgkJfSwKCQlwcmltYXJ5ID0gInBhcmxpYW1lbnQgb2YgY2FuYWRhIiwKCQl1dWlkID0gIkU1RDMzMEZDLTU3QUYtMTFEQi04RTMzLTAwMEQ5MzVDODY5QSIsCgl9LAp9Cg==</lr:hierarchicalKeywords>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/">
+ <xmpTPg:MaxPageSize>
+ <rdf:Description
+ xmlns:stDim="http:ns.adobe.com/xap/1.0/sType/Dimensions#">
+ <stDim:w>4</stDim:w>
+ <stDim:h>3</stDim:h>
+ <stDim:unit>inches</stDim:unit>
+ </rdf:Description>
+ </xmpTPg:MaxPageSize>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/">
+ <Iptc4xmpCore:Location>Parliament Hill, Ottawa, Ontario, Canada</Iptc4xmpCore:Location>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
diff --git a/exempi/tests/test3.cpp b/exempi/tests/test3.cpp
new file mode 100644
index 0000000..90f84a3
--- /dev/null
+++ b/exempi/tests/test3.cpp
@@ -0,0 +1,115 @@
+/*
+ * exempi - test3.cpp
+ *
+ * Copyright (C) 2007-2008 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+#include <iostream>
+
+#include <boost/test/minimal.hpp>
+#include <boost/format.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+
+using boost::unit_test::test_suite;
+
+// void test_exempi_iterate()
+int test_main(int argc, char *argv[])
+{
+ prepare_test(argc, argv, "test1.xmp");
+
+ size_t len;
+ char *buffer;
+
+ FILE *f = fopen(g_testfile.c_str(), "rb");
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ exit(128);
+ }
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buffer = (char *)malloc(len + 1);
+ size_t rlen = fread(buffer, 1, len, f);
+
+ BOOST_CHECK(rlen == len);
+ BOOST_CHECK(len != 0);
+ BOOST_CHECK(xmp_init());
+
+ XmpPtr xmp = xmp_new_empty();
+
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+
+ BOOST_CHECK(xmp != NULL);
+
+ XmpIteratorPtr iter =
+ xmp_iterator_new(xmp, NULL, NULL, XMP_ITER_JUSTLEAFNODES);
+
+ XmpStringPtr the_schema = xmp_string_new();
+ XmpStringPtr the_path = xmp_string_new();
+ XmpStringPtr the_prop = xmp_string_new();
+ uint32_t options;
+
+ while (xmp_iterator_next(iter, the_schema, the_path, the_prop, &options)) {
+ std::cout << xmp_string_cstr(the_schema) << " / "
+ << xmp_string_cstr(the_path) << " = "
+ << xmp_string_cstr(the_prop);
+ if (options) {
+ std::cout << boost::format(" options = 0x%1$x") % options;
+ }
+ std::cout << std::endl;
+ }
+
+ xmp_string_free(the_prop);
+ xmp_string_free(the_path);
+ xmp_string_free(the_schema);
+ BOOST_CHECK(xmp_iterator_free(iter));
+ BOOST_CHECK(xmp_free(xmp));
+
+ free(buffer);
+ fclose(f);
+ xmp_terminate();
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/testcore.sh b/exempi/tests/testcore.sh
new file mode 100755
index 0000000..94c67b4
--- /dev/null
+++ b/exempi/tests/testcore.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Test script.
+# Currently only make sure dumpmainxmp does not crash
+# Written by Hubert Figuiere <hub@figuiere.net>
+
+if [ -z $srcdir ] ; then
+ echo "$srcdir srcdir not defined."
+ exit 255
+fi
+
+SAMPLES="BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif BlueSquare.avi BlueSquare.indd BlueSquare.pdf BlueSquare.psd BlueSquare.wav"
+SAMPLES_DIR=$srcdir/../../samples/testfiles
+DUMPMAINXMP_PROG=../../samples/source/dumpmainxmp
+
+if [ ! -x $DUMPMAINXMP_PROG ] ; then
+ echo "$DUMPMAINXMP_PROG not executable."
+ exit 255
+fi
+
+for i in $SAMPLES
+do
+ echo "Running $DUMPMAINXMP_PROG $SAMPLES_DIR/$i"
+ $VALGRIND $DUMPMAINXMP_PROG $SAMPLES_DIR/$i > /dev/null
+ if [ $? -ne 0 ] ; then
+ echo "Failed"
+ exit 255
+ fi
+done
diff --git a/exempi/tests/testcpp.cpp b/exempi/tests/testcpp.cpp
new file mode 100644
index 0000000..13f944f
--- /dev/null
+++ b/exempi/tests/testcpp.cpp
@@ -0,0 +1,69 @@
+/*
+ * exempi - testcpp.cpp
+ *
+ * Copyright (C) 2011 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmp.h"
+#include "xmpconsts.h"
+#include "xmp++.hpp"
+
+using boost::unit_test::test_suite;
+
+int test_main(int argc, char* argv[])
+{
+ // this test is totally useless without leak checking.
+ // but for compiling.
+ {
+ xmp::ScopedPtr<XmpStringPtr> ptr(xmp_string_new());
+ }
+
+ {
+ xmp::ScopedPtr<XmpFilePtr> ptr(xmp_files_new());
+ }
+
+ {
+ xmp::ScopedPtr<XmpPtr> ptr(xmp_new_empty());
+ {
+ xmp::ScopedPtr<XmpIteratorPtr> iterptr(
+ xmp_iterator_new(ptr, NS_EXIF, NULL, XMP_ITER_JUSTLEAFNODES));
+ }
+ }
+
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/testinit.cpp b/exempi/tests/testinit.cpp
new file mode 100644
index 0000000..0ce70aa
--- /dev/null
+++ b/exempi/tests/testinit.cpp
@@ -0,0 +1,94 @@
+/*
+ * exempi - testinit.cpp
+ *
+ * Copyright (C) 2007 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <boost/test/minimal.hpp>
+
+#include "utils.h"
+#include "xmpconsts.h"
+#include "xmp.h"
+
+// void test_exempi_init()
+int test_main(int argc, char* argv[])
+{
+ prepare_test(argc, argv, "test1.xmp");
+
+ size_t len;
+ char* buffer;
+
+ FILE* f = fopen(g_testfile.c_str(), "rb");
+
+ BOOST_CHECK(f != NULL);
+ if (f == NULL) {
+ exit(128);
+ }
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buffer = (char*)malloc(len + 1);
+ size_t rlen = fread(buffer, 1, len, f);
+
+ BOOST_CHECK(rlen == len);
+ BOOST_CHECK(len != 0);
+
+ BOOST_CHECK(xmp_init());
+ BOOST_CHECK(xmp_init());
+
+ XmpPtr xmp = xmp_new_empty();
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+ BOOST_CHECK(xmp != NULL);
+ BOOST_CHECK(xmp_free(xmp));
+
+ xmp_terminate();
+
+ xmp = xmp_new_empty();
+ BOOST_CHECK(xmp_parse(xmp, buffer, len));
+ BOOST_CHECK(xmp != NULL);
+ BOOST_CHECK(xmp_free(xmp));
+
+ xmp_terminate();
+
+ free(buffer);
+ BOOST_CHECK(!g_lt->check_leaks());
+ BOOST_CHECK(!g_lt->check_errors());
+ return 0;
+}
diff --git a/exempi/tests/utils.cpp b/exempi/tests/utils.cpp
new file mode 100644
index 0000000..1620597
--- /dev/null
+++ b/exempi/tests/utils.cpp
@@ -0,0 +1,119 @@
+/*
+ * exempi - utils.cpp
+ *
+ * Copyright (C) 2007-2016 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+#include "utils.h"
+
+std::string g_testfile;
+std::string g_src_testdir;
+std::unique_ptr<LeakTracker> g_lt(new LeakTracker) ;
+
+void prepare_test(int argc, char *argv[], const char *filename)
+{
+ if (argc == 1) {
+ // no argument, lets run like we are in "check"
+ const char *srcdir = getenv("TEST_DIR");
+
+ BOOST_ASSERT(srcdir != NULL);
+ g_src_testdir = std::string(srcdir) + "/";
+ g_testfile = g_src_testdir + filename;
+ } else {
+ g_src_testdir = "./";
+ g_testfile = argv[1];
+ }
+}
+
+bool copy_file(const std::string &source, const std::string &dest)
+{
+ std::string command = "cp ";
+ command += source + " " + dest;
+ return (system(command.c_str()) >= 0);
+}
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#include <valgrind/valgrind.h>
+#define CC_EXTENSION __extension__
+#else
+#define VALGRIND_COUNT_ERRORS 0
+#define VALGRIND_DO_LEAK_CHECK
+#define VALGRIND_COUNT_LEAKS(a, b, c, d) (a = b = c = d = 0)
+#define CC_EXTENSION
+#endif
+
+LeakTracker::LeakTracker()
+ : m_leaks(0), m_dubious(0), m_reachable(0), m_suppressed(0), m_errors(0)
+{
+}
+
+LeakTracker::~LeakTracker()
+{
+ printf("LeakTracker: leaked = %d, errors = %d\n", m_leaks, m_errors);
+}
+
+int LeakTracker::check_leaks()
+{
+ int leaked = 0;
+ int dubious = 0;
+ int reachable = 0;
+ int suppressed = 0;
+
+ VALGRIND_DO_LEAK_CHECK;
+ VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed);
+ printf("memleaks: sure:%d dubious:%d reachable:%d suppress:%d\n", leaked,
+ dubious, reachable, suppressed);
+ bool has_leaks = (m_leaks != leaked);
+
+ m_leaks = leaked;
+ m_dubious = dubious;
+ m_reachable = reachable;
+ m_suppressed = suppressed;
+
+ return has_leaks;
+}
+
+int LeakTracker::check_errors()
+{
+ int errors = (int)(CC_EXTENSION VALGRIND_COUNT_ERRORS);
+ bool has_new_errors = (m_errors != errors);
+ m_errors = errors;
+ return has_new_errors;
+}
diff --git a/exempi/tests/utils.h b/exempi/tests/utils.h
new file mode 100644
index 0000000..a26ccd2
--- /dev/null
+++ b/exempi/tests/utils.h
@@ -0,0 +1,69 @@
+/*
+ * exempi - utils.h
+ *
+ * Copyright (C) 2007,2010 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_UTILS_H__
+#define __TEST_UTILS_H__
+
+#include <string>
+
+#include <memory>
+
+extern std::string g_testfile;
+extern std::string g_src_testdir;
+
+void prepare_test(int argc, char* argv[], const char* filename);
+
+bool copy_file(const std::string& source, const std::string& dest);
+
+class LeakTracker {
+public:
+ LeakTracker();
+ ~LeakTracker();
+ /** return false if there is NO leak. Will print on stdout */
+ int check_leaks();
+ int check_errors();
+
+private:
+ int m_leaks;
+ int m_dubious;
+ int m_reachable;
+ int m_suppressed;
+ int m_errors;
+};
+
+extern std::unique_ptr<LeakTracker> g_lt;
+
+#endif
diff --git a/exempi/xmp++.hpp b/exempi/xmp++.hpp
new file mode 100644
index 0000000..15b7351
--- /dev/null
+++ b/exempi/xmp++.hpp
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright (C) 2011 Hubert Figuiere
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef __XMP_PLUSPLUS_H__
+#define __XMP_PLUSPLUS_H__
+
+#include <exempi/xmp.h>
+
+namespace xmp {
+
+inline void release(XmpIteratorPtr ptr)
+{
+ xmp_iterator_free(ptr);
+}
+
+inline void release(XmpStringPtr ptr)
+{
+ xmp_string_free(ptr);
+}
+
+inline void release(XmpFilePtr ptr)
+{
+ xmp_files_free(ptr);
+}
+
+inline void release(XmpPtr ptr)
+{
+ xmp_free(ptr);
+}
+
+/**
+ * @brief a scoped pointer for Xmp opaque types
+ */
+template <class T>
+class ScopedPtr {
+public:
+ ScopedPtr(T p) : _p(p) {}
+ ~ScopedPtr()
+ {
+ if (_p)
+ release(_p);
+ }
+ operator T() const { return _p; }
+
+private:
+ T _p;
+
+ // private copy constructor and assignment
+ // to make the class non copiable
+ ScopedPtr(const ScopedPtr<T> &);
+ ScopedPtr &operator=(const ScopedPtr<T> &);
+};
+}
+
+#endif
diff --git a/exempi/xmp.h b/exempi/xmp.h
new file mode 100644
index 0000000..c3cfea9
--- /dev/null
+++ b/exempi/xmp.h
@@ -0,0 +1,742 @@
+/*
+ * exempi - xmp.h
+ *
+ * Copyright (C) 2007-2016 Hubert Figuiere
+ * Copyright 2002-2007 Adobe Systems Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EXEMPI_XMP_H_
+#define __EXEMPI_XMP_H_
+
+#include <stdlib.h>
+/* stdbool choke on Sun (bug #14612) */
+#if !(defined(__sun) && defined(__cplusplus))
+#include <stdbool.h>
+#endif
+#include <stdint.h>
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* enums grafted from XMP_Const.h */
+
+/** Option bits for xmp_files_open() */
+typedef enum {
+ XMP_OPEN_NOOPTION = 0x00000000, /**< No open option */
+ XMP_OPEN_READ = 0x00000001, /**< Open for read-only access. */
+ XMP_OPEN_FORUPDATE = 0x00000002, /**< Open for reading and writing. */
+ XMP_OPEN_ONLYXMP = 0x00000004, /**< Only the XMP is wanted,
+ * allows space/time optimizations. */
+ XMP_OPEN_CACHETNAIL = 0x00000008, /**< Cache thumbnail if possible,
+ * GetThumbnail will be called. */
+ XMP_OPEN_STRICTLY = 0x00000010, /**< Be strict about locating XMP
+ * and reconciling with other forms. */
+ XMP_OPEN_USESMARTHANDLER = 0x00000020, /**< Require the use of a smart
+ * handler. */
+ XMP_OPEN_USEPACKETSCANNING = 0x00000040, /**< Force packet scanning,
+ * don't use a smart handler. */
+ XMP_OPEN_LIMITSCANNING = 0x00000080, /**< Only packet scan files "known"
+ * to need scanning. */
+ XMP_OPEN_REPAIR_FILE =
+ 0x00000100, /**< Attempt to repair a file opened for update,
+ * default is to not open (throw an exception). */
+ XMP_OPEN_OPTIMIZEFILELAYOUT =
+ 0x00000200, /**< Optimize MPEG4 to support stream when updating
+ * This can take some time */
+ XMP_OPEN_INBACKGROUND = 0x10000000 /**< Set if calling from background
+ * thread. */
+} XmpOpenFileOptions;
+
+/** Option bits for xmp_files_close() */
+typedef enum {
+ XMP_CLOSE_NOOPTION = 0x0000, /**< No close option */
+ XMP_CLOSE_SAFEUPDATE = 0x0001 /**< Write into a temporary file and
+ * swap for crash safety. */
+} XmpCloseFileOptions;
+
+typedef enum {
+
+ /* Public file formats. Hex used to avoid gcc warnings. */
+ /* ! Leave them as big endian. There seems to be no decent way on UNIX to
+ determine the target */
+ /* ! endianness at compile time. Forcing it on the client isn't acceptable.
+ */
+
+ XMP_FT_PDF = 0x50444620UL, /* 'PDF ' */
+ XMP_FT_PS = 0x50532020UL, /* 'PS ', general PostScript following DSC
+ conventions. */
+ XMP_FT_EPS = 0x45505320UL, /* 'EPS ', encapsulated PostScript. */
+
+ XMP_FT_JPEG = 0x4A504547UL, /* 'JPEG' */
+ XMP_FT_JPEG2K = 0x4A505820UL, /* 'JPX ', ISO 15444-1 */
+ XMP_FT_TIFF = 0x54494646UL, /* 'TIFF' */
+ XMP_FT_GIF = 0x47494620UL, /* 'GIF ' */
+ XMP_FT_PNG = 0x504E4720UL, /* 'PNG ' */
+ XMP_FT_WEBP = 0x57454250UL, /* 'WEBP' */
+
+ XMP_FT_SWF = 0x53574620UL, /* 'SWF ' */
+ XMP_FT_FLA = 0x464C4120UL, /* 'FLA ' */
+ XMP_FT_FLV = 0x464C5620UL, /* 'FLV ' */
+
+ XMP_FT_MOV = 0x4D4F5620UL, /* 'MOV ', Quicktime */
+ XMP_FT_AVI = 0x41564920UL, /* 'AVI ' */
+ XMP_FT_CIN = 0x43494E20UL, /* 'CIN ', Cineon */
+ XMP_FT_WAV = 0x57415620UL, /* 'WAV ' */
+ XMP_FT_MP3 = 0x4D503320UL, /* 'MP3 ' */
+ XMP_FT_SES = 0x53455320UL, /* 'SES ', Audition session */
+ XMP_FT_CEL = 0x43454C20UL, /* 'CEL ', Audition loop */
+ XMP_FT_MPEG = 0x4D504547UL, /* 'MPEG' */
+ XMP_FT_MPEG2 = 0x4D503220UL, /* 'MP2 ' */
+ XMP_FT_MPEG4 = 0x4D503420UL, /* 'MP4 ', ISO 14494-12 and -14 */
+ XMP_FT_WMAV = 0x574D4156UL, /* 'WMAV', Windows Media Audio and Video */
+ XMP_FT_AIFF = 0x41494646UL, /* 'AIFF' */
+
+ XMP_FT_HTML = 0x48544D4CUL, /* 'HTML' */
+ XMP_FT_XML = 0x584D4C20UL, /* 'XML ' */
+ XMP_FT_TEXT = 0x74657874UL, /* 'text' */
+
+ /* Adobe application file formats. */
+ XMP_FT_PHOTOSHOP = 0x50534420UL, /* 'PSD ' */
+ XMP_FT_ILLUSTRATOR = 0x41492020UL, /* 'AI ' */
+ XMP_FT_INDESIGN = 0x494E4444UL, /* 'INDD' */
+ XMP_FT_AEPROJECT = 0x41455020UL, /* 'AEP ' */
+ XMP_FT_AEPROJTEMPLATE =
+ 0x41455420UL, /* 'AET ', After Effects Project Template */
+ XMP_FT_AEFILTERPRESET = 0x46465820UL, /* 'FFX ' */
+ XMP_FT_ENCOREPROJECT = 0x4E434F52UL, /* 'NCOR' */
+ XMP_FT_PREMIEREPROJECT = 0x5052504AUL, /* 'PRPJ' */
+ XMP_FT_PREMIERETITLE = 0x5052544CUL, /* 'PRTL' */
+
+ /* Catch all. */
+ XMP_FT_UNKNOWN = 0x20202020UL /* ' ' */
+} XmpFileType;
+
+typedef enum {
+
+ XMP_FMT_CAN_INJECT_XMP = 0x00000001,
+ XMP_FMT_CAN_EXPAND = 0x00000002,
+ XMP_FMT_CAN_REWRITE = 0x00000004,
+ XMP_FMT_PREFERS_IN_PLACE = 0x00000008,
+ XMP_FMT_CAN_RECONCILE = 0x00000010,
+ XMP_FMT_ALLOWS_ONLY_XMP = 0x00000020,
+ XMP_FMT_RETURNS_RAW_PACKET = 0x00000040,
+ XMP_FMT_HANDLER_OWNS_FILE = 0x00000100,
+ XMP_FMT_ALLOW_SAFE_UPDATE = 0x00000200,
+ XMP_FMT_NEEDS_READONLY_PACKET = 0x00000400,
+ XMP_FMT_USE_SIDECAR_XMP = 0x00000800,
+ XMP_FMT_FOLDER_BASED_FORMAT = 0x00001000,
+
+ _XMP_FMT_LAST
+} XmpFileFormatOptions;
+
+typedef enum {
+ XMP_ITER_CLASSMASK = 0x00FFUL, /**< The low 8 bits are an enum of
+ * what data structure to iterate. */
+ XMP_ITER_PROPERTIES = 0x0000UL, /**< Iterate the property tree of
+ * a TXMPMeta object. */
+ XMP_ITER_ALIASES = 0x0001UL, /**< Iterate the global alias table. */
+ XMP_ITER_NAMESPACES = 0x0002UL, /**< Iterate the global namespace table. */
+ XMP_ITER_JUSTCHILDREN = 0x0100UL, /**< Just do the immediate children
+ * of the root, default is subtree. */
+ XMP_ITER_JUSTLEAFNODES = 0x0200UL, /**< Just do the leaf nodes, default
+ * is all nodes in the subtree. */
+ XMP_ITER_JUSTLEAFNAME = 0x0400UL, /**< Return just the leaf part of the
+ * path, default is the full path. */
+ XMP_ITER_INCLUDEALIASES = 0x0800UL, /**< Include aliases, default is just
+ * actual properties. */
+ XMP_ITER_OMITQUALIFIERS = 0x1000UL /* Omit all qualifiers. */
+} XmpIterOptions;
+
+typedef enum {
+ XMP_ITER_SKIPSUBTREE = 0x0001UL, /**< Skip the subtree below the
+ * current node. */
+ XMP_ITER_SKIPSIBLINGS =
+ 0x0002UL /**< Skip the subtree below and remaining
+ * siblings of the current
+ * node. */
+} XmpIterSkipOptions;
+
+typedef enum {
+ /** Options relating to the XML string form of the property value. */
+ XMP_PROP_VALUE_IS_URI = 0x00000002UL, /**< The value is a URI, use
+ * rdf:resource attribute.
+ * DISCOURAGED */
+ /** Options relating to qualifiers attached to a property. */
+ XMP_PROP_HAS_QUALIFIERS = 0x00000010UL, /**< The property has qualifiers,
+ * includes rdf:type and
+ * xml:lang. */
+ XMP_PROP_IS_QUALIFIER = 0x00000020UL, /**< This is a qualifier,
+ * includes rdf:type and
+ * xml:lang. */
+ XMP_PROP_HAS_LANG = 0x00000040UL, /**< Implies XMP_PropHasQualifiers,
+ * property has xml:lang. */
+ XMP_PROP_HAS_TYPE = 0x00000080UL, /**< Implies XMP_PropHasQualifiers,
+ * property has rdf:type. */
+
+ /* Options relating to the data structure form. */
+ XMP_PROP_VALUE_IS_STRUCT = 0x00000100UL, /**< The value is a structure
+ * with nested fields. */
+ XMP_PROP_VALUE_IS_ARRAY = 0x00000200UL, /**< The value is an array
+ * (RDF alt/bag/seq). */
+ XMP_PROP_ARRAY_IS_UNORDERED = XMP_PROP_VALUE_IS_ARRAY, /**< The item order
+ * does not matter.*/
+ XMP_PROP_ARRAY_IS_ORDERED = 0x00000400UL, /**< Implies XMP_PropValueIsArray,
+ * item order matters. */
+ XMP_PROP_ARRAY_IS_ALT = 0x00000800UL, /**< Implies XMP_PropArrayIsOrdered,
+ * items are alternates. */
+
+ /** Additional struct and array options. */
+ XMP_PROP_ARRAY_IS_ALTTEXT =
+ 0x00001000UL, /**< Implies kXMP_PropArrayIsAlternate,
+ * items are localized text. */
+ XMP_PROP_ARRAY_INSERT_BEFORE =
+ 0x00004000UL, /**< Used by array functions. */
+ XMP_PROP_ARRAY_INSERT_AFTER = 0x00008000UL, /**< Used by array functions. */
+
+ /* Other miscellaneous options. */
+ XMP_PROP_IS_ALIAS = 0x00010000UL, /**< This property is an alias name for
+ another property. */
+ XMP_PROP_HAS_ALIASES = 0x00020000UL, /**< This property is the base value
+ for a set of aliases. */
+ XMP_PROP_IS_INTERNAL = 0x00040000UL, /**< This property is an "internal"
+ property, owned by applications. */
+ XMP_PROP_IS_STABLE = 0x00100000UL, /**< This property is not derived from
+ * the document content.
+ */
+ XMP_PROP_IS_DERIVED = 0x00200000UL, /**< This property is derived from the
+ document content. */
+ /* kXMPUtil_AllowCommas = 0x10000000UL, ! Used by
+ TXMPUtils::CatenateArrayItems and ::SeparateArrayItems. */
+ /* kXMP_DeleteExisting = 0x20000000UL, ! Used by TXMPMeta::SetXyz
+ functions to delete any pre-existing property. */
+ /* kXMP_SchemaNode = 0x80000000UL, ! Returned by iterators - #define
+ to avoid warnings */
+
+ /* Masks that are multiple flags. */
+ XMP_PROP_ARRAY_FORM_MASK = XMP_PROP_VALUE_IS_ARRAY |
+ XMP_PROP_ARRAY_IS_ORDERED |
+ XMP_PROP_ARRAY_IS_ALT |
+ XMP_PROP_ARRAY_IS_ALTTEXT,
+ XMP_PROP_COMPOSITE_MASK = XMP_PROP_VALUE_IS_STRUCT |
+ XMP_PROP_ARRAY_FORM_MASK, /* Is it simple or
+ composite (array or
+ struct)? */
+ XMP_IMPL_RESERVED_MASK =
+ 0x70000000L /**< Reserved for transient use by the implementation. */
+} XmpPropsBits;
+
+/* convenience macros */
+
+/** set option bits */
+#define XMP_SET_OPTION(var, opt) var |= (opt)
+/** clear option bits */
+#define XMP_CLEAR_OPTION(var, opt) var &= ~(opt)
+/** test if option is set */
+#define XMP_TEST_OPTION_SET(var, opt) (((var) & (opt)) != 0)
+/** test if option is clear */
+#define XMP_TEST_OPTION_CLEAR(var, opt) (((var) & (opt)) == 0)
+
+#define XMP_IS_PROP_SIMPLE(opt) (((opt)&XMP_PROP_COMPOSITE_MASK) == 0)
+#define XMP_IS_PROP_STRUCT(opt) (((opt)&XMP_PROP_VALUE_IS_STRUCT) != 0)
+#define XMP_IS_PROP_ARRAY(opt) (((opt)&XMP_PROP_VALUE_IS_ARRAY) != 0)
+#define XMP_IS_ARRAY_UNORDERED(opt) (((opt)&XMP_PROP_ARRAY_IS_ORDERED) == 0)
+#define XMP_IS_ARRAY_ORDERED(opt) (((opt)&XMP_PROP_ARRAY_IS_ORDERED) != 0)
+#define XMP_IS_ARRAY_ALT(opt) (((opt)&XMP_PROP_ARRAY_IS_ALT) != 0)
+#define XMP_IS_ARRAY_ALTTEXT(opt) (((opt)&XMP_PROP_ARRAY_IS_ALTTEXT) != 0)
+
+#define XMP_HAS_PROP_QUALIFIERS(opt) (((opt)&XMP_PROP_HAS_QUALIFIERS) != 0)
+#define XMP_IS_PROP_QUALIFIER(opt) (((opt)&XMP_PROP_IS_QUALIFIER) != 0)
+#define XMP_HAS_PROP_LANG(opt) (((opt)&XMP_PROP_HAS_LANG) != 0)
+
+#define XMP_IS_NODE_SCHEMA(opt) (((opt)&XMP_SCHEMA_NODE) != 0)
+#define XMP_IS_PROP_ALIAS(opt) (((opt)&XMP_PROP_IS_ALIAS) != 0)
+
+enum { /* Options for xmp_serialize */
+ XMP_SERIAL_OMITPACKETWRAPPER = 0x0010UL, /**< Omit the XML packet
+ * wrapper. */
+ XMP_SERIAL_READONLYPACKET = 0x0020UL, /**< Default is a writeable
+ * packet. */
+ XMP_SERIAL_USECOMPACTFORMAT = 0x0040UL, /**< Use a compact form of
+ * RDF. */
+
+ XMP_SERIAL_INCLUDETHUMBNAILPAD =
+ 0x0100UL, /**< Include a padding allowance
+ * for a thumbnail image. */
+ XMP_SERIAL_EXACTPACKETLENGTH = 0x0200UL, /**< The padding parameter is
+ * the overall packet length. */
+ XMP_SERIAL_WRITEALIASCOMMENTS = 0x0400UL, /**< Show aliases as XML
+ * comments. */
+ XMP_SERIAL_OMITALLFORMATTING = 0x0800UL, /**< Omit all formatting
+ * whitespace. */
+
+ _XMP_LITTLEENDIAN_BIT =
+ 0x0001UL, /* ! Don't use directly, see the combined values below! */
+ _XMP_UTF16_BIT = 0x0002UL,
+ _XMP_UTF32_BIT = 0x0004UL,
+
+ XMP_SERIAL_ENCODINGMASK = 0x0007UL,
+ XMP_SERIAL_ENCODEUTF8 = 0UL,
+ XMP_SERIAL_ENCODEUTF16BIG = _XMP_UTF16_BIT,
+ XMP_SERIAL_ENCODEUTF16LITTLE = _XMP_UTF16_BIT | _XMP_LITTLEENDIAN_BIT,
+ XMP_SERIAL_ENCODEUTF32BIG = _XMP_UTF32_BIT,
+ XMP_SERIAL_ENCODEUTF32LITTLE = _XMP_UTF32_BIT | _XMP_LITTLEENDIAN_BIT
+};
+
+/** pointer to XMP packet. Opaque. */
+typedef struct _Xmp *XmpPtr;
+typedef struct _XmpFile *XmpFilePtr;
+typedef struct _XmpString *XmpStringPtr;
+typedef struct _XmpIterator *XmpIteratorPtr;
+
+typedef struct _XmpDateTime {
+ int32_t year;
+ int32_t month; /* 1..12 */
+ int32_t day; /* 1..31 */
+ int32_t hour; /* 0..23 */
+ int32_t minute; /* 0..59 */
+ int32_t second; /* 0..59 */
+ int32_t tzSign; /* -1..+1, 0 means UTC, -1 is west, +1 is east. */
+ int32_t tzHour; /* 0..23 */
+ int32_t tzMinute; /* 0..59 */
+ int32_t nanoSecond;
+} XmpDateTime;
+
+typedef struct _XmpPacketInfo {
+ /// Packet offset in the file in bytes, -1 if unknown.
+ int64_t offset;
+ /// Packet length in the file in bytes, -1 if unknown.
+ int32_t length;
+ /// Packet padding size in bytes, zero if unknown.
+ int32_t padSize;
+
+ /// Character format using the values \c kXMP_Char8Bit,
+ /// \c kXMP_Char16BitBig, etc.
+ uint8_t charForm;
+ /// True if there is a packet wrapper and the trailer says writeable
+ /// by dumb packet scanners.
+ bool writeable;
+ /// True if there is a packet wrapper, the "<?xpacket...>"
+ /// XML processing instructions.
+ bool hasWrapper;
+
+ /// Padding to make the struct's size be a multiple 4.
+ uint8_t pad;
+} XmpPacketInfo;
+
+/** Values used for tzSign field. */
+enum {
+ XMP_TZ_WEST = -1, /**< West of UTC */
+ XMP_TZ_UTC = 0, /**< UTC */
+ XMP_TZ_EAST = +1 /**< East of UTC */
+};
+
+/** Init the library. Must be called before anything else */
+bool xmp_init(void);
+void xmp_terminate(void);
+
+/** get the error code that last occurred.
+ * @todo make this thread-safe. Getting the error code
+ * from another thread than the on it occurred in is undefined.
+ */
+int xmp_get_error(void);
+
+XmpFilePtr xmp_files_new(void);
+XmpFilePtr xmp_files_open_new(const char *, XmpOpenFileOptions options);
+
+bool xmp_files_open(XmpFilePtr xf, const char *, XmpOpenFileOptions options);
+
+/** Close an XMP file. Will flush the changes
+ * @param xf the file object
+ * @param options the options to close.
+ * @return true on succes, false on error
+ * xmp_get_error() will give the error code.
+ */
+bool xmp_files_close(XmpFilePtr xf, XmpCloseFileOptions options);
+
+/** Get the XMP packet from the file
+ * @param xf the %XmpFilePtr to get the XMP packet from
+ * @return a newly allocated XmpPtr. Use %xmp_free to release it.
+ */
+XmpPtr xmp_files_get_new_xmp(XmpFilePtr xf);
+
+/** File the XMP packet from the file
+ * @param xf the %XmpFilePtr to get the XMP packet from
+ * @param xmp the XMP Packet to fill. Must be valid.
+ */
+bool xmp_files_get_xmp(XmpFilePtr xf, XmpPtr xmp);
+bool xmp_files_get_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet,
+ XmpPacketInfo* packet_info);
+
+bool xmp_files_can_put_xmp(XmpFilePtr xf, XmpPtr xmp);
+bool xmp_files_can_put_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet);
+bool xmp_files_can_put_xmp_cstr(XmpFilePtr xf, const char* xmp_packet,
+ size_t len);
+
+bool xmp_files_put_xmp(XmpFilePtr xf, XmpPtr xmp);
+bool xmp_files_put_xmp_xmpstring(XmpFilePtr xf, XmpStringPtr xmp_packet);
+bool xmp_files_put_xmp_cstr(XmpFilePtr xf, const char* xmp_packet, size_t len);
+
+/** Get the file info from the open file
+ * @param xf the file object
+ * @param[out] filePath the file path object to store the path in. Pass NULL if
+ * not needed.
+ * @param[out] options the options for open. Pass NULL if not needed.
+ * @param[out] file_format the detected file format. Pass NULL if not needed.
+ * @param[out] handler_flags the format options like from
+ * %xmp_files_get_format_info.
+ * @return false in case of error.
+ */
+bool xmp_files_get_file_info(XmpFilePtr xf, XmpStringPtr filePath,
+ XmpOpenFileOptions *options,
+ XmpFileType *file_format,
+ XmpFileFormatOptions *handler_flags);
+
+/** Free a XmpFilePtr
+ * @param xf the file ptr. Cannot be NULL
+ * @return false on error.
+ * Calll %xmp_get_error to retrieve the error code.
+ */
+bool xmp_files_free(XmpFilePtr xf);
+
+/** Get the format info
+ * @param format type identifier
+ * @param options the options for the file format handler
+ * @return false on error
+ */
+bool xmp_files_get_format_info(XmpFileType format,
+ XmpFileFormatOptions *options);
+
+/** Check the file format of a file. Use the same logic as in xmp_files_open()
+ * @param filePath the path to the file
+ * @return XMP_FT_UNKNOWN on error or if the file type is unknown
+ */
+XmpFileType xmp_files_check_file_format(const char *filePath);
+
+/** Register a new namespace to add properties to
+ * This is done automatically when reading the metadata block
+ * @param namespaceURI the namespace URI to register
+ * @param suggestedPrefix the suggested prefix
+ * @param registeredPrefix the really registered prefix. Not necessarily
+ * %suggestedPrefix.
+ * @return true if success, false otherwise.
+ */
+bool xmp_register_namespace(const char *namespaceURI,
+ const char *suggestedPrefix,
+ XmpStringPtr registeredPrefix);
+
+/** Check is a namespace is registered
+ * @param ns the namespace to check.
+ * @param prefix The prefix associated if registered. Pass NULL
+ * if not interested.
+ * @return true if registered.
+ * NEW in 2.1
+ */
+bool xmp_namespace_prefix(const char *ns, XmpStringPtr prefix);
+
+/** Check if a ns prefix is registered.
+ * @param prefix the prefix to check.
+ * @param ns the namespace associated if registered. Pass NULL
+ * if not interested.
+ * @return true if registered.
+ * NEW in 2.1
+ */
+bool xmp_prefix_namespace_uri(const char *prefix, XmpStringPtr ns);
+
+/** Create a new empty XMP packet
+ * @return the packet pointer. Must be free with xmp_free()
+ */
+XmpPtr xmp_new_empty(void);
+
+/** Create a new XMP packet
+ * @param buffer the buffer to load data from. UTF-8 encoded.
+ * @param len the buffer length in byte
+ * @return the packet pointer. Must be free with xmp_free()
+ */
+XmpPtr xmp_new(const char *buffer, size_t len);
+
+/** Create a new XMP packet from the one passed.
+ * @param xmp the instance to copy. Can be NULL.
+ * @return the packet pointer. NULL is failer (or NULL is passed).
+ */
+XmpPtr xmp_copy(XmpPtr xmp);
+
+/** Free the xmp packet
+ * @param xmp the xmp packet to free
+ */
+bool xmp_free(XmpPtr xmp);
+
+/** Parse the XML passed through the buffer and load it.
+ * @param xmp the XMP packet.
+ * @param buffer the buffer.
+ * @param len the length of the buffer.
+ */
+bool xmp_parse(XmpPtr xmp, const char *buffer, size_t len);
+
+/** Serialize the XMP Packet to the given buffer
+ * @param xmp the XMP Packet
+ * @param buffer the buffer to write the XMP to
+ * @param options options on how to write the XMP. See XMP_SERIAL_*
+ * @param padding number of bytes of padding, useful for modifying
+ * embedded XMP in place.
+ * @return TRUE if success.
+ */
+bool xmp_serialize(XmpPtr xmp, XmpStringPtr buffer, uint32_t options,
+ uint32_t padding);
+
+/** Serialize the XMP Packet to the given buffer with formatting
+ * @param xmp the XMP Packet
+ * @param buffer the buffer to write the XMP to
+ * @param options options on how to write the XMP. See XMP_SERIAL_*
+ * @param padding number of bytes of padding, useful for modifying
+ * embedded XMP in place.
+ * @param newline the new line character to use
+ * @param tab the indentation character to use
+ * @param indent the initial indentation level
+ * @return TRUE if success.
+ */
+bool xmp_serialize_and_format(XmpPtr xmp, XmpStringPtr buffer, uint32_t options,
+ uint32_t padding, const char *newline,
+ const char *tab, int32_t indent);
+
+/** Get an XMP property and it option bits from the XMP packet
+ * @param xmp the XMP packet
+ * @param schema
+ * @param name
+ * @param property the allocated XmpStringPtr
+ * @param propsBits pointer to the option bits. Pass NULL if not needed
+ * @return true if found
+ */
+bool xmp_get_property(XmpPtr xmp, const char *schema, const char *name,
+ XmpStringPtr property, uint32_t *propsBits);
+
+bool xmp_get_property_date(XmpPtr xmp, const char *schema, const char *name,
+ XmpDateTime *property, uint32_t *propsBits);
+bool xmp_get_property_float(XmpPtr xmp, const char *schema, const char *name,
+ double *property, uint32_t *propsBits);
+bool xmp_get_property_bool(XmpPtr xmp, const char *schema, const char *name,
+ bool *property, uint32_t *propsBits);
+bool xmp_get_property_int32(XmpPtr xmp, const char *schema, const char *name,
+ int32_t *property, uint32_t *propsBits);
+bool xmp_get_property_int64(XmpPtr xmp, const char *schema, const char *name,
+ int64_t *property, uint32_t *propsBits);
+
+/** Get an item frpm an array property
+ * @param xmp the xmp meta
+ * @param schema the schema
+ * @param name the property name
+ * @param index the index in the array
+ * @param property the property value
+ * @param propsBits the property bits. Pass NULL is unwanted.
+ * @return TRUE if success.
+ */
+bool xmp_get_array_item(XmpPtr xmp, const char *schema, const char *name,
+ int32_t index, XmpStringPtr property,
+ uint32_t *propsBits);
+
+/** Set an XMP property in the XMP packet
+ * @param xmp the XMP packet
+ * @param schema
+ * @param name
+ * @param value 0 terminated string
+ * @param optionBits
+ * @return false if failure
+ */
+bool xmp_set_property(XmpPtr xmp, const char *schema, const char *name,
+ const char *value, uint32_t optionBits);
+
+/** Set a date XMP property in the XMP packet
+ * @param xmp the XMP packet
+ * @param schema
+ * @param name
+ * @param value the date-time struct
+ * @param optionBits
+ * @return false if failure
+ */
+bool xmp_set_property_date(XmpPtr xmp, const char *schema, const char *name,
+ const XmpDateTime *value, uint32_t optionBits);
+
+/** Set a float XMP property in the XMP packet
+ * @param xmp the XMP packet
+ * @param schema
+ * @param name
+ * @param value the float value
+ * @param optionBits
+ * @return false if failure
+ */
+bool xmp_set_property_float(XmpPtr xmp, const char *schema, const char *name,
+ double value, uint32_t optionBits);
+bool xmp_set_property_bool(XmpPtr xmp, const char *schema, const char *name,
+ bool value, uint32_t optionBits);
+bool xmp_set_property_int32(XmpPtr xmp, const char *schema, const char *name,
+ int32_t value, uint32_t optionBits);
+bool xmp_set_property_int64(XmpPtr xmp, const char *schema, const char *name,
+ int64_t value, uint32_t optionBits);
+
+bool xmp_set_array_item(XmpPtr xmp, const char *schema, const char *name,
+ int32_t index, const char *value, uint32_t optionBits);
+
+/** Append a value to the XMP Property array in the XMP Packet provided
+ * @param xmp the XMP packet
+ * @param schema the schema of the property
+ * @param name the name of the property
+ * @param arrayOptions option bits of the parent array
+ * @param value null-terminated string
+ * @param optionBits option bits of the value itself.
+ */
+bool xmp_append_array_item(XmpPtr xmp, const char *schema, const char *name,
+ uint32_t arrayOptions, const char *value,
+ uint32_t optionBits);
+
+/** Delete a property from the XMP Packet provided
+ * @param xmp the XMP packet
+ * @param schema the schema of the property
+ * @param name the name of the property
+ */
+bool xmp_delete_property(XmpPtr xmp, const char *schema, const char *name);
+
+/** Determines if a property exists in the XMP Packet provided
+ * @param xmp the XMP packet
+ * @param schema the schema of the property. Can't be NULL or empty.
+ * @param name the name of the property. Can't be NULL or empty.
+ * @return true is the property exists
+ */
+bool xmp_has_property(XmpPtr xmp, const char *schema, const char *name);
+
+/** Get a localised text from a localisable property.
+ * @param xmp the XMP packet
+ * @param schema the schema
+ * @param name the property name.
+ * @param genericLang the generic language you may want as a fall back.
+ * Can be NULL or empty.
+ * @param specificLang the specific language you want. Can't be NULL or empty.
+ * @param actualLang the actual language of the value. Can be NULL if
+ * not wanted.
+ * @param itemValue the localized value. Can be NULL if not wanted.
+ * @param propBits the options flags describing the property. Can be NULL.
+ * @return true if found, false otherwise.
+ */
+bool xmp_get_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang, const char *specificLang,
+ XmpStringPtr actualLang, XmpStringPtr itemValue,
+ uint32_t *propBits);
+
+/** Set a localised text in a localisable property.
+ * @param xmp the XMP packet
+ * @param schema the schema
+ * @param name the property name.
+ * @param genericLang the generic language you may want to set too.
+ * Can be NULL or empty.
+ * @param specificLang the specific language you want. Can't be NULL or empty.
+ * @param value the localized value. Cannot be NULL.
+ * @param optionBits the options flags describing the property.
+ * @return true if set, false otherwise.
+ */
+bool xmp_set_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang, const char *specificLang,
+ const char *value, uint32_t optionBits);
+
+bool xmp_delete_localized_text(XmpPtr xmp, const char *schema, const char *name,
+ const char *genericLang,
+ const char *specificLang);
+
+/** Instanciate a new string
+ * @return the new instance. Must be freed with
+ * xmp_string_free()
+ */
+XmpStringPtr xmp_string_new(void);
+
+/** Free a XmpStringPtr
+ * @param s the string to free
+ */
+void xmp_string_free(XmpStringPtr s);
+
+/** Get the C string from the XmpStringPtr
+ * @param s the string object
+ * @return the const char * for the XmpStringPtr. It
+ * belong to the object.
+ */
+const char * xmp_string_cstr(XmpStringPtr s);
+
+/** Get the string length from the XmpStringPtr
+ * @param s the string object
+ * @return the string length. The unerlying implementation has it.
+ */
+size_t xmp_string_len(XmpStringPtr s);
+
+/** Create a new iterator.
+ * @param xmp the packet
+ * @param schema the property schema
+ * @param propName the property name
+ * @param options
+ * @return an iterator must be freed with % xmp_iterator_free
+ */
+XmpIteratorPtr xmp_iterator_new(XmpPtr xmp, const char *schema,
+ const char *propName, XmpIterOptions options);
+
+/** Free an iterator.
+ * @param iter the iterator to free.
+ */
+bool xmp_iterator_free(XmpIteratorPtr iter);
+
+/** Iterate to the next value
+ * @param iter the iterator
+ * @param schema the schema name. Pass NULL if not wanted
+ * @param propName the property path. Pass NULL if not wanted
+ * @param propValue the value of the property. Pass NULL if not wanted.
+ * @param options the options for the property. Pass NULL if not wanted.
+ * @return true if still something, false if none
+ */
+bool xmp_iterator_next(XmpIteratorPtr iter, XmpStringPtr schema,
+ XmpStringPtr propName, XmpStringPtr propValue,
+ uint32_t *options);
+
+/**
+ */
+bool xmp_iterator_skip(XmpIteratorPtr iter, XmpIterSkipOptions options);
+
+/** Compare two XmpDateTime
+ * @param left value
+ * @param right value
+ * @return if left < right, return < 0. If left > right, return > 0.
+ * if left == right, return 0.
+ */
+int xmp_datetime_compare(XmpDateTime *left, XmpDateTime *right);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/exempi/xmpconsts.h b/exempi/xmpconsts.h
new file mode 100644
index 0000000..c985d42
--- /dev/null
+++ b/exempi/xmpconsts.h
@@ -0,0 +1,69 @@
+/*
+ * exempi - xmpconsts.h
+ *
+ * Copyright (C) 2007 Hubert Figuiere
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _EXEMPI_XMP_CONSTS_H_
+#define _EXEMPI_XMP_CONSTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char NS_XMP_META[];
+extern const char NS_RDF[];
+extern const char NS_EXIF[];
+extern const char NS_TIFF[];
+extern const char NS_XAP[];
+extern const char NS_XAP_RIGHTS[];
+extern const char NS_DC[];
+extern const char NS_EXIF_AUX[];
+extern const char NS_CRS[];
+extern const char NS_LIGHTROOM[];
+extern const char NS_PHOTOSHOP[];
+extern const char NS_CAMERA_RAW_SETTINGS[];
+extern const char NS_CAMERA_RAW_SAVED_SETTINGS[];
+extern const char NS_IPTC4XMP[];
+extern const char NS_TPG[];
+extern const char NS_DIMENSIONS_TYPE[];
+/** Creative Commons namespace */
+extern const char NS_CC[];
+/* Added in Exempi 2.1 */
+extern const char NS_PDF[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/exempi/xmperrors.h b/exempi/xmperrors.h
new file mode 100644
index 0000000..438294e
--- /dev/null
+++ b/exempi/xmperrors.h
@@ -0,0 +1,86 @@
+/*
+ * exempi - xmperror.h
+ *
+ * Copyright (C) 2007 Hubert Figuiere
+ * Copyright 2002-2007 Adobe Systems Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1 Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2 Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3 Neither the name of the Authors, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software wit hout specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EXEMPI_XMPERROR_H_
+#define __EXEMPI_XMPERROR_H_
+
+enum {
+ /* More or less generic error codes. */
+ XMPErr_Unknown = 0,
+ XMPErr_TBD = -1,
+ XMPErr_Unavailable = -2,
+ XMPErr_BadObject = -3,
+ XMPErr_BadParam = -4,
+ XMPErr_BadValue = -5,
+ XMPErr_AssertFailure = -6,
+ XMPErr_EnforceFailure = -7,
+ XMPErr_Unimplemented = -8,
+ XMPErr_InternalFailure = -9,
+ XMPErr_Deprecated = -10,
+ XMPErr_ExternalFailure = -11,
+ XMPErr_UserAbort = -12,
+ XMPErr_StdException = -13,
+ XMPErr_UnknownException = -14,
+ XMPErr_NoMemory = -15,
+
+ /* More specific parameter error codes. */
+ XMPErr_BadSchema = -101,
+ XMPErr_BadXPath = -102,
+ XMPErr_BadOptions = -103,
+ XMPErr_BadIndex = -104,
+ XMPErr_BadIterPosition = -105,
+ XMPErr_BadParse = -106,
+ XMPErr_BadSerialize = -107,
+ XMPErr_BadFileFormat = -108,
+ XMPErr_NoFileHandler = -109,
+ XMPErr_TooLargeForJPEG = -110,
+
+ /* File format and internal structure error codes. */
+ XMPErr_BadXML = -201,
+ XMPErr_BadRDF = -202,
+ XMPErr_BadXMP = -203,
+ XMPErr_EmptyIterator = -204,
+ XMPErr_BadUnicode = -205,
+ XMPErr_BadTIFF = -206,
+ XMPErr_BadJPEG = -207,
+ XMPErr_BadPSD = -208,
+ XMPErr_BadPSIR = -209,
+ XMPErr_BadIPTC = -210,
+ XMPErr_BadMPEG = -211
+};
+
+#endif
diff --git a/m4/ax_cflags_gcc_option.m4 b/m4/ax_cflags_gcc_option.m4
new file mode 100644
index 0000000..9a4d62a
--- /dev/null
+++ b/m4/ax_cflags_gcc_option.m4
@@ -0,0 +1,230 @@
+##### http://autoconf-archive.cryp.to/ax_cflags_gcc_option.html
+#
+# SYNOPSIS
+#
+# AX_CFLAGS_GCC_OPTION (optionflag [,[shellvar][,[A][,[NA]]])
+#
+# DESCRIPTION
+#
+# AX_CFLAGS_GCC_OPTION(-fvomit-frame) would show a message as like
+# "checking CFLAGS for gcc -fvomit-frame ... yes" and adds the
+# optionflag to CFLAGS if it is understood. You can override the
+# shellvar-default of CFLAGS of course. The order of arguments stems
+# from the explicit macros like AX_CFLAGS_WARN_ALL.
+#
+# The cousin AX_CXXFLAGS_GCC_OPTION would check for an option to add
+# to CXXFLAGS - and it uses the autoconf setup for C++ instead of C
+# (since it is possible to use different compilers for C and C++).
+#
+# The macro is a lot simpler than any special AX_CFLAGS_* macro (or
+# ac_cxx_rtti.m4 macro) but allows to check for arbitrary options.
+# However, if you use this macro in a few places, it would be great
+# if you would make up a new function-macro and submit it to the
+# ac-archive.
+#
+# - $1 option-to-check-for : required ("-option" as non-value)
+# - $2 shell-variable-to-add-to : CFLAGS (or CXXFLAGS in the other case)
+# - $3 action-if-found : add value to shellvariable
+# - $4 action-if-not-found : nothing
+#
+# note: in earlier versions, $1-$2 were swapped. We try to detect the
+# situation and accept a $2=~/-/ as being the old
+# option-to-check-for.
+#
+# also: there are other variants that emerged from the original macro
+# variant which did just test an option to be possibly added.
+# However, some compilers accept an option silently, or possibly for
+# just another option that was not intended. Therefore, we have to do
+# a generic test for a compiler family. For gcc we check "-pedantic"
+# being accepted which is also understood by compilers who just want
+# to be compatible with gcc even when not being made from gcc
+# sources.
+#
+# see also:
+#
+# AX_CFLAGS_SUN_OPTION AX_CFLAGS_HPUX_OPTION
+# AX_CFLAGS_AIX_OPTION AX_CFLAGS_IRIX_OPTION
+#
+# LAST MODIFICATION
+#
+# 2006-12-12
+#
+# COPYLEFT
+#
+# Copyright (c) 2006 Guido U. Draheim <guidod@gmx.de>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# As a special exception, the respective Autoconf Macro's copyright
+# owner gives unlimited permission to copy, distribute and modify the
+# configure scripts that are the output of Autoconf when processing
+# the Macro. You need not follow the terms of the GNU General Public
+# License when using or distributing such scripts, even though
+# portions of the text of the Macro appear in them. The GNU General
+# Public License (GPL) does govern all other use of the material that
+# constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the
+# Autoconf Macro released by the Autoconf Macro Archive. When you
+# make and distribute a modified version of the Autoconf Macro, you
+# may extend this special exception to the GPL to apply to your
+# modified version as well.
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION_OLD], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$2])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC
+ "-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_OLD], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$2])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC
+ "-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl -------------------------------------------------------------------------
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION_NEW], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$1])dnl
+AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC
+ "-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
+ m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_NEW], [dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$1])dnl
+AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC
+ "-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
+ m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+AC_DEFUN([AX_CFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
+[AX_CFLAGS_GCC_OPTION_NEW($@)],[AX_CFLAGS_GCC_OPTION_OLD($@)])])
+
+AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
+[AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])])
diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..af37acd
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,133 @@
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the C++11
+# standard; if necessary, add switches to CXXFLAGS to enable support.
+#
+# The first argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for an extended mode.
+#
+# The second argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline C++11 support is required and that the macro
+# should error out if no mode with that support is found. If specified
+# 'optional', then configuration proceeds regardless, after defining
+# HAVE_CXX11 if and only if a supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 3
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ typedef check<check<bool>> right_angle_brackets;
+
+ int a;
+ decltype(a) b;
+
+ typedef check<int> check_type;
+ check_type c;
+ check_type&& cr = static_cast<check_type&&>(c);
+
+ auto d = a;
+])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+ m4_if([$1], [], [],
+ [$1], [ext], [],
+ [$1], [noext], [],
+ [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
+ m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
+ [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
+ [$2], [optional], [ax_cxx_compile_cxx11_required=false],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+ AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+ ax_cv_cxx_compile_cxx11,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [ax_cv_cxx_compile_cxx11=yes],
+ [ax_cv_cxx_compile_cxx11=no])])
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+ m4_if([$1], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=gnu++11 -std=gnu++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$1], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+ if test x$ax_cxx_compile_cxx11_required = xtrue; then
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+ fi
+ else
+ if test x$ac_success = xno; then
+ HAVE_CXX11=0
+ AC_MSG_NOTICE([No compiler with C++11 support was found])
+ else
+ HAVE_CXX11=1
+ AC_DEFINE(HAVE_CXX11,1,
+ [define if the compiler supports basic C++11 syntax])
+ fi
+
+ AC_SUBST(HAVE_CXX11)
+ fi
+])
diff --git a/m4/ax_ld_check_flag.m4 b/m4/ax_ld_check_flag.m4
new file mode 100644
index 0000000..2339657
--- /dev/null
+++ b/m4/ax_ld_check_flag.m4
@@ -0,0 +1,96 @@
+# ===========================================================================
+# http://autoconf-archive.cryp.to/ax_ld_check_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_LD_CHECK_FLAG(FLAG-TO-CHECK,[PROLOGUE],[BODY],[ACTION-IF-SUCCESS],[ACTION-IF-FAILURE])
+#
+# DESCRIPTION
+#
+# This macro tests if the C++ compiler supports the flag FLAG-TO-CHECK. If
+# successfull execute ACTION-IF-SUCCESS otherwise ACTION-IF-FAILURE.
+# PROLOGUE and BODY are optional and should be used as in AC_LANG_PROGRAM
+# macro.
+#
+# Example:
+#
+# AX_LD_CHECK_FLAG([-Wl,-L/usr/lib],[],[],[
+# ...
+# ],[
+# ...
+# ])
+#
+# This code is inspired from KDE_CHECK_COMPILER_FLAG macro. Thanks to
+# Bogdan Drozdowski <bogdandr@op.pl> for testing and bug fixes.
+#
+# LAST MODIFICATION
+#
+# 2008-04-12
+#
+# COPYLEFT
+#
+# Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program 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 General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Macro Archive. When you make and
+# distribute a modified version of the Autoconf Macro, you may extend this
+# special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_LD_CHECK_FLAG],[
+ AC_PREREQ([2.61])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_SED])
+
+ flag=`echo "$1" | $SED 'y% .=/+-(){}<>:*,%_______________%'`
+
+ AC_CACHE_CHECK([whether the linker accepts the $1 flag],
+ [ax_cv_ld_check_flag_$flag],[
+
+ #AC_LANG_PUSH([C])
+
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $1"
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([$2],[$3])
+ ],[
+ eval "ax_cv_ld_check_flag_$flag=yes"
+ ],[
+ eval "ax_cv_ld_check_flag_$flag=no"
+ ])
+
+ LDFLAGS="$save_LDFLAGS"
+
+ #AC_LANG_POP
+
+ ])
+
+ AS_IF([eval "test \"`echo '$ax_cv_ld_check_flag_'$flag`\" = yes"],[
+ :
+ $4
+ ],[
+ :
+ $5
+ ])
+])
diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4
new file mode 100644
index 0000000..41620a7
--- /dev/null
+++ b/m4/ax_tls.m4
@@ -0,0 +1,78 @@
+# ===========================================================================
+# http://autoconf-archive.cryp.to/ax_tls.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_TLS
+#
+# DESCRIPTION
+#
+# Provides a test for the compiler support of thread local storage (TLS)
+# extensions. Defines TLS if it is found. Currently only knows about GCC
+# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
+# supports either.
+#
+# LAST MODIFICATION
+#
+# 2008-04-12
+#
+# COPYLEFT
+#
+# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program 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 General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Macro Archive. When you make and
+# distribute a modified version of the Autoconf Macro, you may extend this
+# special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_TLS], [
+ AC_MSG_CHECKING(for thread local storage (TLS) class)
+ AC_CACHE_VAL(ac_cv_tls, [
+ ax_tls_keywords="__thread __declspec(thread) none"
+ for ax_tls_keyword in $ax_tls_keywords; do
+ case $ax_tls_keyword in
+ none) ac_cv_tls=none ; break ;;
+ *)
+ AC_TRY_COMPILE(
+ [#include <stdlib.h>
+ static void
+ foo(void) {
+ static ] $ax_tls_keyword [ int bar;
+ exit(1);
+ }],
+ [],
+ [ac_cv_tls=$ax_tls_keyword ; break],
+ ac_cv_tls=none
+ )
+ esac
+ done
+])
+
+ if test "$ac_cv_tls" != "none"; then
+ dnl AC_DEFINE([TLS], [], [If the compiler supports a TLS storage class define it to that here])
+ AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here])
+ fi
+ AC_MSG_RESULT($ac_cv_tls)
+])
diff --git a/m4/boost.m4 b/m4/boost.m4
new file mode 100644
index 0000000..27d063f
--- /dev/null
+++ b/m4/boost.m4
@@ -0,0 +1,1560 @@
+# boost.m4: Locate Boost headers and libraries for autoconf-based projects.
+# Copyright (C) 2007-2011, 2014 Benoit Sigoure <tsuna@lrde.epita.fr>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Additional permission under section 7 of the GNU General Public
+# License, version 3 ("GPLv3"):
+#
+# If you convey this file as part of a work that contains a
+# configuration script generated by Autoconf, you may do so under
+# terms of your choice.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+m4_define([_BOOST_SERIAL], [m4_translit([
+# serial 25
+], [#
+], [])])
+
+# Original sources can be found at http://github.com/tsuna/boost.m4
+# You can fetch the latest version of the script by doing:
+# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4
+
+# ------ #
+# README #
+# ------ #
+
+# This file provides several macros to use the various Boost libraries.
+# The first macro is BOOST_REQUIRE. It will simply check if it's possible to
+# find the Boost headers of a given (optional) minimum version and it will
+# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to
+# your configure so that users can specify non standard locations.
+# If the user's environment contains BOOST_ROOT and --with-boost was not
+# specified, --with-boost=$BOOST_ROOT is implicitly used.
+# For more README and documentation, go to http://github.com/tsuna/boost.m4
+# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry,
+# simply read the README, it will show you what to do step by step.
+
+m4_pattern_forbid([^_?(BOOST|Boost)_])
+
+
+# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------
+# Same as AC_EGREP_CPP, but leave the result in conftest.i.
+#
+# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded
+# in double-quotes, so escape your double quotes.
+#
+# It could be useful to turn this into a macro which extracts the
+# value of any macro.
+m4_define([_BOOST_SED_CPP],
+[AC_LANG_PUSH([C++])dnl
+AC_LANG_PREPROC_REQUIRE()dnl
+AC_REQUIRE([AC_PROG_SED])dnl
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])])
+AS_IF([dnl eval is necessary to expand ac_cpp.
+dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell.
+dnl Beware of Windows end-of-lines, for instance if we are running
+dnl some Windows programs under Wine. In that case, boost/version.hpp
+dnl is certainly using "\r\n", but the regular Unix shell will only
+dnl strip `\n' with backquotes, not the `\r'. This results in
+dnl boost_cv_lib_version='1_37\r' for instance, which breaks
+dnl everything else.
+dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK
+dnl
+dnl Beware that GCC 5, when expanding macros, may embed # line directives
+dnl a within single line:
+dnl
+dnl # 1 "conftest.cc"
+dnl # 1 "<built-in>"
+dnl # 1 "<command-line>"
+dnl # 1 "conftest.cc"
+dnl # 1 "/opt/local/include/boost/version.hpp" 1 3
+dnl # 2 "conftest.cc" 2
+dnl boost-lib-version =
+dnl # 2 "conftest.cc" 3
+dnl "1_56"
+dnl
+dnl So get rid of the # lines, and glue the remaining ones together.
+(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
+ grep -v '#' |
+ tr -d '\r' |
+ tr -s '\n' ' ' |
+ $SED -n -e "$1" >conftest.i 2>&1],
+ [$3],
+ [$4])
+rm -rf conftest*
+AC_LANG_POP([C++])dnl
+])# _BOOST_SED_CPP
+
+
+
+# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------
+# Look for Boost. If version is given, it must either be a literal of the form
+# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a
+# variable "$var".
+# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with
+# the required version, it does not check for any of the Boost libraries.
+# On # success, defines HAVE_BOOST. On failure, calls the optional
+# ACTION-IF-NOT-FOUND action if one was supplied.
+# Otherwise aborts with an error message.
+AC_DEFUN_ONCE([BOOST_REQUIRE],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_PROG_GREP])dnl
+echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD
+boost_save_IFS=$IFS
+boost_version_req=$1
+IFS=.
+set x $boost_version_req 0 0 0
+IFS=$boost_save_IFS
+shift
+boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"`
+boost_version_req_string=$[1].$[2].$[3]
+AC_ARG_WITH([boost],
+ [AS_HELP_STRING([--with-boost=DIR],
+ [prefix of Boost $1 @<:@guess@:>@])])dnl
+AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl
+# If BOOST_ROOT is set and the user has not provided a value to
+# --with-boost, then treat BOOST_ROOT as if it the user supplied it.
+if test x"$BOOST_ROOT" != x; then
+ if test x"$with_boost" = x; then
+ AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT])
+ with_boost=$BOOST_ROOT
+ else
+ AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost])
+ fi
+fi
+AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],
+ ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl
+boost_save_CPPFLAGS=$CPPFLAGS
+ AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string],
+ [boost_cv_inc_path],
+ [boost_cv_inc_path=no
+AC_LANG_PUSH([C++])dnl
+m4_pattern_allow([^BOOST_VERSION$])dnl
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include <boost/version.hpp>
+#if !defined BOOST_VERSION
+# error BOOST_VERSION is not defined
+#elif BOOST_VERSION < $boost_version_req
+# error Boost headers version < $boost_version_req
+#endif
+]])])
+ # If the user provided a value to --with-boost, use it and only it.
+ case $with_boost in #(
+ ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \
+ /usr/include C:/Boost/include;; #(
+ *) set x "$with_boost/include" "$with_boost";;
+ esac
+ shift
+ for boost_dir
+ do
+ # Without --layout=system, Boost (or at least some versions) installs
+ # itself in <prefix>/include/boost-<version>. This inner loop helps to
+ # find headers in such directories.
+ #
+ # Any ${boost_dir}/boost-x_xx directories are searched in reverse version
+ # order followed by ${boost_dir}. The final '.' is a sentinel for
+ # searching $boost_dir" itself. Entries are whitespace separated.
+ #
+ # I didn't indent this loop on purpose (to avoid over-indented code)
+ boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \
+ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \
+ && echo .`
+ for boost_inc in $boost_layout_system_search_list
+ do
+ if test x"$boost_inc" != x.; then
+ boost_inc="$boost_dir/$boost_inc"
+ else
+ boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list
+ fi
+ if test x"$boost_inc" != x; then
+ # We are going to check whether the version of Boost installed
+ # in $boost_inc is usable by running a compilation that
+ # #includes it. But if we pass a -I/some/path in which Boost
+ # is not installed, the compiler will just skip this -I and
+ # use other locations (either from CPPFLAGS, or from its list
+ # of system include directories). As a result we would use
+ # header installed on the machine instead of the /some/path
+ # specified by the user. So in that precise case (trying
+ # $boost_inc), make sure the version.hpp exists.
+ #
+ # Use test -e as there can be symlinks.
+ test -e "$boost_inc/boost/version.hpp" || continue
+ CPPFLAGS="$CPPFLAGS -I$boost_inc"
+ fi
+ AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no])
+ if test x"$boost_cv_inc_path" = xyes; then
+ if test x"$boost_inc" != x; then
+ boost_cv_inc_path=$boost_inc
+ fi
+ break 2
+ fi
+ done
+ done
+AC_LANG_POP([C++])dnl
+ ])
+ case $boost_cv_inc_path in #(
+ no)
+ boost_errmsg="cannot find Boost headers version >= $boost_version_req_string"
+ m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])],
+ [AC_MSG_NOTICE([$boost_errmsg])])
+ $2
+ ;;#(
+ yes)
+ BOOST_CPPFLAGS=
+ ;;#(
+ *)
+ AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl
+ ;;
+ esac
+ if test x"$boost_cv_inc_path" != xno; then
+ AC_DEFINE([HAVE_BOOST], [1],
+ [Defined if the requested minimum BOOST version is satisfied])
+ AC_CACHE_CHECK([for Boost's header version],
+ [boost_cv_lib_version],
+ [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl
+ _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]],
+ [#include <boost/version.hpp>
+boost-lib-version = BOOST_LIB_VERSION],
+ [boost_cv_lib_version=`cat conftest.i`])])
+ # e.g. "134" for 1_34_1 or "135" for 1_35
+ boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'`
+ case $boost_major_version in #(
+ '' | *[[!0-9]]*)
+ AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version'])
+ ;;
+ esac
+fi
+CPPFLAGS=$boost_save_CPPFLAGS
+])# BOOST_REQUIRE
+
+
+# BOOST_STATIC()
+# --------------
+# Add the "--enable-static-boost" configure argument. If this argument is given
+# on the command line, static versions of the libraries will be looked up.
+AC_DEFUN([BOOST_STATIC],
+ [AC_ARG_ENABLE([static-boost],
+ [AS_HELP_STRING([--enable-static-boost],
+ [Prefer the static boost libraries over the shared ones [no]])],
+ [enable_static_boost=yes],
+ [enable_static_boost=no])])# BOOST_STATIC
+
+
+# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND])
+# --------------------------------------------------------------------------
+# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for
+# some parts of the Boost library which are only made of headers and don't
+# require linking (such as Boost.Foreach).
+#
+# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be
+# found in the first place, in which case by default a notice is issued to the
+# user. Presumably if we haven't died already it's because it's OK to not have
+# Boost, which is why only a notice is issued instead of a hard error.
+#
+# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_<HEADER-NAME> in
+# case of success # (where HEADER-NAME is written LIKE_THIS, e.g.,
+# HAVE_BOOST_FOREACH_HPP).
+AC_DEFUN([BOOST_FIND_HEADER],
+[AC_REQUIRE([BOOST_REQUIRE])dnl
+if test x"$boost_cv_inc_path" = xno; then
+ m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])])
+else
+AC_LANG_PUSH([C++])dnl
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_CHECK_HEADER([$1],
+ [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1],
+ [Define to 1 if you have <$1>])])],
+ [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])])
+CPPFLAGS=$boost_save_CPPFLAGS
+AC_LANG_POP([C++])dnl
+fi
+])# BOOST_FIND_HEADER
+
+
+# BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Look for the Boost library COMPONENT-NAME (e.g., `thread', for
+# libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g.,
+# "thread_win32 thread"). Check that HEADER-NAME works and check that
+# libboost_LIB-NAME can link with the code CXX-TEST. The optional
+# argument CXX-PROLOGUE can be used to include some C++ code before
+# the `main' function.
+#
+# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above).
+#
+# Boost libraries typically come compiled with several flavors (with different
+# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one
+# or more of the following letters: sgdpn (in that order). s = static
+# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build,
+# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n'
+# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can
+# start with `mt-' to indicate that there is a preference for multi-thread
+# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp
+# ... If you want to make sure you have a specific version of Boost
+# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro.
+AC_DEFUN([BOOST_FIND_LIBS],
+[AC_REQUIRE([BOOST_REQUIRE])dnl
+AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl
+AC_REQUIRE([BOOST_STATIC])dnl
+AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl
+if test x"$boost_cv_inc_path" = xno; then
+ AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library])
+else
+dnl The else branch is huge and wasn't intended on purpose.
+AC_LANG_PUSH([C++])dnl
+AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl
+AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl
+AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl
+AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl
+BOOST_FIND_HEADER([$4])
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib],
+ [_BOOST_FIND_LIBS($@)])
+case $Boost_lib in #(
+ (no) _AC_MSG_LOG_CONFTEST
+ AC_MSG_ERROR([cannot find the flags to link with Boost $1])
+ ;;
+esac
+AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl
+AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl
+AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl
+AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl
+CPPFLAGS=$boost_save_CPPFLAGS
+AS_VAR_POPDEF([Boost_lib])dnl
+AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl
+AS_VAR_POPDEF([Boost_lib_LDPATH])dnl
+AS_VAR_POPDEF([Boost_lib_LIBS])dnl
+AC_LANG_POP([C++])dnl
+fi
+])
+
+
+# BOOST_FIND_LIB([LIB-NAME],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Backward compatibility wrapper for BOOST_FIND_LIBS.
+AC_DEFUN([BOOST_FIND_LIB],
+[BOOST_FIND_LIBS([$1], $@)])
+
+
+# _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES],
+# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# --------------------------------------------------------------
+# Real implementation of BOOST_FIND_LIBS: rely on these local macros:
+# Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS
+#
+# The algorithm is as follows: first look for a given library name
+# according to the user's PREFERRED-RT-OPT. For each library name, we
+# prefer to use the ones that carry the tag (toolset name). Each
+# library is searched through the various standard paths were Boost is
+# usually installed. If we can't find the standard variants, we try
+# to enforce -mt (for instance on MacOSX, libboost_thread.dylib
+# doesn't exist but there's -obviously- libboost_thread-mt.dylib).
+AC_DEFUN([_BOOST_FIND_LIBS],
+[Boost_lib=no
+ case "$3" in #(
+ (mt | mt-) boost_mt=-mt; boost_rtopt=;; #(
+ (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #(
+ (*) boost_mt=; boost_rtopt=$3;;
+ esac
+ if test $enable_static_boost = yes; then
+ boost_rtopt="s$boost_rtopt"
+ fi
+ # Find the proper debug variant depending on what we've been asked to find.
+ case $boost_rtopt in #(
+ (*d*) boost_rt_d=$boost_rtopt;; #(
+ (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn')
+ boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #(
+ (*) boost_rt_d='-d';;
+ esac
+ # If the PREFERRED-RT-OPT are not empty, prepend a `-'.
+ test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt"
+ $boost_guess_use_mt && boost_mt=-mt
+ # Look for the abs path the static archive.
+ # $libext is computed by Libtool but let's make sure it's non empty.
+ test -z "$libext" &&
+ AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?])
+ boost_save_ac_objext=$ac_objext
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4>
+$6], [$5])])
+dnl Optimization hacks: compiling C++ is slow, especially with Boost. What
+dnl we're trying to do here is guess the right combination of link flags
+dnl (LIBS / LDFLAGS) to use a given library. This can take several
+dnl iterations before it succeeds and is thus *very* slow. So what we do
+dnl instead is that we compile the code first (and thus get an object file,
+dnl typically conftest.o). Then we try various combinations of link flags
+dnl until we succeed to link conftest.o in an executable. The problem is
+dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always
+dnl remove all the temporary files including conftest.o. So the trick here
+dnl is to temporarily change the value of ac_objext so that conftest.o is
+dnl preserved accross tests. This is obviously fragile and I will burn in
+dnl hell for not respecting Autoconf's documented interfaces, but in the
+dnl mean time, it optimizes the macro by a factor of 5 to 30.
+dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left
+dnl empty because the test file is generated only once above (before we
+dnl start the for loops).
+ AC_COMPILE_IFELSE([],
+ [ac_objext=do_not_rm_me_plz],
+ [AC_MSG_ERROR([cannot compile a test that uses Boost $1])])
+ ac_objext=$boost_save_ac_objext
+ boost_failed_libs=
+# Don't bother to ident the following nested for loops, only the 2
+# innermost ones matter.
+for boost_lib_ in $2; do
+for boost_tag_ in -$boost_cv_lib_tag ''; do
+for boost_ver_ in -$boost_cv_lib_version ''; do
+for boost_mt_ in $boost_mt -mt ''; do
+for boost_rtopt_ in $boost_rtopt '' -d; do
+ for boost_lib in \
+ boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \
+ boost_$boost_lib_$boost_tag_$boost_ver_
+ do
+ # Avoid testing twice the same lib
+ case $boost_failed_libs in #(
+ (*@$boost_lib@*) continue;;
+ esac
+ # If with_boost is empty, we'll search in /lib first, which is not quite
+ # right so instead we'll try to a location based on where the headers are.
+ boost_tmp_lib=$with_boost
+ test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include}
+ for boost_ldpath in "$boost_tmp_lib/lib" '' \
+ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \
+ "$with_boost" C:/Boost/lib /lib*
+ do
+ # Don't waste time with directories that don't exist.
+ if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then
+ continue
+ fi
+ boost_save_LDFLAGS=$LDFLAGS
+ # Are we looking for a static library?
+ case $boost_ldpath:$boost_rtopt_ in #(
+ (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt)
+ Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext"
+ test -e "$Boost_lib_LIBS" || continue;; #(
+ (*) # No: use -lboost_foo to find the shared library.
+ Boost_lib_LIBS="-l$boost_lib";;
+ esac
+ boost_save_LIBS=$LIBS
+ LIBS="$Boost_lib_LIBS $LIBS"
+ test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath"
+dnl First argument of AC_LINK_IFELSE left empty because the test file is
+dnl generated only once above (before we start the for loops).
+ _BOOST_AC_LINK_IFELSE([],
+ [Boost_lib=yes], [Boost_lib=no])
+ ac_objext=$boost_save_ac_objext
+ LDFLAGS=$boost_save_LDFLAGS
+ LIBS=$boost_save_LIBS
+ if test x"$Boost_lib" = xyes; then
+ # Check or used cached result of whether or not using -R or
+ # -rpath makes sense. Some implementations of ld, such as for
+ # Mac OSX, require -rpath but -R is the flag known to work on
+ # other systems. https://github.com/tsuna/boost.m4/issues/19
+ AC_CACHE_VAL([boost_cv_rpath_link_ldflag],
+ [case $boost_ldpath in
+ '') # Nothing to do.
+ boost_cv_rpath_link_ldflag=
+ boost_rpath_link_ldflag_found=yes;;
+ *)
+ for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do
+ LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath"
+ LIBS="$boost_save_LIBS $Boost_lib_LIBS"
+ _BOOST_AC_LINK_IFELSE([],
+ [boost_rpath_link_ldflag_found=yes
+ break],
+ [boost_rpath_link_ldflag_found=no])
+ done
+ ;;
+ esac
+ AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"],
+ [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])])
+ LDFLAGS=$boost_save_LDFLAGS
+ LIBS=$boost_save_LIBS
+ ])
+ test x"$boost_ldpath" != x &&
+ Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath"
+ Boost_lib_LDPATH="$boost_ldpath"
+ break 7
+ else
+ boost_failed_libs="$boost_failed_libs@$boost_lib@"
+ fi
+ done
+ done
+done
+done
+done
+done
+done # boost_lib_
+rm -f conftest.$ac_objext
+])
+
+
+
+# --------------------------------------- #
+# Checks for the various Boost libraries. #
+# --------------------------------------- #
+
+# List of boost libraries: http://www.boost.org/libs/libraries.htm
+# The page http://beta.boost.org/doc/libs is useful: it gives the first release
+# version of each library (among other things).
+
+# BOOST_DEFUN(LIBRARY, CODE)
+# --------------------------
+# Define BOOST_<LIBRARY-UPPERCASE> as a macro that runs CODE.
+#
+# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN.
+m4_define([BOOST_DEFUN],
+[m4_indir([AC_DEFUN],
+ m4_toupper([BOOST_$1]),
+[m4_pushdef([BOOST_Library], [$1])dnl
+$2
+m4_popdef([BOOST_Library])dnl
+])
+])
+
+# BOOST_ARRAY()
+# -------------
+# Look for Boost.Array
+BOOST_DEFUN([Array],
+[BOOST_FIND_HEADER([boost/array.hpp])])
+
+
+# BOOST_ASIO()
+# ------------
+# Look for Boost.Asio (new in Boost 1.35).
+BOOST_DEFUN([Asio],
+[AC_REQUIRE([BOOST_SYSTEM])dnl
+BOOST_FIND_HEADER([boost/asio.hpp])])
+
+
+# BOOST_BIND()
+# ------------
+# Look for Boost.Bind.
+BOOST_DEFUN([Bind],
+[BOOST_FIND_HEADER([boost/bind.hpp])])
+
+
+# BOOST_CHRONO()
+# --------------
+# Look for Boost.Chrono.
+BOOST_DEFUN([Chrono],
+[# Do we have to check for Boost.System? This link-time dependency was
+# added as of 1.35.0. If we have a version <1.35, we must not attempt to
+# find Boost.System as it didn't exist by then.
+if test $boost_major_version -ge 135; then
+ BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+boost_filesystem_save_LIBS=$LIBS
+boost_filesystem_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([chrono], [$1],
+ [boost/chrono.hpp],
+ [boost::chrono::thread_clock d;])
+if test $enable_static_boost = yes && test $boost_major_version -ge 135; then
+ BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS"
+fi
+LIBS=$boost_filesystem_save_LIBS
+LDFLAGS=$boost_filesystem_save_LDFLAGS
+])# BOOST_CHRONO
+
+
+# BOOST_CONTEXT([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+#
+# * This library was introduced in Boost 1.51.0
+# * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0
+# * A dependency on boost_thread appears in 1.57.0
+BOOST_DEFUN([Context],
+[boost_context_save_LIBS=$LIBS
+ boost_context_save_LDFLAGS=$LDFLAGS
+if test $boost_major_version -ge 157; then
+ BOOST_THREAD([$1])
+ m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_THREAD_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS"
+fi
+BOOST_FIND_LIB([context], [$1],
+ [boost/context/all.hpp],[[
+
+// creates a stack
+void * stack_pointer = new void*[4096];
+std::size_t const size = sizeof(void*[4096]);
+
+#if BOOST_VERSION <= 105100
+ctx::make_fcontext(&fc, f);
+return ctx::jump_fcontext(&fcm, &fc, 3) == 6;
+
+#else
+
+fc = ctx::make_fcontext(stack_pointer, size, f);
+return ctx::jump_fcontext(&fcm, fc, 3) == 6;
+
+#endif
+
+
+]],[dnl
+
+#include <boost/version.hpp>
+#if BOOST_VERSION <= 105100
+
+namespace ctx = boost::ctx;
+
+static ctx::fcontext_t fcm, fc;
+
+static void f(intptr_t i) {
+ ctx::jump_fcontext(&fc, &fcm, i * 2);
+}
+
+#elif BOOST_VERSION <= 105500
+
+namespace ctx = boost::context;
+
+// context
+static ctx::fcontext_t fcm, *fc;
+
+// context-function
+static void f(intptr_t i) {
+ ctx::jump_fcontext(fc, &fcm, i * 2);
+}
+
+#else
+
+namespace ctx = boost::context;
+
+// context
+static ctx::fcontext_t fcm, fc;
+
+// context-function
+static void f(intptr_t i) {
+ ctx::jump_fcontext(&fc, fcm, i * 2);
+}
+#endif
+])
+LIBS=$boost_context_save_LIBS
+LDFLAGS=$boost_context_save_LDFLAGS
+])# BOOST_CONTEXT
+
+
+# BOOST_CONVERSION()
+# ------------------
+# Look for Boost.Conversion (cast / lexical_cast)
+BOOST_DEFUN([Conversion],
+[BOOST_FIND_HEADER([boost/cast.hpp])
+BOOST_FIND_HEADER([boost/lexical_cast.hpp])
+])# BOOST_CONVERSION
+
+
+# BOOST_COROUTINE([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. This library was introduced in Boost
+# 1.53.0
+BOOST_DEFUN([Coroutine],
+[
+boost_coroutine_save_LIBS=$LIBS
+boost_coroutine_save_LDFLAGS=$LDFLAGS
+# Link-time dependency from coroutine to context
+BOOST_CONTEXT([$1])
+# Starting from Boost 1.55 a dependency on Boost.System is added
+if test $boost_major_version -ge 155; then
+ BOOST_SYSTEM([$1])
+fi
+m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)])
+LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS"
+
+# in 1.53 coroutine was a header only library
+if test $boost_major_version -eq 153; then
+ BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp])
+else
+ BOOST_FIND_LIB([coroutine], [$1],
+ [boost/coroutine/coroutine.hpp],
+ [
+ #include <boost/version.hpp>
+ #if BOOST_VERSION <= 105500
+ boost::coroutines::coroutine<int(int)> coro; coro.get();
+ #else
+ boost::coroutines::asymmetric_coroutine<int>::pull_type coro; coro.get();
+ #endif
+ ])
+fi
+# Link-time dependency from coroutine to context, existed only in 1.53, in 1.54
+# coroutine doesn't use context from its headers but from its library.
+if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then
+ BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS"
+ BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS"
+fi
+if test $enable_static_boost = yes && test $boost_major_version -ge 155; then
+ BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS"
+ BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+fi
+LIBS=$boost_coroutine_save_LIBS
+LDFLAGS=$boost_coroutine_save_LDFLAGS
+])# BOOST_COROUTINE
+
+
+# BOOST_CRC()
+# -----------
+# Look for Boost.CRC
+BOOST_DEFUN([CRC],
+[BOOST_FIND_HEADER([boost/crc.hpp])
+])# BOOST_CRC
+
+
+# BOOST_DATE_TIME([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Date_Time],
+[BOOST_FIND_LIB([date_time], [$1],
+ [boost/date_time/posix_time/posix_time.hpp],
+ [boost::posix_time::ptime t;])
+])# BOOST_DATE_TIME
+
+
+# BOOST_FILESYSTEM([PREFERRED-RT-OPT])
+# ------------------------------------
+# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+# Do not check for boost/filesystem.hpp because this file was introduced in
+# 1.34.
+BOOST_DEFUN([Filesystem],
+[# Do we have to check for Boost.System? This link-time dependency was
+# added as of 1.35.0. If we have a version <1.35, we must not attempt to
+# find Boost.System as it didn't exist by then.
+if test $boost_major_version -ge 135; then
+ BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+boost_filesystem_save_LIBS=$LIBS
+boost_filesystem_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([filesystem], [$1],
+ [boost/filesystem/path.hpp], [boost::filesystem::path p;])
+if test $enable_static_boost = yes && test $boost_major_version -ge 135; then
+ BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"
+fi
+LIBS=$boost_filesystem_save_LIBS
+LDFLAGS=$boost_filesystem_save_LDFLAGS
+])# BOOST_FILESYSTEM
+
+
+# BOOST_FLYWEIGHT()
+# -----------------
+# Look for Boost.Flyweight.
+BOOST_DEFUN([Flyweight],
+[dnl There's a hidden dependency on pthreads.
+AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl
+BOOST_FIND_HEADER([boost/flyweight.hpp])
+AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag])
+])
+
+
+# BOOST_FOREACH()
+# ---------------
+# Look for Boost.Foreach.
+BOOST_DEFUN([Foreach],
+[BOOST_FIND_HEADER([boost/foreach.hpp])])
+
+
+# BOOST_FORMAT()
+# --------------
+# Look for Boost.Format.
+# Note: we can't check for boost/format/format_fwd.hpp because the header isn't
+# standalone. It can't be compiled because it triggers the following error:
+# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std'
+# does not name a type
+BOOST_DEFUN([Format],
+[BOOST_FIND_HEADER([boost/format.hpp])])
+
+
+# BOOST_FUNCTION()
+# ----------------
+# Look for Boost.Function
+BOOST_DEFUN([Function],
+[BOOST_FIND_HEADER([boost/function.hpp])])
+
+
+# BOOST_GEOMETRY()
+# ----------------
+# Look for Boost.Geometry (new since 1.47.0).
+BOOST_DEFUN([Geometry],
+[BOOST_FIND_HEADER([boost/geometry.hpp])
+])# BOOST_GEOMETRY
+
+
+# BOOST_GRAPH([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Graph],
+[boost_graph_save_LIBS=$LIBS
+boost_graph_save_LDFLAGS=$LDFLAGS
+# Link-time dependency from graph to regex was added as of 1.40.0.
+if test $boost_major_version -ge 140; then
+ BOOST_REGEX([$1])
+ m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_REGEX_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS"
+fi
+BOOST_FIND_LIB([graph], [$1],
+ [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;])
+LIBS=$boost_graph_save_LIBS
+LDFLAGS=$boost_graph_save_LDFLAGS
+])# BOOST_GRAPH
+
+
+# BOOST_IOSTREAMS([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([IOStreams],
+[BOOST_FIND_LIB([iostreams], [$1],
+ [boost/iostreams/device/file_descriptor.hpp],
+ [boost::iostreams::file_descriptor fd; fd.close();])
+])# BOOST_IOSTREAMS
+
+
+# BOOST_HASH()
+# ------------
+# Look for Boost.Functional/Hash
+BOOST_DEFUN([Hash],
+[BOOST_FIND_HEADER([boost/functional/hash.hpp])])
+
+
+# BOOST_LAMBDA()
+# --------------
+# Look for Boost.Lambda
+BOOST_DEFUN([Lambda],
+[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])])
+
+
+# BOOST_LOCALE()
+# --------------
+# Look for Boost.Locale
+BOOST_DEFUN([Locale],
+[
+boost_locale_save_LIBS=$LIBS
+boost_locale_save_LDFLAGS=$LDFLAGS
+# require SYSTEM for boost-1.50.0 and up
+if test $boost_major_version -ge 150; then
+ BOOST_SYSTEM([$1])
+ m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+ LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+ LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+fi # end of the Boost.System check.
+BOOST_FIND_LIB([locale], [$1],
+ [boost/locale.hpp],
+ [[boost::locale::generator gen; std::locale::global(gen(""));]])
+LIBS=$boost_locale_save_LIBS
+LDFLAGS=$boost_locale_save_LDFLAGS
+])# BOOST_LOCALE
+
+# BOOST_LOG([PREFERRED-RT-OPT])
+# -----------------------------
+# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Log],
+[boost_log_save_LIBS=$LIBS
+boost_log_save_LDFLAGS=$LDFLAGS
+BOOST_SYSTEM([$1])
+BOOST_FILESYSTEM([$1])
+BOOST_DATE_TIME([$1])
+m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([log], [$1],
+ [boost/log/core/core.hpp],
+ [boost::log::attribute a; a.get_value();])
+LIBS=$boost_log_save_LIBS
+LDFLAGS=$boost_log_save_LDFLAGS
+])# BOOST_LOG
+
+
+# BOOST_LOG_SETUP([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Log_Setup],
+[boost_log_setup_save_LIBS=$LIBS
+boost_log_setup_save_LDFLAGS=$LDFLAGS
+BOOST_LOG([$1])
+m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_LOG_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS"
+BOOST_FIND_LIB([log_setup], [$1],
+ [boost/log/utility/setup/from_settings.hpp],
+ [boost::log::basic_settings<char> bs; bs.empty();])
+LIBS=$boost_log_setup_save_LIBS
+LDFLAGS=$boost_log_setup_save_LDFLAGS
+])# BOOST_LOG_SETUP
+
+
+# BOOST_MATH()
+# ------------
+# Look for Boost.Math
+# TODO: This library isn't header-only but it comes in multiple different
+# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99,
+# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1,
+# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the
+# right thing anyway.
+BOOST_DEFUN([Math],
+[BOOST_FIND_HEADER([boost/math/special_functions.hpp])])
+
+
+# BOOST_MPI([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is
+# set, otherwise tries CXX
+#
+BOOST_DEFUN([MPI],
+[boost_save_CXX=${CXX}
+boost_save_CXXCPP=${CXXCPP}
+if test x"${MPICXX}" != x; then
+ CXX=${MPICXX}
+ CXXCPP="${MPICXX} -E"
+fi
+BOOST_FIND_LIB([mpi], [$1],
+ [boost/mpi.hpp],
+ [int argc = 0;
+ char **argv = 0;
+ boost::mpi::environment env(argc,argv);])
+CXX=${boost_save_CXX}
+CXXCPP=${boost_save_CXXCPP}
+])# BOOST_MPI
+
+
+# BOOST_MULTIARRAY()
+# ------------------
+# Look for Boost.MultiArray
+BOOST_DEFUN([MultiArray],
+[BOOST_FIND_HEADER([boost/multi_array.hpp])])
+
+
+# BOOST_NUMERIC_UBLAS()
+# --------------------------
+# Look for Boost.NumericUblas (Basic Linear Algebra)
+BOOST_DEFUN([Numeric_Ublas],
+[BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp])
+])# BOOST_NUMERIC_UBLAS
+
+
+# BOOST_NUMERIC_CONVERSION()
+# --------------------------
+# Look for Boost.NumericConversion (policy-based numeric conversion)
+BOOST_DEFUN([Numeric_Conversion],
+[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp])
+])# BOOST_NUMERIC_CONVERSION
+
+
+# BOOST_OPTIONAL()
+# ----------------
+# Look for Boost.Optional
+BOOST_DEFUN([Optional],
+[BOOST_FIND_HEADER([boost/optional.hpp])])
+
+
+# BOOST_PREPROCESSOR()
+# --------------------
+# Look for Boost.Preprocessor
+BOOST_DEFUN([Preprocessor],
+[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])])
+
+
+# BOOST_RANGE()
+# --------------------
+# Look for Boost.Range
+BOOST_DEFUN([Range],
+[BOOST_FIND_HEADER([boost/range/adaptors.hpp])])
+
+# BOOST_UNORDERED()
+# -----------------
+# Look for Boost.Unordered
+BOOST_DEFUN([Unordered],
+[BOOST_FIND_HEADER([boost/unordered_map.hpp])])
+
+
+# BOOST_UUID()
+# ------------
+# Look for Boost.Uuid
+BOOST_DEFUN([Uuid],
+[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])])
+
+
+# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT])
+# -----------------------------------------
+# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT,
+# see the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Program_Options],
+[BOOST_FIND_LIB([program_options], [$1],
+ [boost/program_options.hpp],
+ [boost::program_options::options_description d("test");])
+])# BOOST_PROGRAM_OPTIONS
+
+
+
+# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG)
+# ------------------------------------
+# Save VARIABLE, and define it via `python-config --FLAG`.
+# Substitute BOOST_PYTHON_VARIABLE.
+m4_define([_BOOST_PYTHON_CONFIG],
+[AC_SUBST([BOOST_PYTHON_$1],
+ [`python-config --$2 2>/dev/null`])dnl
+boost_python_save_$1=$$1
+$1="$$1 $BOOST_PYTHON_$1"])
+
+
+# BOOST_PYTHON([PREFERRED-RT-OPT])
+# --------------------------------
+# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT,
+# see the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Python],
+[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes])
+_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags])
+_BOOST_PYTHON_CONFIG([LIBS], [libs])
+m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl
+BOOST_FIND_LIBS([python], [python python3], [$1],
+ [boost/python.hpp],
+ [], [BOOST_PYTHON_MODULE(empty) {}])
+CPPFLAGS=$boost_python_save_CPPFLAGS
+LDFLAGS=$boost_python_save_LDFLAGS
+LIBS=$boost_python_save_LIBS
+])# BOOST_PYTHON
+
+
+# BOOST_REF()
+# -----------
+# Look for Boost.Ref
+BOOST_DEFUN([Ref],
+[BOOST_FIND_HEADER([boost/ref.hpp])])
+
+
+# BOOST_REGEX([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Regex],
+[BOOST_FIND_LIB([regex], [$1],
+ [boost/regex.hpp],
+ [boost::regex exp("*"); boost::regex_match("foo", exp);])
+])# BOOST_REGEX
+
+
+# BOOST_SERIALIZATION([PREFERRED-RT-OPT])
+# ---------------------------------------
+# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Serialization],
+[BOOST_FIND_LIB([serialization], [$1],
+ [boost/archive/text_oarchive.hpp],
+ [std::ostream* o = 0; // Cheap way to get an ostream...
+ boost::archive::text_oarchive t(*o);])
+])# BOOST_SERIALIZATION
+
+
+# BOOST_SIGNALS([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Signals],
+[BOOST_FIND_LIB([signals], [$1],
+ [boost/signal.hpp],
+ [boost::signal<void ()> s;])
+])# BOOST_SIGNALS
+
+
+# BOOST_SIGNALS2()
+# ----------------
+# Look for Boost.Signals2 (new since 1.39.0).
+BOOST_DEFUN([Signals2],
+[BOOST_FIND_HEADER([boost/signals2.hpp])
+])# BOOST_SIGNALS2
+
+
+# BOOST_SMART_PTR()
+# -----------------
+# Look for Boost.SmartPtr
+BOOST_DEFUN([Smart_Ptr],
+[BOOST_FIND_HEADER([boost/scoped_ptr.hpp])
+BOOST_FIND_HEADER([boost/shared_ptr.hpp])
+])
+
+
+# BOOST_STATICASSERT()
+# --------------------
+# Look for Boost.StaticAssert
+BOOST_DEFUN([StaticAssert],
+[BOOST_FIND_HEADER([boost/static_assert.hpp])])
+
+
+# BOOST_STRING_ALGO()
+# -------------------
+# Look for Boost.StringAlgo
+BOOST_DEFUN([String_Algo],
+[BOOST_FIND_HEADER([boost/algorithm/string.hpp])
+])
+
+
+# BOOST_SYSTEM([PREFERRED-RT-OPT])
+# --------------------------------
+# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. This library was introduced in Boost
+# 1.35.0.
+BOOST_DEFUN([System],
+[BOOST_FIND_LIB([system], [$1],
+ [boost/system/error_code.hpp],
+ [boost::system::error_code e; e.clear();])
+])# BOOST_SYSTEM
+
+
+# BOOST_TEST([PREFERRED-RT-OPT])
+# ------------------------------
+# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Test],
+[m4_pattern_allow([^BOOST_CHECK$])dnl
+BOOST_FIND_LIB([unit_test_framework], [$1],
+ [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);],
+ [using boost::unit_test::test_suite;
+ test_suite* init_unit_test_suite(int argc, char ** argv)
+ { return NULL; }])
+])# BOOST_TEST
+
+
+# BOOST_THREAD([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Thread],
+[dnl Having the pthread flag is required at least on GCC3 where
+dnl boost/thread.hpp would complain if we try to compile without
+dnl -pthread on GNU/Linux.
+AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl
+boost_thread_save_LIBS=$LIBS
+boost_thread_save_LDFLAGS=$LDFLAGS
+boost_thread_save_CPPFLAGS=$CPPFLAGS
+# Link-time dependency from thread to system was added as of 1.49.0.
+if test $boost_major_version -ge 149; then
+BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag"
+
+# When compiling for the Windows platform, the threads library is named
+# differently. This suffix doesn't exist in new versions of Boost, or
+# possibly new versions of GCC on mingw I am assuming it's Boost's change for
+# now and I am setting version to 1.48, for lack of knowledge as to when this
+# change occurred.
+if test $boost_major_version -lt 148; then
+ case $host_os in
+ (*mingw*) boost_thread_lib_ext=_win32;;
+ esac
+fi
+BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext],
+ [$1],
+ [boost/thread.hpp], [boost::thread t; boost::mutex m;])
+
+case $host_os in
+ (*mingw*) boost_thread_w32_socket_link=-lws2_32;;
+esac
+
+BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link"
+BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS"
+BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag"
+LIBS=$boost_thread_save_LIBS
+LDFLAGS=$boost_thread_save_LDFLAGS
+CPPFLAGS=$boost_thread_save_CPPFLAGS
+])# BOOST_THREAD
+
+AU_ALIAS([BOOST_THREADS], [BOOST_THREAD])
+
+
+# BOOST_TOKENIZER()
+# -----------------
+# Look for Boost.Tokenizer
+BOOST_DEFUN([Tokenizer],
+[BOOST_FIND_HEADER([boost/tokenizer.hpp])])
+
+
+# BOOST_TRIBOOL()
+# ---------------
+# Look for Boost.Tribool
+BOOST_DEFUN([Tribool],
+[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp])
+BOOST_FIND_HEADER([boost/logic/tribool.hpp])
+])
+
+
+# BOOST_TUPLE()
+# -------------
+# Look for Boost.Tuple
+BOOST_DEFUN([Tuple],
+[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])])
+
+
+# BOOST_TYPETRAITS()
+# --------------------
+# Look for Boost.TypeTraits
+BOOST_DEFUN([TypeTraits],
+[BOOST_FIND_HEADER([boost/type_traits.hpp])])
+
+
+# BOOST_UTILITY()
+# ---------------
+# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom,
+# etc.)
+BOOST_DEFUN([Utility],
+[BOOST_FIND_HEADER([boost/utility.hpp])])
+
+
+# BOOST_VARIANT()
+# ---------------
+# Look for Boost.Variant.
+BOOST_DEFUN([Variant],
+[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp])
+BOOST_FIND_HEADER([boost/variant.hpp])])
+
+
+# BOOST_POINTER_CONTAINER()
+# ------------------------
+# Look for Boost.PointerContainer
+BOOST_DEFUN([Pointer_Container],
+[BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp])
+BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp])
+])# BOOST_POINTER_CONTAINER
+
+
+# BOOST_WAVE([PREFERRED-RT-OPT])
+# ------------------------------
+# NOTE: If you intend to use Wave/Spirit with thread support, make sure you
+# call BOOST_THREAD first.
+# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+BOOST_DEFUN([Wave],
+[AC_REQUIRE([BOOST_FILESYSTEM])dnl
+AC_REQUIRE([BOOST_DATE_TIME])dnl
+boost_wave_save_LIBS=$LIBS
+boost_wave_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \
+$BOOST_THREAD_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \
+$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS"
+BOOST_FIND_LIB([wave], [$1],
+ [boost/wave.hpp],
+ [boost::wave::token_id id; get_token_name(id);])
+LIBS=$boost_wave_save_LIBS
+LDFLAGS=$boost_wave_save_LDFLAGS
+])# BOOST_WAVE
+
+
+# BOOST_XPRESSIVE()
+# -----------------
+# Look for Boost.Xpressive (new since 1.36.0).
+BOOST_DEFUN([Xpressive],
+[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])])
+
+
+# ----------------- #
+# Internal helpers. #
+# ----------------- #
+
+
+# _BOOST_PTHREAD_FLAG()
+# ---------------------
+# Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag
+# which must be used in CPPFLAGS and LIBS.
+#
+# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
+# boost/thread.hpp will trigger a #error if -pthread isn't used:
+# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
+# is not turned on. Please set the correct command line options for
+# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
+#
+# Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html
+AC_DEFUN([_BOOST_PTHREAD_FLAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_LANG_PUSH([C++])dnl
+AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag],
+[ boost_cv_pthread_flag=
+ # The ordering *is* (sometimes) important. Some notes on the
+ # individual items follow:
+ # (none): in case threads are in libc; should be tried before -Kthread and
+ # other compiler flags to prevent continual compiler warnings
+ # -lpthreads: AIX (must check this before -lpthread)
+ # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+ # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
+ # -pthreads: Solaris/GCC
+ # -mthreads: MinGW32/GCC, Lynx/GCC
+ # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+ # doesn't hurt to check since this sometimes defines pthreads too;
+ # also defines -D_REENTRANT)
+ # ... -mt is also the pthreads flag for HP/aCC
+ # -lpthread: GNU Linux, etc.
+ # --thread-safe: KAI C++
+ case $host_os in #(
+ *solaris*)
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+ boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #(
+ *)
+ boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \
+ -pthreads -mthreads -lpthread --thread-safe -mt";;
+ esac
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);])])
+ for boost_pthread_flag in '' $boost_pthread_flags; do
+ boost_pthread_ok=false
+dnl Re-use the test file already generated.
+ boost_pthreads__save_LIBS=$LIBS
+ LIBS="$LIBS $boost_pthread_flag"
+ AC_LINK_IFELSE([],
+ [if grep ".*$boost_pthread_flag" conftest.err; then
+ echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD
+ else
+ boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag
+ fi])
+ LIBS=$boost_pthreads__save_LIBS
+ $boost_pthread_ok && break
+ done
+])
+AC_LANG_POP([C++])dnl
+])# _BOOST_PTHREAD_FLAG
+
+
+# _BOOST_gcc_test(MAJOR, MINOR)
+# -----------------------------
+# Internal helper for _BOOST_FIND_COMPILER_TAG.
+m4_define([_BOOST_gcc_test],
+["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl
+
+# _BOOST_mingw_test(MAJOR, MINOR)
+# -----------------------------
+# Internal helper for _BOOST_FIND_COMPILER_TAG.
+m4_define([_BOOST_mingw_test],
+["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \
+ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
+ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl
+
+
+# _BOOST_FIND_COMPILER_TAG()
+# --------------------------
+# Internal. When Boost is installed without --layout=system, each library
+# filename will hold a suffix that encodes the compiler used during the
+# build. The Boost build system seems to call this a `tag'.
+AC_DEFUN([_BOOST_FIND_COMPILER_TAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_CACHE_CHECK([for the toolset name used by Boost for $CXX],
+ [boost_cv_lib_tag],
+[boost_cv_lib_tag=unknown
+if test x$boost_cv_inc_path != xno; then
+ AC_LANG_PUSH([C++])dnl
+ # The following tests are mostly inspired by boost/config/auto_link.hpp
+ # The list is sorted to most recent/common to oldest compiler (in order
+ # to increase the likelihood of finding the right compiler with the
+ # least number of compilation attempt).
+ # Beware that some tests are sensible to the order (for instance, we must
+ # look for MinGW before looking for GCC3).
+ # I used one compilation test per compiler with a #error to recognize
+ # each compiler so that it works even when cross-compiling (let me know
+ # if you know a better approach).
+ # Known missing tags (known from Boost's tools/build/v2/tools/common.jam):
+ # como, edg, kcc, bck, mp, sw, tru, xlc
+ # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines
+ # the same defines as GCC's).
+ for i in \
+ _BOOST_mingw_test(5, 3) \
+ _BOOST_gcc_test(5, 3) \
+ _BOOST_mingw_test(5, 2) \
+ _BOOST_gcc_test(5, 2) \
+ _BOOST_mingw_test(5, 1) \
+ _BOOST_gcc_test(5, 1) \
+ _BOOST_mingw_test(5, 0) \
+ _BOOST_gcc_test(5, 0) \
+ _BOOST_mingw_test(4, 10) \
+ _BOOST_gcc_test(4, 10) \
+ _BOOST_mingw_test(4, 9) \
+ _BOOST_gcc_test(4, 9) \
+ _BOOST_mingw_test(4, 8) \
+ _BOOST_gcc_test(4, 8) \
+ _BOOST_mingw_test(4, 7) \
+ _BOOST_gcc_test(4, 7) \
+ _BOOST_mingw_test(4, 6) \
+ _BOOST_gcc_test(4, 6) \
+ _BOOST_mingw_test(4, 5) \
+ _BOOST_gcc_test(4, 5) \
+ _BOOST_mingw_test(4, 4) \
+ _BOOST_gcc_test(4, 4) \
+ _BOOST_mingw_test(4, 3) \
+ _BOOST_gcc_test(4, 3) \
+ _BOOST_mingw_test(4, 2) \
+ _BOOST_gcc_test(4, 2) \
+ _BOOST_mingw_test(4, 1) \
+ _BOOST_gcc_test(4, 1) \
+ _BOOST_mingw_test(4, 0) \
+ _BOOST_gcc_test(4, 0) \
+ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \
+ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
+ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \
+ _BOOST_gcc_test(3, 4) \
+ _BOOST_gcc_test(3, 3) \
+ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \
+ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \
+ _BOOST_gcc_test(3, 2) \
+ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \
+ _BOOST_gcc_test(3, 1) \
+ _BOOST_gcc_test(3, 0) \
+ "defined __BORLANDC__ @ bcb" \
+ "defined __ICC && (defined __unix || defined __unix__) @ il" \
+ "defined __ICL @ iw" \
+ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \
+ _BOOST_gcc_test(2, 95) \
+ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \
+ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \
+ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \
+ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8"
+ do
+ boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '`
+ boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'`
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if $boost_tag_test
+/* OK */
+#else
+# error $boost_tag_test
+#endif
+]])], [boost_cv_lib_tag=$boost_tag; break], [])
+ done
+AC_LANG_POP([C++])dnl
+ case $boost_cv_lib_tag in #(
+ # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed
+ # to "gcc41" for instance.
+ *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there.
+ gcc*)
+ boost_tag_x=
+ case $host_os in #(
+ darwin*)
+ if test $boost_major_version -ge 136; then
+ # The `x' added in r46793 of Boost.
+ boost_tag_x=x
+ fi;;
+ esac
+ # We can specify multiple tags in this variable because it's used by
+ # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ...
+ boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc"
+ ;; #(
+ unknown)
+ AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]])
+ boost_cv_lib_tag=
+ ;;
+ esac
+fi])dnl end of AC_CACHE_CHECK
+])# _BOOST_FIND_COMPILER_TAG
+
+
+# _BOOST_GUESS_WHETHER_TO_USE_MT()
+# --------------------------------
+# Compile a small test to try to guess whether we should favor MT (Multi
+# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly.
+AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT],
+[# Check whether we do better use `mt' even though we weren't ask to.
+AC_LANG_PUSH([C++])dnl
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if defined _REENTRANT || defined _MT || defined __MT__
+/* use -mt */
+#else
+# error MT not needed
+#endif
+]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false])
+AC_LANG_POP([C++])dnl
+])
+
+# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------------
+# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile,
+# will break when Autoconf changes its internals. Requires that you manually
+# rm -f conftest.$ac_objext in between to really different tests, otherwise
+# you will try to link a conftest.o left behind by a previous test.
+# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this
+# macro).
+#
+# Don't use "break" in the actions, as it would short-circuit some code
+# this macro runs after the actions.
+m4_define([_BOOST_AC_LINK_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+rm -f conftest$ac_exeext
+boost_save_ac_ext=$ac_ext
+boost_use_source=:
+# If we already have a .o, re-use it. We change $ac_ext so that $ac_link
+# tries to link the existing object file instead of compiling from source.
+test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false &&
+ _AS_ECHO_LOG([re-using the existing conftest.$ac_objext])
+AS_IF([_AC_DO_STDERR($ac_link) && {
+ test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_executable_p conftest$ac_exeext
+dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough.
+ }],
+ [$2],
+ [if $boost_use_source; then
+ _AC_MSG_LOG_CONFTEST
+ fi
+ $3])
+ac_objext=$boost_save_ac_objext
+ac_ext=$boost_save_ac_ext
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -f core conftest.err conftest_ipa8_conftest.oo \
+ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl
+])# _BOOST_AC_LINK_IFELSE
+
+# Local Variables:
+# mode: autoconf
+# End:
diff --git a/m4/shave.m4 b/m4/shave.m4
new file mode 100644
index 0000000..5b1f675
--- /dev/null
+++ b/m4/shave.m4
@@ -0,0 +1,40 @@
+dnl Make automake/libtool output more friendly to humans
+dnl
+dnl SHAVE_INIT([shavedir])
+dnl
+dnl shavedir: the directory where the shave script is, it defaults to
+dnl $(top_builddir)
+dnl
+dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just
+dnl before AC_CONFIG_FILE/AC_OUTPUT is perfect. This macro rewrite CC and
+dnl LIBTOOL, you don't want the configure tests to have these variables
+dnl re-defined.
+dnl * This macro requires GNU make's -s option.
+
+AC_DEFUN([SHAVE_INIT], [
+dnl where can we find the shave scripts?
+m4_if([$1],,
+ [shavedir='$(top_builddir)'],
+ [shavedir='$(top_builddir)'/$1])
+AC_SUBST(shavedir)
+dnl make is now quiet
+AC_SUBST([MAKEFLAGS], [-s])
+AC_SUBST([AM_MAKEFLAGS], ['`test -z $V && echo -s`'])
+dnl we need sed
+AC_CHECK_PROG(SED,sed,sed,false)
+dnl substitute libtool
+SHAVE_SAVED_LIBTOOL=$LIBTOOL
+AC_SUBST(SHAVE_SAVED_LIBTOOL)
+LIBTOOL="\$(SHELL) \$(shavedir)/shave-libtool '\$(SHAVE_SAVED_LIBTOOL)'"
+AC_SUBST(LIBTOOL)
+dnl substitute cc
+SHAVE_SAVED_CC=$CC
+SHAVE_SAVED_CXX=$CXX
+AC_SUBST(SHAVE_SAVED_CC)
+AC_SUBST(SHAVE_SAVED_CXX)
+CC="\$(SHELL) \$(shavedir)/shave cc '\$(SHAVE_SAVED_CC)'"
+CXX="\$(SHELL) \$(shavedir)/shave cxx '\$(SHAVE_SAVED_CXX)'"
+AC_SUBST(CC)
+AC_SUBST(CXX)
+])
+
diff --git a/public/Makefile.am b/public/Makefile.am
new file mode 100644
index 0000000..bb4f0aa
--- /dev/null
+++ b/public/Makefile.am
@@ -0,0 +1,38 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+DIST_SUBDIRS = include \ No newline at end of file
diff --git a/public/include/Makefile.am b/public/include/Makefile.am
new file mode 100644
index 0000000..866c7f9
--- /dev/null
+++ b/public/include/Makefile.am
@@ -0,0 +1,50 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+DIST_SUBDIRS = client-glue
+
+xmpdir = $(includedir)/@EXEMPI_INCLUDE_BASE@
+xmp_HEADERS =
+
+noinst_HEADERS = TXMPFiles.hpp TXMPIterator.hpp \
+ TXMPMeta.hpp TXMPUtils.hpp \
+ XMP.hpp XMP_Version.h\
+ XMP.incl_cpp\
+ XMP_Const.h XMP_Environment.h \
+ XMP_IO.hpp \
+ XMP_UnixEndian.h \
+ $(NULL)
diff --git a/public/include/XMP_Const.h b/public/include/XMP_Const.h
index 144baec..b8b904f 100644
--- a/public/include/XMP_Const.h
+++ b/public/include/XMP_Const.h
@@ -41,7 +41,7 @@ extern "C" {
// case only the declarations of the XMP_... types needs to change, not all of the uses. These
// types are used where fixed sizes are required in order to have a known ABI for a DLL build.
-#if XMP_MacBuild | XMP_iOSBuild
+#if XMP_MacBuild || XMP_iOSBuild || defined(HAVE_STDINT_H)
typedef int8_t XMP_Int8;
typedef int16_t XMP_Int16;
@@ -893,6 +893,8 @@ enum {
kXMP_GIFFile = 0x47494620UL,
/// Public file format constant: 'PNG '
kXMP_PNGFile = 0x504E4720UL,
+ /// Public file format constant: 'WEBP '
+ kXMP_WEBPFile = 0x57454250UL,
/// Public file format constant: 'SWF '
kXMP_SWFFile = 0x53574620UL,
diff --git a/public/include/XMP_IO.hpp b/public/include/XMP_IO.hpp
index d485392..3664e3b 100644
--- a/public/include/XMP_IO.hpp
+++ b/public/include/XMP_IO.hpp
@@ -164,7 +164,7 @@ private:
/// share state across multiple XMP_IO objects.
XMP_IO ( const XMP_IO & original );
- void operator= ( const XMP_IO& in ) { *this = in; /* Avoid Win compile warnings. */ };
+ XMP_IO& operator= ( const XMP_IO& in );
};
diff --git a/public/include/XMP_UnixEndian.h b/public/include/XMP_UnixEndian.h
new file mode 100644
index 0000000..ff1699e
--- /dev/null
+++ b/public/include/XMP_UnixEndian.h
@@ -0,0 +1,32 @@
+// Endian check for Unix, refactored because examples needs it.
+//
+
+#ifdef CHECKED_ENDIANNESS
+
+# if defined(WORDS_BIGENDIAN)
+# define kBigEndianHost 1
+# else
+# define kBigEndianHost 0
+# endif
+
+#else
+
+# if __sun
+# include <sys/isa_defs.h>
+# ifdef _LITTLE_ENDIAN
+# define kBigEndianHost 0
+# else
+# define kBigEndianHost 1
+# endif
+# else
+# include <endian.h>
+# if BYTE_ORDER == BIG_ENDIAN
+# define kBigEndianHost 1
+# elif BYTE_ORDER == LITTLE_ENDIAN
+# define kBigEndianHost 0
+# else
+# error "Neither BIG_ENDIAN nor LITTLE_ENDIAN is set"
+# endif
+# endif
+
+#endif // CHECKED_ENDIANNESS
diff --git a/public/include/client-glue/Makefile.am b/public/include/client-glue/Makefile.am
new file mode 100644
index 0000000..30e58b2
--- /dev/null
+++ b/public/include/client-glue/Makefile.am
@@ -0,0 +1,40 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+noinst_HEADERS=TXMPFiles.incl_cpp TXMPMeta.incl_cpp WXMP_Common.hpp \
+ WXMPIterator.hpp WXMPUtils.hpp\
+ TXMPIterator.incl_cpp TXMPUtils.incl_cpp WXMPFiles.hpp WXMPMeta.hpp \ No newline at end of file
diff --git a/public/include/client-glue/WXMPFiles.hpp b/public/include/client-glue/WXMPFiles.hpp
index 2f8bb9a..fc16bb7 100644
--- a/public/include/client-glue/WXMPFiles.hpp
+++ b/public/include/client-glue/WXMPFiles.hpp
@@ -36,7 +36,7 @@ extern "C" {
PropagateException ( wResult ); \
XMPFilesRef result = XMPFilesRef(wResult.ptrResult)
-static XMP_Bool WrapProgressReport ( XMP_ProgressReportProc proc, void * context,
+inline XMP_Bool WrapProgressReport ( XMP_ProgressReportProc proc, void * context,
float elapsedTime, float fractionDone, float secondsToGo )
{
bool ok;
@@ -50,7 +50,7 @@ static XMP_Bool WrapProgressReport ( XMP_ProgressReportProc proc, void * context
// =================================================================================================
-static XMP_Bool WrapFilesErrorNotify ( XMPFiles_ErrorCallbackProc proc, void * context,
+inline XMP_Bool WrapFilesErrorNotify ( XMPFiles_ErrorCallbackProc proc, void * context,
XMP_StringPtr filePath, XMP_ErrorSeverity severity, XMP_Int32 cause, XMP_StringPtr message )
{
bool ok;
diff --git a/public/include/client-glue/WXMPMeta.hpp b/public/include/client-glue/WXMPMeta.hpp
index af5a11e..28a8cdd 100644
--- a/public/include/client-glue/WXMPMeta.hpp
+++ b/public/include/client-glue/WXMPMeta.hpp
@@ -17,7 +17,7 @@ extern "C" {
// =================================================================================================
-static XMP_Bool WrapErrorNotify ( XMPMeta_ErrorCallbackProc proc, void * context,
+inline XMP_Bool WrapErrorNotify ( XMPMeta_ErrorCallbackProc proc, void * context,
XMP_ErrorSeverity severity, XMP_Int32 cause, XMP_StringPtr message )
{
bool ok;
diff --git a/rpm/SLED10.spec b/rpm/SLED10.spec
new file mode 100644
index 0000000..1dbae86
--- /dev/null
+++ b/rpm/SLED10.spec
@@ -0,0 +1,54 @@
+#
+# spec file for package exempi
+#
+# Copyright (c) 2007 Novell Inc.
+# This file and all modifications and additions to the pristine
+# package are under the same license as the package itself.
+#
+
+# norootforbuild
+
+
+Summary: XMP support library
+Name: exempi
+Version: 1.99.5
+Release: 1
+License: BSD
+Group: System/Libraries
+Source0: http://libopenraw.freedesktop.org/download/%name-%{version}.tar.gz
+BuildRoot: /var/tmp/%{name}-buildroot
+BuildRequires: boost-devel, expat
+%define prefix /usr
+
+%description
+XMP parsing and IO library
+
+%prep
+%setup -q
+
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" \
+ ./configure --prefix=%prefix \
+ --libdir=/usr/%_lib
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+DESTDIR=$RPM_BUILD_ROOT make install
+
+%post
+%run_ldconfig
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README COPYING ChangeLog
+
+%{prefix}/%{_lib}/libexempi.*
+%{prefix}/include/exempi-2.0/*
+%{prefix}/%{_lib}/pkgconfig/*.pc
+
+%changelog
diff --git a/samples/BlueSquares/BlueSquare.gif b/samples/BlueSquares/BlueSquare.gif
new file mode 100644
index 0000000..7dcc9e7
--- /dev/null
+++ b/samples/BlueSquares/BlueSquare.gif
Binary files differ
diff --git a/samples/BlueSquares/Makefile.am b/samples/BlueSquares/Makefile.am
new file mode 100644
index 0000000..1aa0f57
--- /dev/null
+++ b/samples/BlueSquares/Makefile.am
@@ -0,0 +1,39 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+EXTRA_DIST=BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\
+BlueSquare.avi BlueSquare.indd BlueSquare.mov BlueSquare.pdf BlueSquare.psd BlueSquare.wav
diff --git a/samples/Makefile.am b/samples/Makefile.am
new file mode 100644
index 0000000..5f583f5
--- /dev/null
+++ b/samples/Makefile.am
@@ -0,0 +1,39 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+SUBDIRS = source
+DIST_SUBDIRS = source testfiles
diff --git a/samples/source/Makefile.am b/samples/source/Makefile.am
new file mode 100644
index 0000000..5ebc13d
--- /dev/null
+++ b/samples/source/Makefile.am
@@ -0,0 +1,94 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+noinst_PROGRAMS = xmpcoverage xmpfilescoverage dumpxmp dumpmainxmp\
+ customschema \
+ modifyingxmp \
+ readingxmp \
+ xmpcommandtool \
+ $(NULL)
+
+AM_CXXFLAGS = -fexceptions -funsigned-char -fPIC \
+ -Wno-multichar -Wno-ctor-dtor-privacy
+AM_CPPFLAGS = -I$(top_srcdir)/public/include -I$(top_srcdir) \
+ -D@EXEMPI_PLATFORM_DEF@=1 -D_FILE_OFFSET_BITS=64
+
+XMPLIBS = $(top_builddir)/XMPCore/source/libXMPCore.la \
+ $(top_builddir)/XMPFiles/source/libXMPFiles.la \
+ $(top_builddir)/source/libxmpcommon.la -lexpat -lz \
+ $(top_builddir)/third-party/zuid/interfaces/libmd5.la \
+ -ldl
+
+if UNIX_ENV
+XMPLIBS += -lrt
+endif
+
+noinst_LTLIBRARIES = libsamplescommon.la
+libsamplescommon_la_SOURCES = common/DumpFile.cpp common/DumpFile.h \
+ common/Log.cpp common/Log.h \
+ common/TagTree.cpp common/TagTree.h \
+ common/LargeFileAccess.hpp \
+ common/XMPScanner.hpp \
+ common/globals.h \
+ $(NULL)
+
+customschema_SOURCES = CustomSchema.cpp
+customschema_LDADD = $(XMPLIBS)
+
+modifyingxmp_SOURCES = ModifyingXMP.cpp
+modifyingxmp_LDADD = $(XMPLIBS)
+
+readingxmp_SOURCES = ReadingXMP.cpp
+readingxmp_LDADD = $(XMPLIBS)
+
+xmpcoverage_SOURCES = XMPCoreCoverage.cpp
+xmpcoverage_LDADD = $(XMPLIBS)
+
+xmpfilescoverage_SOURCES = XMPFilesCoverage.cpp
+xmpfilescoverage_LDADD = $(XMPLIBS)
+
+dumpxmp_SOURCES = DumpScannedXMP.cpp
+dumpxmp_LDADD = $(XMPLIBS)
+
+dumpmainxmp_SOURCES = DumpMainXMP.cpp
+dumpmainxmp_LDADD = $(XMPLIBS)
+
+xmpcommandtool_SOURCES = xmpcommand/Actions.cpp xmpcommand/Actions.h \
+ xmpcommand/PrintUsage.cpp xmpcommand/PrintUsage.h \
+ xmpcommand/XMPCommand.cpp \
+ $(NULL)
+xmpcommandtool_LDADD = $(XMPLIBS) libsamplescommon.la
diff --git a/samples/source/ModifyingXMP.cpp b/samples/source/ModifyingXMP.cpp
index b334e70..13e687b 100644
--- a/samples/source/ModifyingXMP.cpp
+++ b/samples/source/ModifyingXMP.cpp
@@ -32,6 +32,7 @@
#include <iostream>
#include <fstream>
+#include <string.h>
using namespace std;
diff --git a/samples/source/common/TagTree.cpp b/samples/source/common/TagTree.cpp
index 761ab22..6d0ae97 100644
--- a/samples/source/common/TagTree.cpp
+++ b/samples/source/common/TagTree.cpp
@@ -180,8 +180,8 @@ void TagTree::digest(LFA_FileRef file,const std::string key /*=NULL*/,
}
#endif
- delete out;
- if (!returnValue) delete value; //if we own it, we delete it
+ delete [] out;
+ if (!returnValue) delete [] value; //if we own it, we delete it
}
////////////////////////////////////////////////////////////////////////////////////
diff --git a/samples/source/common/XMPScanner.cpp b/samples/source/common/XMPScanner.cpp
index 5678571..762638e 100644
--- a/samples/source/common/XMPScanner.cpp
+++ b/samples/source/common/XMPScanner.cpp
@@ -1246,13 +1246,13 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
} else {
// *** snipPos->fMachine.reset ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) ); VC++ lacks reset
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine> ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );
+ snipPos->fMachine = unique_ptr<PacketMachine> ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
PacketMachine * pm = new PacketMachine ( bufferOffset, bufferOrigin, bufferLength );
- auto_ptr<PacketMachine> ap ( pm );
- snipPos->fMachine = ap;
+ unique_ptr<PacketMachine> ap ( pm );
+ snipPos->fMachine = std::move(ap);
}
#endif
thisMachine = snipPos->fMachine.get();
@@ -1271,11 +1271,11 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
snipPos->fInfo.fState = eRawInputSnip;
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
+ snipPos->fMachine = unique_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
- auto_ptr<PacketMachine> ap ( 0 );
+ unique_ptr<PacketMachine> ap ( 0 );
snipPos->fMachine = ap;
}
#endif
@@ -1364,12 +1364,12 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
// This packet ends exactly at the end of the current snip.
#if 0
- snipPos->fMachine = auto_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
+ snipPos->fMachine = unique_ptr<PacketMachine>(); // *** snipPos->fMachine.reset(); VC++ lacks reset
#else
{
// Some versions of gcc complain about the assignment operator above. This avoids the gcc bug.
- auto_ptr<PacketMachine> ap ( 0 );
- snipPos->fMachine = ap;
+ unique_ptr<PacketMachine> ap ( 0 );
+ snipPos->fMachine = std::move(ap);
}
#endif
bufferDone = true;
@@ -1381,7 +1381,7 @@ XMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64
InternalSnipIterator tailPos = NextSnip ( snipPos );
- tailPos->fMachine = snipPos->fMachine; // auto_ptr assignment - taking ownership
+ tailPos->fMachine = std::move(snipPos->fMachine); // unique_ptr assignment - taking ownership
thisMachine->ResetMachine ();
snipPos = tailPos;
diff --git a/samples/source/common/XMPScanner.hpp b/samples/source/common/XMPScanner.hpp
index 1479d2d..2d2d166 100644
--- a/samples/source/common/XMPScanner.hpp
+++ b/samples/source/common/XMPScanner.hpp
@@ -155,7 +155,7 @@ private: // XMPScanner
public:
SnipInfo fInfo; // The public info about this snip.
- std::auto_ptr<PacketMachine> fMachine; // The state machine for "active" snips.
+ std::unique_ptr<PacketMachine> fMachine; // The state machine for "active" snips.
InternalSnip ( XMP_Int64 offset, XMP_Int64 length );
InternalSnip ( const InternalSnip & );
diff --git a/samples/source/common/globals.h b/samples/source/common/globals.h
index 3998476..32c6a91 100644
--- a/samples/source/common/globals.h
+++ b/samples/source/common/globals.h
@@ -23,7 +23,7 @@
#ifdef WIN_ENV
#define XMPQE_LITTLE_ENDIAN 1
- #elif (defined(MAC_ENV) || defined(UNIX_ENV) || defined(IOS_ENV))
+ #elif (defined(MAC_ENV) || defined(IOS_ENV))
#if __BIG_ENDIAN__
#define XMPQE_BIG_ENDIAN 1
#elif __LITTLE_ENDIAN__
@@ -31,6 +31,13 @@
#else
#error "Neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__ is set"
#endif
+ #elif defined(UNIX_ENV)
+ #include "XMP_UnixEndian.h"
+ #if kBigEndianHost
+ #define XMPQE_BIG_ENDIAN 1
+ #else
+ #define XMPQE_BIG_ENDIAN 0
+ #endif
#else
#error "Unknown build environment, neither WIN_ENV nor MAC_ENV nor UNIX_ENV"
#endif
diff --git a/samples/source/xmpcommand/Actions.h b/samples/source/xmpcommand/Actions.h
index f43afbc..471daba 100644
--- a/samples/source/xmpcommand/Actions.h
+++ b/samples/source/xmpcommand/Actions.h
@@ -9,6 +9,11 @@
#ifndef __ACTIONS_h__
#define __ACTIONS_h__ 1
+// Hack because of the defines.
+#ifdef VERSION
+#undef VERSION
+#endif
+
class Actions {
public:
enum ACTION_TYPE { NONE, VERSION, INFO, PUT, GET, DUMP };
diff --git a/samples/source/xmpcommand/PrintUsage.cpp b/samples/source/xmpcommand/PrintUsage.cpp
index 957caff..8f0fee1 100644
--- a/samples/source/xmpcommand/PrintUsage.cpp
+++ b/samples/source/xmpcommand/PrintUsage.cpp
@@ -14,7 +14,7 @@ using namespace std;
namespace XMPQE {
- void PrintUsageShort(char* exename) {
+ void PrintUsageShort(const char* exename) {
Log::info("%s -version",exename);
Log::info(" Print version information for this utility");
Log::info("");
@@ -28,7 +28,7 @@ namespace XMPQE {
Log::info("");
}
- void PrintUsageLong(char* exename) {
+ void PrintUsageLong(const char* exename) {
Log::info("%s -version",exename);
Log::info(" Print version information for this utility");
Log::info("%s -help",exename);
@@ -64,7 +64,7 @@ namespace XMPQE {
Log::info(" into the specified mediafile.");
Log::info(" get <mediafile> Retrieves the XMP Packet contained in the specified mediafile.");
Log::info(" dump <mediafile> Prints the XMP Packet contained in the specified mediafile to standard output. ");
- Log::info(" <<??>> USE dump ONLY for known-good-output tests, do not use get. <<??>> ");
+ Log::info(" << ?? >> USE dump ONLY for known-good-output tests, do not use get. << ?? >> ");
Log::info("");
Log::info("Examples:");
Log::info("%s info Sample.jpg",exename);
diff --git a/samples/source/xmpcommand/PrintUsage.h b/samples/source/xmpcommand/PrintUsage.h
index 982fe41..b8d467b 100644
--- a/samples/source/xmpcommand/PrintUsage.h
+++ b/samples/source/xmpcommand/PrintUsage.h
@@ -10,8 +10,8 @@
#define __XMPQE_PRINT_USAGE_h__ 1
namespace XMPQE {
- void PrintUsageShort(char* exename);
- void PrintUsageLong(char* exename);
+ void PrintUsageShort(const char* exename);
+ void PrintUsageLong(const char* exename);
}
#endif
diff --git a/samples/testfiles/BlueSquare.gif b/samples/testfiles/BlueSquare.gif
new file mode 100644
index 0000000..7dcc9e7
--- /dev/null
+++ b/samples/testfiles/BlueSquare.gif
Binary files differ
diff --git a/samples/testfiles/BlueSquare.webp b/samples/testfiles/BlueSquare.webp
new file mode 100644
index 0000000..d68328e
--- /dev/null
+++ b/samples/testfiles/BlueSquare.webp
Binary files differ
diff --git a/samples/testfiles/Makefile.am b/samples/testfiles/Makefile.am
new file mode 100644
index 0000000..791f4be
--- /dev/null
+++ b/samples/testfiles/Makefile.am
@@ -0,0 +1,39 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+EXTRA_DIST=BlueSquare.ai BlueSquare.eps BlueSquare.gif BlueSquare.jpg BlueSquare.mp3 BlueSquare.png BlueSquare.tif\
+BlueSquare.avi BlueSquare.indd BlueSquare.mov BlueSquare.pdf BlueSquare.psd BlueSquare.wav BlueSquare.webp
diff --git a/source/EndianUtils.hpp b/source/EndianUtils.hpp
index 1ad23d6..6581f18 100644
--- a/source/EndianUtils.hpp
+++ b/source/EndianUtils.hpp
@@ -35,16 +35,7 @@
#error "Neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__ is set"
#endif
#elif XMP_UNIXBuild
- #ifndef kBigEndianHost // Typically in the makefile for generic UNIX.
- #if __GNUC__ && (__i386__ || __x86_64__)
- #define kBigEndianHost 0
- #elif __GNUC__ && (__sparc__)
- #define kBigEndianHost 1
- #define kLittleEndianHost 0
- #else
- #error "Must define kBigEndianHost as 0 or 1 in the makefile."
- #endif
- #endif
+ #include "public/include/XMP_UnixEndian.h"
#else
#error "Unknown build environment"
#endif
diff --git a/source/Host_IO-POSIX.cpp b/source/Host_IO-POSIX.cpp
index 5f71a28..09ec1d7 100644
--- a/source/Host_IO-POSIX.cpp
+++ b/source/Host_IO-POSIX.cpp
@@ -39,7 +39,7 @@
// =================================================================================================
// Make sure off_t is 64 bits and signed.
-static char check_off_t_size [ (sizeof(off_t) == 8) ? 1 : -1 ];
+// static char check_off_t_size [ (sizeof(off_t) == 8) ? 1 : -1 ];
// *** No std::numeric_limits? static char check_off_t_sign [ std::numeric_limits<off_t>::is_signed ? -1 : 1 ];
static bool HaveWriteAccess( const std::string & path );
@@ -372,7 +372,7 @@ void Host_IO::Write ( Host_IO::FileRef refNum, const void * buffer, XMP_Uns32 co
ssize_t bytesWritten = write ( refNum, buffer, count );
if ( bytesWritten != (ssize_t)count ) {
int osCode = errno; // Capture ASAP and once, might not be thread safe.
- if ( errno == ENOSPC ) {
+ if ( osCode == ENOSPC ) {
XMP_Throw ( "Host_IO::Write, disk full", kXMPErr_DiskSpace );
} else {
XMP_Throw ( "Host_IO::Write, write failure", kXMPErr_WriteError );
diff --git a/source/Makefile.am b/source/Makefile.am
new file mode 100644
index 0000000..681f98f
--- /dev/null
+++ b/source/Makefile.am
@@ -0,0 +1,60 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+noinst_LTLIBRARIES = libxmpcommon.la
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions
+AM_CPPFLAGS = -I$(top_srcdir) \
+ -Wall @XMPCORE_CPPFLAGS@
+
+noinst_HEADERS = UnicodeConversions.hpp ExpatAdapter.hpp EndianUtils.hpp\
+ XMLParserAdapter.hpp XMPFiles_IO.hpp Endian.h Host_IO.hpp XIO.hpp
+
+
+libxmpcommon_la_SOURCES = UnicodeInlines.incl_cpp UnicodeConversions.cpp\
+ XML_Node.cpp XMPFiles_IO.cpp \
+ XMP_LibUtils.hpp XMP_LibUtils.cpp \
+ XIO.cpp Host_IO-POSIX.cpp \
+ XMP_ProgressTracker.hpp XMP_ProgressTracker.cpp \
+ PerfUtils.hpp PerfUtils.cpp \
+ IOUtils.hpp IOUtils.cpp \
+ SafeStringAPIs.h SuppressSAL.h SafeTypes.h \
+ $(NULL)
+
+
+EXTRA_DIST = Host_IO-POSIX.cpp Host_IO-Win.cpp
diff --git a/source/XIO.cpp b/source/XIO.cpp
index d05180e..83c5bfd 100644
--- a/source/XIO.cpp
+++ b/source/XIO.cpp
@@ -37,8 +37,12 @@ static inline void MakeLowerCase ( std::string * str )
void XIO::SplitLeafName ( std::string * path, std::string * leafName )
{
size_t dirPos = path->size();
- // Return if path is empty or just the slash
- if ( dirPos == 0 || (dirPos == 1 && (*path)[dirPos-1] == kDirChar) )
+ // Return if path is empty or just the slash or DOT
+ if ( dirPos == 0 || (dirPos == 1 &&
+ ((*path)[dirPos-1] == kDirChar
+ || (*path)[dirPos-1] == '.')
+ )
+ )
{
leafName->erase();
path->erase();
diff --git a/source/XMLParserAdapter.hpp b/source/XMLParserAdapter.hpp
index b337cb6..2527862 100644
--- a/source/XMLParserAdapter.hpp
+++ b/source/XMLParserAdapter.hpp
@@ -90,10 +90,10 @@ public:
void ClearNode();
XML_Node ( XML_NodePtr _parent, XMP_StringPtr _name, XMP_Uns8 _kind )
- : kind(_kind), name(_name), parent(_parent), nsPrefixLen(0) {};
+ : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {};
XML_Node ( XML_NodePtr _parent, const std::string & _name, XMP_Uns8 _kind )
- : kind(_kind), name(_name), parent(_parent), nsPrefixLen(0) {};
+ : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {};
virtual ~XML_Node() { RemoveAttrs(); RemoveContent(); };
diff --git a/source/XMPFiles_IO.cpp b/source/XMPFiles_IO.cpp
index 3d3c45e..b613dbd 100644
--- a/source/XMPFiles_IO.cpp
+++ b/source/XMPFiles_IO.cpp
@@ -98,8 +98,8 @@ XMPFiles_IO::XMPFiles_IO (
, currOffset(0)
, isTemp(false)
, derivedTemp(0)
- , errorCallback(_errorCallback)
, progressTracker(_progressTracker)
+ , errorCallback(_errorCallback)
{
XMP_FILESIO_START
XMP_Assert ( this->fileRef != Host_IO::noFileRef );
diff --git a/source/XMP_LibUtils.hpp b/source/XMP_LibUtils.hpp
index e4477fa..aa937b6 100644
--- a/source/XMP_LibUtils.hpp
+++ b/source/XMP_LibUtils.hpp
@@ -85,7 +85,7 @@ public:
mutable XMP_Uns32 notifications;
mutable XMP_ErrorSeverity topSeverity;
- GenericErrorCallback() : notifications(0), limit(1), topSeverity(kXMPErrSev_Recoverable) {};
+ GenericErrorCallback() : limit(1), notifications(0), topSeverity(kXMPErrSev_Recoverable) {};
virtual ~GenericErrorCallback() {};
void Clear() { this->notifications = 0; this->limit = 1; this->topSeverity = kXMPErrSev_Recoverable; };
@@ -554,7 +554,7 @@ private:
#define IsHexDigit(ch) ( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) )
#define HexDigitValue(ch) ( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) )
-static const char * kTenSpaces = " ";
+#define kTenSpaces " "
#define OutProcPadding(pad) { size_t padLen = (pad); \
for ( ; padLen >= 10; padLen -= 10 ) OutProcNChars ( kTenSpaces, 10 ); \
for ( ; padLen > 0; padLen -= 1 ) OutProcNChars ( " ", 1 ); }
@@ -579,7 +579,7 @@ static const char * kTenSpaces = " ";
#define OutProcHexByte(num) { snprintf ( buffer, sizeof(buffer), "%.2X", (unsigned char)(num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \
XMP_Status _status = (*outProc) ( refCon, buffer, (XMP_StringLen)strlen(buffer) ); if ( _status != 0 ) return; }
-static const char * kIndent = " ";
+#define kIndent " "
#define OutProcIndent(lev) { for ( size_t i = 0; i < (lev); ++i ) OutProcNChars ( kIndent, 3 ); }
void DumpClearString ( const XMP_VarString & value, XMP_TextOutputProc outProc, void * refCon );
diff --git a/third-party/Makefile.am b/third-party/Makefile.am
new file mode 100644
index 0000000..211ebcf
--- /dev/null
+++ b/third-party/Makefile.am
@@ -0,0 +1,4 @@
+
+SUBDIRS = zuid/interfaces
+
+DIST_SUBDIRS = zuid/interfaces zlib expat
diff --git a/third-party/expat/Makefile.am b/third-party/expat/Makefile.am
new file mode 100644
index 0000000..c6f44fb
--- /dev/null
+++ b/third-party/expat/Makefile.am
@@ -0,0 +1,3 @@
+
+
+EXTRA_DIST=ReadMe.txt lib/expat.h
diff --git a/third-party/expat/lib/expat.h b/third-party/expat/lib/expat.h
new file mode 100644
index 0000000..cca1bc6
--- /dev/null
+++ b/third-party/expat/lib/expat.h
@@ -0,0 +1,3 @@
+// Exempi: use a system header instead
+#include <expat.h>
+
diff --git a/third-party/zlib/Makefile.am b/third-party/zlib/Makefile.am
new file mode 100644
index 0000000..3e40bb2
--- /dev/null
+++ b/third-party/zlib/Makefile.am
@@ -0,0 +1,3 @@
+
+
+EXTRA_DIST=ReadMe.txt zlib.h
diff --git a/third-party/zlib/zlib.h b/third-party/zlib/zlib.h
new file mode 100644
index 0000000..f4615cd
--- /dev/null
+++ b/third-party/zlib/zlib.h
@@ -0,0 +1,2 @@
+// Proxy. Use system zlib.
+#include <zlib.h>
diff --git a/third-party/zuid/interfaces/Makefile.am b/third-party/zuid/interfaces/Makefile.am
new file mode 100644
index 0000000..2a602a1
--- /dev/null
+++ b/third-party/zuid/interfaces/Makefile.am
@@ -0,0 +1,50 @@
+#
+# exempi - Makefile.am
+#
+# Copyright (C) 2007-2013 Hubert Figuiere
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1 Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2 Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the
+# distribution.
+#
+# 3 Neither the name of the Authors, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software wit hout specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+AM_CXXFLAGS = -Wno-multichar -Wno-ctor-dtor-privacy \
+ -funsigned-char -fexceptions
+AM_CPPFLAGS = -I$(top_srcdir)/public/include \
+ -I$(top_srcdir)/public/include/client-glue \
+ -I$(top_srcdir)/build/ \
+ -I$(top_srcdir) \
+ -Wall @XMPCORE_CPPFLAGS@
+
+noinst_LTLIBRARIES = libmd5.la
+
+
+
+libmd5_la_SOURCES = MD5.cpp MD5.h