From 0eac6241abdaf4cf0645210872b1b423f6d41546 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Mon, 18 Dec 2023 15:36:25 +0100 Subject: [PATCH] use a templated type for default values So the default value is hardcoded in the class semantic info and not set in the constructor. A new EbmlElement subclass is created for EbmlElement types that may have a default value. An IsSameValue() method is added to compare an element to a value. This is used by the EbmlElementDefault class to tell if the element value is the same as the default when there is one. --- ebml/EbmlDate.h | 8 +- ebml/EbmlElement.h | 185 ++++++++++++++++++++++++++++++-------- ebml/EbmlFloat.h | 14 +-- ebml/EbmlSInteger.h | 14 +-- ebml/EbmlString.h | 14 +-- ebml/EbmlSubHead.h | 14 +-- ebml/EbmlUInteger.h | 14 +-- ebml/EbmlUnicodeString.h | 14 +-- src/EbmlFloat.cpp | 24 +---- src/EbmlMaster.cpp | 7 +- src/EbmlSInteger.cpp | 10 +-- src/EbmlString.cpp | 37 +------- src/EbmlUInteger.cpp | 23 +---- src/EbmlUnicodeString.cpp | 26 +----- test/test_infinite.cxx | 2 +- test/test_macros.cxx | 56 +++++++++--- 16 files changed, 239 insertions(+), 223 deletions(-) diff --git a/ebml/EbmlDate.h b/ebml/EbmlDate.h index 3397d5a7..08bb5f57 100644 --- a/ebml/EbmlDate.h +++ b/ebml/EbmlDate.h @@ -17,9 +17,9 @@ namespace libebml { \class EbmlDate \brief Handle all operations related to an EBML date */ -class EBML_DLL_API EbmlDate : public EbmlElement { +class EBML_DLL_API EbmlDate : public EbmlElementDefault { public: - EbmlDate(const EbmlCallbacks & classInfo) :EbmlElement(classInfo, 8, false) {} + EbmlDate(const EbmlCallbacksDefault & classInfo) :EbmlElementDefault(classInfo, 8) {} /*! \brief set the date with a UNIX/C/EPOCH form @@ -52,8 +52,8 @@ class EBML_DLL_API EbmlDate : public EbmlElement { filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA) override; - bool IsDefaultValue() const override { - return false; + bool operator==(const std::int64_t & val) const override { + return val == Value; } private: diff --git a/ebml/EbmlElement.h b/ebml/EbmlElement.h index e35c2f19..a80fd2f7 100644 --- a/ebml/EbmlElement.h +++ b/ebml/EbmlElement.h @@ -14,6 +14,7 @@ #include #include +#include namespace libebml { @@ -56,68 +57,75 @@ class EbmlElement; #define DEFINE_xxx_MASTER(x,id,idl,parent,infinite,name,global) \ constexpr const libebml::EbmlId Id_##x (id, idl); \ const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, &Context_##parent, global, &EBML_INFO(x)); \ - constexpr libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); \ + const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); \ x::x() :libebml::EbmlMaster(x::ClassInfos, Context_##x) {} +// define a master class with a custom constructor #define DEFINE_xxx_MASTER_CONS(x,id,idl,parent,infinite,name,global) \ constexpr const libebml::EbmlId Id_##x (id, idl); \ const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, &Context_##parent, global, &EBML_INFO(x)); \ - constexpr libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); + const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); // define a master class with no parent class #define DEFINE_xxx_MASTER_ORPHAN(x,id,idl,infinite,name,global) \ constexpr const libebml::EbmlId Id_##x (id, idl); \ const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, nullptr, global, &EBML_INFO(x)); \ - constexpr libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); \ + const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, name, Context_##x); \ #define DEFINE_xxx_CLASS_CONS(x,id,idl,parent,name,global) \ constexpr const libebml::EbmlId Id_##x (id, idl); \ - const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(0, nullptr, &Context_##parent, global, &EBML_INFO(x)); \ - constexpr libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, false, name, Context_##x); + const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(0, nullptr, &Context_##parent, global, &EBML_INFO(x)); #define DEFINE_xxx_CLASS_BASE(x,BaseClass,id,idl,parent,name,global) \ DEFINE_xxx_CLASS_CONS(x,id,idl,parent,name,global) \ + const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, false, name, Context_##x); \ x::x() :libebml::BaseClass(x::ClassInfos) {} -#define DEFINE_xxx_CLASS_BASE_DEFAULT(x,BaseClass,id,idl,parent,name,global,defval) \ +#define DEFINE_xxx_CLASS_BASE_DEFAULT(x,BaseClass,id,idl,parent,name,global,StorageType,defval) \ DEFINE_xxx_CLASS_CONS(x,id,idl,parent,name,global) \ - x::x() :libebml::BaseClass(x::ClassInfos, defval) {} + const libebml::EbmlCallbacksWithDefault x::ClassInfos(x::Create, Id_##x, defval, name, Context_##x); \ + x::x() :libebml::BaseClass(x::ClassInfos) {} + +#define DEFINE_xxx_CLASS_BASE_NODEFAULT(x,BaseClass,id,idl,parent,name,global,StorageType) \ + DEFINE_xxx_CLASS_CONS(x,id,idl,parent,name,global) \ + const libebml::EbmlCallbacksWithoutDefault x::ClassInfos(x::Create, Id_##x, name, Context_##x); \ + x::x() :libebml::BaseClass(x::ClassInfos) {} #define DEFINE_xxx_UINTEGER(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlUInteger,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlUInteger,id,idl,parent,name,global,std::uint64_t) #define DEFINE_xxx_SINTEGER(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlSInteger,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlSInteger,id,idl,parent,name,global,std::int64_t) #define DEFINE_xxx_STRING(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlString,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlString,id,idl,parent,name,global,const char *) #define DEFINE_xxx_UNISTRING(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlUnicodeString,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlUnicodeString,id,idl,parent,name,global, const wchar_t *) #define DEFINE_xxx_FLOAT(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlFloat,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlFloat,id,idl,parent,name,global,double) #define DEFINE_xxx_DATE(x,id,idl,parent,name,global) \ - DEFINE_xxx_CLASS_BASE(x,EbmlDate,id,idl,parent,name,global) + DEFINE_xxx_CLASS_BASE_NODEFAULT(x,EbmlDate,id,idl,parent,name,global,std::int64_t) #define DEFINE_xxx_BINARY(x,id,idl,parent,name,global) \ DEFINE_xxx_CLASS_BASE(x,EbmlBinary,id,idl,parent,name,global) #define DEFINE_xxx_UINTEGER_DEF(x,id,idl,parent,name,global,defval) \ - DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlUInteger,id,idl,parent,name,global,defval) + DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlUInteger,id,idl,parent,name,global,std::uint64_t,defval) #define DEFINE_xxx_SINTEGER_DEF(x,id,idl,parent,name,global,defval) \ - DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlSInteger,id,idl,parent,name,global,defval) + DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlSInteger,id,idl,parent,name,global,std::int64_t,defval) #define DEFINE_xxx_STRING_DEF(x,id,idl,parent,name,global,defval) \ - DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlString,id,idl,parent,name,global,defval) + DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlString,id,idl,parent,name,global,const char *,defval) #define DEFINE_xxx_UNISTRING_DEF(x,id,idl,parent,name,global,defval) \ - DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlUnicodeString,id,idl,parent,name,global,defval) + DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlUnicodeString,id,idl,parent,name,global,const wchar_t*,defval) #define DEFINE_xxx_FLOAT_DEF(x,id,idl,parent,name,global,defval) \ - DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlFloat,id,idl,parent,name,global,defval) + DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlFloat,id,idl,parent,name,global,double,defval) #define DEFINE_xxx_DATE_DEF(x,id,idl,parent,name,global,defval) \ DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlDate,id,idl,parent,name,global,defval) @@ -125,7 +133,7 @@ class EbmlElement; #define DEFINE_xxx_CLASS_ORPHAN(x,id,idl,name,global) \ constexpr const libebml::EbmlId Id_##x (id, idl); \ const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(0, nullptr, nullptr, global, nullptr); \ - constexpr libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, false, name, Context_##x); \ + const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, false, name, Context_##x); \ #define DEFINE_EBML_CONTEXT(x) DEFINE_xxx_CONTEXT(x,GetEbmlGlobal_Context) #define DEFINE_EBML_MASTER(x,id,idl,parent,infinite,name) DEFINE_xxx_MASTER(x,id,idl,parent,infinite,name,GetEbmlGlobal_Context) @@ -138,39 +146,83 @@ class EbmlElement; #define DEFINE_START_SEMANTIC(x) static const libebml::EbmlSemantic ContextList_##x[] = { #define DEFINE_END_SEMANTIC(x) }; #define DEFINE_SEMANTIC_ITEM(m,u,c) libebml::EbmlSemantic(m, u, EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_UINT(m,u,d,c) EbmlSemantic(m, u, static_cast(d), EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_SINT(m,u,d,c) EbmlSemantic(m, u, static_cast(d), EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_DATE(m,u,d,c) EbmlSemantic(m, u, static_cast(d,true), EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_FLOAT(m,u,d,c) EbmlSemantic(m, u, static_cast(d), EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_STRING(m,u,d,c) EbmlSemantic(m, u, static_cast(d), EBML_INFO(c)), +#define DEFINE_SEMANTIC_ITEM_UTF8(m,u,d,c) EbmlSemantic(m, u, static_cast(d), EBML_INFO(c)), + +#define DECLARE_xxx_BASE_DEFAULT(x, DllApi, BaseClass, StorageType) \ +class DllApi x : public BaseClass { \ + private: \ + static const libebml::EbmlCallbacksWithDefault ClassInfos; \ + public: \ + const libebml::EbmlCallbacksWithDefault & ElementSpec() const override { return ClassInfos; } \ + static const libebml::EbmlCallbacksWithDefault & GetElementSpec() { return ClassInfos; } \ + x(); + +#define DECLARE_xxx_BASE_NODEFAULT(x, DllApi, BaseClass, StorageType) \ +class DllApi x : public BaseClass { \ + private: \ + static const libebml::EbmlCallbacksWithoutDefault ClassInfos; \ + public: \ + const libebml::EbmlCallbacksWithoutDefault & ElementSpec() const override { return ClassInfos; } \ + static const libebml::EbmlCallbacksWithoutDefault & GetElementSpec() { return ClassInfos; } \ + x(); #define DECLARE_xxx_BASE(x, DllApi, BaseClass) \ class DllApi x : public BaseClass { \ + private: \ + static const libebml::EbmlCallbacks ClassInfos; \ public: \ x(); #define DECLARE_xxx_MASTER(x,DllApi) \ DECLARE_xxx_BASE(x, DllApi, libebml::EbmlMaster) +#define DECLARE_xxx_BINARY(x,DllApi) \ + DECLARE_xxx_BASE(x, DllApi, libebml::EbmlBinary) + #define DECLARE_xxx_UINTEGER(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlUInteger) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlUInteger, std::uint64_t) #define DECLARE_xxx_SINTEGER(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlSInteger) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlSInteger, std::int64_t) #define DECLARE_xxx_STRING(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlString) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlString, const char *) #define DECLARE_xxx_UNISTRING(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlUnicodeString) - -#define DECLARE_xxx_BINARY(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlBinary) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlUnicodeString, const wchar_t *) #define DECLARE_xxx_DATE(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlDate) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlDate, std::int64_t) #define DECLARE_xxx_FLOAT(x,DllApi) \ - DECLARE_xxx_BASE(x, DllApi, libebml::EbmlFloat) + DECLARE_xxx_BASE_NODEFAULT(x, DllApi, libebml::EbmlFloat, double) + +#define DECLARE_xxx_UINTEGER_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlUInteger, std::uint64_t) + +#define DECLARE_xxx_SINTEGER_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlSInteger, std::int64_t) + +#define DECLARE_xxx_STRING_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlString, const char *) + +#define DECLARE_xxx_UNISTRING_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlUnicodeString, const wchar_t *) + +#define DECLARE_xxx_DATE_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlDate, std::int64_t) + +#define DECLARE_xxx_FLOAT_DEF(x,DllApi) \ + DECLARE_xxx_BASE_DEFAULT(x, DllApi, libebml::EbmlFloat, double) #define DECLARE_EBML_MASTER(x) DECLARE_xxx_MASTER( x,EBML_DLL_API) -#define DECLARE_EBML_UINTEGER(x) DECLARE_xxx_UINTEGER(x,EBML_DLL_API) -#define DECLARE_EBML_STRING(x) DECLARE_xxx_STRING( x,EBML_DLL_API) +#define DECLARE_EBML_UINTEGER_DEF(x) DECLARE_xxx_UINTEGER_DEF(x,EBML_DLL_API) +#define DECLARE_EBML_STRING_DEF(x) DECLARE_xxx_STRING_DEF( x,EBML_DLL_API) #define DECLARE_EBML_BINARY(x) DECLARE_xxx_BINARY( x,EBML_DLL_API) #define EBML_CONCRETE_CLASS(Type) \ @@ -183,8 +235,6 @@ class DllApi x : public BaseClass { \ static libebml::EbmlElement & Create() {return *(new Type);} \ static constexpr const libebml::EbmlCallbacks & ClassInfo() {return ClassInfos;} \ static const libebml::EbmlId & ClassId() {return ClassInfos.ClassId();} \ - private: \ - static const libebml::EbmlCallbacks ClassInfos; \ #define EBML_INFO(ref) ref::ClassInfo() #define EBML_ID(ref) ref::ClassId() @@ -227,12 +277,15 @@ class EBML_DLL_API EbmlCallbacks { assert(Creator!=nullptr); } + virtual ~EbmlCallbacks() = default; + inline const EbmlId & ClassId() const { return GlobalId; } inline constexpr const EbmlSemanticContext & GetContext() const { return Context; } inline const char * GetName() const { return DebugName; } inline EbmlElement & NewElement() const { return Create(); } /// is infinite/unknown size allowed inline bool CanHaveInfiniteSize() const { return CanInfinite; } + virtual bool HasDefault() const { return false; } private: EbmlElement & (* const Create)(); @@ -242,6 +295,46 @@ class EBML_DLL_API EbmlCallbacks { const EbmlSemanticContext & Context; }; +template +class EBML_DLL_API EbmlCallbacksDefault : public EbmlCallbacks { + public: + constexpr EbmlCallbacksDefault(EbmlElement & (*Creator)(), const EbmlId & aGlobalId, const char * aDebugName, const EbmlSemanticContext & aContext) + :EbmlCallbacks(Creator, aGlobalId, false, aDebugName, aContext) + { + } + + virtual ~EbmlCallbacksDefault() = default; +}; + +template +class EBML_DLL_API EbmlCallbacksWithDefault : public EbmlCallbacksDefault { + public: + constexpr EbmlCallbacksWithDefault(EbmlElement & (*Creator)(), const EbmlId & aGlobalId, const T &def, const char * aDebugName, const EbmlSemanticContext & aContext) + :EbmlCallbacksDefault(Creator, aGlobalId, aDebugName, aContext) + ,defaultValue(def) + { + } + + virtual ~EbmlCallbacksWithDefault() = default; + + inline const T & DefaultValue() const { return defaultValue; } + bool HasDefault() const override { return true; } + + private: + const T defaultValue; +}; + +template +class EBML_DLL_API EbmlCallbacksWithoutDefault : public EbmlCallbacksDefault { + public: + constexpr EbmlCallbacksWithoutDefault(EbmlElement & (*Creator)(), const EbmlId & aGlobalId, const char * aDebugName, const EbmlSemanticContext & aContext) + :EbmlCallbacksDefault(Creator, aGlobalId, aDebugName, aContext) + { + } + + virtual ~EbmlCallbacksWithoutDefault() = default; +}; + /*! \brief contains the semantic informations for a given level and all sublevels \todo move the ID in the element class @@ -325,7 +418,7 @@ class EBML_DLL_API EbmlElement { virtual ~EbmlElement() = default; EbmlElement& operator=(const EbmlElement&) = delete; - const EbmlCallbacks & ElementSpec() const { return ClassInfo; } + virtual const EbmlCallbacks & ElementSpec() const { return ClassInfo; } /// Set the minimum length that will be used to write the element size (-1 = optimal) void SetSizeLength(int NewSizeLength) {SizeLength = NewSizeLength;} @@ -412,7 +505,6 @@ class EBML_DLL_API EbmlElement { */ std::uint64_t VoidMe(IOCallback & output, ShouldWrite writeFilter = WriteSkipDefault) const; - bool DefaultISset() const {return DefaultIsSet;} virtual bool IsDefaultValue() const = 0; bool IsFiniteSize() const {return bSizeIsFinite;} @@ -451,7 +543,6 @@ class EBML_DLL_API EbmlElement { inline std::uint64_t GetDefaultSize() const {return DefaultSize;} inline void SetSize_(std::uint64_t aSize) {Size = aSize;} inline void SetValueIsSet(bool Set = true) {bValueIsSet = Set;} - inline void SetDefaultIsSet(bool Set = true) {DefaultIsSet = Set;} inline std::uint64_t GetSizePosition() const {return SizePosition;} protected: @@ -465,7 +556,29 @@ class EBML_DLL_API EbmlElement { std::uint64_t ElementPosition{0}; std::uint64_t SizePosition{0}; bool bValueIsSet; - bool DefaultIsSet{false}; +}; + +/*! + * \class EbmlElementDefault + * \brief EbmlElement class that may contain default values + */ +template +class EBML_DLL_API EbmlElementDefault : public EbmlElement { + public: + explicit EbmlElementDefault(const libebml::EbmlCallbacksDefault &classInfo, std::uint64_t aDefaultSize) + :EbmlElement(classInfo, aDefaultSize, false) + {} + + bool IsDefaultValue() const final { + if (!ElementSpec().HasDefault()) + return false; + if (!ValueIsSet()) + return true; + const auto & spec = static_cast &>(ElementSpec()); + return *this == spec.DefaultValue(); + } + + virtual bool operator==(const T &) const = 0; }; } // namespace libebml diff --git a/ebml/EbmlFloat.h b/ebml/EbmlFloat.h index ddd5303f..457de1a8 100644 --- a/ebml/EbmlFloat.h +++ b/ebml/EbmlFloat.h @@ -17,15 +17,14 @@ namespace libebml { \class EbmlFloat \brief Handle all operations on a float EBML element */ -class EBML_DLL_API EbmlFloat : public EbmlElement { +class EBML_DLL_API EbmlFloat : public EbmlElementDefault { public: enum Precision { FLOAT_32 ,FLOAT_64 }; - EbmlFloat(const EbmlCallbacks &, Precision prec = FLOAT_32); - EbmlFloat(const EbmlCallbacks &, double DefaultValue, Precision prec = FLOAT_32); + EbmlFloat(const EbmlCallbacksDefault &, Precision prec = FLOAT_32); bool ValidateSize() const override { @@ -54,17 +53,12 @@ class EBML_DLL_API EbmlFloat : public EbmlElement { EbmlFloat &SetValue(double NewValue); double GetValue() const; - void SetDefaultValue(double); - - double DefaultVal() const; - - bool IsDefaultValue() const override { - return (DefaultISset() && Value == DefaultValue); + bool operator==(const double & val) const override { + return val == Value; } private: double Value; /// The actual value of the element - double DefaultValue; }; } // namespace libebml diff --git a/ebml/EbmlSInteger.h b/ebml/EbmlSInteger.h index 3878accd..1e8b5537 100644 --- a/ebml/EbmlSInteger.h +++ b/ebml/EbmlSInteger.h @@ -23,10 +23,9 @@ const int DEFAULT_INT_SIZE = 1; ///< optimal size stored \class EbmlSInteger \brief Handle all operations on a signed integer EBML element */ -class EBML_DLL_API EbmlSInteger : public EbmlElement { +class EBML_DLL_API EbmlSInteger : public EbmlElementDefault { public: - EbmlSInteger(const EbmlCallbacks &); - explicit EbmlSInteger(const EbmlCallbacks &, std::int64_t DefaultValue); + EbmlSInteger(const EbmlCallbacksDefault &); /*! Set the default size of the integer (usually 1,2,4 or 8) @@ -49,17 +48,12 @@ class EBML_DLL_API EbmlSInteger : public EbmlElement { EbmlSInteger &SetValue(std::int64_t NewValue); std::int64_t GetValue() const; - void SetDefaultValue(std::int64_t aValue) {assert(!DefaultISset()); DefaultValue = aValue; SetDefaultIsSet();} - - std::int64_t DefaultVal() const {assert(DefaultISset()); return DefaultValue;} - - bool IsDefaultValue() const override { - return (DefaultISset() && Value == DefaultValue); + bool operator==(const std::int64_t & val) const override { + return val == Value; } private: std::int64_t Value; /// The actual value of the element - std::int64_t DefaultValue; }; } // namespace libebml diff --git a/ebml/EbmlString.h b/ebml/EbmlString.h index c315a905..a1510994 100644 --- a/ebml/EbmlString.h +++ b/ebml/EbmlString.h @@ -19,10 +19,9 @@ namespace libebml { \class EbmlString \brief Handle all operations on a printable string EBML element */ -class EBML_DLL_API EbmlString : public EbmlElement { +class EBML_DLL_API EbmlString : public EbmlElementDefault { public: - EbmlString(const EbmlCallbacks &); - explicit EbmlString(const EbmlCallbacks &, const std::string & aDefaultValue); + EbmlString(const EbmlCallbacksDefault &); bool ValidateSize() const override {return GetSize() < 0x7FFFFFFF;} // any size is possible filepos_t RenderData(IOCallback & output, bool bForceRender, ShouldWrite writeFilter = WriteSkipDefault) override; @@ -35,17 +34,12 @@ class EBML_DLL_API EbmlString : public EbmlElement { EbmlString &SetValue(std::string const &NewValue); std::string GetValue() const; - void SetDefaultValue(std::string &); - - const std::string & DefaultVal() const; - - bool IsDefaultValue() const override { - return (DefaultISset() && Value == DefaultValue); + bool operator==(const char * const & val) const override { + return val == Value; } private: std::string Value; /// The actual value of the element - std::string DefaultValue; }; } // namespace libebml diff --git a/ebml/EbmlSubHead.h b/ebml/EbmlSubHead.h index 47811c6f..de7e55dd 100644 --- a/ebml/EbmlSubHead.h +++ b/ebml/EbmlSubHead.h @@ -15,37 +15,37 @@ namespace libebml { -DECLARE_EBML_UINTEGER(EVersion) +DECLARE_EBML_UINTEGER_DEF(EVersion) public: EBML_CONCRETE_CLASS(EVersion) }; -DECLARE_EBML_UINTEGER(EReadVersion) +DECLARE_EBML_UINTEGER_DEF(EReadVersion) public: EBML_CONCRETE_CLASS(EReadVersion) }; -DECLARE_EBML_UINTEGER(EMaxIdLength) +DECLARE_EBML_UINTEGER_DEF(EMaxIdLength) public: EBML_CONCRETE_CLASS(EMaxIdLength) }; -DECLARE_EBML_UINTEGER(EMaxSizeLength) +DECLARE_EBML_UINTEGER_DEF(EMaxSizeLength) public: EBML_CONCRETE_CLASS(EMaxSizeLength) }; -DECLARE_EBML_STRING(EDocType) +DECLARE_EBML_STRING_DEF(EDocType) public: EBML_CONCRETE_CLASS(EDocType) }; -DECLARE_EBML_UINTEGER(EDocTypeVersion) +DECLARE_EBML_UINTEGER_DEF(EDocTypeVersion) public: EBML_CONCRETE_CLASS(EDocTypeVersion) }; -DECLARE_EBML_UINTEGER(EDocTypeReadVersion) +DECLARE_EBML_UINTEGER_DEF(EDocTypeReadVersion) public: EBML_CONCRETE_CLASS(EDocTypeReadVersion) }; diff --git a/ebml/EbmlUInteger.h b/ebml/EbmlUInteger.h index 9ee34e21..c3d717f8 100644 --- a/ebml/EbmlUInteger.h +++ b/ebml/EbmlUInteger.h @@ -21,10 +21,9 @@ const int DEFAULT_UINT_SIZE = 0; ///< optimal size stored \class EbmlUInteger \brief Handle all operations on an unsigned integer EBML element */ -class EBML_DLL_API EbmlUInteger : public EbmlElement { +class EBML_DLL_API EbmlUInteger : public EbmlElementDefault { public: - EbmlUInteger(const EbmlCallbacks &); - explicit EbmlUInteger(const EbmlCallbacks &, std::uint64_t DefaultValue); + EbmlUInteger(const EbmlCallbacksDefault &); /*! Set the default size of the integer (usually 1,2,4 or 8) @@ -47,17 +46,12 @@ class EBML_DLL_API EbmlUInteger : public EbmlElement { EbmlUInteger &SetValue(std::uint64_t NewValue); std::uint64_t GetValue() const; - void SetDefaultValue(std::uint64_t); - - std::uint64_t DefaultVal() const; - - bool IsDefaultValue() const override { - return (DefaultISset() && Value == DefaultValue); + bool operator==(const std::uint64_t & val) const override { + return val == Value; } private: std::uint64_t Value; /// The actual value of the element - std::uint64_t DefaultValue; }; } // namespace libebml diff --git a/ebml/EbmlUnicodeString.h b/ebml/EbmlUnicodeString.h index cda195b2..56d4cee4 100644 --- a/ebml/EbmlUnicodeString.h +++ b/ebml/EbmlUnicodeString.h @@ -65,10 +65,9 @@ class EBML_DLL_API UTFstring { \brief Handle all operations on a Unicode string EBML element \note internally treated as a string made of wide characters (ie UCS-2 or UCS-4 depending on the machine) */ -class EBML_DLL_API EbmlUnicodeString : public EbmlElement { +class EBML_DLL_API EbmlUnicodeString : public EbmlElementDefault { public: - EbmlUnicodeString(const EbmlCallbacks &); - explicit EbmlUnicodeString(const EbmlCallbacks &, const UTFstring & DefaultValue); + EbmlUnicodeString(const EbmlCallbacksDefault &); bool ValidateSize() const override {return true;} // any size is possible filepos_t RenderData(IOCallback & output, bool bForceRender, ShouldWrite writeFilter = WriteSkipDefault) override; @@ -83,17 +82,12 @@ class EBML_DLL_API EbmlUnicodeString : public EbmlElement { UTFstring GetValue() const; std::string GetValueUTF8() const; - void SetDefaultValue(UTFstring &); - - const UTFstring & DefaultVal() const; - - bool IsDefaultValue() const override { - return (DefaultISset() && Value == DefaultValue); + bool operator==(const wchar_t * const & val) const override { + return static_cast(val) == Value; } private: UTFstring Value; /// The actual value of the element - UTFstring DefaultValue; }; } // namespace libebml diff --git a/src/EbmlFloat.cpp b/src/EbmlFloat.cpp index 3310cc46..0acf950a 100644 --- a/src/EbmlFloat.cpp +++ b/src/EbmlFloat.cpp @@ -12,32 +12,12 @@ namespace libebml { -EbmlFloat::EbmlFloat(const EbmlCallbacks & classInfo, const EbmlFloat::Precision prec) - :EbmlElement(classInfo, 0, false) +EbmlFloat::EbmlFloat(const EbmlCallbacksDefault & classInfo, const EbmlFloat::Precision prec) + :EbmlElementDefault(classInfo, 0) { SetPrecision(prec); } -EbmlFloat::EbmlFloat(const EbmlCallbacks & classInfo, const double aDefaultValue, const EbmlFloat::Precision prec) - :EbmlElement(classInfo, 0, true), Value(aDefaultValue), DefaultValue(aDefaultValue) -{ - SetDefaultIsSet(); - SetPrecision(prec); -} - -void EbmlFloat::SetDefaultValue(double aValue) -{ - assert(!DefaultISset()); - DefaultValue = aValue; - SetDefaultIsSet(); -} - -double EbmlFloat::DefaultVal() const -{ - assert(DefaultISset()); - return DefaultValue; -} - EbmlFloat::operator float() const {return static_cast(Value);} EbmlFloat::operator double() const {return (Value);} diff --git a/src/EbmlMaster.cpp b/src/EbmlMaster.cpp index a0392c1b..77a1bbfe 100644 --- a/src/EbmlMaster.cpp +++ b/src/EbmlMaster.cpp @@ -170,13 +170,12 @@ bool EbmlMaster::CheckMandatory() const for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(MasterContext); EltIdx++) { if (EBML_CTX_IDX(MasterContext,EltIdx).IsMandatory()) { if (FindElt(EBML_CTX_IDX_INFO(MasterContext,EltIdx)) == nullptr) { - const auto testElement = &EBML_CTX_IDX(MasterContext,EltIdx).Create(); - const bool hasDefaultValue = testElement->DefaultISset(); - delete testElement; + const auto & semcb = EBML_CTX_IDX(MasterContext,EltIdx).GetCallbacks(); + const bool hasDefaultValue = semcb.HasDefault(); #if !defined(NDEBUG) // you are missing this Mandatory element -// const char * MissingName = EBML_INFO_NAME(EBML_CTX_IDX_INFO(MasterContext,EltIdx)); +// const char * MissingName = semcb.GetName(); #endif // !NDEBUG if (!hasDefaultValue) return false; diff --git a/src/EbmlSInteger.cpp b/src/EbmlSInteger.cpp index 4df10c00..11d5a494 100644 --- a/src/EbmlSInteger.cpp +++ b/src/EbmlSInteger.cpp @@ -31,16 +31,10 @@ ToSigned(std::uint64_t u) { namespace libebml { -EbmlSInteger::EbmlSInteger(const EbmlCallbacks & classInfo) - :EbmlElement(classInfo, DEFAULT_INT_SIZE, false) +EbmlSInteger::EbmlSInteger(const EbmlCallbacksDefault & classInfo) + :EbmlElementDefault(classInfo, DEFAULT_INT_SIZE) {} -EbmlSInteger::EbmlSInteger(const EbmlCallbacks & classInfo, std::int64_t aDefaultValue) - :EbmlElement(classInfo, DEFAULT_INT_SIZE, true), Value(aDefaultValue) -{ - SetDefaultIsSet(); -} - EbmlSInteger::operator std::int8_t() const {return static_cast(Value);} EbmlSInteger::operator std::int16_t() const {return static_cast(Value);} EbmlSInteger::operator std::int32_t() const {return static_cast(Value);} diff --git a/src/EbmlString.cpp b/src/EbmlString.cpp index f84ec627..f3a5d5df 100644 --- a/src/EbmlString.cpp +++ b/src/EbmlString.cpp @@ -12,44 +12,11 @@ namespace libebml { -EbmlString::EbmlString(const EbmlCallbacks & classInfo) - :EbmlElement(classInfo, 0, false) +EbmlString::EbmlString(const EbmlCallbacksDefault & classInfo) + :EbmlElementDefault(classInfo, 0) { - SetDefaultSize(0); -/* done automatically - SetSize_(Value.length()); - if (GetDefaultSize() > GetSize()) - SetSize_(GetDefaultSize());*/ } -EbmlString::EbmlString(const EbmlCallbacks & classInfo, const std::string & aDefaultValue) - :EbmlElement(classInfo, 0, true), Value(aDefaultValue), DefaultValue(aDefaultValue) -{ - SetDefaultSize(0); - SetDefaultIsSet(); -/* done automatically - SetSize_(Value.length()); - if (GetDefaultSize() > GetSize()) - SetSize_(GetDefaultSize());*/ -} - -/*! - \todo Cloning should be on the same exact type ! -*/ -void EbmlString::SetDefaultValue(std::string & aValue) -{ - assert(!DefaultISset()); - DefaultValue = aValue; - SetDefaultIsSet(); -} - -const std::string & EbmlString::DefaultVal() const -{ - assert(DefaultISset()); - return DefaultValue; -} - - /*! \todo handle exception on errors */ diff --git a/src/EbmlUInteger.cpp b/src/EbmlUInteger.cpp index e5e7f0ab..856a09b0 100644 --- a/src/EbmlUInteger.cpp +++ b/src/EbmlUInteger.cpp @@ -13,29 +13,10 @@ namespace libebml { -EbmlUInteger::EbmlUInteger(const EbmlCallbacks & classInfo) - :EbmlElement(classInfo, DEFAULT_UINT_SIZE, false) +EbmlUInteger::EbmlUInteger(const EbmlCallbacksDefault & classInfo) + :EbmlElementDefault(classInfo, DEFAULT_UINT_SIZE) {} -EbmlUInteger::EbmlUInteger(const EbmlCallbacks & classInfo, std::uint64_t aDefaultValue) - :EbmlElement(classInfo, DEFAULT_UINT_SIZE, true), Value(aDefaultValue), DefaultValue(aDefaultValue) -{ - SetDefaultIsSet(); -} - -void EbmlUInteger::SetDefaultValue(std::uint64_t aValue) -{ - assert(!DefaultISset()); - DefaultValue = aValue; - SetDefaultIsSet(); -} - -std::uint64_t EbmlUInteger::DefaultVal() const -{ - assert(DefaultISset()); - return DefaultValue; -} - EbmlUInteger::operator std::uint8_t() const {return static_cast(Value); } EbmlUInteger::operator std::uint16_t() const {return static_cast(Value);} EbmlUInteger::operator std::uint32_t() const {return static_cast(Value);} diff --git a/src/EbmlUnicodeString.cpp b/src/EbmlUnicodeString.cpp index 9d8809b1..aa24bd63 100644 --- a/src/EbmlUnicodeString.cpp +++ b/src/EbmlUnicodeString.cpp @@ -100,33 +100,11 @@ void UTFstring::UpdateFromUCS2(const std::wstring & WString) // ===================== EbmlUnicodeString class =================== -EbmlUnicodeString::EbmlUnicodeString(const EbmlCallbacks & classInfo) - :EbmlElement(classInfo, 0, false) +EbmlUnicodeString::EbmlUnicodeString(const EbmlCallbacksDefault & classInfo) + :EbmlElementDefault(classInfo, 0) { - SetDefaultSize(0); } -EbmlUnicodeString::EbmlUnicodeString(const EbmlCallbacks & classInfo, const UTFstring & aDefaultValue) - :EbmlElement(classInfo, 0, true), Value(aDefaultValue), DefaultValue(aDefaultValue) -{ - SetDefaultSize(0); - SetDefaultIsSet(); -} - -void EbmlUnicodeString::SetDefaultValue(UTFstring & aValue) -{ - assert(!DefaultISset()); - DefaultValue = aValue; - SetDefaultIsSet(); -} - -const UTFstring & EbmlUnicodeString::DefaultVal() const -{ - assert(DefaultISset()); - return DefaultValue; -} - - /*! \note limited to UCS-2 \todo handle exception on errors diff --git a/test/test_infinite.cxx b/test/test_infinite.cxx index ba7ffa6a..914fd29b 100644 --- a/test/test_infinite.cxx +++ b/test/test_infinite.cxx @@ -7,7 +7,7 @@ using namespace libebml; -DECLARE_xxx_UINTEGER(DummyChild,) +DECLARE_xxx_UINTEGER_DEF(DummyChild,) EBML_CONCRETE_CLASS(DummyChild) }; diff --git a/test/test_macros.cxx b/test/test_macros.cxx index a62ec705..b82d5cae 100644 --- a/test/test_macros.cxx +++ b/test/test_macros.cxx @@ -5,39 +5,59 @@ using namespace libebml; -DECLARE_EBML_STRING(StringWithDefault) +DECLARE_EBML_STRING_DEF(StringWithDefault) EBML_CONCRETE_CLASS(StringWithDefault) }; DEFINE_EBML_STRING_DEF(StringWithDefault, 0x4321, 2, EbmlHead, "StringWithDefault", "Default Value") -DECLARE_EBML_STRING(StringWithoutDefault) +DECLARE_xxx_STRING(StringWithoutDefault,) EBML_CONCRETE_CLASS(StringWithoutDefault) }; DEFINE_xxx_STRING(StringWithoutDefault, 0x4123, 2, EbmlHead, "StringWithoutDefault", GetEbmlGlobal_Context) -DECLARE_xxx_UNISTRING(UniStringWithDefault,) +DECLARE_xxx_UNISTRING_DEF(UniStringWithDefault,) EBML_CONCRETE_CLASS(UniStringWithDefault) }; -DEFINE_xxx_UNISTRING_DEF(UniStringWithDefault, 0x4321, 2, EbmlHead, "UniStringWithDefault", GetEbmlGlobal_Context, UTFstring{L"Default Value"}) +DEFINE_xxx_UNISTRING_DEF(UniStringWithDefault, 0x4321, 2, EbmlHead, "UniStringWithDefault", GetEbmlGlobal_Context, L"Default Value") DECLARE_xxx_UNISTRING(UniStringWithoutDefault,) EBML_CONCRETE_CLASS(UniStringWithoutDefault) }; DEFINE_xxx_UNISTRING(UniStringWithoutDefault, 0x4123, 2, EbmlHead, "UniStringWithoutDefault", GetEbmlGlobal_Context) -DECLARE_EBML_UINTEGER(UIntWithDefault) +DECLARE_EBML_UINTEGER_DEF(UIntWithDefault) EBML_CONCRETE_CLASS(UIntWithDefault) }; DEFINE_EBML_UINTEGER_DEF(UIntWithDefault, 0x654321, 3, EbmlHead, "UIntWithDefault", 42) -DECLARE_EBML_UINTEGER(UIntWithoutDefault) +DECLARE_xxx_UINTEGER(UIntWithoutDefault,) EBML_CONCRETE_CLASS(UIntWithoutDefault) }; DEFINE_xxx_UINTEGER(UIntWithoutDefault, 0x612345, 3, EbmlHead, "UIntWithoutDefault", GetEbmlGlobal_Context) int main(void) { + if (!StringWithDefault::ClassInfo().HasDefault()) + return 1; + if (StringWithoutDefault::ClassInfo().HasDefault()) + return 1; + if (!UniStringWithDefault::ClassInfo().HasDefault()) + return 1; + if (UniStringWithoutDefault::ClassInfo().HasDefault()) + return 1; + if (!UIntWithDefault::ClassInfo().HasDefault()) + return 1; + if (UIntWithoutDefault::ClassInfo().HasDefault()) + return 1; + + if (UIntWithDefault::GetElementSpec().DefaultValue() != 42) + return 1; + UIntWithDefault test0; + auto ClassSpecWithDefault = test0.ElementSpec(); + if (!ClassSpecWithDefault.HasDefault()) + return 1; + test0.SetValue(0); if (test0.IsDefaultValue()) return 1; @@ -47,7 +67,10 @@ int main(void) if (!test42.IsDefaultValue()) return 1; - if (!test42.DefaultISset()) + if (!test42.ElementSpec().HasDefault()) + return 1; + + if (test42.ElementSpec().DefaultValue() != 42) return 1; uint64_t val = static_cast(test42); @@ -64,11 +87,22 @@ int main(void) if (!test42.IsDefaultValue()) return 1; + UIntWithoutDefault testNoDefault0; + auto ClassSpecWithoutDefault = testNoDefault0.ElementSpec(); + if (ClassSpecWithoutDefault.HasDefault()) + return 1; +#ifdef TEST_COMPILATION_ERRORS + if (ClassSpecWithoutDefault.DefaultValue()) + return 1; +#else + (void)ClassSpecWithoutDefault; +#endif + StringWithDefault strdef; if (!strdef.IsDefaultValue()) return 1; - if (!strdef.DefaultISset()) + if (!strdef.GetElementSpec().HasDefault()) return 1; strdef.SetValue("Other"); @@ -83,7 +117,7 @@ int main(void) if (strnodef.IsDefaultValue()) return 1; - if (strnodef.DefaultISset()) + if (strnodef.GetElementSpec().HasDefault()) return 1; strnodef.SetValue("Other"); @@ -95,14 +129,14 @@ int main(void) return 1; EbmlElement & genericdef = test42; - if (!genericdef.DefaultISset()) + if (!genericdef.ElementSpec().HasDefault()) return 1; if (!genericdef.IsDefaultValue()) return 1; EbmlElement & genericnodef = strnodef; - if (genericnodef.DefaultISset()) + if (genericnodef.ElementSpec().HasDefault()) return 1; if (genericnodef.IsDefaultValue())