Ver código fonte

copy functions work for the tested datatypes (Arrays and built in type) variant still missing

opcua 11 anos atrás
pai
commit
6ab6c8ef37

+ 15 - 1
examples/src/opcuaServerACPLT.c

@@ -34,8 +34,22 @@ int main(void) {
 }
 
 #ifdef LINUX
-
+void tmpTestFunction()
+{
+	// given
+	UA_String **srcArray; UA_Array_new((void***)&srcArray,3,UA_STRING);
+	UA_String_copycstring("abc",srcArray[0]);
+	UA_String_copycstring("def",srcArray[1]);
+	UA_String_copycstring("ghi",srcArray[2]);
+	// when
+	UA_String **dstArray;
+	UA_Array_copy((void const*const*)srcArray,3,UA_STRING,(void ***)&dstArray);
+}
 void server_run() {
+	//just for debugging
+#ifdef DEBUG
+	tmpTestFunction();
+#endif
 	TL_Connection connection;
 	connection.connectionState = CONNECTIONSTATE_CLOSED;
 	connection.writerCallback = (TL_Writer) NL_TCP_writer;

+ 1 - 1
examples/src/xml2ns0.c

@@ -456,7 +456,7 @@ void XML_Stack_handleText(void * data, const char *txt, int len) {
 			UA_alloc((void** )&buf, len + 1);
 			strncpy(buf, txt, len);
 			buf[len] = 0;
-			XML_Attr_t attr[3] = { cp->textAttrib, buf, UA_NULL };
+	//		XML_Attr_t attr[3] = { cp->textAttrib, buf, UA_NULL };
 			DBG_VERBOSE(printf("handleText calls start elementHandler %s with dst=%p, attr=%p\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj, (void*) attr));
 			// cp->children[cp->activeChild].elementHandler(s, attr, cp->children[cp->activeChild].obj, TRUE);
 			DBG_VERBOSE(printf("handleText calls finish elementHandler %s with dst=%p, attr=(nil)\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj));

+ 19 - 20
include/ua_basictypes.h

@@ -99,8 +99,7 @@ UA_Int32 UA_Array_copy(void const * const *src,UA_Int32 noElements, UA_Int32 typ
 	UA_Int32 TYPE##_deleteMembers(TYPE * p);							\
 	UA_Int32 TYPE##_init(TYPE * p);										\
 	UA_Int32 TYPE##_new(TYPE ** p); 									\
-
-
+	UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
 
 #define UA_TYPE_METHOD_CALCSIZE_SIZEOF(TYPE) \
 UA_Int32 TYPE##_calcSize(TYPE const * p) { return sizeof(TYPE); }
@@ -121,13 +120,15 @@ UA_Int32 TYPE##_delete(TYPE *p) { \
 	retval |= UA_free(p); \
 	return retval; \
 }
+
 #define UA_TYPE_METHOD_COPY(TYPE) \
 UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst){ \
 	UA_Int32 retval = UA_SUCCESS; \
-	retval |= UA_alloc((void**)&dst, TYPE##_calcSize(UA_NULL)); \
 	retval |= UA_memcpy(dst, src, TYPE##_calcSize(UA_NULL)); \
 	return retval; \
 }
+
+
 #define UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(TYPE) \
 UA_Int32 TYPE##_deleteMembers(TYPE * p) { return UA_SUCCESS; }
 
@@ -148,6 +149,10 @@ UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_Int32* pos, UA_ByteString *dst
 UA_Int32 TYPE##_init(TYPE * p){ \
 	return TYPE_AS##_init((TYPE_AS*)p); \
 }
+#define UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS) \
+UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {return TYPE_AS##_copy((TYPE_AS*) src,(TYPE_AS*)dst); \
+}
+
 
 #define UA_TYPE_METHOD_PROTOTYPES_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_CALCSIZE_AS(TYPE, TYPE_AS) \
@@ -155,7 +160,8 @@ UA_TYPE_METHOD_ENCODEBINARY_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DECODEBINARY_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DELETE_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS)
+UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS) \
+UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS)
 
 
 #define UA_TYPE_METHOD_NEW_DEFAULT(TYPE) \
@@ -172,8 +178,7 @@ UA_Int32 TYPE##_init(TYPE * p){ \
 	*p = (TYPE)0;\
 	return UA_SUCCESS;\
 }
-#define UA_TYPE_COPY_METHOD_PROTOTYPE(TYPE) \
- UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
+//#define UA_TYPE_COPY_METHOD_PROTOTYPE(TYPE) \  UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
 
 
 
@@ -189,18 +194,6 @@ UA_TYPE_METHOD_PROTOTYPES (UA_Int64)
 UA_TYPE_METHOD_PROTOTYPES (UA_UInt64)
 UA_TYPE_METHOD_PROTOTYPES (UA_Float)
 UA_TYPE_METHOD_PROTOTYPES (UA_Double)
-
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_Boolean)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_Byte)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_SByte)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_Int16)
-UA_TYPE_COPY_METHOD_PROTOTYPE (UA_UInt16)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_Int32)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_UInt32)
-UA_TYPE_COPY_METHOD_PROTOTYPE (UA_Int64)
-UA_TYPE_COPY_METHOD_PROTOTYPE (UA_UInt64)
-UA_TYPE_COPY_METHOD_PROTOTYPE(UA_Float)
-UA_TYPE_COPY_METHOD_PROTOTYPE (UA_Double)
 /**
 * StatusCodeBinaryEncoding
 * Part: 6
@@ -224,6 +217,7 @@ typedef struct T_UA_VTable {
 	UA_Int32 (*encodeBinary)(void const * src, UA_Int32* pos, UA_ByteString* dst);
 	UA_Int32 (*init)(void * p);
 	UA_Int32 (*new)(void ** p);
+	UA_Int32 (*copy)(void const *src,void *dst);
 	UA_Int32 (*delete)(void * p);
 	UA_Byte* name;
 } UA_VTable;
@@ -252,7 +246,7 @@ typedef struct T_UA_String
 }
 UA_String;
 UA_TYPE_METHOD_PROTOTYPES (UA_String)
-UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
+//UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
 UA_Int32 UA_String_copycstring(char const * src, UA_String* dst);
 UA_Int32 UA_String_copyprintf(char const * fmt, UA_String* dst, ...);
 UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2);
@@ -263,7 +257,7 @@ void UA_String_printx_hex(char const * label, const UA_String* string);
 /* ByteString - Part: 6, Chapter: 5.2.2.7, Page: 17 */
 UA_TYPE_METHOD_PROTOTYPES (UA_ByteString)
 UA_Int32 UA_ByteString_compare(const UA_ByteString *string1, const UA_ByteString *string2);
-UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
+//UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
 UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length);
 extern UA_ByteString UA_ByteString_securityPoliceNone;
 
@@ -281,6 +275,7 @@ typedef struct T_UA_LocalizedText
 }
 UA_LocalizedText;
 UA_TYPE_METHOD_PROTOTYPES (UA_LocalizedText)
+
 UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst);
 void UA_ByteString_printf(char* label, const UA_ByteString* string);
 void UA_ByteString_printx(char* label, const UA_ByteString* string);
@@ -300,6 +295,7 @@ UA_Int32 UA_Guid_compare(const UA_Guid *g1, const UA_Guid *g2);
 /* DateTime - Part: 6, Chapter: 5.2.2.5, Page: 16 */
 typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
 UA_TYPE_METHOD_PROTOTYPES (UA_DateTime)
+
 UA_DateTime UA_DateTime_now();
 typedef struct T_UA_DateTimeStruct
 {
@@ -332,6 +328,7 @@ typedef struct T_UA_NodeId
     identifier;
 } UA_NodeId;
 UA_TYPE_METHOD_PROTOTYPES (UA_NodeId)
+
 UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2);
 void UA_NodeId_printf(char* label, const UA_NodeId* node);
 
@@ -343,6 +340,7 @@ typedef struct T_UA_XmlElement
 } UA_XmlElement;
 UA_TYPE_METHOD_PROTOTYPES (UA_XmlElement)
 
+
 /* ExpandedNodeId - Part: 6, Chapter: 5.2.2.10, Page: 19 */
 // 62541-6 Chapter 5.2.2.9, Table 5
 #define UA_NODEIDTYPE_NAMESPACE_URI_FLAG 0x80
@@ -361,6 +359,7 @@ UA_TYPE_METHOD_PROTOTYPES(UA_ExpandedNodeId)
 typedef UA_Int32 UA_IdentifierType;
 UA_TYPE_METHOD_PROTOTYPES(UA_IdentifierType)
 
+
 /* ExtensionObjectBinaryEncoding - Part: 6, Chapter: 5.2.2.15, Page: 21 */
 typedef struct T_UA_ExtensionObject {
 	UA_NodeId typeId;

+ 86 - 38
src/ua_basictypes.c

@@ -115,14 +115,14 @@ UA_Int32 UA_Array_copy(void const * const * src, UA_Int32 noElements, UA_Int32 t
 	// Get memory for the pointers
 	CHECKED_DECODE(UA_Array_new(dst, noElements, type), dst = UA_NULL;);
 	void **arr = *dst;
+	UA_Int32 uaIdx = UA_toIndex(type);
+
+	//only namespace zero types atm
+	if(UA_VTable_isValidType(uaIdx) != UA_SUCCESS)
+		return UA_ERROR;
+
 	for(UA_Int32 i=0; i<noElements; i++) {
-		// FIXME: we only have code to do this for strings yet
-		if (type == UA_STRING || type == UA_BYTESTRING) {
-			UA_String_copy((UA_String *)src[i], (UA_String *)arr[i]);
-		} else {
-			retval = UA_ERR_INVALID_VALUE;
-			break;
-		}
+		UA_[type].copy(src[i], arr[i]);
 	}
 	return retval;
 }
@@ -590,9 +590,6 @@ UA_Byte UA_Byte_securityPoliceNoneData[] = "http://opcfoundation.org/UA/Security
 // sizeof()-1 : discard the implicit null-terminator of the c-char-string
 UA_ByteString UA_ByteString_securityPoliceNone = { sizeof(UA_Byte_securityPoliceNoneData)-1, UA_Byte_securityPoliceNoneData };
 
-UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst) {
-	return UA_String_copy((UA_String const*)src,(UA_String*)dst);
-}
 UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length) {
 	UA_Int32 retval = UA_SUCCESS;
 	if ((retval |= UA_alloc((void**)&(p->data),length)) == UA_SUCCESS) {
@@ -649,8 +646,13 @@ UA_Int32 UA_Guid_init(UA_Guid* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Guid)
-UA_TYPE_METHOD_COPY(UA_Guid)
-
+UA_Int32 UA_Guid_copy(UA_Guid const *src, UA_Guid *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)&dst,UA_Guid_calcSize(UA_NULL));
+	retval |= UA_memcpy((void*)dst,(void*)src,UA_Guid_calcSize(UA_NULL));
+	return retval;
+}
 UA_Int32 UA_LocalizedText_calcSize(UA_LocalizedText const * p) {
 	UA_Int32 length = 0;
 	if (p==UA_NULL) {
@@ -668,6 +670,7 @@ UA_Int32 UA_LocalizedText_calcSize(UA_LocalizedText const * p) {
 	}
 	return length;
 }
+
 UA_TYPE_START_ENCODEBINARY(UA_LocalizedText)
 	retval |= UA_Byte_encodeBinary(&(src->encodingMask),pos,dst);
 	if (src->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE) {
@@ -693,10 +696,12 @@ UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const * src, UA_Int32 *pos,
 	}
 	return retval;
 }
+
 UA_TYPE_METHOD_DELETE_STRUCT(UA_LocalizedText)
 UA_Int32 UA_LocalizedText_deleteMembers(UA_LocalizedText* p) {
 	return UA_SUCCESS | UA_String_deleteMembers(&p->locale) | UA_String_deleteMembers(&p->text);
 }
+
 UA_Int32 UA_LocalizedText_init(UA_LocalizedText* p){
 	if(p==UA_NULL) return UA_ERROR;
 	p->encodingMask = 0;
@@ -704,7 +709,9 @@ UA_Int32 UA_LocalizedText_init(UA_LocalizedText* p){
 	UA_String_init(&(p->text));
 	return UA_SUCCESS;
 }
+
 UA_TYPE_METHOD_NEW_DEFAULT(UA_LocalizedText)
+
 UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst) {
 	UA_Int32 retval = UA_SUCCESS;
 	if(dst==UA_NULL) return UA_ERROR;
@@ -716,6 +723,7 @@ UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst) {
 UA_Int32 UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText* dst)
 {
 	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)dst,UA_LocalizedText_calcSize(UA_NULL));
 	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
 	retval |= UA_String_copy(&(src->locale), &(dst->locale));
 	retval |= UA_String_copy(&(src->text), &(dst->text));
@@ -920,10 +928,10 @@ UA_Int32 UA_NodeId_init(UA_NodeId* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_NodeId)
-UA_Int32 UA_NodeId_copy(UA_NodeId *src, UA_NodeId *dst)
+UA_Int32 UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst)
 {
-	UA_Byte_copy(&(src->encodingByte), &(dst->encodingByte));
 	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_Byte_copy(&(src->encodingByte), &(dst->encodingByte));
 
 	switch (src->encodingByte & UA_NODEIDTYPE_MASK) {
 	case UA_NODEIDTYPE_TWOBYTE:
@@ -1000,12 +1008,12 @@ UA_Int32 UA_ExpandedNodeId_init(UA_ExpandedNodeId* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_ExpandedNodeId)
-UA_Int32 UA_ExpandedNodeId_copy(UA_ExpandedNodeId *src, UA_ExpandedNodeId *dst)
+UA_Int32 UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst)
 {
 	UA_Int32 retval = UA_SUCCESS;
-	UA_String_copy(&(src->namespaceUri),&(dst->namespaceUri));
-	UA_NodeId_copy(&(src->nodeId),&(dst->nodeId));
-	UA_UInt32_copy(&(src->serverIndex),&(dst->serverIndex));
+	UA_String_copy(&(src->namespaceUri), &(dst->namespaceUri));
+	UA_NodeId_copy(&(src->nodeId), &(dst->nodeId));
+	UA_UInt32_copy(&(src->serverIndex), &(dst->serverIndex));
 	return retval;
 }
 
@@ -1071,9 +1079,10 @@ UA_Int32 UA_ExtensionObject_init(UA_ExtensionObject* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_ExtensionObject)
-UA_Int32 UA_ExtensionObject_copy(UA_ExtensionObject *src, UA_ExtensionObject *dst)
+UA_Int32 UA_ExtensionObject_copy(UA_ExtensionObject const  *src, UA_ExtensionObject *dst)
 {
 	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ExtensionObject_calcSize(UA_NULL);
 	retval |= UA_Byte_copy(&(src->encoding),&(dst->encoding));
 	retval |= UA_ByteString_copy(&(src->body),&(dst->body));
 	retval |= UA_NodeId_copy(&(src->typeId),&(dst->typeId));
@@ -1207,22 +1216,31 @@ UA_Int32 UA_DiagnosticInfo_init(UA_DiagnosticInfo* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DiagnosticInfo)
-UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo *src, UA_DiagnosticInfo *dst)
+UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo const  *src, UA_DiagnosticInfo *dst)
 {
-	UA_Int32 retval = 0;
+	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_String_copy(&(src->additionalInfo), &(dst->additionalInfo));
 	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
-	retval |= UA_DiagnosticInfo_copy(&(src->innerDiagnosticInfo), &(dst->innerDiagnosticInfo));
-	retval |= UA_String_copy(&(src->innerStatusCode), &(dst->innerStatusCode));
+	retval |= UA_StatusCode_copy(&(src->innerStatusCode), &(dst->innerStatusCode));
+	if(src->innerDiagnosticInfo){
+		retval |= UA_alloc((void**)&(dst->innerDiagnosticInfo),UA_DiagnosticInfo_calcSize(UA_NULL));
+		if(retval == UA_SUCCESS){
+			retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
+		}
+	}
+	else{
+		dst->innerDiagnosticInfo = UA_NULL;
+	}
 	retval |= UA_Int32_copy(&(src->locale), &(dst->locale));
 	retval |= UA_Int32_copy(&(src->localizedText), &(dst->localizedText));
 	retval |= UA_Int32_copy(&(src->namespaceUri), &(dst->namespaceUri));
 	retval |= UA_Int32_copy(&(src->symbolicId), &(dst->symbolicId));
+
 	return retval;
 }
 UA_TYPE_METHOD_PROTOTYPES_AS(UA_DateTime,UA_Int64)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DateTime)
-UA_TYPE_METHOD_COPY(UA_DateTime)
+
 #include <sys/time.h>
 
 // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
@@ -1281,19 +1299,14 @@ UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String* timeString){
 
 UA_TYPE_METHOD_PROTOTYPES_AS(UA_XmlElement, UA_ByteString)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_XmlElement)
-UA_Int32 UA_XmlElement_copy(UA_XmlElement *src, UA_XmlElement *dst)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_copy(&(src->data),&(dst->data));
-	return retval;
-}
+
 /** IntegerId - Part: 4, Chapter: 7.13, Page: 118 */
 UA_TYPE_METHOD_PROTOTYPES_AS(UA_IntegerId, UA_Int32)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_IntegerId)
-UA_TYPE_METHOD_COPY(UA_IntegerId)
+
 UA_TYPE_METHOD_PROTOTYPES_AS(UA_StatusCode, UA_UInt32)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_StatusCode)
-UA_TYPE_METHOD_COPY(UA_StatusCode)
+
 /** QualifiedName - Part 4, Chapter
  * but see Part 6, Chapter 5.2.2.13 for Binary Encoding
  */
@@ -1337,9 +1350,10 @@ UA_Int32 UA_QualifiedName_init(UA_QualifiedName * p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_QualifiedName)
-UA_Int32 UA_QualifiedName_copy(UA_QualifiedName *src, UA_QualifiedName *dst)
+UA_Int32 UA_QualifiedName_copy(UA_QualifiedName const *src, UA_QualifiedName *dst)
 {
 	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)&dst,UA_QualifiedName_calcSize(UA_NULL));
 	retval |= UA_String_copy(&(src->name),&(dst->name));
 	retval |= UA_UInt16_copy(&(src->namespaceIndex),&(dst->namespaceIndex));
 	retval |= UA_UInt16_copy(&(src->reserved),&(dst->reserved));
@@ -1380,6 +1394,7 @@ UA_Int32 UA_Variant_calcSize(UA_Variant const * p) {
 			}
 		} else {
 			length += p->vt->calcSize(p->data[0]);
+
 		}
 	}
 	if (hasDimensions) {
@@ -1449,6 +1464,7 @@ UA_Int32 UA_Variant_decodeBinary(UA_ByteString const * src, UA_Int32 *pos, UA_Va
 	}
 
 	if (dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+
 		// TODO: decode array dimension field
 		printf("shit happens - decode array dimension field wanted");
 	}
@@ -1473,12 +1489,28 @@ UA_Int32 UA_Variant_init(UA_Variant * p){
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Variant)
 
-UA_Int32 UA_Variant_copy(UA_Variant *src, UA_Variant *dst)
+UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst)
 {
-	//UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
-	//UA_Int32_copy(&(src->arrayLength), &(dst->arrayLength));
-	//TODO implement me
-	return UA_ERR_NOT_IMPLEMENTED;
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 ns0Id = dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK;
+	// initialize vTable
+	UA_Int32 uaIdx = UA_toIndex(ns0Id);
+	if(UA_VTable_isValidType(uaIdx) != UA_SUCCESS){
+		return UA_ERROR;
+	}
+	dst->vt = &UA_[uaIdx];
+	retval |= UA_Int32_copy(&(src->arrayLength), &(dst->arrayLength));
+	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+
+	if (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY) {
+
+		retval |=  UA_Array_copy((const void * const *)(src->data),src->arrayLength, uaIdx,(void***)&(dst->data));
+	}
+	else {
+		retval |= src->vt[uaIdx].copy(*src->data,*src->data);
+	}
+
+	return retval;
 }
 
 //TODO: place this define at the server configuration
@@ -1583,6 +1615,19 @@ UA_Int32 UA_DataValue_init(UA_DataValue * p){
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DataValue)
 
+UA_Int32 UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst){
+	UA_Int32 retval = UA_SUCCESS;
+	//TODO can be optimized by direct UA_memcpy call
+	UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+	UA_Int16_copy(&(src->serverPicoseconds),&(dst->serverPicoseconds));
+	UA_DateTime_copy(&(src->serverTimestamp),&(dst->serverTimestamp));
+	UA_Int16_copy(&(src->sourcePicoseconds), &(dst->sourcePicoseconds));
+	UA_DateTime_copy(&(src->sourceTimestamp),&(dst->sourceTimestamp));
+	UA_StatusCode_copy(&(src->status),&(dst->status));
+	UA_Variant_copy(&(src->value),&(dst->value));
+
+	return retval;
+}
 /* UA_InvalidType - internal type necessary to handle inited Variants correctly */
 UA_Int32 UA_InvalidType_calcSize(UA_InvalidType const * p) {
 	return 0;
@@ -1606,6 +1651,9 @@ UA_Int32 UA_InvalidType_deleteMembers(UA_InvalidType* p) {
 UA_Int32 UA_InvalidType_init(UA_InvalidType* p) {
 	return UA_ERR_INVALID_VALUE;
 }
+UA_Int32 UA_InvalidType_copy(UA_InvalidType const* src, UA_InvalidType *dst) {
+	return UA_ERR_INVALID_VALUE;
+}
 UA_Int32 UA_InvalidType_new(UA_InvalidType** p) {
 	return UA_ERR_INVALID_VALUE;
 }

+ 7 - 1
src/ua_transport_binary_secure.c

@@ -167,7 +167,13 @@ UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_Int3
 
 	return retval;
 }
-
+/**
+ *
+ * @param connection
+ * @param msg
+ * @param pos
+ * @return
+ */
 UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_Int32* pos) {
 	DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
 	UA_Int32 retval = UA_SUCCESS;

+ 170 - 7
tests/check_builtin.c

@@ -1,6 +1,6 @@
 /*
  ============================================================================
- Name        : check_stack.c
+ Name        : check_builtin.c
  Author      :
  Copyright   : Your copyright notice
  Description :
@@ -1472,16 +1472,174 @@ START_TEST(UA_DateTime_toStingShallWorkOnExample)
 	ck_assert_int_eq(dst.data[4], '4');
 }
 END_TEST
-START_TEST(UA_Byte_copyShallWorkOnExample)
+START_TEST(UA_ExtensionObject_copyShallWorkOnExample)
 {
-	UA_Byte *dst = UA_NULL;
-	UA_Byte value = 13;
+	UA_ExtensionObject *value = UA_NULL;
+	UA_ExtensionObject *valueCopied = UA_NULL;
+	UA_Int32 i = 0;
+
+	// given
+	UA_Byte data[3] = {1,2,3};
+
+
+	UA_ExtensionObject_new(&value);
+	UA_ExtensionObject_new(&valueCopied);
+
+
+	// empty ExtensionObject, handcoded
+	// when
+	value->typeId.encodingByte = UA_NODEIDTYPE_TWOBYTE;
+	value->typeId.identifier.numeric = 0;
+	value->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED;
+	value->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
+	value->body.data = data;
+	value->body.length = 3;
+
+
+	UA_ExtensionObject_copy(value,valueCopied);
+
+	for(i=0; i<3; i++){
+		ck_assert_int_eq(valueCopied->body.data[i],value->body.data[i]);
+	}
+
+	ck_assert_int_eq(valueCopied->encoding, value->encoding);
+	ck_assert_int_eq(valueCopied->typeId.encodingByte,value->typeId.encodingByte);
+	ck_assert_int_eq(valueCopied->typeId.identifier.numeric,value->typeId.identifier.numeric);
+
+	UA_free(value);
+	UA_free(valueCopied);
+}
+END_TEST
+
+START_TEST(UA_Array_copyByteArrayShallWorkOnExample)
+{
+	UA_String testString;
+	UA_Byte* *srcArray = UA_NULL;
+	UA_Byte** dstArray;
+	UA_Int32 size = 5;
+	UA_Int32 i = 0;
+	testString.data = UA_NULL;
+	UA_alloc((void**)&testString.data, size);
+	UA_alloc((void*)&srcArray,sizeof(UA_Byte*)*5);
+	testString.data[0] = 'O';
+	testString.data[1] = 'P';
+	testString.data[2] = 'C';
+	testString.data[3] = 'U';
+	testString.data[4] = 'A';
+
+	testString.length = 5;
+
+	srcArray[0] = &(testString.data[0]);
+	srcArray[1] = &testString.data[1];
+	srcArray[2] = &testString.data[2];
+	srcArray[3] = &testString.data[3];
+	srcArray[4] = &testString.data[4];
+
+	UA_Array_copy((const void* const*)srcArray,5,UA_BYTE,(void***)&dstArray);
+	for(i=0;i<size;i++){
+		ck_assert_int_eq(*srcArray[i], *dstArray[i]);
+	}
+
+	//UA_free(testString.data);
+	UA_free(*srcArray);
+	UA_free(*dstArray);
+
+}
+END_TEST
+
+START_TEST(UA_Array_copyUA_StringShallWorkOnExample)
+{
+	// given
+	UA_Int32 i,j;
+	UA_String **srcArray; UA_Array_new((void***)&srcArray,3,UA_STRING);
+	UA_String **dstArray;
+	//init
+	UA_String_copycstring("open",srcArray[0]);
+	UA_String_copycstring("62541",srcArray[1]);
+	UA_String_copycstring("opc ua",srcArray[2]);
+    //action
+	UA_Array_copy((void const*const*)srcArray,3,UA_STRING,(void ***)&dstArray);
+	//check
+	for(i=0;i<3;i++){
+		for(j=0;j<3;j++){
+			ck_assert_int_eq(srcArray[i]->data[j], dstArray[i]->data[j]);
+		}
+		ck_assert_int_eq(srcArray[i]->length, dstArray[i]->length);
+	}
+	//clean up
+	UA_free(*srcArray);
+	UA_free(*dstArray);
+
+}
+END_TEST
+
+
+START_TEST(UA_DiagnosticInfo_copyShallWorkOnExample)
+{
+	UA_DiagnosticInfo *value = UA_NULL;
+	UA_DiagnosticInfo *innerValue = UA_NULL;
+	UA_DiagnosticInfo *valueCopied = UA_NULL;
+	UA_String testString;
+	UA_Int32 size = 5;
+	UA_Int32 i = 0;
+	testString.data = UA_NULL;
+
+	UA_alloc((void**)&testString.data,size);
+	testString.data[0] = 'O';
+	testString.data[1] = 'P';
+	testString.data[2] = 'C';
+	testString.data[3] = 'U';
+	testString.data[4] = 'A';
+	testString.length = size;
+
+	UA_DiagnosticInfo_new(&value);
+	UA_DiagnosticInfo_new(&innerValue);
+	value->encodingMask |= UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO;
+	value->innerDiagnosticInfo = innerValue;
+
+	UA_alloc((void**)&valueCopied,UA_DiagnosticInfo_calcSize(UA_NULL));
+	value->additionalInfo.length = testString.length;
+	value->additionalInfo.data = testString.data;
+
+	UA_DiagnosticInfo_copy(value, valueCopied);
+	/*additional info */
+	for(i=0; i<size; i++){
+		ck_assert_int_eq(valueCopied->additionalInfo.data[i],value->additionalInfo.data[i]);
+	}
+	ck_assert_int_eq(valueCopied->additionalInfo.length, value->additionalInfo.length);
+
+	ck_assert_int_eq(valueCopied->encodingMask, value->encodingMask);
+	ck_assert_int_eq(valueCopied->innerDiagnosticInfo->locale,value->innerDiagnosticInfo->locale);
+	ck_assert_int_eq(valueCopied->innerStatusCode,value->innerStatusCode);
+	ck_assert_int_eq(valueCopied->locale,value->locale);
+	ck_assert_int_eq(valueCopied->localizedText,value->localizedText);
+	ck_assert_int_eq(valueCopied->namespaceUri,value->namespaceUri);
+	ck_assert_int_eq(valueCopied->symbolicId,value->symbolicId);
+
+	UA_free(testString.data);
+	UA_free(value);
 
-	UA_Byte_copy(dst,&value);
-	ck_assert_uint_eq(*dst, value);
 }
 END_TEST
+START_TEST(UA_Variant_copyShallWorkOnExample)
+{
+	// given
+	UA_Byte data[] = { UA_INT32_NS0, 0xFF, 0x00, 0x00, 0x00};
+	UA_Variant *value = UA_NULL;
+	UA_Variant *copiedValue = UA_NULL;
+
+	UA_Variant_new(&value);
+	UA_Variant_new(&copiedValue);
+
+	value->arrayLength = 5;
+	value->data = (void**)&data;
+	value->encodingMask = UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
 
+	UA_Variant_copy(value,copiedValue);
+
+	ck_assert_int_eq(value->encodingMask,value->encodingMask);
+}
+END_TEST
 Suite *testSuite_builtin(void)
 {
 	Suite *s = suite_create("Built-in Data Types 62541-6 Table 1");
@@ -1595,7 +1753,12 @@ Suite *testSuite_builtin(void)
 	suite_add_tcase(s,tc_convert);
 
 	TCase *tc_copy = tcase_create("copy");
-	tcase_add_test(tc_copy, UA_Byte_copyShallWorkOnExample);
+	tcase_add_test(tc_copy,UA_Array_copyByteArrayShallWorkOnExample);
+	tcase_add_test(tc_copy,UA_Array_copyUA_StringShallWorkOnExample);
+	tcase_add_test(tc_copy, UA_ExtensionObject_copyShallWorkOnExample);
+	tcase_add_test(tc_copy, UA_Variant_copyShallWorkOnExample);
+	tcase_add_test(tc_copy, UA_DiagnosticInfo_copyShallWorkOnExample);
+	suite_add_tcase(s,tc_copy);
 	return s;
 }
 

+ 20 - 1
tools/generate_builtin.py

@@ -89,6 +89,7 @@ def createEnumerated(element):
     print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_UInt32)", end='\n', file=fc)
     print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_UInt32)", end='\n', file=fc)
     print("UA_TYPE_METHOD_INIT_AS("+name+", UA_UInt32)", end='\n', file=fc)
+    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_UInt32)",'\n', file=fc)  
     print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
     return
     
@@ -139,7 +140,7 @@ def createStructured(element):
     print("UA_Int32 " + name + "_deleteMembers(" + name + "* p);", end='\n', file=fh)
     print("UA_Int32 " + name + "_init("+ name + " * p);", end='\n', file=fh)
     print("UA_Int32 " + name + "_new(" + name + " ** p);", end='\n', file=fh)
-    print("UA_Int32 " + name + "_copy(" + name + " ** p);", end='\n', file=fh)
+    print("UA_Int32 " + name + "_copy(" + name + "* src, " + name + "* dst);", end='\n', file=fh)
 
     print("UA_Int32 "  + name + "_calcSize(" + name + " const * ptr) {", end='', file=fc)
     print("\n\tif(ptr==UA_NULL){return sizeof("+ name +");}", end='', file=fc)
@@ -241,6 +242,22 @@ def createStructured(element):
 
     # code _new
     print("UA_TYPE_METHOD_NEW_DEFAULT(" + name + ")", end='\n', file=fc)
+    # code _copy
+    print("UA_Int32 "+name+"_copy(" + name + " * src," + name + " * dst) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
+    for n,t in valuemap.iteritems():
+        if t in elementary_size:
+            print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
+        else:
+            if t in enum_types:
+                print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
+            elif t.find("**") != -1:
+                print('\tretval |= UA_Int32_copy(&(src->'+n+'Size),&(dst->'+n+'Size)); // size of following array', end='\n', file=fc)
+		print("\tretval |= UA_Array_copy((void const* const*) (src->"+n+"), src->"+n+"Size, UA_" + t[0:t.find("*")].upper()+",(void***)&(dst->"+n+"));", end='\n', file=fc)
+            elif t.find("*") != -1:
+                print('\tretval |= UA_' + t[0:t.find("*")] + '_copy(src->' + n + ',dst->' + n + ');', end='\n', file=fc)
+            else:
+                print('\tretval |= UA_'+t+"_copy(&(src->"+n+"),&(dst->" + n + '));', end='\n', file=fc)
+    print("\treturn retval;\n}\n", end='\n', file=fc)
     
 def createOpaque(element):
     name = "UA_" + element.get("Name")
@@ -257,7 +274,9 @@ def createOpaque(element):
     print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_INIT_AS("+name+", UA_ByteString)", end='\n', file=fc)
+    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
+
     return
 
 ns = {"opc": "http://opcfoundation.org/BinarySchema/"}

+ 2 - 0
tools/generate_namespace.py

@@ -129,6 +129,7 @@ for row in rows2:
           ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
           ",(UA_Int32(*)(void *))"+name+"_init"+
           ",(UA_Int32(*)(void **))"+name+"_new"+
+	  ",(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
           ",(UA_Int32(*)(void *))"+name+"_delete"+
           ',(UA_Byte*)"'+name+'"},',end='\n',file=fc) 
 name = "UA_InvalidType"
@@ -138,6 +139,7 @@ print("\t{0" +
           ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
           ",(UA_Int32(*)(void *))"+name+"_init"+
           ",(UA_Int32(*)(void **))"+name+"_new"+
+	  ",(UA_Int32(*)(void const *, void *))"+name+"_copy"+
           ",(UA_Int32(*)(void *))"+name+"_delete"+
           ',(UA_Byte*)"'+name+'"}',end='\n',file=fc)
 print("};", end='\n', file=fc)