1 #ifndef PROTOZERO_TYPES_HPP
2 #define PROTOZERO_TYPES_HPP
3
4 /*****************************************************************************
5
6 protozero - Minimalistic protocol buffer decoder and encoder in C++.
7
8 This file is from https://github.com/mapbox/protozero where you can find more
9 documentation.
10
11 *****************************************************************************/
12
13 /**
14 * @file types.hpp
15 *
16 * @brief Contains the declaration of low-level types used in the pbf format.
17 */
18
19 #include <algorithm>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstring>
23 #include <string>
24 #include <utility>
25
26 #include <protozero/config.hpp>
27
28 namespace protozero {
29
30 /**
31 * The type used for field tags (field numbers).
32 */
33 using pbf_tag_type = uint32_t;
34
35 /**
36 * The type used to encode type information.
37 * See the table on
38 * https://developers.google.com/protocol-buffers/docs/encoding
39 */
40 enum class pbf_wire_type : uint32_t {
41 varint = 0, // int32/64, uint32/64, sint32/64, bool, enum
42 fixed64 = 1, // fixed64, sfixed64, double
43 length_delimited = 2, // string, bytes, embedded messages,
44 // packed repeated fields
45 fixed32 = 5, // fixed32, sfixed32, float
46 unknown = 99 // used for default setting in this library
47 };
48
49 /**
50 * Get the tag and wire type of the current field in one integer suitable
51 * for comparison with a switch statement.
52 *
53 * See pbf_reader.tag_and_type() for an example how to use this.
54 */
55 template <typename T>
tag_and_type(T tag,pbf_wire_type wire_type)56 constexpr inline uint32_t tag_and_type(T tag, pbf_wire_type wire_type) noexcept {
57 return (static_cast<uint32_t>(static_cast<pbf_tag_type>(tag)) << 3) | static_cast<uint32_t>(wire_type);
58 }
59
60 /**
61 * The type used for length values, such as the length of a field.
62 */
63 using pbf_length_type = uint32_t;
64
65 #ifdef PROTOZERO_USE_VIEW
66 using data_view = PROTOZERO_USE_VIEW;
67 #else
68
69 /**
70 * Holds a pointer to some data and a length.
71 *
72 * This class is supposed to be compatible with the std::string_view
73 * that will be available in C++17.
74 */
75 class data_view {
76
77 const char* m_data;
78 std::size_t m_size;
79
80 public:
81
82 /**
83 * Default constructor. Construct an empty data_view.
84 */
data_view()85 constexpr data_view() noexcept
86 : m_data(nullptr),
87 m_size(0) {
88 }
89
90 /**
91 * Create data_view from pointer and size.
92 *
93 * @param ptr Pointer to the data.
94 * @param length Length of the data.
95 */
data_view(const char * ptr,std::size_t length)96 constexpr data_view(const char* ptr, std::size_t length) noexcept
97 : m_data(ptr),
98 m_size(length) {
99 }
100
101 /**
102 * Create data_view from string.
103 *
104 * @param str String with the data.
105 */
data_view(const std::string & str)106 data_view(const std::string& str) noexcept
107 : m_data(str.data()),
108 m_size(str.size()) {
109 }
110
111 /**
112 * Create data_view from zero-terminated string.
113 *
114 * @param ptr Pointer to the data.
115 */
data_view(const char * ptr)116 data_view(const char* ptr) noexcept
117 : m_data(ptr),
118 m_size(std::strlen(ptr)) {
119 }
120
121 /**
122 * Swap the contents of this object with the other.
123 *
124 * @param other Other object to swap data with.
125 */
swap(data_view & other)126 void swap(data_view& other) noexcept {
127 using std::swap;
128 swap(m_data, other.m_data);
129 swap(m_size, other.m_size);
130 }
131
132 /// Return pointer to data.
data() const133 constexpr const char* data() const noexcept {
134 return m_data;
135 }
136
137 /// Return length of data in bytes.
size() const138 constexpr std::size_t size() const noexcept {
139 return m_size;
140 }
141
142 /// Returns true if size is 0.
empty() const143 constexpr bool empty() const noexcept {
144 return m_size == 0;
145 }
146
147 /**
148 * Convert data view to string.
149 *
150 * @pre Must not be default constructed data_view.
151 */
to_string() const152 std::string to_string() const {
153 protozero_assert(m_data);
154 return std::string{m_data, m_size};
155 }
156
157 /**
158 * Convert data view to string.
159 *
160 * @pre Must not be default constructed data_view.
161 */
operator std::string() const162 explicit operator std::string() const {
163 protozero_assert(m_data);
164 return std::string{m_data, m_size};
165 }
166
167 }; // class data_view
168
169 /**
170 * Swap two data_view objects.
171 *
172 * @param lhs First object.
173 * @param rhs Second object.
174 */
swap(data_view & lhs,data_view & rhs)175 inline void swap(data_view& lhs, data_view& rhs) noexcept {
176 lhs.swap(rhs);
177 }
178
179 /**
180 * Two data_view instances are equal if they have the same size and the
181 * same content.
182 *
183 * @param lhs First object.
184 * @param rhs Second object.
185 */
operator ==(const data_view & lhs,const data_view & rhs)186 inline bool operator==(const data_view& lhs, const data_view& rhs) noexcept {
187 return lhs.size() == rhs.size() && std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data());
188 }
189
190 /**
191 * Two data_view instances are not equal if they have different sizes or the
192 * content differs.
193 *
194 * @param lhs First object.
195 * @param rhs Second object.
196 */
operator !=(const data_view & lhs,const data_view & rhs)197 inline bool operator!=(const data_view& lhs, const data_view& rhs) noexcept {
198 return !(lhs == rhs);
199 }
200
201 #endif
202
203
204 } // end namespace protozero
205
206 #endif // PROTOZERO_TYPES_HPP
207