|  | // Copyright 2014 PDFium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Original code by Matt McCutchen, see the LICENSE file. | 
|  |  | 
|  | #include "BigUnsignedInABase.hh" | 
|  |  | 
|  | BigUnsignedInABase::BigUnsignedInABase(const Digit *d, Index l, Base base) | 
|  | : NumberlikeArray<Digit>(d, l), base(base) { | 
|  | // Check the base | 
|  | if (base < 2) | 
|  | abort(); | 
|  |  | 
|  | // Validate the digits. | 
|  | for (Index i = 0; i < l; i++) | 
|  | if (blk[i] >= base) | 
|  | abort(); | 
|  |  | 
|  | // Eliminate any leading zeros we may have been passed. | 
|  | zapLeadingZeros(); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  | unsigned int bitLen(unsigned int x) { | 
|  | unsigned int len = 0; | 
|  | while (x > 0) { | 
|  | x >>= 1; | 
|  | len++; | 
|  | } | 
|  | return len; | 
|  | } | 
|  | unsigned int ceilingDiv(unsigned int a, unsigned int b) { | 
|  | return (a + b - 1) / b; | 
|  | } | 
|  | } | 
|  |  | 
|  | BigUnsignedInABase::BigUnsignedInABase(const BigUnsigned &x, Base base) { | 
|  | // Check the base | 
|  | if (base < 2) | 
|  | abort(); | 
|  | this->base = base; | 
|  |  | 
|  | // Get an upper bound on how much space we need | 
|  | int maxBitLenOfX = x.getLength() * BigUnsigned::N; | 
|  | int minBitsPerDigit = bitLen(base) - 1; | 
|  | int maxDigitLenOfX = ceilingDiv(maxBitLenOfX, minBitsPerDigit); | 
|  | len = maxDigitLenOfX; // Another change to comply with `staying in bounds'. | 
|  | allocate(len); // Get the space | 
|  |  | 
|  | BigUnsigned x2(x), buBase(base); | 
|  | Index digitNum = 0; | 
|  |  | 
|  | while (!x2.isZero()) { | 
|  | // Get last digit.  This is like `lastDigit = x2 % buBase, x2 /= buBase'. | 
|  | BigUnsigned lastDigit(x2); | 
|  | lastDigit.divideWithRemainder(buBase, x2); | 
|  | // Save the digit. | 
|  | blk[digitNum] = lastDigit.toUnsignedShort(); | 
|  | // Move on.  We can't run out of room: we figured it out above. | 
|  | digitNum++; | 
|  | } | 
|  |  | 
|  | // Save the actual length. | 
|  | len = digitNum; | 
|  | } | 
|  |  | 
|  | BigUnsignedInABase::operator BigUnsigned() const { | 
|  | BigUnsigned ans(0), buBase(base), temp; | 
|  | Index digitNum = len; | 
|  | while (digitNum > 0) { | 
|  | digitNum--; | 
|  | temp.multiply(ans, buBase); | 
|  | ans.add(temp, BigUnsigned(blk[digitNum])); | 
|  | } | 
|  | return ans; | 
|  | } | 
|  |  | 
|  | BigUnsignedInABase::BigUnsignedInABase(const std::string &s, Base base) { | 
|  | // Check the base. | 
|  | if (base > 36) | 
|  | abort(); | 
|  | // Save the base. | 
|  | // This pattern is seldom seen in C++, but the analogous ``this.'' is common in Java. | 
|  | this->base = base; | 
|  |  | 
|  | // `s.length()' is a `size_t', while `len' is a `NumberlikeArray::Index', | 
|  | // also known as an `unsigned int'.  Some compilers warn without this cast. | 
|  | len = Index(s.length()); | 
|  | allocate(len); | 
|  |  | 
|  | Index digitNum, symbolNumInString; | 
|  | for (digitNum = 0; digitNum < len; digitNum++) { | 
|  | symbolNumInString = len - 1 - digitNum; | 
|  | char theSymbol = s[symbolNumInString]; | 
|  | if (theSymbol >= '0' && theSymbol <= '9') | 
|  | blk[digitNum] = theSymbol - '0'; | 
|  | else if (theSymbol >= 'A' && theSymbol <= 'Z') | 
|  | blk[digitNum] = theSymbol - 'A' + 10; | 
|  | else if (theSymbol >= 'a' && theSymbol <= 'z') | 
|  | blk[digitNum] = theSymbol - 'a' + 10; | 
|  | else | 
|  | abort(); | 
|  |  | 
|  | if (blk[digitNum] >= base) | 
|  | abort(); | 
|  | } | 
|  | zapLeadingZeros(); | 
|  | } | 
|  |  | 
|  | BigUnsignedInABase::operator std::string() const { | 
|  | if (base > 36) | 
|  | abort(); | 
|  | if (len == 0) | 
|  | return std::string("0"); | 
|  | // Some compilers don't have push_back, so use a char * buffer instead. | 
|  | char *s = new char[len + 1]; | 
|  | s[len] = '\0'; | 
|  | Index digitNum, symbolNumInString; | 
|  | for (symbolNumInString = 0; symbolNumInString < len; symbolNumInString++) { | 
|  | digitNum = len - 1 - symbolNumInString; | 
|  | Digit theDigit = blk[digitNum]; | 
|  | if (theDigit < 10) | 
|  | s[symbolNumInString] = char('0' + theDigit); | 
|  | else | 
|  | s[symbolNumInString] = char('A' + theDigit - 10); | 
|  | } | 
|  | std::string s2(s); | 
|  | delete [] s; | 
|  | return s2; | 
|  | } |