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 207 2012-12-02 20:38:22Z robc $ |
---|
10 | * |
---|
11 | */ |
---|
12 | |
---|
13 | #include <icxmlc/XMLNamespaceResolver.hpp> |
---|
14 | #include <icxmlc/XMLSymbol.hpp> |
---|
15 | #include <icxmlc/XMLStringU.hpp> |
---|
16 | |
---|
17 | XERCES_CPP_NAMESPACE_BEGIN |
---|
18 | |
---|
19 | /// ----------------------------------------------------------------------------------------------- |
---|
20 | // TODO: should I store a localPartId for xmlns attributes? would the memory cost outweigh the performance gain? |
---|
21 | |
---|
22 | // TODO: if we bind a uri to a prefix and the binding is non-canonical but the canonical entry for the prefix is |
---|
23 | // empty, should we move the prefix into that entry and rewrite all of the symbols? it would require storing a |
---|
24 | // list of symbols per prefix or having a "moved" bitset to tell the resolver to update the symbol's binding. |
---|
25 | // would this be worth the effort? |
---|
26 | |
---|
27 | IDISA_ALWAYS_INLINE |
---|
28 | unsigned int |
---|
29 | XMLNamespaceResolver::bindNamespace(const XMLSymbol * symbol, const XMLCh * uri, const XMLSize_t length, bool & speculatedCorrectly, XMLErrs::Codes & bindingError) |
---|
30 | { |
---|
31 | // 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" |
---|
32 | // or fEmptyNamespaceId if the symbol is "xmlns" |
---|
33 | |
---|
34 | DEBUG_NAMESPACE_MESSAGE |
---|
35 | ( |
---|
36 | "XMLNamespaceResolver::bindNamespace(" |
---|
37 | << symbol |
---|
38 | << ",\"" << uri |
---|
39 | << "\"," << length |
---|
40 | << ',' << speculatedCorrectly |
---|
41 | << ')' |
---|
42 | ); |
---|
43 | |
---|
44 | const static unsigned int XMLNS_URI_ID_TABLE[2] = { XMLNamespaceResolver::fEmptyUriId, XMLNamespaceResolver::fXMLNSUriId }; |
---|
45 | |
---|
46 | const static XMLErrs::Codes BINDING_ERRORS[3] = { XMLErrs::NoError, XMLErrs::XMLURINotMatchXMLPrefix, XMLErrs::NoUseOfxmlnsURI }; |
---|
47 | |
---|
48 | const unsigned int xmlnsUriId = XMLNS_URI_ID_TABLE[symbol->isQualified()]; |
---|
49 | const unsigned int prefixId = symbol->getPrefixId(); |
---|
50 | |
---|
51 | unsigned int localUriId, globalUriId; |
---|
52 | resolveUri(uri, length, prefixId, localUriId, globalUriId); |
---|
53 | |
---|
54 | int namespaceId = resolveNamespaceId(prefixId); |
---|
55 | |
---|
56 | // is the XML URI being bound to some prefix other than "xml" or vice versa? OR was the XMLNS URI bound to some prefix? |
---|
57 | bindingError = BINDING_ERRORS[((prefixId == fXMLUriId) ^ (globalUriId == fXMLUriId)) | ((globalUriId == fXMLNSUriId) << 1)]; |
---|
58 | |
---|
59 | if (unlikely(bindingError != XMLErrs::NoError)) |
---|
60 | { |
---|
61 | return XMLNamespaceResolver::fUnknownUriId; |
---|
62 | } |
---|
63 | if (unlikely(namespaceId == -1)) |
---|
64 | { |
---|
65 | // both the prefixId and the uriId exist, but they are not mapped to one another. |
---|
66 | namespaceId = mapPrefixToUri(prefixId, localUriId, globalUriId); |
---|
67 | |
---|
68 | // add the new namespace to the namespace 'stack' |
---|
69 | fLocallyModifiedNamespaces[fCurrentScope] += namespaceId; |
---|
70 | |
---|
71 | // and mark it as visible |
---|
72 | fCurrentlyVisibleNamespaces += namespaceId; |
---|
73 | |
---|
74 | // since we speculated that the prefixId == globalUriId, if we find that this is not |
---|
75 | // true, then we have to re-resolve everything regarding this element. |
---|
76 | speculatedCorrectly &= (prefixId == globalUriId); |
---|
77 | } |
---|
78 | else |
---|
79 | { |
---|
80 | if (unlikely(fNamespaceToUriBindingTable[namespaceId] != globalUriId)) |
---|
81 | { |
---|
82 | remapPrefixToUri(prefixId, localUriId, globalUriId); |
---|
83 | speculatedCorrectly = 0; |
---|
84 | } |
---|
85 | } |
---|
86 | |
---|
87 | return xmlnsUriId; |
---|
88 | } |
---|
89 | |
---|
90 | /// ----------------------------------------------------------------------------------------------- |
---|
91 | |
---|
92 | IDISA_ALWAYS_INLINE |
---|
93 | unsigned int |
---|
94 | XMLNamespaceResolver::resolveUriId(const XMLSymbol * symbol, const bool isAttribute) const |
---|
95 | { |
---|
96 | bool unknown = 0; |
---|
97 | return resolveUriId(symbol, isAttribute, unknown); |
---|
98 | } |
---|
99 | |
---|
100 | /// ----------------------------------------------------------------------------------------------- |
---|
101 | |
---|
102 | IDISA_ALWAYS_INLINE |
---|
103 | unsigned int |
---|
104 | XMLNamespaceResolver::resolveUriId(const XMLSymbol * symbol, const bool isAttribute, bool & unknown) const |
---|
105 | { |
---|
106 | const unsigned int prefixId = symbol->getPrefixId(); |
---|
107 | |
---|
108 | DEBUG_NAMESPACE_MESSAGE("XMLNamespaceResolver::resolveUriId(" << symbol << ':' << prefixId << ',' << isAttribute << ',' << unknown << ')') |
---|
109 | |
---|
110 | if (isAttribute && (prefixId == fEmptyUriId)) |
---|
111 | { |
---|
112 | return fEmptyUriId; |
---|
113 | } |
---|
114 | return resolveUriId(prefixId, prefixId, unknown); |
---|
115 | } |
---|
116 | |
---|
117 | /// ----------------------------------------------------------------------------------------------- |
---|
118 | |
---|
119 | IDISA_ALWAYS_INLINE |
---|
120 | unsigned int |
---|
121 | XMLNamespaceResolver::resolveUriId(const unsigned int prefixId, const unsigned int defaultUriId, bool & unknown) const |
---|
122 | { |
---|
123 | unsigned int uriId = defaultUriId; |
---|
124 | // first check canonical set to see if this prefix id is also the uri id. |
---|
125 | if (likely(fCanonicalBindingSet.mask_and_extract(fCurrentlyVisibleNamespaces, prefixId))) |
---|
126 | { |
---|
127 | // TODO: investigate the value of having a canonical set that also states localId == globalId? |
---|
128 | uriId = fUriPool[prefixId]->getId(); |
---|
129 | } |
---|
130 | else |
---|
131 | { |
---|
132 | // it's not canonical; resolve which of the possible uri ids this prefix id |
---|
133 | // currently points to |
---|
134 | const int namespaceId = resolveNamespaceId(prefixId); |
---|
135 | |
---|
136 | // if this prefix has not been mapped to a namespace; assume that it will |
---|
137 | // be mapped to the 'adjacent' uri. |
---|
138 | |
---|
139 | if (likely(namespaceId != -1)) |
---|
140 | { |
---|
141 | uriId = fNamespaceToUriBindingTable[namespaceId]; |
---|
142 | } |
---|
143 | else |
---|
144 | { |
---|
145 | unknown = true; |
---|
146 | } |
---|
147 | } |
---|
148 | |
---|
149 | return uriId; |
---|
150 | } |
---|
151 | |
---|
152 | /// ----------------------------------------------------------------------------------------------- |
---|
153 | |
---|
154 | IDISA_ALWAYS_INLINE |
---|
155 | unsigned int |
---|
156 | XMLNamespaceResolver::resolveUriId(const XMLCh * uri) const |
---|
157 | { |
---|
158 | if (unlikely(!uri || *uri == 0)) |
---|
159 | { |
---|
160 | return fEmptyUriId; |
---|
161 | } |
---|
162 | |
---|
163 | XMLSize_t length = XMLStringU::stringLen(uri); |
---|
164 | |
---|
165 | unsigned int localUriId = fUriPool.find(uri, length); |
---|
166 | |
---|
167 | if (unlikely(localUriId == -1)) |
---|
168 | { |
---|
169 | XMLNamespaceResolver * self = const_cast<XMLNamespaceResolver*>(this); |
---|
170 | |
---|
171 | // no, it was already used; claim the next unused uri id. |
---|
172 | self->fNextUnreservedUriId = max(fNextUnreservedUriId, fNextUnreservedPrefixId); |
---|
173 | localUriId = self->fNextUnreservedUriId++; |
---|
174 | self->fGlobalUriPool->addOrFind(localUriId, uri, length, self->fUriPool); |
---|
175 | } |
---|
176 | |
---|
177 | return fUriPool[localUriId]->getId(); |
---|
178 | } |
---|
179 | |
---|
180 | |
---|
181 | /// ----------------------------------------------------------------------------------------------- |
---|
182 | |
---|
183 | IDISA_ALWAYS_INLINE |
---|
184 | unsigned int |
---|
185 | XMLNamespaceResolver::resolveUriId(const QName * qName) |
---|
186 | { |
---|
187 | const XMLCh * prefix = qName->getPrefix(); |
---|
188 | const int length = XMLStringU::stringLen(prefix); |
---|
189 | |
---|
190 | if (unlikely(length <= 0)) |
---|
191 | { |
---|
192 | return fEmptyUriId; |
---|
193 | } |
---|
194 | |
---|
195 | bool unknown; |
---|
196 | return resolveUriId(addOrFindPrefix(prefix, length)->getId(), fUnknownUriId, unknown); |
---|
197 | } |
---|
198 | |
---|
199 | /// ----------------------------------------------------------------------------------------------- |
---|
200 | |
---|
201 | IDISA_ALWAYS_INLINE |
---|
202 | unsigned int |
---|
203 | XMLNamespaceResolver::resolvePrefixId(const XMLCh * qName) |
---|
204 | { |
---|
205 | int length = XMLStringU::stringLenOrIndexOf<chColon>(qName); |
---|
206 | |
---|
207 | if (unlikely(length <= 0)) |
---|
208 | { |
---|
209 | return fEmptyUriId; |
---|
210 | } |
---|
211 | |
---|
212 | // if (XMLString::equals(attLocalName, XMLUni::fgXMLNSString)) |
---|
213 | // emitError(XMLErrs::NoUseOfxmlnsAsPrefix); |
---|
214 | // else if (XMLString::equals(attLocalName, XMLUni::fgXMLString)) |
---|
215 | // { |
---|
216 | // if (!XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) |
---|
217 | // emitError(XMLErrs::PrefixXMLNotMatchXMLURI); |
---|
218 | // } |
---|
219 | |
---|
220 | // if (!namespaceURI) |
---|
221 | // emitError(XMLErrs::NoEmptyStrNamespace, attName); |
---|
222 | // else if(!*namespaceURI && fXMLVersion == XMLReader::XMLV1_0) |
---|
223 | // emitError(XMLErrs::NoEmptyStrNamespace, attName); |
---|
224 | |
---|
225 | |
---|
226 | // get the prefix id of the prefix portion of the qName, e.g., the prefix id of "xmlns" if given "xmlns:ogc" |
---|
227 | // or the prefix of "" if given "xmlns". |
---|
228 | return addOrFindPrefix(qName, length)->getId(); |
---|
229 | } |
---|
230 | |
---|
231 | /// ----------------------------------------------------------------------------------------------- |
---|
232 | |
---|
233 | IDISA_ALWAYS_INLINE |
---|
234 | unsigned int XMLNamespaceResolver::resolvePrefixId(const XMLCh * qName, const XMLSize_t length, int & colon) |
---|
235 | { |
---|
236 | colon = XMLStringU::indexOf<chColon>(qName, length); |
---|
237 | |
---|
238 | assert (colon == XMLString::indexOf(qName, chColon)); |
---|
239 | |
---|
240 | return (unlikely(colon == -1)) ? fEmptyUriId : resolvePrefixId(qName, colon); |
---|
241 | } |
---|
242 | |
---|
243 | /// ----------------------------------------------------------------------------------------------- |
---|
244 | |
---|
245 | IDISA_ALWAYS_INLINE |
---|
246 | unsigned int XMLNamespaceResolver::resolvePrefixId(const XMLCh * qName, const XMLSize_t length) |
---|
247 | { |
---|
248 | return addOrFindPrefix(qName, length)->getId(); |
---|
249 | } |
---|
250 | |
---|
251 | /// ----------------------------------------------------------------------------------------------- |
---|
252 | |
---|
253 | IDISA_ALWAYS_INLINE |
---|
254 | const XMLCh * |
---|
255 | XMLNamespaceResolver::addOrFindPrefix(const XMLCh * qName) |
---|
256 | { |
---|
257 | int length = XMLStringU::stringLenOrIndexOf<chColon>(qName); |
---|
258 | if (unlikely(length <= 0)) |
---|
259 | { |
---|
260 | return XMLUni::fgZeroLenString; |
---|
261 | } |
---|
262 | // get the prefix id of the prefix portion of the qName, e.g., the prefix id of "xmlns" if given "xmlns:ogc" |
---|
263 | // or the prefix of "" if given "xmlns". |
---|
264 | return addOrFindPrefix(qName, length)->getKey(); |
---|
265 | |
---|
266 | } |
---|
267 | |
---|
268 | /// ----------------------------------------------------------------------------------------------- |
---|
269 | |
---|
270 | IDISA_ALWAYS_INLINE |
---|
271 | const XMLCh * |
---|
272 | XMLNamespaceResolver::addOrFindLocalPart(const XMLCh * qName) |
---|
273 | { |
---|
274 | int length = XMLStringU::stringLenOrIndexOf<chColon>(qName); |
---|
275 | if (qName[length] == chColon) |
---|
276 | { |
---|
277 | const XMLCh * localPart = &qName[length + 1]; |
---|
278 | length = XMLStringU::stringLen(localPart); |
---|
279 | return addOrFindPrefix(localPart, length)->getKey(); |
---|
280 | } |
---|
281 | else |
---|
282 | { |
---|
283 | return addOrFindPrefix(qName, length)->getKey(); |
---|
284 | } |
---|
285 | } |
---|
286 | |
---|
287 | /// ----------------------------------------------------------------------------------------------- |
---|
288 | |
---|
289 | IDISA_ALWAYS_INLINE |
---|
290 | const XMLPrefixEntry * |
---|
291 | XMLNamespaceResolver::addOrFindPrefix(const XMLCh * prefix, const int length) |
---|
292 | { |
---|
293 | |
---|
294 | |
---|
295 | // resolve the prefix id from the prefix; since this will not be required |
---|
296 | // very often, just iterate through a list. |
---|
297 | for (unsigned int index = 0; index < fPrefixCount; index++) |
---|
298 | { |
---|
299 | if (fPrefixList[index].equals(prefix, length)) |
---|
300 | { |
---|
301 | return &fPrefixList[index]; |
---|
302 | } |
---|
303 | } |
---|
304 | |
---|
305 | // if our prefix count equals our capacity, then we need to expand all of the related buffers |
---|
306 | if (unlikely(fPrefixCount == fPrefixList.capacity())) |
---|
307 | { |
---|
308 | fPrefixList.expand(fPrefixList.capacity()); |
---|
309 | } |
---|
310 | |
---|
311 | fNextUnreservedPrefixId = max(fNextUnreservedPrefixId, fNextUnreservedUriId); |
---|
312 | const unsigned int prefixId = fNextUnreservedPrefixId++; |
---|
313 | |
---|
314 | if (unlikely(fPrefixToNamespaceBindingTable.setCapacity() <= prefixId)) |
---|
315 | { |
---|
316 | DEBUG_NAMESPACE_MESSAGE(" *** expanding prefix tables from " << fPrefixToNamespaceBindingTable.setCapacity() << " due to prefixId " << prefixId) |
---|
317 | fCanonicalBindingSet.expand(prefixId); |
---|
318 | fPrefixToNamespaceBindingTable.increaseSetCapacity(prefixId); |
---|
319 | // fLocallyModifiedNamespaces.increaseBitCapacity(prefixId); |
---|
320 | } |
---|
321 | |
---|
322 | XMLPrefixEntry * entry = &fPrefixList[fPrefixCount++]; |
---|
323 | // QUESTION: does storing the prefixes in the string pool help or hinder? we can just point to |
---|
324 | // the symbols and store only the prefix's length? |
---|
325 | // NOTE: this may require modifying the TraverseSchema class to do this safely. |
---|
326 | entry->key = fPrefixPool.insert(prefix, length); |
---|
327 | entry->length = length; |
---|
328 | entry->id = prefixId; |
---|
329 | |
---|
330 | // add this entry to the canonical prefix set since we assume that the prefix and uri ids |
---|
331 | // will match |
---|
332 | fCanonicalBindingSet += prefixId; |
---|
333 | |
---|
334 | return entry; |
---|
335 | } |
---|
336 | |
---|
337 | /// ----------------------------------------------------------------------------------------------- |
---|
338 | |
---|
339 | IDISA_ALWAYS_INLINE |
---|
340 | void |
---|
341 | XMLNamespaceResolver::resolveUri(const XMLCh * uri, const XMLSize_t length, const unsigned int preferredUriId, unsigned int & localUriId, unsigned int & globalUriId) |
---|
342 | { |
---|
343 | localUriId = fUriPool.find(uri, length); |
---|
344 | if (unlikely(localUriId == -1)) |
---|
345 | { |
---|
346 | localUriId = preferredUriId; |
---|
347 | // is the reserved uri slot for this prefix still free? |
---|
348 | if (unlikely(fUriPool[preferredUriId]->getKey() != NULL)) |
---|
349 | { |
---|
350 | // no, it was already used; claim the next unused uri id. |
---|
351 | fNextUnreservedUriId = max(fNextUnreservedUriId, fNextUnreservedPrefixId); |
---|
352 | localUriId = fNextUnreservedUriId++; |
---|
353 | } |
---|
354 | |
---|
355 | globalUriId = fGlobalUriPool->addOrFind(localUriId, uri, length, fUriPool); |
---|
356 | } |
---|
357 | else |
---|
358 | { |
---|
359 | globalUriId = fUriPool[localUriId]->getId(); |
---|
360 | } |
---|
361 | } |
---|
362 | |
---|
363 | /// ----------------------------------------------------------------------------------------------- |
---|
364 | |
---|
365 | IDISA_ALWAYS_INLINE |
---|
366 | unsigned int |
---|
367 | XMLNamespaceResolver::mapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId) |
---|
368 | { |
---|
369 | unsigned int namespaceId; |
---|
370 | |
---|
371 | // I want to reserve the LOCAL uriId slot for this prefix; not the GLOBAL uriId slot! |
---|
372 | |
---|
373 | BindingSetIterator namespaceItr(fPrefixToNamespaceBindingTable.get(prefixId), fPrefixToNamespaceBindingTable.bitCapacity()); |
---|
374 | |
---|
375 | size_t count = 0; |
---|
376 | |
---|
377 | while (namespaceItr.next()) |
---|
378 | { |
---|
379 | count++; |
---|
380 | |
---|
381 | if (fNamespaceToUriBindingTable[namespaceItr.pos()] == globalUriId) |
---|
382 | { |
---|
383 | namespaceId = namespaceItr.pos(); |
---|
384 | |
---|
385 | goto FOUND_NAMESPACE_MAPPING; |
---|
386 | } |
---|
387 | } |
---|
388 | |
---|
389 | namespaceId = fNextNamespaceId++; |
---|
390 | |
---|
391 | if (fCurrentlyVisibleNamespaces.capacity() <= namespaceId) |
---|
392 | { |
---|
393 | DEBUG_NAMESPACE_MESSAGE(" *** expanding namespace space due to namespaceId " << fNextNamespaceId); |
---|
394 | fCurrentlyVisibleNamespaces.expand(namespaceId); |
---|
395 | fCanonicalBindingSet.expand(namespaceId); |
---|
396 | fNamespaceToUriBindingTable.expand(namespaceId); |
---|
397 | fLocallyModifiedNamespaces.increaseBitCapacity(namespaceId); |
---|
398 | fDistinctContextSet.increaseBitCapacity(namespaceId); |
---|
399 | } |
---|
400 | |
---|
401 | FOUND_NAMESPACE_MAPPING: |
---|
402 | |
---|
403 | |
---|
404 | // map this prefix to the namespace |
---|
405 | fPrefixToNamespaceBindingTable[prefixId] += namespaceId; |
---|
406 | |
---|
407 | fNamespaceToUriBindingTable[namespaceId] = globalUriId; |
---|
408 | |
---|
409 | if (prefixId == localUriId) |
---|
410 | { |
---|
411 | // if prefix id == uri id == namespace id, then this entry is canonical (again?) |
---|
412 | fCanonicalBindingSet += prefixId; |
---|
413 | } |
---|
414 | else |
---|
415 | { |
---|
416 | // else remove this prefix id from the canonical binding set (assuming it was ever in there) |
---|
417 | fCanonicalBindingSet -= prefixId; |
---|
418 | } |
---|
419 | |
---|
420 | return namespaceId; |
---|
421 | } |
---|
422 | |
---|
423 | /// ----------------------------------------------------------------------------------------------- |
---|
424 | |
---|
425 | IDISA_ALWAYS_INLINE |
---|
426 | unsigned int |
---|
427 | XMLNamespaceResolver::remapPrefixToUri(const unsigned int prefixId, const unsigned int localUriId, const unsigned int globalUriId) |
---|
428 | { |
---|
429 | const int namespaceId = mapPrefixToUri(prefixId, localUriId, globalUriId); |
---|
430 | |
---|
431 | const BindingSet modified = |
---|
432 | (fCurrentlyVisibleNamespaces & fPrefixToNamespaceBindingTable.get(prefixId)) + namespaceId; |
---|
433 | |
---|
434 | // mark any modified namespaces in the namespace 'stack' |
---|
435 | fLocallyModifiedNamespaces[fCurrentScope] += modified; |
---|
436 | |
---|
437 | // remove the old namespace/uri binding (if one exists) and add the new binding to the set of |
---|
438 | // currently visible namespaces |
---|
439 | fCurrentlyVisibleNamespaces ^= modified; |
---|
440 | |
---|
441 | return namespaceId; |
---|
442 | } |
---|
443 | |
---|
444 | /// ----------------------------------------------------------------------------------------------- |
---|
445 | |
---|
446 | IDISA_ALWAYS_INLINE |
---|
447 | void |
---|
448 | XMLNamespaceResolver::addPredefinedPrefix |
---|
449 | ( |
---|
450 | const unsigned int id |
---|
451 | , const XMLCh * prefix |
---|
452 | , const XMLSize_t prefixLength |
---|
453 | , const XMLCh * uri |
---|
454 | , const XMLSize_t uriLength |
---|
455 | ) |
---|
456 | { |
---|
457 | DEBUG_MESSAGE("XMLNamespaceResolver::addPredefinedPrefix(" << id << ',' << prefix << ',' << uri << ')'); |
---|
458 | |
---|
459 | XMLPrefixEntry * entry = &fPrefixList[id]; |
---|
460 | // QUESTION: does storing the prefixes in the string pool help or hinder? we can just point to |
---|
461 | // the symbols and store only the prefix's length? |
---|
462 | // NOTE: this may require modifying the TraverseSchema class to do this safely. |
---|
463 | entry->key = prefix; // _prefixAndUriStringPool.insert(prefix, length); |
---|
464 | entry->length = prefixLength; |
---|
465 | entry->id = id; |
---|
466 | |
---|
467 | // create the namespace entry and add it |
---|
468 | const unsigned int uriId = fGlobalUriPool->addOrFind(id, uri, uriLength, fUriPool); |
---|
469 | |
---|
470 | assert (id == uriId); |
---|
471 | |
---|
472 | mapPrefixToUri(id, id, id); |
---|
473 | } |
---|
474 | |
---|
475 | /// ----------------------------------------------------------------------------------------------- |
---|
476 | /// NAMESPACE CONTEXT HANDLING |
---|
477 | /// ----------------------------------------------------------------------------------------------- |
---|
478 | |
---|
479 | IDISA_ALWAYS_INLINE |
---|
480 | unsigned int |
---|
481 | XMLNamespaceResolver::getCurrentContextId() |
---|
482 | { |
---|
483 | if (unlikely(!fLocallyModifiedNamespaces[fCurrentScope].isEmpty())) |
---|
484 | { |
---|
485 | for (unsigned int index = 0; index < fDistinctContextCount; index++) |
---|
486 | { |
---|
487 | if (fDistinctContextSet[index] == fCurrentlyVisibleNamespaces) |
---|
488 | { |
---|
489 | fCurrentContextId = index; |
---|
490 | return index; |
---|
491 | } |
---|
492 | } |
---|
493 | if (unlikely(fDistinctContextCount == fDistinctContextSet.setCapacity())) |
---|
494 | { |
---|
495 | fDistinctContextSet.increaseSetCapacity(fDistinctContextSet.setCapacity()); |
---|
496 | } |
---|
497 | |
---|
498 | fCurrentContextId = fDistinctContextCount++; |
---|
499 | fDistinctContextSet.set(fCurrentContextId, fCurrentlyVisibleNamespaces); |
---|
500 | } |
---|
501 | return fCurrentContextId; |
---|
502 | } |
---|
503 | |
---|
504 | /// ----------------------------------------------------------------------------------------------- |
---|
505 | |
---|
506 | IDISA_ALWAYS_INLINE |
---|
507 | bool |
---|
508 | XMLNamespaceResolver::isPrefixVisible(const XMLCh * prefix, const unsigned int contextId) |
---|
509 | { |
---|
510 | const unsigned int prefixId = resolvePrefixId(prefix); |
---|
511 | return isPrefixVisible(prefixId, contextId); |
---|
512 | } |
---|
513 | |
---|
514 | /// ----------------------------------------------------------------------------------------------- |
---|
515 | |
---|
516 | IDISA_ALWAYS_INLINE |
---|
517 | bool |
---|
518 | XMLNamespaceResolver::isPrefixVisible(const unsigned int prefixId, const unsigned int contextId) |
---|
519 | { |
---|
520 | return !(fDistinctContextSet[contextId] & fPrefixToNamespaceBindingTable.get(prefixId)).isEmpty(); |
---|
521 | } |
---|
522 | |
---|
523 | /// ----------------------------------------------------------------------------------------------- |
---|
524 | |
---|
525 | IDISA_ALWAYS_INLINE |
---|
526 | unsigned int |
---|
527 | XMLNamespaceResolver::getUriIdForPrefix(const XMLCh * prefix, const unsigned int contextId) |
---|
528 | { |
---|
529 | return getUriIdForPrefix(resolvePrefixId(prefix), contextId); |
---|
530 | } |
---|
531 | |
---|
532 | /// ----------------------------------------------------------------------------------------------- |
---|
533 | |
---|
534 | IDISA_ALWAYS_INLINE |
---|
535 | unsigned int |
---|
536 | XMLNamespaceResolver::getUriIdForPrefix(const unsigned int prefixId, const unsigned int contextId) |
---|
537 | { |
---|
538 | FixedBindingSet bindings(fDistinctContextSet[contextId] & fPrefixToNamespaceBindingTable[prefixId]); |
---|
539 | BindingSetIterator namespaceItr(bindings); |
---|
540 | if (unlikely(!namespaceItr.first())) |
---|
541 | { |
---|
542 | return fUnknownUriId; |
---|
543 | } |
---|
544 | return fNamespaceToUriBindingTable[namespaceItr.pos()]; |
---|
545 | } |
---|
546 | |
---|
547 | /// ----------------------------------------------------------------------------------------------- |
---|
548 | |
---|
549 | IDISA_ALWAYS_INLINE |
---|
550 | const XMLCh * |
---|
551 | XMLNamespaceResolver::getUriForPrefix(const XMLCh * prefix, const unsigned int contextId) |
---|
552 | { |
---|
553 | return getUriForPrefix(resolvePrefixId(prefix), contextId); |
---|
554 | } |
---|
555 | |
---|
556 | /// ----------------------------------------------------------------------------------------------- |
---|
557 | |
---|
558 | IDISA_ALWAYS_INLINE |
---|
559 | const XMLCh * |
---|
560 | XMLNamespaceResolver::getUriForPrefix(const unsigned int prefixId, const unsigned int contextId) |
---|
561 | { |
---|
562 | return getUriForId(getUriIdForPrefix(prefixId, contextId)); |
---|
563 | } |
---|
564 | |
---|
565 | /// ----------------------------------------------------------------------------------------------- |
---|
566 | |
---|
567 | #ifdef PRINT_DEBUG_MESSAGE |
---|
568 | static std::ostream & operator << (std::ostream & out, const XMLNamespaceResolver * resolver) |
---|
569 | { |
---|
570 | if (resolver) |
---|
571 | { |
---|
572 | char leadingChar = '{'; |
---|
573 | const XMLCh * uri; |
---|
574 | |
---|
575 | for (unsigned int uriId = 0; uriId < resolver->fNextUnreservedUriId; uriId++) |
---|
576 | { |
---|
577 | if ((uri = (*resolver)[uriId]) != 0) |
---|
578 | { |
---|
579 | out << leadingChar << uriId << ':' << uri; |
---|
580 | leadingChar = ','; |
---|
581 | } |
---|
582 | } |
---|
583 | if (leadingChar != '{') |
---|
584 | { |
---|
585 | out << '}'; |
---|
586 | } |
---|
587 | } |
---|
588 | return out; |
---|
589 | } |
---|
590 | #endif |
---|
591 | |
---|
592 | XERCES_CPP_NAMESPACE_END |
---|