new macros to hide the internal variables of the context classes

git-svn-id: https://matroska.svn.sourceforge.net/svnroot/matroska/trunk/libebml@23 a6f86f6d-0131-4f8e-9e7b-e335508773d5
This commit is contained in:
Steve Lhomme 2010-03-17 10:26:39 +00:00
parent d9dd385f9f
commit 71367a12c9
3 changed files with 93 additions and 45 deletions

View File

@ -83,14 +83,14 @@ class EbmlElement;
#if defined(EBML_STRICT_API)
#define EBML_CONCRETE_CLASS(Type) \
public: \
virtual const EbmlSemanticContext &Context() const {return ClassInfos.Context;} \
virtual const char *DebugName() const {return ClassInfos.DebugName;} \
virtual operator const EbmlId &() const {return ClassInfos.GlobalId;} \
virtual const EbmlSemanticContext &Context() const {return ClassInfos.GetContext();} \
virtual const char *DebugName() const {return ClassInfos.GetName();} \
virtual operator const EbmlId &() const {return ClassInfos.ClassId();} \
virtual EbmlElement & CreateElement() const {return Create();} \
virtual EbmlElement * Clone() const { return new Type(*this); } \
static EbmlElement & Create() {return *(new Type);} \
static const EbmlCallbacks & ClassInfo() {return ClassInfos;} \
static const EbmlId & ClassId() {return ClassInfos.GlobalId;} \
static const EbmlId & ClassId() {return ClassInfos.ClassId();} \
private: \
static const EbmlCallbacks ClassInfos; \
@ -98,6 +98,18 @@ class EbmlElement;
#define EBML_ID(ref) ref::ClassId()
#define EBML_CONTEXT(e) (e)->Context()
#define EBML_NAME(e) (e)->DebugName()
#define EBML_INFO_ID(cb) (cb).ClassId()
#define EBML_INFO_NAME(cb) (cb).GetName()
#define EBML_INFO_CREATE(cb) (cb).NewElement()
#define EBML_INFO_CONTEXT(cb) (cb).GetContext()
#define EBML_SEM_UNIQUE(s) (s).IsUnique()
#define EBML_SEM_INFO(s) (const EbmlCallbacks &)(s)
#define EBML_CTX_SIZE(c) (c).GetSize()
#define EBML_CTX_MASTER(c) (c).GetMaster()
#define EBML_CTX_PARENT(c) (c).Parent()
#else
#define EBML_CONCRETE_CLASS(Type) \
public: \
@ -112,6 +124,18 @@ class EbmlElement;
#define EBML_ID(ref) ref::ClassInfos.GlobalId
#define EBML_CONTEXT(e) (e)->Generic().Context
#define EBML_NAME(e) (e)->Generic().DebugName
#define EBML_INFO_ID(cb) (cb).GlobalId
#define EBML_INFO_NAME(cb) (cb).DebugName
#define EBML_INFO_CREATE(cb) (cb).Create()
#define EBML_INFO_CONTEXT(cb) (cb).Context
#define EBML_SEM_UNIQUE(s) (s).Unique
#define EBML_SEM_INFO(s) (s).GetCallbacks
#define EBML_CTX_SIZE(c) (c).Size
#define EBML_CTX_MASTER(c) (c).MasterElt
#define EBML_CTX_PARENT(c) (c).UpTable
#endif
// functions for generic handling of data (should be static to all classes)
@ -125,8 +149,17 @@ class EBML_DLL_API EbmlCallbacks {
,GlobalId(aGlobalId)
,DebugName(aDebugName)
,Context(aContext)
{}
{
}
inline const EbmlId & ClassId() const { return GlobalId; }
inline const EbmlSemanticContext & GetContext() const { return Context; }
inline const char * GetName() const { return DebugName; }
inline EbmlElement & NewElement() const { return Create(); }
#if defined(EBML_STRICT_API)
private:
#endif
EbmlElement & (*Create)();
const EbmlId & GlobalId;
const char * DebugName;
@ -142,6 +175,14 @@ class EBML_DLL_API EbmlSemantic {
EbmlSemantic(bool aMandatory, bool aUnique, const EbmlCallbacks & aGetCallbacks)
:Mandatory(aMandatory), Unique(aUnique), GetCallbacks(aGetCallbacks) {}
inline bool IsMandatory() const { return Mandatory; }
inline bool IsUnique() const { return Unique; }
inline EbmlElement & Create() const { return EBML_INFO_CREATE(GetCallbacks); }
inline operator const EbmlCallbacks &() { return GetCallbacks; }
#if defined(EBML_STRICT_API)
private:
#endif
bool Mandatory; ///< wether the element is mandatory in the context or not
bool Unique;
const EbmlCallbacks & GetCallbacks;
@ -155,7 +196,7 @@ typedef const class EbmlSemanticContext & (*_GetSemanticContext)();
*/
class EBML_DLL_API EbmlSemanticContext {
public:
EbmlSemanticContext(unsigned int aSize,
EbmlSemanticContext(size_t aSize,
const EbmlSemantic *aMyTable,
const EbmlSemanticContext *aUpTable,
const _GetSemanticContext aGetGlobalContext,
@ -169,12 +210,19 @@ class EBML_DLL_API EbmlSemanticContext {
(MasterElt != aElt.MasterElt));
}
inline size_t GetSize() const { return Size; }
inline const EbmlCallbacks* GetMaster() const { return MasterElt; }
inline const EbmlSemanticContext* Parent() const { return UpTable; }
unsigned int Size; ///< number of elements in the table
const EbmlSemantic *MyTable; ///< First element in the table
const EbmlSemantic *MyTable; ///< First element in the table
const _GetSemanticContext GetGlobalContext; ///< global elements supported at this level
#if defined(EBML_STRICT_API)
private:
#endif
size_t Size; ///< number of elements in the table
const EbmlSemanticContext *UpTable; ///< Parent element
/// \todo replace with the global context directly
const _GetSemanticContext GetGlobalContext; ///< global elements supported at this level
const EbmlCallbacks *MasterElt;
};

View File

@ -259,7 +259,7 @@ EbmlElement * EbmlElement::FindNextID(IOCallback & DataStream, const EbmlCallbac
if (PossibleId[0] & BitMask) {
// this is the last octet of the ID
// check wether that's the one we're looking for
/* if (PossibleID == ClassInfos.GlobalId) {
/* if (PossibleID == EBML_INFO_ID(ClassInfos)) {
break;
} else {
/// \todo This element should be skipped (use a context ?)
@ -286,9 +286,9 @@ EbmlElement * EbmlElement::FindNextID(IOCallback & DataStream, const EbmlCallbac
EbmlElement *Result = NULL;
EbmlId PossibleID(PossibleId, PossibleID_Length);
if (PossibleID == ClassInfos.GlobalId) {
if (PossibleID == EBML_INFO_ID(ClassInfos)) {
// the element is the one expected
Result = &ClassInfos.Create();
Result = &EBML_INFO_CREATE(ClassInfos);
} else {
/// \todo find the element in the context
Result = new EbmlDummy(PossibleID);
@ -465,17 +465,17 @@ EbmlElement * EbmlElement::SkipData(EbmlStream & DataStream, const EbmlSemanticC
if (Result != NULL) {
unsigned int EltIndex;
// data known in this Master's context
for (EltIndex = 0; EltIndex < Context.Size; EltIndex++) {
if (EbmlId(*Result) == Context.MyTable[EltIndex].GetCallbacks.GlobalId) {
for (EltIndex = 0; EltIndex < EBML_CTX_SIZE(Context); EltIndex++) {
if (EbmlId(*Result) == EBML_INFO_ID(EBML_SEM_INFO(Context.MyTable[EltIndex]))) {
// skip the data with its own context
Result = Result->SkipData(DataStream, Context.MyTable[EltIndex].GetCallbacks.Context, NULL);
Result = Result->SkipData(DataStream, EBML_INFO_CONTEXT(EBML_SEM_INFO(Context.MyTable[EltIndex])), NULL);
break; // let's go to the next ID
}
}
if (EltIndex >= Context.Size) {
if (Context.UpTable != NULL) {
Result = SkipData(DataStream, *Context.UpTable, Result);
if (EltIndex >= EBML_CTX_SIZE(Context)) {
if (EBML_CTX_PARENT(Context) != NULL) {
Result = SkipData(DataStream, *EBML_CTX_PARENT(Context), Result);
} else {
assert(Context.GetGlobalContext != NULL);
if (Context != Context.GetGlobalContext()) {
@ -500,9 +500,9 @@ EbmlElement *EbmlElement::CreateElementUsingContext(const EbmlId & aID, const Eb
EbmlElement *Result = NULL;
// elements at the current level
for (ContextIndex = 0; ContextIndex < Context.Size; ContextIndex++) {
if (aID == Context.MyTable[ContextIndex].GetCallbacks.GlobalId) {
return &Context.MyTable[ContextIndex].GetCallbacks.Create();
for (ContextIndex = 0; ContextIndex < EBML_CTX_SIZE(Context); ContextIndex++) {
if (aID == EBML_INFO_ID(EBML_SEM_INFO(Context.MyTable[ContextIndex]))) {
return &Context.MyTable[ContextIndex].Create();
}
}
@ -524,16 +524,16 @@ EbmlElement *EbmlElement::CreateElementUsingContext(const EbmlId & aID, const Eb
}
// parent elements
if (Context.MasterElt != NULL && aID == Context.MasterElt->GlobalId) {
if (EBML_CTX_MASTER(Context) != NULL && aID == EBML_INFO_ID(*EBML_CTX_MASTER(Context))) {
LowLevel++; // already one level up (same as context)
return &Context.MasterElt->Create();
return &EBML_INFO_CREATE(*EBML_CTX_MASTER(Context));
}
// check wether it's not part of an upper context
if (Context.UpTable != NULL) {
if (EBML_CTX_PARENT(Context) != NULL) {
LowLevel++;
MaxLowerLevel++;
return CreateElementUsingContext(aID, *Context.UpTable, LowLevel, IsGlobalContext, bAllowDummy, MaxLowerLevel);
return CreateElementUsingContext(aID, *EBML_CTX_PARENT(Context), LowLevel, IsGlobalContext, bAllowDummy, MaxLowerLevel);
}
if (!IsGlobalContext && bAllowDummy) {

View File

@ -179,7 +179,7 @@ uint64 EbmlMaster::ReadData(IOCallback & input, ScopeMode ReadFully)
*/
bool EbmlMaster::ProcessMandatory()
{
if (Context.Size == 0)
if (EBML_CTX_SIZE(Context) == 0)
{
return true;
}
@ -187,10 +187,10 @@ bool EbmlMaster::ProcessMandatory()
assert(Context.MyTable != NULL);
unsigned int EltIdx;
for (EltIdx = 0; EltIdx < Context.Size; EltIdx++) {
if (Context.MyTable[EltIdx].Mandatory && Context.MyTable[EltIdx].Unique) {
assert(Context.MyTable[EltIdx].GetCallbacks.Create != NULL);
PushElement(Context.MyTable[EltIdx].GetCallbacks.Create());
for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) {
if (Context.MyTable[EltIdx].IsMandatory() && Context.MyTable[EltIdx].IsUnique()) {
// assert(Context.MyTable[EltIdx].Create() != NULL);
PushElement(Context.MyTable[EltIdx].Create());
}
}
return true;
@ -201,12 +201,12 @@ bool EbmlMaster::CheckMandatory() const
assert(Context.MyTable != NULL);
unsigned int EltIdx;
for (EltIdx = 0; EltIdx < Context.Size; EltIdx++) {
if (Context.MyTable[EltIdx].Mandatory) {
if (FindElt(Context.MyTable[EltIdx].GetCallbacks) == NULL) {
for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) {
if (Context.MyTable[EltIdx].IsMandatory()) {
if (FindElt(EBML_SEM_INFO(Context.MyTable[EltIdx])) == NULL) {
#if defined(_DEBUG) || defined(DEBUG)
// you are missing this Mandatory element
// const char * MissingName = Context.MyTable[EltIdx].GetCallbacks.DebugName;
// const char * MissingName = EBML_INFO_NAME(EBML_SEM_INFO(Context.MyTable[EltIdx]));
#endif // DEBUG
return false;
}
@ -243,14 +243,14 @@ std::vector<std::string> EbmlMaster::FindAllMissingElements()
}
}
unsigned int EltIdx;
for (EltIdx = 0; EltIdx < Context.Size; EltIdx++) {
if (Context.MyTable[EltIdx].Mandatory) {
if (FindElt(Context.MyTable[EltIdx].GetCallbacks) == NULL) {
for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) {
if (Context.MyTable[EltIdx].IsMandatory()) {
if (FindElt(EBML_SEM_INFO(Context.MyTable[EltIdx])) == NULL) {
std::string missingElement;
missingElement = "Missing element \"";
missingElement.append(Context.MyTable[EltIdx].GetCallbacks.DebugName);
missingElement.append(EBML_INFO_NAME(EBML_SEM_INFO(Context.MyTable[EltIdx])));
missingElement.append("\" in EbmlMaster \"");
missingElement.append(Context.MasterElt->DebugName);
missingElement.append(EBML_INFO_NAME(*EBML_CTX_MASTER(Context)));
missingElement.append("\"");
missingElements.push_back(missingElement);
}
@ -266,7 +266,7 @@ EbmlElement *EbmlMaster::FindElt(const EbmlCallbacks & Callbacks) const
for (Index = 0; Index < ElementList.size(); Index++) {
EbmlElement * tmp = ElementList[Index];
if (EbmlId(*tmp) == Callbacks.GlobalId)
if (EbmlId(*tmp) == EBML_INFO_ID(Callbacks))
return tmp;
}
@ -278,13 +278,13 @@ EbmlElement *EbmlMaster::FindFirstElt(const EbmlCallbacks & Callbacks, bool bCre
size_t Index;
for (Index = 0; Index < ElementList.size(); Index++) {
if (EbmlId(*(ElementList[Index])) == Callbacks.GlobalId)
if (EbmlId(*(ElementList[Index])) == EBML_INFO_ID(Callbacks))
return ElementList[Index];
}
if (bCreateIfNull && Callbacks.Create != NULL) {
if (bCreateIfNull) {
// add the element
EbmlElement *NewElt = &(Callbacks.Create());
EbmlElement *NewElt = &EBML_INFO_CREATE(Callbacks);
if (NewElt == NULL)
return NULL;
@ -303,7 +303,7 @@ EbmlElement *EbmlMaster::FindFirstElt(const EbmlCallbacks & Callbacks) const
size_t Index;
for (Index = 0; Index < ElementList.size(); Index++) {
if (EbmlId(*(ElementList[Index])) == Callbacks.GlobalId)
if (EbmlId(*(ElementList[Index])) == EBML_INFO_ID(Callbacks))
return ElementList[Index];
}
@ -375,7 +375,7 @@ EbmlElement *EbmlMaster::FindNextElt(const EbmlElement & PastElt) const
EbmlElement *EbmlMaster::AddNewElt(const EbmlCallbacks & Callbacks)
{
// add the element
EbmlElement *NewElt = &(Callbacks.Create());
EbmlElement *NewElt = &EBML_INFO_CREATE(Callbacks);
if (NewElt == NULL)
return NULL;