Coverage Report

Created: 2023-03-26 07:54

/src/xerces-c/src/xercesc/internal/ElemStack.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
/*
19
 * $Id: ElemStack.cpp 830538 2009-10-28 13:41:11Z amassari $
20
 */
21
22
// ---------------------------------------------------------------------------
23
//  Includes
24
// ---------------------------------------------------------------------------
25
#include <string.h>
26
#include <xercesc/util/EmptyStackException.hpp>
27
#include <xercesc/util/NoSuchElementException.hpp>
28
#include <xercesc/framework/XMLElementDecl.hpp>
29
#include <xercesc/internal/ElemStack.hpp>
30
#include <xercesc/validators/common/Grammar.hpp>
31
32
XERCES_CPP_NAMESPACE_BEGIN
33
34
// ---------------------------------------------------------------------------
35
//  ElemStack: Constructors and Destructor
36
// ---------------------------------------------------------------------------
37
ElemStack::ElemStack(MemoryManager* const manager) :
38
39
    fEmptyNamespaceId(0)
40
    , fGlobalPoolId(0)
41
    , fPrefixPool(109, manager)
42
    , fGlobalNamespaces(0)
43
    , fStack(0)
44
    , fStackCapacity(32)
45
    , fStackTop(0)
46
    , fUnknownNamespaceId(0)
47
    , fXMLNamespaceId(0)
48
    , fXMLPoolId(0)
49
    , fXMLNSNamespaceId(0)
50
    , fXMLNSPoolId(0)
51
    , fNamespaceMap(0)
52
    , fMemoryManager(manager)
53
11.0k
{
54
    // Do an initial allocation of the stack and zero it out
55
11.0k
    fStack = (StackElem**) fMemoryManager->allocate
56
11.0k
    (
57
11.0k
        fStackCapacity * sizeof(StackElem*)
58
11.0k
    );//new StackElem*[fStackCapacity];
59
11.0k
    memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
60
61
11.0k
    fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager);
62
11.0k
}
63
64
ElemStack::~ElemStack()
65
11.0k
{
66
11.0k
    if(fGlobalNamespaces)
67
0
    {
68
0
        fMemoryManager->deallocate(fGlobalNamespaces->fMap);
69
0
        delete fGlobalNamespaces;
70
0
    }
71
72
    //
73
    //  Start working from the bottom of the stack and clear it out as we
74
    //  go up. Once we hit an uninitialized one, we can break out.
75
    //
76
17.1M
    for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++)
77
17.1M
    {
78
        // If this entry has been set, then lets clean it up
79
17.1M
        if (!fStack[stackInd])
80
11.0k
            break;
81
82
17.1M
        fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren;
83
17.1M
        fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap;
84
17.1M
        fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName);
85
17.1M
        delete fStack[stackInd];
86
17.1M
    }
87
88
    // Delete the stack array itself now
89
11.0k
    fMemoryManager->deallocate(fStack);//delete [] fStack;
90
11.0k
    delete fNamespaceMap;
91
11.0k
}
92
93
94
// ---------------------------------------------------------------------------
95
//  ElemStack: Stack access
96
// ---------------------------------------------------------------------------
97
XMLSize_t ElemStack::addLevel()
98
0
{
99
    // See if we need to expand the stack
100
0
    if (fStackTop == fStackCapacity)
101
0
        expandStack();
102
103
    // If this element has not been initialized yet, then initialize it
104
0
    if (!fStack[fStackTop])
105
0
    {
106
0
        fStack[fStackTop] = new (fMemoryManager) StackElem;
107
0
        fStack[fStackTop]->fChildCapacity = 0;
108
0
        fStack[fStackTop]->fChildren = 0;
109
0
        fStack[fStackTop]->fMapCapacity = 0;
110
0
        fStack[fStackTop]->fMap = 0;
111
0
        fStack[fStackTop]->fSchemaElemName = 0;
112
0
        fStack[fStackTop]->fSchemaElemNameMaxLen = 0;
113
0
    }
114
115
    // Set up the new top row
116
0
    fStack[fStackTop]->fThisElement = 0;
117
0
    fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
118
0
    fStack[fStackTop]->fChildCount = 0;
119
0
    fStack[fStackTop]->fMapCount = 0;
120
0
    fStack[fStackTop]->fValidationFlag = false;
121
0
    fStack[fStackTop]->fCommentOrPISeen = false;
122
0
    fStack[fStackTop]->fReferenceEscaped = false;
123
0
    fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
124
0
    fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
125
0
    fStack[fStackTop]->fCurrentGrammar = 0;
126
127
    // Bump the top of stack
128
0
    fStackTop++;
129
130
0
    return fStackTop-1;
131
0
}
132
133
134
XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum)
135
19.7M
{
136
    // See if we need to expand the stack
137
19.7M
    if (fStackTop == fStackCapacity)
138
3.50k
        expandStack();
139
140
    // If this element has not been initialized yet, then initialize it
141
19.7M
    if (!fStack[fStackTop])
142
17.1M
    {
143
17.1M
        fStack[fStackTop] = new (fMemoryManager) StackElem;
144
17.1M
        fStack[fStackTop]->fChildCapacity = 0;
145
17.1M
        fStack[fStackTop]->fChildren = 0;
146
17.1M
        fStack[fStackTop]->fMapCapacity = 0;
147
17.1M
        fStack[fStackTop]->fMap = 0;
148
17.1M
        fStack[fStackTop]->fSchemaElemName = 0;
149
17.1M
        fStack[fStackTop]->fSchemaElemNameMaxLen = 0;
150
17.1M
    }
151
152
    // Set up the new top row
153
19.7M
    fStack[fStackTop]->fThisElement = toSet;
154
19.7M
    fStack[fStackTop]->fReaderNum = readerNum;
155
19.7M
    fStack[fStackTop]->fChildCount = 0;
156
19.7M
    fStack[fStackTop]->fMapCount = 0;
157
19.7M
    fStack[fStackTop]->fValidationFlag = false;
158
19.7M
    fStack[fStackTop]->fCommentOrPISeen = false;
159
19.7M
    fStack[fStackTop]->fReferenceEscaped = false;
160
19.7M
    fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
161
19.7M
    fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
162
19.7M
    fStack[fStackTop]->fCurrentGrammar = 0;
163
164
    // Bump the top of stack
165
19.7M
    fStackTop++;
166
167
19.7M
    return fStackTop-1;
168
19.7M
}
169
170
171
172
const ElemStack::StackElem* ElemStack::popTop()
173
2.61M
{
174
    // Watch for an underflow error
175
2.61M
    if (!fStackTop)
176
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager);
177
178
2.61M
    fStackTop--;
179
2.61M
    return fStack[fStackTop];
180
2.61M
}
181
182
183
void
184
ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum)
185
0
{
186
0
    if (!fStackTop)
187
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
188
189
0
    fStack[fStackTop - 1]->fThisElement = toSet;
190
0
    fStack[fStackTop - 1]->fReaderNum = readerNum;
191
0
}
192
193
194
// ---------------------------------------------------------------------------
195
//  ElemStack: Stack top access
196
// ---------------------------------------------------------------------------
197
XMLSize_t ElemStack::addChild(QName* const child, const bool toParent)
198
19.7M
{
199
19.7M
    if (!fStackTop)
200
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
201
202
    //
203
    //  If they want to add to the parent, then we have to have at least two
204
    //  elements on the stack.
205
    //
206
19.7M
    if (toParent && (fStackTop < 2))
207
0
        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager);
208
209
    // Get a convenience pointer to the stack top row
210
19.7M
    StackElem* curRow = toParent
211
19.7M
                        ? fStack[fStackTop - 2] : fStack[fStackTop - 1];
212
213
    // See if we need to expand this row's child array
214
19.7M
    if (curRow->fChildCount == curRow->fChildCapacity)
215
17.1M
    {
216
        // Increase the capacity by a quarter and allocate a new row
217
17.1M
        const XMLSize_t newCapacity = curRow->fChildCapacity ?
218
11.7k
                                      (XMLSize_t)(curRow->fChildCapacity * 1.25) :
219
17.1M
                                      32;
220
17.1M
        QName** newRow = (QName**) fMemoryManager->allocate
221
17.1M
        (
222
17.1M
            newCapacity * sizeof(QName*)
223
17.1M
        );//new QName*[newCapacity];
224
225
        //
226
        //  Copy over the old contents. We don't have to initialize the new
227
        //  part because The current child count is used to know how much of
228
        //  it is valid.
229
        //
230
        //  Only both doing this if there is any current content, since
231
        //  this code also does the initial faulting in of the array when
232
        //  both the current capacity and child count are zero.
233
        //
234
17.8M
        for (XMLSize_t index = 0; index < curRow->fChildCount; index++)
235
710k
            newRow[index] = curRow->fChildren[index];
236
237
        // Clean up the old children and store the new info
238
17.1M
        fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren;
239
17.1M
        curRow->fChildren = newRow;
240
17.1M
        curRow->fChildCapacity = newCapacity;
241
17.1M
    }
242
243
    // Add this id to the end of the row's child id array and bump the count
244
19.7M
    curRow->fChildren[curRow->fChildCount++] = child;
245
246
    // Return the level of the index we just filled (before the bump)
247
19.7M
    return curRow->fChildCount - 1;
248
19.7M
}
249
250
const ElemStack::StackElem* ElemStack::topElement() const
251
6.85M
{
252
6.85M
    if (!fStackTop)
253
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
254
255
6.85M
    return fStack[fStackTop - 1];
256
6.85M
}
257
258
259
// ---------------------------------------------------------------------------
260
//  ElemStack: Prefix map methods
261
// ---------------------------------------------------------------------------
262
void ElemStack::addGlobalPrefix(const XMLCh* const    prefixToAdd
263
                              , const unsigned int    uriId)
264
0
{
265
0
    if (!fGlobalNamespaces)
266
0
    {
267
0
        fGlobalNamespaces = new (fMemoryManager) StackElem;
268
0
        fGlobalNamespaces->fChildCapacity = 0;
269
0
        fGlobalNamespaces->fChildren = 0;
270
0
        fGlobalNamespaces->fMapCapacity = 0;
271
0
        fGlobalNamespaces->fMap = 0;
272
0
        fGlobalNamespaces->fMapCount = 0;
273
0
        fGlobalNamespaces->fSchemaElemName = 0;
274
0
        fGlobalNamespaces->fSchemaElemNameMaxLen = 0;
275
0
        fGlobalNamespaces->fThisElement = 0;
276
0
        fGlobalNamespaces->fReaderNum = 0xFFFFFFFF;
277
0
        fGlobalNamespaces->fChildCount = 0;
278
0
        fGlobalNamespaces->fValidationFlag = false;
279
0
        fGlobalNamespaces->fCommentOrPISeen = false;
280
0
        fGlobalNamespaces->fReferenceEscaped = false;
281
0
        fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId;
282
0
        fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
283
0
        fGlobalNamespaces->fCurrentGrammar = 0;
284
0
    }
285
286
    // Map the prefix to its unique id
287
0
    const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
288
289
    //
290
    //  Add a new element to the prefix map for this element. If its full,
291
    //  then expand it out.
292
    //
293
0
    if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity)
294
0
        expandMap(fGlobalNamespaces);
295
296
    //
297
    //  And now add a new element for this prefix. Watch for the special case
298
    //  of xmlns=="", and force it to ""=[globalid]
299
    //
300
0
    fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId;
301
0
    if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
302
0
        fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId;
303
0
    else
304
0
        fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId;
305
306
    // Bump the map count now
307
0
    fGlobalNamespaces->fMapCount++;
308
0
}
309
310
void ElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
311
                            , const unsigned int    uriId)
312
0
{
313
0
    if (!fStackTop)
314
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
315
316
    // Get a convenience pointer to the stack top row
317
0
    StackElem* curRow = fStack[fStackTop - 1];
318
319
    // Map the prefix to its unique id
320
0
    const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
321
322
    //
323
    //  Add a new element to the prefix map for this element. If its full,
324
    //  then expand it out.
325
    //
326
0
    if (curRow->fMapCount == curRow->fMapCapacity)
327
0
        expandMap(curRow);
328
329
    //
330
    //  And now add a new element for this prefix. Watch for the special case
331
    //  of xmlns=="", and force it to ""=[globalid]
332
    //
333
0
    curRow->fMap[curRow->fMapCount].fPrefId = prefId;
334
0
    if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
335
0
        curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId;
336
0
    else
337
0
        curRow->fMap[curRow->fMapCount].fURIId = uriId;
338
339
    // Bump the map count now
340
0
    curRow->fMapCount++;
341
0
}
342
343
344
unsigned int ElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
345
                                        ,       bool&           unknown) const
346
0
{
347
    // Assume we find it
348
0
    unknown = false;
349
350
    //
351
    //  Map the prefix to its unique id, from the prefix string pool. If its
352
    //  not a valid prefix, then its a failure.
353
    //
354
0
    unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap);
355
0
    if (prefixId == 0)
356
0
    {
357
0
        unknown = true;
358
0
        return fUnknownNamespaceId;
359
0
    }
360
    //
361
    //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
362
    //  be overridden.
363
    //
364
0
    else if (prefixId == fXMLPoolId)
365
0
        return fXMLNamespaceId;
366
0
    else if (prefixId == fXMLNSPoolId)
367
0
        return fXMLNSNamespaceId;
368
369
    //
370
    //  Start at the stack top and work backwards until we come to some
371
    //  element that mapped this prefix.
372
    //
373
0
    for (XMLSize_t index = fStackTop; index > 0; index--)
374
0
    {
375
        // Get a convenience pointer to the current element
376
0
        StackElem* curRow = fStack[index-1];
377
378
        // Search the map at this level for the passed prefix
379
0
        for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
380
0
        {
381
0
            if (curRow->fMap[mapIndex].fPrefId == prefixId)
382
0
                return curRow->fMap[mapIndex].fURIId;
383
0
        }
384
0
    }
385
    //  If the prefix wasn't found, try in the global namespaces
386
0
    if(fGlobalNamespaces)
387
0
    {
388
0
        for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++)
389
0
        {
390
0
            if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId)
391
0
                return fGlobalNamespaces->fMap[mapIndex].fURIId;
392
0
        }
393
0
    }
394
395
    //
396
    //  If the prefix is an empty string, then we will return the special
397
    //  global namespace id. This can be overridden, but no one has or we
398
    //  would have not gotten here.
399
    //
400
0
    if (!*prefixToMap)
401
0
        return fEmptyNamespaceId;
402
403
    // Oh well, don't have a clue so return the unknown id
404
0
    unknown = true;
405
0
    return fUnknownNamespaceId;
406
0
}
407
408
409
ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const
410
0
{
411
0
    fNamespaceMap->removeAllElements();
412
413
    //  Start at the stack top and work backwards until we come to some
414
    //  element that mapped this prefix.
415
0
    for (XMLSize_t index = fStackTop; index > 0; index--)
416
0
    {
417
        // Get a convenience pointer to the current element
418
0
        StackElem* curRow = fStack[index-1];
419
420
        // If no prefixes mapped at this level, then go the next one
421
0
        if (!curRow->fMapCount)
422
0
            continue;
423
424
        // Search the map at this level for the passed prefix
425
0
        for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
426
0
            fNamespaceMap->addElement(&(curRow->fMap[mapIndex]));
427
0
    }
428
    //  Add the global namespaces
429
0
    if(fGlobalNamespaces)
430
0
    {
431
0
        for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++)
432
0
            fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex]));
433
0
    }
434
435
0
    return fNamespaceMap;
436
0
}
437
438
// ---------------------------------------------------------------------------
439
//  ElemStack: Miscellaneous methods
440
// ---------------------------------------------------------------------------
441
void ElemStack::reset(  const   unsigned int    emptyId
442
                        , const unsigned int    unknownId
443
                        , const unsigned int    xmlId
444
                        , const unsigned int    xmlNSId)
445
11.0k
{
446
11.0k
    if(fGlobalNamespaces)
447
0
    {
448
0
        fMemoryManager->deallocate(fGlobalNamespaces->fMap);
449
0
        delete fGlobalNamespaces;
450
0
        fGlobalNamespaces = 0;
451
0
    }
452
453
    // Reset the stack top to clear the stack
454
11.0k
    fStackTop = 0;
455
456
    // if first time, put in the standard prefixes
457
11.0k
    if (fXMLPoolId == 0) {
458
459
11.0k
        fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
460
11.0k
        fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
461
11.0k
        fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
462
11.0k
    }
463
464
    // And store the new special URI ids
465
11.0k
    fEmptyNamespaceId = emptyId;
466
11.0k
    fUnknownNamespaceId = unknownId;
467
11.0k
    fXMLNamespaceId = xmlId;
468
11.0k
    fXMLNSNamespaceId = xmlNSId;
469
11.0k
}
470
471
472
// ---------------------------------------------------------------------------
473
//  ElemStack: Private helpers
474
// ---------------------------------------------------------------------------
475
void ElemStack::expandMap(StackElem* const toExpand)
476
0
{
477
    // For convenience get the old map size
478
0
    const XMLSize_t oldCap = toExpand->fMapCapacity;
479
480
    //
481
    //  Expand the capacity by 25%, or initialize it to 16 if its currently
482
    //  empty. Then allocate a new temp buffer.
483
    //
484
0
    const XMLSize_t  newCapacity = oldCap ?
485
0
                                     (XMLSize_t )(oldCap * 1.25) : 16;
486
0
    PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
487
0
    (
488
0
        newCapacity * sizeof(PrefMapElem)
489
0
    );//new PrefMapElem[newCapacity];
490
491
    //
492
    //  Copy over the old stuff. We DON'T have to zero out the new stuff
493
    //  since this is a by value map and the current map index controls what
494
    //  is relevant.
495
    //
496
0
    memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem));
497
498
    // Delete the old map and store the new stuff
499
0
    fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap;
500
0
    toExpand->fMap = newMap;
501
0
    toExpand->fMapCapacity = newCapacity;
502
0
}
503
504
void ElemStack::expandStack()
505
3.50k
{
506
    // Expand the capacity by 25% and allocate a new buffer
507
3.50k
    const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25);
508
3.50k
    StackElem** newStack = (StackElem**) fMemoryManager->allocate
509
3.50k
    (
510
3.50k
        newCapacity * sizeof(StackElem*)
511
3.50k
    );//new StackElem*[newCapacity];
512
513
    // Copy over the old stuff
514
3.50k
    memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
515
516
    //
517
    //  And zero out the new stuff. Though we use a stack top, we reuse old
518
    //  stack contents so we need to know if elements have been initially
519
    //  allocated or not as we push new stuff onto the stack.
520
    //
521
3.50k
    memset
522
3.50k
    (
523
3.50k
        &newStack[fStackCapacity]
524
3.50k
        , 0
525
3.50k
        , (newCapacity - fStackCapacity) * sizeof(StackElem*)
526
3.50k
    );
527
528
    // Delete the old array and update our members
529
3.50k
    fMemoryManager->deallocate(fStack);//delete [] fStack;
530
3.50k
    fStack = newStack;
531
3.50k
    fStackCapacity = newCapacity;
532
3.50k
}
533
534
535
536
// ---------------------------------------------------------------------------
537
//  WFElemStack: Constructors and Destructor
538
// ---------------------------------------------------------------------------
539
WFElemStack::WFElemStack(MemoryManager* const manager) :
540
541
    fEmptyNamespaceId(0)
542
    , fGlobalPoolId(0)
543
    , fStackCapacity(32)
544
    , fStackTop(0)
545
    , fUnknownNamespaceId(0)
546
    , fXMLNamespaceId(0)
547
    , fXMLPoolId(0)
548
    , fXMLNSNamespaceId(0)
549
    , fXMLNSPoolId(0)
550
    , fMapCapacity(0)
551
    , fMap(0)
552
    , fStack(0)
553
    , fPrefixPool(109, manager)
554
    , fMemoryManager(manager)
555
0
{
556
    // Do an initial allocation of the stack and zero it out
557
0
    fStack = (StackElem**) fMemoryManager->allocate
558
0
    (
559
0
        fStackCapacity * sizeof(StackElem*)
560
0
    );//new StackElem*[fStackCapacity];
561
0
    memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
562
0
}
563
564
WFElemStack::~WFElemStack()
565
0
{
566
    //
567
    //  Start working from the bottom of the stack and clear it out as we
568
    //  go up. Once we hit an uninitialized one, we can break out.
569
    //
570
0
    for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++)
571
0
    {
572
        // If this entry has been set, then lets clean it up
573
0
        if (!fStack[stackInd])
574
0
            break;
575
576
0
        fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement;
577
0
        delete fStack[stackInd];
578
0
    }
579
580
0
    if (fMap)
581
0
        fMemoryManager->deallocate(fMap);//delete [] fMap;
582
583
    // Delete the stack array itself now
584
0
    fMemoryManager->deallocate(fStack);//delete [] fStack;
585
0
}
586
587
588
// ---------------------------------------------------------------------------
589
//  WFElemStack: Stack access
590
// ---------------------------------------------------------------------------
591
XMLSize_t WFElemStack::addLevel()
592
0
{
593
    // See if we need to expand the stack
594
0
    if (fStackTop == fStackCapacity)
595
0
        expandStack();
596
597
    
598
    // If this element has not been initialized yet, then initialize it
599
0
    if (!fStack[fStackTop])
600
0
    {
601
0
        fStack[fStackTop] = new (fMemoryManager) StackElem;
602
0
        fStack[fStackTop]->fThisElement = 0;
603
0
        fStack[fStackTop]->fElemMaxLength = 0;
604
0
    }
605
606
    // Set up the new top row
607
0
    fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
608
0
    fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
609
0
    fStack[fStackTop]->fTopPrefix = -1;
610
611
0
    if (fStackTop != 0)
612
0
        fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
613
614
    // Bump the top of stack
615
0
    fStackTop++;
616
617
0
    return fStackTop-1;
618
0
}
619
620
621
XMLSize_t
622
WFElemStack::addLevel(const XMLCh* const toSet,
623
                      const unsigned int toSetLen,
624
                      const unsigned int readerNum)
625
0
{
626
    // See if we need to expand the stack
627
0
    if (fStackTop == fStackCapacity)
628
0
        expandStack();
629
630
    // If this element has not been initialized yet, then initialize it
631
0
    if (!fStack[fStackTop])
632
0
    {
633
0
        fStack[fStackTop] = new (fMemoryManager) StackElem;
634
0
        fStack[fStackTop]->fThisElement = 0;
635
0
        fStack[fStackTop]->fElemMaxLength = 0;
636
0
    }
637
638
    // Set up the new top row
639
0
    fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
640
0
    fStack[fStackTop]->fTopPrefix = -1;
641
642
    // And store the new stuff
643
0
    if (toSetLen > fStack[fStackTop]->fElemMaxLength) {
644
645
0
        fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement;
646
0
        fStack[fStackTop]->fElemMaxLength = toSetLen;
647
0
        fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate
648
0
        (
649
0
            (toSetLen + 1) * sizeof(XMLCh)
650
0
        );//new XMLCh[toSetLen + 1];
651
0
    }
652
653
0
    XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1);
654
0
    fStack[fStackTop]->fReaderNum = readerNum;
655
656
0
    if (fStackTop != 0)
657
0
        fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
658
659
    // Bump the top of stack
660
0
    fStackTop++;
661
662
0
    return fStackTop-1;
663
0
}
664
665
666
667
const WFElemStack::StackElem* WFElemStack::popTop()
668
0
{
669
    // Watch for an underflow error
670
0
    if (!fStackTop)
671
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager);
672
673
0
    fStackTop--;
674
0
    return fStack[fStackTop];
675
0
}
676
677
678
void
679
WFElemStack::setElement(const XMLCh* const toSet,
680
                      const unsigned int toSetLen,
681
                      const unsigned int readerNum)
682
0
{
683
0
    if (!fStackTop)
684
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
685
686
0
    if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) {
687
688
0
        fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement;
689
0
        fStack[fStackTop - 1]->fElemMaxLength = toSetLen;
690
0
        fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate
691
0
        (
692
0
            (toSetLen + 1) * sizeof(XMLCh)
693
0
        );//new XMLCh[toSetLen + 1];
694
0
    }
695
696
0
    XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1);
697
0
    fStack[fStackTop - 1]->fReaderNum = readerNum;
698
0
}
699
700
701
// ---------------------------------------------------------------------------
702
//  WFElemStack: Stack top access
703
// ---------------------------------------------------------------------------
704
const WFElemStack::StackElem* WFElemStack::topElement() const
705
0
{
706
0
    if (!fStackTop)
707
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
708
709
0
    return fStack[fStackTop - 1];
710
0
}
711
712
713
// ---------------------------------------------------------------------------
714
//  WFElemStack: Prefix map methods
715
// ---------------------------------------------------------------------------
716
void WFElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
717
                              , const unsigned int    uriId)
718
0
{
719
0
    if (!fStackTop)
720
0
        ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
721
722
    // Get a convenience pointer to the stack top row
723
0
    StackElem* curRow = fStack[fStackTop - 1];
724
725
    // Map the prefix to its unique id
726
0
    const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
727
728
    //
729
    //  Add a new element to the prefix map for this element. If its full,
730
    //  then expand it out.
731
    //
732
0
    if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity)
733
0
        expandMap();
734
735
    //
736
    //  And now add a new element for this prefix. Watch for the special case
737
    //  of xmlns=="", and force it to ""=[globalid]
738
    //
739
0
    fMap[curRow->fTopPrefix + 1].fPrefId = prefId;
740
0
    if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
741
0
        fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId;
742
0
    else
743
0
        fMap[curRow->fTopPrefix + 1].fURIId = uriId;
744
745
    // Bump the map count now
746
0
    curRow->fTopPrefix++;
747
0
}
748
749
750
unsigned int WFElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
751
                                          ,       bool&           unknown) const
752
0
{
753
    // Assume we find it
754
0
    unknown = false;
755
756
    //
757
    //  Map the prefix to its unique id, from the prefix string pool. If its
758
    //  not a valid prefix, then its a failure.
759
    //
760
0
    unsigned int prefixId = fPrefixPool.getId(prefixToMap);
761
0
    if (!prefixId)
762
0
    {
763
0
        unknown = true;
764
0
        return fUnknownNamespaceId;
765
0
    }
766
767
    //
768
    //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
769
    //  be overridden.
770
    //
771
0
    if (prefixId == fXMLPoolId)
772
0
        return fXMLNamespaceId;
773
0
    else if (prefixId == fXMLNSPoolId)
774
0
        return fXMLNSNamespaceId;
775
776
    //
777
    //  Start at the stack top and work backwards until we come to some
778
    //  element that mapped this prefix.
779
    //
780
    //  Get a convenience pointer to the stack top row
781
0
    StackElem* curRow = fStack[fStackTop - 1];
782
0
    for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--)
783
0
    {
784
0
        if (fMap[mapIndex].fPrefId == prefixId)
785
0
            return fMap[mapIndex].fURIId;
786
0
    }
787
788
    //
789
    //  If the prefix is an empty string, then we will return the special
790
    //  global namespace id. This can be overridden, but no one has or we
791
    //  would have not gotten here.
792
    //
793
0
    if (!*prefixToMap)
794
0
        return fEmptyNamespaceId;
795
796
    // Oh well, don't have a clue so return the unknown id
797
0
    unknown = true;
798
0
    return fUnknownNamespaceId;
799
0
}
800
801
802
// ---------------------------------------------------------------------------
803
//  WFElemStack: Miscellaneous methods
804
// ---------------------------------------------------------------------------
805
void WFElemStack::reset(  const   unsigned int    emptyId
806
                          , const unsigned int    unknownId
807
                          , const unsigned int    xmlId
808
                          , const unsigned int    xmlNSId)
809
0
{
810
    // Reset the stack top to clear the stack
811
0
    fStackTop = 0;
812
813
    // if first time, put in the standard prefixes
814
0
    if (fXMLPoolId == 0) {
815
816
0
        fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
817
0
        fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
818
0
        fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
819
0
    }
820
821
    // And store the new special URI ids
822
0
    fEmptyNamespaceId = emptyId;
823
0
    fUnknownNamespaceId = unknownId;
824
0
    fXMLNamespaceId = xmlId;
825
0
    fXMLNSNamespaceId = xmlNSId;
826
0
}
827
828
829
// ---------------------------------------------------------------------------
830
//  WFElemStack: Private helpers
831
// ---------------------------------------------------------------------------
832
void WFElemStack::expandMap()
833
0
{
834
    //
835
    //  Expand the capacity by 25%, or initialize it to 16 if its currently
836
    //  empty. Then allocate a new temp buffer.
837
    //
838
0
    const XMLSize_t newCapacity = fMapCapacity ?
839
0
                                  (XMLSize_t)(fMapCapacity * 1.25) : 16;
840
0
    PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
841
0
    (
842
0
        newCapacity * sizeof(PrefMapElem)
843
0
    );//new PrefMapElem[newCapacity];
844
845
    //
846
    //  Copy over the old stuff. We DON'T have to zero out the new stuff
847
    //  since this is a by value map and the current map index controls what
848
    //  is relevant.
849
    //
850
0
    if (fMapCapacity) {
851
852
0
        memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem));
853
0
        fMemoryManager->deallocate(fMap);//delete [] fMap;
854
0
    }
855
856
0
    fMap = newMap;
857
0
    fMapCapacity = newCapacity;
858
0
}
859
860
void WFElemStack::expandStack()
861
0
{
862
    // Expand the capacity by 25% and allocate a new buffer
863
0
    const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25);
864
0
    StackElem** newStack = (StackElem**) fMemoryManager->allocate
865
0
    (
866
0
        newCapacity * sizeof(StackElem*)
867
0
    );//new StackElem*[newCapacity];
868
869
    // Copy over the old stuff
870
0
    memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
871
872
    //
873
    //  And zero out the new stuff. Though we use a stack top, we reuse old
874
    //  stack contents so we need to know if elements have been initially
875
    //  allocated or not as we push new stuff onto the stack.
876
    //
877
0
    memset
878
0
    (
879
0
        &newStack[fStackCapacity]
880
0
        , 0
881
0
        , (newCapacity - fStackCapacity) * sizeof(StackElem*)
882
0
    );
883
884
    // Delete the old array and update our members
885
0
    fMemoryManager->deallocate(fStack);//delete [] fStack;
886
0
    fStack = newStack;
887
0
    fStackCapacity = newCapacity;
888
0
}
889
890
891
XERCES_CPP_NAMESPACE_END