Allow extending important classes without ABI break

This allows to make ABI breaks less often while still
being able to extend many aspects of the library.
This commit is contained in:
Martchus 2023-05-11 22:54:24 +02:00
parent 6ed968f5e6
commit 8ad28f857b
14 changed files with 201 additions and 145 deletions

View File

@ -14,6 +14,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The AbstractAttachmentPrivate struct contains private fields of the AbstractAttachment class.
struct AbstractAttachmentPrivate {};
/*!
* \class TagParser::StreamDataBlock
* \brief The StreamDataBlock class is a reference to a certain data block of a stream.
@ -127,6 +130,23 @@ FileDataBlock::~FileDataBlock()
* \brief The AbstractAttachment class parses and stores attachment information.
*/
/*!
* \brief Constructs a new attachment.
*/
AbstractAttachment::AbstractAttachment()
: m_id(0)
, m_isDataFromFile(false)
, m_ignored(false)
{
}
/*!
* \brief Destroys the attachment.
*/
AbstractAttachment::~AbstractAttachment()
{
}
/*!
* \brief Returns a label for the track.
*/

View File

@ -102,6 +102,8 @@ inline const MediaFileInfo *FileDataBlock::fileInfo() const
return m_fileInfo.get();
}
struct AbstractAttachmentPrivate;
class TAG_PARSER_EXPORT AbstractAttachment {
public:
const std::string &description() const;
@ -123,7 +125,8 @@ public:
bool isEmpty() const;
protected:
AbstractAttachment();
explicit AbstractAttachment();
virtual ~AbstractAttachment();
private:
std::string m_description;
@ -131,20 +134,11 @@ private:
std::string m_mimeType;
std::uint64_t m_id;
std::unique_ptr<StreamDataBlock> m_data;
std::unique_ptr<AbstractAttachmentPrivate> m_p;
bool m_isDataFromFile;
bool m_ignored;
};
/*!
* \brief Constructs a new attachment.
*/
inline AbstractAttachment::AbstractAttachment()
: m_id(0)
, m_isDataFromFile(false)
, m_ignored(false)
{
}
/*!
* \brief Returns a description of the attachment.
*/

View File

@ -8,6 +8,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The AbstractChapterPrivate struct contains private fields of the AbstractChapter class.
struct AbstractChapterPrivate {};
/*!
* \class TagParser::AbstractChapter
* \brief The AbstractChapter class parses chapter information.

View File

@ -5,6 +5,7 @@
#include <c++utilities/chrono/timespan.h>
#include <memory>
#include <string>
#include <vector>
@ -12,6 +13,7 @@ namespace TagParser {
class AbortableProgressFeedback;
class Diagnostics;
struct AbstractChapterPrivate;
class TAG_PARSER_EXPORT AbstractChapter {
public:
@ -41,6 +43,7 @@ protected:
CppUtilities::TimeSpan m_startTime;
CppUtilities::TimeSpan m_endTime;
std::vector<std::uint64_t> m_tracks;
std::unique_ptr<AbstractChapterPrivate> m_p;
bool m_hidden;
bool m_enabled;
};

View File

@ -6,6 +6,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The AbstractContainerPrivate struct contains private fields of the AbstractContainer class.
struct AbstractContainerPrivate {};
/*!
* \class TagParser::AbstractContainer
* \brief The AbstractContainer class provides an interface and common functionality to parse and make a certain container format.

View File

@ -11,6 +11,7 @@
#include <c++utilities/io/binarywriter.h>
#include <iostream>
#include <memory>
namespace CppUtilities {
class BinaryReader;
@ -25,6 +26,7 @@ class AbstractChapter;
class AbstractAttachment;
class Diagnostics;
class AbortableProgressFeedback;
struct AbstractContainerPrivate;
class TAG_PARSER_EXPORT AbstractContainer {
public:
@ -119,6 +121,7 @@ private:
std::iostream *m_stream;
CppUtilities::BinaryReader m_reader;
CppUtilities::BinaryWriter m_writer;
std::unique_ptr<AbstractContainerPrivate> m_p;
};
/*!

View File

@ -11,6 +11,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The AbstractTrackPrivate struct contains private fields of the AbstractTrack class.
struct AbstractTrackPrivate {};
/*!
* \class TagParser::AbstractTrack
* \brief The AbstractTrack class parses and stores technical information about

View File

@ -15,6 +15,7 @@
#include <c++utilities/misc/flagenumclass.h>
#include <iosfwd>
#include <memory>
#include <string>
#include <string_view>
@ -104,6 +105,8 @@ CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(TagParser, TagParser::TrackFlags)
namespace TagParser {
struct AbstractTrackPrivate;
class TAG_PARSER_EXPORT AbstractTrack {
friend class MpegAudioFrameStream;
friend class WaveAudioStream;
@ -232,6 +235,7 @@ protected:
AlphaMode m_alphaMode;
DisplayUnit m_displayUnit;
AspectRatioType m_aspectRatioType;
std::unique_ptr<AbstractTrackPrivate> m_p;
private:
std::string makeDescription(bool verbose) const;

View File

@ -59,6 +59,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The MediaFileInfoPrivate struct contains private fields of the MediaFileInfo class.
struct MediaFileInfoPrivate {};
/*!
* \class TagParser::MediaFileInfo
* \brief The MediaFileInfo class allows to read and write tag information providing

View File

@ -73,6 +73,8 @@ CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(TagParser, TagParser::MediaFileHandlingFlags)
namespace TagParser {
struct MediaFileInfoPrivate;
class TAG_PARSER_EXPORT MediaFileInfo : public BasicFileInfo {
public:
// constructor, destructor
@ -226,6 +228,7 @@ private:
ElementPosition m_tagPosition;
ElementPosition m_indexPosition;
MediaFileHandlingFlags m_fileHandlingFlags;
std::unique_ptr<MediaFileInfoPrivate> m_p;
};
/*!

View File

@ -4,6 +4,9 @@ using namespace std;
namespace TagParser {
/// \brief The TagPrivate struct contains private fields of the Tag class.
struct TagPrivate {};
/*!
* \class TagParser::Tag
* \brief The Tag class is used to store, read and write tag information.

4
tag.h
View File

@ -8,6 +8,7 @@
#include <c++utilities/io/binaryreader.h>
#include <cstdint>
#include <memory>
#include <string>
#include <type_traits>
@ -160,6 +161,8 @@ constexpr KnownField nextKnownField(KnownField field)
return isKnownFieldDeprecated(next) ? nextKnownField(next) : next;
}
struct TagPrivate;
class TAG_PARSER_EXPORT Tag {
public:
virtual ~Tag();
@ -199,6 +202,7 @@ protected:
std::string m_version;
std::uint64_t m_size;
std::unique_ptr<TagPrivate> m_p;
TagTarget m_target;
};

View File

@ -22,6 +22,9 @@ using namespace CppUtilities;
namespace TagParser {
/// \brief The TagValuePrivate struct contains private fields of the TagValue class.
struct TagValuePrivate {};
/*!
* \brief Returns the string representation of the specified \a dataType.
*/
@ -145,6 +148,140 @@ TagValue::TagValue(const TagValue &other)
}
}
TagValue::TagValue(TagValue &&other) = default;
/*!
* \brief Constructs an empty TagValue.
*/
TagValue::TagValue()
: m_size(0)
, m_type(TagDataType::Undefined)
, m_encoding(TagTextEncoding::Latin1)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textSize Specifies the size of \a text. (The actual number of bytes, not the number of characters.)
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
TagValue::TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textSize, textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned. This string must be null-terminated.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
{
assignText(text, std::strlen(text), textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
TagValue::TagValue(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
TagValue::TagValue(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textEncoding, convertTo);
}
/*!
* \brief Destroys the TagValue.
*/
TagValue::~TagValue()
{
}
/*!
* \brief Constructs a new TagValue with a copy of the given \a data.
*
* \param data Specifies a pointer to the data.
* \param length Specifies the length of the data.
* \param type Specifies the type of the data as TagDataType.
* \param encoding Specifies the encoding of the data as TagTextEncoding. The
* encoding will only be considered if a text is assigned.
* \remarks Strips the BOM of the specified \a data if \a type is TagDataType::Text.
*/
TagValue::TagValue(const char *data, std::size_t length, TagDataType type, TagTextEncoding encoding)
: m_size(length)
, m_type(type)
, m_encoding(encoding)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
if (length) {
if (type == TagDataType::Text) {
stripBom(data, m_size, encoding);
}
m_ptr = std::make_unique<char[]>(m_size);
std::copy(data, data + m_size, m_ptr.get());
}
}
/*!
* \brief Constructs a new TagValue holding with the given \a data.
*
* The \a data is not copied. It is moved.
*
* \param data Specifies a pointer to the data.
* \param length Specifies the length of the data.
* \param type Specifies the type of the data as TagDataType.
* \param encoding Specifies the encoding of the data as TagTextEncoding. The
* encoding will only be considered if a text is assigned.
* \remarks Does not strip the BOM so for consistency the caller must ensure there is no BOM present.
*/
TagValue::TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type, TagTextEncoding encoding)
: m_size(length)
, m_type(type)
, m_encoding(encoding)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
if (length) {
m_ptr = std::move(data);
}
}
/*!
* \brief Assigns the value of another TagValue to the current instance.
*/
@ -170,6 +307,8 @@ TagValue &TagValue::operator=(const TagValue &other)
return *this;
}
TagValue &TagValue::operator=(TagValue &&other) = default;
/// \cond
TagTextEncoding pickUtfEncoding(TagTextEncoding encoding1, TagTextEncoding encoding2)
{

View File

@ -140,6 +140,8 @@ enum class TagValueComparisionFlags : unsigned int {
IgnoreMetaData = 0x2, /**< do *not* take meta-data like description and MIME-types into account */
};
struct TagValuePrivate;
class TAG_PARSER_EXPORT TagValue {
public:
// constructor, destructor
@ -164,12 +166,12 @@ public:
explicit TagValue(CppUtilities::TimeSpan value);
explicit TagValue(const Popularity &value);
TagValue(const TagValue &other);
TagValue(TagValue &&other) = default;
TagValue(TagValue &&other);
~TagValue();
// operators
TagValue &operator=(const TagValue &other);
TagValue &operator=(TagValue &&other) = default;
TagValue &operator=(TagValue &&other);
bool operator==(const TagValue &other) const;
bool operator!=(const TagValue &other) const;
operator bool() const;
@ -260,90 +262,9 @@ private:
TagTextEncoding m_encoding;
TagTextEncoding m_descEncoding;
TagValueFlags m_flags;
std::unique_ptr<TagValuePrivate> m_p;
};
/*!
* \brief Constructs an empty TagValue.
*/
inline TagValue::TagValue()
: m_size(0)
, m_type(TagDataType::Undefined)
, m_encoding(TagTextEncoding::Latin1)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
}
/*!
* \brief Destroys the TagValue.
*/
inline TagValue::~TagValue()
{
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textSize Specifies the size of \a text. (The actual number of bytes, not the number of characters.)
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
inline TagValue::TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textSize, textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned. This string must be null-terminated.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
inline TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
{
assignText(text, std::strlen(text), textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
inline TagValue::TagValue(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding a copy of the given \a text.
* \param text Specifies the text to be assigned.
* \param textEncoding Specifies the encoding of the given \a text.
* \param convertTo Specifies the encoding to convert \a text to; set to TagTextEncoding::Unspecified to
* use \a textEncoding without any character set conversions.
* \throws Throws a ConversionException if the conversion the specified character set fails.
* \remarks Strips the BOM of the specified \a text.
*/
inline TagValue::TagValue(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
: m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
assignText(text, textEncoding, convertTo);
}
/*!
* \brief Constructs a new TagValue holding the given integer \a value.
*/
@ -360,56 +281,6 @@ inline TagParser::TagValue::TagValue(std::uint64_t value)
{
}
/*!
* \brief Constructs a new TagValue with a copy of the given \a data.
*
* \param data Specifies a pointer to the data.
* \param length Specifies the length of the data.
* \param type Specifies the type of the data as TagDataType.
* \param encoding Specifies the encoding of the data as TagTextEncoding. The
* encoding will only be considered if a text is assigned.
* \remarks Strips the BOM of the specified \a data if \a type is TagDataType::Text.
*/
inline TagValue::TagValue(const char *data, std::size_t length, TagDataType type, TagTextEncoding encoding)
: m_size(length)
, m_type(type)
, m_encoding(encoding)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
if (length) {
if (type == TagDataType::Text) {
stripBom(data, m_size, encoding);
}
m_ptr = std::make_unique<char[]>(m_size);
std::copy(data, data + m_size, m_ptr.get());
}
}
/*!
* \brief Constructs a new TagValue holding with the given \a data.
*
* The \a data is not copied. It is moved.
*
* \param data Specifies a pointer to the data.
* \param length Specifies the length of the data.
* \param type Specifies the type of the data as TagDataType.
* \param encoding Specifies the encoding of the data as TagTextEncoding. The
* encoding will only be considered if a text is assigned.
* \remarks Does not strip the BOM so for consistency the caller must ensure there is no BOM present.
*/
inline TagValue::TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type, TagTextEncoding encoding)
: m_size(length)
, m_type(type)
, m_encoding(encoding)
, m_descEncoding(TagTextEncoding::Latin1)
, m_flags(TagValueFlags::None)
{
if (length) {
m_ptr = std::move(data);
}
}
/*!
* \brief Constructs a new TagValue holding a copy of the given PositionInSet \a value.
*/