DEADSOFTWARE

Add type handling (disabled until StdTextModel.internalize is implemented)
[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 BYTE Reader::readByte() {
18 BYTE out;
19 d_rider.read((char*)&out, 1);
20 return out;
21 }
23 INTEGER Reader::readInt() {
24 char *buf = new char[4];
25 d_rider.read(buf, 4);
26 if (isLittleEndian()) {
27 return *(INTEGER *)buf;
28 } else {
29 char *out = new char[4];
30 out[0] = buf[3]; out[1] = buf[2]; out[2] = buf[1]; out[3] = buf[0];
31 return *(INTEGER *)out;
32 }
33 }
35 void Reader::readSString(SHORTCHAR *out) {
36 while (*out = readSChar()) {
37 ++out;
38 }
39 }
41 INTEGER Reader::readVersion(INTEGER min, INTEGER max) {
42 INTEGER version = readByte();
43 //if (version < min || version > max) {
44 // rd.TurnIntoAlien(alienVersion)
45 //}
46 return version;
47 }
49 Store* Reader::readStore() {
50 SHORTCHAR kind = readSChar();
51 if (kind == Store::NIL) {
52 std::cout << "NIL STORE" << std::endl;
53 return readNilStore();
54 } else if (kind == Store::LINK) {
55 std::cout << "LINK STORE" << std::endl;
56 return readLinkStore();
57 } else if (kind == Store::NEWLINK) {
58 std::cout << "NEWLINK STORE" << std::endl;
59 return readNewLinkStore();
60 } else if (kind == Store::STORE) {
61 std::cout << "STORE STORE" << std::endl;
62 return readStoreOrElemStore(false);
63 } else if (kind == Store::ELEM) {
64 std::cout << "ELEM STORE" << std::endl;
65 return readStoreOrElemStore(true);
66 } else {
67 throw 20;
68 }
69 }
70 // PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
71 // VAR a: Alien; t: Kernel.Type;
72 // len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
73 // kind: SHORTCHAR; path: TypePath; type: TypeName;
74 // save: ReaderState;
75 Store *Reader::readNilStore() {
76 return 0;
77 }
78 // IF kind = nil THEN
79 // rd.ReadInt(comment); rd.ReadInt(next);
80 // rd.st.end := rd.Pos();
81 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
82 // x := NIL
83 Store *Reader::readLinkStore() {
84 return 0;
85 }
86 // ELSIF kind = link THEN
87 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
88 // rd.st.end := rd.Pos();
89 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
90 // x := ThisStore(rd.eDict, id)
91 Store *Reader::readNewLinkStore() {
92 return 0;
93 }
94 // ELSIF kind = newlink THEN
95 // rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
96 // rd.st.end := rd.Pos();
97 // IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
98 // x := ThisStore(rd.sDict, id)
100 Store *Reader::readStoreOrElemStore(bool isElem) {
101 INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
102 TypePath path = readPath();
103 std::cout << path.toString() << std::endl;
104 const std::string &type = path[0];
105 INTEGER comment = readInt();
106 std::streampos pos1 = d_rider.tellg();
107 std::streamoff next = readInt();
108 std::streamoff down = readInt();
109 std::streamoff len = readInt();
110 std::streampos pos = d_rider.tellg();
111 if (next > 0) {
112 d_state->next = pos1 + next + (std::streamoff)4;
113 } else {
114 d_state->next = 0;
116 int downPos = 0;
117 if (down > 0) {
118 downPos = pos1 + down + (std::streamoff)8;
120 d_state->end = pos + len;
121 d_cause = 0;
122 // FIXME: insert whole bunch of checks here
123 // ASSERT(len >= 0, 101);
124 // IF next # 0 THEN
125 // ASSERT(rd.st.next > pos1, 102);
126 // IF down # 0 THEN
127 // ASSERT(downPos < rd.st.next, 103)
128 // END
129 // END;
130 // IF down # 0 THEN
131 // ASSERT(downPos > pos1, 104);
132 // ASSERT(downPos < rd.st.end, 105)
133 // END;
135 const TypeProxyBase *t = TypeRegister::getInstance().get(type); // FIXME type lookup here
136 Store *x = 0;
137 if (t != 0) {
138 x = t->newInstance(id);
139 x->internalize(*this);
140 // x := NewStore(t); x.isElem := kind = elem
141 } else {
142 // rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
143 // x := NIL
146 if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE
147 } else {
148 // rd.SetPos(pos);
149 // ASSERT(rd.cause # 0, 107);
150 Alien *alien = new Alien(id, path); //, d_cause); //,file
151 if (d_store == 0) {
152 d_store = alien;
153 } else {
154 // join(d_store, alien)
155 std::cout << "Man, should have written join(.,.)" << std::endl;
157 if (isElem) {
158 d_elemList.push_back(alien);
159 } else {
160 d_storeList.push_back(alien);
162 ReaderState *save = d_state;
163 // rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
164 internalizeAlien(alien, downPos, save->end);
165 d_state = save;
166 // ASSERT(rd.Pos() = rd.st.end, 108);
167 // rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
168 return alien;
171 return x;
173 // t := ThisType(type);
174 // IF t # NIL THEN
175 // x := NewStore(t); x.isElem := kind = elem
176 // ELSE
177 // rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
178 // x := NIL
179 // END;
180 // IF x # NIL THEN
181 // IF SamePath(t, path) THEN
182 // IF kind = elem THEN
183 // x.id := id; AddStore(rd.eDict, rd.eHead, x)
184 // ELSE
185 // x.id := id; AddStore(rd.sDict, rd.sHead, x)
186 // END;
187 // save := rd.st; rd.cause := 0; rd.cancelled := FALSE;
188 // x.Internalize(rd);
189 // rd.st := save;
190 // IF rd.cause # 0 THEN x := NIL
191 // ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN
192 // rd.cause := inconsistentVersion; AlienReport(rd.cause);
193 // x := NIL
194 // END
195 // ELSE
196 // rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
197 // x := NIL
198 // END
199 // END;
200 //
201 // IF x # NIL THEN
202 // IF rd.noDomain THEN
203 // rd.store := x;
204 // rd.noDomain := FALSE
205 // ELSE
206 // Join(rd.store, x)
207 // END
208 // ELSE (* x is an alien *)
209 // rd.SetPos(pos);
210 // ASSERT(rd.cause # 0, 107);
211 // NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base();
212 // IF rd.noDomain THEN
213 // rd.store := a;
214 // rd.noDomain := FALSE
215 // ELSE
216 // Join(rd.store, a)
217 // END;
218 // IF kind = elem THEN
219 // a.id := id; AddStore(rd.eDict, rd.eHead, a)
220 // ELSE
221 // a.id := id; AddStore(rd.sDict, rd.sHead, a)
222 // END;
223 // save := rd.st;
224 // rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
225 // InternalizeAlien(rd, a.comps, downPos, pos, len);
226 // rd.st := save;
227 // x := a;
228 // ASSERT(rd.Pos() = rd.st.end, 108);
229 // rd.cause := 0; rd.cancelled := FALSE; rd.readAlien := TRUE
230 // END
233 void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) {
234 std::streampos next = down != 0 ? down : end;
235 while (d_rider.tellg() < end) {
236 if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured)
237 std::cout << "Alien Piece" << std::endl;
238 size_t len = next - d_rider.tellg();
239 char *buf = new char[len];
240 d_rider.read(buf, len);
241 AlienComponent *comp = new AlienPiece(buf, len);
242 alien->getComponents().push_back(comp);
243 } else { // that means we've got a store
244 std::cout << "Alien Store" << std::endl;
245 d_rider.seekg(next);
246 AlienComponent *comp = new AlienPart(readStore());
247 alien->getComponents().push_back(comp);
248 next = d_state->next > 0 ? d_state->next : end;
253 std::string &Reader::fixTypeName(std::string &name) {
254 size_t pos = name.size() - 4;
255 if (pos > 0 && name.substr(pos, 4).compare("Desc") == 0) {
256 return name.replace(pos, 4, "^");
258 return name;
261 TypePath Reader::readPath() {
262 TypePath path;
263 SHORTCHAR kind = readSChar();
264 SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator).
265 int i;
266 for (i = 0; kind == Store::NEWEXT; ++i) {
267 readSString(buf);
268 std::string name(buf);
269 path.push_back(fixTypeName(name));
270 addPathComponent(i == 0, path[i]);
271 // IF path[i] # elemTName THEN INC(i) END;
272 kind = readSChar();
275 if (kind == Store::NEWBASE) {
276 readSString(buf);
277 std::string name(buf);
278 path.push_back(fixTypeName(name));
279 addPathComponent(i == 0, path[i]);
280 ++i;
281 } else if (kind == Store::OLDTYPE) {
282 int id = readInt();
283 if (i > 0) {
284 d_typeList[d_typeList.size() - 1]->baseId = id;
286 while (id != -1) {
287 path.push_back(d_typeList[id]->name);
288 id = d_typeList[id]->baseId;
289 // IF path[i] # elemTName THEN INC(i) END
290 ++i;
292 } else {
293 throw 100;
295 return path;
298 void Reader::addPathComponent(bool first, const std::string &typeName) {
299 int next = d_typeList.size();
300 int curr = next - 1;
301 if (!first) {
302 d_typeList[curr]->baseId = next;
304 d_typeList.push_back(new TypeEntry(typeName));
307 } // namespace odc