From 9b0fce2b8ea23e4eb23485421e1d80a774c912b3 Mon Sep 17 00:00:00 2001 From: Gert van Valkenhoef Date: Wed, 10 Aug 2011 21:12:41 +0100 Subject: [PATCH] Add some error handling, close to understanding StdTextModel --- Makefile | 2 +- odcread.cc | 4 +- reader.cc | 150 +++++++++++++++++++++++---------------------------- reader.h | 15 ++++-- store.cc | 112 ++++---------------------------------- store.h | 31 +---------- textmodel.cc | 138 +++++++++++++++++++++++++++++++++++++++++++++++ textmodel.h | 38 +++++++++++++ 8 files changed, 271 insertions(+), 219 deletions(-) create mode 100644 textmodel.cc create mode 100644 textmodel.h diff --git a/Makefile b/Makefile index 1ad67d5..c933edc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ HEADERS=oberon.h store.h reader.h domain.h alien.h typeregister.h -odcread: odcread.o reader.o store.o util.o alien.o typeregister.o +odcread: odcread.o reader.o store.o util.o alien.o typeregister.o textmodel.o g++ -o $@ $^ %.o: %.cc $(HEADERS) diff --git a/odcread.cc b/odcread.cc index e049bb0..c843713 100644 --- a/odcread.cc +++ b/odcread.cc @@ -33,6 +33,8 @@ int main(int argc, char *argv[]) { std::cout << s->toString() << std::endl; std::cout << in.tellg() << " " << in.eof() << std::endl; - std::cout << odc::ContainerModel(0).getTypePath().toString() << std::endl; + odc::TypePath path; + odc::ContainerModel(0).getTypePath(&path); + std::cout << path.toString() << std::endl; return 0; } diff --git a/reader.cc b/reader.cc index 3ccfb71..b027bd5 100644 --- a/reader.cc +++ b/reader.cc @@ -2,6 +2,7 @@ #include #include +#include namespace odc { @@ -38,11 +39,22 @@ void Reader::readSString(SHORTCHAR *out) { } } +void Reader::turnIntoAlien(int cause) { + assert(cause > 0); + d_cancelled = true; + d_cause = cause; + d_readAlien = true; +} + +bool Reader::isCancelled() { + return d_cancelled; +} + INTEGER Reader::readVersion(INTEGER min, INTEGER max) { INTEGER version = readByte(); - //if (version < min || version > max) { - // rd.TurnIntoAlien(alienVersion) - //} + if (version < min || version > max) { + turnIntoAlien(ALIENVERSION); + } return version; } @@ -64,6 +76,7 @@ Store* Reader::readStore() { std::cout << "ELEM STORE" << std::endl; return readStoreOrElemStore(true); } else { + std::cout << std::hex << (unsigned int)kind << std::endl; throw 20; } } @@ -119,34 +132,60 @@ Store *Reader::readStoreOrElemStore(bool isElem) { } d_state->end = pos + len; d_cause = 0; - // FIXME: insert whole bunch of checks here -// ASSERT(len >= 0, 101); -// IF next # 0 THEN -// ASSERT(rd.st.next > pos1, 102); -// IF down # 0 THEN -// ASSERT(downPos < rd.st.next, 103) -// END -// END; -// IF down # 0 THEN -// ASSERT(downPos > pos1, 104); -// ASSERT(downPos < rd.st.end, 105) -// END; + assert(len >= 0); + if (next != 0) { + assert(d_state->next > pos1); + if (down != 0) { + assert(downPos < d_state->next); + } + } + if (down > 0) { + assert(downPos > pos1); + assert(downPos < d_state->end); + } 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 + d_cause = TYPENOTFOUND; } if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE + if (true) { // samePath(x, path) + ReaderState *save = d_state; + d_state = new ReaderState(); + x->internalize(*this); + delete d_state; + d_state = save; + + if (d_cause != 0) { + x = 0; + } + assert(d_rider.tellg() == d_state->end); + assert(!d_rider.eof()); + } else { +// rd.cause := inconsistentType; AlienTypeReport(rd.cause, type); + x = 0; + } + } + + if (x != 0) { + if (d_store == 0) { + d_store = x; + } else { + // join(d_store, x) + std::cout << "Man, should have written join(.,.)" << std::endl; + } + if (isElem) { + d_elemList.push_back(x); + } else { + d_storeList.push_back(x); + } } else { -// rd.SetPos(pos); -// ASSERT(rd.cause # 0, 107); + d_rider.seekg(pos); // x->internalize() could have left us anywhere + assert(d_cause != 0); Alien *alien = new Alien(id, path); //, d_cause); //,file if (d_store == 0) { d_store = alien; @@ -160,74 +199,21 @@ Store *Reader::readStoreOrElemStore(bool isElem) { d_storeList.push_back(alien); } ReaderState *save = d_state; -// rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId; + d_state = new ReaderState(); internalizeAlien(alien, downPos, save->end); + delete d_state; d_state = save; -// ASSERT(rd.Pos() = rd.st.end, 108); -// rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE + assert(d_rider.tellg() == d_state->end); + + // we've just read the alien, so reset the state + d_cause = 0; + d_cancelled = false; + d_readAlien = true; return alien; } return x; } -// t := ThisType(type); -// IF t # NIL THEN -// x := NewStore(t); x.isElem := kind = elem -// ELSE -// rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type); -// x := NIL -// END; -// IF x # NIL THEN -// IF SamePath(t, path) THEN -// IF kind = elem THEN -// x.id := id; AddStore(rd.eDict, rd.eHead, x) -// ELSE -// x.id := id; AddStore(rd.sDict, rd.sHead, x) -// END; -// save := rd.st; rd.cause := 0; rd.cancelled := FALSE; -// x.Internalize(rd); -// rd.st := save; -// IF rd.cause # 0 THEN x := NIL -// ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN -// rd.cause := inconsistentVersion; AlienReport(rd.cause); -// x := NIL -// END -// ELSE -// rd.cause := inconsistentType; AlienTypeReport(rd.cause, type); -// x := NIL -// END -// END; -// -// IF x # NIL THEN -// IF rd.noDomain THEN -// rd.store := x; -// rd.noDomain := FALSE -// ELSE -// Join(rd.store, x) -// END -// ELSE (* x is an alien *) -// rd.SetPos(pos); -// ASSERT(rd.cause # 0, 107); -// NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base(); -// IF rd.noDomain THEN -// rd.store := a; -// rd.noDomain := FALSE -// ELSE -// Join(rd.store, a) -// END; -// IF kind = elem THEN -// a.id := id; AddStore(rd.eDict, rd.eHead, a) -// ELSE -// a.id := id; AddStore(rd.sDict, rd.sHead, a) -// END; -// save := rd.st; -// rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId; -// InternalizeAlien(rd, a.comps, downPos, pos, len); -// rd.st := save; -// x := a; -// ASSERT(rd.Pos() = rd.st.end, 108); -// rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE -// END void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) { diff --git a/reader.h b/reader.h index e9b0234..b4f475c 100644 --- a/reader.h +++ b/reader.h @@ -25,6 +25,9 @@ struct TypeEntry { */ class Reader { private: + static const unsigned int TYPENOTFOUND = 1; + static const unsigned int ALIENVERSION = 2; + /* * rider-: Files.Reader * The file rider which links a Reader to a file. @@ -33,7 +36,7 @@ private: /* * cancelled-: BOOLEAN valid during a Store.Internalize call - * Tells whether the currently executing Internalize has been called by ReadVersion or TurnIntoAlien. + * Tells whether the currently executing Internalize has been cancelled by ReadVersion or TurnIntoAlien. */ bool d_cancelled; @@ -43,6 +46,11 @@ private: */ bool d_readAlien; + /** + * Cause of current read being alien. + */ + unsigned int d_cause; + std::vector d_typeList; std::vector d_elemList; // FIXME: WTH, why are these different? @@ -62,8 +70,6 @@ private: }; ReaderState *d_state; - INTEGER d_cause; - public: /** * Construct a reader from the istream rider. @@ -257,6 +263,9 @@ private: * Pre * 20 cause > 0 */ + void turnIntoAlien(int cause); + + bool isCancelled(); private: Store *readStoreOrElemStore(bool isElem); diff --git a/store.cc b/store.cc index ba08425..c2fd5b4 100644 --- a/store.cc +++ b/store.cc @@ -26,7 +26,6 @@ std::string TypePath::toString() const { const std::string Store::TYPENAME("Stores.Store^"); const TypeProxy Store::PROXY; -TypePath *Store::s_typePath = 0; Store::Store(INTEGER id): d_id(id) {} @@ -46,23 +45,16 @@ 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; +void Store::getTypePath(TypePath *out) const { + return calcTypePath(out, getTypeName()); } -TypePath *Store::calcTypePath(const std::string &name) const { +void Store::calcTypePath(TypePath *path, 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(); + calcTypePath(path, *super); } path->push_back(name); - return path; } void Store::internalize(Reader &reader) { @@ -91,7 +83,9 @@ const std::string &Elem::getTypeName() const { } void Elem::internalize(Reader &reader) { - Store::internalize(reader); // just being explicit + Store::internalize(reader); + if (reader.isCancelled()) return; + reader.readVersion(0, 0); } const std::string Model::TYPENAME("Models.Model^"); @@ -113,6 +107,7 @@ const std::string &Model::getTypeName() const { void Model::internalize(Reader &reader) { Elem::internalize(reader); + if (reader.isCancelled()) return; reader.readVersion(0, 0); } @@ -135,97 +130,8 @@ const std::string &ContainerModel::getTypeName() const { void ContainerModel::internalize(Reader &reader) { Model::internalize(reader); + if (reader.isCancelled()) return; 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 54438ab..da84340 100644 --- a/store.h +++ b/store.h @@ -27,7 +27,6 @@ namespace odc { private: static const std::string TYPENAME; static const TypeProxy PROXY; - static TypePath *s_typePath; INTEGER d_id; @@ -63,7 +62,7 @@ namespace odc { * Get the TypePath to this object's type. * @see TypePath */ - const TypePath &getTypePath() const; + void getTypePath(TypePath *path) const; /** * PROCEDURE (s: Store) Domain (): Domain @@ -133,7 +132,7 @@ namespace odc { virtual std::string toString(); private: - TypePath *calcTypePath(const std::string &name) const; + void calcTypePath(TypePath * out, const std::string &name) const; }; class Elem : public Store { @@ -200,32 +199,6 @@ namespace odc { 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/textmodel.cc b/textmodel.cc new file mode 100644 index 0000000..bc76a32 --- /dev/null +++ b/textmodel.cc @@ -0,0 +1,138 @@ +#include +#include + +#include + +namespace odc { + +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); + if (reader.isCancelled()) return; + 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(); +} + +/* + * This is my current theory of how the StdTextModel storage format works: + * byte 0: version + * byte 1-5: len (length of piece descriptions) + * byte 6-5+len: piece descriptions + * byte 6+len-end: pieces (length of each defined in piece descriptions) + */ +void StdTextModel::internalize(Reader &reader) { + TextModel::internalize(reader); + if (reader.isCancelled()) return; + reader.readVersion(0, 1); + if (reader.isCancelled()) return; + + std::vector dict; + INTEGER len = reader.readInt(); + BYTE ano = reader.readByte(); + std::cout << "len " << len << " ano " << (int)ano << std::endl; + while (ano != -1) { + if (ano == dict.size()) { + Store *attr = reader.readStore(); // readAttributes(); Stores.Join(t, attr) + dict.push_back(attr); + } + INTEGER pieceLen = reader.readInt(); + if (pieceLen > 0) { // shortchar piece + std::cout << "Found SChar piece" << std::endl; +// NEW(sp); sp.len := len; sp.attr := attr; +// sp.file := rd.rider.Base(); sp.org := org; un := sp; +// INC(org, len) -- increment org by len ? + } else if (pieceLen < 0) { // longchar piece + std::cout << "Found LChar piece" << std::endl; +// 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) -- increment org by len ? + } else { // embedded view + reader.readInt(); reader.readInt(); + Store *view = reader.readStore(); // fixme: save somewhere +// 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) -- increment org by one?? WTH? + } + ano = reader.readByte(); + } +// rd.SetPos(org); +} +// 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/textmodel.h b/textmodel.h new file mode 100644 index 0000000..13a3d56 --- /dev/null +++ b/textmodel.h @@ -0,0 +1,38 @@ +#ifndef _TEXTMODEL_H_ +#define _TEXTMODEL_H_ + +#include +#include +#include + +namespace odc { + + 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); + }; + +} // namespace odc + +#endif // _TEXTMODEL_H_ -- 2.29.2