class BSON::Decimal128::Builder::FromString
Helper class for parsing a String into Decimal128 high and low bits.
@api private
@since 4.2.0
Constants
- INFINITY_REGEX
Regex matching a string representing positive or negative Infinity.
@return [ Regex ] A regex matching a positive or negative Infinity string.
@since 4.2.0
- NAN_REGEX
Regex matching a string representing NaN.
@return [ Regex ] A regex matching a NaN string.
@since 4.2.0
- SCIENTIFIC_EXPONENT_REGEX
Regex matching a scientific exponent.
@return [ Regex ] A regex matching E, e, E+, e+.
@since 4.2.0
- SIGNIFICAND_WITH_LEADING_ZEROS_REGEX
Regex for the fraction, including leading zeros.
@return [ Regex ] The regex for matching the fraction,
including leading zeros.
@since 4.2.0
- SIGN_AND_DIGITS_REGEX
Regex for separating a negative sign from the significands.
@return [ Regex ] The regex for separating a sign from significands.
@since 4.2.0
- TRAILING_ZEROS_REGEX
Regex for capturing trailing zeros.
@since 4.2.0
- VALID_DECIMAL128_STRING_REGEX
Regex for a valid decimal128 string format.
@return [ Regex ] The regex for a valid decimal128 string.
@since 4.2.0
Public Class Methods
Initialize the FromString Builder object.
@example Create the FromString builder.
Builder::FromString.new(string)
@param [ String ] string The string to create a Decimal128 from.
@since 4.2.0
# File lib/bson/decimal128/builder.rb, line 163 def initialize(string) @string = string end
Public Instance Methods
Get the bits representing the Decimal128 that the string corresponds to.
@example Get the bits for the Decimal128 object created from the string.
builder.bits
@return [ Array ] Tuple of the low and high bits.
@since 4.2.0
# File lib/bson/decimal128/builder.rb, line 175 def bits if special? to_special_bits else validate_format! to_bits end end
Private Instance Methods
# File lib/bson/decimal128/builder.rb, line 226 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
# File lib/bson/decimal128/builder.rb, line 202 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
# File lib/bson/decimal128/builder.rb, line 255 def special? @string =~ NAN_REGEX || @string =~ INFINITY_REGEX end
# File lib/bson/decimal128/builder.rb, line 186 def to_bits original, sign, digits_str = SIGN_AND_DIGITS_REGEX.match(@string).to_a digits, e, scientific_exp = digits_str.partition(SCIENTIFIC_EXPONENT_REGEX) before_decimal, 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
# File lib/bson/decimal128/builder.rb, line 242 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
# File lib/bson/decimal128/builder.rb, line 259 def validate_format! raise BSON::Decimal128::InvalidString.new unless @string =~ VALID_DECIMAL128_STRING_REGEX end