123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- /*
- * cobs.c
- *
- * Consistent Overhead Byte Stuffing
- * https://github.com/cmcqueen/cobs-c
- */
- #include "cobs.h"
- /*****************************************************************************
- * Defines
- ****************************************************************************/
- #ifndef FALSE
- #define FALSE (0)
- #endif
- #ifndef TRUE
- #define TRUE (!FALSE)
- #endif
- /*****************************************************************************
- * Functions
- ****************************************************************************/
- cobs_encode_result cobs_encode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t * src_ptr, size_t src_len)
- {
- cobs_encode_result result = { 0, COBS_ENCODE_OK };
- const uint8_t * src_end_ptr = src_ptr + src_len;
- uint8_t * dst_buf_end_ptr = dst_buf_ptr + dst_buf_len;
- uint8_t * dst_code_write_ptr = dst_buf_ptr;
- uint8_t * dst_write_ptr = dst_code_write_ptr + 1;
- uint8_t src_byte = 0;
- uint8_t search_len = 1;
- /* First, do a NULL pointer check and return immediately if it fails. */
- if ((dst_buf_ptr == NULL) || (src_ptr == NULL))
- {
- result.status = COBS_ENCODE_NULL_POINTER;
- return result;
- }
- if (src_len != 0)
- {
- /* Iterate over the source bytes */
- for (;;)
- {
- /* Check for running out of output buffer space */
- if (dst_write_ptr >= dst_buf_end_ptr)
- {
- result.status |= COBS_ENCODE_OUT_BUFFER_OVERFLOW;
- break;
- }
- src_byte = *src_ptr++;
- if (src_byte == 0)
- {
- /* We found a zero byte */
- *dst_code_write_ptr = search_len;
- dst_code_write_ptr = dst_write_ptr++;
- search_len = 1;
- if (src_ptr >= src_end_ptr)
- {
- break;
- }
- }
- else
- {
- /* Copy the non-zero byte to the destination buffer */
- *dst_write_ptr++ = src_byte;
- search_len++;
- if (src_ptr >= src_end_ptr)
- {
- break;
- }
- if (search_len == 0xFF)
- {
- /* We have a long string of non-zero bytes, so we need
- * to write out a length code of 0xFF. */
- *dst_code_write_ptr = search_len;
- dst_code_write_ptr = dst_write_ptr++;
- search_len = 1;
- }
- }
- }
- }
- /* We've reached the end of the source data (or possibly run out of output buffer)
- * Finalise the remaining output. In particular, write the code (length) byte.
- * Update the pointer to calculate the final output length.
- */
- if (dst_code_write_ptr >= dst_buf_end_ptr)
- {
- /* We've run out of output buffer to write the code byte. */
- result.status |= COBS_ENCODE_OUT_BUFFER_OVERFLOW;
- dst_write_ptr = dst_buf_end_ptr;
- }
- else
- {
- /* Write the last code (length) byte. */
- *dst_code_write_ptr = search_len;
- }
- /* Calculate the output length, from the value of dst_code_write_ptr */
- result.out_len = dst_write_ptr - dst_buf_ptr;
- return result;
- }
- cobs_decode_result cobs_decode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t * src_ptr, size_t src_len)
- {
- cobs_decode_result result = { 0, COBS_DECODE_OK };
- const uint8_t * src_end_ptr = src_ptr + src_len;
- uint8_t * dst_buf_end_ptr = dst_buf_ptr + dst_buf_len;
- uint8_t * dst_write_ptr = dst_buf_ptr;
- size_t remaining_bytes;
- uint8_t src_byte;
- uint8_t i;
- uint8_t len_code;
- /* First, do a NULL pointer check and return immediately if it fails. */
- if ((dst_buf_ptr == NULL) || (src_ptr == NULL))
- {
- result.status = COBS_DECODE_NULL_POINTER;
- return result;
- }
- if (src_len != 0)
- {
- for (;;)
- {
- len_code = *src_ptr++;
- if (len_code == 0)
- {
- result.status |= COBS_DECODE_ZERO_BYTE_IN_INPUT;
- break;
- }
- len_code--;
- /* Check length code against remaining input bytes */
- remaining_bytes = src_end_ptr - src_ptr;
- if (len_code > remaining_bytes)
- {
- result.status |= COBS_DECODE_INPUT_TOO_SHORT;
- len_code = remaining_bytes;
- }
- /* Check length code against remaining output buffer space */
- remaining_bytes = dst_buf_end_ptr - dst_write_ptr;
- if (len_code > remaining_bytes)
- {
- result.status |= COBS_DECODE_OUT_BUFFER_OVERFLOW;
- len_code = remaining_bytes;
- }
- for (i = len_code; i != 0; i--)
- {
- src_byte = *src_ptr++;
- if (src_byte == 0)
- {
- result.status |= COBS_DECODE_ZERO_BYTE_IN_INPUT;
- }
- *dst_write_ptr++ = src_byte;
- }
- if (src_ptr >= src_end_ptr)
- {
- break;
- }
- /* Add a zero to the end */
- if (len_code != 0xFE)
- {
- if (dst_write_ptr >= dst_buf_end_ptr)
- {
- result.status |= COBS_DECODE_OUT_BUFFER_OVERFLOW;
- break;
- }
- *dst_write_ptr++ = 0;
- }
- }
- }
- result.out_len = dst_write_ptr - dst_buf_ptr;
- return result;
- }
|