RegularExpression.hpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:21k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: RegularExpression.hpp,v 1.7 2001/10/15 18:47:23 knoaman Exp $
  58.  */
  59. #if !defined(REGULAREXPRESSION_HPP)
  60. #define REGULAREXPRESSION_HPP
  61. // ---------------------------------------------------------------------------
  62. //  Includes
  63. // ---------------------------------------------------------------------------
  64. #include <util/XMLUniDefs.hpp>
  65. #include <util/regx/Op.hpp>
  66. #include <util/regx/TokenFactory.hpp>
  67. #include <util/regx/BMPattern.hpp>
  68. #include <util/Janitor.hpp>
  69. #include <util/Mutexes.hpp>
  70. #include <util/regx/ModifierToken.hpp>
  71. #include <util/regx/ConditionToken.hpp>
  72. #include <util/regx/OpFactory.hpp>
  73. // ---------------------------------------------------------------------------
  74. //  Forward Declaration
  75. // ---------------------------------------------------------------------------
  76. class Token;
  77. class BMPattern;
  78. class RangeToken;
  79. class Match;
  80. class TokenFactory;
  81. class XMLUTIL_EXPORT RegularExpression {
  82. public:
  83.     // -----------------------------------------------------------------------
  84.     //  Public Constructors and Destructor
  85.     // -----------------------------------------------------------------------
  86.     RegularExpression(const char* const pattern);
  87.     RegularExpression(const char* const pattern, const char* const options);
  88.     RegularExpression(const XMLCh* const pattern);
  89.     RegularExpression(const XMLCh* const pattern, const XMLCh* const options);
  90.     ~RegularExpression();
  91.     // -----------------------------------------------------------------------
  92.     //  Public Constants
  93.     // -----------------------------------------------------------------------
  94.     static const unsigned int   MARK_PARENS;
  95.     static const unsigned int   IGNORE_CASE;
  96.     static const unsigned int   SINGLE_LINE;
  97.     static const unsigned int   MULTIPLE_LINE;
  98.     static const unsigned int   EXTENDED_COMMENT;
  99.     static const unsigned int   USE_UNICODE_CATEGORY;
  100.     static const unsigned int   UNICODE_WORD_BOUNDARY;
  101.     static const unsigned int   PROHIBIT_HEAD_CHARACTER_OPTIMIZATION;
  102.     static const unsigned int   PROHIBIT_FIXED_STRING_OPTIMIZATION;
  103.     static const unsigned int   XMLSCHEMA_MODE;
  104.     static const unsigned int   SPECIAL_COMMA;
  105.     static const unsigned short WT_IGNORE;
  106.     static const unsigned short WT_LETTER;
  107.     static const unsigned short WT_OTHER;
  108.     // -----------------------------------------------------------------------
  109.     //  Public Helper methods
  110.     // -----------------------------------------------------------------------
  111.     static int getOptionValue(const XMLCh ch);
  112.     // -----------------------------------------------------------------------
  113.     //  Matching methods
  114.     // -----------------------------------------------------------------------
  115.     bool matches(const char* const matchString);
  116.     bool matches(const char* const matchString, const int start,
  117.                  const int end);
  118.     bool matches(const char* const matchString, Match* const pMatch);
  119.     bool matches(const char* const matchString, const int start,
  120.                  const int end, Match* const pMatch);
  121.     bool matches(const XMLCh* const matchString);
  122.     bool matches(const XMLCh* const matchString, const int start,
  123.                  const int end);
  124.     bool matches(const XMLCh* const matchString, Match* const pMatch);
  125.     bool matches(const XMLCh* const matchString, const int start,
  126.                  const int end, Match* const pMatch);
  127. private:
  128.     // -----------------------------------------------------------------------
  129.     //  Private data types
  130.     // -----------------------------------------------------------------------
  131.     class Context
  132.     {
  133.         public :
  134.             Context();
  135.             ~Context();
  136.             inline const XMLCh* getString() const { return fString; }
  137.             void reset(const XMLCh* const string, const int start,
  138.                        const int limit, const int noClosures);
  139.             bool nextCh(XMLInt32& ch, int& offset, const short direction);
  140.             bool      fInUse;
  141.             bool      fAdoptMatch;
  142.             int       fStart;
  143.             int       fLimit;
  144.             int       fLength;
  145.             int       fSize;
  146.             int*      fOffsets;
  147.             Match*    fMatch;
  148.             XMLCh*    fString;
  149.             friend class Janitor<Context>;
  150.     };
  151.     // -----------------------------------------------------------------------
  152.     //  Unimplemented constructors and operators
  153.     // -----------------------------------------------------------------------
  154.     RegularExpression(const RegularExpression&);
  155.     void operator=(const RegularExpression&);
  156.     // -----------------------------------------------------------------------
  157.     //  Cleanup methods
  158.     // -----------------------------------------------------------------------
  159.     void cleanUp();
  160.     // -----------------------------------------------------------------------
  161.     //  Setter methods
  162.     // -----------------------------------------------------------------------
  163.     void setPattern(const XMLCh* const pattern, const XMLCh* const options=0);
  164.     // -----------------------------------------------------------------------
  165.     //  Private Helper methods
  166.     // -----------------------------------------------------------------------
  167.     void prepare();
  168.     int parseOptions(const XMLCh* const options);
  169.     bool isSet(const int options, const int flag);
  170.     unsigned short getWordType(const XMLCh* const target, const int begin,
  171.                                const int end, const int offset);
  172.     unsigned short getCharType(const XMLCh ch);
  173.     unsigned short getPreviousWordType(const XMLCh* const target,
  174.                                        const int start, const int end,
  175.                                        int offset);
  176.     /**
  177.       *    Matching helpers
  178.       */
  179.     int match(Context* const context, const Op* const operations, int offset,
  180.               const short direction);
  181.     bool matchIgnoreCase(const XMLInt32 ch1, const XMLInt32 ch2);
  182.     /**
  183.       *    Helper methods used by match(Context* ...)
  184.       */
  185.     bool matchChar(Context* const context, const XMLInt32 ch, int& offset,
  186.                    const short direction, const bool ignoreCase);
  187.     bool matchDot(Context* const context, int& offset, const short direction);
  188.     bool matchRange(Context* const context, const Op* const op,
  189.                     int& offset, const short direction, const bool ignoreCase);
  190.     bool matchAnchor(Context* const context, const XMLInt32 ch,
  191.                      const int offset);
  192.     bool matchBackReference(Context* const context, const XMLInt32 ch,
  193.                             int& offset, const short direction,
  194.                             const bool ignoreCase);
  195.     bool matchString(Context* const context, const XMLCh* const literal,
  196.                      int& offset, const short direction, const bool ignoreCase);
  197.     int  matchUnion(Context* const context, const Op* const op, int offset,
  198.                     const short direction);
  199.     int matchCapture(Context* const context, const Op* const op, int offset,
  200.                      const short direction);
  201.     bool matchCondition(Context* const context, const Op* const op, int offset,
  202.                         const short direction);
  203.     int matchModifier(Context* const context, const Op* const op, int offset,
  204.                       const short direction);
  205.     /**
  206.       *    Converts a token tree into an operation tree
  207.       */
  208.     void compile(const Token* const token);
  209.     Op*  compile(const Token* const token, Op* const next,
  210.                  const bool reverse);
  211.     /**
  212.       *    Helper methods used by compile
  213.       */
  214.     Op* compileSingle(const Token* const token, Op* const next,
  215.                       const unsigned short tokType);
  216.     Op* compileUnion(const Token* const token, Op* const next,
  217.                      const bool reverse);
  218.     Op* compileCondition(const Token* const token, Op* const next,
  219.                          const bool reverse);
  220.     Op* compileParenthesis(const Token* const token, Op* const next,
  221.                            const bool reverse);
  222.     Op* compileLook(const Token* const token, const Op* const next,
  223.                     const bool reverse, const unsigned short tokType);
  224.     Op* compileConcat(const Token* const token, Op* const next,
  225.                       const bool reverse);
  226.     Op* compileClosure(const Token* const token, Op* const next,
  227.                        const bool reverse, const unsigned short tokType);
  228.     // -----------------------------------------------------------------------
  229.     //  Private data members
  230.     // -----------------------------------------------------------------------
  231.     bool               fHasBackReferences;
  232.     bool               fFixedStringOnly;
  233.     int                fNoGroups;
  234.     int                fMinLength;
  235.     int                fNoClosures;
  236.     unsigned int       fOptions;
  237.     Context*           fContext;
  238.     BMPattern*         fBMPattern;
  239.     XMLCh*             fPattern;
  240.     XMLCh*             fFixedString;
  241.     Op*                fOperations;
  242.     Token*             fTokenTree;
  243.     RangeToken*        fFirstChar;
  244.     static RangeToken* fWordRange;
  245.     OpFactory          fOpFactory;
  246.     XMLMutex           fMutex;
  247.     TokenFactory*      fTokenFactory;
  248. };
  249. // ---------------------------------------------------------------------------
  250. //  RegularExpression: Cleanup methods
  251. // ---------------------------------------------------------------------------
  252. inline void RegularExpression::cleanUp() {
  253.     delete [] fPattern;
  254.     delete [] fFixedString;
  255.     delete fContext;
  256.     delete fBMPattern;
  257.     delete fTokenFactory;
  258. }
  259. // ---------------------------------------------------------------------------
  260. //  RegularExpression: Helper methods
  261. // ---------------------------------------------------------------------------
  262. inline bool RegularExpression::isSet(const int options, const int flag) {
  263.     return (options & flag) == flag;
  264. }
  265. inline Op* RegularExpression::compileLook(const Token* const token,
  266.                                           const Op* const next,
  267.                                           const bool reverse,
  268.                                           const unsigned short tokType) {
  269.     Op*    ret = 0;
  270.     Op*    result = compile(token->getChild(0), 0, reverse);
  271.     switch(tokType) {
  272.     case Token::LOOKAHEAD:
  273.         ret = fOpFactory.createLookOp(Op::LOOKAHEAD, next, result);
  274.         break;
  275.     case Token::NEGATIVELOOKAHEAD:
  276.         ret = fOpFactory.createLookOp(Op::NEGATIVELOOKAHEAD, next, result);
  277.         break;
  278.     case Token::LOOKBEHIND:
  279.         ret = fOpFactory.createLookOp(Op::LOOKBEHIND, next, result);
  280.         break;
  281.     case Token::NEGATIVELOOKBEHIND:
  282.         ret = fOpFactory.createLookOp(Op::NEGATIVELOOKBEHIND, next, result);
  283.         break;
  284.     case Token::INDEPENDENT:
  285.         ret = fOpFactory.createIndependentOp(next, result);
  286.         break;
  287.     case Token::MODIFIERGROUP:
  288.         ret = fOpFactory.createModifierOp(next, result,
  289.                                    ((ModifierToken *) token)->getOptions(),
  290.                                    ((ModifierToken *) token)->getOptionsMask());
  291.         break;
  292.     }
  293.     return ret;
  294. }
  295. inline Op* RegularExpression::compileSingle(const Token* const token,
  296.                                             Op* const next,
  297.                                             const unsigned short tokType) {
  298.     Op* ret = 0;
  299.     switch (tokType) {
  300.     case Token::DOT:
  301.         ret = fOpFactory.createDotOp();
  302.         break;
  303.     case Token::CHAR:
  304.         ret = fOpFactory.createCharOp(token->getChar());
  305.         break;
  306.     case Token::ANCHOR:
  307.         ret = fOpFactory.createAnchorOp(token->getChar());
  308.         break;
  309.     case Token::RANGE:
  310.     case Token::NRANGE:
  311.         ret = fOpFactory.createRangeOp(token);
  312.         break;
  313.     case Token::EMPTY:
  314.         ret = next;
  315.         break;
  316.     case Token::STRING:
  317.         ret = fOpFactory.createStringOp(token->getString());
  318.         break;
  319.     case Token::BACKREFERENCE:
  320.         ret = fOpFactory.createBackReferenceOp(token->getReferenceNo());
  321.         break;
  322.     }
  323.     if (tokType != Token::EMPTY)
  324.         ret->setNextOp(next);
  325.     return ret;
  326. }
  327. inline Op* RegularExpression::compileUnion(const Token* const token,
  328.                                            Op* const next,
  329.                                            const bool reverse) {
  330.     int tokSize = token->size();
  331.     UnionOp* uniOp = fOpFactory.createUnionOp(tokSize);
  332.     for (int i=0; i<tokSize; i++) {
  333.         uniOp->addElement(compile(token->getChild(i), next, reverse));
  334.     }
  335.     return uniOp;
  336. }
  337. inline Op* RegularExpression::compileCondition(const Token* const token,
  338.                                                Op* const next,
  339.                                                const bool reverse) {
  340.     Token* condTok = ((ConditionToken*) token)->getConditionToken();
  341.     Token* yesTok  = token->getChild(0);
  342.     Token* noTok   = token->getChild(1);
  343.     int    refNo   = token->getReferenceNo();
  344.     Op*    condOp  = (condTok == 0) ? 0 : compile(condTok, 0, reverse);
  345.     Op*    yesOp   = compile(yesTok, next, reverse);
  346.     Op*    noOp    = (noTok == 0) ? 0 : compile(noTok, next, reverse);
  347.     return fOpFactory.createConditionOp(next, refNo, condOp, yesOp, noOp);
  348. }
  349. inline Op* RegularExpression::compileParenthesis(const Token* const token,
  350.                                                  Op* const next,
  351.                                                  const bool reverse) {
  352.     if (token->getNoParen() == 0)
  353.         return compile(token->getChild(0), next, reverse);
  354.     Op* captureOp    = 0;
  355.     if (reverse) {
  356.         captureOp = fOpFactory.createCaptureOp(token->getNoParen(), next);
  357.         captureOp = compile(token->getChild(0), captureOp, reverse);
  358.         return fOpFactory.createCaptureOp(-token->getNoParen(), captureOp);
  359.     }
  360.     captureOp = fOpFactory.createCaptureOp(-token->getNoParen(), next);
  361.     captureOp = compile(token->getChild(0), captureOp, reverse);
  362.     return fOpFactory.createCaptureOp(token->getNoParen(), captureOp);
  363. }
  364. inline Op* RegularExpression::compileConcat(const Token* const token,
  365.                                             Op*  const next,
  366.                                             const bool reverse) {
  367.     Op* ret = next;
  368.     int tokSize = token->size();
  369.     if (!reverse) {
  370.         for (int i= tokSize - 1; i>=0; i--) {
  371.             ret = compile(token->getChild(i), ret, false);
  372.         }
  373.     }
  374.     else {
  375.         for (int i= 0; i< tokSize; i++) {
  376.             ret = compile(token->getChild(i), ret, true);
  377.         }
  378.     }
  379.     return ret;
  380. }
  381. inline Op* RegularExpression::compileClosure(const Token* const token,
  382.                                              Op* const next,
  383.                                              const bool reverse,
  384.                                              const unsigned short tokType) {
  385.     Op*    ret      = 0;
  386.     Token* childTok = token->getChild(0);
  387.     int    min      = token->getMin();
  388.     int    max      = token->getMax();
  389.     if (min >= 0 && min == max) {
  390.         ret = next;
  391.         for (int i=0; i< min; i++) {
  392.             ret = compile(childTok, ret, reverse);
  393.         }
  394.         return ret;
  395.     }
  396.     if (min > 0 && max > 0)
  397.         max -= min;
  398.     if (max > 0) {
  399.         ret = next;
  400.         for (int i=0; i<max; i++) {
  401.             ChildOp* childOp = fOpFactory.createQuestionOp(
  402.                 tokType == Token::NONGREEDYCLOSURE);
  403.             childOp->setNextOp(next);
  404.             childOp->setChild(compile(childTok, ret, reverse));
  405.             ret = childOp;
  406.         }
  407.     }
  408.     else {
  409.         ChildOp* childOp = 0;
  410.         if (tokType == Token::NONGREEDYCLOSURE) {
  411.             childOp = fOpFactory.createNonGreedyClosureOp();
  412.         }
  413.         else {
  414.             if (childTok->getMinLength() == 0)
  415.                 childOp = fOpFactory.createClosureOp(fNoClosures++);
  416.             else
  417.                 childOp = fOpFactory.createClosureOp(-1);
  418.         }
  419.         childOp->setNextOp(next);
  420.         childOp->setChild(compile(childTok, childOp, reverse));
  421.         ret = childOp;
  422.     }
  423.     if (min > 0) {
  424.         for (int i=0; i< min; i++) {
  425.             ret = compile(childTok, ret, reverse);
  426.         }
  427.     }
  428.     return ret;
  429. }
  430. inline int RegularExpression::matchUnion(Context* const context,
  431.                                          const Op* const op, int offset,
  432.                                          const short direction)
  433. {
  434.     unsigned int opSize = op->getSize();
  435.     int ret = -1;
  436.     for (unsigned int i=0; i < opSize; i++) {
  437.         ret = match(context, op->elementAt(i), offset, direction);
  438.         if (ret == context->fLimit)
  439.             return ret;
  440.     }
  441.     return -1;
  442. }
  443. inline int RegularExpression::matchModifier(Context* const context,
  444.                                             const Op* const op, int offset,
  445.                                             const short direction)
  446. {
  447.     int saveOptions = fOptions;
  448.     fOptions |= (int) op->getData();
  449.     fOptions &= (int) ~op->getData2();
  450.     int ret = match(context, op->getChild(), offset, direction);
  451.     fOptions = saveOptions;
  452.     return ret;
  453. }
  454. inline unsigned short RegularExpression::getWordType(const XMLCh* const target
  455.                                                      , const int begin
  456.                                                      , const int end
  457.                                                      , const int offset)
  458. {
  459.     if (offset < begin || offset >= end)
  460.         return WT_OTHER;
  461.     return getCharType(target[offset]);
  462. }
  463. inline
  464. unsigned short RegularExpression::getPreviousWordType(const XMLCh* const target
  465.                                                       , const int start
  466.                                                       , const int end
  467.                                                       , int offset)
  468. {
  469.     unsigned short ret = getWordType(target, start, end, --offset);
  470.     while (ret == WT_IGNORE) {
  471.         ret = getWordType(target, start, end, --offset);
  472.     }
  473.     return ret;
  474. }
  475. inline bool RegularExpression::matchIgnoreCase(const XMLInt32 ch1,
  476.                                                const XMLInt32 ch2)
  477. {
  478.     //REVISIT - for now we will return a case sensitive match
  479.     return (ch1 == ch2);
  480. }
  481. #endif
  482. /**
  483.   * End of file RegularExpression.hpp
  484.   */