mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
feat(core): Expose binary encoding/decoding functions
This commit is contained in:
parent
4d3422524c
commit
b164c0e7f4
@ -1018,6 +1018,14 @@ struct UA_DataType {
|
||||
UA_DataTypeMember *members;
|
||||
};
|
||||
|
||||
/* Datatype arrays with custom type definitions can be added in a linked list to
|
||||
* the client or server configuration. */
|
||||
typedef struct UA_DataTypeArray {
|
||||
const struct UA_DataTypeArray *next;
|
||||
const size_t typesSize;
|
||||
const UA_DataType *types;
|
||||
} UA_DataTypeArray;
|
||||
|
||||
/* Test if the data type is a numeric builtin data type. This includes Boolean,
|
||||
* integers and floating point numbers. Not included are DateTime and
|
||||
* StatusCode. */
|
||||
@ -1091,6 +1099,41 @@ UA_StatusCode UA_EXPORT
|
||||
UA_print(const void *p, const UA_DataType *type, UA_String *output);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encodeing/Decoding
|
||||
* ^^^^^^^^^^^^^^^^^^
|
||||
* Encodeing and decoding routines for the available formats. For all formats
|
||||
* the _calcSize, _encode and _decode methods are provided. */
|
||||
|
||||
/* Returns the number of bytes the value p takes in binary encoding. Returns
|
||||
* zero if an error occurs. */
|
||||
UA_EXPORT size_t
|
||||
UA_calcSizeBinary(const void *p, const UA_DataType *type);
|
||||
|
||||
/* Encodes a data-structure in the binary format. If outBuf has a length of
|
||||
* zero, a buffer of the required size is allocated. Otherwise, encoding into
|
||||
* the existing outBuf is attempted (and may fail if the buffer is too
|
||||
* small). */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_encodeBinary(const void *p, const UA_DataType *type,
|
||||
UA_ByteString *outBuf);
|
||||
|
||||
/* The structure with the decoding options may be extended in the future.
|
||||
* Zero-out the entire structure initially to ensure code-compatibility when
|
||||
* more fields are added in a later release. */
|
||||
typedef struct {
|
||||
const UA_DataTypeArray *customTypes; /* Begin of a linked list with custom
|
||||
* datatype definitions */
|
||||
} UA_DecodeBinaryOptions;
|
||||
|
||||
/* Decodes a data structure from the input buffer in the binary format. It is
|
||||
* assumed that `p` points to valid memory (not necessarily zeroed out). The
|
||||
* options can be NULL and will be disregarded in that case. */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_decodeBinary(const UA_ByteString *inBuf,
|
||||
void *p, const UA_DataType *type,
|
||||
const UA_DecodeBinaryOptions *options);
|
||||
|
||||
/**
|
||||
* .. _array-handling:
|
||||
*
|
||||
@ -1202,14 +1245,6 @@ UA_Guid UA_EXPORT UA_Guid_random(void); /* no cryptographic entropy */
|
||||
# define UA_TYPENAME(name)
|
||||
#endif
|
||||
|
||||
/* Datatype arrays with custom type definitions can be added in a linked list to
|
||||
* the client or server configuration. */
|
||||
typedef struct UA_DataTypeArray {
|
||||
const struct UA_DataTypeArray *next;
|
||||
const size_t typesSize;
|
||||
const UA_DataType *types;
|
||||
} UA_DataTypeArray;
|
||||
|
||||
/**
|
||||
* .. include:: types_generated.rst */
|
||||
|
||||
|
@ -1492,6 +1492,34 @@ UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_encodeBinary(const void *p, const UA_DataType *type,
|
||||
UA_ByteString *outBuf) {
|
||||
/* Allocate buffer */
|
||||
UA_Boolean allocated = false;
|
||||
status res = UA_STATUSCODE_GOOD;
|
||||
if(outBuf->length == 0) {
|
||||
size_t len = UA_calcSizeBinary(p, type);
|
||||
res = UA_ByteString_allocBuffer(outBuf, len);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
allocated = true;
|
||||
}
|
||||
|
||||
/* Encode */
|
||||
u8 *pos = outBuf->data;
|
||||
const u8 *posEnd = &outBuf->data[outBuf->length];
|
||||
res = UA_encodeBinaryInternal(p, type, &pos, &posEnd, NULL, NULL);
|
||||
|
||||
/* Clean up */
|
||||
if(res == UA_STATUSCODE_GOOD) {
|
||||
outBuf->length = (size_t)((uintptr_t)pos - (uintptr_t)outBuf->data);
|
||||
} else if(allocated) {
|
||||
UA_ByteString_clear(outBuf);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static status
|
||||
decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
|
||||
(void)dst, (void)type, (void)ctx;
|
||||
@ -1683,6 +1711,15 @@ UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
|
||||
return ret;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_decodeBinary(const UA_ByteString *inBuf,
|
||||
void *p, const UA_DataType *type,
|
||||
const UA_DecodeBinaryOptions *options) {
|
||||
size_t offset = 0;
|
||||
const UA_DataTypeArray *customTypes = options ? options->customTypes : NULL;
|
||||
return UA_decodeBinaryInternal(inBuf, &offset, p, type, customTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the Message Size
|
||||
* ------------------------
|
||||
|
@ -67,11 +67,6 @@ UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
|
||||
const UA_DataTypeArray *customTypes)
|
||||
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/* Returns the number of bytes the value p takes in binary encoding. Returns
|
||||
* zero if an error occurs. */
|
||||
size_t
|
||||
UA_calcSizeBinary(const void *p, const UA_DataType *type);
|
||||
|
||||
const UA_DataType *
|
||||
UA_findDataTypeByBinary(const UA_NodeId *typeId);
|
||||
|
||||
|
@ -19,15 +19,12 @@
|
||||
#endif
|
||||
|
||||
#include <open62541/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Internal headers */
|
||||
#include <open62541/types_generated.h>
|
||||
#include <open62541/types_generated_handling.h>
|
||||
|
||||
/* Internal headers */
|
||||
#include "ua_pubsub_networkmessage.h"
|
||||
#include "ua_types_encoding_binary.h"
|
||||
#include "ua_types_encoding_json.h"
|
||||
|
||||
static UA_StatusCode
|
||||
@ -37,17 +34,11 @@ encode(const UA_ByteString *buf, UA_ByteString *out,
|
||||
if(!data)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
|
||||
size_t offset = 0;
|
||||
UA_StatusCode retval = UA_decodeBinary(buf, &offset, data, type, NULL);
|
||||
UA_StatusCode retval = UA_decodeBinary(buf, data, type, NULL);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
free(data);
|
||||
return retval;
|
||||
}
|
||||
if(offset != buf->length) {
|
||||
UA_delete(data, type);
|
||||
fprintf(stderr, "Input buffer not completely read\n");
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
size_t jsonLength = UA_calcSizeJson(data, type, NULL, 0, NULL, 0, true);
|
||||
retval = UA_ByteString_allocBuffer(out, jsonLength);
|
||||
@ -72,34 +63,24 @@ encode(const UA_ByteString *buf, UA_ByteString *out,
|
||||
static UA_StatusCode
|
||||
decode(const UA_ByteString *buf, UA_ByteString *out,
|
||||
const UA_DataType *type) {
|
||||
/* Allocate memory for the type */
|
||||
void *data = malloc(type->memSize);
|
||||
if(!data)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
|
||||
/* Decode JSON */
|
||||
UA_StatusCode retval = UA_decodeJson(buf, data, type);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
free(data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
size_t binLength = UA_calcSizeBinary(data, type);
|
||||
retval = UA_ByteString_allocBuffer(out, binLength);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_delete(data, type);
|
||||
return retval;
|
||||
}
|
||||
/* Encode Binary. Internally allocates the buffer upon success */
|
||||
retval = UA_encodeBinary(data, type, out);
|
||||
|
||||
uint8_t *bufPos = &out->data[0];
|
||||
const uint8_t *bufEnd = &out->data[out->length];
|
||||
retval = UA_encodeBinary(data, type, &bufPos, &bufEnd, NULL, NULL);
|
||||
/* Clean up */
|
||||
UA_delete(data, type);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_ByteString_clear(out);
|
||||
return retval;
|
||||
}
|
||||
|
||||
out->length = (size_t)((uintptr_t)bufPos - (uintptr_t)out->data);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef UA_ENABLE_PUBSUB
|
||||
|
Loading…
Reference in New Issue
Block a user