Original project changes: Vehicle - Add buffer handling tools to ovms utils

This commit is contained in:
Carsten Schmiemann 2022-11-01 14:28:10 +01:00
parent 58402124dd
commit f6f72e8c16
2 changed files with 193 additions and 6 deletions

View file

@ -612,3 +612,19 @@ std::string idtag(const char* tag, void* instance)
std::string res = buf.str();
return res;
}
/**
* get_buff_string: Helper function to get at string value from sized buffer.
*/
bool get_buff_string(const uint8_t *data, uint32_t size, uint32_t index, uint32_t len, std::string &strret)
{
int remain = size - index;
if (remain < 0)
return false;
if (remain < len)
len = remain;
const char *begin = reinterpret_cast<const char *>(data + index) ;
const char *end = begin + len;
strret.assign<const char *>(begin, end);
return true;
}

View file

@ -36,6 +36,7 @@
#include <cstring>
#include <string>
#include <iomanip>
#include <vector>
#include "ovms.h"
// Macro utils:
@ -339,17 +340,187 @@ std::string idtag(const char* tag, void* instance);
#define IDTAG idtag(TAG,this)
/**
* sign_extend: Sign extend an unsigned to a signed integer of the same size.
* sign_extend: Sign extend an unsigned to a signed integer of the same or bigger size.
* Sign bit is not known at compile time.
*/
template <typename UINT, typename INT>
INT sign_extend(UINT uvalue, uint8_t signbit)
template<typename UINT, typename INT>
INT sign_extend( UINT uvalue, uint8_t signbit)
{
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t newuvalue = uvalue;
if (newuvalue & (UINT(1U) << signbit)) {
newuvalue |= ~((uint_t(1U) << signbit) - 1);
UINT signmask = UINT(1U) << signbit;
if ( newuvalue & signmask)
newuvalue |= ~ (static_cast<uint_t>(signmask) - 1);
return reinterpret_cast<INT &>(uvalue);
}
return reinterpret_cast<INT &>(newuvalue);
/**
* sign_extend: Sign extend an unsigned to a signed integer of the same or bigger size.
* Sign bit is known at compile time.
*/
template<typename UINT, typename INT, uint8_t SIGNBIT>
INT sign_extend( UINT uvalue)
{
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t newuvalue = uvalue;
if ( newuvalue & ( UINT(1U) << SIGNBIT) )
newuvalue |= ~((uint_t(1U) << SIGNBIT) - 1);
return reinterpret_cast<INT &>(uvalue);
}
/**
* get_bit: Get at a specific (compile-time defined) bit in a byte.
*/
template<uint8_t BIT>
bool get_bit(uint8_t data)
{
return (0 != (data & (1 << BIT)));
}
// helper to provide a big endian integer from a given number of bytes.
// The helper function checks the length before using this.
template<uint8_t BYTES>
struct ovms_bytes_impl_t
{
static uint32_t get_bytes_int(const uint8_t *data, uint32_t index)
{
return (data[index + (BYTES - 1)])
| (ovms_bytes_impl_t < BYTES - 1 >::get_bytes_int(data, index) << 8);
}
};
template<>
struct ovms_bytes_impl_t<1>
{
static uint32_t get_bytes_int(const uint8_t *data, uint32_t index)
{
return (data[index]);
}
};
// Helper Class to access Little-Endian values.
template<uint8_t BYTES>
struct get_bytes_le_impl_t
{
static uint32_t get_bytes_int( const uint8_t *data, uint32_t index)
{
return ((data[index + (BYTES - 1)]) << (8 * (BYTES - 1)))
| get_bytes_le_impl_t < BYTES - 1 >::get_bytes_int(data, index);
}
};
template<>
struct get_bytes_le_impl_t<1>
{
static uint32_t get_bytes_int(const uint8_t *data, uint32_t index)
{
return (data[index]);
}
};
/**
* get_uint_bytes_be: Access to unsigned integer (big-endian) in a data buffer.
*
* @return true If within bounds
*/
template<uint8_t BYTES>
bool get_uint_bytes_be(const uint8_t *data, uint32_t index, uint32_t length, uint32_t &res)
{
if ((index + (BYTES - 1)) >= length) {
return false;
}
res = ovms_bytes_impl_t<BYTES>::get_bytes_int(data, index);
return true;
}
/**
* get_int_bytes_be: Access to signed integer (big-endian) in a data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES>
bool get_int_bytes_be(const uint8_t *data, uint32_t index, uint32_t length, int32_t &res)
{
if ((index + (BYTES - 1)) >= length)
return false;
uint32_t uresult = ovms_bytes_impl_t<BYTES>::get_bytes_int(data, index);
res = reinterpret_cast<int32_t &>(uresult);
return true;
}
/**
* get_uint_buff_be: Access to unsigned integer (big-endian) in a vector data buffer.
* @return true If successful
*/
template<uint8_t BYTES>
bool get_uint_buff_be(const std::string &data, uint32_t index, uint32_t &ures)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
ures = ovms_bytes_impl_t<BYTES>::get_bytes_int(reinterpret_cast<const uint8_t *>(data.data()), index);
return true;
}
/**
* get_buff_int_be: Access to signed integer (big-endian) in a std::string data buffer.
* @return true If successful
*/
template<uint8_t BYTES>
bool get_buff_int_be(const std::string &data, uint32_t index, int32_t &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
uint32_t ures = ovms_bytes_impl_t<BYTES>::get_bytes_int(reinterpret_cast<const uint8_t *>(data.data()), index);
res = sign_extend < uint32_t, int32_t, BYTES * 8 - 1 > (ures);
return true;
}
/**
* get_bytes_uint_le: Access to unsigned integer (little-endian) in a data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES>
bool get_bytes_uint_le(const uint8_t *data, uint32_t index, uint32_t length, uint32_t &res)
{
if ((index + (BYTES - 1)) >= length)
return false;
res = get_bytes_le_impl_t<BYTES>::get_bytes_int(data, index);
return true;
}
/** Access to unsigned integer (little-endian) in a vector data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES>
bool get_buff_uint_le(const std::string &data, uint32_t index, uint32_t &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
res = get_bytes_le_impl_t<BYTES>::get_bytes_int(reinterpret_cast<const uint8_t *>(data.data()), index);
return true;
}
/** Access to signed integer (little-endian) in a vector data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES>
bool get_buff_int_le(const std::string &data, uint32_t index, int32_t &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
uint32_t uresult = ovms_bytes_impl_t<BYTES>::get_bytes_int(reinterpret_cast<const uint8_t *>(data.data()), index);
res = sign_extend < uint32_t, int32_t, BYTES * 8 - 1 > (uresult);
return true;
}
/** Access a string portion in a vector data buffer.
* @return true if start is within bounds.
*/
bool get_buff_string(const uint8_t *data, uint32_t size, uint32_t index, uint32_t len, std::string &strret);
inline bool get_buff_string(const std::string &data, uint32_t index, uint32_t len, std::string &strret)
{
return get_buff_string(reinterpret_cast<const uint8_t *>(data.data()), data.size(), index, len, strret);
}
#endif // __OVMS_UTILS_H__