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

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.  * $Log: Token.cpp,v $
  58.  * Revision 1.3  2001/05/11 13:26:50  tng
  59.  * Copyright update.
  60.  *
  61.  * Revision 1.2  2001/05/03 18:17:49  knoaman
  62.  * Some design changes:
  63.  * o Changed the TokenFactory from a single static instance, to a
  64.  *    normal class. Each RegularExpression object will have its own
  65.  *    instance of TokenFactory, and that instance will be passed to
  66.  *    other classes that need to use a TokenFactory to create Token
  67.  *    objects (with the exception of RangeTokenMap).
  68.  * o Added a new class RangeTokenMap to map a the different ranges
  69.  *    in a given category to a specific RangeFactory object. In the old
  70.  *    design RangeFactory had dual functionality (act as a Map, and as
  71.  *    a factory for creating RangeToken(s)). The RangeTokenMap will
  72.  *    have its own copy of the TokenFactory. There will be only one
  73.  *    instance of the RangeTokenMap class, and that instance will be
  74.  *    lazily deleted when XPlatformUtils::Terminate is called.
  75.  *
  76.  * Revision 1.1  2001/03/02 19:22:58  knoaman
  77.  * Schema: Regular expression handling part I
  78.  *
  79.  */
  80. // ---------------------------------------------------------------------------
  81. //  Includes
  82. // ---------------------------------------------------------------------------
  83. #include <util/regx/RangeToken.hpp>
  84. #include <util/regx/ModifierToken.hpp>
  85. #include <util/regx/RegularExpression.hpp>
  86. #include <util/regx/RegxUtil.hpp>
  87. // ---------------------------------------------------------------------------
  88. //  Static member data initialization
  89. // ---------------------------------------------------------------------------
  90. const XMLInt32  Token::UTF16_MAX = 0x10FFFF;
  91. const unsigned short Token::FC_CONTINUE = 0;
  92. const unsigned short Token::FC_TERMINAL = 1;
  93. const unsigned short Token::FC_ANY = 2;
  94. // ---------------------------------------------------------------------------
  95. //  Token: Constructors and Destructors
  96. // ---------------------------------------------------------------------------
  97. Token::Token(const unsigned short tokType) : fTokenType(tokType) {
  98. }
  99. Token::~Token() {
  100. }
  101. // ---------------------------------------------------------------------------
  102. //  Token: Getter mthods
  103. // ---------------------------------------------------------------------------
  104. int Token::getMinLength() const {
  105. switch (fTokenType) {
  106. case CONCAT:
  107.         {
  108.             int sum = 0;
  109.             unsigned int childSize = size();
  110.             for (unsigned int i=0; i<childSize; i++) {
  111.                 sum += getChild(i)->getMinLength();
  112.             }
  113.             return sum;
  114.         }
  115. case CONDITION:
  116. case UNION:
  117.         {
  118. unsigned int childSize = size();
  119.             if (childSize == 0) {
  120.                 return 0;
  121.             }
  122. int ret = getChild(0)->getMinLength();
  123.             for (unsigned int i=1; i < childSize; i++) {
  124.                 int min = getChild(i)->getMinLength();
  125.                 if (min < ret)
  126.                     ret = min;
  127.             }
  128. return ret;
  129.         }
  130. case CLOSURE:
  131. case NONGREEDYCLOSURE:
  132.         if (getMin() >= 0)
  133.             return getMin() * getChild(0)->getMinLength();
  134. return 0;
  135. case EMPTY:
  136. case ANCHOR:
  137. return 0;
  138. case DOT:
  139. case CHAR:
  140. case RANGE:
  141. case NRANGE:
  142. return 1;
  143. case INDEPENDENT:
  144. case PAREN:
  145. case MODIFIERGROUP:
  146. return getChild(0)->getMinLength();
  147. case BACKREFERENCE:
  148. return 0; // *****  - REVISIT
  149. case STRING:
  150. return XMLString::stringLen(getString());
  151. case LOOKAHEAD:
  152. case NEGATIVELOOKAHEAD:
  153. case LOOKBEHIND:
  154. case NEGATIVELOOKBEHIND:
  155. return 0; // *****  - REVIST
  156. // default:
  157. // throw;
  158. }
  159. // We should not get here, but we have it to make some compilers happy
  160. return -1;
  161. }
  162. int Token::getMaxLength() const {
  163. switch (fTokenType) {
  164. case CONCAT:
  165.         {
  166.             int sum = 0;
  167.             unsigned int childSize = size();
  168.             for (unsigned int i=0; i<childSize; i++) {
  169.                 int val = getChild(i)->getMaxLength();
  170. if (val < 0){
  171. return -1;
  172. }
  173.                 sum += val;
  174.             }
  175.             return sum;
  176.         }
  177.     case CONDITION:
  178.     case UNION:
  179.         {
  180.             unsigned int childSize = size();
  181. if (childSize == 0)
  182.                 return 0;
  183.             int ret = getChild(0)->getMaxLength();
  184.             for (unsigned i = 1; ret > 0 && i < childSize; i++) {
  185.                 int max = getChild(i)->getMaxLength();
  186.                 if (max < 0) {
  187.                     ret = -1;
  188.                     break;
  189.                 }
  190.                 if (max > ret)
  191.                     ret = max;
  192.             }
  193. return ret;
  194.         }
  195.     case CLOSURE:
  196.     case NONGREEDYCLOSURE:
  197.         if (getMax() >= 0) {
  198.             return getMax() * getChild(0)->getMaxLength();
  199. }
  200. return -1;
  201.     case EMPTY:
  202.     case ANCHOR:
  203.         return 0;
  204.     case CHAR:
  205.         return 1;
  206.     case DOT:
  207.     case RANGE:
  208.     case NRANGE:
  209.         return 2;
  210.     case INDEPENDENT:
  211.     case PAREN:
  212.     case MODIFIERGROUP:
  213.         return getChild(0)->getMaxLength();
  214.     case BACKREFERENCE:
  215. return -1; // REVISIT
  216.     case STRING:
  217.         return XMLString::stringLen(getString());
  218.     case LOOKAHEAD:
  219.     case NEGATIVELOOKAHEAD:
  220.     case LOOKBEHIND:
  221.     case NEGATIVELOOKBEHIND:
  222. return 0; // REVISIT
  223. //    default:
  224. // throw; //ThrowXML(RuntimeException, ...)
  225.     } // end switch
  226. return -1;
  227. }
  228. // ---------------------------------------------------------------------------
  229. //  Token: Helper mthods
  230. // ---------------------------------------------------------------------------
  231. int Token::analyzeFirstCharacter(RangeToken* const rangeTok,
  232.  const int options,
  233.                                  TokenFactory* const tokFactory)
  234. {
  235. switch(fTokenType) {
  236. case CONCAT:
  237. {
  238. int ret = FC_CONTINUE;
  239. for (int i=0; i<size(); i++) {
  240. Token* tok = getChild(i);
  241. if (tok
  242. && (ret=tok->analyzeFirstCharacter(rangeTok,
  243.                                     options, tokFactory))!= FC_CONTINUE)
  244. break;
  245. }
  246. return ret;
  247. }
  248. case UNION:
  249. {
  250. unsigned int childSize = size();
  251.             if (childSize == 0)
  252.                 return FC_CONTINUE;
  253.             int ret = FC_CONTINUE;
  254. bool hasEmpty = false;
  255. for (unsigned int i=0; i < childSize; i++) {
  256.                 ret = getChild(i)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  257. if (ret == FC_ANY)
  258. break;
  259. else
  260. hasEmpty = true;
  261. }
  262. return hasEmpty ? FC_CONTINUE : ret;
  263. }
  264. case CONDITION:
  265. {
  266.             int ret1 = getChild(0)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  267.             if (size() == 1)
  268.                 return FC_CONTINUE;
  269. int ret2;
  270. if (ret1 != FC_ANY) {
  271.     ret2 = getChild(1)->analyzeFirstCharacter(rangeTok, options, tokFactory);
  272. }
  273. if (ret1 == FC_ANY || ret2 == FC_ANY)
  274. return FC_ANY;
  275. if (ret1 == FC_CONTINUE || ret2 == FC_CONTINUE)
  276. return FC_CONTINUE;
  277. return FC_TERMINAL;
  278. }
  279. case CLOSURE:
  280. case NONGREEDYCLOSURE:
  281. {
  282. Token* tok = getChild(0);
  283. if (tok)
  284. tok->analyzeFirstCharacter(rangeTok, options, tokFactory);
  285. return FC_CONTINUE;
  286. }
  287. case DOT:
  288. case EMPTY:
  289. case ANCHOR:
  290. return FC_CONTINUE;
  291. case CHAR:
  292. {
  293.             XMLInt32 ch = getChar();
  294. rangeTok->addRange(ch, ch);
  295. if (ch < 0x1000 && isSet(options,RegularExpression::IGNORE_CASE)) {
  296. //REVISIT
  297. }
  298. }
  299. return FC_TERMINAL;
  300. case RANGE:
  301. {
  302. if (isSet(options, RegularExpression::IGNORE_CASE)) {
  303.                 rangeTok->mergeRanges(((RangeToken*)
  304.                                          this)->getCaseInsensitiveToken(tokFactory));
  305. }
  306. else {
  307. rangeTok->mergeRanges(this);
  308. }
  309. return FC_TERMINAL;
  310. }
  311. case NRANGE:
  312. {
  313. if (isSet(options, RegularExpression::IGNORE_CASE)) {
  314. RangeToken* caseITok = (((RangeToken*)
  315.                        this)->getCaseInsensitiveToken(tokFactory));
  316. rangeTok->mergeRanges(RangeToken::complementRanges(caseITok, tokFactory));
  317. }
  318. else {
  319. rangeTok->mergeRanges(
  320. RangeToken::complementRanges((RangeToken*) this, tokFactory));
  321. }
  322. }
  323. case INDEPENDENT:
  324. case PAREN:
  325. {
  326. Token* tok = getChild(0);
  327. if (tok)
  328. return tok->analyzeFirstCharacter(rangeTok,options, tokFactory);
  329. }
  330. case MODIFIERGROUP:
  331. case BACKREFERENCE:
  332. rangeTok->addRange(0, UTF16_MAX);
  333. return FC_ANY;
  334. case STRING:
  335. {
  336. const XMLCh* str = getString();
  337.             XMLInt32 ch = str[0];
  338. if (RegxUtil::isHighSurrogate((XMLCh) ch)) {
  339. }
  340.     rangeTok->addRange(ch, ch);
  341.     if (ch<0x10000 && isSet(options,RegularExpression::IGNORE_CASE)) {
  342.                 //REVISIT
  343.             }
  344. }
  345. return FC_TERMINAL;
  346. case LOOKAHEAD:
  347. case NEGATIVELOOKAHEAD:
  348. case LOOKBEHIND:
  349. case NEGATIVELOOKBEHIND:
  350. FC_CONTINUE;
  351. // default:
  352. // throw;
  353. }
  354. return 0;
  355. }
  356. Token* Token::findFixedString(int options, int& outOptions) {
  357.     switch(fTokenType) {
  358.     case CHAR:
  359. return 0;
  360.     case STRING:
  361. outOptions = options;
  362. return this;
  363.     case UNION:
  364.     case CLOSURE:
  365.     case NONGREEDYCLOSURE:
  366.     case EMPTY:
  367.     case ANCHOR:
  368.     case RANGE:
  369.     case NRANGE:
  370.     case DOT:
  371.     case BACKREFERENCE:
  372.     case LOOKAHEAD:
  373.     case NEGATIVELOOKAHEAD:
  374.     case LOOKBEHIND:
  375.     case NEGATIVELOOKBEHIND:
  376.     case CONDITION:
  377. return 0;
  378.     case INDEPENDENT:
  379.     case PAREN:
  380. return getChild(0)->findFixedString(options, outOptions);
  381.     case CONCAT:
  382.         {
  383.             Token* prevTok = 0;
  384.             int prevOptions = 0;
  385.             for (int i=0; i<size(); i++) {
  386.                 Token* tok = getChild(i)->findFixedString(options, outOptions);
  387.                 if (prevTok == 0 || prevTok->isShorterThan(tok)) {
  388.                     prevTok = tok;
  389. prevOptions = outOptions;
  390.                 }
  391.             }
  392. outOptions = prevOptions;
  393.             return prevTok;
  394.         }
  395.     case MODIFIERGROUP:
  396.         {
  397.             options |= ((ModifierToken *) this)->getOptions();
  398.             options &= ~((ModifierToken *) this)->getOptionsMask();
  399.             return getChild(0)->findFixedString(options, outOptions);
  400.         }
  401.     } // end switch
  402.     return 0;
  403. }
  404. bool Token::isShorterThan(Token* const tok) {
  405. if (tok == 0)
  406. return false;
  407. if (getTokenType() != STRING && tok->getTokenType() != STRING)
  408. return false; //Should we throw an exception?
  409.     int length = XMLString::stringLen(getString());
  410.     int tokLength = XMLString::stringLen(tok->getString());
  411. return length < tokLength;
  412. }
  413. /**
  414.   * End of file Token.cpp
  415.   */