Refactor formatting list of values

This commit is contained in:
Martchus 2018-07-01 22:11:34 +02:00
parent 943123afa1
commit d64084ec78
5 changed files with 52 additions and 15 deletions

View File

@ -61,4 +61,28 @@ DiagLevel Diagnostics::level() const
return level;
}
/*!
* \brief Concatenates the specified string \a values to a list.
*/
string DiagMessage::formatList(const std::vector<string> &values)
{
auto size = values.size() * 4;
for (const auto &str : values) {
size += str.size();
}
std::string res;
res.reserve(size);
for (auto value = values.cbegin(), end = values.cend(), last = values.cend() - 1; value != end; ++value) {
if (value == last) {
res += " and ";
} else if (!res.empty()) {
res += ", ";
}
res += '\"';
res += *value;
res += '\"';
}
return res;
}
} // namespace TagParser

View File

@ -52,6 +52,8 @@ public:
const ChronoUtilities::DateTime &creationTime() const;
bool operator==(const DiagMessage &other) const;
static std::string formatList(const std::vector<std::string> &values);
private:
DiagLevel m_level;
std::string m_message;

View File

@ -340,20 +340,7 @@ void Id3v2Frame::parse(BinaryReader &reader, uint32 version, uint32 maximalSize,
if (additionalValues.size() == 1) {
return argsToString("value \"", additionalValues.front().toString(TagTextEncoding::Utf8), "\" is ignored.");
}
string valuesString = "values";
for (auto value = additionalValues.cbegin(), end = additionalValues.cend() - 1; value != end; ++value) {
valuesString += ' ';
valuesString += '\"';
valuesString += value->toString(TagTextEncoding::Utf8);
valuesString += '\"';
if (value != end) {
valuesString += ',';
}
}
valuesString += " and \"";
valuesString += additionalValues.back().toString(TagTextEncoding::Utf8);
valuesString += "\" are ignored.";
return valuesString;
return argsToString("values ", DiagMessage::formatList(TagValue::toStrings(additionalValues)), " are ignored.");
}();
// emplace diag message

View File

@ -6,6 +6,7 @@
#include <c++utilities/chrono/datetime.h>
#include <c++utilities/chrono/timespan.h>
#include <c++utilities/conversion/binaryconversion.h>
#include <c++utilities/misc/traits.h>
#include <cstring>
#include <iosfwd>
@ -132,6 +133,11 @@ public:
static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding);
static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
template <typename ContainerType,
Traits::EnableIf<Traits::IsIteratable<ContainerType>,
std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>>
* = nullptr>
static std::vector<std::string> toStrings(const ContainerType &values, TagTextEncoding encoding = TagTextEncoding::Utf8);
private:
std::unique_ptr<char[]> m_ptr;
@ -547,6 +553,24 @@ inline TagTextEncoding TagValue::descriptionEncoding() const
return m_descEncoding;
}
/*!
* \brief Converts the specified \a values to string using the specified \a encoding.
* \throws Throws ConversionException on failure.
* \sa toString()
*/
template <typename ContainerType,
Traits::EnableIf<Traits::IsIteratable<ContainerType>,
std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>> *>
std::vector<std::string> TagValue::toStrings(const ContainerType &values, TagTextEncoding encoding)
{
std::vector<std::string> res;
res.reserve(values.size());
for (const auto &value : values) {
res.emplace_back(Traits::dereferenceMaybe(value).toString(encoding));
}
return res;
}
} // namespace TagParser
#endif // TAG_PARSER_TAGVALUE_H

View File

@ -129,7 +129,7 @@ void OverallTests::checkMp3Testfile2()
CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, m_diag[1].level());
CPPUNIT_ASSERT_EQUAL("parsing TCON frame"s, m_diag[1].context());
CPPUNIT_ASSERT_EQUAL(
"Multiple strings found. This is not supported so far. Hence the additional values \"Test\", \"Example\", and \"Hard Dance\" are ignored."s,
"Multiple strings found. This is not supported so far. Hence the additional values \"Test\", \"Example\" and \"Hard Dance\" are ignored."s,
m_diag[1].message());
break;
case TagStatus::TestMetaDataPresent: