Merge commit '0c6dee4befebf823d839d1092bcae79afbf4f12e' into merge/libosmium-2.11.0

This commit is contained in:
Michael Krasnyk
2017-01-20 14:05:21 +01:00
231 changed files with 2732 additions and 1500 deletions
+1 -1
View File
@@ -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>
-11
View File
@@ -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
-33
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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