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

Other tags:
    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)

Other tags:
    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