LCOV - code coverage report
Current view: top level - src/SLIPStream - SLIPParser.hpp (source / functions) Hit Total Coverage
Test: a50220e856a3e6a640349bc2a11ab5c9f66053af Lines: 34 34 100.0 %
Date: 2020-02-08 16:55:39 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AH/STL/cstddef> // std::nullptr, size_t
       4             : #include <AH/STL/utility> // std::forward
       5             : #include <stddef.h>       // size_t
       6             : 
       7             : #include <SLIPStream/SLIP.hpp>
       8             : 
       9             : #include <boost/integer.hpp>
      10             : 
      11             : /// @addtogroup SLIP
      12             : /// @{
      13             : 
      14             : /**
      15             :  * @brief   Class for parsing SLIP packets.
      16             :  */
      17             : class SLIPParser {
      18             :   public:
      19             :     /** 
      20             :      * @brief   Constructor.
      21             :      * 
      22             :      * @param   buffer
      23             :      *          The byte buffer to store the parsed packets.
      24             :      */
      25             :     template <size_t N>
      26             :     SLIPParser(uint8_t (&buffer)[N]) : SLIPParser(buffer, N) {}
      27             : 
      28             :     /**
      29             :      * @brief   Default constructor for a parser without a buffer.
      30             :      */
      31             :     SLIPParser() : SLIPParser(nullptr) {}
      32             : 
      33             :     /**
      34             :      * @brief   Constructor for a parser without a buffer.
      35             :      */
      36             :     SLIPParser(std::nullptr_t) : SLIPParser(nullptr, 0) {}
      37             : 
      38             :     /** 
      39             :      * @brief   Constructor.
      40             :      * 
      41             :      * @param   buffer
      42             :      *          The byte buffer to store the parsed packets.
      43             :      * @param   bufferSize
      44             :      *          The size of the buffer.
      45             :      */
      46          14 :     SLIPParser(uint8_t *buffer, size_t bufferSize)
      47          28 :         : buffer(buffer), bufferSize(bufferSize) {
      48          14 :         reset();
      49          14 :     }
      50             : 
      51             :     /**
      52             :      * @brief   Parse the given byte, and call the callback for each data byte.
      53             :      * 
      54             :      * @tparam  Callback 
      55             :      *          The type of callback function. Should be a callable object that 
      56             :      *          takes a data byte and the index of that byte in the packet:  
      57             :      *          `void callback(uint8_t databyte, size_t index)`
      58             :      *          
      59             :      * @param   c
      60             :      *          The byte to parse.
      61             :      * @param   callback 
      62             :      *          The callback function to call for each data byte.
      63             :      * @retval  0
      64             :      *          The packet is not finished yet.
      65             :      * @retval >0
      66             :      *          The packet was received in its entirety, and the return value is
      67             :      *          the size of the packet in the buffer.  
      68             :      *          If the packet is not larger than the buffer, this will be the 
      69             :      *          same as the size of the packet. If the packet was larger than 
      70             :      *          the buffer, the return value will be the size of the buffer, and
      71             :      *          @ref wasTruncated will return true.
      72             :      */
      73             :     template <class Callback>
      74             :     size_t parse(uint8_t c, Callback callback);
      75             : 
      76             :     /**
      77             :      * @brief   Parse the given byte without using a callback function.
      78             :      * 
      79             :      * @param   c
      80             :      *          The byte to parse.
      81             :      * @retval  0
      82             :      *          The packet is not finished yet.
      83             :      * @retval >0
      84             :      *          The packet was received in its entirety, and the return value is
      85             :      *          the size of the packet in the buffer.  
      86             :      *          If the packet is not larger than the buffer, this will be the 
      87             :      *          same as the size of the packet. If the packet was larger than 
      88             :      *          the buffer, the return value will be the size of the buffer, and
      89             :      *          @ref wasTruncated will return true.
      90             :      */
      91          97 :     size_t parse(uint8_t c) {
      92         170 :         auto cb = [](uint8_t, size_t) {};
      93         194 :         return parse(c, cb);
      94          97 :     }
      95             : 
      96             :     /**
      97             :      * @brief   Check if the previous packet was truncated.
      98             :      * 
      99             :      * @retval  true
     100             :      *          The previous packet didn't fit the buffer. The size returned by
     101             :      *          @ref SLIPParser::parse was smaller than the actual size of the 
     102             :      *          packet.
     103             :      * @retval  false 
     104             :      *          The buffer was large enough to store the previous packet.
     105             :      */
     106           4 :     bool wasTruncated() const { return truncated > 0; }
     107             : 
     108             :     /**
     109             :      * @brief   Get the number of bytes that were truncated due to the previous
     110             :      *          packet being too large for the buffer.
     111             :      */
     112          40 :     size_t numTruncated() const { return truncated; }
     113             : 
     114             :   private:
     115          44 :     void reset() { write = buffer; }
     116             : 
     117             :   private:
     118             :     uint8_t *buffer   = nullptr;
     119          14 :     uint8_t *write    = nullptr;
     120             :     size_t bufferSize = 0;
     121          14 :     size_t truncated  = 0;
     122          14 :     bool escape       = false;
     123             : };
     124             : 
     125             : /// @}
     126             : 
     127             : /// @addtogroup CRC
     128             : /// @{
     129             : 
     130             : /**
     131             :  * @brief   Class for parsing SLIP packets with a CRC checksum to check the 
     132             :  *          integrity of the packets.
     133             :  * 
     134             :  * @tparam  CRC 
     135             :  *          The CRC type to use.
     136             :  */
     137             : template <class CRC>
     138             : class SLIPParserCRC {
     139             :   public:
     140             :     SLIPParserCRC(const SLIPParser &parser) : parser(parser) {}
     141          10 :     SLIPParserCRC(const SLIPParser &parser, CRC &&crc)
     142          10 :         : parser(parser), crc(std::forward<CRC>(crc)) {}
     143             : 
     144             :     /// The integer type of the checksum.
     145             :     using checksum_t = typename boost::uint_t<CRC::bit_count>::least;
     146             : 
     147             :     /**
     148             :      * @brief   Parse the given byte.
     149             :      * 
     150             :      * @param   c
     151             :      *          The byte to parse.
     152             :      * 
     153             :      * @retval  0
     154             :      *          The packet is not finished yet.
     155             :      * @retval >0
     156             :      *          The packet was received in its entirety, and the return value is
     157             :      *          the size of the packet in the buffer.  
     158             :      *          If the packet is not larger than the buffer, this will be the 
     159             :      *          same as the size of the packet. If the packet was larger than 
     160             :      *          the buffer, the return value will be the size of the buffer, and
     161             :      *          @ref wasTruncated will return true.
     162             :      */
     163         187 :     size_t parse(uint8_t c) {
     164             :         // callback that resets the CRC when necessary, and that feeds the 
     165             :         // parsed byte to the CRC
     166         330 :         auto cb = [this](uint8_t c, size_t index) {
     167         143 :             if (index == 0)
     168          11 :                 crc.reset();
     169         143 :             crc(c);
     170         143 :         };
     171             :         // use the standard SLIPParser
     172         187 :         size_t size = parser.parse(c, cb);
     173             : 
     174             :         // Correct the size of the packet for the size of the checksum
     175         187 :         if (size <= sizeof(checksum_t))
     176         176 :             return 0;
     177          11 :         if (parser.numTruncated() < sizeof(checksum_t))
     178           8 :             return size + parser.numTruncated() - sizeof(checksum_t);
     179           3 :         return size;
     180         187 :     }
     181             : 
     182             :     /**
     183             :      * @brief   Check if the previous packet was truncated.
     184             :      * 
     185             :      * @retval  true
     186             :      *          The previous packet didn't fit the buffer. The size returned by
     187             :      *          @ref SLIPParser::parse was smaller than the actual size of the 
     188             :      *          packet.
     189             :      * @retval  false 
     190             :      *          The buffer was large enough to store the previous packet.
     191             :      */
     192          10 :     bool wasTruncated() const { return numTruncated() > 0; }
     193             : 
     194             :     /**
     195             :      * @brief   Get the number of bytes that were truncated due to the previous
     196             :      *          packet being too large for the buffer.
     197             :      */
     198          15 :     size_t numTruncated() const {
     199          15 :         return parser.numTruncated() < sizeof(checksum_t)
     200             :                    ? 0
     201           6 :                    : parser.numTruncated() - sizeof(checksum_t);
     202             :     }
     203             :     /**
     204             :      * @brief   Get the checksum of the previous packet. A checksum of zero 
     205             :      *          indicates that the packet was received correctly.
     206             :      */
     207          11 :     checksum_t checksum() const { return crc.checksum(); }
     208             : 
     209             :   private:
     210             :     SLIPParser parser;
     211             :     CRC crc;
     212             : };
     213             : 
     214             : /// @}
     215             : 
     216             : #include "SLIPParser.ipp"

Generated by: LCOV version 1.14-6-g40580cd