diff --git a/examples/mongocxx/mongodb.com/documentation_examples.cpp b/examples/mongocxx/mongodb.com/documentation_examples.cpp index 81228e0091..46af1571ca 100644 --- a/examples/mongocxx/mongodb.com/documentation_examples.cpp +++ b/examples/mongocxx/mongodb.com/documentation_examples.cpp @@ -41,7 +41,7 @@ void check_field(const T& document, const char* field, bool should_have, int example_no, - const char* example_type = NULL) { + const char* example_type = nullptr) { std::string example_type_formatted = example_type ? example_type + std::string(" ") : ""; if (should_have) { if (!document[field]) { diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp index ebfa09cb24..756c9e6cbb 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/operators.hpp @@ -117,7 +117,7 @@ class strong_ordering { // nonstd: Swap greater/less values constexpr strong_ordering inverted() const noexcept { - return *this < 0 ? greater : *this > 0 ? less : *this; + return *this < nullptr ? greater : *this > nullptr ? less : *this; } }; diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp index b710926cc2..cd068642fa 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp @@ -124,7 +124,7 @@ struct nullopt_t { explicit constexpr nullopt_t(std::nullptr_t) noexcept {} }; /// Tag constant to construct or compare with an empty optional value -static constexpr nullopt_t nullopt{0}; +static constexpr nullopt_t nullopt{nullptr}; /// Tag used to call the emplacement-constructor of optional static constexpr struct in_place_t { } in_place; diff --git a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp index e2e87393c5..424d07f346 100644 --- a/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp +++ b/src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp @@ -182,7 +182,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: const std::basic_string& str) noexcept : _begin(str.data()), _size(str.size()) {} -#if __cpp_lib_string_view +#if defined(__cpp_lib_string_view) constexpr basic_string_view(std::basic_string_view sv) noexcept : _begin(sv.data()), _size(sv.size()) {} #endif @@ -503,7 +503,7 @@ class basic_string_view : bsoncxx::detail::equality_operators, bsoncxx::detail:: return std::basic_string(data(), size()); } -#if __cpp_lib_string_view +#if defined(__cpp_lib_string_view) explicit operator std::basic_string_view() const noexcept { return std::basic_string_view(data(), size()); } diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/document/element.cpp b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/document/element.cpp index 9c7056f79c..6232619ea2 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/document/element.cpp +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/document/element.cpp @@ -25,9 +25,10 @@ #include -#define BSONCXX_CITER \ - bson_iter_t iter; \ - bson_iter_init_from_data_at_offset(&iter, _raw, _length, _offset, _keylen); +#define BSONCXX_CITER \ + bson_iter_t iter; \ + bson_iter_init_from_data_at_offset(&iter, _raw, _length, _offset, _keylen); \ + ((void)0) namespace bsoncxx { namespace v_noabi { diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/exception/error_code.cpp b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/exception/error_code.cpp index 03b04ad3de..f6f5da75b4 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/exception/error_code.cpp +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/exception/error_code.cpp @@ -58,6 +58,8 @@ class error_category_impl final : public std::error_category { return "unset document::element"; case error_code::k_invalid_oid: return "could not parse Object ID string"; + case error_code::k_failed_converting_bson_to_json: + return "could not convert document to JSON"; case error_code::k_json_parse_failure: return "could not parse JSON document"; case error_code::k_invalid_decimal128: @@ -72,6 +74,8 @@ class error_category_impl final : public std::error_category { return "tried to complete appending an array, but overflowed"; case error_code::k_cannot_end_appending_document: return "tried to complete appending an document, but overflowed"; + case error_code::k_invalid_binary_subtype: + return "invalid BSON binary subtype"; case error_code::k_invalid_bson_type_id: return "invalid BSON type identifier"; #define BSONCXX_ENUM(name, value) \ diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/json.cpp b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/json.cpp index 784d342554..4085faa908 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/json.cpp +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/json.cpp @@ -99,7 +99,7 @@ document::value BSONCXX_CALL from_json(stdx::string_view json) { return document::value{buf, length, bson_free_deleter}; } -document::value BSONCXX_CALL operator"" _bson(const char* str, size_t len) { +document::value BSONCXX_CALL operator""_bson(const char* str, size_t len) { return from_json(stdx::string_view{str, len}); } diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/private/b64_ntop.hh b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/private/b64_ntop.hh index cc940498b5..55e69473bf 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/private/b64_ntop.hh +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/private/b64_ntop.hh @@ -185,7 +185,7 @@ inline int ntop(std::uint8_t const* src, return -1; } target[datalength] = '\0'; /* Returned value doesn't count \0. */ - return (int)datalength; + return static_cast(datalength); } } // namespace b64 diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/private/value.hh b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/private/value.hh index 28cbb626bc..52611e3fca 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/private/value.hh +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/private/value.hh @@ -47,7 +47,8 @@ class value::impl { impl operator=(const impl&) = delete; bson_value::view view() const noexcept { - return bson_value::view{(void*)&_value}; + // ABI backward compatibility. Const is restored in `view::_init`. + return bson_value::view{const_cast(static_cast(&_value))}; } bson_value_t _value; diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/value.cpp b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/value.cpp index 72a57277d8..cebc544bea 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/value.cpp +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/value.cpp @@ -50,7 +50,7 @@ value::value(b_string v) : value(v.value) {} value::value(stdx::string_view v) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_UTF8; _impl->_value.value.v_utf8.str = make_copy_for_libbson(v); - _impl->_value.value.v_utf8.len = (uint32_t)v.size(); + _impl->_value.value.v_utf8.len = static_cast(v.size()); } value::value(b_null) : value(nullptr) {} @@ -90,6 +90,25 @@ value::value(const type id) : _impl{stdx::make_unique()} { case type::k_undefined: _impl->_value.value_type = BSON_TYPE_UNDEFINED; break; + + case type::k_double: + case type::k_string: + case type::k_document: + case type::k_array: + case type::k_binary: + case type::k_oid: + case type::k_bool: + case type::k_date: + case type::k_null: + case type::k_regex: + case type::k_dbpointer: + case type::k_code: + case type::k_symbol: + case type::k_codewscope: + case type::k_int32: + case type::k_timestamp: + case type::k_int64: + case type::k_decimal128: default: throw bsoncxx::v_noabi::exception(error_code::k_invalid_bson_type_id); } @@ -100,7 +119,8 @@ value::value(stdx::string_view regex, stdx::string_view options) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_REGEX; _impl->_value.value.v_regex.regex = make_copy_for_libbson(regex); - _impl->_value.value.v_regex.options = options.empty() ? NULL : make_copy_for_libbson(options); + _impl->_value.value.v_regex.options = + options.empty() ? nullptr : make_copy_for_libbson(options); } value::value(b_code v) : value(v.type_id, v) {} @@ -110,18 +130,37 @@ value::value(const type id, stdx::string_view v) : _impl{stdx::make_unique case type::k_regex: _impl->_value.value_type = BSON_TYPE_REGEX; _impl->_value.value.v_regex.regex = make_copy_for_libbson(v); - _impl->_value.value.v_regex.options = NULL; + _impl->_value.value.v_regex.options = nullptr; break; case type::k_code: _impl->_value.value_type = BSON_TYPE_CODE; _impl->_value.value.v_code.code = make_copy_for_libbson(v); - _impl->_value.value.v_code.code_len = (uint32_t)v.length(); + _impl->_value.value.v_code.code_len = static_cast(v.length()); break; case type::k_symbol: _impl->_value.value_type = BSON_TYPE_SYMBOL; _impl->_value.value.v_symbol.symbol = make_copy_for_libbson(v); - _impl->_value.value.v_symbol.len = (uint32_t)v.length(); + _impl->_value.value.v_symbol.len = static_cast(v.length()); break; + + case type::k_double: + case type::k_string: + case type::k_document: + case type::k_array: + case type::k_binary: + case type::k_undefined: + case type::k_oid: + case type::k_bool: + case type::k_date: + case type::k_null: + case type::k_dbpointer: + case type::k_codewscope: + case type::k_int32: + case type::k_timestamp: + case type::k_int64: + case type::k_decimal128: + case type::k_maxkey: + case type::k_minkey: default: throw bsoncxx::v_noabi::exception(error_code::k_invalid_bson_type_id); } @@ -139,9 +178,29 @@ value::value(type id, uint64_t a, uint64_t b) : _impl{stdx::make_unique()} break; case type::k_timestamp: _impl->_value.value_type = BSON_TYPE_TIMESTAMP; - _impl->_value.value.v_timestamp.increment = (uint32_t)a; - _impl->_value.value.v_timestamp.timestamp = (uint32_t)b; + _impl->_value.value.v_timestamp.increment = static_cast(a); + _impl->_value.value.v_timestamp.timestamp = static_cast(b); break; + + case type::k_double: + case type::k_string: + case type::k_document: + case type::k_array: + case type::k_binary: + case type::k_undefined: + case type::k_oid: + case type::k_bool: + case type::k_date: + case type::k_null: + case type::k_regex: + case type::k_dbpointer: + case type::k_code: + case type::k_symbol: + case type::k_codewscope: + case type::k_int32: + case type::k_int64: + case type::k_maxkey: + case type::k_minkey: default: throw bsoncxx::v_noabi::exception(error_code::k_invalid_bson_type_id); } @@ -151,7 +210,7 @@ value::value(b_dbpointer v) : value(v.collection, v.value) {} value::value(stdx::string_view collection, oid value) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_DBPOINTER; _impl->_value.value.v_dbpointer.collection = make_copy_for_libbson(collection); - _impl->_value.value.v_dbpointer.collection_len = (uint32_t)collection.length(); + _impl->_value.value.v_dbpointer.collection_len = static_cast(collection.length()); std::memcpy(_impl->_value.value.v_dbpointer.oid.bytes, value.bytes(), value.k_oid_length); } @@ -160,9 +219,10 @@ value::value(stdx::string_view code, bsoncxx::v_noabi::document::view_or_value s : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_CODEWSCOPE; _impl->_value.value.v_codewscope.code = make_copy_for_libbson(code); - _impl->_value.value.v_codewscope.code_len = (uint32_t)code.length(); - _impl->_value.value.v_codewscope.scope_len = (uint32_t)scope.view().length(); - _impl->_value.value.v_codewscope.scope_data = (uint8_t*)bson_malloc(scope.view().length()); + _impl->_value.value.v_codewscope.code_len = static_cast(code.length()); + _impl->_value.value.v_codewscope.scope_len = static_cast(scope.view().length()); + _impl->_value.value.v_codewscope.scope_data = + static_cast(bson_malloc(scope.view().length())); std::memcpy( _impl->_value.value.v_codewscope.scope_data, scope.view().data(), scope.view().length()); } @@ -174,8 +234,8 @@ value::value(const uint8_t* data, size_t size, const binary_sub_type sub_type) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_BINARY; _impl->_value.value.v_binary.subtype = static_cast(sub_type); - _impl->_value.value.v_binary.data_len = (uint32_t)size; - _impl->_value.value.v_binary.data = (uint8_t*)bson_malloc(size); + _impl->_value.value.v_binary.data_len = static_cast(size); + _impl->_value.value.v_binary.data = static_cast(bson_malloc(size)); if (size) std::memcpy(_impl->_value.value.v_binary.data, data, size); } @@ -183,16 +243,16 @@ value::value(const uint8_t* data, size_t size, const binary_sub_type sub_type) value::value(b_document v) : value(v.view()) {} value::value(bsoncxx::v_noabi::document::view v) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_DOCUMENT; - _impl->_value.value.v_doc.data_len = (uint32_t)v.length(); - _impl->_value.value.v_doc.data = (uint8_t*)bson_malloc(v.length()); + _impl->_value.value.v_doc.data_len = static_cast(v.length()); + _impl->_value.value.v_doc.data = static_cast(bson_malloc(v.length())); std::memcpy(_impl->_value.value.v_doc.data, v.data(), v.length()); } value::value(b_array v) : value(v.value) {} value::value(bsoncxx::v_noabi::array::view v) : _impl{stdx::make_unique()} { _impl->_value.value_type = BSON_TYPE_ARRAY; - _impl->_value.value.v_doc.data_len = (uint32_t)v.length(); - _impl->_value.value.v_doc.data = (uint8_t*)bson_malloc(v.length()); + _impl->_value.value.v_doc.data_len = static_cast(v.length()); + _impl->_value.value.v_doc.data = static_cast(bson_malloc(v.length())); std::memcpy(_impl->_value.value.v_doc.data, v.data(), v.length()); } @@ -215,7 +275,7 @@ value::value(const std::uint8_t* raw, } value::value(void* internal_value) - : _impl(stdx::make_unique((bson_value_t*)internal_value)) {} + : _impl(stdx::make_unique(static_cast(internal_value))) {} value::value(const value& rhs) : value(&rhs._impl->_value) {} diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/view.cpp b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/view.cpp index acb80e75d6..ca16017d83 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/view.cpp +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/bson_value/view.cpp @@ -23,9 +23,10 @@ #include -#define BSONCXX_CITER \ - bson_iter_t iter; \ - bson_iter_init_from_data_at_offset(&iter, raw, length, offset, keylen); +#define BSONCXX_CITER \ + bson_iter_t iter; \ + bson_iter_init_from_data_at_offset(&iter, raw, length, offset, keylen); \ + ((void)0) #define BSONCXX_TYPE_CHECK(name) \ do { \ @@ -126,7 +127,8 @@ view::view(const std::uint8_t* raw, auto value = bson_iter_value(&iter); - _init((void*)value); + // ABI backward compatibility. Const is restored in `view::_init`. + _init(const_cast(static_cast(value))); } view::view(void* internal_value) noexcept { @@ -140,7 +142,7 @@ void view::_init(void* internal_value) noexcept { return; } - bson_value_t* v = (bson_value_t*)(internal_value); + auto v = static_cast(internal_value); _type = static_cast(v->value_type); switch (_type) { diff --git a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/private/convert.hh b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/private/convert.hh index ef49e7129b..9b6a5dc715 100644 --- a/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/private/convert.hh +++ b/src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/types/private/convert.hh @@ -29,12 +29,12 @@ namespace types { inline char* make_copy_for_libbson(stdx::string_view s, uint32_t* len_out = nullptr) { // Append a nul byte to the end of the string - char* copy = (char*)bson_malloc0(s.length() + 1); + auto copy = static_cast(bson_malloc0(s.length() + 1)); std::memcpy(copy, s.data(), s.length()); copy[s.length()] = '\0'; if (len_out) { - *len_out = (uint32_t)(s.length()); + *len_out = static_cast(s.length()); } return copy; @@ -45,7 +45,7 @@ inline void convert_to_libbson(const b_binary& binary, bson_value_t* v) { v->value.v_binary.subtype = static_cast(binary.sub_type); v->value.v_binary.data_len = binary.size; - v->value.v_binary.data = (uint8_t*)bson_malloc0(binary.size); + v->value.v_binary.data = static_cast(bson_malloc0(binary.size)); std::memcpy(v->value.v_binary.data, binary.bytes, binary.size); } @@ -136,8 +136,9 @@ inline void convert_to_libbson(const b_codewscope& code, bson_value_t* v) { v->value.v_codewscope.scope_data = nullptr; v->value.v_codewscope.scope_len = 0; } else { - v->value.v_codewscope.scope_data = (uint8_t*)bson_malloc0(code.scope.length()); - v->value.v_codewscope.scope_len = (uint32_t)code.scope.length(); + v->value.v_codewscope.scope_data = + static_cast(bson_malloc0(code.scope.length())); + v->value.v_codewscope.scope_len = static_cast(code.scope.length()); std::memcpy(v->value.v_codewscope.scope_data, code.scope.data(), code.scope.length()); } } @@ -159,11 +160,11 @@ inline void convert_to_libbson(const b_maxkey&, bson_value_t* v) { inline void convert_to_libbson(const b_document& doc, bson_value_t* v) { v->value_type = BSON_TYPE_DOCUMENT; - v->value.v_doc.data_len = (uint32_t)doc.value.length(); + v->value.v_doc.data_len = static_cast(doc.value.length()); if (0 == (v->value.v_doc.data_len)) { v->value.v_doc.data = nullptr; } else { - v->value.v_doc.data = (uint8_t*)bson_malloc0(v->value.v_doc.data_len); + v->value.v_doc.data = static_cast(bson_malloc0(v->value.v_doc.data_len)); std::memcpy(v->value.v_doc.data, doc.value.data(), v->value.v_doc.data_len); } } @@ -173,11 +174,11 @@ inline void convert_to_libbson(const b_array& arr, bson_value_t* v) { // The bson_value_t struct does not have a separate union // member for arrays. They are handled the same as the document // BSON type. - v->value.v_doc.data_len = (uint32_t)arr.value.length(); + v->value.v_doc.data_len = static_cast(arr.value.length()); if (v->value.v_doc.data_len == 0) { v->value.v_doc.data = nullptr; } else { - v->value.v_doc.data = (uint8_t*)bson_malloc0(arr.value.length()); + v->value.v_doc.data = static_cast(bson_malloc0(arr.value.length())); std::memcpy(v->value.v_doc.data, arr.value.data(), arr.value.length()); } } @@ -200,7 +201,7 @@ inline void convert_to_libbson(bson_value_t* v, const bson_value::view& bson_vie } } -inline void convert_from_libbson(bson_value_t* v, b_binary* out) { +inline void convert_from_libbson(const bson_value_t* v, b_binary* out) { bson_subtype_t subtype = v->value.v_binary.subtype; std::uint32_t len = v->value.v_binary.data_len; const std::uint8_t* binary = v->value.v_binary.data; @@ -208,59 +209,59 @@ inline void convert_from_libbson(bson_value_t* v, b_binary* out) { *out = {static_cast(subtype), len, binary}; } -inline void convert_from_libbson(bson_value_t* v, b_string* out) { +inline void convert_from_libbson(const bson_value_t* v, b_string* out) { uint32_t len = v->value.v_utf8.len; const char* val = v->value.v_utf8.str; *out = b_string{stdx::string_view{val, len}}; } -inline void convert_from_libbson(bson_value_t* v, b_double* out) { +inline void convert_from_libbson(const bson_value_t* v, b_double* out) { *out = b_double{v->value.v_double}; } -inline void convert_from_libbson(bson_value_t* v, b_int32* out) { +inline void convert_from_libbson(const bson_value_t* v, b_int32* out) { *out = b_int32{v->value.v_int32}; } -inline void convert_from_libbson(bson_value_t* v, b_int64* out) { +inline void convert_from_libbson(const bson_value_t* v, b_int64* out) { *out = b_int64{v->value.v_int64}; } -inline void convert_from_libbson(bson_value_t*, b_undefined* out) { +inline void convert_from_libbson(const bson_value_t*, b_undefined* out) { *out = b_undefined{}; } -inline void convert_from_libbson(bson_value_t* v, b_oid* out) { +inline void convert_from_libbson(const bson_value_t* v, b_oid* out) { const bson_oid_t* boid = &(v->value.v_oid); oid val_oid(reinterpret_cast(boid->bytes), sizeof(boid->bytes)); *out = b_oid{std::move(val_oid)}; } -inline void convert_from_libbson(bson_value_t* v, b_decimal128* out) { +inline void convert_from_libbson(const bson_value_t* v, b_decimal128* out) { bson_decimal128_t d128 = v->value.v_decimal128; *out = b_decimal128{decimal128{d128.high, d128.low}}; } -inline void convert_from_libbson(bson_value_t* v, b_bool* out) { +inline void convert_from_libbson(const bson_value_t* v, b_bool* out) { *out = b_bool{v->value.v_bool}; } -inline void convert_from_libbson(bson_value_t* v, b_date* out) { +inline void convert_from_libbson(const bson_value_t* v, b_date* out) { *out = b_date{std::chrono::milliseconds{v->value.v_datetime}}; } -inline void convert_from_libbson(bson_value_t*, b_null* out) { +inline void convert_from_libbson(const bson_value_t*, b_null* out) { *out = b_null{}; } -inline void convert_from_libbson(bson_value_t* v, b_regex* out) { +inline void convert_from_libbson(const bson_value_t* v, b_regex* out) { const char* options = v->value.v_regex.options; const char* regex = v->value.v_regex.regex; *out = b_regex{regex, options ? options : stdx::string_view{}}; } -inline void convert_from_libbson(bson_value_t* v, b_dbpointer* out) { +inline void convert_from_libbson(const bson_value_t* v, b_dbpointer* out) { uint32_t collection_len = v->value.v_dbpointer.collection_len; const char* collection = v->value.v_dbpointer.collection; const bson_oid_t* boid = &(v->value.v_dbpointer.oid); @@ -270,21 +271,21 @@ inline void convert_from_libbson(bson_value_t* v, b_dbpointer* out) { *out = b_dbpointer{stdx::string_view{collection, collection_len}, std::move(oid)}; } -inline void convert_from_libbson(bson_value_t* v, b_code* out) { +inline void convert_from_libbson(const bson_value_t* v, b_code* out) { uint32_t len = v->value.v_code.code_len; const char* code = v->value.v_code.code; *out = b_code{stdx::string_view{code, len}}; } -inline void convert_from_libbson(bson_value_t* v, b_symbol* out) { +inline void convert_from_libbson(const bson_value_t* v, b_symbol* out) { uint32_t len = v->value.v_symbol.len; const char* symbol = v->value.v_symbol.symbol; *out = b_symbol{stdx::string_view{symbol, len}}; } -inline void convert_from_libbson(bson_value_t* v, b_codewscope* out) { +inline void convert_from_libbson(const bson_value_t* v, b_codewscope* out) { uint32_t code_len = v->value.v_codewscope.code_len; const uint8_t* scope_ptr = v->value.v_codewscope.scope_data; uint32_t scope_len = v->value.v_codewscope.scope_len; @@ -294,28 +295,28 @@ inline void convert_from_libbson(bson_value_t* v, b_codewscope* out) { *out = b_codewscope{stdx::string_view{code, code_len}, view}; } -inline void convert_from_libbson(bson_value_t* v, b_timestamp* out) { +inline void convert_from_libbson(const bson_value_t* v, b_timestamp* out) { uint32_t timestamp = v->value.v_timestamp.timestamp; uint32_t increment = v->value.v_timestamp.increment; *out = {increment, timestamp}; } -inline void convert_from_libbson(bson_value_t*, b_minkey* out) { +inline void convert_from_libbson(const bson_value_t*, b_minkey* out) { *out = b_minkey{}; } -inline void convert_from_libbson(bson_value_t*, b_maxkey* out) { +inline void convert_from_libbson(const bson_value_t*, b_maxkey* out) { *out = b_maxkey{}; } -inline void convert_from_libbson(bson_value_t* v, b_document* out) { +inline void convert_from_libbson(const bson_value_t* v, b_document* out) { const std::uint8_t* buf = v->value.v_doc.data; std::uint32_t len = v->value.v_doc.data_len; *out = b_document{document::view{buf, len}}; } -inline void convert_from_libbson(bson_value_t* v, b_array* out) { +inline void convert_from_libbson(const bson_value_t* v, b_array* out) { // The bson_value_t struct does not have a separate union // member for arrays. They are handled the same as the document // BSON type. diff --git a/src/bsoncxx/test/bson_builder.cpp b/src/bsoncxx/test/bson_builder.cpp index d5a57b9aa3..134af723af 100644 --- a/src/bsoncxx/test/bson_builder.cpp +++ b/src/bsoncxx/test/bson_builder.cpp @@ -172,7 +172,7 @@ TEST_CASE("builder appends oid", "[bsoncxx::builder::stream]") { bson_init(&expected); bson_oid_t oid; - bson_oid_init(&oid, NULL); + bson_oid_init(&oid, nullptr); bson_append_oid(&expected, "foo", -1, &oid); @@ -1339,7 +1339,7 @@ TEST_CASE("list builder appends oid", "[bsoncxx::builder::list]") { bson_init(&expected); bson_oid_t oid; - bson_oid_init(&oid, NULL); + bson_oid_init(&oid, nullptr); bson_append_oid(&expected, "foo", -1, &oid); diff --git a/src/mongocxx/lib/CMakeLists.txt b/src/mongocxx/lib/CMakeLists.txt index a7fbada786..0411360b30 100644 --- a/src/mongocxx/lib/CMakeLists.txt +++ b/src/mongocxx/lib/CMakeLists.txt @@ -192,6 +192,7 @@ set_dist_list(src_mongocxx_lib_DIST mongocxx/v_noabi/mongocxx/private/pool.hh mongocxx/v_noabi/mongocxx/private/read_concern.hh mongocxx/v_noabi/mongocxx/private/read_preference.hh + mongocxx/v_noabi/mongocxx/private/scoped_bson_value.hh mongocxx/v_noabi/mongocxx/private/search_index_model.hh mongocxx/v_noabi/mongocxx/private/search_index_view.hh mongocxx/v_noabi/mongocxx/private/uri.hh diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/client.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/client.cpp index ac5e34d242..a1115d0bfb 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/client.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/client.cpp @@ -45,7 +45,7 @@ class database_names { public: explicit database_names(char** names) { _names = names; - }; + } ~database_names() { bson_strfreev(_names); @@ -58,7 +58,7 @@ class database_names { const char* operator[](const std::size_t i) const { return _names[i]; - }; + } bool operator!() const { return _names == nullptr; diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/collection.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/collection.cpp index 97b5c2ea52..8bf91fd293 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/collection.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/collection.cpp @@ -403,7 +403,7 @@ cursor collection::_find(const client_session* session, const options::find& options) { scoped_bson_t filter_bson{std::move(filter)}; - const mongoc_read_prefs_t* rp_ptr = NULL; + const mongoc_read_prefs_t* rp_ptr = nullptr; if (options.read_preference()) { rp_ptr = options.read_preference()->_impl->read_preference_t; } @@ -483,7 +483,7 @@ cursor collection::_aggregate(const client_session* session, scoped_bson_t options_bson(b.view()); - const ::mongoc_read_prefs_t* rp_ptr = NULL; + const ::mongoc_read_prefs_t* rp_ptr = nullptr; if (options.read_preference()) { rp_ptr = options.read_preference()->_impl->read_preference_t; @@ -922,11 +922,12 @@ stdx::optional collection::_find_one_and_repl const options::find_one_and_replace& options) { mongoc_find_and_modify_flags_t flags = MONGOC_FIND_AND_MODIFY_NONE; if (options.upsert().value_or(false)) { - flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_UPSERT); + flags = static_cast(flags | MONGOC_FIND_AND_MODIFY_UPSERT); } if (options.return_document() == options::return_document::k_after) { - flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW); + flags = + static_cast(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW); } return find_and_modify(_get_impl().collection_t, @@ -959,11 +960,12 @@ stdx::optional collection::_find_one_and_upda const options::find_one_and_update& options) { mongoc_find_and_modify_flags_t flags = MONGOC_FIND_AND_MODIFY_NONE; if (options.upsert().value_or(false)) { - flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_UPSERT); + flags = static_cast(flags | MONGOC_FIND_AND_MODIFY_UPSERT); } if (options.return_document() == options::return_document::k_after) { - flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW); + flags = + static_cast(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW); } return find_and_modify(_get_impl().collection_t, @@ -1055,7 +1057,7 @@ std::int64_t collection::_count_documents(const client_session* session, scoped_bson_t bson_filter{filter}; scoped_bson_t reply; bson_error_t error; - const mongoc_read_prefs_t* read_prefs = NULL; + const mongoc_read_prefs_t* read_prefs = nullptr; if (const auto& rp = options.read_preference()) { read_prefs = rp->_impl->read_preference_t; @@ -1120,7 +1122,7 @@ std::int64_t collection::estimated_document_count( scoped_bson_t reply; bson_error_t error; - const mongoc_read_prefs_t* read_prefs = NULL; + const mongoc_read_prefs_t* read_prefs = nullptr; if (const auto& rp = options.read_preference()) { read_prefs = rp->_impl->read_preference_t; @@ -1208,7 +1210,7 @@ cursor collection::_distinct(const client_session* session, bsoncxx::v_noabi::builder::concatenate_doc{session->_get_impl().to_document()}); } - const mongoc_read_prefs_t* rp_ptr = NULL; + const mongoc_read_prefs_t* rp_ptr = nullptr; if (const auto& rp = options.read_preference()) { rp_ptr = rp->_impl->read_preference_t; } diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/database.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/database.cpp index ba21cfc04f..7f7f62e806 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/database.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/database.cpp @@ -49,7 +49,7 @@ class collection_names { public: explicit collection_names(char** names) { _names = names; - }; + } ~collection_names() { bson_strfreev(_names); @@ -63,7 +63,7 @@ class collection_names { const char* operator[](const std::size_t i) const { return _names[i]; - }; + } bool operator!() const { return _names == nullptr; @@ -128,7 +128,7 @@ cursor database::_aggregate(const client_session* session, scoped_bson_t options_bson(b.view()); - const ::mongoc_read_prefs_t* rp_ptr = NULL; + const ::mongoc_read_prefs_t* rp_ptr = nullptr; if (options.read_preference()) { rp_ptr = options.read_preference()->_impl->read_preference_t; @@ -230,7 +230,7 @@ bsoncxx::v_noabi::document::value database::_run_command( scoped_bson_t options_bson(options_builder.extract()); auto result = libmongoc::database_command_with_opts(_get_impl().database_t, command_bson.bson(), - NULL, + nullptr, options_bson.bson(), reply_bson.bson_for_init(), &error); diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/data_key.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/data_key.cpp index 16dfebf208..e3a32e6a3e 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/data_key.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/data_key.cpp @@ -52,7 +52,7 @@ void* data_key::convert() const { if (!_key_alt_names.empty()) { auto altnames = _key_alt_names; - char** names = (char**)bson_malloc(sizeof(char*) * altnames.size()); + auto names = static_cast(bson_malloc(sizeof(char*) * altnames.size())); uint32_t i = 0; for (auto&& name : altnames) { diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp index 2ce4f2bb5e..25aaa53467 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -81,55 +82,6 @@ const stdx::optional& encrypt::range_opts() const { return _range_opts; } -namespace { - -struct scoped_bson_value { - bson_value_t value = {}; - - // Allow obtaining a pointer to this->value even in rvalue expressions. - bson_value_t* get() noexcept { - return &value; - } - - // Communicate this->value is to be initialized via the resulting pointer. - bson_value_t* value_for_init() noexcept { - return &this->value; - } - - template - auto convert(const T& value) - // Use trailing return type syntax to SFINAE without triggering GCC -Wignored-attributes - // warnings due to using decltype within template parameters. - -> decltype(bsoncxx::v_noabi::types::convert_to_libbson(std::declval(), - std::declval())) { - bsoncxx::v_noabi::types::convert_to_libbson(value, &this->value); - } - - template - explicit scoped_bson_value(const T& value) { - convert(value); - } - - explicit scoped_bson_value(const bsoncxx::v_noabi::types::bson_value::view& view) { - // Argument order is reversed for bsoncxx::v_noabi::types::bson_value::view. - bsoncxx::v_noabi::types::convert_to_libbson(&this->value, view); - } - - ~scoped_bson_value() { - bson_value_destroy(&value); - } - - // Expectation is that value_for_init() will be used to initialize this->value. - scoped_bson_value() = default; - - scoped_bson_value(const scoped_bson_value&) = delete; - scoped_bson_value(scoped_bson_value&&) = delete; - scoped_bson_value& operator=(const scoped_bson_value&) = delete; - scoped_bson_value& operator=(scoped_bson_value&&) = delete; -}; - -} // namespace - void* encrypt::convert() const { using libbson::scoped_bson_t; @@ -158,7 +110,8 @@ void* encrypt::convert() const { "key id must be a binary value with subtype 4 (UUID)"}; } - libmongoc::client_encryption_encrypt_opts_set_keyid(opts, scoped_bson_value(key_id).get()); + libmongoc::client_encryption_encrypt_opts_set_keyid( + opts, detail::scoped_bson_value(key_id).get()); } if (_key_alt_name) { @@ -234,12 +187,12 @@ void* encrypt::convert() const { if (min) { libmongoc::client_encryption_encrypt_range_opts_set_min( - range_opts, scoped_bson_value(min->view()).get()); + range_opts, detail::scoped_bson_value(min->view()).get()); } if (max) { libmongoc::client_encryption_encrypt_range_opts_set_max( - range_opts, scoped_bson_value(max->view()).get()); + range_opts, detail::scoped_bson_value(max->view()).get()); } if (precision) { diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/apm.hh b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/apm.hh index ef82cfe309..3046ff1ddb 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/apm.hh +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/apm.hh @@ -31,7 +31,7 @@ using apm_unique_callbacks = // An APM callback exiting via an exception is documented as being undefined behavior. // For QoI, terminate the program before allowing the exception to bypass libmongoc code. template -static void exception_guard(const char* source, Fn fn) noexcept { +inline void exception_guard(const char* source, Fn fn) noexcept { try { fn(); } catch (...) { @@ -41,80 +41,79 @@ static void exception_guard(const char* source, Fn fn) noexcept { } } -static void command_started(const mongoc_apm_command_started_t* event) noexcept { +inline void command_started(const mongoc_apm_command_started_t* event) noexcept { events::command_started_event started_event(static_cast(event)); auto context = static_cast(libmongoc::apm_command_started_get_context(event)); exception_guard(__func__, [&] { context->command_started()(started_event); }); } -static void command_failed(const mongoc_apm_command_failed_t* event) noexcept { +inline void command_failed(const mongoc_apm_command_failed_t* event) noexcept { events::command_failed_event failed_event(static_cast(event)); auto context = static_cast(libmongoc::apm_command_failed_get_context(event)); exception_guard(__func__, [&] { context->command_failed()(failed_event); }); } -static void command_succeeded(const mongoc_apm_command_succeeded_t* event) noexcept { +inline void command_succeeded(const mongoc_apm_command_succeeded_t* event) noexcept { events::command_succeeded_event succeeded_event(static_cast(event)); auto context = static_cast(libmongoc::apm_command_succeeded_get_context(event)); exception_guard(__func__, [&] { context->command_succeeded()(succeeded_event); }); } -static void server_closed(const mongoc_apm_server_closed_t* event) noexcept { +inline void server_closed(const mongoc_apm_server_closed_t* event) noexcept { events::server_closed_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_server_closed_get_context(event)); exception_guard(__func__, [&] { context->server_closed()(e); }); } -static void server_changed(const mongoc_apm_server_changed_t* event) noexcept { +inline void server_changed(const mongoc_apm_server_changed_t* event) noexcept { events::server_changed_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_server_changed_get_context(event)); exception_guard(__func__, [&] { context->server_changed()(e); }); } -static void server_opening(const mongoc_apm_server_opening_t* event) noexcept { +inline void server_opening(const mongoc_apm_server_opening_t* event) noexcept { events::server_opening_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_server_opening_get_context(event)); exception_guard(__func__, [&] { context->server_opening()(e); }); } -static void topology_closed(const mongoc_apm_topology_closed_t* event) noexcept { +inline void topology_closed(const mongoc_apm_topology_closed_t* event) noexcept { events::topology_closed_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_topology_closed_get_context(event)); exception_guard(__func__, [&] { context->topology_closed()(e); }); } -static void topology_changed(const mongoc_apm_topology_changed_t* event) noexcept { +inline void topology_changed(const mongoc_apm_topology_changed_t* event) noexcept { events::topology_changed_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_topology_changed_get_context(event)); exception_guard(__func__, [&] { context->topology_changed()(e); }); } -static void topology_opening(const mongoc_apm_topology_opening_t* event) noexcept { +inline void topology_opening(const mongoc_apm_topology_opening_t* event) noexcept { events::topology_opening_event e(static_cast(event)); auto context = static_cast(libmongoc::apm_topology_opening_get_context(event)); exception_guard(__func__, [&] { context->topology_opening()(e); }); } -static void heartbeat_started(const mongoc_apm_server_heartbeat_started_t* event) noexcept { +inline void heartbeat_started(const mongoc_apm_server_heartbeat_started_t* event) noexcept { events::heartbeat_started_event started_event(static_cast(event)); auto context = static_cast(libmongoc::apm_server_heartbeat_started_get_context(event)); exception_guard(__func__, [&] { context->heartbeat_started()(started_event); }); } -static void heartbeat_failed(const mongoc_apm_server_heartbeat_failed_t* event) noexcept { +inline void heartbeat_failed(const mongoc_apm_server_heartbeat_failed_t* event) noexcept { events::heartbeat_failed_event failed_event(static_cast(event)); auto context = static_cast(libmongoc::apm_server_heartbeat_failed_get_context(event)); exception_guard(__func__, [&] { context->heartbeat_failed()(failed_event); }); } -static void heartbeat_succeeded(const mongoc_apm_server_heartbeat_succeeded_t* event) noexcept { +inline void heartbeat_succeeded(const mongoc_apm_server_heartbeat_succeeded_t* event) noexcept { events::heartbeat_succeeded_event succeeded_event(static_cast(event)); auto context = static_cast(libmongoc::apm_server_heartbeat_succeeded_get_context(event)); exception_guard(__func__, [&] { context->heartbeat_succeeded()(succeeded_event); }); } -BSON_MAYBE_UNUSED -static apm_unique_callbacks make_apm_callbacks(const apm& apm_opts) { +inline apm_unique_callbacks make_apm_callbacks(const apm& apm_opts) { mongoc_apm_callbacks_t* callbacks = libmongoc::apm_callbacks_new(); if (apm_opts.command_started()) { diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/server_api.hh b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/server_api.hh index 2546708bed..469680a141 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/server_api.hh +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/private/server_api.hh @@ -29,8 +29,7 @@ namespace options { using unique_server_api = std::unique_ptr; -BSON_MAYBE_UNUSED -static unique_server_api make_server_api(const server_api& opts) { +inline unique_server_api make_server_api(const server_api& opts) { mongoc_server_api_version_t mongoc_api_version; // Convert version enum value to std::string then to c_str to create mongoc api version. diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/client_encryption.hh b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/client_encryption.hh index f7479a585d..836c56a6ea 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/client_encryption.hh +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/client_encryption.hh @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -43,51 +44,6 @@ class client_encryption::impl { private: using scoped_bson_t = mongocxx::libbson::scoped_bson_t; - struct scoped_bson_value { - bson_value_t value = {}; - - // Allow obtaining a pointer to this->value even in rvalue expressions. - bson_value_t* get() noexcept { - return &value; - } - - // Communicate this->value is to be initialized via the resulting pointer. - bson_value_t* value_for_init() noexcept { - return &this->value; - } - - template - auto convert(const T& value) - // Use trailing return type syntax to SFINAE without triggering GCC -Wignored-attributes - // warnings due to using decltype within template parameters. - -> decltype(bsoncxx::v_noabi::types::convert_to_libbson( - std::declval(), std::declval())) { - bsoncxx::v_noabi::types::convert_to_libbson(value, &this->value); - } - - template - explicit scoped_bson_value(const T& value) { - convert(value); - } - - explicit scoped_bson_value(const bsoncxx::v_noabi::types::bson_value::view& view) { - // Argument order is reversed for bsoncxx::v_noabi::types::bson_value::view. - bsoncxx::v_noabi::types::convert_to_libbson(&this->value, view); - } - - ~scoped_bson_value() { - bson_value_destroy(&value); - } - - // Expectation is that value_for_init() will be used to initialize this->value. - scoped_bson_value() = default; - - scoped_bson_value(const scoped_bson_value&) = delete; - scoped_bson_value(scoped_bson_value&&) = delete; - scoped_bson_value& operator=(const scoped_bson_value&) = delete; - scoped_bson_value& operator=(scoped_bson_value&&) = delete; - }; - struct encrypt_opts_deleter { void operator()(mongoc_client_encryption_encrypt_opts_t* ptr) noexcept { libmongoc::client_encryption_encrypt_opts_destroy(ptr); @@ -133,7 +89,7 @@ class client_encryption::impl { const auto datakey_opts = datakey_opts_ptr(static_cast(opts.convert())); - scoped_bson_value keyid; + detail::scoped_bson_value keyid; bson_error_t error; if (!libmongoc::client_encryption_create_datakey(_client_encryption.get(), @@ -152,11 +108,11 @@ class client_encryption::impl { const auto encrypt_opts = encrypt_opts_ptr(static_cast(opts.convert())); - scoped_bson_value ciphertext; + detail::scoped_bson_value ciphertext; bson_error_t error; if (!libmongoc::client_encryption_encrypt(_client_encryption.get(), - scoped_bson_value(value).get(), + detail::scoped_bson_value(value).get(), encrypt_opts.get(), ciphertext.value_for_init(), &error)) { @@ -187,11 +143,11 @@ class client_encryption::impl { bsoncxx::v_noabi::types::bson_value::value decrypt( bsoncxx::v_noabi::types::bson_value::view value) { - scoped_bson_value decrypted_value; + detail::scoped_bson_value decrypted_value; bson_error_t error; if (!libmongoc::client_encryption_decrypt(_client_encryption.get(), - scoped_bson_value(value).get(), + detail::scoped_bson_value(value).get(), decrypted_value.value_for_init(), &error)) { throw_exception(error); @@ -257,7 +213,7 @@ class client_encryption::impl { bson_error_t error; if (!libmongoc::client_encryption_delete_key(_client_encryption.get(), - scoped_bson_value(id.view()).get(), + detail::scoped_bson_value(id.view()).get(), reply.bson_for_init(), &error)) { throw_exception(error); @@ -281,7 +237,7 @@ class client_encryption::impl { bson_error_t error; if (!libmongoc::client_encryption_get_key(_client_encryption.get(), - scoped_bson_value(id.view()).get(), + detail::scoped_bson_value(id.view()).get(), key_doc.bson_for_init(), &error)) { throw_exception(error); @@ -311,11 +267,12 @@ class client_encryption::impl { scoped_bson_t key_doc; bson_error_t error; - if (!libmongoc::client_encryption_add_key_alt_name(_client_encryption.get(), - scoped_bson_value(id.view()).get(), - key_alt_name.terminated().data(), - key_doc.bson_for_init(), - &error)) { + if (!libmongoc::client_encryption_add_key_alt_name( + _client_encryption.get(), + detail::scoped_bson_value(id.view()).get(), + key_alt_name.terminated().data(), + key_doc.bson_for_init(), + &error)) { throw_exception(error); } @@ -347,11 +304,12 @@ class client_encryption::impl { scoped_bson_t key_doc; bson_error_t error; - if (!libmongoc::client_encryption_remove_key_alt_name(_client_encryption.get(), - scoped_bson_value(id.view()).get(), - key_alt_name.terminated().data(), - key_doc.bson_for_init(), - &error)) { + if (!libmongoc::client_encryption_remove_key_alt_name( + _client_encryption.get(), + detail::scoped_bson_value(id.view()).get(), + key_alt_name.terminated().data(), + key_doc.bson_for_init(), + &error)) { throw_exception(error); } diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/scoped_bson_value.hh b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/scoped_bson_value.hh new file mode 100644 index 0000000000..95371cd184 --- /dev/null +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/scoped_bson_value.hh @@ -0,0 +1,72 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include +#include +#include + +namespace mongocxx { +namespace detail { + +struct scoped_bson_value { + bson_value_t value = {}; + + // Allow obtaining a pointer to this->value even in rvalue expressions. + bson_value_t* get() noexcept { + return &value; + } + + // Communicate this->value is to be initialized via the resulting pointer. + bson_value_t* value_for_init() noexcept { + return &this->value; + } + + template + auto convert(const T& value) + // Use trailing return type syntax to SFINAE without triggering GCC -Wignored-attributes + // warnings due to using decltype within template parameters. + -> decltype(bsoncxx::v_noabi::types::convert_to_libbson(std::declval(), + std::declval())) { + bsoncxx::v_noabi::types::convert_to_libbson(value, &this->value); + } + + template + explicit scoped_bson_value(const T& value) { + convert(value); + } + + explicit scoped_bson_value(const bsoncxx::v_noabi::types::bson_value::view& view) { + // Argument order is reversed for bsoncxx::v_noabi::types::bson_value::view. + bsoncxx::v_noabi::types::convert_to_libbson(&this->value, view); + } + + ~scoped_bson_value() { + bson_value_destroy(&value); + } + + // Expectation is that value_for_init() will be used to initialize this->value. + scoped_bson_value() = default; + + scoped_bson_value(const scoped_bson_value&) = delete; + scoped_bson_value(scoped_bson_value&&) = delete; + scoped_bson_value& operator=(const scoped_bson_value&) = delete; + scoped_bson_value& operator=(scoped_bson_value&&) = delete; +}; + +} // namespace detail +} // namespace mongocxx diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/read_concern.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/read_concern.cpp index c667086a55..a4ca934de1 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/read_concern.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/read_concern.cpp @@ -60,7 +60,7 @@ void read_concern::acknowledge_level(read_concern::level rc_level) { break; case read_concern::level::k_server_default: // libmongoc uses a NULL level to mean "use the server's default read_concern." - libmongoc::read_concern_set_level(_impl->read_concern_t, NULL); + libmongoc::read_concern_set_level(_impl->read_concern_t, nullptr); break; case read_concern::level::k_available: libmongoc::read_concern_set_level(_impl->read_concern_t, @@ -70,6 +70,8 @@ void read_concern::acknowledge_level(read_concern::level rc_level) { libmongoc::read_concern_set_level(_impl->read_concern_t, MONGOC_READ_CONCERN_LEVEL_SNAPSHOT); break; + + case read_concern::level::k_unknown: default: throw exception{error_code::k_unknown_read_concern}; } @@ -79,7 +81,7 @@ void read_concern::acknowledge_string(stdx::string_view rc_string) { // libmongoc uses a NULL level to mean "use the server's default read_concern." libmongoc::read_concern_set_level( _impl->read_concern_t, - rc_string.empty() ? NULL : bsoncxx::v_noabi::string::to_string(rc_string).data()); + rc_string.empty() ? nullptr : bsoncxx::v_noabi::string::to_string(rc_string).data()); } read_concern::level read_concern::acknowledge_level() const { @@ -118,7 +120,7 @@ bsoncxx::v_noabi::document::value read_concern::to_document() const { bsoncxx::v_noabi::builder::basic::document doc; if (level) { doc.append(kvp("level", level)); - }; + } return doc.extract(); } diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/uri.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/uri.cpp index c38b61bce3..49f59bf1cf 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/uri.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/uri.cpp @@ -103,7 +103,7 @@ mongocxx::v_noabi::read_concern uri::read_concern() const { mongocxx::v_noabi::read_preference uri::read_preference() const { auto rp = libmongoc::uri_get_read_prefs_t(_impl->uri_t); - return (mongocxx::v_noabi::read_preference)( + return mongocxx::v_noabi::read_preference( stdx::make_unique(libmongoc::read_prefs_copy(rp))); } @@ -136,7 +136,7 @@ mongocxx::v_noabi::write_concern uri::write_concern() const { static stdx::optional _string_option(mongoc_uri_t* uri, std::string opt_name) { const char* value; - value = libmongoc::uri_get_option_as_utf8(uri, opt_name.c_str(), NULL); + value = libmongoc::uri_get_option_as_utf8(uri, opt_name.c_str(), nullptr); if (!value) { return {}; } diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/write_concern.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/write_concern.cpp index 7897f605fe..e7c80d7b17 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/write_concern.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/write_concern.cpp @@ -175,6 +175,12 @@ bsoncxx::v_noabi::document::value write_concern::to_document() const { if (auto t = tag()) { doc.append(kvp("w", *t)); } + break; + + case write_concern::level::k_acknowledged: + // `ns.has_value()` implies an acknowledged write. + break; + default: break; } diff --git a/src/mongocxx/test/change_streams.cpp b/src/mongocxx/test/change_streams.cpp index cad8c719f3..4137f63abf 100644 --- a/src/mongocxx/test/change_streams.cpp +++ b/src/mongocxx/test/change_streams.cpp @@ -77,7 +77,7 @@ const auto gen_error = [](bool has_error) { "expected error"); *bson = &err_doc; } else { - *bson = NULL; + *bson = nullptr; } return has_error; }; diff --git a/src/mongocxx/test/client_side_encryption.cpp b/src/mongocxx/test/client_side_encryption.cpp index 8d943b37a0..d7ffbc0dc6 100644 --- a/src/mongocxx/test/client_side_encryption.cpp +++ b/src/mongocxx/test/client_side_encryption.cpp @@ -2847,7 +2847,7 @@ TEST_CASE("Custom Key Material Test", "[client_side_encryption]") { mongocxx::libbson::scoped_bson_t bson_doc; bson_doc.init_from_static(doc); mongocxx::libbson::scoped_bson_t doc_without_id; - bson_copy_to_excluding_noinit(bson_doc.bson(), doc_without_id.bson_for_init(), "_id", NULL); + bson_copy_to_excluding_noinit(bson_doc.bson(), doc_without_id.bson_for_init(), "_id", nullptr); bsoncxx::document::value new_doc(doc_without_id.steal()); diff --git a/src/mongocxx/test/collection_mocked.cpp b/src/mongocxx/test/collection_mocked.cpp index 6dc8544c4d..8d567ef434 100644 --- a/src/mongocxx/test/collection_mocked.cpp +++ b/src/mongocxx/test/collection_mocked.cpp @@ -213,7 +213,7 @@ TEST_CASE("Collection", "[collection]") { REQUIRE(o.find("writeConcern") == o.end()); } - return NULL; + return nullptr; }); pipe.match(make_document(kvp("foo", "bar"))); @@ -268,7 +268,7 @@ TEST_CASE("Collection", "[collection]") { if (expected_opts) { bson_t opts_without_skip_or_limit = BSON_INITIALIZER; bson_copy_to_excluding_noinit( - opts, &opts_without_skip_or_limit, "skip", "limit", NULL); + opts, &opts_without_skip_or_limit, "skip", "limit", nullptr); REQUIRE(bson_equal(&opts_without_skip_or_limit, expected_opts)); bson_destroy(&opts_without_skip_or_limit); } @@ -454,7 +454,7 @@ TEST_CASE("Collection", "[collection]") { libmongoc::conversions::read_mode_t_from_read_mode( mongo_coll.read_preference().mode())); - mongoc_cursor_t* cursor = NULL; + mongoc_cursor_t* cursor = nullptr; return cursor; });