diff --git a/reader.cc b/reader.cc
index 54ca8c1a2ff99ffee3554ca75353775616ea6964..14b3b0c605ae4d52bfebff1c371f52d8139f2146 100644 (file)
--- a/reader.cc
+++ b/reader.cc
#include <reader.h>
+#include <alien.h>
+
+#include <string>
+#include <assert.h>
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;
return out;
}
+void Reader::readSChar(SHORTCHAR *buf, size_t len) {
+ d_rider.read(buf, len);
+}
+
+CHAR Reader::readLChar() {
+ CHAR buf;
+ char *bufPtr = (char *)&buf;
+ d_rider.read(bufPtr, 2);
+ if (isLittleEndian()) {
+ return buf;
+ } else {
+ CHAR out;
+ char *outPtr = (char *)&out;
+ outPtr[0] = bufPtr[1]; outPtr[1] = bufPtr[0];
+ return out;
+ }
+}
+
+void Reader::readLChar(CHAR *buf, size_t len) {
+ char *bufPtr = (char *)buf;
+ int len2 = len * 2;
+ d_rider.read(bufPtr, len2);
+ if (isBigEndian()) {
+ char tmp;
+ for (int i = 0; i < len2; i += 2) {
+ tmp = bufPtr[i];
+ bufPtr[i] = bufPtr[i + 1];
+ bufPtr[i + 1] = tmp;
+ }
+ }
+}
+
+BYTE Reader::readByte() {
+ BYTE out;
+ d_rider.read((char*)&out, 1);
+ return out;
+}
+
+SHORTINT Reader::readSInt() {
+ SHORTINT buf;
+ char *bufPtr = (char*)&buf;
+ d_rider.read(bufPtr, 2);
+ if (isLittleEndian()) {
+ return buf;
+ } else {
+ SHORTINT out;
+ char *outPtr = (char *)&out;
+ outPtr[0] = bufPtr[1]; outPtr[1] = bufPtr[0];
+ return out;
+ }
+}
+
INTEGER Reader::readInt() {
- char *buf = new char[4];
- d_rider.read(buf, 4);
+ INTEGER buf;
+ char *bufPtr = (char*)&buf;
+ d_rider.read(bufPtr, 4);
if (isLittleEndian()) {
- return *(INTEGER *)buf;
+ return buf;
} else {
- char *out = new char[4];
- out[0] = buf[3]; out[1] = buf[2]; out[2] = buf[1]; out[3] = buf[0];
- return *(INTEGER *)out;
+ INTEGER out;
+ char *outPtr = (char *)&out;
+ outPtr[0] = bufPtr[3]; outPtr[1] = bufPtr[2]; outPtr[2] = bufPtr[1]; outPtr[3] = bufPtr[0];
+ return out;
}
}
+void Reader::readSString(SHORTCHAR *out) {
+ while (*out = readSChar()) {
+ ++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) {
+ turnIntoAlien(ALIENVERSION);
+ }
+ return version;
+}
+
Store* Reader::readStore() {
SHORTCHAR kind = readSChar();
if (kind == Store::NIL) {
+ //std::cout << "NIL STORE" << std::endl;
return readNilStore();
} else if (kind == Store::LINK) {
+ //std::cout << "LINK STORE" << std::endl;
return readLinkStore();
} else if (kind == Store::NEWLINK) {
+ //std::cout << "NEWLINK STORE" << std::endl;
return readNewLinkStore();
} else if (kind == Store::STORE) {
+ //std::cout << "STORE STORE" << std::endl;
return readStoreOrElemStore(false);
} else if (kind == Store::ELEM) {
+ //std::cout << "ELEM STORE" << std::endl;
return readStoreOrElemStore(true);
} else {
+ //std::cout << std::hex << (unsigned int)kind << std::endl;
throw 20;
}
}
// len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
// kind: SHORTCHAR; path: TypePath; type: TypeName;
// save: ReaderState;
+
Store *Reader::readNilStore() {
+ INTEGER comment = readInt();
+ std::streamoff next = readInt();
+ d_state->end = d_rider.tellg();
+ if (next > 0 || (next == 0 && comment % 2 == 1)) {
+ d_state->next = d_state->end + next;
+ } else {
+ d_state->next = 0;
+ }
return 0;
}
// IF kind = nil THEN
// rd.st.end := rd.Pos();
// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
// x := NIL
+
Store *Reader::readLinkStore() {
- return 0;
+ throw "Reader::readLinkStore() not implemented";
}
// ELSIF kind = link THEN
// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
// rd.st.end := rd.Pos();
// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
// x := ThisStore(rd.eDict, id)
+
Store *Reader::readNewLinkStore() {
- return 0;
+ throw "Reader::readNewLinkStore() not implemented";
}
// ELSIF kind = newlink THEN
// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
// x := ThisStore(rd.sDict, id)
Store *Reader::readStoreOrElemStore(bool isElem) {
- INTEGER id = isElem ? d_nextElemId++ : d_nextStoreId++;
- CHAR** path = newTypePath();
- readPath(path);
- CHAR* type = path[0];
- std::cout << type << std::endl;
+ INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
+ TypePath path = readPath();
+ //std::cout << path.toString() << std::endl;
+ const std::string &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;
-// 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;
-// 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
+ 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;
+ 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);
+ } else {
+ 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 := 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::readPath(CHAR **path) {
+ x = 0;
+ }
+ }
+
+ if (x != 0) {
+ if (d_store == 0) {
+ d_store = x;
+ } else {
+ // join(d_store, x)
+ // I have no idea what this would actually mean if it happened.
+ throw "Joining of stores not implemented";
+ }
+ if (isElem) {
+ d_elemList.push_back(x);
+ } else {
+ d_storeList.push_back(x);
+ }
+ } else {
+ 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;
+ } else {
+ // join(d_store, alien)
+ // I have no idea what this would actually mean if it happened.
+ throw "Joining of stores not implemented";
+ }
+ if (isElem) {
+ d_elemList.push_back(alien);
+ } else {
+ d_storeList.push_back(alien);
+ }
+ ReaderState *save = d_state;
+ d_state = new ReaderState();
+ internalizeAlien(alien, downPos, save->end);
+ delete d_state;
+ d_state = save;
+ 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;
+}
+
+
+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)
+ 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
+ d_rider.seekg(next);
+ AlienComponent *comp = new AlienPart(readStore());
+ alien->getComponents().push_back(comp);
+ next = d_state->next > 0 ? d_state->next : end;
+ }
+ }
+}
+
+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();
- for (int i = 0; kind == Store::NEWEXT; ++i) {
- std::cout << "NEWEXT" << std::endl;
- //readXString(path[i]);
-// AddPathComp(rd); INC(rd.nextTypeId);
+ SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator).
+ int i;
+ for (i = 0; kind == Store::NEWEXT; ++i) {
+ readSString(buf);
+ std::string name(buf);
+ path.push_back(fixTypeName(name));
+ 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(buf);
+ std::string name(buf);
+ path.push_back(fixTypeName(name));
+ addPathComponent(i == 0, path[i]);
+ ++i;
} else if (kind == Store::OLDTYPE) {
- std::cout << "OLDTYPE" << std::endl;
+ int id = readInt();
+ if (i > 0) {
+ d_typeList[d_typeList.size() - 1]->baseId = id;
+ }
+ while (id != -1) {
+ path.push_back(d_typeList[id]->name);
+ id = d_typeList[id]->baseId;
+// IF path[i] # elemTName THEN INC(i) END
+ ++i;
+ }
} else {
throw 100;
}
+ return path;
+}
- // FIXME
- path[0][0] = 'H';
- path[0][1] = 'i';
- path[0][2] = 0;
-}
-// PROCEDURE ReadPath (VAR rd: Reader; VAR path: TypePath);
-// VAR h: TypeDict; id, extId: INTEGER; i: INTEGER; kind: SHORTCHAR;
-//
-// PROCEDURE AddPathComp (VAR rd: Reader);
-// BEGIN
-// IF h # NIL THEN AddBaseId(h, extId, rd.nextTypeId) END;
-// AddType(rd.tDict, rd.tHead, rd.nextTypeId, path[i]);
-// h := rd.tHead; extId := rd.nextTypeId
-// END AddPathComp;
-//
-// BEGIN
-// h := NIL; i := 0; rd.ReadSChar(kind);
-// WHILE kind = newExt DO
-// rd.ReadXString(path[i]);
-// AddPathComp(rd); INC(rd.nextTypeId);
-// IF path[i] # elemTName THEN INC(i) END;
-// rd.ReadSChar(kind)
-// END;
-// IF kind = newBase THEN
-// rd.ReadXString(path[i]);
-// AddPathComp(rd); INC(rd.nextTypeId); INC(i)
-// ELSE
-// ASSERT(kind = oldType, 100);
-// rd.ReadInt(id);
-// IF h # NIL THEN AddBaseId(h, extId, id) END;
-// REPEAT
-// GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id);
-// IF path[i] # elemTName THEN INC(i) END
-// UNTIL id = -1
-// END;
-// path[i] := ""
-// END ReadPath;
+void Reader::addPathComponent(bool first, const std::string &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