Skip to content

Commit 5360c23

Browse files
author
Micah Scott
committed
initial implementation for bsoncxx::vector
1 parent b316f50 commit 5360c23

File tree

9 files changed

+1307
-0
lines changed

9 files changed

+1307
-0
lines changed
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
// Copyright 2009-present 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 <cstdint>
18+
#include <cstring>
19+
20+
#include <bsoncxx/config/prelude.hpp>
21+
22+
namespace bsoncxx {
23+
namespace v_noabi {
24+
namespace vector {
25+
26+
namespace iterators {
27+
28+
template <typename Iterator>
29+
class packed_bit_element;
30+
31+
template <typename Iterator>
32+
class packed_bit_byte;
33+
34+
} // namespace iterators
35+
36+
namespace elements {
37+
38+
/// @brief A 32-bit float value in packed little-endian format
39+
class float32 {
40+
public:
41+
/// @brief Construct a packed little-endian value from a float input in the local byte order.
42+
/// @param value Floating point value to convert
43+
float32(float value) noexcept {
44+
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
45+
std::memcpy(bytes, &value, sizeof value);
46+
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
47+
std::uint32_t u32;
48+
std::memcpy(&u32, &value, sizeof value);
49+
u32 = bswap32(u32);
50+
std::memcpy(bytes, &u32, sizeof value);
51+
#else
52+
#error No implementation for storing 32-bit little endian unaligned float
53+
#endif
54+
}
55+
56+
/// Convert a packed little-endian floating point value back to the local byte order.
57+
operator float() const noexcept {
58+
float value;
59+
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
60+
std::memcpy(&value, bytes, sizeof value);
61+
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
62+
std::uint32_t u32;
63+
std::memcpy(&u32, bytes, sizeof value);
64+
u32 = bswap32(u32);
65+
std::memcpy(&value, &u32, sizeof value);
66+
#else
67+
#error No implementation for loading 32-bit little endian unaligned float
68+
#endif
69+
return value;
70+
}
71+
72+
/// Operator +=, emulating normal float behavior
73+
float32& operator+=(float const& other) noexcept {
74+
return *this = *this + other;
75+
}
76+
77+
/// Operator -=, emulating normal float behavior
78+
float32& operator-=(float const& other) noexcept {
79+
return *this = *this - other;
80+
}
81+
82+
/// Operator *=, emulating normal float behavior
83+
float32& operator*=(float const& other) noexcept {
84+
return *this = *this * other;
85+
}
86+
87+
/// Operator /=, emulating normal float behavior
88+
float32& operator/=(float const& other) noexcept {
89+
return *this = *this / other;
90+
}
91+
92+
private:
93+
static std::uint32_t bswap32(std::uint32_t value) {
94+
#ifndef _WIN32
95+
return __builtin_bswap32(value);
96+
#else
97+
return _byteswap_ulong(value);
98+
#endif
99+
}
100+
101+
std::uint8_t bytes[4];
102+
};
103+
104+
/// @brief Reference to a single element in a packed_bit vector.
105+
/// @tparam Iterator Underlying byte iterator type, optionally const.
106+
template <typename Iterator>
107+
class packed_bit_element {
108+
public:
109+
/// Value type chosen to represent a single-bit element
110+
using value_type = bool;
111+
112+
/// Obtain the referenced element's current value
113+
constexpr operator value_type() const {
114+
return ((*byte & mask) == UINT8_C(0)) ? value_type(0) : value_type(1);
115+
}
116+
117+
/// Set the value of the element referenced
118+
packed_bit_element const& operator=(value_type const& v) const {
119+
if (v == 0) {
120+
*byte &= ~mask;
121+
} else {
122+
*byte |= mask;
123+
}
124+
return *this;
125+
}
126+
127+
/// Copy the referenced value from another reference of the same type
128+
packed_bit_element const& operator=(packed_bit_element const& v) const noexcept {
129+
return *this = value_type(v);
130+
}
131+
132+
/// Operator +=, emulating number reference behavior
133+
packed_bit_element const& operator+=(value_type const& other) const noexcept {
134+
return *this = *this + other;
135+
}
136+
137+
/// Operator -=, emulating number reference behavior
138+
packed_bit_element const& operator-=(value_type const& other) const noexcept {
139+
return *this = *this - other;
140+
}
141+
142+
/// Operator *=, emulating number reference behavior
143+
packed_bit_element const& operator*=(value_type const& other) const noexcept {
144+
return *this = *this * other;
145+
}
146+
147+
/// Operator /=, emulating number reference behavior
148+
packed_bit_element const& operator/=(value_type const& other) const noexcept {
149+
return *this = *this / other;
150+
}
151+
152+
/// Operator %=, emulating number reference behavior
153+
packed_bit_element const& operator%=(value_type const& other) const noexcept {
154+
return *this = *this % other;
155+
}
156+
157+
/// Operator ^=, emulating number reference behavior
158+
packed_bit_element const& operator^=(value_type const& other) const noexcept {
159+
return *this = *this ^ other;
160+
}
161+
162+
/// Operator &=, emulating number reference behavior
163+
packed_bit_element const& operator&=(value_type const& other) const noexcept {
164+
return *this = *this & other;
165+
}
166+
167+
/// Operator |=, emulating number reference behavior
168+
packed_bit_element const& operator|=(value_type const& other) const noexcept {
169+
return *this = *this | other;
170+
}
171+
172+
constexpr packed_bit_element(packed_bit_element const& other) : byte(other.byte), mask(other.mask) {}
173+
174+
private:
175+
friend class iterators::packed_bit_element<Iterator>;
176+
177+
constexpr packed_bit_element(Iterator byte_iter, uint8_t bit_index) noexcept
178+
: byte(byte_iter), mask(uint8_t(0x80u >> bit_index)) {}
179+
180+
Iterator byte;
181+
std::uint8_t mask;
182+
};
183+
184+
/// packed_bit_element is Swappable even when it's not an lvalue reference
185+
template <typename Iterator>
186+
void swap(packed_bit_element<Iterator> a, packed_bit_element<Iterator> b) noexcept {
187+
bool a_value = a;
188+
bool b_value = b;
189+
a = b_value;
190+
b = a_value;
191+
}
192+
193+
/// @brief Reference to a byte or partial byte within a vector of packed_bit elements.
194+
/// Allows access to each byte as a uint8_t, while masking off writes to reserved bits.
195+
/// @tparam Iterator Underlying byte iterator type, optionally const.
196+
template <typename Iterator>
197+
class packed_bit_byte {
198+
public:
199+
/// @brief Read the entire byte, as a std::uint8_t.
200+
constexpr operator std::uint8_t() const noexcept {
201+
return *byte;
202+
}
203+
204+
/// @brief Overwrite the usable portion of the byte, and set reserved bits to zero.
205+
/// @param v Byte to write. Reserved bits are ignored.
206+
/// @return *this
207+
packed_bit_byte const& operator=(std::uint8_t const& v) const noexcept {
208+
*byte = v & mask;
209+
return *this;
210+
}
211+
212+
/// Copy the referenced value from another reference of the same type
213+
packed_bit_byte const& operator=(packed_bit_byte const& v) const noexcept {
214+
return *this = std::uint8_t(v);
215+
}
216+
217+
/// Operator +=, emulating number reference behavior
218+
packed_bit_byte const& operator+=(std::uint8_t const& other) const noexcept {
219+
return *this = *this + other;
220+
}
221+
222+
/// Operator -=, emulating number reference behavior
223+
packed_bit_byte const& operator-=(std::uint8_t const& other) const noexcept {
224+
return *this = *this - other;
225+
}
226+
227+
/// Operator *=, emulating number reference behavior
228+
packed_bit_byte const& operator*=(std::uint8_t const& other) const noexcept {
229+
return *this = *this * other;
230+
}
231+
232+
/// Operator /=, emulating number reference behavior
233+
packed_bit_byte const& operator/=(std::uint8_t const& other) const noexcept {
234+
return *this = *this / other;
235+
}
236+
237+
/// Operator %=, emulating number reference behavior
238+
packed_bit_byte const& operator%=(std::uint8_t const& other) const noexcept {
239+
return *this = *this % other;
240+
}
241+
242+
/// Operator ^=, emulating number reference behavior
243+
packed_bit_byte const& operator^=(std::uint8_t const& other) const noexcept {
244+
return *this = *this ^ other;
245+
}
246+
247+
/// Operator &=, emulating number reference behavior
248+
packed_bit_byte const& operator&=(std::uint8_t const& other) const noexcept {
249+
return *this = *this & other;
250+
}
251+
252+
/// Operator |=, emulating number reference behavior
253+
packed_bit_byte const& operator|=(std::uint8_t const& other) const noexcept {
254+
return *this = *this | other;
255+
}
256+
257+
constexpr packed_bit_byte(packed_bit_byte const& other) : byte(other.byte), mask(other.mask) {}
258+
259+
private:
260+
friend class iterators::packed_bit_byte<Iterator>;
261+
262+
constexpr packed_bit_byte(Iterator byte_iter, uint8_t byte_mask) noexcept : byte(byte_iter), mask(byte_mask) {}
263+
264+
Iterator byte;
265+
std::uint8_t mask;
266+
};
267+
268+
/// packed_bit_byte is Swappable even when it's not an lvalue reference
269+
template <typename Iterator>
270+
void swap(packed_bit_byte<Iterator> a, packed_bit_byte<Iterator> b) noexcept {
271+
std::uint8_t a_value = a;
272+
std::uint8_t b_value = b;
273+
a = b_value;
274+
b = a_value;
275+
}
276+
277+
} // namespace elements
278+
} // namespace vector
279+
} // namespace v_noabi
280+
} // namespace bsoncxx
281+
282+
#include <bsoncxx/config/postlude.hpp>
283+
284+
///
285+
/// @file
286+
/// Special purpose element reference types for BSON Binary Vector access
287+
///
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2009-present 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+
namespace bsoncxx {
20+
namespace v_noabi {
21+
namespace vector {
22+
namespace formats {
23+
24+
struct f_float32;
25+
struct f_int8;
26+
struct f_packed_bit;
27+
28+
} // namespace formats
29+
} // namespace vector
30+
} // namespace v_noabi
31+
} // namespace bsoncxx
32+
33+
namespace bsoncxx {
34+
namespace vector {
35+
namespace formats {
36+
37+
using ::bsoncxx::v_noabi::vector::formats::f_float32;
38+
using ::bsoncxx::v_noabi::vector::formats::f_int8;
39+
using ::bsoncxx::v_noabi::vector::formats::f_packed_bit;
40+
41+
} // namespace formats
42+
} // namespace vector
43+
} // namespace bsoncxx
44+
45+
#include <bsoncxx/config/postlude.hpp>
46+
47+
///
48+
/// @file
49+
/// Declares vector formats:
50+
/// @ref bsoncxx::vector::formats::f_float32
51+
/// @ref bsoncxx::vector::formats::f_int8
52+
/// @ref bsoncxx::vector::formats::f_packed_bit
53+
///
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2009-present 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/vector/formats-fwd.hpp>
18+
19+
#include <bsoncxx/config/prelude.hpp>
20+
21+
namespace bsoncxx {
22+
namespace v_noabi {
23+
namespace vector {
24+
namespace formats {
25+
26+
/// @brief Vector format for 32-bit floating point elements, packed least significant byte first.
27+
struct f_float32 {};
28+
29+
/// @brief Vector format for signed 8-bit integer elements.
30+
struct f_int8 {};
31+
32+
/// @brief Vector format for single bit elements, packed most significant bit first.
33+
struct f_packed_bit {};
34+
35+
} // namespace formats
36+
} // namespace vector
37+
} // namespace v_noabi
38+
} // namespace bsoncxx
39+
40+
#include <bsoncxx/config/postlude.hpp>
41+
42+
///
43+
/// @file
44+
/// Declares vector formats:
45+
/// @ref bsoncxx::v_noabi::vector::formats::f_float32
46+
/// @ref bsoncxx::v_noabi::vector::formats::f_int8
47+
/// @ref bsoncxx::v_noabi::vector::formats::f_packed_bit
48+
///

0 commit comments

Comments
 (0)