The following encoder can be used to encode frames into a byte stream. It operates on complete buffers (i.e. this is not a streaming encoder) but is fast and easy to use.
/* * Author: Uli Köhler - techoverflow.net * License: CC0 1.0 Universal * * Description: * This is a C++ implementation of a buffer-based SLIP encoder. * It can be used to encode frames unambiguously into a stream of bytes. * The encoder does not use any memory allocation, but instead requires * the caller to provide a buffer for the encoded data - hence being * ideally suited for use in embedded systems */ #pragma once #include <cstdint> #include <cstddef> #define SLIP_END ((uint8_t)0300) // SLIP end of packet character #define SLIP_ESC ((uint8_t)0333) // SLIP escape character #define SLIP_ESCEND ((uint8_t)0334) // Escaped END data byte #define SLIP_ESCESC ((uint8_t)0335) // Escaped ESC data byte // Return value of slip_encode_packet if the output buffer is not large enough #define SLIP_ENCODE_ERROR SIZE_MAX // Maximum value of size_t /** * Determine the packet length when sending the given buffer [p] using SLIP. * This DOES NOT ENCODE ANYTHING, it just determines the length * which an encoded version of the data would have * @return The number of bytes a SLIP encoded version of [in] would consume */ size_t slip_packet_length(const uint8_t* in, size_t inlen); /** * Encode given input data using SLIP, saving it into the given output buffer. * WARNING! The output buffer MUST have a length of at least the return value of * slip_packet_len(in, inlen) * In case the output buffer is not large enough, this function will return SLIP_ENCODE_ERROR and * the output buffer will be left in an undefined space. * Take special care that the input data does not change between the calls to * slip_packet_len() and slip_encode_packet() * @return The number of bytes in [out], or SLIP_ENCODE_ERROR */ size_t slip_encode_packet(const uint8_t* in, size_t inlen, uint8_t* out, size_t outlen);
/* * Author: Uli Köhler - techoverflow.net * License: CC0 1.0 Universal * * Description: * This is a C++ implementation of a buffer-based SLIP encoder. * It can be used to encode frames unambiguously into a stream of bytes. * The encoder does not use any memory allocation, but instead requires * the caller to provide a buffer for the encoded data - hence being * ideally suited for use in embedded systems */ #include "SLIPEncoder.hpp" size_t slip_packet_length(const uint8_t* in, size_t inlen) { // This variable contains the length of the data size_t outlen = 0; const uint8_t* inend = in + inlen; // First character AFTER the for (; in < inend ; in++) { switch (*in) { case SLIP_END: // Need to escape END character to avoid RX seeing end of frame // Same as "case SLIP_ESC" so just continue. case SLIP_ESC: // Need to escape ESC character, we'll send outlen += 2; // Will send ESC + ESCESC break; default: // Any other character => will just copy outlen++; // Will only send the given character } } // + 1: SLIP END bytes return outlen + 1; } size_t slip_encode_packet(const uint8_t* in, size_t inlen, uint8_t* out, size_t outlen) { // This variable contains the length of the data uint8_t* out_start = out; // We will increment [out], hence copy the original value. // Output buffer must be AT LEAST as long as input data (sanity check) if(outlen < inlen) { return SLIP_ENCODE_ERROR; } uint8_t* outend = out + outlen; // First character AFTER the const uint8_t* inend = in + inlen; // First character AFTER the for (; in < inend ; in++) { switch (*in) { case SLIP_END: // Need to escape END character to avoid RX seeing end of frame // Check out of bounds memory acces if(out + 2 >= outend) { return SLIP_ENCODE_ERROR; } // Copy escaped END character *out++ = SLIP_ESC; *out++ = SLIP_ESCEND; break; case SLIP_ESC: // Need to escape ESC character, we'll send // Check out of bounds memory access if(out + 2 >= outend) { return SLIP_ENCODE_ERROR; } // Copy escaped END character *out++ = SLIP_ESC; *out++ = SLIP_ESCESC; break; default: // Any other character => just copy the character if(out + 1 >= outend) { return SLIP_ENCODE_ERROR; } *out++ = *in; } } // Check out of bounds access for END byte if(out + 1 > outend) { // NOTE: > instead of >= since there is only ONE character to be written return SLIP_ENCODE_ERROR; } // Insert END byte *out++ = SLIP_END; // Return number of bytes return (out - out_start); }