| // 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; | 
 | } |