DEADSOFTWARE

Can now read entire "empty" document as Alien
[odcread.git] / reader.cc
1 #include <reader.h>
2 #include <alien.h>
4 #include <string>
6 namespace odc {
8 Reader::Reader(std::istream &rider): d_rider(rider), d_cancelled(false), d_readAlien(false), d_typeList(),
9 d_state(new ReaderState()) {}
11 SHORTCHAR Reader::readSChar() {
12 SHORTCHAR out;
13 d_rider.read(&out, 1);
14 return out;
15 }
17 INTEGER Reader::readInt() {
18 char *buf = new char[4];
19 d_rider.read(buf, 4);
20 if (isLittleEndian()) {
21 return *(INTEGER *)buf;
22 } else {
23 char *out = new char[4];
24 out[0] = buf[3]; out[1] = buf[2]; out[2] = buf[1]; out[3] = buf[0];
25 return *(INTEGER *)out;
26 }
27 }
29 void Reader::readSString(SHORTCHAR *out) {
30 while (*out = readSChar()) {
31 ++out;
32 }
33 }
35 Store* Reader::readStore() {
36 SHORTCHAR kind = readSChar();
37 if (kind == Store::NIL) {
38 return readNilStore();
39 } else if (kind == Store::LINK) {
40 return readLinkStore();
41 } else if (kind == Store::NEWLINK) {
42 return readNewLinkStore();
43 } else if (kind == Store::STORE) {
44 return readStoreOrElemStore(false);
45 } else if (kind == Store::ELEM) {
46 return readStoreOrElemStore(true);
47 } else {
48 throw 20;
49 }
50 }
51 // PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
52 // VAR a: Alien; t: Kernel.Type;
53 // len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
54 // kind: SHORTCHAR; path: TypePath; type: TypeName;
55 // save: ReaderState;
56 Store *Reader::readNilStore() {
57 return 0;
58 }
59 // IF kind = nil THEN
60 // rd.ReadInt(comment); rd.ReadInt(next);
61 // rd.st.end := rd.Pos();
62 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
63 // x := NIL
64 Store *Reader::readLinkStore() {
65 return 0;
66 }
67 // ELSIF kind = link THEN
68 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
69 // rd.st.end := rd.Pos();
70 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
71 // x := ThisStore(rd.eDict, id)
72 Store *Reader::readNewLinkStore() {
73 return 0;
74 }
75 // ELSIF kind = newlink THEN
76 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
77 // rd.st.end := rd.Pos();
78 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
79 // x := ThisStore(rd.sDict, id)
81 Store *Reader::readStoreOrElemStore(bool isElem) {
82 INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
83 SHORTCHAR** path = newTypePath();
84 readPath(path);
85 for (int i = 0; path[i] != 0; ++i) {
86 std::cout << path[i] << std::endl;
87 }
88 SHORTCHAR* type = path[0];
89 INTEGER comment = readInt();
90 std::streampos pos1 = d_rider.tellg();
91 std::streamoff next = readInt();
92 std::streamoff down = readInt();
93 std::streamoff len = readInt();
94 std::streampos pos = d_rider.tellg();
95 if (next > 0) {
96 d_state->next = pos1 + next + (std::streamoff)4;
97 } else {
98 d_state->next = 0;
99 }
100 int downPos = 0;
101 if (down > 0) {
102 downPos = pos1 + down + (std::streamoff)8;
104 d_state->end = pos + len;
105 d_cause = 0;
106 // FIXME: insert whole bunch of checks here
107 // ASSERT(len >= 0, 101);
108 // IF next # 0 THEN
109 // ASSERT(rd.st.next > pos1, 102);
110 // IF down # 0 THEN
111 // ASSERT(downPos < rd.st.next, 103)
112 // END
113 // END;
114 // IF down # 0 THEN
115 // ASSERT(downPos > pos1, 104);
116 // ASSERT(downPos < rd.st.end, 105)
117 // END;
119 void *t = 0; // FIXME type lookup here
120 if (t != 0) {
121 // x := NewStore(t); x.isElem := kind = elem
122 } else {
123 // rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
124 // x := NIL
127 Store *x = 0;
128 if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE
129 } else {
130 // rd.SetPos(pos);
131 // ASSERT(rd.cause # 0, 107);
132 Alien *alien = new Alien(id, path); //, d_cause); //,file
133 if (d_store == 0) {
134 d_store = alien;
135 } else {
136 // join(d_store, alien)
137 std::cout << "Man, should have written join(.,.)" << std::endl;
139 if (isElem) {
140 d_elemList.push_back(alien);
141 } else {
142 d_storeList.push_back(alien);
144 ReaderState *save = d_state;
145 // rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
146 internalizeAlien(alien, downPos, save->end);
147 d_state = save;
148 // ASSERT(rd.Pos() = rd.st.end, 108);
149 // rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
150 return alien;
153 return x;
155 // t := ThisType(type);
156 // IF t # NIL THEN
157 // x := NewStore(t); x.isElem := kind = elem
158 // ELSE
159 // rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
160 // x := NIL
161 // END;
162 // IF x # NIL THEN
163 // IF SamePath(t, path) THEN
164 // IF kind = elem THEN
165 // x.id := id; AddStore(rd.eDict, rd.eHead, x)
166 // ELSE
167 // x.id := id; AddStore(rd.sDict, rd.sHead, x)
168 // END;
169 // save := rd.st; rd.cause := 0; rd.cancelled := FALSE;
170 // x.Internalize(rd);
171 // rd.st := save;
172 // IF rd.cause # 0 THEN x := NIL
173 // ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN
174 // rd.cause := inconsistentVersion; AlienReport(rd.cause);
175 // x := NIL
176 // END
177 // ELSE
178 // rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
179 // x := NIL
180 // END
181 // END;
182 //
183 // IF x # NIL THEN
184 // IF rd.noDomain THEN
185 // rd.store := x;
186 // rd.noDomain := FALSE
187 // ELSE
188 // Join(rd.store, x)
189 // END
190 // ELSE (* x is an alien *)
191 // rd.SetPos(pos);
192 // ASSERT(rd.cause # 0, 107);
193 // NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base();
194 // IF rd.noDomain THEN
195 // rd.store := a;
196 // rd.noDomain := FALSE
197 // ELSE
198 // Join(rd.store, a)
199 // END;
200 // IF kind = elem THEN
201 // a.id := id; AddStore(rd.eDict, rd.eHead, a)
202 // ELSE
203 // a.id := id; AddStore(rd.sDict, rd.sHead, a)
204 // END;
205 // save := rd.st;
206 // rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
207 // InternalizeAlien(rd, a.comps, downPos, pos, len);
208 // rd.st := save;
209 // x := a;
210 // ASSERT(rd.Pos() = rd.st.end, 108);
211 // rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
212 // END
215 void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) {
216 std::streampos next = down != 0 ? down : end;
217 while (d_rider.tellg() < end) {
218 if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured)
219 std::cout << "Alien Piece" << std::endl;
220 size_t len = next - d_rider.tellg();
221 char *buf = new char[len];
222 d_rider.read(buf, len);
223 AlienComponent *comp = new AlienPiece(buf, len);
224 alien->getComponents().push_back(comp);
225 } else { // that means we've got a store
226 std::cout << "Alien Store" << std::endl;
227 d_rider.seekg(next);
228 AlienComponent *comp = new AlienPart(readStore());
229 alien->getComponents().push_back(comp);
230 next = d_state->next > 0 ? d_state->next : end;
235 void Reader::readPath(SHORTCHAR **path) {
236 SHORTCHAR kind = readSChar();
237 int i;
238 for (i = 0; kind == Store::NEWEXT; ++i) {
239 readSString(path[i]);
240 addPathComponent(i == 0, path[i]);
241 // IF path[i] # elemTName THEN INC(i) END;
242 kind = readSChar();
245 if (kind == Store::NEWBASE) {
246 readSString(path[i]);
247 addPathComponent(i == 0, path[i]);
248 ++i;
249 } else if (kind == Store::OLDTYPE) {
250 int id = readInt();
251 d_typeList[d_typeList.size() - 1]->baseId = id;
252 // REPEAT
253 // GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id);
254 // IF path[i] # elemTName THEN INC(i) END
255 // UNTIL id = -1
256 } else {
257 throw 100;
259 path[i] = 0;
261 // PROCEDURE ReadPath (VAR rd: Reader; VAR path: TypePath);
262 // VAR h: TypeDict; id, extId: INTEGER; i: INTEGER; kind: SHORTCHAR;
263 //
264 // PROCEDURE AddPathComp (VAR rd: Reader);
265 // BEGIN
266 // IF h # NIL THEN AddBaseId(h, extId, rd.nextTypeId) END;
267 // AddType(rd.tDict, rd.tHead, rd.nextTypeId, path[i]);
268 // h := rd.tHead; extId := rd.nextTypeId
269 // END AddPathComp;
270 //
271 // BEGIN
272 // h := NIL; i := 0; rd.ReadSChar(kind);
273 // WHILE kind = newExt DO
274 // rd.ReadXString(path[i]);
275 // AddPathComp(rd); INC(rd.nextTypeId);
276 // IF path[i] # elemTName THEN INC(i) END;
277 // rd.ReadSChar(kind)
278 // END;
279 // IF kind = newBase THEN
280 // rd.ReadXString(path[i]);
281 // AddPathComp(rd); INC(rd.nextTypeId); INC(i)
282 // ELSE
283 // ASSERT(kind = oldType, 100);
284 // rd.ReadInt(id);
285 // IF h # NIL THEN AddBaseId(h, extId, id) END;
286 // REPEAT
287 // GetThisType(rd.tDict, id, path[i]); id := ThisBaseId(rd.tDict, id);
288 // IF path[i] # elemTName THEN INC(i) END
289 // UNTIL id = -1
290 // END;
291 // path[i] := ""
292 // END ReadPath;
294 void Reader::addPathComponent(bool first, SHORTCHAR *typeName) {
295 int next = d_typeList.size();
296 int curr = next - 1;
297 if (!first) {
298 d_typeList[curr]->baseId = next;
300 d_typeList.push_back(new TypeEntry(typeName));
303 } // namespace odc