/** * @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 #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 static inline size_t getElementCount(const T& type) { return type.getElementCount(); } /// For internal use only. @internal template 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 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 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 a_util::result::Result find_struct_index(const T& decoder, const std::string& struct_name, size_t& index) { return detail::find_complex_index(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 a_util::result::Result find_array_index(const T& decoder, const std::string& array_name, size_t& index) { return detail::find_complex_index(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 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 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 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 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 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 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(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 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 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 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(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 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(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 a_util::result::Result get_struct_value(const CODEC& decoder, const std::string& struct_name, T* struct_value) { const T* address = get_struct_address(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 a_util::result::Result set_struct_value(CODEC& codec, const std::string& struct_name, const T* struct_value) { T* address = get_struct_address(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 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(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 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(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 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(end_adress) - static_cast(start_address); } else { // it reaches til the end size_t start_offset = static_cast(start_address) - static_cast(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 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 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 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 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