1 #ifndef OSMIUM_MEMORY_BUFFER_HPP 2 #define OSMIUM_MEMORY_BUFFER_HPP 61 std::runtime_error{
"Osmium buffer is full"} {
113 std::unique_ptr<unsigned char[]> m_memory{};
114 unsigned char* m_data =
nullptr;
115 std::size_t m_capacity = 0;
116 std::size_t m_written = 0;
117 std::size_t m_committed = 0;
119 uint8_t m_builder_count = 0;
130 if (capacity < min_capacity) {
137 assert(m_data &&
"This must be a valid buffer");
139 throw std::logic_error{
"Can't grow Buffer if it doesn't use internal memory management."};
142 std::unique_ptr<Buffer> old{
new Buffer{std::move(m_memory), m_capacity, m_committed}};
143 m_memory = std::unique_ptr<unsigned char[]>{
new unsigned char[m_capacity]};
144 m_data = m_memory.
get();
146 m_written -= m_committed;
147 std::copy_n(old->data() + m_committed, m_written, m_data);
150 old->m_next_buffer = std::move(m_next_buffer);
151 m_next_buffer = std::move(old);
178 explicit Buffer(
unsigned char* data, std::size_t size) :
185 throw std::invalid_argument{
"buffer size needs to be multiple of alignment"};
201 explicit Buffer(
unsigned char* data, std::size_t capacity, std::size_t committed) :
204 m_capacity(capacity),
205 m_written(committed),
206 m_committed(committed) {
208 throw std::invalid_argument{
"buffer capacity needs to be multiple of alignment"};
211 throw std::invalid_argument{
"buffer parameter 'committed' needs to be multiple of alignment"};
213 if (committed > capacity) {
214 throw std::invalid_argument{
"buffer parameter 'committed' can not be larger than capacity"};
231 explicit Buffer(std::unique_ptr<
unsigned char[]> data, std::size_t capacity, std::size_t committed) :
233 m_memory(
std::move(data)),
234 m_data(m_memory.get()),
235 m_capacity(capacity),
236 m_written(committed),
237 m_committed(committed) {
239 throw std::invalid_argument{
"buffer capacity needs to be multiple of alignment"};
242 throw std::invalid_argument{
"buffer parameter 'committed' needs to be multiple of alignment"};
244 if (committed > capacity) {
245 throw std::invalid_argument{
"buffer parameter 'committed' can not be larger than capacity"};
263 m_memory(new unsigned char[calculate_capacity(capacity)]),
264 m_data(m_memory.get()),
265 m_capacity(calculate_capacity(capacity)),
275 m_next_buffer(std::move(other.m_next_buffer)),
276 m_memory(std::move(other.m_memory)),
277 m_data(other.m_data),
278 m_capacity(other.m_capacity),
279 m_written(other.m_written),
280 m_committed(other.m_committed),
282 m_builder_count(other.m_builder_count),
284 m_auto_grow(other.m_auto_grow),
285 m_full(std::move(other.m_full)) {
286 other.m_data =
nullptr;
287 other.m_capacity = 0;
289 other.m_committed = 0;
291 other.m_builder_count = 0;
296 m_next_buffer = std::move(other.m_next_buffer);
297 m_memory = std::move(other.m_memory);
298 m_data = other.m_data;
299 m_capacity = other.m_capacity;
300 m_written = other.m_written;
301 m_committed = other.m_committed;
303 m_builder_count = other.m_builder_count;
305 m_auto_grow = other.m_auto_grow;
306 m_full = std::move(other.m_full);
307 other.m_data =
nullptr;
308 other.m_capacity = 0;
310 other.m_committed = 0;
312 other.m_builder_count = 0;
317 ~
Buffer() noexcept =
default;
325 assert(m_builder_count > 0);
330 return m_builder_count;
339 unsigned char*
data() const noexcept {
340 assert(m_data &&
"This must be a valid buffer");
376 assert(m_data &&
"This must be a valid buffer");
396 assert(m_data &&
"This must be a valid buffer");
416 assert(m_data &&
"This must be a valid buffer");
418 throw std::logic_error{
"Can't grow Buffer if it doesn't use internal memory management."};
420 size = calculate_capacity(size);
421 if (m_capacity < size) {
422 std::unique_ptr<unsigned char[]> memory{
new unsigned char[size]};
423 std::copy_n(m_memory.get(), m_capacity, memory.get());
425 swap(m_memory, memory);
426 m_data = m_memory.get();
438 return m_next_buffer !=
nullptr;
448 assert(has_nested_buffers());
469 assert(m_data &&
"This must be a valid buffer");
470 assert(m_builder_count == 0 &&
"Make sure there are no Builder objects still in scope");
471 assert(is_aligned());
473 const std::size_t offset = m_committed;
474 m_committed = m_written;
485 assert(m_data &&
"This must be a valid buffer");
486 assert(m_builder_count == 0 &&
"Make sure there are no Builder objects still in scope");
487 m_written = m_committed;
500 assert(m_builder_count == 0 &&
"Make sure there are no Builder objects still in scope");
501 const std::size_t committed = m_committed;
517 template <
typename T>
518 T&
get(
const std::size_t offset)
const {
519 assert(m_data &&
"This must be a valid buffer");
520 assert(offset %
alignof(T) == 0 &&
"Wrong alignment");
521 return *
reinterpret_cast<T*
>(&m_data[offset]);
558 assert(m_data &&
"This must be a valid buffer");
560 if (m_written + size > m_capacity && m_full) {
564 if (m_written + size > m_capacity) {
565 if (!m_memory || m_auto_grow == auto_grow::no) {
568 if (m_auto_grow == auto_grow::internal && m_committed != 0) {
571 if (m_written + size > m_capacity) {
573 std::size_t new_capacity = m_capacity * 2;
574 while (m_written + size > new_capacity) {
580 unsigned char* data = &m_data[m_written];
600 template <
typename T>
602 assert(m_data &&
"This must be a valid buffer");
603 unsigned char* target = reserve_space(item.padded_size());
604 std::copy_n(reinterpret_cast<const unsigned char*>(&item), item.padded_size(), target);
605 return *
reinterpret_cast<T*
>(target);
620 assert(m_data &&
"This must be a valid buffer");
621 assert(buffer &&
"Buffer parameter must be a valid buffer");
622 assert(m_builder_count == 0 &&
"Make sure there are no Builder objects still in scope");
623 unsigned char* target = reserve_space(buffer.
committed());
637 assert(m_data &&
"This must be a valid buffer");
638 assert(m_builder_count == 0 &&
"Make sure there are no Builder objects still in scope");
647 template <
typename T>
654 template <
typename T>
669 template <
typename T>
674 template <
typename T>
687 template <
typename T>
689 assert(m_data &&
"This must be a valid buffer");
702 assert(m_data &&
"This must be a valid buffer");
703 return {m_data, m_data + m_committed};
715 template <
typename T>
717 assert(m_data &&
"This must be a valid buffer");
718 assert(offset %
alignof(T) == 0 &&
"Wrong alignment");
719 return {m_data + offset, m_data + m_committed};
732 assert(m_data &&
"This must be a valid buffer");
733 assert(offset %
alignof(
OSMEntity) == 0 &&
"Wrong alignment");
734 return {m_data + offset, m_data + m_committed};
745 template <
typename T>
747 assert(m_data &&
"This must be a valid buffer");
748 return {m_data + m_committed, m_data + m_committed};
760 assert(m_data &&
"This must be a valid buffer");
761 return {m_data + m_committed, m_data + m_committed};
764 template <
typename T>
766 assert(m_data &&
"This must be a valid buffer");
767 return {m_data, m_data + m_committed};
771 assert(m_data &&
"This must be a valid buffer");
772 return {m_data, m_data + m_committed};
775 template <
typename T>
777 assert(m_data &&
"This must be a valid buffer");
778 assert(offset %
alignof(T) == 0 &&
"Wrong alignment");
779 return {m_data + offset, m_data + m_committed};
783 assert(m_data &&
"This must be a valid buffer");
784 assert(offset %
alignof(
OSMEntity) == 0 &&
"Wrong alignment");
785 return {m_data + offset, m_data + m_committed};
788 template <
typename T>
790 assert(m_data &&
"This must be a valid buffer");
791 return {m_data + m_committed, m_data + m_committed};
795 assert(m_data &&
"This must be a valid buffer");
796 return {m_data + m_committed, m_data + m_committed};
799 template <
typename T>
808 template <
typename T>
820 explicit operator bool() const noexcept {
821 return m_data !=
nullptr;
853 template <
typename TCallbackClass>
855 assert(m_data &&
"This must be a valid buffer");
864 next = std::next(it_read);
865 if (!it_read->removed()) {
866 if (it_read != it_write) {
867 assert(it_read.data() >= data());
868 assert(it_write.
data() >= data());
869 const auto old_offset =
static_cast<std::size_t
>(it_read.data() - data());
870 const auto new_offset =
static_cast<std::size_t
>(it_write.
data() - data());
871 callback->moving_in_buffer(old_offset, new_offset);
872 std::memmove(it_write.
data(), it_read.data(), it_read->padded_size());
878 assert(it_write.
data() >= data());
879 m_written =
static_cast<std::size_t
>(it_write.
data() - data());
880 m_committed = m_written;
900 return lhs.data() == rhs.data() && lhs.capacity() == rhs.capacity() && lhs.committed() == rhs.committed();
904 return !(lhs == rhs);
911 #endif // OSMIUM_MEMORY_BUFFER_HPP Buffer(Buffer &&other) noexcept
Definition: buffer.hpp:274
void swap(Buffer &other)
Definition: buffer.hpp:824
std::size_t capacity() const noexcept
Definition: buffer.hpp:348
t_const_iterator< T > begin() const
Definition: buffer.hpp:800
std::size_t commit()
Definition: buffer.hpp:468
#define OSMIUM_DEPRECATED
Definition: compatibility.hpp:50
bool is_aligned() const noexcept
Definition: buffer.hpp:375
iterator get_iterator(std::size_t offset)
Definition: buffer.hpp:731
Definition: item_iterator.hpp:175
void grow_internal()
Definition: buffer.hpp:136
t_const_iterator< T > cend() const
Definition: buffer.hpp:789
const_iterator cend() const
Definition: buffer.hpp:794
Definition: item_iterator.hpp:59
OSMIUM_DEPRECATED void set_full_callback(const std::function< void(Buffer &)> &full)
Definition: buffer.hpp:395
constexpr bool operator==(const Box &lhs, const Box &rhs) noexcept
Definition: box.hpp:212
unsigned char * m_data
Definition: buffer.hpp:114
InputIterator< Reader > end(Reader &)
Definition: reader_iterator.hpp:47
std::size_t m_committed
Definition: buffer.hpp:117
void increment_builder_count() noexcept
Definition: buffer.hpp:320
Definition: location.hpp:550
ItemIteratorRange< const T > select() const
Definition: buffer.hpp:675
OSMEntity is the abstract base class for the OSMObject and Changeset classes.
Definition: entity.hpp:64
void swap(Buffer &lhs, Buffer &rhs)
Definition: buffer.hpp:885
t_const_iterator< T > get_iterator(std::size_t offset) const
Definition: buffer.hpp:776
std::size_t clear()
Definition: buffer.hpp:499
static std::size_t calculate_capacity(std::size_t capacity) noexcept
Definition: buffer.hpp:124
constexpr std::size_t padded_length(std::size_t length) noexcept
Definition: item.hpp:64
std::size_t committed() const noexcept
Definition: buffer.hpp:356
std::unique_ptr< Buffer > m_next_buffer
Definition: buffer.hpp:112
Buffer(std::size_t capacity, auto_grow auto_grow=auto_grow::yes)
Definition: buffer.hpp:261
const_iterator begin() const
Definition: buffer.hpp:804
InputIterator< Reader > begin(Reader &reader)
Definition: reader_iterator.hpp:43
std::size_t m_capacity
Definition: buffer.hpp:115
t_iterator< T > end()
Definition: buffer.hpp:746
auto_grow
Definition: buffer.hpp:104
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
T & add_item(const T &item)
Definition: buffer.hpp:601
void purge_removed(TCallbackClass *callback)
Definition: buffer.hpp:854
t_iterator< T > begin()
Definition: buffer.hpp:688
void add_buffer(const Buffer &buffer)
Definition: buffer.hpp:619
T & get(const std::size_t offset) const
Definition: buffer.hpp:518
std::size_t written() const noexcept
Definition: buffer.hpp:365
uint8_t builder_count() const noexcept
Definition: buffer.hpp:329
Buffer(unsigned char *data, std::size_t capacity, std::size_t committed)
Definition: buffer.hpp:201
Buffer(unsigned char *data, std::size_t size)
Definition: buffer.hpp:178
std::size_t m_written
Definition: buffer.hpp:116
ItemIterator< TMember > & advance_once() noexcept
Definition: item_iterator.hpp:114
unsigned char * data() const noexcept
Definition: buffer.hpp:339
Buffer() noexcept
Definition: buffer.hpp:164
void grow(std::size_t size)
Definition: buffer.hpp:415
unsigned char * reserve_space(const std::size_t size)
Definition: buffer.hpp:557
auto_grow m_auto_grow
Definition: buffer.hpp:121
void push_back(const osmium::memory::Item &item)
Definition: buffer.hpp:636
Buffer(std::unique_ptr< unsigned char[]> data, std::size_t capacity, std::size_t committed)
Definition: buffer.hpp:231
iterator end()
Definition: buffer.hpp:759
iterator begin()
Definition: buffer.hpp:701
bool has_nested_buffers() const noexcept
Definition: buffer.hpp:437
const_iterator get_iterator(std::size_t offset) const
Definition: buffer.hpp:782
Definition: buffer.hpp:97
Buffer & operator=(Buffer &&other) noexcept
Definition: buffer.hpp:295
t_const_iterator< T > cbegin() const
Definition: buffer.hpp:765
Definition: buffer.hpp:58
void decrement_builder_count() noexcept
Definition: buffer.hpp:324
const_iterator end() const
Definition: buffer.hpp:813
t_const_iterator< T > end() const
Definition: buffer.hpp:809
data_type data() noexcept
Definition: item_iterator.hpp:135
t_iterator< T > get_iterator(std::size_t offset)
Definition: buffer.hpp:716
buffer_is_full()
Definition: buffer.hpp:60
ItemIteratorRange< T > select()
Definition: buffer.hpp:670
void rollback()
Definition: buffer.hpp:484
std::unique_ptr< unsigned char[]> m_memory
Definition: buffer.hpp:113
bool operator!=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:446
std::unique_ptr< Buffer > get_last_nested()
Definition: buffer.hpp:447
const_iterator cbegin() const
Definition: buffer.hpp:770
std::function< void(Buffer &)> m_full
Definition: buffer.hpp:122