Skip to content

Commit

Permalink
Merge 1e6d032 into b0b34cc
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfr committed Feb 1, 2019
2 parents b0b34cc + 1e6d032 commit ac7a8bf
Show file tree
Hide file tree
Showing 10 changed files with 581 additions and 533 deletions.
4 changes: 2 additions & 2 deletions examples/custom_datatype/custom_datatype.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ static const UA_DataType PointType = {
{1, UA_NODEIDTYPE_NUMERIC, {4242}}, /* .typeId */
sizeof(Point), /* .memSize */
0, /* .typeIndex, in the array of custom types */
3, /* .membersSize */
false, /* .builtin */
UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
true, /* .pointerFree */
false, /* .overlayable (depends on endianness and
the absence of padding) */
3, /* .membersSize */
0, /* .binaryEncodingId, the numeric
identifier used on the wire (the
namespaceindex is from .typeId) */
Expand Down
60 changes: 48 additions & 12 deletions include/ua_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -797,22 +797,58 @@ typedef struct {
UA_Boolean isArray : 1; /* The member is an array */
} UA_DataTypeMember;

/* The DataType "kind" is an internal type classification. It is used to
* dispatch handling to the correct routines. */
#define UA_DATATYPEKINDS 31
typedef enum {
UA_DATATYPEKIND_BOOLEAN = 0,
UA_DATATYPEKIND_SBYTE = 1,
UA_DATATYPEKIND_BYTE = 2,
UA_DATATYPEKIND_INT16 = 3,
UA_DATATYPEKIND_UINT16 = 4,
UA_DATATYPEKIND_INT32 = 5,
UA_DATATYPEKIND_UINT32 = 6,
UA_DATATYPEKIND_INT64 = 7,
UA_DATATYPEKIND_UINT64 = 8,
UA_DATATYPEKIND_FLOAT = 9,
UA_DATATYPEKIND_DOUBLE = 10,
UA_DATATYPEKIND_STRING = 11,
UA_DATATYPEKIND_DATETIME = 12,
UA_DATATYPEKIND_GUID = 13,
UA_DATATYPEKIND_BYTESTRING = 14,
UA_DATATYPEKIND_XMLELEMENT = 15,
UA_DATATYPEKIND_NODEID = 16,
UA_DATATYPEKIND_EXPANDEDNODEID = 17,
UA_DATATYPEKIND_STATUSCODE = 18,
UA_DATATYPEKIND_QUALIFIEDNAME = 19,
UA_DATATYPEKIND_LOCALIZEDTEXT = 20,
UA_DATATYPEKIND_EXTENSIONOBJECT = 21,
UA_DATATYPEKIND_DATAVALUE = 22,
UA_DATATYPEKIND_VARIANT = 23,
UA_DATATYPEKIND_DIAGNOSTICINFO = 24,
UA_DATATYPEKIND_DECIMAL = 25,
UA_DATATYPEKIND_ENUM = 26,
UA_DATATYPEKIND_STRUCTURE = 27,
UA_DATATYPEKIND_OPTSTRUCT = 28, /* struct with optional fields */
UA_DATATYPEKIND_UNION = 29,
UA_DATATYPEKIND_BITFIELDCLUSTER = 30 /* bitfields + padding */
} UA_DataTypeKind;

struct UA_DataType {
#ifdef UA_ENABLE_TYPENAMES
const char *typeName;
#endif
UA_NodeId typeId; /* The nodeid of the type */
UA_UInt16 memSize; /* Size of the struct in memory */
UA_UInt16 typeIndex; /* Index of the type in the datatypetable */
UA_Byte membersSize; /* How many members does the type have? */
UA_Boolean builtin : 1; /* The type is "builtin" and has dedicated de-
and encoding functions */
UA_Boolean pointerFree : 1; /* The type (and its members) contains no
pointers that need to be freed */
UA_Boolean overlayable : 1; /* The type has the identical memory layout in
memory and on the binary stream. */
UA_UInt16 binaryEncodingId; /* NodeId of datatype when encoded as binary */
//UA_UInt16 xmlEncodingId; /* NodeId of datatype when encoded as XML */
UA_NodeId typeId; /* The nodeid of the type */
UA_UInt16 memSize; /* Size of the struct in memory */
UA_UInt16 typeIndex; /* Index of the type in the datatypetable */
UA_UInt32 typeKind : 6; /* Dispatch index for the handling routines */
UA_UInt32 pointerFree : 1; /* The type (and its members) contains no
* pointers that need to be freed */
UA_UInt32 overlayable : 1; /* The type has the identical memory layout
* in memory and on the binary stream. */
UA_UInt32 membersSize : 8; /* How many members does the type have? */
UA_UInt32 binaryEncodingId : 16; /* NodeId of datatype when encoded as binary */
//UA_UInt16 xmlEncodingId; /* NodeId of datatype when encoded as XML */
UA_DataTypeMember *members;
};

Expand Down
25 changes: 8 additions & 17 deletions src/server/ua_services_attribute.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,21 +568,12 @@ UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
/* Type Checking */
/*****************/

enum type_equivalence {
TYPE_EQUIVALENCE_NONE,
TYPE_EQUIVALENCE_ENUM,
TYPE_EQUIVALENCE_OPAQUE
};

static enum type_equivalence
static UA_DataTypeKind
typeEquivalence(const UA_DataType *t) {
if(t->membersSize != 1 || !t->members[0].namespaceZero)
return TYPE_EQUIVALENCE_NONE;
if(t->members[0].memberTypeIndex == UA_TYPES_INT32)
return TYPE_EQUIVALENCE_ENUM;
if(t->members[0].memberTypeIndex == UA_TYPES_BYTE && t->members[0].isArray)
return TYPE_EQUIVALENCE_OPAQUE;
return TYPE_EQUIVALENCE_NONE;
UA_DataTypeKind k = (UA_DataTypeKind)t->typeKind;
if(k == UA_DATATYPEKIND_ENUM)
return UA_DATATYPEKIND_INT32;
return k;
}

static const UA_NodeId enumNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ENUMERATION}};
Expand Down Expand Up @@ -839,9 +830,9 @@ adjustValue(UA_Server *server, UA_Variant *value,

/* An enum was sent as an int32, or an opaque type as a bytestring. This
* is detected with the typeIndex indicating the "true" datatype. */
enum type_equivalence te1 = typeEquivalence(targetDataType);
enum type_equivalence te2 = typeEquivalence(value->type);
if(te1 != TYPE_EQUIVALENCE_NONE && te1 == te2) {
UA_DataTypeKind te1 = typeEquivalence(targetDataType);
UA_DataTypeKind te2 = typeEquivalence(value->type);
if(te1 == te2 && te1 <= UA_DATATYPEKIND_ENUM) {
value->type = targetDataType;
return;
}
Expand Down
182 changes: 96 additions & 86 deletions src/ua_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ const UA_Guid UA_GUID_NULL = {0, 0, 0, {0,0,0,0,0,0,0,0}};
const UA_NodeId UA_NODEID_NULL = {0, UA_NODEIDTYPE_NUMERIC, {0}};
const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {{0, UA_NODEIDTYPE_NUMERIC, {0}}, {0, NULL}, 0};

typedef UA_StatusCode (*UA_copySignature)(const void *src, void *dst,
const UA_DataType *type);
typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);

extern const UA_copySignature copyJumpTable[UA_DATATYPEKINDS];
extern const UA_clearSignature clearJumpTable[UA_DATATYPEKINDS];

/* TODO: The standard-defined types are ordered. See if binary search is
* more efficient. */
const UA_DataType *
Expand Down Expand Up @@ -88,9 +95,6 @@ UA_UInt32_random(void) {
/* Builtin Types */
/*****************/

static void clear_noInit(void *p, const UA_DataType *type);
static UA_StatusCode copy_noInit(const void *src, void *dst, const UA_DataType *type);

UA_String
UA_String_fromChars(char const src[]) {
UA_String str;
Expand Down Expand Up @@ -753,7 +757,7 @@ Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
} else {
for(size_t i = 0; i < block_count; ++i) {
for(size_t j = 0; j < block; ++j) {
clear_noInit((void*)nextdst, v->type);
clearJumpTable[v->type->typeKind]((void*)nextdst, v->type);
retval |= UA_copy((void*)nextsrc, (void*)nextdst, v->type);
nextdst += elem_size;
nextsrc += elem_size;
Expand Down Expand Up @@ -887,53 +891,19 @@ copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
return UA_STATUSCODE_GOOD;
}

typedef UA_StatusCode
(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);

static const UA_copySignature copyJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
(UA_copySignature)copyByte, // Boolean
(UA_copySignature)copyByte, // SByte
(UA_copySignature)copyByte, // Byte
(UA_copySignature)copy2Byte, // Int16
(UA_copySignature)copy2Byte, // UInt16
(UA_copySignature)copy4Byte, // Int32
(UA_copySignature)copy4Byte, // UInt32
(UA_copySignature)copy8Byte, // Int64
(UA_copySignature)copy8Byte, // UInt64
(UA_copySignature)copy4Byte, // Float
(UA_copySignature)copy8Byte, // Double
(UA_copySignature)String_copy,
(UA_copySignature)copy8Byte, // DateTime
(UA_copySignature)copyGuid, // Guid
(UA_copySignature)String_copy, // ByteString
(UA_copySignature)String_copy, // XmlElement
(UA_copySignature)NodeId_copy,
(UA_copySignature)ExpandedNodeId_copy,
(UA_copySignature)copy4Byte, // StatusCode
(UA_copySignature)QualifiedName_copy,
(UA_copySignature)LocalizedText_copy,
(UA_copySignature)ExtensionObject_copy,
(UA_copySignature)DataValue_copy,
(UA_copySignature)Variant_copy,
(UA_copySignature)DiagnosticInfo_copy,
(UA_copySignature)copy_noInit // all others
};

static UA_StatusCode
copy_noInit(const void *src, void *dst, const UA_DataType *type) {
copyStructure(const void *src, void *dst, const UA_DataType *type) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
uintptr_t ptrs = (uintptr_t)src;
uintptr_t ptrd = (uintptr_t)dst;
u8 membersSize = type->membersSize;
for(size_t i = 0; i < membersSize; ++i) {
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < type->membersSize; ++i) {
const UA_DataTypeMember *m= &type->members[i];
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
if(!m->isArray) {
ptrs += m->padding;
ptrd += m->padding;
size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
retval |= copyJumpTable[fi]((const void*)ptrs, (void*)ptrd, mt);
retval |= copyJumpTable[mt->typeKind]((const void*)ptrs, (void*)ptrd, mt);
ptrs += mt->memSize;
ptrd += mt->memSize;
} else {
Expand All @@ -955,61 +925,64 @@ copy_noInit(const void *src, void *dst, const UA_DataType *type) {
return retval;
}

static UA_StatusCode
copyNotImplemented(const void *src, void *dst, const UA_DataType *type) {
return UA_STATUSCODE_BADNOTIMPLEMENTED;
}

const UA_copySignature copyJumpTable[UA_DATATYPEKINDS] = {
(UA_copySignature)copyByte, /* Boolean */
(UA_copySignature)copyByte, /* SByte */
(UA_copySignature)copyByte, /* Byte */
(UA_copySignature)copy2Byte, /* Int16 */
(UA_copySignature)copy2Byte, /* UInt16 */
(UA_copySignature)copy4Byte, /* Int32 */
(UA_copySignature)copy4Byte, /* UInt32 */
(UA_copySignature)copy8Byte, /* Int64 */
(UA_copySignature)copy8Byte, /* UInt64 */
(UA_copySignature)copy4Byte, /* Float */
(UA_copySignature)copy8Byte, /* Double */
(UA_copySignature)String_copy,
(UA_copySignature)copy8Byte, /* DateTime */
(UA_copySignature)copyGuid, /* Guid */
(UA_copySignature)String_copy, /* ByteString */
(UA_copySignature)String_copy, /* XmlElement */
(UA_copySignature)NodeId_copy,
(UA_copySignature)ExpandedNodeId_copy,
(UA_copySignature)copy4Byte, /* StatusCode */
(UA_copySignature)QualifiedName_copy,
(UA_copySignature)LocalizedText_copy,
(UA_copySignature)ExtensionObject_copy,
(UA_copySignature)DataValue_copy,
(UA_copySignature)Variant_copy,
(UA_copySignature)DiagnosticInfo_copy,
(UA_copySignature)copyNotImplemented, /* Decimal */
(UA_copySignature)copy4Byte, /* Enumeration */
(UA_copySignature)copyStructure,
(UA_copySignature)copyNotImplemented, /* Structure with Optional Fields */
(UA_copySignature)copyNotImplemented, /* Union */
(UA_copySignature)copyNotImplemented /* BitfieldCluster*/
};

UA_StatusCode
UA_copy(const void *src, void *dst, const UA_DataType *type) {
memset(dst, 0, type->memSize); /* init */
UA_StatusCode retval = copy_noInit(src, dst, type);
UA_StatusCode retval = copyJumpTable[type->typeKind](src, dst, type);
if(retval != UA_STATUSCODE_GOOD)
UA_clear(dst, type);
return retval;
}

static void nopClear(void *p, const UA_DataType *type) { }

typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);

static const
UA_clearSignature clearJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
(UA_clearSignature)nopClear, // Boolean
(UA_clearSignature)nopClear, // SByte
(UA_clearSignature)nopClear, // Byte
(UA_clearSignature)nopClear, // Int16
(UA_clearSignature)nopClear, // UInt16
(UA_clearSignature)nopClear, // Int32
(UA_clearSignature)nopClear, // UInt32
(UA_clearSignature)nopClear, // Int64
(UA_clearSignature)nopClear, // UInt64
(UA_clearSignature)nopClear, // Float
(UA_clearSignature)nopClear, // Double
(UA_clearSignature)String_clear, // String
(UA_clearSignature)nopClear, // DateTime
(UA_clearSignature)nopClear, // Guid
(UA_clearSignature)String_clear, // ByteString
(UA_clearSignature)String_clear, // XmlElement
(UA_clearSignature)NodeId_clear,
(UA_clearSignature)ExpandedNodeId_clear,
(UA_clearSignature)nopClear, // StatusCode
(UA_clearSignature)QualifiedName_clear,
(UA_clearSignature)LocalizedText_clear,
(UA_clearSignature)ExtensionObject_clear,
(UA_clearSignature)DataValue_clear,
(UA_clearSignature)Variant_clear,
(UA_clearSignature)DiagnosticInfo_clear,
(UA_clearSignature)clear_noInit,
};

static void
clear_noInit(void *p, const UA_DataType *type) {
clearStructure(void *p, const UA_DataType *type) {
uintptr_t ptr = (uintptr_t)p;
u8 membersSize = type->membersSize;
for(size_t i = 0; i < membersSize; ++i) {
const UA_DataTypeMember *m= &type->members[i];
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 < type->membersSize; ++i) {
const UA_DataTypeMember *m = &type->members[i];
const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
if(!m->isArray) {
ptr += m->padding;
size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
clearJumpTable[fi]((void*)ptr, mt);
clearJumpTable[mt->typeKind]((void*)ptr, mt);
ptr += mt->memSize;
} else {
ptr += m->padding;
Expand All @@ -1021,15 +994,52 @@ clear_noInit(void *p, const UA_DataType *type) {
}
}

static void nopClear(void *p, const UA_DataType *type) { }

const
UA_clearSignature clearJumpTable[UA_DATATYPEKINDS] = {
(UA_clearSignature)nopClear, /* Boolean */
(UA_clearSignature)nopClear, /* SByte */
(UA_clearSignature)nopClear, /* Byte */
(UA_clearSignature)nopClear, /* Int16 */
(UA_clearSignature)nopClear, /* UInt16 */
(UA_clearSignature)nopClear, /* Int32 */
(UA_clearSignature)nopClear, /* UInt32 */
(UA_clearSignature)nopClear, /* Int64 */
(UA_clearSignature)nopClear, /* UInt64 */
(UA_clearSignature)nopClear, /* Float */
(UA_clearSignature)nopClear, /* Double */
(UA_clearSignature)String_clear, /* String */
(UA_clearSignature)nopClear, /* DateTime */
(UA_clearSignature)nopClear, /* Guid */
(UA_clearSignature)String_clear, /* ByteString */
(UA_clearSignature)String_clear, /* XmlElement */
(UA_clearSignature)NodeId_clear,
(UA_clearSignature)ExpandedNodeId_clear,
(UA_clearSignature)nopClear, /* StatusCode */
(UA_clearSignature)QualifiedName_clear,
(UA_clearSignature)LocalizedText_clear,
(UA_clearSignature)ExtensionObject_clear,
(UA_clearSignature)DataValue_clear,
(UA_clearSignature)Variant_clear,
(UA_clearSignature)DiagnosticInfo_clear,
(UA_clearSignature)nopClear, /* Decimal, not implemented */
(UA_clearSignature)nopClear, /* Enumeration */
(UA_clearSignature)clearStructure,
(UA_clearSignature)nopClear, /* Struct with Optional Fields, not implemented*/
(UA_clearSignature)nopClear, /* Union, not implemented*/
(UA_clearSignature)nopClear /* BitfieldCluster, not implemented*/
};

void
UA_clear(void *p, const UA_DataType *type) {
clear_noInit(p, type);
clearJumpTable[type->typeKind](p, type);
memset(p, 0, type->memSize); /* init */
}

void
UA_delete(void *p, const UA_DataType *type) {
clear_noInit(p, type);
clearJumpTable[type->typeKind](p, type);
UA_free(p);
}

Expand Down
Loading

0 comments on commit ac7a8bf

Please sign in to comment.