flatudp: the signal-list codec, with a hand-computed decode check

This commit is contained in:
Martino Ferrari committed 2026-11-02 00:58:02 +01:00
1 parent dde2dad5b1
commit 6e8e71b32f
6 files changed
+311

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2026 Martino Ferrari
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace udpscope::flatudp {
/// The numeric value is the `SignalInfo::type_code` (the order of the client library's `UDPS_T_*`).
enum class Type : std::uint8_t { U8 = 0, I8, U16, I16, U32, I32, U64, I64, F32, F64 };
constexpr std::uint32_t kMaxCount = 4096;
constexpr std::size_t kMaxDatagram = 65507; ///< the largest UDP payload over IPv4
/// One signal of the sender's datagram: `count` consecutive values of `type`.
struct Row {
std::string name;
Type type = Type::F32;
std::uint32_t count = 1;
bool operator==(const Row&) const = default;
};
std::size_t type_size(Type t);
const char* type_name(Type t); ///< "uint8" ... "float64"
bool parse_type(const std::string& s, Type& out);
/// The bytes one datagram must have: the sum of `type_size * count`.
std::size_t datagram_size(const std::vector<Row>& rows);
/// True when no row is a vector. Such a list can be batched, several datagrams to a frame.
bool all_scalar(const std::vector<Row>& rows);
/// `name:type[,name:type[count]...]`; a count of 1 is written without brackets.
std::string format(const std::vector<Row>& rows);
/// The inverse of `format`. Whitespace around names, types and counts is ignored. An empty text
/// is an empty list (and not an error: `problem` reports it). Returns an error in words, empty
/// on success; `rows` is empty after a failure.
std::string parse(const std::string& text, std::vector<Row>& rows);
/// The first reason this list cannot describe a datagram, in words for the user; empty when valid.
std::string problem(const std::vector<Row>& rows);
/// Decodes one datagram of `datagram_size(rows)` bytes to doubles, row by row, byte-swapping when
/// `big_endian` differs from the host. Appends to `cols[s]`; the caller clears them between uses.
void decode_datagram(const std::vector<Row>& rows, const std::uint8_t* data, bool big_endian,
std::vector<std::vector<double>>& cols);
} // namespace udpscope::flatudp