ddl/ddlrepresentation/ddlimporter.cpp
2019-12-12 14:41:47 +01:00

2663 lines
100 KiB
C++
Raw Permalink Blame History

/**
* @file
*
* @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 "ddlimporter.h"
#include <sstream>
#include "a_util/result/error_def.h"
#include "legacy_error_macros.h"
#include "ddldescription.h"
#include "ddlunit.h"
#include "ddlbaseunit.h"
#include "ddlprefix.h"
#include "ddldatatype.h"
#include "ddlenum.h"
#include "ddlcomplex.h"
#include "ddlstream.h"
#include "ddlstreammetatype.h"
#include "ddlheader.h"
#include "ddlextdeclaration.h"
#include "ddlrefunit.h"
#include "ddlelement.h"
#include "ddlstreamstruct.h"
#include "ddlversion.h"
namespace ddl
{
//define all needed error types and values locally
_MAKE_RESULT(-2, ERR_UNKNOWN)
_MAKE_RESULT(-4, ERR_POINTER)
_MAKE_RESULT(-5, ERR_INVALID_ARG)
_MAKE_RESULT(-15, ERR_RESOURCE_IN_USE)
_MAKE_RESULT(-18, ERR_NO_CLASS)
_MAKE_RESULT(-20, ERR_NOT_FOUND)
_MAKE_RESULT(-27, ERR_OPEN_FAILED)
_MAKE_RESULT(-36, ERR_UNKNOWN_FORMAT)
_MAKE_RESULT(-37, ERR_NOT_INITIALIZED)
/**
* Iterator type for cDOMElementList
*/
typedef a_util::xml::DOMElementList::iterator tDOMElemIt;
#define RETURN_IF_FAILED_AND_LOG_ERROR_STR_DDLIMPORTER(code, desc) \
{ \
a_util::result::Result __err_code = code; \
if (isFailed(__err_code)){ _fnLogOutput(( desc ), LOG_LVL_ERROR, __FILE__, (uint32_t) __LINE__, (code)); \
ImporterMsg sError = {std::string(desc), importer_error}; \
_errors.push_back(sError); \
return (__err_code); }\
}
DDLImporter::DDLImporter(bool bBasicCheck, bool bSorted) :
_dom{},
_ddl_desc{},
_current_ref_ddl{},
_unknown_units{},
_unknown_structs{},
_unknown_stream_meta_types{},
_init_flag{},
_creation_level{1},
_full_check{},
_errors{},
_basic_check{bBasicCheck},
_merge_defaults{true},
_sorted{bSorted},
_prefere_reference{true}
{
}
DDLImporter::DDLImporter(const a_util::filesystem::Path& strFile, bool bBasicCheck, bool bSorted) :
DDLImporter(bBasicCheck, bSorted)
{
_init_flag = isOk(setFile(strFile));
}
DDLImporter::DDLImporter(const char* strFile, bool bBasicCheck, bool bSorted) :
DDLImporter(a_util::filesystem::Path(strFile), bBasicCheck, bSorted)
{
}
DDLImporter::DDLImporter(int nCreationLevel, bool bBasicCheck, bool bSorted) :
DDLImporter(bBasicCheck, bSorted)
{
_creation_level = nCreationLevel;
}
DDLImporter& DDLImporter::operator=(DDLImporter other)
{
swap(*this, other);
return *this;
}
DDLImporter::DDLImporter(DDLImporter&& other)
{
swap(*this, other);
}
DDLImporter::~DDLImporter()
{
// The DDL object does not get deleted because the caller/user of this
// object is responsible for it.
_ddl_desc = NULL;
_current_ref_ddl = NULL;
_unknown_units.deleteAll();
_unknown_structs.deleteAll();
_unknown_stream_meta_types.deleteAll();
}
void swap(DDLImporter& lhs, DDLImporter& rhs) noexcept
{
using std::swap;
swap(lhs._basic_check, rhs._basic_check);
swap(lhs._creation_level, rhs._creation_level);
swap(lhs._current_ref_ddl, rhs._current_ref_ddl);
swap(lhs._ddl_desc, rhs._ddl_desc);
swap(lhs._dom, rhs._dom);
swap(lhs._errors, rhs._errors);
swap(lhs._full_check, rhs._full_check);
swap(lhs._init_flag, rhs._init_flag);
swap(lhs._merge_defaults, rhs._merge_defaults);
swap(lhs._prefere_reference, rhs._prefere_reference);
swap(lhs._sorted, rhs._sorted);
swap(lhs._unknown_stream_meta_types, rhs._unknown_stream_meta_types);
swap(lhs._unknown_structs, rhs._unknown_structs);
swap(lhs._unknown_units, rhs._unknown_units);
}
std::string DDLImporter::getErrorDesc() const
{
// compatibility to cDDLChecker
return getLastErrorDesc();
}
std::string DDLImporter::getLastErrorDesc() const
{
// return description of most recently added error element
for (ImporterMsgList::const_reverse_iterator itMsgs = _errors.rbegin();
_errors.rend() != itMsgs; ++itMsgs)
{
if (importer_error == itMsgs->severity)
{
return std::string(itMsgs->desc);
}
}
return a_util::strings::empty_string;
}
void DDLImporter::printAllMessages(ImporterMsgSeverity eLeastSeverity /* = importer_info */)
{
for (ImporterMsgList::const_iterator itMsg = _errors.begin();
_errors.end() != itMsg; ++itMsg)
{
switch (itMsg->severity)
{
case importer_error:
{
LOG_ERROR(itMsg->desc.c_str());
break;
}
case importer_warning:
{
if (importer_error != eLeastSeverity)
{
LOG_WARNING(itMsg->desc.c_str());
}
break;
}
case importer_info:
{
if (importer_info == eLeastSeverity)
{
LOG_INFO(itMsg->desc.c_str());
}
break;
}
default:
{
LOG_ERROR("Unknown message severity detected.");
break;
}
}
}
}
ImporterMsgList DDLImporter::getAllMessages() const
{
return _errors;
}
DDLDescription * DDLImporter::getDDL() const
{
return _ddl_desc;
}
void DDLImporter::destroyDDL()
{
destroyDDL(_ddl_desc);
_ddl_desc = NULL;
// no DDL objects => no valid messages
_errors.clear();
}
void DDLImporter::destroyDDL(DDLDescription *poDDL)
{
delete poDDL;
}
a_util::result::Result DDLImporter::setFile(const a_util::filesystem::Path& strFile)
{
_init_flag = _dom.load(strFile);
if (!_init_flag)
{
ImporterMsg sError = {_dom.getLastError(), importer_error };
_errors.push_back(sError);
return ERR_OPEN_FAILED;
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::setXML(const std::string& strXML)
{
_init_flag = _dom.fromString(strXML);
if (!_init_flag)
{
ImporterMsg sError = {_dom.getLastError(), importer_error};
_errors.push_back(sError);
LOG_ERROR(_dom.getLastError().c_str());
return ERR_OPEN_FAILED;
}
return a_util::result::SUCCESS;
}
void DDLImporter::setCreationLevel(int const nLevel)
{
_creation_level = nLevel;
}
void DDLImporter::setFullCheckDescriptionMode(bool bFullCheck)
{
_full_check = bFullCheck;
}
void DDLImporter::setMergeDefaults(bool bMergeDefaults)
{
_merge_defaults = bMergeDefaults;
}
void DDLImporter::setPreferReferenceEntities(bool bPrefereReference)
{
_prefere_reference = bPrefereReference;
}
a_util::result::Result DDLImporter::createNew(const DDLVersion& requestedVersion /* = 0 */)
{
DDLVersion version = requestedVersion;
if (version == DDLVersion::ddl_version_invalid)
{
version = DDLVersion::ddl_version_current;
}
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
// The DDL object does not get deleted because the caller/user of this
// object is responsible for it.
_ddl_desc = NULL;
// build up new DDL
if (_full_check)
{
if (isFailed(buildHeader()) && _ddl_desc == NULL)
{
_ddl_desc = new DDLDescription(new DDLHeader(),
DDLUnitVec(_sorted),
DDLBaseunitVec(_sorted),
DDLPrefixVec(_sorted),
DDLDTVec(_sorted),
DDLComplexVec(_sorted),
DDLStreamVec(_sorted),
DDLEnumVec(_sorted),
_merge_defaults);
}
buildUnits();
buildDatatypes();
buildEnums();
buildStructs();
buildStreams();
if (version >= DDLVersion::ddl_version_40) buildStreamMetaTypes();
// check if any error occurred during build up new DDL
for (ImporterMsgList::const_iterator itMsg = _errors.begin();
_errors.end() != itMsg; ++itMsg)
{
if (itMsg->severity == importer_error)
{
return ERR_UNKNOWN_FORMAT;
}
}
}
else
{
RETURN_IF_FAILED(buildHeader());
RETURN_IF_FAILED(buildUnits());
RETURN_IF_FAILED(buildDatatypes());
RETURN_IF_FAILED(buildEnums());
RETURN_IF_FAILED(buildStructs());
RETURN_IF_FAILED(buildStreams());
if (version >= DDLVersion::ddl_version_40) RETURN_IF_FAILED(buildStreamMetaTypes());
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::createPartial(const DDLDescription* poRefDDL, const DDLVersion& requestedVersion)
{
DDLVersion version = requestedVersion;
if (!poRefDDL) { return ERR_POINTER; }
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
_current_ref_ddl = poRefDDL;
_ddl_desc = NULL;
std::string strElementType = _dom.getRoot().getName();
if (strElementType == "adtf:ddl" ||
strElementType == "description" ||
strElementType == "units" ||
strElementType == "datatypes" ||
strElementType == "structs" ||
strElementType == "streams" ||
strElementType == "enums" ||
strElementType == "streammetatypes" ||
(strElementType != "datatype"
&& strElementType != "baseunit"
&& strElementType != "prefixes"
&& strElementType != "unit"
&& strElementType != "datatype"
&& strElementType != "struct"
&& strElementType != "stream"
&& strElementType != "enum"
&& strElementType != "streammetatype"))
{
a_util::xml::DOMElement oRoot = _dom.getRoot();
a_util::xml::DOMElement oTmpElement;
bool bValidElementFound = false;
bool bFoundEnums = false;
//this is to detect 2.0 MediaDescriptions
//i.e. the device-tb etc. uses enums!! and did not raise the version number at all!!!
if (_dom.findNode("//enums", oTmpElement))
{
bFoundEnums = true;
if (version < DDLVersion::ddl_version_20)
{
version = DDLVersion::ddl_version_20;
}
}
if (oRoot.findNode("header", oTmpElement))
{
RETURN_IF_FAILED(buildHeader());
bValidElementFound = true;
}
else
{
_ddl_desc = DDLDescription::createDefault(version, _creation_level, _sorted);
}
//this is to detect 2.0 MediaDescriptions
//i.e. the device-tb etc. uses enums!! and did not raise the version number at all!!!device-tb etc. uses enums!! and did not raise the version number at all!!!
if (_ddl_desc && _ddl_desc->getHeader() && bFoundEnums)
{
if (_ddl_desc->getHeader()->getLanguageVersion() < DDLVersion::ddl_version_20)
{
_ddl_desc->getHeader()->setLanguageVersion(DDLVersion::ddl_version_20);
}
}
if (_dom.findNode("//units", oTmpElement))
{
RETURN_IF_FAILED(buildUnits());
bValidElementFound = true;
}
if (_dom.findNode("//datatypes", oTmpElement))
{
RETURN_IF_FAILED(buildDatatypes());
bValidElementFound = true;
}
if (_dom.findNode("//enums", oTmpElement))
{
RETURN_IF_FAILED(buildEnums());
bValidElementFound = true;
}
if (_dom.findNode("//structs", oTmpElement))
{
RETURN_IF_FAILED(buildStructs());
bValidElementFound = true;
}
if (_dom.findNode("//streams", oTmpElement))
{
RETURN_IF_FAILED(buildStreams());
bValidElementFound = true;
}
if (_dom.findNode("//streammetatypes", oTmpElement))
{
RETURN_IF_FAILED(buildStreamMetaTypes());
bValidElementFound = true;
}
_current_ref_ddl = NULL;
if (!bValidElementFound)
{
return ERR_UNKNOWN_FORMAT;
}
return a_util::result::SUCCESS;
}
// _current_ref_ddl = NULL;
_ddl_desc = DDLDescription::createDefault(version, _creation_level, _sorted);
DDLBaseunit * poBUTmp = NULL;
if (strElementType == "baseunit")
{
RETURN_IF_FAILED(buildSingleBaseunit(&poBUTmp, _dom.getRoot()));
_ddl_desc->addBaseunit(poBUTmp);
return a_util::result::SUCCESS;
}
DDLPrefix * poPrefixTmp = NULL;
if (strElementType == "prefixes")
{
RETURN_IF_FAILED(buildSinglePrefix(&poPrefixTmp, _dom.getRoot()));
_ddl_desc->addPrefix(poPrefixTmp);
return a_util::result::SUCCESS;
}
DDLUnit * poUnitTmp = NULL;
if (strElementType == "unit")
{
RETURN_IF_FAILED(buildSingleUnit(&poUnitTmp, _dom.getRoot()));
_ddl_desc->addUnit(poUnitTmp);
return a_util::result::SUCCESS;
}
if (strElementType == "datatype")
{
DDLDataType * poDTTmp = NULL;
RETURN_IF_FAILED(buildSingleDatatype(&poDTTmp, _dom.getRoot()));
_ddl_desc->addDatatype(poDTTmp);
return a_util::result::SUCCESS;
}
if (strElementType == "enum")
{
DDLEnum * poEnumTmp = NULL;
RETURN_IF_FAILED(buildSingleEnum(&poEnumTmp, _dom.getRoot()));
_ddl_desc->addEnum(poEnumTmp);
return a_util::result::SUCCESS;
}
if (strElementType == "struct")
{
DDLComplex * poStructTmp = NULL;
RETURN_IF_FAILED(buildSingleStruct(&poStructTmp, _dom.getRoot()));
_ddl_desc->addStruct(poStructTmp);
return a_util::result::SUCCESS;
}
if (strElementType == "stream")
{
DDLStream * poStreamTmp = NULL;
RETURN_IF_FAILED(buildSingleStream(&poStreamTmp, _dom.getRoot()));
_ddl_desc->addStream(poStreamTmp);
return a_util::result::SUCCESS;
}
if (strElementType == "streammetatype")
{
RETURN_IF_FAILED(buildSingleStreamMetaType(_dom.getRoot(),
_ddl_desc->getStreamMetaTypes()));
return a_util::result::SUCCESS;
}
return ERR_UNKNOWN_FORMAT;
}
a_util::result::Result DDLImporter::buildHeader()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oHeaderElement;
a_util::xml::DOMElement oTmpElement;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!_dom.findNode("//header", oHeaderElement))
{
pushMessage(std::string("DDL does not contain a header."), importer_error);
return ERR_OPEN_FAILED;
}
else
{
std::string strVersion = a_util::strings::empty_string;
if (!oHeaderElement.findNode("language_version", oTmpElement))
{
pushMessage(std::string("DDL does not contain a language_version in header"), importer_error);
nResult = ERR_NOT_FOUND;
if (false == _full_check)
{
return nResult;
}
}
else
{
strVersion = oTmpElement.getData();
a_util::strings::trim(strVersion);
}
std::string strAuthor = a_util::strings::empty_string;
if (!oHeaderElement.findNode("author", oTmpElement))
{
pushMessage(std::string("DDL does not contain an author in header."), importer_error);
nResult = ERR_NOT_FOUND;
if (false == _full_check)
{
return nResult;
}
}
else
{
strAuthor = oTmpElement.getData();
}
a_util::datetime::Date sDateCreation(1900, 1, 1);
if (!oHeaderElement.findNode("date_creation", oTmpElement))
{
pushMessage(std::string("DDL does not contain a creation date in header."), importer_error);
nResult = ERR_NOT_FOUND;
if (false == _full_check)
{
return nResult;
}
}
else
{
sDateCreation = DDLHeader::dateFromString(oTmpElement.getData());
}
a_util::datetime::Date sDateChange(1900, 1, 1);
if (!oHeaderElement.findNode("date_change", oTmpElement))
{
pushMessage(std::string("DDL does not contain a change date in header."), importer_error);
nResult = ERR_NOT_FOUND;
if (false == _full_check)
{
return nResult;
}
}
else
{
sDateChange = DDLHeader::dateFromString(oTmpElement.getData());
}
std::string strDescription = a_util::strings::empty_string;
if (!oHeaderElement.findNode("description", oTmpElement))
{
pushMessage(std::string("DDL does not contain a description in header."), importer_error);
nResult = ERR_NOT_FOUND;
if (false == _full_check)
{
return nResult;
}
}
else
{
strDescription = oTmpElement.getData();
}
// do not continue with header, if any header property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
DDLExtDeclarationVec vecExtDecls;
_ddl_desc = new DDLDescription(new DDLHeader(DDLVersion::fromString(strVersion),
strAuthor, sDateCreation, sDateChange, strDescription, vecExtDecls),
DDLUnitVec(_sorted),
DDLBaseunitVec(_sorted),
DDLPrefixVec(_sorted),
DDLDTVec(_sorted),
DDLComplexVec(_sorted),
DDLStreamVec(_sorted),
DDLEnumVec(_sorted),
_merge_defaults);
return nResult;
}
a_util::xml::DOMElementList oExtDeclarations;
oHeaderElement.findNodes("ext_declaration", oExtDeclarations);
DDLExtDeclarationVec vecExtDecls;
for (tDOMElemIt it = oExtDeclarations.begin(); oExtDeclarations.end() != it; ++it)
{
a_util::result::Result nRes;
if (!it->hasAttribute("key"))
{
pushMessage(std::string("There is an external declaration without key in header."), importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
else
{
if (!it->hasAttribute("value"))
{
pushMessage(a_util::strings::format("The external declaration with key '%s' has no value.",
it->getAttribute("key").c_str()), importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
}
if (!it->hasAttribute("value"))
{
pushMessage(std::string("There is an external declaration without value in header."), importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
// do not create new DDLExtDeclaration, if any key property could not found (all properties are mandatory!)
continue;
}
vecExtDecls.push_back(new DDLExtDeclaration(it->getAttribute("key"),
it->getAttribute("value")));
}
_ddl_desc = new DDLDescription(new DDLHeader(DDLVersion::fromString(strVersion),
strAuthor, sDateCreation, sDateChange, strDescription, vecExtDecls),
DDLUnitVec(_sorted),
DDLBaseunitVec(_sorted),
DDLPrefixVec(_sorted),
DDLDTVec(_sorted),
DDLComplexVec(_sorted),
DDLStreamVec(_sorted),
DDLEnumVec(_sorted),
_merge_defaults);
if (isFailed(nResult))
{
return nResult;
}
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSingleBaseunit(DDLBaseunit ** ppoNewBU, const a_util::xml::DOMElement& oBUElement)
{
if (!ppoNewBU) { return ERR_POINTER; }
*ppoNewBU = NULL;
std::string name = oBUElement.getAttribute("name");
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!oBUElement.hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'baseunit' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
if (!oBUElement.hasAttribute("symbol"))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'baseunit' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'baseunit' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
if (!oBUElement.hasAttribute("description"))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'description' is missing in 'baseunit' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'description' is missing in 'baseunit' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
// do not create new DDLBaseunit, if any base unit property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
*ppoNewBU = new DDLBaseunit(oBUElement.getAttribute("name"), oBUElement.getAttribute("symbol"),
oBUElement.getAttribute("description"), _creation_level);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSinglePrefix(DDLPrefix ** ppoNewPrefix,
const a_util::xml::DOMElement& oPrefixElement)
{
if (!ppoNewPrefix) { return ERR_POINTER; }
*ppoNewPrefix = NULL;
std::string name = oPrefixElement.getAttribute("name");
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!oPrefixElement.hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'prefix' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
if (!oPrefixElement.hasAttribute("symbol"))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'prefix' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'prefix' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
if (!oPrefixElement.hasAttribute("power"))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'power' is missing in 'prefix' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'power' is missing in 'prefix' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
// do not create new DDLPrefix, if any prefix property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
*ppoNewPrefix = new DDLPrefix(oPrefixElement.getAttribute("name"),
oPrefixElement.getAttribute("symbol"), a_util::strings::toInt32(oPrefixElement.getAttribute("power")),
_creation_level);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSingleUnit(DDLUnit ** ppoNewUnit,
const a_util::xml::DOMElement& oUnitElement)
{
if (!ppoNewUnit) { return ERR_POINTER; }
*ppoNewUnit = NULL;
DDLBaseunitVec vecDDLBaseunits = _ddl_desc->getBaseunits();
DDLPrefixVec vecDDLPrefixes = _ddl_desc->getPrefixes();
DDLUnitVec vecDDLUnits = _ddl_desc->getUnits();
DDLBaseunitVec vecDDLBaseunitRefs;
DDLPrefixVec vecDDLPrefixeRefs;
DDLUnitVec vecDDLUnitRefs;
if (_current_ref_ddl != NULL)
{
vecDDLUnitRefs = _current_ref_ddl->getUnits();
vecDDLPrefixeRefs = _current_ref_ddl->getPrefixes();
vecDDLBaseunitRefs = _current_ref_ddl->getBaseunits();
}
a_util::result::Result nResult = a_util::result::SUCCESS;
std::string name = oUnitElement.getAttribute("name");
if (name.empty())
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'unit' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
a_util::xml::DOMElement oTmpElement;
std::string strNumerator = a_util::strings::empty_string;
if (!oUnitElement.findNode("numerator", oTmpElement))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'numerator' is missing in 'unit' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'numerator' is missing in 'unit' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
strNumerator = oTmpElement.getData();
}
std::string strDenominator = a_util::strings::empty_string;
if (!oUnitElement.findNode("denominator", oTmpElement))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'denominator' is missing in 'unit' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'denominator' is missing in 'unit' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
strDenominator = oTmpElement.getData();
}
double fOffset = 0.0F;
if (!oUnitElement.findNode("offset", oTmpElement))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'offset' is missing in 'unit' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'offset' is missing in 'unit' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
fOffset = static_cast<double> (a_util::strings::toDouble(oTmpElement.getData()));
}
a_util::xml::DOMElementList oRefUnits;
oUnitElement.findNodes("refUnit", oRefUnits);
DDLRefUnitVec vecDDLRefUnits;
a_util::result::Result nRes = a_util::result::SUCCESS;
for (tDOMElemIt itRU = oRefUnits.begin();
oRefUnits.end() != itRU; ++itRU)
{
std::string strRefUnitName = a_util::strings::empty_string;
if (itRU->hasAttribute("name"))
{
strRefUnitName = itRU->getAttribute("name");
}
nRes = a_util::result::SUCCESS;
if (!itRU->hasAttribute("name") ||
!itRU->hasAttribute("power") ||
!itRU->hasAttribute("prefix"))
{
std::transform(vecDDLRefUnits.begin(), vecDDLRefUnits.end(), vecDDLRefUnits.begin(), DDLDescription::deleteChild<DDLRefUnit>);
if (!itRU->hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'refUnit' tag."),
importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
if (!itRU->hasAttribute("power"))
{
if (!strRefUnitName.empty())
{
pushMessage(a_util::strings::format("Attribute 'power' is missing in 'refUnit' tag '%s'.",
strRefUnitName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'power' is missing in 'refUnit' tag."),
importer_error);
}
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
if (!itRU->hasAttribute("prefix"))
{
if (!strRefUnitName.empty())
{
pushMessage(a_util::strings::format("Attribute 'prefix' is missing in 'refUnit' tag '%s'.",
strRefUnitName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'prefix' is missing in 'refUnit' tag."),
importer_error);
}
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nRes;
}
// do not continue with this ref unit, if any property could not found (all properties are mandatory!)
continue;
}
}
DDLPrefix* pPrefix = tryToFind(itRU->getAttribute("prefix"), vecDDLPrefixeRefs, vecDDLPrefixes );
if (pPrefix == NULL)
{
// not found in prefixes vector => not defined
if (!name.empty() && !strRefUnitName.empty())
{
pushMessage(a_util::strings::format("RefUnit '%s' in unit '%s' references to unknown prefix '%s'",
strRefUnitName.c_str(), name.c_str(), itRU->getAttribute("prefix").c_str()), importer_error);
}
else if (!name.empty())
{
pushMessage(a_util::strings::format("RefUnit in unit '%s' references to unknown prefix '%s'",
name.c_str(), itRU->getAttribute("prefix").c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("RefUnit in unit references to unknown prefix '%s'",
itRU->getAttribute("prefix").c_str()), importer_error);
}
std::transform(vecDDLRefUnits.begin(), vecDDLRefUnits.end(), vecDDLRefUnits.begin(), DDLDescription::deleteChild<DDLRefUnit>);
nRes = ERR_NO_CLASS;
if (false == _full_check)
{
return nRes;
}
}
std::string strAttr = itRU->getAttribute("name");
DDLBaseunit* pBaseUnit = tryToFind(strAttr, vecDDLBaseunitRefs, vecDDLBaseunits);
if (pBaseUnit == NULL)
{
DDLUnit* pUnit = tryToFind(strAttr, vecDDLUnitRefs, vecDDLUnits);
if (pUnit == NULL)
{
pUnit = tryToFind(strAttr, _unknown_units, vecDDLUnits);
if (pUnit == NULL)
{
// => create placeholder object, mark Unit object
// as unknown, and continue
pUnit = new DDLUnit(strAttr, "1", "1", 0.0f);
_unknown_units.insert(pUnit);
vecDDLRefUnits.push_back(new DDLRefUnit(pUnit,
a_util::strings::toInt32(itRU->getAttribute("power")),
pPrefix));
}
else
{
// already marked as unknown
vecDDLRefUnits.push_back(new DDLRefUnit(pUnit,
a_util::strings::toInt32(itRU->getAttribute("power")),
pPrefix));
}
}
else
{
// known Unit
vecDDLRefUnits.push_back(new DDLRefUnit(pUnit,
a_util::strings::toInt32(itRU->getAttribute("power")),
pPrefix));
}
}
else
{
vecDDLRefUnits.push_back(new DDLRefUnit(pBaseUnit,
a_util::strings::toInt32(itRU->getAttribute("power")),
pPrefix));
}
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
}
}
// do not create new DDLUnit, if any unit property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
DDLUnitIt itUnknown = std::find_if(_unknown_units.begin(), _unknown_units.end(), DDLCompareFunctor<>(name));
if (_unknown_units.end() == itUnknown)
{
// create new object
*ppoNewUnit = new DDLUnit(name, strNumerator, strDenominator, fOffset, DDLRefUnitVec(), _creation_level);
}
else
{
// use placeholder object
(*itUnknown)->create(name, strNumerator, strDenominator, fOffset, DDLRefUnitVec(), _creation_level);
*ppoNewUnit = *itUnknown;
// unmark object
_unknown_units.erase(itUnknown);
}
(*ppoNewUnit)->setRefUnits(vecDDLRefUnits);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildUnits()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oUnits;
if (!_dom.findNode("//units", oUnits))
{
// as units are not supported in ADTF => no error
pushMessage(std::string("DDL does not contain the 'units' element."),
importer_warning);
return a_util::result::SUCCESS;
}
else
{
a_util::result::Result nResult = a_util::result::SUCCESS;
// build up base-unit objects
a_util::xml::DOMElementList oBaseunits;
if (!oUnits.findNodes("baseunit", oBaseunits))
{
// no error
}
else
{
DDLBaseunitVec vecDDLBaseunits(_sorted);
a_util::result::Result nRes = a_util::result::SUCCESS;
for (tDOMElemIt itBU = oBaseunits.begin();
oBaseunits.end() != itBU; ++itBU)
{
DDLBaseunit * poBUTmp = NULL;
nRes = buildSingleBaseunit(&poBUTmp, *itBU);
if (isFailed(nRes))
{
vecDDLBaseunits.deleteAll();
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (_basic_check && vecDDLBaseunits.find(poBUTmp->getName()))
{
pushMessage(a_util::strings::format("The baseunit '%s' is specified more than once.",
poBUTmp->getName().c_str()), importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
vecDDLBaseunits.insert(poBUTmp);
}
_ddl_desc->refBaseunits(vecDDLBaseunits);
}
// build up prefix objects
a_util::xml::DOMElementList oPrefixes;
if (!oUnits.findNodes("prefixes", oPrefixes))
{
// => no error
}
else
{
DDLPrefixVec vecDDLPrefixes(_sorted);
a_util::result::Result nRes = a_util::result::SUCCESS;
for (tDOMElemIt itP = oPrefixes.begin();
oPrefixes.end() != itP; ++itP)
{
DDLPrefix * poPrefixTmp = NULL;
nRes = buildSinglePrefix(&poPrefixTmp, *itP);
if (isFailed(nRes))
{
vecDDLPrefixes.deleteAll();
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (_basic_check && vecDDLPrefixes.find(poPrefixTmp->getName()))
{
pushMessage(a_util::strings::format("The prefix '%s' is specified more than once.",
poPrefixTmp->getName().c_str()), importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
vecDDLPrefixes.insert(poPrefixTmp);
}
_ddl_desc->refPrefixes(vecDDLPrefixes);
}
// build up unit objects
a_util::xml::DOMElementList oUnitList;
if (!oUnits.findNodes("unit", oUnitList))
{
// => no error
}
else
{
DDLUnitVec vecDDLUnits(_sorted);
a_util::result::Result nRes = a_util::result::SUCCESS;
_ddl_desc->cloneUnits(vecDDLUnits);
for (tDOMElemIt itU = oUnitList.begin(); oUnitList.end() != itU; ++itU)
{
DDLUnit * poUnitTmp = NULL;
nRes = buildSingleUnit(&poUnitTmp, *itU);
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (_basic_check && _ddl_desc->getUnitByName(poUnitTmp->getName()))
{
pushMessage(a_util::strings::format("The unit '%s' is specified more than once.",
poUnitTmp->getName().c_str()), importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
_ddl_desc->addUnit(poUnitTmp);
}
}
for (DDLUnitIt itUnknown = _unknown_units.begin();
_unknown_units.end() != itUnknown; ++itUnknown)
{
pushMessage(a_util::strings::format("The unit '%s' was referenced but not specified.",
(*itUnknown)->getName().c_str()), importer_error);
nResult = ERR_UNKNOWN;
if (false == _full_check)
{
return nResult;
}
}
if (!_unknown_units.empty())
{
std::stringstream logUnspecifiedStructs;
logUnspecifiedStructs<< "The following units are unknown in this description: ";
for (DDLUnitIt itUnknown = _unknown_units.begin();
_unknown_units.end() != itUnknown; ++itUnknown)
{
logUnspecifiedStructs << " " << (*itUnknown)->getName();
if (false == _full_check)
{
logUnspecifiedStructs << ".";
pushMessage(logUnspecifiedStructs.str(), importer_error);
nResult = ERR_UNKNOWN;
return nResult;
}
logUnspecifiedStructs << ",";
}
logUnspecifiedStructs.seekp(-1, logUnspecifiedStructs.cur);
logUnspecifiedStructs << ".";
pushMessage(logUnspecifiedStructs.str(), importer_error);
nResult = ERR_UNKNOWN;
}
if (isFailed(nResult))
{
return nResult;
}
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSingleDatatype(DDLDataType ** ppoNewDatatype, const a_util::xml::DOMElement& oDTElement)
{
if (!ppoNewDatatype) { return ERR_POINTER; }
*ppoNewDatatype = NULL;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!oDTElement.hasAttribute("size"))
{
pushMessage(a_util::strings::format("Attribute 'size' is missing in 'datatype' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
std::string name = a_util::strings::empty_string;
if (_ddl_desc->getHeader()->getLanguageVersion() <= DDLVersion::ddl_version_11)
{
if (!oDTElement.hasAttribute("type"))
{
if (oDTElement.hasAttribute("name"))
{
//NF: ADTF ist robust!!
name = oDTElement.getAttribute("name");
}
else
{
pushMessage(a_util::strings::format("Attribute 'type' is missing in 'datatype' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
}
else
{
name = oDTElement.getAttribute("type");
}
}
else
{
if (!oDTElement.hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'datatype' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
name = oDTElement.getAttribute("name");
}
}
std::string strDescription = a_util::strings::empty_string;
if (oDTElement.hasAttribute("description"))
{
strDescription = oDTElement.getAttribute("description");
}
unsigned int uiArraysize = 1;
if (oDTElement.hasAttribute("arraysize"))
{
uiArraysize = static_cast<unsigned int>
(a_util::strings::toUInt32(oDTElement.getAttribute("arraysize")));
}
DDLAlignment::AlignmentType eAlignment = DDLAlignment::e1;
if (oDTElement.hasAttribute("alignment"))
{
eAlignment = DDLAlignment::fromString(oDTElement.getAttribute("alignment"));
if (eAlignment == DDLAlignment::e_invalid)
{
pushMessage(a_util::strings::format("Attribute 'alignment' is out of range in 'datatype' tag '%s'.",
name.c_str()), importer_error);
nResult = ERR_INVALID_ARG;
if (false == _full_check)
{
return nResult;
}
}
}
if (oDTElement.hasAttribute("size"))
{
std::string s = oDTElement.getAttribute("size");
if (!a_util::strings::isInt32(s) || a_util::strings::toInt32(s) <= 0)
{
pushMessage(a_util::strings::format("Attribute 'size' is out of range in 'datatype' tag '%s'.",
name.c_str()), importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
}
std::string strMinVal;
bool bMinValid = false;
if (oDTElement.hasAttribute("min"))
{
strMinVal = oDTElement.getAttribute("min");
bMinValid = true;
}
std::string strMaxVal;
bool bMaxValid = false;
if (oDTElement.hasAttribute("max"))
{
strMaxVal = oDTElement.getAttribute("max");
bMaxValid = true;
}
IDDLUnit* pUnitRef = NULL;
if (oDTElement.hasAttribute("unit"))
{
DDLBaseunit* pBaseUnit = NULL;
DDLUnit* pUnit = NULL;
DDLBaseunitVec vecDDLBaseunits = _ddl_desc->getBaseunits();
DDLUnitVec vecDDLUnits = _ddl_desc->getUnits();
DDLUnitVec vecDDLUnitRefs;
DDLBaseunitVec vecDDLBaseunitRefs;
if (_current_ref_ddl)
{
vecDDLBaseunitRefs = _current_ref_ddl->getBaseunits();
vecDDLUnitRefs = _current_ref_ddl->getUnits();
}
std::string strAttr = oDTElement.getAttribute("unit");
pBaseUnit = tryToFind(strAttr, vecDDLBaseunitRefs, vecDDLBaseunits);
if (pBaseUnit == NULL)
{
pUnit = tryToFind(strAttr, vecDDLUnitRefs, vecDDLUnits);
if (pUnit == NULL)
{
pushMessage(a_util::strings::format("No 'unit' or 'refUnit' found with name='%s' defined in datatype '%s'.",
strAttr.c_str(), name.c_str()), importer_error);
nResult = ERR_NO_CLASS;
if (false == _full_check)
{
return nResult;
}
}
else
{
pUnitRef = (IDDLUnit*) pUnit;
}
}
else
{
pUnitRef = (IDDLUnit*) pBaseUnit;
}
}
*ppoNewDatatype = new DDLDataType(name,
static_cast<unsigned int>(a_util::strings::toUInt32(oDTElement.getAttribute("size"))),
pUnitRef,
strDescription,
eAlignment,
uiArraysize,
_creation_level,
a_util::strings::empty_string,
bMinValid,
strMinVal,
bMaxValid,
strMaxVal);
// Add version information for behavior differentiation
DDLVersion language_version = DDLVersion::getDefaultVersion();
DDLHeader* pHeader = _ddl_desc->getHeader();
if (NULL != pHeader)
{
language_version = pHeader->getLanguageVersion();
}
(*ppoNewDatatype)->setDDLVersion(language_version);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildDatatypes()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oDatatypesNode;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!_dom.findNode("//datatypes", oDatatypesNode))
{
pushMessage(std::string("DDL does not contain the 'datatypes' element"),
importer_error);
return ERR_NOT_FOUND;
}
a_util::xml::DOMElementList oDatatypes;
oDatatypesNode.findNodes("datatype", oDatatypes);
DDLDTVec vecDDLDataTypes(_sorted);
for (tDOMElemIt it = oDatatypes.begin(); oDatatypes.end() != it; ++it)
{
DDLDataType * poDTTmp = NULL;
a_util::result::Result nRes = buildSingleDatatype(&poDTTmp, *it);
if (isFailed(nRes))
{
vecDDLDataTypes.deleteAll();
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (_basic_check && vecDDLDataTypes.find(poDTTmp->getName()))
{
pushMessage(a_util::strings::format("The datatype '%s' is specified more than once.",
poDTTmp->getName().c_str()),
importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
vecDDLDataTypes.insert(poDTTmp);
}
_ddl_desc->refDatatypes(vecDDLDataTypes);
if (isFailed(nResult))
{
return nResult;
}
return a_util::result::SUCCESS;
}
static inline bool CheckAttrib(const a_util::xml::DOMAttributes oAttrs, const std::string& strAttrib, unsigned int& nRes)
{
a_util::xml::DOMAttributes::const_iterator itAttr = oAttrs.find(strAttrib);
if (itAttr != oAttrs.end())
{
nRes = a_util::strings::toUInt32(itAttr->second);
return true;
}
return false;
}
static inline bool CheckAttrib(const a_util::xml::DOMAttributes oAttrs, const std::string& strAttrib, std::string& strRes)
{
a_util::xml::DOMAttributes::const_iterator itAttr = oAttrs.find(strAttrib);
if (itAttr != oAttrs.end())
{
strRes = itAttr->second.c_str();
return true;
}
return false;
}
a_util::result::Result DDLImporter::buildSingleStruct(DDLComplex ** ppoNewStruct, const a_util::xml::DOMElement& oStructElement)
{
if (!ppoNewStruct) { return ERR_POINTER; }
*ppoNewStruct = NULL;
// get already defined types
DDLDTVec vecDTs = _ddl_desc->getDatatypes();
DDLComplexVec vecStructs = _ddl_desc->getStructs();
DDLEnumVec vecEnums = _ddl_desc->getEnums();
// get already defined types
DDLDTVec vecDTRefs;
DDLComplexVec vecStructRefs;
DDLEnumVec vecEnumRefs;
if (_current_ref_ddl)
{
vecDTRefs = _current_ref_ddl->getDatatypes();
vecStructRefs = _current_ref_ddl->getStructs();
vecEnumRefs = _current_ref_ddl->getEnums();
}
a_util::result::Result nResult = a_util::result::SUCCESS;
std::string strStructName = oStructElement.getAttribute("name");
if (!oStructElement.hasAttribute("name"))
{
strStructName = oStructElement.getAttribute("type");
if (!oStructElement.hasAttribute("type"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'struct' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
}
// mandatory property, but no error (compatibility to former DDL versions)
std::string strVersion = a_util::strings::empty_string;
if (!oStructElement.hasAttribute("version"))
{
// mandatory property, but no error (compatibility to former DDL versions)
}
else
{
strVersion = oStructElement.getAttribute("version");
}
std::string strComment = a_util::strings::empty_string;
if (oStructElement.hasAttribute("comment"))
{
strComment = oStructElement.getAttribute("comment");
}
DDLAlignment::AlignmentType eAlignment = DDLAlignment::e1;
if (oStructElement.hasAttribute("alignment"))
{
std::string strAttr = oStructElement.getAttribute("alignment");
eAlignment = DDLAlignment::fromString(strAttr);
if (eAlignment == DDLAlignment::e_invalid)
{
pushMessage(a_util::strings::format("The struct '%s' has an invalid alignment of '%s'", strStructName.c_str(), strAttr.c_str()),
importer_error);
nResult = ERR_INVALID_ARG;
if (false == _full_check)
{
return nResult;
}
}
}
a_util::xml::DOMElementList oElements;
oStructElement.findNodes("element", oElements);
DDLElementVec vecDDLElements;
for (tDOMElemIt itElem = oElements.begin();
oElements.end() != itElem;
++itElem)
{
std::string strElementName;
if (itElem->hasAttribute("name"))
{
strElementName = itElem->getAttribute("name");
}
if (_basic_check &&
std::find_if(vecDDLElements.begin(), vecDDLElements.end(),
DDLCompareFunctor<DDLElement>(strElementName)) != vecDDLElements.end())
{
pushMessage(a_util::strings::format("The struct element name '%s.%s' is already used", strStructName.c_str(), strElementName.c_str()),
importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
// check optional attributes
unsigned int uiBitpos = 0;
CheckAttrib(itElem->getAttributes(), "bitpos", uiBitpos);
unsigned int uiNumBits = 0;
CheckAttrib(itElem->getAttributes(), "numbits", uiNumBits);
a_util::result::Result nRes = a_util::result::SUCCESS;
bool bNoBytePosSet = !itElem->hasAttribute("bytepos");
std::string strBytePos = itElem->getAttribute("bytepos");
bool bNoByteOrderSet = !itElem->hasAttribute("byteorder");
std::string strByteOrder = itElem->getAttribute("byteorder");
bool bNoAlignmentSet = !itElem->hasAttribute("alignment");
std::string strAlignment = itElem->getAttribute("alignment");
a_util::xml::DOMElement oDeserialized;
if (itElem->findNode("deserialized", oDeserialized))
{
bNoAlignmentSet = !oDeserialized.hasAttribute("alignment");
strAlignment = oDeserialized.getAttribute("alignment");
}
a_util::xml::DOMElement oSerialized;
if (itElem->findNode("serialized", oSerialized))
{
bNoBytePosSet = !oSerialized.hasAttribute("bytepos");
strBytePos = oSerialized.getAttribute("bytepos");
bNoByteOrderSet = !oSerialized.hasAttribute("byteorder");
strByteOrder = oSerialized.getAttribute("byteorder");
CheckAttrib(oSerialized.getAttributes(), "bitpos", uiBitpos);
CheckAttrib(oSerialized.getAttributes(), "numbits", uiNumBits);
}
if (!itElem->hasAttribute("type") ||
!itElem->hasAttribute("name") ||
bNoBytePosSet ||
!itElem->hasAttribute("arraysize") ||
bNoByteOrderSet ||
bNoAlignmentSet)
{
std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild<DDLElement>);
if (!itElem->hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'struct' tag."),
importer_error);
}
if (!itElem->hasAttribute("type"))
{
if (!strElementName.empty())
{
pushMessage(a_util::strings::format("Attribute 'type' is missing in 'struct' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'type' is missing in 'struct' tag."),
importer_error);
}
}
if (bNoBytePosSet)
{
if (!strElementName.empty())
{
pushMessage(a_util::strings::format("Attribute 'bytepos' is missing in 'struct' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'bytepos' is missing in 'struct' tag."),
importer_error);
}
}
if (!itElem->hasAttribute("arraysize"))
{
if (!strElementName.empty())
{
pushMessage(a_util::strings::format("Attribute 'arraysize' is missing in 'struct' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'arraysize' is missing in 'struct' tag."),
importer_error);
}
}
if (bNoByteOrderSet)
{
if (!strElementName.empty())
{
pushMessage(a_util::strings::format("Attribute 'byteorder' is missing in 'struct' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'byteorder' is missing in 'struct' tag."),
importer_error);
}
}
if (bNoAlignmentSet)
{
if (!strElementName.empty())
{
pushMessage(a_util::strings::format("Attribute 'alignment' is missing in 'struct' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'alignment' is missing in 'struct' tag."),
importer_error);
}
}
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
if (itElem->getAttribute("type") == strStructName)
{
std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild<DDLElement>);
pushMessage(a_util::strings::format("Unresolvable recursion in struct '%s'.",
strStructName.c_str()), importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
// resolve type
// if the Importer is called with createPartial then the DDL will search for Referenced first
// after that it will reference to a local DDL Type or put it to the unresolved types
DDLDataType * poDataType = NULL;
DDLComplex * poComplex = NULL;
DDLEnum* poEnum = NULL;
std::string strTypeAttr = itElem->getAttribute("type");
poDataType = tryToFind(strTypeAttr, vecDTRefs, vecDTs);
if (poDataType == NULL)
{
poComplex = tryToFind(strTypeAttr, vecStructRefs, vecStructs);
if (poComplex == NULL)
{
poComplex = tryToFind(strTypeAttr, _unknown_structs, vecStructs);
if (poComplex == NULL)
{
poEnum = tryToFind(strTypeAttr, vecEnumRefs, vecEnums);
if(poEnum == NULL)
{
// => create object, mark it, and continue
poComplex = new DDLComplex(strTypeAttr, 1);
_unknown_structs.insert(poComplex);
}
}
}
}
if (_basic_check && itElem->hasAttribute("arraysize"))
{
if (uiNumBits > 0 && a_util::strings::toInt32(itElem->getAttribute("arraysize")) > 1)
{
pushMessage(a_util::strings::format("Attribute 'numbits' is not allowed in array elements."),
importer_error);
return ERR_INVALID_ARG;
}
}
std::string strDescription;
CheckAttrib(itElem->getAttributes(), "description", strDescription);
std::string strComment;
CheckAttrib(itElem->getAttributes(), "comment", strComment);
// value is used in combination with enums to implement constants
std::string strConstantValue;
CheckAttrib(itElem->getAttributes(), "value", strConstantValue);
std::string strMinValue;
bool bMinValid = CheckAttrib(itElem->getAttributes(), "min", strMinValue);
std::string strMaxValue;
bool bMaxValid = CheckAttrib(itElem->getAttributes(), "max", strMaxValue);
std::string strDefaultValue;
bool bDefaultValid = CheckAttrib(itElem->getAttributes(), "default", strDefaultValue);
std::string strScaleValue;
bool bScaleValid = CheckAttrib(itElem->getAttributes(), "scale", strScaleValue);
std::string strOffsetValue;
bool bOffsetValid = CheckAttrib(itElem->getAttributes(), "offset", strOffsetValue);
// resolve unit
// if the Importer is called with createPartial then the DDL will search for Referenced first
// after that it will reference to a local DDL Type or put it to the unresolved types
DDLUnit* poUnit = NULL;
DDLBaseunit* poBaseUnit = NULL;
IDDLUnit* pUnitRef = NULL;
if (itElem->hasAttribute("unit"))
{
DDLUnitVec vecDDLUnits = _ddl_desc->getUnits();
DDLUnitVec vecDDLUnitRefs;
if (_current_ref_ddl != NULL)
{
vecDDLUnitRefs = _current_ref_ddl->getUnits();
}
DDLBaseunitVec vecDDLBaseUnits = _ddl_desc->getBaseunits();
DDLBaseunitVec vecDDLBaseUnitRefs;
if (_current_ref_ddl != NULL)
{
vecDDLBaseUnitRefs = _current_ref_ddl->getBaseunits();
}
std::string strUnitAttr = itElem->getAttribute("unit");
poUnit = tryToFind(strUnitAttr, vecDDLUnitRefs, vecDDLUnits);
if (poUnit == NULL)
{
poBaseUnit = tryToFind(strUnitAttr, vecDDLBaseUnitRefs, vecDDLBaseUnits);
if (poBaseUnit != NULL)
{
pUnitRef = (IDDLUnit*) poBaseUnit;
}
}
else
{
pUnitRef = (IDDLUnit*) poUnit;
}
if (pUnitRef == NULL)
{
std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild<DDLElement>);
pushMessage(a_util::strings::format("Missing class '%s' for unit in element '%s' in struct '%s'.",
strUnitAttr.c_str(), strElementName.c_str(), strStructName.c_str()), importer_error);
nRes = ERR_NO_CLASS;
if (false == _full_check)
{
return nRes;
}
}
}
// do not continue with struct, if any mandatory property could not found
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (DDLAlignment::fromString(strAlignment) == DDLAlignment::e_invalid)
{
pushMessage(a_util::strings::format("The struct element '%s.%s' has an invalid alignment of '%s'", strStructName.c_str(), strElementName.c_str(), strAlignment.c_str()),
importer_error);
nResult = ERR_INVALID_ARG;
if (false == _full_check)
{
return nResult;
}
}
const std::string& strArraySize = itElem->getAttribute("arraysize");
if (NULL == poDataType)
{
if (poEnum != NULL)
{
bool bIsDynamic = !a_util::strings::isUInt32(strArraySize);
vecDDLElements.push_back(new DDLElement(poEnum,
strElementName,
static_cast<unsigned int>(a_util::strings::toUInt32(strBytePos)),
bIsDynamic ? 0 : static_cast<unsigned int>(a_util::strings::toUInt32(strArraySize)),
DDLByteorder::fromString(strByteOrder),
DDLAlignment::fromString(strAlignment),
pUnitRef,
uiBitpos,
uiNumBits,
strDescription,
strComment,
bIsDynamic ? strArraySize: a_util::strings::empty_string,
strConstantValue));
}
else
{
bool bIsDynamic = !a_util::strings::isUInt32(strArraySize);
vecDDLElements.push_back(new DDLElement(poComplex,
strElementName,
static_cast<unsigned int>(a_util::strings::toUInt32(strBytePos)),
bIsDynamic ? 0 : static_cast<unsigned int>(a_util::strings::toUInt32(strArraySize)),
DDLByteorder::fromString(strByteOrder),
DDLAlignment::fromString(strAlignment),
pUnitRef,
uiBitpos,
uiNumBits,
strDescription,
strComment,
bIsDynamic ? strArraySize : a_util::strings::empty_string));
}
}
else
{
bool bIsDynamic = !a_util::strings::isUInt32(strArraySize);
vecDDLElements.push_back(new DDLElement(poDataType,
strElementName,
static_cast<unsigned int>(a_util::strings::toUInt32(strBytePos)),
bIsDynamic ? 0 : static_cast<unsigned int>(a_util::strings::toUInt32(strArraySize)),
DDLByteorder::fromString(strByteOrder),
DDLAlignment::fromString(strAlignment),
pUnitRef,
uiBitpos,
uiNumBits,
strDescription,
strComment,
bIsDynamic ? strArraySize : a_util::strings::empty_string,
a_util::strings::empty_string,
bMinValid,
strMinValue,
bMaxValid,
strMaxValue,
bDefaultValid,
strDefaultValue,
bScaleValid,
strScaleValue,
bOffsetValid,
strOffsetValue));
}
}
// do not create new DDLComplex, if any mandatory property could not found
if (isFailed(nResult))
{
return nResult;
}
DDLComplexIt itUnknown = std::find_if(_unknown_structs.begin(), _unknown_structs.end(), DDLCompareFunctor<>(oStructElement.getAttribute("name")));
if (_unknown_structs.end() == itUnknown)
{
// create new object
*ppoNewStruct = new DDLComplex(strStructName,
static_cast<unsigned int>(a_util::strings::toUInt32(strVersion)),
strComment,
eAlignment,
DDLElementVec(),
_creation_level);
}
else
{
// use placeholder object and fill it with concrete data
(*itUnknown)->create(strStructName,
static_cast<unsigned int>(a_util::strings::toUInt32(strVersion)),
strComment,
eAlignment,
DDLElementVec(),
_creation_level);
*ppoNewStruct = *itUnknown;
// unmark object
_unknown_structs.erase(itUnknown);
}
if (oStructElement.hasAttribute("ddlversion"))
{
auto version = DDLVersion::fromString(oStructElement.getAttribute("ddlversion"));
(*ppoNewStruct)->setDDLVersion(version);
}
else
{
// Add version information for behavior differentiation
DDLVersion language_version = DDLVersion::getDefaultVersion();
DDLHeader* pHeader = _ddl_desc->getHeader();
if (NULL != pHeader)
{
language_version = pHeader->getLanguageVersion();
}
(*ppoNewStruct)->setDDLVersion(language_version);
}
(*ppoNewStruct)->setElements(vecDDLElements);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildStructs()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oStructs;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!_dom.findNode("//structs", oStructs))
{
pushMessage(std::string("DDL does not contain the 'structs' element"),
importer_error);
return ERR_NOT_FOUND;
}
else
{
// build up struct objects
a_util::xml::DOMElementList oStructList;
if (!oStructs.findNodes("struct", oStructList))
{
// => no error
}
else
{
DDLComplexVec vecStructs(_sorted);
_ddl_desc->cloneStructs(vecStructs);
for (tDOMElemIt it = oStructList.begin(); oStructList.end() != it; ++it)
{
DDLComplex * poStructTmp = NULL;
a_util::result::Result nRes = buildSingleStruct(&poStructTmp, *it);
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
if (_basic_check && vecStructs.find(poStructTmp->getName()))
{
pushMessage(a_util::strings::format("The struct '%s' is specified more than once.",
poStructTmp->getName().c_str()),
importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
_ddl_desc->addStruct(poStructTmp);
}
for (DDLComplexIt itUnknown = _unknown_structs.begin();
_unknown_structs.end() != itUnknown; ++itUnknown)
{
pushMessage(a_util::strings::format("The struct '%s' was referenced but not defined.",
(*itUnknown)->getName().c_str()), importer_error);
}
if (!_unknown_structs.empty())
{
vecStructs.deleteAll();
// unmark object
pushMessage(std::string("There are undefined types/structs in this description."),
importer_error);
nResult = ERR_UNKNOWN;
if (false == _full_check)
{
return nResult;
}
}
}
if (isFailed(nResult))
{
return nResult;
}
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSingleStream(DDLStream ** ppoNewStream, a_util::xml::DOMElement oStreamElement)
{
if (!ppoNewStream) { return ERR_POINTER; }
*ppoNewStream = NULL;
std::string name = a_util::strings::empty_string;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!oStreamElement.hasAttribute("name"))
{
if (!oStreamElement.hasAttribute("type"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'stream' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
// compatibility with old versions
oStreamElement.setAttribute("name", oStreamElement.getAttribute("type"));
name = oStreamElement.getAttribute("type");
}
}
else
{
name = oStreamElement.getAttribute("name");
}
// resolve type
DDLComplexVec vecStructs = _ddl_desc->getStructs();
DDLComplexVec vecStructRefs;
if (_current_ref_ddl)
{
vecStructRefs = _current_ref_ddl->getStructs();
}
DDLComplex* pTypeFound = tryToFind(oStreamElement.getAttribute("type"), vecStructRefs , vecStructs);
if (pTypeFound == NULL)
{
if (!name.empty())
{
pushMessage(a_util::strings::format("The type '%s' of the stream '%s' is not defined.",
oStreamElement.getAttribute("type").c_str(), name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("The type '%s' of an unnamed stream is not defined.",
oStreamElement.getAttribute("type").c_str()), importer_error);
}
nResult = ERR_NO_CLASS;
if (false == _full_check)
{
return nResult;
}
}
// check optional attribute
std::string strDescription = a_util::strings::empty_string;
if (oStreamElement.hasAttribute("description"))
{
strDescription = oStreamElement.getAttribute("description");
}
a_util::xml::DOMElementList oStructs;
oStreamElement.findNodes("struct", oStructs);
DDLStreamStructVec vecDDLStreamStructs;
for (tDOMElemIt itStruct = oStructs.begin();
oStructs.end() != itStruct; ++itStruct)
{
std::string strElementName = itStruct->getAttribute("name");
a_util::result::Result nRes = a_util::result::SUCCESS;
if (!itStruct->hasAttribute("type") ||
!itStruct->hasAttribute("bytepos"))
{
std::transform(vecDDLStreamStructs.begin(), vecDDLStreamStructs.end(), vecDDLStreamStructs.begin(), DDLDescription::deleteChild<DDLStreamStruct>);
if (!strElementName.empty() && !name.empty())
{
pushMessage(a_util::strings::format("The struct '%s' in stream '%s' is missing required attributes (type/bytepos).",
strElementName.c_str(), name.c_str()), importer_error);
}
else if (!name.empty())
{
pushMessage(a_util::strings::format("An unnamed struct in stream '%s' is missing required attributes (type/bytepos).",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("An unnamed struct in an unnamed stream is missing required attributes (type/bytepos)."),
importer_error);
}
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
// resolve type
DDLComplex* pStreamStructType = tryToFind(itStruct->getAttribute("type"), vecStructRefs , vecStructs);
if (pStreamStructType == NULL)
{
std::transform(vecDDLStreamStructs.begin(), vecDDLStreamStructs.end(), vecDDLStreamStructs.begin(), DDLDescription::deleteChild<DDLStreamStruct>);
pushMessage(a_util::strings::format("The type '%s' of a struct of stream '%s' is not defined.",
itStruct->getAttribute("type").c_str(), name.c_str()), importer_error);
nRes = ERR_NO_CLASS;
if (false == _full_check)
{
return nRes;
}
}
// check optional attribute
std::string strStructName = pStreamStructType->getName();
if (itStruct->hasAttribute("name"))
{
strStructName = itStruct->getAttribute("name");
}
// do not continue with stream struct, if any mandatory property could not found
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
vecDDLStreamStructs.push_back(new DDLStreamStruct(pStreamStructType,
static_cast<unsigned int>(a_util::strings::toUInt32(itStruct->getAttribute("bytepos"))),
strStructName));
}
// do not create new DDLStream, if any mandatory property could not found
if (isFailed(nResult))
{
return nResult;
}
*ppoNewStream = new DDLStream(pTypeFound,
name,
strDescription,
DDLStreamStructVec(),
_creation_level);
// Add version information for behavior differentiation
DDLVersion language_version = DDLVersion::ddl_version_invalid;
DDLHeader* pHeader = _ddl_desc->getHeader();
if (NULL != pHeader)
{
language_version = pHeader->getLanguageVersion();
}
(*ppoNewStream)->setDDLVersion(language_version);
(*ppoNewStream)->refStructs(vecDDLStreamStructs);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildStreams()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oStreams;
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!_dom.findNode("//streams", oStreams))
{
pushMessage(std::string("DDL does not contain the 'streams' element"),
importer_error);
return nResult;
}
else
{
a_util::xml::DOMElementList oStreamList;
DDLStreamVec vecStreams(_sorted);
if (!oStreams.findNodes("stream", oStreamList))
{
// => no error
}
else
{
for (tDOMElemIt it = oStreamList.begin(); oStreamList.end() != it; ++it)
{
DDLStream * poStreamTmp = NULL;
a_util::result::Result nRes = buildSingleStream(&poStreamTmp, *it);
if (isFailed(nRes))
{
vecStreams.deleteAll();
nResult = nRes;
if (isFailed(nResult))
{
return nResult;
}
continue;
}
if (_basic_check && vecStreams.find(poStreamTmp->getName()))
{
pushMessage(a_util::strings::format("The stream '%s' is specified more than once.",
poStreamTmp->getName().c_str()),
importer_error);
nResult = ERR_RESOURCE_IN_USE;
if (false == _full_check)
{
return nResult;
}
}
vecStreams.insert(poStreamTmp);
}
// make all elements of stream vector unique
_ddl_desc->refStreams(vecStreams);
}
if (isFailed(nResult))
{
return nResult;
}
}
return a_util::result::SUCCESS;
}
void DDLImporter::pushMessage(const std::string& strMsg, ImporterMsgSeverity severity)
{
ImporterMsg sError = {strMsg, severity};
_errors.push_back(sError);
}
template<typename T>
T* DDLImporter::tryToFind(const std::string& name,
DDLContainer<T>& first_data,
DDLContainer<T>& second_data)
{
T* pRes = NULL;
if (_prefere_reference)
{
pRes = first_data.find(name);
if (!pRes)
{
pRes = second_data.find(name);
}
}
else
{
pRes = second_data.find(name);
if (!pRes)
{
pRes = first_data.find(name);
}
}
return pRes;
}
a_util::result::Result DDLImporter::buildEnums()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oEnums;
if (!_dom.findNode("//enums", oEnums))
{
//kompatibilit<69>t zu alten files!!
if (_ddl_desc->getHeader()->getLanguageVersion() < DDLVersion::ddl_version_20)
{
return a_util::result::SUCCESS;
}
else
{
pushMessage(std::string("DDL does not contain the 'enums' element."),
importer_warning);
}
return a_util::result::SUCCESS;
}
else
{
a_util::result::Result nResult = a_util::result::SUCCESS;
// build up enum objects
a_util::xml::DOMElementList oEnumList;
if (!oEnums.findNodes("enum", oEnumList))
{
// => no error
}
else
{
DDLEnumVec vecDDLEnums(_sorted);
for (tDOMElemIt it = oEnumList.begin(); oEnumList.end() != it; ++it)
{
DDLEnum * poEnumTmp = NULL;
a_util::result::Result nRes = buildSingleEnum(&poEnumTmp, *it);
if (isFailed(nRes))
{
vecDDLEnums.deleteAll();
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
vecDDLEnums.insert(poEnumTmp);
}
_ddl_desc->refEnums(vecDDLEnums);
}
if (isFailed(nResult))
{
return nResult;
}
}
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildSingleEnum( DDLEnum** ppoNewEnum, const a_util::xml::DOMElement& oEnumElement )
{
if (!ppoNewEnum) { return ERR_POINTER; }
*ppoNewEnum = NULL;
std::string name = oEnumElement.getAttribute("name");
a_util::result::Result nResult = a_util::result::SUCCESS;
if (!oEnumElement.hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'enum' tag."),
importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
std::string strType;
if (!oEnumElement.hasAttribute("type"))
{
if (!name.empty())
{
pushMessage(a_util::strings::format("Attribute 'type' is missing in 'constant' tag '%s'.",
name.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("Attribute 'type' is missing in 'constant' tag."),
importer_error);
}
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
else
{
strType = oEnumElement.getAttribute("type");
}
// do not continue with enum, if any enum property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
EnumNameValueVec vecNameValues;
a_util::xml::DOMElementList oEnumElements;
oEnumElement.findNodes("element", oEnumElements);
a_util::result::Result nRes = a_util::result::SUCCESS;
for (a_util::xml::DOMElementList::iterator itEnumElement = oEnumElements.begin();
itEnumElement != oEnumElements.end();
++itEnumElement)
{
nRes = a_util::result::SUCCESS;
std::string strElementName;
if(!itEnumElement->hasAttribute("name"))
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'enum/element' tag."),
importer_error);
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
else
{
strElementName = itEnumElement->getAttribute("name");
}
std::string strElementValue;
if(!itEnumElement->hasAttribute("value"))
{
if (!name.empty() && !strElementName.empty())
{
pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag '%s/%s'.",
name.c_str(), strElementName.c_str()), importer_error);
}
else if (!strElementName.empty())
{
pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag '%s'.",
strElementName.c_str()), importer_error);
}
else
{
pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag."),
importer_error);
}
nRes = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nRes;
}
}
else
{
strElementValue = itEnumElement->getAttribute("value");
}
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
return nResult;
}
continue;
}
vecNameValues.push_back(std::make_pair<std::string, std::string>(std::string(strElementName), std::string(strElementValue)));
}
// do not continue with enum, if any enum element property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
// get already defined types
DDLDTVec vecDTs = _ddl_desc->getDatatypes();
// get already defined types
DDLDTVec vecDTRefs;
if (_current_ref_ddl)
{
vecDTRefs = _current_ref_ddl->getDatatypes();
}
DDLDataType * poDataType = NULL;
poDataType = tryToFind(strType, vecDTRefs, vecDTs);
if (poDataType == NULL)
{
pushMessage(a_util::strings::format("Data type '%s' could not be resolved.",
strType.c_str()), importer_error);
nResult = ERR_UNKNOWN_FORMAT;
if (false == _full_check)
{
return nResult;
}
}
// do not create new DDLEnum, if any enum property could not found (all properties are mandatory!)
if (isFailed(nResult))
{
return nResult;
}
*ppoNewEnum = new DDLEnum(poDataType, name, vecNameValues, NULL, _creation_level);
return a_util::result::SUCCESS;
}
a_util::result::Result DDLImporter::buildStreamMetaTypes()
{
if (!_init_flag)
{
return ERR_NOT_INITIALIZED;
}
a_util::xml::DOMElement oTypes;
if (!_dom.findNode("//streammetatypes", oTypes))
{
return a_util::result::SUCCESS;
}
a_util::result::Result nResult = a_util::result::SUCCESS;
// build up stream meta type objects
a_util::xml::DOMElementList oTypeList;
if (oTypes.findNodes("streammetatype", oTypeList))
{
DDLStreamMetaTypeVec vecDDLStreamMetaTypes(_sorted);
for (a_util::xml::DOMElementList::iterator it = oTypeList.begin(); it != oTypeList.end(); ++it)
{
a_util::result::Result nRes = buildSingleStreamMetaType(*it, vecDDLStreamMetaTypes);
if (isFailed(nRes))
{
nResult = nRes;
if (false == _full_check)
{
vecDDLStreamMetaTypes.deleteAll();
return nRes;
}
continue;
}
}
for (DDLStreamMetaTypeVec::iterator it = _unknown_stream_meta_types.begin(); it != _unknown_stream_meta_types.end(); ++it)
{
pushMessage(a_util::strings::format("The struct '%s' was referenced but not defined.",
(*it)->getName().c_str()), importer_error);
}
if (!_unknown_stream_meta_types.empty())
{
vecDDLStreamMetaTypes.deleteAll();
// unmark object
pushMessage(std::string("There are undefined streammetatypes in this description."),
importer_error);
nResult = ERR_UNKNOWN;
if (false == _full_check)
{
return nResult;
}
}
_ddl_desc->refStreamMetaTypes(vecDDLStreamMetaTypes);
}
return nResult;
}
a_util::result::Result DDLImporter::buildSingleStreamMetaType(const a_util::xml::DOMElement& oStreamMetaTypeElement,
DDLStreamMetaTypeVec& vecStreamMetaTypes)
{
const a_util::xml::DOMAttributes oAttributes = oStreamMetaTypeElement.getAttributes();
a_util::xml::DOMAttributes::const_iterator itName = oAttributes.find("name");
a_util::xml::DOMAttributes::const_iterator itVersion = oAttributes.find("version");
a_util::xml::DOMAttributes::const_iterator itParent = oAttributes.find("parent");
if (itName == oAttributes.end())
{
pushMessage(a_util::strings::format("Attribute 'name' is missing in 'streammetatype' tag."),
importer_error);
return ERR_UNKNOWN_FORMAT;
}
if (itVersion == oAttributes.end())
{
pushMessage(a_util::strings::format("Attribute 'version' is missing in 'streammetatype' tag."),
importer_error);
return ERR_UNKNOWN_FORMAT;
}
a_util::result::Result nResult = a_util::result::SUCCESS;
DDLStreamMetaType* pParent = NULL;
if (itParent != oAttributes.end() && !itParent->second.empty())
{
if (_current_ref_ddl)
{
pParent = const_cast<DDLStreamMetaType*>(_current_ref_ddl->getStreamMetaTypeByName(itParent->second));
}
if (!pParent)
{
pParent = tryToFind(itParent->second, _unknown_stream_meta_types, vecStreamMetaTypes);
if (!pParent)
{
pParent = new DDLStreamMetaType(itParent->second, "1");
_unknown_stream_meta_types.insert(pParent);
}
}
}
DDLPropertyVec oProps;
a_util::xml::DOMElementList oPropertyNodes;
if (oStreamMetaTypeElement.findNodes("property", oPropertyNodes))
{
for (a_util::xml::DOMElementList::const_iterator it = oPropertyNodes.begin();
it != oPropertyNodes.end(); ++it)
{
a_util::xml::DOMAttributes attrs = it->getAttributes();
a_util::xml::DOMAttributes::const_iterator itName = attrs.find("name");
a_util::xml::DOMAttributes::const_iterator itType = attrs.find("type");
if (itName != attrs.end() && itType != attrs.end())
{
oProps.push_back(new DDLProperty(itName->second,
itType->second));
}
}
}
a_util::memory::unique_ptr<DDLStreamMetaType> pStreamMetaType(new DDLStreamMetaType(itName->second, itVersion->second,
oProps, pParent));
DDLStreamMetaTypeVec::iterator itUnknown = std::find_if(_unknown_stream_meta_types.begin(),
_unknown_stream_meta_types.end(),
DDLCompareFunctor<>(itName->second));
if (itUnknown != _unknown_stream_meta_types.end())
{
*(*itUnknown) = *pStreamMetaType.get();
vecStreamMetaTypes.insert(*itUnknown);
_unknown_stream_meta_types.erase(itUnknown);
}
else
{
vecStreamMetaTypes.insert(pStreamMetaType.release());
}
return nResult;
}
} // namespace ddl