Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't export EbmlMaster context, use the class static member #269

Merged
merged 16 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ebml/EbmlContexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@

#include "EbmlTypes.h"
#include "EbmlElement.h"
#include "EbmlHead.h"

namespace libebml {

extern const EbmlSemanticContext EBML_DLL_API Context_EbmlHead;
#define Context_EbmlHead EBML_CLASS_CONTEXT(EbmlHead)

// global elements
extern const EbmlSemanticContext EBML_DLL_API & GetEbmlGlobal_Context();
extern const EbmlSemanticContextMaster EBML_DLL_API & GetEbmlGlobal_Context();

} // namespace libebml

Expand Down
103 changes: 81 additions & 22 deletions ebml/EbmlElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,31 @@ std::uint64_t EBML_DLL_API ReadCodedSizeValue(const binary * InBuffer, std::uint

class EbmlStream;
class EbmlSemanticContext;
class EbmlSemanticContextMaster;
class EbmlElement;

#define DEFINE_xxx_CONTEXT(x,global) \
const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, nullptr, global, nullptr); \
constexpr const libebml::EbmlSemanticContextMaster Context_##x = libebml::EbmlSemanticContextMaster(countof(ContextList_##x), ContextList_##x, nullptr, global, nullptr); \

#define DEFINE_xxx_MASTER(x,id,parent,infinite,name,versions,global) \
static constexpr const libebml::EbmlId Id_##x {id}; static_assert(libebml::EbmlId::IsValid(Id_##x .GetValue()), "invalid id for " name ); \
const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, &Context_##parent, global, &EBML_INFO(x)); \
constexpr const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, false, name, Context_##x, versions); \
DEFINE_xxx_MASTER_CONS(x,id,parent,infinite,name,versions,global) \
x::x() :libebml::EbmlMaster(x::ClassInfos) {}

// define a master class with a custom constructor
#define DEFINE_xxx_MASTER_CONS(x,id,parent,infinite,name,versions,global) \
static constexpr const libebml::EbmlId Id_##x {id}; static_assert(libebml::EbmlId::IsValid(Id_##x .GetValue()), "invalid id for " name ); \
const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, &Context_##parent, global, &EBML_INFO(x)); \
constexpr const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, false, name, Context_##x, versions);
constexpr const libebml::EbmlSemanticContextMaster x::SemanticContext = libebml::EbmlSemanticContextMaster(countof(ContextList_##x), ContextList_##x, &parent::SemanticContext, global, &EBML_INFO(x)); \
constexpr const libebml::EbmlCallbacksMaster x::ClassInfos(x::Create, Id_##x, infinite, name, x::SemanticContext, versions); \

// define a master class with no parent class
// define a master class with no parent class (can be used globally)
#define DEFINE_xxx_MASTER_ORPHAN(x,id,infinite,name,versions,global) \
static constexpr const libebml::EbmlId Id_##x {id}; static_assert(libebml::EbmlId::IsValid(Id_##x .GetValue()), "invalid id for " name ); \
const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(countof(ContextList_##x), ContextList_##x, nullptr, global, &EBML_INFO(x)); \
constexpr const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, infinite, false, name, Context_##x, versions); \
constexpr const libebml::EbmlSemanticContextMaster x::SemanticContext = libebml::EbmlSemanticContextMaster(countof(ContextList_##x), ContextList_##x, nullptr, global, &EBML_INFO(x)); \
constexpr const libebml::EbmlCallbacksMaster x::ClassInfos(x::Create, Id_##x, infinite, name, x::SemanticContext, versions); \

#define DEFINE_xxx_CLASS_CONS(x,id,parent,name,global) \
static constexpr const libebml::EbmlId Id_##x {id}; static_assert(libebml::EbmlId::IsValid(Id_##x .GetValue()), "invalid id for " name ); \
static constexpr const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(0, nullptr, &Context_##parent, global, &EBML_INFO(x));
static constexpr const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext( &parent::SemanticContext, global, &EBML_INFO(x));

#define DEFINE_xxx_CLASS_BASE(x,BaseClass,id,parent,name,versions,global) \
DEFINE_xxx_CLASS_CONS(x,id,parent,name,global) \
Expand Down Expand Up @@ -132,9 +131,10 @@ class EbmlElement;
#define DEFINE_xxx_DATE_DEF(x,id,parent,name,versions,global,defval) \
DEFINE_xxx_CLASS_BASE_DEFAULT(x,EbmlDate,id,parent,name,versions,global,defval, versions)

// define a class with no parent class (can be used globally)
#define DEFINE_xxx_CLASS_ORPHAN(x,id,name,versions,global) \
static constexpr const libebml::EbmlId Id_##x {id}; static_assert(libebml::EbmlId::IsValid(Id_##x .GetValue()), "invalid id for " name ); \
static constexpr const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(0, nullptr, nullptr, global, nullptr); \
static constexpr const libebml::EbmlSemanticContext Context_##x = libebml::EbmlSemanticContext(nullptr, global, nullptr); \
constexpr const libebml::EbmlCallbacks x::ClassInfos(x::Create, Id_##x, false, false, name, Context_##x, versions); \

#define DEFINE_EBML_CONTEXT(x) DEFINE_xxx_CONTEXT(x,GetEbmlGlobal_Context)
Expand Down Expand Up @@ -174,15 +174,27 @@ class DllApi x : public BaseClass { \
static constexpr const libebml::EbmlCallbacksDefault<StorageType> & GetElementSpec() { return ClassInfos; } \
x();

#define DECLARE_xxx_BASE_MASTER(x, DllApi, BaseClass) \
class DllApi x : public BaseClass { \
private: \
static const libebml::EbmlCallbacksMaster ClassInfos; \
public: \
const libebml::EbmlCallbacksMaster & ElementSpec() const override { return ClassInfos; } \
static constexpr const libebml::EbmlCallbacksMaster & GetElementSpec() { return ClassInfos; } \
x();

#define DECLARE_xxx_BASE(x, DllApi, BaseClass) \
class DllApi x : public BaseClass { \
private: \
static const libebml::EbmlCallbacks ClassInfos; \
public: \
static constexpr const libebml::EbmlCallbacks & GetElementSpec() { return ClassInfos; } \
x();

#define DECLARE_xxx_MASTER(x,DllApi) \
DECLARE_xxx_BASE(x, DllApi, libebml::EbmlMaster)
DECLARE_xxx_BASE_MASTER(x, DllApi, libebml::EbmlMaster) \
static const libebml::EbmlSemanticContextMaster SemanticContext; \
static const libebml::EbmlSemanticContextMaster & GetContextMaster() { return SemanticContext; }

#define DECLARE_xxx_BINARY(x,DllApi) \
DECLARE_xxx_BASE(x, DllApi, libebml::EbmlBinary)
Expand Down Expand Up @@ -240,10 +252,9 @@ class DllApi x : public BaseClass { \
static libebml::EbmlElement & Create() {return *(new Type);} \
static constexpr const libebml::EbmlCallbacks & ClassInfo() {return ClassInfos;} \

#define EBML_INFO(ref) ref::ClassInfo()
#define EBML_INFO(ref) ref::GetElementSpec()
#define EBML_ID(ref) EBML_INFO_ID(EBML_INFO(ref))
#define EBML_CLASS_SEMCONTEXT(ref) Context_##ref
#define EBML_CLASS_CONTEXT(ref) EBML_INFO_CONTEXT(EBML_INFO(ref))
#define EBML_CONTEXT(e) tEBML_CONTEXT(e)
#define EBML_NAME(e) tEBML_NAME(e)

Expand All @@ -263,6 +274,8 @@ class DllApi x : public BaseClass { \
#define EBML_CTX_IDX_INFO(c,i) EBML_SEM_SPECS(EBML_CTX_IDX(c,i))
#define EBML_CTX_IDX_ID(c,i) EBML_INFO_ID(EBML_CTX_IDX_INFO(c,i))

#define EBML_CLASS_CONTEXT(ref) (EBML_INFO(ref)).GetContextMaster()

#if !defined(INVALID_FILEPOS_T)
#define INVALID_FILEPOS_T 0
#endif
Expand Down Expand Up @@ -435,37 +448,42 @@ static inline EbmlElement & tEBML_SEM_CREATE(const EbmlSemantic & s)
return s.Create();
}

using _GetSemanticContext = const EbmlSemanticContext &(*)();
using _GetSemanticContext = const EbmlSemanticContextMaster &(*)();

/*!
Context of the element
\todo allow more than one parent ?
*/
class EBML_DLL_API EbmlSemanticContext {
public:
protected:
constexpr EbmlSemanticContext(std::size_t aSize,
const EbmlSemantic *aMyTable,
const EbmlSemanticContext *aUpTable,
const _GetSemanticContext aGetGlobalContext,
const EbmlCallbacks *aMasterElt)
: GetGlobalContext(aGetGlobalContext), MyTable(aMyTable), Size(aSize),
: GetGlobalContext(aGetGlobalContext), Size(aSize),
UpTable(aUpTable), MasterElt(aMasterElt) {}

public:
constexpr EbmlSemanticContext(
const EbmlSemanticContext *aUpTable,
const _GetSemanticContext aGetGlobalContext,
const EbmlCallbacks *aMasterElt)
: GetGlobalContext(aGetGlobalContext), Size(0),
UpTable(aUpTable), MasterElt(aMasterElt) {}

bool operator!=(const EbmlSemanticContext & aElt) const {
return ((Size != aElt.Size) || (MyTable != aElt.MyTable) ||
return ((Size != aElt.Size) ||
(UpTable != aElt.UpTable) || (GetGlobalContext != aElt.GetGlobalContext) ||
(MasterElt != aElt.MasterElt));
}

inline constexpr std::size_t GetSize() const { return Size; }
inline constexpr const EbmlCallbacks* GetMaster() const { return MasterElt; }
inline constexpr const EbmlSemanticContext* Parent() const { return UpTable; }
const EbmlSemantic & GetSemantic(std::size_t i) const;

const _GetSemanticContext GetGlobalContext; ///< global elements supported at this level

private:
const EbmlSemantic *MyTable; ///< First element in the table
const std::size_t Size; ///< number of elements in the table
const EbmlSemanticContext *UpTable; ///< Parent element
/// \todo replace with the global context directly
Expand All @@ -487,11 +505,52 @@ static inline constexpr const EbmlSemanticContext * tEBML_CTX_PARENT(const EbmlS
return c.Parent();
}

static inline const EbmlSemantic & tEBML_CTX_IDX(const EbmlSemanticContext & c, std::size_t i)
class EBML_DLL_API EbmlSemanticContextMaster : public EbmlSemanticContext {
public:
constexpr EbmlSemanticContextMaster(std::size_t aSize,
const EbmlSemantic *aMyTable,
const EbmlSemanticContext *aUpTable,
const _GetSemanticContext aGetGlobalContext,
const EbmlCallbacks *aMasterElt)
: EbmlSemanticContext(aSize, aUpTable, aGetGlobalContext, aMasterElt)
, MyTable(aMyTable)
{}

bool operator!=(const EbmlSemanticContext & aElt) const {
if (EbmlSemanticContext::operator!=(aElt))
return true;

if (MyTable != reinterpret_cast<const EbmlSemanticContextMaster &>(aElt).MyTable)
return true;

return false;
}

const EbmlSemantic & GetSemantic(std::size_t i) const;

private:
const EbmlSemantic *MyTable; ///< First element in the table
};

static inline const EbmlSemantic & tEBML_CTX_IDX(const EbmlSemanticContextMaster & c, std::size_t i)
{
return c.GetSemantic(i);
}

class EBML_DLL_API EbmlCallbacksMaster : public EbmlCallbacks {
public:
constexpr EbmlCallbacksMaster(EbmlElement & (*Creator)(), const EbmlId & aGlobalId, bool aCanInfinite,
const char * aDebugName, const EbmlSemanticContextMaster & aContext,
const EbmlDocVersion & aVersion)
:EbmlCallbacks(Creator, aGlobalId, aCanInfinite, false, aDebugName, aContext, aVersion)
{
}

inline constexpr const EbmlSemanticContextMaster & GetContextMaster() const {
return static_cast<const EbmlSemanticContextMaster &>(GetContext());
}
};

/*!
\class EbmlElement
\brief Hold basic informations about an EBML element (ID + length)
Expand Down
17 changes: 16 additions & 1 deletion ebml/EbmlMaster.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ constexpr const bool bChecksumUsedByDefault = false;
*/
class EBML_DLL_API EbmlMaster : public EbmlElement {
public:
explicit EbmlMaster(const EbmlCallbacks &, bool bSizeIsKnown = true);
explicit EbmlMaster(const EbmlCallbacksMaster &, bool bSizeIsKnown = true);
EbmlMaster(const EbmlMaster & ElementToClone);
EbmlMaster& operator=(const EbmlMaster&) = delete;
bool SizeIsValid(std::uint64_t /*size*/) const override {return true;}
Expand All @@ -37,6 +37,11 @@ class EBML_DLL_API EbmlMaster : public EbmlElement {
*/
~EbmlMaster() override;

constexpr const EbmlSemanticContextMaster & ContextMaster() const
{
return static_cast<const EbmlSemanticContextMaster &>(Context());
}

filepos_t RenderData(IOCallback & output, bool bForceRender, const ShouldWrite & writeFilter = WriteSkipDefault) override;
filepos_t ReadData(IOCallback & input, ScopeMode ReadFully) override;
filepos_t UpdateSize(const ShouldWrite & writeFilter = WriteSkipDefault, bool bForceRender = false) override;
Expand Down Expand Up @@ -146,6 +151,16 @@ class EBML_DLL_API EbmlMaster : public EbmlElement {
bool ProcessMandatory();
};

static inline constexpr const EbmlSemanticContextMaster & tEBML_CONTEXT(const EbmlMaster * e)
{
return e->ContextMaster();
}

static inline constexpr const EbmlSemanticContextMaster & tEBML_INFO_CONTEXT(const EbmlCallbacksMaster & cb)
{
return cb.GetContextMaster();
}

///< \todo add a restriction to only elements legal in the context
template <typename Type>
Type & GetChild(EbmlMaster & Master)
Expand Down
2 changes: 1 addition & 1 deletion src/EbmlContexts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ DEFINE_END_SEMANTIC(EbmlGlobal)

static DEFINE_xxx_CONTEXT(EbmlGlobal, GetEbmlGlobal_Context)

const EbmlSemanticContext & GetEbmlGlobal_Context()
const EbmlSemanticContextMaster & GetEbmlGlobal_Context()
{
return Context_EbmlGlobal;
}
Expand Down
47 changes: 21 additions & 26 deletions src/EbmlElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <sstream>

#include "ebml/EbmlElement.h"
#include "ebml/EbmlStream.h"
Expand Down Expand Up @@ -118,18 +117,6 @@ std::uint64_t ReadCodedSizeValue(const binary * InBuffer, std::uint32_t & Buffer
}


const EbmlSemantic & EbmlSemanticContext::GetSemantic(std::size_t i) const
{
assert(i<Size);
if (i<Size)
return MyTable[i];

std::stringstream ss;
ss << "EbmlSemanticContext::GetSemantic: programming error: index i outside of table size (" << i << " >= " << Size << ")";
throw std::logic_error(ss.str());
}


EbmlElement::EbmlElement(const EbmlCallbacks & classInfo, std::uint64_t aDefaultSize, bool bValueSet)
: ClassInfo(classInfo)
, DefaultSize(aDefaultSize)
Expand Down Expand Up @@ -386,13 +373,17 @@ EbmlElement * EbmlElement::SkipData(EbmlStream & DataStream, const EbmlSemanticC
}

if (Result != nullptr) {
unsigned int EltIndex;
unsigned int EltIndex = EBML_CTX_SIZE(Context);
// data known in this Master's context
for (EltIndex = 0; EltIndex < EBML_CTX_SIZE(Context); EltIndex++) {
if (EbmlId(*Result) == EBML_CTX_IDX_ID(Context,EltIndex)) {
// skip the data with its own context
Result = Result->SkipData(DataStream, EBML_SEM_CONTEXT(EBML_CTX_IDX(Context,EltIndex)), nullptr);
break; // let's go to the next ID
if (EBML_CTX_SIZE(Context))
{
const auto & MasterContext = static_cast<const EbmlSemanticContextMaster &>(Context);
for (EltIndex = 0; EltIndex < EBML_CTX_SIZE(MasterContext); EltIndex++) {
if (EbmlId(*Result) == EBML_CTX_IDX_ID(MasterContext,EltIndex)) {
// skip the data with its own context
Result = Result->SkipData(DataStream, EBML_SEM_CONTEXT(EBML_CTX_IDX(MasterContext,EltIndex)), nullptr);
break; // let's go to the next ID
}
}
}

Expand Down Expand Up @@ -424,13 +415,17 @@ EbmlElement *EbmlElement::CreateElementUsingContext(const EbmlId & aID, const Eb
EbmlElement *Result = nullptr;

// elements at the current level
for (unsigned int ContextIndex = 0; ContextIndex < EBML_CTX_SIZE(Context); ContextIndex++) {
if (aID == EBML_CTX_IDX_ID(Context,ContextIndex)) {
if (AsInfiniteSize && !EBML_CTX_IDX_INFO(Context,ContextIndex).CanHaveInfiniteSize())
return nullptr;
Result = &EBML_SEM_CREATE(EBML_CTX_IDX(Context,ContextIndex));
Result->SetSizeInfinite(AsInfiniteSize);
return Result;
if (EBML_CTX_SIZE(Context))
{
const auto & MasterContext = static_cast<const EbmlSemanticContextMaster &>(Context);
for (unsigned int ContextIndex = 0; ContextIndex < EBML_CTX_SIZE(MasterContext); ContextIndex++) {
if (aID == EBML_CTX_IDX_ID(MasterContext,ContextIndex)) {
if (AsInfiniteSize && !EBML_CTX_IDX_INFO(MasterContext,ContextIndex).CanHaveInfiniteSize())
return nullptr;
Result = &EBML_SEM_CREATE(EBML_CTX_IDX(MasterContext,ContextIndex));
Result->SetSizeInfinite(AsInfiniteSize);
return Result;
}
}
}

Expand Down
Loading