| /* |
| * 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. |
| */ |
| |
| #include "Long.h" |
| #include <decaf/lang/Character.h> |
| #include <sstream> |
| |
| using namespace decaf; |
| using namespace decaf::lang; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Long::Long( long long value ) { |
| this->value = value; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Long::Long( const std::string& value ) throw( exceptions::NumberFormatException ) { |
| this->value = parseLong( value ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::compareTo( const Long& l ) const { |
| return this->value < l.value ? -1 : this->value == l.value ? 0 : 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::compareTo( const long long& l ) const { |
| return this->value < l ? -1 : this->value == l ? 0 : 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::bitCount( long long value ) { |
| |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| |
| uvalue = (uvalue & 0x5555555555555555LL) + ((uvalue >> 1) & 0x5555555555555555LL); |
| uvalue = (uvalue & 0x3333333333333333LL) + ((uvalue >> 2) & 0x3333333333333333LL); |
| // adjust for 64-bit integer |
| unsigned int i = (unsigned int)( (uvalue >> 32) + uvalue ); |
| i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F); |
| i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF); |
| i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF); |
| return i; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Long Long::decode( const std::string& value ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| int length = value.length(), i = 0; |
| if( length == 0 ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::decode - Zero length string given." ); |
| } |
| |
| char firstDigit = value[i]; |
| bool negative = firstDigit == '-'; |
| if( negative ) { |
| if( length == 1 ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::decode - Invalid length string given.", |
| value.c_str() ); |
| } |
| firstDigit = value[++i]; |
| } |
| |
| int base = 10; |
| if( firstDigit == '0' ) { |
| if( ++i == length ) { |
| return valueOf( 0LL ); |
| } |
| if( ( firstDigit = value[i] ) == 'x' || firstDigit == 'X' ) { |
| if ( i == length ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::decode - Invalid length string given.", |
| value.c_str() ); |
| } |
| i++; |
| base = 16; |
| } else { |
| base = 8; |
| } |
| } else if( firstDigit == '#' ) { |
| if( i == length ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::decode - Invalid length string given.", |
| value.c_str() ); |
| } |
| i++; |
| base = 16; |
| } |
| |
| long long result = parse( value, i, base, negative ); |
| return valueOf( result ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::highestOneBit( long long value ) { |
| |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| |
| uvalue |= (uvalue >> 1); |
| uvalue |= (uvalue >> 2); |
| uvalue |= (uvalue >> 4); |
| uvalue |= (uvalue >> 8); |
| uvalue |= (uvalue >> 16); |
| uvalue |= (uvalue >> 32); |
| return ( uvalue & ~( uvalue >> 1 ) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::lowestOneBit( long long value ) { |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| return ( uvalue & (-uvalue) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::numberOfLeadingZeros( long long value ) { |
| |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| |
| value |= value >> 1; |
| value |= value >> 2; |
| value |= value >> 4; |
| value |= value >> 8; |
| value |= value >> 16; |
| value |= value >> 32; |
| return Long::bitCount( ~uvalue ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::numberOfTrailingZeros( long long value ) { |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| return Long::bitCount( (uvalue & -uvalue) - 1 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::parseLong( const std::string& value ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| return Long::parseLong( value, 10 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::parseLong( const std::string& value, int radix ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| if( radix < Character::MIN_RADIX || |
| radix > Character::MAX_RADIX ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Given Radix is out of range." ); |
| } |
| |
| int length = value.length(); |
| int i = 0; |
| |
| if( length == 0 ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Zero length string is illegal." ); |
| } |
| |
| bool negative = value[i] == '-'; |
| if( negative && ++i == length ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Only a minus given, string is invalid." ); |
| } |
| |
| return Long::parse( value, i, radix, negative ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::parse( const std::string& value, int offset, |
| int radix, bool negative ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| long long max = Long::MIN_VALUE / radix; |
| long long result = 0; |
| long long length = value.length(); |
| |
| while( offset < length ) { |
| int digit = Character::digit( value[offset++], radix ); |
| |
| if( digit == -1 ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - String contains no digit characters." ); |
| } |
| |
| if( max > result ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Parsed value greater than max for radix." ); |
| } |
| |
| long long next = result * radix - digit; |
| |
| if( next > result ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Only a minus given, string is invalid." ); |
| } |
| |
| result = next; |
| } |
| |
| if( !negative ) { |
| result = -result; |
| if( result < 0 ) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Long::parseLong - Value less than zero, but no minus sign." ); |
| } |
| } |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::reverseBytes( long long value ) { |
| |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| |
| long long b7 = (uvalue >> 56); |
| long long b6 = (uvalue >> 40) & 0xFF00ULL; |
| long long b5 = (uvalue >> 24) & 0xFF0000ULL; |
| long long b4 = (uvalue >> 8) & 0xFF000000ULL; |
| long long b3 = (uvalue & 0xFF000000ULL) << 8; |
| long long b2 = (uvalue & 0xFF0000ULL) << 24; |
| long long b1 = (uvalue & 0xFF00ULL) << 40; |
| long long b0 = (uvalue << 56); |
| return ( b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::reverse( long long value ) { |
| |
| if( value == 0 ) { |
| return 0; |
| } |
| |
| unsigned long long uvalue = (unsigned long long)value; |
| |
| // From Hacker's Delight, 7-1, Figure 7-1 |
| uvalue = ( uvalue & 0x5555555555555555ULL ) << 1 | (uvalue >> 1) & |
| 0x5555555555555555ULL; |
| uvalue = ( uvalue & 0x3333333333333333ULL ) << 2 | (uvalue >> 2) & |
| 0x3333333333333333ULL; |
| uvalue = ( uvalue & 0x0F0F0F0F0F0F0F0FULL ) << 4 | (uvalue >> 4) & |
| 0x0F0F0F0F0F0F0F0FULL; |
| |
| return reverseBytes( uvalue ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::rotateLeft( long long value, int distance ) { |
| unsigned long long i = (unsigned long long)value; |
| int j = distance & 0x1F; |
| return ( i << j ) | ( i >> (-j & 0x1F ) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long Long::rotateRight( long long value, int distance ) { |
| unsigned long long i = (unsigned long long)value; |
| int j = distance & 0x1F; |
| return ( i >> j ) | ( i << (-j & 0x1F ) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Long::signum( long long value ) { |
| return ( value == 0 ? 0 : ( value < 0 ? -1 : 1 ) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toString() const { |
| return Long::toString( this->value, 10 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toString( long long value ) { |
| return Long::toString( value, 10 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toString( long long value, int radix ) { |
| |
| if( radix < Character::MIN_RADIX || radix > Character::MAX_RADIX ) { |
| radix = 10; |
| } |
| |
| if( value == 0 ) { |
| return "0"; |
| } |
| |
| int count = 2; |
| long long j = value; |
| bool negative = value < 0; |
| |
| if( !negative ) { |
| count = 1; |
| j = -value; |
| } |
| |
| while( (value /= radix) != 0 ) { |
| count++; |
| } |
| |
| // Save length and allocate a new buffer for the string, add one |
| // more for the null character. |
| int length = count; |
| char* buffer = new char[length + 1]; |
| |
| 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] = '-'; |
| } |
| |
| // Ensure there's a null |
| buffer[length] = 0; |
| std::string result( &buffer[0] ); |
| delete [] buffer; |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toBinaryString( long long value ) { |
| |
| int count = 1; |
| long long j = value; |
| |
| if( value < 0 ) { |
| count = 32; |
| } else { |
| while ( (j >>= 1) != 0) { |
| count++; |
| } |
| } |
| |
| // Save length and allocate a new buffer for the string, add one |
| // more for the null character. |
| int length = count; |
| char* buffer = new char[length + 1]; |
| |
| do { |
| buffer[--count] = (char)( (value & 1) + '0' ); |
| value >>= 1; |
| } while( count > 0 ); |
| |
| // Ensure there's a null |
| buffer[length] = 0; |
| std::string result( &buffer[0] ); |
| delete [] buffer; |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toOctalString( long long value ) { |
| |
| int count = 1; |
| long long j = value; |
| |
| if( value < 0 ) { |
| count = 11; |
| } else { |
| while ( (j >>= 3) != 0 ) { |
| count++; |
| } |
| } |
| |
| // Save length and allocate a new buffer for the string, add one |
| // more for the null character. |
| int length = count; |
| char* buffer = new char[length + 1]; |
| |
| do { |
| buffer[--count] = (char)( (value & 7) + '0' ); |
| value >>= 3; |
| } while( count > 0 ); |
| |
| // Ensure there's a null |
| buffer[length] = 0; |
| std::string result( &buffer[0] ); |
| delete [] buffer; |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Long::toHexString( long long value ) { |
| |
| int count = 1; |
| long long j = value; |
| |
| if( value < 0 ) { |
| count = 8; |
| } else { |
| while( (j >>= 4) != 0 ) { |
| count++; |
| } |
| } |
| |
| // Save length and allocate a new buffer for the string, add one |
| // more for the null character. |
| int length = count; |
| char* buffer = new char[length + 1]; |
| |
| do { |
| int t = value & 15; |
| if( t > 9 ) { |
| t = t - 10 + 'a'; |
| } else { |
| t += '0'; |
| } |
| buffer[--count] = (char)t; |
| value >>= 4; |
| } while( count > 0 ); |
| |
| // Ensure there's a null |
| buffer[length] = 0; |
| std::string result( &buffer[0] ); |
| delete [] buffer; |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Long Long::valueOf( const std::string& value ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| return Long( Long::parseLong( value ) ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Long Long::valueOf( const std::string& value, int radix ) |
| throw ( exceptions::NumberFormatException ) { |
| |
| return Long( Long::parseLong( value, radix ) ); |
| } |