一個在數據流中解析、提取數據幀的c++類


工作中經常遇到需要在數據流中提取數據幀的任務。這種數據幀一般以某種特定數據序列表示開始(例如0xa5,0x5a)和結束(0xb5, 0x5b),起始標記間的數據為幀有效數據。為了完成這一任務,包裝了一個簡易的解析類,在性能要求不高場合使用。

2019-08-02升級:

可以用參數 discardTag 控制在解析數據幀時是否帶起始、結束標記數據

解析類代碼如下

 1 #ifndef FRAMEPARSER_H
 2 #define FRAMEPARSER_H
 3 
 4 #include <vector>
 5 #include <algorithm>
 6 #include <iterator>
 7 
 8 template <typename T>
 9 class FrameParser
10 {
11 public:
12     FrameParser(const std::vector<T> &headTag, const std::vector<T> &tailTag, const bool discardTag=true) 
13         : frameHeadTag(headTag), frameTailTag(tailTag), discardFrameTag{ discardTag }
14     {}
15 
16     bool isDiscardFrameTag() const {
17         return discardFrameTag;
18     }
19 
20     template<class It>
21     void append(It f, It l) {
22         buffer.insert(buffer.end(), f, l);
23     }
24     void append(const std::vector<T> &data) {
25         buffer.insert(buffer.end(), data.cbegin(), data.cend());
26     }
27 
28     void parse(std::vector<std::vector<T>>& frames)
29     {
30         auto it_head{ buffer.cbegin() };
31         for (auto it_tail{ std::search(it_head, buffer.cend(), frameTailTag.cbegin(), frameTailTag.cend()) };
32             it_tail != buffer.cend(); it_tail = std::search(it_head, buffer.cend(), frameTailTag.cbegin(), frameTailTag.cend()))
33         {
34             it_head = std::search(it_head, it_tail, frameHeadTag.cbegin(), frameHeadTag.cend());
35             if (it_head != it_tail) {
36                 frames.emplace_back(isDiscardFrameTag() ? it_head + frameHeadTag.size() : it_head
37                     , isDiscardFrameTag() ? it_tail : it_tail + frameTailTag.size());
38             }
39             it_head = std::next(it_tail, frameTailTag.size());
40         }
41 
42         tempBuffer.insert(tempBuffer.end(), it_head, buffer.cend());
43         std::swap(buffer, tempBuffer);
44         tempBuffer.clear();
45     }
46 
47 private:
48     bool discardFrameTag{ true };
49     const std::vector<T> frameHeadTag;
50     const std::vector<T> frameTailTag;
51     std::vector<T> buffer;
52     std::vector<T> tempBuffer;
53 };
54 
55 #endif // FRAMEPARSER_H

 

 使用測試代碼如下

 1     FrameParser<std::uint8_t> parser{{ 0xa5, 0x5a }, { 0xb5, 0x5b }};
 2     std::vector<std::vector<std::uint8_t>> frames;    
 3 
 4     parser.append({
 5         0x01, 0x02, 0x03, 0xb5, 0x5b
 6         , 0xa5, 0x5a, 0x04, 0x05, 0x06, 0x07, 0xb5, 0x5b
 7         , 0xa5, 0x5a, 0x08, 0x09, 0x0a
 8     });
 9     parser.parse(frames);
10 
11     parser.append({ 0x0b, 0xb5, 0x5b, 0xa5, 0x5a, 0x0c });
12     parser.parse(frames);
13 
14     parser.append({ 0x0b, 0xb5 });
15     parser.parse(frames);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM