Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.2 KiB

/*
* Copyright (c) 2024 Kelly Helmut Lord
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <stdint.h>
#include <zephyr/data/cobs.h>
int cobs_encode(struct net_buf *src, struct net_buf *dst, uint32_t flags)
{
uint8_t delimiter = COBS_FLAG_CUSTOM_DELIMITER(flags);
/* Calculate required space for worst case */
size_t max_encoded_size = cobs_max_encoded_len(src->len, flags);
/* Check if destination has enough space */
if (net_buf_tailroom(dst) < max_encoded_size) {
return -ENOMEM;
}
uint8_t *code_ptr = net_buf_add(dst, 1);
uint8_t code = 1;
/* Process all input bytes */
uint8_t data = 0;
while (src->len > 0) {
data = net_buf_pull_u8(src);
if (data == delimiter) {
/* Delimiter found - write current code and start new block */
*code_ptr = code;
code_ptr = net_buf_add(dst, 1);
code = 1;
} else {
/* Add non-zero byte to output */
net_buf_add_u8(dst, data);
code++;
/* If we've reached maximum block size, start a new block */
if (code == 0xFF && (src->len - 1 >= 0)) {
*code_ptr = code;
code_ptr = net_buf_add(dst, 1);
code = 1;
}
}
}
*code_ptr = code;
if (flags & COBS_FLAG_TRAILING_DELIMITER) {
/* Add final delimiter */
net_buf_add_u8(dst, delimiter);
}
return 0;
}
int cobs_decode(struct net_buf *src, struct net_buf *dst, uint32_t flags)
{
uint8_t delimiter = COBS_FLAG_CUSTOM_DELIMITER(flags);
if (flags & COBS_FLAG_TRAILING_DELIMITER) {
uint8_t end_delim = net_buf_remove_u8(src);
if (end_delim != delimiter) {
return -EINVAL;
}
}
while (src->len > 0) {
/* Pull the COBS offset byte */
uint8_t offset = net_buf_pull_u8(src);
if (offset == delimiter && !(flags & COBS_FLAG_TRAILING_DELIMITER)) {
return -EINVAL;
}
/* Verify we have enough data */
if (src->len < (offset - 1)) {
return -EINVAL;
}
/* Copy offset-1 bytes */
for (uint8_t i = 0; i < offset - 1; i++) {
uint8_t byte = net_buf_pull_u8(src);
if (byte == delimiter) {
return -EINVAL;
}
net_buf_add_u8(dst, byte);
}
/* If this wasn't a maximum offset and we have more data,
* there was a delimiter here in the original data
*/
if (offset != 0xFF && src->len > 0) {
net_buf_add_u8(dst, delimiter);
}
}
return 0;
}