]> granicus.if.org Git - taglib/commitdiff
Basic implementation of a PropertyMap.
authorMichael Helmling <helmling@mathematik.uni-kl.de>
Mon, 16 Jan 2012 21:37:30 +0000 (22:37 +0100)
committerMichael Helmling <helmling@mathematik.uni-kl.de>
Mon, 16 Jan 2012 21:37:30 +0000 (22:37 +0100)
Implemented key/valuelist property map with
case-insensitive ASCII keys and StringList values.

Todo:
- subclass StringList to add flags indicating whether a value could
be written to the specific file format
- add member attribute indicating list of frames that could not be
parsed into the PropertyMap representation.

taglib/CMakeLists.txt
taglib/mpeg/id3v2/id3v2dicttools.cpp
taglib/toolkit/tpropertymap.cpp [new file with mode: 0644]
taglib/toolkit/tpropertymap.h [new file with mode: 0644]

index ec8a5d81f8e771b5dabee0c6753f75960c2bd115..a7777a5b97ee008c83e12eca3d1130cf06a114d6 100644 (file)
@@ -48,6 +48,7 @@ set(tag_HDRS
   toolkit/tfilestream.h
   toolkit/tmap.h
   toolkit/tmap.tcc
+  toolkit/tpropertymap.h
   mpeg/mpegfile.h
   mpeg/mpegproperties.h
   mpeg/mpegheader.h
@@ -277,6 +278,7 @@ set(toolkit_SRCS
   toolkit/tfile.cpp
   toolkit/tfilestream.cpp
   toolkit/tdebug.cpp
+  toolkit/tpropertymap.cpp
   toolkit/unicode.cpp
 )
 
index 7ee6c83dc302277280a45d67403ccda338fff490..63a0398ba4d54eaf2642bf4578584d30d8abf3e6 100644 (file)
@@ -134,6 +134,33 @@ namespace TagLib {
       return m;
     }
 
+    // list of TXXX frame description conversions
+    static const uint txxxConversionSize = 4;
+    static const char *txxxConversionFrames[][2] = {
+      {"MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID"},
+      {"MusicBrainz Disc Id", "MUSICBRAINZ_DISCID"},
+      {"MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"},
+      {"MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID"},
+      {"MusicMagic Fingerprint", "MUSICIP_FINGERPRINT"},
+      {"MusicIP PUID", "MUSICIP_PUID"},
+      {"MusicBrainz Album Release Country", "RELEASECOUNTRY"},
+      {"MusicBrainz Album Status", "MUSICBRAINZ_ALBUMSTATUS"},
+      {"MusicBrainz Album Type", "MUSICBRAINZ_ALBUMTYPE"},
+      {"MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASE_GROUPID"},
+      {"MusicBrainz Work Id", "MUSICBRAINZ_WORKID"},
+      {"MusicBrainz Original Album Id", "MUSICBRAINZ_ORIGINALALBUMID"},
+      {"Acoustid Fingerprint", "ACOUSTID_FINGERPRINT"},
+      {"Acoustid Id", "ACOUSTID_ID"}
+    };
+
+    FrameIDMap &txxxConversionMap()
+    {
+      static FrameIDMap txxxMap;
+      if (txxxMap.isEmpty())
+        for(uint i = 0; i < txxxConversionSize; ++i)
+          txxxMap[txxxConversionFrames[i][0]] = txxxConversionFrames[i][1];
+      return txxxMap;
+    }
     String frameIDToTagName(const ByteVector &id)
     {
       Map<ByteVector, String> &m = idMap();
diff --git a/taglib/toolkit/tpropertymap.cpp b/taglib/toolkit/tpropertymap.cpp
new file mode 100644 (file)
index 0000000..08b94ba
--- /dev/null
@@ -0,0 +1,120 @@
+/***************************************************************************
+    copyright           : (C) 2012 by Michael Helmling
+    email               : helmling@mathematik.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it  under the terms of the GNU Lesser General Public License version  *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library 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     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,            *
+ *   MA  02110-1301  USA                                                   *
+ ***************************************************************************/
+
+#include "tpropertymap.h"
+
+using namespace TagLib;
+
+typedef Map<String,StringList> supertype;
+
+PropertyMap::PropertyMap() : Map<String,StringList>()
+{
+}
+
+PropertyMap::PropertyMap(const PropertyMap &m) : Map<String,StringList>(m)
+{
+}
+
+PropertyMap::~PropertyMap()
+{
+}
+
+bool PropertyMap::insert(const String &key, const StringList &values)
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return false;
+
+  supertype::operator[](realKey).append(values);
+  return true;
+}
+
+bool PropertyMap::replace(const String &key, const StringList &values)
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return false;
+  supertype::erase(realKey);
+  supertype::insert(realKey, values);
+  return true;
+}
+
+PropertyMap::Iterator PropertyMap::find(const String &key)
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return end();
+  return supertype::find(realKey);
+}
+
+PropertyMap::ConstIterator PropertyMap::find(const String &key) const
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return end();
+  return supertype::find(realKey);
+}
+
+bool PropertyMap::contains(const String &key) const
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return false;
+  return supertype::contains(realKey);
+}
+
+/*!
+ * Erase the \a key and its values from the map.
+ */
+PropertyMap &PropertyMap::erase(const String &key)
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return *this;
+  supertype::erase(realKey);
+  return *this;
+}
+
+const StringList &PropertyMap::operator[](const String &key) const
+{
+  String realKey = prepareKey(key);
+  return supertype::operator[](realKey);
+}
+
+StringList &PropertyMap::operator[](const String &key)
+{
+  String realKey = prepareKey(key);
+  if (realKey.isNull())
+    return supertype::operator[](realKey); // invalid case
+  if (!supertype::contains(realKey))
+    supertype::insert(realKey, StringList());
+  return supertype::operator[](realKey);
+}
+
+String PropertyMap::prepareKey(const String &proposed) const {
+  if (proposed.isEmpty())
+    return String::null;
+  for (String::ConstIterator it = proposed.begin(); it != proposed.end(); it++)
+    // forbid non-printable, non-ascii, '=' (#61) and '~' (#126)
+    if (*it < 32 || *it >= 128 || *it == 61 || *it == 126)
+      return String::null;
+  return proposed.upper();
+}
diff --git a/taglib/toolkit/tpropertymap.h b/taglib/toolkit/tpropertymap.h
new file mode 100644 (file)
index 0000000..f82a7df
--- /dev/null
@@ -0,0 +1,118 @@
+/***************************************************************************
+    copyright           : (C) 2012 by Michael Helmling
+    email               : helmling@mathematik.uni-kl.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it  under the terms of the GNU Lesser General Public License version  *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library 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     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,            *
+ *   MA  02110-1301  USA                                                   *
+ ***************************************************************************/
+
+#ifndef PROPERTYMAP_H_
+#define PROPERTYMAP_H_
+
+#include "tmap.h"
+#include "tstringlist.h"
+
+namespace TagLib {
+
+
+  //! A map for format-independent <key,valuelist> tag representations.
+
+  /*!
+   * This map implements a generic representation of textual audio metadata
+   * ("tags") realized as pairs of a case-insensitive key
+   * and a nonempty list of corresponding values, each value being an an arbitrary
+   * Unicode String.
+   * The key has the same restrictions as in the vorbis comment specification,
+   * i.e. it must contain at least one character; all printable ASCII characters
+   * except '=' and '~' are allowed.
+   *
+   */
+
+  class PropertyMap: public Map<String,StringList>
+  {
+  public:
+
+    typedef Map<String,StringList>::Iterator Iterator;
+    typedef Map<String,StringList>::ConstIterator ConstIterator;
+
+    PropertyMap();
+
+    PropertyMap(const PropertyMap &m);
+
+    virtual ~PropertyMap();
+
+    /*!
+     * Inserts \a values under \a key in the map.  If \a key already exists,
+     * then \values will be appended to the existing StringList.
+     * The returned value indicates success, i.e. whether \a key is a
+     * valid key.
+     */
+    bool insert(const String &key, const StringList &values);
+
+    /*!
+     * Replaces any existing values for \a key with the given \a values,
+     * and simply insert them if \a key did not exist before.
+     * The returned value indicates success, i.e. whether \a key is a
+     * valid key.
+     */
+    bool replace(const String &key, const StringList &values);
+
+    /*!
+     * Find the first occurrence of \a key.
+     */
+    Iterator find(const String &key);
+
+    /*!
+     * Find the first occurrence of \a key.
+     */
+    ConstIterator find(const String &key) const;
+
+    /*!
+     * Returns true if the map contains values for \a key.
+     */
+    bool contains(const String &key) const;
+
+    /*!
+     * Erase the \a key and its values from the map.
+     */
+    PropertyMap &erase(const String &key);
+
+    /*!
+     * Returns a reference to the value associated with \a key.
+     *
+     * \note: This has undefined behavior if the key is not valid.
+     */
+    const StringList &operator[](const String &key) const;
+
+    /*!
+     * Returns a reference to the value associated with \a key.
+     *
+     * If \a key is not present in the map, an empty list is inserted and
+     * returned.
+     *
+     * \note: This has undefined behavior if the key is not valid.
+     */
+    StringList &operator[](const String &key);
+
+    /*!
+     * Converts \a proposed into another String suitable to be used as
+     * a key, or returns String::null if this is not possible.
+     */
+    String prepareKey(const String &proposed) const;
+  };
+
+}
+#endif /* PROPERTYMAP_H_ */