[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:39:15 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=e878166
The following commit has been merged in the master branch:
commit e878166f0d2af72c910f15fe8a85aefcf8be31b2
Author: Andreas Huggel <ahuggel at gmx.net>
Date: Wed Mar 5 07:45:16 2008 +0000
Improved XMP value toLong, toFloat and toRational using new functions parseLong, parseFloat and parseRational. (Vladimir Nadvornik)
---
samples/Makefile | 1 +
samples/stringto-test.cpp | 77 ++++++++++++++++++++++
samples/xmpsample.cpp | 61 +++++++++++++++++
src/crwimage.cpp | 6 +-
src/types.cpp | 99 ++++++++++++++++++++++++++++
src/types.hpp | 81 ++++++++++++++++++++++-
src/value.cpp | 12 ++--
src/xmp.hpp | 2 +-
test/Makefile | 4 +-
test/data/stringto-test.out | 24 +++++++
test/data/xmpparser-test.out | 4 +-
test/{makernote-test.sh => stringto-test.sh} | 8 +--
12 files changed, 356 insertions(+), 23 deletions(-)
diff --git a/samples/Makefile b/samples/Makefile
index 9a990e1..b36b2c1 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -69,6 +69,7 @@ BINSRC = addmoddel.cpp \
key-test.cpp \
largeiptc-test.cpp \
makernote-test.cpp \
+ stringto-test.cpp \
write-test.cpp \
write2-test.cpp \
tiffparse.cpp \
diff --git a/samples/stringto-test.cpp b/samples/stringto-test.cpp
new file mode 100644
index 0000000..973dcfc
--- /dev/null
+++ b/samples/stringto-test.cpp
@@ -0,0 +1,77 @@
+// ***************************************************************** -*- C++ -*-
+// stringto-test.cpp, $Rev$
+// Test conversions from string to long, float and Rational types.
+
+#include <exiv2/types.hpp>
+#include <exiv2/error.hpp>
+#include <iostream>
+#include <iomanip>
+
+const char* testcases[] = {
+ // bool
+ "True",
+ "False",
+ "t",
+ "f",
+ // long
+ "-1",
+ "0",
+ "1",
+ // float
+ "0.0",
+ "0.1",
+ "0.01",
+ "0.001",
+ "-1.49999",
+ "-1.5",
+ "1.49999",
+ "1.5",
+ // Rational
+ "0/1",
+ "1/1",
+ "1/3",
+ "-1/3",
+ "4/3",
+ "-4/3",
+ "0/0",
+ // nok
+ "text"
+};
+
+int main()
+{
+ std::cout << std::setfill(' ');
+
+ std::cout << std::setw(12) << std::left << "string";
+ std::cout << std::setw(12) << std::left << "long";
+ std::cout << std::setw(12) << std::left << "float";
+ std::cout << std::setw(12) << std::left << "Rational";
+
+ std::cout << std::endl;
+
+ for (unsigned int i = 0; i < EXV_COUNTOF(testcases); ++i) try {
+ std::string s(testcases[i]);
+ std::cout << std::setw(12) << std::left << s;
+ bool ok;
+
+ long l = Exiv2::parseLong(s, ok);
+ std::cout << std::setw(12) << std::left;
+ if (ok) std::cout << l; else std::cout << "nok";
+
+ float f = Exiv2::parseFloat(s, ok);
+ std::cout << std::setw(12) << std::left;
+ if (ok) std::cout << f; else std::cout << "nok";
+
+ Exiv2::Rational r = Exiv2::parseRational(s, ok);
+ if (ok) std::cout << r.first << "/" << r.second;
+ else std::cout << "nok";
+
+ std::cout << std::endl;
+ }
+ catch (Exiv2::AnyError& e) {
+ std::cout << "Caught Exiv2 exception '" << e << "'
";
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/samples/xmpsample.cpp b/samples/xmpsample.cpp
index b8416dc..7654134 100644
--- a/samples/xmpsample.cpp
+++ b/samples/xmpsample.cpp
@@ -8,6 +8,14 @@
#include <string>
#include <iostream>
#include <iomanip>
+#include <cassert>
+#include <cmath>
+
+bool isEqual(float a, float b)
+{
+ double d = std::fabs(a - b);
+ return d < 0.00001;
+}
int main()
try {
@@ -39,6 +47,59 @@ try {
// In addition, there is a dedicated assignment operator for Exiv2::Value
Exiv2::XmpTextValue val("Seven");
xmpData["Xmp.dc.seven"] = val;
+ xmpData["Xmp.dc.eight"] = true;
+
+ // Extracting values
+ assert(xmpData["Xmp.dc.one"].toLong() == -1);
+ assert(xmpData["Xmp.dc.one"].value().ok());
+
+ const Exiv2::Value &getv1 = xmpData["Xmp.dc.one"].value();
+ assert(isEqual(getv1.toFloat(), -1));
+ assert(getv1.ok());
+ assert(getv1.toRational() == Exiv2::Rational(-1, 1));
+ assert(getv1.ok());
+
+ const Exiv2::Value &getv2 = xmpData["Xmp.dc.two"].value();
+ assert(isEqual(getv2.toFloat(), 3.1415));
+ assert(getv2.ok());
+ assert(getv2.toLong() == 3);
+ assert(getv2.ok());
+ Exiv2::Rational R = getv2.toRational();
+ assert(getv2.ok());
+ assert(isEqual(static_cast<float>(R.first) / R.second, 3.1415 ));
+
+ const Exiv2::Value &getv3 = xmpData["Xmp.dc.three"].value();
+ assert(isEqual(getv3.toFloat(), 5.0/7.0));
+ assert(getv3.ok());
+ assert(getv3.toLong() == 0); // long(5.0 / 7.0)
+ assert(getv3.ok());
+ assert(getv3.toRational() == Exiv2::Rational(5, 7));
+ assert(getv3.ok());
+
+ const Exiv2::Value &getv6 = xmpData["Xmp.dc.six"].value();
+ assert(getv6.toLong() == 0);
+ assert(getv6.ok());
+ assert(getv6.toFloat() == 0.0);
+ assert(getv6.ok());
+ assert(getv6.toRational() == Exiv2::Rational(0, 1));
+ assert(getv6.ok());
+
+ const Exiv2::Value &getv7 = xmpData["Xmp.dc.seven"].value();
+ getv7.toLong(); // this should fail
+ assert(!getv7.ok());
+
+ const Exiv2::Value &getv8 = xmpData["Xmp.dc.eight"].value();
+ assert(getv8.toLong() == 1);
+ assert(getv8.ok());
+ assert(getv8.toFloat() == 1.0);
+ assert(getv8.ok());
+ assert(getv8.toRational() == Exiv2::Rational(1, 1));
+ assert(getv8.ok());
+
+ // Deleting an XMP property
+ Exiv2::XmpData::iterator pos = xmpData.findKey(Exiv2::XmpKey("Xmp.dc.eight"));
+ if (pos == xmpData.end()) throw Exiv2::Error(1, "Key not found");
+ xmpData.erase(pos);
// -------------------------------------------------------------------------
// Exiv2 has specialized values for simple XMP properties, arrays of simple
diff --git a/src/crwimage.cpp b/src/crwimage.cpp
index b2a53cb..8808756 100644
--- a/src/crwimage.cpp
+++ b/src/crwimage.cpp
@@ -960,11 +960,7 @@ namespace Exiv2 {
if (ifdId == canonSiIfdId) {
// Exif.Photo.FNumber
float f = fnumber(canonEv(aperture));
- // Beware: primitive conversion algorithm
- uint32_t den = 1000000;
- uint32_t nom = static_cast<uint32_t>(f * den);
- uint32_t g = gcd(nom, den);
- URational ur(nom/g, den/g);
+ URational ur = floatToRationalCast(f);
URationalValue fn;
fn.value_.push_back(ur);
image.exifData().add(ExifKey("Exif.Photo.FNumber"), &fn);
diff --git a/src/types.cpp b/src/types.cpp
index b3f5d3a..b162fd7 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -43,6 +43,7 @@ EXIV2_RCSID("@(#) $Id$")
#include <cctype>
#include <ctime>
#include <cstdio>
+#include <cstdlib>
#include <cassert>
#include <cstring>
@@ -349,6 +350,104 @@ namespace Exiv2 {
return str;
#endif
}
+
+ template<>
+ bool stringTo<bool>(const std::string& s, bool& ok)
+ {
+ std::string lcs(s); /* lowercase string */
+ for(unsigned i = 0; i < lcs.length(); i++) {
+ lcs[i] = std::tolower(s[i]);
+ }
+ /* handle the same values as xmp sdk */
+ if (lcs == "false" || lcs == "f" || lcs == "0") {
+ ok = true;
+ return false;
+ }
+ if (lcs == "true" || lcs == "t" || lcs == "1") {
+ ok = true;
+ return true;
+ }
+ ok = false;
+ return false;
+ }
+
+ long parseLong(const std::string& s, bool& ok)
+ {
+ long ret = stringTo<long>(s, ok);
+ if (ok) return ret;
+
+ float f = stringTo<float>(s, ok);
+ if (ok) return static_cast<long>(f);
+
+ Rational r = stringTo<Rational>(s, ok);
+ if (ok) {
+ if (r.second == 0) {
+ ok = false;
+ return 0;
+ }
+ return static_cast<long>(static_cast<float>(r.first) / r.second);
+ }
+
+ bool b = stringTo<bool>(s, ok);
+ if (ok) return b ? 1 : 0;
+
+ // everything failed, return from stringTo<long> is probably the best fit
+ return ret;
+ }
+
+ float parseFloat(const std::string& s, bool& ok)
+ {
+ float ret = stringTo<float>(s, ok);
+ if (ok) return ret;
+
+ Rational r = stringTo<Rational>(s, ok);
+ if (ok) {
+ if (r.second == 0) {
+ ok = false;
+ return 0.0;
+ }
+ return static_cast<float>(r.first) / r.second;
+ }
+
+ bool b = stringTo<bool>(s, ok);
+ if (ok) return b ? 1.0 : 0.0;
+
+ // everything failed, return from stringTo<float> is probably the best fit
+ return ret;
+ }
+
+ Rational parseRational(const std::string& s, bool& ok)
+ {
+ Rational ret = stringTo<Rational>(s, ok);
+ if (ok) return ret;
+
+ long l = stringTo<long>(s, ok);
+ if (ok) return Rational(l, 1);
+
+ float f = stringTo<float>(s, ok);
+ if (ok) return floatToRationalCast(f);
+
+ bool b = stringTo<bool>(s, ok);
+ if (ok) return b ? Rational(1, 1) : Rational(0, 1);
+
+ // everything failed, return from stringTo<Rational> is probably the best fit
+ return ret;
+ }
+
+ Rational floatToRationalCast(float f)
+ {
+ // Beware: primitive conversion algorithm
+ int32_t den = 1000000;
+ if (std::labs(static_cast<long>(f)) > 2147) den = 10000;
+ if (std::labs(static_cast<long>(f)) > 214748) den = 100;
+ if (std::labs(static_cast<long>(f)) > 21474836) den = 1;
+ const float rnd = f >= 0 ? 0.5 : -0.5;
+ const int32_t nom = static_cast<int32_t>(f * den + rnd);
+ const int32_t g = gcd(nom, den);
+
+ return Rational(nom/g, den/g);
+ }
+
} // namespace Exiv2
#ifdef EXV_ENABLE_NLS
diff --git a/src/types.hpp b/src/types.hpp
index 3664e64..40407f2 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -321,6 +321,58 @@ namespace Exiv2 {
*/
const char* exvGettext(const char* str);
+ /*!
+ @brief Return a \em long set to the value represented by \em s.
+
+ Besides strings that represent \em long values, the function also
+ handles \em float, \em Rational and boolean
+ (see also: stringTo(const std::string& s, bool& ok)).
+
+ @param s String to parse
+ @param ok Output variable indicating the success of the operation.
+ @return Returns the \em long value represented by \em s and sets \em ok
+ to
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list