source: icXML/icXML-devel/src/icxmlc/XMLNamespaceResolver.c @ 3563

Last change on this file since 3563 was 3563, checked in by cameron, 5 years ago

Update icxmlc files

File size: 24.9 KB
Line 
1/*
2 *  Copyright © 2012 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icXML is a trademark of International Characters.
5 */
6
7/*
8 * @author Nigel Medforth, nigelm -at- interational-characters.com
9 * @version $Id: XMLNamespaceResolver.c 388 2013-10-29 21:25:27Z nigelm $
10 *
11 */
12
13#include <icxmlc/XMLNamespaceResolver.hpp>
14#include <icxmlc/XMLSymbol.hpp>
15#include <icxmlc/XMLStringU.hpp>
16
17XERCES_CPP_NAMESPACE_BEGIN
18
19/// -----------------------------------------------------------------------------------------------
20// TODO: if we bind a uri to a prefix and the binding is non-canonical but the canonical entry for the prefix is
21// empty, should we move the prefix into that entry and rewrite all of the symbols? it would require storing a
22// list of symbols per prefix or having a "moved" bitset to tell the resolver to update the symbol's binding.
23// would this be worth the effort?
24
25IDISA_ALWAYS_INLINE
26gid_t
27XMLNamespaceResolver::bindNamespace(const XMLSymbol & symbol, const XMLCh * uri, const XMLSize_t length, const bool isXMLV1_1, bool & speculatedCorrectly)
28{
29        // Get the prefix id of the local part of this symbol name, e.g. the prefix id of "ogc" if the symbol is "xmlns:ogc"
30        // or fEmptyNamespaceId if the symbol is "xmlns"
31
32    const gid_t prefixId = symbol.getLocalPartId();
33
34    DEBUG_NAMESPACE_MESSAGE("prefixId=" << prefixId)
35
36    gid_t uriId = resolveUri(uri, length, prefixId);
37
38    DEBUG_NAMESPACE_MESSAGE("uriId=" << uriId)
39
40    // test if this prefix/uri pair is an error
41    if (unlikely(uriId == XMLNamespaceResolver::fEmptyUriId))
42    {
43        // in the case that an empty string is used as a URI, assume that we're dealing with an XML 1.1 document.
44        if (likely(isXMLV1_1))
45        {
46            uriId = XMLNamespaceResolver::fUnknownUriId;
47        }
48        else
49        {
50            // Namespaces in XML 1.0 (Third Edition)
51            //
52            // The empty string, though it is a legal URI reference, cannot be used as a namespace name. (2.2)
53            // The attribute's normalized value MUST be either a URI reference — the namespace name identifying the namespace — or an empty string. (3)
54            // In a namespace declaration for a prefix (i.e., where the NSAttName is a PrefixedAttName), the attribute value MUST NOT be empty. (5)
55
56            if (unlikely(prefixId != XMLNamespaceResolver::fEmptyUriId))
57            {
58                throw XMLErrs::NoEmptyStrNamespace;
59            }
60        }
61    }
62    else
63    {
64        // is the XML URI being bound to some prefix other than "xml" or vice versa?
65        if (unlikely((prefixId == fXMLUriId) ^ (uriId == fXMLUriId)))
66        {
67            throw (uriId == fXMLUriId) ? XMLErrs::XMLURINotMatchXMLPrefix : XMLErrs::PrefixXMLNotMatchXMLURI;
68        }       
69        else if (unlikely(uriId == fXMLNSUriId)) // was the XMLNS URI bound to some prefix?
70        {           
71            throw XMLErrs::NoUseOfxmlnsURI;
72        }
73    }
74
75    const int namespaceId = resolveNamespaceId(prefixId);
76
77    DEBUG_NAMESPACE_MESSAGE("namespaceId=" << namespaceId)
78
79    if (unlikely(namespaceId == -1))
80        {
81                // both the prefixId and the uriId exist, but they are not mapped to one another.
82        mapPrefixToUri(prefixId, uriId);
83
84        // since we speculated that the prefixId == globalUriId, if we find that this is not
85                // true, then we have to re-resolve everything regarding this element.
86        speculatedCorrectly &= (prefixId == uriId);
87        }
88    else
89    {
90        const gid_t storedUriId = getNamespaceUriId(namespaceId);
91
92        DEBUG_NAMESPACE_MESSAGE("storedUriId=" << storedUriId)
93
94        if (likely(storedUriId != uriId))
95        {
96            remapPrefixToUri(prefixId, uriId);
97            speculatedCorrectly = 0;
98        }
99    }
100    return XMLNamespaceResolver::fXMLNSUriId;
101}
102
103/// -----------------------------------------------------------------------------------------------
104
105IDISA_ALWAYS_INLINE
106gid_t
107XMLNamespaceResolver::resolveUriId(const XMLSymbol & symbol, const bool isAttribute) const
108{
109    bool unknown = 0;
110    return resolveUriId(symbol, isAttribute, false, unknown);
111}
112
113/// -----------------------------------------------------------------------------------------------
114
115IDISA_ALWAYS_INLINE
116gid_t
117XMLNamespaceResolver::resolveUriId(const XMLSymbol & symbol, const bool isAttribute, const bool misspeculated, bool & unknown) const
118{   
119    if (isAttribute && !symbol.isQualified())
120        {
121        return fEmptyUriId;
122        }
123    return resolveUriId(symbol.getPrefixId(), (isAttribute && likely(!misspeculated) ? symbol.getPrefixId() : fUnknownUriId), unknown);
124}
125
126/// -----------------------------------------------------------------------------------------------
127
128IDISA_ALWAYS_INLINE
129gid_t
130XMLNamespaceResolver::resolveUriId(const gid_t prefixId, const gid_t defaultUriId, bool & unknown) const
131{
132    gid_t uriId = defaultUriId;
133        // first check canonical set to see if this prefix id is also the uri id.
134        if (likely(fCanonicalBindingSet.mask_and_extract(fCurrentlyVisibleNamespaces, prefixId)))
135        {
136        uriId = prefixId;
137        }
138        else
139        {
140                // it's not canonical; resolve which of the possible uri ids this prefix id
141                // currently points to
142                const int namespaceId = resolveNamespaceId(prefixId);
143                // if this prefix has not been mapped to a namespace; assume that it will
144                // be mapped to the 'adjacent' uri.
145
146                if (likely(namespaceId != -1))
147                {
148            uriId = getNamespaceUriId(namespaceId);
149            unknown = (uriId == XMLNamespaceResolver::fUnknownUriId);
150                }
151                else
152                {
153                        unknown = true;
154                }
155        }
156        return uriId;
157}
158
159/// -----------------------------------------------------------------------------------------------
160
161IDISA_ALWAYS_INLINE
162gid_t
163XMLNamespaceResolver::resolveUriId(const XMLCh * uri) const
164{
165        if (unlikely(!uri || *uri == 0))
166        {
167                return fEmptyUriId;
168        }
169
170        XMLSize_t length = XMLStringU::stringLen(uri);
171
172    const gid_t linkId = fUriPool.find(uri, length);
173
174    gid_t uriId;
175
176    if (unlikely(linkId == XMLNamespaceResolver::fUnknownUriId))
177        {
178        XMLNamespaceResolver * const self = const_cast<XMLNamespaceResolver*>(this);
179        // no, it was already used; claim the next unused link id.
180        uriId = self->fUriPool.add(max<size_t>(fPrefixCount, fUriPool.count()), uri, length, self->fGlobalUriPool);
181        }
182    else
183    {
184        #ifdef PRINT_DEBUG_MESSAGE
185        assert (linkId < fUriPool.count());
186        assert (XMLString::compareString(fUriPool[linkId].fKey, uri) == 0);
187        #endif
188        uriId = fUriPool[linkId].getId();
189    }
190
191    return uriId;
192}
193
194/// -----------------------------------------------------------------------------------------------
195
196// get the prefix id of the prefix portion of the qName, e.g., the prefix id of "xmlns" if given "xmlns:ogc"
197// or the prefix of "" if given "xmlns".
198
199IDISA_ALWAYS_INLINE
200gid_t
201XMLNamespaceResolver::resolvePrefixId(const XMLCh * qName, int & colonPos) const
202{
203    int length = XMLStringU::stringLenOrIndexOf<chColon>(qName);
204
205    if (unlikely(qName[length] == chNull))
206    {
207        colonPos = -1;
208        }
209    else
210    {
211        colonPos = length;
212    }
213
214    const XMLPrefixEntry * entry = findPrefix(qName, length);
215    if (likely(entry != 0))
216    {
217        return entry->getId();
218    }
219
220    return XMLNamespaceResolver::fUnknownUriId;
221}
222
223/// -----------------------------------------------------------------------------------------------
224
225IDISA_ALWAYS_INLINE
226gid_t XMLNamespaceResolver::addOrFindPrefixId(const XMLCh * qName, const XMLSize_t length, int & colon)
227{
228    colon = XMLStringU::indexOf<chColon>(qName, length);
229    return (unlikely(colon == -1)) ? XMLNamespaceResolver::fEmptyUriId : addOrFindPrefixId(qName, colon);
230}
231
232/// -----------------------------------------------------------------------------------------------
233
234IDISA_ALWAYS_INLINE
235gid_t XMLNamespaceResolver::addOrFindPrefixId(const XMLCh * qName, const XMLSize_t length)
236{
237    return addOrFindPrefix(qName, length)->getId();
238}
239
240/// -----------------------------------------------------------------------------------------------
241
242IDISA_ALWAYS_INLINE
243const XMLCh *
244XMLNamespaceResolver::addOrFindPrefix(const XMLCh * qName)
245{
246        int length = XMLStringU::stringLenOrIndexOf<chColon>(qName);
247    if (unlikely(length == -1))
248        {
249                return XMLUni::fgZeroLenString;
250        }
251        // get the prefix id of the prefix portion of the qName, e.g., the prefix id of "xmlns" if given "xmlns:ogc"
252        // or the prefix of "" if given "xmlns".
253        return addOrFindPrefix(qName, length)->getKey();
254}
255
256/// -----------------------------------------------------------------------------------------------
257
258IDISA_ALWAYS_INLINE
259const XMLPrefixEntry *
260XMLNamespaceResolver::findPrefix(const XMLCh * prefix, const int length) const
261{
262    // resolve the prefix id from the prefix; since this will not be required
263    // very often, just iterate through a list.
264    for (gid_t index = 0; index < fPrefixCount; index++)
265    {
266        if (fPrefixList[index].equals(prefix, length))
267        {
268            return &fPrefixList[index];
269        }
270    }
271
272    return 0;
273}
274
275/// -----------------------------------------------------------------------------------------------
276
277IDISA_ALWAYS_INLINE
278const XMLCh *
279XMLNamespaceResolver::getPrefixForId(const gid_t prefixId) const
280{
281    if (likely((prefixId < fPrefixCount) && (fPrefixList[prefixId].id == prefixId)))
282    {
283        return fPrefixList[prefixId].getKey();
284    }
285
286    // resolve the prefix id from the prefix; since this will not be required
287    // very often, just iterate through a list.
288    for (gid_t index = 0; index < fPrefixCount; index++)
289    {
290        if (fPrefixList[index].id == prefixId)
291        {
292            return fPrefixList[index].getKey();
293        }
294    }
295
296    return XMLUni::fgZeroLenString;
297}
298
299/// -----------------------------------------------------------------------------------------------
300
301IDISA_ALWAYS_INLINE
302const XMLPrefixEntry *
303XMLNamespaceResolver::addOrFindPrefix(const XMLCh * prefix, const int length)
304{
305    DEBUG_NAMESPACE_MESSAGE("addOrFindPrefix(" << prefix << ',' << length << ')')
306
307        // resolve the prefix id from the prefix; since this will not be required
308        // very often, just iterate through a list.
309    const XMLPrefixEntry * knownPrefix = findPrefix(prefix, length);
310    if (likely(knownPrefix != 0))
311    {
312        return knownPrefix;
313    }
314
315    const gid_t prefixId = max<size_t>(fPrefixCount, fUriPool.count());
316
317        if (unlikely(fPrefixToNamespaceBindingTable.setCapacity() <= prefixId))
318        {
319        DEBUG_NAMESPACE_MESSAGE(" *** EXPANDING PREFIX TABLES " << fPrefixToNamespaceBindingTable.setCapacity())
320                fCanonicalBindingSet.expand(prefixId);
321                fPrefixToNamespaceBindingTable.increaseSetCapacity(prefixId);
322                // fLocallyModifiedNamespaces.increaseBitCapacity(prefixId);
323        }
324
325    // if our prefix count equals our capacity, then we need to expand all of the related buffers
326    if (unlikely(fPrefixCount == fPrefixList.capacity()))
327    {
328        DEBUG_NAMESPACE_MESSAGE(" -- resizing fPrefixList");
329        fPrefixList.resizeToFit(fPrefixList.capacity(), fPrefixList.capacity() * 2);
330    }
331
332    XMLPrefixEntry * newPrefix = &fPrefixList[fPrefixCount++];
333        // QUESTION: does storing the prefixes in the string pool help or hinder? we can just point to
334        // the symbols and store only the prefix's length?
335        // NOTE: this may require modifying the TraverseSchema class to do this safely.
336    newPrefix->key = fPrefixPool.insert(prefix, length);
337    newPrefix->length = length;
338    newPrefix->id = prefixId;
339
340        // add this entry to the canonical prefix set since we assume that the prefix and uri ids
341        // will match
342        fCanonicalBindingSet += prefixId;
343
344    return newPrefix;
345}
346
347/// -----------------------------------------------------------------------------------------------
348
349IDISA_ALWAYS_INLINE
350gid_t
351XMLNamespaceResolver::resolveUri(const XMLCh * uri, const XMLSize_t length, const gid_t prefixId)
352{   
353    gid_t linkId = fUriPool.find(uri, length);
354    if (unlikely(linkId == XMLNamespaceResolver::fUnknownUriId))
355        {
356        DEBUG_MESSAGE(" -- adding new uriId")
357        linkId = prefixId;
358        if (unlikely(prefixId > fUriPool.capacity()))
359        {
360            fUriPool.resizeToFit(prefixId);
361        }
362                // is the reserved uri slot for this prefix still free?
363        else if (unlikely(fUriPool[prefixId].getKey() != NULL))
364                {
365                        // no, it was already used; claim the next unused uri id.
366            linkId = fUriPool.count();
367                }
368
369        return fUriPool.add(linkId, uri, length, fGlobalUriPool);
370        }
371    else
372    {
373        return fUriPool[linkId].getId();
374    }
375}
376
377/// -----------------------------------------------------------------------------------------------
378
379IDISA_ALWAYS_INLINE
380void
381XMLNamespaceResolver::mapPrefixToUri(const gid_t prefixId, const gid_t uriId)
382{
383
384    // both the prefixId and the uriId exist, but they are not mapped to one another.
385    const gid_t namespaceId = bindPrefixToUri(prefixId, uriId);
386
387    // add the new namespace to the namespace 'stack'
388    fLocallyModifiedNamespaces[fScope] += namespaceId;
389
390    // and mark it as visible
391    fCurrentlyVisibleNamespaces += namespaceId;
392}
393
394/// -----------------------------------------------------------------------------------------------
395
396IDISA_ALWAYS_INLINE
397void
398XMLNamespaceResolver::remapPrefixToUri(const gid_t prefixId, const gid_t uriId)
399{
400    const int namespaceId = bindPrefixToUri(prefixId, uriId);
401
402    BindingSet modified = (fCurrentlyVisibleNamespaces & fPrefixToNamespaceBindingTable[prefixId]);
403
404    modified = modified + namespaceId;
405    // mark any modified namespaces in the namespace 'stack'
406    fLocallyModifiedNamespaces[fScope] += modified;
407    // remove the old namespace/uri binding (if one exists) and add the new binding to the set of
408    // currently visible namespaces
409    fCurrentlyVisibleNamespaces ^= modified;
410}
411
412/// -----------------------------------------------------------------------------------------------
413
414IDISA_ALWAYS_INLINE
415gid_t
416XMLNamespaceResolver::bindPrefixToUri(const gid_t prefixId, const gid_t uriId)
417{
418    gid_t namespaceId = 0;
419
420    // Reserve the LOCAL uriId slot for this prefix; not the GLOBAL uriId slot!
421
422        BindingSetIterator namespaceItr(fPrefixToNamespaceBindingTable.get(prefixId), fPrefixToNamespaceBindingTable.bitCapacity());
423
424        size_t count = 0;
425
426        while (namespaceItr.next())
427        {
428                count++;
429
430        if (getNamespaceUriId(namespaceItr.pos()) == uriId)
431                {
432                        namespaceId = namespaceItr.pos();
433
434            DEBUG_NAMESPACE_MESSAGE(" --- found namespace mapping! " << namespaceId)
435
436                        goto FOUND_NAMESPACE_MAPPING;
437                }
438        }
439
440        namespaceId = fNextNamespaceId++;
441
442    DEBUG_NAMESPACE_MESSAGE(" --- created new namespace mapping! " << namespaceId)
443
444    if (unlikely(fCurrentlyVisibleNamespaces.capacity() <= namespaceId))
445        {
446                DEBUG_NAMESPACE_MESSAGE(" *** expanding namespace space due to namespaceId " << fNextNamespaceId);
447                fCurrentlyVisibleNamespaces.expand(namespaceId);
448                fCanonicalBindingSet.expand(namespaceId);               
449        fNamespaceToUriBindingTable.expand(namespaceId);
450        fNamespaceToPrefixBindingTable.expand(namespaceId);
451        fPrefixToNamespaceBindingTable.increaseBitCapacity(namespaceId);
452                fLocallyModifiedNamespaces.increaseBitCapacity(namespaceId);
453                fDistinctContextSet.increaseBitCapacity(namespaceId);
454        }
455
456FOUND_NAMESPACE_MAPPING:
457
458    // TODO: are declaring (or redeclaring) a namespace binding? or are we undeclaring it?
459
460    // map this prefix to the namespace and the URI back to the namespace
461    assert (fPrefixToNamespaceBindingTable.setCapacity() > prefixId);
462    assert (fPrefixToNamespaceBindingTable.bitCapacity() > namespaceId);
463    assert (fNamespaceToPrefixBindingTable.capacity() > namespaceId);
464    assert (fNamespaceToUriBindingTable.capacity() > namespaceId);
465
466    fPrefixToNamespaceBindingTable[prefixId] += namespaceId;
467    fNamespaceToPrefixBindingTable[namespaceId] = prefixId;   
468    fNamespaceToUriBindingTable[namespaceId] = uriId;
469
470    if (prefixId == uriId)
471        {
472        // if prefixId == uriId, then this entry is canonical
473                fCanonicalBindingSet += prefixId;
474        }
475        else
476        {
477        // else remove this prefixId from the canonical binding set
478                fCanonicalBindingSet -= prefixId;       
479        }
480
481        return namespaceId;
482}
483
484/// -----------------------------------------------------------------------------------------------
485
486IDISA_ALWAYS_INLINE
487void
488XMLNamespaceResolver::addPredefinedPrefix
489(
490    const gid_t id
491        , const XMLCh *         prefix
492        , const XMLSize_t       prefixLength
493        , const XMLCh *         uri
494        , const XMLSize_t       uriLength
495)
496{
497    DEBUG_MESSAGE("addPredefinedPrefix(" << id << ',' << prefix << ',' << uri << ')')
498
499
500        XMLPrefixEntry * entry = &fPrefixList[id];
501        // QUESTION: does storing the prefixes in the string pool help or hinder? we can just point to
502        // the symbols and store only the prefix's length?
503        // NOTE: this may require modifying the TraverseSchema class to do this safely.
504        entry->key = prefix; // _prefixAndUriStringPool.insert(prefix, length);
505        entry->length = prefixLength;
506        entry->id = id;
507
508        // create the namespace entry and add it
509    const gid_t uriId = fUriPool.add(id, uri, uriLength, fGlobalUriPool);
510
511    assert (id == uriId);
512
513    mapPrefixToUri(id, id);
514}
515
516/// -----------------------------------------------------------------------------------------------
517/// NAMESPACE CONTEXT HANDLING
518/// -----------------------------------------------------------------------------------------------
519
520void XMLNamespaceResolver::enterScope()
521{
522    fScope++;
523    #ifdef ALLOW_NAMESPACE_SCOPE_SPECULATION
524    const binding_t * locallyModified = fLocallyModifiedNamespaces.get(fCurrentScope);
525    fSpeculatedNamespaces = locallyModified;
526    fCurrentlyVisibleNamespaces ^= locallyModified;
527    #endif
528    fLocallyModifiedNamespaces[fScope] = 0;
529}
530
531gid_t XMLNamespaceResolver::finalizeScope(const bool isEmpty, const bool containedXmlnsAttribute)
532{
533    size_t contextId;
534    if (unlikely(containedXmlnsAttribute))
535    {
536        for (contextId = 0; contextId < fDistinctContextCount; contextId++)
537        {
538            if (fDistinctContextSet[contextId] == fCurrentlyVisibleNamespaces)
539            {               
540                goto FoundExistingContextId;
541            }
542        }
543
544        if (unlikely(fDistinctContextCount == fDistinctContextSet.setCapacity()))
545        {
546            fDistinctContextSet.increaseSetCapacity(fDistinctContextSet.setCapacity());
547        }
548        contextId = fDistinctContextCount++;
549        fDistinctContextSet.set(contextId, fCurrentlyVisibleNamespaces);
550    }
551    else
552    {
553        contextId = fCurrentContextId;
554    }
555
556FoundExistingContextId:
557
558    if (isEmpty)
559    {
560        if (unlikely(containedXmlnsAttribute))
561        {
562            // if this empty tag did not contain any xmlns attributes, then it's impossible for
563            // it to have modified the visible namespaces.
564            fCurrentlyVisibleNamespaces ^= fLocallyModifiedNamespaces.get(fScope);           
565        }
566        fScope--;
567    }
568    else
569    {
570        fCurrentContextId = contextId;
571        fContextIdStack[fScope] = contextId;
572    }
573    return contextId;
574}
575
576gid_t XMLNamespaceResolver::leaveScope(bool & namespaceContextChange)
577{
578    fCurrentlyVisibleNamespaces ^= fLocallyModifiedNamespaces.get(fScope--);
579    const gid_t contextId = fContextIdStack[fScope];
580    namespaceContextChange = (contextId != fCurrentContextId);
581    fCurrentContextId = contextId;
582    return contextId;
583}
584
585
586/// -----------------------------------------------------------------------------------------------
587
588IDISA_ALWAYS_INLINE
589BindingSetIterator XMLNamespaceResolver::getNamespaceIterator(const gid_t contextId) const
590{   
591    return BindingSetIterator(fDistinctContextSet[contextId]);
592}
593
594/// -----------------------------------------------------------------------------------------------
595
596IDISA_ALWAYS_INLINE
597MaskedBindingSetIterator XMLNamespaceResolver::getNamespaceIterator(const gid_t contextId0, const gid_t contextId1) const
598{
599    return MaskedBindingSetIterator(fDistinctContextSet[contextId0], fDistinctContextSet[contextId1], true);
600}
601
602/// -----------------------------------------------------------------------------------------------
603
604IDISA_ALWAYS_INLINE
605gid_t
606XMLNamespaceResolver::getSchemaNamespaceId()
607{
608    if (unlikely(fSchemaNamespaceId == XMLNamespaceResolver::fUnknownUriId))
609    {
610        fSchemaNamespaceId = fGlobalUriPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
611    }
612    return fSchemaNamespaceId;
613}
614
615/// -----------------------------------------------------------------------------------------------
616
617IDISA_ALWAYS_INLINE
618gid_t
619XMLNamespaceResolver::getNamespaceUriId(const gid_t namespaceId) const
620{
621    return fNamespaceToUriBindingTable[namespaceId];
622}
623
624/// -----------------------------------------------------------------------------------------------
625
626IDISA_ALWAYS_INLINE
627const XMLCh *
628XMLNamespaceResolver::getPrefixForNamespaceId(const gid_t namespaceId) const
629{
630    return getPrefixForId(fNamespaceToPrefixBindingTable[namespaceId]);
631}
632
633/// -----------------------------------------------------------------------------------------------
634
635IDISA_ALWAYS_INLINE
636const XMLCh *
637XMLNamespaceResolver::getUriForNamespaceId(const gid_t namespaceId) const
638{
639    return getUriForId(fNamespaceToUriBindingTable[namespaceId]);
640}
641
642/// -----------------------------------------------------------------------------------------------
643
644IDISA_ALWAYS_INLINE
645bool
646XMLNamespaceResolver::isPrefixVisible(const XMLCh * prefix, const gid_t contextId) const
647{
648    int colonPos;
649    const gid_t prefixId = resolvePrefixId(prefix, colonPos);
650        return isPrefixVisible(prefixId, contextId);
651}
652
653/// -----------------------------------------------------------------------------------------------
654
655IDISA_ALWAYS_INLINE
656bool
657XMLNamespaceResolver::isPrefixVisible(const gid_t prefixId) const
658{
659    if (unlikely(prefixId == XMLNamespaceResolver::fUnknownUriId))
660    {
661        return false;
662    }   
663    const int namespaceId = resolveNamespaceId(prefixId);
664
665    if (unlikely(namespaceId == -1))
666    {
667        return false;
668    }
669    else
670    {
671        return (getNamespaceUriId(namespaceId) != XMLNamespaceResolver::fUnknownUriId);
672    }
673}
674
675/// -----------------------------------------------------------------------------------------------
676
677IDISA_ALWAYS_INLINE
678bool
679XMLNamespaceResolver::isPrefixVisible(const gid_t prefixId, const gid_t contextId) const
680{
681    if (unlikely(prefixId == XMLNamespaceResolver::fUnknownUriId))
682    {
683        return false;
684    }
685
686    const gid_t namespaceId = fPrefixToNamespaceBindingTable[prefixId].first(fDistinctContextSet[contextId]);
687    if (unlikely(namespaceId == -1))
688    {
689        return false;
690    }
691    else
692    {
693        return (getNamespaceUriId(namespaceId) != XMLNamespaceResolver::fUnknownUriId);
694    }
695}
696
697/// -----------------------------------------------------------------------------------------------
698
699IDISA_ALWAYS_INLINE
700gid_t
701XMLNamespaceResolver::getUriIdForQName(const XMLCh * prefix, const gid_t contextId, int & colonPos) const
702{
703    gid_t prefixId = resolvePrefixId(prefix, colonPos);
704    return getUriIdForPrefix(prefixId, contextId);
705}
706
707/// -----------------------------------------------------------------------------------------------
708
709IDISA_ALWAYS_INLINE
710gid_t
711XMLNamespaceResolver::getUriIdForPrefix(const XMLCh * prefix, const gid_t contextId) const
712{
713    int colonPos;
714    return getUriIdForPrefix(resolvePrefixId(prefix, colonPos), contextId);
715}
716
717/// -----------------------------------------------------------------------------------------------
718
719IDISA_ALWAYS_INLINE
720gid_t
721XMLNamespaceResolver::getUriIdForPrefix(const gid_t prefixId, const gid_t contextId) const
722{
723    if (unlikely(prefixId == fUnknownUriId))
724    {
725        return fUnknownUriId;
726    }
727    MaskedBindingSetIterator namespaceItr(fDistinctContextSet[contextId], fPrefixToNamespaceBindingTable[prefixId], false);
728        if (unlikely(!namespaceItr.first()))
729        {
730                return fUnknownUriId;
731        }
732        return fNamespaceToUriBindingTable[namespaceItr.pos()];
733}
734
735/// -----------------------------------------------------------------------------------------------
736
737IDISA_ALWAYS_INLINE
738const XMLCh *
739XMLNamespaceResolver::getUriForQName(const XMLCh * prefix, const gid_t contextId, int & colonPos) const
740{
741    gid_t uriId = getUriIdForQName(prefix, contextId, colonPos);
742    return getUriForId(uriId);
743}
744
745
746/// -----------------------------------------------------------------------------------------------
747
748IDISA_ALWAYS_INLINE
749const XMLCh *
750XMLNamespaceResolver::getUriForPrefix(const XMLCh * prefix, const gid_t contextId) const
751{
752    int colonPos;
753    return getUriForPrefix(resolvePrefixId(prefix, colonPos), contextId);
754}
755
756/// -----------------------------------------------------------------------------------------------
757
758IDISA_ALWAYS_INLINE
759const XMLCh *
760XMLNamespaceResolver::getUriForPrefix(const gid_t prefixId, const gid_t contextId) const
761{   
762    return getUriForId(getUriIdForPrefix(prefixId, contextId));
763}
764
765/// -----------------------------------------------------------------------------------------------
766
767#ifdef PRINT_DEBUG_MESSAGE
768static std::ostream & operator << (std::ostream & out, const XMLNamespaceResolver * resolver)
769{
770        if (resolver)
771        {
772                char leadingChar = '{';
773                const XMLCh * uri;
774
775        for (gid_t uriId = 0; uriId < resolver->getUriCount(); uriId++)
776                {
777                        if ((uri = (*resolver)[uriId]) != 0)
778                        {
779                                out << leadingChar << uriId << ':' << uri;
780                                leadingChar = ',';
781                        }
782                }
783                if (leadingChar != '{')
784                {
785                        out << '}';
786                }
787        }
788        return out;
789}
790#endif
791
792XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.