summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@10gen.com>2013-12-23 14:19:12 -0500
committerAndy Schwerin <schwerin@10gen.com>2014-01-07 16:42:09 -0500
commit7ad6ad2e90f4b17c73c0f74f57460ef50469fa0b (patch)
tree7675fa497209b6ea8ce562df27ff75f0eff6c874 /src
parent8c2b72f7f76368653e417778cddb0793ffed64e7 (diff)
downloadmongo-7ad6ad2e90f4b17c73c0f74f57460ef50469fa0b.tar.gz
SERVER-11995 Add basic integer support to bson_extract.h.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/bson/util/bson_extract.cpp42
-rw-r--r--src/mongo/bson/util/bson_extract.h29
-rw-r--r--src/mongo/bson/util/bson_extract_test.cpp40
3 files changed, 109 insertions, 2 deletions
diff --git a/src/mongo/bson/util/bson_extract.cpp b/src/mongo/bson/util/bson_extract.cpp
index a20e2aef4e5..19ca41c47fc 100644
--- a/src/mongo/bson/util/bson_extract.cpp
+++ b/src/mongo/bson/util/bson_extract.cpp
@@ -67,17 +67,20 @@ namespace mongo {
Status status = bsonExtractField(object, fieldName, &value);
if (status == ErrorCodes::NoSuchKey) {
*out = defaultValue;
+ return Status::OK();
}
else if (!status.isOK()) {
return status;
}
else if (!value.isNumber() && !value.isBoolean()) {
- return Status(ErrorCodes::TypeMismatch, "Expected boolean or number type");
+ return Status(ErrorCodes::TypeMismatch, mongoutils::str::stream() <<
+ "Expected boolean or number type for field \"" << fieldName <<
+ "\", found " << typeName(value.type()));
}
else {
*out = value.trueValue();
+ return Status::OK();
}
- return Status::OK();
}
Status bsonExtractStringField(const BSONObj& object,
@@ -105,4 +108,39 @@ namespace mongo {
return Status::OK();
}
+ Status bsonExtractIntegerField(const BSONObj& object,
+ const StringData& fieldName,
+ long long* out) {
+ BSONElement value;
+ Status status = bsonExtractField(object, fieldName, &value);
+ if (!status.isOK())
+ return status;
+ if (!value.isNumber()) {
+ return Status(ErrorCodes::TypeMismatch, mongoutils::str::stream() <<
+ "Expected field \"" << fieldName <<
+ "\" to have numeric type, but found " << typeName(value.type()));
+ }
+ long long result = value.safeNumberLong();
+ if (result != value.numberDouble()) {
+ return Status(ErrorCodes::BadValue, mongoutils::str::stream() <<
+ "Expected field \"" << fieldName << " to have an value "
+ "exactly representable as a 64-bit integer, but found " <<
+ value);
+ }
+ *out = result;
+ return Status::OK();
+ }
+
+ Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
+ const StringData& fieldName,
+ long long defaultValue,
+ long long* out) {
+ Status status = bsonExtractIntegerField(object, fieldName, out);
+ if (status == ErrorCodes::NoSuchKey) {
+ *out = defaultValue;
+ status = Status::OK();
+ }
+ return status;
+ }
+
} // namespace mongo
diff --git a/src/mongo/bson/util/bson_extract.h b/src/mongo/bson/util/bson_extract.h
index 8887a782f83..fd1c6ca057b 100644
--- a/src/mongo/bson/util/bson_extract.h
+++ b/src/mongo/bson/util/bson_extract.h
@@ -62,6 +62,20 @@ namespace mongo {
bool* out);
/**
+ * Finds an element named "fieldName" in "object" that represents an integral value.
+ *
+ * Returns Status::OK() and sets *out to the element's 64-bit integer value representation on
+ * success. Returns ErrorCodes::NoSuchKey if there are no matches for "fieldName". Returns
+ * ErrorCodes::TypeMismatch if the value of the matching element is not of a numeric type.
+ * Returns ErrorCodes::BadValue if the value does not have an exact 64-bit integer
+ * representation. For return values other than Status::OK(), the resulting value of "*out" is
+ * undefined.
+ */
+ Status bsonExtractIntegerField(const BSONObj& object,
+ const StringData& fieldName,
+ long long* out);
+
+ /**
* Finds a string-typed element named "fieldName" in "object" and stores its value in "out".
*
* Returns Status::OK() and sets *out to the found element's string value on success. Returns
@@ -89,6 +103,21 @@ namespace mongo {
bool* out);
/**
+ * Finds an element named "fieldName" in "object" that represents an integral value.
+ *
+ * If a field named "fieldName" is present and is a value of numeric type with an exact 64-bit
+ * integer representation, returns that representation in *out and returns Status::OK(). If
+ * there is no field named "fieldName", stores defaultValue into *out and returns Status::OK().
+ * If the field is found, but has non-numeric type, returns ErrorCodes::TypeMismatch. If the
+ * value has numeric type, but cannot be represented as a 64-bit integer, returns
+ * ErrorCodes::BadValue.
+ */
+ Status bsonExtractIntegerFieldWithDefault(const BSONObj& object,
+ const StringData& fieldName,
+ long long defaultValue,
+ long long* out);
+
+ /**
* Finds a string element named "fieldName" in "object".
*
* If a field named "fieldName" is present, and is a string, stores the value of the field into
diff --git a/src/mongo/bson/util/bson_extract_test.cpp b/src/mongo/bson/util/bson_extract_test.cpp
index 38c9e568bd0..78774104063 100644
--- a/src/mongo/bson/util/bson_extract_test.cpp
+++ b/src/mongo/bson/util/bson_extract_test.cpp
@@ -96,3 +96,43 @@ TEST(ExtractBSON, ExtractBooleanFieldWithDefault) {
ASSERT_EQUALS(ErrorCodes::TypeMismatch,
bsonExtractBooleanFieldWithDefault(obj1, "b", true, &b));
}
+
+TEST(ExtractBSON, ExtractIntegerField) {
+ long long v;
+ ASSERT_EQUALS(ErrorCodes::NoSuchKey, bsonExtractIntegerField(
+ BSON("a" << 1),
+ "b",
+ &v));
+ ASSERT_OK(bsonExtractIntegerFieldWithDefault(
+ BSON("a" << 1),
+ "b",
+ -1LL,
+ &v));
+ ASSERT_EQUALS(-1LL, v);
+ ASSERT_EQUALS(ErrorCodes::TypeMismatch, bsonExtractIntegerField(
+ BSON("a" << false),
+ "a",
+ &v));
+ ASSERT_EQUALS(ErrorCodes::BadValue, bsonExtractIntegerField(
+ BSON("a" << nan("")),
+ "a",
+ &v));
+ ASSERT_EQUALS(ErrorCodes::BadValue, bsonExtractIntegerField(
+ BSON("a" << pow(2.0, 64)),
+ "a",
+ &v));
+ ASSERT_EQUALS(ErrorCodes::BadValue, bsonExtractIntegerField(
+ BSON("a" << -1.5),
+ "a",
+ &v));
+ ASSERT_OK(bsonExtractIntegerField(
+ BSON("a" << -pow(2.0, 55)),
+ "a",
+ &v));
+ ASSERT_EQUALS(-(1LL << 55), v);
+ ASSERT_OK(bsonExtractIntegerField(
+ BSON("a" << 5178),
+ "a",
+ &v));
+ ASSERT_EQUALS(5178, v);
+}