Browse Source

endian agnostic coding resolves #10

Leon Urbas 10 years ago
parent
commit
d5b3f69f88
4 changed files with 144 additions and 44 deletions
  1. 33 35
      src/opcua_basictypes.c
  2. 61 2
      tests/check_builtin.c
  3. 31 3
      tests/check_encode.c
  4. 19 4
      tests/check_stack.c

+ 33 - 35
src/opcua_basictypes.c

@@ -164,14 +164,13 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_SByte)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt16)
 UA_Int32 UA_UInt16_encode(UA_UInt16 const *src, UA_Int32* pos, UA_Byte * dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_UInt16));
-	*pos += sizeof(UA_UInt16);
+	dst[(*pos)++] = (*src & 0x00FF) >> 0;
+	dst[(*pos)++] = (*src & 0xFF00) >> 8;
 	return UA_SUCCESS;
 }
 UA_Int32 UA_UInt16_decode(UA_Byte const * src, UA_Int32* pos, UA_UInt16* dst) {
-	UA_Byte t1 = src[(*pos)++];
-	UA_UInt16 t2 = (UA_UInt16) (src[(*pos)++] << 8);
-	*dst = t1 + t2;
+	*dst =  (UA_UInt16) src[(*pos)++] << 0;
+	*dst |= (UA_UInt16) src[(*pos)++] << 8;
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_DELETE_FREE(UA_UInt16)
@@ -181,14 +180,11 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_UInt16)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int16)
 UA_Int32 UA_Int16_encode(UA_Int16 const * src, UA_Int32* pos, UA_Byte* dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_Int16));
-	*pos += sizeof(UA_Int16);
-	return UA_SUCCESS;
+	return UA_UInt16_encode((UA_UInt16 const *) src,pos,dst);
 }
 UA_Int32 UA_Int16_decode(UA_Byte const * src, UA_Int32* pos, UA_Int16 *dst) {
-	UA_Int16 t1 = (UA_Int16) (((UA_SByte) (src[(*pos)++]) & 0xFF));
-	UA_Int16 t2 = (UA_Int16) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 8);
-	*dst = t1 + t2;
+	*dst  = (UA_Int16) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 0);
+	*dst |= (UA_Int16) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 8);
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_DELETE_FREE(UA_Int16)
@@ -198,16 +194,17 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_Int16)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int32)
 UA_Int32 UA_Int32_encode(UA_Int32 const * src, UA_Int32* pos, UA_Byte* dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_Int32));
-	*pos += sizeof(UA_Int32);
+	dst[(*pos)++] = (*src & 0x000000FF) >> 0;
+	dst[(*pos)++] = (*src & 0x0000FF00) >> 8;
+	dst[(*pos)++] = (*src & 0x00FF0000) >> 16;
+	dst[(*pos)++] = (*src & 0xFF000000) >> 24;
 	return UA_SUCCESS;
 }
 UA_Int32 UA_Int32_decode(UA_Byte const * src, UA_Int32* pos, UA_Int32* dst) {
-	UA_Int32 t1 = (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF));
-	UA_Int32 t2 = (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 8);
-	UA_Int32 t3 = (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 16);
-	UA_Int32 t4 = (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 24);
-	*dst = t1 + t2 + t3 + t4;
+	*dst  = (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 0);
+	*dst |= (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 8);
+	*dst |= (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 16);
+	*dst |= (UA_Int32) (((UA_SByte) (src[(*pos)++]) & 0xFF) << 24);
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_DELETE_FREE(UA_Int32)
@@ -217,9 +214,7 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_Int32)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt32)
 UA_Int32 UA_UInt32_encode(UA_UInt32 const * src, UA_Int32* pos, UA_Byte* dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_UInt32));
-	*pos += sizeof(UA_UInt32);
-	return UA_SUCCESS;
+	return UA_Int32_encode((UA_Int32 const *)src,pos,dst);
 }
 UA_Int32 UA_UInt32_decode(UA_Byte const * src, UA_Int32* pos, UA_UInt32 *dst) {
 	UA_UInt32 t1 = (UA_UInt32)((UA_Byte)(src[(*pos)++] & 0xFF));
@@ -236,20 +231,25 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_UInt32)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int64)
 UA_Int32 UA_Int64_encode(UA_Int64 const * src, UA_Int32* pos, UA_Byte *dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_Int64));
-	*pos += sizeof(UA_Int64);
+	dst[(*pos)++] = (*src & 0x00000000000000FF) >> 0;
+	dst[(*pos)++] = (*src & 0x000000000000FF00) >> 8;
+	dst[(*pos)++] = (*src & 0x0000000000FF0000) >> 16;
+	dst[(*pos)++] = (*src & 0x00000000FF000000) >> 24;
+	dst[(*pos)++] = (*src & 0x000000FF00000000) >> 32;
+	dst[(*pos)++] = (*src & 0x0000FF0000000000) >> 40;
+	dst[(*pos)++] = (*src & 0x00FF000000000000) >> 48;
+	dst[(*pos)++] = (*src & 0xFF00000000000000) >> 56;
 	return UA_SUCCESS;
 }
 UA_Int32 UA_Int64_decode(UA_Byte const * src, UA_Int32* pos, UA_Int64* dst) {
-	UA_Int64 t1 = (UA_Int64) src[(*pos)++];
-	UA_Int64 t2 = (UA_Int64) src[(*pos)++] << 8;
-	UA_Int64 t3 = (UA_Int64) src[(*pos)++] << 16;
-	UA_Int64 t4 = (UA_Int64) src[(*pos)++] << 24;
-	UA_Int64 t5 = (UA_Int64) src[(*pos)++] << 32;
-	UA_Int64 t6 = (UA_Int64) src[(*pos)++] << 40;
-	UA_Int64 t7 = (UA_Int64) src[(*pos)++] << 48;
-	UA_Int64 t8 = (UA_Int64) src[(*pos)++] << 56;
-	*dst = t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8;
+	*dst  = (UA_Int64) src[(*pos)++] << 0;
+	*dst |= (UA_Int64) src[(*pos)++] << 8;
+	*dst |= (UA_Int64) src[(*pos)++] << 16;
+	*dst |= (UA_Int64) src[(*pos)++] << 24;
+	*dst |= (UA_Int64) src[(*pos)++] << 32;
+	*dst |= (UA_Int64) src[(*pos)++] << 40;
+	*dst |= (UA_Int64) src[(*pos)++] << 48;
+	*dst |= (UA_Int64) src[(*pos)++] << 56;
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_DELETE_FREE(UA_Int64)
@@ -259,9 +259,7 @@ UA_TYPE_METHOD_NEW_DEFAULT(UA_Int64)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt64)
 UA_Int32 UA_UInt64_encode(UA_UInt64 const * src , UA_Int32* pos, UA_Byte * dst) {
-	memcpy(&(dst[*pos]), src, sizeof(UA_UInt64));
-	*pos += sizeof(UA_UInt64);
-	return UA_SUCCESS;
+	return UA_Int64_encode((UA_Int64 const *)src,pos,dst);
 }
 UA_Int32 UA_UInt64_decode(UA_Byte const * src, UA_Int32* pos, UA_UInt64* dst) {
 	UA_UInt64 t1 = (UA_UInt64) src[(*pos)++];

+ 61 - 2
tests/check_builtin.c

@@ -576,8 +576,8 @@ START_TEST(UA_UInt16_decodeShallNotRespectSign)
 	// given
 	UA_Int32 pos = 0;
 	UA_Byte src[] = {
-			0xFF,0xFF,	// -1
-			0x00,0x80,	// -32768
+			0xFF,0xFF,	// (2^16)-1
+			0x00,0x80,	// (2^15)
 	};
 	// when
 	UA_UInt16 val_ff_ff, val_00_80;
@@ -590,6 +590,62 @@ START_TEST(UA_UInt16_decodeShallNotRespectSign)
 	ck_assert_uint_eq(val_00_80, (0x01 << 15));
 }
 END_TEST
+START_TEST(UA_Int32_decodeShallAssumeLittleEndian)
+{
+	// given
+	UA_Int32 pos = 0;
+	UA_Byte src[] = {
+			0x01,0x00,0x00,0x00,	// 1
+			0x00,0x01,0x00,0x00		// 256
+	};
+	// when
+	UA_Int32 val_01_00, val_00_01;
+	UA_Int32 retval = UA_Int32_decode(src,&pos,&val_01_00);
+	retval |= UA_Int32_decode(src,&pos,&val_00_01);
+	// then
+	ck_assert_int_eq(retval,UA_SUCCESS);
+	ck_assert_int_eq(val_01_00,1);
+	ck_assert_int_eq(val_00_01,256);
+	ck_assert_int_eq(pos,8);
+}
+END_TEST
+START_TEST(UA_Int32_decodeShallRespectSign)
+{
+	// given
+	UA_Int32 pos = 0;
+	UA_Byte src[] = {
+			0xFF,0xFF,0xFF,0xFF,	// -1
+			0x00,0x80,0xFF,0xFF		// -32768
+	};
+	// when
+	UA_Int32 val_ff_ff, val_00_80;
+	UA_Int32 retval = UA_Int32_decode(src,&pos,&val_ff_ff);
+	retval |= UA_Int32_decode(src,&pos,&val_00_80);
+	// then
+	ck_assert_int_eq(retval,UA_SUCCESS);
+	ck_assert_int_eq(val_ff_ff,-1);
+	ck_assert_int_eq(val_00_80,-32768);
+}
+END_TEST
+START_TEST(UA_UInt32_decodeShallNotRespectSign)
+{
+	// given
+	UA_Int32 pos = 0;
+	UA_Byte src[] = {
+			0xFF,0xFF,0xFF,0xFF,	// (2^32)-1
+			0x00,0x00,0x00,0x80		// (2^31)
+	};
+	// when
+	UA_UInt32 val_ff_ff, val_00_80;
+	UA_Int32 retval = UA_UInt32_decode(src,&pos,&val_ff_ff);
+	retval |= UA_UInt32_decode(src,&pos,&val_00_80);
+	// then
+	ck_assert_int_eq(retval,UA_SUCCESS);
+	ck_assert_int_eq(pos,8);
+	ck_assert_uint_eq(val_ff_ff, (UA_UInt32) ( (0x01LL << 32 ) - 1 ));
+	ck_assert_uint_eq(val_00_80, (UA_UInt32) (0x01 << 31));
+}
+END_TEST
 START_TEST(UA_String_decodeShallAllocateMemoryAndCopyString)
 {
 	// given
@@ -836,6 +892,9 @@ Suite *testSuite_builtin(void)
 	tcase_add_test(tc_decode, UA_Int16_decodeShallAssumeLittleEndian);
 	tcase_add_test(tc_decode, UA_Int16_decodeShallRespectSign);
 	tcase_add_test(tc_decode, UA_UInt16_decodeShallNotRespectSign);
+	tcase_add_test(tc_decode, UA_Int32_decodeShallAssumeLittleEndian);
+	tcase_add_test(tc_decode, UA_Int32_decodeShallRespectSign);
+	tcase_add_test(tc_decode, UA_UInt32_decodeShallNotRespectSign);
 	tcase_add_test(tc_decode, UA_String_decodeShallAllocateMemoryAndCopyString);
 	tcase_add_test(tc_decode, UA_String_decodeWithNegativeSizeShallNotAllocateMemoryAndNullPtr);
 	tcase_add_test(tc_decode, UA_String_decodeWithZeroSizeShallNotAllocateMemoryAndNullPtr);

+ 31 - 3
tests/check_encode.c

@@ -106,9 +106,36 @@ START_TEST(encodeUInt32_test)
 
 }
 END_TEST
-START_TEST(encodeInt32_test)
+START_TEST(encodeInt32ShallEncodeLittleEndian)
 {
-
+	// given
+	UA_Int32 value = 0x01020304;
+	UA_Byte  buf[4];
+	UA_Int32 p = 0;
+	// when
+	UA_Int32_encode(&value,&p,buf);
+	// then
+	ck_assert_int_eq(p,4);
+	ck_assert_uint_eq(buf[0],0x04);
+	ck_assert_uint_eq(buf[1],0x03);
+	ck_assert_uint_eq(buf[2],0x02);
+	ck_assert_uint_eq(buf[3],0x01);
+}
+END_TEST
+START_TEST(encodeInt32NegativeShallEncodeLittleEndian)
+{
+	// given
+	UA_Int32 value = -1;
+	UA_Byte  buf[4];
+	UA_Int32 p = 0;
+	// when
+	UA_Int32_encode(&value,&p,buf);
+	// then
+	ck_assert_int_eq(p,4);
+	ck_assert_uint_eq(buf[0],0xFF);
+	ck_assert_uint_eq(buf[1],0xFF);
+	ck_assert_uint_eq(buf[2],0xFF);
+	ck_assert_uint_eq(buf[3],0xFF);
 }
 END_TEST
 START_TEST(encodeUInt64_test)
@@ -294,7 +321,8 @@ Suite*testSuite_encodeInt32(void)
 {
 	Suite *s = suite_create("encodeInt32_test");
 	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, encodeInt32_test);
+	tcase_add_test(tc_core, encodeInt32ShallEncodeLittleEndian);
+	tcase_add_test(tc_core, encodeInt32NegativeShallEncodeLittleEndian);
 	suite_add_tcase(s,tc_core);
 	return s;
 }

+ 19 - 4
tests/check_stack.c

@@ -65,7 +65,6 @@ START_TEST(encode_builtInDatatypeArray_test_String)
 	UA_ByteString s2 = { -1, UA_NULL };
 	UA_ByteString* array[] = { &s1, &s2	};
 	UA_Int32 pos = 0;
-	UA_UInt32 i;
 	UA_Byte buf[256];
 	UA_Byte result[] = {
 			0x02, 0x00, 0x00, 0x00,		// noElements
@@ -78,10 +77,26 @@ START_TEST(encode_builtInDatatypeArray_test_String)
 
 	// check size
 	ck_assert_int_eq(pos, 4 + 4 + 6 + 4);
+	ck_assert_int_eq(pos, sizeof(result));
 	// check result
-	for (i=0; i < sizeof(result); i++) {
-		ck_assert_int_eq(buf[i],result[i]);
-	}
+	ck_assert_int_eq(buf[0],result[0]);
+	ck_assert_int_eq(buf[1],result[1]);
+	ck_assert_int_eq(buf[2],result[2]);
+	ck_assert_int_eq(buf[3],result[3]);
+	ck_assert_int_eq(buf[4],result[4]);
+	ck_assert_int_eq(buf[5],result[5]);
+	ck_assert_int_eq(buf[6],result[6]);
+	ck_assert_int_eq(buf[7],result[7]);
+	ck_assert_int_eq(buf[8],result[8]);
+	ck_assert_int_eq(buf[9],result[9]);
+	ck_assert_int_eq(buf[10],result[10]);
+	ck_assert_int_eq(buf[11],result[11]);
+	ck_assert_int_eq(buf[12],result[12]);
+	ck_assert_int_eq(buf[13],result[13]);
+	ck_assert_int_eq(buf[14],result[14]);
+	ck_assert_int_eq(buf[15],result[15]);
+	ck_assert_int_eq(buf[16],result[16]);
+	ck_assert_int_eq(buf[17],result[17]);
 }
 END_TEST