GME
13
|
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