Subversion Repositories tpanel

Rev

Rev 480 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 andreas 1
/*
486 andreas 2
 * Copyright (C) 2022 to 2025 by Andreas Theofilu <andreas@theosys.at>
446 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program 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
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <fstream>
20
#include <iomanip>
21
 
22
#include <string.h>
23
 
24
#include "texpat++.h"
25
#include "terror.h"
26
 
27
using namespace Expat;
28
using std::string;
29
using std::vector;
30
using std::ifstream;
31
 
32
int TExpat::mDepth = 0;
33
string TExpat::mContent;
34
string TExpat::mLastName;
35
vector<_ATTRIBUTE_t> TExpat::mAttributes;
36
 
37
TExpat::TExpat()
38
{
39
    DECL_TRACER("TExpat::TExpat()");
40
}
41
 
42
TExpat::TExpat(const std::string &file)
43
    : mFile(file)
44
{
45
    DECL_TRACER("TExpat::TExpat(const std::string &file)");
46
 
47
    mLastIter = mElements.end();
48
}
49
 
50
TExpat::~TExpat()
51
{
52
    DECL_TRACER("TExpat::~TExpat()");
53
}
54
 
55
void TExpat::setEncoding(TENCODING_t enc)
56
{
57
    DECL_TRACER("TExpat::setEncoding(TENCODING_t enc)");
58
 
59
    mSetEncoding = enc;
60
 
61
    switch(enc)
62
    {
63
        case ENC_ISO_8859_1:    mEncoding = "ISO-8859-1"; break;
64
        case ENC_US_ASCII:      mEncoding = "US-ASCII"; break;
65
        case ENC_UTF16:         mEncoding = "UTF-16"; break;
66
        case ENC_CP1250:        mEncoding = "CP1250"; break;
67
 
68
        default:
69
            mEncoding = "UTF-8";
70
            mSetEncoding = ENC_UTF8;
71
    }
72
}
73
 
74
bool TExpat::parse(bool debug)
75
{
76
    DECL_TRACER("TExpat::parse()");
77
 
78
    if (!isValidFile(mFile))
79
    {
80
        MSG_ERROR("Invalid file: " << mFile);
81
        TError::setError();
82
        return false;
83
    }
84
 
85
    string buf;
86
    size_t size = 0;
87
 
88
    // First we read the whole XML file into a buffer
89
    try
90
    {
91
        ifstream stream(mFile, std::ios::in);
92
 
93
        if (!stream || !stream.is_open())
94
            return false;
95
 
96
        stream.seekg(0, stream.end);    // Find the end of the file
97
        size = stream.tellg();          // Get the position and save it
98
        stream.seekg(0, stream.beg);    // rewind to the beginning of the file
99
 
100
        buf.resize(size, '\0');         // Initialize the buffer with zeros
101
        char *begin = &*buf.begin();    // Assign the plain data buffer
102
        stream.read(begin, size);       // Read the whole file
103
        stream.close();                 // Close the file
104
    }
105
    catch (std::exception& e)
106
    {
107
        MSG_ERROR("File error: " << e.what());
108
        TError::setError();
109
        return false;
110
    }
111
 
112
    // Now we parse the file and write the relevant contents into our internal
113
    // variables.
114
    // First we initialialize the parser.
115
    int done = 1;   // 1 = Buffer is complete
116
    XML_Parser parser = XML_ParserCreate(NULL);
117
    XML_SetElementHandler(parser, &TExpat::startElement, &TExpat::endElement);
118
    XML_SetCharacterDataHandler(parser, &TExpat::CharacterDataHandler);
119
    XML_SetEncoding(parser, mEncoding.c_str());
120
    XML_SetUserData(parser, &mElements);
121
 
122
    if (mSetEncoding == ENC_CP1250)
123
        XML_SetUnknownEncodingHandler(parser, &TExpat::cp1250_encoding_handler, NULL);
124
 
125
    MSG_TRACE("Parsing XML file " << mFile);
126
 
127
    if (XML_Parse(parser, buf.data(), size, done) == XML_STATUS_ERROR)
128
    {
129
        MSG_ERROR(XML_ErrorString(XML_GetErrorCode(parser)) << " at line " << XML_GetCurrentLineNumber(parser));
130
        XML_ParserFree(parser);
131
        TError::setError();
132
        return false;
133
    }
134
 
135
    XML_ParserFree(parser);
136
 
137
    if (TStreamError::checkFilter(HLOG_DEBUG) && debug && mElements.size() > 0)
138
    {
139
        // Print out the whole XML file formatted
140
        vector<_ELEMENT_t>::iterator iter;
141
        size_t cnt = 0;
142
 
143
        for (iter = mElements.begin(); iter != mElements.end(); ++iter)
144
        {
145
            string sIndent;
146
 
147
            for (int i = 0; i < iter->depth; i++)
148
                sIndent += "   ";
149
 
150
            string attrs;
151
 
152
            if ((iter->eType == _ET_START || iter->eType == _ET_ATOMIC) && iter->attrs.size() > 0)
153
            {
154
                vector<ATTRIBUTE_t>::iterator atiter;
155
 
156
                for (atiter = iter->attrs.begin(); atiter != iter->attrs.end(); ++atiter)
157
                {
158
                    if (!attrs.empty())
159
                        attrs += " ";
160
 
161
                    attrs += atiter->name + " = \"" + atiter->content + "\"";
162
                }
163
            }
164
 
165
            if (iter->eType == _ET_START)
166
            {
167
                if (iter->attrs.size() > 0)
168
                {
169
                    MSG_DEBUG(std::setw(3) << std::setfill(' ') << "[" << cnt << "] (" << std::setw(0) << iter->depth << ") " << sIndent << "<" << iter->name << " " << attrs << ">");
170
                }
171
                else
172
                {
173
                    MSG_DEBUG(std::setw(3) << std::setfill(' ') << "[" << cnt << "] (" << std::setw(0) << iter->depth << ") " << sIndent << "<" << iter->name << ">");
174
                }
175
            }
176
            else if (iter->eType == _ET_ATOMIC)
177
            {
178
                if (iter->attrs.size() > 0)
179
                {
180
                    MSG_DEBUG(std::setw(3) << std::setfill(' ') << "[" << cnt << "] (" << std::setw(0) << iter->depth << ") " << sIndent << "<" << iter->name << " " << attrs << ">" << iter->content << "</" << iter->name << ">");
181
                }
182
                else
183
                {
184
                    MSG_DEBUG(std::setw(3) << std::setfill(' ') << "[" << cnt << "] (" << std::setw(0) << iter->depth << ") " << sIndent << "<" << iter->name << ">" << iter->content << "</" << iter->name << ">");
185
                }
186
            }
187
            else
188
            {
189
                MSG_DEBUG(std::setw(3) << std::setfill(' ') << "[" << cnt << "] (" << std::setw(0) << iter->depth << ") " << sIndent << "</" << iter->name << ">");
190
            }
191
 
192
            cnt++;
193
        }
194
    }
195
 
196
    return true;
197
}
198
 
199
string TExpat::getElement(const string &name, int depth, bool *valid)
200
{
201
    DECL_TRACER("TExpat::getElement(const string &name, int depth)");
202
 
203
    vector<_ELEMENT_t>::iterator iter, startElement;
204
    bool start = false;
205
 
206
    if (!mElements.empty() && mLastIter != mElements.end())
207
        startElement = mLastIter;
208
    else if (!mElements.empty())
209
        startElement = mElements.begin();
210
    else
211
    {
212
        MSG_DEBUG("Have no elements in queue!");
213
 
214
        if (valid)
215
            *valid = false;
216
 
217
        return string();
218
    }
219
 
220
    for (iter = startElement; iter != mElements.end(); ++iter)
221
    {
222
        if (!start && iter->depth == depth && iter->eType != _ET_END)
223
            start = true;
224
 
225
        if (start && iter->eType != _ET_END && iter->name.compare(name)  == 0 && iter->depth == depth)
226
        {
227
            if (valid)
228
                *valid = true;
229
 
230
            return iter->content;
231
        }
232
        else if (start && (iter->eType == _ET_END || iter->depth != depth))
233
            break;
234
    }
235
 
236
    if (valid)
237
        *valid = false;
238
 
239
    return string();
240
}
241
 
242
int TExpat::getElementInt(const string &name, int depth, bool *valid)
243
{
244
    DECL_TRACER("TExpat::getElementInt(const string &name, int depth, bool *valid)");
245
 
246
    bool val;
247
    string erg = getElement(name, depth, &val);
248
 
249
    if (valid)
250
        *valid = val;
251
 
252
    if (!val)
253
        return 0;
254
 
255
    return atoi(erg.c_str());
256
}
257
 
258
long TExpat::getElementLong(const string &name, int depth, bool *valid)
259
{
260
    DECL_TRACER("TExpat::getElementLong(const string &name, int depth, bool *valid)");
261
 
262
    bool val;
263
    string erg = getElement(name, depth, &val);
264
 
265
    if (valid)
266
        *valid = val;
267
 
268
    if (!val)
269
        return 0;
270
 
271
    return atol(erg.c_str());
272
}
273
 
274
float TExpat::getElementFloat(const string &name, int depth, bool *valid)
275
{
276
    DECL_TRACER("TExpat::getElementFloat(const string &name, int depth, bool *valid)");
277
 
278
    bool val;
279
    string erg = getElement(name, depth, &val);
280
 
281
    if (valid)
282
        *valid = val;
283
 
284
    if (!val)
285
        return 0;
286
 
287
    return (float)atof(erg.c_str());
288
}
289
 
290
double TExpat::getElementDouble(const string &name, int depth, bool *valid)
291
{
292
    DECL_TRACER("TExpat::getElementDouble(const string &name, int depth, bool *valid)");
293
 
294
    bool val = false;
295
    string erg = getElement(name, depth, &val);
296
 
297
    if (valid)
298
        *valid = val;
299
 
300
    if (!val)
301
        return 0;
302
 
303
    return atof(erg.c_str());
304
}
305
 
306
size_t TExpat::getElementIndex(const string& name, int depth)
307
{
308
    DECL_TRACER("TExpat::getElementIndex(const string& name, int depth)");
309
 
310
    vector<_ELEMENT_t>::iterator iter;
311
    size_t idx = 0;
312
 
313
    if (mElements.size() == 0)
314
    {
315
        mLastIter = mElements.end();
316
        return npos;
317
    }
318
 
319
    for (iter = mElements.begin(); iter != mElements.end(); ++iter)
320
    {
321
        if (iter->eType != _ET_END && iter->name.compare(name) == 0 && iter->depth == depth)
322
        {
323
            mLastIter = iter;
324
            return idx;
325
        }
326
 
327
        idx++;
328
    }
329
 
330
    mLastIter = mElements.end();
331
    return npos;
332
}
333
 
334
size_t TExpat::getElementIndex(const string& name, int* depth)
335
{
336
    DECL_TRACER("TExpat::getElementIndex(const string& name, int* depth)");
337
 
338
    if (mElements.size() == 0)
339
    {
340
        mLastIter = mElements.end();
341
        return npos;
342
    }
343
 
344
    vector<_ELEMENT_t>::iterator iter;
345
    size_t idx = 0;
346
 
347
    for (iter = mElements.begin(); iter != mElements.end(); ++iter)
348
    {
349
        if (iter->eType != _ET_END && iter->name.compare(name) == 0)
350
        {
351
            if (depth)
352
                *depth = iter->depth;
353
 
354
            mLastIter = iter;
355
            return idx;
356
        }
357
 
358
        idx++;
359
    }
360
 
361
    if (depth)
362
        *depth = -1;
363
 
364
    mLastIter = mElements.end();
365
    return npos;
366
}
367
 
368
size_t TExpat::getElementFromIndex(size_t index, string* name, string* content, vector<ATTRIBUTE_t> *attrs)
369
{
370
    DECL_TRACER("TExpat::getElementFromIndex(size_t index, string* name, string* content, vector<ATTRIBUTE_t> *attrs)");
371
 
372
    if (index == npos || index >= mElements.size() || mElements.at(index).eType == _ET_END)
373
        return npos;
374
 
375
    if (name)
376
        name->assign(mElements.at(index).name);
377
 
378
    if (content)
379
        content->assign(mElements.at(index).content);
380
 
381
    if (attrs)
382
        *attrs = mElements.at(index).attrs;
383
 
384
    return index;
385
}
386
 
387
size_t TExpat::getNextElementFromIndex(size_t index, string* name, string* content, vector<ATTRIBUTE_t>* attrs)
388
{
389
    DECL_TRACER("TExpat::getNextElementFromIndex(size_t index, int depth, string* name, string* content, vector<ATTRIBUTE_t>* attrs)");
390
 
391
    if (index == npos)
392
        return npos;
393
 
394
    size_t idx = index + 1;
395
 
396
    if (idx >= mElements.size() || mElements.at(idx).eType == _ET_END)
397
        return npos;
398
 
399
    if (name)
400
        name->assign(mElements.at(idx).name);
401
 
402
    if (content)
403
        content->assign(mElements.at(idx).content);
404
 
405
    if (attrs)
406
        *attrs = mElements.at(idx).attrs;
407
 
408
    return idx;
409
}
410
 
411
string TExpat::getFirstElement(const string &name, int *depth)
412
{
413
    DECL_TRACER("TExpat::getFirstElement(const string &name, int *depth)");
414
 
415
    vector<_ELEMENT_t>::iterator iter;
416
 
417
    for (iter = mElements.begin(); iter != mElements.end(); ++iter)
418
    {
419
        if (iter->eType != _ET_END && iter->name.compare(name) == 0)
420
        {
421
            if (depth)
422
                *depth = iter->depth;
423
 
424
            mLastIter = iter;
425
            return iter->content;
426
        }
427
    }
428
 
429
    if (depth)
430
        *depth = -1;
431
 
432
    mLastIter = mElements.end();
433
    return string();
434
}
435
 
436
string TExpat::getNextElement(const string &name, int depth, bool *valid)
437
{
438
    DECL_TRACER("TExpat::getNextElement(const string &name, int depth)");
439
 
440
    if (valid)
441
        *valid = false;
442
 
443
    if (mLastIter == mElements.end())
444
        return string();
445
 
446
    mLastIter++;
447
 
448
    while (mLastIter != mElements.end())
449
    {
450
        if (mLastIter == mElements.end() || mLastIter->eType == _ET_END)
451
            return string();
452
 
453
        if (mLastIter->name.compare(name) == 0 && mLastIter->depth == depth)
454
        {
455
            if (valid)
456
                *valid = true;
457
 
458
            return mLastIter->content;
459
        }
460
 
461
        mLastIter++;
462
    }
463
 
464
    return string();
465
}
466
 
467
size_t TExpat::getNextElementIndex(const string& name, int depth)
468
{
469
    DECL_TRACER("TExpat::getNextElementIndex(const string& name, int depth)");
470
 
471
    if (mLastIter == mElements.end())
472
        return npos;
473
 
474
    mLastIter++;
475
 
476
    while (mLastIter != mElements.end())
477
    {
478
        if (mLastIter->eType == _ET_END && mLastIter->depth < depth)
479
            break;
480
 
481
        if (mLastIter->name.compare(name)  == 0 && mLastIter->depth == depth && mLastIter->eType != _ET_END)
482
        {
483
            size_t idx = 0;
484
            vector<_ELEMENT_t>::iterator iter;
485
 
486
            for (iter = mElements.begin(); iter != mElements.end(); ++iter)
487
            {
488
                if (iter == mLastIter)
489
                    return idx;
490
 
491
                idx++;
492
            }
493
        }
494
 
495
        mLastIter++;
496
    }
497
 
498
    return npos;
499
}
500
 
501
string TExpat::getAttribute(const string& name, vector<ATTRIBUTE_t>& attrs)
502
{
503
    DECL_TRACER("TExpat::getAttribute(const string& name, vector<ATTRIBUTE_t>& attrs)");
504
 
505
    vector<ATTRIBUTE_t>::iterator iter;
506
 
507
    if (attrs.size() == 0)
508
        return string();
509
 
510
    for (iter = attrs.begin(); iter != attrs.end(); ++iter)
511
    {
512
        if (iter->name.compare(name) == 0)
513
            return iter->content;
514
    }
515
 
516
    return string();
517
}
518
 
480 andreas 519
bool TExpat::getAttributeBool(const string& name, vector<ATTRIBUTE_t>& attrs)
520
{
521
    DECL_TRACER("TExpat::getAttributeBool(const string& name, vector<ATTRIBUTE_t>& attrs)");
522
 
523
    string b = getAttribute(name, attrs);
524
 
525
    if (b == "true" || b == "True" || b == "TRUE")
526
        return true;
527
 
528
    return false;
529
}
530
 
446 andreas 531
int TExpat::getAttributeInt(const string& name, vector<ATTRIBUTE_t>& attrs)
532
{
533
    DECL_TRACER("TExpat::getAttributeInt(const string& name, vector<ATTRIBUTE_t>& attrs)");
534
 
535
    return atoi(getAttribute(name, attrs).c_str());
536
}
537
 
538
long Expat::TExpat::getAttributeLong(const std::string& name, std::vector<ATTRIBUTE_t>& attrs)
539
{
540
    DECL_TRACER("TExpat::getAttributeLong(const string& name, vector<ATTRIBUTE_t>& attrs)");
541
 
542
    return atol(getAttribute(name, attrs).c_str());
543
}
544
 
545
float Expat::TExpat::getAttributeFloat(const std::string& name, std::vector<ATTRIBUTE_t>& attrs)
546
{
547
    DECL_TRACER("TExpat::getAttributeFloat(const string& name, vector<ATTRIBUTE_t>& attrs)");
548
 
549
    return (float)atof(getAttribute(name, attrs).c_str());
550
}
551
 
552
double Expat::TExpat::getAttributeDouble(const std::string& name, std::vector<ATTRIBUTE_t>& attrs)
553
{
554
    DECL_TRACER("TExpat::getAttributeDouble(const string& name, vector<ATTRIBUTE_t>& attrs)");
555
 
556
    return atof(getAttribute(name, attrs).c_str());
557
}
558
 
486 andreas 559
bool TExpat::convertElementToBool(const string& content, bool def)
480 andreas 560
{
486 andreas 561
    DECL_TRACER("TExpat::convertElementToBool(const string& content, bool def)");
480 andreas 562
 
486 andreas 563
    if (content == "true" || content == "True" || content == "TRUE" || content == "1")
480 andreas 564
        return true;
565
 
486 andreas 566
    return def;
480 andreas 567
}
568
 
486 andreas 569
int TExpat::convertElementToInt(const string& content, int def)
446 andreas 570
{
486 andreas 571
    DECL_TRACER("TExpat::convertElementToInt(const string& content, int def)");
446 andreas 572
 
573
    if (content.empty())
574
    {
486 andreas 575
        MSG_WARNING("Error converting to INT: Empty content");
576
        return def;
446 andreas 577
    }
578
 
579
    return atoi(content.c_str());
580
}
581
 
486 andreas 582
long TExpat::convertElementToLong(const string& content, long def)
446 andreas 583
{
486 andreas 584
    DECL_TRACER("TExpat::convertElementToLong(const string& content, long def)");
446 andreas 585
 
586
    if (content.empty())
587
    {
486 andreas 588
        MSG_WARNING("Error converting to LONG: Empty content");
589
        return def;
446 andreas 590
    }
591
 
592
    return atol(content.c_str());
593
}
594
 
486 andreas 595
float TExpat::convertElementToFloat(const string& content, float def)
446 andreas 596
{
486 andreas 597
    DECL_TRACER("TExpat::convertElementToFloat(const string& content, float def)");
446 andreas 598
 
599
    if (content.empty())
600
    {
486 andreas 601
        MSG_WARNING("Error converting to FLOAT: Empty content");
602
        return def;
446 andreas 603
    }
604
 
486 andreas 605
    return static_cast<float>(atof(content.c_str()));
446 andreas 606
}
607
 
486 andreas 608
double TExpat::convertElementToDouble(const string& content, double def)
446 andreas 609
{
486 andreas 610
    DECL_TRACER("TExpat::convertElementToDouble(const string& content, double def)");
446 andreas 611
 
612
    if (content.empty())
613
    {
486 andreas 614
        MSG_WARNING("Error converting to DOUBLE: Empty content");
615
        return def;
446 andreas 616
    }
617
 
618
    return atof(content.c_str());
619
}
620
 
621
bool TExpat::setIndex(size_t index)
622
{
623
    DECL_TRACER("TExpat::setIndex(size_t index)");
624
 
625
    if (index >= mElements.size())
626
    {
486 andreas 627
        MSG_ERROR("Error setting index: Invalid index " << index);
446 andreas 628
        TError::setErrorMsg("Invalid index " + std::to_string(index) + "!");
629
        mLastIter = mElements.end();
630
        return false;
631
    }
632
 
633
    vector<_ELEMENT_t>::iterator iter;
634
    size_t idx = 0;
635
 
636
    for (iter = mElements.begin(); iter != mElements.end(); ++iter)
637
    {
638
        if (idx == index)
639
        {
640
            mLastIter = iter;
641
            return true;
642
        }
643
 
644
        idx++;
645
    }
646
 
647
    mLastIter = mElements.end();
648
    return false;   // Should not happen and is just for satisfy the compiler.
649
}
650
 
651
vector<ATTRIBUTE_t> TExpat::getAttributes()
652
{
653
    DECL_TRACER("TExpat::getAttributes()");
654
 
655
    if (mLastIter == mElements.end())
656
        return vector<ATTRIBUTE_t>();
657
 
658
    return mLastIter->attrs;
659
}
660
 
661
vector<ATTRIBUTE_t> TExpat::getAttributes(size_t index)
662
{
663
    DECL_TRACER("TExpat::getAttributes(size_t index)");
664
 
665
    if (index >= mElements.size())
666
        return vector<ATTRIBUTE_t>();
667
 
668
    return mElements.at(index).attrs;
669
}
670
 
486 andreas 671
bool TExpat::isElementTypeStart(size_t index)
672
{
673
    DECL_TRACER("TExpat::isElementTypeStart(size_t index)");
674
 
675
    if (index >= mElements.size() || mElements.at(index).eType != _ET_START)
676
        return false;
677
 
678
    return true;
679
}
680
 
681
bool TExpat::isElementTypeEnd(size_t index)
682
{
683
    DECL_TRACER("TExpat::isElementTypeEnd(size_t index)");
684
 
685
    if (index >= mElements.size() || mElements.at(index).eType == _ET_END)
686
        return true;
687
 
688
    return false;
689
}
690
 
691
bool TExpat::isElementTypeAtomic(size_t index)
692
{
693
    DECL_TRACER("TExpat::isElementTypeAtomic(size_t index)");
694
 
695
    if (index >= mElements.size() || mElements.at(index).eType != _ET_ATOMIC)
696
        return false;
697
 
698
    return true;
699
}
700
 
701
_ETYPE_t TExpat::getElementType(size_t index)
702
{
703
    DECL_TRACER("TExpat::getElementType(size_t index)");
704
 
705
    if (index >= mElements.size())
706
        return _ET_END;
707
 
708
    return mElements.at(index).eType;
709
}
710
 
711
string TExpat::getElementTypeStr(size_t index)
712
{
713
    DECL_TRACER("TExpat::getElementTypeStr(size_t index)");
714
 
715
    if (index >= mElements.size())
716
        return "END";
717
 
718
    switch(mElements.at(index).eType)
719
    {
720
        case _ET_START:     return "START";
721
        case _ET_END:       return "END";
722
        case _ET_ATOMIC:    return "ATOMIC";
723
    }
724
 
725
    // Should not come here but needed to satisfy the compiler.
726
    return "END";
727
}
728
 
446 andreas 729
string TExpat::getElementName(bool *valid)
730
{
731
    DECL_TRACER("TExpat::getElementName()");
732
 
733
    if (mLastIter != mElements.end())
734
    {
735
        if (valid)
736
            *valid = true;
737
 
738
        return mLastIter->name;
739
    }
740
 
741
    if (valid)
742
        *valid = false;
743
 
744
    return string();
745
}
746
 
747
string TExpat::getElementContent(bool *valid)
748
{
749
    DECL_TRACER("TExpat::getElementContent()");
750
 
751
    if (mLastIter != mElements.end())
752
    {
753
        if (valid)
754
            *valid = true;
755
 
756
        return mLastIter->content;
757
    }
758
 
759
    if (valid)
760
        *valid = false;
761
 
762
    return string();
763
}
764
 
765
int TExpat::getElementContentInt(bool *valid)
766
{
767
    DECL_TRACER("TExpat::getElementContentInt(bool *valid)");
768
 
769
    if (mLastIter != mElements.end())
770
    {
771
        if (valid)
772
            *valid = true;
773
 
774
        return atoi(mLastIter->content.c_str());
775
    }
776
 
777
    if (valid)
778
        *valid = false;
779
 
780
    return 0;
781
}
782
 
783
long TExpat::getElementContentLong(bool *valid)
784
{
785
    DECL_TRACER("TExpat::getElementContentLong(bool *valid)");
786
 
787
    if (mLastIter != mElements.end())
788
    {
789
        if (valid)
790
            *valid = true;
791
 
792
        return atol(mLastIter->content.c_str());
793
    }
794
 
795
    if (valid)
796
        *valid = false;
797
 
798
    return 0;
799
}
800
 
801
float TExpat::getElementContentFloat(bool *valid)
802
{
803
    DECL_TRACER("TExpat::getElementContentFloat(bool *valid)");
804
 
805
    if (mLastIter != mElements.end())
806
    {
807
        if (valid)
808
            *valid = true;
809
 
810
        return (float)atof(mLastIter->content.c_str());
811
    }
812
 
813
    if (valid)
814
        *valid = false;
815
 
816
    return 0.0;
817
}
818
 
819
double TExpat::getElementContentDouble(bool *valid)
820
{
821
    DECL_TRACER("TExpat::getElementContentDouble(bool *valid)");
822
 
823
    if (mLastIter != mElements.end())
824
    {
825
        if (valid)
826
            *valid = true;
827
 
828
        return atof(mLastIter->content.c_str());
829
    }
830
 
831
    if (valid)
832
        *valid = false;
833
 
834
    return 0.0;
835
}
836
 
837
/******************************************************************************
838
 *                        Static methods starting here
839
 ******************************************************************************/
840
 
841
void TExpat::createCP1250Encoding(XML_Encoding* enc)
842
{
843
    if (!enc)
844
        return;
845
 
846
    for (int i = 0; i < 0x0100; i++)
847
    {
848
        if (i < 0x007f)
849
            enc->map[i] = i;
850
        else
851
        {
852
            switch(i)
853
            {
854
                case 0x080: enc->map[i] = 0x20AC; break;
855
                case 0x082: enc->map[i] = 0x201A; break;
856
                case 0x083: enc->map[i] = 0x0192; break;
857
                case 0x084: enc->map[i] = 0x201E; break;
858
                case 0x085: enc->map[i] = 0x2026; break;
859
                case 0x086: enc->map[i] = 0x2020; break;
860
                case 0x087: enc->map[i] = 0x2021; break;
861
                case 0x088: enc->map[i] = 0x02C6; break;
862
                case 0x089: enc->map[i] = 0x2030; break;
863
                case 0x08A: enc->map[i] = 0x0160; break;
864
                case 0x08B: enc->map[i] = 0x2039; break;
865
                case 0x08C: enc->map[i] = 0x0152; break;
866
                case 0x08D: enc->map[i] = 0x00A4; break;
867
                case 0x08E: enc->map[i] = 0x017D; break;
868
                case 0x08F: enc->map[i] = 0x00B9; break;
869
                case 0x091: enc->map[i] = 0x2018; break;
870
                case 0x092: enc->map[i] = 0x2019; break;
871
                case 0x093: enc->map[i] = 0x201C; break;
872
                case 0x094: enc->map[i] = 0x201D; break;
873
                case 0x095: enc->map[i] = 0x2022; break;
874
                case 0x096: enc->map[i] = 0x2013; break;
875
                case 0x097: enc->map[i] = 0x2014; break;
876
                case 0x098: enc->map[i] = 0x02DC; break;
877
                case 0x099: enc->map[i] = 0x2122; break;
878
                case 0x09A: enc->map[i] = 0x0161; break;
879
                case 0x09B: enc->map[i] = 0x203A; break;
880
                case 0x09C: enc->map[i] = 0x0153; break;
881
                case 0x09D: enc->map[i] = 0x00A5; break;
882
                case 0x09E: enc->map[i] = 0x017E; break;
883
                case 0x09F: enc->map[i] = 0x0178; break;
884
                case 0x0A0: enc->map[i] = 0x02A0; break;
885
                case 0x0A1: enc->map[i] = 0x02C7; break;
886
                case 0x0A2: enc->map[i] = 0x02D8; break;
887
                case 0x0A3: enc->map[i] = 0x0141; break;
888
                case 0x0A4: enc->map[i] = 0x00A4; break;
889
                case 0x0A5: enc->map[i] = 0x0104; break;
890
                case 0x0A6: enc->map[i] = 0x00A6; break;
891
                case 0x0A7: enc->map[i] = 0x00A7; break;
892
                case 0x0A8: enc->map[i] = 0x00A8; break;
893
                case 0x0A9: enc->map[i] = 0x00A9; break;
894
                case 0x0AA: enc->map[i] = 0x015E; break;
895
                case 0x0AB: enc->map[i] = 0x00AB; break;
896
                case 0x0AC: enc->map[i] = 0x00AC; break;
897
                case 0x0AD: enc->map[i] = 0x00AD; break;
898
                case 0x0AE: enc->map[i] = 0x00AE; break;
899
                case 0x0AF: enc->map[i] = 0x017B; break;
900
                case 0x0B0: enc->map[i] = 0x00B0; break;
901
                case 0x0B1: enc->map[i] = 0x00B1; break;
902
                case 0x0B2: enc->map[i] = 0x02DB; break;
903
                case 0x0B3: enc->map[i] = 0x0142; break;
904
                case 0x0B4: enc->map[i] = 0x00B4; break;
905
                case 0x0B5: enc->map[i] = 0x00B5; break;
906
                case 0x0B6: enc->map[i] = 0x00B6; break;
907
                case 0x0B7: enc->map[i] = 0x00B7; break;
908
                case 0x0B8: enc->map[i] = 0x00B8; break;
909
                case 0x0B9: enc->map[i] = 0x0105; break;
910
                case 0x0BA: enc->map[i] = 0x015F; break;
911
                case 0x0BB: enc->map[i] = 0x00BB; break;
912
                case 0x0BC: enc->map[i] = 0x013D; break;
913
                case 0x0BD: enc->map[i] = 0x02DD; break;
914
                case 0x0BE: enc->map[i] = 0x013E; break;
915
                case 0x0BF: enc->map[i] = 0x017C; break;
916
                case 0x0C0: enc->map[i] = 0x0154; break;
917
                case 0x0C1: enc->map[i] = 0x00C1; break;
918
                case 0x0C2: enc->map[i] = 0x00C2; break;
919
                case 0x0C3: enc->map[i] = 0x0102; break;
920
                case 0x0C4: enc->map[i] = 0x00C4; break;
921
                case 0x0C5: enc->map[i] = 0x0139; break;
922
                case 0x0C6: enc->map[i] = 0x0106; break;
923
                case 0x0C7: enc->map[i] = 0x00C7; break;
924
                case 0x0C8: enc->map[i] = 0x010C; break;
925
                case 0x0C9: enc->map[i] = 0x00C9; break;
926
                case 0x0CA: enc->map[i] = 0x0118; break;
927
                case 0x0CB: enc->map[i] = 0x00CB; break;
928
                case 0x0CC: enc->map[i] = 0x00CC; break;    //0x011A
929
                case 0x0CD: enc->map[i] = 0x00CD; break;
930
                case 0x0CE: enc->map[i] = 0x00CE; break;
931
                case 0x0CF: enc->map[i] = 0x00CF; break;
932
                case 0x0D0: enc->map[i] = 0x0110; break;
933
                case 0x0D1: enc->map[i] = 0x0143; break;
934
                case 0x0D2: enc->map[i] = 0x0147; break;
935
                case 0x0D3: enc->map[i] = 0x00D3; break;
936
                case 0x0D4: enc->map[i] = 0x00D4; break;
937
                case 0x0D5: enc->map[i] = 0x0150; break;
938
                case 0x0D6: enc->map[i] = 0x00D6; break;
939
                case 0x0D7: enc->map[i] = 0x00D7; break;
940
                case 0x0D8: enc->map[i] = 0x0158; break;
941
                case 0x0D9: enc->map[i] = 0x016E; break;
942
                case 0x0DA: enc->map[i] = 0x00DA; break;
943
                case 0x0DB: enc->map[i] = 0x0170; break;
944
                case 0x0DC: enc->map[i] = 0x00DC; break;
945
                case 0x0DD: enc->map[i] = 0x00DD; break;
946
                case 0x0DE: enc->map[i] = 0x0162; break;
947
                case 0x0DF: enc->map[i] = 0x00DF; break;
948
                case 0x0E0: enc->map[i] = 0x0155; break;
949
                case 0x0E1: enc->map[i] = 0x00E1; break;
950
                case 0x0E2: enc->map[i] = 0x00E2; break;
951
                case 0x0E3: enc->map[i] = 0x0103; break;
952
                case 0x0E4: enc->map[i] = 0x00E4; break;
953
                case 0x0E5: enc->map[i] = 0x013A; break;
954
                case 0x0E6: enc->map[i] = 0x0107; break;
955
                case 0x0E7: enc->map[i] = 0x00E7; break;
956
                case 0x0E8: enc->map[i] = 0x010D; break;
957
                case 0x0E9: enc->map[i] = 0x00E9; break;
958
                case 0x0EA: enc->map[i] = 0x0119; break;
959
                case 0x0EB: enc->map[i] = 0x00EB; break;
960
                case 0x0EC: enc->map[i] = 0x011B; break;
961
                case 0x0ED: enc->map[i] = 0x00ED; break;
962
                case 0x0EE: enc->map[i] = 0x00EE; break;
963
                case 0x0EF: enc->map[i] = 0x010F; break;
964
                case 0x0F0: enc->map[i] = 0x0111; break;
965
                case 0x0F1: enc->map[i] = 0x0144; break;
966
                case 0x0F2: enc->map[i] = 0x0148; break;
967
                case 0x0F3: enc->map[i] = 0x00F3; break;
968
                case 0x0F4: enc->map[i] = 0x00F4; break;
969
                case 0x0F5: enc->map[i] = 0x0151; break;
970
                case 0x0F6: enc->map[i] = 0x00F6; break;
971
                case 0x0F7: enc->map[i] = 0x00F7; break;
972
                case 0x0F8: enc->map[i] = 0x0159; break;
973
                case 0x0F9: enc->map[i] = 0x016F; break;
974
                case 0x0FA: enc->map[i] = 0x00FA; break;
975
                case 0x0FB: enc->map[i] = 0x0171; break;
976
                case 0x0FC: enc->map[i] = 0x00FC; break;
977
                case 0x0FD: enc->map[i] = 0x00FD; break;
978
                case 0x0FE: enc->map[i] = 0x0163; break;
979
                case 0x0FF: enc->map[i] = 0x02D9; break;
980
 
981
                default:
982
                    enc->map[i] = -1;
983
            }
984
        }
985
    }
986
}
987
 
988
void TExpat::startElement(void *userData, const XML_Char *name, const XML_Char **attrs)
989
{
990
    if (!name)
991
        return;
992
 
993
    std::vector<_ELEMENT_t> *ud = (std::vector<_ELEMENT_t> *)userData;
994
    _ELEMENT_t el;
995
 
996
    mLastName.assign(name);
997
    mDepth++;
998
    mAttributes.clear();
999
    mContent.clear();
1000
 
1001
    el.depth = mDepth;
1002
    el.name = mLastName;
1003
    el.eType = _ET_START;
1004
 
1005
    if (attrs && *attrs)
1006
    {
1007
        for (int i = 0; attrs[i]; i += 2)
1008
        {
1009
            _ATTRIBUTE_t at;
1010
            at.name.assign(attrs[i]);
1011
            at.content.assign(attrs[i + 1]);
1012
            mAttributes.push_back(at);
1013
        }
1014
 
1015
        el.attrs = mAttributes;
1016
    }
1017
 
1018
    ud->push_back(el);
1019
}
1020
 
1021
void TExpat::endElement(void *userData, const XML_Char *name)
1022
{
1023
    if (!userData || !name)
1024
        return;
1025
 
1026
    std::vector<_ELEMENT_t> *ud = (std::vector<_ELEMENT_t> *)userData;
1027
 
1028
    if (mLastName.compare(name) == 0)
1029
    {
1030
        if (ud->back().depth == mDepth)
1031
        {
1032
            ud->back().eType = _ET_ATOMIC;
1033
            ud->back().content = mContent;
1034
 
1035
            mDepth--;
1036
            mLastName.clear();
1037
            mContent.clear();
1038
            return;
1039
        }
1040
    }
1041
 
1042
    _ELEMENT_t el;
1043
    el.depth = mDepth;
1044
    el.name.assign(name);
1045
    el.eType = _ET_END;
1046
    ud->push_back(el);
1047
    mDepth--;
1048
 
1049
    mLastName.clear();
1050
    mContent.clear();
1051
}
1052
 
1053
void TExpat::CharacterDataHandler(void *, const XML_Char *s, int len)
1054
{
1055
    if (!s || len <= 0 || mLastName.empty())
1056
        return;
1057
 
1058
    mContent.append(s, len);
1059
}
1060
 
1061
int XMLCALL TExpat::cp1250_encoding_handler(void *, const XML_Char *encoding, XML_Encoding *info)
1062
{
1063
    if (!info)
1064
        return XML_STATUS_ERROR;
1065
 
1066
    if (encoding && strcmp(encoding, "CP1250") != 0)
1067
    {
1068
        MSG_ERROR("Invalid encoding handler (" << encoding << ")");
1069
        TError::setError();
1070
        return XML_STATUS_ERROR;
1071
    }
1072
 
1073
    memset(info, 0, sizeof(XML_Encoding));
1074
    createCP1250Encoding(info);
1075
    return XML_STATUS_OK;
1076
}