Skip to content

Commit c8a76db

Browse files
CXX-739 Add a string::view_or_value class
1 parent ffb3771 commit c8a76db

File tree

4 files changed

+149
-6
lines changed

4 files changed

+149
-6
lines changed

src/bsoncxx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ set(bsoncxx_sources
4141
private/error_code.cpp
4242
private/itoa.cpp
4343
private/libbson_error.cpp
44+
string/view_or_value.cpp
4445
types.cpp
4546
types/value.cpp
4647
validate.cpp

src/bsoncxx/string/view_or_value.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2015 MongoDB Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <bsoncxx/config/prelude.hpp>
16+
17+
#include <bsoncxx/string/view_or_value.hpp>
18+
19+
namespace bsoncxx {
20+
BSONCXX_INLINE_NAMESPACE_BEGIN
21+
namespace string {
22+
23+
const char* view_or_value::c_str() {
24+
// If we do not own our string, we cannot guarantee that it is null-terminated,
25+
// so make an owned copy.
26+
if (!_value) {
27+
_value = std::move(_view.to_string());
28+
_view = *_value;
29+
}
30+
31+
return _value->c_str();
32+
}
33+
34+
} // namespace string
35+
BSONCXX_INLINE_NAMESPACE_END
36+
} // namespace bsoncxx

src/bsoncxx/string/view_or_value.hpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2015 MongoDB Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <bsoncxx/config/prelude.hpp>
18+
19+
#include <string>
20+
21+
#include <bsoncxx/stdx/string_view.hpp>
22+
#include <bsoncxx/view_or_value.hpp>
23+
24+
namespace bsoncxx {
25+
BSONCXX_INLINE_NAMESPACE_BEGIN
26+
namespace string {
27+
28+
///
29+
/// Class representing a view-or-value variant type for strings.
30+
///
31+
/// This class adds several string-specific methods to the bsoncxx::view_or_value template:
32+
/// - a constructor overload for const char*
33+
/// - a constructor overload for std::string by l-value reference
34+
/// - a safe c_str() operation to return null-terminated c-style strings.
35+
///
36+
class BSONCXX_API view_or_value : public bsoncxx::view_or_value<stdx::string_view, std::string> {
37+
public:
38+
///
39+
/// Forward all bsoncxx::view_or_value constructors.
40+
///
41+
using bsoncxx::view_or_value<stdx::string_view, std::string>::view_or_value;
42+
43+
///
44+
/// Construct a string::view_or_value using a null-terminated const char *.
45+
/// The resulting view_or_value will keep a string_view of 'str', so it is
46+
/// important that the passed-in string outlive this object.
47+
///
48+
/// @param str A null-terminated string
49+
///
50+
BSONCXX_INLINE view_or_value(const char* str)
51+
: bsoncxx::view_or_value<stdx::string_view, std::string>(stdx::string_view(str)) {
52+
}
53+
54+
///
55+
/// Allow construction with an l-value reference to a std::string. The resulting
56+
/// view_or_value will keep a string_view of 'str', so it is important that the
57+
/// passed-in string outlive this object.
58+
///
59+
/// Construction calls passing a std::string by r-value reference will use the
60+
/// constructor defined in the parent view_or_value class.
61+
///
62+
/// @param str A std::string l-value reference.
63+
///
64+
BSONCXX_INLINE view_or_value(const std::string& str)
65+
: bsoncxx::view_or_value<stdx::string_view, std::string>(stdx::string_view(str)) {
66+
}
67+
68+
///
69+
/// Return a null-terminated string from this string::view_or_value.
70+
///
71+
/// @note if we are non-owning, we cannot assume our string_view is null-terminated.
72+
/// In this case we must make a new, owning view_or_value with a null-terminated
73+
/// copy of our view.
74+
///
75+
/// @return A pointer to the original string, or a null-terminated copy.
76+
///
77+
const char* c_str();
78+
};
79+
80+
///
81+
/// Compare string::view_or_value directly with const char *.
82+
///
83+
84+
BSONCXX_INLINE bool operator==(const view_or_value& lhs, const char* rhs) {
85+
return lhs.view() == stdx::string_view(rhs);
86+
}
87+
88+
BSONCXX_INLINE bool operator!=(const view_or_value& lhs, const char* rhs) {
89+
return !(lhs == rhs);
90+
}
91+
92+
BSONCXX_INLINE bool operator==(const char* lhs, const view_or_value& rhs) {
93+
return rhs == lhs;
94+
}
95+
96+
BSONCXX_INLINE bool operator!=(const char* lhs, const view_or_value& rhs) {
97+
return !(rhs == lhs);
98+
}
99+
100+
} // namespace string
101+
BSONCXX_INLINE_NAMESPACE_END
102+
} // namespace bsoncxx
103+
104+
#include <bsoncxx/config/postlude.hpp>

src/bsoncxx/view_or_value.hpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,32 @@ class view_or_value {
6666
/// @param value
6767
/// A Value type.
6868
///
69-
BSONCXX_INLINE view_or_value(Value&& value) : _value{std::move(value)}, _view{_value->view()} {
69+
BSONCXX_INLINE view_or_value(Value&& value) : _value(std::move(value)), _view(*_value) {
7070
}
7171

7272
///
7373
/// Construct a view_or_value from a copied view_or_value.
7474
///
7575
BSONCXX_INLINE view_or_value(const view_or_value& other)
76-
: _value{other._value}, _view{_value ? _value->view() : other._view} {
76+
: _value(other._value), _view(_value ? *_value : other._view) {
7777
}
7878

7979
///
8080
/// Assign to this view_or_value from a copied view_or_value.
8181
///
8282
BSONCXX_INLINE view_or_value& operator=(const view_or_value& other) {
8383
_value = other._value;
84-
_view = _value ? _value->view() : other._view;
84+
_view = _value ? *_value : other._view;
8585
return *this;
8686
}
8787

8888
///
8989
/// Construct a view_or_value from a moved-in view_or_value.
9090
///
91+
9192
/// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
9293
BSONCXX_INLINE view_or_value(view_or_value&& other) noexcept
93-
: _value{std::move(other._value)}, _view{_value ? _value->view() : std::move(other._view)} {
94+
: _value{std::move(other._value)}, _view(_value ? *_value : std::move(other._view)) {
9495
other._view = View();
9596
other._value = stdx::nullopt;
9697
}
@@ -101,7 +102,7 @@ class view_or_value {
101102
/// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
102103
BSONCXX_INLINE view_or_value& operator=(view_or_value&& other) noexcept {
103104
_value = std::move(other._value);
104-
_view = _value ? _value->view() : std::move(other._view);
105+
_view = _value ? *_value : std::move(other._view);
105106
other._view = View();
106107
other._value = stdx::nullopt;
107108
return *this;
@@ -120,7 +121,8 @@ class view_or_value {
120121
return _view;
121122
}
122123

123-
private:
124+
// TODO: make these private again (CXX-801)
125+
protected:
124126
stdx::optional<Value> _value;
125127
View _view;
126128
};

0 commit comments

Comments
 (0)