From: Gert van Valkenhoef Date: Mon, 8 Aug 2011 20:37:02 +0000 (+0100) Subject: Can now read entire "empty" document as Alien X-Git-Url: https://deadsoftware.ru/gitweb?p=odcread.git;a=commitdiff_plain;h=121a58d72f3b5e537007072f93397f6e6661fb90 Can now read entire "empty" document as Alien --- diff --git a/Makefile b/Makefile index e03bf66..b3cdd99 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -HEADERS=oberon.h store.h reader.h domain.h +HEADERS=oberon.h store.h reader.h domain.h alien.h -odcread: odcread.o reader.o store.o util.o +odcread: odcread.o reader.o store.o util.o alien.o g++ -o $@ $^ %.o: %.cc $(HEADERS) diff --git a/alien.cc b/alien.cc new file mode 100644 index 0000000..7a225b7 --- /dev/null +++ b/alien.cc @@ -0,0 +1,31 @@ +#include + +namespace odc { + +AlienPiece::AlienPiece(const char * const _data, const size_t _len): data(_data), len(_len) {} + +std::string AlienPiece::toString() { + return std::string("AlienPiece"); +} + +AlienPart::AlienPart(Store * const _store): store(_store) {} + +std::string AlienPart::toString() { + return store->toString(); +} + +Alien::Alien(INTEGER id, SHORTCHAR **path): Store(id), d_path(path), d_comps() {} + +std::vector & Alien::getComponents() { + return d_comps; +} + +std::string Alien::toString() { + std::string sofar = std::string(d_path[0]) + "{ "; + for (int i = 0; i < d_comps.size(); ++i) { + sofar += d_comps[i]->toString() + " "; + } + return sofar + "}"; +} + +} diff --git a/alien.h b/alien.h new file mode 100644 index 0000000..40ef09a --- /dev/null +++ b/alien.h @@ -0,0 +1,59 @@ +#ifndef _ALIEN_H_ +#define _ALIEN_H_ + +#include +#include +#include +#include + +namespace odc { + +/** + * Part of an alien store + */ +struct AlienComponent { + virtual std::string toString() = 0; +}; + +/** + * Totally unstructured part of an alien store + */ +struct AlienPiece : public AlienComponent { + const char * const data; + const size_t len; + + AlienPiece(const char * const data, const size_t len); + + virtual std::string toString(); +}; + +/** + * Store component of an alien store + */ +struct AlienPart : public AlienComponent { + Store * const store; + + AlienPart(Store * const _store); + + virtual std::string toString(); +}; + +class Alien : public Store { + SHORTCHAR **d_path; + std::vector d_comps; + + public: + + Alien(INTEGER id, SHORTCHAR **path); + + std::vector & getComponents(); + + // cause-: INTEGER; (** # 0, the cause that turned this store into an alien **) + // file-: Files.File; (** base file holding alien pieces **) + // comps-: AlienComp (** the constituent components of this alien store **) + + virtual std::string toString(); +}; + +} +#endif // _ALIEN_H_ diff --git a/odcread.cc b/odcread.cc index 77a2694..32fcd6b 100644 --- a/odcread.cc +++ b/odcread.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -26,6 +27,7 @@ namespace odc { int main(int argc, char *argv[]) { std::ifstream in(argv[1], std::ios::in | std::ios::binary); odc::Store* s = odc::importDocument(in); - std::cout << s << std::endl; + std::cout << s->toString() << std::endl; + std::cout << in.tellg() << " " << in.eof() << std::endl; return 0; } diff --git a/reader.cc b/reader.cc index 54ca8c1..46a0b81 100644 --- a/reader.cc +++ b/reader.cc @@ -1,8 +1,12 @@ #include +#include + +#include namespace odc { -Reader::Reader(std::istream &rider): d_rider(rider), d_cancelled(false), d_readAlien(false) {} +Reader::Reader(std::istream &rider): d_rider(rider), d_cancelled(false), d_readAlien(false), d_typeList(), + d_state(new ReaderState()) {} SHORTCHAR Reader::readSChar() { SHORTCHAR out; @@ -22,6 +26,12 @@ INTEGER Reader::readInt() { } } +void Reader::readSString(SHORTCHAR *out) { + while (*out = readSChar()) { + ++out; + } +} + Store* Reader::readStore() { SHORTCHAR kind = readSChar(); if (kind == Store::NIL) { @@ -69,24 +79,31 @@ Store *Reader::readNewLinkStore() { // x := ThisStore(rd.sDict, id) Store *Reader::readStoreOrElemStore(bool isElem) { - INTEGER id = isElem ? d_nextElemId++ : d_nextStoreId++; - CHAR** path = newTypePath(); + INTEGER id = isElem ? d_elemList.size() : d_storeList.size(); + SHORTCHAR** path = newTypePath(); readPath(path); - CHAR* type = path[0]; - std::cout << type << std::endl; + for (int i = 0; path[i] != 0; ++i) { + std::cout << path[i] << std::endl; + } + SHORTCHAR* type = path[0]; INTEGER comment = readInt(); - return 0; -} -// ReadPath(rd, path); type := path[0]; -// nextTypeId := rd.nextTypeId; nextElemId := rd.nextElemId; nextStoreId := rd.nextStoreId; -// rd.ReadInt(comment); -// pos1 := rd.Pos(); -// rd.ReadInt(next); rd.ReadInt(down); rd.ReadInt(len); -// pos := rd.Pos(); -// IF next > 0 THEN rd.st.next := pos1 + next + 4 ELSE rd.st.next := 0 END; -// IF down > 0 THEN downPos := pos1 + down + 8 ELSE downPos := 0 END; -// rd.st.end := pos + len; -// rd.cause := 0; + std::streampos pos1 = d_rider.tellg(); + std::streamoff next = readInt(); + std::streamoff down = readInt(); + std::streamoff len = readInt(); + std::streampos pos = d_rider.tellg(); + if (next > 0) { + d_state->next = pos1 + next + (std::streamoff)4; + } else { + d_state->next = 0; + } + int downPos = 0; + if (down > 0) { + downPos = pos1 + down + (std::streamoff)8; + } + 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); @@ -98,6 +115,43 @@ Store *Reader::readStoreOrElemStore(bool isElem) { // ASSERT(downPos > pos1, 104); // ASSERT(downPos < rd.st.end, 105) // END; + + void *t = 0; // FIXME type lookup here + if (t != 0) { +// 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); +// ASSERT(rd.cause # 0, 107); + Alien *alien = new Alien(id, path); //, d_cause); //,file + if (d_store == 0) { + d_store = alien; + } else { + // join(d_store, alien) + std::cout << "Man, should have written join(.,.)" << std::endl; + } + if (isElem) { + d_elemList.push_back(alien); + } else { + d_storeList.push_back(alien); + } + ReaderState *save = d_state; +// rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId; + internalizeAlien(alien, downPos, save->end); + d_state = save; +// ASSERT(rd.Pos() = rd.st.end, 108); +// rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE + return alien; + } + + return x; +} // t := ThisType(type); // IF t # NIL THEN // x := NewStore(t); x.isElem := kind = elem @@ -157,28 +211,52 @@ Store *Reader::readStoreOrElemStore(bool isElem) { // rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE // END -void Reader::readPath(CHAR **path) { + +void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) { + std::streampos next = down != 0 ? down : end; + while (d_rider.tellg() < end) { + if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured) + std::cout << "Alien Piece" << std::endl; + size_t len = next - d_rider.tellg(); + char *buf = new char[len]; + d_rider.read(buf, len); + AlienComponent *comp = new AlienPiece(buf, len); + alien->getComponents().push_back(comp); + } else { // that means we've got a store + std::cout << "Alien Store" << std::endl; + d_rider.seekg(next); + AlienComponent *comp = new AlienPart(readStore()); + alien->getComponents().push_back(comp); + next = d_state->next > 0 ? d_state->next : end; + } + } +} + +void Reader::readPath(SHORTCHAR **path) { SHORTCHAR kind = readSChar(); - for (int i = 0; kind == Store::NEWEXT; ++i) { - std::cout << "NEWEXT" << std::endl; - //readXString(path[i]); -// AddPathComp(rd); INC(rd.nextTypeId); + int i; + for (i = 0; kind == Store::NEWEXT; ++i) { + readSString(path[i]); + addPathComponent(i == 0, path[i]); // IF path[i] # elemTName THEN INC(i) END; -// rd.ReadSChar(kind) + kind = readSChar(); } if (kind == Store::NEWBASE) { - std::cout << "NEWBASE" << std::endl; + readSString(path[i]); + addPathComponent(i == 0, path[i]); + ++i; } else if (kind == Store::OLDTYPE) { - std::cout << "OLDTYPE" << std::endl; + int id = readInt(); + d_typeList[d_typeList.size() - 1]->baseId = id; +// REPEAT +// GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id); +// IF path[i] # elemTName THEN INC(i) END +// UNTIL id = -1 } else { throw 100; } - - // FIXME - path[0][0] = 'H'; - path[0][1] = 'i'; - path[0][2] = 0; + path[i] = 0; } // PROCEDURE ReadPath (VAR rd: Reader; VAR path: TypePath); // VAR h: TypeDict; id, extId: INTEGER; i: INTEGER; kind: SHORTCHAR; @@ -213,4 +291,13 @@ void Reader::readPath(CHAR **path) { // path[i] := "" // END ReadPath; +void Reader::addPathComponent(bool first, SHORTCHAR *typeName) { + int next = d_typeList.size(); + int curr = next - 1; + if (!first) { + d_typeList[curr]->baseId = next; + } + d_typeList.push_back(new TypeEntry(typeName)); +} + } // namespace odc diff --git a/reader.h b/reader.h index cfd4fc5..208cf28 100644 --- a/reader.h +++ b/reader.h @@ -2,12 +2,22 @@ #define _READER_H_ #include +#include #include #include +#include namespace odc { +class TypeEntry { + public: + SHORTCHAR *name; + INTEGER baseId; + + TypeEntry(SHORTCHAR *typeName) : name(typeName), baseId(-1) {} +}; + /** * TYPE Reader * Reader for Component Pascal values like integers, reals, or sets. A reader contains a Files.Reader, to which it forwards most operations. @@ -34,8 +44,26 @@ private: */ bool d_readAlien; - INTEGER d_nextElemId; - INTEGER d_nextStoreId; + std::vector d_typeList; + + std::vector d_elemList; // FIXME: WTH, why are these different? + std::vector d_storeList; + + Store *d_store; + + struct ReaderState { + /** + * Position of the next store in the current level + */ + std::streampos next; + /** + * Position just after the last read store + */ + std::streampos end; + }; + ReaderState *d_state; + + INTEGER d_cause; public: /** @@ -102,7 +130,9 @@ private: * NEW * Same as ReadSChar, but has a CHAR-type parameter. * This procedure is provided to simplify migration from Release 1.2 to 1.3. - * + */ + CHAR readXChar(); + /** * PROCEDURE (VAR rd: Reader) ReadChar (OUT x: CHAR) * NEW * Reads a character (0000X..0FFFFX). @@ -148,19 +178,24 @@ private: * PROCEDURE (VAR rd: Reader) ReadSet (OUT x: SET) * NEW * Reads a set (32 elements). - * + */ + /** * PROCEDURE (VAR rd: Reader) ReadSString (OUT x: ARRAY OF SHORTCHAR) * NEW * Reads a 0X-terminated short string. * * Pre * invalid index LEN(x) > Length(string) - * + */ + void readSString(SHORTCHAR *out); + /** * PROCEDURE (VAR rd: Reader) ReadXString (OUT x: ARRAY OF CHAR) * NEW * Same as ReadSString, but has a string-type parameter. * This procedure is provided to simplify migration from Release 1.2 to 1.3. - * + */ + //void readXString(CHAR *out); + /** * PROCEDURE (VAR rd: Reader) ReadString (OUT x: ARRAY OF CHAR) * NEW * Reads a 0X-terminated string. @@ -224,23 +259,28 @@ private: Store *readNilStore(); Store *readLinkStore(); Store *readNewLinkStore(); + void internalizeAlien(Alien *alien, std::streampos down, std::streampos end); /* TypeName* = ARRAY 64 OF CHAR; TypePath* = ARRAY 16 OF TypeName; OpName* = ARRAY 32 OF CHAR; */ - inline CHAR *newTypeName() { - return new CHAR[64]; + inline SHORTCHAR *newTypeName() { + return new SHORTCHAR[64]; } - inline CHAR **newTypePath() { - CHAR **out = new CHAR*[16]; + inline SHORTCHAR **newTypePath() { + SHORTCHAR **out = new SHORTCHAR*[16]; for (int i = 0; i < 16; ++i) { out[i] = newTypeName(); } return out; } - void readPath(CHAR **path); + void readPath(SHORTCHAR **path); + /** + * Add another component to the current path. If first==true, start a new path. + */ + void addPathComponent(bool first, SHORTCHAR *typeName); }; } // namespace odc diff --git a/store.cc b/store.cc index 51729e1..d7db23b 100644 --- a/store.cc +++ b/store.cc @@ -2,6 +2,12 @@ namespace odc { +Store::Store(INTEGER id): d_id(id) {} + +INTEGER Store::getId() { + return d_id; +} + Domain* Store::getDomain() { return 0; } diff --git a/store.h b/store.h index 381cca7..be351b7 100644 --- a/store.h +++ b/store.h @@ -4,6 +4,8 @@ #include #include +#include + namespace odc { /** @@ -14,6 +16,9 @@ namespace odc { * Stores are used as base types for all objects that must be both extensible and persistent. */ class Store { + private: + INTEGER d_id; + public: static const SHORTCHAR NEWBASE = 0xF0; // (* new base type (level = 0), i.e. not yet in dict *) static const SHORTCHAR NEWEXT = 0xF1; // (* new extension type (level = 1), i.e. not yet in dict *) @@ -23,6 +28,12 @@ namespace odc { static const SHORTCHAR STORE = 0x82; // (* general store *) static const SHORTCHAR ELEM = 0x83; // (* elem store *) static const SHORTCHAR NEWLINK = 0x84; // (* link to another non-elem store in same file *) + + Store(INTEGER id); + + INTEGER getId(); + + /** * PROCEDURE (s: Store) Domain (): Domain * NEW @@ -87,6 +98,8 @@ namespace odc { * s1 = s guaranteed */ // FIXME + + virtual std::string toString() = 0; }; }