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

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

XAlignedMemory, path updates, config files

File size: 9.8 KB
RevLine 
[2720]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 207 2012-12-02 20:38:22Z robc $
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>
[2728]20#include <icxercesc/util/XMLString.hpp>
[2720]21#include <xercesc/util/XMLUni.hpp>
[2728]22#include <icxercesc/util/QName.hpp>
[2720]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
196                unsigned int getCurrentContextId();
197
198                bool isPrefixVisible(const XMLCh * prefix, const unsigned int contextId);
199
200                bool isPrefixVisible(const unsigned int prefixId, const unsigned int contextId);
201
202                const XMLCh * getUriForPrefix(const XMLCh * prefix, const unsigned int contextId);
203
204                const XMLCh * getUriForPrefix(const unsigned int prefixId, const unsigned int contextId);
205
206                unsigned int getUriIdForPrefix(const XMLCh * prefix, const unsigned int contextId);
207
208                unsigned int getUriIdForPrefix(const unsigned int prefixId, const unsigned int contextId);
209
210                unsigned int resolvePrefixId(const XMLCh * qName);
211
212        unsigned int resolvePrefixId(const XMLCh * qName, const XMLSize_t length);
213
214        unsigned int resolvePrefixId(const XMLCh * qName, const XMLSize_t length, int & colon);
215
216                const XMLCh * addOrFindPrefix(const XMLCh * qName);
217
218                const XMLCh * addOrFindLocalPart(const XMLCh * qName);
219
220                IDISA_ALWAYS_INLINE
221                const XMLCh * operator[](const int uriId) const
222                {
223            const XMLNamespaceEntry * entry = (*fGlobalUriPool)[uriId];
224            return entry->getKey();
225                }
226
227                IDISA_ALWAYS_INLINE
228                const XMLCh * getUriForId(const int uriId, const bool isAttribute = 0) const
229                {
230                        if (unlikely((isAttribute && (uriId == fEmptyUriId)) || (uriId == fUnknownUriId)))
231                        {
232                                return NULL;
233                        }
234                        const XMLCh * uri = (*this)[uriId];
235                        if (unlikely(!uri))
236                        {
237                                uri = XMLUni::fgZeroLenString;
238                        }
239                        return uri;
240                }
241
242                IDISA_ALWAYS_INLINE
243                size_t getUriCount() const
244                {
245                        return fGlobalUriPool->count();
246                }
247
248                IDISA_ALWAYS_INLINE
249                const XMLCh * getPrefixForId(const unsigned int prefixId) const
250                {
251                        // resolve the prefix id from the prefix; since this will not be required
252                        // very often, just iterate through a list.
253                        for (unsigned int index = 0; index < fPrefixCount; index++)
254                        {
255                                if (fPrefixList[index].id == prefixId)
256                                {
257                                        return fPrefixList[index].getKey();
258                                }
259                        }
260                        return XMLUni::fgZeroLenString;
261                }
262
263                IDISA_ALWAYS_INLINE
264                unsigned int getEmptyUriId() const
265                {
266                        bool unknown;
267                        return resolveUriId(fEmptyUriId, fEmptyUriId, unknown);
268                }
269
270                #ifdef PRINT_DEBUG_MESSAGE
271                friend std::ostream & operator << (std::ostream &, const XMLNamespaceResolver *);
272                #endif
273
274        private:
275
276                unsigned int resolveUriId(const unsigned int prefixId, const unsigned int defaultUriId, bool & unknown) const;
277
278                const XMLPrefixEntry * addOrFindPrefix(const XMLCh * prefix, const int length);
279
280        void resolveUri(const XMLCh * uri, const XMLSize_t length, const unsigned int preferredUriId, unsigned int & localUriId, unsigned int & globalUriId);
281
282        unsigned int mapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId);
283
284        unsigned int remapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId);
285
286                IDISA_ALWAYS_INLINE
287                int resolveNamespaceId(const unsigned int prefixId) const
288                {
289                        return fCurrentlyVisibleNamespaces.first(fPrefixToNamespaceBindingTable[prefixId]);
290                }
291
292                void addPredefinedPrefix(const unsigned int id, const XMLCh * prefix, const XMLSize_t prefixLength, const XMLCh * uri, const XMLSize_t uriLength);
293
294        private:
295
296                unsigned int                                                                                                    fNextUnreservedPrefixId;
297                unsigned int                                                                                                    fNextNamespaceId;
298                unsigned int                                                                                                    fPrefixCount;
299
300                BindingSet                                                                                                              fCurrentlyVisibleNamespaces;
301                BindingSet                                                                                                              fCanonicalBindingSet;
302                #ifdef ALLOW_NAMESPACE_SCOPE_SPECULATION
303                BindingSet                                                                                                              fSpeculatedNamespaces;
304                #endif
305
306                BindingSets<sizeof(hash_t) * 8>                                                                 fPrefixToNamespaceBindingTable;
307
308                DynamicArray<unsigned int, sizeof(hash_t) * 8>                                  fNamespaceToUriBindingTable;
309
310                unsigned int                                                                                                    fCurrentScope;
311
312                BindingSets<INITIAL_MAX_SCOPE>                                                                  fLocallyModifiedNamespaces;
313                DynamicArray<XMLPrefixEntry, sizeof(hash_t) * 8>                                fPrefixList;
314
315                // carry over variables
316                unsigned int                                                                                                    fNextUnreservedUriId;
317                XMLNamespaceTable                                                                                               fUriPool;
318
319                BindingSets<INITIAL_MAX_SCOPE>                                                                  fDistinctContextSet;
320                unsigned int                                                                                                    fDistinctContextCount;
321                unsigned int                                                                                                    fCurrentContextId;
322
323                XMLGlobalNamespaceTable * const                                                                 fGlobalUriPool;
324                const bool                                                                                                              fAdoptedGlobalUriPool;
325
326        StringPool<XMLCh, DEFAULT_PREFIX_POOL_SIZE>                     fPrefixPool;
327};
328
329XERCES_CPP_NAMESPACE_END
330
331#if !defined(XERCES_TMPLSINC)
332#include <icxmlc/XMLNamespaceResolver.c>
333#endif
334
335#endif // XMLNAMESPACETABLE_H
Note: See TracBrowser for help on using the repository browser.