ud3tn/components/bundle6/sdnv.c
Felix Walter 553cb23bdd Fix constParameter and constVariable warnings by cppcheck
This improves const correctness, at least for pointers (making the
pointed-to data const where possible).

Some suppressions are added for false positive warnings, such as in
`simple_queue.c` where an arithmethic operation is used on the pointer
to calculate a non-const pointer that is returned (thus, the passed
pointer should also not point to const).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-09-11 10:13:21 +02:00

204 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "bundle6/sdnv.h"
/* 0b01111111 */
#define SDNV_VALUE_MASK 0x7F
/* 0b10000000 */
#define SDNV_MARKER_MASK 0x80
void sdnv_reset(struct sdnv_state *state)
{
state->status = SDNV_IN_PROGRESS;
state->error = SDNV_ERROR_NONE;
state->bytes_parsed = 0;
}
static inline int sdnv_validate_byte_u32
(const struct sdnv_state *state, const uint32_t *value)
{
/* returns true if the byte can fit into the already parsed value. */
/* This is independent of the value itself, but dependent on its */
/* length. Up to four bytes definitely fit; if we get a fifth byte, */
/* the value has to be checked whether it contains bits that would */
/* ´fall out´ when left-shifting by 7... */
/* a SDNV for the max. u32 0xFFFFFFFF would be 0x8FFFFFFF7F and */
/* after reading 4 bits the *value would be equal to 0x1FFFFFF */
return (
(state->bytes_parsed < 4) ||
(state->bytes_parsed == 4 && *value <= 0x1FFFFFF)
);
}
static inline int sdnv_validate_byte_u8
(const struct sdnv_state *state, const uint8_t *value)
{
/* max. SDNV: 0x817F */
return (
(state->bytes_parsed < 1) ||
(state->bytes_parsed == 1 && *value <= 0x1)
);
}
static inline int sdnv_validate_byte_u16
(const struct sdnv_state *state, const uint16_t *value)
{
/* max. SDNV: 0x83FF7F */
return (
(state->bytes_parsed < 2) ||
(state->bytes_parsed == 2 && *value <= 0x1FF)
);
}
static inline int sdnv_validate_byte_u64
(const struct sdnv_state *state, const uint64_t *value)
{
/* max. SDNV: 0x81FFFFFFFFFFFFFFFF7F */
return (
(state->bytes_parsed < 9) ||
(state->bytes_parsed == 9 && *value <= 0x1FFFFFFFFFFFFFF)
);
}
#define sdnv_read_generic(state, value, byte, validate_function) \
do { \
__typeof__(state) _state = (state); \
__typeof__(value) _value = (value); \
__typeof__(byte) _byte = (byte); \
if (!(validate_function)(_state, _value)) { \
_state->error = SDNV_ERROR_OVERFLOW; \
_state->status = SDNV_ERROR; \
} else if (_state->status == SDNV_DONE) { \
_state->error = SDNV_ERROR_ALREADY_DONE; \
_state->status = SDNV_ERROR; \
} else { \
if (_state->bytes_parsed == 0) \
*_value = 0; \
else \
*_value <<= 7; \
*_value |= (_byte & SDNV_VALUE_MASK); \
if (!(_byte & SDNV_MARKER_MASK)) \
_state->status = SDNV_DONE; \
++_state->bytes_parsed; \
} \
} while (0)
void sdnv_read_u8(struct sdnv_state *state, uint8_t *value, uint8_t byte)
{
sdnv_read_generic(state, value, byte, sdnv_validate_byte_u8);
}
void sdnv_read_u16(struct sdnv_state *state, uint16_t *value, uint8_t byte)
{
sdnv_read_generic(state, value, byte, sdnv_validate_byte_u16);
}
void sdnv_read_u32(struct sdnv_state *state, uint32_t *value, uint8_t byte)
{
sdnv_read_generic(state, value, byte, sdnv_validate_byte_u32);
}
void sdnv_read_u64(struct sdnv_state *state, uint64_t *value, uint8_t byte)
{
sdnv_read_generic(state, value, byte, sdnv_validate_byte_u64);
}
int_fast8_t sdnv_get_size_u8(uint8_t value)
{
if ((value & 0x80) == 0)
return 1;
else
return 2;
}
int_fast8_t sdnv_get_size_u16(uint16_t value)
{
if ((value & 0xFF80) == 0)
return 1;
else if ((value & 0xC000) == 0)
return 2;
else
return 3;
}
int_fast8_t sdnv_get_size_u32(uint32_t value)
{
if ((value & 0xFFFFFF80) == 0)
return 1;
else if ((value & 0xFFFFC000) == 0)
return 2;
else if ((value & 0xFFE00000) == 0)
return 3;
else if ((value & 0xF0000000) == 0)
return 4;
else
return 5;
}
int_fast8_t sdnv_get_size_u64(uint64_t value)
{
if ((value & 0xFFFFFFFFFFFFFF80) == 0)
return 1;
else if ((value & 0xFFFFFFFFFFFFC000) == 0)
return 2;
else if ((value & 0xFFFFFFFFFFE00000) == 0)
return 3;
else if ((value & 0xFFFFFFFFF0000000) == 0)
return 4;
else if ((value & 0xFFFFFFF800000000) == 0)
return 5;
else if ((value & 0xFFFFFC0000000000) == 0)
return 6;
else if ((value & 0xFFFE000000000000) == 0)
return 7;
else if ((value & 0xFF00000000000000) == 0)
return 8;
else if ((value & 0x8000000000000000) == 0)
return 9;
else
return 10;
}
#define sdnv_write_generic(sdnv_bytes, buffer, value) \
do { \
__typeof__(sdnv_bytes) _sdnv_bytes = (sdnv_bytes); \
__typeof__(buffer) _buffer = (buffer); \
__typeof__(value) _value = (value); \
uint8_t *_last_byte = _buffer + _sdnv_bytes - 1; \
for (uint8_t *_b = _last_byte; _b >= _buffer; _b--) { \
(*_b) = (_value & SDNV_VALUE_MASK) | SDNV_MARKER_MASK; \
_value >>= 7; \
} \
(*_last_byte) &= SDNV_VALUE_MASK; \
} while (0)
int_fast8_t sdnv_write_u8(uint8_t *buffer, uint8_t value)
{
int_fast8_t sdnv_bytes = sdnv_get_size_u8(value);
sdnv_write_generic(sdnv_bytes, buffer, value);
return sdnv_bytes;
}
int_fast8_t sdnv_write_u16(uint8_t *buffer, uint16_t value)
{
int_fast8_t sdnv_bytes = sdnv_get_size_u16(value);
sdnv_write_generic(sdnv_bytes, buffer, value);
return sdnv_bytes;
}
int_fast8_t sdnv_write_u32(uint8_t *buffer, uint32_t value)
{
int_fast8_t sdnv_bytes = sdnv_get_size_u32(value);
sdnv_write_generic(sdnv_bytes, buffer, value);
return sdnv_bytes;
}
int_fast8_t sdnv_write_u64(uint8_t *buffer, uint64_t value)
{
int_fast8_t sdnv_bytes = sdnv_get_size_u64(value);
sdnv_write_generic(sdnv_bytes, buffer, value);
return sdnv_bytes;
}