initial commit for github
This commit is contained in:
commit
60968612de
370 changed files with 68427 additions and 0 deletions
345
codec/struct_layout.cpp
Normal file
345
codec/struct_layout.cpp
Normal file
|
@ -0,0 +1,345 @@
|
|||
/**
|
||||
* @file
|
||||
* Implementation of the ADTF default media description.
|
||||
*
|
||||
* @copyright
|
||||
* @verbatim
|
||||
Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved.
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla
|
||||
Public License, v. 2.0. If a copy of the MPL was not distributed
|
||||
with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file, then
|
||||
You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
#include "a_util/result/error_def.h"
|
||||
#include "legacy_error_macros.h"
|
||||
|
||||
#include "struct_layout.h"
|
||||
|
||||
#include <ddl.h>
|
||||
|
||||
namespace ddl
|
||||
{
|
||||
//define all needed error types and values locally
|
||||
_MAKE_RESULT(-5, ERR_INVALID_ARG)
|
||||
_MAKE_RESULT(-19, ERR_NOT_SUPPORTED)
|
||||
_MAKE_RESULT(-37, ERR_NOT_INITIALIZED)
|
||||
|
||||
StructLayout::StructLayout(const DDLComplex* pStruct)
|
||||
{
|
||||
_static_buffer_sizes.deserialized = 0;
|
||||
_static_buffer_sizes.serialized = 0;
|
||||
_calculations_result = calculate(pStruct);
|
||||
}
|
||||
|
||||
StructLayout::StructLayout():
|
||||
_calculations_result(ERR_NOT_INITIALIZED)
|
||||
{
|
||||
_static_buffer_sizes.deserialized = 0;
|
||||
_static_buffer_sizes.serialized = 0;
|
||||
}
|
||||
|
||||
#define IF_TYPE(__type, __vtype, __size) \
|
||||
if (strType == __type) \
|
||||
{ \
|
||||
type = a_util::variant::__vtype;\
|
||||
nTypeSize = __size; \
|
||||
return a_util::result::SUCCESS; \
|
||||
}
|
||||
|
||||
static a_util::result::Result getType(const std::string& strType, a_util::variant::VariantType& type, size_t& nTypeSize)
|
||||
{
|
||||
IF_TYPE("tBool", VT_Bool, 8)
|
||||
else IF_TYPE("tChar", VT_Int8, 8)
|
||||
else IF_TYPE("tInt8", VT_Int8, 8)
|
||||
else IF_TYPE("tUInt8", VT_UInt8, 8)
|
||||
else IF_TYPE("tInt16", VT_Int16, 16)
|
||||
else IF_TYPE("tUInt16", VT_UInt16, 16)
|
||||
else IF_TYPE("tInt32", VT_Int32, 32)
|
||||
else IF_TYPE("tUInt32", VT_UInt32, 32)
|
||||
else IF_TYPE("tInt64", VT_Int64, 64)
|
||||
else IF_TYPE("tUInt64", VT_UInt64, 64)
|
||||
else IF_TYPE("tFloat32", VT_Float32, 32)
|
||||
else IF_TYPE("tFloat64", VT_Float64, 64)
|
||||
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
class cConverter
|
||||
{
|
||||
public:
|
||||
cConverter(std::vector<StructLayoutElement>& static_elements,
|
||||
std::vector<DynamicStructLayoutElement>& dynamic_elements,
|
||||
std::map<std::string, EnumType>& oEnums):
|
||||
m_bDynamicSectionStarted(false),
|
||||
_static_elements(static_elements),
|
||||
_dynamic_elements(dynamic_elements),
|
||||
_enums(oEnums)
|
||||
{
|
||||
m_sOffsets.deserialized = 0;
|
||||
m_sOffsets.serialized = 0;
|
||||
}
|
||||
|
||||
a_util::result::Result Convert(DDLComplex* pStruct)
|
||||
{
|
||||
return addStruct(pStruct, "", m_sOffsets.serialized, pStruct->getDDLVersion() >= DDLVersion::ddl_version_30);
|
||||
}
|
||||
|
||||
Offsets getStaticBufferBitSizes()
|
||||
{
|
||||
return m_sOffsets;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// we are not using a standard visitor pattern because we would have to recreate a stack
|
||||
// for passing along all the additional parameters
|
||||
a_util::result::Result Add(IDDLDataType* pType, const std::string& strFullName, size_t& nSerializedOffset,
|
||||
int byte_order, int nNumBits, const std::string& strConstant, bool is_last_array_element)
|
||||
{
|
||||
DDLDataType* pPODType = dynamic_cast<DDLDataType*>(pType);
|
||||
DDLEnum* p_enum = dynamic_cast<DDLEnum*>(pType);
|
||||
EnumType* pCodecEnum = NULL;
|
||||
if (p_enum)
|
||||
{
|
||||
pPODType = dynamic_cast<DDLDataType*>(p_enum->getTypeObject());
|
||||
pCodecEnum = GetCodecEnum(p_enum);
|
||||
}
|
||||
|
||||
if (pPODType)
|
||||
{
|
||||
return AddPODElement(pPODType, strFullName, nSerializedOffset, byte_order,
|
||||
nNumBits, pCodecEnum, strConstant);
|
||||
}
|
||||
else
|
||||
{
|
||||
DDLComplex* pStruct = dynamic_cast<DDLComplex*>(pType);
|
||||
if (pStruct)
|
||||
{
|
||||
return addStruct(pStruct, strFullName, nSerializedOffset,
|
||||
// prior to DDL 3.0 the last array element is not padded to the alignment
|
||||
!is_last_array_element || pStruct->getDDLVersion() >= DDLVersion::ddl_version_30);
|
||||
}
|
||||
|
||||
return ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
EnumType* GetCodecEnum(DDLEnum* p_enum)
|
||||
{
|
||||
std::map<std::string, EnumType>::iterator itEnum = _enums.find(p_enum->getName());
|
||||
if (itEnum == _enums.end())
|
||||
{
|
||||
EnumType oCodecEnum;
|
||||
const EnumNameValueVec& vecValues = p_enum->getValues();
|
||||
for (EnumNameValueVec::const_iterator it = vecValues.begin(); it != vecValues.end(); ++it)
|
||||
{
|
||||
oCodecEnum.insert(std::make_pair(it->first, a_util::variant::Variant(it->second.c_str())));
|
||||
}
|
||||
itEnum = _enums.insert(std::make_pair(p_enum->getName(), oCodecEnum)).first;
|
||||
}
|
||||
return &itEnum->second;
|
||||
}
|
||||
|
||||
a_util::result::Result AddPODElement(DDLDataType* pDataType, const std::string& strFullName,
|
||||
size_t& nSerializedOffset, int byte_order, int nNumBits,
|
||||
EnumType* p_enum,
|
||||
const std::string& strConstant)
|
||||
{
|
||||
StructLayoutElement sElement;
|
||||
sElement.name = strFullName;
|
||||
RETURN_IF_FAILED(getType(pDataType->getName(), sElement.type, sElement.deserialized.bit_size));
|
||||
sElement.deserialized.bit_offset = m_sOffsets.deserialized;
|
||||
sElement.serialized.bit_offset = nSerializedOffset;
|
||||
sElement.serialized.bit_size = nNumBits ? nNumBits : pDataType->getNumBits();
|
||||
sElement.byte_order = byte_order;
|
||||
sElement.p_enum = p_enum;
|
||||
sElement.constant = FindConstant(strConstant);
|
||||
_static_elements.push_back(sElement);
|
||||
|
||||
m_sOffsets.deserialized += sElement.deserialized.bit_size;
|
||||
nSerializedOffset += sElement.serialized.bit_size;
|
||||
return a_util::result::SUCCESS;
|
||||
}
|
||||
|
||||
const a_util::variant::Variant* FindConstant(const std::string& strConstant)
|
||||
{
|
||||
if (!strConstant.empty())
|
||||
{
|
||||
for (std::map<std::string, EnumType>::const_iterator it = _enums.begin(); it != _enums.end(); ++it)
|
||||
{
|
||||
EnumType::const_iterator itValue = it->second.find(strConstant);
|
||||
if (itValue != it->second.end())
|
||||
{
|
||||
return &itValue->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a_util::result::Result addStruct(DDLComplex* pStruct, const std::string& strFullName, size_t& nSerializedOffset, bool resize_to_alignment)
|
||||
{
|
||||
std::string strStructPrefix = (!strFullName.empty()) ? strFullName + "." : "";
|
||||
|
||||
bool bWasDynamicSectionStartedBefore = m_bDynamicSectionStarted;
|
||||
size_t nStructBaseOffset = m_sOffsets.deserialized;
|
||||
|
||||
size_t nMaxSerializedOffset = nSerializedOffset;
|
||||
DDLElementVec& vecElements = pStruct->getElements();
|
||||
for (DDLElementVec::iterator it = vecElements.begin(); it != vecElements.end(); ++it)
|
||||
{
|
||||
size_t nElementOffset = nSerializedOffset;
|
||||
RETURN_IF_FAILED(addElement(*it, strStructPrefix,
|
||||
nElementOffset,
|
||||
nStructBaseOffset));
|
||||
nMaxSerializedOffset = std::max(nMaxSerializedOffset, nElementOffset);
|
||||
}
|
||||
nSerializedOffset = nMaxSerializedOffset;
|
||||
|
||||
if (resize_to_alignment)
|
||||
{
|
||||
MoveOffsetToAlignment(pStruct->getAlignment(), nStructBaseOffset);
|
||||
}
|
||||
|
||||
if (m_bDynamicSectionStarted && !bWasDynamicSectionStartedBefore)
|
||||
{
|
||||
// add an alignment marker to ensure that the next element starts at the
|
||||
// correct position
|
||||
_dynamic_elements.push_back(pStruct->getAlignment());
|
||||
}
|
||||
|
||||
return a_util::result::SUCCESS;
|
||||
}
|
||||
|
||||
void MoveOffsetToAlignment(DDLAlignment::AlignmentType eAlignment, size_t alignment_base_offset)
|
||||
{
|
||||
size_t nRelativeOffset = m_sOffsets.deserialized - alignment_base_offset;
|
||||
size_t nBitRest = nRelativeOffset % 8;
|
||||
if (nBitRest)
|
||||
{
|
||||
nRelativeOffset += 8 - nBitRest;
|
||||
}
|
||||
|
||||
size_t nByteOffset = nRelativeOffset / 8;
|
||||
size_t nRest = nByteOffset % eAlignment;
|
||||
if (nRest)
|
||||
{
|
||||
nRelativeOffset += (eAlignment - nRest) * 8;
|
||||
}
|
||||
m_sOffsets.deserialized = alignment_base_offset + nRelativeOffset;
|
||||
}
|
||||
|
||||
a_util::result::Result addElement(DDLElement* pElement, const std::string& strStructPrefix, size_t& nSerializedOffset, size_t nStructBaseOffset)
|
||||
{
|
||||
if (!m_bDynamicSectionStarted)
|
||||
{
|
||||
m_bDynamicSectionStarted = pElement->getArraysize() == 0;
|
||||
}
|
||||
|
||||
if (!m_bDynamicSectionStarted)
|
||||
{
|
||||
MoveOffsetToAlignment(pElement->getAlignment(), nStructBaseOffset);
|
||||
nSerializedOffset += pElement->getBytepos() * 8 + pElement->getBitpos();
|
||||
}
|
||||
|
||||
size_t nArraySize = std::max(pElement->getArraysize(), 1u);
|
||||
for (size_t nArrayIndex = 0; nArrayIndex < nArraySize; ++nArrayIndex)
|
||||
{
|
||||
std::string strCurrentElementName = strStructPrefix + pElement->getName();
|
||||
if (nArraySize > 1)
|
||||
{
|
||||
strCurrentElementName += a_util::strings::format("[%d]", nArrayIndex);
|
||||
}
|
||||
|
||||
if (!m_bDynamicSectionStarted)
|
||||
{
|
||||
RETURN_IF_FAILED(Add(pElement->getTypeObject(), strCurrentElementName,
|
||||
nSerializedOffset, pElement->getByteorder(),
|
||||
pElement->getNumBits(),
|
||||
pElement->getConstantValue(),
|
||||
nArrayIndex == nArraySize - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_IF_FAILED(addDynamicElement(pElement, strCurrentElementName, strStructPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
return a_util::result::SUCCESS;
|
||||
}
|
||||
|
||||
a_util::result::Result addDynamicElement(const DDLElement* pElement, const std::string& strFullName,
|
||||
const std::string& strStructPrefix)
|
||||
{
|
||||
DynamicStructLayoutElement sDynamicElement;
|
||||
|
||||
cConverter oChildConverter(sDynamicElement.static_elements,
|
||||
sDynamicElement.dynamic_elements,
|
||||
_enums);
|
||||
size_t nDummy = 0;
|
||||
RETURN_IF_FAILED(oChildConverter.Add(pElement->getTypeObject(), "",
|
||||
nDummy, pElement->getByteorder(),
|
||||
pElement->getNumBits(),
|
||||
pElement->getConstantValue(),
|
||||
false));
|
||||
|
||||
sDynamicElement.name = strFullName;
|
||||
sDynamicElement.alignment = pElement->getAlignment();
|
||||
|
||||
if (pElement->getArraysize() == 0)
|
||||
{
|
||||
if (pElement->getArraySizeSource().empty())
|
||||
{
|
||||
return ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
sDynamicElement.size_element_name = strStructPrefix + pElement->getArraySizeSource();
|
||||
}
|
||||
|
||||
_dynamic_elements.push_back(sDynamicElement);
|
||||
|
||||
return a_util::result::SUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
Offsets m_sOffsets;
|
||||
bool m_bDynamicSectionStarted;
|
||||
std::vector<StructLayoutElement>& _static_elements;
|
||||
std::vector<DynamicStructLayoutElement>& _dynamic_elements;
|
||||
std::map<std::string, EnumType>& _enums;
|
||||
};
|
||||
|
||||
a_util::result::Result StructLayout::calculate(const DDLComplex* pStruct)
|
||||
{
|
||||
cConverter oConverter(_static_elements,
|
||||
_dynamic_elements,
|
||||
_enums);
|
||||
RETURN_IF_FAILED(oConverter.Convert(const_cast<DDLComplex*>(pStruct)));
|
||||
_static_buffer_sizes = oConverter.getStaticBufferBitSizes();
|
||||
|
||||
return a_util::result::SUCCESS;
|
||||
}
|
||||
|
||||
size_t StructLayout::getStaticBufferSize(DataRepresentation eRep) const
|
||||
{
|
||||
size_t nResult = eRep == deserialized ?
|
||||
_static_buffer_sizes.deserialized :
|
||||
_static_buffer_sizes.serialized;
|
||||
if (nResult % 8)
|
||||
{
|
||||
return nResult / 8 + 1;
|
||||
}
|
||||
return nResult / 8;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue