FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
stream_registry.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2026-present FERS Contributors (see AUTHORS.md).
4//
5// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
6
8
9#include <stdexcept>
10
11namespace serial::vita49
12{
13 namespace
14 {
15 [[nodiscard]] std::uint32_t fnv1a32(const std::string& value) noexcept
16 {
17 std::uint32_t hash = 2166136261u;
18 for (const char ch : value)
19 {
20 hash ^= static_cast<std::uint8_t>(ch);
21 hash *= 16777619u;
22 }
23 return hash;
24 }
25 }
26
27 bool StreamRegistry::Key::operator==(const Key& other) const noexcept
28 {
29 return receiver_id == other.receiver_id && receiver_name == other.receiver_name && mode == other.mode;
30 }
31
32 std::size_t StreamRegistry::KeyHash::operator()(const Key& key) const noexcept
33 {
34 return static_cast<std::size_t>(initialStreamId(key));
35 }
36
38 {
39 Key key{.receiver_id = stream.receiver_id, .receiver_name = stream.receiver_name, .mode = stream.mode};
40 if (const auto found = _by_key.find(key); found != _by_key.end())
41 {
42 return found->second;
43 }
44
45 std::uint32_t stream_id = initialStreamId(key);
46 for (std::uint32_t attempts = 0; attempts < 0x7FFFFFFFu; ++attempts)
47 {
48 if (stream_id == 0)
49 {
50 stream_id = 1;
51 }
52 if (!_by_stream_id.contains(stream_id))
53 {
54 _by_key.emplace(key, stream_id);
55 _by_stream_id.emplace(stream_id, key);
56 _descriptors.emplace(stream_id, stream);
57 return stream_id;
58 }
59 stream_id = (stream_id & 0x7FFFFFFFu) + 1u;
60 }
61
62 throw std::runtime_error("Unable to allocate collision-free VITA stream ID");
63 }
64
65 bool StreamRegistry::contains(const std::uint32_t stream_id) const { return _by_stream_id.contains(stream_id); }
66
67 const core::ReceiverStreamDescriptor& StreamRegistry::descriptor(const std::uint32_t stream_id) const
68 {
69 const auto found = _descriptors.find(stream_id);
70 if (found == _descriptors.end())
71 {
72 throw std::out_of_range("Unknown VITA stream ID");
73 }
74 return found->second;
75 }
76
77 std::uint32_t StreamRegistry::initialStreamId(const Key& key) noexcept
78 {
79 const std::string material = std::to_string(key.receiver_id) + ":" + key.receiver_name + ":" + key.mode;
80 std::uint32_t stream_id = fnv1a32(material) & 0x7FFFFFFFu;
81 if (stream_id == 0)
82 {
83 stream_id = 1;
84 }
85 return stream_id;
86 }
87}
const core::ReceiverStreamDescriptor & descriptor(std::uint32_t stream_id) const
bool contains(std::uint32_t stream_id) const
std::uint32_t registerStream(const core::ReceiverStreamDescriptor &stream)
math::Vec3 max