From: Gert van Valkenhoef Date: Tue, 9 Aug 2011 22:03:13 +0000 (+0100) Subject: Add type handling (disabled until StdTextModel.internalize is implemented) X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=8987976196a50e3e9639879990c7473610ff5369;p=odcread.git Add type handling (disabled until StdTextModel.internalize is implemented) --- diff --git a/Makefile b/Makefile index b3cdd99..1ad67d5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -HEADERS=oberon.h store.h reader.h domain.h alien.h +HEADERS=oberon.h store.h reader.h domain.h alien.h typeregister.h -odcread: odcread.o reader.o store.o util.o alien.o +odcread: odcread.o reader.o store.o util.o alien.o typeregister.o g++ -o $@ $^ %.o: %.cc $(HEADERS) diff --git a/odcread.cc b/odcread.cc index a6765e9..e049bb0 100644 --- a/odcread.cc +++ b/odcread.cc @@ -32,5 +32,7 @@ int main(int argc, char *argv[]) { odc::Store* s = odc::importDocument(in); std::cout << s->toString() << std::endl; std::cout << in.tellg() << " " << in.eof() << std::endl; + + std::cout << odc::ContainerModel(0).getTypePath().toString() << std::endl; return 0; } diff --git a/reader.cc b/reader.cc index 08bd498..3ccfb71 100644 --- a/reader.cc +++ b/reader.cc @@ -14,6 +14,12 @@ SHORTCHAR Reader::readSChar() { return out; } +BYTE Reader::readByte() { + BYTE out; + d_rider.read((char*)&out, 1); + return out; +} + INTEGER Reader::readInt() { char *buf = new char[4]; d_rider.read(buf, 4); @@ -32,6 +38,14 @@ void Reader::readSString(SHORTCHAR *out) { } } +INTEGER Reader::readVersion(INTEGER min, INTEGER max) { + INTEGER version = readByte(); + //if (version < min || version > max) { + // rd.TurnIntoAlien(alienVersion) + //} + return version; +} + Store* Reader::readStore() { SHORTCHAR kind = readSChar(); if (kind == Store::NIL) { @@ -118,15 +132,17 @@ Store *Reader::readStoreOrElemStore(bool isElem) { // ASSERT(downPos < rd.st.end, 105) // END; - void *t = 0; // FIXME type lookup here + const TypeProxyBase *t = TypeRegister::getInstance().get(type); // FIXME type lookup here + Store *x = 0; if (t != 0) { + x = t->newInstance(id); + x->internalize(*this); // x := NewStore(t); x.isElem := kind = elem } else { // rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type); // x := NIL } - Store *x = 0; if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE } else { // rd.SetPos(pos); @@ -234,6 +250,14 @@ void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos } } +std::string &Reader::fixTypeName(std::string &name) { + size_t pos = name.size() - 4; + if (pos > 0 && name.substr(pos, 4).compare("Desc") == 0) { + return name.replace(pos, 4, "^"); + } + return name; +} + TypePath Reader::readPath() { TypePath path; SHORTCHAR kind = readSChar(); @@ -241,7 +265,8 @@ TypePath Reader::readPath() { int i; for (i = 0; kind == Store::NEWEXT; ++i) { readSString(buf); - path.push_back(std::string(buf)); + std::string name(buf); + path.push_back(fixTypeName(name)); addPathComponent(i == 0, path[i]); // IF path[i] # elemTName THEN INC(i) END; kind = readSChar(); @@ -249,7 +274,8 @@ TypePath Reader::readPath() { if (kind == Store::NEWBASE) { readSString(buf); - path.push_back(std::string(buf)); + std::string name(buf); + path.push_back(fixTypeName(name)); addPathComponent(i == 0, path[i]); ++i; } else if (kind == Store::OLDTYPE) { diff --git a/reader.h b/reader.h index 764a276..e9b0234 100644 --- a/reader.h +++ b/reader.h @@ -135,11 +135,14 @@ private: * PROCEDURE (VAR rd: Reader) ReadChar (OUT x: CHAR) * NEW * Reads a character (0000X..0FFFFX). - * + */ + /** * PROCEDURE (VAR rd: Reader) ReadByte (OUT x: BYTE) * NEW * Reads a very short integer (-128..127). - * + */ + BYTE readByte(); + /** * PROCEDURE (VAR rd: Reader) ReadSInt (OUT x: SHORTINT) * NEW * Reads a short integer (-32768..32767). @@ -244,7 +247,9 @@ private: * rd.cause = alienVersion * rd.cancelled * rd.readAlien - * + */ + INTEGER readVersion(INTEGER min, INTEGER max); + /* * PROCEDURE (VAR rd: Reader) TurnIntoAlien (cause: INTEGER) * NEW * A store which is currently being internalized can turn itself into an alien, e.g., if it has read a component store which is an alien. @@ -260,6 +265,7 @@ private: Store *readNewLinkStore(); void internalizeAlien(Alien *alien, std::streampos down, std::streampos end); + std::string &fixTypeName(std::string &name); TypePath readPath(); /** * Add another component to the current path. If first==true, start a new path. diff --git a/store.cc b/store.cc index 82e20e6..fe5fa62 100644 --- a/store.cc +++ b/store.cc @@ -1,4 +1,8 @@ #include +#include + +#include + namespace odc { @@ -20,14 +24,208 @@ std::string TypePath::toString() const { return join(begin(), end(), std::string("->")); } +const std::string Store::TYPENAME("Stores.Store^"); +const TypeProxy Store::PROXY; +TypePath *Store::s_typePath = 0; + Store::Store(INTEGER id): d_id(id) {} INTEGER Store::getId() { return d_id; } -Domain* Store::getDomain() { +const std::string &Store::getType() { + return Store::TYPENAME; +} + +const std::string *Store::getSuper() { return 0; } +const std::string &Store::getTypeName() const { + return Store::getType(); +} + +const TypePath &Store::getTypePath() const { + if (s_typePath == 0) { + s_typePath = calcTypePath(getTypeName()); + } + return *s_typePath; +} + +TypePath *Store::calcTypePath(const std::string &name) const { + const std::string *super = TypeRegister::getInstance().get(name)->getSuper(); + TypePath *path; + if (super != 0) { + path = calcTypePath(*super); + } else { + path = new TypePath(); + } + path->push_back(name); + return path; +} + +void Store::internalize(Reader &reader) { + reader.readVersion(0, 0); +} + +std::string Store::toString() { + return getTypeName(); +} + +const std::string Elem::TYPENAME("Stores.Elem^"); +const TypeProxy Elem::PROXY; + +Elem::Elem(INTEGER id) : Store(id) {} + +const std::string &Elem::getType() { + return TYPENAME; +} + +const std::string *Elem::getSuper() { + return &Store::getType(); +} + +const std::string &Elem::getTypeName() const { + return getType(); +} + +void Elem::internalize(Reader &reader) { + Store::internalize(reader); // just being explicit +} + +const std::string Model::TYPENAME("Models.Model^"); +const TypeProxy Model::PROXY; + +Model::Model(INTEGER id) : Elem(id) {} + +const std::string &Model::getType() { + return TYPENAME; +} + +const std::string *Model::getSuper() { + return &Elem::getType(); +} + +const std::string &Model::getTypeName() const { + return getType(); +} + +void Model::internalize(Reader &reader) { + Model::internalize(reader); + reader.readVersion(0, 0); } + +const std::string ContainerModel::TYPENAME("Containers.Model^"); +const TypeProxy ContainerModel::PROXY; + +ContainerModel::ContainerModel(INTEGER id) : Model(id) {} + +const std::string &ContainerModel::getType() { + return TYPENAME; +} + +const std::string *ContainerModel::getSuper() { + return &Model::getType(); +} + +const std::string &ContainerModel::getTypeName() const { + return getType(); +} + +void ContainerModel::internalize(Reader &reader) { + Model::internalize(reader); + reader.readVersion(0, 0); +} + +const std::string TextModel::TYPENAME("TextModels.Model^"); +const TypeProxy TextModel::PROXY; + +TextModel::TextModel(INTEGER id) : ContainerModel(id) {} + +const std::string &TextModel::getType() { + return TYPENAME; +} + +const std::string *TextModel::getSuper() { + return &ContainerModel::getType(); +} + +const std::string &TextModel::getTypeName() const { + return getType(); +} + +void TextModel::internalize(Reader &reader) { + ContainerModel::internalize(reader); + reader.readVersion(0, 0); +} + +const std::string StdTextModel::TYPENAME("TextModels.StdModel^"); +//const TypeProxy StdTextModel::PROXY; + +StdTextModel::StdTextModel(INTEGER id) : TextModel(id) {} + +const std::string &StdTextModel::getType() { + return TYPENAME; +} + +const std::string *StdTextModel::getSuper() { + return &TextModel::getType(); +} + +const std::string &StdTextModel::getTypeName() const { + return getType(); +} + +void StdTextModel::internalize(Reader &reader) { + TextModel::internalize(reader); + reader.readVersion(0, 1); + +// PROCEDURE (t: StdModel) Internalize (VAR rd: Stores.Reader); +// VAR u, un: Run; sp: Piece; lp: LPiece; v: ViewRef; +// org, len: INTEGER; ano: BYTE; thisVersion: INTEGER; +// attr: Attributes; dict: AttrDict; +// BEGIN +// ASSERT(t.Domain() = NIL, 20); ASSERT(t.len = 0, 21); +// t.Internalize^(rd); IF rd.cancelled THEN RETURN END; +// rd.ReadVersion(minVersion, maxStdModelVersion, thisVersion); +// IF rd.cancelled THEN RETURN END; +// StdInit(t); +// dict.len := 0; u := t.trailer; +// rd.ReadInt(len); org := rd.Pos() + len; +// rd.ReadByte(ano); +// WHILE ano # -1 DO +// IF ano = dict.len THEN +// ReadAttr(rd, attr); Stores.Join(t, attr); +// IF dict.len < dictSize THEN dict.attr[dict.len] := attr; INC(dict.len) END +// ELSE +// attr := dict.attr[ano] +// END; +// rd.ReadInt(len); +// IF len > 0 THEN (* piece *) +// NEW(sp); sp.len := len; sp.attr := attr; +// sp.file := rd.rider.Base(); sp.org := org; un := sp; +// INC(org, len) +// ELSIF len < 0 THEN (* longchar piece *) +// len := -len; ASSERT(~ODD(len), 100); +// NEW(lp); lp.len := len DIV 2; lp.attr := attr; +// lp.file := rd.rider.Base(); lp.org := org; un := lp; +// INC(org, len) +// ELSE (* len = 0 => embedded view *) +// NEW(v); v.len := 1; v.attr := attr; +// rd.ReadInt(v.w); rd.ReadInt(v.h); Views.ReadView(rd, v.view); +// v.view.InitContext(NewContext(v, t)); +// un := v; INC(org) +// END; +// INC(t.len, un.len); u.next := un; un.prev := u; u := un; +// rd.ReadByte(ano) +// END; +// rd.SetPos(org); +// u.next := t.trailer; t.trailer.prev := u +// END Internalize; +// +} + + + +} // namespace odc diff --git a/store.h b/store.h index 039354d..54438ab 100644 --- a/store.h +++ b/store.h @@ -3,11 +3,13 @@ #include #include +#include #include #include namespace odc { + class Reader; // forward decl class TypePath : public std::vector { public: @@ -23,6 +25,10 @@ namespace odc { */ class Store { private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + static TypePath *s_typePath; + INTEGER d_id; public: @@ -39,6 +45,25 @@ namespace odc { INTEGER getId(); + /** + * Get the TypeName of this object. + * @see TypeRegister + */ + static const std::string &getType(); + /** + * Get the TypeName of the supertype of this object. Return 0 pointer if no supertype. + * @see TypeRegister + */ + static const std::string *getSuper(); + /** + * Get the TypeName for this object. + */ + virtual const std::string &getTypeName() const; + /** + * Get the TypePath to this object's type. + * @see TypePath + */ + const TypePath &getTypePath() const; /** * PROCEDURE (s: Store) Domain (): Domain @@ -46,7 +71,7 @@ namespace odc { * A store may be associated with a domain. This is done by the procedure InitDomain, which assigns a domain to the store. * Domain may be called by arbitrary clients. */ - Domain* getDomain(); + //Domain* getDomain(); /** * PROCEDURE (s: Store) CopyFrom- (source: Store) @@ -72,7 +97,7 @@ namespace odc { * source.Domain() = NIL guaranteed * source is not yet initialized guaranteed */ -// void internalize(Reader &reader) { + virtual void internalize(Reader &reader); // PROCEDURE (s: Store) Internalize- (VAR rd: Reader), NEW, EXTENSIBLE; // VAR thisVersion: INTEGER; // BEGIN @@ -105,9 +130,102 @@ namespace odc { */ // FIXME - virtual std::string toString() = 0; + virtual std::string toString(); + + private: + TypePath *calcTypePath(const std::string &name) const; }; + class Elem : public Store { + private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + + public: + Elem(INTEGER id); + + /** + * Get the TypeName of this object. + * @see TypeRegister + */ + static const std::string &getType(); + /** + * Get the TypeName of the supertype of this object. Return 0 pointer if no supertype. + * @see TypeRegister + */ + static const std::string *getSuper(); + /** + * Get the TypeName for this object. + */ + virtual const std::string &getTypeName() const; + + virtual void internalize(Reader &reader); + }; + + class Model : public Elem { + private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + + public: + Model(INTEGER id); + + /** + * Get the TypeName of this object. + * @see TypeRegister + */ + static const std::string &getType(); + /** + * Get the TypeName of the supertype of this object. Return 0 pointer if no supertype. + * @see TypeRegister + */ + static const std::string *getSuper(); + /** + * Get the TypeName for this object. + */ + virtual const std::string &getTypeName() const; + + virtual void internalize(Reader &reader); + }; + + class ContainerModel : public Model { + private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + + public: + ContainerModel(INTEGER id); + static const std::string &getType(); + static const std::string *getSuper(); + virtual const std::string &getTypeName() const; + virtual void internalize(Reader &reader); + }; + + class TextModel : public ContainerModel { + private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + + public: + TextModel(INTEGER id); + static const std::string &getType(); + static const std::string *getSuper(); + virtual const std::string &getTypeName() const; + virtual void internalize(Reader &reader); + }; + + class StdTextModel : public TextModel { + private: + static const std::string TYPENAME; + static const TypeProxy PROXY; + + public: + StdTextModel(INTEGER id); + static const std::string &getType(); + static const std::string *getSuper(); + virtual const std::string &getTypeName() const; + virtual void internalize(Reader &reader); + }; } #endif // _STORE_H_ diff --git a/typeregister.cc b/typeregister.cc new file mode 100644 index 0000000..b2ba566 --- /dev/null +++ b/typeregister.cc @@ -0,0 +1,30 @@ +#include + +#include + +namespace odc { + +TypeRegister::TypeRegister(): d_map() {} + +TypeRegister *TypeRegister::s_instance = 0; + +TypeRegister &TypeRegister::getInstance() { + if (s_instance == 0) { + s_instance = new TypeRegister(); + } + return *s_instance; +} + +void TypeRegister::add(const std::string &name, TypeProxyBase *proxy) { + d_map[name] = proxy; +} + +const TypeProxyBase *TypeRegister::get(const std::string &name) { + return d_map[name]; +} + +TypeProxyBase::TypeProxyBase(const std::string &name) { + TypeRegister::getInstance().add(name, this); +} + +} diff --git a/typeregister.h b/typeregister.h new file mode 100644 index 0000000..d647b5b --- /dev/null +++ b/typeregister.h @@ -0,0 +1,51 @@ +#ifndef _CLASSREGISTER_H_ +#define _CLASSREGISTER_H_ + +#include +#include +#include + +namespace odc { + class Store; + class TypeProxyBase; // forward declaration + + class TypeRegister { + static TypeRegister *s_instance; + + std::map d_map; + + TypeRegister(); + TypeRegister(const TypeRegister &other); // NI + TypeRegister &operator=(const TypeRegister &other); // NI + + public: + static TypeRegister &getInstance(); + + void add(const std::string &name, TypeProxyBase *proxy); + const TypeProxyBase *get(const std::string &name); + }; + + class TypeProxyBase { + public: + TypeProxyBase(const std::string &name); + virtual const std::string &getName() const = 0; + virtual const std::string *getSuper() const = 0; + virtual Store *newInstance(INTEGER id) const = 0; + }; + + template class TypeProxy : public TypeProxyBase { + public: + TypeProxy(): TypeProxyBase(T::getType()) {} + virtual const std::string &getName() const { + return T::getType(); + } + virtual const std::string *getSuper() const { + return T::getSuper(); + } + virtual Store *newInstance(INTEGER id) const { + return new T(id); + } + }; +} + +#endif // _CLASSREGISTER_H_