blob: cfbe6486d42dd7376f66342ea992598d7c8bc6da [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.
*/
#ifndef _DECAF_INTERNAL_UTIL_HEXSTRINGPARSER_H_
#define _DECAF_INTERNAL_UTIL_HEXSTRINGPARSER_H_
#include <decaf/util/Config.h>
#include <string>
namespace decaf{
namespace internal{
namespace util{
class HexStringParser {
private:
static const unsigned int DOUBLE_EXPONENT_WIDTH = 11;
static const unsigned int DOUBLE_MANTISSA_WIDTH = 52;
static const unsigned int FLOAT_EXPONENT_WIDTH = 8;
static const unsigned int FLOAT_MANTISSA_WIDTH = 23;
static const unsigned int HEX_RADIX = 16;
static const unsigned int MAX_SIGNIFICANT_LENGTH = 15;
static const std::string HEX_SIGNIFICANT;
static const std::string BINARY_EXPONENT;
static const std::string FLOAT_TYPE_SUFFIX;
static const std::string HEX_PATTERN;
// TODO
//static final Pattern PATTERN = Pattern.compile(HEX_PATTERN);
private:
int EXPONENT_WIDTH;
int MANTISSA_WIDTH;
long EXPONENT_BASE;
long MAX_EXPONENT;
long MIN_EXPONENT;
long MANTISSA_MASK;
long sign;
long exponent;
long mantissa;
std::string abandonedNumber;
public:
/**
* Create a new HexParser
* @param exponentWidth - Width of the exponent for the type to parse
* @param mantissaWidth - Width of the mantissa for the type to parse
*/
HexStringParser( int exponentWidth, int mantissaWidth );
virtual ~HexStringParser() {}
/**
* Parses a hex string using the specs given in the constructor
* and returns a long long with the bits of the parsed string, the
* caller can then convert those to a float or doulbe as needed.
* @param hexString - string to parse
* @returns the bits parsed from the string
*/
long long parse( const std::string& hexString );
private:
/*
* Parses the sign field.
* @param sign string to parse
*/
void parseHexSign( const std::string& signStr ) {
this->sign = signStr.compare("-") == 0 ? 1 : 0;
}
/*
* Parses the exponent field.
* @param exponent string to parse
*/
void parseExponent( const std::string& exponentStr );
/*
* Parses the mantissa field.
* @param mantissa string to parse
*/
void parseMantissa( const std::string& significantStr );
void setInfinite() {
exponent = MAX_EXPONENT;
mantissa = 0;
}
void setZero() {
exponent = 0;
mantissa = 0;
}
/*
* Sets the exponent variable to Long::MAX_VALUE or -Long::MAX_VALUE if
* overflow or underflow happens.
* @param the offset to set
*/
void checkedAddExponent( long long offset );
void processNormalNumber();
void processSubNormalNumber();
int countBitsLength( long long value );
/*
* Adjusts the mantissa to desired width for further analysis.
*/
void fitMantissaInDesiredWidth( int desiredWidth );
/*
* Stores the discarded bits to abandonedNumber.
*/
void discardTrailingBits( long long num );
/*
* The value is rounded up or down to the nearest infinitely precise result.
* If the value is exactly halfway between two infinitely precise results,
* then it should be rounded up to the nearest infinitely precise even.
*/
void round();
/*
* Returns the normalized significand after removing the leading zeros.
*/
std::string getNormalizedSignificand( const std::string& strIntegerPart,
const std::string& strDecimalPart );
/*
* Calculates the offset between the normalized number and unnormalized
* number. In a normalized representation, significand is represented by the
* characters "0x1." followed by a lowercase hexadecimal representation of
* the rest of the significand as a fraction.
*/
int getOffset( const std::string& strIntegerPart,
const std::string& strDecimalPart );
public: // Statics
/*
* Parses the hex string to a double number.
* @param hexString - string to parse
* @returns the parsed double value
*/
static double parseDouble( const std::string& hexString );
/*
* Parses the hex string to a float number.
* @param hexString - string to parse
* @returns the parsed float value
*/
static float parseFloat( const std::string& hexString );
private: // Static
/*
* Analyzes the hex string and extracts the sign and digit segments.
* @param hexString - string to parse
* @returns array of three strings holding the segments caller owns
*/
static std::string* getSegmentsFromHexString( const std::string& hexString );
std::string& replaceFirst( std::string& target,
const std::string& find,
const std::string& replace ) {
std::string::size_type pos = std::string::npos;
if( ( pos = target.find_first_of( find, 0 ) ) != std::string::npos ) {
return target.replace( pos, find.length(), replace );
}
return target;
}
std::string& replaceAll( std::string& target,
const std::string& find,
const std::string& replace ) {
std::string::size_type pos = std::string::npos;
while( ( pos = target.find( find ) ) != std::string::npos ) {
target.replace( pos, find.length(), replace );
}
return target;
}
};
}}}
#endif /*_DECAF_INTERNAL_UTIL_HEXSTRINGPARSER_H_*/