Add a method to get the value of a specific tag.

Fix #258
This commit is contained in:
Matthieu Gautier 2019-09-16 10:48:36 +02:00
parent 2a6772b76d
commit 6ee174b546
3 changed files with 97 additions and 0 deletions

View File

@ -235,6 +235,27 @@ class Reader
*/ */
string getTags(bool original=false) const; string getTags(bool original=false) const;
/**
* Get the value (as a string) of a specific tag.
*
* According to https://wiki.openzim.org/wiki/Tags
*
* @return The value of the specified tag.
* @throw std::out_of_range if the specified tag is not found.
*/
string getTagStr(const std::string& tagName) const;
/**
* Get the boolean value of a specific tag.
*
* According to https://wiki.openzim.org/wiki/Tags
*
* @return The boolean value of the specified tag.
* @throw std::out_of_range if the specified tag is not found.
* std::domain_error if the value of the tag cannot be convert to bool.
*/
bool getTagBool(const std::string& tagName) const;
/** /**
* Get the relations of the zim file. * Get the relations of the zim file.
* *

View File

@ -400,6 +400,48 @@ string Reader::getTags(bool original) const
return join(tags, ";"); return join(tags, ";");
} }
string getTagValueFromTagList(const std::vector<std::string>& tagList, const std::string& tagName)
{
for (auto tag: tagList) {
if (tag[0] == '_') {
auto delimPos = tag.find(':');
if (delimPos == string::npos) {
// No delimiter... what to do ?
continue;
}
auto cTagName = tag.substr(1, delimPos-1);
auto cTagValue = tag.substr(delimPos+1);
if (cTagName == tagName) {
return cTagValue;
}
}
}
std::stringstream ss;
ss << tagName << " cannot be found";
throw std::out_of_range(ss.str());
}
string Reader::getTagStr(const std::string& tagName) const
{
string tags_str;
getMetadata("Tags", tags_str);
return getTagValueFromTagList(convertTags(tags_str), tagName);
}
bool Reader::getTagBool(const std::string& tagName) const
{
auto tagValue = getTagStr(tagName);
if (tagValue == "yes") {
return true;
} else if (tagValue == "no") {
return false;
} else {
std::stringstream ss;
ss << "Tag value '" << tagValue << "' for " << tagName << " cannot be converted to bool.";
throw std::domain_error(ss.str());
}
}
string Reader::getRelation() const string Reader::getRelation() const
{ {
METADATA("Relation") METADATA("Relation")

View File

@ -60,6 +60,40 @@ TEST(ParseTagTest, convert)
} }
} }
TEST(ParseTagTest, valid)
{
std::string tagStr = "_ftindex:yes;_pictures:no;_videos:no;_details:yes;_category:foo;bar";
auto tagList = convertTags(tagStr);
ASSERT_EQ(parse_tag(tagList, "ftindex"), "yes");
ASSERT_EQ(parse_tag(tagList, "pictures"), "no");
ASSERT_EQ(parse_tag(tagList, "category"), "foo");
ASSERT_EQ(parse_tag(tagList, "details"), "yes");
ASSERT_THROW(parse_tag(tagList, "detail"), std::out_of_range);
}
TEST(ParseTagTest, compat)
{
std::string tagStr = "_ftindex;nopic;foo;bar";
auto tagList = convertTags(tagStr);
ASSERT_EQ(parse_tag(tagList, "ftindex"), "yes");
ASSERT_EQ(parse_tag(tagList, "pictures"), "no");
ASSERT_EQ(parse_tag(tagList, "videos"), "yes");
ASSERT_EQ(parse_tag(tagList, "details"), "yes");
}
TEST(ParseTagTest, invalid)
{
std::string tagStr = "_ftindex:y;_pictures;_videos:;_details:yes;_details:no;_category:foo;bar";
auto tagList = convertTags(tagStr);
ASSERT_EQ(parse_tag(tagList, "ftindex"), "y");
ASSERT_EQ(parse_tag(tagList, "pictures"), "yes");
ASSERT_EQ(parse_tag(tagList, "videos"), "");
ASSERT_EQ(parse_tag(tagList, "details"), "yes");
}
}; };
int main(int argc, char** argv) int main(int argc, char** argv)
{ {