Skip to content

Commit

Permalink
Indices not pointers (#24)
Browse files Browse the repository at this point in the history
* move cobs_decode_inplace to indices instead of pointers, do better error-checking and the code got smaller

* whitespace

* move cobs_encode_inplace to indice, smaller code + binary

* update docs

* fix C4706

* tighter windows warnings

* /WX not /Wx

* wow catch2 does not work with /WX
  • Loading branch information
charlesnicholson authored May 9, 2021
1 parent 26bef40 commit 1d7f466
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 50 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ Also I didn't see as many unit tests as I'd have liked in the other libraries, e

It's pretty small.
```
../gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -Os -c cobs.c
../gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-nm --print-size --size-sort cobs.o
00000082 00000018 T cobs_encode_max (24 bytes)
0000004a 00000038 T cobs_decode_inplace (56 bytes)
00000000 0000004a T cobs_encode_inplace (74 bytes)
0000009a 0000007e T cobs_encode (126 bytes)
00000118 0000008e T cobs_decode (142 bytes)
❯ arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -Os -c cobs.c
❯ arm-none-eabi-nm --print-size --size-sort cobs.o
0000007a 00000018 T cobs_encode_max (24 bytes)
00000048 00000032 T cobs_decode_inplace (50 bytes)
00000000 00000048 T cobs_encode_inplace (72 bytes)
00000092 0000007a T cobs_encode (122 bytes)
0000010c 00000084 T cobs_decode (132 bytes)
```

## Usage
Expand Down Expand Up @@ -93,7 +93,7 @@ cobs_ret_t const result = cobs_decode(encoded, encoded_len, decoded, sizeof(deco
if (result == COBS_RET_SUCCESS) {
// decoding succeeded, 'decoded' and 'decoded_len' hold details.
} else {
// decoding failed, look to 'result' for details.
// decoding failed, look to 'result' for details.
}
```

Expand All @@ -117,7 +117,7 @@ if (result == COBS_RET_SUCCESS) {
```
## Developing

`nanocobs` uses [catch2](https://github.com/catchorg/Catch2) for unit and functional testing; its unified mega-header is checked in to the `tests` directory. To build and run all tests on macOS or Linux, run `make -j` from a terminal. To build + run all tests on Windows, run the `vsvarsXX.bat` of your choice to set up the VS environment, then run `make-win.bat` (if you want to make that part better, pull requests are very welcome).
`nanocobs` uses [catch2](https://github.com/catchorg/Catch2) for unit and functional testing; its unified mega-header is checked in to the `tests` directory. To build and run all tests on macOS or Linux, run `make -j` from a terminal. To build + run all tests on Windows, run the `vsvarsXX.bat` of your choice to set up the VS environment, then run `make-win.bat` (if you want to make that part better, pull requests are very welcome).

Also, it's really amazing how long it takes to compile the Catch2 amalgamated file, thanks C++!

Expand Down
62 changes: 23 additions & 39 deletions cobs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,44 @@
typedef unsigned char cobs_byte_t;

cobs_ret_t cobs_encode_inplace(void *buf, unsigned len) {
if (!buf || (len < 2)) {
return COBS_RET_ERR_BAD_ARG;
}
if (!buf || (len < 2)) { return COBS_RET_ERR_BAD_ARG; }

cobs_byte_t *cur = (cobs_byte_t *)buf;
cobs_byte_t const *const end = cur + len - 1;
if ((*cur != COBS_ISV) || (*end != COBS_ISV)) {
cobs_byte_t *const src = (cobs_byte_t *)buf;
if ((src[0] != COBS_ISV) || (src[len - 1] != COBS_ISV)) {
return COBS_RET_ERR_BAD_PAYLOAD;
}

cobs_byte_t *patch = cur++;
while (cur < end) {
if (*cur == 0) {
unsigned const ofs = (unsigned)(cur - patch);
if (ofs > 255) {
return COBS_RET_ERR_BAD_PAYLOAD;
}
*patch = (cobs_byte_t)ofs;
unsigned patch = 0, cur = 1;
while (cur < len - 1) {
if (!src[cur]) {
unsigned const ofs = cur - patch;
if (ofs > 255) { return COBS_RET_ERR_BAD_PAYLOAD; }
src[patch] = (cobs_byte_t)ofs;
patch = cur;
}
++cur;
}

unsigned const ofs = (unsigned)(cur - patch);
if (ofs > 255) {
return COBS_RET_ERR_BAD_PAYLOAD;
}
*patch = (cobs_byte_t)ofs;
*cur = 0;
unsigned const ofs = cur - patch;
if (ofs > 255) { return COBS_RET_ERR_BAD_PAYLOAD; }
src[patch] = (cobs_byte_t)ofs;
src[cur] = 0;
return COBS_RET_SUCCESS;
}

cobs_ret_t cobs_decode_inplace(void *buf, unsigned len) {
if (!buf || (len < 2)) {
return COBS_RET_ERR_BAD_ARG;
}
cobs_ret_t cobs_decode_inplace(void *buf, unsigned const len) {
if (!buf || (len < 2)) { return COBS_RET_ERR_BAD_ARG; }

cobs_byte_t *cur = (cobs_byte_t *)buf;
cobs_byte_t const *const end = cur + len - 1;
if ((*cur == 0) || (*end != 0)) {
return COBS_RET_ERR_BAD_PAYLOAD;
}

while (*cur) {
unsigned const ofs = *cur;
*cur = 0;
cobs_byte_t *const src = (cobs_byte_t *)buf;
unsigned ofs, cur = 0;
while ((ofs = src[cur]) != 0) {
src[cur] = 0;
cur += ofs;
if (cur > end) {
return COBS_RET_ERR_BAD_PAYLOAD;
}
if (cur > len) { return COBS_RET_ERR_BAD_PAYLOAD; }
}

*(cobs_byte_t *)buf = COBS_ISV;
*cur = COBS_ISV;
if (cur != len - 1) { return COBS_RET_ERR_BAD_PAYLOAD; }
src[0] = COBS_ISV;
src[len - 1] = COBS_ISV;
return COBS_RET_SUCCESS;
}

Expand Down
2 changes: 1 addition & 1 deletion make-win.bat
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cl.exe /W4 /EHsc ^
cl.exe /W4 /WX /EHsc ^
cobs.c ^
tests/test_cobs_encode_max.cc ^
tests/test_cobs_encode.cc ^
Expand Down
2 changes: 2 additions & 0 deletions tests/test_cobs_decode_inplace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ TEST_CASE("Inplace decoding validation", "[cobs_decode_inplace]") {
REQUIRE( cobs_decode_vec(buf) == COBS_RET_ERR_BAD_PAYLOAD );
buf = byte_vec_t{0x03, 0x01, 0x00}; // first byte jumps past end
REQUIRE( cobs_decode_vec(buf) == COBS_RET_ERR_BAD_PAYLOAD );
buf = byte_vec_t{0x01, 0x00, 0x00}; // land on an interior 0x00
REQUIRE( cobs_decode_vec(buf) == COBS_RET_ERR_BAD_PAYLOAD );
}
}

Expand Down

0 comments on commit 1d7f466

Please sign in to comment.