§ Coverage
1/*2 * sc_cobs.c -- implementation. Blocks are tagged with the low-level3 * requirement they satisfy; see requirements/sc_cobs.md.4 *5 * Encode uses "lazy" block splitting: a full 254-byte block is only6 * closed with a 0xFF code when there is a following byte, so a payload of7 * exactly 254 non-zero bytes encodes to 255 bytes, not 256.8 */9#include "sc_cobs.h"1011#define COBS_FULL_BLOCK 0xFFu /* code value meaning "254 data bytes, no trailing zero" */121320uint32_t sc_cobs_max_encoded(uint32_t payload_len)14{15 uint32_t result;161720 if (payload_len == 0u)condition outcomes covered 2/218 {193 result = 1u; /* LLR-COBS-1 */20 }21 else22 {2317 result = payload_len + ((payload_len - 1u) / 254u) + 1u;24 }252620 return result;27}282918uint32_t sc_cobs_encode(const uint8_t *in, uint32_t in_len,30 uint8_t *out, uint32_t out_cap)31{3218 uint32_t result = 0u;333434 if ((in == NULL) || (out == NULL) ||condition outcomes covered 6/63516 (sc_cobs_max_encoded(in_len) > out_cap))36 {373 result = 0u; /* LLR-COBS-2 */38 }39 else40 {4115 uint32_t rd = 0u;4215 uint32_t wr = 1u; /* out[0] reserved for the first code */4315 uint32_t code_at = 0u;4415 uint8_t code = 1u;45461569 while (rd < in_len) /* LLR-COBS-3 */condition outcomes covered 2/247 {481554 if (code == COBS_FULL_BLOCK) /* LLR-COBS-6: close a full block */condition outcomes covered 2/249 {503 out[code_at] = code;513 code_at = wr;523 wr++;533 code = 1u;54 }55561554 if (in[rd] == 0u)condition outcomes covered 2/257 {5812 out[code_at] = code; /* LLR-COBS-4: close block on zero */5912 code_at = wr;6012 wr++;6112 code = 1u;62 }63 else64 {651542 out[wr] = in[rd]; /* LLR-COBS-5: copy non-zero */661542 wr++;671542 code = (uint8_t)(code + 1u);68 }691554 rd++;70 }717215 out[code_at] = code; /* LLR-COBS-7: final code */7315 result = wr;74 }757618 return result;77}787914uint32_t sc_cobs_decode(const uint8_t *in, uint32_t in_len,80 uint8_t *out, uint32_t out_cap)81{8214 uint32_t result = 0u;838414 if ((in == NULL) || (out == NULL))condition outcomes covered 4/485 {862 result = 0u; /* LLR-COBS-8 */87 }88 else89 {9012 uint32_t rd = 0u;9112 uint32_t wr = 0u;9212 bool ok = true;939434 while ((rd < in_len) && ok) /* LLR-COBS-9 */condition outcomes covered 4/495 {9622 uint8_t code = in[rd];979822 rd++;9910022 if (code == 0u)condition outcomes covered 2/2101 {1021 ok = false; /* LLR-COBS-10: 0x00 is not a valid code */103 }104 else105 {10621 uint32_t span = (uint32_t)code - 1u;10710821 if ((span > (in_len - rd)) || (span > (out_cap - wr)))condition outcomes covered 4/4109 {1102 ok = false; /* malformed / no room */111 }112 else113 {114 uint32_t k;1151548 for (k = 0u; k < span; k++) /* LLR-COBS-11: copy block */condition outcomes covered 2/2116 {1171529 out[wr] = in[rd];1181529 wr++;1191529 rd++;120 }12119 if ((code != COBS_FULL_BLOCK) && (rd < in_len))condition outcomes covered 4/4122 {1238 if (wr >= out_cap)condition outcomes covered 2/2124 {1251 ok = false;126 }127 else128 {1297 out[wr] = 0u; /* LLR-COBS-12: inter-block zero */1307 wr++;131 }132 }133 }134 }135 }13613712 result = ok ? wr : 0u; /* LLR-COBS-13 */condition outcomes covered 2/2138 }13914014 return result;141}