6#include "../packet/packet.hpp"
8#include "libxr_mem.hpp"
13 : topic_map_([](const uint32_t& a, const uint32_t& b) {
return (a > b) - (a < b); }),
14 queue_(1, buffer_length)
16 ASSERT(buffer_length > PACK_BASE_SIZE);
17 parse_buff_.size_ = buffer_length;
24 ASSERT(topic !=
nullptr);
25 ASSERT(topic->
data_.payload_size != 0);
26 ASSERT(topic->
data_.payload_alignment != 0);
29 ASSERT(topic->
data_.payload_size + PACK_BASE_SIZE <= parse_buff_.size_);
32 topic_map_.Insert(*node, topic->
key);
37 return ParseDataRaw(data,
false,
false);
42 return ParseDataRaw(data,
true, in_isr);
49 (void)queue_.PushBatchBytes(data.
addr_, data.
size_);
53 if (status_ == Status::WAIT_START && !SyncToPacketStart())
58 if (status_ == Status::WAIT_TOPIC && !ReadHeader())
63 if (status_ == Status::WAIT_DATA_CRC)
65 switch (ReadPayload(from_callback, in_isr))
67 case ParseResult::NEED_MORE:
69 case ParseResult::DROPPED:
71 case ParseResult::DELIVERED:
81 auto queue_size = queue_.Size();
82 for (uint32_t i = 0; i < queue_size; i++)
85 queue_.PeekBytes(&prefix);
86 if (prefix == PACKET_PREFIX)
88 status_ = Status::WAIT_TOPIC;
99 if (queue_.Size() <
sizeof(PackedDataHeader))
104 queue_.PopBatchBytes(parse_buff_.addr_,
sizeof(PackedDataHeader));
105 if (!
CRC8::Verify(parse_buff_.addr_,
sizeof(PackedDataHeader)))
111 auto* header =
reinterpret_cast<PackedDataHeader*
>(parse_buff_.addr_);
112 if (header->version != PACKET_VERSION)
118 auto* node = topic_map_.Search<
TopicHandle>(header->topic_name_crc32);
125 data_len_ = header->GetDataLen();
126 current_timestamp_ = header->GetTimestamp();
127 current_topic_ = *node;
128 const auto target_size = current_topic_->
data_.payload_size;
130 if (target_size + PACK_BASE_SIZE > parse_buff_.size_)
136 if (data_len_ + PACK_BASE_SIZE > queue_.length_)
142 status_ = Status::WAIT_DATA_CRC;
148 if (queue_.Size() < data_len_ +
sizeof(uint8_t))
150 return ParseResult::NEED_MORE;
154 reinterpret_cast<uint8_t*
>(parse_buff_.addr_) +
sizeof(PackedDataHeader);
155 queue_.PopBatchBytes(payload_addr, data_len_ +
sizeof(uint8_t));
158 data_len_ +
sizeof(PackedDataHeader) +
sizeof(uint8_t)))
161 return ParseResult::DROPPED;
164 const auto target_size = current_topic_->data_.payload_size;
165 void* publish_addr = payload_addr;
166 if (
reinterpret_cast<uintptr_t
>(payload_addr) %
167 current_topic_->data_.payload_alignment !=
170 publish_addr = parse_buff_.addr_;
171 if (data_len_ >= target_size)
181 auto topic =
Topic(current_topic_);
184 topic.PublishBytesFromServerCallback(publish_addr, target_size, current_timestamp_,
189 topic.PublishBytesFromServer(publish_addr, target_size, current_timestamp_);
193 return ParseResult::DELIVERED;
198 status_ = Status::WAIT_START;
200 current_topic_ =
nullptr;
static bool Verify(const void *raw, size_t len)
验证数据的 CRC8 校验码 / Verifies the CRC8 checksum of the given data
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
static void FastMove(void *dst, const void *src, size_t size)
内存搬移 / Memory move
微秒时间戳 / Microsecond timestamp
Key key
节点键值 (Key associated with the node).
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Data data_
存储的数据 (Stored data).
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
size_t ParseDataRaw(ConstRawData data, bool from_callback, bool in_isr)
ParseData*() 的共享实现 / Shared implementation behind ParseData*()
void Register(TopicHandle topic)
注册一个可接收 packet 的 topic / Register one topic that may receive parsed packets
void ResetParser()
清空当前包的解析上下文并回到找起点状态 / Clear the current packet parsing context and return to the start-search state
size_t ParseData(ConstRawData data)
在普通上下文里喂入一批新字节 / Feed one new byte batch in normal context
ParseResult
一次 payload 阶段处理结果 / Result of one payload-stage handling step
size_t ParseDataFromCallback(ConstRawData data, bool in_isr)
在回调/ISR 路径里喂入一批新字节 / Feed one new byte batch in callback/ISR path
bool ReadHeader()
在已对齐前缀后继续读取并校验完整头部 / Read and validate the full header after the prefix is aligned
bool SyncToPacketStart()
把输入流同步到下一条 packet 起点 / Synchronize the input stream to the next packet start
Server(size_t buffer_length)
构造 parser 并分配内部暂存队列 / Construct the parser and allocate its internal staging queue
ParseResult ReadPayload(bool from_callback, bool in_isr)
读取当前包的 payload 和尾 CRC,并在成功时发布 / Read the payload and trailing CRC of the current packet and publish i...
Topic()
构造一个空 topic 视图 / Construct one empty topic view
constexpr size_t CACHE_LINE_SIZE
兼容旧代码的缓存行别名 / Backward-compatible cache-line alias for existing code