From 21788f4a2667695a2b57cb7463fa43f6b4539afb Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 19 Nov 2015 10:07:10 +0900 Subject: [PATCH] Efficient lookup for the ID3v2 frame ID table. Linear lookup is much faster and memory efficient when an array is very small. --- .../id3v2/frames/textidentificationframe.cpp | 2 +- taglib/mpeg/id3v2/frames/urllinkframe.cpp | 2 +- taglib/mpeg/id3v2/id3v2frame.cpp | 106 +++++++----------- taglib/mpeg/id3v2/id3v2frame.h | 4 +- 4 files changed, 44 insertions(+), 70 deletions(-) diff --git a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp index b77dd547..07bf0ede 100644 --- a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp @@ -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; } diff --git a/taglib/mpeg/id3v2/frames/urllinkframe.cpp b/taglib/mpeg/id3v2/frames/urllinkframe.cpp index 1225b524..e42d64d1 100644 --- a/taglib/mpeg/id3v2/frames/urllinkframe.cpp +++ b/taglib/mpeg/id3v2/frames/urllinkframe.cpp @@ -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 diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index 4313bcc6..a130d003 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -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 &idMap() -{ - static Map m; - if(m.isEmpty()) - for(size_t i = 0; i < frameTranslationSize; ++i) - m[frameTranslation[i][0]] = frameTranslation[i][1]; - return m; -} - -Map &txxxMap() -{ - static Map 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 &deprecationMap() -{ - static Map 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 &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 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 &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 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(); diff --git a/taglib/mpeg/id3v2/id3v2frame.h b/taglib/mpeg/id3v2/id3v2frame.h index 3771f4f0..ae1e2473 100644 --- a/taglib/mpeg/id3v2/id3v2frame.h +++ b/taglib/mpeg/id3v2/id3v2frame.h @@ -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 &);