6#include <c++utilities/conversion/conversionexception.h>
7#include <c++utilities/conversion/stringbuilder.h>
10#include <initializer_list>
60 CPP_UTILITIES_UNUSED(diag)
62 stream.read(buffer, 128);
63 if (buffer[0] != 0x54 || buffer[1] != 0x41 || buffer[2] != 0x47) {
67 readValue(m_title, 30, buffer + 3);
68 readValue(m_artist, 30, buffer + 33);
69 readValue(m_album, 30, buffer + 63);
70 readValue(m_year, 4, buffer + 93);
71 const auto is11 = buffer[125] == 0;
73 readValue(m_comment, 28, buffer + 97);
76 readValue(m_comment, 30, buffer + 97);
79 readValue(m_comment, is11 ? 28 : 30, buffer + 97);
95 static const string context(
"making ID3v1 tag");
100 stream.write(buffer, 3);
103 writeValue(m_title, 30, buffer, stream, diag);
104 writeValue(m_artist, 30, buffer, stream, diag);
105 writeValue(m_album, 30, buffer, stream, diag);
106 writeValue(m_year, 4, buffer, stream, diag);
107 writeValue(m_comment, 28, buffer, stream, diag);
118 if (position < 0x00 || position > 0xFF) {
119 throw ConversionException();
121 buffer[1] =
static_cast<char>(position);
122 }
catch (
const ConversionException &) {
124 DiagLevel::Warning,
"Track position field can not be set because given value can not be converted appropriately.", context);
131 if (genreIndex < 0x00 || genreIndex > 0xFF) {
132 throw ConversionException();
134 buffer[2] =
static_cast<char>(genreIndex);
135 }
catch (
const ConversionException &) {
137 "Genre field can not be set because given value can not be converted to a standard genre number supported by ID3v1.", context);
140 stream.write(buffer, 3);
235 auto count = std::size_t(0);
236 for (
const auto &
value : std::initializer_list<const TagValue *>{ &m_title, &m_artist, &m_album, &m_year, &m_comment, &m_trackPos, &m_genre }) {
262 for (
auto *
value : initializer_list<TagValue *>{ &m_title, &m_artist, &m_album, &m_year, &m_comment, &m_trackPos, &m_genre }) {
278void Id3v1Tag::readValue(
TagValue &value,
size_t maxLength,
const char *buffer)
280 const char *end = buffer + maxLength - 1;
281 while ((*end == 0x0 || *end ==
' ') && end >= buffer) {
288 if (maxLength >= 3 && BE::toUInt24(buffer) == 0x00EFBBBF) {
298void Id3v1Tag::writeValue(
const TagValue &value,
size_t length,
char *buffer, ostream &targetStream, Diagnostics &diag)
301 memset(buffer, 0, length);
304 string valueAsString;
307 }
catch (
const ConversionException &) {
309 DiagLevel::Warning,
"Field can not be set because given value can not be converted appropriately.",
"making ID3v1 tag field");
313 auto *valueStart = buffer;
314 auto valueLength = length;
315 auto hasProblematicEncoding =
false;
321 for (
const auto c : valueAsString) {
322 if ((c & 0x80) == 0) {
325 buffer[0] =
static_cast<char>(0xEF);
326 buffer[1] =
static_cast<char>(0xBB);
327 buffer[2] =
static_cast<char>(0xBF);
330 hasProblematicEncoding =
true;
335 hasProblematicEncoding =
true;
337 if (hasProblematicEncoding) {
338 diag.emplace_back(
DiagLevel::Warning,
"The used encoding is unlikely to be supported by other software.",
"making ID3v1 tag field");
342 if (valueAsString.size() > length) {
344 DiagLevel::Warning, argsToString(
"Value has been truncated. Max. ", length,
" characters supported."),
"making ID3v1 tag field");
346 valueAsString.copy(valueStart, valueLength);
348 targetStream.write(buffer,
static_cast<streamsize
>(length));
The Diagnostics class is a container for DiagMessage.
Id3v1Tag()
Constructs a new tag.
void make(std::ostream &targetStream, Diagnostics &diag)
Writes tag information to the specified stream.
void ensureTextValuesAreProperlyEncoded() override
Ensures the encoding of all assigned text values is supported by the tag by converting the character ...
std::size_t fieldCount() const override
Returns the number of present fields.
bool canEncodingBeUsed(TagTextEncoding encoding) const override
Returns only true for TagTextEncoding::Latin1.
bool hasField(KnownField field) const override
Returns an indication whether the specified field is present.
const TagValue & value(KnownField value) const override
Returns the value of the specified field.
bool supportsField(KnownField field) const override
Returns an indication whether the specified field is supported by the tag.
void removeAllFields() override
Removes all fields from the tag.
bool setValueConsideringTypeInfo(KnownField field, const TagValue &value, const std::string &typeInfo)
static constexpr std::string_view tagName
TagType type() const override
Returns the type of the tag as TagParser::TagType.
std::string_view typeName() const override
Returns the type name of the tag as C-style string.
bool setValue(KnownField field, const TagValue &value) override
Assigns the given value to the specified field.
void parse(std::istream &sourceStream, Diagnostics &diag)
Parses tag information from the specified stream.
The exception that is thrown when the data to be parsed holds no parsable information (e....
constexpr std::int32_t position() const
Returns the element position of the current instance.
The TagValue class wraps values of different types.
TagTextEncoding dataEncoding() const
Returns the data encoding.
void assignPosition(PositionInSet value)
Assigns the given PositionInSet value.
void assignData(const char *data, std::size_t length, TagDataType type=TagDataType::Binary, TagTextEncoding encoding=TagTextEncoding::Latin1)
PositionInSet toPositionInSet() const
Converts the value of the current TagValue object to its equivalent PositionInSet representation.
void clearDataAndMetadata()
Wipes assigned data including meta data.
void convertDataEncoding(TagTextEncoding encoding)
Converts the currently assigned text value to the specified encoding.
void assignStandardGenreIndex(int index)
Assigns the given standard genre index to be assigned.
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
static const TagValue & empty()
Returns a default-constructed TagValue where TagValue::isNull() and TagValue::isEmpty() both return t...
bool isEmpty() const
Returns whether no or an empty value is assigned.
int toStandardGenreIndex() const
Converts the value of the current TagValue object to its equivalent standard genre index.
Contains all classes and functions of the TagInfo library.
KnownField
Specifies the field.
TagTextEncoding
Specifies the text encoding.
TagType
Specifies the tag type.