blob: 7992d80306b69589e3b41134ad78b8ca64f7825f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef _WIN32
#pragma warning( disable: 4146 )
#endif
#include <decaf/lang/Integer.h>
#include <decaf/lang/Character.h>
#include <sstream>
#include <vector>
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
const int Integer::SIZE = 32;
const int Integer::MAX_VALUE = (int)0x7FFFFFFF;
const int Integer::MIN_VALUE = (int)0x80000000;
////////////////////////////////////////////////////////////////////////////////
Integer::Integer(int value) : value(value) {
}
////////////////////////////////////////////////////////////////////////////////
Integer::Integer(const std::string& value) : value() {
this->value = parseInt(value);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::compareTo(const Integer& i) const {
return this->value < i.value ? -1 : this->value == i.value ? 0 : 1;
}
////////////////////////////////////////////////////////////////////////////////
int Integer::compareTo(const int& i) const {
return this->value < i ? -1 : this->value == i ? 0 : 1;
}
////////////////////////////////////////////////////////////////////////////////
Integer::~Integer() {
}
////////////////////////////////////////////////////////////////////////////////
int Integer::bitCount(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
// 32-bit recursive reduction using SWAR...
// but first step is mapping 2-bit values
// into sum of 2 1-bit values in sneaky way
uvalue -= ((uvalue >> 1) & 0x55555555);
uvalue = (((uvalue >> 2) & 0x33333333) + (uvalue & 0x33333333));
uvalue = (((uvalue >> 4) + uvalue) & 0x0F0F0F0F);
uvalue += (uvalue >> 8);
uvalue += (uvalue >> 16);
return (uvalue & 0x0000003F);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::reverseBytes(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
unsigned int b3 = uvalue >> 24;
unsigned int b2 = (uvalue >> 8) & 0xFF00;
unsigned int b1 = (uvalue & 0xFF00) << 8;
unsigned int b0 = uvalue << 24;
return (b0 | b1 | b2 | b3);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::reverse(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
uvalue = (((uvalue & 0xAAAAAAAA) >> 1) | ((uvalue & 0x55555555) << 1));
uvalue = (((uvalue & 0xCCCCCCCC) >> 2) | ((uvalue & 0x33333333) << 2));
uvalue = (((uvalue & 0xF0F0F0F0) >> 4) | ((uvalue & 0x0F0F0F0F) << 4));
uvalue = (((uvalue & 0xFF00FF00) >> 8) | ((uvalue & 0x00FF00FF) << 8));
return ((uvalue >> 16) | (uvalue << 16));
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toString() const {
return Integer::toString(this->value, 10);
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toString(int value) {
return Integer::toString(value, 10);
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toString(int value, int radix) {
if (radix < Character::MIN_RADIX || radix > Character::MAX_RADIX) {
radix = 10;
}
if (value == 0) {
return "0";
}
int count = 2, j = value;
bool negative = value < 0;
if (!negative) {
count = 1;
j = -value;
}
while ((value /= radix) != 0) {
count++;
}
std::vector<char> buffer(count);
do {
int ch = 0 - (j % radix);
if (ch > 9) {
ch = ch - 10 + 'a';
} else {
ch += '0';
}
buffer[--count] = (char) ch;
} while ((j /= radix) != 0);
if (negative) {
buffer[0] = '-';
}
return std::string(&buffer[0], buffer.size());
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toBinaryString(int value) {
int count = 1;
int j = value;
if (value < 0) {
count = 32;
} else {
while ((j >>= 1) != 0) {
count++;
}
}
std::vector<char> buffer(count);
do {
buffer[--count] = (char) ((value & 1) + '0');
value >>= 1;
} while (count > 0);
return std::string(&buffer[0], buffer.size());
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toOctalString(int value) {
int count = 1, j = value;
unsigned int uvalue = (unsigned int) value;
if (value < 0) {
count = 11; // (8 * sizeof(value) + 2) / 3;
} else {
while ((j >>= 3) != 0) {
count++;
}
}
std::vector<char> buffer(count);
do {
buffer[--count] = (char) ((uvalue & 7) + '0');
uvalue >>= 3;
} while (count > 0);
return std::string(&buffer[0], buffer.size());
}
////////////////////////////////////////////////////////////////////////////////
std::string Integer::toHexString(int value) {
int count = 1;
int j = value;
if (value < 0) {
count = 8;
} else {
while ((j >>= 4) != 0) {
count++;
}
}
std::vector<char> buffer(count);
do {
int t = value & 15;
if (t > 9) {
t = t - 10 + 'a';
} else {
t += '0';
}
buffer[--count] = (char) t;
value >>= 4;
} while (count > 0);
return std::string(&buffer[0], buffer.size());
}
////////////////////////////////////////////////////////////////////////////////
int Integer::parseInt(const String& value) {
return Integer::parseInt(value, 10);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::parseInt(const String& value, int radix) {
if (radix < Character::MIN_RADIX ||
radix > Character::MAX_RADIX ) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid radix" );
}
int length = (int)value.length(), i = 0;
if (length == 0) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid: zero length string");
}
bool negative = value.charAt(i) == '-';
if (negative && ++i == length) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid only a minus sign given");
}
return Integer::parse(value, i, radix, negative);
}
////////////////////////////////////////////////////////////////////////////////
Integer Integer::valueOf(const String& value) {
return Integer(Integer::parseInt(value));
}
////////////////////////////////////////////////////////////////////////////////
Integer Integer::valueOf(const String& value, int radix) {
return Integer(Integer::parseInt(value, radix));
}
////////////////////////////////////////////////////////////////////////////////
Integer Integer::decode(const String& value) {
int length = (int) value.length(), i = 0;
if (length == 0) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid zero size string");
}
char firstDigit = value.charAt(i);
bool negative = firstDigit == '-';
if (negative) {
if (length == 1) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid zero string, minus only");
}
firstDigit = value.charAt(++i);
}
int base = 10;
if (firstDigit == '0') {
if (++i == length) {
return valueOf(0);
}
if ((firstDigit = value.charAt(i)) == 'x' || firstDigit == 'X') {
if( i == length ) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid zero string, minus only");
}
i++;
base = 16;
} else {
base = 8;
}
} else if (firstDigit == '#') {
if (i == length) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer:decode - Invalid zero string, minus only");
}
i++;
base = 16;
}
int result = parse(value, i, base, negative);
return valueOf(result);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::parse(const String& value, int offset, int radix, bool negative) {
int max = Integer::MIN_VALUE / radix;
int result = 0, length = (int) value.length();
while (offset < length) {
int digit = Character::digit(value.charAt(offset++), radix);
if (digit == -1) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer::parse - number string is invalid: ", value.c_str());
}
if (max > result) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer::parse - number string is invalid: ", value.c_str());
}
int next = result * radix - digit;
if (next > result) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer::parse - number string is invalid: ", value.c_str());
}
result = next;
}
if (!negative) {
result = -result;
if (result < 0) {
throw NumberFormatException(
__FILE__, __LINE__,
"Integer::parse - number string is invalid: ", value.c_str());
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
int Integer::highestOneBit(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
uvalue |= (uvalue >> 1);
uvalue |= (uvalue >> 2);
uvalue |= (uvalue >> 4);
uvalue |= (uvalue >> 8);
uvalue |= (uvalue >> 16);
return (uvalue & ~(uvalue >> 1));
}
////////////////////////////////////////////////////////////////////////////////
int Integer::lowestOneBit(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
return (uvalue & (-uvalue));
}
////////////////////////////////////////////////////////////////////////////////
int Integer::numberOfLeadingZeros(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return Integer::bitCount(~uvalue);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::numberOfTrailingZeros(int value) {
if (value == 0) {
return 0;
}
unsigned int uvalue = (unsigned int) value;
return bitCount((uvalue & -uvalue) - 1);
}
////////////////////////////////////////////////////////////////////////////////
int Integer::rotateLeft(int value, int distance) {
unsigned int i = (unsigned int) value;
int j = distance & 0x1F;
return (i << j) | (i >> (-j & 0x1F));
}
////////////////////////////////////////////////////////////////////////////////
int Integer::rotateRight(int value, int distance) {
unsigned int i = (unsigned int) value;
int j = distance & 0x1F;
return (i >> j) | (i << (-j & 0x1F));
}
////////////////////////////////////////////////////////////////////////////////
int Integer::signum(int value) {
return (value == 0 ? 0 : (value < 0 ? -1 : 1));
}