工作中经常遇到需要在数据流中提取数据帧的任务。这种数据帧一般以某种特定数据序列表示开始(例如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);