evecache 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ };