source: icXML/icXML-devel/src/xercesc/validators/schema/identity/XercesXPath.cpp @ 3565

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

Updates to xercesc sources

File size: 52.2 KB
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: XercesXPath.cpp 903997 2010-01-28 08:28:06Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/validators/schema/identity/XercesXPath.hpp>
26#include <xercesc/validators/schema/identity/XPathSymbols.hpp>
27#include <xercesc/validators/schema/identity/XPathException.hpp>
28#include <icxercesc/validators/schema/NamespaceScope.hpp>
29#include <xercesc/util/StringPool.hpp>
30#include <xercesc/util/Janitor.hpp>
31#include <icxercesc/framework/XMLBuffer.hpp>
32#include <icxercesc/internal/XMLReader.hpp>
33#include <xercesc/util/RuntimeException.hpp>
34#include <xercesc/util/OutOfMemoryException.hpp>
35
36#include <xercesc/internal/XTemplateSerializer.hpp>
37
38XERCES_CPP_NAMESPACE_BEGIN
39
40
41// ---------------------------------------------------------------------------
42//  Static data
43// ---------------------------------------------------------------------------
44const XMLByte XPathScanner::fASCIICharMap[128] =
45{
46    0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  2,  0,  0,
47    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
48    2,  3,  4,  1,  5,  1,  1,  4,  6,  7,  8,  9, 10, 11, 12, 13,
49    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,  1, 16, 17, 18,  1,
50    19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
51    20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,  1, 22,  1, 23,
52    1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
53    20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  1, 24,  1,  1,  1
54};
55
56
57// ---------------------------------------------------------------------------
58//  XercesNodeTest: Constructors and Destructor
59// ---------------------------------------------------------------------------
60XercesNodeTest::XercesNodeTest(const short aType, XMLStringPool * const qNameManager, MemoryManager* const manager)
61: fType(aType)
62, fName(new (manager) QName(qNameManager))
63{
64}
65
66XercesNodeTest::XercesNodeTest(const XMLCh* const prefix, const unsigned int uriId, XMLStringPool* const qNameManager, MemoryManager* const manager)
67: fType(NodeType_NAMESPACE)
68, fName(new (manager) QName(prefix, XMLUni::fgZeroLenString, uriId, qNameManager))
69{
70
71}
72
73
74XercesNodeTest::XercesNodeTest(const QName* const qName)
75: fType(NodeType_QNAME)
76, fName(new (qName->getMemoryManager()) QName(*qName))
77{
78
79}
80
81XercesNodeTest::XercesNodeTest(const XercesNodeTest& other)
82: XSerializable(other)
83, XMemory(other)
84, fType(other.fType)
85, fName(new ((other.fName)->getMemoryManager()) QName(*other.fName))
86{
87
88}
89
90XercesNodeTest::XercesNodeTest(const short, MemoryManager* const)
91{
92    DEPRECATED_FEATURE_IN_ICXML;
93}
94
95XercesNodeTest::XercesNodeTest(const XMLCh* const, const unsigned int, MemoryManager* const)
96{
97    DEPRECATED_FEATURE_IN_ICXML;
98}
99
100
101/***
102 * Support for Serialization/De-serialization
103 ***/
104
105IMPL_XSERIALIZABLE_TOCREATE(XercesNodeTest)
106
107void XercesNodeTest::serialize(XSerializeEngine& serEng)
108{
109
110    if (serEng.isStoring())
111    {
112        serEng<<fType;
113        serEng<<fName;
114    }
115    else
116    {
117        serEng>>fType;
118        serEng>>fName;
119    }
120}
121
122XercesNodeTest::XercesNodeTest(MemoryManager* const)
123:fType(NodeType_UNKNOWN)
124,fName(0)
125{
126}
127
128// ---------------------------------------------------------------------------
129//  XercesNodeTest: Operators
130// ---------------------------------------------------------------------------
131XercesNodeTest& XercesNodeTest::operator=(const XercesNodeTest& other)
132{
133    if (this == &other)
134        return *this;
135
136    fType = other.fType;
137    fName->setValues(*(other.fName));
138    return *this;
139}
140
141bool XercesNodeTest::operator ==(const XercesNodeTest& other) const {
142
143    if (this == &other)
144        return true;
145
146    if (fType != other.fType)
147        return false;
148
149    return (*fName == *(other.fName));
150}
151
152
153bool XercesNodeTest::operator !=(const XercesNodeTest& other) const {
154
155    return !operator==(other);
156}
157
158// ---------------------------------------------------------------------------
159//  XercesStep: Constructors and Destructor
160// ---------------------------------------------------------------------------
161XercesStep::XercesStep(const unsigned short axisType, XercesNodeTest* const nodeTest)
162    : fAxisType(axisType)
163    , fNodeTest(nodeTest)
164{
165}
166
167XercesStep::XercesStep(const XercesStep& other)
168    : XSerializable(other)
169    , XMemory(other)
170    , fAxisType(other.fAxisType)
171    , fNodeTest(0)
172{
173    fNodeTest = new (other.fNodeTest->getName()->getMemoryManager()) XercesNodeTest(*(other.fNodeTest));
174}
175
176
177// ---------------------------------------------------------------------------
178//  XercesStep: Operators
179// ---------------------------------------------------------------------------
180XercesStep& XercesStep::operator=(const XercesStep& other)
181{
182    if (this == &other)
183        return *this;
184
185    fAxisType = other.fAxisType;
186    *fNodeTest = *(other.fNodeTest);
187    return *this;
188}
189
190bool XercesStep::operator==(const XercesStep& other) const {
191
192    if (this == &other)
193        return true;
194
195    if (fAxisType != other.fAxisType)
196        return false;
197
198    if (fAxisType == XercesStep::AxisType_CHILD ||
199        fAxisType == XercesStep::AxisType_ATTRIBUTE) {
200        return (*fNodeTest == *(other.fNodeTest));
201    }
202
203    return true;
204}
205
206bool XercesStep::operator!=(const XercesStep& other) const {
207
208    return !operator==(other);
209}
210
211/***
212 * Support for Serialization/De-serialization
213 ***/
214
215IMPL_XSERIALIZABLE_TOCREATE(XercesStep)
216
217void XercesStep::serialize(XSerializeEngine& serEng)
218{
219    if (serEng.isStoring())
220    {
221        serEng<<(int)fAxisType;
222        serEng<<fNodeTest;
223    }
224    else
225    {
226        int i;
227        serEng>>i;
228        fAxisType = (unsigned short) i;
229
230        serEng>>fNodeTest;
231    }
232}
233
234XercesStep::XercesStep(MemoryManager* const)
235:fAxisType(AxisType_UNKNOWN)
236,fNodeTest(0)
237{
238}
239
240// ---------------------------------------------------------------------------
241//  XercesLocationPath: Constructors and Destructor
242// ---------------------------------------------------------------------------
243XercesLocationPath::XercesLocationPath(RefVectorOf<XercesStep>* const steps)
244    : fSteps(steps)
245{
246}
247
248// ---------------------------------------------------------------------------
249//  XercesLocationPath: Operators
250// ---------------------------------------------------------------------------
251bool XercesLocationPath::operator==(const XercesLocationPath& other) const {
252
253    XMLSize_t stepsSize = fSteps->size();
254
255    if (stepsSize != other.fSteps->size())
256        return false;
257
258    for (XMLSize_t i=0; i < stepsSize; i++) {
259        if (*(fSteps->elementAt(i)) != *(other.fSteps->elementAt(i)))
260            return false;
261    }
262
263    return true;
264}
265
266bool XercesLocationPath::operator!=(const XercesLocationPath& other) const {
267
268    return !operator==(other);
269}
270
271/***
272 * Support for Serialization/De-serialization
273 ***/
274
275IMPL_XSERIALIZABLE_TOCREATE(XercesLocationPath)
276
277void XercesLocationPath::serialize(XSerializeEngine& serEng)
278{
279    if (serEng.isStoring())
280    {
281        /***
282         * Serialize RefVectorOf<XercesStep>* fSteps;
283         ***/
284        XTemplateSerializer::storeObject(fSteps, serEng);
285    }
286    else
287    {
288        /***
289         * Deserialize RefVectorOf<XercesStep>* fSteps;
290         ***/
291        XTemplateSerializer::loadObject(&fSteps, 8, true, serEng);
292    }
293}
294
295XercesLocationPath::XercesLocationPath(MemoryManager* const)
296:fSteps(0)
297{
298}
299
300typedef JanitorMemFunCall<XercesXPath>  CleanupType;
301
302// ---------------------------------------------------------------------------
303//  XercesPath: Constructors and Destructor
304// ---------------------------------------------------------------------------
305XercesXPath::XercesXPath(const XMLCh* const xpathExpr,
306                         XMLStringPool* const stringPool,
307                         XercesNamespaceResolver* const scopeContext,
308                         const unsigned int emptyNamespaceId,
309                         const bool isSelector,
310                         MemoryManager* const manager)
311    : fEmptyNamespaceId(emptyNamespaceId)
312    , fExpression(0)
313    , fLocationPaths(0)
314    , fMemoryManager(manager)
315{
316    CleanupType cleanup(this, &XercesXPath::cleanUp);
317
318    try
319    {
320        fExpression = XMLString::replicate(xpathExpr, fMemoryManager);
321        parseExpression(stringPool, scopeContext);
322
323        if (isSelector) {
324            checkForSelectedAttributes();
325        }
326    }
327    catch(const OutOfMemoryException&)
328    {
329        cleanup.release();
330
331        throw;
332    }
333
334    cleanup.release();
335}
336
337XercesXPath::~XercesXPath() {
338    cleanUp();
339}
340
341
342// ---------------------------------------------------------------------------
343//  XercesXPath: Operators
344// ---------------------------------------------------------------------------
345bool XercesXPath::operator==(const XercesXPath& other) const {
346
347    XMLSize_t locPathSize = fLocationPaths->size();
348
349    if (locPathSize != other.fLocationPaths->size())
350        return false;
351
352    for (XMLSize_t i=0; i < locPathSize; i++) {
353        if (*(fLocationPaths->elementAt(i)) != *(other.fLocationPaths->elementAt(i)))
354            return false;
355    }
356
357    return true;
358}
359
360bool XercesXPath::operator!=(const XercesXPath& other) const {
361
362    return !operator==(other);
363}
364
365// ---------------------------------------------------------------------------
366//  XercesPath: Helper methods
367// ---------------------------------------------------------------------------
368void XercesXPath::cleanUp() {
369
370    fMemoryManager->deallocate(fExpression);//delete [] fExpression;
371    delete fLocationPaths;
372}
373
374void XercesXPath::checkForSelectedAttributes() {
375
376    // verify that an attribute is not selected
377    XMLSize_t locSize = (fLocationPaths) ? fLocationPaths->size() : 0;
378
379    for (XMLSize_t i = 0; i < locSize; i++) {
380
381        XercesLocationPath* locPath = fLocationPaths->elementAt(i);
382        XMLSize_t stepSize = locPath->getStepSize();
383
384        if (stepSize) {
385            if (locPath->getStep(stepSize - 1)->getAxisType() == XercesStep::AxisType_ATTRIBUTE) {
386                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoAttrSelector, fMemoryManager);
387            }
388                }
389    }
390}
391
392void XercesXPath::parseExpression(XMLStringPool* const stringPool,
393                                  XercesNamespaceResolver* const scopeContext) {
394
395    XMLSize_t length = XMLString::stringLen(fExpression);
396
397    if (!length) {
398        return;
399    }
400
401    ValueVectorOf<int>                tokens(16, fMemoryManager);
402    XPathScannerForSchema             scanner(stringPool);
403    if(!scanner.scanExpression(fExpression, 0, length, &tokens))
404        ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, fMemoryManager);
405
406    bool                              firstTokenOfLocationPath=true;
407    XMLSize_t                         tokenCount = tokens.size();
408    RefVectorOf<XercesStep>*          stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
409    Janitor<RefVectorOf<XercesStep> > janSteps(stepsVector);
410
411    if (tokenCount) {
412        fLocationPaths = new (fMemoryManager) RefVectorOf<XercesLocationPath>(8, true, fMemoryManager);
413    }
414
415    for (XMLSize_t i = 0; i < tokenCount; i++) {
416
417        int  aToken = tokens.elementAt(i);
418        bool isNamespace=false;
419
420        switch (aToken) {
421        case  XercesXPath::EXPRTOKEN_OPERATOR_UNION:
422            {
423                if (i == 0) {
424                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtStart, fMemoryManager);
425                }
426
427                XMLSize_t stepsSize = stepsVector->size();
428
429                if (stepsSize == 0) {
430                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoMultipleUnion, fMemoryManager);
431                }
432
433                if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
434                {
435                    // prepend ./
436                    XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, stringPool, fMemoryManager);
437                    XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
438                    stepsVector->insertElementAt(step, 0);
439                }
440                XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
441                janSteps.orphan();
442                bool bFound=false;
443                for(XMLSize_t i=0;i<fLocationPaths->size();i++)
444                    if((*(fLocationPaths->elementAt(i)))==(*newPath))
445                    {
446                        bFound=true;
447                        break;
448                    }
449                if(bFound)
450                    delete newPath;
451                else
452                    fLocationPaths->addElement(newPath);
453                stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
454                janSteps.reset(stepsVector);
455                firstTokenOfLocationPath = true;
456            }
457            break;
458        case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE:
459            {
460                // consume "::" token and drop through
461                i++;
462            }
463        case XercesXPath::EXPRTOKEN_ATSIGN:
464            {
465                // consume QName token
466                if (i == tokenCount - 1) {
467                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_MissingAttr, fMemoryManager);
468                }
469
470                aToken = tokens.elementAt(++i);
471
472                if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME
473                    && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY
474                    && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) {
475                        ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedToken1, fMemoryManager);
476                }
477
478                bool isNamespaceAtt=false;
479
480                switch (aToken) {
481
482                case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
483                    {
484                        XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, stringPool, fMemoryManager);
485                        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
486                        stepsVector->addElement(step);
487                        break;
488                    }
489                case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
490                    {
491                        isNamespaceAtt = true;
492                    }
493                case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
494                    {
495                        aToken = tokens.elementAt(++i);
496
497                        const XMLCh* prefix = XMLUni::fgZeroLenString;
498                        unsigned int uri = fEmptyNamespaceId;
499
500                        if (scopeContext && aToken != -1) {
501
502                            prefix = stringPool->getValueForId(aToken);
503                            uri = scopeContext->getNamespaceForPrefix(prefix);
504                        }
505
506                        if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
507                            ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
508                        }
509
510                        if (isNamespaceAtt) {
511
512                            // build step
513                            XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, stringPool, fMemoryManager);
514                            XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
515                            stepsVector->addElement(step);
516                            break;
517                        }
518
519                        aToken = tokens.elementAt(++i);
520
521                        const XMLCh* localPart = stringPool->getValueForId(aToken);
522                        QName aQName(prefix, localPart, uri, stringPool);
523
524                        // build step
525                        XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
526                        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
527                        stepsVector->addElement(step);
528                        break;
529                    }
530                                }
531
532                firstTokenOfLocationPath=false;
533                break;
534            }
535        case XercesXPath::EXPRTOKEN_DOUBLE_COLON:
536            {
537                // should never have a bare double colon
538                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleColon, fMemoryManager);
539            }
540        case XercesXPath::EXPRTOKEN_AXISNAME_CHILD:
541            {
542                // consume "::" token and drop through
543                i++;
544
545                if (i == tokenCount - 1) {
546                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep1, fMemoryManager);
547                }
548
549                firstTokenOfLocationPath=false;
550                break;
551            }
552        case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
553            {
554                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, stringPool, fMemoryManager);
555                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
556                stepsVector->addElement(step);
557                firstTokenOfLocationPath = false;
558                break;
559            }
560        case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
561            {
562                isNamespace=true;
563            }
564        case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
565            {
566                // consume QName token
567                aToken = tokens.elementAt(++i);
568
569                const XMLCh* prefix = XMLUni::fgZeroLenString;
570                unsigned int uri = fEmptyNamespaceId;
571
572                if (scopeContext && aToken != -1) {
573
574                    prefix = stringPool->getValueForId(aToken);
575                    uri = scopeContext->getNamespaceForPrefix(prefix);
576                }
577
578                if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
579                    ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
580                }
581
582                if (isNamespace) {
583
584                    // build step
585                    XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, stringPool, fMemoryManager);
586                    XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
587                    stepsVector->addElement(step);
588                    break;
589                }
590
591                aToken = tokens.elementAt(++i);
592                const XMLCh* localPart = stringPool->getValueForId(aToken);
593                QName aQName(prefix, localPart, uri, stringPool);
594
595                // build step
596                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
597                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
598                stepsVector->addElement(step);
599                firstTokenOfLocationPath = false;
600                break;
601            }
602        case XercesXPath::EXPRTOKEN_PERIOD:
603            {
604                // build step
605                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, stringPool, fMemoryManager);
606                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
607                stepsVector->addElement(step);
608
609                if (firstTokenOfLocationPath && i+1 < tokenCount) {
610
611                    aToken = tokens.elementAt(i+1);
612
613                    if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){
614
615                        if (++i == tokenCount - 1) {
616                            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep2, fMemoryManager);
617                        }
618
619                        if (i+1 < tokenCount)   {
620
621                            aToken = tokens.elementAt(i+1);
622
623                            if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) {
624                                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlash, fMemoryManager);
625                            }
626                        }
627                        // build step
628                        nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, stringPool, fMemoryManager);
629                        step = new (fMemoryManager) XercesStep(XercesStep::AxisType_DESCENDANT, nodeTest);
630                        stepsVector->addElement(step);
631                    }
632                }
633                firstTokenOfLocationPath=false;
634                break;
635            }
636        case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
637            {
638                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash, fMemoryManager);
639            }
640        case XercesXPath::EXPRTOKEN_OPERATOR_SLASH:
641            {
642                if (i == 0) {
643                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart, fMemoryManager);
644                }
645
646                // keep on truckin'
647                if (firstTokenOfLocationPath) {
648                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoSelectionOfRoot, fMemoryManager);
649                }
650
651                if (i == tokenCount - 1) {
652                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
653                }
654
655                aToken = tokens.elementAt(i+1);
656                if(aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION)
657                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
658
659                firstTokenOfLocationPath=false;
660                break;
661            }
662        default:
663            firstTokenOfLocationPath=false;
664        }
665    }
666
667    XMLSize_t stepsSize = stepsVector->size();
668
669    if (stepsSize == 0) {
670        if (!fLocationPaths || fLocationPaths->size() == 0) {
671            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_EmptyExpr, fMemoryManager);
672        }
673        else {
674            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtEnd, fMemoryManager);
675        }
676    }
677
678    if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
679    {
680        // prepend ./
681        XercesNodeTest * nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, stringPool, fMemoryManager);
682        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
683        stepsVector->insertElementAt(step, 0);
684    }
685    XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
686    janSteps.orphan();
687    bool bFound=false;
688    for(XMLSize_t j=0;j<fLocationPaths->size();j++)
689        if((*(fLocationPaths->elementAt(j)))==(*newPath))
690        {
691            bFound=true;
692            break;
693        }
694    if(bFound)
695        delete newPath;
696    else
697        fLocationPaths->addElement(newPath);
698}
699
700/***
701 * Support for Serialization/De-serialization
702 ***/
703
704IMPL_XSERIALIZABLE_TOCREATE(XercesXPath)
705
706void XercesXPath::serialize(XSerializeEngine& serEng)
707{
708
709    if (serEng.isStoring())
710    {
711        serEng<<fEmptyNamespaceId;
712        serEng.writeString(fExpression);
713
714        /***
715         * Serialize RefVectorOf<XercesLocationPath>* fLocationPaths;
716         ***/
717        XTemplateSerializer::storeObject(fLocationPaths, serEng);
718    }
719    else
720    {
721        serEng>>fEmptyNamespaceId;
722        serEng.readString(fExpression);
723
724        /***
725         * Deserialize RefVectorOf<XercesLocationPath>* fLocationPaths;
726         ***/
727        XTemplateSerializer::loadObject(&fLocationPaths, 8, true, serEng);
728    }
729}
730
731XercesXPath::XercesXPath(MemoryManager* const manager)
732:fEmptyNamespaceId(0)
733,fExpression(0)
734,fLocationPaths(0)
735,fMemoryManager(manager)
736{
737}
738
739// ---------------------------------------------------------------------------
740//  XPathScanner: Constructors and Destructor
741// ---------------------------------------------------------------------------
742XPathScanner::XPathScanner(XMLStringPool* const stringPool)
743    : fAndSymbol (0)
744    , fOrSymbol(0)
745    , fModSymbol(0)
746    , fDivSymbol(0)
747    , fCommentSymbol(0)
748    , fTextSymbol(0)
749    , fPISymbol(0)
750    , fNodeSymbol(0)
751    , fAncestorSymbol(0)
752    , fAncestorOrSelfSymbol(0)
753    , fAttributeSymbol(0)
754    , fChildSymbol(0)
755    , fDescendantSymbol(0)
756    , fDescendantOrSelfSymbol(0)
757    , fFollowingSymbol(0)
758    , fFollowingSiblingSymbol(0)
759    , fNamespaceSymbol(0)
760    , fParentSymbol(0)
761    , fPrecedingSymbol(0)
762    , fPrecedingSiblingSymbol(0)
763    , fSelfSymbol(0)
764    , fStringPool(stringPool)
765{
766    init();
767}
768
769// ---------------------------------------------------------------------------
770//  XPathScanner: Helper methods
771// ---------------------------------------------------------------------------
772void XPathScanner::init() {
773
774    fAndSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_AND);
775    fOrSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_OR);
776    fModSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_MOD);
777    fDivSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DIV);
778    fCommentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_COMMENT);
779    fTextSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_TEXT);
780    fPISymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PI);
781    fNodeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NODE);
782    fAncestorSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR);
783    fAncestorOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR_OR_SELF);
784    fAttributeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ATTRIBUTE);
785    fChildSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_CHILD);
786    fDescendantSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT);
787    fDescendantOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT_OR_SELF);
788    fFollowingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING);
789    fFollowingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING_SIBLING);
790    fNamespaceSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NAMESPACE);
791    fParentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PARENT);
792    fPrecedingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING);
793    fPrecedingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING_SIBLING);
794    fSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_SELF);
795}
796
797
798// ---------------------------------------------------------------------------
799//  XPathScanner: Scan methods
800// ---------------------------------------------------------------------------
801bool XPathScanner::scanExpression(const XMLCh* const data,
802                                  XMLSize_t currentOffset,
803                                  const XMLSize_t endOffset,
804                                  ValueVectorOf<int>* const tokens) {
805
806    bool      starIsMultiplyOperator = false;
807    XMLSize_t nameOffset = 0;
808    int       nameHandle = -1;
809    int       prefixHandle = -1;
810    XMLCh     ch;
811    XMLBuffer dataBuffer(128, tokens->getMemoryManager());
812
813    while (currentOffset != endOffset) {
814
815        ch = data[currentOffset];
816
817        while (XMLChar1_0::isWhitespace(ch)) {
818
819            if (++currentOffset == endOffset) {
820                break;
821            }
822
823            ch = data[currentOffset];
824        }
825
826        if (currentOffset == endOffset) {
827            break;
828        }
829        //
830        // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
831        //                  | NameTest | NodeType | Operator | FunctionName
832        //                  | AxisName | Literal | Number | VariableReference
833        //
834        XMLByte chartype = (ch >= 0x80) ? (XMLByte)CHARTYPE_NONASCII : fASCIICharMap[ch];
835
836        switch (chartype) {
837        case CHARTYPE_OPEN_PAREN:       // '('
838            addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
839            starIsMultiplyOperator = false;
840            ++currentOffset;
841            break;
842        case CHARTYPE_CLOSE_PAREN:      // ')'
843            addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_PAREN);
844            starIsMultiplyOperator = true;
845            ++currentOffset;
846            break;
847        case CHARTYPE_OPEN_BRACKET:     // '['
848            addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_BRACKET);
849            starIsMultiplyOperator = false;
850            ++currentOffset;
851            break;
852        case CHARTYPE_CLOSE_BRACKET:    // ']'
853            addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_BRACKET);
854            starIsMultiplyOperator = true;
855            ++currentOffset;
856            break;
857                //
858                // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
859                //                                         ^^^^^^^^^^
860                //
861        case CHARTYPE_PERIOD:           // '.', '..' or '.' Digits
862            if (currentOffset + 1 == endOffset) {
863                addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
864                starIsMultiplyOperator = true;
865                currentOffset++;
866                break;
867            }
868
869            ch = data[currentOffset + 1];
870
871            if (ch == chPeriod) {            // '..'
872                addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_PERIOD);
873                starIsMultiplyOperator = true;
874                currentOffset += 2;
875            } else if (ch >= chDigit_0 && ch <= chDigit_9) {
876                addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
877                starIsMultiplyOperator = true;
878                currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
879            } else if (ch == chForwardSlash) {
880                addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
881                starIsMultiplyOperator = true;
882                currentOffset++;
883            } else if (ch == chPipe) { // '|'
884                addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
885                starIsMultiplyOperator = true;
886                currentOffset++;
887            } else if (XMLChar1_0::isWhitespace(ch)) {
888                do {
889                    if (++currentOffset == endOffset)
890                        break;
891
892                    ch = data[currentOffset];
893                } while (XMLChar1_0::isWhitespace(ch));
894
895                if (currentOffset == endOffset || ch == chPipe || ch == chForwardSlash) {
896                                    addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
897                    starIsMultiplyOperator = true;
898                    break;
899                }
900            } else {
901                XMLCh str[2]= {ch, 0 };
902                ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager());
903            }
904
905            break;
906        case CHARTYPE_ATSIGN:           // '@'
907            addToken(tokens, XercesXPath::EXPRTOKEN_ATSIGN);
908            starIsMultiplyOperator = false;
909            ++currentOffset;
910            break;
911        case CHARTYPE_COMMA:            // ','
912            addToken(tokens, XercesXPath::EXPRTOKEN_COMMA);
913            starIsMultiplyOperator = false;
914            ++currentOffset;
915            break;
916        case CHARTYPE_COLON:            // '::'
917            if (++currentOffset == endOffset) {
918                return false; // REVISIT
919            }
920            ch = data[currentOffset];
921
922            if (ch != chColon) {
923                return false; // REVISIT
924            }
925            addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
926            starIsMultiplyOperator = false;
927            ++currentOffset;
928            break;
929        case CHARTYPE_SLASH:            // '/' and '//'
930            if (++currentOffset == endOffset) {
931                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
932                starIsMultiplyOperator = false;
933                break;
934            }
935
936            ch = data[currentOffset];
937
938            if (ch == chForwardSlash) { // '//'
939                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH);
940                starIsMultiplyOperator = false;
941                ++currentOffset;
942            } else {
943                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
944                starIsMultiplyOperator = false;
945            }
946            break;
947        case CHARTYPE_UNION:            // '|'
948            addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_UNION);
949            starIsMultiplyOperator = false;
950            ++currentOffset;
951            break;
952        case CHARTYPE_PLUS:             // '+'
953            addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_PLUS);
954            starIsMultiplyOperator = false;
955            ++currentOffset;
956            break;
957        case CHARTYPE_MINUS:            // '-'
958            addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MINUS);
959            starIsMultiplyOperator = false;
960            ++currentOffset;
961            break;
962        case CHARTYPE_EQUAL:            // '='
963            addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_EQUAL);
964            starIsMultiplyOperator = false;
965            ++currentOffset;
966            break;
967        case CHARTYPE_EXCLAMATION:      // '!='
968            if (++currentOffset == endOffset) {
969                return false; // REVISIT
970            }
971
972            ch = data[currentOffset];
973
974            if (ch != chEqual) {
975                return false; // REVISIT
976            }
977
978            addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_NOT_EQUAL);
979            starIsMultiplyOperator = false;
980            ++currentOffset;
981            break;
982        case CHARTYPE_LESS: // '<' and '<='
983            if (++currentOffset == endOffset) {
984                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
985                starIsMultiplyOperator = false;
986                break;
987            }
988
989            ch = data[currentOffset];
990
991            if (ch == chEqual) { // '<='
992                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS_EQUAL);
993                starIsMultiplyOperator = false;
994                ++currentOffset;
995            } else {
996                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
997                starIsMultiplyOperator = false;
998            }
999            break;
1000        case CHARTYPE_GREATER: // '>' and '>='
1001            if (++currentOffset == endOffset) {
1002                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
1003                starIsMultiplyOperator = false;
1004                break;
1005            }
1006
1007            ch = data[currentOffset];
1008
1009            if (ch == chEqual) { // '>='
1010                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER_EQUAL);
1011                starIsMultiplyOperator = false;
1012                ++currentOffset;
1013            } else {
1014                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
1015                starIsMultiplyOperator = false;
1016            }
1017            break;
1018        //
1019        // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
1020        //
1021        case CHARTYPE_QUOTE:            // '\"' or '\''
1022            {
1023                XMLCh qchar = ch;
1024                if (++currentOffset == endOffset) {
1025                    return false; // REVISIT
1026                }
1027
1028                ch = data[currentOffset];
1029
1030                XMLSize_t litOffset = currentOffset;
1031                while (ch != qchar) {
1032                    if (++currentOffset == endOffset) {
1033                        return false; // REVISIT
1034                    }
1035
1036                    ch = data[currentOffset];
1037                }
1038
1039                addToken(tokens, XercesXPath::EXPRTOKEN_LITERAL);
1040                starIsMultiplyOperator = true;
1041
1042                dataBuffer.set(data + litOffset, currentOffset - litOffset);
1043                tokens->addElement(fStringPool->addOrFind(dataBuffer.getRawBuffer()));
1044                ++currentOffset;
1045                break;
1046            }
1047        //
1048        // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
1049        // [31] Digits ::= [0-9]+
1050        //
1051        case CHARTYPE_DIGIT:
1052            addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
1053            starIsMultiplyOperator = true;
1054            currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
1055            break;
1056        //
1057        // [36] VariableReference ::= '$' QName
1058        //
1059        case CHARTYPE_DOLLAR:
1060            if (++currentOffset == endOffset) {
1061                return false; // REVISIT
1062            }
1063            nameOffset = currentOffset;
1064            currentOffset = scanNCName(data, endOffset, currentOffset);
1065
1066            if (currentOffset == nameOffset) {
1067                return false; // REVISIT
1068            }
1069
1070            if (currentOffset < endOffset) {
1071                ch = data[currentOffset];
1072            }
1073            else {
1074                ch = 0;
1075            }
1076
1077            dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
1078            nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
1079            prefixHandle = -1;
1080
1081            if (ch == chColon) {
1082
1083                prefixHandle = nameHandle;
1084                if (++currentOffset == endOffset) {
1085                    return false; // REVISIT
1086                }
1087                nameOffset = currentOffset;
1088                currentOffset = scanNCName(data, endOffset, currentOffset);
1089
1090                if (currentOffset == nameOffset) {
1091                    return false; // REVISIT
1092                }
1093
1094                dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
1095                nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
1096            }
1097            addToken(tokens, XercesXPath::EXPRTOKEN_VARIABLE_REFERENCE);
1098            starIsMultiplyOperator = true;
1099            tokens->addElement(prefixHandle);
1100            tokens->addElement(nameHandle);
1101            break;
1102        //
1103        // [37] NameTest ::= '*' | NCName ':' '*' | QName
1104        // [34] MultiplyOperator ::= '*'
1105        //
1106        case CHARTYPE_STAR:             // '*'
1107            //
1108            // 3.7 Lexical Structure
1109            //
1110            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1111            //  an Operator, then a * must be recognized as a MultiplyOperator.
1112            //
1113            // Otherwise, the token must not be recognized as a MultiplyOperator.
1114            //
1115            if (starIsMultiplyOperator) {
1116                addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MULT);
1117                starIsMultiplyOperator = false;
1118            } else {
1119                addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_ANY);
1120                starIsMultiplyOperator = true;
1121            }
1122
1123            ++currentOffset;
1124            break;
1125        //
1126        // NCName, QName and non-terminals
1127        //
1128        case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic)
1129        case CHARTYPE_LETTER:
1130        case CHARTYPE_UNDERSCORE:
1131            {
1132            //
1133            // 3.7 Lexical Structure
1134            //
1135            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1136            //  an Operator, then an NCName must be recognized as an OperatorName.
1137            //
1138            //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
1139            //  then the token must be recognized as a NodeType or a FunctionName.
1140            //
1141            //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
1142            //  are ::, then the token must be recognized as an AxisName.
1143            //
1144            //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
1145            //  FunctionName, or an AxisName.
1146            //
1147            // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
1148            // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
1149            // [35] FunctionName ::= QName - NodeType
1150            // [6] AxisName ::= (see above)
1151            //
1152            // [37] NameTest ::= '*' | NCName ':' '*' | QName
1153            // [5] NCName ::= (Letter | '_') (NCNameChar)*
1154            // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_'  (ascii subset of 'NCNameChar')
1155            // [?] QName ::= (NCName ':')? NCName
1156            // [?] Letter ::= [A-Za-z]                              (ascii subset of 'Letter')
1157            // [?] Digit ::= [0-9]                                  (ascii subset of 'Digit')
1158            //
1159            nameOffset = currentOffset;
1160            currentOffset = scanNCName(data, endOffset, currentOffset);
1161            if (currentOffset == nameOffset) {
1162                return false; // REVISIT
1163                        }
1164
1165            if (currentOffset < endOffset) {
1166                ch = data[currentOffset];
1167            }
1168            else {
1169                ch = 0;
1170            }
1171
1172            dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
1173            nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
1174
1175            bool isNameTestNCName = false;
1176            bool isAxisName = false;
1177            prefixHandle = -1;
1178
1179            if (ch == chColon) {
1180
1181                if (++currentOffset == endOffset) {
1182                    return false; // REVISIT
1183                }
1184
1185                ch = data[currentOffset];
1186
1187                if (ch == chAsterisk) {
1188                    if (++currentOffset < endOffset) {
1189                        ch = data[currentOffset];
1190                    }
1191
1192                    isNameTestNCName = true;
1193                } else if (ch == chColon) {
1194                    if (++currentOffset < endOffset) {
1195                        ch = data[currentOffset];
1196                    }
1197
1198                    isAxisName = true;
1199                } else {
1200                    prefixHandle = nameHandle;
1201                    nameOffset = currentOffset;
1202                    currentOffset = scanNCName(data, endOffset, currentOffset);
1203                    if (currentOffset == nameOffset) {
1204                        return false; // REVISIT
1205                    }
1206                    if (currentOffset < endOffset) {
1207                        ch = data[currentOffset];
1208                    }
1209                    else {
1210                        ch = 0;
1211                    }
1212
1213                    dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
1214                    nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
1215                }
1216            }
1217            //
1218            // [39] ExprWhitespace ::= S
1219            //
1220            while (XMLChar1_0::isWhitespace(ch)) {
1221                if (++currentOffset == endOffset) {
1222                    break;
1223                }
1224                ch = data[currentOffset];
1225            }
1226
1227            //
1228            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1229            //  an Operator, then an NCName must be recognized as an OperatorName.
1230            //
1231            if (starIsMultiplyOperator) {
1232                if (nameHandle == fAndSymbol) {
1233                    addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_AND);
1234                    starIsMultiplyOperator = false;
1235                } else if (nameHandle == fOrSymbol) {
1236                    addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_OR);
1237                    starIsMultiplyOperator = false;
1238                } else if (nameHandle == fModSymbol) {
1239                    addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MOD);
1240                    starIsMultiplyOperator = false;
1241                } else if (nameHandle == fDivSymbol) {
1242                    addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DIV);
1243                    starIsMultiplyOperator = false;
1244                } else {
1245                    return false; // REVISIT
1246                }
1247
1248                if (isNameTestNCName) {
1249                    return false; // REVISIT - NCName:* where an OperatorName is required
1250                } else if (isAxisName) {
1251                    return false; // REVISIT - AxisName:: where an OperatorName is required
1252                }
1253                break;
1254            }
1255            //
1256            //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
1257            //  then the token must be recognized as a NodeType or a FunctionName.
1258            //
1259            if (ch == chOpenParen && !isNameTestNCName && !isAxisName) {
1260                if (nameHandle == fCommentSymbol) {
1261                    addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_COMMENT);
1262                } else if (nameHandle == fTextSymbol) {
1263                    addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_TEXT);
1264                } else if (nameHandle == fPISymbol) {
1265                    addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_PI);
1266                } else if (nameHandle == fNodeSymbol) {
1267                    addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_NODE);
1268                } else {
1269                    addToken(tokens, XercesXPath::EXPRTOKEN_FUNCTION_NAME);
1270                    tokens->addElement(prefixHandle);
1271                    tokens->addElement(nameHandle);
1272                }
1273                addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
1274                starIsMultiplyOperator = false;
1275                ++currentOffset;
1276                break;
1277            }
1278
1279            //
1280            //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
1281            //  are ::, then the token must be recognized as an AxisName.
1282            //
1283            if (isAxisName ||
1284                (ch == chColon && currentOffset + 1 < endOffset &&
1285                 data[currentOffset + 1] == chColon)) {
1286
1287                if (nameHandle == fAncestorSymbol) {
1288                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR);
1289                } else if (nameHandle == fAncestorOrSelfSymbol) {
1290                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF);
1291                } else if (nameHandle == fAttributeSymbol) {
1292                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE);
1293                } else if (nameHandle == fChildSymbol) {
1294                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_CHILD);
1295                } else if (nameHandle == fDescendantSymbol) {
1296                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT);
1297                } else if (nameHandle == fDescendantOrSelfSymbol) {
1298                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF);
1299                } else if (nameHandle == fFollowingSymbol) {
1300                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING);
1301                } else if (nameHandle == fFollowingSiblingSymbol) {
1302                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING);
1303                } else if (nameHandle == fNamespaceSymbol) {
1304                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_NAMESPACE);
1305                } else if (nameHandle == fParentSymbol) {
1306                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PARENT);
1307                } else if (nameHandle == fPrecedingSymbol) {
1308                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING);
1309                } else if (nameHandle == fPrecedingSiblingSymbol) {
1310                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING_SIBLING);
1311                } else if (nameHandle == fSelfSymbol) {
1312                    addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_SELF);
1313                } else {
1314                    return false; // REVISIT
1315                }
1316
1317                if (isNameTestNCName) {
1318                    return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required
1319                }
1320
1321                addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
1322                starIsMultiplyOperator = false;
1323                if (!isAxisName) {
1324                    currentOffset += 2;
1325                }
1326                break;
1327            }
1328            //
1329            //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
1330            //  FunctionName, or an AxisName.
1331            //
1332            if (isNameTestNCName) {
1333                addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE);
1334                tokens->addElement(nameHandle);
1335            } else {
1336                addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_QNAME);
1337                tokens->addElement(prefixHandle);
1338                tokens->addElement(nameHandle);
1339            }
1340
1341            starIsMultiplyOperator = true;
1342            break;
1343            }
1344        default:
1345            {
1346            XMLCh str[2]= {ch, 0 };
1347            ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager());
1348            break;
1349            }
1350        }
1351    }
1352
1353    return true;
1354}
1355
1356
1357XMLSize_t XPathScanner::scanNCName(const XMLCh* const data,
1358                             const XMLSize_t endOffset,
1359                             XMLSize_t currentOffset) {
1360
1361    XMLCh ch = data[currentOffset];
1362
1363    if (!XMLChar1_0::isFirstNCNameChar(ch)) {
1364        return currentOffset;
1365    }
1366
1367    while (++currentOffset < endOffset) {
1368
1369        ch = data[currentOffset];
1370
1371        if (!XMLChar1_0::isNCNameChar(ch)) {
1372            break;
1373        }
1374    }
1375
1376    return currentOffset;
1377}
1378
1379
1380XMLSize_t XPathScanner::scanNumber(const XMLCh* const data,
1381                             const XMLSize_t endOffset,
1382                             XMLSize_t currentOffset,
1383                             ValueVectorOf<int>* const tokens) {
1384
1385    XMLCh ch = data[currentOffset];
1386    int   whole = 0;
1387    int   part = 0;
1388
1389    while (ch >= chDigit_0 && ch <= chDigit_9) {
1390
1391        whole = (whole * 10) + (ch - chDigit_0);
1392
1393        if (++currentOffset == endOffset) {
1394            break;
1395        }
1396
1397        ch = data[currentOffset];
1398    }
1399
1400    if (ch == chPeriod) {
1401
1402        if (++currentOffset < endOffset) {
1403
1404            ch = data[currentOffset];
1405
1406            while (ch >= chDigit_0 && ch <= chDigit_9) {
1407
1408                part = (part * 10) + (ch - chDigit_0);
1409
1410                if (++currentOffset == endOffset) {
1411                    break;
1412                }
1413
1414                ch = data[currentOffset];
1415            }
1416
1417            if (part != 0) {
1418                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::XPath_FindSolution, tokens->getMemoryManager());
1419            }
1420        }
1421    }
1422
1423    tokens->addElement(whole);
1424    tokens->addElement(part);
1425
1426    return currentOffset;
1427}
1428
1429
1430// ---------------------------------------------------------------------------
1431//  XPathScannerForSchema: Constructors and Destructor
1432// ---------------------------------------------------------------------------
1433XPathScannerForSchema::XPathScannerForSchema(XMLStringPool* const stringPool)
1434    : XPathScanner(stringPool)
1435{
1436}
1437
1438
1439// ---------------------------------------------------------------------------
1440//  XPathScannerForSchema: Helper methods
1441// ---------------------------------------------------------------------------
1442void XPathScannerForSchema::addToken(ValueVectorOf<int>* const tokens,
1443                                     const int aToken) {
1444
1445    if (aToken == XercesXPath::EXPRTOKEN_ATSIGN ||
1446        aToken == XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE ||
1447        aToken == XercesXPath::EXPRTOKEN_AXISNAME_CHILD ||
1448        //token == XercesXPath::EXPRTOKEN_AXISNAME_SELF ||
1449        aToken == XercesXPath::EXPRTOKEN_DOUBLE_COLON ||
1450        aToken == XercesXPath::EXPRTOKEN_NAMETEST_QNAME ||
1451        //token == XercesXPath::EXPRTOKEN_NODETYPE_NODE ||
1452        aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH ||
1453        aToken == XercesXPath::EXPRTOKEN_PERIOD ||
1454        aToken == XercesXPath::EXPRTOKEN_NAMETEST_ANY ||
1455        aToken == XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE ||
1456        aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH ||
1457        aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION) {
1458
1459        tokens->addElement(aToken);
1460        return;
1461    }
1462
1463    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, tokens->getMemoryManager());
1464}
1465
1466XERCES_CPP_NAMESPACE_END
1467
1468/**
1469  * End of file XercesPath.cpp
1470  */
Note: See TracBrowser for help on using the repository browser.