view release on metacpan or search on metacpan
bson/bson-decimal128.c view on Meta::CPAN
*
*------------------------------------------------------------------------------
*/
void
bson_decimal128_to_string (const bson_decimal128_t *dec, /* IN */
char *str) /* OUT */
{
uint32_t COMBINATION_MASK = 0x1f; /* Extract least significant 5 bits */
uint32_t EXPONENT_MASK = 0x3fff; /* Extract least significant 14 bits */
uint32_t COMBINATION_INFINITY = 30; /* Value of combination field for Inf */
uint32_t COMBINATION_NAN = 31; /* Value of combination field for NaN */
uint32_t EXPONENT_BIAS = 6176; /* decimal128 exponent bias */
char *str_out = str; /* output pointer in string */
char significand_str[35]; /* decoded significand digits */
/* Note: bits in this routine are referred to starting at 0, */
/* from the sign bit, towards the coefficient. */
uint32_t high; /* bits 0 - 31 */
uint32_t midh; /* bits 32 - 63 */
bson/bson-decimal128.c view on Meta::CPAN
high = (uint32_t)(dec->high >> 32);
/* Decode combination field and exponent */
combination = (high >> 26) & COMBINATION_MASK;
if (BSON_UNLIKELY ((combination >> 3) == 3)) {
/* Check for 'special' values */
if (combination == COMBINATION_INFINITY) { /* Infinity */
strcpy (str_out, "Inf");
return;
} else if (combination == COMBINATION_NAN) { /* NaN */
/* str, not str_out, to erase the sign */
strcpy (str, "NaN");
/* we don't care about the NaN payload. */
return;
} else {
biased_exponent = (high >> 15) & EXPONENT_MASK;
significand_msb = 0x8 + ((high >> 14) & 0x1);
}
} else {
significand_msb = (high >> 14) & 0x7;
biased_exponent = (high >> 17) & EXPONENT_MASK;
}
bson/bson-decimal128.c view on Meta::CPAN
return true;
}
/**
*------------------------------------------------------------------------------
*
* bson_decimal128_from_string --
*
* This function converts @string in the format [+-]ddd[.]ddd[E][+-]dddd to
* decimal128. Out of range values are converted to +/-Infinity. Invalid
* strings are converted to NaN.
*
* If more digits are provided than the available precision allows,
* round to the nearest expressable decimal128 with ties going to even will
* occur.
*
* Note: @string must be ASCII only!
*
* Returns:
* true on success, or false on failure. @dec will be NaN if @str was invalid
* The &bson_decimal128_t converted from @string at @dec.
*
* Side effects:
* None.
*
*------------------------------------------------------------------------------
*/
bool
bson_decimal128_from_string (const char *string, /* IN */
bson_decimal128_t *dec) /* OUT */
bson/bson-decimal128.c view on Meta::CPAN
BSON_ASSERT (dec);
dec->high = 0;
dec->low = 0;
if (*str_read == '+' || *str_read == '-') {
is_negative = *(str_read++) == '-';
includes_sign = true;
}
/* Check for Infinity or NaN */
if (!isdigit (*str_read) && *str_read != '.') {
if (_dec128_istreq (str_read, "inf") ||
_dec128_istreq (str_read, "infinity")) {
BSON_DECIMAL128_SET_INF (*dec, is_negative);
return true;
} else if (_dec128_istreq (str_read, "nan")) {
BSON_DECIMAL128_SET_NAN (*dec);
return true;
}
corpus/README.md view on Meta::CPAN
{ "$code": "<code here>" }
# Javascript with scope
{ "$code": "<code here>": "$scope": { "x":1, "y":1 } }
# Int32
{ "$numberInt": "<number>" }
However, this corpus extends JSON further to include the following:
# Double (needed for NaN, etc.)
{ "$numberDouble": "<value|NaN|Inf|-Inf>" }
# DBpointer (deprecated): <id> is 24 hex chars
{ "$dbpointer": "<id>", "$ns":"<namespace>" }
# Symbol (deprecated)
{ "$symbol": "<text>" }
## Visualizing BSON
The directory includes a Perl script `bsonview`, which will decompose and
corpus/decimal128-1.json view on Meta::CPAN
{
"description": "Decimal128",
"bson_type": "0x13",
"test_key": "d",
"valid": [
{
"description": "Special - Canonical NaN",
"canonical_bson": "180000001364000000000000000000000000000000007C00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
},
{
"description": "Special - Negative NaN",
"canonical_bson": "18000000136400000000000000000000000000000000FC00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
"lossy": true
},
{
"description": "Special - Negative NaN",
"canonical_bson": "18000000136400000000000000000000000000000000FC00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-NaN\"}}",
"lossy": true
},
{
"description": "Special - Canonical SNaN",
"canonical_bson": "180000001364000000000000000000000000000000007E00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
"lossy": true
},
{
"description": "Special - Negative SNaN",
"canonical_bson": "18000000136400000000000000000000000000000000FE00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
"lossy": true
},
{
"description": "Special - NaN with a payload",
"canonical_bson": "180000001364001200000000000000000000000000007E00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}",
"lossy": true
},
{
"description": "Special - Canonical Positive Infinity",
"canonical_bson": "180000001364000000000000000000000000000000007800",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
},
{
"description": "Special - Canonical Negative Infinity",
"canonical_bson": "18000000136400000000000000000000000000000000F800",
corpus/decimal128-1.json view on Meta::CPAN
{
"description": "Non-Canonical Parsing - Long Decimal String",
"canonical_bson": "180000001364000100000000000000000000000000722800",
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-999\"}}"
},
{
"description": "Non-Canonical Parsing - nan",
"canonical_bson": "180000001364000000000000000000000000000000007C00",
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"nan\"}}",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
},
{
"description": "Non-Canonical Parsing - nAn",
"canonical_bson": "180000001364000000000000000000000000000000007C00",
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"nAn\"}}",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
},
{
"description": "Non-Canonical Parsing - +infinity",
"canonical_bson": "180000001364000000000000000000000000000000007800",
"degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+infinity\"}}",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
},
{
"description": "Non-Canonical Parsing - infinity",
"canonical_bson": "180000001364000000000000000000000000000000007800",
corpus/decimal128-2.json view on Meta::CPAN
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}"
},
{
"description": "[decq528] Specials",
"canonical_bson": "18000000136400000000000000000000000000000000F800",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}"
},
{
"description": "[decq541] Specials",
"canonical_bson": "180000001364000000000000000000000000000000007C00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}"
},
{
"description": "[decq074] Nmin and below",
"canonical_bson": "18000000136400000000000A5BC138938D44C64D31000000",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E-6143\"}}"
},
{
"description": "[decq602] fold-down full sequence",
"canonical_bson": "18000000136400000000000A5BC138938D44C64D31FE5F00",
"canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}"
corpus/decimal128-4.json view on Meta::CPAN
{
"description": "[basx568] Near-specials (Conversion_syntax)",
"string": "-Infinit"
},
{
"description": "[basx590] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": ".Infinity"
},
{
"description": "[basx562] Near-specials (Conversion_syntax)",
"string": "NaNq"
},
{
"description": "[basx563] Near-specials (Conversion_syntax)",
"string": "NaNs"
},
{
"description": "[dqbas939] overflow results at different rounding modes (Overflow & Inexact & Rounded)",
"string": "-7e10000"
},
{
"description": "[dqbsr534] negatives (Rounded & Inexact)",
"string": "-1.11111111111111111111111111111234650"
},
{
corpus/decimal128-7.json view on Meta::CPAN
{
"description": "[basx569] Near-specials (Conversion_syntax)",
"string": "0Inf"
},
{
"description": "[basx571] Near-specials (Conversion_syntax)",
"string": "-0Inf"
},
{
"description": "[basx575] Near-specials (Conversion_syntax)",
"string": "0sNaN"
},
{
"description": "[basx503] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "++1"
},
{
"description": "[basx504] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "--1"
},
{
corpus/decimal128-7.json view on Meta::CPAN
{
"description": "[basx585] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": "-.E"
},
{
"description": "[basx589] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": "+.Inf"
},
{
"description": "[basx586] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": ".NaN"
},
{
"description": "[basx587] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": "-.NaN"
},
{
"description": "[basx545] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "ONE"
},
{
"description": "[basx561] Near-specials (Conversion_syntax)",
"string": "qNaN"
},
{
"description": "[basx573] Near-specials (Conversion_syntax)",
"string": "-sNa"
},
{
"description": "[basx588] some baddies with dots and Es and dots and specials (Conversion_syntax)",
"string": "+.sNaN"
},
{
"description": "[basx544] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "ten"
},
{
"description": "[basx527] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "u0b65"
},
{
"description": "[basx526] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "u0e5a"
},
{
"description": "[basx515] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "x"
},
{
"description": "[basx574] Near-specials (Conversion_syntax)",
"string": "xNaN"
},
{
"description": "[basx530] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": ".123.5"
},
{
"description": "[basx500] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)",
"string": "1..2"
},
{
corpus/double.json view on Meta::CPAN
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"0.0\"}}",
"relaxed_extjson": "{\"d\" : 0.0}"
},
{
"description": "-0.0",
"canonical_bson": "10000000016400000000000000008000",
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-0.0\"}}",
"relaxed_extjson": "{\"d\" : -0.0}"
},
{
"description": "NaN",
"canonical_bson": "10000000016400000000000000F87F00",
"canonical_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}",
"relaxed_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}",
"lossy": true
},
{
"description": "NaN with payload",
"canonical_bson": "10000000016400120000000000F87F00",
"canonical_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}",
"relaxed_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}",
"lossy": true
},
{
"description": "Inf",
"canonical_bson": "10000000016400000000000000F07F00",
"canonical_extjson": "{\"d\": {\"$numberDouble\": \"Infinity\"}}",
"relaxed_extjson": "{\"d\": {\"$numberDouble\": \"Infinity\"}}"
},
{
"description": "-Inf",
s++; if (s == send || (*s != 'F' && *s != 'f')) return 0;
s++; if (s < send && (*s == 'I' || *s == 'i')) {
s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
s++; if (s == send || (*s != 'I' && *s != 'i')) return 0;
s++; if (s == send || (*s != 'T' && *s != 't')) return 0;
s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0;
s++;
}
sawinf = 1;
} else if (*s == 'N' || *s == 'n') {
/* XXX TODO: There are signaling NaNs and quiet NaNs. */
s++; if (s == send || (*s != 'A' && *s != 'a')) return 0;
s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
s++;
sawnan = 1;
} else
return 0;
if (sawinf) {
numtype &= IS_NUMBER_NEG; /* Keep track of sign */
numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
t/mapping/decimal128.t view on Meta::CPAN
# test overloading
is( bson_decimal128("3.14159"), "3.14159", "overloading correct" );
# BSON::Decimal128 -> BSON::Decimal128
$hash = decode( encode( { A => bson_decimal128("3.14159") } ) );
is( ref( $hash->{A} ), 'BSON::Decimal128', "BSON::Decimal128->BSON::Decimal128" );
is( $hash->{A}->value, "3.14159", "value correct" );
# test special decimal128s
for my $s ( qw/Infinity -Infinity NaN/ ) {
$hash = decode( encode( { A => bson_decimal128($s) } ) );
is( $hash->{A}->value, $s, "$s value correct" );
}
# to JSON
is( to_myjson( { a => bson_decimal128("0.0") } ),
q[{"a":"0.0"}], 'bson_decimal128(0.0)' );
is( to_myjson( { a => bson_decimal128("42") } ),
q[{"a":"42"}], 'bson_decimal128(42)' );
is( to_myjson( { a => bson_decimal128("0.1") } ),
t/mapping/double.t view on Meta::CPAN
# BSON::Double -> BSON::Double
$hash = decode( encode( { A => bson_double(3.14159) } ), wrap_numbers => 1 );
is( ref( $hash->{A} ), 'BSON::Double', "BSON::Double->BSON::Double" );
packed_is( FLOAT, $hash->{A}->value, 3.14159, "value correct" );
# test special doubles
my %special = (
"Inf" => BSON::Double::pInf(),
"-Inf" => BSON::Double::nInf(),
"NaN" => BSON::Double::NaN(),
);
for my $s ( qw/Inf -Inf NaN/ ) {
$hash = decode( encode( { A => $special{$s} } ) );
is( sv_type( $hash->{A} ), 'PVNV', "$s as double->double" );
packed_is( FLOAT, $hash->{A}, $special{$s}, "value correct" );
}
for my $s ( qw/Inf -Inf NaN/ ) {
$hash = decode( encode( { A => $special{$s} } ), wrap_numbers => 1 );
is( ref( $hash->{A} ), 'BSON::Double', "$s as double->BSON::Double" )
or diag explain $hash;
packed_is( FLOAT, $hash->{A}, $special{$s}, "value correct" );
}
# test special BSON::Double
for my $s ( qw/Inf -Inf NaN/ ) {
$hash = decode( encode( { A => bson_double($special{$s}) } ) );
is( sv_type( $hash->{A} ), 'PVNV', "$s as BSON::Double->BSON::Double" );
packed_is( FLOAT, $hash->{A}, $special{$s}, "value correct" );
}
for my $s ( qw/Inf -Inf NaN/ ) {
$hash = decode( encode( { A => bson_double($special{$s}) } ), wrap_numbers => 1 );
is( ref( $hash->{A} ), 'BSON::Double', "$s as BSON::Double->BSON::Double" )
or diag explain $hash;
packed_is( FLOAT, $hash->{A}, $special{$s}, "value correct" );
}
# to JSON
# Depending on the JSON parser (and version), .0 might get encoded in various
# lossy ways, so we check with a regex for any of the various things we might see
switch(bson_iter_type(iter)) {
case BSON_TYPE_OID: {
value = bson_oid_to_sv(iter);
break;
}
case BSON_TYPE_DOUBLE: {
SV *tempsv;
SV *d = newSVnv(bson_iter_double(iter));
/* Check for Inf and NaN */
if (Perl_isinf(SvNV(d)) || Perl_isnan(SvNV(d)) ) {
SvPV_nolen(d); /* force to PVNV for compatibility */
}
if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
value = new_object_from_pairs("BSON::Double", "value", sv_2mortal(d), NULL);
}
else {
value = d;
}