Browse Source

Encoding: Cosmetic refactor and documentation improvements

Julius Pfrommer 5 years ago
parent
commit
48584473cf
1 changed files with 90 additions and 62 deletions
  1. 90 62
      src/ua_types_encoding_binary.c

+ 90 - 62
src/ua_types_encoding_binary.c

@@ -448,6 +448,7 @@ Array_encodeBinaryComplex(uintptr_t ptr, size_t length, const UA_DataType *type,
         u8 *oldpos = ctx->pos;
         status ret = encodeType((const void*)ptr, type, ctx);
         ptr += type->memSize;
+
         /* Encoding failed, switch to the next chunk when possible */
         if(ret != UA_STATUSCODE_GOOD) {
             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 UA_STATUSCODE_GOOD;
 }
 
@@ -758,7 +760,6 @@ DECODE_BINARY(ExpandedNodeId) {
 }
 
 /* QualifiedName */
-
 ENCODE_BINARY(QualifiedName) {
     return ENCODE_DIRECT(&src->namespaceIndex, UInt16) |
            ENCODE_DIRECT(&src->name, String);
@@ -766,7 +767,7 @@ ENCODE_BINARY(QualifiedName) {
 
 DECODE_BINARY(QualifiedName) {
     return DECODE_DIRECT(&dst->namespaceIndex, UInt16) |
-        DECODE_DIRECT(&dst->name, String);
+           DECODE_DIRECT(&dst->name, String);
 }
 
 /* LocalizedText */
@@ -947,22 +948,27 @@ DECODE_BINARY(ExtensionObject) {
         return ret;
     }
 
-    if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
+    switch(encoding) {
+    case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
         ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
         UA_NodeId_deleteMembers(&binTypeId);
-    } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
+        break;
+    case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
         dst->encoding = (UA_ExtensionObjectEncoding)encoding;
         dst->content.encoded.typeId = binTypeId; /* move to dst */
         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->content.encoded.typeId = binTypeId; /* move to dst */
         ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
         if(ret != UA_STATUSCODE_GOOD)
             UA_NodeId_deleteMembers(&dst->content.encoded.typeId);
-    } else {
+        break;
+    default:
         UA_NodeId_deleteMembers(&binTypeId);
         ret = UA_STATUSCODE_BADDECODINGERROR;
+        break;
     }
 
     return ret;
@@ -1011,8 +1017,6 @@ enum UA_VARIANT_ENCODINGMASKTYPE {
     UA_VARIANT_ENCODINGMASKTYPE_ARRAY       = (0x01 << 7)  /* bit 7 */
 };
 
-
-
 ENCODE_BINARY(Variant) {
     /* Quit early for the empty variant */
     u8 encoding = 0;
@@ -1386,33 +1390,41 @@ encodeBinaryInternal(const void *src, const UA_DataType *type, Ctx *ctx) {
     status ret = UA_STATUSCODE_GOOD;
     u8 membersSize = type->membersSize;
     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_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);
             ptr += sizeof(size_t);
             ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype, ctx);
             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;
     u8 membersSize = type->membersSize;
     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) {
         const UA_DataTypeMember *member = &type->members[i];
         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;
             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*);
+            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--;
@@ -1568,7 +1585,7 @@ CALCSIZE_BINARY(Guid) {
 }
 
 CALCSIZE_BINARY(NodeId) {
-    size_t s = 1; /* encoding byte */
+    size_t s = 1; /* Encoding byte */
     switch(src->identifierType) {
     case UA_NODEIDTYPE_NUMERIC:
         if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
@@ -1607,7 +1624,7 @@ CALCSIZE_BINARY(QualifiedName) {
 }
 
 CALCSIZE_BINARY(LocalizedText) {
-    size_t s = 1; /* encoding byte */
+    size_t s = 1; /* Encoding byte */
     if(src->locale.data)
         s += String_calcSizeBinary(&src->locale, NULL);
     if(src->text.data)
@@ -1616,18 +1633,10 @@ CALCSIZE_BINARY(LocalizedText) {
 }
 
 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);
         switch(src->encoding) {
         case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
@@ -1639,12 +1648,25 @@ CALCSIZE_BINARY(ExtensionObject) {
         default:
             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;
 }
 
 CALCSIZE_BINARY(Variant) {
-    size_t s = 1; /* encoding byte */
+    size_t s = 1; /* Encoding byte */
     if(!src->type)
         return s;
 
@@ -1680,7 +1702,7 @@ CALCSIZE_BINARY(Variant) {
 }
 
 CALCSIZE_BINARY(DataValue) {
-    size_t s = 1; /* encoding byte */
+    size_t s = 1; /* Encoding byte */
     if(src->hasValue)
         s += Variant_calcSizeBinary(&src->value, NULL);
     if(src->hasStatus)
@@ -1697,7 +1719,7 @@ CALCSIZE_BINARY(DataValue) {
 }
 
 CALCSIZE_BINARY(DiagnosticInfo) {
-    size_t s = 1; /* encoding byte */
+    size_t s = 1; /* Encoding byte */
     if(src->hasSymbolicId)
         s += 4;
     if(src->hasNamespaceUri)
@@ -1750,21 +1772,27 @@ UA_calcSizeBinary(const void *p, const UA_DataType *type) {
     uintptr_t ptr = (uintptr_t)p;
     u8 membersSize = type->membersSize;
     const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+
+    /* Loop over members */
     for(size_t i = 0; i < membersSize; ++i) {
         const UA_DataTypeMember *member = &type->members[i];
         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);
             ptr += sizeof(size_t);
             s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
             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;
 }