Tag Parser 12.4.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1#include "./helper.h"
2
3#include "../aspectratio.h"
4#include "../backuphelper.h"
5#include "../diagnostics.h"
6#include "../exceptions.h"
7#include "../margin.h"
8#include "../mediafileinfo.h"
9#include "../mediaformat.h"
10#include "../positioninset.h"
11#include "../progressfeedback.h"
12#include "../signature.h"
13#include "../size.h"
14#include "../tagtarget.h"
15
16#include "../id3/id3v2tag.h"
17
18#include <c++utilities/conversion/stringbuilder.h>
19#include <c++utilities/tests/testutils.h>
20using namespace CppUtilities;
21
22#include <cppunit/TestFixture.h>
23#include <cppunit/extensions/HelperMacros.h>
24
25#include <cstdio>
26#include <filesystem>
27#include <regex>
28
29using namespace std;
30using namespace CppUtilities::Literals;
31using namespace TagParser;
32using namespace CPPUNIT_NS;
33
37class UtilitiesTests : public TestFixture {
38 CPPUNIT_TEST_SUITE(UtilitiesTests);
39 CPPUNIT_TEST(testSize);
40 CPPUNIT_TEST(testTagTarget);
41 CPPUNIT_TEST(testSignature);
42 CPPUNIT_TEST(testMargin);
43 CPPUNIT_TEST(testAspectRatio);
44 CPPUNIT_TEST(testMediaFormat);
45 CPPUNIT_TEST(testPositionInSet);
46 CPPUNIT_TEST(testProgressFeedback);
48 CPPUNIT_TEST(testDiagnostics);
49 CPPUNIT_TEST(testBackupFile);
50 CPPUNIT_TEST(testFieldConversions);
51 CPPUNIT_TEST_SUITE_END();
52
53public:
54 void setUp() override;
55 void tearDown() override;
56
57 void testSize();
59 void testTagTarget();
60 void testSignature();
61 void testMargin();
62 void testAspectRatio();
63 void testMediaFormat();
64 void testPositionInSet();
67 void testDiagnostics();
68 void testBackupFile();
70};
71
73
75{
76}
77
81
83{
84 static_assert(Size().isNull(), "Size::isNull()");
85 static_assert(!Size(3, 4).isNull(), "Size::isNull()");
86 static_assert(Size(3, 4).resolution() == 12, "Size::resolution");
87
88 Size size(1920, 1080);
89 CPPUNIT_ASSERT_EQUAL("width: 1920, height: 1080"s, size.toString());
90 CPPUNIT_ASSERT_EQUAL("1080p"s, string(size.abbreviation()));
91 size.setWidth(1280);
92 size.setHeight(720);
93 CPPUNIT_ASSERT_EQUAL("720p"s, string(size.abbreviation()));
94}
95
97{
98 TagTarget target;
99 CPPUNIT_ASSERT(target.isEmpty());
100 CPPUNIT_ASSERT_EQUAL_MESSAGE("default level is 50", static_cast<std::uint64_t>(50), target.level());
101 CPPUNIT_ASSERT_EQUAL("level 50"s, target.toString(TagTargetLevel::Unspecified));
102 target = TagTarget(30, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 });
103 CPPUNIT_ASSERT(!target.isEmpty());
104 const auto mapping = [](std::uint64_t level) { return level == 30 ? TagTargetLevel::Track : TagTargetLevel::Unspecified; };
105 CPPUNIT_ASSERT_EQUAL(
106 "level 30 'track, song, chapter', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
107 target.toString(mapping));
108 target.setLevel(40);
109 CPPUNIT_ASSERT_EQUAL("level 40, track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
110 target.toString(mapping));
111 target.setLevelName("test");
112 CPPUNIT_ASSERT_EQUAL("level 40 'test', track 1, track 2, track 3, chapter 4, edition 5, edition 6, attachment 7, attachment 8, attachment 9"s,
113 target.toString(mapping));
114 CPPUNIT_ASSERT(target == TagTarget(40, { 1, 2, 3 }, { 4 }, { 5, 6 }, { 7, 8, 9 }));
115 target.clear();
116 CPPUNIT_ASSERT(target.isEmpty());
117}
118
120{
121 const unsigned char xzHead[12] = { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x04, 0xe6, 0xd6, 0xb4, 0x46 };
122
123 // truncated buffer
124 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown, parseSignature(reinterpret_cast<const char *>(xzHead), 3));
125 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown, parseSignature(reinterpret_cast<const char *>(xzHead), 2));
126 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown, parseSignature(reinterpret_cast<const char *>(xzHead), 0));
127
128 const auto containerFormat = parseSignature(reinterpret_cast<const char *>(xzHead), sizeof(xzHead));
129 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Xz, containerFormat);
130 CPPUNIT_ASSERT_EQUAL("xz compressed file"s, string(containerFormatName(containerFormat)));
131 CPPUNIT_ASSERT_EQUAL("xz"s, string(containerFormatAbbreviation(containerFormat)));
132 CPPUNIT_ASSERT_EQUAL(string(), string(containerFormatSubversion(containerFormat)));
133}
134
136{
137 static_assert(Margin().isNull(), "empty margin");
138 static_assert(!Margin(0, 2).isNull(), "non-empty margin");
139
140 CPPUNIT_ASSERT_EQUAL("top: 1; left: 2; bottom: 3; right: 4"s, Margin(1, 2, 3, 4).toString());
141}
142
144{
145 static_assert(!AspectRatio().isValid(), "invalid aspect ratio");
146 static_assert(AspectRatio(16, 9).isValid(), "valid aspect ratio");
147 static_assert(AspectRatio(16, 9).isExtended(), "extended aspect ratio");
148
149 const AspectRatio ratio(4);
150 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(16), ratio.numerator);
151 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(11), ratio.denominator);
152 const AspectRatio ratio2(77);
153 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0), ratio2.numerator);
154 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(0), ratio2.denominator);
155}
156
158{
159 // unspecific format
160 MediaFormat aac(GeneralMediaFormat::Aac);
161 CPPUNIT_ASSERT_EQUAL("Advanced Audio Coding"s, string(aac.name()));
162 CPPUNIT_ASSERT_EQUAL("AAC"s, string(aac.abbreviation()));
163 CPPUNIT_ASSERT_EQUAL("AAC"s, string(aac.shortAbbreviation()));
164
165 // specific format
167 CPPUNIT_ASSERT(aac == GeneralMediaFormat::Aac);
168 CPPUNIT_ASSERT(aac != GeneralMediaFormat::Mpeg1Audio);
169 CPPUNIT_ASSERT_EQUAL("Advanced Audio Coding Low Complexity Profile"s, string(aac.name()));
170 CPPUNIT_ASSERT_EQUAL("MPEG-4 AAC-LC"s, string(aac.abbreviation()));
171 CPPUNIT_ASSERT_EQUAL("HE-AAC"s, string(aac.shortAbbreviation()));
172 CPPUNIT_ASSERT_EQUAL("Spectral Band Replication / HE-AAC"s, string(aac.extensionName()));
173}
174
176{
177 const PositionInSet empty;
178 CPPUNIT_ASSERT(empty.isNull());
179 CPPUNIT_ASSERT_EQUAL(0, empty.position());
180 CPPUNIT_ASSERT_EQUAL(0, empty.total());
181 CPPUNIT_ASSERT_EQUAL(""s, empty.toString());
182
183 const PositionInSet oneOfThree(1, 3);
184 CPPUNIT_ASSERT(!oneOfThree.isNull());
185 CPPUNIT_ASSERT_EQUAL(1, oneOfThree.position());
186 CPPUNIT_ASSERT_EQUAL(3, oneOfThree.total());
187 CPPUNIT_ASSERT_EQUAL("1/3"s, oneOfThree.toString());
188
189 const PositionInSet posOnly(5, 0);
190 CPPUNIT_ASSERT(!posOnly.isNull());
191 CPPUNIT_ASSERT_EQUAL(5, posOnly.position());
192 CPPUNIT_ASSERT_EQUAL(0, posOnly.total());
193 CPPUNIT_ASSERT_EQUAL("5"s, posOnly.toString());
194
195 const PositionInSet totalOnly(0, 5);
196 CPPUNIT_ASSERT(!totalOnly.isNull());
197 CPPUNIT_ASSERT_EQUAL(0, totalOnly.position());
198 CPPUNIT_ASSERT_EQUAL(5, totalOnly.total());
199 CPPUNIT_ASSERT_EQUAL("/5"s, totalOnly.toString());
200}
201
203{
204 unsigned int steps = 0;
205 string step;
206 unsigned int stepPercentage;
207 unsigned int overallPercentage = 0;
208
209 ProgressFeedback progressFeedback(
210 [&](const ProgressFeedback &progress) {
211 ++steps;
212 step = progress.step();
213 stepPercentage = progress.stepPercentage();
214 overallPercentage = progress.overallPercentage();
215 },
216 [&](const ProgressFeedback &progress) {
217 stepPercentage = progress.stepPercentage();
218 overallPercentage = progress.overallPercentage();
219 });
220 CPPUNIT_ASSERT_EQUAL(0u, steps);
221 progressFeedback.updateOverallPercentage(25);
222 CPPUNIT_ASSERT_EQUAL(0u, steps);
223 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
224 progressFeedback.updateStep("foo", 45);
225 CPPUNIT_ASSERT_EQUAL(1u, steps);
226 CPPUNIT_ASSERT_EQUAL("foo"s, step);
227 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
228 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
229 progressFeedback.updateStepPercentage(60);
230 CPPUNIT_ASSERT_EQUAL(1u, steps);
231 CPPUNIT_ASSERT_EQUAL("foo"s, step);
232 CPPUNIT_ASSERT_EQUAL(60u, stepPercentage);
233 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
234 progressFeedback.updateStepPercentageFromFraction(0.75);
235 CPPUNIT_ASSERT_EQUAL(1u, steps);
236 CPPUNIT_ASSERT_EQUAL("foo"s, step);
237 CPPUNIT_ASSERT_EQUAL(75u, stepPercentage);
238 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
239}
240
242{
243 unsigned int steps = 0;
244 string step;
245 unsigned int stepPercentage;
246 unsigned int overallPercentage = 0;
247
248 AbortableProgressFeedback progressFeedback(
249 [&](const AbortableProgressFeedback &progress) {
250 ++steps;
251 step = progress.step();
252 stepPercentage = progress.stepPercentage();
253 overallPercentage = progress.overallPercentage();
254 },
255 [&](const AbortableProgressFeedback &progress) {
256 stepPercentage = progress.stepPercentage();
257 overallPercentage = progress.overallPercentage();
258 });
259 CPPUNIT_ASSERT(!progressFeedback.isAborted());
260 CPPUNIT_ASSERT_NO_THROW_MESSAGE("stop does nothing if not aborted", progressFeedback.stopIfAborted());
261 CPPUNIT_ASSERT_EQUAL(0u, steps);
262 progressFeedback.updateOverallPercentage(25);
263 CPPUNIT_ASSERT_EQUAL(0u, steps);
264 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
265 progressFeedback.updateStep("foo", 45);
266 CPPUNIT_ASSERT_EQUAL(1u, steps);
267 CPPUNIT_ASSERT_EQUAL("foo"s, step);
268 CPPUNIT_ASSERT_EQUAL(45u, stepPercentage);
269 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
270 CPPUNIT_ASSERT_NO_THROW_MESSAGE("next step continues if not aborted", progressFeedback.nextStepOrStop("bar", 33));
271 CPPUNIT_ASSERT_EQUAL(2u, steps);
272 CPPUNIT_ASSERT_EQUAL("bar"s, step);
273 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
274 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
275 progressFeedback.tryToAbort();
276 CPPUNIT_ASSERT(progressFeedback.isAborted());
277 CPPUNIT_ASSERT_THROW(progressFeedback.nextStepOrStop("not going to happen", 33), OperationAbortedException);
278 CPPUNIT_ASSERT_EQUAL(2u, steps);
279 CPPUNIT_ASSERT_EQUAL("bar"s, step);
280 CPPUNIT_ASSERT_EQUAL(33u, stepPercentage);
281 CPPUNIT_ASSERT_EQUAL(25u, overallPercentage);
282}
283
285{
286 Diagnostics diag;
287 CPPUNIT_ASSERT_EQUAL(DiagLevel::None, diag.level());
288 diag.emplace_back(DiagLevel::Warning, "warning msg", "context");
289 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.level());
290 CPPUNIT_ASSERT(!diag.has(DiagLevel::Critical));
291 diag.emplace_back(DiagLevel::Critical, "critical msg", "context");
292 CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.level());
293 CPPUNIT_ASSERT(diag.has(DiagLevel::Critical));
294}
295
297{
298 using namespace BackupHelper;
299
300 // setup testfile
301 MediaFileInfo file(workingCopyPath("unsupported.bin"));
302 file.setBackupDirectory(string()); // ensure backup directory is empty, so backups will be created in the same directory as the original file
303 const auto workingDir(file.containingDirectory());
304 file.open();
305
306 // create backup file
307 string backupPath1, backupPath2;
308 NativeFileStream backupStream1, backupStream2;
309 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
310 CPPUNIT_ASSERT_EQUAL(workingDir + "/unsupported.bin.bak", backupPath1);
311
312 // recreate original file (like the 'make' methods would do to apply changes)
313 file.stream().open(file.path(), ios_base::out);
314 file.stream() << "test1" << endl;
315
316 // create a 2nd backup which should not override the first one
317 createBackupFile(string(), file.path(), backupPath2, file.stream(), backupStream2);
318 CPPUNIT_ASSERT_EQUAL(workingDir + "/unsupported.bin.1.bak", backupPath2);
319
320 // get rid of 2nd backup, recreate original file
321 backupStream2.close();
322 remove(backupPath2.data());
323 file.stream().open(file.path(), ios_base::out);
324 file.stream() << "test2" << endl;
325
326 // create backup under another location
327 try {
328 createBackupFile("bak", file.path(), backupPath2, file.stream(), backupStream2);
329 CPPUNIT_FAIL("renaming failed because backup dir does not exist");
330 } catch (const std::ios_base::failure &failure) {
331 TESTUTILS_ASSERT_LIKE("renaming error", "Unable to create backup file .* of .* before rewriting it: .*"s, string(failure.what()));
332 }
333 backupStream2.clear();
334 workingCopyPath("bak/unsupported.bin", WorkingCopyMode::NoCopy);
335 createBackupFile("bak", file.path(), backupPath2, file.stream(), backupStream2);
336 CPPUNIT_ASSERT_EQUAL(workingDir + "/bak/unsupported.bin", backupPath2);
337
338 // get rid of 2nd backup (again)
339 backupStream2.close();
340 CPPUNIT_ASSERT_EQUAL_MESSAGE("remove " + backupPath2, 0, remove(backupPath2.data()));
341 std::filesystem::remove_all(workingDir + "/bak");
342
343 // should be able to use backup stream, eg. seek to the end
344 backupStream1.seekg(0, ios_base::end);
345 CPPUNIT_ASSERT_EQUAL(41_st, static_cast<size_t>(backupStream1.tellg()));
346
347 // restore backup
348 restoreOriginalFileFromBackupFile(file.path(), backupPath1, file.stream(), backupStream1);
349
350 // check restored backup
351 file.open(true);
352 file.stream().seekg(0x1D);
353 CPPUNIT_ASSERT_EQUAL(0x34_st, static_cast<size_t>(file.stream().get()));
354 file.close();
355
356 // restore after user aborted
357 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
358 try {
360 } catch (...) {
361 Diagnostics diag;
362 CPPUNIT_ASSERT_THROW(
363 handleFailureAfterFileModified(file, backupPath1, file.stream(), backupStream1, diag, "test"), OperationAbortedException);
364 CPPUNIT_ASSERT(diag.level() < DiagLevel::Critical);
365 CPPUNIT_ASSERT(!diag.empty());
366 CPPUNIT_ASSERT_EQUAL("Rewriting the file to apply changed tag information has been aborted."s, diag.front().message());
367 CPPUNIT_ASSERT_EQUAL("The original file has been restored."s, diag.back().message());
368 }
369
370 // restore after error
371 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
372 try {
373 throw Failure();
374 } catch (...) {
375 Diagnostics diag;
376 CPPUNIT_ASSERT_THROW(handleFailureAfterFileModified(file, backupPath1, file.stream(), backupStream1, diag, "test"), Failure);
377 CPPUNIT_ASSERT(diag.level() >= DiagLevel::Critical);
378 CPPUNIT_ASSERT_EQUAL("Rewriting the file to apply changed tag information failed."s, diag.front().message());
379 CPPUNIT_ASSERT_EQUAL("The original file has been restored."s, diag.back().message());
380 }
381
382 // restore after io failure
383 createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1);
384 try {
385 throw std::ios_base::failure("simulated IO failure");
386 } catch (const std::ios_base::failure &) {
387 Diagnostics diag;
388 CPPUNIT_ASSERT_THROW_MESSAGE("IO failure re-thrown",
389 handleFailureAfterFileModified(file, backupPath1, file.stream(), backupStream1, diag, "test"), std::ios_base::failure);
390 CPPUNIT_ASSERT(diag.level() >= DiagLevel::Critical);
391 CPPUNIT_ASSERT_EQUAL("An IO error occurred when rewriting the file to apply changed tag information."s, diag.front().message());
392 CPPUNIT_ASSERT_EQUAL("The original file has been restored."s, diag.back().message());
393 }
394
395 CPPUNIT_ASSERT_EQUAL(0, remove(file.path().data()));
396}
397
402{
403 auto tag = Id3v2Tag();
404 tag.setVersion(4, 0);
405 for (auto knownField = firstKnownField; knownField != KnownField::Invalid; knownField = nextKnownField(knownField)) {
406 if (const auto fieldId = tag.fieldId(knownField)) {
407 CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse mapping for known field exists", knownField, tag.knownField(fieldId));
408 }
409 }
410 tag.setVersion(2, 0);
411 for (auto knownField = firstKnownField; knownField != KnownField::Invalid; knownField = nextKnownField(knownField)) {
412 if (const auto fieldId = tag.fieldId(knownField)) {
413 CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse mapping for known field exists", knownField, tag.knownField(fieldId));
414 }
415 }
416}
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
const std::string & path() const
Returns the path of the current file.
static std::string containingDirectory(std::string_view path)
Returns the path of the directory containing the given file.
CppUtilities::NativeFileStream & stream()
Returns the std::fstream for the current instance.
void open(bool readOnly=false)
Opens a std::fstream for the current file.
void close()
A possibly opened std::fstream will be closed.
std::uint8_t stepPercentage() const
Returns the percentage of the current step (initially 0, supposed to be a value from 0 to 100).
const std::string & step() const
Returns the name of the current step (initially empty).
std::uint8_t overallPercentage() const
Returns the overall percentage (initially 0, supposed to be a value from 0 to 100).
The Diagnostics class is a container for DiagMessage.
bool has(DiagLevel level) const
Returns whether there's at least one DiagMessage which is at least as worse as level.
DiagLevel level() const
Returns the worst diag level present in the container.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
The Margin class defines the four margins of a rectangle.
Definition margin.h:16
constexpr bool isNull() const
Returns true if all margins are is 0; otherwise returns false;.
Definition margin.h:115
The MediaFileInfo class allows to read and write tag information providing a container/tag format ind...
void setBackupDirectory(std::string_view backupDirectory)
Sets the directory used to store backup files.
The MediaFormat class specifies the format of media data.
std::string_view abbreviation() const
Returns the abbreviation of the media format as C-style string.
std::string_view shortAbbreviation() const
Returns a short abbreviation of the media format as C-style string.
std::string_view name() const
Returns the name of the media format as C-style string.
std::string_view extensionName() const
Returns the abbreviation of the media format as C-style string.
The exception that is thrown when an operation has been stopped and thus not successfully completed b...
The PositionInSet class describes the position of an element in a set which consists of a certain num...
constexpr std::int32_t position() const
Returns the element position of the current instance.
constexpr std::int32_t total() const
Returns the total element count of the current instance.
StringType toString() const
Returns the string representation of the current PositionInSet.
constexpr bool isNull() const
Returns an indication whether both the element position and total element count is 0.
The ProgressFeedback class provides feedback about an ongoing operation via callbacks.
The Size class defines the size of a two-dimensional object using integer point precision.
Definition size.h:17
void setWidth(std::uint32_t value)
Sets the width.
Definition size.h:76
bool constexpr isNull() const
Returns an indication whether both the width and height is 0.
Definition size.h:100
std::string toString() const
Returns the string representation of the current size.
Definition size.h:125
constexpr std::uint32_t resolution() const
Returns the resolution of the current instance (product of with and height).
Definition size.h:92
void setHeight(std::uint32_t value)
Sets the height.
Definition size.h:84
std::string_view abbreviation() const
Returns an abbreviation for the current instance, eg.
Definition size.cpp:17
The TagTarget class specifies the target of a tag.
std::uint64_t level() const
Returns the level.
Definition tagtarget.h:73
std::string toString(const std::function< TagTargetLevel(std::uint64_t)> &tagTargetMapping) const
Returns the string representation of the current instance.
Definition tagtarget.h:217
bool isEmpty() const
Returns an indication whether the target is empty.
Definition tagtarget.h:169
void clear()
Clears the TagTarget.
Definition tagtarget.h:177
void setLevel(std::uint64_t level)
Sets the level.
Definition tagtarget.h:81
void setLevelName(const std::string &levelName)
Sets the level name.
Definition tagtarget.h:97
The UtilitiesTests class tests various utility classes and functions of the tagparser library.
Definition utils.cpp:37
void testPositionInSet()
Definition utils.cpp:175
void testSize()
Definition utils.cpp:82
void testTagTarget()
Definition utils.cpp:96
void testProgressFeedback()
Definition utils.cpp:202
void tearDown() override
Definition utils.cpp:78
void testFieldConversions()
Tests whether field mappings are consistent.
Definition utils.cpp:401
void testStatusProvider()
void testAbortableProgressFeedback()
Definition utils.cpp:241
void testAspectRatio()
Definition utils.cpp:143
void testMargin()
Definition utils.cpp:135
void testSignature()
Definition utils.cpp:119
void testDiagnostics()
Definition utils.cpp:284
void setUp() override
Definition utils.cpp:74
void testBackupFile()
Definition utils.cpp:296
void testMediaFormat()
Definition utils.cpp:157
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TAG_PARSER_EXPORT std::string_view containerFormatSubversion(ContainerFormat containerFormat)
Returns the subversion of the container format as C-style string.
TAG_PARSER_EXPORT std::string_view containerFormatAbbreviation(ContainerFormat containerFormat, MediaType mediaType=MediaType::Unknown, unsigned int version=0)
Returns the abbreviation of the container format as C-style string considering the specified media ty...
constexpr KnownField nextKnownField(KnownField field)
Returns the next known field skipping any deprecated fields.
Definition tag.h:171
TAG_PARSER_EXPORT std::string_view containerFormatName(ContainerFormat containerFormat)
Returns the name of the specified container format as C-style string.
TAG_PARSER_EXPORT ContainerFormat parseSignature(const char *buffer, std::size_t bufferSize)
Definition signature.h:83
constexpr KnownField firstKnownField
The first valid entry in the TagParser::KnownField enum.
Definition tag.h:147
The AspectRatio struct defines an aspect ratio.
std::uint16_t numerator
Definition aspectratio.h:22
std::uint16_t denominator
Definition aspectratio.h:23
constexpr bool isExtended() const
Returns whether numerator and denominator must be read from extended SAR header.
Definition aspectratio.h:58
constexpr bool isValid() const
Returns an indication whether the aspect ratio is present and valid.
Definition aspectratio.h:50
CPPUNIT_TEST_SUITE_REGISTRATION(UtilitiesTests)