mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
651 lines
26 KiB
C++
651 lines
26 KiB
C++
#ifndef SDV_SERDES_INL
|
|
#define SDV_SERDES_INL
|
|
|
|
#ifndef SDV_SERDES_H
|
|
#error Do not include "serdes.inl" directly. Include "serdes.h" instead!
|
|
#endif //!defined SDV_SERDES_H
|
|
|
|
#include <type_traits>
|
|
|
|
namespace sdv
|
|
{
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline serializer<eTargetEndianess, TCRC>::serializer() noexcept
|
|
{}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
template <typename T>
|
|
inline void serializer<eTargetEndianess, TCRC>::push_back(T tValue)
|
|
{
|
|
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
|
|
|
// Make certain the data fits and align to the proper address.
|
|
extend_and_align<T>();
|
|
|
|
// Without buffer there is no serialization.
|
|
if (!m_ptrBuffer) return;
|
|
|
|
if constexpr (eTargetEndianess == GetPlatformEndianess()) // No swapping
|
|
*reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset) = tValue;
|
|
else // Swap bytes
|
|
{
|
|
uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
|
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
|
pData[nIndex] = reinterpret_cast<uint8_t*>(&tValue)[sizeof(T) - nIndex - 1];
|
|
}
|
|
|
|
// Calculate CRC
|
|
for (size_t nIndex = m_nOffset; nIndex < m_nOffset + sizeof(T); nIndex++)
|
|
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
|
|
|
// Increase offset
|
|
m_nOffset += sizeof(T);
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline void serializer<eTargetEndianess, TCRC>::attach(pointer<uint8_t>&& rptrBuffer, size_t nOffset /*= 0*/, typename TCRC::TCRCType uiChecksum /*= 0u*/)
|
|
{
|
|
if (nOffset > rptrBuffer.size())
|
|
{
|
|
XOffsetPastBufferSize exception;
|
|
exception.uiOffset = static_cast<uint32_t>(nOffset);
|
|
exception.uiSize = static_cast<uint32_t>(rptrBuffer.size());
|
|
throw exception;
|
|
}
|
|
|
|
m_ptrBuffer = std::move(rptrBuffer);
|
|
m_nOffset = nOffset;
|
|
m_crcChecksum.set_checksum(uiChecksum);
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline void serializer<eTargetEndianess, TCRC>::detach(pointer<uint8_t>& rptrBuffer)
|
|
{
|
|
// Reduce the buffer to the currently calculated offset.
|
|
if (m_ptrBuffer)
|
|
m_ptrBuffer.resize(m_nOffset);
|
|
|
|
// Assign the buffer
|
|
rptrBuffer = std::move(m_ptrBuffer);
|
|
|
|
// Clear the offset
|
|
m_nOffset = 0;
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline void serializer<eTargetEndianess, TCRC>::reserve(size_t nSize)
|
|
{
|
|
// Check whether reservation is required.
|
|
if (m_ptrBuffer.size() < m_nOffset + nSize)
|
|
m_ptrBuffer.resize(m_ptrBuffer.size() + nSize);
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline pointer<uint8_t> serializer<eTargetEndianess, TCRC>::buffer() const
|
|
{
|
|
pointer<uint8_t> ptrLocal = m_ptrBuffer;
|
|
|
|
// Reduce the buffer to the currently calculated offset.
|
|
if (ptrLocal)
|
|
ptrLocal.resize(m_nOffset);
|
|
|
|
// Return a copy of the smart pointer to the internal buffer.
|
|
return ptrLocal;
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline typename TCRC::TCRCType serializer<eTargetEndianess, TCRC>::checksum() const noexcept
|
|
{
|
|
return m_crcChecksum.get_checksum();
|
|
}
|
|
|
|
template <EEndian eTargetEndianess, typename TCRC>
|
|
inline size_t serializer<eTargetEndianess, TCRC>::offset() const
|
|
{
|
|
return m_nOffset;
|
|
}
|
|
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
template <typename T>
|
|
inline void serializer<eTargetEndianess, TCRC>::extend_and_align()
|
|
{
|
|
// Align the offset position dependable on the size of the variable to add.
|
|
size_t nOffsetNew = m_nOffset;
|
|
if ((nOffsetNew & (sizeof(T) - 1)) != 0)
|
|
nOffsetNew = (nOffsetNew | (sizeof(T) - 1)) + 1;
|
|
|
|
// Check if the buffer size is large enough to hold the alignment and the type.
|
|
// If not, extend with 1024 bytes.
|
|
if ((nOffsetNew + sizeof(T)) > m_ptrBuffer.size())
|
|
m_ptrBuffer.resize(m_ptrBuffer.size() + 1024);
|
|
|
|
// Fill the buffer with padding and add the padding to the checksum value calculation.
|
|
for (size_t nIndex = m_nOffset; nIndex != nOffsetNew; nIndex++)
|
|
{
|
|
m_ptrBuffer[m_nOffset] = 0x00;
|
|
m_crcChecksum.add(static_cast<uint8_t>(0x00));
|
|
}
|
|
|
|
// Set the new offset
|
|
m_nOffset = nOffsetNew;
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline deserializer<eSourceEndianess, TCRC>::deserializer()
|
|
{}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
template <typename T>
|
|
inline void deserializer<eSourceEndianess, TCRC>::pop_front(T& rtValue)
|
|
{
|
|
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
|
|
|
// Without buffer there is no deserialization.
|
|
if (!m_ptrBuffer) return;
|
|
|
|
// Align to the proper address.
|
|
align<T>();
|
|
|
|
// Check whether the buffer contains the data requested
|
|
if (m_ptrBuffer.size() < m_nOffset + sizeof(T))
|
|
{
|
|
sdv::XBufferTooSmall exception;
|
|
exception.uiSize = m_nOffset + sizeof(T);
|
|
exception.uiCapacity = m_ptrBuffer.size();
|
|
throw exception;
|
|
}
|
|
|
|
// Calculate CRC
|
|
for (size_t nIndex = m_nOffset; nIndex < m_nOffset + sizeof(T); nIndex++)
|
|
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
|
|
|
// Copy data
|
|
if constexpr (eSourceEndianess == GetPlatformEndianess()) // No swapping
|
|
rtValue = *reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset);
|
|
else // Swap bytes
|
|
{
|
|
const uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
|
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
|
reinterpret_cast<uint8_t*>(&rtValue)[nIndex] = pData[sizeof(T) - nIndex - 1];
|
|
}
|
|
|
|
// Increase offset
|
|
m_nOffset += sizeof(T);
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
template <typename T>
|
|
inline void deserializer<eSourceEndianess, TCRC>::peek_front(T& rtValue)
|
|
{
|
|
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_enum_v<T>);
|
|
|
|
// Without buffer there is no deserialization.
|
|
if (!m_ptrBuffer) return;
|
|
|
|
// Store the offset and checksum
|
|
size_t nOffsetTemp = m_nOffset;
|
|
auto nChecksum = m_crcChecksum.get_checksum();
|
|
|
|
// Make certain the data fits and align to the proper address.
|
|
align<T>();
|
|
|
|
// Check whether the buffer contains the data requested
|
|
if (m_ptrBuffer.size() < m_nOffset + sizeof(T))
|
|
{
|
|
sdv::XBufferTooSmall exception;
|
|
exception.uiSize = m_nOffset + sizeof(T);
|
|
exception.uiCapacity = m_ptrBuffer.size();
|
|
throw exception;
|
|
}
|
|
|
|
// Copy data
|
|
if constexpr (eSourceEndianess == GetPlatformEndianess()) // No swapping
|
|
rtValue = *reinterpret_cast<T*>(m_ptrBuffer.get() + m_nOffset);
|
|
else // Swap bytes
|
|
{
|
|
const uint8_t* pData = m_ptrBuffer.get() + m_nOffset;
|
|
for (size_t nIndex = 0; nIndex < sizeof(T); nIndex++)
|
|
reinterpret_cast<uint8_t*>(&rtValue)[nIndex] = pData[sizeof(T) - nIndex - 1];
|
|
}
|
|
|
|
// Reset the offset and checksum
|
|
m_nOffset = nOffsetTemp;
|
|
m_crcChecksum.set_checksum(nChecksum);
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline void deserializer<eSourceEndianess, TCRC>::assign(const uint8_t* pData, size_t nSize, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
|
{
|
|
if (!pData) throw XNullPointer();
|
|
|
|
// Check the checksum value
|
|
if (uiChecksum)
|
|
{
|
|
crcCCITT_FALSE crcChecksum;
|
|
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
|
crcChecksum.add(pData[nIndex]);
|
|
if (crcChecksum.get_checksum() != uiChecksum)
|
|
{
|
|
XHashNotMatching exception;
|
|
exception.uiCalculated = crcChecksum.get_checksum();
|
|
exception.uiProvided = uiChecksum;
|
|
throw exception;
|
|
}
|
|
}
|
|
|
|
m_pData = pData;
|
|
m_nSize = nSize;
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline void deserializer<eSourceEndianess, TCRC>::attach(const pointer<uint8_t>& rptrData, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
|
{
|
|
m_ptrBuffer = rptrData;
|
|
assign(rptrData.get(), rptrData.size(), uiChecksum);
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline typename TCRC::TCRCType deserializer<eSourceEndianess, TCRC>::checksum() const noexcept
|
|
{
|
|
return m_crcChecksum.get_checksum();
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
template <typename T>
|
|
inline void deserializer<eSourceEndianess, TCRC>::align()
|
|
{
|
|
// Align the offset position dependable on the size of the variable to get.
|
|
if ((m_nOffset & (sizeof(T) - 1)) != 0)
|
|
{
|
|
size_t nOffsetNew = (m_nOffset | (sizeof(T) - 1)) + 1;
|
|
|
|
// Add the padding to the checksum value calculation.
|
|
for (size_t nIndex = m_nOffset; nIndex != nOffsetNew; nIndex++)
|
|
m_crcChecksum.add(m_ptrBuffer[nIndex]);
|
|
|
|
m_nOffset = nOffsetNew;
|
|
}
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline size_t deserializer<eSourceEndianess, TCRC>::size() const
|
|
{
|
|
return m_nSize;
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline size_t deserializer<eSourceEndianess, TCRC>::offset() const
|
|
{
|
|
return m_nOffset;
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
inline size_t deserializer<eSourceEndianess, TCRC>::remaining() const
|
|
{
|
|
return m_nSize - std::min(m_nOffset, m_nSize);
|
|
}
|
|
|
|
template <EEndian eSourceEndianess, typename TCRC>
|
|
void deserializer<eSourceEndianess, TCRC>::jump(size_t nOffset, typename TCRC::TCRCType uiChecksum /*= 0*/)
|
|
{
|
|
if (nOffset > m_ptrBuffer.size())
|
|
{
|
|
XOffsetPastBufferSize exception;
|
|
exception.uiOffset = static_cast<uint32_t>(nOffset);
|
|
exception.uiSize = static_cast<uint32_t>(m_ptrBuffer.size());
|
|
throw exception;
|
|
}
|
|
|
|
m_nOffset = nOffset;
|
|
m_crcChecksum.set_checksum(uiChecksum);
|
|
}
|
|
|
|
template <typename T>
|
|
inline void ser_size(const T& rtValue, size_t& rnSize)
|
|
{
|
|
serdes::CSerdes<T>::CalcSize(rtValue, rnSize);
|
|
}
|
|
} // namespace sdv
|
|
|
|
namespace serdes
|
|
{
|
|
template <typename T>
|
|
inline void CSerdes<T>::CalcSize([[maybe_unused]] const T& rtValue, size_t& rnSize)
|
|
{
|
|
static_assert(std::is_fundamental_v<T> || std::is_enum_v<T>);
|
|
|
|
// Add alignment if necessary
|
|
size_t nBytes = rnSize % sizeof(T);
|
|
if (nBytes) rnSize += sizeof(T) - nBytes;
|
|
|
|
// Increase the size
|
|
rnSize += sizeof(T);
|
|
}
|
|
|
|
template <typename T>
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline sdv::serializer<eTargetEndianess, TCRC>& CSerdes<T>::Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue)
|
|
{
|
|
rSerializer.push_back(rtValue);
|
|
return rSerializer;
|
|
}
|
|
|
|
template <typename T>
|
|
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
|
inline sdv::deserializer<eSourceEndianess, TCRC>& CSerdes<T>::Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue)
|
|
{
|
|
rDeserializer.pop_front(rtValue);
|
|
return rDeserializer;
|
|
}
|
|
|
|
/**
|
|
* @brief Specialization of serializer/deserializer class.
|
|
* @tparam T Type of the variable.
|
|
* @tparam nSize The size of the provided array.
|
|
*/
|
|
template <typename T, size_t nSize>
|
|
class CSerdes<T[nSize]>
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Calculate the size of the value in serialized form.
|
|
* @remarks Dependable on the size value, padding is added to align data.
|
|
* @param[in] rrgtValue Reference to an array with variables.
|
|
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
|
*/
|
|
static void CalcSize([[maybe_unused]] const T(&rrgtValue)[nSize], size_t& rnSize)
|
|
{
|
|
for (const T& rtValue : rrgtValue)
|
|
sdv::ser_size(rtValue, rnSize);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the variable into the serializer.
|
|
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rSerializer Reference to the serializer.
|
|
* @param[in] rrgtValue Reference to an array with variables.
|
|
* @return Reference to the serializer.
|
|
*/
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T(&rrgtValue)[nSize])
|
|
{
|
|
// Reserve the space in the serializer (this speeds up the serialization process).
|
|
rSerializer.reserve(nSize * sizeof(T));
|
|
|
|
// Serialize all entries
|
|
for (const T& rtValue : rrgtValue)
|
|
CSerdes<T>::Serialize(rSerializer, rtValue);
|
|
return rSerializer;
|
|
}
|
|
|
|
/**
|
|
* @brief Stream a variable from the deserializer.
|
|
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rDeserializer Reference to the deserializer.
|
|
* @param[out] rrgtValue Reference to an array with variables to be filled.
|
|
* @return Reference to the deserializer.
|
|
*/
|
|
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
|
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T(&rrgtValue)[nSize])
|
|
{
|
|
for (T& rtValue : rrgtValue)
|
|
CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
|
return rDeserializer;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief Specialization of serializer/deserializer class.
|
|
* @tparam T Type of the variable.
|
|
* @tparam nFixedSize The fixed size of the pointer or 0 when the pointer is dynamic.
|
|
*/
|
|
template <typename T, size_t nFixedSize>
|
|
class CSerdes<sdv::pointer<T, nFixedSize>>
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Calculate the size of the value in serialized form.
|
|
* @remarks Dependable on the size value, padding is added to align data.
|
|
* @param[in] rptrValue Reference to the pointer.
|
|
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
|
*/
|
|
static void CalcSize(const sdv::pointer<T, nFixedSize>& rptrValue, size_t& rnSize)
|
|
{
|
|
sdv::ser_size(static_cast<uint64_t>(rptrValue.size()), rnSize);
|
|
if constexpr (std::is_fundamental_v<T>)
|
|
rnSize += rptrValue.size() * sizeof(T);
|
|
else
|
|
{
|
|
for (size_t n = 0; n < rptrValue.size(); n++)
|
|
sdv::ser_size(rptrValue.get()[n], rnSize);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the pointer variable into the serializer.
|
|
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rSerializer Reference to the serializer.
|
|
* @param[in] rptrValue Reference to the pointer.
|
|
* @return Reference to the serializer.
|
|
*/
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::pointer<T, nFixedSize>& rptrValue)
|
|
{
|
|
rSerializer << static_cast<uint64_t>(rptrValue.size());
|
|
if (rptrValue)
|
|
{
|
|
// Reserve the space in the serializer (this speeds up the serialization process).
|
|
rSerializer.reserve(rptrValue.size() * sizeof(T));
|
|
|
|
// Serialize all entries
|
|
const T* ptValue = rptrValue.get();
|
|
for (size_t nIndex = 0; nIndex < rptrValue.size(); nIndex++)
|
|
CSerdes<T>::Serialize(rSerializer, ptValue[nIndex]);
|
|
}
|
|
return rSerializer;
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the pointer variable from the deserializer.
|
|
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rDeserializer Reference to the deserializer.
|
|
* @param[in] rptrValue Reference to the pointer.
|
|
* @return Reference to the deserializer.
|
|
*/
|
|
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
|
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::pointer<T, nFixedSize>& rptrValue)
|
|
{
|
|
uint64_t nSize = 0;
|
|
rDeserializer >> nSize;
|
|
if (nSize * sizeof(T) > rDeserializer.remaining())
|
|
{
|
|
sdv::XOffsetPastBufferSize exception;
|
|
exception.uiSize = rDeserializer.size();
|
|
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(T);
|
|
throw exception;
|
|
}
|
|
rptrValue.resize(nSize);
|
|
if (nSize && rptrValue)
|
|
{
|
|
T* ptValue = rptrValue.get();
|
|
for (size_t nIndex = 0; nIndex < nSize; nIndex++)
|
|
CSerdes<T>::Deserialize(rDeserializer, ptValue[nIndex]);
|
|
}
|
|
return rDeserializer;
|
|
}
|
|
};
|
|
/**
|
|
* @brief Specialization of serializer/deserializer class.
|
|
* @tparam T Type of the variable.
|
|
* @tparam nFixedSize The fixed size of the sequence or 0 when the sequence is dynamic.
|
|
*/
|
|
template <typename T, size_t nFixedSize>
|
|
class CSerdes<sdv::sequence<T, nFixedSize>>
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Calculate the size of the value in serialized form.
|
|
* @remarks Dependable on the size value, padding is added to align data.
|
|
* @param[in] rseqValue Reference to the sequence.
|
|
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
|
*/
|
|
static void CalcSize(const sdv::sequence<T, nFixedSize>& rseqValue, size_t& rnSize)
|
|
{
|
|
sdv::ser_size(static_cast<uint64_t>(rseqValue.size()), rnSize);
|
|
if constexpr (std::is_fundamental_v<T>)
|
|
rnSize += rseqValue.size() * sizeof(T);
|
|
else
|
|
{
|
|
for (const T& rValue: rseqValue)
|
|
sdv::ser_size(rValue, rnSize);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the sequence variable into the serializer.
|
|
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rSerializer Reference to the serializer.
|
|
* @param[in] rseqValue Reference to the sequence.
|
|
* @return Reference to the serializer.
|
|
*/
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::sequence<T, nFixedSize>& rseqValue)
|
|
{
|
|
rSerializer << static_cast<uint64_t>(rseqValue.size());
|
|
|
|
// Reserve the space in the serializer (this speeds up the serialization process).
|
|
rSerializer.reserve(rseqValue.size() * sizeof(T));
|
|
|
|
// Serialize all entries
|
|
for (const T& rtValue : rseqValue)
|
|
CSerdes<T>::Serialize(rSerializer, rtValue);
|
|
return rSerializer;
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the sequence variable from the deserializer.
|
|
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rDeserializer Reference to the deserializer.
|
|
* @param[in] rseqValue Reference to the sequence.
|
|
* @return Reference to the deserializer.
|
|
*/
|
|
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
|
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::sequence<T, nFixedSize>& rseqValue)
|
|
{
|
|
uint64_t nSize = 0;
|
|
rDeserializer >> nSize;
|
|
if (nSize * sizeof(T) > rDeserializer.remaining())
|
|
{
|
|
sdv::XOffsetPastBufferSize exception;
|
|
exception.uiSize = rDeserializer.size();
|
|
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(T);
|
|
throw exception;
|
|
}
|
|
rseqValue.resize(nSize);
|
|
if (nSize)
|
|
{
|
|
for (T& rtValue : rseqValue)
|
|
CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
|
}
|
|
return rDeserializer;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief Specialization of serializer/deserializer class.
|
|
* @tparam TCharType Type of the string.
|
|
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @tparam bUnicode When set, the string is a unicode string.
|
|
* @tparam nFixedSize The fixed size of the string or 0 when the string is dynamic.
|
|
*/
|
|
template <typename TCharType, bool bUnicode, size_t nFixedSize>
|
|
class CSerdes<sdv::string_base<TCharType, bUnicode, nFixedSize>>
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Calculate the size of the value in serialized form.
|
|
* @remarks Dependable on the size value, padding is added to align data.
|
|
* @param[in] rssValue Reference to the string.
|
|
* @param[in, out] rnSize Reference to the variable containing the current size and increased by the size of the value.
|
|
*/
|
|
static void CalcSize(const sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue, size_t& rnSize)
|
|
{
|
|
sdv::ser_size(static_cast<uint64_t>(rssValue.size()), rnSize);
|
|
rnSize += rssValue.size() * sizeof(TCharType);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the string variable into the serializer.
|
|
* @tparam eTargetEndianess The target endianess detemines whether to swap the bytes before storing them into the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rSerializer Reference to the serializer.
|
|
* @param[in] rssValue Reference to the string.
|
|
* @return Reference to the serializer.
|
|
*/
|
|
template <sdv::EEndian eTargetEndianess, typename TCRC>
|
|
static sdv::serializer<eTargetEndianess, TCRC>& Serialize(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue)
|
|
{
|
|
rSerializer << static_cast<uint64_t>(rssValue.size());
|
|
|
|
// Reserve the space in the serializer (this speeds up the serialization process).
|
|
rSerializer.reserve(rssValue.size() * sizeof(TCharType));
|
|
|
|
// Serialize all entries
|
|
for (TCharType tValue : rssValue)
|
|
CSerdes<TCharType>::Serialize(rSerializer, tValue);
|
|
return rSerializer;
|
|
}
|
|
|
|
/**
|
|
* @brief Stream the string variable from the deserializer.
|
|
* @tparam eSourceEndianess The source endianess detemines whether to swap the bytes after retrieving them from the buffer.
|
|
* @tparam TCRC The CRC type to use for the checksum calculation.
|
|
* @param[in] rDeserializer Reference to the deserializer.
|
|
* @param[in] rssValue Reference to the string.
|
|
* @return Reference to the deserializer.
|
|
*/
|
|
template <sdv::EEndian eSourceEndianess, typename TCRC>
|
|
static sdv::deserializer<eSourceEndianess, TCRC>& Deserialize(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, sdv::string_base<TCharType, bUnicode, nFixedSize>& rssValue)
|
|
{
|
|
uint64_t nSize = 0;
|
|
rDeserializer >> nSize;
|
|
if (nSize * sizeof(TCharType) > rDeserializer.remaining())
|
|
{
|
|
sdv::XOffsetPastBufferSize exception;
|
|
exception.uiSize = rDeserializer.size();
|
|
exception.uiOffset = rDeserializer.offset() + nSize * sizeof(TCharType);
|
|
throw exception;
|
|
}
|
|
rssValue.resize(nSize);
|
|
if (nSize)
|
|
{
|
|
for (TCharType& rtValue : rssValue)
|
|
CSerdes<TCharType>::Deserialize(rDeserializer, rtValue);
|
|
}
|
|
return rDeserializer;
|
|
}
|
|
};
|
|
} // namespace serdes
|
|
|
|
template <typename T, sdv::EEndian eTargetEndianess, typename TCRC>
|
|
inline sdv::serializer<eTargetEndianess, TCRC>& operator<<(sdv::serializer<eTargetEndianess, TCRC>& rSerializer, const T& rtValue)
|
|
{
|
|
serdes::CSerdes<T>::Serialize(rSerializer, rtValue);
|
|
return rSerializer;
|
|
}
|
|
|
|
template <typename T, sdv::EEndian eSourceEndianess, typename TCRC>
|
|
inline sdv::deserializer<eSourceEndianess, TCRC>& operator>>(sdv::deserializer<eSourceEndianess, TCRC>& rDeserializer, T& rtValue)
|
|
{
|
|
serdes::CSerdes<T>::Deserialize(rDeserializer, rtValue);
|
|
return rDeserializer;
|
|
}
|
|
|
|
#endif // !defined SDV_SERDES_INL
|