1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code by Matt McCutchen, see the LICENSE file.
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "BigUnsignedInABase.hh"
8*3ac0a46fSAndroid Build Coastguard Worker
BigUnsignedInABase(const Digit * d,Index l,Base base)9*3ac0a46fSAndroid Build Coastguard Worker BigUnsignedInABase::BigUnsignedInABase(const Digit *d, Index l, Base base)
10*3ac0a46fSAndroid Build Coastguard Worker : NumberlikeArray<Digit>(d, l), base(base) {
11*3ac0a46fSAndroid Build Coastguard Worker // Check the base
12*3ac0a46fSAndroid Build Coastguard Worker if (base < 2)
13*3ac0a46fSAndroid Build Coastguard Worker abort();
14*3ac0a46fSAndroid Build Coastguard Worker
15*3ac0a46fSAndroid Build Coastguard Worker // Validate the digits.
16*3ac0a46fSAndroid Build Coastguard Worker for (Index i = 0; i < l; i++)
17*3ac0a46fSAndroid Build Coastguard Worker if (blk[i] >= base)
18*3ac0a46fSAndroid Build Coastguard Worker abort();
19*3ac0a46fSAndroid Build Coastguard Worker
20*3ac0a46fSAndroid Build Coastguard Worker // Eliminate any leading zeros we may have been passed.
21*3ac0a46fSAndroid Build Coastguard Worker zapLeadingZeros();
22*3ac0a46fSAndroid Build Coastguard Worker }
23*3ac0a46fSAndroid Build Coastguard Worker
24*3ac0a46fSAndroid Build Coastguard Worker namespace {
bitLen(unsigned int x)25*3ac0a46fSAndroid Build Coastguard Worker unsigned int bitLen(unsigned int x) {
26*3ac0a46fSAndroid Build Coastguard Worker unsigned int len = 0;
27*3ac0a46fSAndroid Build Coastguard Worker while (x > 0) {
28*3ac0a46fSAndroid Build Coastguard Worker x >>= 1;
29*3ac0a46fSAndroid Build Coastguard Worker len++;
30*3ac0a46fSAndroid Build Coastguard Worker }
31*3ac0a46fSAndroid Build Coastguard Worker return len;
32*3ac0a46fSAndroid Build Coastguard Worker }
ceilingDiv(unsigned int a,unsigned int b)33*3ac0a46fSAndroid Build Coastguard Worker unsigned int ceilingDiv(unsigned int a, unsigned int b) {
34*3ac0a46fSAndroid Build Coastguard Worker return (a + b - 1) / b;
35*3ac0a46fSAndroid Build Coastguard Worker }
36*3ac0a46fSAndroid Build Coastguard Worker }
37*3ac0a46fSAndroid Build Coastguard Worker
BigUnsignedInABase(const BigUnsigned & x,Base base)38*3ac0a46fSAndroid Build Coastguard Worker BigUnsignedInABase::BigUnsignedInABase(const BigUnsigned &x, Base base) {
39*3ac0a46fSAndroid Build Coastguard Worker // Check the base
40*3ac0a46fSAndroid Build Coastguard Worker if (base < 2)
41*3ac0a46fSAndroid Build Coastguard Worker abort();
42*3ac0a46fSAndroid Build Coastguard Worker this->base = base;
43*3ac0a46fSAndroid Build Coastguard Worker
44*3ac0a46fSAndroid Build Coastguard Worker // Get an upper bound on how much space we need
45*3ac0a46fSAndroid Build Coastguard Worker int maxBitLenOfX = x.getLength() * BigUnsigned::N;
46*3ac0a46fSAndroid Build Coastguard Worker int minBitsPerDigit = bitLen(base) - 1;
47*3ac0a46fSAndroid Build Coastguard Worker int maxDigitLenOfX = ceilingDiv(maxBitLenOfX, minBitsPerDigit);
48*3ac0a46fSAndroid Build Coastguard Worker len = maxDigitLenOfX; // Another change to comply with `staying in bounds'.
49*3ac0a46fSAndroid Build Coastguard Worker allocate(len); // Get the space
50*3ac0a46fSAndroid Build Coastguard Worker
51*3ac0a46fSAndroid Build Coastguard Worker BigUnsigned x2(x), buBase(base);
52*3ac0a46fSAndroid Build Coastguard Worker Index digitNum = 0;
53*3ac0a46fSAndroid Build Coastguard Worker
54*3ac0a46fSAndroid Build Coastguard Worker while (!x2.isZero()) {
55*3ac0a46fSAndroid Build Coastguard Worker // Get last digit. This is like `lastDigit = x2 % buBase, x2 /= buBase'.
56*3ac0a46fSAndroid Build Coastguard Worker BigUnsigned lastDigit(x2);
57*3ac0a46fSAndroid Build Coastguard Worker lastDigit.divideWithRemainder(buBase, x2);
58*3ac0a46fSAndroid Build Coastguard Worker // Save the digit.
59*3ac0a46fSAndroid Build Coastguard Worker blk[digitNum] = lastDigit.toUnsignedShort();
60*3ac0a46fSAndroid Build Coastguard Worker // Move on. We can't run out of room: we figured it out above.
61*3ac0a46fSAndroid Build Coastguard Worker digitNum++;
62*3ac0a46fSAndroid Build Coastguard Worker }
63*3ac0a46fSAndroid Build Coastguard Worker
64*3ac0a46fSAndroid Build Coastguard Worker // Save the actual length.
65*3ac0a46fSAndroid Build Coastguard Worker len = digitNum;
66*3ac0a46fSAndroid Build Coastguard Worker }
67*3ac0a46fSAndroid Build Coastguard Worker
operator BigUnsigned() const68*3ac0a46fSAndroid Build Coastguard Worker BigUnsignedInABase::operator BigUnsigned() const {
69*3ac0a46fSAndroid Build Coastguard Worker BigUnsigned ans(0), buBase(base), temp;
70*3ac0a46fSAndroid Build Coastguard Worker Index digitNum = len;
71*3ac0a46fSAndroid Build Coastguard Worker while (digitNum > 0) {
72*3ac0a46fSAndroid Build Coastguard Worker digitNum--;
73*3ac0a46fSAndroid Build Coastguard Worker temp.multiply(ans, buBase);
74*3ac0a46fSAndroid Build Coastguard Worker ans.add(temp, BigUnsigned(blk[digitNum]));
75*3ac0a46fSAndroid Build Coastguard Worker }
76*3ac0a46fSAndroid Build Coastguard Worker return ans;
77*3ac0a46fSAndroid Build Coastguard Worker }
78*3ac0a46fSAndroid Build Coastguard Worker
BigUnsignedInABase(const std::string & s,Base base)79*3ac0a46fSAndroid Build Coastguard Worker BigUnsignedInABase::BigUnsignedInABase(const std::string &s, Base base) {
80*3ac0a46fSAndroid Build Coastguard Worker // Check the base.
81*3ac0a46fSAndroid Build Coastguard Worker if (base > 36)
82*3ac0a46fSAndroid Build Coastguard Worker abort();
83*3ac0a46fSAndroid Build Coastguard Worker // Save the base.
84*3ac0a46fSAndroid Build Coastguard Worker // This pattern is seldom seen in C++, but the analogous ``this.'' is common in Java.
85*3ac0a46fSAndroid Build Coastguard Worker this->base = base;
86*3ac0a46fSAndroid Build Coastguard Worker
87*3ac0a46fSAndroid Build Coastguard Worker // `s.length()' is a `size_t', while `len' is a `NumberlikeArray::Index',
88*3ac0a46fSAndroid Build Coastguard Worker // also known as an `unsigned int'. Some compilers warn without this cast.
89*3ac0a46fSAndroid Build Coastguard Worker len = Index(s.length());
90*3ac0a46fSAndroid Build Coastguard Worker allocate(len);
91*3ac0a46fSAndroid Build Coastguard Worker
92*3ac0a46fSAndroid Build Coastguard Worker Index digitNum, symbolNumInString;
93*3ac0a46fSAndroid Build Coastguard Worker for (digitNum = 0; digitNum < len; digitNum++) {
94*3ac0a46fSAndroid Build Coastguard Worker symbolNumInString = len - 1 - digitNum;
95*3ac0a46fSAndroid Build Coastguard Worker char theSymbol = s[symbolNumInString];
96*3ac0a46fSAndroid Build Coastguard Worker if (theSymbol >= '0' && theSymbol <= '9')
97*3ac0a46fSAndroid Build Coastguard Worker blk[digitNum] = theSymbol - '0';
98*3ac0a46fSAndroid Build Coastguard Worker else if (theSymbol >= 'A' && theSymbol <= 'Z')
99*3ac0a46fSAndroid Build Coastguard Worker blk[digitNum] = theSymbol - 'A' + 10;
100*3ac0a46fSAndroid Build Coastguard Worker else if (theSymbol >= 'a' && theSymbol <= 'z')
101*3ac0a46fSAndroid Build Coastguard Worker blk[digitNum] = theSymbol - 'a' + 10;
102*3ac0a46fSAndroid Build Coastguard Worker else
103*3ac0a46fSAndroid Build Coastguard Worker abort();
104*3ac0a46fSAndroid Build Coastguard Worker
105*3ac0a46fSAndroid Build Coastguard Worker if (blk[digitNum] >= base)
106*3ac0a46fSAndroid Build Coastguard Worker abort();
107*3ac0a46fSAndroid Build Coastguard Worker }
108*3ac0a46fSAndroid Build Coastguard Worker zapLeadingZeros();
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker
operator std::string() const111*3ac0a46fSAndroid Build Coastguard Worker BigUnsignedInABase::operator std::string() const {
112*3ac0a46fSAndroid Build Coastguard Worker if (base > 36)
113*3ac0a46fSAndroid Build Coastguard Worker abort();
114*3ac0a46fSAndroid Build Coastguard Worker if (len == 0)
115*3ac0a46fSAndroid Build Coastguard Worker return std::string("0");
116*3ac0a46fSAndroid Build Coastguard Worker // Some compilers don't have push_back, so use a char * buffer instead.
117*3ac0a46fSAndroid Build Coastguard Worker char *s = new char[len + 1];
118*3ac0a46fSAndroid Build Coastguard Worker s[len] = '\0';
119*3ac0a46fSAndroid Build Coastguard Worker Index digitNum, symbolNumInString;
120*3ac0a46fSAndroid Build Coastguard Worker for (symbolNumInString = 0; symbolNumInString < len; symbolNumInString++) {
121*3ac0a46fSAndroid Build Coastguard Worker digitNum = len - 1 - symbolNumInString;
122*3ac0a46fSAndroid Build Coastguard Worker Digit theDigit = blk[digitNum];
123*3ac0a46fSAndroid Build Coastguard Worker if (theDigit < 10)
124*3ac0a46fSAndroid Build Coastguard Worker s[symbolNumInString] = char('0' + theDigit);
125*3ac0a46fSAndroid Build Coastguard Worker else
126*3ac0a46fSAndroid Build Coastguard Worker s[symbolNumInString] = char('A' + theDigit - 10);
127*3ac0a46fSAndroid Build Coastguard Worker }
128*3ac0a46fSAndroid Build Coastguard Worker std::string s2(s);
129*3ac0a46fSAndroid Build Coastguard Worker delete [] s;
130*3ac0a46fSAndroid Build Coastguard Worker return s2;
131*3ac0a46fSAndroid Build Coastguard Worker }
132