Blame include/exiv2/properties.hpp

Packit 01d647
// ***************************************************************** -*- C++ -*-
Packit 01d647
/*
Packit 01d647
 * Copyright (C) 2004-2018 Exiv2 authors
Packit 01d647
 * This program is part of the Exiv2 distribution.
Packit 01d647
 *
Packit 01d647
 * This program is free software; you can redistribute it and/or
Packit 01d647
 * modify it under the terms of the GNU General Public License
Packit 01d647
 * as published by the Free Software Foundation; either version 2
Packit 01d647
 * of the License, or (at your option) any later version.
Packit 01d647
 *
Packit 01d647
 * This program is distributed in the hope that it will be useful,
Packit 01d647
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 01d647
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 01d647
 * GNU General Public License for more details.
Packit 01d647
 *
Packit 01d647
 * You should have received a copy of the GNU General Public License
Packit 01d647
 * along with this program; if not, write to the Free Software
Packit 01d647
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit 01d647
 */
Packit 01d647
/*!
Packit 01d647
  @file    properties.hpp
Packit 01d647
  @brief   XMP property and type information.
References:
Packit 01d647
  XMP Specification from Adobe
Packit 01d647
  (Property descriptions copied from the XMP specification with the permission of Adobe)
Packit 01d647
  @author  Andreas Huggel (ahu)
Packit 01d647
           ahuggel@gmx.net
Packit 01d647
  @author  Gilles Caulier (cgilles)
Packit 01d647
           caulier dot gilles at gmail dot com
Packit 01d647
  @date    13-Jul-07, ahu: created
Packit 01d647
 */
Packit 01d647
#ifndef PROPERTIES_HPP_
Packit 01d647
#define PROPERTIES_HPP_
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
#include "exiv2lib_export.h"
Packit 01d647
Packit 01d647
// included header files
Packit 01d647
#include "datasets.hpp"
Packit 01d647
#include "rwlock.hpp"
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// namespace extensions
Packit 01d647
namespace Exiv2 {
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class declarations
Packit 01d647
    class XmpKey;
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class definitions
Packit 01d647
Packit 01d647
    //! Category of an XMP property
Packit 01d647
    enum XmpCategory { xmpInternal, xmpExternal };
Packit 01d647
Packit 01d647
    //! Information about one XMP property.
Packit 01d647
    struct EXIV2API XmpPropertyInfo {
Packit 01d647
        //! Comparison operator for name
Packit 01d647
        bool operator==(const std::string& name) const;
Packit 01d647
Packit 01d647
        const char*   name_;            //!< Property name
Packit 01d647
        const char*   title_;           //!< Property title or label
Packit 01d647
        const char*   xmpValueType_;    //!< XMP value type (for info only)
Packit 01d647
        TypeId        typeId_;          //!< Exiv2 default type for the property
Packit 01d647
        XmpCategory   xmpCategory_;     //!< Category (internal or external)
Packit 01d647
        const char*   desc_;            //!< Property description
Packit 01d647
    };
Packit 01d647
Packit 01d647
    //! Structure mapping XMP namespaces and (preferred) prefixes.
Packit 01d647
    struct EXIV2API XmpNsInfo {
Packit 01d647
        //! For comparison with prefix
Packit 01d647
        struct Prefix {
Packit 01d647
            //! Constructor.
Packit 01d647
            explicit Prefix(const std::string& prefix);
Packit 01d647
            //! The prefix string.
Packit 01d647
            std::string prefix_;
Packit 01d647
        };
Packit 01d647
        //! For comparison with namespace
Packit 01d647
        struct Ns {
Packit 01d647
            //! Constructor.
Packit 01d647
            explicit Ns(const std::string& ns);
Packit 01d647
            //! The namespace string
Packit 01d647
            std::string ns_;
Packit 01d647
        };
Packit 01d647
        //! Comparison operator for namespace
Packit 01d647
        bool operator==(const Ns& ns) const;
Packit 01d647
        //! Comparison operator for prefix
Packit 01d647
        bool operator==(const Prefix& prefix) const;
Packit 01d647
Packit 01d647
        const char* ns_;                //!< Namespace
Packit 01d647
        const char* prefix_;            //!< (Preferred) prefix
Packit 01d647
        const XmpPropertyInfo* xmpPropertyInfo_; //!< List of known properties
Packit 01d647
        const char* desc_;              //!< Brief description of the namespace
Packit 01d647
    };
Packit 01d647
Packit 01d647
    //! XMP property reference, implemented as a static class.
Packit 01d647
    class EXIV2API XmpProperties {
Packit 01d647
        //! Prevent construction: not implemented.
Packit 01d647
        XmpProperties();
Packit 01d647
        //! Prevent copy-construction: not implemented.
Packit 01d647
        XmpProperties(const XmpProperties& rhs);
Packit 01d647
        //! Prevent assignment: not implemented.
Packit 01d647
        XmpProperties& operator=(const XmpProperties& rhs);
Packit 01d647
Packit 01d647
      private:
Packit 01d647
        static const XmpNsInfo* nsInfoUnsafe(const std::string& prefix);
Packit 01d647
        static void unregisterNsUnsafe(const std::string& ns);
Packit 01d647
        static const XmpNsInfo* lookupNsRegistryUnsafe(const XmpNsInfo::Prefix& prefix);
Packit 01d647
Packit 01d647
    public:
Packit 01d647
        /*!
Packit 01d647
          @brief Return the title (label) of the property.
Packit 01d647
          @param key The property key
Packit 01d647
          @return The title (label) of the property, 0 if the
Packit 01d647
                 key is of an unknown property.
Packit 01d647
         */
Packit 01d647
        static const char* propertyTitle(const XmpKey& key);
Packit 01d647
        /*!
Packit 01d647
          @brief Return the description of the property.
Packit 01d647
          @param key The property key
Packit 01d647
          @return The description of the property, 0 if the
Packit 01d647
                 key is of an unknown property.
Packit 01d647
         */
Packit 01d647
        static const char* propertyDesc(const XmpKey& key);
Packit 01d647
        /*!
Packit 01d647
          @brief Return the type for property \em key. The default
Packit 01d647
                 for unknown keys is xmpText.
Packit 01d647
          @param key The property key
Packit 01d647
          @return The type of the property
Packit 01d647
         */
Packit 01d647
        static TypeId propertyType(const XmpKey& key);
Packit 01d647
        /*!
Packit 01d647
          @brief Return information for the property for key.
Packit 01d647
Packit 01d647
          If the key is a path to a nested property (one which contains a slash,
Packit 01d647
          like \c Xmp.MP.RegionInfo/MPRI:Regions), determines the innermost element
Packit 01d647
          (\c Xmp.MPRI.Regions) and returns its property information.
Packit 01d647
Packit 01d647
          @param key The property key
Packit 01d647
          @return A pointer to the property information, 0 if the
Packit 01d647
                 key is of an unknown property.
Packit 01d647
         */
Packit 01d647
        static const XmpPropertyInfo* propertyInfo(const XmpKey& key);
Packit 01d647
        /*!
Packit 01d647
           @brief Return the namespace name for the schema associated
Packit 01d647
                  with \em prefix.
Packit 01d647
           @param prefix Prefix
Packit 01d647
           @return The namespace name
Packit 01d647
           @throw Error if no namespace is registered with \em prefix.
Packit 01d647
         */
Packit 01d647
        static std::string ns(const std::string& prefix);
Packit 01d647
        /*!
Packit 01d647
           @brief Return the namespace description for the schema associated
Packit 01d647
                  with \em prefix.
Packit 01d647
           @param prefix Prefix
Packit 01d647
           @return The namespace description
Packit 01d647
           @throw Error if no namespace is registered with \em prefix.
Packit 01d647
         */
Packit 01d647
        static const char* nsDesc(const std::string& prefix);
Packit 01d647
        /*!
Packit 01d647
          @brief Return read-only list of built-in properties for \em prefix.
Packit 01d647
          @param prefix Prefix
Packit 01d647
          @return Pointer to the built-in properties for prefix, may be 0 if
Packit 01d647
                  none is configured in the namespace info.
Packit 01d647
          @throw Error if no namespace is registered with \em prefix.
Packit 01d647
         */
Packit 01d647
        static const XmpPropertyInfo* propertyList(const std::string& prefix);
Packit 01d647
        /*!
Packit 01d647
          @brief Return information about a schema namespace for \em prefix.
Packit 01d647
                 Always returns a valid pointer.
Packit 01d647
          @param prefix The prefix
Packit 01d647
          @return A pointer to the related information
Packit 01d647
          @throw Error if no namespace is registered with \em prefix.
Packit 01d647
         */
Packit 01d647
        static const XmpNsInfo* nsInfo(const std::string& prefix);
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
           @brief Return the (preferred) prefix for schema namespace \em ns.
Packit 01d647
           @param ns Schema namespace
Packit 01d647
           @return The prefix or an empty string if namespace \em ns is not
Packit 01d647
                  registered.
Packit 01d647
         */
Packit 01d647
        static std::string prefix(const std::string& ns);
Packit 01d647
        //! Print a list of properties of a schema namespace to output stream \em os.
Packit 01d647
        static void printProperties(std::ostream& os, const std::string& prefix);
Packit 01d647
Packit 01d647
        //! Interpret and print the value of an XMP property
Packit 01d647
        static std::ostream& printProperty(std::ostream& os,
Packit 01d647
                                           const std::string& key,
Packit 01d647
                                           const Value& value);
Packit 01d647
        /*!
Packit 01d647
          @brief Register namespace \em ns with preferred prefix \em prefix.
Packit 01d647
Packit 01d647
          If the prefix is a known or previously registered prefix, the
Packit 01d647
          corresponding namespace URI is overwritten.
Packit 01d647
Packit 01d647
          @note This invalidates XMP keys generated with the previous prefix.
Packit 01d647
         */
Packit 01d647
        static void registerNs(const std::string& ns, const std::string& prefix);
Packit 01d647
        /*!
Packit 01d647
          @brief Unregister a custom namespace \em ns.
Packit 01d647
Packit 01d647
          The function only has an effect if there is a namespace \em ns
Packit 01d647
          registered earlier, it does not unregister built-in namespaces.
Packit 01d647
Packit 01d647
          @note This invalidates XMP keys generated in this namespace.
Packit 01d647
         */
Packit 01d647
        static void unregisterNs(const std::string& ns);
Packit 01d647
Packit 01d647
        //! lock to be used while modifying properties
Packit 01d647
        static Exiv2::RWLock rwLock_;
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Unregister all custom namespaces.
Packit 01d647
Packit 01d647
          The function only unregisters namespaces registered earlier, it does not
Packit 01d647
          unregister built-in namespaces.
Packit 01d647
Packit 01d647
          @note This invalidates XMP keys generated in any custom namespace.
Packit 01d647
         */
Packit 01d647
        static void unregisterNs();
Packit 01d647
        //! Type for the namespace registry
Packit 01d647
        typedef std::map<std::string, XmpNsInfo> NsRegistry;
Packit 01d647
        /*!
Packit 01d647
          @brief Get the registered namespace for a specific \em prefix from the registry.
Packit 01d647
         */
Packit 01d647
        static const XmpNsInfo* lookupNsRegistry(const XmpNsInfo::Prefix& prefix);
Packit 01d647
Packit 01d647
        // DATA
Packit 01d647
        static NsRegistry nsRegistry_;          //!< Namespace registry
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Get all registered namespaces (for both Exiv2 and XMPsdk)
Packit 01d647
         */
Packit 01d647
        static void registeredNamespaces(Exiv2::Dictionary& nsDict);
Packit 01d647
Packit 01d647
    }; // class XmpProperties
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Concrete keys for XMP metadata.
Packit 01d647
     */
Packit 01d647
    class EXIV2API XmpKey : public Key
Packit 01d647
    {
Packit 01d647
    public:
Packit 01d647
        //! Shortcut for an %XmpKey auto pointer.
Packit 01d647
        typedef std::auto_ptr<XmpKey> AutoPtr;
Packit 01d647
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        /*!
Packit 01d647
          @brief Constructor to create an XMP key from a key string.
Packit 01d647
Packit 01d647
          @param key The key string.
Packit 01d647
          @throw Error if the first part of the key is not 'Xmp' or
Packit 01d647
                 the second part of the key cannot be parsed and converted
Packit 01d647
                 to a known (i.e., built-in or registered) schema prefix.
Packit 01d647
        */
Packit 01d647
        explicit XmpKey(const std::string& key);
Packit 01d647
        /*!
Packit 01d647
          @brief Constructor to create an XMP key from a schema prefix
Packit 01d647
                 and a property name.
Packit 01d647
Packit 01d647
          @param prefix   Schema prefix name
Packit 01d647
          @param property Property name
Packit 01d647
Packit 01d647
          @throw Error if the schema prefix is not known.
Packit 01d647
        */
Packit 01d647
        XmpKey(const std::string& prefix, const std::string& property);
Packit 01d647
        //! Copy constructor.
Packit 01d647
        XmpKey(const XmpKey& rhs);
Packit 01d647
        //! Virtual destructor.
Packit 01d647
        virtual ~XmpKey();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        //! Assignment operator.
Packit 01d647
        XmpKey& operator=(const XmpKey& rhs);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        virtual std::string key() const;
Packit 01d647
        virtual const char* familyName() const;
Packit 01d647
        /*!
Packit 01d647
          @brief Return the name of the group (the second part of the key).
Packit 01d647
                 For XMP keys, the group name is the schema prefix name.
Packit 01d647
        */
Packit 01d647
        virtual std::string groupName() const;
Packit 01d647
        virtual std::string tagName() const;
Packit 01d647
        virtual std::string tagLabel() const;
Packit 01d647
        //! Properties don't have a tag number. Return 0.
Packit 01d647
        virtual uint16_t tag() const;
Packit 01d647
Packit 01d647
        AutoPtr clone() const;
Packit 01d647
Packit 01d647
        // Todo: Should this be removed? What about tagLabel then?
Packit 01d647
        //! Return the schema namespace for the prefix of the key
Packit 01d647
        std::string ns() const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        //! Internal virtual copy constructor.
Packit 01d647
        virtual XmpKey* clone_() const;
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        // Pimpl idiom
Packit 01d647
        struct Impl;
Packit 01d647
        std::auto_ptr<Impl> p_;
Packit 01d647
Packit 01d647
    };  // class XmpKey
Packit 01d647
Packit 01d647
    // *****************************************************************************
Packit 01d647
    // free functions
Packit 01d647
Packit 01d647
    //! Output operator for property info
Packit 01d647
    EXIV2API std::ostream& operator<<(std::ostream& os, const XmpPropertyInfo& propertyInfo);
Packit 01d647
Packit 01d647
}                                       // namespace Exiv2
Packit 01d647
Packit 01d647
#endif                                  // #ifndef PROPERTIES_HPP_