GME  13
XMLBigInteger.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: XMLBigInteger.cpp 555320 2007-07-11 16:05:13Z amassari $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/util/XMLBigInteger.hpp>
00026 #include <xercesc/util/XMLString.hpp>
00027 #include <xercesc/util/NumberFormatException.hpp>
00028 #include <xercesc/util/PlatformUtils.hpp>
00029 #include <xercesc/util/TransService.hpp>
00030 #include <xercesc/util/XMLUniDefs.hpp>
00031 #include <xercesc/util/Janitor.hpp>
00032 #include <xercesc/util/XMLChar.hpp>
00033 
00034 XERCES_CPP_NAMESPACE_BEGIN
00035 
00036 XMLCh* XMLBigInteger::getCanonicalRepresentation(const XMLCh*         const rawData
00037                                                ,       MemoryManager* const memMgr
00038                                                ,       bool           /*      isNonPositiveInteger */)
00039 {
00040     try 
00041     {
00042         XMLCh* retBuf = (XMLCh*) memMgr->allocate( (XMLString::stringLen(rawData) + 2) * sizeof(XMLCh));
00043         ArrayJanitor<XMLCh> jan(retBuf, memMgr);
00044         int    sign = 0;
00045 
00046         XMLBigInteger::parseBigInteger(rawData, retBuf, sign);
00047 
00048         if (sign == 0)
00049         {
00050            retBuf[0] = chDigit_0;
00051            retBuf[1] = chNull;           
00052         }
00053         else if (sign == -1)
00054         {
00055             XMLCh* retBuffer = (XMLCh*) memMgr->allocate( (XMLString::stringLen(retBuf) + 2) * sizeof(XMLCh));
00056             retBuffer[0] = chDash;
00057             XMLString::copyString(&(retBuffer[1]), retBuf);
00058             return retBuffer;
00059         }
00060 
00061         jan.release();
00062         return retBuf;
00063 
00064     }
00065     catch (const NumberFormatException&)
00066     {
00067         return 0;
00068     }
00069 
00070 }
00071 
00072 /***
00073    *
00074    *  Leading and trailing whitespaces are allowed, and trimmed
00075    *
00076    *  Only one and either of (+,-) after the leading whitespace, before
00077    *  any other characters are allowed, and trimmed
00078    *
00079    *  Leading zero, after leading whitespace, (+|-), before any other
00080    *  characters are allowed, and trimmed
00081    *
00082    *  '.' NOT allowed
00083 
00084    *  return status: void
00085    *  ret_buf: w/o leading and/or trailing whitespace
00086    *           w/o '+' and '-'
00087    *           w/o leading zero
00088    *
00089    *  see XMLString::parseInt();
00090    *      XMLString::textToBin();
00091    *
00092    *  "    +000203456"            "203456"
00093    *  "    -000203456"            "203456"
00094    *
00095 ***/
00096 
00097 void XMLBigInteger::parseBigInteger(const XMLCh* const toConvert
00098                                   , XMLCh* const retBuffer
00099                                   , int&   signValue
00100                                   , MemoryManager* const manager)
00101 {
00102     // If no string, then its a failure
00103     if ((!toConvert) || (!*toConvert))
00104         ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, manager);
00105 
00106     //
00107     // Note: in Java's BigInteger, it seems any leading and/or trailing
00108     // whitespaces are not allowed. If this is the case, we may
00109     // need to skip the trimming below.
00110     //
00111 
00112     // Scan past any whitespace. If we hit the end, then return failure
00113     const XMLCh* startPtr = toConvert;
00114     while (XMLChar1_0::isWhitespace(*startPtr))
00115         startPtr++;
00116 
00117     if (!*startPtr)
00118         ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_WSString, manager);
00119 
00120     // Start at the end and work back through any whitespace
00121     const XMLCh* endPtr = toConvert + XMLString::stringLen(toConvert);
00122     while (XMLChar1_0::isWhitespace(*(endPtr - 1)))
00123         endPtr--;
00124 
00125     //
00126     //  Work through what remains and convert each char to a digit.
00127     //  anything other than '
00128     //
00129     XMLCh* retPtr = retBuffer;
00130     signValue = 1;
00131 
00132     //
00133     // '+' or '-' is allowed only at the first position
00134     //
00135     if (*startPtr == chDash)
00136     {
00137         signValue = -1;
00138         startPtr++;
00139         if (startPtr == endPtr)
00140         {
00141             ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
00142         }
00143     }
00144     else if (*startPtr == chPlus)
00145     {
00146         // skip the '+'
00147         startPtr++;
00148         if (startPtr == endPtr)
00149         {
00150             ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
00151         }
00152     }
00153 
00154 
00155     // Scan past any leading zero.
00156     while (*startPtr == chDigit_0)
00157         startPtr++;
00158 
00159     if (startPtr >= endPtr)
00160     {
00161         signValue = 0;
00162         // containning zero, only zero, nothing but zero
00163         // it is a zero, indeed
00164         return;
00165     }
00166 
00167     while (startPtr < endPtr)
00168     {
00169         // If not valid decimal digit, then an error
00170         if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
00171             ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
00172 
00173         // copy over
00174         *retPtr = *startPtr;
00175         retPtr++;
00176         startPtr++;
00177     }
00178 
00179     *retPtr = 0;   //terminated
00180     return;
00181 }
00182 
00183 
00191 XMLBigInteger::XMLBigInteger(const XMLCh* const strValue,
00192                              MemoryManager* const manager)
00193 : fSign(0)
00194 , fMagnitude(0)
00195 , fRawData(0)
00196 , fMemoryManager(manager)
00197 {
00198     if (!strValue)
00199         ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, fMemoryManager);
00200 
00201     XMLCh* ret_value = (XMLCh*) fMemoryManager->allocate
00202     (
00203        (XMLString::stringLen(strValue) + 1) * sizeof(XMLCh)
00204     );//new XMLCh[XMLString::stringLen(strValue)+1];
00205     ArrayJanitor<XMLCh> janName(ret_value, fMemoryManager);
00206 
00207     parseBigInteger(strValue, ret_value, fSign, fMemoryManager);
00208 
00209     if (fSign == 0)
00210         fMagnitude = XMLString::replicate(XMLUni::fgZeroLenString, fMemoryManager);
00211     else
00212         fMagnitude = XMLString::replicate(ret_value, fMemoryManager);
00213 
00214         fRawData = XMLString::replicate(strValue, fMemoryManager);
00215 }
00216 
00217 XMLBigInteger::~XMLBigInteger()
00218 {
00219     fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
00220         if (fRawData)
00221                 fMemoryManager->deallocate(fRawData);//delete[] fRawData;
00222 }
00223 
00224 XMLBigInteger::XMLBigInteger(const XMLBigInteger& toCopy)
00225 : XMemory(toCopy)
00226 , fSign(toCopy.fSign)
00227 , fMagnitude(0)
00228 , fRawData(0)
00229 , fMemoryManager(toCopy.fMemoryManager)
00230 {
00231     fMagnitude = XMLString::replicate(toCopy.fMagnitude, fMemoryManager);
00232         fRawData = XMLString::replicate(toCopy.fRawData, fMemoryManager);
00233 }
00234 
00239 int  XMLBigInteger::compareValues(const XMLBigInteger* const lValue
00240                                 , const XMLBigInteger* const rValue
00241                                 , MemoryManager* const manager)
00242 {
00243     if ((!lValue) || (!rValue) )
00244         ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
00245 
00246     int lSign = lValue->getSign();
00247     int rSign = rValue->getSign();
00248 
00249     //
00250     // different sign
00251     //
00252     if (lSign != rSign)
00253         return(lSign > rSign ? 1 : -1);
00254 
00255     //
00256     // same sign
00257     //
00258     if (lSign == 0)    // optimization
00259         return 0;
00260 
00261     XMLSize_t lStrLen = XMLString::stringLen(lValue->fMagnitude);
00262     XMLSize_t rStrLen = XMLString::stringLen(rValue->fMagnitude);
00263 
00264     //
00265     // different length
00266     //
00267     if (lStrLen > rStrLen)
00268         return ( lSign > 0 ? 1 : -1 );
00269     else if (lStrLen < rStrLen)
00270         return ( lSign > 0 ? -1 : 1 );
00271 
00272     //
00273     // same length
00274     // XMLString::compareString() return > 0, 0 and <0
00275     // we need to convert it to 1, 0, and -1
00276     //
00277     int retVal = XMLString::compareString(lValue->fMagnitude, rValue->fMagnitude);
00278 
00279     if ( retVal > 0 )
00280     {
00281         return ( lSign > 0 ? 1 : -1 );
00282     }
00283     else if ( retVal < 0 )
00284     {
00285         return ( lSign > 0 ? -1 : 1 );
00286     }
00287     else
00288         return 0;
00289 
00290 }
00291 
00292 int XMLBigInteger::compareValues(const XMLCh*         const lString
00293                                , const int&                 lSign
00294                                , const XMLCh*         const rString
00295                                , const int&                 rSign
00296                                ,       MemoryManager* const manager)
00297 {
00298     if ((!lString) || (!rString) )
00299         ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
00300 
00301     //
00302     // different sign
00303     //
00304     if (lSign != rSign)
00305         return(lSign > rSign ? 1 : -1);
00306 
00307     //
00308     // same sign
00309     //
00310     if (lSign == 0)    // optimization
00311         return 0;
00312 
00313     XMLSize_t lStrLen = XMLString::stringLen(lString);
00314     XMLSize_t rStrLen = XMLString::stringLen(rString);
00315 
00316     //
00317     // different length
00318     //
00319     if (lStrLen > rStrLen)
00320         return ( lSign > 0 ? 1 : -1 );
00321     else if (lStrLen < rStrLen)
00322         return ( lSign > 0 ? -1 : 1 );
00323 
00324     //
00325     // same length
00326     // XMLString::compareString() return > 0, 0 and <0
00327     // we need to convert it to 1, 0, and -1
00328     //
00329     int retVal = XMLString::compareString(lString, rString);
00330 
00331     if ( retVal > 0 )
00332     {
00333         return ( lSign > 0 ? 1 : -1 );
00334     }
00335     else if ( retVal < 0 )
00336     {
00337         return ( lSign > 0 ? -1 : 1 );
00338     }
00339     else
00340         return 0;
00341 
00342 }
00343 
00348 void XMLBigInteger::multiply(const unsigned int byteToShift)
00349 {
00350     if (byteToShift <= 0)
00351         return;
00352 
00353     XMLSize_t strLen = XMLString::stringLen(fMagnitude);
00354     XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
00355     (
00356         (strLen + byteToShift + 1) * sizeof(XMLCh)
00357     );//new XMLCh[strLen+byteToShift+1];
00358     XMLString::moveChars(tmp, fMagnitude, strLen);
00359 
00360     unsigned int i = 0;
00361     for ( ; i < byteToShift; i++)
00362         tmp[strLen+i] = chDigit_0;
00363 
00364     tmp[strLen+i] = chNull;
00365 
00366     fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
00367     fMagnitude = tmp;
00368 }
00369 
00374 void XMLBigInteger::divide(const unsigned int byteToShift)
00375 {
00376     if (byteToShift <= 0)
00377         return;
00378 
00379     XMLSize_t strLen = XMLString::stringLen(fMagnitude);
00380     XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
00381     (
00382         (strLen - byteToShift + 1) * sizeof(XMLCh)
00383     );//new XMLCh[strLen-byteToShift+1];
00384     XMLString::moveChars(tmp, fMagnitude, strLen-byteToShift);
00385 
00386     tmp[strLen-byteToShift] = chNull;
00387 
00388     fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
00389     fMagnitude = tmp;
00390 }
00391 
00392 //
00393 //
00394 //
00395 int XMLBigInteger::intValue() const
00396 {
00397     unsigned int retVal;
00398     XMLString::textToBin(fMagnitude, retVal, fMemoryManager);
00399     return retVal * getSign();
00400 }
00401 
00402 XERCES_CPP_NAMESPACE_END