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

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: RangeToken.cpp,v $
  58.  * Revision 1.4  2001/05/29 19:39:33  knoaman
  59.  * Typo fix
  60.  *
  61.  * Revision 1.3  2001/05/11 13:26:45  tng
  62.  * Copyright update.
  63.  *
  64.  * Revision 1.2  2001/05/03 18:17:37  knoaman
  65.  * Some design changes:
  66.  * o Changed the TokenFactory from a single static instance, to a
  67.  *    normal class. Each RegularExpression object will have its own
  68.  *    instance of TokenFactory, and that instance will be passed to
  69.  *    other classes that need to use a TokenFactory to create Token
  70.  *    objects (with the exception of RangeTokenMap).
  71.  * o Added a new class RangeTokenMap to map a the different ranges
  72.  *    in a given category to a specific RangeFactory object. In the old
  73.  *    design RangeFactory had dual functionality (act as a Map, and as
  74.  *    a factory for creating RangeToken(s)). The RangeTokenMap will
  75.  *    have its own copy of the TokenFactory. There will be only one
  76.  *    instance of the RangeTokenMap class, and that instance will be
  77.  *    lazily deleted when XPlatformUtils::Terminate is called.
  78.  *
  79.  * Revision 1.1  2001/03/02 19:26:46  knoaman
  80.  * Schema: Regular expression handling part II
  81.  *
  82.  */
  83. // ---------------------------------------------------------------------------
  84. //  Includes
  85. // ---------------------------------------------------------------------------
  86. #include <util/regx/RangeToken.hpp>
  87. #include <util/regx/TokenFactory.hpp>
  88. #include <util/XMLExceptMsgs.hpp>
  89. // ---------------------------------------------------------------------------
  90. //  Static member data initialization
  91. // ---------------------------------------------------------------------------
  92. const int RangeToken::MAPSIZE = 256;
  93. const unsigned int RangeToken::INITIALSIZE = 16;
  94. // ---------------------------------------------------------------------------
  95. //  RangeToken: Constructors and Destructors
  96. // ---------------------------------------------------------------------------
  97. RangeToken::RangeToken(const unsigned short tokType) : Token(tokType)
  98.     , fSorted(false)
  99.     , fCompacted(false)
  100.     , fNonMapIndex(0)
  101.     , fElemCount(0)
  102.     , fMaxCount(0)
  103.     , fMap(0)
  104.     , fRanges(0)
  105.     , fCaseIToken(0)
  106. {
  107. }
  108. RangeToken::~RangeToken() {
  109.     delete fMap;
  110.     delete[] fRanges;
  111. }
  112. // ---------------------------------------------------------------------------
  113. //  RangeToken: Getter methods
  114. // ---------------------------------------------------------------------------
  115. RangeToken* RangeToken::getCaseInsensitiveToken(TokenFactory* const tokFactory) {
  116.     // REVIST
  117.     // We will not build a token with case insenstive ranges
  118.     // For now we will return a copy of ourselves.
  119.     if (fCaseIToken == 0 && tokFactory) {
  120.         bool isNRange = (getTokenType() == NRANGE) ? true : false;
  121.         RangeToken* lwrToken = tokFactory->createRange(isNRange);
  122.         lwrToken->mergeRanges(this);
  123.         fCaseIToken = lwrToken;
  124.     }
  125.     return fCaseIToken;
  126. }
  127. // ---------------------------------------------------------------------------
  128. //  RangeToken: Range manipulation methods
  129. // ---------------------------------------------------------------------------
  130. void RangeToken::addRange(const XMLInt32 start, const XMLInt32 end) {
  131.     XMLInt32 val1, val2;
  132.     fCaseIToken = 0;
  133.     if (start <= end) {
  134.         val1 = start;
  135.         val2 = end;
  136.     }
  137.     else {
  138.         val1 = end;
  139.         val2 = start;
  140.     }
  141.     if (fRanges == 0) {
  142.         fMaxCount = INITIALSIZE;
  143.         fRanges = new XMLInt32[fMaxCount];
  144.         fRanges[0] = val1;
  145.         fRanges[1] = val2;
  146.         fElemCount = 2;
  147.         fSorted = true;
  148.     }
  149.     else {
  150.         if (fRanges[fElemCount-1] + 1 == val1) {
  151.             fRanges[fElemCount-1] = val2;
  152.             return;
  153.         }
  154.         if (fElemCount + 2 >= fMaxCount) {
  155.             expand(2);
  156.         }
  157.         if (fRanges[fElemCount-1] >= val1)
  158.             fSorted = false;
  159.         fRanges[fElemCount++] = val1;
  160.         fRanges[fElemCount++] = val2;
  161.         if (!fSorted) {
  162.             sortRanges();
  163.         }
  164.     }
  165. }
  166. void RangeToken::sortRanges() {
  167.     if (fSorted || fRanges == 0)
  168.         return;
  169.     for (int i = fElemCount - 4; i >= 0; i -= 2) {
  170.         for (int j = 0; j <= i; j +=2) {
  171.             if (fRanges[j] > fRanges[j + 2]
  172.                 || (fRanges[j]==fRanges[j+2] && fRanges[j+1] > fRanges[j+3])) {
  173.                 XMLInt32 tmpVal = fRanges[j+2];
  174.                 fRanges[j+2] = fRanges[j];
  175.                 fRanges[j] = tmpVal;
  176.                 tmpVal = fRanges[j+3];
  177.                 fRanges[j+3] = fRanges[j+1];
  178.                 fRanges[j+1] = tmpVal;
  179.             }
  180.         }
  181.     }
  182.     fSorted = true;
  183. }
  184. void RangeToken::compactRanges() {
  185.     if (fCompacted || fRanges == 0 || fElemCount <= 2)
  186.         return;
  187.     unsigned int base = 0;
  188.     unsigned int target = 0;
  189.     while (target < fElemCount) {
  190.         if (base != target) {
  191.             fRanges[base] = fRanges[target++];
  192.             fRanges[base+1] = fRanges[target++];
  193.         }
  194.         else
  195.             target += 2;
  196.         XMLInt32 baseEnd = fRanges[base + 1];
  197.         while (target < fElemCount) {
  198.             XMLInt32 startRange = fRanges[target];
  199.             if (baseEnd + 1 < startRange)
  200.                 break;
  201.             XMLInt32 endRange = fRanges[target + 1];
  202.             if (baseEnd + 1 == startRange || baseEnd < endRange) {
  203.                 baseEnd = endRange;
  204.                 fRanges[base+1] = baseEnd;
  205.                 target += 2;
  206.             }
  207.             else if (baseEnd >= endRange) {
  208.                 target += 2;
  209.             }
  210.             else {
  211.                 ThrowXML(RuntimeException, XMLExcepts::Regex_CompactRangesError);
  212.             }
  213.         } // inner while
  214.         base += 2;
  215.     }
  216.     if (base != fElemCount) {
  217.         while (fElemCount > base) {
  218.             fRanges[fElemCount--] = 0;
  219.         }
  220.     }
  221.     fCompacted = true;
  222. }
  223. void RangeToken::mergeRanges(const Token *const tok) {
  224.     if (tok->getTokenType() != this->getTokenType())
  225.         ThrowXML(IllegalArgumentException, XMLExcepts::Regex_MergeRangesTypeMismatch);
  226.     RangeToken* rangeTok = (RangeToken *) tok;
  227.     if (rangeTok->fRanges == 0)
  228.         return;
  229.     fCaseIToken = 0;
  230.     sortRanges();
  231.     rangeTok->sortRanges();
  232.     if (fRanges == 0) {
  233.         fMaxCount = rangeTok->fMaxCount;
  234.         fRanges = new XMLInt32[fMaxCount];
  235.         for (unsigned int index = 0; index < rangeTok->fElemCount; index++) {
  236.             fRanges[index] = rangeTok->fRanges[index];
  237.         }
  238.         fElemCount = rangeTok->fElemCount;
  239.         return;
  240.     }
  241.     unsigned int newMaxCount = (fElemCount + rangeTok->fElemCount >= fMaxCount)
  242.                                  ? fMaxCount + rangeTok->fMaxCount : fMaxCount;
  243.     XMLInt32* result = new XMLInt32[newMaxCount];
  244.     for (unsigned int i=0, j=0, k=0; i < fElemCount || j < rangeTok->fElemCount;) {
  245.         if (i >= fElemCount) {
  246.             for (int count = 0; count < 2; count++) {
  247.                 result[k++] = rangeTok->fRanges[j++];
  248.             }
  249.         }
  250.         else if (j >= rangeTok->fElemCount) {
  251.             for (int count = 0; count < 2; count++) {
  252.                 result[k++] = fRanges[i++];
  253.             }
  254.         }
  255.         else if (rangeTok->fRanges[j] < fRanges[i]
  256.                  || (rangeTok->fRanges[j] == fRanges[i]
  257.                      && rangeTok->fRanges[j+1] < fRanges[i+1])) {
  258.             for (int count = 0; count < 2; count++) {
  259.                 result[k++] = rangeTok->fRanges[j++];
  260.             }
  261.         }
  262.         else {
  263.             for (int count = 0; count < 2; count++) {
  264.                 result[k++] = fRanges[i++];
  265.             }
  266.         }
  267.     }
  268.     delete [] fRanges;
  269.     fElemCount += rangeTok->fElemCount;
  270.     fRanges = result;
  271.     fMaxCount = newMaxCount;
  272. }
  273. void RangeToken::subtractRanges(RangeToken* const tok) {
  274.     if (fRanges == 0 || tok->fRanges == 0)
  275.         return;
  276.     if (tok->getTokenType() == NRANGE) {
  277.         intersectRanges(tok);
  278.         return;
  279.     }
  280.     fCaseIToken = 0;
  281.     sortRanges();
  282.     compactRanges();
  283.     tok->sortRanges();
  284.     tok->compactRanges();
  285.     unsigned int newMax = (fElemCount + tok->fElemCount >= fMaxCount)
  286.                              ? fMaxCount + tok->fMaxCount : fMaxCount;
  287.     XMLInt32* result = new XMLInt32[newMax];
  288.     unsigned int newElemCount = 0;
  289.     unsigned int srcCount = 0;
  290.     unsigned int subCount = 0;
  291.     while (srcCount < fElemCount && subCount < tok->fElemCount) {
  292.         XMLInt32 srcBegin = fRanges[srcCount];
  293.         XMLInt32 srcEnd = fRanges[srcCount + 1];
  294.         XMLInt32 subBegin = tok->fRanges[subCount];
  295.         XMLInt32 subEnd = tok->fRanges[subCount + 1];
  296.         if (srcEnd < subBegin) { // no overlap
  297.             result[newElemCount++] = fRanges[srcCount++];
  298.             result[newElemCount++] = fRanges[srcCount++];
  299.         }
  300.         else if (srcEnd >= subBegin && srcBegin <= subEnd) {
  301.             if (subBegin <= srcBegin && srcEnd <= subEnd) {
  302.                 srcCount += 2;
  303.             }
  304.             else if (subBegin <= srcBegin) {
  305.                 fRanges[srcCount] = subEnd + 1;
  306.                 subCount += 2;
  307.             }
  308.             else if (srcEnd <= subEnd) {
  309.                 result[newElemCount++] = srcBegin;
  310.                 result[newElemCount++] = subBegin - 1;
  311.                 srcCount += 2;
  312.             }
  313.             else {
  314.                 result[newElemCount++] = srcBegin;
  315.                 result[newElemCount++] = subBegin - 1;
  316.                 fRanges[srcCount] = subEnd + 1;
  317.                 subCount += 2;
  318.             }
  319.         }
  320.         else if (subEnd < srcBegin) {
  321.             subCount += 2;
  322.         }
  323.         else {
  324.             delete [] result;
  325.             ThrowXML(RuntimeException, XMLExcepts::Regex_SubtractRangesError);
  326.         }
  327.     } //end while
  328.     while (srcCount < fElemCount) {
  329.         result[newElemCount++] = fRanges[srcCount++];
  330.         result[newElemCount++] = fRanges[srcCount++];
  331.     }
  332.     delete [] fRanges;
  333.     fRanges = result;
  334.     fElemCount = newElemCount;
  335.     fMaxCount = newMax;
  336. }
  337. /**
  338.   * Ignore whether 'tok' is NRANGE or not.
  339.   */
  340. void RangeToken::intersectRanges(RangeToken* const tok) {
  341.     if (fRanges == 0 || tok->fRanges == 0)
  342.         return;
  343.     fCaseIToken = 0;
  344.     sortRanges();
  345.     compactRanges();
  346.     tok->sortRanges();
  347.     tok->compactRanges();
  348.     unsigned int newMax = (fElemCount + tok->fElemCount >= fMaxCount)
  349.                              ? fMaxCount + tok->fMaxCount : fMaxCount;
  350.     XMLInt32* result = new XMLInt32[newMax];
  351.     unsigned int newElemCount = 0;
  352.     unsigned int srcCount = 0;
  353.     unsigned int tokCount = 0;
  354.     while (srcCount < fElemCount && tokCount < tok->fElemCount) {
  355.         XMLInt32 srcBegin = fRanges[srcCount];
  356.         XMLInt32 srcEnd = fRanges[srcCount + 1];
  357.         XMLInt32 tokBegin = tok->fRanges[tokCount];
  358.         XMLInt32 tokEnd = tok->fRanges[tokCount + 1];
  359.         if (srcEnd < tokBegin) {
  360.             srcCount += 2;
  361.         }
  362.         else if (srcEnd >= tokBegin && srcBegin <= tokEnd) {
  363.             if (tokBegin <= srcBegin && srcEnd <= tokEnd) {
  364.                 result[newElemCount++] = srcBegin;
  365.                 result[newElemCount++] = srcEnd;
  366.                 srcCount += 2;
  367.             }
  368.             else if (tokBegin <= srcBegin) {
  369.                 result[newElemCount++] = srcBegin;
  370.                 result[newElemCount++] = tokEnd;
  371.                 tokCount += 2;
  372.                 if (tokCount < tok->fElemCount)
  373.                     fRanges[srcCount] = tokEnd + 1;
  374.                 else
  375.                     srcCount += 2;
  376.             }
  377.             else if (srcEnd <= tokEnd) {
  378.                 result[newElemCount++] = tokBegin;
  379.                 result[newElemCount++] = srcEnd;
  380.                 srcCount += 2;
  381.             }
  382.             else {
  383.                 result[newElemCount++] = tokBegin;
  384.                 result[newElemCount++] = tokEnd;
  385.                 tokCount += 2;
  386.                 if (tokCount < tok->fElemCount)
  387.                     fRanges[srcCount] = tokEnd + 1;
  388.                 else
  389.                     srcCount += 2;
  390.             }
  391.         }
  392.         else if (tokEnd < srcBegin) {
  393.             tokCount += 2;
  394.             if (tokCount >= tok->fElemCount)
  395.                 srcCount += 2;
  396.         }
  397.         else {
  398.             delete [] result;
  399.             ThrowXML(RuntimeException, XMLExcepts::Regex_IntersectRangesError);
  400.         }
  401.     } //end while
  402.     delete [] fRanges;
  403.     fRanges = result;
  404.     fElemCount = newElemCount;
  405.     fMaxCount = newMax;
  406. }
  407. /**
  408.   * for RANGE: Creates complement.
  409.   * for NRANGE: Creates the same meaning RANGE.
  410.   */
  411. Token* RangeToken::complementRanges(RangeToken* const tok,
  412.                                     TokenFactory* const tokFactory) {
  413.     if (tok->getTokenType() != RANGE && tok->getTokenType() != NRANGE)
  414.         ThrowXML(IllegalArgumentException, XMLExcepts::Regex_ComplementRangesInvalidArg);
  415.     tok->sortRanges();
  416.     tok->compactRanges();
  417.     XMLInt32 lastElem = tok->fRanges[tok->fElemCount - 1];
  418.     RangeToken* rangeTok = tokFactory->createRange();
  419.     if (tok->fRanges[0] > 0) {
  420.         rangeTok->addRange(0, tok->fRanges[0] - 1);
  421.     }
  422.     for (unsigned int i= 1; i< tok->fElemCount - 2; i += 2) {
  423.         rangeTok->addRange(tok->fRanges[i] + 1, tok->fRanges[i+1] - 1);
  424.     }
  425.     if (lastElem != UTF16_MAX) {
  426.         rangeTok->addRange(lastElem + 1, UTF16_MAX);
  427.     }
  428.     rangeTok->fCompacted = true;
  429.     return rangeTok;
  430. }
  431. // ---------------------------------------------------------------------------
  432. //  RangeToken: Match methods
  433. // ---------------------------------------------------------------------------
  434. bool RangeToken::match(const XMLInt32 ch) {
  435.     if (fMap == 0)
  436.         createMap();
  437.     bool ret;
  438.     if (getTokenType() == RANGE) {
  439.         if (ch < MAPSIZE)
  440.             return ((fMap[ch/32] & (1<<(ch&0x1f))) != 0);
  441.         ret = false;
  442.         for (unsigned int i= fNonMapIndex; i< fElemCount; i +=2) {
  443.             if (fRanges[i] <= ch && ch <= fRanges[i+1])
  444.                 return true;
  445.         }
  446.     }
  447.     else {
  448.         if (ch < MAPSIZE)
  449.             return ((fMap[ch/32] & (1<<(ch&0x1f))) == 0);
  450.         ret = true;
  451.         for (unsigned int i= fNonMapIndex; i< fElemCount; i += 2) {
  452.             if (fRanges[i] <= ch && ch <= fRanges[i+1])
  453.                 return false;
  454.         }
  455.     }
  456.     return ret;
  457. }
  458. // ---------------------------------------------------------------------------
  459. //  RangeToken: Private helpers methods
  460. // ---------------------------------------------------------------------------
  461. void RangeToken::expand(const unsigned int length) {
  462.     unsigned int newMax = fElemCount + length;
  463.     // Avoid too many reallocations by expanding by a percentage
  464.     unsigned int minNewMax = (unsigned int)((double)fElemCount * 1.25);
  465.     if (newMax < minNewMax)
  466.         newMax = minNewMax;
  467.     XMLInt32* newList = new XMLInt32[newMax];
  468.     for (unsigned int index = 0; index < fElemCount; index++)
  469.         newList[index] = fRanges[index];
  470.     delete [] fRanges;
  471.     fRanges = newList;
  472.     fMaxCount = newMax;
  473. }
  474. void RangeToken::createMap() {
  475.     int asize = MAPSIZE/32;
  476.     fMap = new int[asize];
  477.     fNonMapIndex = fElemCount;
  478.     for (int i = 0; i < asize; i++) {
  479.         fMap[i] = 0;
  480.     }
  481.     for (unsigned int j= 0; j < fElemCount; j += 2) {
  482.         XMLInt32 begin = fRanges[j];
  483.         XMLInt32 end = fRanges[j+1];
  484.         if (begin < MAPSIZE) {
  485.             for (int k = begin; k <= end && k < MAPSIZE; k++) {
  486.                 fMap[k/32] |= 1<<(k&0x1F);
  487.             }
  488.         }
  489.         else {
  490.             fNonMapIndex = j;
  491.             break;
  492.         }
  493.         if (end >= MAPSIZE) {
  494.             fNonMapIndex = j;
  495.             break;
  496.         }
  497.     }
  498. }
  499. /**
  500.   * End of file RangeToken.cpp
  501.   */