[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