|
@@ -448,6 +448,7 @@ Array_encodeBinaryComplex(uintptr_t ptr, size_t length, const UA_DataType *type,
|
|
u8 *oldpos = ctx->pos;
|
|
u8 *oldpos = ctx->pos;
|
|
status ret = encodeType((const void*)ptr, type, ctx);
|
|
status ret = encodeType((const void*)ptr, type, ctx);
|
|
ptr += type->memSize;
|
|
ptr += type->memSize;
|
|
|
|
+
|
|
/* Encoding failed, switch to the next chunk when possible */
|
|
/* Encoding failed, switch to the next chunk when possible */
|
|
if(ret != UA_STATUSCODE_GOOD) {
|
|
if(ret != UA_STATUSCODE_GOOD) {
|
|
if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
|
|
if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
|
|
@@ -461,6 +462,7 @@ Array_encodeBinaryComplex(uintptr_t ptr, size_t length, const UA_DataType *type,
|
|
return ret; /* Unrecoverable fail */
|
|
return ret; /* Unrecoverable fail */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
return UA_STATUSCODE_GOOD;
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -758,7 +760,6 @@ DECODE_BINARY(ExpandedNodeId) {
|
|
}
|
|
}
|
|
|
|
|
|
/* QualifiedName */
|
|
/* QualifiedName */
|
|
-
|
|
|
|
ENCODE_BINARY(QualifiedName) {
|
|
ENCODE_BINARY(QualifiedName) {
|
|
return ENCODE_DIRECT(&src->namespaceIndex, UInt16) |
|
|
return ENCODE_DIRECT(&src->namespaceIndex, UInt16) |
|
|
ENCODE_DIRECT(&src->name, String);
|
|
ENCODE_DIRECT(&src->name, String);
|
|
@@ -766,7 +767,7 @@ ENCODE_BINARY(QualifiedName) {
|
|
|
|
|
|
DECODE_BINARY(QualifiedName) {
|
|
DECODE_BINARY(QualifiedName) {
|
|
return DECODE_DIRECT(&dst->namespaceIndex, UInt16) |
|
|
return DECODE_DIRECT(&dst->namespaceIndex, UInt16) |
|
|
- DECODE_DIRECT(&dst->name, String);
|
|
|
|
|
|
+ DECODE_DIRECT(&dst->name, String);
|
|
}
|
|
}
|
|
|
|
|
|
/* LocalizedText */
|
|
/* LocalizedText */
|
|
@@ -947,22 +948,27 @@ DECODE_BINARY(ExtensionObject) {
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
|
|
|
|
|
|
+ switch(encoding) {
|
|
|
|
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
|
|
ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
|
|
ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
|
|
UA_NodeId_deleteMembers(&binTypeId);
|
|
UA_NodeId_deleteMembers(&binTypeId);
|
|
- } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
|
|
|
|
|
|
+ break;
|
|
|
|
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
|
|
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
|
|
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
|
|
dst->content.encoded.typeId = binTypeId; /* move to dst */
|
|
dst->content.encoded.typeId = binTypeId; /* move to dst */
|
|
dst->content.encoded.body = UA_BYTESTRING_NULL;
|
|
dst->content.encoded.body = UA_BYTESTRING_NULL;
|
|
- } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
|
|
|
|
|
|
+ break;
|
|
|
|
+ case UA_EXTENSIONOBJECT_ENCODED_XML:
|
|
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
|
|
dst->encoding = (UA_ExtensionObjectEncoding)encoding;
|
|
dst->content.encoded.typeId = binTypeId; /* move to dst */
|
|
dst->content.encoded.typeId = binTypeId; /* move to dst */
|
|
ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
|
|
ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
|
|
if(ret != UA_STATUSCODE_GOOD)
|
|
if(ret != UA_STATUSCODE_GOOD)
|
|
UA_NodeId_deleteMembers(&dst->content.encoded.typeId);
|
|
UA_NodeId_deleteMembers(&dst->content.encoded.typeId);
|
|
- } else {
|
|
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
UA_NodeId_deleteMembers(&binTypeId);
|
|
UA_NodeId_deleteMembers(&binTypeId);
|
|
ret = UA_STATUSCODE_BADDECODINGERROR;
|
|
ret = UA_STATUSCODE_BADDECODINGERROR;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -1011,8 +1017,6 @@ enum UA_VARIANT_ENCODINGMASKTYPE {
|
|
UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) /* bit 7 */
|
|
UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) /* bit 7 */
|
|
};
|
|
};
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
ENCODE_BINARY(Variant) {
|
|
ENCODE_BINARY(Variant) {
|
|
/* Quit early for the empty variant */
|
|
/* Quit early for the empty variant */
|
|
u8 encoding = 0;
|
|
u8 encoding = 0;
|
|
@@ -1386,33 +1390,41 @@ encodeBinaryInternal(const void *src, const UA_DataType *type, Ctx *ctx) {
|
|
status ret = UA_STATUSCODE_GOOD;
|
|
status ret = UA_STATUSCODE_GOOD;
|
|
u8 membersSize = type->membersSize;
|
|
u8 membersSize = type->membersSize;
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
- for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
|
|
|
|
|
|
+
|
|
|
|
+ /* Loop over members */
|
|
|
|
+ for(size_t i = 0; i < membersSize; ++i) {
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
- if(!member->isArray) {
|
|
|
|
- ptr += member->padding;
|
|
|
|
- size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
- size_t memSize = membertype->memSize;
|
|
|
|
- u8 *oldpos = ctx->pos;
|
|
|
|
- ret = encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype, ctx);
|
|
|
|
- ptr += memSize;
|
|
|
|
- if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
|
|
|
|
- ctx->pos = oldpos; /* exchange/send the buffer */
|
|
|
|
- ret = exchangeBuffer(ctx);
|
|
|
|
- ptr -= member->padding + memSize; /* encode the same member in the next iteration */
|
|
|
|
- if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED || ctx->pos + memSize > ctx->end) {
|
|
|
|
- /* the send buffer is too small to encode the member, even after exchangeBuffer */
|
|
|
|
- ret = UA_STATUSCODE_BADRESPONSETOOLARGE;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- --i;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- ptr += member->padding;
|
|
|
|
|
|
+ ptr += member->padding;
|
|
|
|
+
|
|
|
|
+ /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */
|
|
|
|
+ if(member->isArray) {
|
|
const size_t length = *((const size_t*)ptr);
|
|
const size_t length = *((const size_t*)ptr);
|
|
ptr += sizeof(size_t);
|
|
ptr += sizeof(size_t);
|
|
ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype, ctx);
|
|
ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype, ctx);
|
|
ptr += sizeof(void*);
|
|
ptr += sizeof(void*);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Scalar */
|
|
|
|
+ size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
+ size_t memSize = membertype->memSize;
|
|
|
|
+ u8 *oldpos = ctx->pos;
|
|
|
|
+ ret = encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype, ctx);
|
|
|
|
+ ptr += memSize;
|
|
|
|
+
|
|
|
|
+ /* Exchange/send the buffer */
|
|
|
|
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
|
|
|
|
+ ctx->pos = oldpos;
|
|
|
|
+ ret = exchangeBuffer(ctx);
|
|
|
|
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED || ctx->pos + memSize > ctx->end) {
|
|
|
|
+ /* the send buffer is too small to encode the member, even after exchangeBuffer */
|
|
|
|
+ ret = UA_STATUSCODE_BADRESPONSETOOLARGE;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ /* Try to encode the same member in the next iteration on the new buffer */
|
|
|
|
+ ptr -= member->padding + memSize;
|
|
|
|
+ --i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1483,22 +1495,27 @@ decodeBinaryInternal(void *dst, const UA_DataType *type, Ctx *ctx) {
|
|
status ret = UA_STATUSCODE_GOOD;
|
|
status ret = UA_STATUSCODE_GOOD;
|
|
u8 membersSize = type->membersSize;
|
|
u8 membersSize = type->membersSize;
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
|
|
+
|
|
|
|
+ /* Loop over members */
|
|
for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
|
|
for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
- if(!member->isArray) {
|
|
|
|
- ptr += member->padding;
|
|
|
|
- size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
- size_t memSize = membertype->memSize;
|
|
|
|
- ret |= decodeBinaryJumpTable[fi]((void *UA_RESTRICT)ptr, membertype, ctx);
|
|
|
|
- ptr += memSize;
|
|
|
|
- } else {
|
|
|
|
- ptr += member->padding;
|
|
|
|
|
|
+ ptr += member->padding;
|
|
|
|
+
|
|
|
|
+ /* Array */
|
|
|
|
+ if(member->isArray) {
|
|
size_t *length = (size_t*)ptr;
|
|
size_t *length = (size_t*)ptr;
|
|
ptr += sizeof(size_t);
|
|
ptr += sizeof(size_t);
|
|
- ret |= Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, membertype, ctx);
|
|
|
|
|
|
+ ret = Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, membertype, ctx);
|
|
ptr += sizeof(void*);
|
|
ptr += sizeof(void*);
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Scalar */
|
|
|
|
+ size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
+ size_t memSize = membertype->memSize;
|
|
|
|
+ ret = decodeBinaryJumpTable[fi]((void *UA_RESTRICT)ptr, membertype, ctx);
|
|
|
|
+ ptr += memSize;
|
|
}
|
|
}
|
|
|
|
|
|
ctx->depth--;
|
|
ctx->depth--;
|
|
@@ -1568,7 +1585,7 @@ CALCSIZE_BINARY(Guid) {
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(NodeId) {
|
|
CALCSIZE_BINARY(NodeId) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
switch(src->identifierType) {
|
|
switch(src->identifierType) {
|
|
case UA_NODEIDTYPE_NUMERIC:
|
|
case UA_NODEIDTYPE_NUMERIC:
|
|
if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
|
|
if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
|
|
@@ -1607,7 +1624,7 @@ CALCSIZE_BINARY(QualifiedName) {
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(LocalizedText) {
|
|
CALCSIZE_BINARY(LocalizedText) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
if(src->locale.data)
|
|
if(src->locale.data)
|
|
s += String_calcSizeBinary(&src->locale, NULL);
|
|
s += String_calcSizeBinary(&src->locale, NULL);
|
|
if(src->text.data)
|
|
if(src->text.data)
|
|
@@ -1616,18 +1633,10 @@ CALCSIZE_BINARY(LocalizedText) {
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(ExtensionObject) {
|
|
CALCSIZE_BINARY(ExtensionObject) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
- if(src->encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
|
|
|
|
- if(!src->content.decoded.type || !src->content.decoded.data)
|
|
|
|
- return 0;
|
|
|
|
- if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
|
|
|
|
- return 0;
|
|
|
|
- s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL);
|
|
|
|
- s += 4; /* length */
|
|
|
|
- const UA_DataType *type = src->content.decoded.type;
|
|
|
|
- size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
- s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, type);
|
|
|
|
- } else {
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
|
|
+
|
|
|
|
+ /* Encoded content */
|
|
|
|
+ if(src->encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
|
|
s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
|
|
s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
|
|
switch(src->encoding) {
|
|
switch(src->encoding) {
|
|
case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
|
|
case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
|
|
@@ -1639,12 +1648,25 @@ CALCSIZE_BINARY(ExtensionObject) {
|
|
default:
|
|
default:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+ return s;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Decoded content */
|
|
|
|
+ if(!src->content.decoded.type || !src->content.decoded.data)
|
|
|
|
+ return 0;
|
|
|
|
+ if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL); /* Type encoding length */
|
|
|
|
+ s += 4; /* Encoding length field */
|
|
|
|
+ const UA_DataType *type = src->content.decoded.type;
|
|
|
|
+ size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
+ s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, type); /* Encoding length */
|
|
return s;
|
|
return s;
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(Variant) {
|
|
CALCSIZE_BINARY(Variant) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
if(!src->type)
|
|
if(!src->type)
|
|
return s;
|
|
return s;
|
|
|
|
|
|
@@ -1680,7 +1702,7 @@ CALCSIZE_BINARY(Variant) {
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(DataValue) {
|
|
CALCSIZE_BINARY(DataValue) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
if(src->hasValue)
|
|
if(src->hasValue)
|
|
s += Variant_calcSizeBinary(&src->value, NULL);
|
|
s += Variant_calcSizeBinary(&src->value, NULL);
|
|
if(src->hasStatus)
|
|
if(src->hasStatus)
|
|
@@ -1697,7 +1719,7 @@ CALCSIZE_BINARY(DataValue) {
|
|
}
|
|
}
|
|
|
|
|
|
CALCSIZE_BINARY(DiagnosticInfo) {
|
|
CALCSIZE_BINARY(DiagnosticInfo) {
|
|
- size_t s = 1; /* encoding byte */
|
|
|
|
|
|
+ size_t s = 1; /* Encoding byte */
|
|
if(src->hasSymbolicId)
|
|
if(src->hasSymbolicId)
|
|
s += 4;
|
|
s += 4;
|
|
if(src->hasNamespaceUri)
|
|
if(src->hasNamespaceUri)
|
|
@@ -1750,21 +1772,27 @@ UA_calcSizeBinary(const void *p, const UA_DataType *type) {
|
|
uintptr_t ptr = (uintptr_t)p;
|
|
uintptr_t ptr = (uintptr_t)p;
|
|
u8 membersSize = type->membersSize;
|
|
u8 membersSize = type->membersSize;
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
|
|
|
|
+
|
|
|
|
+ /* Loop over members */
|
|
for(size_t i = 0; i < membersSize; ++i) {
|
|
for(size_t i = 0; i < membersSize; ++i) {
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataTypeMember *member = &type->members[i];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
|
|
- if(!member->isArray) {
|
|
|
|
- ptr += member->padding;
|
|
|
|
- size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
- s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
|
|
|
|
- ptr += membertype->memSize;
|
|
|
|
- } else {
|
|
|
|
- ptr += member->padding;
|
|
|
|
|
|
+ ptr += member->padding;
|
|
|
|
+
|
|
|
|
+ /* Array */
|
|
|
|
+ if(member->isArray) {
|
|
const size_t length = *((const size_t*)ptr);
|
|
const size_t length = *((const size_t*)ptr);
|
|
ptr += sizeof(size_t);
|
|
ptr += sizeof(size_t);
|
|
s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
|
|
s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
|
|
ptr += sizeof(void*);
|
|
ptr += sizeof(void*);
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Scalar */
|
|
|
|
+ size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
|
|
|
|
+ s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
|
|
|
|
+ ptr += membertype->memSize;
|
|
}
|
|
}
|
|
|
|
+
|
|
return s;
|
|
return s;
|
|
}
|
|
}
|