BSON-XS

 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",

ppport.h  view on Meta::CPAN

    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

xs/XS.xs  view on Meta::CPAN


  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;
    }



( run in 0.365 second using v1.01-cache-2.11-cpan-fd5d4e115d8 )