commit 38d79a190b9f2adf34c2c84c4014f90912f368d9 | |
Author: David Golden <dagolden@cpan.org> | |
Date: Wed May 20 19:47:03 2015 -0400 | |
encode integers as BSON Int32 if they fit | |
diff --git a/perl_mongo.c b/perl_mongo.c | |
index 54833fe..9cc619b 100644 | |
--- a/perl_mongo.c | |
+++ b/perl_mongo.c | |
@@ -908,7 +908,13 @@ sv_to_bson_elem (bson_t * bson, const char * in_key, SV *sv, HV *opts, stackette | |
/* if it's publicly an int OR (privately an int AND not publicly a string) */ | |
if (aggressively_number || (!is_string && (SvIOK(sv) || (SvIOKp(sv) && !SvPOK(sv))))) { | |
#if defined(MONGO_USE_64_BIT_INT) | |
- bson_append_int64(bson, key, -1, (int64_t)SvIV(sv)); | |
+ IV i = SvIV(sv); | |
+ if ( i >= INT32_MIN && i <= INT32_MAX) { | |
+ bson_append_int32(bson, key, -1, (int)i); | |
+ } | |
+ else { | |
+ bson_append_int64(bson, key, -1, (int64_t)i); | |
+ } | |
#else | |
bson_append_int32(bson, key, -1, (int)SvIV(sv)); | |
#endif | |
diff --git a/t/bson_codec/elements.t b/t/bson_codec/elements.t | |
index bbcc7e0..e0c769d 100644 | |
--- a/t/bson_codec/elements.t | |
+++ b/t/bson_codec/elements.t | |
@@ -19,6 +19,7 @@ use Test::More 0.96; | |
use Test::Deep 0.086; # num() function | |
use Test::Fatal; | |
+use Config; | |
use DateTime; | |
use DateTime::Tiny; | |
use MongoDB; | |
@@ -69,6 +70,8 @@ use constant { | |
BSON_DATETIME => "\x09", | |
BSON_NULL => "\x0A", | |
BSON_REGEXP => "\x0B", | |
+ BSON_INT32 => "\x10", | |
+ BSON_INT64 => "\x12", | |
}; | |
my $class = "MongoDB::BSON"; | |
@@ -144,8 +147,37 @@ my @cases = ( | |
output => | |
{ a => [ '$db' => $dbref->db, '$id' => $dbref->id, '$ref' => $dbref->ref ] }, | |
}, | |
+ { | |
+ label => "BSON Int32", | |
+ input => { a => 66 }, | |
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(66) ), | |
+ output => { a => 66 }, | |
+ }, | |
+ { | |
+ label => "BSON Int64 (max 32 bit int)", | |
+ input => { a => 2147483647 }, | |
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(2147483647) ), | |
+ output => { a => 2147483647 }, | |
+ }, | |
+ { | |
+ label => "BSON Int64 (min 32 bit int)", | |
+ input => { a => -2147483647-1 }, | |
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(-2147483647-1) ), | |
+ output => { a => -2147483647-1 }, | |
+ }, | |
); | |
+if ( $Config{use64bitint} ) { | |
+ my $big = 20 << 40; | |
+ push @cases, | |
+ { | |
+ label => "BSON Int64", | |
+ input => { a => $big }, | |
+ bson => _doc( BSON_INT64 . _ename("a") . _int64($big) ), | |
+ output => { a => $big }, | |
+ }; | |
+} | |
+ | |
for my $c (@cases) { | |
my ( $label, $input, $bson, $output ) = @{$c}{qw/label input bson output/}; | |
my $encoded = $codec->encode_one( $input, $c->{enc_opts} || {} ); | |
@@ -175,6 +207,10 @@ BEGIN { *_ename = \&_cstring } | |
sub _double { return pack( "d", shift ) } | |
+sub _int32 { return pack( P_INT32, shift ) } | |
+ | |
+sub _int64 { return pack( P_INT64, shift ) } | |
+ | |
sub _string { | |
my ($string) = shift; | |
return pack( P_INT32, 1 + length($string) ) . $string . "\x00"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment