evecache 0.42.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,325 @@
1
+ // libevecache - EVE Cache File Reader Library
2
+ // Copyright (C) 2009-2010 StackFoundry LLC and Yann Ramin
3
+ //
4
+ // This library is free software; you can redistribute it and/or
5
+ // modify it under the terms of the GNU General Public
6
+ // License as published by the Free Software Foundation; either
7
+ // version 2 of the License, or (at your option) any later version.
8
+ //
9
+ // This library is distributed in the hope that it will be useful,
10
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ // General Public License for more details.
13
+ //
14
+ // You should have received a copy of the GNU General Public
15
+ // License along with this library; if not, write to the Free Software
16
+ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ //
18
+ // http://dev.eve-central.com/libevecache/
19
+ // http://gitorious.org/libevecache
20
+
21
+
22
+
23
+ #include "evecache/market.hpp"
24
+ #include "evecache/dbtypes.hpp"
25
+ #include "evecache/reader.hpp"
26
+ #include "evecache/parser.hpp"
27
+ #include "evecache/exceptions.hpp"
28
+
29
+ #include <iostream>
30
+ #include <iomanip>
31
+ #include <string>
32
+ #include <sstream>
33
+
34
+ #include <time.h>
35
+
36
+ namespace EveCache {
37
+
38
+
39
+ std::string MarketOrder::toCsv() const
40
+ {
41
+ std::stringstream ss;
42
+ ss << std::fixed << std::showpoint << std::setprecision(2);
43
+ ss << price() / 10000.0;
44
+
45
+ ss << std::setprecision(1);
46
+ ss << "," << volRemaining();
47
+ ss << "," << type();
48
+ ss << "," << range();
49
+ ss << "," << orderID();
50
+ ss << "," << volEntered();
51
+ ss << "," << minVolume();
52
+
53
+ if (isBid())
54
+ ss << "," << "True";
55
+ else
56
+ ss << "," << "False";
57
+
58
+
59
+ time_t t = windows_to_unix_time(issued());
60
+ struct tm *tmp;
61
+
62
+ tmp = gmtime(&t);
63
+
64
+ char times[200];
65
+ strftime(times, 200, "%Y-%m-%d %H:%M:%S", tmp);
66
+
67
+
68
+ ss << "," << times << ".000";
69
+ ss << "," << duration();
70
+ ss << "," << stationID();
71
+ ss << "," << regionID();
72
+ ss << "," << solarSystemID();
73
+ ss << "," << jumps();
74
+ return ss.str();
75
+ }
76
+
77
+ MarketList::MarketList(int type, int region) : _type(type), _region(region)
78
+ {
79
+ }
80
+
81
+ MarketList::MarketList() : _type(0), _region(0), _ts(0)
82
+ {
83
+ }
84
+
85
+ void MarketList::addOrder(MarketOrder& order)
86
+ {
87
+ if (order.isBid())
88
+ _buyOrders.push_back(order);
89
+ else
90
+ _sellOrders.push_back(order);
91
+ }
92
+
93
+ MarketList MarketParser::getList() const
94
+ {
95
+ return _list;
96
+ }
97
+
98
+
99
+
100
+ MarketParser::MarketParser(const SNode* stream) : _stream(stream), _valid(false)
101
+ {
102
+
103
+ }
104
+
105
+ MarketParser::MarketParser(const char* fileName) : _valid(false)
106
+ {
107
+ try {
108
+ initWithFile(std::string(fileName));
109
+ } catch (ParseException &e) {
110
+ return;
111
+ }
112
+ }
113
+
114
+ MarketParser::MarketParser(const std::string fileName) : _valid(false)
115
+ {
116
+ try{
117
+ initWithFile(fileName);
118
+ } catch (ParseException &e) {
119
+ return;
120
+ }
121
+ }
122
+
123
+ MarketParser::~MarketParser()
124
+ {
125
+ }
126
+
127
+ void MarketParser::initWithFile(const std::string& fileName)
128
+ {
129
+ CacheFile cF(fileName);
130
+ if (cF.readFile() == false) {
131
+ throw new ParseException("Can't open file" + fileName);
132
+ }
133
+ CacheFile_Iterator i = cF.begin();
134
+ Parser *parser = new Parser(&i);
135
+ parser->parse();
136
+ const SNode* snode = parser->streams()[0];
137
+ _stream = snode;
138
+ parse();
139
+ delete parser;
140
+ _stream = NULL;
141
+ _valid = true;
142
+ }
143
+
144
+ bool MarketParser::valid() const
145
+ {
146
+ return _valid;
147
+ }
148
+
149
+
150
+ void MarketParser::parseDbRow(const SNode* node)
151
+ {
152
+ MarketOrder order;
153
+
154
+ std::vector<SNode*>::const_iterator i = node->members().begin();
155
+
156
+ for (; i != node->members().end(); ++i)
157
+ {
158
+
159
+
160
+ SNode* value = *i;
161
+ ++i;
162
+ SMarker* key = dynamic_cast<SMarker*>(*i);
163
+ SIdent* ident = dynamic_cast<SIdent*>(*i);
164
+
165
+ int typeKey = -1;
166
+
167
+ if (key != 0) {
168
+ typeKey = key->id();
169
+ } else {
170
+ if (ident->name() == "issueDate") {
171
+ typeKey = 131;
172
+ } else {
173
+ std::cerr << "Can't parse - giving up" << std::endl;
174
+ break;
175
+ }
176
+ }
177
+
178
+
179
+
180
+ SInt* intV = dynamic_cast<SInt*>(value);
181
+ SLongLong* longV = dynamic_cast<SLongLong*>(value);
182
+ SReal* realV = dynamic_cast<SReal*>(value);
183
+
184
+ int sintV = 0;
185
+ long long slongV = 0;
186
+ double srealV = 0.0;
187
+
188
+ if (longV != NULL)
189
+ slongV = longV->value();
190
+
191
+ if (intV != NULL)
192
+ sintV = intV->value();
193
+
194
+ if (realV != NULL)
195
+ srealV = realV->value();
196
+
197
+
198
+ switch(typeKey) {
199
+ case 139:
200
+ order.setPrice(slongV);
201
+ break;
202
+ case 161:
203
+ order.setVolRemaining(srealV);
204
+ break;
205
+ case 131:
206
+ order.setIssued(slongV);
207
+ break;
208
+ case 138:
209
+ order.setOrderID(slongV);
210
+ break;
211
+ case 160:
212
+ order.setVolEntered(sintV);
213
+ break;
214
+ case 137:
215
+ order.setMinVolume(sintV);
216
+ break;
217
+ case 155:
218
+ order.setStationID(sintV);
219
+ break;
220
+ case 141:
221
+ order.setRegionID(sintV);
222
+ _list.setRegion(sintV);
223
+ break;
224
+ case 150:
225
+ order.setSolarSystemID(sintV);
226
+ break;
227
+ case 41:
228
+ order.setJumps(sintV);
229
+ break;
230
+ case 74:
231
+ order.setType(sintV);
232
+ _list.setType(sintV);
233
+ break;
234
+ case 140:
235
+ order.setRange(sintV);
236
+ break;
237
+ case 126:
238
+ order.setDuration(sintV);
239
+ break;
240
+ case 116:
241
+ if (sintV)
242
+ order.setBid(true);
243
+ else
244
+ order.setBid(false);
245
+ break;
246
+ default:
247
+ std::cout << "Unknown key ID:" << (int)key->id() << " r: " << srealV << " l: " << slongV << " i: " << sintV << std::endl;
248
+ break;
249
+
250
+ }
251
+ }
252
+ _list.addOrder(order);
253
+
254
+
255
+ }
256
+
257
+ void MarketParser::parse(const SNode* node)
258
+ {
259
+ if (node->members().size() > 0) {
260
+ std::vector<SNode*>::const_iterator i = node->members().begin();
261
+ for (; i!= node->members().end(); ++i) {
262
+ SDBRow *dbrow = dynamic_cast<SDBRow*>(*i);
263
+ if (dbrow != NULL) {
264
+ ++i;
265
+ parseDbRow(*i);
266
+ } else {
267
+ parse(*i);
268
+ }
269
+ }
270
+ }
271
+ }
272
+
273
+ void MarketParser::parse()
274
+ {
275
+ if (_stream == NULL)
276
+ return;
277
+
278
+ /* Todo: fixed offsets = bad :) */
279
+ /* Step 1: Determine if this is a market order file */
280
+ if (_stream->members().size() < 1)
281
+ throw ParseException("Not a valid file");
282
+
283
+ SNode *base = _stream->members()[0];
284
+
285
+ if (base->members().size() < 1)
286
+ throw ParseException("Not a valid orders file");
287
+ if (base->members()[0]->members().size() < 2)
288
+ throw ParseException("Not a valid orders file");
289
+
290
+ SIdent *id = dynamic_cast<SIdent*>(base->members()[0]->members()[1]);
291
+ if (id == NULL)
292
+ throw ParseException("Can't determine method name");
293
+ if (id->name() != "GetOrders")
294
+ throw ParseException("Not a valid orders file");
295
+
296
+ /* Retrieve the region and type */
297
+
298
+ SInt *region = dynamic_cast<SInt*>(base->members()[0]->members()[2]);
299
+ SInt *type = dynamic_cast<SInt*>(base->members()[0]->members()[3]);
300
+
301
+ _list.setRegion(region->value());
302
+ _list.setType(type->value());
303
+
304
+ /* Try to extract the in-file timestamp */
305
+
306
+ SDict *dict = dynamic_cast<SDict*>(base->members()[1]);
307
+ if (dict == NULL)
308
+ throw ParseException("Can't read file timestamp");
309
+
310
+ // Grab the version entry of the version tuple
311
+ SLongLong *time = dynamic_cast<SLongLong*>(dict->getByName("version")->members()[0]);
312
+ if (time == NULL)
313
+ throw ParseException("Can't read file timestamp");
314
+
315
+ std::cout << "TS: " << time->value() << std::endl;
316
+ _list.setTimestamp(windows_to_unix_time(time->value()));
317
+
318
+ SNode *obj = dynamic_cast<SObject*>(base->members()[1]->members()[0]);
319
+ if (obj == NULL)
320
+ return;
321
+ parse(obj);
322
+ _valid = true;
323
+ }
324
+
325
+ };
@@ -0,0 +1,1249 @@
1
+ // libevecache - EVE Cache File Reader Library
2
+ // Copyright (C) 2009-2010 StackFoundry LLC and Yann Ramin
3
+ //
4
+ // This library is free software; you can redistribute it and/or
5
+ // modify it under the terms of the GNU General Public
6
+ // License as published by the Free Software Foundation; either
7
+ // version 2 of the License, or (at your option) any later version.
8
+ //
9
+ // This library is distributed in the hope that it will be useful,
10
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ // General Public License for more details.
13
+ //
14
+ // You should have received a copy of the GNU General Public
15
+ // License along with this library; if not, write to the Free Software
16
+ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ //
18
+ // http://dev.eve-central.com/libevecache/
19
+ // http://gitorious.org/libevecache
20
+
21
+
22
+ #include "evecache/parser.hpp"
23
+ #include "evecache/reader.hpp"
24
+ #include "evecache/exceptions.hpp"
25
+
26
+ #include <assert.h>
27
+
28
+ #include <iostream>
29
+ #include <iomanip>
30
+ #include <sstream>
31
+
32
+ namespace EveCache {
33
+
34
+
35
+ struct packer_opcap {
36
+ unsigned char tlen : 3;
37
+ bool tzero : 1;
38
+ unsigned char blen : 3;
39
+ bool bzero : 1;
40
+ };
41
+
42
+ static void rle_unpack(const unsigned char* in_buf, int in_length, std::vector<unsigned char> &buffer)
43
+ {
44
+ buffer.clear();
45
+ if(in_length == 0)
46
+ return;
47
+
48
+ const unsigned char *end = in_buf + in_length;
49
+ while (in_buf < end)
50
+ {
51
+
52
+ const packer_opcap opcap = *(reinterpret_cast<const packer_opcap*>(in_buf++));
53
+ if (opcap.tzero) {
54
+ unsigned char count = opcap.tlen + 1;
55
+ //std::cerr << "RLE: t zero " << count << std::endl;
56
+ for (; count > 0; count--)
57
+ {
58
+ buffer.push_back(0);
59
+ }
60
+ } else {
61
+ unsigned int count = 8 - opcap.tlen;
62
+ //std::cerr << "RLE: t copy " << count << std::endl;
63
+ for (; count > 0 && in_buf < end ; count--) {
64
+ buffer.push_back(*in_buf++);
65
+ }
66
+ }
67
+ if (opcap.bzero) {
68
+ unsigned char count = opcap.blen + 1;
69
+ //std::cerr << "RLE: b zero " << count << std::endl;
70
+ for (; count > 0; count--)
71
+ {
72
+ buffer.push_back(0);
73
+ }
74
+ } else {
75
+ unsigned int count = 8 - opcap.blen;
76
+ //std::cerr << "RLE: b copy " << count << std::endl;
77
+ for (; count > 0 && in_buf < end ; count--) {
78
+ buffer.push_back(*in_buf++);
79
+ }
80
+ }
81
+
82
+ }
83
+ }
84
+
85
+
86
+
87
+ std::string SNode::repl() const
88
+ {
89
+ std::stringstream msg(std::stringstream::out);
90
+ msg << "<SNode type " << std::hex << type() << ">";
91
+ return msg.str();
92
+ }
93
+
94
+ SNode::SNode(EStreamCode t) : _type(t)
95
+ {
96
+ }
97
+
98
+ SNode::SNode(const SNode& rhs)
99
+ {
100
+ std::vector<SNode*>::const_iterator i = rhs._members.begin();
101
+ for ( ; i != rhs._members.end(); ++i)
102
+ {
103
+ _members.push_back((*i)->clone());
104
+ }
105
+ _type = rhs._type;
106
+ }
107
+
108
+ SNode* SNode::clone() const
109
+ {
110
+ return new SNode(*this);
111
+ }
112
+
113
+ SNode::~SNode()
114
+ {
115
+ std::vector<SNode*>::iterator i = _members.begin();
116
+ for (; i != _members.end(); ++i)
117
+ {
118
+ delete *i;
119
+ }
120
+ }
121
+
122
+ EStreamCode SNode::type() const
123
+ {
124
+ return _type;
125
+ }
126
+
127
+ void SNode::setType(EStreamCode t)
128
+ {
129
+ _type = t;
130
+ }
131
+
132
+ void SNode::addMember(SNode* node)
133
+ {
134
+ _members.push_back(node);
135
+ }
136
+
137
+ const std::vector<SNode*>& SNode::members() const
138
+ {
139
+ return _members;
140
+ }
141
+
142
+
143
+ /***********************************************************************/
144
+
145
+ SStreamNode::SStreamNode() : SNode(EStreamStart)
146
+ {
147
+ }
148
+
149
+ SStreamNode::SStreamNode(EStreamCode t) : SNode(t)
150
+ {
151
+ }
152
+
153
+ SStreamNode::SStreamNode(const SStreamNode& rhs) : SNode(rhs)
154
+ {
155
+ }
156
+
157
+ std::string SStreamNode::repl() const
158
+ {
159
+ std::stringstream ss;
160
+ ss << " <SStreamNode> ";
161
+ return ss.str();
162
+ }
163
+
164
+ SStreamNode* SStreamNode::clone() const
165
+ {
166
+ return new SStreamNode(*this);
167
+ }
168
+
169
+ /***********************************************************************/
170
+
171
+ SDBHeader::SDBHeader() : SNode(ECompressedRow)
172
+ {
173
+ }
174
+
175
+ std::string SDBHeader::repl() const
176
+ {
177
+ return std::string("<SDBHeader>");
178
+ }
179
+
180
+
181
+ SDBHeader* SDBHeader::clone() const
182
+ {
183
+ return new SDBHeader(*this);
184
+ }
185
+
186
+ /***********************************************************************/
187
+
188
+
189
+ STuple::STuple(unsigned int len) : SNode(ETuple), _givenLength(len)
190
+ {
191
+ }
192
+
193
+ STuple::STuple(const STuple &rhs) : SNode(rhs)
194
+ {
195
+ _givenLength = rhs._givenLength;
196
+ }
197
+
198
+ STuple::~STuple()
199
+ {
200
+ }
201
+
202
+ void STuple::addMember(SNode* node)
203
+ {
204
+ assert(_members.size() < _givenLength);
205
+ _members.push_back(node);
206
+ }
207
+
208
+
209
+ unsigned int STuple::givenLength() const
210
+ {
211
+ return _givenLength;
212
+ }
213
+
214
+ std::string STuple::repl() const
215
+ {
216
+ std::stringstream ss;
217
+ ss << " <STuple> ";
218
+ return ss.str();
219
+ }
220
+
221
+ STuple* STuple::clone() const
222
+ {
223
+ return new STuple(*this);
224
+ }
225
+
226
+
227
+ /***********************************************************************/
228
+
229
+ SDict::SDict(unsigned int len) : SNode(EDict), _givenLength(len)
230
+ {
231
+ }
232
+
233
+ SDict::SDict(const SDict &rhs) : SNode(rhs)
234
+ {
235
+ _givenLength = rhs._givenLength;
236
+ }
237
+
238
+ SDict::~SDict()
239
+ {
240
+ }
241
+
242
+ void SDict::addMember(SNode* node)
243
+ {
244
+ assert(_members.size() < _givenLength);
245
+ _members.push_back(node);
246
+ }
247
+
248
+ unsigned int SDict::givenLength() const
249
+ {
250
+ return _givenLength;
251
+ }
252
+
253
+ std::string SDict::repl() const
254
+ {
255
+ std::stringstream ss;
256
+ ss << " <SDict> ";
257
+ return ss.str();
258
+ }
259
+
260
+ SDict* SDict::clone() const
261
+ {
262
+ return new SDict(*this);
263
+ }
264
+
265
+ SNode* SDict::getByName(const std::string &target) const
266
+ {
267
+ if (_members.size() < 2 || _members.size() & 1)
268
+ return NULL;
269
+
270
+ /* Non idiomatic C++ coming, you've been warned */
271
+ /* Optimization improvement: replace this thing with a real map */
272
+
273
+ for (unsigned int i = 1; i < _members.size(); i += 2) {
274
+ SIdent *name = dynamic_cast<SIdent*>(_members[i]);
275
+ if (name != NULL) {
276
+ if (name->name() == target)
277
+ return _members[i - 1];
278
+ }
279
+ }
280
+ return NULL;
281
+ }
282
+
283
+
284
+ /***********************************************************************/
285
+
286
+
287
+ SMarker::SMarker(unsigned char i) : SNode(EMarker), _id(i)
288
+ {
289
+ }
290
+
291
+ std::string SMarker::repl() const
292
+ {
293
+ std::stringstream ss;
294
+ ss << " <SMarker ID: " << static_cast<unsigned int>(id()) << " '" << string() << "' > ";
295
+ return ss.str();
296
+ }
297
+
298
+ unsigned char SMarker::id() const
299
+ {
300
+ return _id;
301
+ }
302
+
303
+ std::string SMarker::string() const
304
+ {
305
+ std::string name = ColumnLookup::lookupName(id());
306
+ if (name.empty())
307
+ {
308
+ std::stringstream ss;
309
+ ss << "UNKNOWN:" << static_cast<unsigned int>(id());
310
+ return ss.str();
311
+ } else
312
+ return name;
313
+ }
314
+
315
+ SMarker* SMarker::clone() const
316
+ {
317
+ return new SMarker(*this);
318
+ }
319
+
320
+ /***********************************************************************/
321
+
322
+ SIdent::SIdent(const std::string& n) : SNode(EIdent), _name(n)
323
+ {
324
+ }
325
+
326
+ std::string SIdent::repl() const
327
+ {
328
+ std::stringstream ss;
329
+ ss << " <SIdent '" << name() << "'> ";
330
+ return ss.str();
331
+ }
332
+
333
+ std::string SIdent::name() const
334
+ {
335
+ return _name;
336
+ }
337
+
338
+
339
+ SIdent* SIdent::clone() const
340
+ {
341
+ return new SIdent(*this);
342
+ }
343
+
344
+ /***********************************************************************/
345
+
346
+ SString::SString(const std::string& n) : SNode(EString), _name(n)
347
+ {
348
+ }
349
+
350
+ std::string SString::string() const
351
+ {
352
+ return _name;
353
+ }
354
+
355
+ std::string SString::repl() const
356
+ {
357
+ std::stringstream ss;
358
+ ss << " <SString '" << string() << "'> ";
359
+ return ss.str();
360
+ }
361
+
362
+ SString* SString::clone() const
363
+ {
364
+ return new SString(*this);
365
+ }
366
+
367
+
368
+
369
+ /***********************************************************************/
370
+
371
+ SInt::SInt(int val) : SNode(EInteger), _value(val)
372
+ {
373
+ }
374
+
375
+ int SInt::value() const
376
+ {
377
+ return _value;
378
+ }
379
+
380
+ std::string SInt::repl() const
381
+ {
382
+ std::stringstream ss;
383
+ ss << " <SInt '" << value() << "'> ";
384
+ return ss.str();
385
+ }
386
+
387
+ SInt* SInt::clone() const
388
+ {
389
+ return new SInt(*this);
390
+ }
391
+
392
+
393
+ /***********************************************************************/
394
+
395
+ SReal::SReal(double val) : SNode(EReal), _value(val)
396
+ {
397
+ }
398
+
399
+ double SReal::value() const
400
+ {
401
+ return _value;
402
+ }
403
+
404
+ std::string SReal::repl() const
405
+ {
406
+ std::stringstream ss;
407
+ ss << " <SReal '" << value() << "'> ";
408
+ return ss.str();
409
+ }
410
+
411
+ SReal* SReal::clone() const
412
+ {
413
+ return new SReal(*this);
414
+ }
415
+
416
+
417
+ /***********************************************************************/
418
+
419
+ SLongLong::SLongLong(long long val) : SNode(ELongLong), _value(val)
420
+ {
421
+ }
422
+
423
+ long long SLongLong::value() const
424
+ {
425
+ return _value;
426
+ }
427
+
428
+ std::string SLongLong::repl() const
429
+ {
430
+ std::stringstream ss;
431
+ ss << " <SLongLong '" << value() << "'> ";
432
+ return ss.str();
433
+ }
434
+
435
+ SLongLong* SLongLong::clone() const
436
+ {
437
+ return new SLongLong(*this);
438
+ }
439
+
440
+
441
+ /***********************************************************************/
442
+
443
+ SObject::SObject() : SNode(EObject)
444
+ {
445
+ }
446
+
447
+ std::string SObject::name() const
448
+ {
449
+ const SNode *cur = this;
450
+ while (cur->members().size())
451
+ cur = static_cast<SNode*>(cur->members()[0]);
452
+
453
+ const SString *str = dynamic_cast<const SString*>(cur);
454
+
455
+ if (str != NULL)
456
+ return str->string();
457
+ return std::string("");
458
+ }
459
+
460
+ std::string SObject::repl() const
461
+ {
462
+ std::stringstream ss;
463
+ ss << " <SObject '" << name() << "' " << this << "> ";
464
+ return ss.str();
465
+ }
466
+
467
+
468
+ SObject* SObject::clone() const
469
+ {
470
+ return new SObject(*this);
471
+ }
472
+
473
+ /***********************************************************************/
474
+
475
+ SNone::SNone() : SNode(ENone)
476
+ {
477
+ }
478
+ std::string SNone::repl() const
479
+ {
480
+ std::stringstream ss;
481
+ ss << " <NONE> ";
482
+ return ss.str();
483
+ }
484
+
485
+ SNone* SNone::clone() const
486
+ {
487
+ return new SNone(*this);
488
+ }
489
+
490
+ /***********************************************************************/
491
+
492
+ SSubstream::SSubstream(int len) : SNode(ESubstream), _len(len)
493
+ {
494
+ }
495
+
496
+ std::string SSubstream::repl() const
497
+ {
498
+ std::stringstream ss;
499
+ ss << " <SSubstream> ";
500
+ return ss.str();
501
+ }
502
+
503
+ SSubstream* SSubstream::clone() const
504
+ {
505
+ return new SSubstream(*this);
506
+ }
507
+
508
+ /***********************************************************************/
509
+
510
+ SDBRow::SDBRow(int magic, const std::vector<unsigned char>& data)
511
+ : SNode(ECompressedRow), _id(magic), _last(false), _data(data)
512
+ {
513
+ }
514
+
515
+ std::string SDBRow::repl() const
516
+ {
517
+ std::stringstream ss;
518
+ ss << " <DBRow ";
519
+
520
+ std::vector<unsigned char>::const_iterator kk = _data.begin();
521
+
522
+ for (; kk != _data.end(); ++kk)
523
+ {
524
+ ss << std::setw(2) <<
525
+ std::setfill('0') << std::hex << static_cast<int>(*kk);
526
+ }
527
+
528
+ if (isLast())
529
+ ss << " LAST ";
530
+
531
+ ss << ">";
532
+ return ss.str();
533
+ }
534
+
535
+ bool SDBRow::isLast() const
536
+ {
537
+ return _last;
538
+ }
539
+
540
+ void SDBRow::setLast(bool last)
541
+ {
542
+ _last = last;
543
+ }
544
+
545
+ SDBRow* SDBRow::clone() const
546
+ {
547
+ return new SDBRow(*this);
548
+ }
549
+
550
+
551
+
552
+ /***********************************************************************/
553
+
554
+ SDBRecords::SDBRecords() : SNode(ECompressedRow)
555
+ {
556
+ }
557
+
558
+ std::string SDBRecords::repl() const
559
+ {
560
+ return std::string("");
561
+ }
562
+
563
+ SDBRecords* SDBRecords::clone() const
564
+ {
565
+ return new SDBRecords(*this);
566
+ }
567
+
568
+ /***********************************************************************/
569
+
570
+ Parser::Parser(CacheFile_Iterator *iter)
571
+ : _iter(iter), _sharecount(0), _sharecursor(0), _shareobj(NULL), _sharemap(NULL)
572
+ {
573
+ }
574
+
575
+ Parser::~Parser()
576
+ {
577
+
578
+ std::vector<SNode*>::iterator i = _streams.begin();
579
+ for (; i != _streams.end(); ++i)
580
+ {
581
+ delete *i;
582
+ }
583
+
584
+ if (_shareobj != NULL)
585
+ for (unsigned int j = 0; j <= _sharecount; j++) {
586
+ if (_shareobj[j] != NULL)
587
+ delete _shareobj[j];
588
+ }
589
+
590
+
591
+ if (_shareobj != NULL)
592
+ delete [] _shareobj;
593
+ if (_sharemap != NULL)
594
+ delete [] _sharemap;
595
+ }
596
+
597
+ SNode* Parser::parseone()
598
+ {
599
+ char check;
600
+ char isshared = 0;
601
+ SNode *thisobj = NULL;
602
+ SDBRow *lastDbRow = NULL;
603
+
604
+ try {
605
+ char type = _iter->readChar();
606
+ check = type & 0x3f;
607
+ isshared = type & 0x40;
608
+ } catch (EndOfFileException &e) {
609
+ return NULL;
610
+ }
611
+
612
+ //std::cerr << "DEB: parseone, pos " << _iter->position() << ", type " << std::hex << static_cast<unsigned int>(check) << ", shared " << static_cast<unsigned int>(isshared) << std::endl;
613
+
614
+ switch(check) {
615
+ case ENone:
616
+ {
617
+ thisobj = new SNone();
618
+ }
619
+ break;
620
+ case EReal:
621
+ {
622
+ double val = _iter->readDouble();
623
+ thisobj = new SReal(val);
624
+ }
625
+ break;
626
+ case E0Real:
627
+ {
628
+ thisobj = new SReal(0);
629
+ }
630
+ break;
631
+ case EInteger:
632
+ {
633
+ unsigned int val = _iter->readInt();
634
+ thisobj = new SInt(val);
635
+ }
636
+ break;
637
+ case EBoolFalse:
638
+ case E0Integer:
639
+ {
640
+ thisobj = new SInt(0);
641
+ }
642
+ break;
643
+ case EBoolTrue: /* Replace with a real Bool node one day */
644
+ case E1Integer:
645
+ {
646
+ thisobj = new SInt(1);
647
+ }
648
+ break;
649
+ case ENeg1Integer:
650
+ {
651
+ thisobj = new SInt(-1);
652
+ };
653
+ break;
654
+ case ELongLong:
655
+ {
656
+ long long val = _iter->readLongLong();
657
+ thisobj = new SLongLong(val);
658
+ }
659
+ break;
660
+ case EShort:
661
+ {
662
+ int i = _iter->readShort();
663
+ thisobj = new SInt(i);
664
+ }
665
+ break;
666
+ case EByte:
667
+ {
668
+ int i = _iter->readChar();
669
+ thisobj = new SInt(i);
670
+ }
671
+ break;
672
+ case ESizedInt:
673
+ {
674
+ unsigned char len = _iter->readChar();
675
+ if (len == 8)
676
+ thisobj = new SLongLong(_iter->readLongLong());
677
+ else if (len == 4)
678
+ thisobj = new SInt(_iter->readInt()); // not observed
679
+ else if (len == 2)
680
+ thisobj = new SInt(_iter->readShort()); // not observed
681
+ else if (len == 3)
682
+ thisobj = new SInt((_iter->readChar()) + (_iter->readChar() << 16) + (_iter->readChar() << 24));
683
+ }
684
+ break;
685
+ case EIdent:
686
+ {
687
+ unsigned int len = getLen();
688
+ std::string data = _iter->readString(len);
689
+ thisobj = new SIdent(data);
690
+ }
691
+ break;
692
+ case EEmptyString:
693
+ {
694
+ thisobj = new SString("");
695
+ }
696
+ break;
697
+ case EUnicodeString2:
698
+ {
699
+ /* Single unicode character */
700
+ std::string data = _iter->readString(2);
701
+ thisobj = new SString(data);
702
+ }
703
+ break;
704
+ case EString3:
705
+ {
706
+ std::string data = _iter->readString(1);
707
+ thisobj = new SString(data);
708
+ }
709
+ break;
710
+ case E0String:
711
+ {
712
+ std::string data;
713
+ thisobj = new SString(data);
714
+ }
715
+ break;
716
+ case EUnicodeString:
717
+ case EString4:
718
+ case EString2:
719
+ case EString:
720
+ {
721
+ int len = _iter->readChar();
722
+ std::string data = _iter->readString(len);
723
+ thisobj = new SString(data);
724
+
725
+ // if (len == 0 && (_iter->limit() - _iter->position()) <= 0xf) {
726
+ // HACK HACK HACK - 0 length string is probably the end of this substream
727
+ // lets just give up now
728
+ // while(!_iter->atEnd())
729
+ // _iter->readChar();
730
+ // return;
731
+ // }
732
+ }
733
+ break;
734
+ case EDict:
735
+ {
736
+ unsigned int len = getLen();
737
+ SDict* dict = new SDict(len * 2); // key & val
738
+ thisobj = dict;
739
+ try {
740
+ parse(dict, len * 2);
741
+ } catch (ParseException &e) {
742
+ delete dict;
743
+ throw e;
744
+ } catch (EndOfFileException &e) {
745
+ delete dict;
746
+ throw e;
747
+ }
748
+ }
749
+ break;
750
+ case ETuple2:
751
+ case ETuple:
752
+ {
753
+ unsigned int len = getLen();
754
+ thisobj = new STuple(len);
755
+ try {
756
+ parse(thisobj, len);
757
+ } catch (ParseException &e) {
758
+ delete thisobj;
759
+ throw e;
760
+ } catch (EndOfFileException &e) {
761
+ delete thisobj;
762
+ throw e;
763
+ }
764
+
765
+ }
766
+ break;
767
+ case E2Tuple:
768
+ {
769
+ thisobj = new STuple(2);
770
+ try {
771
+ parse(thisobj, 2);
772
+ } catch (ParseException &e) {
773
+ delete thisobj;
774
+ throw e;
775
+ } catch (EndOfFileException &e) {
776
+ delete thisobj;
777
+ throw e;
778
+ }
779
+
780
+ }
781
+ break;
782
+ case E1Tuple2:
783
+ case E1Tuple:
784
+ {
785
+ thisobj = new STuple(1);
786
+ try {
787
+ parse(thisobj, 1);
788
+ } catch (ParseException &e) {
789
+ delete thisobj;
790
+ throw e;
791
+ } catch (EndOfFileException &e) {
792
+ delete thisobj;
793
+ throw e;
794
+ }
795
+
796
+ }
797
+ break;
798
+ case E0Tuple2:
799
+ case E0Tuple:
800
+ {
801
+ thisobj = new STuple(0);
802
+ }
803
+ break;
804
+ case EMarker:
805
+ {
806
+ unsigned int t = getLen();
807
+ thisobj = new SMarker(t);
808
+ }
809
+ break;
810
+ case EObject:
811
+ {
812
+ SObject *obj = new SObject();
813
+ thisobj = obj;
814
+ try {
815
+ parse(obj, 2);
816
+ } catch (ParseException &e) {
817
+ delete obj;
818
+ throw e;
819
+ } catch (EndOfFileException &e) {
820
+ delete obj;
821
+ throw e;
822
+ }
823
+ }
824
+ break;
825
+ case EObject22:
826
+ case EObject23:
827
+ {
828
+ SObject *obj = new SObject();
829
+ thisobj = obj;
830
+ try {
831
+ parse(obj, 1);
832
+ } catch (ParseException &e) {
833
+ delete obj;
834
+ throw e;
835
+ } catch (EndOfFileException &e) {
836
+ delete obj;
837
+ throw e;
838
+ }
839
+
840
+ std::string oclass(obj->name());
841
+ //std::cerr << "Obj: " << obj << " == " << obj->repl() << ", class " << oclass << std::endl;
842
+
843
+ // HALP
844
+ // out of ideas at this point
845
+ // some kind of hook for class-specific object processing
846
+ // needs to be attached here, that handles the objects depeding
847
+ // on the classname which should be in cur at this point.
848
+ //
849
+ // f.ex. dbutil.RowList -> keep reading rows until you hit the 0x2d marker
850
+ //
851
+ if (! oclass.compare("dbutil.RowList")) {
852
+ try {
853
+ SNode *row;
854
+ while ( (row = parseone()) ) {
855
+ obj->addMember(row);
856
+ }
857
+ } catch (ParseException &e) {
858
+ delete obj;
859
+ throw e;
860
+ } catch (EndOfFileException &e) {
861
+ delete obj;
862
+ throw e;
863
+ }
864
+ }
865
+
866
+ }
867
+ break;
868
+ case ESubstream:
869
+ {
870
+ unsigned int len = getLen();
871
+ //char sig = _iter->readChar(); // 0x7e
872
+ //assert(sig == 0x7e);
873
+ CacheFile_Iterator iter_sub(*_iter);
874
+ iter_sub.setLimit(len);
875
+ SSubstream *ss = new SSubstream(len);
876
+ thisobj = ss;
877
+ try {
878
+ Parser sp(&iter_sub);
879
+ sp.parse();
880
+ for (unsigned int i = 0; i < sp.streams().size(); i++) {
881
+ ss->addMember(sp.streams()[i]->clone());
882
+ }
883
+ } catch (ParseException &e) {
884
+ delete ss;
885
+ throw e;
886
+ } catch (EndOfFileException &e) {
887
+ delete ss;
888
+ throw e;
889
+ }
890
+
891
+ _iter->seek(iter_sub.position());
892
+ }
893
+ break;
894
+ case ECompressedRow:
895
+ {
896
+ try {
897
+ thisobj = getDBRow();
898
+ } catch (ParseException &e) {
899
+ delete thisobj;
900
+ throw e;
901
+ } catch (EndOfFileException &e) {
902
+ delete thisobj;
903
+ throw e;
904
+ }
905
+ }
906
+ break;
907
+ case ESharedObj:
908
+ {
909
+ unsigned int id = getLen();
910
+ thisobj = shareGet(id);
911
+ }
912
+ break;
913
+ case EChecksum:
914
+ {
915
+
916
+ thisobj = new SString("checksum");
917
+ _iter->readInt();
918
+ }
919
+ break;
920
+ case 0x2d:
921
+ {
922
+ if(_iter->readChar() != 0x2d) {
923
+ std::stringstream msg;
924
+ msg << "Didn't encounter a double 0x2d where I thought there should be one at " << _iter->position();
925
+ throw ParseException(msg.str());
926
+ }
927
+ if (lastDbRow)
928
+ lastDbRow->setLast(true);
929
+ return NULL;
930
+ }
931
+ break;
932
+ case 0:
933
+ break;
934
+ default:
935
+ {
936
+ // if (_iter->limit() == 0xa && check == 0x0)
937
+ // {
938
+ // while(!_iter->atEnd())
939
+ // _iter->readChar();
940
+ // HACK HACK - valid end of file, in bizarro CCP land?
941
+ // return;
942
+ // }
943
+ std::stringstream msg;
944
+ msg << "Can't identify type 0x" << std::hex << static_cast<unsigned int>(check)
945
+ << " at position 0x" << _iter->position() << " limit " << _iter->limit();
946
+ throw ParseException(msg.str());
947
+ }
948
+ }
949
+
950
+ if (!thisobj) {
951
+ throw ParseException("no thisobj in parseone");
952
+ }
953
+
954
+ if (isshared) {
955
+ if (!thisobj) {
956
+ throw ParseException("shared flag but no obj");
957
+ }
958
+ try {
959
+ shareAdd(thisobj);
960
+ } catch (ParseException &e) {
961
+ delete thisobj;
962
+ throw e;
963
+ }
964
+
965
+ }
966
+
967
+ return thisobj;
968
+ }
969
+
970
+ void Parser::parse(SNode* stream, int limit)
971
+ {
972
+ while (!_iter->atEnd() && limit != 0)
973
+ {
974
+ SNode *thisobj = parseone();
975
+ if (thisobj) {
976
+ stream->addMember(thisobj);
977
+ }
978
+ limit -= 1;
979
+ }
980
+
981
+ }
982
+
983
+ void Parser::parse()
984
+ {
985
+
986
+ try {
987
+ while(!_iter->atEnd()) {
988
+ char check = _iter->readChar();
989
+ SNode* stream = new SNode(EStreamStart);
990
+
991
+ if (check != EStreamStart) {
992
+ delete stream;
993
+ //throw ParseException("No stream start detected...");
994
+ continue;
995
+ }
996
+
997
+ _streams.push_back(stream);
998
+ shareInit();
999
+ parse(stream, 1); // -1 = not sure how long this will be
1000
+
1001
+ shareSkip();
1002
+ }
1003
+ } catch (EndOfFileException &e) {
1004
+ // Ignore the exception, parser has run amok!
1005
+ }
1006
+ }
1007
+
1008
+ SNode* Parser::getDBRow()
1009
+ {
1010
+ SNode *nhead = parseone();
1011
+ // get header
1012
+ SObject* head = dynamic_cast<SObject*>(nhead);
1013
+ if (head == NULL) {
1014
+ delete nhead;
1015
+ throw ParseException("The DBRow header isn't present...");
1016
+ }
1017
+
1018
+ if (head->name().compare("blue.DBRowDescriptor")) {
1019
+ delete head;
1020
+ throw ParseException("bad descriptor name");
1021
+ }
1022
+
1023
+ STuple* fields = dynamic_cast<STuple*>(head->members()[0]->members()[1]->members()[0]);
1024
+ //std::cerr << "DBRow: fields: " << fields << " == " << fields->repl() << ", size " << static_cast<unsigned int>(fields->members().size()) << std::endl;
1025
+
1026
+ unsigned int len = getLen();
1027
+ std::string compdata = _iter->readString(len);
1028
+ const unsigned char* olddata = reinterpret_cast<const unsigned char*>
1029
+ (compdata.c_str());
1030
+
1031
+ std::vector<unsigned char> newdata;
1032
+ rle_unpack(olddata, len, newdata);
1033
+ SNode* body = new SDBRow(17, newdata);
1034
+
1035
+ CacheFile cF(newdata);
1036
+ CacheFile_Iterator blob = cF.begin();
1037
+
1038
+ SDict *dict = new SDict(999999); // TODO: need dynamic sized dict
1039
+ int step = 1;
1040
+ while (step < 6)
1041
+ {
1042
+ std::vector<SNode*>::const_iterator vi = fields->members().begin();
1043
+
1044
+ for (; vi != fields->members().end(); ++vi)
1045
+ {
1046
+ SNode *fn = (*vi)->members()[0]->clone();
1047
+ SInt *ft = (SInt*)(*vi)->members()[1];
1048
+ int fti = ft->value();
1049
+
1050
+ //std::cerr << "DBRow: step " << step << ", type " << fti << ", name " << fn->repl() << std::endl;
1051
+
1052
+ unsigned char boolcount=0;
1053
+ unsigned char boolbuf=0;
1054
+ SNode *obj=NULL;
1055
+ switch(fti) {
1056
+ case 21:
1057
+ case 20: if (step == 1) // 64bit int
1058
+ {
1059
+ long long val = blob.readLongLong();
1060
+ obj = new SLongLong(val);
1061
+ }
1062
+ break;
1063
+ case 6: if (step == 1) // currency
1064
+ {
1065
+ long long val = blob.readLongLong();
1066
+ obj = new SLongLong(val);
1067
+ }
1068
+ break;
1069
+ case 64: if (step == 1) // timestamp
1070
+ {
1071
+ long long val = blob.readLongLong();
1072
+ obj = new SLongLong(val);
1073
+ }
1074
+ break;
1075
+ case 5: if (step == 1) // double
1076
+ {
1077
+ double val = blob.readDouble();
1078
+ obj = new SReal(val);
1079
+ }
1080
+ break;
1081
+ case 4:
1082
+ {
1083
+ double val = blob.readFloat();
1084
+ obj = new SReal(val);
1085
+ }
1086
+ break;
1087
+ case 19:
1088
+ case 3: if (step == 2) // 32bit int
1089
+ {
1090
+ int val = blob.readInt();
1091
+ obj = new SInt(val);
1092
+ }
1093
+ break;
1094
+ case 18:
1095
+ case 2: if (step == 3) // 16bit int
1096
+ {
1097
+ int val = blob.readShort();
1098
+ obj = new SInt(val);
1099
+ }
1100
+ break;
1101
+ case 17:
1102
+ case 16:
1103
+ {
1104
+ int val = blob.readChar();
1105
+ obj = new SInt(val);
1106
+ }
1107
+ break;
1108
+ case 11: if (step == 5) // boolean
1109
+ {
1110
+ if (!boolcount) {
1111
+ boolbuf = blob.readChar();
1112
+ //std::cerr << "Boolbuf" << (int)boolbuf << std::endl;
1113
+ boolcount = 0x1;
1114
+ }
1115
+ if (boolbuf & boolcount) {
1116
+ obj = new SInt(1);
1117
+ } else {
1118
+ obj = new SInt(0);
1119
+ }
1120
+ boolcount <<= 1;
1121
+ }
1122
+ break;
1123
+ case 129: // String types
1124
+ case 128:
1125
+ case 130:
1126
+ {
1127
+ obj = new SString("I can't parse strings yet - be patient");
1128
+ }
1129
+ break;
1130
+ default:
1131
+ {
1132
+ if (obj != NULL)
1133
+ delete obj;
1134
+ delete fn;
1135
+ delete body;
1136
+ delete head;
1137
+ delete dict;
1138
+ std::stringstream ss;
1139
+ ss << "Unhandled ADO type " << fti;
1140
+ throw ParseException(ss.str());
1141
+ }
1142
+ }
1143
+ if (obj) {
1144
+ dict->addMember(obj);
1145
+ dict->addMember(fn);
1146
+ } else {
1147
+ delete fn;
1148
+ }
1149
+ }
1150
+
1151
+ step++;
1152
+
1153
+ }
1154
+
1155
+
1156
+ SNode* fakerow = new STuple(3);
1157
+ fakerow->addMember(head);
1158
+ fakerow->addMember(body);
1159
+ fakerow->addMember(dict);
1160
+ return fakerow;
1161
+ }
1162
+
1163
+ unsigned int Parser::shareInit()
1164
+ {
1165
+ unsigned int shares = _iter->readInt();
1166
+ if (shares >= 16384) // Some large number
1167
+ return 0;
1168
+
1169
+ unsigned int shareskip = 0;
1170
+ if (shares) {
1171
+ _sharemap = new unsigned int[shares+1];
1172
+ _shareobj = new SNode*[shares+1];
1173
+
1174
+ shareskip = 4 * shares;
1175
+ unsigned int opos = _iter->position();
1176
+ unsigned int olim = _iter->limit();
1177
+ _iter->seek(opos + olim - shareskip);
1178
+ unsigned int i;
1179
+ for (i=0; i < shares; i++) {
1180
+ _sharemap[i] = _iter->readInt();
1181
+ _shareobj[i] = NULL;
1182
+ }
1183
+ _shareobj[shares] = NULL;
1184
+ _sharemap[shares] = 0;
1185
+
1186
+ _iter->seek(opos);
1187
+ _iter->setLimit(olim - shareskip);
1188
+ }
1189
+ _sharecount = shares;
1190
+ return shares;
1191
+ }
1192
+
1193
+ void Parser::shareAdd(SNode *obj)
1194
+ {
1195
+ if (_sharemap == NULL || _shareobj == NULL)
1196
+ throw ParseException("Uninitialized share");
1197
+ if (_sharecursor >= _sharecount)
1198
+ throw ParseException("cursor out of range");
1199
+ unsigned int shareid = _sharemap[_sharecursor];
1200
+ if (shareid > _sharecount)
1201
+ throw ParseException("shareid out of range");
1202
+
1203
+ /** This is bad, but a memory leak fix until the sharetab support is better */
1204
+ if (_shareobj[shareid] != NULL) {
1205
+ //throw ParseException("already have obj");
1206
+ delete _shareobj[shareid];
1207
+ }
1208
+ _shareobj[shareid] = obj->clone();
1209
+
1210
+ _sharecursor++;
1211
+ }
1212
+
1213
+ SNode* Parser::shareGet(unsigned int id)
1214
+ {
1215
+ if (id > _sharecount) {
1216
+ std::stringstream ss;
1217
+ ss << "ShareID out of range " << id << " > " << _sharecount;
1218
+ throw ParseException(ss.str());
1219
+ }
1220
+
1221
+ if (_shareobj[id] == NULL) {
1222
+ std::stringstream ss;
1223
+ ss << "ShareTab: No entry at position " << id;
1224
+ throw ParseException(ss.str());
1225
+ }
1226
+
1227
+ return _shareobj[id]->clone();
1228
+ }
1229
+
1230
+ void Parser::shareSkip()
1231
+ {
1232
+ _iter->advance(_sharecount*4);
1233
+ }
1234
+
1235
+ int Parser::getLen()
1236
+ {
1237
+ unsigned int len = _iter->readChar();
1238
+ if ((len & 0xff) == 0xFF)
1239
+ len = _iter->readInt();
1240
+ return len;
1241
+ }
1242
+
1243
+ std::vector<SNode*> Parser::streams() const
1244
+ {
1245
+ return _streams;
1246
+ }
1247
+
1248
+
1249
+ };