blob: 8bf67f22c0dd74d7c70d02b74018fdd90235ac8e [file] [log] [blame]
#include <stdlib.h>
#include <string.h>
static bool is_big_endian(void)
{
union
{
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
/* Decode an unsigned int LEB128 at buf into r, returning the nr of bytes read.
*/
inline size_t
decode_uint_leb(const uint8_t* buf, const uint8_t* buf_end, uint64_t* r)
{
const uint8_t* p = buf;
uint8_t shift = 0;
uint64_t result = 0;
uint8_t byte;
do
{
if (p >= buf_end)
{
return 0;
}
byte = *p++;
result |= ((uint64_t)(byte & 0x7f)) << shift;
shift += 7;
} while ((byte & 0x80) != 0);
*r = result;
return p - buf;
}
/* Decodes a string
*/
inline size_t decode_string(uint8_t str_len,
const uint8_t* buf,
const uint8_t* buf_end,
char* char_buf)
{
// Return zero bytes read on buffer overflow
if (buf_end - buf < str_len)
{
return 0;
}
const uint8_t* p = buf;
for (int i = 0; i < str_len; i++)
{
char_buf[i] = *p++;
}
// Add the null terminator
char_buf[str_len] = '\0';
return str_len;
}
/* Decodes a double (8 bytes)
*/
inline size_t
decode_double(const uint8_t* buf, const uint8_t* buf_end, double* r)
{
// Return zero bytes read on buffer overflow
if (buf_end - buf < ((unsigned) sizeof(double)))
{
return 0;
}
if (is_big_endian())
{
uint8_t inverted[8] = {buf[7],
buf[6],
buf[5],
buf[4],
buf[3],
buf[2],
buf[1],
buf[0]};
memcpy(r, inverted, sizeof(double));
}
else
{
memcpy(r, buf, sizeof(double));
}
return sizeof(double);
}
/* Decodes a float (4 bytes)
*/
inline size_t decode_float(const uint8_t* buf, const uint8_t* buf_end, float* r)
{
// Return zero bytes read on buffer overflow
if (buf_end - buf < (unsigned) sizeof(float))
{
return 0;
}
if (is_big_endian())
{
uint8_t inverted[4] = {buf[3], buf[2], buf[1], buf[0]};
memcpy(r, inverted, sizeof(float));
}
else
{
memcpy(r, buf, sizeof(float));
}
return sizeof(float);
}
/* Decodes a single byte
*/
inline size_t
decode_uint_8(const uint8_t* buf, const uint8_t* buf_end, uint8_t* r)
{
// Return zero bytes read on buffer overflow
if (buf_end - buf < (unsigned) sizeof(uint8_t))
{
return 0;
}
memcpy(r, buf, sizeof(uint8_t));
return sizeof(uint8_t);
}
/* Decodes a 32 bit unsigned integer.
*/
inline size_t
decode_uint_32(const uint8_t* buf, const uint8_t* buf_end, uint32_t* r)
{
// Return zero bytes read on buffer overflow
if (buf_end - buf < (unsigned) sizeof(uint32_t))
{
return 0;
}
if (is_big_endian())
{
uint8_t inverted[4] = {buf[3], buf[2], buf[1], buf[0]};
memcpy(r, inverted, sizeof(uint32_t));
}
else
{
memcpy(r, buf, sizeof(uint32_t));
}
return sizeof(uint32_t);
}