source: NonGTP/Xerces/xerces/include/xercesc/util/regx/RegularExpression.hpp @ 358

Revision 358, 23.2 KB checked in by bittner, 19 years ago (diff)

xerces added

Line 
1/*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * $Id: RegularExpression.hpp,v 1.19 2004/09/08 13:56:47 peiyongz Exp $
19 */
20
21#if !defined(REGULAREXPRESSION_HPP)
22#define REGULAREXPRESSION_HPP
23
24// ---------------------------------------------------------------------------
25//  Includes
26// ---------------------------------------------------------------------------
27#include <xercesc/util/RefArrayVectorOf.hpp>
28#include <xercesc/util/XMLString.hpp>
29#include <xercesc/util/Janitor.hpp>
30#include <xercesc/util/Mutexes.hpp>
31#include <xercesc/util/regx/Op.hpp>
32#include <xercesc/util/regx/TokenFactory.hpp>
33#include <xercesc/util/regx/BMPattern.hpp>
34#include <xercesc/util/regx/ModifierToken.hpp>
35#include <xercesc/util/regx/ConditionToken.hpp>
36#include <xercesc/util/regx/OpFactory.hpp>
37
38XERCES_CPP_NAMESPACE_BEGIN
39
40// ---------------------------------------------------------------------------
41//  Forward Declaration
42// ---------------------------------------------------------------------------
43class RangeToken;
44class Match;
45
46class XMLUTIL_EXPORT RegularExpression : public XMemory
47{
48public:
49    // -----------------------------------------------------------------------
50    //  Public Constructors and Destructor
51    // -----------------------------------------------------------------------
52    RegularExpression
53    (
54        const char* const pattern
55        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
56    );
57    RegularExpression
58    (
59        const char* const pattern
60        , const char* const options
61        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
62    );
63    RegularExpression
64    (
65        const XMLCh* const pattern
66        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
67    );
68    RegularExpression
69    (
70        const XMLCh* const pattern
71        , const XMLCh* const options
72        , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
73    );
74    ~RegularExpression();
75
76    // -----------------------------------------------------------------------
77    //  Public Constants
78    // -----------------------------------------------------------------------
79    static const unsigned int   MARK_PARENS;
80    static const unsigned int   IGNORE_CASE;
81    static const unsigned int   SINGLE_LINE;
82    static const unsigned int   MULTIPLE_LINE;
83    static const unsigned int   EXTENDED_COMMENT;
84    static const unsigned int   USE_UNICODE_CATEGORY;
85    static const unsigned int   UNICODE_WORD_BOUNDARY;
86    static const unsigned int   PROHIBIT_HEAD_CHARACTER_OPTIMIZATION;
87    static const unsigned int   PROHIBIT_FIXED_STRING_OPTIMIZATION;
88    static const unsigned int   XMLSCHEMA_MODE;
89    static const unsigned int   SPECIAL_COMMA;
90    static const unsigned short WT_IGNORE;
91    static const unsigned short WT_LETTER;
92    static const unsigned short WT_OTHER;
93
94    // -----------------------------------------------------------------------
95    //  Public Helper methods
96    // -----------------------------------------------------------------------
97    static int getOptionValue(const XMLCh ch);
98
99    // -----------------------------------------------------------------------
100    //  Matching methods
101    // -----------------------------------------------------------------------
102    bool matches(const char* const matchString, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
103    bool matches(const char* const matchString, const int start,
104                 const int end, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
105    bool matches(const char* const matchString, Match* const pMatch, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
106    bool matches(const char* const matchString, const int start,
107                 const int end, Match* const pMatch, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
108
109    bool matches(const XMLCh* const matchString, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
110    bool matches(const XMLCh* const matchString, const int start,
111                 const int end, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
112    bool matches(const XMLCh* const matchString, Match* const pMatch, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
113    bool matches(const XMLCh* const matchString, const int start,
114                 const int end, Match* const pMatch, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
115
116    // -----------------------------------------------------------------------
117    //  Tokenize methods
118    // -----------------------------------------------------------------------
119    // Note: The caller owns the string vector that is returned, and is responsible
120    //       for deleting it.
121    RefArrayVectorOf<XMLCh> *tokenize(const char* const matchString);
122    RefArrayVectorOf<XMLCh> *tokenize(const char* const matchString, const int start,
123                                      const int end);
124
125    RefArrayVectorOf<XMLCh> *tokenize(const XMLCh* const matchString);
126    RefArrayVectorOf<XMLCh> *tokenize(const XMLCh* const matchString,
127                                      const int start, const int end);
128
129    // -----------------------------------------------------------------------
130    //  Replace methods
131    // -----------------------------------------------------------------------
132    // Note: The caller owns the XMLCh* that is returned, and is responsible for
133    //       deleting it.
134    XMLCh *replace(const char* const matchString, const char* const replaceString);
135    XMLCh *replace(const char* const matchString, const char* const replaceString,
136                   const int start, const int end);
137
138    XMLCh *replace(const XMLCh* const matchString, const XMLCh* const replaceString);
139    XMLCh *replace(const XMLCh* const matchString, const XMLCh* const replaceString,
140                   const int start, const int end);
141
142private:
143    // -----------------------------------------------------------------------
144    //  Private data types
145    // -----------------------------------------------------------------------
146    class XMLUTIL_EXPORT Context : public XMemory
147    {
148        public :
149            Context(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
150            ~Context();
151
152            inline const XMLCh* getString() const { return fString; }
153            void reset(const XMLCh* const string, const int stringLen,
154                       const int start, const int limit, const int noClosures);
155            bool nextCh(XMLInt32& ch, int& offset, const short direction);
156           
157            bool      fAdoptMatch;
158            int       fStart;
159            int       fLimit;
160            int       fLength;    // fLimit - fStart
161            int       fSize;
162            int       fStringMaxLen;
163            int*      fOffsets;
164            Match*    fMatch;
165            XMLCh*    fString;
166            MemoryManager* fMemoryManager;
167
168            friend class Janitor<Context>;
169    };
170
171    // -----------------------------------------------------------------------
172    //  Unimplemented constructors and operators
173    // -----------------------------------------------------------------------
174    RegularExpression(const RegularExpression&);
175    RegularExpression& operator=(const RegularExpression&);
176
177    // -----------------------------------------------------------------------
178    //  Cleanup methods
179    // -----------------------------------------------------------------------
180    void cleanUp();
181
182    // -----------------------------------------------------------------------
183    //  Setter methods
184    // -----------------------------------------------------------------------
185    void setPattern(const XMLCh* const pattern, const XMLCh* const options=0);
186
187    // -----------------------------------------------------------------------
188    //  Private Helper methods
189    // -----------------------------------------------------------------------
190    void prepare();
191    int parseOptions(const XMLCh* const options);
192    bool isSet(const int options, const int flag);
193    unsigned short getWordType(const XMLCh* const target, const int begin,
194                               const int end, const int offset);
195    unsigned short getCharType(const XMLCh ch);
196    unsigned short getPreviousWordType(const XMLCh* const target,
197                                       const int start, const int end,
198                                       int offset);
199
200    /**
201      *    Matching helpers
202      */
203    int match(Context* const context, const Op* const operations, int offset,
204              const short direction);
205    bool matchIgnoreCase(const XMLInt32 ch1, const XMLInt32 ch2);
206
207    /**
208      *    Helper methods used by match(Context* ...)
209      */
210    bool matchChar(Context* const context, const XMLInt32 ch, int& offset,
211                   const short direction, const bool ignoreCase);
212    bool matchDot(Context* const context, int& offset, const short direction);
213    bool matchRange(Context* const context, const Op* const op,
214                    int& offset, const short direction, const bool ignoreCase);
215    bool matchAnchor(Context* const context, const XMLInt32 ch,
216                     const int offset);
217    bool matchBackReference(Context* const context, const XMLInt32 ch,
218                            int& offset, const short direction,
219                            const bool ignoreCase);
220    bool matchString(Context* const context, const XMLCh* const literal,
221                     int& offset, const short direction, const bool ignoreCase);
222    int  matchUnion(Context* const context, const Op* const op, int offset,
223                    const short direction);
224    int matchCapture(Context* const context, const Op* const op, int offset,
225                     const short direction);
226    bool matchCondition(Context* const context, const Op* const op, int offset,
227                        const short direction);
228    int matchModifier(Context* const context, const Op* const op, int offset,
229                      const short direction);
230
231    /**
232     *    Tokenize helper
233     *
234     *    This overloaded tokenize is for internal use only. It provides a way to
235     *    keep track of the sub-expressions in each match of the pattern.
236     *
237     *    It is called by the other tokenize methods, and by the replace method.
238     *    The caller is responsible for the deletion of the returned
239     *    RefArrayVectorOf<XMLCh*>
240     */
241    RefArrayVectorOf<XMLCh> *tokenize(const XMLCh* const matchString,
242                                      const int start, const int end,
243                                      RefVectorOf<Match> *subEx);
244    /**
245     *    Replace helpers
246     *
247     *    Note: the caller owns the XMLCh* that is returned
248     */
249    const XMLCh *subInExp(const XMLCh* const repString,
250                          const XMLCh* const origString,
251                          const Match* subEx);
252    /**
253     *    Converts a token tree into an operation tree
254     */
255    void compile(const Token* const token);
256    Op*  compile(const Token* const token, Op* const next,
257                 const bool reverse);
258    /**
259      *    Helper methods used by compile
260      */
261    Op* compileSingle(const Token* const token, Op* const next,
262                      const unsigned short tokType);
263    Op* compileUnion(const Token* const token, Op* const next,
264                     const bool reverse);
265    Op* compileCondition(const Token* const token, Op* const next,
266                         const bool reverse);
267    Op* compileParenthesis(const Token* const token, Op* const next,
268                           const bool reverse);
269    Op* compileLook(const Token* const token, const Op* const next,
270                    const bool reverse, const unsigned short tokType);
271    Op* compileConcat(const Token* const token, Op* const next,
272                      const bool reverse);
273    Op* compileClosure(const Token* const token, Op* const next,
274                       const bool reverse, const unsigned short tokType);
275
276    // -----------------------------------------------------------------------
277    //  Private data members
278    // -----------------------------------------------------------------------
279    bool               fHasBackReferences;
280    bool               fFixedStringOnly;
281    int                fNoGroups;
282    int                fMinLength;
283    int                fNoClosures;
284    unsigned int       fOptions;
285    BMPattern*         fBMPattern;
286    XMLCh*             fPattern;
287    XMLCh*             fFixedString;
288    Op*                fOperations;
289    Token*             fTokenTree;
290    RangeToken*        fFirstChar;
291    static RangeToken* fWordRange;
292    OpFactory          fOpFactory;
293    XMLMutex           fMutex;
294    TokenFactory*      fTokenFactory;
295    MemoryManager*     fMemoryManager;
296};
297
298
299  // ---------------------------------------------------------------------------
300  //  RegularExpression: Cleanup methods
301  // ---------------------------------------------------------------------------
302  inline void RegularExpression::cleanUp() {
303
304      fMemoryManager->deallocate(fPattern);//delete [] fPattern;
305      fMemoryManager->deallocate(fFixedString);//delete [] fFixedString;     
306      delete fBMPattern;
307      delete fTokenFactory;
308  }
309
310  // ---------------------------------------------------------------------------
311  //  RegularExpression: Helper methods
312  // ---------------------------------------------------------------------------
313  inline bool RegularExpression::isSet(const int options, const int flag) {
314
315      return (options & flag) == flag;
316  }
317
318  inline Op* RegularExpression::compileLook(const Token* const token,
319                                            const Op* const next,
320                                            const bool reverse,
321                                            const unsigned short tokType) {
322
323      Op*    ret = 0;
324      Op*    result = compile(token->getChild(0), 0, reverse);
325
326      switch(tokType) {
327      case Token::T_LOOKAHEAD:
328          ret = fOpFactory.createLookOp(Op::O_LOOKAHEAD, next, result);
329          break;
330      case Token::T_NEGATIVELOOKAHEAD:
331          ret = fOpFactory.createLookOp(Op::O_NEGATIVELOOKAHEAD, next, result);
332          break;
333      case Token::T_LOOKBEHIND:
334          ret = fOpFactory.createLookOp(Op::O_LOOKBEHIND, next, result);
335          break;
336      case Token::T_NEGATIVELOOKBEHIND:
337          ret = fOpFactory.createLookOp(Op::O_NEGATIVELOOKBEHIND, next, result);
338          break;
339      case Token::T_INDEPENDENT:
340          ret = fOpFactory.createIndependentOp(next, result);
341          break;
342      case Token::T_MODIFIERGROUP:
343          ret = fOpFactory.createModifierOp(next, result,
344                                     ((const ModifierToken *) token)->getOptions(),
345                                     ((const ModifierToken *) token)->getOptionsMask());
346          break;
347      }
348
349
350      return ret;
351  }
352
353  inline Op* RegularExpression::compileSingle(const Token* const token,
354                                              Op* const next,
355                                              const unsigned short tokType) {
356
357      Op* ret = 0;
358
359      switch (tokType) {
360      case Token::T_DOT:
361          ret = fOpFactory.createDotOp();
362          break;
363      case Token::T_CHAR:
364          ret = fOpFactory.createCharOp(token->getChar());
365          break;
366      case Token::T_ANCHOR:
367          ret = fOpFactory.createAnchorOp(token->getChar());
368          break;
369      case Token::T_RANGE:
370      case Token::T_NRANGE:
371          ret = fOpFactory.createRangeOp(token);
372          break;
373      case Token::T_EMPTY:
374          ret = next;
375          break;
376      case Token::T_STRING:
377          ret = fOpFactory.createStringOp(token->getString());
378          break;
379      case Token::T_BACKREFERENCE:
380          ret = fOpFactory.createBackReferenceOp(token->getReferenceNo());
381          break;
382      }
383
384      if (tokType != Token::T_EMPTY)
385          ret->setNextOp(next);
386
387      return ret;
388  }
389
390
391  inline Op* RegularExpression::compileUnion(const Token* const token,
392                                             Op* const next,
393                                             const bool reverse) {
394
395      int tokSize = token->size();
396      UnionOp* uniOp = fOpFactory.createUnionOp(tokSize);
397
398      for (int i=0; i<tokSize; i++) {
399
400          uniOp->addElement(compile(token->getChild(i), next, reverse));
401      }
402
403      return uniOp;
404  }
405
406
407  inline Op* RegularExpression::compileCondition(const Token* const token,
408                                                 Op* const next,
409                                                 const bool reverse) {
410
411      Token* condTok = ((const ConditionToken*) token)->getConditionToken();
412      Token* yesTok  = token->getChild(0);
413      Token* noTok   = token->getChild(1);
414      int    refNo   = token->getReferenceNo();
415      Op*    condOp  = (condTok == 0) ? 0 : compile(condTok, 0, reverse);
416      Op*    yesOp   = compile(yesTok, next, reverse);
417      Op*    noOp    = (noTok == 0) ? 0 : compile(noTok, next, reverse);
418
419      return fOpFactory.createConditionOp(next, refNo, condOp, yesOp, noOp);
420  }
421
422
423  inline Op* RegularExpression::compileParenthesis(const Token* const token,
424                                                   Op* const next,
425                                                   const bool reverse) {
426
427      if (token->getNoParen() == 0)
428          return compile(token->getChild(0), next, reverse);
429
430      Op* captureOp    = 0;
431
432      if (reverse) {
433
434          captureOp = fOpFactory.createCaptureOp(token->getNoParen(), next);
435          captureOp = compile(token->getChild(0), captureOp, reverse);
436
437          return fOpFactory.createCaptureOp(-token->getNoParen(), captureOp);
438      }
439
440      captureOp = fOpFactory.createCaptureOp(-token->getNoParen(), next);
441      captureOp = compile(token->getChild(0), captureOp, reverse);
442
443      return fOpFactory.createCaptureOp(token->getNoParen(), captureOp);
444  }
445
446  inline Op* RegularExpression::compileConcat(const Token* const token,
447                                              Op*  const next,
448                                              const bool reverse) {
449
450      Op* ret = next;
451      int tokSize = token->size();
452
453      if (!reverse) {
454
455          for (int i= tokSize - 1; i>=0; i--) {
456              ret = compile(token->getChild(i), ret, false);
457          }
458      }
459      else {
460
461          for (int i= 0; i< tokSize; i++) {
462              ret = compile(token->getChild(i), ret, true);
463          }
464      }
465
466      return ret;
467  }
468
469  inline Op* RegularExpression::compileClosure(const Token* const token,
470                                               Op* const next,
471                                               const bool reverse,
472                                               const unsigned short tokType) {
473
474      Op*    ret      = 0;
475      Token* childTok = token->getChild(0);
476      int    min      = token->getMin();
477      int    max      = token->getMax();
478
479      if (min >= 0 && min == max) {
480
481          ret = next;
482          for (int i=0; i< min; i++) {
483              ret = compile(childTok, ret, reverse);
484          }
485
486          return ret;
487      }
488
489      if (min > 0 && max > 0)
490          max -= min;
491
492      if (max > 0) {
493
494          ret = next;
495          for (int i=0; i<max; i++) {
496
497              ChildOp* childOp = fOpFactory.createQuestionOp(
498                  tokType == Token::T_NONGREEDYCLOSURE);
499
500              childOp->setNextOp(next);
501              childOp->setChild(compile(childTok, ret, reverse));
502              ret = childOp;
503          }
504      }
505      else {
506
507          ChildOp* childOp = 0;
508
509          if (tokType == Token::T_NONGREEDYCLOSURE) {
510              childOp = fOpFactory.createNonGreedyClosureOp();
511          }
512          else {
513
514              if (childTok->getMinLength() == 0)
515                  childOp = fOpFactory.createClosureOp(fNoClosures++);
516              else
517                  childOp = fOpFactory.createClosureOp(-1);
518          }
519
520          childOp->setNextOp(next);
521          childOp->setChild(compile(childTok, childOp, reverse));
522          ret = childOp;
523      }
524
525      if (min > 0) {
526
527          for (int i=0; i< min; i++) {
528              ret = compile(childTok, ret, reverse);
529          }
530      }
531
532      return ret;
533  }
534
535  inline int RegularExpression::matchUnion(Context* const context,
536                                           const Op* const op, int offset,
537                                           const short direction)
538  {
539      unsigned int opSize = op->getSize();
540      int ret = -1;
541
542      for (unsigned int i=0; i < opSize; i++) {
543
544          ret = match(context, op->elementAt(i), offset, direction);
545
546          if (ret == context->fLimit)
547              return ret;
548      }
549
550      return -1;
551  }
552
553  inline int RegularExpression::matchModifier(Context* const context,
554                                              const Op* const op, int offset,
555                                              const short direction)
556  {
557      int saveOptions = fOptions;
558      fOptions |= (int) op->getData();
559      fOptions &= (int) ~op->getData2();
560
561      int ret = match(context, op->getChild(), offset, direction);
562
563      fOptions = saveOptions;
564
565      return ret;
566  }
567
568  inline unsigned short RegularExpression::getWordType(const XMLCh* const target
569                                                       , const int begin
570                                                       , const int end
571                                                       , const int offset)
572  {
573      if (offset < begin || offset >= end)
574          return WT_OTHER;
575
576      return getCharType(target[offset]);
577  }
578
579  inline
580  unsigned short RegularExpression::getPreviousWordType(const XMLCh* const target
581                                                        , const int start
582                                                        , const int end
583                                                        , int offset)
584  {
585      unsigned short ret = getWordType(target, start, end, --offset);
586
587      while (ret == WT_IGNORE) {
588          ret = getWordType(target, start, end, --offset);
589      }
590
591      return ret;
592  }
593
594  inline bool RegularExpression::matchIgnoreCase(const XMLInt32 ch1,
595                                                 const XMLInt32 ch2)
596  {
597
598      return (0==XMLString::compareNIString((const XMLCh*)&ch1,(const XMLCh*)&ch2, 1));
599  }
600
601
602XERCES_CPP_NAMESPACE_END
603
604#endif
605/**
606  * End of file RegularExpression.hpp
607  */
608
Note: See TracBrowser for help on using the repository browser.