class BSON::Decimal128::Builder::FromString
@since 4.2.0
@api private
Helper class for parsing a String into Decimal128 high and low bits.
def bits
- Since: - 4.2.0
Returns:
-
(Array)
- Tuple of the low and high bits.
Other tags:
- Example: Get the bits for the Decimal128 object created from the string. -
def bits if special? to_special_bits else validate_format! to_bits end end
def clamp(exponent, significand)
def clamp(exponent, significand) if exponent > Decimal128::MAX_EXPONENT if significand.to_i == 0 adjust = exponent - Decimal128::MAX_EXPONENT significand = '0' else adjust = [ (exponent - Decimal128::MAX_EXPONENT), Decimal128::MAX_DIGITS_OF_PRECISION - significand.length ].min significand << '0'* adjust end exponent -= adjust end [ exponent, significand ] end
def initialize(string)
- Since: - 4.2.0
Parameters:
-
string
(String
) -- The string to create a Decimal128 from.
Other tags:
- Example: Create the FromString builder. -
def initialize(string) @string = string end
def round_exact(exponent, significand)
def round_exact(exponent, significand) if exponent < Decimal128::MIN_EXPONENT if significand.to_i == 0 round = Decimal128::MIN_EXPONENT - exponent exponent += round elsif trailing_zeros = TRAILING_ZEROS_REGEX.match(significand) round = [ (Decimal128::MIN_EXPONENT - exponent), trailing_zeros[1].size ].min significand = significand[0...-round] exponent += round end elsif significand.length > Decimal128::MAX_DIGITS_OF_PRECISION trailing_zeros = TRAILING_ZEROS_REGEX.match(significand) if trailing_zeros round = [ trailing_zeros[1].size, (significand.length - Decimal128::MAX_DIGITS_OF_PRECISION), (Decimal128::MAX_EXPONENT - exponent)].min significand = significand[0...-round] exponent += round end end [ exponent, significand ] end
def special?
def special? @string =~ NAN_REGEX || @string =~ INFINITY_REGEX end
def to_bits
def to_bits _, sign, digits_str = SIGN_AND_DIGITS_REGEX.match(@string).to_a digits, _, scientific_exp = digits_str.partition(SCIENTIFIC_EXPONENT_REGEX) before_decimal, _, after_decimal = digits.partition('.') significand_str = before_decimal << after_decimal significand_str = SIGNIFICAND_WITH_LEADING_ZEROS_REGEX.match(significand_str).to_a[2] exponent = -(after_decimal.length) exponent = exponent + scientific_exp.to_i exponent, significand_str = round_exact(exponent, significand_str) exponent, significand_str = clamp(exponent, significand_str) Builder.parts_to_bits(significand_str.to_i, exponent, sign == '-') end
def to_special_bits
def to_special_bits high = 0 if match = NAN_REGEX.match(@string) high = NAN_MASK high = high | SIGN_BIT_MASK if match[1] high = high | SNAN_MASK if match[2] elsif match = INFINITY_REGEX.match(@string) high = INFINITY_MASK high = high | SIGN_BIT_MASK if match[1] == '-' end [ 0, high ] end
def validate_format!
def validate_format! raise Error::InvalidDecimal128String.new unless @string =~ VALID_DECIMAL128_STRING_REGEX end