Basic implementation of a PropertyMap.

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.
This commit is contained in:
Michael Helmling 2012-01-16 22:37:30 +01:00
parent 67d896e6a7
commit d11189b975
4 changed files with 267 additions and 0 deletions

View 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
)

View 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();

View File

@ -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();
}

View File

@ -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_ */