Efficient lookup for the ID3v2 frame ID table.

Linear lookup is much faster and memory efficient when an array is very small.
This commit is contained in:
Tsuda Kageyu 2015-11-19 10:07:10 +09:00
parent 74cb6f3fc7
commit 21788f4a26
4 changed files with 44 additions and 70 deletions

View File

@ -146,7 +146,7 @@ PropertyMap TextIdentificationFrame::asProperties() const
return makeTMCLProperties();
PropertyMap map;
String tagName = frameIDToKey(frameID());
if(tagName.isNull()) {
if(tagName.isEmpty()) {
map.unsupportedData().append(frameID());
return map;
}

View File

@ -84,7 +84,7 @@ PropertyMap UrlLinkFrame::asProperties() const
{
String key = frameIDToKey(frameID());
PropertyMap map;
if(key.isNull())
if(key.isEmpty())
// unknown W*** frame - this normally shouldn't happen
map.unsupportedData().append(frameID());
else

View File

@ -116,7 +116,7 @@ Frame *Frame::createTextualFrame(const String &key, const StringList &values) //
{
// check if the key is contained in the key<=>frameID mapping
ByteVector frameID = keyToFrameID(key);
if(!frameID.isNull()) {
if(!frameID.isEmpty()) {
// Apple proprietary WFED (Podcast URL) is in fact a text frame.
if(frameID[0] == 'T' || frameID == "WFED"){ // text frame
TextIdentificationFrame *frame = new TextIdentificationFrame(frameID, String::UTF8);
@ -364,7 +364,7 @@ String::Type Frame::checkTextEncoding(const StringList &fields, String::Type enc
return checkEncoding(fields, encoding, header()->version());
}
static const TagLib::uint frameTranslationSize = 51;
static const size_t frameTranslationSize = 51;
static const char *frameTranslation[][2] = {
// Text information frames
{ "TALB", "ALBUM"},
@ -436,41 +436,20 @@ static const char *frameTranslation[][2] = {
{ "WFED", "PODCASTURL" },
};
static const TagLib::uint txxxFrameTranslationSize = 8;
static const size_t txxxFrameTranslationSize = 8;
static const char *txxxFrameTranslation[][2] = {
{ "MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
{ "MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
{ "MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
{ "MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
{ "MusicBrainz Work Id", "MUSICBRAINZ_WORKID" },
{ "Acoustid Id", "ACOUSTID_ID" },
{ "Acoustid Fingerprint", "ACOUSTID_FINGERPRINT" },
{ "MusicIP PUID", "MUSICIP_PUID" },
{ "MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID" },
{ "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ_ARTISTID" },
{ "MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ_ALBUMARTISTID" },
{ "MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID" },
{ "MUSICBRAINZ WORK ID", "MUSICBRAINZ_WORKID" },
{ "ACOUSTID ID", "ACOUSTID_ID" },
{ "ACOUSTID FINGERPRINT", "ACOUSTID_FINGERPRINT" },
{ "MUSICIP PUID", "MUSICIP_PUID" },
};
Map<ByteVector, String> &idMap()
{
static Map<ByteVector, String> m;
if(m.isEmpty())
for(size_t i = 0; i < frameTranslationSize; ++i)
m[frameTranslation[i][0]] = frameTranslation[i][1];
return m;
}
Map<String, String> &txxxMap()
{
static Map<String, String> m;
if(m.isEmpty()) {
for(size_t i = 0; i < txxxFrameTranslationSize; ++i) {
String key = String(txxxFrameTranslation[i][0]).upper();
m[key] = txxxFrameTranslation[i][1];
}
}
return m;
}
// list of deprecated frames and their successors
static const TagLib::uint deprecatedFramesSize = 4;
static const size_t deprecatedFramesSize = 4;
static const char *deprecatedFrames[][2] = {
{"TRDA", "TDRC"}, // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
{"TDAT", "TDRC"}, // 2.3 -> 2.4
@ -478,53 +457,49 @@ static const char *deprecatedFrames[][2] = {
{"TIME", "TDRC"}, // 2.3 -> 2.4
};
Map<ByteVector,ByteVector> &deprecationMap()
{
static Map<ByteVector,ByteVector> depMap;
if(depMap.isEmpty())
for(TagLib::uint i = 0; i < deprecatedFramesSize; ++i)
depMap[deprecatedFrames[i][0]] = deprecatedFrames[i][1];
return depMap;
}
String Frame::frameIDToKey(const ByteVector &id)
{
Map<ByteVector, String> &m = idMap();
if(m.contains(id))
return m[id];
if(deprecationMap().contains(id))
return m[deprecationMap()[id]];
return String::null;
ByteVector id24 = id;
for(size_t i = 0; i < deprecatedFramesSize; ++i) {
if(id24 == deprecatedFrames[i][0]) {
id24 = deprecatedFrames[i][1];
break;
}
}
for(size_t i = 0; i < frameTranslationSize; ++i) {
if(id24 == frameTranslation[i][0])
return frameTranslation[i][1];
}
return String();
}
ByteVector Frame::keyToFrameID(const String &s)
{
static Map<String, ByteVector> m;
if(m.isEmpty())
for(size_t i = 0; i < frameTranslationSize; ++i)
m[frameTranslation[i][1]] = frameTranslation[i][0];
if(m.contains(s.upper()))
return m[s];
return ByteVector::null;
const String key = s.upper();
for(size_t i = 0; i < frameTranslationSize; ++i) {
if(key == frameTranslation[i][1])
return frameTranslation[i][0];
}
return ByteVector();
}
String Frame::txxxToKey(const String &description)
{
Map<String, String> &m = txxxMap();
String d = description.upper();
if(m.contains(d))
return m[d];
const String d = description.upper();
for(size_t i = 0; i < txxxFrameTranslationSize; ++i) {
if(d == txxxFrameTranslation[i][0])
return txxxFrameTranslation[i][1];
}
return d;
}
String Frame::keyToTXXX(const String &s)
{
static Map<String, String> m;
if(m.isEmpty())
for(size_t i = 0; i < txxxFrameTranslationSize; ++i)
m[txxxFrameTranslation[i][1]] = txxxFrameTranslation[i][0];
if(m.contains(s.upper()))
return m[s];
const String key = s.upper();
for(size_t i = 0; i < txxxFrameTranslationSize; ++i) {
if(key == txxxFrameTranslation[i][1])
return txxxFrameTranslation[i][0];
}
return s;
}
@ -560,7 +535,6 @@ PropertyMap Frame::asProperties() const
void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
PropertyMap &tiplProperties, PropertyMap &tmclProperties)
{
singleFrameProperties.clear();
tiplProperties.clear();
tmclProperties.clear();

View File

@ -264,13 +264,13 @@ namespace TagLib {
/*!
* Returns an appropriate ID3 frame ID for the given free-form tag key. This method
* will return ByteVector::null if no specialized translation is found.
* will return an empty ByteVector if no specialized translation is found.
*/
static ByteVector keyToFrameID(const String &);
/*!
* Returns a free-form tag name for the given ID3 frame ID. Note that this does not work
* for general frame IDs such as TXXX or WXXX; in such a case String::null is returned.
* for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned.
*/
static String frameIDToKey(const ByteVector &);