Overall the code is well-written and easy to read. I found no major things to remark on, just details:
cvaluetypes
is only used by the .c file and should be declaredstatic
, to achieve private encapsulation. It's good that you use* const
for read-only pointer tables, since this typically makes them flash allocated on embedded systems, as opposed to RAM where they shouldn't be.Minor remark: to avoid multiple returns from a function, it is best to make a habit of doing:
static uint8_t BucketGetRegisteredFeedSlot(const cbucket_t *data){ uint8_t slotIdx = 0xFF; ... if(data == registeredFeed[slotIdx]){ break; } return slotIdx; }
There's a few cases of "magic numbers" like 99. These should be made named constants with #define or const.
unsigned head
,const int
etc. You suddenly slip back to the native C types here and there. Stick with stdint.h or usesize_t
for sizes of types and arrays.Strive to keep for loops as simple as possible. That is, always count upwards and avoid multiple iterators. For example you could as well do this:
uint16_t start = cBucketBufTail - cBucketBuf + offset; for(size_t i=start; i<size; i++)
There's many such needlessly complicated for loops in the code.
Avoid
strncpy
, it's a dangerous function since it is prone to mess up the null termination. And needlessly slow when you know the exact size in advance. So you could have used memcpy:memcpy(key, registeredFeed[slotIdx]->key, strlen(registeredFeed[slotIdx]->key) + 1);
Although in this specific case, since you call
strlen
anyway, you should use neither of these functions includingstrlen
. The correct function here isstrcpy
:strcpy(key, registeredFeed[slotIdx]->key);
Your error handling is inconsistent - some times you use
bool
, some times magic numbers -1, -2 etc. All of these function results should be replaced by a consistent error type used by the whole library, in the form of atypedef enum {...} bucket_err_t;
Then document which functions that return which error codes, in what situations.Comments containing the function documentation should be placed in the header, in case of public functions. Comments documenting private
static
functions obviously need to be in the .c file like you have though.You forget const correctness in a few places like
void PrintFeedValue(cbucket_t *feed)
->const cbucket_t *
.It's ok to use
uint8_t
as the string type, particularly in embedded systems. However please note that this might upset compilers when you call standard libs with that type. Therefore make a habit of casting tochar*
before callingstrlen
etc.
EDIT
- In case you have functions doing
return false
etc upon error and those functions also return values through parameter pointers, you must document what happens to those parameters in case of errors. Are they untouched in case of errors, are they set to some error code or known value, or are they to be considered as indeterminate values?