Skip to content

Commit

Permalink
refactor encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan McDermid authored and jonathanmcdermid committed Nov 8, 2024
1 parent dfb3f09 commit 9f5abcd
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 37 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Benchmark
on:
push:
branches:
- main
- dev-jmcdermid-benchmarks

jobs:
benchmark:
Expand Down Expand Up @@ -41,3 +41,9 @@ jobs:
tool: 'googlecpp'
output-file-path: benchmark_output.json
github-token: ${{ secrets.GITHUB_TOKEN }}
comment-on-alert: true
summary-always: true
alert-comment-cc-users: '@jonathanmcdermid'
auto-push: true
alert-threshold: 120%
fail-threshold: 200%
26 changes: 14 additions & 12 deletions include/novatel_edie/decoders/common/encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,19 @@ template <typename... Args> [[nodiscard]] bool PrintToBuffer(char** ppcBuffer_,
}

// -------------------------------------------------------------------------------------------------------
template <typename T> constexpr std::array<char, 7> MakeConversionString(const FieldContainer& fc_)
template <typename T> constexpr std::array<char, 7> FloatingPointConversionString(const FieldContainer& fc_)
{
static_assert(std::is_floating_point_v<T>, "FloatingPointConversionString must be called with a floating point type");
std::array<char, 7> acConvert{};
const int32_t iBefore = fc_.fieldDef->conversionBeforePoint;
const int32_t iAfter = fc_.fieldDef->conversionAfterPoint;
const auto fVal = std::get<T>(fc_.fieldValue);
const auto absVal = fabs(std::get<T>(fc_.fieldValue));

[[maybe_unused]] int32_t iRes = fabs(fVal) < std::numeric_limits<T>::epsilon() ? snprintf(acConvert.data(), 7, "%%0.%df", iAfter)
: iAfter == 0 && iBefore == 0 ? snprintf(acConvert.data(), 7, "%%0.1f")
: fabs(fVal) > pow(10.0, iBefore) ? snprintf(acConvert.data(), 7, "%%0.%de", iBefore + iAfter - 1)
: fabs(fVal) < pow(10.0, -iBefore) ? snprintf(acConvert.data(), 7, "%%0.%de", iAfter)
: snprintf(acConvert.data(), 7, "%%0.%df", iAfter);
[[maybe_unused]] int32_t iRes = absVal < std::numeric_limits<T>::epsilon() ? snprintf(acConvert.data(), 7, "%%0.%df", iAfter)
: iAfter == 0 && iBefore == 0 ? snprintf(acConvert.data(), 7, "%%0.1f")
: absVal > pow(10, iBefore) ? snprintf(acConvert.data(), 7, "%%0.%de", iBefore + iAfter - 1)
: absVal < pow(10, -iBefore) ? snprintf(acConvert.data(), 7, "%%0.%de", iAfter)
: snprintf(acConvert.data(), 7, "%%0.%df", iAfter);

assert(0 <= iRes && iRes < 7);
return acConvert;
Expand All @@ -96,7 +97,7 @@ template <typename T> [[nodiscard]] bool CopyToBuffer(unsigned char** ppucBuffer
{
uint32_t uiItemSize;

if constexpr (std::is_same<T, const char>()) { uiItemSize = static_cast<uint32_t>(strlen(ptItem_)); }
if constexpr (std::is_same<T, const char>()) { uiItemSize = static_cast<uint32_t>(std::strlen(ptItem_)); }
else { uiItemSize = sizeof(*ptItem_); }

if (uiBytesLeft_ < uiItemSize) { return false; }
Expand Down Expand Up @@ -137,18 +138,19 @@ class EncoderBase

// Encode binary
template <bool Flatten, bool Align>
[[nodiscard]] bool EncodeBinaryBody(const std::vector<FieldContainer>& stInterMessage_, unsigned char** ppucOutBuf_, uint32_t& uiBytesLeft_);
[[nodiscard]] virtual bool FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_);
[[nodiscard]] bool EncodeBinaryBody(const std::vector<FieldContainer>& stInterMessage_, unsigned char** ppucOutBuf_,
uint32_t& uiBytesLeft_) const;
[[nodiscard]] virtual bool FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_) const;

// Encode ascii
template <bool Abbreviated>
[[nodiscard]] bool EncodeAsciiBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
[[maybe_unused]] uint32_t uiIndentationLevel_ = 1);
[[maybe_unused]] uint32_t uiIndentationLevel_ = 1) const;
[[nodiscard]] bool FieldToAscii(const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const;

// Encode JSON
[[nodiscard]] bool FieldToJson(const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const;
[[nodiscard]] bool EncodeJsonBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_);
[[nodiscard]] bool EncodeJsonBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const;

virtual void InitEnumDefinitions();
virtual void InitFieldMaps();
Expand Down
8 changes: 4 additions & 4 deletions include/novatel_edie/decoders/oem/encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Encoder : public EncoderBase
// Encode binary
[[nodiscard]] static bool EncodeBinaryHeader(const IntermediateHeader& stInterHeader_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_);
[[nodiscard]] static bool EncodeBinaryShortHeader(const IntermediateHeader& stInterHeader_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_);
[[nodiscard]] bool FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_) override;
[[nodiscard]] bool FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_) const override;

// Encode ascii
[[nodiscard]] bool EncodeAsciiHeader(const IntermediateHeader& stInterHeader_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const;
Expand Down Expand Up @@ -109,7 +109,7 @@ class Encoder : public EncoderBase
//----------------------------------------------------------------------------
[[nodiscard]] STATUS Encode(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const IntermediateHeader& stHeader_,
const std::vector<FieldContainer>& stMessage_, MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_,
ENCODE_FORMAT eFormat_);
ENCODE_FORMAT eFormat_) const;

//----------------------------------------------------------------------------
//! \brief Encode an OEM message header from the provided intermediate header.
Expand Down Expand Up @@ -142,7 +142,7 @@ class Encoder : public EncoderBase
//----------------------------------------------------------------------------
[[nodiscard]] STATUS EncodeHeader(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const IntermediateHeader& stHeader_,
MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_, ENCODE_FORMAT eFormat_,
bool bIsEmbeddedHeader_ = false);
bool bIsEmbeddedHeader_ = false) const;

//----------------------------------------------------------------------------
//! \brief Encode an OEM message body from the provided intermediate message.
Expand Down Expand Up @@ -172,7 +172,7 @@ class Encoder : public EncoderBase
//! encoding.
//----------------------------------------------------------------------------
[[nodiscard]] STATUS EncodeBody(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const std::vector<FieldContainer>& stMessage_,
MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_, ENCODE_FORMAT eFormat_);
MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_, ENCODE_FORMAT eFormat_) const;
};

} // namespace novatel::edie::oem
Expand Down
20 changes: 10 additions & 10 deletions src/decoders/common/src/encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void EncoderBase::SetLoggerLevel(const spdlog::level::level_enum eLevel_) const

// -------------------------------------------------------------------------------------------------------
template <bool Flatten, bool Align>
bool EncoderBase::EncodeBinaryBody(const std::vector<FieldContainer>& stInterMessage_, unsigned char** ppucOutBuf_, uint32_t& uiBytesLeft_)
bool EncoderBase::EncodeBinaryBody(const std::vector<FieldContainer>& stInterMessage_, unsigned char** ppucOutBuf_, uint32_t& uiBytesLeft_) const
{
unsigned char* pucTempStart;

Expand Down Expand Up @@ -204,13 +204,13 @@ bool EncoderBase::EncodeBinaryBody(const std::vector<FieldContainer>& stInterMes
}

// explicit template instantiations
template bool EncoderBase::EncodeBinaryBody<false, false>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&);
template bool EncoderBase::EncodeBinaryBody<false, true>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&);
template bool EncoderBase::EncodeBinaryBody<true, false>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&);
template bool EncoderBase::EncodeBinaryBody<true, true>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&);
template bool EncoderBase::EncodeBinaryBody<false, false>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&) const;
template bool EncoderBase::EncodeBinaryBody<false, true>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&) const;
template bool EncoderBase::EncodeBinaryBody<true, false>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&) const;
template bool EncoderBase::EncodeBinaryBody<true, true>(const std::vector<FieldContainer>&, unsigned char**, uint32_t&) const;

// -------------------------------------------------------------------------------------------------------
bool EncoderBase::FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_)
bool EncoderBase::FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_) const
{
switch (fc_.fieldDef->dataType.name)
{
Expand All @@ -236,7 +236,7 @@ bool EncoderBase::FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOu
// -------------------------------------------------------------------------------------------------------
template <bool Abbreviated>
bool EncoderBase::EncodeAsciiBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
const uint32_t uiIndentationLevel_)
const uint32_t uiIndentationLevel_) const
{
// cant figure out how to do this constexpr since derived classes need to change values
const char separator = Abbreviated ? SeparatorAbbAscii() : SeparatorAscii();
Expand Down Expand Up @@ -387,8 +387,8 @@ bool EncoderBase::EncodeAsciiBody(const std::vector<FieldContainer>& vIntermedia
}

// explicit template instantiations
template bool EncoderBase::EncodeAsciiBody<true>(const std::vector<FieldContainer>&, char**, uint32_t& uiBytesLeft_, uint32_t);
template bool EncoderBase::EncodeAsciiBody<false>(const std::vector<FieldContainer>&, char**, uint32_t& uiBytesLeft_, uint32_t);
template bool EncoderBase::EncodeAsciiBody<true>(const std::vector<FieldContainer>&, char**, uint32_t& uiBytesLeft_, uint32_t) const;
template bool EncoderBase::EncodeAsciiBody<false>(const std::vector<FieldContainer>&, char**, uint32_t& uiBytesLeft_, uint32_t) const;

// -------------------------------------------------------------------------------------------------------
bool EncoderBase::FieldToAscii(const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const
Expand Down Expand Up @@ -418,7 +418,7 @@ bool EncoderBase::FieldToAscii(const FieldContainer& fc_, char** ppcOutBuf_, uin
}

// -------------------------------------------------------------------------------------------------------
bool EncoderBase::EncodeJsonBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_)
bool EncoderBase::EncodeJsonBody(const std::vector<FieldContainer>& vIntermediateFormat_, char** ppcOutBuf_, uint32_t& uiBytesLeft_) const
{
if (!CopyToBuffer(reinterpret_cast<unsigned char**>(ppcOutBuf_), uiBytesLeft_, "{")) { return false; }

Expand Down
20 changes: 10 additions & 10 deletions src/decoders/oem/src/encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ void Encoder::InitFieldMaps()

asciiFieldMap[CalculateBlockCrc32("k")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
[[maybe_unused]] JsonReader* pclMsgDb_) {
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, MakeConversionString<float>(fc_).data(), std::get<float>(fc_.fieldValue));
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, FloatingPointConversionString<float>(fc_).data(), std::get<float>(fc_.fieldValue));
};

asciiFieldMap[CalculateBlockCrc32("lk")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
[[maybe_unused]] JsonReader* pclMsgDb_) {
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, MakeConversionString<double>(fc_).data(), std::get<double>(fc_.fieldValue));
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, FloatingPointConversionString<double>(fc_).data(), std::get<double>(fc_.fieldValue));
};

asciiFieldMap[CalculateBlockCrc32("c")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
Expand Down Expand Up @@ -139,12 +139,12 @@ void Encoder::InitFieldMaps()

jsonFieldMap[CalculateBlockCrc32("k")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
[[maybe_unused]] JsonReader* pclMsgDb_) {
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, MakeConversionString<float>(fc_).data(), std::get<float>(fc_.fieldValue));
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, FloatingPointConversionString<float>(fc_).data(), std::get<float>(fc_.fieldValue));
};

jsonFieldMap[CalculateBlockCrc32("lk")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
[[maybe_unused]] JsonReader* pclMsgDb_) {
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, MakeConversionString<double>(fc_).data(), std::get<double>(fc_.fieldValue));
return PrintToBuffer(ppcOutBuf_, uiBytesLeft_, FloatingPointConversionString<double>(fc_).data(), std::get<double>(fc_.fieldValue));
};

jsonFieldMap[CalculateBlockCrc32("s")] = [](const FieldContainer& fc_, char** ppcOutBuf_, uint32_t& uiBytesLeft_,
Expand Down Expand Up @@ -177,7 +177,7 @@ bool Encoder::EncodeBinaryShortHeader(const IntermediateHeader& stInterHeader_,
}

// -------------------------------------------------------------------------------------------------------
bool Encoder::FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_)
bool Encoder::FieldToBinary(const FieldContainer& fc_, unsigned char** ppcOutBuf_, uint32_t& uiBytesLeft_) const
{
switch (fc_.fieldDef->dataType.name)
{
Expand Down Expand Up @@ -334,7 +334,7 @@ bool Encoder::EncodeJsonShortHeader(const IntermediateHeader& stInterHeader_, ch
STATUS
Encoder::Encode(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const IntermediateHeader& stHeader_,
const std::vector<FieldContainer>& stMessage_, MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_,
const ENCODE_FORMAT eFormat_)
const ENCODE_FORMAT eFormat_) const
{
if (ppucBuffer_ == nullptr || *ppucBuffer_ == nullptr) { return STATUS::NULL_PROVIDED; }

Expand Down Expand Up @@ -376,7 +376,7 @@ Encoder::Encode(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const Inter
// -------------------------------------------------------------------------------------------------------
STATUS
Encoder::EncodeHeader(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const IntermediateHeader& stHeader_, MessageDataStruct& stMessageData_,
const MetaDataStruct& stMetaData_, const ENCODE_FORMAT eFormat_, const bool bIsEmbeddedHeader_)
const MetaDataStruct& stMetaData_, const ENCODE_FORMAT eFormat_, const bool bIsEmbeddedHeader_) const
{
if (ppucBuffer_ == nullptr || *ppucBuffer_ == nullptr) { return STATUS::NULL_PROVIDED; }

Expand Down Expand Up @@ -428,7 +428,7 @@ Encoder::EncodeHeader(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const
// -------------------------------------------------------------------------------------------------------
STATUS
Encoder::EncodeBody(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const std::vector<FieldContainer>& stMessage_,
MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_, ENCODE_FORMAT eFormat_)
MessageDataStruct& stMessageData_, const MetaDataStruct& stMetaData_, ENCODE_FORMAT eFormat_) const
{
// TODO: this entire function should be in common, only header stuff and map redefinitions belong in this file
if (ppucBuffer_ == nullptr || *ppucBuffer_ == nullptr) { return STATUS::NULL_PROVIDED; }
Expand All @@ -442,7 +442,7 @@ Encoder::EncodeBody(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const s
case ENCODE_FORMAT::ASCII: {
if (!EncodeAsciiBody<false>(stMessage_, reinterpret_cast<char**>(&pucTempBuffer), uiBufferSize_)) { return STATUS::BUFFER_FULL; }
pucTempBuffer--; // Remove last delimiter ','
const uint32_t uiCrc = CalculateBlockCrc32(pucTempBuffer - stMessageData_.pucMessageHeader - 1, 0, stMessageData_.pucMessageHeader + 1);
const uint32_t uiCrc = CalculateBlockCrc32(stMessageData_.pucMessageHeader + 1, pucTempBuffer - stMessageData_.pucMessageHeader - 1);
if (!PrintToBuffer(reinterpret_cast<char**>(&pucTempBuffer), uiBufferSize_, "*%08x\r\n", uiCrc)) { return STATUS::BUFFER_FULL; }
break;
}
Expand Down Expand Up @@ -474,7 +474,7 @@ Encoder::EncodeBody(unsigned char** ppucBuffer_, uint32_t uiBufferSize_, const s
{
reinterpret_cast<Oem4BinaryShortHeader*>(stMessageData_.pucMessageHeader)->ucLength = static_cast<uint8_t>(pucTempBuffer - *ppucBuffer_);
}
uint32_t uiCrc = CalculateBlockCrc32(pucTempBuffer - stMessageData_.pucMessageHeader, 0, stMessageData_.pucMessageHeader);
uint32_t uiCrc = CalculateBlockCrc32(stMessageData_.pucMessageHeader, pucTempBuffer - stMessageData_.pucMessageHeader);
if (!CopyToBuffer(&pucTempBuffer, uiBufferSize_, &uiCrc)) { return STATUS::BUFFER_FULL; }
break;
}
Expand Down

0 comments on commit 9f5abcd

Please sign in to comment.