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

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

Original Xerces files with import mods for icxercesc

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