[protozero] 01/04: Imported Upstream version 1.4.3

Bas Couwenberg sebastic at debian.org
Tue Nov 15 14:02:53 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository protozero.

commit df3d81293a7f190660ed6e87bc2b27e932e1c6aa
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Tue Nov 15 14:43:48 2016 +0100

    Imported Upstream version 1.4.3
---
 CHANGELOG.md                      |  11 +-
 doc/macros.md                     |  14 +-
 doc/tutorial.md                   | 446 +++++++++++++++++++++-----------------
 include/protozero/byteswap.hpp    |  57 ++---
 include/protozero/iterators.hpp   |  20 +-
 include/protozero/pbf_message.hpp |   4 +-
 include/protozero/pbf_reader.hpp  |  45 ++--
 include/protozero/pbf_writer.hpp  |   9 +-
 include/protozero/types.hpp       |  18 +-
 include/protozero/version.hpp     |   4 +-
 package.json                      |   2 +-
 test/t/endian/test_cases.cpp      |  24 +-
 12 files changed, 343 insertions(+), 311 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a7dd14..24ef9a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 ### Fixed
 
 
+## [1.4.3] - 2016-11-15
+
+### Fixed
+
+- Undefined behaviour in byte swapping code.
+- Rename some parameters to avoid "shadow" warning from some compilers.
+
+
 ## [1.4.2] - 2016-08-27
 
 ### Fixed
@@ -108,7 +116,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 - Make pbf reader and writer code endianess-aware.
 
 
-[unreleased]: https://github.com/osmcode/libosmium/compare/v1.4.2...HEAD
+[unreleased]: https://github.com/osmcode/libosmium/compare/v1.4.3...HEAD
+[1.4.3]: https://github.com/osmcode/libosmium/compare/v1.4.2...v1.4.3
 [1.4.2]: https://github.com/osmcode/libosmium/compare/v1.4.1...v1.4.2
 [1.4.1]: https://github.com/osmcode/libosmium/compare/v1.4.0...v1.4.1
 [1.4.0]: https://github.com/osmcode/libosmium/compare/v1.3.0...v1.4.0
diff --git a/doc/macros.md b/doc/macros.md
index 4b9fe65..37780a1 100644
--- a/doc/macros.md
+++ b/doc/macros.md
@@ -41,8 +41,14 @@ others taking a `protozero::data_view` as parameters.
 ## `PROTOZERO_DO_NOT_USE_BARE_POINTER`
 
 Can be set to force Protozero to not use bare pointers for some iterators
-returned from `get_packed_*` calls. It is usually not necessary to use this
-and might affect performance if you do. If you are getting errors about
-unaligned memory access or a SIGBUS, you can try to set this. (Please also
-report on error if this is the case.)
+returned from `get_packed_*` calls. Use of the bare pointers leads to undefined
+behaviour according to the C++ standard, so define this if you don't want to
+have that.
+
+But it is usually not necessary to use this and might affect performance if you
+do. If you are getting errors about unaligned memory access or a SIGBUS, you
+can try to set this. (Please also report an error if this is the case.)
+
+If you don't set this, the clang UBSan (Undefined behaviour sanitizer) will
+report unaligned memory accesses.
 
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 58b2d43..65c00c9 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -25,7 +25,9 @@ You need a C++11-capable compiler for protozero to work. Copy the files in the
 `include/protozero` directory somewhere where your build system can find them.
 Keep the `protozero` directory and include the files in the form
 
-    #include <protozero/FILENAME.hpp>
+```cpp
+#include <protozero/FILENAME.hpp>
+```
 
 You always need `byteswap.hpp`, `config.hpp`, `types.hpp`, `varint.hpp`,
 and `exception.hpp`. For reading you need `pbf_reader.hpp` and probably
@@ -40,7 +42,9 @@ defining the library version.
 
 To use the `pbf_reader` class, add this include to your C++ program:
 
-    #include <protozero/pbf_reader.hpp>
+```cpp
+#include <protozero/pbf_reader.hpp>
+```
 
 The `pbf_reader` class contains asserts that will detect some programming
 errors. We encourage you to compile with asserts enabled in your debug builds.
@@ -50,46 +54,49 @@ errors. We encourage you to compile with asserts enabled in your debug builds.
 
 Lets say you have a protocol description in a `.proto` file like this:
 
-    message Example1 {
-        required uint32 x  =  1;
-        optional string s  =  2;
-        repeated fixed64 r = 17;
-    }
+```cpp
+message Example1 {
+    required uint32 x  =  1;
+    optional string s  =  2;
+    repeated fixed64 r = 17;
+}
+```
 
 To read messages created according to that description, you will have code that
 looks somewhat like this:
 
-    #include <protozero/pbf_reader.hpp>
-
-    // get data from somewhere into the input string
-    std::string input = get_input_data();
-
-    // initialize pbf message with this data
-    protozero::pbf_reader message(input);
-
-    // iterate over fields in the message
-    while (message.next()) {
-
-        // switch depending on the field tag (the field name is not available)
-        switch (message.tag()) {
-            case 1:
-                // get data for tag 1 (in this case an uint32)
-                auto x = message.get_uint32();
-                break;
-            case 2:
-                // get data for tag 2 (in this case a string)
-                std::string s = message.get_string();
-                break;
-            case 17:
-                // ignore data for tag 17
-                message.skip();
-                break;
-            default:
-                // ignore data for unknown tags to allow for future extensions
-                message.skip();
-        }
-
+```cpp
+#include <protozero/pbf_reader.hpp>
+
+// get data from somewhere into the input string
+std::string input = get_input_data();
+
+// initialize pbf message with this data
+protozero::pbf_reader message(input);
+
+// iterate over fields in the message
+while (message.next()) {
+
+    // switch depending on the field tag (the field name is not available)
+    switch (message.tag()) {
+        case 1:
+            // get data for tag 1 (in this case an uint32)
+            auto x = message.get_uint32();
+            break;
+        case 2:
+            // get data for tag 2 (in this case a string)
+            std::string s = message.get_string();
+            break;
+        case 17:
+            // ignore data for tag 17
+            message.skip();
+            break;
+        default:
+            // ignore data for unknown tags to allow for future extensions
+            message.skip();
     }
+}
+```
 
 You always have to call `next()` and then either one of the accessor functions
 (like `get_uint32()` or `get_string()`) to get the field value or `skip()` to
@@ -114,14 +121,15 @@ field.
 If, out of a protocol buffer message, you only need the value of a single
 field, you can use the version of the `next()` function with a parameter:
 
-    // same .proto file and initialization as above
-
-    // get all fields with tag 17, skip all others
-    while (message.next(17)) {
-        auto r = message.get_fixed64();
-        std::cout << r << "\n";
-    }
+```cpp
+// same .proto file and initialization as above
 
+// get all fields with tag 17, skip all others
+while (message.next(17)) {
+    auto r = message.get_fixed64();
+    std::cout << r << "\n";
+}
+```
 
 ### Handling Scalar Fields
 
@@ -146,24 +154,28 @@ are used to access the data.
 So, for example, if you have a protocol description in a `.proto` file like
 this:
 
-    message Example2 {
-        repeated sint32 i = 1 [packed=true];
-    }
+```cpp
+message Example2 {
+    repeated sint32 i = 1 [packed=true];
+}
+```
 
 You can get to the data like this:
 
-    protozero::pbf_reader message(input.data(), input.size());
+```cpp
+protozero::pbf_reader message(input.data(), input.size());
 
-    // set current field
-    item.next(1);
+// set current field
+item.next(1);
 
-    // get an iterator pair
-    auto pi = item.get_packed_sint32();
+// get an iterator pair
+auto pi = item.get_packed_sint32();
 
-    // iterate to get to all values
-    for (auto it = pi.first; it != pi.second; ++it) {
-        std::cout << *it << "\n";
-    }
+// iterate to get to all values
+for (auto it = pi.first; it != pi.second; ++it) {
+    std::cout << *it << "\n";
+}
+```
 
 So you are getting a pair of normal forward iterators that can be used with any
 STL algorithms etc.
@@ -177,37 +189,40 @@ repeated fields are handled in the usual way for scalar fields.
 Protocol Buffers can embed any message inside another message. To access an
 embedded message use the `get_message()` function. So for this description:
 
-    message Point {
-        required double x = 1;
-        required double y = 2;
-    }
+```cpp
+message Point {
+    required double x = 1;
+    required double y = 2;
+}
 
-    message Example3 {
-        repeated Point point = 10;
-    }
+message Example3 {
+    repeated Point point = 10;
+}
+```
 
 you can parse with this code:
 
-    protozero::pbf_reader message(input);
-
-    while (message.next(10)) {
-        protozero::pbf_reader point = message.get_message();
-        double x, y;
-        while (point.next()) {
-            switch (point.tag()) {
-                case 1:
-                    x = point.get_double();
-                    break;
-                case 2:
-                    y = point.get_double();
-                    break;
-                default:
-                    point.skip();
-            }
+```cpp
+protozero::pbf_reader message(input);
+
+while (message.next(10)) {
+    protozero::pbf_reader point = message.get_message();
+    double x, y;
+    while (point.next()) {
+        switch (point.tag()) {
+            case 1:
+                x = point.get_double();
+                break;
+            case 2:
+                y = point.get_double();
+                break;
+            default:
+                point.skip();
         }
-        std::cout << "x=" << x << " y=" << y << "\n";
     }
-
+    std::cout << "x=" << x << " y=" << y << "\n";
+}
+```
 
 ### Handling Enums
 
@@ -284,19 +299,23 @@ class` and then use the `pbf_message` template class instead of the
 Here is the first example again, this time using this new technique. So you
 have the following in a `.proto` file:
 
-    message Example1 {
-        required uint32 x  =  1;
-        optional string s  =  2;
-        repeated fixed64 r = 17;
-    }
+```cpp
+message Example1 {
+    required uint32 x  =  1;
+    optional string s  =  2;
+    repeated fixed64 r = 17;
+}
+```
 
 Add the following declaration in one of your header files:
 
-    enum class Example1 : protozero::pbf_tag_type {
-        required_uint32_x  =  1,
-        optional_string_s  =  2,
-        repeated_fixed64_r = 17
-    };
+```cpp
+enum class Example1 : protozero::pbf_tag_type {
+    required_uint32_x  =  1,
+    optional_string_s  =  2,
+    repeated_fixed64_r = 17
+};
+```
 
 The message name becomes the name of the `enum class` which is always built
 on top of the `protozero::pbf_tag_type` type. Each field in the message
@@ -309,34 +328,35 @@ To read messages created according to that description, you will have code that
 looks somewhat like this, this time using `pbf_message` instead of
 `pbf_reader`:
 
-    #include <protozero/pbf_message.hpp>
-
-    // get data from somewhere into the input string
-    std::string input = get_input_data();
-
-    // initialize pbf message with this data
-    protozero::pbf_message<Example1> message(input);
-
-    // iterate over fields in the message
-    while (message.next()) {
-
-        // switch depending on the field tag (the field name is not available)
-        switch (message.tag()) {
-            case Example1::required_uint32_x:
-                auto x = message.get_uint32();
-                break;
-            case Example1::optional_string_s:
-                std::string s = message.get_string();
-                break;
-            case Example1::repeated_fixed64_r:
-                message.skip();
-                break;
-            default:
-                // ignore data for unknown tags to allow for future extensions
-                message.skip();
-        }
-
+```cpp
+#include <protozero/pbf_message.hpp>
+
+// get data from somewhere into the input string
+std::string input = get_input_data();
+
+// initialize pbf message with this data
+protozero::pbf_message<Example1> message(input);
+
+// iterate over fields in the message
+while (message.next()) {
+
+    // switch depending on the field tag (the field name is not available)
+    switch (message.tag()) {
+        case Example1::required_uint32_x:
+            auto x = message.get_uint32();
+            break;
+        case Example1::optional_string_s:
+            std::string s = message.get_string();
+            break;
+        case Example1::repeated_fixed64_r:
+            message.skip();
+            break;
+        default:
+            // ignore data for unknown tags to allow for future extensions
+            message.skip();
     }
+}
+```
 
 Note the correspondance between the enum value (for instance
 `required_uint32_x`) and the name of the getter function (for instance
@@ -365,7 +385,9 @@ data). You can switch of this warning with `-Wno-covered-switch-default`).
 
 To use the `pbf_writer` class, add this include to your C++ program:
 
-    #include <protozero/pbf_writer.hpp>
+```cpp
+#include <protozero/pbf_writer.hpp>
+```
 
 The `pbf_writer` class contains asserts that will detect some programming
 errors. We encourage you to compile with asserts enabled in your debug builds.
@@ -375,25 +397,29 @@ errors. We encourage you to compile with asserts enabled in your debug builds.
 
 Lets say you have a protocol description in a `.proto` file like this:
 
-    message Example {
-        required uint32 x = 1;
-        optional string s = 2;
-        repeated fixed64 r = 17;
-    }
+```cpp
+message Example {
+    required uint32 x = 1;
+    optional string s = 2;
+    repeated fixed64 r = 17;
+}
+```
 
 To write messages created according to that description, you will have code
 that looks somewhat like this:
 
-    #include <protozero/pbf_writer.hpp>
+```cpp
+#include <protozero/pbf_writer.hpp>
 
-    std::string data;
-    protozero::pbf_writer pbf_example(data);
+std::string data;
+protozero::pbf_writer pbf_example(data);
 
-    pbf_example.add_uint32(1, 27);       // uint32_t x
-    pbf_example.add_fixed64(17, 1);      // fixed64 r
-    pbf_example.add_fixed64(17, 2);
-    pbf_example.add_fixed64(17, 3);
-    pbf_example.add_string(2, "foobar"); // string s
+pbf_example.add_uint32(1, 27);       // uint32_t x
+pbf_example.add_fixed64(17, 1);      // fixed64 r
+pbf_example.add_fixed64(17, 2);
+pbf_example.add_fixed64(17, 3);
+pbf_example.add_string(2, "foobar"); // string s
+```
 
 First you need a string which will be used as buffer to assemble the
 protobuf-formatted message. The `pbf_writer` object contains a reference to
@@ -423,22 +449,26 @@ the `.proto` file are not available.
 
 Repeated packed fields can easily be set from a pair of iterators:
 
-    std::string data;
-    protozero::pbf_writer pw(data);
+```cpp
+std::string data;
+protozero::pbf_writer pw(data);
 
-    std::vector<int> v = { 1, 4, 9, 16, 25, 36 };
-    pw.add_packed_int32(1, std::begin(v), std::end(v));
+std::vector<int> v = { 1, 4, 9, 16, 25, 36 };
+pw.add_packed_int32(1, std::begin(v), std::end(v));
+```
 
 If you don't have an iterator you can use the alternative form:
 
-    std::string data;
-    protozero::pbf_writer pw(data);
-    {
-        protozero::packed_field_int32 field{pw, 1};
-        field.add_element(1);
-        field.add_element(10);
-        field.add_element(100);
-    }
+```cpp
+std::string data;
+protozero::pbf_writer pw(data);
+{
+    protozero::packed_field_int32 field{pw, 1};
+    field.add_element(1);
+    field.add_element(10);
+    field.add_element(100);
+}
+```
 
 Of course you can add as many elements as you want. If you add no elements
 at all, this code will still work, protozero detects this special case and
@@ -452,13 +482,15 @@ the right value. You must close that scope before adding other fields to the
 If you know how many elements you will add to the field and your field contains
 fixed length elements, you can tell Protozero and it can optimize this case:
 
-    std::string data;
-    protozero::pbf_writer pw(data);
-    {
-        protozero::packed_field_fixed32 field{pw, 1, 2}; // exactly two elements
-        field.add_element(42);
-        field.add_element(13);
-    }
+```cpp
+std::string data;
+protozero::pbf_writer pw(data);
+{
+    protozero::packed_field_fixed32 field{pw, 1, 2}; // exactly two elements
+    field.add_element(42);
+    field.add_element(13);
+}
+```
 
 In this case you have to supply exactly as many elements as you promised,
 otherwise you will get a broken protobuf message.
@@ -470,14 +502,16 @@ This works for `packed_field_fixed32`, `packed_field_sfixed32`,
 You can abandon writing of the packed field if this becomes necessary by
 calling `rollback()`:
 
-    std::string data;
-    protozero::pbf_writer pw(data);
-    {
-        protozero::packed_field_int32 field{pw, 1};
-        field.add_element(42);
-        // some error occurs, you don't want to have this field at all
-        field.rollback();
-    }
+```cpp
+std::string data;
+protozero::pbf_writer pw(data);
+{
+    protozero::packed_field_int32 field{pw, 1};
+    field.add_element(42);
+    // some error occurs, you don't want to have this field at all
+    field.rollback();
+}
+```
 
 The result is the same as if the lines inside the nested brackets had never
 been called. Do not try to call `add_element()` after a rollback.
@@ -488,42 +522,46 @@ been called. Do not try to call `add_element()` after a rollback.
 Nested sub-messages can be handled by first creating the submessage and then
 adding to the parent message:
 
-    std::string buffer_sub;
-    protozero::pbf_writer pbf_sub(buffer_sub);
+```cpp
+std::string buffer_sub;
+protozero::pbf_writer pbf_sub(buffer_sub);
 
-    // add fields to sub-message
-    pbf_sub.add_...(...);
-    // ...
+// add fields to sub-message
+pbf_sub.add_...(...);
+// ...
 
-    // sub-message is finished here
+// sub-message is finished here
 
-    std::string buffer_parent;
-    protozero::pbf_writer pbf_parent(buffer_parent);
-    pbf_parent.add_message(1, buffer_sub);
+std::string buffer_parent;
+protozero::pbf_writer pbf_parent(buffer_parent);
+pbf_parent.add_message(1, buffer_sub);
+```
 
 This is easy to do but it has the drawback of needing a separate `std::string`
 buffer. If this concerns you (and why would you use protozero and not the
 Google protobuf library if it doesn't?) there is another way:
 
-    std::string data;
-    protozero::pbf_writer pbf_parent(data);
+```cpp
+std::string data;
+protozero::pbf_writer pbf_parent(data);
 
-    // optionally add fields to parent here
-    pbf_parent.add_...(...);
+// optionally add fields to parent here
+pbf_parent.add_...(...);
 
-    // open a new scope
-    {
-        // create new pbf_writer with parent and the tag (field number)
-        // as parameters
-        protozero::pbf_writer pbf_sub(pbf_parent, 1);
+// open a new scope
+{
+    // create new pbf_writer with parent and the tag (field number)
+    // as parameters
+    protozero::pbf_writer pbf_sub(pbf_parent, 1);
 
-        // add fields to sub here...
-        pbf_sub.add_...(...);
+    // add fields to sub here...
+    pbf_sub.add_...(...);
 
-    } // closing the scope will close the sub-message
+} // closing the scope will close the sub-message
 
-    // optionally add more fields to parent here
-    pbf_parent.add_...(...);
+// optionally add more fields to parent here
+pbf_parent.add_...(...);
+```
 
 This can be nested arbitrarily deep.
 
@@ -537,24 +575,26 @@ than was available, the rest of the buffer is moved over a few bytes.
 You can abandon writing of submessage if this becomes necessary by
 calling `rollback()`:
 
-    std::string data;
-    protozero::pbf_writer pbf_parent(data);
+```cpp
+std::string data;
+protozero::pbf_writer pbf_parent(data);
 
-    // open a new scope
-    {
-        // create new pbf_writer with parent and the tag (field number)
-        // as parameters
-        protozero::pbf_writer pbf_sub(pbf_parent, 1);
+// open a new scope
+{
+    // create new pbf_writer with parent and the tag (field number)
+    // as parameters
+    protozero::pbf_writer pbf_sub(pbf_parent, 1);
 
-        // add fields to sub here...
-        pbf_sub.add_...(...);
+    // add fields to sub here...
+    pbf_sub.add_...(...);
 
-        // some problem occurs and you want to abandon the submessage:
-        pbf_sub.rollback();
-    }
+    // some problem occurs and you want to abandon the submessage:
+    pbf_sub.rollback();
+}
 
-    // optionally add more fields to parent here
-    pbf_parent.add_...(...);
+// optionally add more fields to parent here
+pbf_parent.add_...(...);
+```
 
 The result is the same as if the lines inside the nested brackets had never
 been called. Do not try to call any of the `add_*` functions on the submessage
@@ -601,12 +641,14 @@ To use the low-level, add this include to your C++ program:
 
 The following functions are then available:
 
-    decode_varint()
-    write_varint()
-    encode_zigzag32()
-    encode_zigzag64()
-    decode_zigzag32()
-    decode_zigzag64()
+```cpp
+decode_varint()
+write_varint()
+encode_zigzag32()
+encode_zigzag64()
+decode_zigzag32()
+decode_zigzag64()
+```
 
 See the reference documentation created by `make doc` for details.
 
diff --git a/include/protozero/byteswap.hpp b/include/protozero/byteswap.hpp
index 06ba6de..9de42a2 100644
--- a/include/protozero/byteswap.hpp
+++ b/include/protozero/byteswap.hpp
@@ -18,54 +18,45 @@ documentation.
 
 #include <cstdint>
 #include <cassert>
+#include <type_traits>
 
 #include <protozero/config.hpp>
 
 namespace protozero {
+namespace detail {
 
-/**
- * Swap N byte value between endianness formats. This template function must
- * be specialized to actually work.
- */
-template <int N>
-inline void byteswap(const char* /*data*/, char* /*result*/) noexcept {
-    static_assert(N == 1, "Can only swap 4 or 8 byte values");
-}
-
-/**
- * Swap 4 byte value (int32_t, uint32_t, float) between endianness formats.
- */
-template <>
-inline void byteswap<4>(const char* data, char* result) noexcept {
+inline uint32_t byteswap_impl(uint32_t value) noexcept {
 #ifdef PROTOZERO_USE_BUILTIN_BSWAP
-    *reinterpret_cast<uint32_t*>(result) = __builtin_bswap32(*reinterpret_cast<const uint32_t*>(data));
+    return __builtin_bswap32(value);
 #else
-    result[3] = data[0];
-    result[2] = data[1];
-    result[1] = data[2];
-    result[0] = data[3];
+    return ((value & 0xff000000) >> 24) |
+           ((value & 0x00ff0000) >>  8) |
+           ((value & 0x0000ff00) <<  8) |
+           ((value & 0x000000ff) << 24);
 #endif
 }
 
-/**
- * Swap 8 byte value (int64_t, uint64_t, double) between endianness formats.
- */
-template <>
-inline void byteswap<8>(const char* data, char* result) noexcept {
+inline uint64_t byteswap_impl(uint64_t value) noexcept {
 #ifdef PROTOZERO_USE_BUILTIN_BSWAP
-    *reinterpret_cast<uint64_t*>(result) = __builtin_bswap64(*reinterpret_cast<const uint64_t*>(data));
+    return __builtin_bswap64(value);
 #else
-    result[7] = data[0];
-    result[6] = data[1];
-    result[5] = data[2];
-    result[4] = data[3];
-    result[3] = data[4];
-    result[2] = data[5];
-    result[1] = data[6];
-    result[0] = data[7];
+    return ((value & 0xff00000000000000ULL) >> 56) |
+           ((value & 0x00ff000000000000ULL) >> 40) |
+           ((value & 0x0000ff0000000000ULL) >> 24) |
+           ((value & 0x000000ff00000000ULL) >>  8) |
+           ((value & 0x00000000ff000000ULL) <<  8) |
+           ((value & 0x0000000000ff0000ULL) << 24) |
+           ((value & 0x000000000000ff00ULL) << 40) |
+           ((value & 0x00000000000000ffULL) << 56);
 #endif
 }
 
+template <typename T>
+inline void byteswap_inplace(T& value) noexcept {
+    value = static_cast<T>(byteswap_impl(static_cast<typename std::make_unsigned<T>::type>(value)));
+}
+
+} // end namespace detail
 } // end namespace protozero
 
 #endif // PROTOZERO_BYTESWAP_HPP
diff --git a/include/protozero/iterators.hpp b/include/protozero/iterators.hpp
index 00ba919..c3107b5 100644
--- a/include/protozero/iterators.hpp
+++ b/include/protozero/iterators.hpp
@@ -29,21 +29,6 @@ documentation.
 
 namespace protozero {
 
-namespace detail {
-
-    // Copy N bytes from src to dest on little endian machines, on big
-    // endian swap the bytes in the process.
-    template <int N>
-    inline void copy_or_byteswap(const char* src, void* dest) noexcept {
-#if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN
-        std::memcpy(dest, src, N);
-#else
-        byteswap<N>(src, reinterpret_cast<char*>(dest));
-#endif
-    }
-
-} // end namespace detail
-
 /**
  * A range of iterators based on std::pair. Created from beginning and
  * end iterators. Used as a return type from some pbf_reader methods
@@ -213,7 +198,10 @@ public:
 
     value_type operator*() const {
         value_type result;
-        detail::copy_or_byteswap<sizeof(value_type)>(m_data , &result);
+        std::memcpy(&result, m_data, sizeof(value_type));
+#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
+        detail::byteswap_inplace(result);
+#endif
         return result;
     }
 
diff --git a/include/protozero/pbf_message.hpp b/include/protozero/pbf_message.hpp
index 0557734..f66604a 100644
--- a/include/protozero/pbf_message.hpp
+++ b/include/protozero/pbf_message.hpp
@@ -79,8 +79,8 @@ public:
         return pbf_reader::next();
     }
 
-    bool next(T tag) {
-        return pbf_reader::next(pbf_tag_type(tag));
+    bool next(T next_tag) {
+        return pbf_reader::next(pbf_tag_type(next_tag));
     }
 
     T tag() const noexcept {
diff --git a/include/protozero/pbf_reader.hpp b/include/protozero/pbf_reader.hpp
index 2f4054d..6187fc2 100644
--- a/include/protozero/pbf_reader.hpp
+++ b/include/protozero/pbf_reader.hpp
@@ -75,7 +75,10 @@ class pbf_reader {
     T get_fixed() {
         T result;
         skip_bytes(sizeof(T));
-        detail::copy_or_byteswap<sizeof(T)>(m_data - sizeof(T), &result);
+        std::memcpy(&result, m_data - sizeof(T), sizeof(T));
+#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
+        detail::byteswap_inplace(result);
+#endif
         return result;
     }
 
@@ -134,7 +137,7 @@ public:
     /**
      * Construct a pbf_reader message from a data_view. The pointer from the
      * data_view will be stored inside the pbf_reader object, no data is
-     * copied. So you must* make sure the view stays valid as long as the
+     * copied. So you must make sure the view stays valid as long as the
      * pbf_reader object is used.
      *
      * The buffer must contain a complete protobuf message.
@@ -149,25 +152,27 @@ public:
     }
 
     /**
-     * Construct a pbf_reader message from a data pointer and a length. The pointer
-     * will be stored inside the pbf_reader object, no data is copied. So you must
-     * make sure the buffer stays valid as long as the pbf_reader object is used.
+     * Construct a pbf_reader message from a data pointer and a length. The
+     * pointer will be stored inside the pbf_reader object, no data is copied.
+     * So you must make sure the buffer stays valid as long as the pbf_reader
+     * object is used.
      *
      * The buffer must contain a complete protobuf message.
      *
      * @post There is no current field.
      */
-    pbf_reader(const char* data, std::size_t length) noexcept
+    pbf_reader(const char* data, std::size_t size) noexcept
         : m_data(data),
-          m_end(data + length),
+          m_end(data + size),
           m_wire_type(pbf_wire_type::unknown),
           m_tag(0) {
     }
 
     /**
-     * Construct a pbf_reader message from a data pointer and a length. The pointer
-     * will be stored inside the pbf_reader object, no data is copied. So you must
-     * make sure the buffer stays valid as long as the pbf_reader object is used.
+     * Construct a pbf_reader message from a data pointer and a length. The
+     * pointer will be stored inside the pbf_reader object, no data is copied.
+     * So you must make sure the buffer stays valid as long as the pbf_reader
+     * object is used.
      *
      * The buffer must contain a complete protobuf message.
      *
@@ -181,10 +186,10 @@ public:
     }
 
     /**
-     * Construct a pbf_reader message from a std::string. A pointer to the string
-     * internals will be stored inside the pbf_reader object, no data is copied.
-     * So you must make sure the string is unchanged as long as the pbf_reader
-     * object is used.
+     * Construct a pbf_reader message from a std::string. A pointer to the
+     * string internals will be stored inside the pbf_reader object, no data
+     * is copied. So you must make sure the string is unchanged as long as the
+     * pbf_reader object is used.
      *
      * The string must contain a complete protobuf message.
      *
@@ -231,8 +236,9 @@ public:
     }
 
     /**
-     * In a boolean context the pbf_reader class evaluates to `true` if there are
-     * still fields available and to `false` if the last field has been read.
+     * In a boolean context the pbf_reader class evaluates to `true` if there
+     * are still fields available and to `false` if the last field has been
+     * read.
      */
     operator bool() const noexcept {
         return m_data < m_end;
@@ -276,7 +282,8 @@ public:
 
         // tags 0 and 19000 to 19999 are not allowed as per
         // https://developers.google.com/protocol-buffers/docs/proto
-        protozero_assert(((m_tag > 0 && m_tag < 19000) || (m_tag > 19999 && m_tag <= ((1 << 29) - 1))) && "tag out of range");
+        protozero_assert(((m_tag >     0 && m_tag < 19000) ||
+                          (m_tag > 19999 && m_tag <= ((1 << 29) - 1))) && "tag out of range");
 
         m_wire_type = pbf_wire_type(value & 0x07);
         switch (m_wire_type) {
@@ -317,9 +324,9 @@ public:
      * @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 tag) {
+    bool next(pbf_tag_type next_tag) {
         while (next()) {
-            if (m_tag == tag) {
+            if (m_tag == next_tag) {
                 return true;
             } else {
                 skip();
diff --git a/include/protozero/pbf_writer.hpp b/include/protozero/pbf_writer.hpp
index bce1c3f..5a9f114 100644
--- a/include/protozero/pbf_writer.hpp
+++ b/include/protozero/pbf_writer.hpp
@@ -90,13 +90,10 @@ class pbf_writer {
     void add_fixed(T value) {
         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);
-#if PROTOZERO_BYTE_ORDER == PROTOZERO_LITTLE_ENDIAN
-        m_data->append(reinterpret_cast<const char*>(&value), sizeof(T));
-#else
-        const auto size = m_data->size();
-        m_data->resize(size + sizeof(T));
-        byteswap<sizeof(T)>(reinterpret_cast<const char*>(&value), const_cast<char*>(m_data->data() + size));
+#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
+        detail::byteswap_inplace(value);
 #endif
+        m_data->append(reinterpret_cast<const char*>(&value), sizeof(T));
     }
 
     template <typename T, typename It>
diff --git a/include/protozero/types.hpp b/include/protozero/types.hpp
index 8b04638..431c207 100644
--- a/include/protozero/types.hpp
+++ b/include/protozero/types.hpp
@@ -78,12 +78,12 @@ public:
     /**
      * Create data_view from pointer and size.
      *
-     * @param data Pointer to the data.
-     * @param size Length of the data.
+     * @param ptr Pointer to the data.
+     * @param length Length of the data.
      */
-    constexpr data_view(const char* data, std::size_t size) noexcept
-        : m_data(data),
-          m_size(size) {
+    constexpr data_view(const char* ptr, std::size_t length) noexcept
+        : m_data(ptr),
+          m_size(length) {
     }
 
     /**
@@ -99,11 +99,11 @@ public:
     /**
      * Create data_view from zero-terminated string.
      *
-     * @param data Pointer to the data.
+     * @param ptr Pointer to the data.
      */
-    data_view(const char* data) noexcept
-        : m_data(data),
-          m_size(std::strlen(data)) {
+    data_view(const char* ptr) noexcept
+        : m_data(ptr),
+          m_size(std::strlen(ptr)) {
     }
 
     /**
diff --git a/include/protozero/version.hpp b/include/protozero/version.hpp
index 127e649..fbaaaf1 100644
--- a/include/protozero/version.hpp
+++ b/include/protozero/version.hpp
@@ -23,13 +23,13 @@ documentation.
 #define PROTOZERO_VERSION_MINOR 4
 
 /// The patch number
-#define PROTOZERO_VERSION_PATCH 2
+#define PROTOZERO_VERSION_PATCH 3
 
 /// 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.2"
+#define PROTOZERO_VERSION_STRING "1.4.3"
 
 
 #endif // PROTOZERO_VERSION_HPP
diff --git a/package.json b/package.json
index 8598938..4bb4b21 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "protozero",
-    "version": "1.4.2",
+    "version": "1.4.3",
     "description": "Minimalist protocol buffer decoder and encoder in C++",
     "main": "include_dirs.js",
     "repository"   :  {
diff --git a/test/t/endian/test_cases.cpp b/test/t/endian/test_cases.cpp
index 146992d..da36f48 100644
--- a/test/t/endian/test_cases.cpp
+++ b/test/t/endian/test_cases.cpp
@@ -7,24 +7,16 @@
 
 namespace {
 
-    int32_t check_swap_4(const int32_t data) {
-        int32_t swapped;
-        int32_t back;
-
-        protozero::byteswap<4>(reinterpret_cast<const char*>(&data), reinterpret_cast<char*>(&swapped));
-        protozero::byteswap<4>(reinterpret_cast<const char*>(&swapped), reinterpret_cast<char*>(&back));
-
-        return back;
+    int32_t check_swap_4(int32_t data) {
+        protozero::detail::byteswap_inplace(data);
+        protozero::detail::byteswap_inplace(data);
+        return data;
     }
 
-    int64_t check_swap_8(const int64_t data) {
-        int64_t swapped;
-        int64_t back;
-
-        protozero::byteswap<8>(reinterpret_cast<const char*>(&data), reinterpret_cast<char*>(&swapped));
-        protozero::byteswap<8>(reinterpret_cast<const char*>(&swapped), reinterpret_cast<char*>(&back));
-
-        return back;
+    int64_t check_swap_8(int64_t data) {
+        protozero::detail::byteswap_inplace(data);
+        protozero::detail::byteswap_inplace(data);
+        return data;
     }
 
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/protozero.git



More information about the Pkg-grass-devel mailing list