initial commit for github

This commit is contained in:
Pierre 2019-12-12 14:41:47 +01:00
commit 60968612de
370 changed files with 68427 additions and 0 deletions

573
codec/access_element.h Normal file
View file

@ -0,0 +1,573 @@
/**
* @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
*/
#ifndef DDL_STRUCT_ELEMENT_ACCESS_CLASS_HEADER
#define DDL_STRUCT_ELEMENT_ACCESS_CLASS_HEADER
#include <a_util/result.h>
#include "struct_element.h"
#include "codec_factory.h"
namespace ddl
{
namespace access_element
{
//define all needed error types and values locally
_MAKE_RESULT(-3, ERR_UNEXPECTED)
_MAKE_RESULT(-20, ERR_NOT_FOUND)
namespace detail
{
/// For internal use only. @internal
template <typename T>
static inline size_t getElementCount(const T& type)
{
return type.getElementCount();
}
/// For internal use only. @internal
template <typename T>
static inline a_util::result::Result getElement(const T& type, size_t element_index, const StructElement*& element)
{
return type.getElement(element_index, element);
}
/// For internal use only. @internal
template <>
inline size_t getElementCount(const CodecFactory& type)
{
return type.getStaticElementCount();
}
/// For internal use only. @internal
template <>
inline a_util::result::Result getElement(const CodecFactory& type, size_t element_index, const StructElement*& element)
{
return type.getStaticElement(element_index, element);
}
/// For internal use only. @internal
template <typename T>
a_util::result::Result find_complex_index(const T& decoder, const std::string& struct_name,
size_t& index, const char* post_fix)
{
if (struct_name.empty())
{
index = 0;
return a_util::result::SUCCESS;
}
size_t element_count = getElementCount(decoder);
std::string prefix = struct_name + post_fix;
for (size_t element_index = 0; element_index < element_count; ++element_index)
{
const StructElement* element;
if (isOk(getElement(decoder, element_index, element)))
{
if (a_util::strings::compare(element->name.c_str(), prefix.c_str(), 0, prefix.size()) == 0)
{
index = element_index;
return a_util::result::SUCCESS;
}
}
}
return ERR_NOT_FOUND;
}
}
/**
* find the index of an element by name.
* @param[in] decoder The decoder or factory.
* @param[in] element_name The name of the element.
* @param[out] index The index of the found element.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result find_index(const T& decoder, const std::string& element_name, size_t& index)
{
size_t element_count = detail::getElementCount(decoder);
for (size_t element_index = 0; element_index < element_count; ++element_index)
{
const StructElement* element;
if (isOk(detail::getElement(decoder, element_index, element)))
{
if (element->name == element_name)
{
index = element_index;
return a_util::result::SUCCESS;
}
}
}
return ERR_NOT_FOUND;
}
/**
* find the index of the first element of a sub-structure by name.
* @param[in] decoder The decoder or factory.
* @param[in] struct_name The name of the sub-structure.
* @param[out] index The index of the found element.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result find_struct_index(const T& decoder, const std::string& struct_name, size_t& index)
{
return detail::find_complex_index<T>(decoder, struct_name, index, ".");
}
/**
* find the index of the first element of an array by name.
* @param[in] decoder The decoder or factory.
* @param[in] array_name The name of the array.
* @param[out] index The index of the found element.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result find_array_index(const T& decoder, const std::string& array_name, size_t& index)
{
return detail::find_complex_index<T>(decoder, array_name, index, "[");
}
/**
* find the index of the first element after an array by name.
* @param[in] decoder The decoder or factory.
* @param[in] array_name The name of the array.
* @param[out] index The index of the found element.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result find_array_end_index(const T& decoder, const std::string& array_name, size_t& index)
{
size_t element_count = detail::getElementCount(decoder);
std::string prefix = array_name + "[";
for (index += 1; index < element_count; ++index)
{
const StructElement* element;
if (isFailed(detail::getElement(decoder, index, element)))
{
return a_util::result::SUCCESS;
}
if (a_util::strings::compare(element->name.c_str(), prefix.c_str(), 0, prefix.size()) != 0)
{
return a_util::result::SUCCESS;
}
}
return a_util::result::SUCCESS;
}
/**
* Get the value of an element by name.
* @param[in] decoder The decoder.
* @param[in] element_name The name of the element.
* @param[out] value The location where the value should be copied to.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result get_value(const T& decoder, const std::string& element_name, void* value)
{
size_t element_index;
a_util::result::Result res = find_index(decoder, element_name, element_index);
if (a_util::result::isFailed(res)) return res;
return decoder.getElementValue(element_index, value);
}
/**
* Set the value of an element by name.
* @param[in] codec The codec.
* @param[in] element_name The name of the element.
* @param[in] value The location where the value should be copied from.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result set_value(T& codec, const std::string& element_name, const void* value)
{
size_t element_index;
a_util::result::Result res = find_index(codec, element_name, element_index);
if (a_util::result::isFailed(res)) return res;
return codec.setElementValue(element_index, value);
}
/**
* Get the value of an element by name.
* @param[in] decoder The decoder.
* @param[in] element_name The name of the element.
* @retval The value of the element.
*/
template <typename T>
a_util::variant::Variant get_value(const T& decoder, const std::string& element_name)
{
a_util::variant::Variant result;
size_t element_index;
if (isOk(find_index(decoder, element_name, element_index)))
{
decoder.getElementValue(element_index, result);
}
return result;
}
/**
* Set the value of an element by name.
* @param[in] codec The codec.
* @param[in] element_name The name of the element.
* @param[in] value The new value.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result set_value(T& codec, const std::string& element_name, const a_util::variant::Variant& value)
{
size_t element_index;
a_util::result::Result res = find_index(codec, element_name, element_index);
if (a_util::result::isFailed(res)) return res;
return codec.setElementValue(element_index, value);
}
/**
* Get the value of an element by index.
* @param[in] decoder The decoder.
* @param[in] element_index The index of the element.
* @retval The value of the element.
*/
template <typename T>
a_util::variant::Variant get_value(const T& decoder, size_t element_index)
{
a_util::variant::Variant result;
if (isOk(decoder.getElementValue(element_index, result)))
{
return result;
}
return a_util::variant::Variant(static_cast<int32_t>(0));
}
/**
* Get a pointer to an element by name.
* @param[in] decoder The decoder.
* @param[in] element_name The name of the element.
* @return Address of the element.
*/
template <typename T>
const void* get_value_address(const T& decoder, const std::string& element_name)
{
size_t element_index;
if (isOk(find_index(decoder, element_name, element_index)))
{
return decoder.getElementAddress(element_index);
}
return NULL;
}
/**
* Get a pointer to an element by name.
* @param[in] codec The codec.
* @param[in] element_name The name of the element.
* @return Address of the element.
*/
template <typename T>
void* get_value_address(T& codec, const std::string& element_name)
{
size_t element_index;
if (isOk(find_index(codec, element_name, element_index)))
{
return codec.getElementAddress(element_index);
}
return NULL;
}
/**
* Get a pointer to a sub-structure by name.
* @param[in] decoder The codec.
* @param[in] struct_name The name of the structure.
* @return Address of the sub-structure.
*/
template <typename STRUCT, typename T>
const STRUCT* get_struct_address(const T& decoder, const std::string& struct_name)
{
size_t element_index;
if (isOk(find_struct_index(decoder, struct_name, element_index)))
{
return reinterpret_cast<const STRUCT*>(decoder.getElementAddress(element_index));
}
return NULL;
}
/**
* Get a pointer to a sub-structure by name.
* @param[in] codec The codec.
* @param[in] struct_name The name of the structure.
* @return Address of the sub-structure.
*/
template <typename STRUCT, typename T>
STRUCT* get_struct_address(T& codec, const std::string& struct_name)
{
size_t element_index;
if (isOk(find_struct_index(codec, struct_name, element_index)))
{
return reinterpret_cast<STRUCT*>(codec.getElementAddress(element_index));
}
return NULL;
}
/**
* Copy a sub-structure out of the structure.
* @param[in] decoder The decoder.
* @param[in] struct_name The name of the structure.
* @param[out] struct_value The location the sub-structure will be copied to.
* @retval ERR_NOT_FOUND No structure with the requested name was found.
*/
template <typename T, typename CODEC>
a_util::result::Result get_struct_value(const CODEC& decoder, const std::string& struct_name, T* struct_value)
{
const T* address = get_struct_address<T>(decoder, struct_name);
if (!address)
{
return ERR_NOT_FOUND;
}
a_util::memory::copy(struct_value, sizeof(T), address, sizeof(T));
return a_util::result::SUCCESS;
}
/**
* Copy a sub-structure into the structure.
* @param[in] codec The codec.
* @param[in] struct_name The name of the structure.
* @param[in] struct_value The location the sub-structure will be copied from.
* @retval ERR_NOT_FOUND No structure with the requested name was found.
*/
template <typename T, typename CODEC>
a_util::result::Result set_struct_value(CODEC& codec, const std::string& struct_name, const T* struct_value)
{
T* address = get_struct_address<T>(codec, struct_name);
if (!address)
{
return ERR_NOT_FOUND;
}
a_util::memory::copy(address, sizeof(T), struct_value, sizeof(T));
return a_util::result::SUCCESS;
}
/**
* Get a pointer to an array by name.
* @param[in] decoder The decoder.
* @param[in] array_name The name of the array.
* @return Address of the array.
*/
template <typename ARRAY_TYPE, typename T>
const ARRAY_TYPE* get_array_address(const T& decoder, const std::string& array_name)
{
size_t element_index;
if (isOk(find_array_index(decoder, array_name, element_index)))
{
return reinterpret_cast<const ARRAY_TYPE*>(decoder.getElementAddress(element_index));
}
return NULL;
}
/**
* Get a pointer to an array by name.
* @param[in] codec The codec.
* @param[in] array_name The name of the array.
* @return Address of the array.
*/
template <typename ARRAY_TYPE, typename T>
ARRAY_TYPE* get_array_address(T& codec, const std::string& array_name)
{
size_t element_index;
if (isOk(find_array_index(codec, array_name, element_index)))
{
return reinterpret_cast<ARRAY_TYPE*>(codec.getElementAddress(element_index));
}
return NULL;
}
/**
* Get information about an array.
* @param[in] decoder The decoder.
* @param[in] array_name The name of the array.
* @param[out] start_address The address of the first element of the array.
* @param[out] size The amount of elements of the array.
* @retval ERR_NOT_FOUND No array with the requested name was found.
*/
template <typename CODEC>
a_util::result::Result get_array(const CODEC& decoder, const std::string& array_name,
const void*& start_address, size_t& size)
{
size_t start_index = 0;
a_util::result::Result res = find_array_index(decoder, array_name, start_index);
if (a_util::result::isFailed(res)) return res;
size_t end_index = start_index;
res = find_array_end_index(decoder, array_name, end_index);
if (a_util::result::isFailed(res)) return res;
start_address = decoder.getElementAddress(start_index);
if (!start_address)
{
return ERR_UNEXPECTED;
}
const void* end_adress = decoder.getElementAddress(end_index);
if (end_adress)
{
size = static_cast<const uint8_t*>(end_adress) -
static_cast<const uint8_t*>(start_address);
}
else
{
// it reaches til the end
size_t start_offset = static_cast<const uint8_t*>(start_address) -
static_cast<const uint8_t*>(decoder.getElementAddress(0));
size = decoder.getBufferSize(decoder.getRepresentation()) - start_offset;
}
return a_util::result::SUCCESS;
}
/**
* Copy an array out of the structure.
* @param[in] decoder The decoder.
* @param[in] array_name The name of the array.
* @param[out] array_value The location the array will be copied to.
* @retval ERR_NOT_FOUND No array with the requested name was found.
*/
template <typename T, typename CODEC>
a_util::result::Result get_array_value(const CODEC& decoder, const std::string& array_name, T* array_value)
{
const void* start_address;
size_t size;
a_util::result::Result res = get_array(decoder, array_name, start_address, size);
if (a_util::result::isFailed(res)) return res;
a_util::memory::copy(array_value, size, start_address, size);
return a_util::result::SUCCESS;
}
/**
* Set the value of the requested element to zero.
* @param[in] codec The codec.
* @param[in] element_name The name of the element.
* @retval ERR_NOT_FOUND No element with the requested name was found.
*/
template <typename T>
a_util::result::Result reset(T& codec, const std::string& element_name)
{
size_t element_index;
a_util::result::Result res = find_index(codec, element_name, element_index);
if (a_util::result::isFailed(res)) return res;
uint64_t zero = 0;
return codec.setElementValue(element_index, &zero);
}
///For internal use only. @internal
#define GET_ENUM_CASE(__variant_type, __data_type) \
case a_util::variant::VT_##__variant_type:\
{\
__data_type xValue = value.get##__variant_type();\
for (EnumType::const_iterator it = element->p_enum->begin(); it != element->p_enum->end(); ++it)\
{\
if (xValue == it->second.as##__variant_type())\
{\
return it->first;\
}\
}\
break;\
}
/**
* Get the value of an element as a string, using enum value names if available.
* @param[in] decoder The decoder.
* @param[in] element The index of the element.
* @return A string representation of the value.
*/
template <typename T>
std::string get_value_as_string(const T& decoder, size_t element_index)
{
a_util::variant::Variant value;
const StructElement* element;
if (isOk(decoder.getElement(element_index, element)))
{
if (isOk(decoder.getElementValue(element_index, value)))
{
if (element->p_enum)
{
switch (value.getType())
{
GET_ENUM_CASE(Bool, bool)
GET_ENUM_CASE(Int8, int8_t)
GET_ENUM_CASE(UInt8, uint8_t)
GET_ENUM_CASE(Int16, int16_t)
GET_ENUM_CASE(UInt16, uint16_t)
GET_ENUM_CASE(Int32, int32_t)
GET_ENUM_CASE(UInt32, uint32_t)
GET_ENUM_CASE(Int64, int64_t)
GET_ENUM_CASE(UInt64, uint64_t)
GET_ENUM_CASE(Float, float)
GET_ENUM_CASE(Double, double)
default: break;
}
}
}
}
return value.asString();
}
/**
* Get the value of an element as a string, using enum value names if available.
* @param[in] decoder The decoder.
* @param[in] element_name The name of the element.
* @return A string representation of the value.
*/
template <typename T>
std::string get_value_as_string(const T& decoder, const std::string& element_name)
{
size_t element_index;
if (isOk(find_index(decoder, element_name, element_index)))
{
return get_value_as_string(decoder, element_index);
}
return "";
}
}
}
#endif

97
codec/bitserializer.cpp Normal file
View file

@ -0,0 +1,97 @@
/**
* @file
* Raw memory related functionality
*
* @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/memory.h"
#include "bitserializer.h"
using namespace a_util;
using namespace a_util::memory;
a_util::memory::Endianess a_util::memory::get_platform_endianess()
{
uint32_t value = 0x01020304;
if (((unsigned char*)&value)[0] == 0x04 &&
((unsigned char*)&value)[2] == 0x02)
{
return bit_little_endian;
}
else if (((unsigned char*)&value)[0] == 0x01 &&
((unsigned char*)&value)[2] == 0x03)
{
return bit_big_endian;
}
else
{
throw std::runtime_error("unsupported endianess");
}
}
std::string a_util::memory::detail::formatBits(uint64_t value)
{
std::string bit_string;
for (int i = 0; i < (int)sizeof(uint64_t) * 8; i++)
{
if (i % 8 == 0)
{
bit_string += " | ";
}
bit_string += a_util::strings::toString((value >> (63 - i)) & 1);
}
return bit_string;
}
a_util::result::Result a_util::memory::detail::convertSignalEndianess(uint64_t *signal, Endianess endianess, size_t bit_length)
{
if (bit_length > 8) // Signal is bigger than one byte
{
if (endianess != get_platform_endianess()) // Byteorder was different on writing platform
{
if (bit_length > (4 * 8)) // 64 Bit
{
// If the BE signal is shorter than 8 byte, make sure the value is aligned
// at the LSB end, seen from a BE viewpoint.
if (endianess == bit_big_endian)
{
*signal <<= (((8 * 8) - (bit_length)) / 8) * 8;
}
*reinterpret_cast<uint64_t*>(signal) = a_util::memory::swapEndianess(*reinterpret_cast<uint64_t*>(signal));
}
else if (bit_length > (2 * 8)) // 32 Bit
{
// If the BE signal is shorter than 4 byte, make sure the value is aligned
// at the LSB end, seen from a BE viewpoint.
if (endianess == bit_big_endian)
{
*signal <<= (((4 * 8) - (bit_length)) / 8) * 8;
}
*reinterpret_cast<uint32_t*>(signal) = a_util::memory::swapEndianess(*reinterpret_cast<uint32_t*>(signal));
}
else // 16 Bit
{
*reinterpret_cast<uint16_t*>(signal) = a_util::memory::swapEndianess(*reinterpret_cast<uint16_t*>(signal));
}
}
}
return a_util::result::SUCCESS;
}

750
codec/bitserializer.h Normal file
View file

@ -0,0 +1,750 @@
/**
* @file
* Raw memory related functionality
*
* @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
*/
#ifndef A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED
#define A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED
#include <algorithm>
#include "a_util/memory.h"
#include "a_util/result.h"
namespace a_util
{
namespace memory
{
//define all needed error types and values locally
_MAKE_RESULT(-4, ERR_POINTER);
_MAKE_RESULT(-5, ERR_INVALID_ARG);
/// Enum describing the endianess
typedef enum
{
bit_little_endian = 1,
bit_big_endian = 2,
} Endianess;
/**
* Returns the endianess of the platform
* @return See \ref Endianess
*/
Endianess get_platform_endianess();
namespace detail
{
/**
* Format the bit pattern of a uint64_t value to a string
* Used for debug purposes.
*
* @param [in] value The value to print.
* @retval The bitstring
*/
std::string formatBits(uint64_t value);
/**
* Convert the endianess of a signal by correctly swapping the byte order if required.
* The variable signal is a uint64_t, but the value that needs conversion might be smaller.
* The parameter bit_length determines if a 16, 32 or 64 value should be swapped.
* For a LE system, reading BE signals of 3, 5, 6 or 7 bytes length the value will be aligned
* within a 4 or 8 byte value before swapping bytes.
*
* @param [in,out] signal Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to convert.
* @param [in] bit_length Number of bits to read.
*
* @return Returns a standard result code.
*/
a_util::result::Result convertSignalEndianess(uint64_t *signal, Endianess endianess, size_t bit_length);
/**
* Converter Base
* Contains the base methods used by all inheriting Converter classes.
*/
template<typename T>
class ConverterBase {
protected:
/**
* Read value from bitfield.
* Operating on a uint64_t copy to allow bit shifting and masking operations.
*
* @param [in] buffer Pointer to the memory buffer to read from.
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] value Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to read from.
*
* @return Returns a standard result code.
*/
static a_util::result::Result readSignal(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value,
Endianess endianess = get_platform_endianess())
{
/*
* offset_end offset_start
* _ ____
* | | | |
* ....|...abcde|fghijklm|no......|.... Buffer (index 0 on the right end side)
* |_______________|
* bit_length ^
* |
* start_bit
*/
// 1) COPY relevant bytes of Buffer content to result variable.
uint64_t result = 0; // Result value
uint64_t ninth_byte = 0; // variable to eventually store a ninth byte from buffer
size_t bytes_to_read = 0;
copyBytesFromBuffer(buffer, &result, start_bit, bit_length, &ninth_byte, &bytes_to_read);
// 2) TRIM unrelevant bits and SHIFT to align value.
// Number of bits the start position is offset from 0 (0 for aligned signal)
size_t offset_start = start_bit % 8;
// Number of bits the end position is offset from the end of the last byte (0 for complete bytes)
size_t offset_end = (8 - ((start_bit + bit_length) % 8)) % 8;
/**********************************************************************************************
* Distinguish between LE and BE operating systems to get the shift operations right *
**********************************************************************************************/
// On LE System
if (get_platform_endianess() == bit_little_endian)
{
/* Use bit mask to remove bits on the higher end, which do not belong to the value to read.
*
* ...|...abcde|fghijklm|no......| => 000|000abcde|fghijklm|no......|
*
*/
cutLeadingBits(&result, bit_length + offset_start);
/* Shift right to align start at position 0 (also trims the right end).
*
* 000|000abcde|fghijklm|no......| => 000|00000000|0abcdefg|hijklmno|
*
*/
result >>= offset_start;
// Eventually get bits from the copied 9th byte.
if (ninth_byte > 0) // nothing to take care of if nothing was copied or all copied bits are 0.
{
// deleteAll unwanted bits from ninth byte.
cutLeadingBits(&ninth_byte, (8 - offset_end));
size_t bit_size = sizeof(result) * 8;
// Shift requested bits from the 9th byte into the right position to be combined with result.
ninth_byte <<= (bit_size - offset_start);
// merge value together from all nine bytes.
result = result | ninth_byte;
}
// BE Signal needs byte order swapping.
if (endianess == bit_big_endian)
{
// Only for reading partial bytes. Filling the missing bits differs from LE Signal.
if (bit_length % 8 != 0)
{
/* Shift left to align end position.
*
* 000|0abcdefg|hijklmno| => 000|abcdefgh|ijklmno0|
*
*/
result <<= (offset_end + offset_start) % 8;
/* Shift bits within MSByte, filling the gap with 0s.
*
* 000|abcdefgh|ijklmno0| => 000|abcdefgh|0ijklmno|
* ^ ^
* MSByte MSByte
*/
uint8_t *ms_byte = (uint8_t*)&result;
ms_byte[0] >>= (offset_end + offset_start) % 8;
}
/* swap bytes to LE.
*
* 000|abcdefgh|0ijklmno| => 000|0ijklmno|abcdefgh|
*
*/
detail::convertSignalEndianess(&result, endianess, bit_length);
}
}
// On BE System
else
{
/* swap bytes to simulate LE shifting operations.
*
* |...abcde|fghijklm|no......|... => ...|no......|fghijklm|...abcde|
*
*/
detail::convertSignalEndianess(&result, bit_little_endian, sizeof(result) * 8);
// LE Signal
if (endianess == bit_little_endian)
{
/* Use bit mask to remove bits on the higher end, which do not belong to the value to read.
*
* ...|no......|fghijklm|...abcde| => ...|no......|fghijklm|000abcde|
*
*/
cutLeadingBits(&result, (sizeof(result) * 8) - offset_end); // Cut away only offset_end bits.
/* Shift right to align bits within LSByte (BE Shifting!).
*
* ...|no......|fghijklm|000abcde| => ...|hijklmno|0abcdefg|00000000|
*
*/
result >>= offset_start;
/* Shift right to align LSByte on the left side (BE Shifting!).
*
* ...|hijklmno|0abcdefg|00000000| => |hijklmno|0abcdefg|000
*
* Shift over all
* empty bytes = (all bits - occupied bits (bit_length) - already shifted bits) / number of bytes
*/
result >>= (((sizeof(result) * 8) - bit_length - offset_start) / sizeof(result)) * 8;
// No further byte swap, because there has been one swap before the shift operations already.
}
// BE Signal
else
{
/* Shift left to align bits within LSByte (now rightmost byte because of byte swap).
* Also deletes bits from end offset.
*
* ...|no......|fghijklm|...abcde| => ...|........|ijklmno.|abcdefgh|
*
*/
result <<= offset_end;
// Only for reading partial bytes. Filling the missing bits differs from LE Signal.
if (bit_length % 8 != 0)
{
/* Shift bits within MSByte to move 0s to the highest bits (also deleting all unwanted bits from start offset).
*
* ...|........|ijklmno.|abcdefgh| => ...|........|0ijklmno|abcdefgh|
*
*/
uint8_t *ms_byte = (uint8_t*)&result + (bit_length / 8); // position of the value's MSByte
ms_byte[0] >>= (offset_end + offset_start) % 8; // amount of unused bits within MSByte
}
/* swap bytes back to BE
*
* ...|........|0ijklmno|abcdefgh| => |abcdefgh|0ijklmno|...
*
*/
detail::convertSignalEndianess(&result, bit_little_endian, sizeof(result) * 8); // Change the simulated LE value back
/* Use bit mask to remove bits on the higher end, which do not belong to the value to read.
*
* |abcdefgh|0ijklmno|... => |abcdefgh|0ijklmno|000
*
* Remove everything behind the value length plus the gap within MSByte.
*/
cutLeadingBits(&result, bit_length + (offset_end + offset_start) % 8);
}
}
// Copy the resulting value to the target variable. No Casting! Data might be lost otherwise.
size_t sz = std::min(sizeof(*value), sizeof(result));
a_util::memory::copy(value, sz, &result, sz);
return a_util::result::SUCCESS;
}
/**
* Write value to bitfield.
* Operating on a uint64_t copy to allow bit shifting and masking operations.
*
* @param [in] buffer Pointer to the memory buffer to write to.
* @param [in] start_bit Bit position to start writing to. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to write.
* @param [out] value Value to write to the bitfield.
* @param [in] endianess Parameter describing the endianess of the bitfield to write to.
*
* @return Returns a standard result code.
*/
static a_util::result::Result writeSignal(uint8_t *buffer, size_t start_bit, size_t bit_length, T value,
Endianess endianess = get_platform_endianess())
{
// 1) Copy relevant bytes of Buffer content to be overwritten.
uint64_t buffer_copy = 0;
uint64_t ninth_byte = 0; // storage variable for the ninth bit from buffer
size_t bytes_to_read = 0;
copyBytesFromBuffer(buffer, &buffer_copy, start_bit, bit_length, &ninth_byte, &bytes_to_read);
// 2) Erase Bits from Buffer copy that will be overwritten TODO: BE LE system difference important here?
// Number of bits the start position is offset from 0
size_t offset_start = start_bit % 8;
// Number of bits the end position is offset from the end of the last byte
size_t offset_end = (8 - ((start_bit + bit_length) % 8)) % 8;
uint64_t mask_left = ~0ULL;
if ((bit_length + offset_start) >= (sizeof(mask_left) * 8))
{
mask_left = 0;
}
else
{
mask_left = ~0ULL;
mask_left <<= (bit_length + offset_start);
}
uint64_t mask = ~0ULL;
mask <<= offset_start;
mask = ~mask;
mask |= mask_left;
buffer_copy &= mask;
// 3) Copy value to UInt64 variable to work with.
uint64_t signal;
a_util::memory::copy(&signal, sizeof(signal), &value, sizeof(signal));
// 4) Keep only nLength bits: Remove bits that should not be written to the Buffer.
cutLeadingBits(&signal, bit_length);
// 5) Shift to align at start bit position.
int shift_amount = (int)offset_start; // Initialized to fit LE Signal shift
// BE Signal
if (endianess == bit_big_endian)
{
// swap bytes
detail::convertSignalEndianess(&signal, endianess, bit_length);
// Remove gap for partial bytes within MSByte
uint8_t *ms_byte = (uint8_t*)&signal;
int ms_shift = (8 - (bit_length % 8)) % 8;
ms_byte[0] <<= ms_shift;
shift_amount -= ms_shift;
}
// Copy most significant byte to ninth buffer byte before losing bits with the shift.
if ((offset_start + bit_length) > (sizeof(signal) * 8))
{
uint64_t signal_for_ninth_byte = signal;
signal_for_ninth_byte >>= (sizeof(signal) - 1) * 8;
signal_for_ninth_byte >>= (8 - offset_start); // Only LE Signal
uint64_t mask = ~0ULL;
mask <<= (8 - offset_end);
ninth_byte &= mask;
ninth_byte |= signal_for_ninth_byte;
}
if (shift_amount < 0)
{
signal >>= std::abs(shift_amount);
}
else
{
signal <<= shift_amount;
}
// 7) Write bytes with integrated signal back to the buffer.
buffer_copy |= signal;
size_t sz = std::min(bytes_to_read, sizeof(signal));
a_util::memory::copy(buffer + (start_bit / 8), sz, &buffer_copy, sz);
// Eventually copy ninth byte back to buffer
if (bytes_to_read > sizeof(signal))
{
a_util::memory::copy(buffer + (start_bit / 8) + sizeof(signal), 1, &ninth_byte, 1);
}
return a_util::result::SUCCESS;
}
/**
* Set the highest bits of a uint64_t value to zero. The number of bit_length lowest bits
* remain unchanged.
*
* @param [out] value Pointer to the variable to trim.
* @param [in] bit_length Number of trailing bits to remain unchanged.
*
* @return Returns a standard result code.
*/
static a_util::result::Result cutLeadingBits(uint64_t *value, size_t bit_length)
{
size_t bit_size = (sizeof(*value) * 8);
if (bit_length < bit_size)
{
uint64_t mask = ~0ULL;
mask >>= (bit_size - bit_length);
*value &= mask;
}
return a_util::result::SUCCESS;
}
/**
* Copy bytes_to_read number of bytes from the buffer to value and ninth_byte.
* Determines how many bytes need to be copied to receive a copy of all bits in the range described
* by start_bit and bit_length. The maximum for bit_length is 64, but for unaligned values the range
* may exceed 8 bytes. In this case, the required ninth byte will be copied to ninth_byte.
*
* @param [in] buffer Pointer to the memory buffer to copy from.
* @param [out] value Pointer to the variable to store the copied value in.
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] ninth_byte Pointer to the variable to eventually store a copied ninth byte in.
* @param [out] bytes_to_read Number of bytes that need to be copied to attain all requested bits.
*
* @return Returns a standard result code.
*/
static a_util::result::Result copyBytesFromBuffer(uint8_t *buffer, uint64_t *value, size_t start_bit, size_t bit_length, uint64_t *ninth_byte, size_t *bytes_to_read)
{
// Byte within the buffer to start reading at
size_t start_byte = start_bit / 8;
// Number of bits to read: signal length + bits to fill in the offset on both sides for unaligned signals
size_t bits_to_read = bit_length + (start_bit % 8);
if ((bits_to_read % 8) > 0)
{
bits_to_read += (8 - (bits_to_read % 8));
}
// Number of bytes to read from the buffer
*bytes_to_read = bits_to_read / 8;
// Copy up to 8 bytes to result
if (*bytes_to_read > (size_t)sizeof(*value))
{
a_util::memory::copy(value, sizeof(*value), buffer + start_byte, sizeof(*value));
}
else
{
a_util::memory::copy(value, *bytes_to_read, buffer + start_byte, *bytes_to_read);
}
// The max signal size is 8 byte, but if the signal is not aligned, it might spread over 9 bytes.
if (*bytes_to_read > sizeof(*value))
{
// Get a copy of the most significant byte, which could not yet be saved to result
a_util::memory::copy(ninth_byte, 1, buffer + start_byte + sizeof(*value), 1);
}
return a_util::result::SUCCESS;
}
};
/// Template converter class to differentiate between float, signed and unsigned integer values.
template<typename T, int is_signed, int is_floating_point> class Converter;
/// Partially specialized class for Unsigned Integers
template<typename T>
class Converter<T, 0, 0> : public ConverterBase<T>
{
public:
/**
* Read unsigned integer from bitfield.
*
* @param [in] buffer Pointer to the memory buffer to read from.
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] value Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to read from.
*
* @return Returns a standard result code.
*/
static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value,
Endianess endianess)
{
return ConverterBase<T>::readSignal(buffer, start_bit, bit_length, value, endianess);
}
/**
* Write unsigned integer to bitfield.
*
* @param [in] buffer Pointer to the memory buffer to write to.
* @param [in] start_bit Bit position to start writing to. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to write.
* @param [out] value Value to write to the bitfield.
* @param [in] endianess Parameter describing the endianess of the bitfield to write to.
*
* @return Returns a standard result code.
*/
static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value,
Endianess endianess)
{
return ConverterBase<T>::writeSignal(buffer, start_bit, bit_length, value, endianess);
}
};
/// Partially specialized class for Signed Integers
template<typename T>
class Converter<T, 1, 0> : public ConverterBase<T>
{
public:
/**
* Read signed integer from bitfield.
*
* @param [in] buffer Pointer to the memory buffer to read from.
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] value Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to read from.
*
* @return Returns a standard result code.
*/
static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value,
Endianess endianess)
{
a_util::result::Result res = ConverterBase<T>::readSignal(buffer, start_bit, bit_length, value, endianess);
if (res != a_util::result::SUCCESS)
{
return res;
}
// replicate sign bit
*value <<= (sizeof(T) * 8) - bit_length;
*value >>= (sizeof(T) * 8) - bit_length;
return a_util::result::SUCCESS;
}
/**
* Write signed integer to bitfield.
*
* @param [in] buffer Pointer to the memory buffer to write to.
* @param [in] start_bit Bit position to start writing to. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to write.
* @param [out] value Value to write to the bitfield.
* @param [in] endianess Parameter describing the endianess of the bitfield to write to.
*
* @return Returns a standard result code.
*/
static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value,
Endianess endianess)
{
// Nothing special to take care of for writing signed integers, compared to writing unsigned integers.
return ConverterBase<T>::writeSignal(buffer, start_bit, bit_length, value, endianess);
}
};
/// Specialized class for Floats (Floats are always signed!)
template<typename T>
class Converter<T, 1, 1> : public ConverterBase<T>
{
public:
/**
* Read tFloat from bitfield.
*
* @param [in] buffer Pointer to the memory buffer to read from.
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] value Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to read from.
*
* @return Returns a standard result code.
*/
static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value,
Endianess endianess)
{
// Read only values of size tFloat
if (sizeof(T) * 8 == bit_length)
{
return ConverterBase<T>::readSignal(buffer, start_bit, bit_length, value, endianess);
}
else
{
return ERR_INVALID_ARG;
}
}
/**
* Write tFloat to bitfield.
*
* @param [in] buffer Pointer to the memory buffer to write to.
* @param [in] start_bit Bit position to start writing to. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to write.
* @param [out] value Value to write to the bitfield.
* @param [in] endianess Parameter describing the endianess of the bitfield to write to.
*
* @return Returns a standard result code.
*/
static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value,
Endianess endianess)
{
// Write only values of size tFloat
if (sizeof(T) * 8 == bit_length)
{
return ConverterBase<T>::writeSignal(buffer, start_bit, bit_length, value, endianess);
}
else
{
return ERR_INVALID_ARG;
}
}
};
} // namespace detail
/// Bit Serializer Class
class BitSerializer
{
public:
/**
* Constructor
*/
BitSerializer(void* data, size_t data_size) :
_buffer(static_cast<uint8_t*>(data)), _buffer_bytes(data_size),
_buffer_bits(_buffer_bytes * 8)
{
}
/**
* Default Constructor
*/
BitSerializer() : _buffer(NULL), _buffer_bytes(0), _buffer_bits(0)
{
}
/**
* Read value from bitfield. Value can be of type tFloat or an unsigned or signed integer.
*
* ....|...*****|********|**......|.... Buffer (index 0 on the right end side)
* |_______________|
* bit_length ^
* |
* start_bit
*
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [out] value Pointer to the variable to store the read value in.
* @param [in] endianess Parameter describing the endianess of the bitfield to read from.
*
* @return Returns a standard result code.
*/
template<typename T>
a_util::result::Result read(size_t start_bit, size_t bit_length, T* value,
Endianess endianess = get_platform_endianess())
{
// Check if in range
a_util::result::Result result_code = checkForInvalidArguments(start_bit, bit_length, sizeof(T));
if (result_code != a_util::result::SUCCESS)
{
return result_code;
}
// Call template function
detail::Converter<T, std::is_signed<T>::value,
std::is_floating_point<T>::value>
::read(_buffer, start_bit, bit_length, value, endianess);
return a_util::result::SUCCESS;
}
/**
* Write value to bitfield. Value can be of type tFloat or an unsigned or signed integer.
*
* ....|...*****|********|**......|.... Buffer (index 0 on the right end side)
* |_______________|
* bit_length ^
* |
* start_bit
*
* @param [in] start_bit Bit position to start writing to. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to write.
* @param [out] value Value to write to the bitfield.
* @param [in] endianess Parameter describing the endianess of the bitfield to write to.
*
* @return Returns a standard result code.
*/
template<typename T>
a_util::result::Result write(size_t start_bit, size_t bit_length, T value,
Endianess endianess = get_platform_endianess())
{
// Check if in range
a_util::result::Result result_code = checkForInvalidArguments(start_bit, bit_length, sizeof(T));
if (result_code != a_util::result::SUCCESS)
{
return result_code;
}
// Call template function
detail::Converter<T, std::is_signed<T>::value,
std::is_floating_point<T>::value>
::write(_buffer, start_bit, bit_length, value, endianess);
return a_util::result::SUCCESS;
}
private:
/// internal buffer
uint8_t *_buffer;
/// size of internal buffer in bytes
size_t _buffer_bytes;
/// size of internal buffer in bits
size_t _buffer_bits;
/**
* Check if the parameters for the reading and writing access are valid.
* The variable to read from or into might be too small and the accessed region of the memory buffer
* might be out of range.
*
* @param [in] start_bit Bit position to start reading from. The least significant bit
* has the index 0.
* @param [in] bit_length Number of bits to read.
* @param [in] size_variable Size of the variable to read into or write from.
*
* @return Returns a standard result code.
*/
a_util::result::Result checkForInvalidArguments(size_t start_bit, size_t bit_length, size_t size_variable)
{
if (!_buffer)
{
return ERR_POINTER;
}
// Check invalid starting point
if (start_bit >= _buffer_bits)
{
return ERR_INVALID_ARG;
}
// Check out of buffer bounds or length < 1
if ((bit_length < 1)
|| (_buffer_bits < start_bit + bit_length))
{
return ERR_INVALID_ARG;
}
// Check variable size
if (size_variable * 8 < bit_length)
{
return ERR_INVALID_ARG;
}
return a_util::result::SUCCESS;
}
};
} // namespace memory
} // namespace a_util
#endif // A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED

323
codec/codec.cpp Normal file
View file

@ -0,0 +1,323 @@
/**
* @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 "codec.h"
#include "a_util/result/error_def.h"
#include "a_util/logging.h"
#include "legacy_error_macros.h"
#include "struct_layout.h"
#include "static_codec.h"
#include "element_accessor.h"
#include "access_element.h"
namespace ddl
{
//define all needed error types and values locally
_MAKE_RESULT(-5, ERR_INVALID_ARG)
_MAKE_RESULT(-10, ERR_INVALID_INDEX)
static inline void BitToBytes(size_t& size)
{
if (size % 8)
{
size = size/ 8 + 1;
}
else
{
size /= 8;
}
}
Decoder::Decoder(const Decoder& oDecoder, const void* pData, size_t nDataSize,
DataRepresentation eRep):
StaticDecoder(oDecoder._layout, pData, nDataSize, eRep),
_dynamic_elements(oDecoder._dynamic_elements),
_buffer_sizes(oDecoder._buffer_sizes)
{
}
Decoder::Decoder(a_util::memory::shared_ptr<const StructLayout> pLayout, const void* pData, size_t nDataSize,
DataRepresentation eRep):
StaticDecoder(pLayout, pData, nDataSize, eRep),
_buffer_sizes(pLayout->getStaticBufferBitSizes())
{
if (_layout->hasDynamicElements())
{
a_util::result::Result oResult = calculateDynamicElements();
if (isFailed(oResult))
{
LOG_ERROR("Failed to calculate dynamic elements");
}
}
BitToBytes(_buffer_sizes.deserialized);
BitToBytes(_buffer_sizes.serialized);
}
a_util::result::Result Decoder::isValid() const
{
RETURN_IF_FAILED(_layout->isValid());
if (_data_size < getBufferSize(getRepresentation()))
{
return ERR_INVALID_ARG;
}
return a_util::result::SUCCESS;
}
a_util::result::Result Decoder::calculateDynamicElements()
{
_dynamic_elements.reset(new std::vector<StructLayoutElement>());
for (std::vector<DynamicStructLayoutElement>::const_iterator
itDynamicElement = _layout->getDynamicElements().begin();
itDynamicElement != _layout->getDynamicElements().end(); ++ itDynamicElement)
{
RETURN_IF_FAILED(addDynamicElements(*itDynamicElement, _buffer_sizes, ""));
}
return a_util::result::SUCCESS;
}
void Decoder::moveToAlignment(size_t& bit_offset, size_t alignment)
{
size_t nBitRest = bit_offset % 8;
if (nBitRest)
{
bit_offset += 8 - nBitRest;
}
size_t nByteOffset = bit_offset / 8;
size_t nRest = nByteOffset % alignment;
if (nRest)
{
bit_offset += (alignment - nRest) * 8;
}
}
a_util::result::Result Decoder::addDynamicElements(const DynamicStructLayoutElement& sDynamicElement,
Offsets& sOverallOffsets,
const std::string& strPrefix)
{
moveToAlignment(sOverallOffsets.deserialized, sDynamicElement.alignment);
if (sDynamicElement.isAlignmentElement())
{
return a_util::result::SUCCESS;
}
a_util::variant::Variant oArraySize((uint64_t)1);
bool bIsArray = sDynamicElement.isDynamicArray();
if (bIsArray)
{
oArraySize = access_element::get_value(*this,
strPrefix + sDynamicElement.size_element_name);
}
size_t nArraySize = static_cast<size_t>(oArraySize.asUInt64());
for (size_t nArrayIndex = 0; nArrayIndex < nArraySize; ++nArrayIndex)
{
RETURN_IF_FAILED(addDynamicElement(sDynamicElement,
bIsArray ? a_util::strings::format("[%d]", nArrayIndex) : "",
sOverallOffsets, strPrefix));
}
moveToAlignment(sOverallOffsets.deserialized, sDynamicElement.alignment);
return a_util::result::SUCCESS;
}
a_util::result::Result Decoder::addDynamicElement(const DynamicStructLayoutElement& sDynamicElement,
const std::string& strArrayIndex,
Offsets& sOverallOffsets,
const std::string& strPrefix)
{
RETURN_IF_FAILED(addStaticStructElements(sDynamicElement, strArrayIndex, sOverallOffsets, strPrefix));
RETURN_IF_FAILED(addDynamicStructElements(sDynamicElement, strArrayIndex, sOverallOffsets, strPrefix));
return a_util::result::SUCCESS;
}
a_util::result::Result Decoder::addStaticStructElements(const DynamicStructLayoutElement& sDynamicElement,
const std::string& strArrayIndex,
Offsets& nOverallBitOffset,
const std::string& strPrefix)
{
Offsets sStartOffsets = nOverallBitOffset;
for (std::vector<StructLayoutElement>::const_iterator itStaticElement = sDynamicElement.static_elements.begin();
itStaticElement != sDynamicElement.static_elements.end(); ++itStaticElement)
{
StructLayoutElement sElement = *itStaticElement;
sElement.deserialized.bit_offset += sStartOffsets.deserialized;
sElement.serialized.bit_offset += sStartOffsets.serialized;
nOverallBitOffset.deserialized = sElement.deserialized.bit_offset + sElement.deserialized.bit_size;
nOverallBitOffset.serialized = sElement.serialized.bit_offset + sElement.serialized.bit_size;
if (!sElement.name.empty())
{
sElement.name = a_util::strings::format("%s%s%s.%s", strPrefix.c_str(),
sDynamicElement.name.c_str(),
strArrayIndex.c_str(),
itStaticElement->name.c_str());
}
else
{
// not part of a struct, just a plain array element
sElement.name = a_util::strings::format("%s%s%s", strPrefix.c_str(),
sDynamicElement.name.c_str(),
strArrayIndex.c_str());
}
RETURN_IF_FAILED(addDynamicStructElement(sElement));
}
return a_util::result::SUCCESS;
}
a_util::result::Result Decoder::addDynamicStructElements(const DynamicStructLayoutElement& sDynamicElement,
const std::string& strArrayIndex,
Offsets& sOverallOffsets,
const std::string& strPrefix)
{
std::string strChildPrefix = a_util::strings::format("%s%s%s.", strPrefix.c_str(),
sDynamicElement.name.c_str(),
strArrayIndex.c_str());
for (std::vector<DynamicStructLayoutElement>::const_iterator
itDynamicChildElement = sDynamicElement.dynamic_elements.begin();
itDynamicChildElement != sDynamicElement.dynamic_elements.end();
++itDynamicChildElement)
{
RETURN_IF_FAILED(addDynamicElements(*itDynamicChildElement, sOverallOffsets, strChildPrefix));
}
return a_util::result::SUCCESS;
}
a_util::result::Result Decoder::addDynamicStructElement(const StructLayoutElement& sElement)
{
const Position& sPos = _element_accessor->getRepresentation() == deserialized ?
sElement.deserialized : sElement.serialized;
if (sPos.bit_offset + sPos.bit_size > _data_size * 8)
{
return ERR_INVALID_ARG;
}
_dynamic_elements->push_back(sElement);
return a_util::result::SUCCESS;
}
size_t Decoder::getElementCount() const
{
if (_dynamic_elements)
{
return _layout->getStaticElements().size() + _dynamic_elements->size();
}
return _layout->getStaticElements().size();
}
size_t Decoder::getBufferSize(DataRepresentation eRep) const
{
return eRep == deserialized ?
_buffer_sizes.deserialized :
_buffer_sizes.serialized;
}
Codec Decoder::makeCodecFor(void* pData, size_t nDataSize, DataRepresentation eRep) const
{
return Codec(*this, pData, nDataSize, eRep);
}
const StructLayoutElement* Decoder::getLayoutElement(size_t nIndex) const
{
const StructLayoutElement* pElement = NULL;
size_t nStaticElementCount = _layout->getStaticElements().size();
if (nIndex < nStaticElementCount)
{
pElement = &_layout->getStaticElements()[nIndex];
}
else if (_dynamic_elements &&
nIndex - nStaticElementCount < _dynamic_elements->size())
{
pElement = &(*_dynamic_elements)[nIndex - nStaticElementCount];
}
return pElement;
}
Codec::Codec(a_util::memory::shared_ptr<const StructLayout> pLayout, void* pData, size_t nDataSize,
DataRepresentation eRep):
Decoder(pLayout, pData, nDataSize, eRep)
{
}
Codec::Codec(const Decoder& oDecoder, void* pData, size_t nDataSize, DataRepresentation eRep):
Decoder(oDecoder, pData, nDataSize, eRep)
{
}
a_util::result::Result Codec::setElementValue(size_t nIndex, const void* pValue)
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->setValue(*pElement,
const_cast<void*>(_data),
_data_size,
pValue);
}
a_util::result::Result Codec::setElementValue(size_t nIndex, const a_util::variant::Variant& oValue)
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->setValue(*pElement, const_cast<void*>(_data),
_data_size, oValue);
}
void* Codec::getElementAddress(size_t nIndex)
{
return const_cast<void*>(StaticDecoder::getElementAddress(nIndex));
}
a_util::result::Result Codec::setConstants()
{
if (_layout->hasEnums())
{
size_t nElementCount = getElementCount();
for (size_t nElement = 0; nElement < nElementCount; ++nElement)
{
const StructLayoutElement* pElement = getLayoutElement(nElement);
if (pElement->constant)
{
RETURN_IF_FAILED(_element_accessor->setValue(*pElement, const_cast<void*>(_data),
_data_size, *pElement->constant));
}
}
}
return a_util::result::SUCCESS;
}
}

161
codec/codec.h Normal file
View file

@ -0,0 +1,161 @@
/**
* @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
*/
#ifndef DDL_CODEC_CLASS_HEADER
#define DDL_CODEC_CLASS_HEADER
#include "a_util/result.h"
#include "static_codec.h"
namespace ddl
{
class Codec;
/**
* Decoder for dynamic structures defined by a DDL definition.
*/
class Decoder: public StaticDecoder
{
public:
/**
* @copydoc StaticDecoder::isValid
*/
virtual a_util::result::Result isValid() const;
/**
* @copydoc StaticDecoder::getElementCount
*/
virtual size_t getElementCount() const;
/**
* @param[in] rep The data representation for which the buffer size should be returned.
* @return The size of the structure in the requested data representation.
*/
size_t getBufferSize(DataRepresentation rep = deserialized) const;
/**
* Create a new codec with the current dynamic structure layout for a new data buffer.
* @param[in] data The pointer to the new raw data.
* @param[in] data_size The size of the new raw data.
* @param[in] rep The representation that the data should be encoded in.
* @return A codec.
*/
Codec makeCodecFor(void* data, size_t data_size, DataRepresentation rep) const;
protected:
friend class CodecFactory;
/// For internal use only. @internal
Decoder(a_util::memory::shared_ptr<const StructLayout> layout, const void* data, size_t data_size,
DataRepresentation rep);
/// For internal use only. @internal
Decoder(const Decoder& decoder, const void* data, size_t data_size,
DataRepresentation rep);
/// For internal use only. @internal
virtual const StructLayoutElement* getLayoutElement(size_t index) const;
private:
/// For internal use only. @internal
a_util::result::Result calculateDynamicElements();
/// For internal use only. @internal
a_util::result::Result addDynamicElements(const DynamicStructLayoutElement& dynamic_element,
Offsets& overall_offsets,
const std::string& prefix);
/// For internal use only. @internal
a_util::result::Result addDynamicElement(const DynamicStructLayoutElement& dynamic_element,
const std::string& array_index,
Offsets& overall_offsets,
const std::string& prefix);
/// For internal use only. @internal
a_util::result::Result addStaticStructElements(const DynamicStructLayoutElement& dynamic_element,
const std::string& array_index,
Offsets& overall_offsets,
const std::string& prefix);
/// For internal use only. @internal
a_util::result::Result addDynamicStructElements(const DynamicStructLayoutElement& dynamic_element,
const std::string& array_index,
Offsets& overall_offsets,
const std::string& prefix);
/// For internal use only. @internal
a_util::result::Result addDynamicStructElement(const StructLayoutElement& element);
/// For internal use only. @internal
void moveToAlignment(size_t& bit_offset, size_t alignment);
protected:
/// For internal use only. @internal
a_util::memory::shared_ptr<std::vector<StructLayoutElement> > _dynamic_elements;
/// For internal use only. @internal
Offsets _buffer_sizes;
};
/**
* Decoder for dynamic structures defined by a DDL definition.
* Currently the amount of dynamic elements is determined during construction
* only (by the current values in the structure).
*/
class Codec: public Decoder
{
public:
/**
* Sets the current value of the given element by copying its data
* from the passed-in location.
* @param[in] index The index of the element.
* @param[in] value The location where the data should be copied from.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result setElementValue(size_t index, const void* value);
/**
* Sets the current value of the given element to the given value.
* @param[in] index The index of the element.
* @param[in] value The value.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result setElementValue(size_t index, const a_util::variant::Variant& value);
/**
* @param[in] index The index of the element.
* @return A pointer to the element or NULL in case of an error.
*/
void* getElementAddress(size_t index);
using StaticDecoder::getElementAddress;
/**
* Sets all elements to their constant values defined in the DDL.
* @return Standard result.
*/
a_util::result::Result setConstants();
protected:
friend class CodecFactory;
friend class Decoder;
/// For internal use only. @internal
Codec(a_util::memory::shared_ptr<const StructLayout> layout, void* data, size_t data_size,
DataRepresentation rep);
/// For internal use only. @internal
Codec(const Decoder& decoder, void* data, size_t data_size,
DataRepresentation rep);
};
}
#endif

29
codec/codec.sources Normal file
View file

@ -0,0 +1,29 @@
set(CODEC_DIR codec)
set(CODEC_H_PUBLIC
${CODEC_DIR}/pkg_codec.h
${CODEC_DIR}/struct_element.h
${CODEC_DIR}/access_element.h
${CODEC_DIR}/static_codec.h
${CODEC_DIR}/codec.h
${CODEC_DIR}/codec_factory.h
${CODEC_DIR}/bitserializer.h
)
set(CODEC_H
${CODEC_H_PUBLIC}
${CODEC_DIR}/struct_layout.h
${CODEC_DIR}/element_accessor.h
)
set(CODEC_CPP
${CODEC_DIR}/struct_layout.cpp
${CODEC_DIR}/element_accessor.cpp
${CODEC_DIR}/static_codec.cpp
${CODEC_DIR}/codec.cpp
${CODEC_DIR}/codec_factory.cpp
${CODEC_DIR}/bitserializer.cpp
)
set(CODEC_INSTALL ${CODEC_H_PUBLIC})
source_group(${CODEC_DIR} FILES ${CODEC_H} ${CODEC_CPP})

117
codec/codec_factory.cpp Normal file
View file

@ -0,0 +1,117 @@
/**
* @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 "struct_layout.h"
#include "codec_factory.h"
#include "ddlrepresentation/ddl_error.h"
#include "ddlrepresentation/ddldescription.h"
#include "ddlrepresentation/ddlimporter.h"
#include "ddlrepresentation/ddlversion.h"
namespace ddl
{
//define all needed error types and values locally
_MAKE_RESULT(-10, ERR_INVALID_INDEX)
_MAKE_RESULT(-20, ERR_NOT_FOUND)
_MAKE_RESULT(-37, ERR_NOT_INITIALIZED)
static a_util::result::Result getDDL(const char* strMediaDescription,
a_util::memory::unique_ptr<DDLDescription>& pDDL)
{
DDLVersion version_helper = DDLVersion::ddl_version_current;
ddl::DDLImporter oImporter;
a_util::memory::unique_ptr<ddl::DDLDescription> pDefaultDescription(
ddl::DDLDescription::createDefault(version_helper, 4));
RETURN_DDLERROR_IF_FAILED_DESC(oImporter.setXML(strMediaDescription), oImporter.getErrorDesc());
RETURN_DDLERROR_IF_FAILED_DESC(oImporter.createPartial(pDefaultDescription.get(),
version_helper),
oImporter.getErrorDesc());
pDDL.reset(oImporter.getDDL());
return a_util::result::SUCCESS;
}
CodecFactory::CodecFactory():
_layout(new StructLayout()),
_constructor_result(ERR_NOT_INITIALIZED)
{
}
CodecFactory::CodecFactory(const char* strStructName, const char* strMediaDescription)
{
a_util::memory::unique_ptr<DDLDescription> pDDL;
_constructor_result = getDDL(strMediaDescription, pDDL);
if(isOk(_constructor_result))
{
DDLComplex* pStruct = pDDL->getStructByName(strStructName);
if (pStruct)
{
_layout.reset(new StructLayout(pStruct));
_constructor_result = _layout->isValid();
}
else
{
_constructor_result = ERR_NOT_FOUND;
}
}
if (!_layout)
{
_layout.reset(new StructLayout());
}
}
CodecFactory::CodecFactory(const DDLComplex* pStruct):
_layout(new StructLayout(pStruct))
{
_constructor_result = _layout->isValid();
}
a_util::result::Result CodecFactory::isValid() const
{
return _constructor_result;
}
size_t CodecFactory::getStaticElementCount() const
{
return _layout->getStaticElements().size();
}
a_util::result::Result CodecFactory::getStaticElement(size_t nIndex, const StructElement*& pElement) const
{
if (nIndex >= getStaticElementCount())
{
return ERR_INVALID_INDEX;
}
pElement = &_layout->getStaticElements()[nIndex];
return a_util::result::SUCCESS;
}
size_t CodecFactory::getStaticBufferSize(DataRepresentation eRep) const
{
return _layout->getStaticBufferSize(eRep);
}
}

147
codec/codec_factory.h Normal file
View file

@ -0,0 +1,147 @@
/**
* @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
*/
#ifndef DDL_CODEC_FACTORY_CLASS_HEADER
#define DDL_CODEC_FACTORY_CLASS_HEADER
#include "codec.h"
#include "ddlrepresentation/ddlcomplex.h"
#include "struct_element.h"
#include "static_codec.h"
namespace ddl
{
/**
* Factory class for ddl codecs.
*/
class CodecFactory
{
public:
/**
* Empty constructor. This exists to enable uninitialized member variables of this type
* that are move-assigned later on.
*/
CodecFactory();
/**
* Constructor that take a DDL string for initialization.
* @param[in] struct_name The name of the struct for which codecs should be generated.
* @param[in] media_description The DDL description.
*/
CodecFactory(const char* struct_name,
const char* media_description);
/**
* Constructor that uses an OO-DDL struct for initialization.
* @param[in] ddl_struct The struct definition.
*/
CodecFactory(const DDLComplex* ddl_struct);
/**
* Check if the factory is in a valid state.
* @return Any errors during construction.
*/
a_util::result::Result isValid() const;
/**
* Creates a static decoder for the given data.
* @param[in] data The pointer to the raw data.
* @param[in] data_size The size of the raw data.
* @param[in] rep The representation that the data is encoded in.
* @return a static decoder.
*/
inline StaticDecoder makeStaticDecoderFor(const void* data, size_t data_size,
DataRepresentation rep = deserialized) const
{
return StaticDecoder(_layout, data, data_size, rep);
}
/**
* Creates a static codec for the given data.
* @param[in] data The pointer to the raw data.
* @param[in] data_size The size of the raw data.
* @param[in] rep The representation that the data is encoded in.
* @return a static codec.
*/
inline StaticCodec makeStaticCodecFor(void* data, size_t data_size,
DataRepresentation rep = deserialized) const
{
return StaticCodec(_layout, data, data_size, rep);
}
/**
* Creates a decoder for the given data.
* @param[in] data The pointer to the raw data.
* @param[in] data_size The size of the raw data.
* @param[in] rep The representation that the data is encoded in.
* @return a decoder.
*/
inline Decoder makeDecoderFor(const void* data, size_t data_size,
DataRepresentation rep = deserialized) const
{
return Decoder(_layout, data, data_size, rep);
}
/**
* Creates a codec for the given data.
* @param[in] data The pointer to the raw data.
* @param[in] data_size The size of the raw data.
* @param[in] rep The representation that the data is encoded in.
* @return a codec.
*/
inline Codec makeCodecFor(void* data, size_t data_size,
DataRepresentation rep = deserialized) const
{
return Codec(_layout, data, data_size, rep);
}
/**
* @return The amount of static elements contained in the handled structure.
*/
size_t getStaticElementCount() const;
/**
* Access information about an element.
* @param[in] index The index of the element.
* @param[out] element Pointer that will be updated to point to the element information.
* @retval ERR_INVALID_INDEX Invalid index.
*/
a_util::result::Result getStaticElement(size_t index, const StructElement*& element) const;
/**
* @param[in] rep The data representation for which the buffer size should be returned.
* @return The size of the structure in the requested data representation.
*/
size_t getStaticBufferSize(DataRepresentation rep = deserialized) const;
private:
/// For internal use only. @internal The struct layout.
a_util::memory::shared_ptr<const StructLayout> _layout;
/// For internal use only. @internal The constructor result.
a_util::result::Result _constructor_result;
};
}
#endif

228
codec/element_accessor.cpp Normal file
View file

@ -0,0 +1,228 @@
/**
* @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 <assert.h>
#include "a_util/result/error_def.h"
#include "a_util/variant.h"
#include "a_util/memory.h"
#include "element_accessor.h"
#include "legacy_error_macros.h"
#include "bitserializer.h"
namespace ddl
{
//define all needed error types and values locally
_MAKE_RESULT(-5, ERR_INVALID_ARG)
_MAKE_RESULT(-19, ERR_NOT_SUPPORTED)
template <typename T>
a_util::result::Result get_typed_element_value(const StructLayoutElement& sElement, const void* pData,
size_t nDataSize, a_util::variant::Variant& oValue,
const ElementAccessor& oAccessor)
{
T xValue;
RETURN_IF_FAILED(oAccessor.getValue(sElement, pData, nDataSize, &xValue));
oValue = xValue;
return a_util::result::SUCCESS;
}
#define GET_CASE_TYPE(__variant_type, __data_type) \
case a_util::variant::__variant_type: \
{ \
return get_typed_element_value<__data_type>(sElement, pData, nDataSize, oValue, *this); \
}
template <typename T>
a_util::result::Result set_typed_element_value(const StructLayoutElement& sElement, void* pData,
size_t nDataSize, const a_util::variant::Variant& oValue,
const ElementAccessor& oAccessor)
{
T xHelper = oValue;
return oAccessor.setValue(sElement, pData, nDataSize, &xHelper);
}
#define SET_CASE_TYPE(__variant_type, __data_type) \
case a_util::variant::__variant_type: \
{ \
return set_typed_element_value<__data_type>(sElement, pData, nDataSize, oValue, *this); \
}
a_util::result::Result ElementAccessor::getValue(const StructLayoutElement& sElement, const void* pData,
size_t nDataSize, a_util::variant::Variant& oValue) const
{
switch(sElement.type)
{
GET_CASE_TYPE(VT_Bool, bool)
GET_CASE_TYPE(VT_Int8, int8_t)
GET_CASE_TYPE(VT_UInt8, uint8_t)
GET_CASE_TYPE(VT_Int16, int16_t)
GET_CASE_TYPE(VT_UInt16, uint16_t)
GET_CASE_TYPE(VT_Int32, int32_t)
GET_CASE_TYPE(VT_UInt32, uint32_t)
GET_CASE_TYPE(VT_Int64, int64_t)
GET_CASE_TYPE(VT_UInt64, uint64_t)
GET_CASE_TYPE(VT_Float32, float)
GET_CASE_TYPE(VT_Float64, double)
default: return ERR_NOT_SUPPORTED;
}
}
a_util::result::Result ElementAccessor::setValue(const StructLayoutElement& sElement, void* pData,
size_t nDataSize, const a_util::variant::Variant& oValue) const
{
switch(sElement.type)
{
SET_CASE_TYPE(VT_Bool, bool)
SET_CASE_TYPE(VT_Int8, int8_t)
SET_CASE_TYPE(VT_UInt8, uint8_t)
SET_CASE_TYPE(VT_Int16, int16_t)
SET_CASE_TYPE(VT_UInt16, uint16_t)
SET_CASE_TYPE(VT_Int32, int32_t)
SET_CASE_TYPE(VT_UInt32, uint32_t)
SET_CASE_TYPE(VT_Int64, int64_t)
SET_CASE_TYPE(VT_UInt64, uint64_t)
SET_CASE_TYPE(VT_Float32, float)
SET_CASE_TYPE(VT_Float64, double)
default: return ERR_NOT_SUPPORTED;
}
}
a_util::result::Result DeserializedAccessor::getValue(const StructLayoutElement& sElement, const void* pData,
size_t nDataSize, void* pElementValue) const
{
assert(sElement.deserialized.bit_offset % 8 == 0);
assert(sElement.deserialized.bit_size % 8 == 0);
size_t nByteOffset = sElement.deserialized.bit_offset / 8;
size_t nByteSize = sElement.deserialized.bit_size / 8;
if (nDataSize < nByteOffset + nByteSize)
{
return ERR_INVALID_ARG;
}
a_util::memory::copy(pElementValue, nByteSize,
reinterpret_cast<const void*>(static_cast<const uint8_t*>(pData) + nByteOffset),
nByteSize);
return a_util::result::SUCCESS;
}
a_util::result::Result DeserializedAccessor::setValue(const StructLayoutElement& sElement, void* pData,
size_t nDataSize, const void* pElementValue) const
{
assert(sElement.deserialized.bit_offset % 8 == 0);
assert(sElement.deserialized.bit_size % 8 == 0);
size_t nByteOffset = sElement.deserialized.bit_offset / 8;
size_t nByteSize = sElement.deserialized.bit_size / 8;
if (nDataSize < nByteOffset + nByteSize)
{
return ERR_INVALID_ARG;
}
a_util::memory::copy(static_cast<uint8_t*>(pData) + nByteOffset, nByteSize,
pElementValue,
nByteSize);
return a_util::result::SUCCESS;
}
const ElementAccessor& DeserializedAccessor::getInstance()
{
static DeserializedAccessor oInstance;
return oInstance;
}
const ElementAccessor& SerializedAccessor::getInstance()
{
static SerializedAccessor oInstance;
return oInstance;
}
template <typename T>
a_util::result::Result read_typed_bits(const StructLayoutElement& sElement, const void* pData,
size_t nDataSize, void* pElementValue)
{
a_util::memory::BitSerializer oHelper(const_cast<void*>(pData), nDataSize);
return oHelper.read<T>(sElement.serialized.bit_offset, sElement.serialized.bit_size,
reinterpret_cast<T*>(pElementValue),
(a_util::memory::Endianess)sElement.byte_order);
}
#define GET_CASE_TYPE_SER(__variant_type, __data_type) \
case a_util::variant::__variant_type: \
{ \
return read_typed_bits<__data_type>(sElement, pData, nDataSize, pElementValue); \
}
a_util::result::Result SerializedAccessor::getValue(const StructLayoutElement& sElement, const void* pData,
size_t nDataSize, void* pElementValue) const
{
switch(sElement.type)
{
GET_CASE_TYPE_SER(VT_Bool, bool)
GET_CASE_TYPE_SER(VT_Int8, int8_t)
GET_CASE_TYPE_SER(VT_UInt8, uint8_t)
GET_CASE_TYPE_SER(VT_Int16, int16_t)
GET_CASE_TYPE_SER(VT_UInt16, uint16_t)
GET_CASE_TYPE_SER(VT_Int32, int32_t)
GET_CASE_TYPE_SER(VT_UInt32, uint32_t)
GET_CASE_TYPE_SER(VT_Int64, int64_t)
GET_CASE_TYPE_SER(VT_UInt64, uint64_t)
GET_CASE_TYPE_SER(VT_Float32, float)
GET_CASE_TYPE_SER(VT_Float64, double)
default: return ERR_NOT_SUPPORTED;
}
}
template <typename T>
a_util::result::Result write_typed_bits(const StructLayoutElement& sElement, void* pData,
size_t nDataSize, const void* pElementValue)
{
a_util::memory::BitSerializer oHelper(pData, nDataSize);
return oHelper.write<T>(sElement.serialized.bit_offset, sElement.serialized.bit_size,
*reinterpret_cast<const T*>(pElementValue),
(a_util::memory::Endianess)sElement.byte_order);
}
#define SET_CASE_TYPE_SER(__variant_type, __data_type) \
case a_util::variant::__variant_type: \
{ \
return write_typed_bits<__data_type>(sElement, pData, nDataSize, pElementValue); \
}
a_util::result::Result SerializedAccessor::setValue(const StructLayoutElement& sElement, void* pData,
size_t nDataSize, const void* pElementValue) const
{
switch(sElement.type)
{
SET_CASE_TYPE_SER(VT_Bool, bool)
SET_CASE_TYPE_SER(VT_Int8, int8_t)
SET_CASE_TYPE_SER(VT_UInt8, uint8_t)
SET_CASE_TYPE_SER(VT_Int16, int16_t)
SET_CASE_TYPE_SER(VT_UInt16, uint16_t)
SET_CASE_TYPE_SER(VT_Int32, int32_t)
SET_CASE_TYPE_SER(VT_UInt32, uint32_t)
SET_CASE_TYPE_SER(VT_Int64, int64_t)
SET_CASE_TYPE_SER(VT_UInt64, uint64_t)
SET_CASE_TYPE_SER(VT_Float32, float)
SET_CASE_TYPE_SER(VT_Float64, double)
default: return ERR_NOT_SUPPORTED;
}
}
}

83
codec/element_accessor.h Normal file
View file

@ -0,0 +1,83 @@
/**
* @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
*/
#ifndef DDL_STRUCT_ELEMENT_ACCESS_PRIVATE_CLASS_HEADER
#define DDL_STRUCT_ELEMENT_ACCESS_PRIVATE_CLASS_HEADER
#include "a_util/result.h"
#include "struct_layout.h"
namespace ddl
{
class ElementAccessor
{
public:
virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data,
size_t data_size, void* element_value) const = 0;
virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data,
size_t data_size, const void* element_value) const = 0;
virtual DataRepresentation getRepresentation() const = 0;
a_util::result::Result getValue(const StructLayoutElement& element, const void* data,
size_t data_size, a_util::variant::Variant& value) const;
a_util::result::Result setValue(const StructLayoutElement& element, void* data,
size_t data_size, const a_util::variant::Variant& value) const;
};
class DeserializedAccessor: public ElementAccessor
{
public:
virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data,
size_t data_size, void* element_value) const;
virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data,
size_t data_size, const void* element_value) const;
virtual DataRepresentation getRepresentation() const
{
return deserialized;
}
static const ElementAccessor& getInstance();
};
class SerializedAccessor: public ElementAccessor
{
public:
virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data,
size_t data_size, void* element_value) const;
virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data,
size_t data_size, const void* element_value) const;
virtual DataRepresentation getRepresentation() const
{
return serialized;
}
static const ElementAccessor& getInstance();
};
}
#endif

32
codec/pkg_codec.h Normal file
View file

@ -0,0 +1,32 @@
/**
* @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
*/
#ifndef _DDL_CODEC_PKG_HEADER_
#define _DDL_CODEC_PKG_HEADER_
#include "struct_element.h"
#include "static_codec.h"
#include "codec.h"
#include "codec_factory.h"
#include "access_element.h"
#include "bitserializer.h"
#endif

198
codec/static_codec.cpp Normal file
View file

@ -0,0 +1,198 @@
/**
* @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 "static_codec.h"
#include "a_util/result/error_def.h"
#include "legacy_error_macros.h"
#include "element_accessor.h"
namespace ddl
{
//define all needed error types and values locally
_MAKE_RESULT(-5, ERR_INVALID_ARG)
_MAKE_RESULT(-10, ERR_INVALID_INDEX)
StaticDecoder::StaticDecoder(a_util::memory::shared_ptr<const StructLayout> pLayout,
const void* pData, size_t nDataSize,
DataRepresentation eRep):
_layout(pLayout),
_data(pData),
_data_size(nDataSize),
_element_accessor(eRep == deserialized ?
&DeserializedAccessor::getInstance() :
&SerializedAccessor::getInstance())
{
}
a_util::result::Result StaticDecoder::isValid() const
{
RETURN_IF_FAILED(_layout->isValid());
if (_data_size < getStaticBufferSize(getRepresentation()))
{
return ERR_INVALID_ARG;
}
return a_util::result::SUCCESS;
}
size_t StaticDecoder::getElementCount() const
{
return _layout->getStaticElements().size();
}
a_util::result::Result StaticDecoder::getElement(size_t nIndex, const StructElement*& pElement) const
{
pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return a_util::result::SUCCESS;
}
a_util::result::Result StaticDecoder::getElementValue(size_t nIndex, void* pValue) const
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->getValue(*pElement, _data, _data_size, pValue);
}
a_util::result::Result StaticDecoder::getElementValue(size_t nIndex, a_util::variant::Variant& oValue) const
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->getValue(*pElement, _data, _data_size, oValue);
}
const void* StaticDecoder::getElementAddress(size_t nIndex) const
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return NULL;
}
size_t nBitPos = _element_accessor->getRepresentation() == deserialized ?
pElement->deserialized.bit_offset :
pElement->serialized.bit_offset;
if (nBitPos % 8)
{
return NULL;
}
size_t bit_size = _element_accessor->getRepresentation() == deserialized ?
pElement->deserialized.bit_size :
pElement->serialized.bit_size;
if ((nBitPos / 8) + (bit_size / 8) + (bit_size % 8 ? 1 : 0) >
_data_size)
{
return NULL;
}
return static_cast<const uint8_t*>(_data) + (nBitPos / 8);
}
const StructLayoutElement* StaticDecoder::getLayoutElement(size_t nIndex) const
{
const StructLayoutElement* pElement = NULL;
if (nIndex < _layout->getStaticElements().size())
{
pElement = &_layout->getStaticElements()[nIndex];
}
return pElement;
}
size_t StaticDecoder::getStaticBufferSize(DataRepresentation eRep) const
{
return _layout->getStaticBufferSize(eRep);
}
DataRepresentation StaticDecoder::getRepresentation() const
{
return _element_accessor->getRepresentation();
}
StaticCodec::StaticCodec(a_util::memory::shared_ptr<const StructLayout> pLayout,
void* pData, size_t nDataSize, DataRepresentation eRep):
StaticDecoder(pLayout, pData, nDataSize, eRep)
{
}
a_util::result::Result StaticCodec::setElementValue(size_t nIndex, const void* pValue)
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->setValue(*pElement,
const_cast<void*>(_data),
_data_size,
pValue);
}
a_util::result::Result StaticCodec::setElementValue(size_t nIndex, const a_util::variant::Variant& oValue)
{
const StructLayoutElement* pElement = getLayoutElement(nIndex);
if (!pElement)
{
return ERR_INVALID_INDEX;
}
return _element_accessor->setValue(*pElement, const_cast<void*>(_data),
_data_size, oValue);
}
void* StaticCodec::getElementAddress(size_t nIndex)
{
return const_cast<void*>(StaticDecoder::getElementAddress(nIndex));
}
a_util::result::Result StaticCodec::setConstants()
{
if (_layout->hasEnums())
{
size_t nElementCount = getElementCount();
for (size_t nElement = 0; nElement < nElementCount; ++nElement)
{
const StructLayoutElement* pElement = getLayoutElement(nElement);
if (pElement->constant)
{
RETURN_IF_FAILED(_element_accessor->setValue(*pElement, const_cast<void*>(_data),
_data_size, *pElement->constant));
}
}
}
return a_util::result::SUCCESS;
}
}

181
codec/static_codec.h Normal file
View file

@ -0,0 +1,181 @@
/**
* @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
*/
#ifndef DDL_STATIC_CODEC_CLASS_HEADER
#define DDL_STATIC_CODEC_CLASS_HEADER
#include "a_util/result.h"
#include "a_util/variant.h"
#include "a_util/memory.h"
#include "struct_element.h"
namespace ddl
{
class StructLayout;
class ElementAccessor;
/**
* Decoder for static structures defined by a DDL definition.
*/
class StaticDecoder
{
public:
/**
* Noncopyable
*/
StaticDecoder(const StaticDecoder&) = delete;
/**
* Noncopyable
*/
StaticDecoder& operator=(const StaticDecoder&) = delete;
/**
* Move constructor.
*/
StaticDecoder(StaticDecoder&&) = default;
/**
* Move assignment operator.
*/
StaticDecoder& operator=(StaticDecoder&&) = default;
/**
* @return Whether or not the decoder is valid.
* @retval ERR_INVALID_ARG The passed data is not large enough.
*/
virtual a_util::result::Result isValid() const;
/**
* @return The amount of elements contained in the data structure.
*/
virtual size_t getElementCount() const;
/**
* Access information about an element.
* @param[in] index The index of the element.
* @param[out] element Pointer that will be updated to point to the element information.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result getElement(size_t index, const StructElement*& element) const;
/**
* Returns the current value of the given element by copying its data
* to the passed-in location.
* @param[in] index The index of the element.
* @param[out] value The location where the value should be copied to.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result getElementValue(size_t index, void* value) const;
/**
* Returns the current value of the given element as a variant.
* @param[in] index The index of the element.
* @param[out] value The will be set to the current value.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result getElementValue(size_t index, a_util::variant::Variant& value) const;
/**
* @param[in] index The index of the element.
* @return A pointer to the element or NULL in case of an error.
*/
const void* getElementAddress(size_t index) const;
/**
* @param[in] rep The data representation for which the buffer size should be returned.
* @return The size of the structure in the requested data representation.
*/
size_t getStaticBufferSize(DataRepresentation rep = deserialized) const;
/**
* @return The data representation which this decoder handles.
*/
DataRepresentation getRepresentation() const;
protected:
friend class CodecFactory;
/// For internal use only. @internal
StaticDecoder(a_util::memory::shared_ptr<const StructLayout> layout,
const void* data, size_t data_size,
DataRepresentation rep);
/// For internal use only. @internal
virtual const StructLayoutElement* getLayoutElement(size_t index) const;
protected:
/// For internal use only. @internal
a_util::memory::shared_ptr<const StructLayout> _layout;
/// For internal use only. @internal
const void* _data;
/// For internal use only. @internal
size_t _data_size;
/// For internal use only. @internal
const ElementAccessor* _element_accessor;
};
/**
* Codec for static structures defined by a DDL definition.
*/
class StaticCodec: public StaticDecoder
{
public:
/**
* Sets the current value of the given element by copying its data
* from the passed-in location.
* @param[in] index The index of the element.
* @param[in] value The location where the data should be copied from.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result setElementValue(size_t index, const void* value);
/**
* Sets the current value of the given element to the given value.
* @param[in] index The index of the element.
* @param[in] value The value.
* @retval ERR_INVALID_INDEX Invalid element index.
*/
a_util::result::Result setElementValue(size_t index, const a_util::variant::Variant& value);
/**
* @param[in] index The index of the element.
* @return A pointer to the element or NULL in case of an error.
*/
void* getElementAddress(size_t index);
using StaticDecoder::getElementAddress;
/**
* Sets all elements to their constant values defined in the DDL.
* @return Standard result.
*/
a_util::result::Result setConstants();
private:
friend class CodecFactory;
/// For internal use only. @internal
StaticCodec(a_util::memory::shared_ptr<const StructLayout> layout, void* data, size_t data_size,
DataRepresentation rep);
};
}
#endif

115
codec/struct_element.h Normal file
View file

@ -0,0 +1,115 @@
/**
* @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
*/
#ifndef DDL_STRUCT_ELEMENT_CLASS_HEADER
#define DDL_STRUCT_ELEMENT_CLASS_HEADER
#include <map>
#include <string>
#include "a_util/variant.h"
#include "a_util/result.h"
namespace ddl
{
/**
* Enumeration for the data representation
*/
enum DataRepresentation
{
serialized, ///< serialized data, i.e network, on disks, can msgs, ...
deserialized ///< deserialized data, c-structs, arrays, ...
};
/**
* Typedef for enumerations name -> value.
*/
typedef std::map<std::string, a_util::variant::Variant> EnumType;
/**
* Information about an element accessible with a decoder or codec.
*/
struct StructElement
{
std::string name; ///< The full name of the element.
a_util::variant::VariantType type; ///< The type of the element.
const EnumType* p_enum; ///< pointer to an enum, can be NULL.
};
// The following classes are for internal use only
/**
* \cond INTERNAL
*/
struct Position
{
size_t bit_offset;
size_t bit_size;
};
struct StructLayoutElement: public StructElement
{
Position deserialized;
Position serialized;
int byte_order;
const a_util::variant::Variant* constant;
};
struct DynamicStructLayoutElement
{
std::string name;
size_t alignment;
std::string size_element_name;
std::vector<StructLayoutElement> static_elements;
std::vector<DynamicStructLayoutElement> dynamic_elements;
DynamicStructLayoutElement() = default;
DynamicStructLayoutElement(size_t alignment):
alignment(alignment)
{
}
bool isAlignmentElement() const
{
return name.empty();
}
bool isDynamicArray() const
{
return !size_element_name.empty();
}
};
struct Offsets
{
size_t deserialized;
size_t serialized;
};
/**
* \endcond INTERNAL
*/
}
#endif

345
codec/struct_layout.cpp Normal file
View 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;
}
}

87
codec/struct_layout.h Normal file
View file

@ -0,0 +1,87 @@
/**
* @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
*/
#ifndef DDL_STRUCT_LAYOUT_CLASS_HEADER
#define DDL_STRUCT_LAYOUT_CLASS_HEADER
#include "struct_element.h"
namespace ddl
{
class DDLComplex;
/**
* @internal
* This class is for internal use only.
*/
class StructLayout
{
public:
StructLayout();
StructLayout(const DDLComplex* ddl_struct);
a_util::result::Result isValid() const
{
return _calculations_result;
}
const std::vector<StructLayoutElement>& getStaticElements() const
{
return _static_elements;
}
const std::vector<DynamicStructLayoutElement>& getDynamicElements() const
{
return _dynamic_elements;
}
bool hasDynamicElements() const
{
return !_dynamic_elements.empty();
}
bool hasEnums() const
{
return !_enums.empty();
}
const Offsets& getStaticBufferBitSizes() const
{
return _static_buffer_sizes;
}
size_t getStaticBufferSize(DataRepresentation rep) const;
private:
a_util::result::Result calculate(const DDLComplex* ddl_struct);
private:
std::vector<StructLayoutElement> _static_elements;
std::vector<DynamicStructLayoutElement> _dynamic_elements;
std::map<std::string, EnumType> _enums;
Offsets _static_buffer_sizes;
a_util::result::Result _calculations_result;
};
}
#endif