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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/README.txt +24 -0
- data/Rakefile +5 -0
- data/evecache.gemspec +16 -0
- data/ext/evecache/Makefile +237 -0
- data/ext/evecache/dbtypes.cpp +237 -0
- data/ext/evecache/evecache.cxx +16354 -0
- data/ext/evecache/evecache/config.hpp +19 -0
- data/ext/evecache/evecache/dbtypes.hpp +64 -0
- data/ext/evecache/evecache/exceptions.hpp +47 -0
- data/ext/evecache/evecache/market.hpp +166 -0
- data/ext/evecache/evecache/parser.hpp +316 -0
- data/ext/evecache/evecache/reader.hpp +110 -0
- data/ext/evecache/exceptions.cpp +46 -0
- data/ext/evecache/extconf.rb +8 -0
- data/ext/evecache/libevecache.i +431 -0
- data/ext/evecache/market.cpp +325 -0
- data/ext/evecache/parser.cpp +1249 -0
- data/ext/evecache/reader.cpp +322 -0
- data/lib/evecache.rb +83 -0
- data/test/test_evecache.rb +7 -0
- metadata +67 -0
@@ -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
|
+
};
|