#include "pch.h"
#ifdef DREAMCAST
#define _UNALIGNED __unaligned
#else
#define _UNALIGNED
#endif
class MDLBinaryNameSpace :
public INameSpace,
public IBinaryReaderSite
{
private:
ZString m_strName;
TRef<Modeler> m_pmodeler;
TRef<ZFile> m_pfile;
BYTE* m_pdata;
TVector<TRef<INameSpace> > m_pnsImports;
TVector<ZString> m_strExportNames;
TVector<TRef<IObject> > m_pobjectImports;
TVector<TRef<IObject> > m_pobjects;
bool Error(const ZString& str)
{
ZError(str);
return false;
}
DWORD ReadDWORD()
{
ZAssert(m_pdata);
m_pdata += sizeof(DWORD);
return *(_UNALIGNED DWORD*)(m_pdata - sizeof(DWORD));
}
float ReadFloat()
{
ZAssert(m_pdata);
m_pdata += sizeof(float);
return *(_UNALIGNED float*)(m_pdata - sizeof(float));
}
ZString ReadString()
{
ZAssert(m_pdata);
ZString str((PCC)m_pdata);
int length = str.GetLength() + 1;
int paddedlength = (length + 3) & (~0x3);
m_pdata += paddedlength;
return str;
}
TRef<IObject> ReadList()
{
TRef<IObjectList> plist = new IObjectList();
DWORD count = ReadDWORD();
for (DWORD index = 0; index < count; index++) {
TRef<IObject> pobject = ReadObject();
plist->PushEnd(pobject);
}
return plist;
}
TRef<IObject> ReadApply(ObjectStack& stack)
{
TRef<IFunction> pfunction; CastTo(pfunction, stack.Pop());
return pfunction->Apply(stack);
}
TRef<IObject> ReadBinary(ObjectStack& stack)
{
TRef<IFunction> pfunction; CastTo(pfunction, stack.Pop());
return pfunction->Read(this, stack);
}
TRef<IObject> ReadPair(ObjectStack& stack)
{
TRef<IObject> pobject1 = stack.Pop();
TRef<IObject> pobject2 = stack.Pop();
return new IObjectPair(pobject1, pobject2);
}
TRef<IObject> ReadObject()
{
ObjectStack stack;
while (true) {
DWORD token = GetDWORD();
switch (token) {
case ObjectFloat:
stack.Push(new Number(ReadFloat()));
break;
case ObjectString:
stack.Push(new StringValue(ReadString()));
break;
case ObjectTrue:
stack.Push(new Boolean(true));
break;
case ObjectFalse:
stack.Push(new Boolean(false));
break;
case ObjectList:
stack.Push(ReadList());
break;
case ObjectApply:
stack.Push(ReadApply(stack));
break;
case ObjectBinary:
stack.Push(ReadBinary(stack));
break;
case ObjectReference:
stack.Push(m_pobjects[ReadDWORD()]);
break;
case ObjectImport:
stack.Push(m_pobjectImports[ReadDWORD()]);
break;
case ObjectPair:
stack.Push(ReadPair(stack));
break;
case ObjectEnd:
ZAssert(stack.GetCount() == 1);
return stack.Pop();
default:
ZError("ReadObject: Bad token");
break;
}
};
}
bool ReadFile()
{
DWORD index;
DWORD magic = ReadDWORD();
DWORD version = ReadDWORD();
DWORD countNameSpaces = ReadDWORD();
DWORD countImports = ReadDWORD();
DWORD countExports = ReadDWORD();
DWORD countDefinitions = ReadDWORD();
if (magic != MDLMagic) {
return Error("Invalid file type");
}
if (version != MDLVersion) {
return Error("Invalid version number");
}
m_pnsImports.SetCount(countNameSpaces);
for(index = 0; index < countNameSpaces; index++) {
ZString str = ReadString();
TRef<INameSpace> pns = m_pmodeler->GetNameSpace(str);
ZAssert(pns != NULL);
m_pnsImports.Set(index, pns);
}
m_pobjectImports.SetCount(countImports);
for(index = 0; index < countImports; index++) {
DWORD indexLibrary = ReadDWORD();
ZString str = ReadString();
ZAssert(indexLibrary < countNameSpaces);
TRef<IObject> pobject = m_pnsImports[indexLibrary]->FindMemberLocal(str);
ZAssert(pobject != NULL);
m_pobjectImports.Set(index, pobject);
}
m_pobjects.SetCount(countExports + countDefinitions);
m_strExportNames.SetCount(countExports);
for(index = 0; index < countExports; index++) {
m_strExportNames.Set(index, ReadString());
}
for(index = 0; index < countExports + countDefinitions; index++) {
DWORD indexObject = ReadDWORD();
m_pobjects.Set(indexObject, ReadObject());
}
#if defined(_DEBUG) && !defined(DREAMCAST)
for(index = 0; index < countExports; index++) {
Value* pvalue = dynamic_cast<Value*>((IObject*)m_pobjects[index]);
if (pvalue != NULL) {
pvalue->SetNameSpaceInfo(CreateNameSpaceInfo(this, m_strExportNames[index]));
}
}
#endif
return true;
}
public:
MDLBinaryNameSpace(const ZString& strName, Modeler* pmodeler, ZFile* pfile) :
m_pmodeler(pmodeler),
m_strName(strName)
{
m_pfile = pfile;
m_pdata = pfile->GetPointer(false, false);
ReadFile();
m_pdata = NULL;
pfile = NULL;
}
const ZString& GetName()
{
return m_strName;
}
void AddMember(const ZString& strName, IObject* pobject)
{
ZUnimplemented();
}
IObject* FindMemberAndNameSpace(const ZString& strName, INameSpace*& pns)
{
IObject* pobject = FindMemberLocal(strName);
if (pobject != NULL) {
pns = this;
return pobject;
}
int count = m_pnsImports.GetCount();
for(int index = 0; index < count; index++) {
pobject = m_pnsImports[index]->FindMemberAndNameSpace(strName, pns);
if (pobject != NULL) {
return pobject;
}
}
return NULL;
}
IObject* FindMember(const ZString& strName)
{
INameSpace* pns;
return FindMemberAndNameSpace(strName, pns);
}
IObject* FindMemberLocal(const ZString& strName)
{
int count = m_strExportNames.GetCount();
for(int index = 0; index < count; index++) {
if (m_strExportNames[index] == strName) {
return m_pobjects[index];
}
}
return NULL;
}
void AddType(const ZString& strName, MDLType* ptype)
{
ZUnimplemented();
}
MDLType* FindType(const ZString& strName)
{
ZUnimplemented();
return NULL;
}
MDLType* FindTypeLocal(const ZString& strName)
{
ZUnimplemented();
return NULL;
}
void WriteTypeHeader(ZFile* pfile)
{
ZUnimplemented();
}
void WriteToTextFile(int indent, ZFile* pfile)
{
ZUnimplemented();
}
void WriteToBinaryFile(ZFile* pfile)
{
ZUnimplemented();
}
ZString GetString()
{
return ReadString();
}
DWORD GetDWORD()
{
return ReadDWORD();
}
BYTE* GetPointer()
{
ZAssert(m_pdata);
return m_pdata;
}
void MovePointer(int count)
{
ZAssert(m_pdata);
m_pdata += count;
}
IObject* GetMemoryObject()
{
ZAssert(m_pfile);
return m_pfile;
}
IObject* GetObject()
{
return m_pobjects[ReadDWORD()];
}
};
TRef<INameSpace> CreateBinaryNameSpace(const ZString& strName, Modeler* pmodeler, ZFile* pfile)
{
return new MDLBinaryNameSpace(strName, pmodeler, pfile);
}