Merge commit 'babbda98a6ea1d53a8bc5015ef5dfb313c47186a' into libosmium-2.10.0
This commit is contained in:
+56
-26
@@ -113,6 +113,9 @@ namespace osmium {
|
||||
size_t m_capacity;
|
||||
size_t m_written;
|
||||
size_t m_committed;
|
||||
#ifndef NDEBUG
|
||||
uint8_t m_builder_count{0};
|
||||
#endif
|
||||
auto_grow m_auto_grow {auto_grow::no};
|
||||
std::function<void(Buffer&)> m_full;
|
||||
|
||||
@@ -216,13 +219,28 @@ namespace osmium {
|
||||
|
||||
~Buffer() = default;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void increment_builder_count() noexcept {
|
||||
++m_builder_count;
|
||||
}
|
||||
|
||||
void decrement_builder_count() noexcept {
|
||||
assert(m_builder_count > 0);
|
||||
--m_builder_count;
|
||||
}
|
||||
|
||||
uint8_t builder_count() const noexcept {
|
||||
return m_builder_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return a pointer to data inside the buffer.
|
||||
*
|
||||
* @pre The buffer must be valid.
|
||||
*/
|
||||
unsigned char* data() const noexcept {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return m_data;
|
||||
}
|
||||
|
||||
@@ -258,7 +276,7 @@ namespace osmium {
|
||||
* @pre The buffer must be valid.
|
||||
*/
|
||||
bool is_aligned() const noexcept {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return (m_written % align_bytes == 0) && (m_committed % align_bytes == 0);
|
||||
}
|
||||
|
||||
@@ -283,7 +301,7 @@ namespace osmium {
|
||||
* than the difference between committed() and capacity().
|
||||
*/
|
||||
OSMIUM_DEPRECATED void set_full_callback(std::function<void(Buffer&)> full) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
m_full = full;
|
||||
}
|
||||
|
||||
@@ -292,7 +310,6 @@ namespace osmium {
|
||||
* This works only with internally memory-managed buffers.
|
||||
* If the given size is not larger than the current capacity,
|
||||
* nothing is done.
|
||||
* Already written but not committed data is discarded.
|
||||
*
|
||||
* @pre The buffer must be valid.
|
||||
*
|
||||
@@ -305,7 +322,7 @@ namespace osmium {
|
||||
* @throws std::bad_alloc if there isn't enough memory available.
|
||||
*/
|
||||
void grow(size_t size) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
if (!m_memory) {
|
||||
throw std::logic_error("Can't grow Buffer if it doesn't use internal memory management.");
|
||||
}
|
||||
@@ -325,15 +342,18 @@ namespace osmium {
|
||||
/**
|
||||
* Mark currently written bytes in the buffer as committed.
|
||||
*
|
||||
* @pre The buffer must be valid and aligned properly (as indicated
|
||||
* @pre The buffer must be valid.
|
||||
* @pre The buffer must be aligned properly (as indicated
|
||||
* by is_aligned().
|
||||
* @pre No builder can be open on this buffer.
|
||||
*
|
||||
* @returns Number of committed bytes before this commit. Can be
|
||||
* used as an offset into the buffer to get to the
|
||||
* object being committed by this call.
|
||||
*/
|
||||
size_t commit() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||
assert(is_aligned());
|
||||
|
||||
const size_t offset = m_committed;
|
||||
@@ -345,9 +365,11 @@ namespace osmium {
|
||||
* Roll back changes in buffer to last committed state.
|
||||
*
|
||||
* @pre The buffer must be valid.
|
||||
* @pre No builder can be open on this buffer.
|
||||
*/
|
||||
void rollback() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||
m_written = m_committed;
|
||||
}
|
||||
|
||||
@@ -356,9 +378,12 @@ namespace osmium {
|
||||
*
|
||||
* No-op on an invalid buffer.
|
||||
*
|
||||
* @pre No builder can be open on this buffer.
|
||||
*
|
||||
* @returns Number of bytes in the buffer before it was cleared.
|
||||
*/
|
||||
size_t clear() {
|
||||
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||
const size_t committed = m_committed;
|
||||
m_written = 0;
|
||||
m_committed = 0;
|
||||
@@ -377,7 +402,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename T>
|
||||
T& get(const size_t offset) const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return *reinterpret_cast<T*>(&m_data[offset]);
|
||||
}
|
||||
|
||||
@@ -415,7 +440,7 @@ namespace osmium {
|
||||
* no callback defined and the buffer isn't auto-growing.
|
||||
*/
|
||||
unsigned char* reserve_space(const size_t size) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
// try to flush the buffer empty first.
|
||||
if (m_written + size > m_capacity && m_full) {
|
||||
m_full(*this);
|
||||
@@ -455,7 +480,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename T>
|
||||
T& add_item(const T& item) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
unsigned char* target = reserve_space(item.padded_size());
|
||||
std::copy_n(reinterpret_cast<const unsigned char*>(&item), item.padded_size(), target);
|
||||
return *reinterpret_cast<T*>(target);
|
||||
@@ -465,6 +490,7 @@ namespace osmium {
|
||||
* Add committed contents of the given buffer to this buffer.
|
||||
*
|
||||
* @pre The buffer must be valid.
|
||||
* @pre No builder can be open on this buffer.
|
||||
*
|
||||
* Note that you have to eventually call commit() to actually
|
||||
* commit this data.
|
||||
@@ -472,7 +498,9 @@ namespace osmium {
|
||||
* @param buffer The source of the copy. Must be valid.
|
||||
*/
|
||||
void add_buffer(const Buffer& buffer) {
|
||||
assert(m_data && buffer);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
assert(buffer && "Buffer parameter must be a valid buffer");
|
||||
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||
unsigned char* target = reserve_space(buffer.committed());
|
||||
std::copy_n(buffer.data(), buffer.committed(), target);
|
||||
}
|
||||
@@ -482,11 +510,13 @@ namespace osmium {
|
||||
* you can use std::back_inserter.
|
||||
*
|
||||
* @pre The buffer must be valid.
|
||||
* @pre No builder can be open on this buffer.
|
||||
*
|
||||
* @param item The item to be added.
|
||||
*/
|
||||
void push_back(const osmium::memory::Item& item) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
assert(m_builder_count == 0 && "Make sure there are no Builder objects still in scope");
|
||||
add_item(item);
|
||||
commit();
|
||||
}
|
||||
@@ -537,7 +567,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename T>
|
||||
t_iterator<T> begin() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_iterator<T>(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -550,7 +580,7 @@ namespace osmium {
|
||||
* @returns Iterator to first OSMEntity in the buffer.
|
||||
*/
|
||||
iterator begin() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return iterator(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -565,7 +595,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename T>
|
||||
t_iterator<T> get_iterator(size_t offset) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_iterator<T>(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -579,7 +609,7 @@ namespace osmium {
|
||||
* buffer.
|
||||
*/
|
||||
iterator get_iterator(size_t offset) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return iterator(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -593,7 +623,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename T>
|
||||
t_iterator<T> end() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -606,40 +636,40 @@ namespace osmium {
|
||||
* @returns End iterator.
|
||||
*/
|
||||
iterator end() {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return iterator(m_data + m_committed, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
t_const_iterator<T> cbegin() const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_const_iterator<T>(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return const_iterator(m_data, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
t_const_iterator<T> get_iterator(size_t offset) const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_const_iterator<T>(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
const_iterator get_iterator(size_t offset) const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return const_iterator(m_data + offset, m_data + m_committed);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
t_const_iterator<T> cend() const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return t_const_iterator<T>(m_data + m_committed, m_data + m_committed);
|
||||
}
|
||||
|
||||
const_iterator cend() const {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
return const_iterator(m_data + m_committed, m_data + m_committed);
|
||||
}
|
||||
|
||||
@@ -698,7 +728,7 @@ namespace osmium {
|
||||
*/
|
||||
template <typename TCallbackClass>
|
||||
void purge_removed(TCallbackClass* callback) {
|
||||
assert(m_data);
|
||||
assert(m_data && "This must be a valid buffer");
|
||||
if (begin() == end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
+32
-15
@@ -46,9 +46,9 @@ namespace osmium {
|
||||
template <typename TMember>
|
||||
class CollectionIterator {
|
||||
|
||||
// This data_type is either 'unsigned char*' or 'const unsigned char*' depending
|
||||
// on whether TMember is const. This allows this class to be used as an iterator and
|
||||
// as a const_iterator.
|
||||
// This data_type is either 'unsigned char*' or 'const unsigned
|
||||
// char*' depending on whether TMember is const. This allows this
|
||||
// class to be used as an iterator and as a const_iterator.
|
||||
using data_type = typename std::conditional<std::is_const<TMember>::value, const unsigned char*, unsigned char*>::type;
|
||||
|
||||
data_type m_data;
|
||||
@@ -92,11 +92,11 @@ namespace osmium {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
TMember& operator*() const {
|
||||
TMember& operator*() const noexcept {
|
||||
return *reinterpret_cast<TMember*>(m_data);
|
||||
}
|
||||
|
||||
TMember* operator->() const {
|
||||
TMember* operator->() const noexcept {
|
||||
return reinterpret_cast<TMember*>(m_data);
|
||||
}
|
||||
|
||||
@@ -118,9 +118,12 @@ namespace osmium {
|
||||
|
||||
public:
|
||||
|
||||
using iterator = CollectionIterator<TMember>;
|
||||
using const_iterator = CollectionIterator<const TMember>;
|
||||
using value_type = TMember;
|
||||
using value_type = TMember;
|
||||
using reference = TMember&;
|
||||
using const_reference = const TMember&;
|
||||
using iterator = CollectionIterator<TMember>;
|
||||
using const_iterator = CollectionIterator<const TMember>;
|
||||
using size_type = size_t;
|
||||
|
||||
static constexpr osmium::item_type itemtype = TCollectionItemType;
|
||||
|
||||
@@ -128,31 +131,45 @@ namespace osmium {
|
||||
Item(sizeof(Collection<TMember, TCollectionItemType>), TCollectionItemType) {
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
/**
|
||||
* Does this collection contain any items?
|
||||
*
|
||||
* Complexity: Constant.
|
||||
*/
|
||||
bool empty() const noexcept {
|
||||
return sizeof(Collection<TMember, TCollectionItemType>) == byte_size();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
/**
|
||||
* Returns the number of items in this collection.
|
||||
*
|
||||
* Complexity: Linear in the number of items.
|
||||
*/
|
||||
size_type size() const noexcept {
|
||||
return static_cast<size_type>(std::distance(begin(), end()));
|
||||
}
|
||||
|
||||
iterator begin() noexcept {
|
||||
return iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
iterator end() noexcept {
|
||||
return iterator(data() + byte_size());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const {
|
||||
const_iterator cbegin() const noexcept {
|
||||
return const_iterator(data() + sizeof(Collection<TMember, TCollectionItemType>));
|
||||
}
|
||||
|
||||
const_iterator cend() const {
|
||||
const_iterator cend() const noexcept {
|
||||
return const_iterator(data() + byte_size());
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
const_iterator begin() const noexcept {
|
||||
return cbegin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
const_iterator end() const noexcept {
|
||||
return cend();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -59,9 +59,9 @@ namespace osmium {
|
||||
using item_size_type = uint32_t;
|
||||
|
||||
// align datastructures to this many bytes
|
||||
constexpr item_size_type align_bytes = 8;
|
||||
constexpr const item_size_type align_bytes = 8;
|
||||
|
||||
inline std::size_t padded_length(std::size_t length) noexcept {
|
||||
inline constexpr std::size_t padded_length(std::size_t length) noexcept {
|
||||
return (length + align_bytes - 1) & ~(align_bytes - 1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user