| /* |
| * 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 "HexStringParser.h" |
| |
| #include <decaf/lang/Character.h> |
| #include <decaf/lang/Integer.h> |
| #include <decaf/lang/Long.h> |
| #include <decaf/lang/Double.h> |
| #include <decaf/lang/Float.h> |
| #include <decaf/util/StringTokenizer.h> |
| #include <decaf/lang/exceptions/NumberFormatException.h> |
| #include <apr_pools.h> |
| #include <apr_strmatch.h> |
| |
| using namespace decaf; |
| using namespace decaf::util; |
| using namespace decaf::lang; |
| using namespace decaf::lang::exceptions; |
| using namespace decaf::internal; |
| using namespace decaf::internal::util; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| const std::string HexStringParser::HEX_SIGNIFICANT = |
| "0[xX](\\p{XDigit}+\\.?|\\p{XDigit}*\\.\\p{XDigit}+)"; |
| const std::string HexStringParser::BINARY_EXPONENT = |
| "[pP]([+-]?\\d+)"; |
| const std::string HexStringParser::FLOAT_TYPE_SUFFIX = |
| "[fFdD]?"; |
| const std::string HexStringParser::HEX_PATTERN = |
| "[\\x00-\\x20]*([+-]?)" + HEX_SIGNIFICANT + BINARY_EXPONENT + FLOAT_TYPE_SUFFIX + "[\\x00-\\x20]*"; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| HexStringParser::HexStringParser( int exponentWidth, int mantissaWidth ) { |
| |
| this->EXPONENT_WIDTH = exponentWidth; |
| this->MANTISSA_WIDTH = mantissaWidth; |
| |
| this->EXPONENT_BASE = ~( -1 << (exponentWidth - 1) ); |
| this->MAX_EXPONENT = ~( -1 << exponentWidth ); |
| this->MIN_EXPONENT = -( MANTISSA_WIDTH + 1 ); |
| this->MANTISSA_MASK = ~( -1 << mantissaWidth ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| double HexStringParser::parseDouble( const std::string& hexString ) { |
| |
| HexStringParser parser( DOUBLE_EXPONENT_WIDTH, DOUBLE_MANTISSA_WIDTH ); |
| long long result = parser.parse( hexString ); |
| return Double::longBitsToDouble( result ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| float HexStringParser::parseFloat( const std::string& hexString ) { |
| |
| HexStringParser parser( FLOAT_EXPONENT_WIDTH, FLOAT_MANTISSA_WIDTH ); |
| int result = (int)parser.parse( hexString ); |
| return Float::intBitsToFloat( result ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| long long HexStringParser::parse( const std::string& hexString ) { |
| |
| std::string* hexSegments = getSegmentsFromHexString( hexString ); |
| std::string signStr = hexSegments[0]; |
| std::string significantStr = hexSegments[1]; |
| std::string exponentStr = hexSegments[2]; |
| delete hexSegments; |
| |
| parseHexSign( signStr ); |
| parseExponent( exponentStr ); |
| parseMantissa( significantStr ); |
| |
| sign <<= ( MANTISSA_WIDTH + EXPONENT_WIDTH ); |
| exponent <<= MANTISSA_WIDTH; |
| return sign | exponent | mantissa; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string* HexStringParser::getSegmentsFromHexString( DECAF_UNUSED const std::string& hexString ) { |
| |
| // apr_pool_t* thePool = NULL; |
| // apr_pool_create( &thePool, NULL ); |
| // apr_strmatch_pattern* pattern = |
| // apr_strmatch_precompile( thePool, HEX_PATTERN.c_str(), 0 ); |
| // |
| // std::vector<std::string> hexSegments; |
| // |
| |
| |
| // TODO |
| // Matcher matcher = PATTERN.matcher(hexString); |
| // if( !matcher.matches() ) { |
| // throw NumberFormatException( |
| // __FILE__, __LINE__, |
| // "HexStringParser::getSegmentsFromHexString" |
| // "Invalid hex string:", hexString.c_str() ); |
| // } |
| // |
| // std::string* hexSegments = new std::string[3]; |
| // hexSegments[0] = matcher.group(1); |
| // hexSegments[1] = matcher.group(2); |
| // hexSegments[2] = matcher.group(3); |
| // |
| // return hexSegments; |
| |
| return NULL; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::parseExponent(const std::string& exponentStr) { |
| |
| std::string newExponentStr = exponentStr; |
| |
| char leadingChar = newExponentStr.at(0); |
| int expSign = ( leadingChar == '-' ? -1 : 1 ); |
| if( !Character::isDigit( leadingChar ) ) { |
| newExponentStr = newExponentStr.substr( 1, newExponentStr.size() ); |
| } |
| |
| try { |
| exponent = expSign * Long::parseLong( exponentStr ); |
| checkedAddExponent( EXPONENT_BASE ); |
| } catch( exceptions::NumberFormatException& e ) { |
| exponent = expSign * Long::MAX_VALUE; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::parseMantissa(const std::string& significantStr) { |
| |
| StringTokenizer tokenizer( significantStr, "\\." ); |
| std::vector<std::string> strings; |
| |
| tokenizer.toArray( strings ); |
| |
| std::string strIntegerPart = strings[0]; |
| std::string strDecimalPart = strings.size() > 1 ? strings[1] : ""; |
| |
| std::string significand = |
| getNormalizedSignificand( strIntegerPart, strDecimalPart) ; |
| |
| if( significand == "0" ) { |
| setZero(); |
| return; |
| } |
| |
| int offset = getOffset( strIntegerPart, strDecimalPart ); |
| checkedAddExponent( offset ); |
| |
| if( exponent >= MAX_EXPONENT ) { |
| setInfinite(); |
| return; |
| } |
| |
| if( exponent <= MIN_EXPONENT ) { |
| setZero(); |
| return; |
| } |
| |
| if( significand.length() > MAX_SIGNIFICANT_LENGTH ) { |
| abandonedNumber = significand.substr( MAX_SIGNIFICANT_LENGTH ); |
| significand = significand.substr( 0, MAX_SIGNIFICANT_LENGTH ); |
| } |
| |
| mantissa = Long::parseLong( significand, HEX_RADIX ); |
| |
| if( exponent >= 1 ) { |
| processNormalNumber(); |
| } else{ |
| processSubNormalNumber(); |
| } |
| |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::checkedAddExponent( long long offset ) { |
| |
| long long result = exponent + offset; |
| int expSign = Long::signum( exponent ); |
| |
| if( expSign * Long::signum( offset ) > 0 && |
| expSign * Long::signum( result ) < 0 ) { |
| |
| exponent = expSign * Long::MAX_VALUE; |
| } else { |
| exponent = result; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::processNormalNumber() { |
| int desiredWidth = MANTISSA_WIDTH + 2; |
| fitMantissaInDesiredWidth( desiredWidth ); |
| round(); |
| mantissa = mantissa & MANTISSA_MASK; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::processSubNormalNumber() { |
| int desiredWidth = MANTISSA_WIDTH + 1; |
| desiredWidth += (int)exponent;//lends bit from mantissa to exponent |
| exponent = 0; |
| fitMantissaInDesiredWidth( desiredWidth ); |
| round(); |
| mantissa = mantissa & MANTISSA_MASK; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::fitMantissaInDesiredWidth(int desiredWidth){ |
| int bitLength = countBitsLength( mantissa ); |
| if( bitLength > desiredWidth ) { |
| discardTrailingBits( bitLength - desiredWidth ); |
| } else { |
| mantissa <<= ( desiredWidth - bitLength ); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::discardTrailingBits( long long num ) { |
| long long mask = ~( -1L << num ); |
| abandonedNumber += ( mantissa & mask ); |
| mantissa >>= num; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| void HexStringParser::round() { |
| |
| std::string result = abandonedNumber; |
| replaceAll( result, "0+", "" ); |
| |
| bool moreThanZero = ( result.length() > 0 ? true : false ); |
| |
| int lastDiscardedBit = (int)( mantissa & 1L ); |
| mantissa >>= 1; |
| int tailBitInMantissa = (int)( mantissa & 1L ); |
| |
| if( lastDiscardedBit == 1 && ( moreThanZero || tailBitInMantissa == 1 ) ) { |
| |
| int oldLength = countBitsLength( mantissa ); |
| mantissa += 1L; |
| int newLength = countBitsLength( mantissa ); |
| |
| //Rounds up to exponent when whole bits of mantissa are one-bits. |
| if( oldLength >= MANTISSA_WIDTH && newLength > oldLength ) { |
| checkedAddExponent( 1 ); |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string HexStringParser::getNormalizedSignificand( |
| const std::string& strIntegerPart, const std::string& strDecimalPart ) { |
| |
| std::string significand = strIntegerPart + strDecimalPart; |
| |
| replaceFirst( significand, "^0x", "" ); |
| |
| if( significand.length() == 0 ) { |
| significand = "0"; |
| } |
| return significand; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int HexStringParser::getOffset( |
| const std::string& strIntegerPart, const std::string& strDecimalPart ) { |
| |
| std::string strIntegerPart2 = strIntegerPart; |
| |
| replaceFirst( strIntegerPart2, "^0+", "" ); |
| |
| //If the Interger part is a nonzero number. |
| if( strIntegerPart.length() != 0 ) { |
| std::string leadingNumber = strIntegerPart.substr( 0, 1 ); |
| return ( strIntegerPart.length() - 1) * 4 + |
| countBitsLength(Long::parseLong( leadingNumber,HEX_RADIX ) ) - 1; |
| } |
| |
| //If the Interger part is a zero number. |
| int i; |
| for( i = 0; (std::size_t)i < strDecimalPart.length() && strDecimalPart.at(i) == '0'; i++ ); |
| |
| if( (std::size_t)i == strDecimalPart.length() ) { |
| return 0; |
| } |
| |
| std::string leadingNumber = strDecimalPart.substr( i,i + 1 ); |
| |
| return (-i - 1) * 4 + |
| countBitsLength( Long::parseLong( leadingNumber, HEX_RADIX) ) - 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int HexStringParser::countBitsLength(long long value) { |
| int leadingZeros = Long::numberOfLeadingZeros( value ); |
| return Long::SIZE - leadingZeros; |
| } |