| /* |
| * 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> |
| |
| 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) : EXPONENT_WIDTH(exponentWidth), |
| MANTISSA_WIDTH(mantissaWidth), |
| EXPONENT_BASE(0), |
| MAX_EXPONENT(0), |
| MIN_EXPONENT(), |
| MANTISSA_MASK(), |
| sign(0), |
| exponent(0), |
| mantissa(0), |
| abandonedNumber() { |
| 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 += (char) (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 Integer part is a nonzero number. |
| if (strIntegerPart.length() != 0) { |
| std::string leadingNumber = strIntegerPart.substr(0, 1); |
| return (int) ((strIntegerPart.length() - 1) * 4 + countBitsLength(Long::parseLong(leadingNumber, HEX_RADIX)) - 1); |
| } |
| |
| //If the Integer 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; |
| } |