Merge commit '0c6dee4befebf823d839d1092bcae79afbf4f12e' into merge/libosmium-2.11.0
This commit is contained in:
+1
-1
@@ -16,8 +16,8 @@ documentation.
|
||||
* @brief Contains functions to swap bytes in values (for different endianness).
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
|
||||
|
||||
@@ -35,17 +35,6 @@ documentation.
|
||||
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// On some ARM machines and depending on compiler settings access to unaligned
|
||||
// floating point values will result in a SIGBUS. Do not use the bare pointers
|
||||
// in this case.
|
||||
#if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN
|
||||
# if !defined(__arm__) && !defined(_M_ARM)
|
||||
# ifndef PROTOZERO_DO_NOT_USE_BARE_POINTER
|
||||
# define PROTOZERO_USE_BARE_POINTER_FOR_PACKED_FIXED
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Check whether __builtin_bswap is available
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define PROTOZERO_USE_BUILTIN_BSWAP
|
||||
|
||||
@@ -138,25 +138,6 @@ inline void swap(iterator_range<T>& lhs, iterator_range<T>& rhs) noexcept {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#ifdef PROTOZERO_USE_BARE_POINTER_FOR_PACKED_FIXED
|
||||
|
||||
template <typename T>
|
||||
using const_fixed_iterator = const T*;
|
||||
|
||||
/**
|
||||
* Create iterator_range from char pointers to beginning and end of range.
|
||||
*
|
||||
* @param first Beginning of range.
|
||||
* @param last End of range.
|
||||
*/
|
||||
template <typename T>
|
||||
inline iterator_range<const_fixed_iterator<T>> create_fixed_iterator_range(const char* first, const char* last) {
|
||||
return iterator_range<const_fixed_iterator<T>>{reinterpret_cast<const T*>(first),
|
||||
reinterpret_cast<const T*>(last)};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* A forward iterator used for accessing packed repeated fields of fixed
|
||||
* length (fixed32, sfixed32, float, double).
|
||||
@@ -226,20 +207,6 @@ public:
|
||||
|
||||
}; // class const_fixed_iterator
|
||||
|
||||
/**
|
||||
* Create iterator_range from char pointers to beginning and end of range.
|
||||
*
|
||||
* @param first Beginning of range.
|
||||
* @param last End of range.
|
||||
*/
|
||||
template <typename T>
|
||||
inline iterator_range<const_fixed_iterator<T>> create_fixed_iterator_range(const char* first, const char* last) {
|
||||
return iterator_range<const_fixed_iterator<T>>{const_fixed_iterator<T>(first, last),
|
||||
const_fixed_iterator<T>(last, last)};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A forward iterator used for accessing packed repeated varint fields
|
||||
* (int32, uint32, int64, uint64, bool, enum).
|
||||
|
||||
+6
-1
@@ -18,8 +18,8 @@ documentation.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <protozero/types.hpp>
|
||||
#include <protozero/pbf_writer.hpp>
|
||||
#include <protozero/types.hpp>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
@@ -87,6 +87,11 @@ public:
|
||||
pbf_writer::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
void add_bytes_vectored(T tag, Ts&&... values) {
|
||||
pbf_writer::add_bytes_vectored(pbf_tag_type(tag), std::forward<Ts>(values)...);
|
||||
}
|
||||
|
||||
void add_string(T tag, const char* value, std::size_t size) {
|
||||
pbf_writer::add_string(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
+73
-4
@@ -87,7 +87,8 @@ class pbf_reader {
|
||||
protozero_assert(tag() != 0 && "call next() before accessing field value");
|
||||
const auto len = get_len_and_skip();
|
||||
protozero_assert(len % sizeof(T) == 0);
|
||||
return create_fixed_iterator_range<T>(m_data - len, m_data);
|
||||
return iterator_range<const_fixed_iterator<T>>{const_fixed_iterator<T>(m_data - len, m_data),
|
||||
const_fixed_iterator<T>(m_data, m_data)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -178,7 +179,7 @@ public:
|
||||
*
|
||||
* @post There is no current field.
|
||||
*/
|
||||
pbf_reader(std::pair<const char*, std::size_t> data) noexcept
|
||||
pbf_reader(const std::pair<const char*, std::size_t>& data) noexcept
|
||||
: m_data(data.first),
|
||||
m_end(data.first + data.second),
|
||||
m_wire_type(pbf_wire_type::unknown),
|
||||
@@ -320,6 +321,9 @@ public:
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Note that this will not check the wire type. The two-argument version
|
||||
* of this function will also check the wire type.
|
||||
*
|
||||
* @returns `true` if there is a next field with this tag.
|
||||
* @pre There must be no current field.
|
||||
* @post If it returns `true` there is a current field now with the given tag.
|
||||
@@ -335,6 +339,45 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set next field with given tag and wire type in the message as the
|
||||
* current field. Fields with other tags are skipped. This is usually
|
||||
* called in a while loop for repeated fields:
|
||||
*
|
||||
* @code
|
||||
* pbf_reader message(...);
|
||||
* while (message.next(17, pbf_wire_type::varint)) {
|
||||
* // handle field
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* or you can call it just once to get the one field with this tag:
|
||||
*
|
||||
* @code
|
||||
* pbf_reader message(...);
|
||||
* if (message.next(17, pbf_wire_type::varint)) {
|
||||
* // handle field
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Note that this will also check the wire type. The one-argument version
|
||||
* of this function will not check the wire type.
|
||||
*
|
||||
* @returns `true` if there is a next field with this tag.
|
||||
* @pre There must be no current field.
|
||||
* @post If it returns `true` there is a current field now with the given tag.
|
||||
*/
|
||||
bool next(pbf_tag_type next_tag, pbf_wire_type wire_type) {
|
||||
while (next()) {
|
||||
if (m_tag == next_tag && m_wire_type == wire_type) {
|
||||
return true;
|
||||
} else {
|
||||
skip();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag of the current field. The tag is the field number from the
|
||||
* description in the .proto file.
|
||||
@@ -367,6 +410,32 @@ public:
|
||||
return m_wire_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag and wire type of the current field in one integer suitable
|
||||
* for comparison with a switch statement.
|
||||
*
|
||||
* Use it like this:
|
||||
*
|
||||
* @code
|
||||
* pbf_reader message(...);
|
||||
* while (message.next()) {
|
||||
* switch (message.tag_and_type()) {
|
||||
* case tag_and_type(17, pbf_wire_type::length_delimited):
|
||||
* ....
|
||||
* break;
|
||||
* case tag_and_type(21, pbf_wire_type::varint):
|
||||
* ....
|
||||
* break;
|
||||
* default:
|
||||
* message.skip();
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
uint32_t tag_and_type() const noexcept {
|
||||
return protozero::tag_and_type(tag(), wire_type());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the wire type of the current field.
|
||||
*
|
||||
@@ -598,7 +667,7 @@ public:
|
||||
protozero_assert(tag() != 0 && "call next() before accessing field value");
|
||||
protozero_assert(has_wire_type(pbf_wire_type::length_delimited) && "not of type string, bytes or message");
|
||||
const auto len = get_len_and_skip();
|
||||
return data_view{m_data-len, len};
|
||||
return data_view{m_data - len, len};
|
||||
}
|
||||
|
||||
#ifndef PROTOZERO_STRICT_API
|
||||
@@ -614,7 +683,7 @@ public:
|
||||
protozero_assert(tag() != 0 && "call next() before accessing field value");
|
||||
protozero_assert(has_wire_type(pbf_wire_type::length_delimited) && "not of type string, bytes or message");
|
||||
const auto len = get_len_and_skip();
|
||||
return std::make_pair(m_data-len, len);
|
||||
return std::make_pair(m_data - len, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+52
-14
@@ -226,8 +226,7 @@ public:
|
||||
*/
|
||||
explicit pbf_writer(std::string& data) noexcept :
|
||||
m_data(&data),
|
||||
m_parent_writer(nullptr),
|
||||
m_pos(0) {
|
||||
m_parent_writer(nullptr) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,8 +235,7 @@ public:
|
||||
*/
|
||||
pbf_writer() noexcept :
|
||||
m_data(nullptr),
|
||||
m_parent_writer(nullptr),
|
||||
m_pos(0) {
|
||||
m_parent_writer(nullptr) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,8 +250,7 @@ public:
|
||||
*/
|
||||
pbf_writer(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size=0) :
|
||||
m_data(parent_writer.m_data),
|
||||
m_parent_writer(&parent_writer),
|
||||
m_pos(0) {
|
||||
m_parent_writer(&parent_writer) {
|
||||
m_parent_writer->open_submessage(tag, size);
|
||||
}
|
||||
|
||||
@@ -504,6 +501,37 @@ public:
|
||||
add_bytes(tag, value.data(), value.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data using vectored input. All the data in the
|
||||
* 2nd and further arguments is "concatenated" with only a single copy
|
||||
* into the final buffer.
|
||||
*
|
||||
* This will work with objects of any type supporting the data() and
|
||||
* size() methods like std::string or protozero::data_view.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* std::string data1 = "abc";
|
||||
* std::string data2 = "xyz";
|
||||
* writer.add_bytes_vectored(1, data1, data2);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam Ts List of types supporting data() and size() methods.
|
||||
* @param tag Tag (field number) of the field
|
||||
* @param values List of objects of types Ts with data to be appended.
|
||||
*/
|
||||
template <typename... Ts>
|
||||
void add_bytes_vectored(pbf_tag_type tag, Ts&&... values) {
|
||||
protozero_assert(m_pos == 0 && "you can't add fields to a parent pbf_writer if there is an existing pbf_writer for a submessage");
|
||||
protozero_assert(m_data);
|
||||
size_t sum_size = 0;
|
||||
(void)std::initializer_list<size_t>{sum_size += values.size()...};
|
||||
protozero_assert(sum_size <= std::numeric_limits<pbf_length_type>::max());
|
||||
add_length_varint(tag, pbf_length_type(sum_size));
|
||||
m_data->reserve(m_data->size() + sum_size);
|
||||
(void)std::initializer_list<int>{(m_data->append(values.data(), values.size()), 0)...};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
@@ -814,6 +842,12 @@ namespace detail {
|
||||
|
||||
public:
|
||||
|
||||
packed_field(const packed_field&) = delete;
|
||||
packed_field& operator=(const packed_field&) = delete;
|
||||
|
||||
packed_field(packed_field&&) = default;
|
||||
packed_field& operator=(packed_field&&) = default;
|
||||
|
||||
packed_field(pbf_writer& parent_writer, pbf_tag_type tag) :
|
||||
m_writer(parent_writer, tag) {
|
||||
}
|
||||
@@ -833,12 +867,14 @@ namespace detail {
|
||||
|
||||
public:
|
||||
|
||||
packed_field_fixed(pbf_writer& parent_writer, pbf_tag_type tag) :
|
||||
packed_field(parent_writer, tag) {
|
||||
template <typename P>
|
||||
packed_field_fixed(pbf_writer& parent_writer, P tag) :
|
||||
packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
|
||||
}
|
||||
|
||||
packed_field_fixed(pbf_writer& parent_writer, pbf_tag_type tag, std::size_t size) :
|
||||
packed_field(parent_writer, tag, size * sizeof(T)) {
|
||||
template <typename P>
|
||||
packed_field_fixed(pbf_writer& parent_writer, P tag, std::size_t size) :
|
||||
packed_field(parent_writer, static_cast<pbf_tag_type>(tag), size * sizeof(T)) {
|
||||
}
|
||||
|
||||
void add_element(T value) {
|
||||
@@ -852,8 +888,9 @@ namespace detail {
|
||||
|
||||
public:
|
||||
|
||||
packed_field_varint(pbf_writer& parent_writer, pbf_tag_type tag) :
|
||||
packed_field(parent_writer, tag) {
|
||||
template <typename P>
|
||||
packed_field_varint(pbf_writer& parent_writer, P tag) :
|
||||
packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
|
||||
}
|
||||
|
||||
void add_element(T value) {
|
||||
@@ -867,8 +904,9 @@ namespace detail {
|
||||
|
||||
public:
|
||||
|
||||
packed_field_svarint(pbf_writer& parent_writer, pbf_tag_type tag) :
|
||||
packed_field(parent_writer, tag) {
|
||||
template <typename P>
|
||||
packed_field_svarint(pbf_writer& parent_writer, P tag) :
|
||||
packed_field(parent_writer, static_cast<pbf_tag_type>(tag)) {
|
||||
}
|
||||
|
||||
void add_element(T value) {
|
||||
|
||||
+13
-2
@@ -45,6 +45,17 @@ enum class pbf_wire_type : uint32_t {
|
||||
unknown = 99 // used for default setting in this library
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the tag and wire type of the current field in one integer suitable
|
||||
* for comparison with a switch statement.
|
||||
*
|
||||
* See pbf_reader.tag_and_type() for an example how to use this.
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr inline uint32_t tag_and_type(T tag, pbf_wire_type wire_type) noexcept {
|
||||
return (static_cast<uint32_t>(static_cast<pbf_tag_type>(tag)) << 3) | static_cast<uint32_t>(wire_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type used for length values, such as the length of a field.
|
||||
*/
|
||||
@@ -166,7 +177,7 @@ inline void swap(data_view& lhs, data_view& rhs) noexcept {
|
||||
* @param lhs First object.
|
||||
* @param rhs Second object.
|
||||
*/
|
||||
inline bool operator==(data_view& lhs, data_view& rhs) noexcept {
|
||||
inline bool operator==(const data_view& lhs, const data_view& rhs) noexcept {
|
||||
return lhs.size() == rhs.size() && !std::strcmp(lhs.data(), rhs.data());
|
||||
}
|
||||
|
||||
@@ -177,7 +188,7 @@ inline bool operator==(data_view& lhs, data_view& rhs) noexcept {
|
||||
* @param lhs First object.
|
||||
* @param rhs Second object.
|
||||
*/
|
||||
inline bool operator!=(data_view& lhs, data_view& rhs) noexcept {
|
||||
inline bool operator!=(const data_view& lhs, const data_view& rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
+7
-7
@@ -142,7 +142,7 @@ inline void skip_varint(const char** data, const char* end) {
|
||||
*/
|
||||
template <typename T>
|
||||
inline int write_varint(T data, uint64_t value) {
|
||||
int n=1;
|
||||
int n = 1;
|
||||
|
||||
while (value >= 0x80) {
|
||||
*data++ = char((value & 0x7f) | 0x80);
|
||||
@@ -157,29 +157,29 @@ inline int write_varint(T data, uint64_t value) {
|
||||
/**
|
||||
* ZigZag encodes a 32 bit integer.
|
||||
*/
|
||||
inline uint32_t encode_zigzag32(int32_t value) noexcept {
|
||||
inline constexpr uint32_t encode_zigzag32(int32_t value) noexcept {
|
||||
return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* ZigZag encodes a 64 bit integer.
|
||||
*/
|
||||
inline uint64_t encode_zigzag64(int64_t value) noexcept {
|
||||
inline constexpr uint64_t encode_zigzag64(int64_t value) noexcept {
|
||||
return (static_cast<uint64_t>(value) << 1) ^ (static_cast<uint64_t>(value >> 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a 32 bit ZigZag-encoded integer.
|
||||
*/
|
||||
inline int32_t decode_zigzag32(uint32_t value) noexcept {
|
||||
return int32_t(value >> 1) ^ -int32_t(value & 1);
|
||||
inline constexpr int32_t decode_zigzag32(uint32_t value) noexcept {
|
||||
return static_cast<int32_t>(value >> 1) ^ -static_cast<int32_t>(value & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a 64 bit ZigZag-encoded integer.
|
||||
*/
|
||||
inline int64_t decode_zigzag64(uint64_t value) noexcept {
|
||||
return int64_t(value >> 1) ^ -int64_t(value & 1);
|
||||
inline constexpr int64_t decode_zigzag64(uint64_t value) noexcept {
|
||||
return static_cast<int64_t>(value >> 1) ^ -static_cast<int64_t>(value & 1);
|
||||
}
|
||||
|
||||
} // end namespace protozero
|
||||
|
||||
+3
-4
@@ -20,16 +20,15 @@ documentation.
|
||||
#define PROTOZERO_VERSION_MAJOR 1
|
||||
|
||||
/// The minor version number
|
||||
#define PROTOZERO_VERSION_MINOR 4
|
||||
#define PROTOZERO_VERSION_MINOR 5
|
||||
|
||||
/// The patch number
|
||||
#define PROTOZERO_VERSION_PATCH 4
|
||||
#define PROTOZERO_VERSION_PATCH 1
|
||||
|
||||
/// The complete version number
|
||||
#define PROTOZERO_VERSION_CODE (PROTOZERO_VERSION_MAJOR * 10000 + PROTOZERO_VERSION_MINOR * 100 + PROTOZERO_VERSION_PATCH)
|
||||
|
||||
/// Version number as string
|
||||
#define PROTOZERO_VERSION_STRING "1.4.4"
|
||||
|
||||
#define PROTOZERO_VERSION_STRING "1.5.1"
|
||||
|
||||
#endif // PROTOZERO_VERSION_HPP
|
||||
|
||||
Reference in New Issue
Block a user