source: icXML/icXML-devel/src/xercesc/util/XMLBigInteger.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 11.0 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: XMLBigInteger.cpp 555320 2007-07-11 16:05:13Z amassari $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/util/XMLBigInteger.hpp>
26#include <icxercesc/util/XMLString.hpp>
27#include <xercesc/util/NumberFormatException.hpp>
28#include <icxercesc/util/PlatformUtils.hpp>
29#include <icxercesc/util/TransService.hpp>
30#include <xercesc/util/XMLUniDefs.hpp>
31#include <xercesc/util/Janitor.hpp>
32#include <xercesc/util/XMLChar.hpp>
33
34XERCES_CPP_NAMESPACE_BEGIN
35
36XMLCh* XMLBigInteger::getCanonicalRepresentation(const XMLCh*         const rawData
37                                               ,       MemoryManager* const memMgr
38                                               ,       bool           /*      isNonPositiveInteger */)
39{
40    try
41    {
42        XMLCh* retBuf = (XMLCh*) memMgr->allocate( (XMLString::stringLen(rawData) + 2) * sizeof(XMLCh));
43        ArrayJanitor<XMLCh> jan(retBuf, memMgr);
44        int    sign = 0;
45
46        XMLBigInteger::parseBigInteger(rawData, retBuf, sign);
47
48        if (sign == 0)
49        {
50           retBuf[0] = chDigit_0;
51           retBuf[1] = chNull;           
52        }
53        else if (sign == -1)
54        {
55            XMLCh* retBuffer = (XMLCh*) memMgr->allocate( (XMLString::stringLen(retBuf) + 2) * sizeof(XMLCh));
56            retBuffer[0] = chDash;
57            XMLString::copyString(&(retBuffer[1]), retBuf);
58            return retBuffer;
59        }
60
61        jan.release();
62        return retBuf;
63
64    }
65    catch (const NumberFormatException&)
66    {
67        return 0;
68    }
69
70}
71
72/***
73   *
74   *  Leading and trailing whitespaces are allowed, and trimmed
75   *
76   *  Only one and either of (+,-) after the leading whitespace, before
77   *  any other characters are allowed, and trimmed
78   *
79   *  Leading zero, after leading whitespace, (+|-), before any other
80   *  characters are allowed, and trimmed
81   *
82   *  '.' NOT allowed
83
84   *  return status: void
85   *  ret_buf: w/o leading and/or trailing whitespace
86   *           w/o '+' and '-'
87   *           w/o leading zero
88   *
89   *  see XMLString::parseInt();
90   *      XMLString::textToBin();
91   *
92   *  "    +000203456"            "203456"
93   *  "    -000203456"            "203456"
94   *
95***/
96
97void XMLBigInteger::parseBigInteger(const XMLCh* const toConvert
98                                  , XMLCh* const retBuffer
99                                  , int&   signValue
100                                  , MemoryManager* const manager)
101{
102    // If no string, then its a failure
103    if ((!toConvert) || (!*toConvert))
104        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, manager);
105
106    //
107    // Note: in Java's BigInteger, it seems any leading and/or trailing
108    // whitespaces are not allowed. If this is the case, we may
109    // need to skip the trimming below.
110    //
111
112    // Scan past any whitespace. If we hit the end, then return failure
113    const XMLCh* startPtr = toConvert;
114    while (XMLChar1_0::isWhitespace(*startPtr))
115        startPtr++;
116
117    if (!*startPtr)
118        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_WSString, manager);
119
120    // Start at the end and work back through any whitespace
121    const XMLCh* endPtr = toConvert + XMLString::stringLen(toConvert);
122    while (XMLChar1_0::isWhitespace(*(endPtr - 1)))
123        endPtr--;
124
125    //
126    //  Work through what remains and convert each char to a digit.
127    //  anything other than '
128    //
129    XMLCh* retPtr = retBuffer;
130    signValue = 1;
131
132    //
133    // '+' or '-' is allowed only at the first position
134    //
135    if (*startPtr == chDash)
136    {
137        signValue = -1;
138        startPtr++;
139        if (startPtr == endPtr)
140        {
141            ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
142        }
143    }
144    else if (*startPtr == chPlus)
145    {
146        // skip the '+'
147        startPtr++;
148        if (startPtr == endPtr)
149        {
150            ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
151        }
152    }
153
154
155    // Scan past any leading zero.
156    while (*startPtr == chDigit_0)
157        startPtr++;
158
159    if (startPtr >= endPtr)
160    {
161        signValue = 0;
162        // containning zero, only zero, nothing but zero
163        // it is a zero, indeed
164        return;
165    }
166
167    while (startPtr < endPtr)
168    {
169        // If not valid decimal digit, then an error
170        if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
171            ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);
172
173        // copy over
174        *retPtr = *startPtr;
175        retPtr++;
176        startPtr++;
177    }
178
179    *retPtr = 0;   //terminated
180    return;
181}
182
183
184/**
185         * Translates a string containing an optional minus sign followed by a
186         * sequence of one or more digits into a BigInteger.
187         * Any extraneous characters (including whitespace),
188         * inclusive, will result in a NumberFormatException.
189 */
190
191XMLBigInteger::XMLBigInteger(const XMLCh* const strValue,
192                             MemoryManager* const manager)
193: fSign(0)
194, fMagnitude(0)
195, fRawData(0)
196, fMemoryManager(manager)
197{
198    if (!strValue)
199        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, fMemoryManager);
200
201    XMLCh* ret_value = (XMLCh*) fMemoryManager->allocate
202    (
203       (XMLString::stringLen(strValue) + 1) * sizeof(XMLCh)
204    );//new XMLCh[XMLString::stringLen(strValue)+1];
205    ArrayJanitor<XMLCh> janName(ret_value, fMemoryManager);
206
207    parseBigInteger(strValue, ret_value, fSign, fMemoryManager);
208
209    if (fSign == 0)
210        fMagnitude = XMLString::replicate(XMLUni::fgZeroLenString, fMemoryManager);
211    else
212        fMagnitude = XMLString::replicate(ret_value, fMemoryManager);
213
214        fRawData = XMLString::replicate(strValue, fMemoryManager);
215}
216
217XMLBigInteger::~XMLBigInteger()
218{
219    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
220        if (fRawData)
221                fMemoryManager->deallocate(fRawData);//delete[] fRawData;
222}
223
224XMLBigInteger::XMLBigInteger(const XMLBigInteger& toCopy)
225: XMemory(toCopy)
226, fSign(toCopy.fSign)
227, fMagnitude(0)
228, fRawData(0)
229, fMemoryManager(toCopy.fMemoryManager)
230{
231    fMagnitude = XMLString::replicate(toCopy.fMagnitude, fMemoryManager);
232        fRawData = XMLString::replicate(toCopy.fRawData, fMemoryManager);
233}
234
235/**
236 * Returns -1, 0 or 1 as lValue is less than, equal to, or greater
237 * than rValue.
238*/
239int  XMLBigInteger::compareValues(const XMLBigInteger* const lValue
240                                , const XMLBigInteger* const rValue
241                                , MemoryManager* const manager)
242{
243    if ((!lValue) || (!rValue) )
244        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
245
246    int lSign = lValue->getSign();
247    int rSign = rValue->getSign();
248
249    //
250    // different sign
251    //
252    if (lSign != rSign)
253        return(lSign > rSign ? 1 : -1);
254
255    //
256    // same sign
257    //
258    if (lSign == 0)    // optimization
259        return 0;
260
261    XMLSize_t lStrLen = XMLString::stringLen(lValue->fMagnitude);
262    XMLSize_t rStrLen = XMLString::stringLen(rValue->fMagnitude);
263
264    //
265    // different length
266    //
267    if (lStrLen > rStrLen)
268        return ( lSign > 0 ? 1 : -1 );
269    else if (lStrLen < rStrLen)
270        return ( lSign > 0 ? -1 : 1 );
271
272    //
273    // same length
274    // XMLString::compareString() return > 0, 0 and <0
275    // we need to convert it to 1, 0, and -1
276    //
277    int retVal = XMLString::compareString(lValue->fMagnitude, rValue->fMagnitude);
278
279    if ( retVal > 0 )
280    {
281        return ( lSign > 0 ? 1 : -1 );
282    }
283    else if ( retVal < 0 )
284    {
285        return ( lSign > 0 ? -1 : 1 );
286    }
287    else
288        return 0;
289
290}
291
292int XMLBigInteger::compareValues(const XMLCh*         const lString
293                               , const int&                 lSign
294                               , const XMLCh*         const rString
295                               , const int&                 rSign
296                               ,       MemoryManager* const manager)
297{
298    if ((!lString) || (!rString) )
299        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);
300
301    //
302    // different sign
303    //
304    if (lSign != rSign)
305        return(lSign > rSign ? 1 : -1);
306
307    //
308    // same sign
309    //
310    if (lSign == 0)    // optimization
311        return 0;
312
313    XMLSize_t lStrLen = XMLString::stringLen(lString);
314    XMLSize_t rStrLen = XMLString::stringLen(rString);
315
316    //
317    // different length
318    //
319    if (lStrLen > rStrLen)
320        return ( lSign > 0 ? 1 : -1 );
321    else if (lStrLen < rStrLen)
322        return ( lSign > 0 ? -1 : 1 );
323
324    //
325    // same length
326    // XMLString::compareString() return > 0, 0 and <0
327    // we need to convert it to 1, 0, and -1
328    //
329    int retVal = XMLString::compareString(lString, rString);
330
331    if ( retVal > 0 )
332    {
333        return ( lSign > 0 ? 1 : -1 );
334    }
335    else if ( retVal < 0 )
336    {
337        return ( lSign > 0 ? -1 : 1 );
338    }
339    else
340        return 0;
341
342}
343
344/**
345 * Shift the fMagnitude to the left
346 */
347
348void XMLBigInteger::multiply(const unsigned int byteToShift)
349{
350    if (byteToShift <= 0)
351        return;
352
353    XMLSize_t strLen = XMLString::stringLen(fMagnitude);
354    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
355    (
356        (strLen + byteToShift + 1) * sizeof(XMLCh)
357    );//new XMLCh[strLen+byteToShift+1];
358    XMLString::moveChars(tmp, fMagnitude, strLen);
359
360    unsigned int i = 0;
361    for ( ; i < byteToShift; i++)
362        tmp[strLen+i] = chDigit_0;
363
364    tmp[strLen+i] = chNull;
365
366    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
367    fMagnitude = tmp;
368}
369
370/**
371 * Shift the fMagnitude to the right
372 * by doing this, we lose precision.
373 */
374void XMLBigInteger::divide(const unsigned int byteToShift)
375{
376    if (byteToShift <= 0)
377        return;
378
379    XMLSize_t strLen = XMLString::stringLen(fMagnitude);
380    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
381    (
382        (strLen - byteToShift + 1) * sizeof(XMLCh)
383    );//new XMLCh[strLen-byteToShift+1];
384    XMLString::moveChars(tmp, fMagnitude, strLen-byteToShift);
385
386    tmp[strLen-byteToShift] = chNull;
387
388    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
389    fMagnitude = tmp;
390}
391
392//
393//
394//
395int XMLBigInteger::intValue() const
396{
397    unsigned int retVal;
398    XMLString::textToBin(fMagnitude, retVal, fMemoryManager);
399    return retVal * getSign();
400}
401
402XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.