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
};