Skip to content

Commit 860a7d5

Browse files
committed
Make access to Protobuf packed data slightly more type-safe
By using derived classes for the different types.
1 parent 38bb539 commit 860a7d5

1 file changed

Lines changed: 96 additions & 62 deletions

File tree

include/osmium/io/detail/pbf_decoder.hpp

Lines changed: 96 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,22 @@ namespace osmium {
8181

8282
using protozero::data_view;
8383

84-
class varint_range {
84+
class values_access {
8585

8686
const char* m_data = nullptr;
8787
const char* m_end = nullptr;
8888

89+
protected:
90+
8991
std::uint64_t next() {
9092
return protozero::decode_varint(&m_data, m_end);
9193
}
9294

9395
public:
9496

95-
varint_range() = default;
97+
values_access() = default;
9698

97-
explicit varint_range(const data_view& data) :
99+
explicit values_access(const data_view& data) :
98100
m_data(data.data()),
99101
m_end(data.data() + data.size()) {
100102
}
@@ -116,23 +118,55 @@ namespace osmium {
116118
});
117119
}
118120

119-
std::int32_t next_int32() {
121+
}; // class values_access
122+
123+
class values_access_int32 : public values_access {
124+
125+
public:
126+
127+
using values_access::values_access;
128+
129+
int32_t next_int32() {
120130
return static_cast<int32_t>(next());
121131
}
122132

123-
std::uint32_t next_uint32() {
133+
}; // class values_access_int32
134+
135+
class values_access_uint32 : public values_access {
136+
137+
public:
138+
139+
using values_access::values_access;
140+
141+
uint32_t next_uint32() {
124142
return static_cast<uint32_t>(next());
125143
}
126144

127-
std::int32_t next_sint32() {
145+
}; // class values_access_uint32
146+
147+
class values_access_sint32 : public values_access {
148+
149+
public:
150+
151+
using values_access::values_access;
152+
153+
int32_t next_sint32() {
128154
return protozero::decode_zigzag32(static_cast<uint32_t>(next()));
129155
}
130156

131-
std::int64_t next_sint64() {
157+
}; // class values_access_sint32
158+
159+
class values_access_sint64 : public values_access {
160+
161+
public:
162+
163+
using values_access::values_access;
164+
165+
int64_t next_sint64() {
132166
return protozero::decode_zigzag64(next());
133167
}
134168

135-
}; // class varint_range
169+
}; // class values_access_sint64
136170

137171
using osm_string_len_type = std::pair<const char*, osmium::string_size_type>;
138172

@@ -300,7 +334,7 @@ namespace osmium {
300334
return user;
301335
}
302336

303-
void build_tag_list(osmium::builder::Builder& parent, varint_range& keys, varint_range& vals) {
337+
void build_tag_list(osmium::builder::Builder& parent, values_access_uint32& keys, values_access_uint32& vals) {
304338
if (keys.empty() || vals.empty()) {
305339
return;
306340
}
@@ -325,8 +359,8 @@ namespace osmium {
325359
osmium::builder::NodeBuilder builder{m_buffer};
326360
osmium::Node& node = builder.object();
327361

328-
varint_range keys;
329-
varint_range vals;
362+
values_access_uint32 keys;
363+
values_access_uint32 vals;
330364
int64_t lon = std::numeric_limits<int64_t>::max();
331365
int64_t lat = std::numeric_limits<int64_t>::max();
332366

@@ -339,10 +373,10 @@ namespace osmium {
339373
node.set_id(pbf_node.get_sint64());
340374
break;
341375
case protozero::tag_and_type(OSMFormat::Node::packed_uint32_keys, protozero::pbf_wire_type::length_delimited):
342-
keys = varint_range{pbf_node.get_view()};
376+
keys = values_access_uint32{pbf_node.get_view()};
343377
break;
344378
case protozero::tag_and_type(OSMFormat::Node::packed_uint32_vals, protozero::pbf_wire_type::length_delimited):
345-
vals = varint_range{pbf_node.get_view()};
379+
vals = values_access_uint32{pbf_node.get_view()};
346380
break;
347381
case protozero::tag_and_type(OSMFormat::Node::optional_Info_info, protozero::pbf_wire_type::length_delimited):
348382
if (m_read_metadata == osmium::io::read_meta::yes) {
@@ -381,11 +415,11 @@ namespace osmium {
381415
void decode_way(const data_view& data) {
382416
osmium::builder::WayBuilder builder{m_buffer};
383417

384-
varint_range keys;
385-
varint_range vals;
386-
varint_range refs;
387-
varint_range lats;
388-
varint_range lons;
418+
values_access_uint32 keys;
419+
values_access_uint32 vals;
420+
values_access_sint64 refs;
421+
values_access_sint64 lats;
422+
values_access_sint64 lons;
389423

390424
osm_string_len_type user{"", 0};
391425

@@ -396,10 +430,10 @@ namespace osmium {
396430
builder.object().set_id(pbf_way.get_int64());
397431
break;
398432
case protozero::tag_and_type(OSMFormat::Way::packed_uint32_keys, protozero::pbf_wire_type::length_delimited):
399-
keys = varint_range{pbf_way.get_view()};
433+
keys = values_access_uint32{pbf_way.get_view()};
400434
break;
401435
case protozero::tag_and_type(OSMFormat::Way::packed_uint32_vals, protozero::pbf_wire_type::length_delimited):
402-
vals = varint_range{pbf_way.get_view()};
436+
vals = values_access_uint32{pbf_way.get_view()};
403437
break;
404438
case protozero::tag_and_type(OSMFormat::Way::optional_Info_info, protozero::pbf_wire_type::length_delimited):
405439
if (m_read_metadata == osmium::io::read_meta::yes) {
@@ -409,13 +443,13 @@ namespace osmium {
409443
}
410444
break;
411445
case protozero::tag_and_type(OSMFormat::Way::packed_sint64_refs, protozero::pbf_wire_type::length_delimited):
412-
refs = varint_range{pbf_way.get_view()};
446+
refs = values_access_sint64{pbf_way.get_view()};
413447
break;
414448
case protozero::tag_and_type(OSMFormat::Way::packed_sint64_lat, protozero::pbf_wire_type::length_delimited):
415-
lats = varint_range{pbf_way.get_view()};
449+
lats = values_access_sint64{pbf_way.get_view()};
416450
break;
417451
case protozero::tag_and_type(OSMFormat::Way::packed_sint64_lon, protozero::pbf_wire_type::length_delimited):
418-
lons = varint_range{pbf_way.get_view()};
452+
lons = values_access_sint64{pbf_way.get_view()};
419453
break;
420454
default:
421455
pbf_way.skip();
@@ -450,11 +484,11 @@ namespace osmium {
450484
void decode_relation(const data_view& data) {
451485
osmium::builder::RelationBuilder builder{m_buffer};
452486

453-
varint_range keys;
454-
varint_range vals;
455-
varint_range roles;
456-
varint_range refs;
457-
varint_range types;
487+
values_access_uint32 keys;
488+
values_access_uint32 vals;
489+
values_access_int32 roles;
490+
values_access_sint64 refs;
491+
values_access_int32 types;
458492

459493
osm_string_len_type user{"", 0};
460494

@@ -465,10 +499,10 @@ namespace osmium {
465499
builder.object().set_id(pbf_relation.get_int64());
466500
break;
467501
case protozero::tag_and_type(OSMFormat::Relation::packed_uint32_keys, protozero::pbf_wire_type::length_delimited):
468-
keys = varint_range{pbf_relation.get_view()};
502+
keys = values_access_uint32{pbf_relation.get_view()};
469503
break;
470504
case protozero::tag_and_type(OSMFormat::Relation::packed_uint32_vals, protozero::pbf_wire_type::length_delimited):
471-
vals = varint_range{pbf_relation.get_view()};
505+
vals = values_access_uint32{pbf_relation.get_view()};
472506
break;
473507
case protozero::tag_and_type(OSMFormat::Relation::optional_Info_info, protozero::pbf_wire_type::length_delimited):
474508
if (m_read_metadata == osmium::io::read_meta::yes) {
@@ -478,13 +512,13 @@ namespace osmium {
478512
}
479513
break;
480514
case protozero::tag_and_type(OSMFormat::Relation::packed_int32_roles_sid, protozero::pbf_wire_type::length_delimited):
481-
roles = varint_range{pbf_relation.get_view()};
515+
roles = values_access_int32{pbf_relation.get_view()};
482516
break;
483517
case protozero::tag_and_type(OSMFormat::Relation::packed_sint64_memids, protozero::pbf_wire_type::length_delimited):
484-
refs = varint_range{pbf_relation.get_view()};
518+
refs = values_access_sint64{pbf_relation.get_view()};
485519
break;
486520
case protozero::tag_and_type(OSMFormat::Relation::packed_MemberType_types, protozero::pbf_wire_type::length_delimited):
487-
types = varint_range{pbf_relation.get_view()};
521+
types = values_access_int32{pbf_relation.get_view()};
488522
break;
489523
default:
490524
pbf_relation.skip();
@@ -514,7 +548,7 @@ namespace osmium {
514548
build_tag_list(builder, keys, vals);
515549
}
516550

517-
void build_tag_list_from_dense_nodes(osmium::builder::NodeBuilder& builder, varint_range& tags) {
551+
void build_tag_list_from_dense_nodes(osmium::builder::NodeBuilder& builder, values_access_int32& tags) {
518552
osmium::builder::TagListBuilder tl_builder{builder};
519553
while (!tags.empty()) {
520554
const auto idx = tags.next_int32();
@@ -531,25 +565,25 @@ namespace osmium {
531565
}
532566

533567
void decode_dense_nodes_without_metadata(const data_view& data) {
534-
varint_range ids;
535-
varint_range lats;
536-
varint_range lons;
537-
varint_range tags;
568+
values_access_sint64 ids;
569+
values_access_sint64 lats;
570+
values_access_sint64 lons;
571+
values_access_int32 tags;
538572

539573
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes{data};
540574
while (pbf_dense_nodes.next()) {
541575
switch (pbf_dense_nodes.tag_and_type()) {
542576
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_id, protozero::pbf_wire_type::length_delimited):
543-
ids = varint_range{pbf_dense_nodes.get_view()};
577+
ids = values_access_sint64{pbf_dense_nodes.get_view()};
544578
break;
545579
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_lat, protozero::pbf_wire_type::length_delimited):
546-
lats = varint_range{pbf_dense_nodes.get_view()};
580+
lats = values_access_sint64{pbf_dense_nodes.get_view()};
547581
break;
548582
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_lon, protozero::pbf_wire_type::length_delimited):
549-
lons = varint_range{pbf_dense_nodes.get_view()};
583+
lons = values_access_sint64{pbf_dense_nodes.get_view()};
550584
break;
551585
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_int32_keys_vals, protozero::pbf_wire_type::length_delimited):
552-
tags = varint_range{pbf_dense_nodes.get_view()};
586+
tags = values_access_int32{pbf_dense_nodes.get_view()};
553587
break;
554588
default:
555589
pbf_dense_nodes.skip();
@@ -592,22 +626,22 @@ namespace osmium {
592626
void decode_dense_nodes(const data_view& data) {
593627
bool has_info = false;
594628

595-
varint_range ids;
596-
varint_range lats;
597-
varint_range lons;
598-
varint_range tags;
599-
varint_range versions;
600-
varint_range timestamps;
601-
varint_range changesets;
602-
varint_range uids;
603-
varint_range user_sids;
604-
varint_range visibles;
629+
values_access_sint64 ids;
630+
values_access_sint64 lats;
631+
values_access_sint64 lons;
632+
values_access_int32 tags;
633+
values_access_int32 versions;
634+
values_access_sint64 timestamps;
635+
values_access_sint64 changesets;
636+
values_access_sint32 uids;
637+
values_access_sint32 user_sids;
638+
values_access_int32 visibles;
605639

606640
protozero::pbf_message<OSMFormat::DenseNodes> pbf_dense_nodes{data};
607641
while (pbf_dense_nodes.next()) {
608642
switch (pbf_dense_nodes.tag_and_type()) {
609643
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_id, protozero::pbf_wire_type::length_delimited):
610-
ids = varint_range{pbf_dense_nodes.get_view()};
644+
ids = values_access_sint64{pbf_dense_nodes.get_view()};
611645
break;
612646
case protozero::tag_and_type(OSMFormat::DenseNodes::optional_DenseInfo_denseinfo, protozero::pbf_wire_type::length_delimited):
613647
{
@@ -616,22 +650,22 @@ namespace osmium {
616650
while (pbf_dense_info.next()) {
617651
switch (pbf_dense_info.tag_and_type()) {
618652
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_int32_version, protozero::pbf_wire_type::length_delimited):
619-
versions = varint_range{pbf_dense_info.get_view()};
653+
versions = values_access_int32{pbf_dense_info.get_view()};
620654
break;
621655
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_sint64_timestamp, protozero::pbf_wire_type::length_delimited):
622-
timestamps = varint_range{pbf_dense_info.get_view()};
656+
timestamps = values_access_sint64{pbf_dense_info.get_view()};
623657
break;
624658
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_sint64_changeset, protozero::pbf_wire_type::length_delimited):
625-
changesets = varint_range{pbf_dense_info.get_view()};
659+
changesets = values_access_sint64{pbf_dense_info.get_view()};
626660
break;
627661
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_sint32_uid, protozero::pbf_wire_type::length_delimited):
628-
uids = varint_range{pbf_dense_info.get_view()};
662+
uids = values_access_sint32{pbf_dense_info.get_view()};
629663
break;
630664
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_sint32_user_sid, protozero::pbf_wire_type::length_delimited):
631-
user_sids = varint_range{pbf_dense_info.get_view()};
665+
user_sids = values_access_sint32{pbf_dense_info.get_view()};
632666
break;
633667
case protozero::tag_and_type(OSMFormat::DenseInfo::packed_bool_visible, protozero::pbf_wire_type::length_delimited):
634-
visibles = varint_range{pbf_dense_info.get_view()};
668+
visibles = values_access_int32{pbf_dense_info.get_view()};
635669
break;
636670
default:
637671
pbf_dense_info.skip();
@@ -640,13 +674,13 @@ namespace osmium {
640674
}
641675
break;
642676
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_lat, protozero::pbf_wire_type::length_delimited):
643-
lats = varint_range{pbf_dense_nodes.get_view()};
677+
lats = values_access_sint64{pbf_dense_nodes.get_view()};
644678
break;
645679
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_sint64_lon, protozero::pbf_wire_type::length_delimited):
646-
lons = varint_range{pbf_dense_nodes.get_view()};
680+
lons = values_access_sint64{pbf_dense_nodes.get_view()};
647681
break;
648682
case protozero::tag_and_type(OSMFormat::DenseNodes::packed_int32_keys_vals, protozero::pbf_wire_type::length_delimited):
649-
tags = varint_range{pbf_dense_nodes.get_view()};
683+
tags = values_access_int32{pbf_dense_nodes.get_view()};
650684
break;
651685
default:
652686
pbf_dense_nodes.skip();

0 commit comments

Comments
 (0)