You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
707 lines
17 KiB
707 lines
17 KiB
|
1 year ago
|
/*
|
||
|
|
* Copyright 2023 Ingemar Hedvall
|
||
|
|
* SPDX-License-Identifier: MIT
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "a2lhelper.h"
|
||
|
|
#include <cstring>
|
||
|
|
#include <fstream>
|
||
|
|
#include <sstream>
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
constexpr uint8_t kMask[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
|
||
|
|
using signed64 = union {
|
||
|
|
int64_t val1 : 1;
|
||
|
|
int64_t val2 : 2;
|
||
|
|
int64_t val3 : 3;
|
||
|
|
int64_t val4 : 4;
|
||
|
|
int64_t val5 : 5;
|
||
|
|
int64_t val6 : 6;
|
||
|
|
int64_t val7 : 7;
|
||
|
|
int64_t val8 : 8;
|
||
|
|
int64_t val9 : 9;
|
||
|
|
int64_t val10 : 10;
|
||
|
|
int64_t val11 : 11;
|
||
|
|
int64_t val12 : 12;
|
||
|
|
int64_t val13 : 13;
|
||
|
|
int64_t val14 : 14;
|
||
|
|
int64_t val15 : 15;
|
||
|
|
int64_t val16 : 16;
|
||
|
|
int64_t val17 : 17;
|
||
|
|
int64_t val18 : 18;
|
||
|
|
int64_t val19 : 19;
|
||
|
|
int64_t val20 : 20;
|
||
|
|
int64_t val21 : 21;
|
||
|
|
int64_t val22 : 22;
|
||
|
|
int64_t val23 : 23;
|
||
|
|
int64_t val24 : 24;
|
||
|
|
int64_t val25 : 25;
|
||
|
|
int64_t val26 : 26;
|
||
|
|
int64_t val27 : 27;
|
||
|
|
int64_t val28 : 28;
|
||
|
|
int64_t val29 : 29;
|
||
|
|
int64_t val30 : 30;
|
||
|
|
int64_t val31 : 31;
|
||
|
|
int64_t val32 : 32;
|
||
|
|
int64_t val33 : 33;
|
||
|
|
int64_t val34 : 34;
|
||
|
|
int64_t val35 : 35;
|
||
|
|
int64_t val36 : 36;
|
||
|
|
int64_t val37 : 37;
|
||
|
|
int64_t val38 : 38;
|
||
|
|
int64_t val39 : 39;
|
||
|
|
int64_t val40 : 40;
|
||
|
|
int64_t val41 : 41;
|
||
|
|
int64_t val42 : 42;
|
||
|
|
int64_t val43 : 43;
|
||
|
|
int64_t val44 : 44;
|
||
|
|
int64_t val45 : 45;
|
||
|
|
int64_t val46 : 46;
|
||
|
|
int64_t val47 : 47;
|
||
|
|
int64_t val48 : 48;
|
||
|
|
int64_t val49 : 49;
|
||
|
|
int64_t val50 : 50;
|
||
|
|
int64_t val51 : 51;
|
||
|
|
int64_t val52 : 52;
|
||
|
|
int64_t val53 : 53;
|
||
|
|
int64_t val54 : 54;
|
||
|
|
int64_t val55 : 55;
|
||
|
|
int64_t val56 : 56;
|
||
|
|
int64_t val57 : 57;
|
||
|
|
int64_t val58 : 58;
|
||
|
|
int64_t val59 : 59;
|
||
|
|
int64_t val60 : 60;
|
||
|
|
int64_t val61 : 61;
|
||
|
|
int64_t val62 : 62;
|
||
|
|
int64_t val63 : 63;
|
||
|
|
int64_t val64 : 64;
|
||
|
|
};
|
||
|
|
|
||
|
|
} // end namespace empty
|
||
|
|
|
||
|
|
namespace a2l {
|
||
|
|
|
||
|
|
void A2lHelper::DoubleToRaw(bool little_endian, size_t start, size_t length,
|
||
|
|
double value, uint8_t* dest) {
|
||
|
|
if (dest == nullptr || length < 64) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
length = 64;
|
||
|
|
|
||
|
|
uint64_t mask = 1ULL << 63;
|
||
|
|
uint64_t temp = 0;
|
||
|
|
memcpy(&temp, &value, sizeof(temp));
|
||
|
|
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if ((temp & mask) != 0) {
|
||
|
|
dest[byte] |= kMask[bit];
|
||
|
|
} else {
|
||
|
|
dest[byte] &= ~kMask[bit];
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
if (byte >= (start + length) /8) {
|
||
|
|
// Buffer overrun. Most likely invalid start bit
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void A2lHelper::FloatToRaw(bool little_endian, size_t start, size_t length,
|
||
|
|
float value, uint8_t* raw) {
|
||
|
|
if (raw == nullptr || length < 32) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
length = 32;
|
||
|
|
uint32_t mask = 1UL << 31;
|
||
|
|
uint32_t temp = 0;
|
||
|
|
memcpy(&temp, &value, sizeof(temp));
|
||
|
|
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if ((temp & mask) != 0) {
|
||
|
|
raw[byte] |= kMask[bit];
|
||
|
|
} else {
|
||
|
|
raw[byte] &= ~kMask[bit];
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
if (byte >= (start + length) / 8) {
|
||
|
|
// Buffer overrun. Most likely invalid start bit
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void A2lHelper::SignedToRaw(bool little_endian, size_t start, size_t length,
|
||
|
|
int64_t value, uint8_t* raw) {
|
||
|
|
if (raw == nullptr || length == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
signed64 temp_val{};
|
||
|
|
|
||
|
|
switch (length) {
|
||
|
|
case 1:
|
||
|
|
temp_val.val1 = value;
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
temp_val.val2 = value;
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
temp_val.val3 = value;
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
temp_val.val4 = value;
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
temp_val.val5 = value;
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
temp_val.val6 = value;
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
temp_val.val7 = value;
|
||
|
|
break;
|
||
|
|
case 8:
|
||
|
|
temp_val.val8 = value;
|
||
|
|
break;
|
||
|
|
case 9:
|
||
|
|
temp_val.val9 = value;
|
||
|
|
break;
|
||
|
|
case 10:
|
||
|
|
temp_val.val10 = value;
|
||
|
|
break;
|
||
|
|
case 11:
|
||
|
|
temp_val.val11 = value;
|
||
|
|
break;
|
||
|
|
case 12:
|
||
|
|
temp_val.val12 = value;
|
||
|
|
break;
|
||
|
|
case 13:
|
||
|
|
temp_val.val13 = value;
|
||
|
|
break;
|
||
|
|
case 14:
|
||
|
|
temp_val.val14 = value;
|
||
|
|
break;
|
||
|
|
case 15:
|
||
|
|
temp_val.val15 = value;
|
||
|
|
break;
|
||
|
|
case 16:
|
||
|
|
temp_val.val16 = value;
|
||
|
|
break;
|
||
|
|
case 17:
|
||
|
|
temp_val.val17 = value;
|
||
|
|
break;
|
||
|
|
case 18:
|
||
|
|
temp_val.val18 = value;
|
||
|
|
break;
|
||
|
|
case 19:
|
||
|
|
temp_val.val19 = value;
|
||
|
|
break;
|
||
|
|
case 20:
|
||
|
|
temp_val.val20 = value;
|
||
|
|
break;
|
||
|
|
case 21:
|
||
|
|
temp_val.val21 = value;
|
||
|
|
break;
|
||
|
|
case 22:
|
||
|
|
temp_val.val22 = value;
|
||
|
|
break;
|
||
|
|
case 23:
|
||
|
|
temp_val.val23 = value;
|
||
|
|
break;
|
||
|
|
case 24:
|
||
|
|
temp_val.val24 = value;
|
||
|
|
break;
|
||
|
|
case 25:
|
||
|
|
temp_val.val25 = value;
|
||
|
|
break;
|
||
|
|
case 26:
|
||
|
|
temp_val.val26 = value;
|
||
|
|
break;
|
||
|
|
case 27:
|
||
|
|
temp_val.val27 = value;
|
||
|
|
break;
|
||
|
|
case 28:
|
||
|
|
temp_val.val28 = value;
|
||
|
|
break;
|
||
|
|
case 29:
|
||
|
|
temp_val.val29 = value;
|
||
|
|
break;
|
||
|
|
case 30:
|
||
|
|
temp_val.val30 = value;
|
||
|
|
break;
|
||
|
|
case 31:
|
||
|
|
temp_val.val31 = value;
|
||
|
|
break;
|
||
|
|
case 32:
|
||
|
|
temp_val.val32 = value;
|
||
|
|
break;
|
||
|
|
case 33:
|
||
|
|
temp_val.val33 = value;
|
||
|
|
break;
|
||
|
|
case 34:
|
||
|
|
temp_val.val34 = value;
|
||
|
|
break;
|
||
|
|
case 35:
|
||
|
|
temp_val.val35 = value;
|
||
|
|
break;
|
||
|
|
case 36:
|
||
|
|
temp_val.val36 = value;
|
||
|
|
break;
|
||
|
|
case 37:
|
||
|
|
temp_val.val37 = value;
|
||
|
|
break;
|
||
|
|
case 38:
|
||
|
|
temp_val.val38 = value;
|
||
|
|
break;
|
||
|
|
case 39:
|
||
|
|
temp_val.val39 = value;
|
||
|
|
break;
|
||
|
|
case 40:
|
||
|
|
temp_val.val40 = value;
|
||
|
|
break;
|
||
|
|
case 41:
|
||
|
|
temp_val.val41 = value;
|
||
|
|
break;
|
||
|
|
case 42:
|
||
|
|
temp_val.val42 = value;
|
||
|
|
break;
|
||
|
|
case 43:
|
||
|
|
temp_val.val43 = value;
|
||
|
|
break;
|
||
|
|
case 44:
|
||
|
|
temp_val.val44 = value;
|
||
|
|
break;
|
||
|
|
case 45:
|
||
|
|
temp_val.val45 = value;
|
||
|
|
break;
|
||
|
|
case 46:
|
||
|
|
temp_val.val46 = value;
|
||
|
|
break;
|
||
|
|
case 47:
|
||
|
|
temp_val.val47 = value;
|
||
|
|
break;
|
||
|
|
case 48:
|
||
|
|
temp_val.val48 = value;
|
||
|
|
break;
|
||
|
|
case 49:
|
||
|
|
temp_val.val49 = value;
|
||
|
|
break;
|
||
|
|
case 50:
|
||
|
|
temp_val.val50 = value;
|
||
|
|
break;
|
||
|
|
case 51:
|
||
|
|
temp_val.val51 = value;
|
||
|
|
break;
|
||
|
|
case 52:
|
||
|
|
temp_val.val52 = value;
|
||
|
|
break;
|
||
|
|
case 53:
|
||
|
|
temp_val.val53 = value;
|
||
|
|
break;
|
||
|
|
case 54:
|
||
|
|
temp_val.val54 = value;
|
||
|
|
break;
|
||
|
|
case 55:
|
||
|
|
temp_val.val55 = value;
|
||
|
|
break;
|
||
|
|
case 56:
|
||
|
|
temp_val.val56 = value;
|
||
|
|
break;
|
||
|
|
case 57:
|
||
|
|
temp_val.val57 = value;
|
||
|
|
break;
|
||
|
|
case 58:
|
||
|
|
temp_val.val58 = value;
|
||
|
|
break;
|
||
|
|
case 59:
|
||
|
|
temp_val.val59 = value;
|
||
|
|
break;
|
||
|
|
case 60:
|
||
|
|
temp_val.val60 = value;
|
||
|
|
break;
|
||
|
|
case 61:
|
||
|
|
temp_val.val61 = value;
|
||
|
|
break;
|
||
|
|
case 62:
|
||
|
|
temp_val.val62 = value;
|
||
|
|
break;
|
||
|
|
case 63:
|
||
|
|
temp_val.val63 = value;
|
||
|
|
break;
|
||
|
|
case 64:
|
||
|
|
temp_val.val64 = value;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t mask = 1ULL << (length - 1);
|
||
|
|
uint64_t temp = 0;
|
||
|
|
memcpy(&temp, &temp_val, sizeof(temp));
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if ((temp & mask) != 0) {
|
||
|
|
raw[byte] |= kMask[bit];
|
||
|
|
} else {
|
||
|
|
raw[byte] &= ~kMask[bit];
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void A2lHelper::UnsignedToRaw(bool little_endian, size_t start, size_t length,
|
||
|
|
uint64_t value, uint8_t* raw) {
|
||
|
|
if (raw == nullptr || length == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t mask = 1ULL << (length - 1);
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if ((value & mask) != 0) {
|
||
|
|
raw[byte] |= kMask[bit];
|
||
|
|
} else {
|
||
|
|
raw[byte] &= ~kMask[bit];
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<uint8_t> A2lHelper::RawToByteArray(size_t start, size_t length,
|
||
|
|
const unsigned char* raw )
|
||
|
|
{
|
||
|
|
// Only byte aligned strings are supported
|
||
|
|
if ( raw == nullptr || (length % 8) != 0 || (start % 8) != 0) {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
const auto byte_start = start / 8;
|
||
|
|
const auto byte_size = length / 8;
|
||
|
|
std::vector<uint8_t> temp;
|
||
|
|
temp.resize(byte_size, 0);
|
||
|
|
memcpy(temp.data(), raw + byte_start, byte_size);
|
||
|
|
return temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
double A2lHelper::RawToDouble(bool little_endian, size_t start, size_t length,
|
||
|
|
const unsigned char* raw )
|
||
|
|
{
|
||
|
|
double value = 0.0;
|
||
|
|
uint64_t temp = 0;
|
||
|
|
uint64_t mask = 1ULL << ( length - 1 );
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
for (size_t index = 0; index < length; ++index ) {
|
||
|
|
if ((raw[byte] & kMask[bit] ) != 0) {
|
||
|
|
temp |= mask;
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
memcpy( &value, &temp, sizeof(value));
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
float A2lHelper::RawToFloat(bool little_endian, size_t start, size_t length,
|
||
|
|
const unsigned char* raw )
|
||
|
|
{
|
||
|
|
float value = 0.0;
|
||
|
|
uint32_t temp = 0;
|
||
|
|
uint32_t mask = 1ULL << ( length - 1 );
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
for (size_t index = 0; index < length; ++index ) {
|
||
|
|
if ((raw[byte] & kMask[bit] ) != 0) {
|
||
|
|
temp |= mask;
|
||
|
|
}
|
||
|
|
mask >>= 1;
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
memcpy( &value, &temp, sizeof(value));
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
int64_t A2lHelper::RawToSigned(bool little_endian, size_t start, size_t length,
|
||
|
|
const uint8_t* raw )
|
||
|
|
{
|
||
|
|
int64_t value = 0;
|
||
|
|
|
||
|
|
uint64_t temp = 0;
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if ( index > 0 ) temp <<= 1;
|
||
|
|
if ((raw[byte] & kMask[bit]) != 0) {
|
||
|
|
temp |= 1;
|
||
|
|
}
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
signed64 temp_value {};
|
||
|
|
memcpy( &temp_value, &temp, sizeof(temp));
|
||
|
|
|
||
|
|
switch ( length ) {
|
||
|
|
case 1: value = temp_value.val1; break;
|
||
|
|
case 2: value = temp_value.val2; break;
|
||
|
|
case 3: value = temp_value.val3; break;
|
||
|
|
case 4: value = temp_value.val4; break;
|
||
|
|
case 5: value = temp_value.val5; break;
|
||
|
|
case 6: value = temp_value.val6; break;
|
||
|
|
case 7: value = temp_value.val7; break;
|
||
|
|
case 8: value = temp_value.val8; break;
|
||
|
|
case 9: value = temp_value.val9; break;
|
||
|
|
case 10: value = temp_value.val10; break;
|
||
|
|
case 11: value = temp_value.val11; break;
|
||
|
|
case 12: value = temp_value.val12; break;
|
||
|
|
case 13: value = temp_value.val13; break;
|
||
|
|
case 14: value = temp_value.val14; break;
|
||
|
|
case 15: value = temp_value.val15; break;
|
||
|
|
case 16: value = temp_value.val16; break;
|
||
|
|
case 17: value = temp_value.val17; break;
|
||
|
|
case 18: value = temp_value.val18; break;
|
||
|
|
case 19: value = temp_value.val19; break;
|
||
|
|
case 20: value = temp_value.val20; break;
|
||
|
|
case 21: value = temp_value.val21; break;
|
||
|
|
case 22: value = temp_value.val22; break;
|
||
|
|
case 23: value = temp_value.val23; break;
|
||
|
|
case 24: value = temp_value.val24; break;
|
||
|
|
case 25: value = temp_value.val25; break;
|
||
|
|
case 26: value = temp_value.val26; break;
|
||
|
|
case 27: value = temp_value.val27; break;
|
||
|
|
case 28: value = temp_value.val28; break;
|
||
|
|
case 29: value = temp_value.val29; break;
|
||
|
|
case 30: value = temp_value.val30; break;
|
||
|
|
case 31: value = temp_value.val31; break;
|
||
|
|
case 32: value = temp_value.val32; break;
|
||
|
|
case 33: value = temp_value.val33; break;
|
||
|
|
case 34: value = temp_value.val34; break;
|
||
|
|
case 35: value = temp_value.val35; break;
|
||
|
|
case 36: value = temp_value.val36; break;
|
||
|
|
case 37: value = temp_value.val37; break;
|
||
|
|
case 38: value = temp_value.val38; break;
|
||
|
|
case 39: value = temp_value.val39; break;
|
||
|
|
case 40: value = temp_value.val40; break;
|
||
|
|
case 41: value = temp_value.val41; break;
|
||
|
|
case 42: value = temp_value.val42; break;
|
||
|
|
case 43: value = temp_value.val43; break;
|
||
|
|
case 44: value = temp_value.val44; break;
|
||
|
|
case 45: value = temp_value.val45; break;
|
||
|
|
case 46: value = temp_value.val46; break;
|
||
|
|
case 47: value = temp_value.val47; break;
|
||
|
|
case 48: value = temp_value.val48; break;
|
||
|
|
case 49: value = temp_value.val49; break;
|
||
|
|
case 50: value = temp_value.val50; break;
|
||
|
|
case 51: value = temp_value.val51; break;
|
||
|
|
case 52: value = temp_value.val52; break;
|
||
|
|
case 53: value = temp_value.val53; break;
|
||
|
|
case 54: value = temp_value.val54; break;
|
||
|
|
case 55: value = temp_value.val55; break;
|
||
|
|
case 56: value = temp_value.val56; break;
|
||
|
|
case 57: value = temp_value.val57; break;
|
||
|
|
case 58: value = temp_value.val58; break;
|
||
|
|
case 59: value = temp_value.val59; break;
|
||
|
|
case 60: value = temp_value.val60; break;
|
||
|
|
case 61: value = temp_value.val61; break;
|
||
|
|
case 62: value = temp_value.val62; break;
|
||
|
|
case 63: value = temp_value.val63; break;
|
||
|
|
case 64: value = temp_value.val64; break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t A2lHelper::RawToUnsigned(bool little_endian, size_t start,
|
||
|
|
size_t length, const uint8_t* raw)
|
||
|
|
{
|
||
|
|
uint64_t value = 0;
|
||
|
|
|
||
|
|
auto bit = little_endian ? static_cast<int>(start + length - 1)
|
||
|
|
: static_cast<int>(start);
|
||
|
|
auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
if (index > 0) {
|
||
|
|
value <<= 1;
|
||
|
|
}
|
||
|
|
if ((raw[byte] & kMask[bit]) != 0) {
|
||
|
|
value |= 1;
|
||
|
|
}
|
||
|
|
--bit;
|
||
|
|
if (bit < 0) {
|
||
|
|
bit = 7;
|
||
|
|
little_endian ? --byte : ++byte;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
void A2lHelper::SetAllBits(size_t start, size_t length, uint8_t* raw ) {
|
||
|
|
if (raw == nullptr) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for ( size_t index = 0; index < length; ++index) {
|
||
|
|
auto bit = start + index;
|
||
|
|
const auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
raw[byte] |= kMask[bit];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool A2lHelper::IsAllBitsSet(size_t start, size_t length, const uint8_t* raw) {
|
||
|
|
if (raw == nullptr) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (length <= 1) {
|
||
|
|
return false; // 1 bit cannot have an invalid flag
|
||
|
|
}
|
||
|
|
for (size_t index = 0; index < length; ++index) {
|
||
|
|
auto bit = start + index;
|
||
|
|
const auto byte = bit / 8;
|
||
|
|
bit %= 8;
|
||
|
|
if ((raw[byte] & kMask[bit]) == 0 ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string A2lHelper::GetStem(const std::string& path) {
|
||
|
|
// First parse out the file name
|
||
|
|
const auto last_back_pos = path.find_last_of('\\');
|
||
|
|
const auto back_pos = last_back_pos != std::string::npos;
|
||
|
|
|
||
|
|
const auto last_forward_pos = path.find_last_of('/');
|
||
|
|
const auto forward_pos = last_forward_pos != std::string::npos;
|
||
|
|
|
||
|
|
std::string filename;
|
||
|
|
if (back_pos && forward_pos) {
|
||
|
|
if ( last_back_pos > last_forward_pos) {
|
||
|
|
// Use backward slash position
|
||
|
|
filename = path.substr(last_back_pos + 1);
|
||
|
|
} else {
|
||
|
|
// Use forward slash position
|
||
|
|
filename = path.substr(last_forward_pos + 1);
|
||
|
|
}
|
||
|
|
} else if (back_pos) {
|
||
|
|
filename = path.substr(last_back_pos + 1);
|
||
|
|
} else if (forward_pos) {
|
||
|
|
filename = path.substr(last_forward_pos + 1);
|
||
|
|
} else {
|
||
|
|
filename = path;
|
||
|
|
}
|
||
|
|
// Strip out the extension
|
||
|
|
std::string stem;
|
||
|
|
const auto last_dot_pos = filename.find_last_of('.');
|
||
|
|
if (last_dot_pos != std::string::npos) {
|
||
|
|
stem = filename.substr(0,last_dot_pos);
|
||
|
|
} else {
|
||
|
|
stem = filename;
|
||
|
|
}
|
||
|
|
|
||
|
|
return stem;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool A2lHelper::FileExist(const std::string& path) {
|
||
|
|
std::ifstream temp(path);
|
||
|
|
return temp.good();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool A2lHelper::IsLittleEndian() {
|
||
|
|
constexpr int temp = 1;
|
||
|
|
return *((const int8_t*) &temp) == 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string A2lHelper::ParseIfDataProtocol(const std::string& input) {
|
||
|
|
constexpr std::string_view begin = "/begin";
|
||
|
|
constexpr std::string_view if_data = "IF_DATA";
|
||
|
|
size_t pos = 0;
|
||
|
|
if (strncmp(input.data(), begin.data(), begin.size()) != 0) {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
pos += begin.size();
|
||
|
|
while (std::isspace(input[pos])) {
|
||
|
|
++pos;
|
||
|
|
}
|
||
|
|
if (strncmp(input.data() + pos, if_data.data(), if_data.size()) != 0) {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
pos += if_data.size();
|
||
|
|
while (std::isspace(input[pos])) {
|
||
|
|
++pos;
|
||
|
|
}
|
||
|
|
std::ostringstream protocol;
|
||
|
|
while (input[pos] != '\0' && !std::isspace(input[pos])) {
|
||
|
|
protocol << input[pos];
|
||
|
|
++pos;
|
||
|
|
}
|
||
|
|
return protocol.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
int A2lHelper::stricmp(const char *__s1, const char *__s2) {
|
||
|
|
#if (_MSC_VER)
|
||
|
|
return _stricmp(__s1, __s2);
|
||
|
|
#else
|
||
|
|
return strcasecmp(__s1, __s2);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|