source: icXML/icXML-devel/src/icxmlc/XMLNamespaceResolver.hpp @ 2774

Last change on this file since 2774 was 2774, checked in by cameron, 6 years ago

Various fixes

File size: 10.1 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.hpp 224 2012-12-12 03:31:56Z nigelm $
10 *
11 */
12
13#if !defined(XMLNAMESPACETABLE_H)
14#define XMLNAMESPACETABLE_H
15
16#include <icxmlc/HashTable.hpp>
17#include <xercesc/util/XMLUni.hpp>
18#include <icxmlc/stringpool.h>
19#include <xercesc/framework/MemoryManager.hpp>
20#include <icxercesc/util/XMLString.hpp>
21#include <xercesc/util/XMLUni.hpp>
22#include <icxercesc/util/QName.hpp>
23#include <icxmlc/XMLNamespaceBindingSet.hpp>
24#include <icxmlc/XMLStringHash.hpp>
25#include <icxmlc/XMLStringU.hpp>
26#include <icxmlc/XMLNamespaceUriTable.hpp>
27#include <xercesc/framework/XMLErrorCodes.hpp>
28#include <icxmlc/XMLConfig.hpp>
29
30XERCES_CPP_NAMESPACE_BEGIN
31
32class XMLNamespaceResolver;
33class XMLSynchronizedNamespaceResolver;
34class XMLNamespaceIterator;
35class XMLSymbol;
36class XMLScanner;
37
38#define DEFAULT_PREFIX_POOL_SIZE 256
39
40#ifdef PRINT_DEBUG_MESSAGE
41static std::ostream & operator << (std::ostream & out, const XMLNamespaceResolver * resolver);
42#endif
43
44/** --------------------------------------------------------------------------------------------------------- **/
45class XMLPrefixEntry
46{
47        friend class XMLNamespaceResolver;
48        friend class XMLSynchronizedNamespaceResolver;
49
50        protected:
51
52                const XMLCh *  key;
53                unsigned int   length;
54                unsigned int   id;
55
56                // QUESTION: should this contain a set of flags that indicates whether this prefix is XML, XMLNS, or is
57                // associated with a XSI uri? Or should this contain a list of associated symbols?
58
59        public:
60
61                XMLPrefixEntry()
62                : key(NULL)
63                , length(0)
64                , id(0)
65                {
66
67
68                }
69
70                const XMLCh * getKey() const { return key; }
71
72                unsigned int getLength() const { return length; }
73
74                unsigned int getId() const { return id; }
75
76                XMLPrefixEntry & operator=(const XMLPrefixEntry & other)
77                {
78                        key = other.key;
79                        length = other.length;
80                        id = other.id;
81                        return *this;
82                }
83
84                IDISA_ALWAYS_INLINE
85                bool equals(const XMLCh * otherKey, const unsigned int length) const
86                {
87                        // QUESTION: would a length based dispatch be preferable here? prefixes are likely relatively short
88            return (getLength() == length) && (XMLStringU::equals(otherKey, getKey(), length));
89                }
90};
91
92/// ---------------------------------------------------------------------------------------------------------
93
94class XMLNamespaceResolver
95{
96        friend class XMLSynchronizedNamespaceResolver;
97        friend class XMLNamespaceIterator;
98
99        public:
100
101                enum PredefinedNamespaces
102                {
103                        fUnknownUriId                   = -1
104                        , fEmptyUriId                   = 0
105                        , fXMLUriId                             = 1
106                        , fXMLNSUriId                   = 2
107                        , fSchemaInstanceUriId  = 3
108
109                        , fPredefinedCount              = 4
110                };
111
112                // TODO: would adding SchemaSymbols::fgURI_SCHEMAFORSCHEMA as a predefined (or pseudo-predefined) uri help?
113
114                XMLNamespaceResolver(XMLNamespaceResolver * parent, MemoryManager* manager)
115                        : fNextUnreservedPrefixId(fPredefinedCount)
116                        , fNextUnreservedUriId(fPredefinedCount)
117                        , fNextNamespaceId(0)
118                        , fPrefixCount(fPredefinedCount)
119                        , fCurrentScope(0)
120                        , fUriPool(manager)
121                        , fDistinctContextCount(0)
122                        , fCurrentContextId(0)
123                        , fGlobalUriPool(parent ? parent->fGlobalUriPool : new XMLGlobalNamespaceTable(manager))
124                        , fAdoptedGlobalUriPool(parent != 0)
125            , fPrefixPool(manager)
126                {
127                        addPredefinedPrefix(fEmptyUriId, XMLUni::fgZeroLenString, 0, XMLUni::fgZeroLenString, 0);
128                        addPredefinedPrefix(fXMLUriId, XMLUni::fgXMLString, 3, XMLUni::fgXMLURIName, 36);
129                        addPredefinedPrefix(fXMLNSUriId, XMLUni::fgXMLNSString, 5, XMLUni::fgXMLNSURIName, 29);
130                        addPredefinedPrefix(fSchemaInstanceUriId, SchemaSymbols::fgXSI, 3, SchemaSymbols::fgURI_XSI, 41);
131                        fCurrentlyVisibleNamespaces += fEmptyUriId;
132                        fCurrentlyVisibleNamespaces += fXMLUriId;
133                        fCurrentlyVisibleNamespaces += fXMLNSUriId;
134                }
135
136                ~XMLNamespaceResolver()
137                {
138                        if (!fAdoptedGlobalUriPool)
139                        {
140                                delete fGlobalUriPool;
141                        }
142                }
143
144        unsigned int bindNamespace(const XMLSymbol * symbol, const XMLCh * uri, const XMLSize_t length, bool & speculatedCorrectly, XMLErrs::Codes & bindingError);
145
146                void setEmptyUriId(const unsigned int uriId);
147
148                unsigned int resolveUriId(const XMLSymbol * symbol, const bool isAttribute) const;
149
150                unsigned int resolveUriId(const XMLSymbol * symbol, const bool isAttribute, bool & unknown) const;
151
152                unsigned int resolveUriId(const XMLCh * uri) const;
153
154                unsigned int resolveUriId(const QName * qName);
155
156                IDISA_ALWAYS_INLINE
157                void enterScope()
158                {
159                        ++fCurrentScope;
160                        if (unlikely(fCurrentScope == fLocallyModifiedNamespaces.setCapacity()))
161                        {
162                                fLocallyModifiedNamespaces.increaseSetCapacity(fLocallyModifiedNamespaces.setCapacity()); //horizontally
163                        }
164                        else
165                        {
166                                #ifdef ALLOW_NAMESPACE_SCOPE_SPECULATION
167                                const binding_t * locallyModified = fLocallyModifiedNamespaces.get(fCurrentScope);
168                                fSpeculatedNamespaces = locallyModified;
169                                fCurrentlyVisibleNamespaces ^= locallyModified;
170                                #endif
171                                fLocallyModifiedNamespaces[fCurrentScope] = 0;
172                        }
173                }
174
175                IDISA_ALWAYS_INLINE
176                void leaveScope()
177                {
178                        fCurrentlyVisibleNamespaces ^= fLocallyModifiedNamespaces.get(fCurrentScope--);
179                }
180
181                IDISA_ALWAYS_INLINE
182                void misspeculated()
183                {
184                        #ifdef ALLOW_NAMESPACE_SCOPE_SPECULATION
185                        fCurrentlyVisibleNamespaces ^= fSpeculatedNamespaces - fLocallyModifiedNamespaces[fCurrentScope];
186                        #endif
187                }
188
189                IDISA_ALWAYS_INLINE
190                int getScope()
191                {
192                        return fCurrentScope;
193                }
194
195        unsigned int getNamespaceUriId(const unsigned int namespaceId) const;
196
197        unsigned int getCurrentContextId();
198
199        BindingSetIterator getNamespaceIterator(const unsigned int contextId) const;
200
201        const XMLCh * getPrefixForNamespaceId(const unsigned int namespaceId) const;
202
203                bool isPrefixVisible(const XMLCh * prefix, const unsigned int contextId);
204
205                bool isPrefixVisible(const unsigned int prefixId, const unsigned int contextId);
206
207                const XMLCh * getUriForPrefix(const XMLCh * prefix, const unsigned int contextId);
208
209                const XMLCh * getUriForPrefix(const unsigned int prefixId, const unsigned int contextId);
210
211                unsigned int getUriIdForPrefix(const XMLCh * prefix, const unsigned int contextId);
212
213                unsigned int getUriIdForPrefix(const unsigned int prefixId, const unsigned int contextId);
214
215                unsigned int resolvePrefixId(const XMLCh * qName);
216
217        unsigned int resolvePrefixId(const XMLCh * qName, const XMLSize_t length);
218
219        unsigned int resolvePrefixId(const XMLCh * qName, const XMLSize_t length, int & colon);
220
221                const XMLCh * addOrFindPrefix(const XMLCh * qName);
222
223                const XMLCh * addOrFindLocalPart(const XMLCh * qName);
224
225                IDISA_ALWAYS_INLINE
226                const XMLCh * operator[](const int uriId) const
227                {
228            const XMLNamespaceEntry * entry = (*fGlobalUriPool)[uriId];
229            return entry->getKey();
230                }
231
232                IDISA_ALWAYS_INLINE
233                const XMLCh * getUriForId(const int uriId, const bool isAttribute = 0) const
234                {
235                        if (unlikely((isAttribute && (uriId == fEmptyUriId)) || (uriId == fUnknownUriId)))
236                        {
237                                return NULL;
238                        }
239                        const XMLCh * uri = (*this)[uriId];
240                        if (unlikely(!uri))
241                        {
242                                uri = XMLUni::fgZeroLenString;
243                        }
244                        return uri;
245                }
246
247                IDISA_ALWAYS_INLINE
248                size_t getUriCount() const
249                {
250                        return fGlobalUriPool->count();
251                }
252
253                IDISA_ALWAYS_INLINE
254                const XMLCh * getPrefixForId(const unsigned int prefixId) const
255                {
256                        // resolve the prefix id from the prefix; since this will not be required
257                        // very often, just iterate through a list.
258                        for (unsigned int index = 0; index < fPrefixCount; index++)
259                        {
260                                if (fPrefixList[index].id == prefixId)
261                                {
262                                        return fPrefixList[index].getKey();
263                                }
264                        }
265                        return XMLUni::fgZeroLenString;
266                }
267
268                IDISA_ALWAYS_INLINE
269                unsigned int getEmptyUriId() const
270                {
271                        bool unknown;
272                        return resolveUriId(fEmptyUriId, fEmptyUriId, unknown);
273                }
274
275                #ifdef PRINT_DEBUG_MESSAGE
276                friend std::ostream & operator << (std::ostream &, const XMLNamespaceResolver *);
277                #endif
278
279        private:
280
281                unsigned int resolveUriId(const unsigned int prefixId, const unsigned int defaultUriId, bool & unknown) const;
282
283                const XMLPrefixEntry * addOrFindPrefix(const XMLCh * prefix, const int length);
284
285        void resolveUri(const XMLCh * uri, const XMLSize_t length, const unsigned int preferredUriId, unsigned int & localUriId, unsigned int & globalUriId);
286
287        unsigned int mapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId);
288
289        unsigned int remapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId);
290
291                IDISA_ALWAYS_INLINE
292                int resolveNamespaceId(const unsigned int prefixId) const
293                {
294                        return fCurrentlyVisibleNamespaces.first(fPrefixToNamespaceBindingTable[prefixId]);
295                }
296
297                void addPredefinedPrefix(const unsigned int id, const XMLCh * prefix, const XMLSize_t prefixLength, const XMLCh * uri, const XMLSize_t uriLength);
298
299        private:
300
301                unsigned int                                                                                                    fNextUnreservedPrefixId;
302                unsigned int                                                                                                    fNextNamespaceId;
303                unsigned int                                                                                                    fPrefixCount;
304
305                BindingSet                                                                                                              fCurrentlyVisibleNamespaces;
306                BindingSet                                                                                                              fCanonicalBindingSet;
307                #ifdef ALLOW_NAMESPACE_SCOPE_SPECULATION
308                BindingSet                                                                                                              fSpeculatedNamespaces;
309                #endif
310
311                BindingSets<sizeof(hash_t) * 8>                                                                 fPrefixToNamespaceBindingTable;
312
313                DynamicArray<unsigned int, sizeof(hash_t) * 8>                                  fNamespaceToUriBindingTable;
314
315        DynamicArray<unsigned int, sizeof(hash_t) * 8>                                  fNamespaceToPrefixBindingTable;
316
317                unsigned int                                                                                                    fCurrentScope;
318
319                BindingSets<INITIAL_MAX_SCOPE>                                                                  fLocallyModifiedNamespaces;
320                DynamicArray<XMLPrefixEntry, sizeof(hash_t) * 8>                                fPrefixList;
321
322                // carry over variables
323                unsigned int                                                                                                    fNextUnreservedUriId;
324                XMLNamespaceTable                                                                                               fUriPool;
325
326                BindingSets<INITIAL_MAX_SCOPE>                                                                  fDistinctContextSet;
327                unsigned int                                                                                                    fDistinctContextCount;
328                unsigned int                                                                                                    fCurrentContextId;
329
330                XMLGlobalNamespaceTable * const                                                                 fGlobalUriPool;
331                const bool                                                                                                              fAdoptedGlobalUriPool;
332
333        StringPool<XMLCh, DEFAULT_PREFIX_POOL_SIZE>                     fPrefixPool;
334};
335
336XERCES_CPP_NAMESPACE_END
337
338#if !defined(XERCES_TMPLSINC)
339#include <icxmlc/XMLNamespaceResolver.c>
340#endif
341
342#endif // XMLNAMESPACETABLE_H
Note: See TracBrowser for help on using the repository browser.