FlatCityBuf C++ reader 0.8.0
Native C++17 reader for FlatCityBuf, the cloud-optimized CityJSON format
Loading...
Searching...
No Matches
layout.cpp
Go to the documentation of this file.
1#include <fcb/layout.hpp>
2
3#include <cstring>
4#include <string>
5
6#include "detail/checked.hpp"
7
8namespace fcb {
9
13
15 if (b.size() < kMagicBytesSize)
16 return false;
17 static const std::uint8_t kFcb[3] = {'f', 'c', 'b'};
18 if (std::memcmp(b.data() + 0, kFcb, 3) != 0)
19 return false;
20 if (std::memcmp(b.data() + 4, kFcb, 3) != 0)
21 return false;
22 // Forward-compat rejection, not equality: a future version byte fails.
23 return b[3] <= kVersion;
24}
25
26std::uint64_t rtree_index_size(std::uint64_t num_items, std::uint16_t node_size) {
27 // Rust asserts node_size >= 2 (packed_rtree/mod.rs:879). 0 or 1 means the
28 // file is corrupt: reject rather than clamp, so we never invent a layout.
29 if (node_size < 2) {
31 "invalid index_node_size: " + std::to_string(node_size));
32 }
33 if (num_items == 0) {
34 // The loop below would never terminate.
35 throw Error(ErrorCode::IllegalHeaderSize, "rtree_index_size requires num_items > 0");
36 }
37 const std::uint64_t ns = node_size;
38 std::uint64_t n = num_items;
39 std::uint64_t num_nodes = n;
40 for (;;) {
41 n = ceil_div(n, ns);
42 num_nodes = checked_add(num_nodes, n, "rtree num_nodes");
43 if (n == 1)
44 break;
45 }
46 return checked_mul(num_nodes, kNodeItemSize, "rtree index size");
47}
48
49FileLayout compute_layout(std::uint32_t header_size, std::uint64_t features_count,
50 std::uint16_t index_node_size, std::uint64_t attr_index_size) {
51 if (header_size < kHeaderMinBufferSize || header_size > kHeaderMaxBufferSize) {
53 "illegal header size: " + std::to_string(header_size));
54 }
55
56 FileLayout l{};
57 l.header_len = kMagicBytesSize + kHeaderSizeSize + header_size;
58 l.rtree_begin = l.header_len;
59 // index_node_size == 0 means "no spatial index" and is legal; any other
60 // value below 2 is corrupt and rtree_index_size rejects it.
61 l.rtree_size = (index_node_size == 0 || features_count == 0)
62 ? 0
63 : rtree_index_size(features_count, index_node_size);
64 l.attr_index_begin = checked_add(l.rtree_begin, l.rtree_size, "attr_index_begin");
65 l.attr_index_size = attr_index_size;
66 l.feature_begin = checked_add(l.attr_index_begin, l.attr_index_size, "feature_begin");
67 return l;
68}
69
70void validate_layout_against_size(const FileLayout& l, std::uint64_t total_size) {
71 if (l.feature_begin > total_size) {
72 throw Error(
74 "sections extend past end of file: feature_begin=" + std::to_string(l.feature_begin) +
75 " total_size=" + std::to_string(total_size));
76 }
77}
78
79} // namespace fcb
Every failure the library reports is one of these.
Definition error.hpp:30
Minimal C++17 stand-in for std::span: a non-owning view over contiguous memory.
Definition span.hpp:13
std::size_t size() const noexcept
Definition span.hpp:26
T * data() const noexcept
Definition span.hpp:25
std::uint64_t checked_mul(std::uint64_t a, std::uint64_t b, const char *what="mul")
Definition checked.hpp:24
std::uint64_t checked_add(std::uint64_t a, std::uint64_t b, const char *what="add")
Definition checked.hpp:16
std::uint64_t ceil_div(std::uint64_t a, std::uint64_t b)
ceil(a / b) without the (a + b - 1) overflow hazard.
Definition checked.hpp:34
std::uint64_t rtree_index_size(std::uint64_t num_items, std::uint16_t node_size)
Mirrors PackedRTree::index_size (packed_rtree/mod.rs:879-898).
Definition layout.cpp:26
constexpr std::size_t kNodeItemSize
Definition layout.hpp:15
constexpr std::size_t kHeaderMaxBufferSize
Definition layout.hpp:13
constexpr std::size_t kHeaderSizeSize
Definition layout.hpp:11
FileLayout compute_layout(std::uint32_t header_size, std::uint64_t features_count, std::uint16_t index_node_size, std::uint64_t attr_index_size)
Throws fcb::Error{IllegalHeaderSize} when header_size is out of range or any size arithmetic overflow...
Definition layout.cpp:49
constexpr std::uint8_t kVersion
Definition layout.hpp:14
void validate_layout_against_size(const FileLayout &l, std::uint64_t total_size)
Throws unless the computed sections fit inside the resource.
Definition layout.cpp:70
bool check_magic_bytes(bytes_view b)
Mirrors fcb_core::check_magic_bytes (src/rust/fcb_core/src/lib.rs:56-58).
Definition layout.cpp:14
constexpr std::size_t kMagicBytesSize
Definition layout.hpp:10
std::uint64_t node_size
Definition stree.cpp:167
Byte offsets of each section.
Definition layout.hpp:32
std::uint64_t header_len
Definition layout.hpp:33
std::uint64_t feature_begin
Definition layout.hpp:38