Remove FMPS parser
This commit is contained in:
parent
8f32038891
commit
f645099a39
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(MESSAGES tagreadermessages.proto)
|
||||
set(SOURCES fmpsparser.cpp tagreader.cpp)
|
||||
set(SOURCES tagreader.cpp)
|
||||
|
||||
protobuf_generate_cpp(PROTO_SOURCES PROTO_HEADERS ${MESSAGES})
|
||||
|
||||
|
@ -1,132 +0,0 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Strawberry 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QChar>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
|
||||
#include "fmpsparser.h"
|
||||
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
FMPSParser::FMPSParser() :
|
||||
// The float regex ends with (?:$|(?=::|;;)) to ensure it matches all the way
|
||||
// up to the end of the value. Without it, it would match a string that
|
||||
// starts with a number, like "123abc".
|
||||
float_re_("\\s*([+-]?\\d+(?:\\.\\d+)?)\\s*(?:$|(?=::|;;))"),
|
||||
|
||||
// Matches any character except unescaped slashes, colons and semicolons.
|
||||
string_re_("((?:[^\\\\;:]|(?:\\\\[\\\\:;]))+)(?:$|(?=::|;;))"),
|
||||
|
||||
// Used for replacing escaped characters.
|
||||
escape_re_("\\\\([\\\\:;])") {}
|
||||
|
||||
// Parses a list of things (of type T) that are separated by two consecutive
|
||||
// Separator characters. Each individual thing is parsed by the F function.
|
||||
// For example, to parse this data:
|
||||
// foo::bar::baz
|
||||
// Use:
|
||||
// QVariantList ret;
|
||||
// ParseContainer<':'>(data, ParseValue, &ret);
|
||||
// ret will then contain "foo", "bar", and "baz".
|
||||
// Returns the number of characters that were consumed from data.
|
||||
//
|
||||
// You can parse lists of lists by using different separator characters:
|
||||
// ParseContainer<';'>(data, ParseContainer<':'>, &ret);
|
||||
template <char Separator, typename F, typename T>
|
||||
static int ParseContainer(const QStringRef& data, F f, QList<T>* ret) {
|
||||
ret->clear();
|
||||
|
||||
T value;
|
||||
int pos = 0;
|
||||
while (pos < data.length()) {
|
||||
const int len = data.length() - pos;
|
||||
int matched_len = f(QStringRef(data.string(), data.position() + pos, len), &value);
|
||||
if (matched_len == -1 || matched_len > len)
|
||||
break;
|
||||
|
||||
ret->append(value);
|
||||
pos += matched_len;
|
||||
|
||||
// Expect two separators in a row
|
||||
if (pos + 2 <= data.length() && data.at(pos) == Separator && data.at(pos+1) == Separator) {
|
||||
pos += 2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool FMPSParser::Parse(const QString &data) {
|
||||
|
||||
result_ = Result();
|
||||
|
||||
// Only return success if we matched the whole string
|
||||
return ParseListList(data, &result_) == data.length();
|
||||
}
|
||||
|
||||
int FMPSParser::ParseValueRef(const QStringRef& data, QVariant* ret) const {
|
||||
// Try to match a float
|
||||
QRegularExpressionMatch re_match = float_re_.match(*data.string(), data.position());
|
||||
if (re_match.capturedStart() == data.position()) {
|
||||
*ret = re_match.captured(1).toDouble();
|
||||
return re_match.capturedLength();
|
||||
}
|
||||
|
||||
// Otherwise try to match a string
|
||||
re_match = string_re_.match(*data.string(), data.position());
|
||||
if (re_match.capturedStart() == data.position()) {
|
||||
// Replace escape sequences with their actual characters
|
||||
QString value = re_match.captured(1);
|
||||
value.replace(escape_re_, "\\1");
|
||||
*ret = value;
|
||||
return re_match.capturedLength();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Parses an inner list - a list of values
|
||||
int FMPSParser::ParseListRef(const QStringRef &data, QVariantList *ret) const {
|
||||
return ParseContainer<':'>(data, std::bind(&FMPSParser::ParseValueRef, this, _1, _2), ret);
|
||||
}
|
||||
|
||||
// Parses an outer list - a list of lists
|
||||
int FMPSParser::ParseListListRef(const QStringRef &data, Result *ret) const {
|
||||
return ParseContainer<';'>(data, std::bind(&FMPSParser::ParseListRef, this, _1, _2), ret);
|
||||
}
|
||||
|
||||
// Convenience functions that take QStrings instead of QStringRefs. Use the QStringRef versions if possible, they're faster.
|
||||
int FMPSParser::ParseValue(const QString &data, QVariant *ret) const {
|
||||
return ParseValueRef(QStringRef(&data), ret);
|
||||
}
|
||||
int FMPSParser::ParseList(const QString &data, QVariantList *ret) const {
|
||||
return ParseListRef(QStringRef(&data), ret);
|
||||
}
|
||||
int FMPSParser::ParseListList(const QString &data, Result *ret) const {
|
||||
return ParseListListRef(QStringRef(&data), ret);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Strawberry 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FMPSPARSER_H
|
||||
#define FMPSPARSER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
|
||||
class QVariant;
|
||||
|
||||
class FMPSParser {
|
||||
public:
|
||||
FMPSParser();
|
||||
|
||||
// A FMPS result is a list of lists of values (where a value is a string or
|
||||
// a float).
|
||||
typedef QList<QVariantList> Result;
|
||||
|
||||
// Parses a FMPS value and returns true on success.
|
||||
bool Parse(const QString &data);
|
||||
|
||||
// Gets the result of the last successful Parse.
|
||||
Result result() const { return result_; }
|
||||
|
||||
// Returns true if result() is empty.
|
||||
bool is_empty() const { return result().isEmpty() || result()[0].isEmpty(); }
|
||||
|
||||
// Internal functions, public for unit tests
|
||||
int ParseValue(const QString &data, QVariant *ret) const;
|
||||
int ParseValueRef(const QStringRef &data, QVariant *ret) const;
|
||||
|
||||
int ParseList(const QString &data, QVariantList *ret) const;
|
||||
int ParseListRef(const QStringRef &data, QVariantList *ret) const;
|
||||
|
||||
int ParseListList(const QString &data, Result *ret) const;
|
||||
int ParseListListRef(const QStringRef &data, Result *ret) const;
|
||||
|
||||
private:
|
||||
QRegularExpression float_re_;
|
||||
QRegularExpression string_re_;
|
||||
QRegularExpression escape_re_;
|
||||
Result result_;
|
||||
};
|
||||
|
||||
#endif // FMPSPARSER_H
|
@ -90,8 +90,6 @@
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/messagehandler.h"
|
||||
|
||||
#include "fmpsparser.h"
|
||||
#include "core/timeconstants.h"
|
||||
|
||||
class FileRefFactory {
|
||||
@ -300,15 +298,6 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
}
|
||||
}
|
||||
|
||||
// Parse FMPS frames
|
||||
for (uint i = 0; i < map["TXXX"].size(); ++i) {
|
||||
const TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<const TagLib::ID3v2::UserTextIdentificationFrame*>(map["TXXX"][i]);
|
||||
|
||||
if (frame && frame->description().startsWith("FMPS_")) {
|
||||
ParseFMPSFrame(TStringToQString(frame->description()), TStringToQString(frame->fieldList()[1]), song);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,33 +512,6 @@ void TagReader::ParseAPETag(const TagLib::APE::ItemListMap &map, const QTextCode
|
||||
|
||||
}
|
||||
|
||||
void TagReader::ParseFMPSFrame(const QString &name, const QString &value, pb::tagreader::SongMetadata *song) const {
|
||||
|
||||
qLog(Debug) << "Parsing FMPSFrame" << name << ", " << value;
|
||||
FMPSParser parser;
|
||||
|
||||
if (!parser.Parse(value) || parser.is_empty()) return;
|
||||
|
||||
QVariant var;
|
||||
|
||||
if (name == "FMPS_PlayCount") {
|
||||
var = parser.result()[0][0];
|
||||
if (var.type() == QVariant::Double) {
|
||||
song->set_playcount(var.toDouble());
|
||||
}
|
||||
}
|
||||
else if (name == "FMPS_PlayCount_User") {
|
||||
// Take a user playcount only if there's no playcount already set
|
||||
if (song->playcount() == 0 && parser.result()[0].count() >= 2) {
|
||||
var = parser.result()[0][1];
|
||||
if (var.type() == QVariant::Double) {
|
||||
song->set_playcount(var.toDouble());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReader::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comments, const pb::tagreader::SongMetadata &song) const {
|
||||
|
||||
vorbis_comments->addField("COMPOSER", StdStringToTaglibString(song.composer()), true);
|
||||
|
@ -66,7 +66,6 @@ class TagReader {
|
||||
|
||||
void ParseOggTag(const TagLib::Ogg::FieldListMap &map, const QTextCodec *codec, QString *disc, QString *compilation, pb::tagreader::SongMetadata *song) const;
|
||||
void ParseAPETag(const TagLib::APE::ItemListMap &map, const QTextCodec *codec, QString *disc, QString *compilation, pb::tagreader::SongMetadata *song) const;
|
||||
void ParseFMPSFrame(const QString &name, const QString &value, pb::tagreader::SongMetadata *song) const;
|
||||
|
||||
void SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comments, const pb::tagreader::SongMetadata &song) const;
|
||||
void SaveAPETag(TagLib::APE::Tag *tag, const pb::tagreader::SongMetadata &song) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user