From ac418f8bbbd8029645b585c601189f6bd8abd83e Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Fri, 25 Oct 2024 23:31:53 +0200 Subject: [PATCH] feat(util): Add UA_AttributeOperand_print --- include/open62541/util.h | 13 ++++++++---- src/util/ua_util.c | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/open62541/util.h b/include/open62541/util.h index 696b2cb8a83..1a74814c567 100644 --- a/include/open62541/util.h +++ b/include/open62541/util.h @@ -312,8 +312,8 @@ UA_RelativePath_print(const UA_RelativePath *rp, UA_String *out); /** * .. _parse-sao: * - * Print and Parse SimpleAttributeOperand Expression - * ------------------------------------------------- + * Print and Parse AttributeId and SimpleAttributeOperand Expression + * ----------------------------------------------------------------- * The SimpleAttributeOperand is used to specify the location of up values. * SimpleAttributeOperands are used for example in EventFilters to select the * values reported for each event instance. @@ -336,6 +336,9 @@ UA_RelativePath_print(const UA_RelativePath *rp, UA_String *out); * For the index range, see the section on :ref:`numericrange`. * The BNF definition of the SimpleAttributeOperand is as follows:: * + * AttributeOperand := + * NodeIdId? RelativePath? ("#" Attribute)? ("[" IndexRange "]")? + * * SimpleAttributeOperand := * TypeDefinitionId? SimpleBrowsePath ("#" Attribute)? ("[" IndexRange "]")? * @@ -352,8 +355,7 @@ UA_RelativePath_print(const UA_RelativePath *rp, UA_String *out); #ifdef UA_ENABLE_PARSING UA_EXPORT UA_StatusCode -UA_AttributeOperand_parse(UA_AttributeOperand *ao, - const UA_String str); +UA_AttributeOperand_parse(UA_AttributeOperand *ao, const UA_String str); UA_EXPORT UA_StatusCode UA_SimpleAttributeOperand_parse(UA_SimpleAttributeOperand *sao, @@ -361,6 +363,9 @@ UA_SimpleAttributeOperand_parse(UA_SimpleAttributeOperand *sao, /* The out-string can be pre-allocated. Then the size is adjusted or an error * returned. If the out-string is NULL, then memory is allocated for it. */ +UA_EXPORT UA_StatusCode +UA_AttributeOperand_print(const UA_AttributeOperand *ao, UA_String *out); + UA_EXPORT UA_StatusCode UA_SimpleAttributeOperand_print(const UA_SimpleAttributeOperand *sao, UA_String *out); diff --git a/src/util/ua_util.c b/src/util/ua_util.c index e75b261f736..0ddfd73538b 100644 --- a/src/util/ua_util.c +++ b/src/util/ua_util.c @@ -891,6 +891,50 @@ UA_SimpleAttributeOperand_print(const UA_SimpleAttributeOperand *sao, return moveTmpToOut(&tmp, out); } +UA_StatusCode +UA_AttributeOperand_print(const UA_AttributeOperand *ao, + UA_String *out) { + UA_String tmp = UA_STRING_NULL; + UA_StatusCode res = UA_STATUSCODE_GOOD; + + /* Print the TypeDefinitionId */ + if(!UA_NodeId_equal(&hierarchicalRefs, &ao->nodeId)) { + UA_Byte nodeIdBuf[512]; + UA_String nodeIdBufStr = {512, nodeIdBuf}; + res |= UA_NodeId_print(&ao->nodeId, &nodeIdBufStr); + res |= UA_String_escapeAppend(&tmp, nodeIdBufStr, true); + } + + /* Print the BrowsePath */ + UA_String rpstr = UA_STRING_NULL; + res |= UA_RelativePath_print(&ao->browsePath, &rpstr); + res |= UA_String_escapeAppend(&tmp, rpstr, true); + UA_String_clear(&rpstr); + + /* Print the attribute name */ + if(ao->attributeId != UA_ATTRIBUTEID_VALUE) { + const char *attrName= UA_AttributeId_name((UA_AttributeId)ao->attributeId); + res |= UA_String_append(&tmp, UA_STRING("#")); + res |= UA_String_append(&tmp, UA_STRING((char*)(uintptr_t)attrName)); + } + + /* Print the IndexRange + * TODO: Validate the indexRange string */ + if(ao->indexRange.length > 0) { + res |= UA_String_append(&tmp, UA_STRING("[")); + res |= UA_String_append(&tmp, ao->indexRange); + res |= UA_String_append(&tmp, UA_STRING("]")); + } + + /* Encoding failed, clean up */ + if(res != UA_STATUSCODE_GOOD) { + UA_String_clear(&tmp); + return res; + } + + return moveTmpToOut(&tmp, out); +} + #endif /************************/