Support `CppUtilities::DateTimeExpression` in `TagValue`
This commit is contained in:
parent
d6a2903749
commit
4aff37b788
|
@ -185,7 +185,7 @@ set(RES_FILES "${LANGUAGE_HEADER_ISO_639_2}")
|
|||
set(CONFIGURATION_PACKAGE_SUFFIX
|
||||
""
|
||||
CACHE STRING "sets the suffix for find_package() calls to packages configured via c++utilities")
|
||||
find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.13.0 REQUIRED)
|
||||
find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.19.0 REQUIRED)
|
||||
use_cpp_utilities(VISIBILITY PUBLIC)
|
||||
|
||||
# link against a possibly required extra library for std::filesystem
|
||||
|
|
55
tagvalue.cpp
55
tagvalue.cpp
|
@ -48,6 +48,8 @@ std::string_view tagDataTypeString(TagDataType dataType)
|
|||
return "popularity";
|
||||
case TagDataType::UnsignedInteger:
|
||||
return "unsigned integer";
|
||||
case TagDataType::DateTimeExpression:
|
||||
return "date time expression";
|
||||
default:
|
||||
return "undefined";
|
||||
}
|
||||
|
@ -203,8 +205,6 @@ TagTextEncoding pickUtfEncoding(TagTextEncoding encoding1, TagTextEncoding encod
|
|||
* - If any of the differently typed values can not be converted to a string (eg. it is binary data) the values
|
||||
* are *not* considered equal. So the text "foo" and the binary value "foo" are not considered equal although
|
||||
* the raw data is identical.
|
||||
* - In fact, values of the types TagDataType::DateTime, TagDataType::TimeSpan, TagDataType::Picture, TagDataType::Binary
|
||||
* and TagDataType::Unspecified will never be considered equal with a value of another type.
|
||||
* - If the type is TagDataType::Text and the encoding differs values might still be considered equal if they
|
||||
* represent the same characters. The same counts for the description.
|
||||
* - This might be a costly operation due to possible conversions.
|
||||
|
@ -303,6 +303,8 @@ bool TagValue::compareTo(const TagValue &other, TagValueComparisionFlags options
|
|||
return toTimeSpan() == other.toTimeSpan();
|
||||
case TagDataType::DateTime:
|
||||
return toDateTime() == other.toDateTime();
|
||||
case TagDataType::DateTimeExpression:
|
||||
return toDateTimeExpression() == other.toDateTimeExpression();
|
||||
case TagDataType::Picture:
|
||||
case TagDataType::Binary:
|
||||
case TagDataType::Undefined:
|
||||
|
@ -318,6 +320,7 @@ bool TagValue::compareTo(const TagValue &other, TagValueComparisionFlags options
|
|||
switch (dataType) {
|
||||
case TagDataType::TimeSpan:
|
||||
case TagDataType::DateTime:
|
||||
case TagDataType::DateTimeExpression:
|
||||
case TagDataType::Picture:
|
||||
case TagDataType::Binary:
|
||||
case TagDataType::Undefined:
|
||||
|
@ -595,7 +598,7 @@ TimeSpan TagValue::toTimeSpan() const
|
|||
case sizeof(std::int64_t):
|
||||
return TimeSpan(*(reinterpret_cast<std::int64_t *>(m_ptr.get())));
|
||||
default:
|
||||
throw ConversionException("The size of the assigned integer is not appropriate for conversion to time span.");
|
||||
throw ConversionException("The size of the assigned data is not appropriate for conversion to time span.");
|
||||
}
|
||||
case TagDataType::UnsignedInteger:
|
||||
switch (m_size) {
|
||||
|
@ -615,7 +618,7 @@ TimeSpan TagValue::toTimeSpan() const
|
|||
|
||||
/*!
|
||||
* \brief Converts the value of the current TagValue object to its equivalent
|
||||
* DateTime representation.
|
||||
* DateTime representation (using the UTC timezone).
|
||||
* \throws Throws ConversionException on failure.
|
||||
*/
|
||||
DateTime TagValue::toDateTime() const
|
||||
|
@ -640,7 +643,43 @@ DateTime TagValue::toDateTime() const
|
|||
} else if (m_size == sizeof(std::uint64_t)) {
|
||||
return DateTime(*(reinterpret_cast<std::uint64_t *>(m_ptr.get())));
|
||||
} else {
|
||||
throw ConversionException("The size of the assigned integer is not appropriate for conversion to date time.");
|
||||
throw ConversionException("The size of the assigned data is not appropriate for conversion to date time.");
|
||||
}
|
||||
case TagDataType::DateTimeExpression:
|
||||
return toDateTimeExpression().gmt();
|
||||
default:
|
||||
throw ConversionException(argsToString("Can not convert ", tagDataTypeString(m_type), " to date time."));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the value of the current TagValue object to its equivalent
|
||||
* DateTimeExpression representation.
|
||||
* \throws Throws ConversionException on failure.
|
||||
*/
|
||||
CppUtilities::DateTimeExpression TagParser::TagValue::toDateTimeExpression() const
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return DateTimeExpression();
|
||||
}
|
||||
switch (m_type) {
|
||||
case TagDataType::Text: {
|
||||
const auto str = toString(m_encoding == TagTextEncoding::Utf8 ? TagTextEncoding::Utf8 : TagTextEncoding::Latin1);
|
||||
try {
|
||||
return DateTimeExpression::fromIsoString(str.data());
|
||||
} catch (const ConversionException &) {
|
||||
return DateTimeExpression::fromString(str.data());
|
||||
}
|
||||
}
|
||||
case TagDataType::Integer:
|
||||
case TagDataType::DateTime:
|
||||
case TagDataType::UnsignedInteger:
|
||||
return DateTimeExpression{ .value = toDateTime(), .delta = TimeSpan(), .parts = DateTimeParts::DateTime };
|
||||
case TagDataType::DateTimeExpression:
|
||||
if (m_size == sizeof(DateTimeExpression)) {
|
||||
return *reinterpret_cast<DateTimeExpression *>(m_ptr.get());
|
||||
} else {
|
||||
throw ConversionException("The size of the assigned data is not appropriate for conversion to date time expression.");
|
||||
}
|
||||
default:
|
||||
throw ConversionException(argsToString("Can not convert ", tagDataTypeString(m_type), " to date time."));
|
||||
|
@ -908,6 +947,9 @@ void TagValue::toString(string &result, TagTextEncoding encoding) const
|
|||
case TagDataType::UnsignedInteger:
|
||||
result = numberToString(toUnsignedInteger());
|
||||
break;
|
||||
case TagDataType::DateTimeExpression:
|
||||
result = toDateTimeExpression().toIsoString();
|
||||
break;
|
||||
default:
|
||||
throw ConversionException(argsToString("Can not convert ", tagDataTypeString(m_type), " to string."));
|
||||
}
|
||||
|
@ -998,6 +1040,9 @@ void TagValue::toWString(std::u16string &result, TagTextEncoding encoding) const
|
|||
case TagDataType::UnsignedInteger:
|
||||
regularStrRes = numberToString(toUnsignedInteger());
|
||||
break;
|
||||
case TagDataType::DateTimeExpression:
|
||||
regularStrRes = toDateTimeExpression().toIsoString();
|
||||
break;
|
||||
default:
|
||||
throw ConversionException(argsToString("Can not convert ", tagDataTypeString(m_type), " to string."));
|
||||
}
|
||||
|
|
20
tagvalue.h
20
tagvalue.h
|
@ -128,6 +128,7 @@ enum class TagDataType : unsigned int {
|
|||
Undefined, /**< undefined/invalid data type */
|
||||
Popularity, /**< rating with user info and play counter (as in ID3v2's "Popularimeter") */
|
||||
UnsignedInteger, /**< unsigned integer */
|
||||
DateTimeExpression, /**< date time expression, see CppUtilities::DateTimeExpression */
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -159,6 +160,7 @@ public:
|
|||
TagTextEncoding encoding = TagTextEncoding::Latin1);
|
||||
explicit TagValue(PositionInSet value);
|
||||
explicit TagValue(CppUtilities::DateTime value);
|
||||
explicit TagValue(const CppUtilities::DateTimeExpression &value);
|
||||
explicit TagValue(CppUtilities::TimeSpan value);
|
||||
explicit TagValue(const Popularity &value);
|
||||
TagValue(const TagValue &other);
|
||||
|
@ -190,6 +192,7 @@ public:
|
|||
PositionInSet toPositionInSet() const;
|
||||
CppUtilities::TimeSpan toTimeSpan() const;
|
||||
CppUtilities::DateTime toDateTime() const;
|
||||
CppUtilities::DateTimeExpression toDateTimeExpression() const;
|
||||
Popularity toPopularity() const;
|
||||
Popularity toScaledPopularity(TagType scale = TagType::Unspecified) const;
|
||||
std::size_t dataSize() const;
|
||||
|
@ -231,6 +234,7 @@ public:
|
|||
void assignPosition(PositionInSet value);
|
||||
void assignTimeSpan(CppUtilities::TimeSpan value);
|
||||
void assignDateTime(CppUtilities::DateTime value);
|
||||
void assignDateTimeExpression(const CppUtilities::DateTimeExpression &value);
|
||||
void assignPopularity(const Popularity &value);
|
||||
|
||||
static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding);
|
||||
|
@ -422,6 +426,14 @@ inline TagValue::TagValue(CppUtilities::DateTime value)
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new TagValue holding a copy of the given DateTimeExpression \a value.
|
||||
*/
|
||||
inline TagValue::TagValue(const CppUtilities::DateTimeExpression &value)
|
||||
: TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTimeExpression)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new TagValue holding a copy of the given TimeSpan \a value.
|
||||
*/
|
||||
|
@ -523,6 +535,14 @@ inline void TagValue::assignDateTime(CppUtilities::DateTime value)
|
|||
assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Assigns the given DateTimeExpression \a value.
|
||||
*/
|
||||
inline void TagParser::TagValue::assignDateTimeExpression(const CppUtilities::DateTimeExpression &value)
|
||||
{
|
||||
assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTimeExpression);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Assigns the given standard genre \a index to be assigned.
|
||||
* \param index Specifies the index to be assigned.
|
||||
|
|
|
@ -28,6 +28,7 @@ class TagValueTests : public TestFixture {
|
|||
CPPUNIT_TEST(testPositionInSet);
|
||||
CPPUNIT_TEST(testTimeSpan);
|
||||
CPPUNIT_TEST(testDateTime);
|
||||
CPPUNIT_TEST(testDateTimeExpression);
|
||||
CPPUNIT_TEST(testPopularity);
|
||||
CPPUNIT_TEST(testString);
|
||||
CPPUNIT_TEST(testEqualityOperator);
|
||||
|
@ -45,6 +46,7 @@ public:
|
|||
void testPositionInSet();
|
||||
void testTimeSpan();
|
||||
void testDateTime();
|
||||
void testDateTimeExpression();
|
||||
void testPopularity();
|
||||
void testString();
|
||||
void testEqualityOperator();
|
||||
|
@ -179,6 +181,20 @@ void TagValueTests::testDateTime()
|
|||
CPPUNIT_ASSERT_THROW(dateTime.toPositionInSet(), ConversionException);
|
||||
}
|
||||
|
||||
void TagValueTests::testDateTimeExpression()
|
||||
{
|
||||
auto expr = DateTimeExpression::fromIsoString("2007");
|
||||
auto value = TagValue();
|
||||
value.assignDateTimeExpression(expr);
|
||||
CPPUNIT_ASSERT_EQUAL(value, TagValue(expr));
|
||||
CPPUNIT_ASSERT_EQUAL(expr.value, value.toDateTime());
|
||||
CPPUNIT_ASSERT_EQUAL(expr, value.toDateTimeExpression());
|
||||
CPPUNIT_ASSERT_EQUAL(expr.toIsoString(), value.toString());
|
||||
CPPUNIT_ASSERT_THROW(value.toInteger(), ConversionException);
|
||||
CPPUNIT_ASSERT_THROW(value.toTimeSpan(), ConversionException);
|
||||
CPPUNIT_ASSERT_THROW(value.toPositionInSet(), ConversionException);
|
||||
}
|
||||
|
||||
void TagValueTests::testPopularity()
|
||||
{
|
||||
const auto tagValue = TagValue(Popularity{ .user = "foo", .rating = 40.0, .playCounter = 123, .scale = TagType::VorbisComment });
|
||||
|
@ -228,7 +244,9 @@ void TagValueTests::testString()
|
|||
"conversion to pos", PositionInSet(15), TagValue("\0\x31\0\x35", 4, TagTextEncoding::Utf16BigEndian).toPositionInSet());
|
||||
CPPUNIT_ASSERT_THROW_MESSAGE("failing conversion pos", TagValue("a4 / 15", 7, TagTextEncoding::Utf8).toPositionInSet(), ConversionException);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
"conversion to date", DateTime::fromDate(2004, 4, 15), TagValue("2004-04-15", 10, TagTextEncoding::Utf8).toDateTime());
|
||||
"conversion to date time", DateTime::fromDate(2004, 4, 15), TagValue("2004-04-15", 10, TagTextEncoding::Utf8).toDateTime());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("conversion to date time expression", DateTimeExpression::fromIsoString("2004-04"),
|
||||
TagValue("2004-04-15", 7, TagTextEncoding::Utf8).toDateTimeExpression());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("conversion to date from UTF-16", DateTime::fromDate(2015, 4, 15),
|
||||
TagValue("\0\x32\0\x30\0\x31\0\x35\0\x2d\0\x30\0\x34\0\x2d\0\x31\0\x35", 20, TagTextEncoding::Utf16BigEndian).toDateTime());
|
||||
CPPUNIT_ASSERT_THROW_MESSAGE("failing conversion to date", TagValue("_", 1, TagTextEncoding::Utf8).toDateTime(), ConversionException);
|
||||
|
|
Loading…
Reference in New Issue