Skip to content
This repository was archived by the owner on Oct 31, 2023. It is now read-only.

Commit 990b2ef

Browse files
committed
SERVER-9763 Remove BSONObjBuilder append unsigned method
1 parent 5813046 commit 990b2ef

35 files changed

+279
-208
lines changed

src/mongo/bson/bsonobjbuilder.h

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <cstdint>
4040
#include <limits>
4141
#include <map>
42+
#include <type_traits>
4243

4344
#include "mongo/base/data_view.h"
4445
#include "mongo/base/parse_number.h"
@@ -48,8 +49,8 @@
4849
#include "mongo/bson/bsonobj.h"
4950
#include "mongo/bson/util/builder.h"
5051
#include "mongo/platform/decimal128.h"
51-
#include "mongo/stdx/type_traits.h"
5252
#include "mongo/util/decimal_counter.h"
53+
#include "mongo/util/if_constexpr.h"
5354

5455
namespace mongo {
5556

@@ -268,56 +269,28 @@ class BSONObjBuilder {
268269
return *this;
269270
}
270271

271-
/** Append a boolean element */
272-
BSONObjBuilder& append(StringData fieldName, bool val) {
273-
_b.appendNum((char)Bool);
274-
_b.appendStr(fieldName);
275-
_b.appendNum((char)(val ? 1 : 0));
276-
return *this;
277-
}
278-
279-
/** Append a 32 bit integer element */
280-
BSONObjBuilder& append(StringData fieldName, int n) {
281-
_b.appendNum((char)NumberInt);
282-
_b.appendStr(fieldName);
283-
_b.appendNum(n);
284-
return *this;
285-
}
286-
287-
/** Append a 32 bit unsigned element - cast to a signed int. */
288-
BSONObjBuilder& append(StringData fieldName, unsigned n) {
289-
return append(fieldName, (int)n);
290-
}
291-
292-
/** Append a NumberDecimal */
293-
BSONObjBuilder& append(StringData fieldName, Decimal128 n) {
294-
_b.appendNum(static_cast<char>(NumberDecimal));
295-
_b.appendStr(fieldName);
296-
// Make sure we write data in a Little Endian conforming manner
297-
_b.appendNum(n);
298-
return *this;
299-
}
300-
301-
/** Append a NumberLong */
302-
BSONObjBuilder& append(StringData fieldName, long long n) {
303-
_b.appendNum((char)NumberLong);
272+
/** Append elements that have the BSONObjAppendFormat trait */
273+
template <typename T, typename = std::enable_if_t<IsBSONObjAppendable<T>::value>>
274+
BSONObjBuilder& append(StringData fieldName, const T& n) {
275+
constexpr BSONType type = BSONObjAppendFormat<T>::value;
276+
_b.appendNum(static_cast<char>(type));
304277
_b.appendStr(fieldName);
305-
_b.appendNum(n);
278+
IF_CONSTEXPR(type == Bool) {
279+
_b.appendNum(static_cast<char>(n));
280+
}
281+
else IF_CONSTEXPR(type == NumberInt) {
282+
_b.appendNum(static_cast<int>(n));
283+
}
284+
else {
285+
_b.appendNum(n);
286+
}
306287
return *this;
307288
}
308289

309-
/**
310-
* Append a NumberLong (if int64_t isn't the same as long long)
311-
*/
312-
template <typename Int64_t,
313-
typename = stdx::enable_if_t<std::is_same<Int64_t, int64_t>::value &&
314-
!std::is_same<int64_t, long long>::value>>
315-
BSONObjBuilder& append(StringData fieldName, Int64_t n) {
316-
_b.appendNum((char)NumberLong);
317-
_b.appendStr(fieldName);
318-
_b.appendNum(n);
319-
return *this;
320-
}
290+
template <typename T,
291+
typename = std::enable_if_t<!IsBSONObjAppendable<T>::value && std::is_integral_v<T>>,
292+
typename = void>
293+
BSONObjBuilder& append(StringData fieldName, const T& n) = delete;
321294

322295
/** appends a number. if n < max(int)/2 then uses int, otherwise long long */
323296
BSONObjBuilder& appendIntOrLL(StringData fieldName, long long n) {
@@ -374,14 +347,6 @@ class BSONObjBuilder {
374347
return *this;
375348
}
376349

377-
/** Append a double element */
378-
BSONObjBuilder& append(StringData fieldName, double n) {
379-
_b.appendNum((char)NumberDouble);
380-
_b.appendStr(fieldName);
381-
_b.appendNum(n);
382-
return *this;
383-
}
384-
385350
/** Append a BSON Object ID (OID type).
386351
@deprecated Generally, it is preferred to use the append append(name, oid)
387352
method for this.

src/mongo/bson/bsonobjbuilder_test.cpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include "mongo/platform/basic.h"
3131

32+
#include <type_traits>
33+
3234
#include "mongo/db/jsobj.h"
3335
#include "mongo/db/json.h"
3436
#include "mongo/unittest/unittest.h"
@@ -73,35 +75,18 @@ TEST(BSONObjBuilderTest, AppendInt64T) {
7375
ASSERT_EQ(obj["b"].Long(), 1ll << 40);
7476
}
7577

76-
/**
77-
* current conversion ranges in append(unsigned n)
78-
* dbl/int max/min in comments refer to max/min encodable constants
79-
* 0 <= n <= uint_max -----> int
80-
*/
78+
template <typename T, typename = void>
79+
struct isUnsignedAppendable : std::false_type {};
8180

82-
TEST(BSONObjBuilderTest, AppendUnsignedInt) {
83-
struct {
84-
unsigned int v;
85-
BSONType t;
86-
} data[] = {{0, mongo::NumberInt},
87-
{100, mongo::NumberInt},
88-
{maxEncodableInt, mongo::NumberInt},
89-
{maxEncodableInt + 1, mongo::NumberInt},
90-
{static_cast<unsigned int>(maxInt), mongo::NumberInt},
91-
{static_cast<unsigned int>(maxInt) + 1U, mongo::NumberInt},
92-
{(std::numeric_limits<unsigned int>::max)(), mongo::NumberInt},
93-
{0, mongo::Undefined}};
94-
for (int i = 0; data[i].t != mongo::Undefined; i++) {
95-
unsigned int v = data[i].v;
96-
BSONObjBuilder b;
97-
b.append("a", v);
98-
BSONObj o = b.obj();
99-
ASSERT_EQUALS(o.nFields(), 1);
100-
BSONElement e = o.getField("a");
101-
unsigned int n = e.numberLong();
102-
ASSERT_EQUALS(n, v);
103-
assertBSONTypeEquals(e.type(), data[i].t, v, i);
104-
}
81+
template <typename T>
82+
struct isUnsignedAppendable<T, std::void_t<decltype(BSONObjAppendFormat<T>::value)>>
83+
: std::true_type {};
84+
85+
TEST(BSONObjBuilderTest, AppendUnsignedIsForbidden) {
86+
MONGO_STATIC_ASSERT(!isUnsignedAppendable<unsigned>::value);
87+
MONGO_STATIC_ASSERT(!isUnsignedAppendable<unsigned long>::value);
88+
MONGO_STATIC_ASSERT(!isUnsignedAppendable<unsigned long long>::value);
89+
MONGO_STATIC_ASSERT(!isUnsignedAppendable<uint64_t>::value);
10590
}
10691

10792
/**

src/mongo/bson/bsontypes.cpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@
2727
* it in the license file.
2828
*/
2929

30+
#include <fmt/format.h>
31+
3032
#include "mongo/bson/bsontypes.h"
3133

3234
#include "mongo/config.h"
3335
#include "mongo/db/jsobj.h"
36+
#include "mongo/util/string_map.h"
3437

3538
namespace mongo {
39+
using namespace fmt::literals;
3640

3741
const char kMaxKeyData[] = {7, 0, 0, 0, static_cast<char>(MaxKey), 0, 0};
3842
const BSONObj kMaxBSONKey(kMaxKeyData);
@@ -93,35 +97,41 @@ const char* typeName(BSONType type) {
9397
}
9498
}
9599

96-
const StringMap<BSONType> kTypeAliasMap = {
97-
{typeName(BSONType::NumberDouble), BSONType::NumberDouble},
98-
{typeName(BSONType::String), BSONType::String},
99-
{typeName(BSONType::Object), BSONType::Object},
100-
{typeName(BSONType::Array), BSONType::Array},
101-
{typeName(BSONType::BinData), BSONType::BinData},
102-
{typeName(BSONType::Undefined), BSONType::Undefined},
103-
{typeName(BSONType::jstOID), BSONType::jstOID},
104-
{typeName(BSONType::Bool), BSONType::Bool},
105-
{typeName(BSONType::Date), BSONType::Date},
106-
{typeName(BSONType::jstNULL), BSONType::jstNULL},
107-
{typeName(BSONType::RegEx), BSONType::RegEx},
108-
{typeName(BSONType::DBRef), BSONType::DBRef},
109-
{typeName(BSONType::Code), BSONType::Code},
110-
{typeName(BSONType::Symbol), BSONType::Symbol},
111-
{typeName(BSONType::CodeWScope), BSONType::CodeWScope},
112-
{typeName(BSONType::NumberInt), BSONType::NumberInt},
113-
{typeName(BSONType::bsonTimestamp), BSONType::bsonTimestamp},
114-
{typeName(BSONType::NumberLong), BSONType::NumberLong},
115-
{typeName(BSONType::NumberDecimal), BSONType::NumberDecimal},
116-
{typeName(BSONType::MaxKey), BSONType::MaxKey},
117-
{typeName(BSONType::MinKey), BSONType::MinKey}};
100+
boost::optional<BSONType> findBSONTypeAlias(StringData key) {
101+
// intentionally leaked
102+
static const auto& typeAliasMap =
103+
*new StringMap<BSONType>{{typeName(BSONType::NumberDouble), BSONType::NumberDouble},
104+
{typeName(BSONType::String), BSONType::String},
105+
{typeName(BSONType::Object), BSONType::Object},
106+
{typeName(BSONType::Array), BSONType::Array},
107+
{typeName(BSONType::BinData), BSONType::BinData},
108+
{typeName(BSONType::Undefined), BSONType::Undefined},
109+
{typeName(BSONType::jstOID), BSONType::jstOID},
110+
{typeName(BSONType::Bool), BSONType::Bool},
111+
{typeName(BSONType::Date), BSONType::Date},
112+
{typeName(BSONType::jstNULL), BSONType::jstNULL},
113+
{typeName(BSONType::RegEx), BSONType::RegEx},
114+
{typeName(BSONType::DBRef), BSONType::DBRef},
115+
{typeName(BSONType::Code), BSONType::Code},
116+
{typeName(BSONType::Symbol), BSONType::Symbol},
117+
{typeName(BSONType::CodeWScope), BSONType::CodeWScope},
118+
{typeName(BSONType::NumberInt), BSONType::NumberInt},
119+
{typeName(BSONType::bsonTimestamp), BSONType::bsonTimestamp},
120+
{typeName(BSONType::NumberLong), BSONType::NumberLong},
121+
{typeName(BSONType::NumberDecimal), BSONType::NumberDecimal},
122+
{typeName(BSONType::MaxKey), BSONType::MaxKey},
123+
{typeName(BSONType::MinKey), BSONType::MinKey}};
124+
125+
auto it = typeAliasMap.find(key);
126+
if (it == typeAliasMap.end())
127+
return boost::none;
128+
return it->second;
129+
}
118130

119131
BSONType typeFromName(StringData name) {
120-
auto typeIt = kTypeAliasMap.find(name);
121-
uassert(ErrorCodes::BadValue,
122-
str::stream() << "Unknown type name: " << name,
123-
typeIt != kTypeAliasMap.end());
124-
return typeIt->second;
132+
auto typeAlias = findBSONTypeAlias(name);
133+
uassert(ErrorCodes::BadValue, "Unknown type name: {}"_format(name), typeAlias);
134+
return *typeAlias;
125135
}
126136

127137
std::ostream& operator<<(std::ostream& stream, BSONType type) {

src/mongo/bson/bsontypes.h

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@
2929

3030
#pragma once
3131

32+
#include <boost/optional.hpp>
33+
#include <cstdint>
3234
#include <iosfwd>
35+
#include <type_traits>
3336

37+
#include "mongo/base/counter.h"
38+
#include "mongo/base/string_data.h"
3439
#include "mongo/config.h"
3540
#include "mongo/platform/decimal128.h"
3641
#include "mongo/util/assert_util.h"
37-
#include "mongo/util/string_map.h"
3842

3943
namespace mongo {
4044

@@ -113,7 +117,7 @@ enum BSONType {
113117
* Maps from the set of type aliases accepted by the $type query operator to the corresponding BSON
114118
* types. Excludes "number", since this alias maps to a set of BSON types.
115119
*/
116-
extern const StringMap<BSONType> kTypeAliasMap;
120+
boost::optional<BSONType> findBSONTypeAlias(StringData key);
117121

118122
/**
119123
* returns the name of the argument's type
@@ -223,4 +227,80 @@ inline int canonicalizeBSONType(BSONType type) {
223227
return -1;
224228
}
225229
}
226-
}
230+
231+
template <BSONType value>
232+
struct FormatKind : std::integral_constant<BSONType, value> {};
233+
234+
template <typename T>
235+
struct BSONObjAppendFormat;
236+
237+
namespace bsontype_detail {
238+
239+
/* BSONObjFallbackFormat is the trait that BSONObjAppendFormat falls back to in case there is
240+
no explicit specialization for a type. It has a second templated parameter so it can be enabled
241+
for groups of types, e.g. enums. */
242+
template <typename T, typename = void>
243+
struct BSONObjFallbackFormat {};
244+
245+
template <typename T>
246+
struct BSONObjFallbackFormat<T, std::enable_if_t<std::is_enum_v<T>>> : FormatKind<NumberInt> {};
247+
248+
/** This is a special case because long long and int64_t are the same on some platforms but
249+
* different on others. If they are the same, the long long partial specialization of
250+
* BSONObjAppendFormat is accepted, otherwise the int64_t partial specialization of
251+
* BSONObjFallbackFormat is chosen. */
252+
template <>
253+
struct BSONObjFallbackFormat<std::int64_t> : FormatKind<NumberLong> {};
254+
255+
/** Determine if T is appendable based on whether or not BSONOBjAppendFormat<T> has a value. */
256+
template <typename T, typename = void>
257+
struct IsBSONObjAppendable : std::false_type {};
258+
259+
template <typename T>
260+
struct IsBSONObjAppendable<T, std::void_t<decltype(BSONObjAppendFormat<T>::value)>>
261+
: std::true_type {};
262+
263+
} // namespace bsontype_detail
264+
265+
template <typename T>
266+
using IsBSONObjAppendable = bsontype_detail::IsBSONObjAppendable<T>;
267+
268+
template <typename T>
269+
struct BSONObjAppendFormat : bsontype_detail::BSONObjFallbackFormat<T> {};
270+
271+
template <>
272+
struct BSONObjAppendFormat<bool> : FormatKind<Bool> {};
273+
274+
template <>
275+
struct BSONObjAppendFormat<char> : FormatKind<NumberInt> {};
276+
277+
template <>
278+
struct BSONObjAppendFormat<unsigned char> : FormatKind<NumberInt> {};
279+
280+
template <>
281+
struct BSONObjAppendFormat<short> : FormatKind<NumberInt> {};
282+
283+
template <>
284+
struct BSONObjAppendFormat<unsigned short> : FormatKind<NumberInt> {};
285+
286+
template <>
287+
struct BSONObjAppendFormat<int> : FormatKind<NumberInt> {};
288+
289+
/* For platforms where long long and int64_t are the same, this partial specialization will be
290+
used for both. Otherwise, int64_t will use the specialization above. */
291+
template <>
292+
struct BSONObjAppendFormat<long long> : FormatKind<NumberLong> {};
293+
294+
template <>
295+
struct BSONObjAppendFormat<Counter64> : FormatKind<NumberLong> {};
296+
297+
template <>
298+
struct BSONObjAppendFormat<Decimal128> : FormatKind<NumberDecimal> {};
299+
300+
template <>
301+
struct BSONObjAppendFormat<double> : FormatKind<NumberDouble> {};
302+
303+
template <>
304+
struct BSONObjAppendFormat<float> : FormatKind<NumberDouble> {};
305+
306+
} // namespace mongo

src/mongo/client/remote_command_targeter_mock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#pragma once
3131

32+
#include <set>
33+
3234
#include "mongo/client/connection_string.h"
3335
#include "mongo/client/remote_command_targeter.h"
3436
#include "mongo/util/net/hostandport.h"

src/mongo/db/commands/generic_servers.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ class FeaturesCmd : public BasicCommand {
8181
bb.done();
8282
}
8383
if (cmdObj["oidReset"].trueValue()) {
84-
result.append("oidMachineOld", OID::getMachineId());
84+
result.append("oidMachineOld", static_cast<int>(OID::getMachineId()));
8585
OID::regenMachineId();
8686
}
87-
result.append("oidMachine", OID::getMachineId());
87+
result.append("oidMachine", static_cast<int>(OID::getMachineId()));
8888
return true;
8989
}
9090

@@ -121,10 +121,10 @@ class HostInfoCmd : public BasicCommand {
121121

122122
bSys.appendDate("currentTime", jsTime());
123123
bSys.append("hostname", prettyHostName());
124-
bSys.append("cpuAddrSize", p.getAddrSize());
125-
bSys.append("memSizeMB", static_cast<unsigned>(p.getSystemMemSizeMB()));
126-
bSys.append("memLimitMB", static_cast<unsigned>(p.getMemSizeMB()));
127-
bSys.append("numCores", p.getNumCores());
124+
bSys.append("cpuAddrSize", static_cast<int>(p.getAddrSize()));
125+
bSys.append("memSizeMB", static_cast<long long>(p.getSystemMemSizeMB()));
126+
bSys.append("memLimitMB", static_cast<long long>(p.getMemSizeMB()));
127+
bSys.append("numCores", static_cast<int>(p.getNumCores()));
128128
bSys.append("cpuArch", p.getArch());
129129
bSys.append("numaEnabled", p.hasNumaEnabled());
130130
bOs.append("type", p.getOsType());

0 commit comments

Comments
 (0)