DEADSOFTWARE

b027bd57299f3347c75b7c87d98c8dbcddc73c37
[odcread.git] / reader.cc
1 #include <reader.h>
2 #include <alien.h>
4 #include <string>
5 #include <assert.h>
7 namespace odc {
9 Reader::Reader(std::istream &rider): d_rider(rider), d_cancelled(false), d_readAlien(false), d_typeList(),
10 d_state(new ReaderState()) {}
12 SHORTCHAR Reader::readSChar() {
13 SHORTCHAR out;
14 d_rider.read(&out, 1);
15 return out;
16 }
18 BYTE Reader::readByte() {
19 BYTE out;
20 d_rider.read((char*)&out, 1);
21 return out;
22 }
24 INTEGER Reader::readInt() {
25 char *buf = new char[4];
26 d_rider.read(buf, 4);
27 if (isLittleEndian()) {
28 return *(INTEGER *)buf;
29 } else {
30 char *out = new char[4];
31 out[0] = buf[3]; out[1] = buf[2]; out[2] = buf[1]; out[3] = buf[0];
32 return *(INTEGER *)out;
33 }
34 }
36 void Reader::readSString(SHORTCHAR *out) {
37 while (*out = readSChar()) {
38 ++out;
39 }
40 }
42 void Reader::turnIntoAlien(int cause) {
43 assert(cause > 0);
44 d_cancelled = true;
45 d_cause = cause;
46 d_readAlien = true;
47 }
49 bool Reader::isCancelled() {
50 return d_cancelled;
51 }
53 INTEGER Reader::readVersion(INTEGER min, INTEGER max) {
54 INTEGER version = readByte();
55 if (version < min || version > max) {
56 turnIntoAlien(ALIENVERSION);
57 }
58 return version;
59 }
61 Store* Reader::readStore() {
62 SHORTCHAR kind = readSChar();
63 if (kind == Store::NIL) {
64 std::cout << "NIL STORE" << std::endl;
65 return readNilStore();
66 } else if (kind == Store::LINK) {
67 std::cout << "LINK STORE" << std::endl;
68 return readLinkStore();
69 } else if (kind == Store::NEWLINK) {
70 std::cout << "NEWLINK STORE" << std::endl;
71 return readNewLinkStore();
72 } else if (kind == Store::STORE) {
73 std::cout << "STORE STORE" << std::endl;
74 return readStoreOrElemStore(false);
75 } else if (kind == Store::ELEM) {
76 std::cout << "ELEM STORE" << std::endl;
77 return readStoreOrElemStore(true);
78 } else {
79 std::cout << std::hex << (unsigned int)kind << std::endl;
80 throw 20;
81 }
82 }
83 // PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
84 // VAR a: Alien; t: Kernel.Type;
85 // len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
86 // kind: SHORTCHAR; path: TypePath; type: TypeName;
87 // save: ReaderState;
88 Store *Reader::readNilStore() {
89 return 0;
90 }
91 // IF kind = nil THEN
92 // rd.ReadInt(comment); rd.ReadInt(next);
93 // rd.st.end := rd.Pos();
94 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
95 // x := NIL
96 Store *Reader::readLinkStore() {
97 return 0;
98 }
99 // ELSIF kind = link THEN
100 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
101 // rd.st.end := rd.Pos();
102 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
103 // x := ThisStore(rd.eDict, id)
104 Store *Reader::readNewLinkStore() {
105 return 0;
107 // ELSIF kind = newlink THEN
108 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
109 // rd.st.end := rd.Pos();
110 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
111 // x := ThisStore(rd.sDict, id)
113 Store *Reader::readStoreOrElemStore(bool isElem) {
114 INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
115 TypePath path = readPath();
116 std::cout << path.toString() << std::endl;
117 const std::string &type = path[0];
118 INTEGER comment = readInt();
119 std::streampos pos1 = d_rider.tellg();
120 std::streamoff next = readInt();
121 std::streamoff down = readInt();
122 std::streamoff len = readInt();
123 std::streampos pos = d_rider.tellg();
124 if (next > 0) {
125 d_state->next = pos1 + next + (std::streamoff)4;
126 } else {
127 d_state->next = 0;
129 int downPos = 0;
130 if (down > 0) {
131 downPos = pos1 + down + (std::streamoff)8;
133 d_state->end = pos + len;
134 d_cause = 0;
135 assert(len >= 0);
136 if (next != 0) {
137 assert(d_state->next > pos1);
138 if (down != 0) {
139 assert(downPos < d_state->next);
142 if (down > 0) {
143 assert(downPos > pos1);
144 assert(downPos < d_state->end);
147 const TypeProxyBase *t = TypeRegister::getInstance().get(type); // FIXME type lookup here
148 Store *x = 0;
149 if (t != 0) {
150 x = t->newInstance(id);
151 } else {
152 d_cause = TYPENOTFOUND;
155 if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE
156 if (true) { // samePath(x, path)
157 ReaderState *save = d_state;
158 d_state = new ReaderState();
159 x->internalize(*this);
160 delete d_state;
161 d_state = save;
163 if (d_cause != 0) {
164 x = 0;
166 assert(d_rider.tellg() == d_state->end);
167 assert(!d_rider.eof());
168 } else {
169 // rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
170 x = 0;
174 if (x != 0) {
175 if (d_store == 0) {
176 d_store = x;
177 } else {
178 // join(d_store, x)
179 std::cout << "Man, should have written join(.,.)" << std::endl;
181 if (isElem) {
182 d_elemList.push_back(x);
183 } else {
184 d_storeList.push_back(x);
186 } else {
187 d_rider.seekg(pos); // x->internalize() could have left us anywhere
188 assert(d_cause != 0);
189 Alien *alien = new Alien(id, path); //, d_cause); //,file
190 if (d_store == 0) {
191 d_store = alien;
192 } else {
193 // join(d_store, alien)
194 std::cout << "Man, should have written join(.,.)" << std::endl;
196 if (isElem) {
197 d_elemList.push_back(alien);
198 } else {
199 d_storeList.push_back(alien);
201 ReaderState *save = d_state;
202 d_state = new ReaderState();
203 internalizeAlien(alien, downPos, save->end);
204 delete d_state;
205 d_state = save;
206 assert(d_rider.tellg() == d_state->end);
208 // we've just read the alien, so reset the state
209 d_cause = 0;
210 d_cancelled = false;
211 d_readAlien = true;
212 return alien;
215 return x;
219 void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) {
220 std::streampos next = down != 0 ? down : end;
221 while (d_rider.tellg() < end) {
222 if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured)
223 std::cout << "Alien Piece" << std::endl;
224 size_t len = next - d_rider.tellg();
225 char *buf = new char[len];
226 d_rider.read(buf, len);
227 AlienComponent *comp = new AlienPiece(buf, len);
228 alien->getComponents().push_back(comp);
229 } else { // that means we've got a store
230 std::cout << "Alien Store" << std::endl;
231 d_rider.seekg(next);
232 AlienComponent *comp = new AlienPart(readStore());
233 alien->getComponents().push_back(comp);
234 next = d_state->next > 0 ? d_state->next : end;
239 std::string &Reader::fixTypeName(std::string &name) {
240 size_t pos = name.size() - 4;
241 if (pos > 0 && name.substr(pos, 4).compare("Desc") == 0) {
242 return name.replace(pos, 4, "^");
244 return name;
247 TypePath Reader::readPath() {
248 TypePath path;
249 SHORTCHAR kind = readSChar();
250 SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator).
251 int i;
252 for (i = 0; kind == Store::NEWEXT; ++i) {
253 readSString(buf);
254 std::string name(buf);
255 path.push_back(fixTypeName(name));
256 addPathComponent(i == 0, path[i]);
257 // IF path[i] # elemTName THEN INC(i) END;
258 kind = readSChar();
261 if (kind == Store::NEWBASE) {
262 readSString(buf);
263 std::string name(buf);
264 path.push_back(fixTypeName(name));
265 addPathComponent(i == 0, path[i]);
266 ++i;
267 } else if (kind == Store::OLDTYPE) {
268 int id = readInt();
269 if (i > 0) {
270 d_typeList[d_typeList.size() - 1]->baseId = id;
272 while (id != -1) {
273 path.push_back(d_typeList[id]->name);
274 id = d_typeList[id]->baseId;
275 // IF path[i] # elemTName THEN INC(i) END
276 ++i;
278 } else {
279 throw 100;
281 return path;
284 void Reader::addPathComponent(bool first, const std::string &typeName) {
285 int next = d_typeList.size();
286 int curr = next - 1;
287 if (!first) {
288 d_typeList[curr]->baseId = next;
290 d_typeList.push_back(new TypeEntry(typeName));
293 } // namespace odc