X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=reader.cc;h=a57e9bebefc50265d0b11cc48160d5c85e9cb3c8;hb=20254ed23eb75d8c3832b807ea97616fd684976e;hp=051ddf555539dbc7440b12694dbe4f2ad7f62383;hpb=d1698791effc588bc36cf85a28b5131e25ba5a49;p=odcread.git diff --git a/reader.cc b/reader.cc index 051ddf5..a57e9be 100644 --- a/reader.cc +++ b/reader.cc @@ -2,6 +2,7 @@ #include #include +#include namespace odc { @@ -14,15 +15,69 @@ SHORTCHAR Reader::readSChar() { 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; } } @@ -32,24 +87,44 @@ 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) { + turnIntoAlien(ALIENVERSION); + } + return version; +} + Store* Reader::readStore() { SHORTCHAR kind = readSChar(); if (kind == Store::NIL) { - std::cout << "NIL STORE" << std::endl; + //std::cout << "NIL STORE" << std::endl; return readNilStore(); } else if (kind == Store::LINK) { - std::cout << "LINK STORE" << std::endl; + //std::cout << "LINK STORE" << std::endl; return readLinkStore(); } else if (kind == Store::NEWLINK) { - std::cout << "NEWLINK STORE" << std::endl; + //std::cout << "NEWLINK STORE" << std::endl; return readNewLinkStore(); } else if (kind == Store::STORE) { - std::cout << "STORE STORE" << std::endl; + //std::cout << "STORE STORE" << std::endl; return readStoreOrElemStore(false); } else if (kind == Store::ELEM) { - std::cout << "ELEM STORE" << std::endl; + //std::cout << "ELEM STORE" << std::endl; return readStoreOrElemStore(true); } else { + //std::cout << std::hex << (unsigned int)kind << std::endl; throw 20; } } @@ -58,7 +133,16 @@ Store* Reader::readStore() { // 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 @@ -66,16 +150,18 @@ Store *Reader::readNilStore() { // 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); @@ -85,12 +171,9 @@ Store *Reader::readNewLinkStore() { Store *Reader::readStoreOrElemStore(bool isElem) { INTEGER id = isElem ? d_elemList.size() : d_storeList.size(); - SHORTCHAR** path = newTypePath(); - readPath(path); - for (int i = 0; path[i] != 0; ++i) { - std::cout << path[i] << std::endl; - } - SHORTCHAR* type = path[0]; + TypePath path = readPath(); + //std::cout << path.toString() << std::endl; + const std::string &type = path[0]; INTEGER comment = readInt(); std::streampos pos1 = d_rider.tellg(); std::streamoff next = readInt(); @@ -108,38 +191,64 @@ 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; - - void *t = 0; // FIXME type lookup here + 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 := NewStore(t); x.isElem := kind = elem + x = t->newInstance(id); } else { -// rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type); -// x := NIL + d_cause = TYPENOTFOUND; } - Store *x = 0; 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) + } + 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; } else { // join(d_store, alien) - std::cout << "Man, should have written join(.,.)" << std::endl; } if (isElem) { d_elemList.push_back(alien); @@ -147,88 +256,33 @@ 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) { 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); @@ -237,18 +291,32 @@ void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos } } -void Reader::readPath(SHORTCHAR **path) { +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(); + SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator). int i; for (i = 0; kind == Store::NEWEXT; ++i) { - readSString(path[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; kind = readSChar(); } if (kind == Store::NEWBASE) { - readSString(path[i]); + readSString(buf); + std::string name(buf); + path.push_back(fixTypeName(name)); addPathComponent(i == 0, path[i]); ++i; } else if (kind == Store::OLDTYPE) { @@ -257,7 +325,7 @@ void Reader::readPath(SHORTCHAR **path) { d_typeList[d_typeList.size() - 1]->baseId = id; } while (id != -1) { - path[i] = d_typeList[id]->name; + path.push_back(d_typeList[id]->name); id = d_typeList[id]->baseId; // IF path[i] # elemTName THEN INC(i) END ++i; @@ -265,10 +333,10 @@ void Reader::readPath(SHORTCHAR **path) { } else { throw 100; } - path[i] = 0; + return path; } -void Reader::addPathComponent(bool first, SHORTCHAR *typeName) { +void Reader::addPathComponent(bool first, const std::string &typeName) { int next = d_typeList.size(); int curr = next - 1; if (!first) {