Skip to content

Commit

Permalink
feat(util): Allow NodeIds for the ReferenceTypes in RelativePath parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfr committed Dec 19, 2023
1 parent d900f56 commit d01f197
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 2 deletions.
6 changes: 6 additions & 0 deletions include/open62541/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ UA_readNumberWithBase(const UA_Byte *buf, size_t buflen,
* - ``<#Aggregates>1:Boiler/``
* - ``<!HasChild>Truck``
* - ``<HasChild>``
*
* Extension: ReferenceTypeNodeIds
* ```````````````````````````````
*
* As a non-standard extension we allow the ReferenceType in angle-brackets to
* be defined as a NodeId. For example ``/1:Boiler<ns=1;i=345>1:HeatSensor``.
*/
#ifdef UA_ENABLE_PARSING
UA_EXPORT UA_StatusCode
Expand Down
11 changes: 10 additions & 1 deletion src/util/ua_types_lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ parse_relativepath(UA_Server *server, UA_RelativePath *rp, const UA_String str)
YYSTAGP(finish);
YYSHIFTSTAG(finish, -1);
{

// Process modifier characters
for(; begin < finish; begin++) {
if(*begin== '#')
current.includeSubtypes = false;
Expand All @@ -803,8 +805,15 @@ parse_relativepath(UA_Server *server, UA_RelativePath *rp, const UA_String str)
else
break;
}

// Try to parse a NodeId for the ReferenceType (non-standard!)
res = parse_nodeid(&current.referenceTypeId, begin, finish);
if(res == UA_STATUSCODE_GOOD)
goto reftype_target;

// Parse the the ReferenceType from its BrowseName
UA_QualifiedName refqn;
res |= parse_refpath_qn(&refqn, begin, finish);
res = parse_refpath_qn(&refqn, begin, finish);
res |= lookupRefType(server, &refqn, &current.referenceTypeId);
UA_QualifiedName_clear(&refqn);
goto reftype_target;
Expand Down
11 changes: 10 additions & 1 deletion src/util/ua_types_lex.re
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,8 @@ parse_relativepath(UA_Server *server, UA_RelativePath *rp, const UA_String str)
// ReferenceType BrowseName with modifiers
"<" @begin ([^\000>] | "&>")+ @finish ">" {
// Process modifier characters
for(; begin < finish; begin++) {
if(*begin== '#')
current.includeSubtypes = false;
Expand All @@ -345,8 +347,15 @@ parse_relativepath(UA_Server *server, UA_RelativePath *rp, const UA_String str)
else
break;
}
// Try to parse a NodeId for the ReferenceType (non-standard!)
res = parse_nodeid(&current.referenceTypeId, begin, finish);
if(res == UA_STATUSCODE_GOOD)
goto reftype_target;
// Parse the the ReferenceType from its BrowseName
UA_QualifiedName refqn;
res |= parse_refpath_qn(&refqn, begin, finish);
res = parse_refpath_qn(&refqn, begin, finish);
res |= lookupRefType(server, &refqn, &current.referenceTypeId);
UA_QualifiedName_clear(&refqn);
goto reftype_target;
Expand Down
7 changes: 7 additions & 0 deletions tests/check_types_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ START_TEST(parseRelativePath) {
ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(rp.elementsSize, 1);
UA_RelativePath_clear(&rp);

UA_NodeId testRef = UA_NODEID_NUMERIC(1, 345);
res = UA_RelativePath_parse(&rp, UA_STRING("/1:Boiler<ns=1;i=345>1:HeatSensor"));
ck_assert_int_eq(res, UA_STATUSCODE_GOOD);
ck_assert_uint_eq(rp.elementsSize, 2);
ck_assert(UA_NodeId_equal(&rp.elements[1].referenceTypeId, &testRef));
UA_RelativePath_clear(&rp);
} END_TEST

START_TEST(parseRelativePathWithServer) {
Expand Down

0 comments on commit d01f197

Please sign in to comment.