[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:35:56 UTC 2017


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=440571b

The following commit has been merged in the master branch:
commit 440571b5447dde7eba1c735091344f1fa7f99b9c
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Sun Jan 18 16:53:12 2004 +0000

    Values implemented
---
 src/exif.cpp     | 226 +++++++++++++++++++++++++++++++------------
 src/exif.hpp     | 286 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/exiftest.cpp |  48 ++++++----
 src/tags.cpp     |  52 ++++++++--
 src/tags.hpp     |  45 +++++++--
 5 files changed, 524 insertions(+), 133 deletions(-)

diff --git a/src/exif.cpp b/src/exif.cpp
index 70cfd0a..4183ccc 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -12,7 +12,7 @@
 
   RCS information
    $Name:  $
-   $Revision: 1.3 $
+   $Revision: 1.4 $
  */
 // *****************************************************************************
 // included header files
@@ -24,6 +24,7 @@
 #include <iomanip>
 #include <sstream>
 #include <fstream>
+#include <utility>
 
 #include <cstring>
 
@@ -101,15 +102,15 @@ namespace Exif {
         if (getUShort(marker, bigEndian) != app1_) return 3;
 
         // Read the length of the APP1 field and the Exif identifier
-        char buf[8];
-        ::memset(buf, 0x0, 8);
-        is.read(buf, 8);
+        char tmpbuf[8];
+        ::memset(tmpbuf, 0x0, 8);
+        is.read(tmpbuf, 8);
         if (!is.good()) return 1;
         // Get the length of the APP1 field and do a plausibility check
-        long app1Length = getUShort(buf, bigEndian);
+        long app1Length = getUShort(tmpbuf, bigEndian);
         if (app1Length < 8) return 4;
         // Check the Exif identifier
-        if (::memcmp(buf+2, exifId_, 6) != 0) return 4;
+        if (::memcmp(tmpbuf+2, exifId_, 6) != 0) return 4;
  
         // Read the rest of the APP1 field (Exif data)
         long sizeExifData = app1Length - 8;
@@ -166,95 +167,112 @@ namespace Exif {
         return size();
     }
 
-    Value* Value::create(TypeId typeId, ByteOrder byteOrder)
+    Value* Value::create(TypeId typeId)
     {
         Value* value = 0;
         switch (typeId) {
         case invalid:
+            value = new DataValue(invalid);
             break;
         case unsignedByte:
-            value = new AsciiValue;
+            value = new DataValue(unsignedByte);
             break;
         case asciiString:
             value =  new AsciiValue;
             break;
         case unsignedShort:
-            value = new UShortValue(byteOrder);
+            value = new ValueType<uint16>;
             break;
         case unsignedLong:
+            value = new ValueType<uint32>;
+            break;
         case unsignedRational:
-        case signedByte:
+            value = new ValueType<URational>;
+            break;
+        case invalid6:
+            value = new DataValue(invalid6);
+            break;
         case undefined:
+            value = new DataValue;
+            break;
         case signedShort:
+            value = new ValueType<int16>;
+            break;
         case signedLong:
+            value = new ValueType<int32>;
+            break;
         case signedRational:
-        case singleFloat:
-        case doubleFloat:
-            value = new AsciiValue;
+            value = new ValueType<Rational>;
             break;
         }
         return value;
     } // Value::create
 
-    void AsciiValue::read(const char* buf, long len)
+    void DataValue::read(const char* buf, long len, ByteOrder byteOrder)
     {
+        // byteOrder not needed 
         value_ = std::string(buf, len);
     }
 
-    void AsciiValue::read(const std::string& buf)
+    void DataValue::read(const std::string& buf)
     {
+        // Todo: read from a string of bytes??
         value_ = buf;
     }
 
-    long AsciiValue::copy(char* buf) const
+    long DataValue::copy(char* buf, ByteOrder byteOrder) const
     {
+        // byteOrder not needed
         return value_.copy(buf, value_.size());
     }
 
-    long AsciiValue::size() const
+    long DataValue::size() const
     {
         return value_.size();
     }
 
-    Value* AsciiValue::clone() const
+    Value* DataValue::clone() const
     {
-        return new AsciiValue(*this);
+        return new DataValue(*this);
     }
 
-    std::ostream& AsciiValue::write(std::ostream& os) const
+    std::ostream& DataValue::write(std::ostream& os) const
     {
-        return os << value_;
+        std::string::size_type end = value_.size();
+        for (std::string::size_type i = 0; i != end; ++i) {
+            os << (int)(unsigned char)value_[i] << " ";
+        }
+        return os;
     }
 
-    void UShortValue::read(const char* buf, long len)
+    void AsciiValue::read(const char* buf, long len, ByteOrder byteOrder)
     {
-        // Todo: Should we check to make sure that len is 2
-        value_ = getUShort(buf, byteOrder_);
+        // byteOrder not needed 
+        value_ = std::string(buf, len);
     }
 
-    void UShortValue::read(const std::string& buf)
+    void AsciiValue::read(const std::string& buf)
     {
-        std::istringstream is(buf);
-        is >> value_;
+        value_ = buf;
     }
 
-    long UShortValue::copy(char* buf) const
+    long AsciiValue::copy(char* buf, ByteOrder byteOrder) const
     {
-        us2Data(buf, value_, byteOrder_);
-        return size();
+        // byteOrder not needed
+        return value_.copy(buf, value_.size());
     }
 
-    long UShortValue::size() const
+    long AsciiValue::size() const
     {
-        return 2;
+        return value_.size();
     }
 
-    Value* UShortValue::clone() const
+    Value* AsciiValue::clone() const
     {
-        return new UShortValue(*this);
+        return new AsciiValue(*this);
     }
 
-    std::ostream& UShortValue::write(std::ostream& os) const
+    std::ostream& AsciiValue::write(std::ostream& os) const
     {
         return os << value_;
     }
@@ -287,6 +305,8 @@ namespace Exif {
 
     Metadatum& Metadatum::operator=(const Metadatum& rhs)
     {
+        if (this == &rhs) return *this;
+
         tag_ = rhs.tag_;
         type_ = rhs.type_;
         count_ = rhs.count_;
@@ -361,15 +381,15 @@ namespace Exif {
         for (i = eb; i != ee; ++i) {
             delete i->value_;
             //! Todo: Create the correct type here, once we have them
-            i->value_ = Value::create(TypeId(i->type_), byteOrder);
+            i->value_ = Value::create(TypeId(i->type_));
             if (i->size_ > 4) {
                 i->offset_ = i->offset_ - offset_;
-                i->value_->read(buf + i->offset_, i->size_);
+                i->value_->read(buf + i->offset_, i->size_, byteOrder);
             }
             else {
-                char value[4];
-                ul2Data(value, i->offset_, byteOrder);
-                i->value_->read(value, 4);
+                char tmpbuf[4];
+                ul2Data(tmpbuf, i->offset_, byteOrder);
+                i->value_->read(tmpbuf, i->size_, byteOrder);
             }
         }
         return 0;
@@ -411,7 +431,10 @@ namespace Exif {
                 dataSize += i->size_;
             }
             else {
-                ul2Data(buf+o+8, i->offset_, byteOrder);
+                char tmpbuf[4];
+                ::memset(tmpbuf, 0x0, 4);
+                i->value_->copy(tmpbuf, byteOrder);
+                ::memcpy(buf+o+8, tmpbuf, 4);
             }
             o += 12;
         }
@@ -432,7 +455,7 @@ namespace Exif {
                 // Todo: Check this! There seems to be an inconsistency
                 // in the use of size_ and the return value of copy() here
                 // Todo: And can value_ be 0?
-                o += i->value_->copy(buf+o);
+                o += i->value_->copy(buf+o, byteOrder);
             }
         }
 
@@ -449,7 +472,7 @@ namespace Exif {
            << ",   IFD Entries: " 
            << std::setfill(' ') << std::dec << std::right
            << entries_.size() << "
"
-           << prefix << "Entry     Tag  Format   (Bytes each)  Number  Offset/Data
"
+           << prefix << "Entry     Tag  Format   (Bytes each)  Number  Offset
"
            << prefix << "-----  ------  ---------------------  ------  -----------
";
 
         const Metadata::const_iterator b = entries_.begin();
@@ -458,19 +481,22 @@ namespace Exif {
         for (; i != e; ++i) {
             std::ostringstream offset;
             if (i->typeSize() * i->count_ <= 4) {
-                // Minor cheat here: we use value_ instead of offset_ to avoid
-                // having to invoke ul2Data() which would require byte order.
-                // Todo: can value_ be 0 here?
-                char tmpbuf[4];
-                i->value_->copy(tmpbuf);
-                offset << std::setw(2) << std::setfill('0') << std::hex
-                       << (int)*(unsigned char*)tmpbuf << " "
-                       << std::setw(2) << std::setfill('0') << std::hex
-                       << (int)*(unsigned char*)(tmpbuf+1) << " "
-                       << std::setw(2) << std::setfill('0') << std::hex 
-                       << (int)*(unsigned char*)(tmpbuf+2) << " "
-                       << std::setw(2) << std::setfill('0') << std::hex
-                       << (int)*(unsigned char*)(tmpbuf+3) << " ";
+
+// Todo: Fix me! This doesn't work with Value anymore because we do not know
+// the byte order here. (Wait for Ifd to use a more special type)
+//
+//              char tmpbuf[4];
+//              i->value_->copy(tmpbuf, byteOrder);
+//              offset << std::setw(2) << std::setfill('0') << std::hex
+//                     << (int)*(unsigned char*)tmpbuf << " "
+//                     << std::setw(2) << std::setfill('0') << std::hex
+//                     << (int)*(unsigned char*)(tmpbuf+1) << " "
+//                     << std::setw(2) << std::setfill('0') << std::hex
+//                     << (int)*(unsigned char*)(tmpbuf+2) << " "
+//                     << std::setw(2) << std::setfill('0') << std::hex
+//                     << (int)*(unsigned char*)(tmpbuf+3) << " ";
+
+                offset << "n/a";
             }
             else {
                 offset << " 0x" << std::setw(8) << std::setfill('0') << std::hex
@@ -622,13 +648,80 @@ namespace Exif {
         }
     }
 
-    std::string getString(const char* buf, long len)
+    URational getURational(const char* buf, ByteOrder byteOrder)
+    {
+        uint32 nominator = getULong(buf, byteOrder);
+        uint32 denominator = getULong(buf + 4, byteOrder);
+        return std::make_pair(nominator, denominator);
+    }
+
+    int16 getShort(const char* buf, ByteOrder byteOrder)
+    {
+        if (byteOrder == littleEndian) {
+            return (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
+        }
+        else {
+            return (unsigned char)buf[0] << 8 | (unsigned char)buf[1];
+        }
+    }
+
+    int32 getLong(const char* buf, ByteOrder byteOrder)
+    {
+        if (byteOrder == littleEndian) {
+            return   (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16 
+                   | (unsigned char)buf[1] <<  8 | (unsigned char)buf[0];
+        }
+        else {
+            return   (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16 
+                   | (unsigned char)buf[2] <<  8 | (unsigned char)buf[3];
+        }
+    }
+
+    Rational getRational(const char* buf, ByteOrder byteOrder)
+    {
+        int32 nominator = getLong(buf, byteOrder);
+        int32 denominator = getLong(buf + 4, byteOrder);
+        return std::make_pair(nominator, denominator);
+    }
+
+    long us2Data(char* buf, uint16 s, ByteOrder byteOrder)
+    {
+        if (byteOrder == littleEndian) {
+            buf[0] =  s & 0x00ff;
+            buf[1] = (s & 0xff00) >> 8;
+        }
+        else {
+            buf[0] = (s & 0xff00) >> 8;
+            buf[1] =  s & 0x00ff;
+        }
+        return 2;
+    }
+
+    long ul2Data(char* buf, uint32 l, ByteOrder byteOrder)
+    {
+        if (byteOrder == littleEndian) {
+            buf[0] =  l & 0x000000ff;
+            buf[1] = (l & 0x0000ff00) >> 8;
+            buf[2] = (l & 0x00ff0000) >> 16;
+            buf[3] = (l & 0xff000000) >> 24;
+        }
+        else {
+            buf[0] = (l & 0xff000000) >> 24;
+            buf[1] = (l & 0x00ff0000) >> 16;
+            buf[2] = (l & 0x0000ff00) >> 8;
+            buf[3] =  l & 0x000000ff;
+        }
+        return 4;
+    }
+
+    long ur2Data(char* buf, URational l, ByteOrder byteOrder)
     {
-        std::string txt(buf, len);
-        return txt;
+        long o = ul2Data(buf, l.first, byteOrder);
+        o += ul2Data(buf+o, l.second, byteOrder);
+        return o;
     }
 
-    char* us2Data(char* buf, uint16 s, ByteOrder byteOrder)
+    long s2Data(char* buf, int16 s, ByteOrder byteOrder)
     {
         if (byteOrder == littleEndian) {
             buf[0] =  s & 0x00ff;
@@ -638,10 +731,10 @@ namespace Exif {
             buf[0] = (s & 0xff00) >> 8;
             buf[1] =  s & 0x00ff;
         }
-        return buf;
+        return 2;
     }
 
-    char* ul2Data(char* buf, uint32 l, ByteOrder byteOrder)
+    long l2Data(char* buf, int32 l, ByteOrder byteOrder)
     {
         if (byteOrder == littleEndian) {
             buf[0] =  l & 0x000000ff;
@@ -655,7 +748,14 @@ namespace Exif {
             buf[2] = (l & 0x0000ff00) >> 8;
             buf[3] =  l & 0x000000ff;
         }
-        return buf;
+        return 4;
+    }
+
+    long r2Data(char* buf, Rational l, ByteOrder byteOrder)
+    {
+        long o = l2Data(buf, l.first, byteOrder);
+        o += l2Data(buf+o, l.second, byteOrder);
+        return o;
     }
 
     void hexdump(std::ostream& os, const char* buf, long len)
diff --git a/src/exif.hpp b/src/exif.hpp
index a5f2b11..5150842 100644
--- a/src/exif.hpp
+++ b/src/exif.hpp
@@ -8,7 +8,7 @@
 /*!
   @file    exif.hpp
   @brief   Encoding and decoding of %Exif data
-  @version $Name:  $ $Revision: 1.3 $
+  @version $Name:  $ $Revision: 1.4 $
   @author  Andreas Huggel (ahu)
   @date    09-Jan-03, ahu: created
  */
@@ -22,7 +22,8 @@
 // + standard includes
 #include <string>
 #include <vector>
-#include <iosfwd>
+#include <iostream>
+#include <sstream>
 
 // *****************************************************************************
 // namespace extensions
@@ -145,7 +146,14 @@ namespace Exif {
         uint32 offset_;
     }; // class TiffHeader
 
-    //! Common interface for all values 
+    /*!
+      @brief Common interface for all values. The interface provides a uniform
+             way to access values independent from their actual C++ type for 
+             simple tasks like reading the values. For other tasks, like modifying
+             values you need to downcast it to the actual subclass of Value so
+             that you can access the subclass specific interface (e.g., assignment
+             operator for a vector of unsigned longs). 
+     */
     class Value {
     public:
         //! Constructor, taking a type id to initialize the base class with
@@ -157,8 +165,9 @@ namespace Exif {
 
           @param buf Pointer to the data buffer to read from
           @param len Number of bytes in the data buffer 
+          @param byteOrder Applicable byte order (little or big endian).
          */
-        virtual void read(const char* buf, long len) =0;
+        virtual void read(const char* buf, long len, ByteOrder byteOrder) =0;
         //! Set the value from a string buffer
         virtual void read(const std::string& buf) =0;
         /*!
@@ -168,13 +177,14 @@ namespace Exif {
           the call results in undefined behaviour.
 
           @param buf Data buffer to write to.
+          @param byteOrder Applicable byte order (little or big endian).
           @return Number of characters written.
         */
-        virtual long copy(char* buf) const =0;
-        //! Returns the size of the value in bytes
+        virtual long copy(char* buf, ByteOrder byteOrder) const =0;
+        //! Return the size of the value in bytes
         virtual long size() const =0;
         /*!
-          @brief Returns a pointer to a copy of itself (deep copy).
+          @brief Return a pointer to a copy of itself (deep copy).
                  The caller owns this copy and is responsible to delete it!
          */
         virtual Value* clone() const =0;
@@ -185,12 +195,10 @@ namespace Exif {
           @brief A (simple) factory to create a Value type.
 
           @param typeId Type of the value.
-          @param byteOrder Applicable byte order (little or big endian).
-
           @return Pointer to the newly created Value.
                   The caller owns this copy and is responsible to delete it!
          */
-        static Value* create(TypeId typeId, ByteOrder byteOrder);
+        static Value* create(TypeId typeId);
 
     protected:
         const TypeId typeId_;                   //!< Format type identifier
@@ -203,14 +211,31 @@ namespace Exif {
         return value.write(os);
     }
 
-    //! %Value representing an Ascii string type.
+    //! %Value for an undefined data type.
+    class DataValue : public Value {
+    public:
+        //! Default constructor.
+        DataValue(TypeId typeId =undefined) : Value(typeId) {}
+        virtual void read(const char* buf, long len, ByteOrder byteOrder);
+        virtual void read(const std::string& buf);
+        virtual long copy(char* buf, ByteOrder byteOrder) const;
+        virtual long size() const;
+        virtual Value* clone() const;
+        virtual std::ostream& write(std::ostream& os) const;
+
+    private:
+        std::string value_;
+
+    };
+
+    //! %Value for an Ascii string type.
     class AsciiValue : public Value {
     public:
         //! Default constructor.
         AsciiValue() : Value(asciiString) {}
-        virtual void read(const char* buf, long len);
+        virtual void read(const char* buf, long len, ByteOrder byteOrder);
         virtual void read(const std::string& buf);
-        virtual long copy(char* buf) const;
+        virtual long copy(char* buf, ByteOrder byteOrder) const;
         virtual long size() const;
         virtual Value* clone() const;
         virtual std::ostream& write(std::ostream& os) const;
@@ -220,22 +245,25 @@ namespace Exif {
 
     };
 
-    //! %Value representing one unsigned short type.
-    class UShortValue : public Value {
+    /*!
+      @brief Template for a %Value for a basic Type. This is used for unsigned 
+             and signed short, long and rational.
+     */    
+    template<typename T>
+    class ValueType : public Value {
     public:
-        //! Constructor, taking the byte order (endianness) as argument
-        UShortValue(ByteOrder byteOrder)
-            : Value(unsignedShort), byteOrder_(byteOrder) {}
-        virtual void read(const char* buf, long len);
+        //! Default constructor.
+        ValueType() : Value(getType<T>()) {}
+        virtual void read(const char* buf, long len, ByteOrder byteOrder);
         virtual void read(const std::string& buf);
-        virtual long copy(char* buf) const;
+        virtual long copy(char* buf, ByteOrder byteOrder) const;
         virtual long size() const;
         virtual Value* clone() const;
         virtual std::ostream& write(std::ostream& os) const;
 
     private:
-        ByteOrder byteOrder_;
-        uint16 value_;
+        typedef std::vector<T> ValueList;
+        ValueList value_;
 
     };
 
@@ -252,9 +280,9 @@ namespace Exif {
         //! Return the name of the type
         const char* tagName() const { return ExifTags::tagName(tag_, ifdId_); }
         //! Return the name of the type
-        const char* typeName() const { return ExifTags::typeName(type_); }
+        const char* typeName() const { return ExifTags::typeName(TypeId(type_)); }
         //! Return the size in bytes of one element of this type
-        long typeSize() const { return ExifTags::typeSize(type_); }
+        long typeSize() const { return ExifTags::typeSize(TypeId(type_)); }
         //! Return the name of the IFD
         const char* ifdName() const { return ExifTags::ifdName(ifdId_); }
         //! Return the related image item (image or thumbnail)
@@ -273,7 +301,7 @@ namespace Exif {
 
     public:
         uint16 tag_;                   //!< Tag value
-        uint16 type_;                  //!< Type of the data
+        uint16 type_;                  //!< Type of the data Todo: change to TypeId?
         uint32 count_;                 //!< Number of components
         uint32 offset_;                //!< Offset of the data from start of IFD
         long size_;                    //!< Size of the data in bytes
@@ -445,28 +473,220 @@ namespace Exif {
         TiffHeader tiffHeader_;
         Metadata metadata_;
     }; // class ExifData
-   
+
 // *****************************************************************************
 // free functions
 
     //! Read a 2 byte unsigned short value from the data buffer
     uint16 getUShort(const char* buf, ByteOrder byteOrder);
-
     //! Read a 4 byte unsigned long value from the data buffer
     uint32 getULong(const char* buf, ByteOrder byteOrder);
+    //! Read an 8 byte unsigned rational value from the data buffer
+    URational getURational(const char* buf, ByteOrder byteOrder);
+    //! Read a 2 byte signed short value from the data buffer
+    int16 getShort(const char* buf, ByteOrder byteOrder);
+    //! Read a 4 byte signed long value from the data buffer
+    int32 getLong(const char* buf, ByteOrder byteOrder);
+    //! Read an 8 byte signed rational value from the data buffer
+    Rational getRational(const char* buf, ByteOrder byteOrder);
+
+    /*!
+      @brief Read a value of type T from the data buffer.
+
+      We need this template function for the ValueType template classes. 
+      There are only specializations of this function available; no default
+      implementation is provided.
+
+      @param buf Pointer to the data buffer to read from.
+      @param byteOrder Applicable byte order (little or big endian).
+      @return A value of type T.
+     */
+    template<typename T> T getValue(const char* buf, ByteOrder byteOrder);
+    // Specialization for a 2 byte unsigned short value.
+    template<> inline uint16 getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getUShort(buf, byteOrder);
+    }
+    // Specialization for a 4 byte unsigned long value.
+    template<> inline uint32 getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getULong(buf, byteOrder);
+    }
+    // Specialization for an 8 byte unsigned rational value.
+    template<> inline URational getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getURational(buf, byteOrder);
+    }
+    // Specialization for a 2 byte signed short value.
+    template<> inline int16 getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getShort(buf, byteOrder);
+    }
+    // Specialization for a 4 byte signed long value.
+    template<> inline int32 getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getLong(buf, byteOrder);
+    }
+    // Specialization for an 8 byte signed rational value.
+    template<> inline Rational getValue(const char* buf, ByteOrder byteOrder)
+    {
+        return getRational(buf, byteOrder);
+    }
+
+    /*!
+      @brief Convert an unsigned short to data, write the data to the buffer, 
+             return number of bytes written.
+     */
+    long us2Data(char* buf, uint16 s, ByteOrder byteOrder);
+    /*!
+      @brief Convert an unsigned long to data, write the data to the buffer,
+             return number of bytes written.
+     */
+    long ul2Data(char* buf, uint32 l, ByteOrder byteOrder);
+    /*!
+      @brief Convert an unsigned rational to data, write the data to the buffer,
+             return number of bytes written.
+     */
+    long ur2Data(char* buf, URational l, ByteOrder byteOrder);
+    /*!
+      @brief Convert a signed short to data, write the data to the buffer, 
+             return number of bytes written.
+     */
+    long s2Data(char* buf, int16 s, ByteOrder byteOrder);
+    /*!
+      @brief Convert a signed long to data, write the data to the buffer,
+             return number of bytes written.
+     */
+    long l2Data(char* buf, int32 l, ByteOrder byteOrder);
+    /*!
+      @brief Convert a signed rational to data, write the data to the buffer,
+             return number of bytes written.
+     */
+    long r2Data(char* buf, Rational l, ByteOrder byteOrder);
 
-    //! Convert len bytes from the data buffer into a string
-    std::string getString(const char* buf, long len);
+    /*!
+      @brief Convert a value of type T to data, write the data to the data buffer.
 
-    //! Write an unsigned short to the data buffer
-    char* us2Data(char* buf, uint16 s, ByteOrder byteOrder);
+      We need this template function for the ValueType template classes. 
+      There are only specializations of this function available; no default
+      implementation is provided.
 
-    //! Convert an unsigned long to data, write the data to the buffer
-    char* ul2Data(char* buf, uint32 l, ByteOrder byteOrder);
+      @param buf Pointer to the data buffer to write to.
+      @param t Value to be converted.
+      @param byteOrder Applicable byte order (little or big endian).
+      @return The number of bytes written to the buffer.
+     */
+    template<typename T> long toData(char* buf, T t, ByteOrder byteOrder);
+    /*! 
+      @brief Specialization to write an unsigned short to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, uint16 t, ByteOrder byteOrder)
+    {
+        return us2Data(buf, t, byteOrder);
+    }
+    /*! 
+      @brief Specialization to write an unsigned long to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, uint32 t, ByteOrder byteOrder)
+    {
+        return ul2Data(buf, t, byteOrder);
+    }
+    /*!
+      @brief Specialization to write an unsigned rational to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, URational t, ByteOrder byteOrder)
+    {
+        return ur2Data(buf, t, byteOrder);
+    }
+    /*! 
+      @brief Specialization to write a signed short to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, int16 t, ByteOrder byteOrder)
+    {
+        return s2Data(buf, t, byteOrder);
+    }
+    /*! 
+      @brief Specialization to write a signed long to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, int32 t, ByteOrder byteOrder)
+    {
+        return l2Data(buf, t, byteOrder);
+    }
+    /*!
+      @brief Specialization to write a signed rational to the data buffer.
+             Return the number of bytes written.
+     */
+    template<> inline long toData(char* buf, Rational t, ByteOrder byteOrder)
+    {
+        return r2Data(buf, t, byteOrder);
+    }
 
     //! Print len bytes from buf in hex and ASCII format to the given stream
     void hexdump(std::ostream& os, const char* buf, long len);
 
+// *****************************************************************************
+// template definitions
+
+    template<typename T>
+    void ValueType<T>::read(const char* buf, long len, ByteOrder byteOrder)
+    {
+        value_.clear();
+        for (long i = 0; i < len; i += ExifTags::typeSize(typeId_)) {
+            value_.push_back(getValue<T>(buf + i, byteOrder));
+        }
+    }
+
+    template<typename T>
+    void ValueType<T>::read(const std::string& buf)
+    {
+        std::istringstream is(buf);
+        T tmp;
+        value_.clear();
+        while (is >> tmp) {
+            value_.push_back(tmp);
+        }
+    }
+
+    template<typename T>
+    long ValueType<T>::copy(char* buf, ByteOrder byteOrder) const
+    {
+        long offset = 0;
+        typename ValueList::const_iterator end = value_.end();
+        for (typename ValueList::const_iterator i = value_.begin(); i != end; ++i) {
+            offset += toData(buf + offset, *i, byteOrder);
+        }
+        return offset;
+    }
+
+    template<typename T>
+    long ValueType<T>::size() const
+    {
+        return ExifTags::typeSize(typeId_) * value_.size();
+    }
+
+    template<typename T>
+    Value* ValueType<T>::clone() const
+    {
+        return new ValueType(*this);
+    }
+
+    template<typename T>
+    std::ostream& ValueType<T>::write(std::ostream& os) const
+    {
+        typename ValueList::const_iterator end = value_.end();
+        typename ValueList::const_iterator i = value_.begin();
+        while (i != end) {
+            os << *i;
+            if (++i != end) os << " ";
+        }
+        return os;
+    }
+   
 }                                       // namespace Exif
 
 #endif                                  // #ifndef _EXIF_HPP_
diff --git a/src/exiftest.cpp b/src/exiftest.cpp
index 4c7dd81..2bcb1ef 100644
--- a/src/exiftest.cpp
+++ b/src/exiftest.cpp
@@ -1,3 +1,4 @@
+#include "tags.hpp"
 #include "exif.hpp"
 #include <iostream>
 #include <iomanip>
@@ -19,34 +20,39 @@ int main(int argc, char* const argv[])
         ExifData::const_iterator end = exifData.end();
         ExifData::const_iterator i = beg;
         for (; i != end; ++i) {
-
             std::cout << "0x" 
                       << std::hex << std::setw(4) << std::setfill('0') << std::right
                       << i->tag_ << " " 
-                      << std::setw(50) << std::setfill(' ') << std::left
-                      << i->key() << " ";
-
-            if (i->type_ == 2 || i->type_ == 3) {
-                std::cout << std::dec << i->value() << "
";
-            }
-            else {
-                std::cout << std::setw(17) << std::setfill(' ') << std::left
-                          << i->typeName() << " "
-                          << std::dec << std::setw(3) 
-                          << std::setfill(' ') << std::right
-                          << i->count_ << " " 
-                          << std::dec << std::setw(3)
-                          << std::setfill(' ') << std::right
-                          << i->typeSize() * i->count_ << "
";
-            }
-
+                      << std::setw(27) << std::setfill(' ') << std::left
+                      << i->tagName() << " "
+                      << std::setw(17) << std::setfill(' ') << std::left
+                      << i->typeName() << " "
+                      << std::dec << std::setw(3) 
+                      << std::setfill(' ') << std::right
+                      << i->count_ << " " 
+                      << std::dec << i->value() << "
";
         }
     }
 
-    std::string tmp = "12";
-    Value* val = Value::create(unsignedShort, littleEndian);
+//    std::string tmp = "12 2ddd4. xd35";
+    std::string tmp = " 1 2 3";
+    Value* val = Value::create(unsignedShort);
+    std::cout << "Reading test string \"" << tmp << "\"
";
     val->read(tmp);
-    std::cout << "And the answer is: " << *val << "
";
+    std::cout << "And the answer is: " << *val << ", size is " << val->size() << "
";
+    Rational r = std::make_pair(1,72);
+    URational ur = std::make_pair(2,3);
+
+    std::cout << "Rational  r  = " << r << "
";
+    std::cout << "URational ur = " << ur << "
";
+
+    ValueType<Rational> vr;
+    ValueType<URational> vur;
+
+    std::string str(" 4 / 5 x2 5/3");
+    vr.read(str);
+    std::cout << "ValueType<Rational> vr  = " << vr 
+              << ", size is " << vr.size() << "
";
 
     return rc;
 
diff --git a/src/tags.cpp b/src/tags.cpp
index beed3df..31441d3 100644
--- a/src/tags.cpp
+++ b/src/tags.cpp
@@ -12,12 +12,14 @@
 
   RCS information
    $Name:  $
-   $Revision: 1.3 $
+   $Revision: 1.4 $
  */
 // *****************************************************************************
 // included header files
 #include "tags.hpp"
 
+#include <iostream>
+
 // *****************************************************************************
 // class member definitions
 namespace Exif {
@@ -80,13 +82,11 @@ namespace Exif {
         TagFormat(unsignedShort,    "unsigned short",    2),
         TagFormat(unsignedLong,     "unsigned long",     4),
         TagFormat(unsignedRational, "unsigned rational", 8),
-        TagFormat(signedByte,       "signed byte",       1),
+        TagFormat(invalid6,         "invalid (6)",       1),
         TagFormat(undefined,        "undefined",         1),
         TagFormat(signedShort,      "signed short",      2),
         TagFormat(signedLong,       "signed long",       4),
-        TagFormat(signedRational,   "signed rational",   8),
-        TagFormat(singleFloat,      "single float",      4),
-        TagFormat(doubleFloat,      "double float",      8)
+        TagFormat(signedRational,   "signed rational",   8)
     };
 
     TagInfo::TagInfo(
@@ -281,14 +281,14 @@ namespace Exif {
         return sectionInfo_[tagInfo[tagInfoIdx(tag, ifdId)].sectionId_].name_;
     }
 
-    const char* ExifTags::typeName(uint16 type)
+    const char* ExifTags::typeName(TypeId typeId)
     {
-        return tagFormat_[type].name_;
+        return tagFormat_[typeId].name_;
     }
 
-    long ExifTags::typeSize(uint16 type)
+    long ExifTags::typeSize(TypeId typeId)
     {
-        return tagFormat_[type].size_;
+        return tagFormat_[typeId].size_;
     }
 
     const char* ExifTags::ifdName(IfdId ifdId)
@@ -306,4 +306,38 @@ namespace Exif {
         return sectionInfo_[sectionId].name_;
     }
 
+
+    // *************************************************************************
+    // free functions
+
+    std::ostream& operator<<(std::ostream& os, const Rational& r) 
+    {
+        return os << r.first << "/" << r.second;
+    }
+
+    std::istream& operator>>(std::istream& is, Rational& r) 
+    { 
+        int32 nominator;
+        int32 denominator;
+        char c;
+        is >> nominator >> c >> denominator; 
+        if (is && c == '/') r = std::make_pair(nominator, denominator);
+        return is;
+    }
+
+    std::ostream& operator<<(std::ostream& os, const URational& r) 
+    { 
+        return os << r.first << "/" << r.second;
+    }
+
+    std::istream& operator>>(std::istream& is, URational& r) 
+    {
+        uint32 nominator;
+        uint32 denominator;
+        char c;
+        is >> nominator >> c >> denominator; 
+        if (is && c == '/') r = std::make_pair(nominator, denominator);
+        return is;
+    }
+
 }                                       // namespace Exif
diff --git a/src/tags.hpp b/src/tags.hpp
index fedb288..0eff1df 100644
--- a/src/tags.hpp
+++ b/src/tags.hpp
@@ -8,7 +8,7 @@
 /*!
   @file    tags.hpp
   @brief   %Exif tag and type information
-  @version $Name:  $ $Revision: 1.3 $
+  @version $Name:  $ $Revision: 1.4 $
   @author  Andreas Huggel (ahu)
   @date    15-Jan-03, ahu: created
  */
@@ -20,6 +20,7 @@
 
 // + standard includes
 #include <utility>                              // for std::pair
+#include <iosfwd>
 
 // *****************************************************************************
 // namespace extensions
@@ -44,16 +45,18 @@ namespace Exif {
 
     //! Type identifiers for IFD format types
     enum TypeId { invalid, unsignedByte, asciiString, unsignedShort, 
-                  unsignedLong, unsignedRational, signedByte, undefined,
-                  signedShort, signedLong, signedRational, singleFloat, 
-                  doubleFloat };
+                  unsignedLong, unsignedRational, invalid6, undefined,
+                  signedShort, signedLong, signedRational };
 
     //! Type to specify the IFD to which a metadata belongs
     enum IfdId { IfdIdNotSet, 
                  ifd0, exifIfd, gpsIfd, makerIfd, iopIfd, 
                  ifd1, ifd1ExifIfd, ifd1GpsIfd, ifd1MakerIfd, ifd1IopIfd };
 
-    //! Section identifiers to logically group tags 
+    /*!
+      @brief Section identifiers to logically group tags. A section consists
+             of nothing more than a name, based on the Exif standard.
+     */
     enum SectionId { SectionIdNotSet, 
                      imgStruct, recOffset, imgCharacter, otherTags, exifFormat, 
                      exifVersion, imgConfig, userInfo, relatedFile, dateTime,
@@ -119,9 +122,9 @@ namespace Exif {
         //! Returns the name of the tag
         static const char* tagName(uint16 tag, IfdId ifdId);
         //! Returns the name of the type
-        static const char* typeName(uint16 type);
+        static const char* typeName(TypeId typeId);
         //! Returns the size in bytes of one element of this type
-        static long typeSize(uint16 type);
+        static long typeSize(TypeId typeId);
         //! Returns the name of the IFD
         static const char* ifdName(IfdId ifdId);
         //! Returns the related image item (image or thumbnail)
@@ -145,6 +148,34 @@ namespace Exif {
 // *****************************************************************************
 // free functions
 
+    //! Output operator for our fake rational
+    std::ostream& operator<<(std::ostream& os, const Rational& r);
+    //! Input operator for our fake rational
+    std::istream& operator>>(std::istream& is, Rational& r);
+    //! Output operator for our fake unsigned rational
+    std::ostream& operator<<(std::ostream& os, const URational& r);
+    //! Input operator for our fake unsigned rational
+    std::istream& operator>>(std::istream& is, URational& r);
+
+    //! Template to determine the TypeId for a type T
+    template<typename T> TypeId getType();
+
+    //! Specialization for an unsigned short
+    template<> inline TypeId getType<uint16>() { return unsignedShort; }
+    //! Specialization for an unsigned long
+    template<> inline TypeId getType<uint32>() { return unsignedLong; }
+    //! Specialization for an unsigned rational
+    template<> inline TypeId getType<URational>() { return unsignedRational; }
+    //! Specialization for a signed short
+    template<> inline TypeId getType<int16>() { return signedShort; }
+    //! Specialization for a signed long
+    template<> inline TypeId getType<int32>() { return signedLong; }
+    //! Specialization for a signed rational
+    template<> inline TypeId getType<Rational>() { return signedRational; }
+
+    // No default implementation: let the compiler/linker complain
+//    template<typename T> inline TypeId getType() { return invalid; }
+
 }                                       // namespace Exif
 
 #endif                                  // #ifndef _TAGS_HPP_

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list