FlatCityBuf C++ reader 0.8.0
Native C++17 reader for FlatCityBuf, the cloud-optimized CityJSON format
Loading...
Searching...
No Matches
fcb Namespace Reference

Namespaces

namespace  detail
 

Classes

struct  AttrCondition
 One condition of an attribute query. More...
 
struct  AttributeIndexEntry
 One indexable (column, value) pair pulled out of a feature for the static B+tree builder (M6). More...
 
struct  AttributeIndexInfo
 One attribute column's B+tree index metadata, as recorded in the header (AttributeIndex, header.fbs). More...
 
struct  AttrIndexInfo
 Where one column's B+tree index lives, and how it is shaped. More...
 
struct  AttrQueryOptions
 
struct  AttrValue
 One decoded attribute value. More...
 
struct  BBox
 A 2D query rectangle. More...
 
struct  BtreeEntry
 One (key, feature byte offset) pair to be indexed. More...
 
class  BufferedRangeReader
 Caching decorator: over-fetches to min_req_size and serves subsequent reads inside the cached window without touching the inner reader. More...
 
struct  BuiltBtreeIndex
 The finished index: the flat node array concatenated with the payload section (mirrors Stree::stream_write, stree.rs:1575-1589), plus the two header fields (AttributeIndexInfo.branching_factor/ .num_unique_items, M4's header_serializer.hpp) that only the builder itself can compute – branching_factor here is just the caller's own value echoed back (kept alongside the bytes so a caller building several columns' indices doesn't have to separately remember what it asked for each one), and num_unique_items counts distinct KEYS, not input entries. More...
 
struct  ColumnInfo
 One attribute column's schema, copied out of the header. More...
 
struct  CoType
 A CityObjectType tag, plus the verbatim CityJSON name when the tag is ExtensionObject (which has no spelling of its own). More...
 
struct  CurlOptions
 
class  CurlRangeReader
 HTTP range-request adapter, opt-in via the FCB_WITH_CURL CMake option. More...
 
struct  EncodedGeometry
 Everything one CityJSON geometry object flattens to. More...
 
class  Error
 Every failure the library reports is one of these. More...
 
class  FcbReader
 The library's entry point. More...
 
class  FcbWriter
 Streaming writer for one .fcb file, mirroring Rust's own FcbWriter (writer/mod.rs) shape: each add_feature call encodes and spools that feature's bytes to a private temporary file rather than keeping every encoded feature in memory at once – the same reason Rust's own writer uses the tempfile crate. More...
 
struct  FcbWriterOptions
 Configuration for FcbWriter. More...
 
class  Feature
 One decoded feature that OWNS the bytes it points into. More...
 
class  FeatureIterator
 Single-pass iterator over features. Not copyable. More...
 
struct  FileInfo
 Everything a caller normally wants from the header, as owned values. More...
 
struct  FileLayout
 Byte offsets of each section. More...
 
class  FileRangeReader
 Local-file adapter. More...
 
struct  GMBoundaries
 Flattened geometry boundaries: a flat vertex-index list plus one count array per level of the dimensional hierarchy (rings-per-surface, surfaces-per-shell, shells-per-solid). More...
 
struct  GMSemantics
 Flattened semantics: surfaces is the CityJSON semantics.surfaces array, passed through verbatim (FlatBuffers SemanticObject encoding, including its "other" attributes, is M3's job). More...
 
class  HeaderView
 A parsed header that OWNS its backing bytes. More...
 
struct  HeaderWriterOptions
 Configuration for header writing. More...
 
class  KeyValue
 A decoded index key. More...
 
struct  LevelBound
 Half-open [start, end) node index range for one tree level, in the flat node array shared by every level. More...
 
struct  MaterialMapping
 One theme's material mapping. More...
 
struct  NodeItem
 One R-tree node entry: 4 doubles then a u64, all little-endian, 40 bytes with no padding (packed_rtree/mod.rs:23-33). More...
 
struct  ParsedReferenceSystem
 A metadata.referenceSystem URL, parsed into its OGC three-element form. More...
 
struct  PocOffsets
 Builds the pointOfContact fields of a header from CityJSON metadata.pointOfContact. More...
 
class  RangeReader
 Synchronous byte-range source. More...
 
struct  RangeRequest
 One range in a batched read. data is filled in place by read_batch(). More...
 
struct  SearchResultItem
 One hit from an index traversal. More...
 
class  span
 Minimal C++17 stand-in for std::span: a non-owning view over contiguous memory. More...
 
struct  StreeLevelBound
 Half-open [start, end) node index range for one tree level, in the flat node array shared by every level. More...
 
struct  SurfaceType
 A SemanticSurfaceType tag, plus the verbatim CityJSON name when the tag is ExtraSemanticSurface. More...
 
struct  TextureMapping
 One theme's texture mapping. More...
 

Typedefs

using UIntView = span< const std::uint32_t >
 
using bytes_view = span< const std::uint8_t >
 The workhorse alias: a read-only view over bytes.
 
using AttrQuery = std::vector< AttrCondition >
 
using AttributeSchema = std::map< std::string, std::pair< std::uint16_t, ::ColumnType > >
 Attribute schema: name -> (column index, column type).
 

Enumerations

enum class  ErrorCode {
  MissingMagicBytes , IllegalHeaderSize , InvalidFlatbuffer , NoIndex ,
  AttributeIndexNotFound , NoColumnsInHeader , MissingRequiredField , UnsupportedColumnType ,
  InvalidAttributeValue , QueryExecutionError , IoError , HttpError ,
  JsonError
}
 Error categories, mirroring fcb_core::error::Error (src/rust/fcb_core/src/error.rs) so the two implementations report the same failures under the same names. More...
 
enum class  GeometryKind : std::uint8_t {
  MultiPoint = 0 , MultiLineString = 1 , MultiSurface = 2 , CompositeSurface = 3 ,
  Solid = 4 , MultiSolid = 5 , CompositeSolid = 6 , GeometryInstance = 7
}
 The FlatBuffers GeometryType enumerators, mirrored here so a caller can name a geometry type without pulling in the generated headers. More...
 
enum class  KeyKind {
  Int8 , UInt8 , Int16 , UInt16 ,
  Int32 , UInt32 , Int64 , UInt64 ,
  Float32 , Float64 , Bool , DateTime ,
  String20 , String50 , String100
}
 The concrete key types the B+tree index can hold. More...
 
enum class  IterationMode { SequentialScan , OffsetList }
 How a FeatureIterator decides what to visit. More...
 
enum class  Operator {
  Eq , Ne , Gt , Ge ,
  Lt , Le
}
 Comparison operators the attribute index supports. More...
 

Functions

std::vector< std::pair< std::string, AttrValue > > decode_attributes (bytes_view blob, const std::vector< ColumnInfo > &schema)
 Decode a feature's attribute blob against the column schema.
 
nlohmann::json attributes_to_json (bytes_view blob, const std::vector< ColumnInfo > &schema)
 Same decode, rendered as a JSON object for CityJSON emission.
 
nlohmann::json to_cityjson_metadata (const HeaderView &header)
 The CityJSON metadata envelope: type, version, transform, extent, CRS.
 
nlohmann::json to_cityjson_feature (const Feature &feature, const HeaderView &header)
 One feature as a CityJSONFeature object.
 
std::string city_object_type_name (std::uint8_t type)
 CityJSON name for a CityObjectType enumerator, e.g.
 
std::string semantic_surface_type_name (std::uint8_t type)
 CityJSON name for a SemanticSurfaceType enumerator, e.g.
 
nlohmann::json decode_boundaries (GeometryKind type, UIntView solids, UIntView shells, UIntView surfaces, UIntView strings, UIntView indices)
 Rebuild CityJSON's nested boundaries from the five flattened arrays, at the depth type implies.
 
nlohmann::json decode_semantics_values (GeometryKind type, UIntView solids, UIntView shells, UIntView values)
 Rebuild the nested semantics values array from the flat run of semantic indices.
 
nlohmann::json decode_material_values (GeometryKind type, UIntView solids, UIntView shells, UIntView vertices)
 Rebuild the values array of one material theme from a MaterialMapping.
 
nlohmann::json decode_texture_values (GeometryKind type, UIntView solids, UIntView shells, UIntView surfaces, UIntView strings, UIntView vertices)
 Rebuild the values array of one texture theme from a TextureMapping.
 
std::string geometry_type_name (std::uint8_t type)
 CityJSON name for a GeometryType enumerator, e.g.
 
HeaderView read_header (std::shared_ptr< RangeReader > reader)
 Read and validate the file preamble and header.
 
std::size_t key_serialized_size (KeyKind kind)
 Serialized width in bytes. DateTime is 12: i64 seconds + u32 nanos.
 
std::vector< std::uint8_t > encode_key (const KeyValue &v)
 
KeyValue decode_key (KeyKind kind, bytes_view b)
 
int compare_keys (const KeyValue &a, const KeyValue &b)
 Three-way comparison.
 
KeyValue key_min (KeyKind kind)
 Sentinels used to lower open-ended range queries.
 
KeyValue key_max (KeyKind kind)
 
KeyKind key_kind_for_column (std::uint8_t column_type)
 Column type to key kind, following what the WRITER emits.
 
bool check_magic_bytes (bytes_view b)
 Mirrors fcb_core::check_magic_bytes (src/rust/fcb_core/src/lib.rs:56-58).
 
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).
 
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 overflows.
 
void validate_layout_against_size (const FileLayout &l, std::uint64_t total_size)
 Throws unless the computed sections fit inside the resource.
 
std::uint64_t rtree_num_nodes (std::uint64_t num_items, std::uint16_t node_size)
 Total node count in the tree, per the Rust level-bounds loop (packed_rtree/mod.rs:342-375).
 
std::vector< LevelBoundrtree_level_bounds (std::uint64_t num_items, std::uint16_t node_size)
 Mirrors generate_level_bounds (packed_rtree/mod.rs:342-375).
 
std::vector< SearchResultItemrtree_search_bbox (RangeReader &reader, std::uint64_t index_begin, std::uint64_t num_items, std::uint16_t node_size, const BBox &query)
 Breadth-first bbox search over the packed R-tree, reading nodes through the supplied reader.
 
bool is_payload_ref (std::uint64_t off)
 
std::uint64_t payload_offset (std::uint64_t off)
 
std::uint64_t stree_num_nodes (std::uint64_t num_items, std::uint16_t branching_factor)
 Total node count.
 
std::vector< StreeLevelBoundstree_level_bounds (std::uint64_t num_items, std::uint16_t branching_factor)
 Mirrors Stree::generate_level_bounds (stree.rs:474-508).
 
std::vector< std::uint64_t > decode_payload_entry (bytes_view b)
 Decode a payload entry: u32 count then count x u64, all little-endian.
 
void encode_payload_entry (std::vector< std::uint8_t > &out, const std::vector< std::uint64_t > &offsets)
 Encode a payload entry: u32 count then count x u64, all little-endian (mirrors PayloadEntry::serialize, payload.rs:42-49).
 
std::vector< SearchResultItemstree_query (RangeReader &reader, const AttrIndexInfo &index, KeyKind kind, Operator op, const KeyValue &value)
 Run one condition against one column's index blob, returning candidate feature offsets (relative to the features section).
 
void add_attributes (AttributeSchema &schema, const nlohmann::ordered_json &attrs)
 Adds every member of a JSON object to schema, assigning each new, non-null name the next free column index, in the order attrs's own members appear (see the ordered_json note above) – NOT alphabetically.
 
std::size_t attr_size (::ColumnType coltype, const nlohmann::ordered_json &colval)
 Byte width one value of coltype occupies in the attribute blob, EXCLUDING the 2-byte column-index prefix every record also carries.
 
std::vector< std::uint8_t > encode_attributes_with_schema (const nlohmann::ordered_json &attr, const AttributeSchema &schema)
 Encodes attr (a CityJSON attributes object) against schema: repeated [u16 LE column index][value] records, one per schema member present and non-null in attr, in ascending column-index order (NOT attr's own JSON key order).
 
::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::Column > > > to_columns (::flatbuffers::FlatBufferBuilder &fbb, const AttributeSchema &schema)
 Builds the Column vector for Header.columns or CityObject.columns, in ascending column-index order.
 
std::vector< AttributeIndexEntryattribute_to_index_entries (const nlohmann::ordered_json &attr, const AttributeSchema &schema, const std::vector< std::string > &indexing_attr)
 Extracts index entries for indexing_attr from one CityJSON attributes object.
 
std::vector< AttributeIndexEntrycityfeature_to_index_entries (const nlohmann::ordered_json &city_feature, const AttributeSchema &schema, const std::vector< std::string > &indexing_attr)
 Same, over every object in one CityJSONFeature's CityObjects, visited in ascending object-id order (not JSON key order, which need not be stable) so that duplicate-key payload ordering in the eventual B+tree is reproducible.
 
BuiltBtreeIndex build_static_btree (const std::vector< BtreeEntry > &entries, KeyKind kind, std::uint16_t branching_factor)
 Builds one column's complete attribute index blob from its (key, offset) entries.
 
CoType city_object_type_from_name (const std::string &name)
 Maps a CityJSON CityObject type string to the FlatBuffers tag.
 
SurfaceType semantic_surface_type_from_name (const std::string &name)
 Maps a CityJSON semantic surface type string to the FlatBuffers tag.
 
::flatbuffers::Offset<::Appearance > to_appearance (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &appearance)
 Builds the Appearance table (materials, textures, UV vertices, default themes) from a CityJSON appearance object.
 
::flatbuffers::Offset<::Geometry > to_geometry (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &geometry, const AttributeSchema *semantic_attr_schema)
 Builds one Geometry table – boundaries, and whatever semantics, material and texture it carries – from a CityJSON geometry object (everything but a GeometryInstance, which to_geometry_instance handles).
 
::flatbuffers::Offset<::GeometryInstanceto_geometry_instance (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &geometry)
 Builds a GeometryInstance table: the template index, the 4x4 transformation matrix, and the single-element boundaries array holding the reference vertex index.
 
::GeographicalExtent to_geographical_extent (const std::array< double, 6 > &extent)
 Builds a GeographicalExtent struct from a 6-element [minx,miny,minz,maxx,maxy,maxz] array.
 
::flatbuffers::Offset<::CityObject > to_city_object (::flatbuffers::FlatBufferBuilder &fbb, const std::string &id, const nlohmann::ordered_json &co, const AttributeSchema &attr_schema, const AttributeSchema *semantic_attr_schema)
 Builds one CityObject table: type, geographical extent, geometry (split into non-instance and GeometryInstance entries), attributes (against attr_schema, or the object's own schema when its attribute keys are not all present in attr_schema), children/children-roles/ parents.
 
std::pair<::flatbuffers::Offset<::CityFeature >, NodeItemto_fcb_city_feature (::flatbuffers::FlatBufferBuilder &fbb, const std::string &id, const nlohmann::ordered_json &city_feature, const AttributeSchema &attr_schema, const AttributeSchema *semantic_attr_schema)
 Builds one CityFeature table – its CityObjects (visited in ascending id order), vertices, and optional feature-level appearance – from a CityJSONFeature JSON object, plus its 2D bounding box over the RAW (untransformed, still-integer) vertex coordinates.
 
GeometryKind geometry_kind_from_name (const std::string &name)
 Maps a CityJSON geometry type string to GeometryKind.
 
GMBoundaries encode_boundaries (GeometryKind kind, const nlohmann::ordered_json &boundaries)
 Flattens boundaries (nested CityJSON boundary arrays, straight off the JSON as parsed – no intermediate typed representation) at exactly the depth kind implies.
 
GMSemantics encode_semantics (const nlohmann::ordered_json &semantics, const GMBoundaries &boundaries)
 Flattens semantics (the CityJSON semantics object: surfaces plus values), using boundaries's shell/solid counts to expand a null shell or solid into the right number of per-surface nulls (there is no wire encoding for a whole-null shell in semantics, unlike material).
 
std::vector< MaterialMappingencode_material (const nlohmann::ordered_json &material)
 Flattens material (the CityJSON geometry.material object: theme name -> {"value": N} / {"values": [...]} / {"values": null}).
 
std::vector< TextureMappingencode_texture (const nlohmann::ordered_json &texture)
 Flattens texture (the CityJSON geometry.texture object).
 
EncodedGeometry encode (const nlohmann::ordered_json &geometry)
 Flattens one CityJSON geometry object – its boundaries and whatever semantics, material and texture it carries – into the FlatCityBuf arrays.
 
::Transform to_transform (const nlohmann::ordered_json &transform)
 Builds the Transform struct (scale + translate) from CityJSON's top-level transform member.
 
std::optional< ParsedReferenceSystemparse_reference_system (const std::string &url)
 Parses a referenceSystem URL (https://www.opengis.net/def/crs/{authority}/{version}/{code}, per cjseq2's ReferenceSystem::from_url) into its three OGC elements.
 
::flatbuffers::Offset<::ReferenceSystem > to_reference_system (::flatbuffers::FlatBufferBuilder &fbb, const ParsedReferenceSystem &ref_sys)
 Builds the ReferenceSystem table from a parsed metadata.referenceSystem URL.
 
::flatbuffers::Offset<::Extension > to_extension (::flatbuffers::FlatBufferBuilder &fbb, const std::string &name, const std::string &url, const std::string &version)
 Builds one extensions entry: only name/url/version are written (the schema document itself is never fetched or embedded).
 
::flatbuffers::Offset<::flatbuffers::Vector< const ::DoubleVertex * > > to_templates_vertices (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &vertices_templates)
 Builds Header.templates_vertices from CityJSON's geometry-templates.vertices-templates (f64 precision, unlike a feature's own int32 vertices).
 
PocOffsets to_point_of_contact (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &poc)
 
::flatbuffers::Offset<::Header > to_fcb_header (::flatbuffers::FlatBufferBuilder &fbb, const nlohmann::ordered_json &cj, const HeaderWriterOptions &options, const AttributeSchema &attr_schema, const AttributeSchema *semantic_attr_schema, const std::vector< AttributeIndexInfo > *attribute_indices_info)
 Builds the whole Header table from the CityJSON metadata line (the first line of a CityJSONSeq: type/version/transform/metadata/ geometry-templates/appearance/extensions), the writer options, and the attribute schema(s).
 
std::uint32_t hilbert (std::uint32_t x, std::uint32_t y)
 The Hilbert curve index of point (x, y) on a 65536x65536 grid (16 bits per axis).
 
std::uint32_t hilbert_bbox (const NodeItem &r, std::uint32_t hilbert_max, const NodeItem &extent)
 A NodeItem's Hilbert index: its bbox center, scaled into [0, hilbert_max] against extent, fed through hilbert.
 
void hilbert_sort (std::vector< NodeItem > &items, const NodeItem &extent)
 Sorts items in place by descending Hilbert index (the item furthest along the curve first) – a STABLE sort, matching Rust's slice sort_by guarantee.
 
NodeItem calc_extent (const std::vector< NodeItem > &nodes)
 The bbox union of every item, via repeated NodeItem::expand starting from NodeItem::empty(0).
 
std::vector< NodeItembuild_packed_rtree (const std::vector< NodeItem > &nodes, const NodeItem &extent, std::uint16_t node_size)
 Builds the full flat packed-R-tree node array (leaves first in nodes's own order at the array's tail per rtree_level_bounds, then every internal level above it, bottom-up) from already Hilbert-sorted leaf nodes with their FINAL byte offsets already set.
 
std::vector< std::uint8_t > encode_packed_rtree (const std::vector< NodeItem > &tree)
 Serializes every node in tree (as returned by build_packed_rtree) in array order, 40 bytes each.
 

Variables

constexpr std::size_t kMagicBytesSize = 8
 
constexpr std::size_t kHeaderSizeSize = 4
 
constexpr std::size_t kHeaderMinBufferSize = 8
 
constexpr std::size_t kHeaderMaxBufferSize = 1024ULL * 1024ULL * 512ULL
 
constexpr std::uint8_t kVersion = 1
 
constexpr std::size_t kNodeItemSize = 40
 
constexpr std::uint16_t kDefaultNodeSize = 16
 
constexpr std::uint64_t kMaxFeatureSize = 256ULL * 1024ULL * 1024ULL
 Hard ceiling on a single feature's byte length, enforced before allocating.
 
constexpr std::uint64_t kPayloadTag = 1ULL << 63
 The MSB of a leaf offset marks a payload reference rather than a direct feature offset (stree.rs:15-17).
 
constexpr std::uint64_t kPayloadMask = ~kPayloadTag
 
constexpr std::uint16_t kDefaultBranchingFactor = 16
 Mirrors static_btree::DEFAULT_BRANCHING_FACTOR (static_btree/mod.rs:19), used whenever a caller requests an attribute index without naming an explicit branching factor.
 
static constexpr std::size_t kBodyAlignPad = 0
 No padding needed.
 
static constexpr std::size_t kBodyAlignPad = 0
 No padding needed; see the note in header.cpp.
 

Typedef Documentation

◆ AttributeSchema

using fcb::AttributeSchema = typedef std::map<std::string, std::pair<std::uint16_t, ::ColumnType> >

Attribute schema: name -> (column index, column type).

std::map here is just a lookup table – its own key order is never read; every consumer (to_columns, encode_attributes_with_schema) sorts by the stored column INDEX before emitting anything. That index comes from schema.size() at insert time, so what actually determines column numbering is the ITERATION ORDER of the attrs object passed to add_attributes below – which is why that parameter is nlohmann::ordered_json, not the library's default nlohmann::json.

nlohmann::json's default object type is std::map (alphabetical), and the original design here assumed serde_json::Map was equivalently alphabetical (its documented default, a BTreeMap, absent the preserve_order feature). Empirically, it is not: this workspace's bson dependency (used by fcb_core and fcb_cli) transitively activates serde_json's preserve_order feature for the WHOLE build, so serde_json::Map is actually insertion-ordered here, and Rust's add_attributes assigns column indices in DOCUMENT order, not alphabetical order (confirmed against real fcb-CLI output in the M3 oracle tests – e.g. single_feature.city.jsonl's {"name":...,"n":...} gets name->0, n->1, the reverse of alphabetical). ordered_json preserves that same document order, so this stays byte-compatible.

Definition at line 42 of file attribute.hpp.

◆ AttrQuery

using fcb::AttrQuery = typedef std::vector<AttrCondition>

Definition at line 26 of file stree.hpp.

◆ bytes_view

using fcb::bytes_view = typedef span<const std::uint8_t>

The workhorse alias: a read-only view over bytes.

Definition at line 43 of file span.hpp.

◆ UIntView

using fcb::UIntView = typedef span<const std::uint32_t>

Definition at line 16 of file geometry.hpp.

Enumeration Type Documentation

◆ ErrorCode

enum class fcb::ErrorCode
strong

Error categories, mirroring fcb_core::error::Error (src/rust/fcb_core/src/error.rs) so the two implementations report the same failures under the same names.

Enumerator
MissingMagicBytes 
IllegalHeaderSize 
InvalidFlatbuffer 
NoIndex 
AttributeIndexNotFound 
NoColumnsInHeader 
MissingRequiredField 
UnsupportedColumnType 
InvalidAttributeValue 
QueryExecutionError 
IoError 
HttpError 
JsonError 

Definition at line 11 of file error.hpp.

◆ GeometryKind

enum class fcb::GeometryKind : std::uint8_t
strong

The FlatBuffers GeometryType enumerators, mirrored here so a caller can name a geometry type without pulling in the generated headers.

The values are the declaration order in src/fbs/geometry.fbs and are checked against the generated enum with a static_assert in geometry.cpp.

Enumerator
MultiPoint 
MultiLineString 
MultiSurface 
CompositeSurface 
Solid 
MultiSolid 
CompositeSolid 
GeometryInstance 

Definition at line 22 of file geometry.hpp.

◆ IterationMode

enum class fcb::IterationMode
strong

How a FeatureIterator decides what to visit.

This is an explicit mode rather than "an empty offset list means scan everything": an empty list is also the perfectly normal result of a query that matched nothing, and conflating the two would silently turn a zero-result query into a full scan.

Enumerator
SequentialScan 

walk the features section start to finish

OffsetList 

visit exactly the offsets supplied (possibly none)

Definition at line 29 of file reader.hpp.

◆ KeyKind

enum class fcb::KeyKind
strong

The concrete key types the B+tree index can hold.

StringKey20 exists in the format but the writer never emits it.

Enumerator
Int8 
UInt8 
Int16 
UInt16 
Int32 
UInt32 
Int64 
UInt64 
Float32 
Float64 
Bool 
DateTime 
String20 
String50 
String100 

Definition at line 14 of file key.hpp.

◆ Operator

enum class fcb::Operator
strong

Comparison operators the attribute index supports.

Enumerator
Eq 
Ne 
Gt 
Ge 
Lt 
Le 

Definition at line 17 of file stree.hpp.

Function Documentation

◆ add_attributes()

void fcb::add_attributes ( AttributeSchema schema,
const nlohmann::ordered_json &  attrs 
)

Adds every member of a JSON object to schema, assigning each new, non-null name the next free column index, in the order attrs's own members appear (see the ordered_json note above) – NOT alphabetically.

A non-object attrs becomes a single "json" column, matching the writer's fallback for untyped attribute payloads. Existing names and null values are left alone.

Definition at line 222 of file attribute.cpp.

References key.

◆ attr_size()

std::size_t fcb::attr_size ( ::ColumnType  coltype,
const nlohmann::ordered_json &  colval 
)

Byte width one value of coltype occupies in the attribute blob, EXCLUDING the 2-byte column-index prefix every record also carries.

Definition at line 244 of file attribute.cpp.

References UnsupportedColumnType.

Referenced by encode_attributes_with_schema().

◆ attribute_to_index_entries()

std::vector< AttributeIndexEntry > fcb::attribute_to_index_entries ( const nlohmann::ordered_json &  attr,
const AttributeSchema schema,
const std::vector< std::string > &  indexing_attr 
)

Extracts index entries for indexing_attr from one CityJSON attributes object.

Only Bool, Int, UInt, Long, ULong, Float, Double, String and DateTime columns produce entries – Byte, UByte, Short, UShort, Json and Binary are silently skipped, matching the Rust writer's attribute_to_index_entries exactly (a known, deliberate gap: those types ARE supported by the B+tree builder itself, just never reached through this normal extraction path). A name in indexing_attr absent from attr or from schema is skipped.

Definition at line 382 of file attribute.cpp.

References fcb::KeyValue::from_bool(), fcb::KeyValue::from_datetime(), fcb::KeyValue::from_f32(), fcb::KeyValue::from_f64(), fcb::KeyValue::from_i32(), fcb::KeyValue::from_i64(), fcb::KeyValue::from_string(), fcb::KeyValue::from_u32(), fcb::KeyValue::from_u64(), index, and String50.

Referenced by cityfeature_to_index_entries().

◆ attributes_to_json()

nlohmann::json fcb::attributes_to_json ( bytes_view  blob,
const std::vector< ColumnInfo > &  schema 
)

◆ build_packed_rtree()

std::vector< NodeItem > fcb::build_packed_rtree ( const std::vector< NodeItem > &  nodes,
const NodeItem extent,
std::uint16_t  node_size 
)

Builds the full flat packed-R-tree node array (leaves first in nodes's own order at the array's tail per rtree_level_bounds, then every internal level above it, bottom-up) from already Hilbert-sorted leaf nodes with their FINAL byte offsets already set.

Mirrors PackedRTree::build+init+generate_nodes (packed_rtree/mod.rs:327-397,432-451). Throws fcb::Error for node_size < 2, matching Rust's own assert!(node_size >= 2, ...) – its subsequent .clamp(2, 65535) only narrows the upper bound (a no-op for u16), it does not round an invalid low value up. nodes must be non-empty.

Definition at line 117 of file rtree_builder.cpp.

References fcb::NodeItem::empty(), fcb::LevelBound::end, fcb::NodeItem::expand(), IllegalHeaderSize, node_size, rtree_level_bounds(), and fcb::LevelBound::start.

Referenced by fcb::FcbWriter::write().

◆ build_static_btree()

BuiltBtreeIndex fcb::build_static_btree ( const std::vector< BtreeEntry > &  entries,
KeyKind  kind,
std::uint16_t  branching_factor 
)

Builds one column's complete attribute index blob from its (key, offset) entries.

Every entry's key.kind() must be the same kind. branching_factor below 2 is silently clamped up to 2, matching Stree::build (stree.rs:638-640) exactly – unlike the packed R-tree's build_packed_rtree, which THROWS for an invalid node size, Stree:: build clamps branching_factor before its own init() ever gets a chance to reject it, so a sub-2 value never actually errors through this entry point. Throws fcb::Error only for an empty entries (mirrors Stree::init's OTHER check, Err(Error::InvalidFormat(...)) for zero leaf nodes, stree.rs:456-459 – an attribute with zero indexable values is a normal condition this writer's caller (M7) is expected to skip before ever calling this, not a programmer bug, but Rust's own build() does not special-case it away either).

Definition at line 163 of file btree_builder.cpp.

References AttributeIndexNotFound, encode_key(), key_serialized_size(), kind, stree_level_bounds(), and UnsupportedColumnType.

Referenced by fcb::FcbWriter::write().

◆ calc_extent()

NodeItem fcb::calc_extent ( const std::vector< NodeItem > &  nodes)

The bbox union of every item, via repeated NodeItem::expand starting from NodeItem::empty(0).

Mirrors calc_extent (packed_rtree/mod.rs:308-313). nodes must be non-empty: the identity element (+inf/+inf/-inf/-inf) is never a meaningful result on its own and no caller here needs it (M7 only calls this when features exist).

Definition at line 110 of file rtree_builder.cpp.

References fcb::NodeItem::empty(), and fcb::NodeItem::expand().

Referenced by fcb::FcbWriter::write().

◆ check_magic_bytes()

bool fcb::check_magic_bytes ( bytes_view  b)

Mirrors fcb_core::check_magic_bytes (src/rust/fcb_core/src/lib.rs:56-58).

Compares only bytes [0,3) and [4,7); byte 7 is never validated.

Definition at line 14 of file layout.cpp.

References fcb::span< T >::data(), kMagicBytesSize, kVersion, and fcb::span< T >::size().

◆ city_object_type_from_name()

CoType fcb::city_object_type_from_name ( const std::string &  name)

Maps a CityJSON CityObject type string to the FlatBuffers tag.

A name outside CityJSON's ~33 known object types becomes ExtensionObject plus the name verbatim – never an error. Mirrors to_co_type (writer/serializer.rs:745-792).

Definition at line 126 of file feature_serializer.cpp.

Referenced by to_city_object().

◆ city_object_type_name()

std::string fcb::city_object_type_name ( std::uint8_t  type)

CityJSON name for a CityObjectType enumerator, e.g.

"BuildingPart".

A tag with no CityJSON name of its own – ExtensionObject, whose real name lives in the object's extension_type string, or anything a newer encoder added – becomes "+UnknownCityObject". See the unknown-tag policy note at the top of cityjson.cpp.

Definition at line 559 of file cityjson.cpp.

Referenced by to_cityjson_feature().

◆ cityfeature_to_index_entries()

std::vector< AttributeIndexEntry > fcb::cityfeature_to_index_entries ( const nlohmann::ordered_json &  city_feature,
const AttributeSchema schema,
const std::vector< std::string > &  indexing_attr 
)

Same, over every object in one CityJSONFeature's CityObjects, visited in ascending object-id order (not JSON key order, which need not be stable) so that duplicate-key payload ordering in the eventual B+tree is reproducible.

An object with no attributes member, or an explicit "attributes": null, contributes nothing.

Definition at line 447 of file attribute.cpp.

References attribute_to_index_entries().

Referenced by fcb::FcbWriter::add_feature().

◆ compare_keys()

int fcb::compare_keys ( const KeyValue a,
const KeyValue b 
)

Three-way comparison.

Throws if the kinds differ, rather than inventing an ordering between unrelated types.

Definition at line 272 of file key.cpp.

◆ compute_layout()

FileLayout fcb::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 overflows.

Definition at line 49 of file layout.cpp.

References fcb::FileLayout::header_len, IllegalHeaderSize, kHeaderMaxBufferSize, kHeaderSizeSize, kMagicBytesSize, and rtree_index_size().

◆ decode_attributes()

std::vector< std::pair< std::string, AttrValue > > fcb::decode_attributes ( bytes_view  blob,
const std::vector< ColumnInfo > &  schema 
)

Decode a feature's attribute blob against the column schema.

Wire format (reader/deserializer.rs:249-372): repeated records of a u16 little-endian column index followed by the value, encoded per the column's type. Fixed-width types are packed little-endian; String, DateTime and Json are a u32 little-endian byte length then UTF-8, and Binary is that same length prefix followed by raw bytes.

Throws on a column index absent from the schema, a truncated record, or an out-of-range ColumnType (whose width is unknown, so the rest of the blob cannot be parsed).

Byte, UByte and Binary are decoded here. The Rust reader used to hit unreachable!() on them despite the writer emitting them; that has been fixed upstream, so both implementations handle them.

Definition at line 47 of file attribute.cpp.

References fcb::AttrValue::Binary, fcb::AttrValue::Bool, fcb::span< T >::data(), fcb::AttrValue::Double, fcb::span< T >::empty(), found, fcb::AttrValue::Int, InvalidAttributeValue, fcb::AttrValue::Json, fcb::ColumnInfo::name, fcb::span< T >::size(), fcb::AttrValue::String, fcb::ColumnInfo::type, and fcb::AttrValue::UInt.

Referenced by attributes_to_json(), and fcb::FcbReader::select_attr().

◆ decode_boundaries()

nlohmann::json fcb::decode_boundaries ( GeometryKind  type,
UIntView  solids,
UIntView  shells,
UIntView  surfaces,
UIntView  strings,
UIntView  indices 
)

Rebuild CityJSON's nested boundaries from the five flattened arrays, at the depth type implies.

The encoder always writes one redundant count level above the geometry's own depth (a MultiSurface carries a one-entry shells, a Solid a one-entry solids), except for the 5-deep types. This reader ignores that top count entirely; the old cascading reader used it as its depth signal, which is where all the ambiguity came from.

Mirrors decode_points/decode_rings/decode_surfaces/decode_shells/ decode_solids (geom_decoder.rs:106-146), except for one DELIBERATE divergence: a cursor overrun throws here, where the reference clamps and yields a short array.

This is a choice, not a constraint. Clamping is perfectly safe in C++ – the three appearance decoders below do exactly that, and do not throw. We choose to error because count arrays that disagree with the index array mean the file is corrupt, and reporting corruption is more useful to a caller than a plausible-looking short geometry. Only reachable on a file our own writer could not have produced.

The same reasoning settles an unknown type: it never reaches this function, because geometry_type_name rejects it first. The default: arm in the switch is a C++ formality with no fallback semantics – see the policy note at the top of cityjson.cpp.

Definition at line 164 of file geometry.cpp.

References CompositeSolid, CompositeSurface, GeometryInstance, MultiLineString, MultiPoint, MultiSolid, MultiSurface, shells, fcb::span< T >::size(), Solid, strings, and surfaces.

◆ decode_key()

KeyValue fcb::decode_key ( KeyKind  kind,
bytes_view  b 
)

Definition at line 219 of file key.cpp.

◆ decode_material_values()

nlohmann::json fcb::decode_material_values ( GeometryKind  type,
UIntView  solids,
UIntView  shells,
UIntView  vertices 
)

Rebuild the values array of one material theme from a MaterialMapping.

Material indices sit two levels shallower than boundaries: one index per SURFACE, not per ring. So there is no surfaces/strings argument – shells[i] is the number of material indices in shell i.

material.values is nullable at EVERY level (verified against geomprimitives.schema.json), so a UINT32_MAX entry in shells or solids is a whole null shell or solid and comes back as JSON null, never as an empty array.

Mirrors decode_materials (geom_decoder.rs:339). Unlike decode_boundaries this NEVER throws: the reference reads a missing count as zero and clamps every slice to the vertex array, so a mapping that over-claims yields short or empty entries rather than an error.

Definition at line 268 of file geometry.cpp.

References CompositeSolid, MultiSolid, shells, fcb::span< T >::size(), Solid, vertex, and vertices.

◆ decode_payload_entry()

std::vector< std::uint64_t > fcb::decode_payload_entry ( bytes_view  b)

Decode a payload entry: u32 count then count x u64, all little-endian.

Definition at line 331 of file stree.cpp.

References AttributeIndexNotFound, and fcb::span< T >::size().

◆ decode_semantics_values()

nlohmann::json fcb::decode_semantics_values ( GeometryKind  type,
UIntView  solids,
UIntView  shells,
UIntView  values 
)

Rebuild the nested semantics values array from the flat run of semantic indices.

semantics.values is one level shallower than the boundaries. A semantics mapping carries no count arrays of its own, so the group sizes come from the boundary solids/shells.

UINT32_MAX is null at the leaf. There is no wire encoding for a null shell or solid in semantics; the encoder expands one to a null per surface. Mirrors decode_semantics (geom_decoder.rs:226).

Definition at line 224 of file geometry.cpp.

References CompositeSolid, MultiSolid, shells, fcb::span< T >::size(), and Solid.

◆ decode_texture_values()

nlohmann::json fcb::decode_texture_values ( GeometryKind  type,
UIntView  solids,
UIntView  shells,
UIntView  surfaces,
UIntView  strings,
UIntView  vertices 
)

Rebuild the values array of one texture theme from a TextureMapping.

Texture values nest exactly as deeply as the boundaries – solid, shell, surface, ring – except the innermost list is [texture index, then one UV-vertex index per ring vertex] rather than vertex indices.

Unlike a material, texture.values is nullable ONLY at the leaf: the schema types every intermediate level as a plain "array". So nothing here decodes an intermediate null.

Mirrors decode_textures (geom_decoder.rs:468). Also never throws; see above.

Definition at line 331 of file geometry.cpp.

References CompositeSolid, CompositeSurface, MultiSolid, MultiSurface, shells, fcb::span< T >::size(), Solid, strings, surfaces, and vertices.

◆ encode()

EncodedGeometry fcb::encode ( const nlohmann::ordered_json &  geometry)

Flattens one CityJSON geometry object – its boundaries and whatever semantics, material and texture it carries – into the FlatCityBuf arrays.

geometry is read directly off the parsed JSON (type, boundaries, and optionally semantics/material/texture); a GeometryInstance carries none of these except a differently-shaped boundaries (a single reference vertex index, not nested arrays) that this never touches – it is encoded separately by M3's to_geometry_instance, and yields empty arrays here. Mirrors encode (writer/geom_encoder.rs:102-120).

Definition at line 415 of file geom_encoder.cpp.

References fcb::EncodedGeometry::boundaries, encode_boundaries(), encode_material(), encode_semantics(), encode_texture(), geometry_kind_from_name(), kind, fcb::EncodedGeometry::materials, fcb::EncodedGeometry::semantics, and fcb::EncodedGeometry::textures.

Referenced by encode_packed_rtree(), and to_geometry().

◆ encode_attributes_with_schema()

std::vector< std::uint8_t > fcb::encode_attributes_with_schema ( const nlohmann::ordered_json &  attr,
const AttributeSchema schema 
)

Encodes attr (a CityJSON attributes object) against schema: repeated [u16 LE column index][value] records, one per schema member present and non-null in attr, in ascending column-index order (NOT attr's own JSON key order).

A schema member absent from attr, or explicitly null, is skipped – not zero-filled. Returns an empty vector for a non-object or empty attr.

Definition at line 279 of file attribute.cpp.

References attr_size(), index, and offset.

◆ encode_boundaries()

GMBoundaries fcb::encode_boundaries ( GeometryKind  kind,
const nlohmann::ordered_json &  boundaries 
)

Flattens boundaries (nested CityJSON boundary arrays, straight off the JSON as parsed – no intermediate typed representation) at exactly the depth kind implies.

Mirrors encode_boundaries (writer/geom_encoder.rs:160-189). GeometryKind::GeometryInstance yields an empty GMBoundaries; it is encoded separately (M3).

Definition at line 216 of file geom_encoder.cpp.

References CompositeSolid, CompositeSurface, GeometryInstance, kind, MultiLineString, MultiPoint, MultiSolid, MultiSurface, ring, fcb::GMBoundaries::shells, Solid, surface, and fcb::GMBoundaries::surfaces.

Referenced by encode().

◆ encode_key()

std::vector< std::uint8_t > fcb::encode_key ( const KeyValue v)

Definition at line 147 of file key.cpp.

Referenced by build_static_btree().

◆ encode_material()

std::vector< MaterialMapping > fcb::encode_material ( const nlohmann::ordered_json &  material)

Flattens material (the CityJSON geometry.material object: theme name -> {"value": N} / {"values": [...]} / {"values": null}).

Themes are visited in ascending name order – sorted EXPLICITLY, unlike an attribute schema's document order (writer/attribute.hpp): material corresponds to Rust's HashMap<String, CjMaterialReference>, genuinely unordered, so Rust sorts theme names itself (themes.sort_unstable()) rather than trusting iteration order, and this does the same regardless of what order the input JSON's material object happens to have. A null shell or solid – legal at every level – is recorded as a UINT32_MAX count, not dropped, so it decodes back as null rather than an empty array.

As with encode_semantics, the depth of a values array is determined by sniffing its own JSON shape shallowest-first, mirroring Rust's untagged MaterialValues enum, rather than from the enclosing geometry's type – see that function's doc comment for why this matters for cardinality-inconsistent-but-schema-valid files. Mirrors encode_material (writer/geom_encoder.rs:204-284).

Definition at line 295 of file geom_encoder.cpp.

References fcb::MaterialMapping::kind, fcb::MaterialMapping::NullValues, shell, fcb::MaterialMapping::solids, fcb::MaterialMapping::theme, fcb::MaterialMapping::Value, fcb::MaterialMapping::value, fcb::MaterialMapping::Values, and fcb::MaterialMapping::vertices.

Referenced by encode().

◆ encode_packed_rtree()

std::vector< std::uint8_t > fcb::encode_packed_rtree ( const std::vector< NodeItem > &  tree)

Serializes every node in tree (as returned by build_packed_rtree) in array order, 40 bytes each.

Mirrors PackedRTree::stream_write (packed_rtree/mod.rs:900-906).

Definition at line 173 of file rtree_builder.cpp.

References encode(), and fcb::NodeItem::kSize.

Referenced by fcb::FcbWriter::write().

◆ encode_payload_entry()

void fcb::encode_payload_entry ( std::vector< std::uint8_t > &  out,
const std::vector< std::uint64_t > &  offsets 
)

Encode a payload entry: u32 count then count x u64, all little-endian (mirrors PayloadEntry::serialize, payload.rs:42-49).

Appends to out.

Definition at line 350 of file stree.cpp.

◆ encode_semantics()

GMSemantics fcb::encode_semantics ( const nlohmann::ordered_json &  semantics,
const GMBoundaries boundaries 
)

Flattens semantics (the CityJSON semantics object: surfaces plus values), using boundaries's shell/solid counts to expand a null shell or solid into the right number of per-surface nulls (there is no wire encoding for a whole-null shell in semantics, unlike material).

The depth is determined by SNIFFING values's own JSON shape – trying the shallowest interpretation (a flat array of number-or-null) first, then one array level deeper, then two – rather than from the enclosing geometry's type. This mirrors what Rust's SemanticsValues actually does (an untagged serde enum, whose variants are tried shallowest-first): for ordinary, cardinality-consistent files the sniffed depth always agrees with the geometry-type-implied depth, but they can disagree for a schema-valid-yet-inconsistent file (e.g. a Solid whose semantics.values is written as a flat one-element array instead of properly nested) – shape-sniffing is what makes this port byte-compatible with Rust on those files too, not just the well-formed ones. Mirrors encode_semantics (writer/geom_encoder.rs:379-447).

Definition at line 248 of file geom_encoder.cpp.

References shell, fcb::GMBoundaries::solids, fcb::GMSemantics::surfaces, and fcb::GMSemantics::values.

Referenced by encode().

◆ encode_texture()

std::vector< TextureMapping > fcb::encode_texture ( const nlohmann::ordered_json &  texture)

Flattens texture (the CityJSON geometry.texture object).

texture.values nests exactly as deeply as boundaries itself (one UV-vertex index per boundary vertex index), unlike material, which is one level shallower. Nullable only at the leaf: unlike material, there is no wire encoding for a whole-null intermediate level, so nothing here decodes an intermediate null.

As with encode_semantics/encode_material, depth is sniffed from values's own JSON shape (shallowest-first: a list of TexturedSurface, then of TexturedShell, then of shell-lists), mirroring Rust's untagged TextureValues enum, rather than taken from the enclosing geometry's type. Mirrors encode_texture (writer/geom_encoder.rs:290-361).

Definition at line 369 of file geom_encoder.cpp.

References fcb::TextureMapping::has_values, shell, fcb::TextureMapping::shells, fcb::TextureMapping::solids, surface, and fcb::TextureMapping::theme.

Referenced by encode().

◆ geometry_kind_from_name()

GeometryKind fcb::geometry_kind_from_name ( const std::string &  name)

Maps a CityJSON geometry type string to GeometryKind.

Throws Error{InvalidAttributeValue} on any string outside CityJSON's eight known geometry types.

Definition at line 196 of file geom_encoder.cpp.

References CompositeSolid, CompositeSurface, GeometryInstance, InvalidAttributeValue, MultiLineString, MultiPoint, MultiSolid, MultiSurface, and Solid.

Referenced by encode(), and to_geometry().

◆ geometry_type_name()

std::string fcb::geometry_type_name ( std::uint8_t  type)

CityJSON name for a GeometryType enumerator, e.g.

"MultiSurface".

Throws on a tag outside the eight the spec defines. CityJSON offers no '+'-prefixed extension mechanism for geometry types (unlike City Object types and semantic surface types, which get "+UnknownCityObject" and "+GenericSurface" respectively), so there is no schema-valid string to return and no honest alternative to an error. Mirrors GeometryType::to_cj (geom_decoder.rs); see the policy note at the top of cityjson.cpp.

Definition at line 376 of file geometry.cpp.

References InvalidFlatbuffer.

◆ hilbert()

std::uint32_t fcb::hilbert ( std::uint32_t  x,
std::uint32_t  y 
)

The Hilbert curve index of point (x, y) on a 65536x65536 grid (16 bits per axis).

A fixed bit-twiddling function with no branches or loops – every operation is ^/&/|/<</>> on uint32_t, none of which can overflow in the sense Rust's debug-mode overflow checks mean (those only instrument +/-/*), so this is a direct transliteration of hilbert (packed_rtree/mod.rs:236-289) with no wraparound-semantics concerns.

Definition at line 21 of file rtree_builder.cpp.

Referenced by hilbert_bbox().

◆ hilbert_bbox()

std::uint32_t fcb::hilbert_bbox ( const NodeItem r,
std::uint32_t  hilbert_max,
const NodeItem extent 
)

A NodeItem's Hilbert index: its bbox center, scaled into [0, hilbert_max] against extent, fed through hilbert.

Mirrors hilbert_bbox (packed_rtree/mod.rs:291-298); hilbert_max is always (1 << 16) - 1 in practice (HILBERT_MAX), taken as a parameter only to keep the two constants visible together at the call site, as in Rust.

Definition at line 94 of file rtree_builder.cpp.

References hilbert(), fcb::NodeItem::max_x, fcb::NodeItem::max_y, fcb::NodeItem::min_x, and fcb::NodeItem::min_y.

◆ hilbert_sort()

void fcb::hilbert_sort ( std::vector< NodeItem > &  items,
const NodeItem extent 
)

Sorts items in place by descending Hilbert index (the item furthest along the curve first) – a STABLE sort, matching Rust's slice sort_by guarantee.

Mirrors hilbert_sort (packed_rtree/mod.rs:300-306).

Definition at line 102 of file rtree_builder.cpp.

Referenced by fcb::FcbWriter::write().

◆ is_payload_ref()

bool fcb::is_payload_ref ( std::uint64_t  off)
inline

Definition at line 41 of file stree.hpp.

References kPayloadTag.

◆ key_kind_for_column()

KeyKind fcb::key_kind_for_column ( std::uint8_t  column_type)

Column type to key kind, following what the WRITER emits.

Byte maps to UInt8, not Int8 – see the Byte note in key.cpp.

Takes the raw ubyte rather than the generated ::ColumnType so that consumers of this header never see the generated FlatBuffers API. ColumnInfo::type carries exactly this value.

Definition at line 387 of file key.cpp.

References Bool, DateTime, Float32, Float64, Int16, Int32, Int64, String100, String50, UInt16, UInt32, UInt64, UInt8, and UnsupportedColumnType.

Referenced by fcb::FcbReader::select_attr(), and fcb::FcbWriter::write().

◆ key_max()

◆ key_min()

KeyValue fcb::key_min ( KeyKind  kind)

Sentinels used to lower open-ended range queries.

These reproduce the reference's quirks deliberately: the float maximum is +inf even though NaN sorts above it (so NaN-keyed features are invisible to range queries), and the DateTime minimum is epoch 0 even though the wire format allows negative seconds.

Definition at line 313 of file key.cpp.

References Bool, DateTime, Float32, Float64, fcb::KeyValue::from_bool(), fcb::KeyValue::from_datetime(), fcb::KeyValue::from_f32(), fcb::KeyValue::from_f64(), fcb::KeyValue::from_i16(), fcb::KeyValue::from_i32(), fcb::KeyValue::from_i64(), fcb::KeyValue::from_i8(), fcb::KeyValue::from_string(), fcb::KeyValue::from_u16(), fcb::KeyValue::from_u32(), fcb::KeyValue::from_u64(), fcb::KeyValue::from_u8(), Int16, Int32, Int64, Int8, kind, String100, String20, String50, UInt16, UInt32, UInt64, UInt8, and UnsupportedColumnType.

Referenced by stree_query().

◆ key_serialized_size()

std::size_t fcb::key_serialized_size ( KeyKind  kind)

Serialized width in bytes. DateTime is 12: i64 seconds + u32 nanos.

Definition at line 61 of file key.cpp.

References Bool, DateTime, Float32, Float64, Int16, Int32, Int64, Int8, kind, String100, String20, String50, UInt16, UInt32, UInt64, UInt8, and UnsupportedColumnType.

Referenced by build_static_btree(), and key_max().

◆ parse_reference_system()

std::optional< ParsedReferenceSystem > fcb::parse_reference_system ( const std::string &  url)

Parses a referenceSystem URL (https://www.opengis.net/def/crs/{authority}/{version}/{code}, per cjseq2's ReferenceSystem::from_url) into its three OGC elements.

version/code default to 0 when their segment is absent OR fails to parse as a whole int32 (matching Rust's .parse::<i32>().ok(). unwrap_or(0) exactly – a segment like "7415x" does NOT parse as 7415; it fails whole, same as Rust). Returns std::nullopt when url matches neither the http:// nor https:// OGC prefix – Rust's TryFrom<String> would fail the WHOLE document's deserialization in that case instead, which this milestone does not replicate (out of scope; disclosed here rather than silently matched).

Definition at line 104 of file header_serializer.cpp.

References fcb::ParsedReferenceSystem::authority, fcb::ParsedReferenceSystem::code, and fcb::ParsedReferenceSystem::version.

Referenced by to_fcb_header().

◆ payload_offset()

std::uint64_t fcb::payload_offset ( std::uint64_t  off)
inline

Definition at line 42 of file stree.hpp.

References kPayloadMask.

◆ read_header()

HeaderView fcb::read_header ( std::shared_ptr< RangeReader reader)

Read and validate the file preamble and header.

Takes SHARED ownership so it can construct its own per-query BufferedRangeReader internally (over-fetching the header plus the top R-tree levels in one request, as the Rust HTTP reader does).

Definition at line 199 of file header.cpp.

Referenced by fcb::FcbReader::open().

◆ rtree_index_size()

std::uint64_t fcb::rtree_index_size ( std::uint64_t  num_items,
std::uint16_t  node_size 
)

Mirrors PackedRTree::index_size (packed_rtree/mod.rs:879-898).

Returns bytes. Throws on node_size < 2, num_items == 0, or arithmetic overflow.

Definition at line 26 of file layout.cpp.

References IllegalHeaderSize, kNodeItemSize, and node_size.

Referenced by compute_layout().

◆ rtree_level_bounds()

std::vector< LevelBound > fcb::rtree_level_bounds ( std::uint64_t  num_items,
std::uint16_t  node_size 
)

Mirrors generate_level_bounds (packed_rtree/mod.rs:342-375).

Shared by the reader (rtree_search_bbox) and the writer's R-tree builder (M5) – both need the exact same per-level array layout to agree on where a child index or search cursor actually lands.

Definition at line 125 of file packed_rtree.cpp.

References fcb::detail::ceil_div(), fcb::detail::checked_add(), IllegalHeaderSize, node_size, and NoIndex.

Referenced by build_packed_rtree(), and rtree_search_bbox().

◆ rtree_num_nodes()

std::uint64_t fcb::rtree_num_nodes ( std::uint64_t  num_items,
std::uint16_t  node_size 
)

Total node count in the tree, per the Rust level-bounds loop (packed_rtree/mod.rs:342-375).

Breaks at n == 1 – note this differs from the B+tree, which breaks at n < branching_factor.

Definition at line 107 of file packed_rtree.cpp.

References fcb::detail::ceil_div(), fcb::detail::checked_add(), IllegalHeaderSize, and node_size.

Referenced by rtree_search_bbox().

◆ rtree_search_bbox()

std::vector< SearchResultItem > fcb::rtree_search_bbox ( RangeReader reader,
std::uint64_t  index_begin,
std::uint64_t  num_items,
std::uint16_t  node_size,
const BBox query 
)

Breadth-first bbox search over the packed R-tree, reading nodes through the supplied reader.

Results are returned sorted by feature offset so the caller reads forward through the file.

Definition at line 161 of file packed_rtree.cpp.

References fcb::detail::checked_add(), fcb::detail::checked_mul(), fcb::NodeItem::decode(), index_begin, fcb::NodeItem::intersects(), fcb::NodeItem::kSize, node_size, NoIndex, fcb::NodeItem::offset, fcb::RangeReader::read(), reader, rtree_level_bounds(), and rtree_num_nodes().

Referenced by fcb::FcbReader::select_bbox().

◆ semantic_surface_type_from_name()

SurfaceType fcb::semantic_surface_type_from_name ( const std::string &  name)

Maps a CityJSON semantic surface type string to the FlatBuffers tag.

A name outside CityJSON's 18 known surface types becomes ExtraSemanticSurface plus the name verbatim. Mirrors FcbSemanticSurfaceType::from (writer/serializer.rs:820-883).

Definition at line 134 of file feature_serializer.cpp.

◆ semantic_surface_type_name()

std::string fcb::semantic_surface_type_name ( std::uint8_t  type)

CityJSON name for a SemanticSurfaceType enumerator, e.g.

"RoofSurface".

A tag with no CityJSON name of its own – ExtraSemanticSurface, whose real name lives in the surface's extension_type string, or anything a newer encoder added – becomes "+GenericSurface". Same policy note.

Definition at line 572 of file cityjson.cpp.

◆ stree_level_bounds()

std::vector< StreeLevelBound > fcb::stree_level_bounds ( std::uint64_t  num_items,
std::uint16_t  branching_factor 
)

Mirrors Stree::generate_level_bounds (stree.rs:474-508).

Mirrors Stree::generate_level_bounds (stree.rs:462-497).

Shared by the reader (stree_query) and the writer's B+tree builder (M6) – both need the exact same per-level array layout to agree on where a child index or search cursor actually lands. Named Stree... (not LevelBound, unlike the R-tree's fcb::LevelBound in packed_rtree.hpp) only to avoid a name collision between the two headers – the two types are structurally identical and otherwise unrelated.

The loop divides by branching_factor and stops at n < branching_factor – NOT at n == 1 as the R-tree does. Searching, meanwhile, uses branching_factor - 1 entries per node. Both asymmetries are real: the entry count per node is one less than the fan-out because each entry is a separator key, and the level loop stops as soon as a level fits in one node's worth of separators.

Definition at line 20 of file stree.cpp.

References AttributeIndexNotFound, fcb::detail::ceil_div(), and fcb::detail::checked_add().

Referenced by build_static_btree(), and stree_query().

◆ stree_num_nodes()

std::uint64_t fcb::stree_num_nodes ( std::uint64_t  num_items,
std::uint16_t  branching_factor 
)

Total node count.

NOTE the loop breaks at n < branching_factor, unlike the R-tree's n == 1 (stree.rs:462-497). The asymmetry is deliberate in the reference; do not "fix" it.

Definition at line 313 of file stree.cpp.

References AttributeIndexNotFound, fcb::detail::ceil_div(), and fcb::detail::checked_add().

Referenced by stree_query().

◆ stree_query()

std::vector< SearchResultItem > fcb::stree_query ( RangeReader reader,
const AttrIndexInfo index,
KeyKind  kind,
Operator  op,
const KeyValue value 
)

Run one condition against one column's index blob, returning candidate feature offsets (relative to the features section).

Definition at line 360 of file stree.cpp.

References AttributeIndexNotFound, fcb::detail::checked_add(), fcb::detail::checked_mul(), Eq, Ge, Gt, index, key_max(), key_min(), kind, Le, Lt, Ne, QueryExecutionError, reader, stree_level_bounds(), stree_num_nodes(), String100, String20, and String50.

Referenced by fcb::FcbReader::select_attr().

◆ to_appearance()

flatbuffers::Offset<::Appearance > fcb::to_appearance ( ::flatbuffers::FlatBufferBuilder &  fbb,
const nlohmann::ordered_json &  appearance 
)

Builds the Appearance table (materials, textures, UV vertices, default themes) from a CityJSON appearance object.

Mirrors to_appearance (writer/serializer.rs:533-622); fb_wrap_mode/fb_texture_type/ fb_texture_format are folded in directly since nothing else calls them.

Definition at line 142 of file feature_serializer.cpp.

Referenced by to_fcb_city_feature(), and to_fcb_header().

◆ to_city_object()

flatbuffers::Offset<::CityObject > fcb::to_city_object ( ::flatbuffers::FlatBufferBuilder &  fbb,
const std::string &  id,
const nlohmann::ordered_json &  co,
const AttributeSchema attr_schema,
const AttributeSchema semantic_attr_schema 
)

Builds one CityObject table: type, geographical extent, geometry (split into non-instance and GeometryInstance entries), attributes (against attr_schema, or the object's own schema when its attribute keys are not all present in attr_schema), children/children-roles/ parents.

Mirrors to_city_object (writer/serializer.rs:632-730).

Definition at line 419 of file feature_serializer.cpp.

References city_object_type_from_name(), to_columns(), to_geographical_extent(), to_geometry(), and to_geometry_instance().

Referenced by to_fcb_city_feature().

◆ to_cityjson_feature()

nlohmann::json fcb::to_cityjson_feature ( const Feature feature,
const HeaderView header 
)

One feature as a CityJSONFeature object.

Attributes are decoded against each CityObject's OWN column schema when it declares one, falling back to the header's – see the per-object schema note in the plan. Using the wrong schema yields silent garbage.

Definition at line 682 of file cityjson.cpp.

References attributes_to_json(), fcb::Feature::city_object_count(), city_object_type_name(), fcb::FileInfo::columns, fcb::detail::FeatureAccess::get(), fcb::Feature::id(), fcb::HeaderView::info(), MissingRequiredField, fcb::Feature::object_attributes(), fcb::Feature::object_columns(), fcb::Feature::object_extent(), fcb::Feature::object_has_attributes(), fcb::Feature::object_has_columns(), fcb::Feature::object_id(), and fcb::FileInfo::semantic_columns.

◆ to_cityjson_metadata()

nlohmann::json fcb::to_cityjson_metadata ( const HeaderView header)

The CityJSON metadata envelope: type, version, transform, extent, CRS.

This is the first line of a CityJSONSeq stream.

Definition at line 585 of file cityjson.cpp.

References fcb::detail::HeaderAccess::get(), and fcb::HeaderView::info().

◆ to_columns()

flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::Column > > > fcb::to_columns ( ::flatbuffers::FlatBufferBuilder &  fbb,
const AttributeSchema schema 
)

Builds the Column vector for Header.columns or CityObject.columns, in ascending column-index order.

Definition at line 366 of file attribute.cpp.

Referenced by to_city_object(), and to_fcb_header().

◆ to_extension()

flatbuffers::Offset<::Extension > fcb::to_extension ( ::flatbuffers::FlatBufferBuilder &  fbb,
const std::string &  name,
const std::string &  url,
const std::string &  version 
)

Builds one extensions entry: only name/url/version are written (the schema document itself is never fetched or embedded).

Mirrors to_extension (writer/serializer.rs:378-397).

Definition at line 138 of file header_serializer.cpp.

Referenced by to_fcb_header().

◆ to_fcb_city_feature()

std::pair<::flatbuffers::Offset<::CityFeature >, NodeItem > fcb::to_fcb_city_feature ( ::flatbuffers::FlatBufferBuilder &  fbb,
const std::string &  id,
const nlohmann::ordered_json &  city_feature,
const AttributeSchema attr_schema,
const AttributeSchema semantic_attr_schema 
)

Builds one CityFeature table – its CityObjects (visited in ascending id order), vertices, and optional feature-level appearance – from a CityJSONFeature JSON object, plus its 2D bounding box over the RAW (untransformed, still-integer) vertex coordinates.

Applying the file's Transform scale/translate to that bbox, and everything about hilbert ordering and index assembly, is the caller's job (M7's FcbWriter). Mirrors to_fcb_city_feature (writer/serializer.rs:410-489).

Definition at line 537 of file feature_serializer.cpp.

References to_appearance(), and to_city_object().

Referenced by fcb::FcbWriter::add_feature().

◆ to_fcb_header()

flatbuffers::Offset<::Header > fcb::to_fcb_header ( ::flatbuffers::FlatBufferBuilder &  fbb,
const nlohmann::ordered_json &  cj,
const HeaderWriterOptions options,
const AttributeSchema attr_schema,
const AttributeSchema semantic_attr_schema,
const std::vector< AttributeIndexInfo > *  attribute_indices_info 
)

Builds the whole Header table from the CityJSON metadata line (the first line of a CityJSONSeq: type/version/transform/metadata/ geometry-templates/appearance/extensions), the writer options, and the attribute schema(s).

attribute_indices_info is nullptr before M6 exists / when no attribute indices were configured. Mirrors to_fcb_header (writer/serializer.rs:52-231).

EVERY fbb.CreateString/CreateVector call this function makes – directly or through a helper – happens in the exact sequence Rust's own let bindings run in, never as an inline call argument: FlatBuffers builder calls are side-effecting and append to the buffer in call order, so call order is part of the wire format (a real bug caught by M3's byte-exact oracle, documented in feature_serializer.cpp).

The table itself is assembled via the generated CreateHeader free function, not a hand-sequenced HeaderBuilder: flatc emits Create* in a fixed, width-sorted add_* order (identical across every language backend), and a field's byte offset WITHIN the table is determined by that call order, not by which vtable slot it occupies. Building the HeaderBuilder calls by hand – even with every field present and correct – lays the table out differently from Rust's output and fails byte-exactness despite decoding to identical values; this was a real regression caught by this milestone's own oracle test (test_writer_oracle.cpp).

Definition at line 203 of file header_serializer.cpp.

References fcb::PocOffsets::address_country, fcb::PocOffsets::address_locality, fcb::PocOffsets::address_postcode, fcb::PocOffsets::address_thoroughfare_name, fcb::PocOffsets::address_thoroughfare_number, fcb::PocOffsets::contact_name, fcb::PocOffsets::contact_type, fcb::PocOffsets::email, fcb::HeaderWriterOptions::feature_count, fcb::HeaderWriterOptions::geographical_extent, fcb::HeaderWriterOptions::index_node_size, parse_reference_system(), fcb::PocOffsets::phone, fcb::PocOffsets::role, to_appearance(), to_columns(), to_extension(), to_geographical_extent(), to_geometry(), to_point_of_contact(), to_reference_system(), to_templates_vertices(), to_transform(), and fcb::PocOffsets::website.

Referenced by fcb::FcbWriter::write().

◆ to_geographical_extent()

GeographicalExtent fcb::to_geographical_extent ( const std::array< double, 6 > &  extent)

Builds a GeographicalExtent struct from a 6-element [minx,miny,minz,maxx,maxy,maxz] array.

Shared with the header (M4), which has its own geographicalExtent. Mirrors to_geographical_extent (writer/serializer.rs:233-250).

Definition at line 383 of file feature_serializer.cpp.

Referenced by to_city_object(), and to_fcb_header().

◆ to_geometry()

flatbuffers::Offset<::Geometry > fcb::to_geometry ( ::flatbuffers::FlatBufferBuilder &  fbb,
const nlohmann::ordered_json &  geometry,
const AttributeSchema semantic_attr_schema 
)

Builds one Geometry table – boundaries, and whatever semantics, material and texture it carries – from a CityJSON geometry object (everything but a GeometryInstance, which to_geometry_instance handles).

semantic_attr_schema is nullptr when the file has no semantic attribute schema at all; a present-but-empty schema is a distinct, valid state. Mirrors to_geometry (writer/serializer.rs:891-1065).

Definition at line 257 of file feature_serializer.cpp.

References fcb::EncodedGeometry::boundaries, encode(), geometry_kind_from_name(), fcb::GMBoundaries::indices, kind, fcb::EncodedGeometry::materials, fcb::MaterialMapping::NullValues, fcb::EncodedGeometry::semantics, fcb::GMBoundaries::shells, shells, fcb::GMBoundaries::solids, fcb::GMBoundaries::strings, strings, surface, fcb::GMBoundaries::surfaces, surfaces, fcb::EncodedGeometry::textures, fcb::MaterialMapping::Value, fcb::MaterialMapping::Values, and vertices.

Referenced by to_city_object(), and to_fcb_header().

◆ to_geometry_instance()

flatbuffers::Offset<::GeometryInstance > fcb::to_geometry_instance ( ::flatbuffers::FlatBufferBuilder &  fbb,
const nlohmann::ordered_json &  geometry 
)

Builds a GeometryInstance table: the template index, the 4x4 transformation matrix, and the single-element boundaries array holding the reference vertex index.

Throws fcb::Error if geometry's type is not "GeometryInstance" (Rust panic!s here instead – a programmer-error assertion that becomes a catchable exception in a library rather than an abort). Mirrors to_geometry_instance (writer/serializer.rs:1067-1102).

Definition at line 358 of file feature_serializer.cpp.

References InvalidAttributeValue.

Referenced by to_city_object().

◆ to_point_of_contact()

◆ to_reference_system()

flatbuffers::Offset<::ReferenceSystem > fcb::to_reference_system ( ::flatbuffers::FlatBufferBuilder &  fbb,
const ParsedReferenceSystem ref_sys 
)

Builds the ReferenceSystem table from a parsed metadata.referenceSystem URL.

Mirrors to_reference_system (writer/serializer.rs:273-301); code_string is always absent, matching Rust's own None there.

Definition at line 132 of file header_serializer.cpp.

References fcb::ParsedReferenceSystem::authority, fcb::ParsedReferenceSystem::code, and fcb::ParsedReferenceSystem::version.

Referenced by to_fcb_header().

◆ to_templates_vertices()

flatbuffers::Offset<::flatbuffers::Vector< const ::DoubleVertex * > > fcb::to_templates_vertices ( ::flatbuffers::FlatBufferBuilder &  fbb,
const nlohmann::ordered_json &  vertices_templates 
)

Builds Header.templates_vertices from CityJSON's geometry-templates.vertices-templates (f64 precision, unlike a feature's own int32 vertices).

A non-3-number-array element is skipped, not guessed at. Mirrors to_templates_vertices (writer/serializer.rs:1107-1125).

Definition at line 148 of file header_serializer.cpp.

Referenced by to_fcb_header().

◆ to_transform()

Transform fcb::to_transform ( const nlohmann::ordered_json &  transform)

Builds the Transform struct (scale + translate) from CityJSON's top-level transform member.

Mirrors to_transform (writer/serializer.rs:257-265).

Definition at line 95 of file header_serializer.cpp.

Referenced by to_fcb_header().

◆ validate_layout_against_size()

void fcb::validate_layout_against_size ( const FileLayout l,
std::uint64_t  total_size 
)

Throws unless the computed sections fit inside the resource.

Call this immediately after compute_layout, before issuing any index read.

Definition at line 70 of file layout.cpp.

References fcb::FileLayout::feature_begin, and IllegalHeaderSize.

Variable Documentation

◆ kBodyAlignPad [1/2]

constexpr std::size_t fcb::kBodyAlignPad = 0
staticconstexpr

No padding needed.

FlatBuffers aligns a size-prefixed buffer's contents relative to the START OF THE BUFFER (prefix included), so placing the buffer at an 8-aligned address – which std::vector's allocation already guarantees – makes every struct inside correctly aligned. Kept as a named constant so the reasoning stays visible and the slicing arithmetic reads the same.

Definition at line 20 of file header.cpp.

Referenced by fcb::FeatureIterator::next().

◆ kBodyAlignPad [2/2]

constexpr std::size_t fcb::kBodyAlignPad = 0
staticconstexpr

No padding needed; see the note in header.cpp.

Definition at line 18 of file reader.cpp.

◆ kDefaultBranchingFactor

constexpr std::uint16_t fcb::kDefaultBranchingFactor = 16
constexpr

Mirrors static_btree::DEFAULT_BRANCHING_FACTOR (static_btree/mod.rs:19), used whenever a caller requests an attribute index without naming an explicit branching factor.

Definition at line 16 of file btree_builder.hpp.

Referenced by fcb::FcbWriter::write().

◆ kDefaultNodeSize

constexpr std::uint16_t fcb::kDefaultNodeSize = 16
constexpr

Definition at line 16 of file layout.hpp.

◆ kHeaderMaxBufferSize

constexpr std::size_t fcb::kHeaderMaxBufferSize = 1024ULL * 1024ULL * 512ULL
constexpr

Definition at line 13 of file layout.hpp.

Referenced by compute_layout().

◆ kHeaderMinBufferSize

constexpr std::size_t fcb::kHeaderMinBufferSize = 8
constexpr

Definition at line 12 of file layout.hpp.

◆ kHeaderSizeSize

constexpr std::size_t fcb::kHeaderSizeSize = 4
constexpr

Definition at line 11 of file layout.hpp.

Referenced by compute_layout().

◆ kMagicBytesSize

constexpr std::size_t fcb::kMagicBytesSize = 8
constexpr

Definition at line 10 of file layout.hpp.

Referenced by check_magic_bytes(), and compute_layout().

◆ kMaxFeatureSize

constexpr std::uint64_t fcb::kMaxFeatureSize = 256ULL * 1024ULL * 1024ULL
constexpr

Hard ceiling on a single feature's byte length, enforced before allocating.

A crafted 4-byte prefix would otherwise request up to 4 GiB.

Definition at line 20 of file layout.hpp.

Referenced by fcb::FeatureIterator::next().

◆ kNodeItemSize

constexpr std::size_t fcb::kNodeItemSize = 40
constexpr

Definition at line 15 of file layout.hpp.

Referenced by rtree_index_size().

◆ kPayloadMask

constexpr std::uint64_t fcb::kPayloadMask = ~kPayloadTag
constexpr

Definition at line 39 of file stree.hpp.

Referenced by payload_offset().

◆ kPayloadTag

constexpr std::uint64_t fcb::kPayloadTag = 1ULL << 63
constexpr

The MSB of a leaf offset marks a payload reference rather than a direct feature offset (stree.rs:15-17).

Definition at line 38 of file stree.hpp.

Referenced by is_payload_ref().

◆ kVersion

constexpr std::uint8_t fcb::kVersion = 1
constexpr

Definition at line 14 of file layout.hpp.

Referenced by check_magic_bytes().