ua_types_encoding_binary.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. #include "ua_types_encoding_binary.h"
  2. #include "ua_namespace_0.h"
  3. static INLINE UA_Boolean is_builtin(UA_NodeId *typeid) {
  4. return (typeid->namespace == 0 && 1 <= typeid->identifier.numeric && typeid->identifier.numeric <= 25);
  5. }
  6. /*********/
  7. /* Array */
  8. /*********/
  9. UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_VTable_Entry *vt, const void *data) {
  10. if(vt == UA_NULL)
  11. return 0; // do not return error as the result will be used to allocate memory
  12. if(data == UA_NULL) //NULL Arrays are encoded as length = -1
  13. return sizeof(UA_Int32);
  14. UA_Int32 length = sizeof(UA_Int32);
  15. UA_UInt32 memSize = vt->memSize;
  16. const UA_Byte *cdata = (const UA_Byte *)data;
  17. for(UA_Int32 i = 0;i < nElements;i++) {
  18. length += vt->encodings[UA_ENCODING_BINARY].calcSize(cdata);
  19. cdata += memSize;
  20. }
  21. return length;
  22. }
  23. static UA_Int32 UA_Array_calcSizeBinary_asExtensionObject(UA_Int32 nElements, UA_VTable_Entry *vt, const void *data) {
  24. if(vt == UA_NULL)
  25. return 0; // do not return error as the result will be used to allocate memory
  26. if(data == UA_NULL) //NULL Arrays are encoded as length = -1
  27. return sizeof(UA_Int32);
  28. UA_Int32 length = sizeof(UA_Int32);
  29. UA_UInt32 memSize = vt->memSize;
  30. UA_Boolean isBuiltin = is_builtin(&vt->typeId);
  31. const UA_Byte *cdata = (const UA_Byte *)data;
  32. for(UA_Int32 i = 0;i < nElements;i++) {
  33. length += vt->encodings[UA_ENCODING_BINARY].calcSize(cdata);
  34. cdata += memSize;
  35. }
  36. if(isBuiltin)
  37. length += 9*nElements; // extensionobject header for each element
  38. return length;
  39. }
  40. UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, UA_ByteString *dst, UA_UInt32 *offset) {
  41. UA_Int32 retval = UA_SUCCESS;
  42. if(vt == UA_NULL || dst == UA_NULL || offset == UA_NULL || ((src == UA_NULL) && (noElements > 0)))
  43. return UA_ERROR;
  44. //Null Arrays are encoded with length = -1 // part 6 - §5.24
  45. if(noElements < -1)
  46. noElements = -1;
  47. retval = UA_Int32_encodeBinary(&noElements, dst, offset);
  48. const UA_Byte *csrc = (const UA_Byte *)src;
  49. UA_UInt32 memSize = vt->memSize;
  50. for(UA_Int32 i = 0;i < noElements && retval == UA_SUCCESS;i++) {
  51. retval |= vt->encodings[UA_ENCODING_BINARY].encode(csrc, dst, offset);
  52. csrc += memSize;
  53. }
  54. return retval;
  55. }
  56. static UA_Int32 UA_Array_encodeBinary_asExtensionObject(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt,
  57. UA_ByteString *dst, UA_UInt32 *offset) {
  58. UA_Int32 retval = UA_SUCCESS;
  59. if(vt == UA_NULL || dst == UA_NULL || offset == UA_NULL || (src == UA_NULL && noElements > 0))
  60. return UA_ERROR;
  61. //Null Arrays are encoded with length = -1 // part 6 - §5.24
  62. if(noElements < -1)
  63. noElements = -1;
  64. retval = UA_Int32_encodeBinary(&noElements, dst, offset);
  65. const UA_Byte *csrc = (const UA_Byte *)src;
  66. UA_UInt32 memSize = vt->memSize;
  67. UA_Boolean isBuiltin = is_builtin(&vt->typeId);
  68. for(UA_Int32 i = 0;i < noElements && retval == UA_SUCCESS;i++) {
  69. if(!isBuiltin) {
  70. // print the extensionobject header
  71. UA_NodeId_encodeBinary(&vt->typeId, dst, offset);
  72. UA_Byte eoEncoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
  73. UA_Byte_encodeBinary(&eoEncoding, dst, offset);
  74. UA_Int32 eoEncodingLength = vt->encodings[UA_ENCODING_BINARY].calcSize(csrc);
  75. UA_Int32_encodeBinary(&eoEncodingLength, dst, offset);
  76. }
  77. retval |= vt->encodings[UA_ENCODING_BINARY].encode(csrc, dst, offset);
  78. csrc += memSize;
  79. }
  80. return retval;
  81. }
  82. UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements, UA_VTable_Entry *vt,
  83. void **dst) {
  84. UA_Int32 retval = UA_SUCCESS;
  85. if(vt == UA_NULL || src == UA_NULL || dst == UA_NULL || offset == UA_NULL)
  86. return UA_ERROR;
  87. if(noElements <= 0) {
  88. *dst = UA_NULL;
  89. return retval;
  90. }
  91. retval |= UA_Array_new(dst, noElements, vt);
  92. UA_Byte *arr = (UA_Byte *)*dst;
  93. UA_Int32 i = 0;
  94. UA_UInt32 memSize = vt->memSize;
  95. for(;i < noElements && retval == UA_SUCCESS;i++) {
  96. retval |= vt->encodings[UA_ENCODING_BINARY].decode(src, offset, arr);
  97. arr += memSize;
  98. }
  99. /* If dynamically sized elements have already been decoded into the array. */
  100. if(retval != UA_SUCCESS) {
  101. i--; // undo last increase
  102. UA_Array_delete(*dst, i, vt);
  103. *dst = UA_NULL;
  104. }
  105. return retval;
  106. }
  107. /************/
  108. /* Built-In */
  109. /************/
  110. #define UA_TYPE_CALCSIZEBINARY_SIZEOF(TYPE) \
  111. UA_Int32 TYPE##_calcSizeBinary(TYPE const *p) { return sizeof(TYPE); }
  112. #define UA_TYPE_ENCODEBINARY(TYPE, CODE) \
  113. UA_Int32 TYPE##_encodeBinary(TYPE const *src, UA_ByteString * dst, UA_UInt32 *offset) { \
  114. UA_Int32 retval = UA_SUCCESS; \
  115. if((UA_Int32)(*offset + TYPE##_calcSizeBinary(src)) > dst->length ) { \
  116. return UA_ERR_INVALID_VALUE; \
  117. } else { \
  118. CODE \
  119. } \
  120. return retval; \
  121. }
  122. // Attention! this macro works only for TYPEs with memSize = encodingSize
  123. #define UA_TYPE_DECODEBINARY(TYPE, CODE) \
  124. UA_Int32 TYPE##_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, TYPE * dst) { \
  125. UA_Int32 retval = UA_SUCCESS; \
  126. if((UA_Int32)(*offset + TYPE##_calcSizeBinary(UA_NULL)) > src->length ) { \
  127. return UA_ERR_INVALID_VALUE; \
  128. } else { \
  129. CODE \
  130. } \
  131. return retval; \
  132. }
  133. /* Boolean */
  134. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Boolean)
  135. UA_TYPE_ENCODEBINARY(UA_Boolean,
  136. UA_Boolean tmpBool = ((*src > 0) ? UA_TRUE : UA_FALSE);
  137. memcpy(&dst->data[(*offset)++], &tmpBool, sizeof(UA_Boolean)); )
  138. UA_TYPE_DECODEBINARY(UA_Boolean, *dst = ((UA_Boolean)(src->data[(*offset)++]) > (UA_Byte)0) ? UA_TRUE : UA_FALSE; )
  139. /* SByte */
  140. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_SByte)
  141. UA_TYPE_ENCODEBINARY(UA_SByte, dst->data[(*offset)++] = *src; )
  142. UA_TYPE_DECODEBINARY(UA_SByte, *dst = src->data[(*offset)++]; )
  143. /* Byte */
  144. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Byte)
  145. UA_TYPE_ENCODEBINARY(UA_Byte, dst->data[(*offset)++] = *src; )
  146. UA_TYPE_DECODEBINARY(UA_Byte, *dst = src->data[(*offset)++]; )
  147. /* Int16 */
  148. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int16)
  149. UA_TYPE_ENCODEBINARY(UA_Int16, retval = UA_UInt16_encodeBinary((UA_UInt16 const *)src, dst, offset); )
  150. UA_TYPE_DECODEBINARY(UA_Int16,
  151. *dst = (UA_Int16)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 0);
  152. *dst |= (UA_Int16)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 8); )
  153. /* UInt16 */
  154. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt16)
  155. UA_TYPE_ENCODEBINARY(UA_UInt16,
  156. dst->data[(*offset)++] = (*src & 0x00FF) >> 0;
  157. dst->data[(*offset)++] = (*src & 0xFF00) >> 8; )
  158. UA_TYPE_DECODEBINARY(UA_UInt16,
  159. *dst = (UA_UInt16)src->data[(*offset)++] << 0;
  160. *dst |= (UA_UInt16)src->data[(*offset)++] << 8; )
  161. /* Int32 */
  162. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int32)
  163. UA_TYPE_ENCODEBINARY(UA_Int32,
  164. dst->data[(*offset)++] = (*src & 0x000000FF) >> 0;
  165. dst->data[(*offset)++] = (*src & 0x0000FF00) >> 8;
  166. dst->data[(*offset)++] = (*src & 0x00FF0000) >> 16;
  167. dst->data[(*offset)++] = (*src & 0xFF000000) >> 24; )
  168. UA_TYPE_DECODEBINARY(UA_Int32,
  169. *dst = (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 0);
  170. *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 8);
  171. *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 16);
  172. *dst |= (UA_Int32)(((UA_SByte)(src->data[(*offset)++]) & 0xFF) << 24); )
  173. /* UInt32 */
  174. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt32)
  175. UA_TYPE_ENCODEBINARY(UA_UInt32, retval = UA_Int32_encodeBinary((UA_Int32 const *)src, dst, offset); )
  176. UA_TYPE_DECODEBINARY(UA_UInt32,
  177. UA_UInt32 t1 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++] & 0xFF));
  178. UA_UInt32 t2 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 8);
  179. UA_UInt32 t3 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 16);
  180. UA_UInt32 t4 = (UA_UInt32)((UA_Byte)(src->data[(*offset)++]& 0xFF) << 24);
  181. *dst = t1 + t2 + t3 + t4; )
  182. /* Int64 */
  183. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Int64)
  184. UA_TYPE_ENCODEBINARY(UA_Int64,
  185. dst->data[(*offset)++] = (*src & 0x00000000000000FF) >> 0;
  186. dst->data[(*offset)++] = (*src & 0x000000000000FF00) >> 8;
  187. dst->data[(*offset)++] = (*src & 0x0000000000FF0000) >> 16;
  188. dst->data[(*offset)++] = (*src & 0x00000000FF000000) >> 24;
  189. dst->data[(*offset)++] = (*src & 0x000000FF00000000) >> 32;
  190. dst->data[(*offset)++] = (*src & 0x0000FF0000000000) >> 40;
  191. dst->data[(*offset)++] = (*src & 0x00FF000000000000) >> 48;
  192. dst->data[(*offset)++] = (*src & 0xFF00000000000000) >> 56; )
  193. UA_TYPE_DECODEBINARY(UA_Int64,
  194. *dst = (UA_Int64)src->data[(*offset)++] << 0;
  195. *dst |= (UA_Int64)src->data[(*offset)++] << 8;
  196. *dst |= (UA_Int64)src->data[(*offset)++] << 16;
  197. *dst |= (UA_Int64)src->data[(*offset)++] << 24;
  198. *dst |= (UA_Int64)src->data[(*offset)++] << 32;
  199. *dst |= (UA_Int64)src->data[(*offset)++] << 40;
  200. *dst |= (UA_Int64)src->data[(*offset)++] << 48;
  201. *dst |= (UA_Int64)src->data[(*offset)++] << 56; )
  202. /* UInt64 */
  203. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_UInt64)
  204. UA_TYPE_ENCODEBINARY(UA_UInt64, return UA_Int64_encodeBinary((UA_Int64 const *)src, dst, offset); )
  205. UA_TYPE_DECODEBINARY(UA_UInt64,
  206. UA_UInt64 t1 = (UA_UInt64)src->data[(*offset)++];
  207. UA_UInt64 t2 = (UA_UInt64)src->data[(*offset)++] << 8;
  208. UA_UInt64 t3 = (UA_UInt64)src->data[(*offset)++] << 16;
  209. UA_UInt64 t4 = (UA_UInt64)src->data[(*offset)++] << 24;
  210. UA_UInt64 t5 = (UA_UInt64)src->data[(*offset)++] << 32;
  211. UA_UInt64 t6 = (UA_UInt64)src->data[(*offset)++] << 40;
  212. UA_UInt64 t7 = (UA_UInt64)src->data[(*offset)++] << 48;
  213. UA_UInt64 t8 = (UA_UInt64)src->data[(*offset)++] << 56;
  214. *dst = t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8; )
  215. /* Float */
  216. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Float)
  217. // FIXME: Implement NaN, Inf and Zero(s)
  218. UA_Byte UA_FLOAT_ZERO[] = { 0x00, 0x00, 0x00, 0x00 };
  219. UA_TYPE_DECODEBINARY(UA_Float,
  220. UA_Float mantissa;
  221. UA_UInt32 biasedExponent;
  222. UA_Float sign;
  223. if(memcmp(&src->data[*offset], UA_FLOAT_ZERO,
  224. 4) == 0) return UA_Int32_decodeBinary(src, offset, (UA_Int32 *)dst);
  225. mantissa = (UA_Float)(src->data[*offset] & 0xFF); // bits 0-7
  226. mantissa = (mantissa / 256.0 ) + (UA_Float)(src->data[*offset+1] & 0xFF); // bits 8-15
  227. mantissa = (mantissa / 256.0 ) + (UA_Float)(src->data[*offset+2] & 0x7F); // bits 16-22
  228. biasedExponent = (src->data[*offset+2] & 0x80) >> 7; // bits 23
  229. biasedExponent |= (src->data[*offset+3] & 0x7F) << 1; // bits 24-30
  230. sign = ( src->data[*offset+ 3] & 0x80 ) ? -1.0 : 1.0; // bit 31
  231. if(biasedExponent >= 127)
  232. *dst = (UA_Float)sign * (1 << (biasedExponent-127)) * (1.0 + mantissa / 128.0 );
  233. else
  234. *dst = (UA_Float)sign * 2.0 * (1.0 + mantissa / 128.0 ) / ((UA_Float)(biasedExponent-127));
  235. *offset += 4; )
  236. UA_TYPE_ENCODEBINARY(UA_Float, return UA_UInt32_encodeBinary((UA_UInt32 *)src, dst, offset); )
  237. /* Double */
  238. UA_TYPE_CALCSIZEBINARY_SIZEOF(UA_Double)
  239. // FIXME: Implement NaN, Inf and Zero(s)
  240. UA_Byte UA_DOUBLE_ZERO[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  241. UA_TYPE_DECODEBINARY(UA_Double,
  242. UA_Double sign;
  243. UA_Double mantissa;
  244. UA_UInt32 biasedExponent;
  245. if(memcmp(&src->data[*offset], UA_DOUBLE_ZERO,
  246. 8) == 0) return UA_Int64_decodeBinary(src, offset, (UA_Int64 *)dst);
  247. mantissa = (UA_Double)(src->data[*offset] & 0xFF); // bits 0-7
  248. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+1] & 0xFF); // bits 8-15
  249. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+2] & 0xFF); // bits 16-23
  250. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+3] & 0xFF); // bits 24-31
  251. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+4] & 0xFF); // bits 32-39
  252. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+5] & 0xFF); // bits 40-47
  253. mantissa = (mantissa / 256.0 ) + (UA_Double)(src->data[*offset+6] & 0x0F); // bits 48-51
  254. DBG_VERBOSE(printf("UA_Double_decodeBinary - mantissa=%f\n", mantissa));
  255. biasedExponent = (src->data[*offset+6] & 0xF0) >> 4; // bits 52-55
  256. DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent52-55=%d, src=%d\n", biasedExponent,
  257. src->data[*offset+6]));
  258. biasedExponent |= ((UA_UInt32)(src->data[*offset+7] & 0x7F)) << 4; // bits 56-62
  259. DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent56-62=%d, src=%d\n", biasedExponent,
  260. src->data[*offset+7]));
  261. sign = ( src->data[*offset+7] & 0x80 ) ? -1.0 : 1.0; // bit 63
  262. if(biasedExponent >= 1023)
  263. *dst = (UA_Double)sign * (1 << (biasedExponent-1023)) * (1.0 + mantissa / 8.0 );
  264. else
  265. *dst = (UA_Double)sign * 2.0 * (1.0 + mantissa / 8.0 ) / ((UA_Double)(biasedExponent-1023));
  266. *offset += 8; )
  267. UA_TYPE_ENCODEBINARY(UA_Double, return UA_UInt64_encodeBinary((UA_UInt64 *)src, dst, offset); )
  268. /* String */
  269. UA_Int32 UA_String_calcSizeBinary(UA_String const *string) {
  270. if(string == UA_NULL) // internal size for UA_memalloc
  271. return sizeof(UA_String);
  272. else { // binary encoding size
  273. if(string->length > 0)
  274. return sizeof(UA_Int32) + string->length * sizeof(UA_Byte);
  275. else
  276. return sizeof(UA_Int32);
  277. }
  278. }
  279. UA_Int32 UA_String_encodeBinary(UA_String const *src, UA_ByteString *dst, UA_UInt32 *offset) {
  280. UA_Int32 retval = UA_SUCCESS;
  281. if(src == UA_NULL)
  282. return UA_ERR_INVALID_VALUE;
  283. if((UA_Int32)(*offset+ UA_String_calcSizeBinary(src)) > dst->length)
  284. return UA_ERR_INVALID_VALUE;
  285. retval |= UA_Int32_encodeBinary(&src->length, dst, offset);
  286. if(src->length > 0) {
  287. retval |= UA_memcpy(&dst->data[*offset], src->data, src->length);
  288. *offset += src->length;
  289. }
  290. return retval;
  291. }
  292. UA_Int32 UA_String_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_String *dst) {
  293. UA_Int32 retval = UA_SUCCESS;
  294. UA_String_init(dst);
  295. retval |= UA_Int32_decodeBinary(src, offset, &dst->length);
  296. if(dst->length > (UA_Int32)(src->length - *offset))
  297. retval = UA_ERR_INVALID_VALUE;
  298. if(retval != UA_SUCCESS || dst->length <= 0) {
  299. dst->length = -1;
  300. dst->data = UA_NULL;
  301. } else {
  302. CHECKED_DECODE(UA_alloc((void **)&dst->data, dst->length), dst->length = -1);
  303. CHECKED_DECODE(UA_memcpy(dst->data, &src->data[*offset], dst->length), UA_free(
  304. dst->data); dst->data = UA_NULL; dst->length = -1);
  305. *offset += dst->length;
  306. }
  307. return retval;
  308. }
  309. /* DateTime */
  310. UA_TYPE_BINARY_ENCODING_AS(UA_DateTime, UA_Int64)
  311. /* Guid */
  312. UA_Int32 UA_Guid_calcSizeBinary(UA_Guid const *p) {
  313. return 16;
  314. }
  315. UA_TYPE_ENCODEBINARY(UA_Guid,
  316. CHECKED_DECODE(UA_UInt32_encodeBinary(&src->data1, dst, offset),; );
  317. CHECKED_DECODE(UA_UInt16_encodeBinary(&src->data2, dst, offset),; );
  318. CHECKED_DECODE(UA_UInt16_encodeBinary(&src->data3, dst, offset),; );
  319. for(UA_Int32 i = 0;i < 8;i++)
  320. CHECKED_DECODE(UA_Byte_encodeBinary(&src->data4[i], dst, offset),; ); )
  321. UA_TYPE_DECODEBINARY(UA_Guid,
  322. // TODO: This could be done with a single memcpy (if the compiler does no fancy realigning of structs)
  323. CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->data1),; );
  324. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data2),; );
  325. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->data3),; );
  326. for(UA_Int32 i = 0;i < 8;i++)
  327. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->data4[i]),; ); )
  328. /* ByteString */
  329. UA_TYPE_BINARY_ENCODING_AS(UA_ByteString, UA_String)
  330. /* XmlElement */
  331. UA_TYPE_BINARY_ENCODING_AS(UA_XmlElement, UA_String)
  332. /* NodeId */
  333. /* The shortened numeric nodeid types. */
  334. #define UA_NODEIDTYPE_TWOBYTE 0
  335. #define UA_NODEIDTYPE_FOURBYTE 1
  336. UA_Int32 UA_NodeId_calcSizeBinary(UA_NodeId const *p) {
  337. UA_Int32 length = 0;
  338. if(p == UA_NULL)
  339. length = sizeof(UA_NodeId);
  340. else {
  341. switch(p->nodeIdType) {
  342. case UA_NODEIDTYPE_NUMERIC:
  343. if(p->identifier.numeric > UA_UINT16_MAX || p->namespace > UA_BYTE_MAX)
  344. length = sizeof(UA_Byte) + sizeof(UA_UInt16) + sizeof(UA_UInt32);
  345. else if(p->identifier.numeric > UA_BYTE_MAX || p->namespace > 0)
  346. length = 4; /* UA_NODEIDTYPE_FOURBYTE */
  347. else
  348. length = 2; /* UA_NODEIDTYPE_TWOBYTE*/
  349. break;
  350. case UA_NODEIDTYPE_STRING:
  351. length = sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_String_calcSizeBinary(&p->identifier.string);
  352. break;
  353. case UA_NODEIDTYPE_GUID:
  354. length = sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_Guid_calcSizeBinary(&p->identifier.guid);
  355. break;
  356. case UA_NODEIDTYPE_BYTESTRING:
  357. length = sizeof(UA_Byte) + sizeof(UA_UInt16) + UA_ByteString_calcSizeBinary(&p->identifier.byteString);
  358. break;
  359. default:
  360. break; // calcSize does not return errors. But the encoding function will.
  361. }
  362. }
  363. return length;
  364. }
  365. UA_TYPE_ENCODEBINARY(UA_NodeId,
  366. // temporary variables for endian-save code
  367. UA_Byte srcByte;
  368. UA_UInt16 srcUInt16;
  369. UA_Int32 retval = UA_SUCCESS;
  370. switch(src->nodeIdType) {
  371. case UA_NODEIDTYPE_NUMERIC:
  372. if(src->identifier.numeric > UA_UINT16_MAX || src->namespace > UA_BYTE_MAX) {
  373. srcByte = UA_NODEIDTYPE_NUMERIC;
  374. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  375. retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
  376. retval |= UA_UInt32_encodeBinary(&src->identifier.numeric, dst, offset);
  377. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespace > 0) { /* UA_NODEIDTYPE_FOURBYTE */
  378. srcByte = UA_NODEIDTYPE_FOURBYTE;
  379. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  380. srcByte = src->namespace;
  381. srcUInt16 = src->identifier.numeric;
  382. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  383. retval |= UA_UInt16_encodeBinary(&srcUInt16, dst, offset);
  384. } else { /* UA_NODEIDTYPE_TWOBYTE */
  385. srcByte = UA_NODEIDTYPE_TWOBYTE;
  386. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  387. srcByte = src->identifier.numeric;
  388. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  389. }
  390. break;
  391. case UA_NODEIDTYPE_STRING:
  392. srcByte = UA_NODEIDTYPE_STRING;
  393. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  394. retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
  395. retval |= UA_String_encodeBinary(&src->identifier.string, dst, offset);
  396. break;
  397. case UA_NODEIDTYPE_GUID:
  398. srcByte = UA_NODEIDTYPE_GUID;
  399. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  400. retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
  401. retval |= UA_Guid_encodeBinary(&src->identifier.guid, dst, offset);
  402. break;
  403. case UA_NODEIDTYPE_BYTESTRING:
  404. srcByte = UA_NODEIDTYPE_BYTESTRING;
  405. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  406. retval |= UA_UInt16_encodeBinary(&src->namespace, dst, offset);
  407. retval |= UA_ByteString_encodeBinary(&src->identifier.byteString, dst, offset);
  408. break;
  409. default:
  410. retval = UA_ERROR;
  411. }
  412. )
  413. UA_Int32 UA_NodeId_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_NodeId *dst) {
  414. UA_Int32 retval = UA_SUCCESS;
  415. UA_NodeId_init(dst);
  416. // temporary variables to overcome decoder's non-endian-saveness for datatypes with different length
  417. UA_Byte dstByte;
  418. UA_UInt16 dstUInt16;
  419. UA_Byte encodingByte;
  420. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingByte),; );
  421. switch(encodingByte) {
  422. case UA_NODEIDTYPE_TWOBYTE: // Table 7
  423. dst->nodeIdType = UA_NODEIDTYPE_NUMERIC;
  424. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
  425. dst->identifier.numeric = dstByte;
  426. dst->namespace = 0; // default namespace
  427. break;
  428. case UA_NODEIDTYPE_FOURBYTE: // Table 8
  429. dst->nodeIdType = UA_NODEIDTYPE_NUMERIC;
  430. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
  431. dst->namespace = dstByte;
  432. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dstUInt16),; );
  433. dst->identifier.numeric = dstUInt16;
  434. break;
  435. case UA_NODEIDTYPE_NUMERIC: // Table 6, first entry
  436. dst->nodeIdType = UA_NODEIDTYPE_NUMERIC;
  437. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
  438. CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->identifier.numeric),; );
  439. break;
  440. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  441. dst->nodeIdType = UA_NODEIDTYPE_STRING;
  442. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
  443. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->identifier.string),; );
  444. break;
  445. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  446. dst->nodeIdType = UA_NODEIDTYPE_GUID;
  447. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
  448. CHECKED_DECODE(UA_Guid_decodeBinary(src, offset, &dst->identifier.guid),; );
  449. break;
  450. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  451. dst->nodeIdType = UA_NODEIDTYPE_BYTESTRING;
  452. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespace),; );
  453. CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->identifier.byteString),; );
  454. break;
  455. default:
  456. retval = UA_ERROR;
  457. }
  458. return retval;
  459. }
  460. /* ExpandedNodeId */
  461. UA_Int32 UA_ExpandedNodeId_calcSizeBinary(UA_ExpandedNodeId const *p) {
  462. UA_Int32 length = 0;
  463. if(p == UA_NULL)
  464. length = sizeof(UA_ExpandedNodeId);
  465. else {
  466. length = UA_NodeId_calcSizeBinary(&p->nodeId);
  467. if(p->namespaceUri.length > 0)
  468. length += UA_String_calcSizeBinary(&p->namespaceUri);
  469. if(p->serverIndex > 0)
  470. length += sizeof(UA_UInt32);
  471. }
  472. return length;
  473. }
  474. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
  475. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
  476. UA_TYPE_ENCODEBINARY(UA_ExpandedNodeId,
  477. UA_Byte flags = 0;
  478. UA_UInt32 start = *offset;
  479. retval |= UA_NodeId_encodeBinary(&src->nodeId, dst, offset);
  480. if(src->namespaceUri.length > 0) {
  481. // TODO: Set namespaceIndex to 0 in the nodeid as the namespaceUri takes precedence
  482. retval |= UA_String_encodeBinary(&src->namespaceUri, dst, offset);
  483. flags |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
  484. }
  485. if(src->serverIndex > 0) {
  486. retval |= UA_UInt32_encodeBinary(&src->serverIndex, dst, offset);
  487. flags |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
  488. }
  489. if(flags != 0)
  490. dst->data[start] |= flags;
  491. )
  492. UA_Int32 UA_ExpandedNodeId_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_ExpandedNodeId *dst) {
  493. UA_UInt32 retval = UA_SUCCESS;
  494. UA_ExpandedNodeId_init(dst);
  495. // get encodingflags and leave a "clean" nodeidtype
  496. if((UA_Int32)*offset >= src->length)
  497. return UA_ERROR;
  498. UA_Byte encodingByte = src->data[*offset];
  499. src->data[*offset] = encodingByte & ~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG | UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
  500. CHECKED_DECODE(UA_NodeId_decodeBinary(src, offset, &dst->nodeId), UA_ExpandedNodeId_deleteMembers(dst));
  501. if(encodingByte & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
  502. dst->nodeId.namespace = 0;
  503. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->namespaceUri), UA_ExpandedNodeId_deleteMembers(dst));
  504. }
  505. if(encodingByte & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
  506. CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->serverIndex), UA_ExpandedNodeId_deleteMembers(dst));
  507. return retval;
  508. }
  509. /* StatusCode */
  510. UA_TYPE_BINARY_ENCODING_AS(UA_StatusCode, UA_UInt32)
  511. /* QualifiedName */
  512. UA_Int32 UA_QualifiedName_calcSizeBinary(UA_QualifiedName const *p) {
  513. UA_Int32 length = 0;
  514. if(p == UA_NULL) return sizeof(UA_QualifiedName);
  515. length += sizeof(UA_UInt16); //qualifiedName->namespaceIndex
  516. // length += sizeof(UA_UInt16); //qualifiedName->reserved
  517. length += UA_String_calcSizeBinary(&p->name); //qualifiedName->name
  518. return length;
  519. }
  520. UA_Int32 UA_QualifiedName_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_QualifiedName *dst) {
  521. UA_Int32 retval = UA_SUCCESS;
  522. UA_QualifiedName_init(dst);
  523. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
  524. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->name),; );
  525. return retval;
  526. }
  527. UA_TYPE_ENCODEBINARY(UA_QualifiedName,
  528. retval |= UA_UInt16_encodeBinary(&src->namespaceIndex, dst, offset);
  529. retval |= UA_String_encodeBinary(&src->name, dst, offset); )
  530. /* LocalizedText */
  531. UA_Int32 UA_LocalizedText_calcSizeBinary(UA_LocalizedText const *p) {
  532. UA_Int32 length = 1; // for encodingMask
  533. if(p == UA_NULL)
  534. return sizeof(UA_LocalizedText);
  535. if(p->locale.data != UA_NULL)
  536. length += UA_String_calcSizeBinary(&p->locale);
  537. if(p->text.data != UA_NULL)
  538. length += UA_String_calcSizeBinary(&p->text);
  539. return length;
  540. }
  541. UA_TYPE_ENCODEBINARY(UA_LocalizedText,
  542. UA_Byte encodingMask = 0;
  543. if(src->locale.data != UA_NULL)
  544. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  545. if(src->text.data != UA_NULL)
  546. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  547. retval |= UA_Byte_encodeBinary(&encodingMask, dst, offset);
  548. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  549. retval |= UA_String_encodeBinary(&src->locale, dst, offset);
  550. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  551. retval |= UA_String_encodeBinary(&src->text, dst, offset); )
  552. UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_LocalizedText *dst) {
  553. UA_Int32 retval = UA_SUCCESS;
  554. retval |= UA_LocalizedText_init(dst);
  555. UA_Byte encodingMask = 0;
  556. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingMask),; );
  557. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  558. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->locale),
  559. UA_LocalizedText_deleteMembers(dst));
  560. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  561. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->text),
  562. UA_LocalizedText_deleteMembers(dst));
  563. return retval;
  564. }
  565. /* ExtensionObject */
  566. UA_Int32 UA_ExtensionObject_calcSizeBinary(UA_ExtensionObject const *p) {
  567. UA_Int32 length = 0;
  568. if(p == UA_NULL)
  569. length = sizeof(UA_ExtensionObject);
  570. else {
  571. length += UA_NodeId_calcSizeBinary(&p->typeId);
  572. length += 1; //p->encoding
  573. switch(p->encoding) {
  574. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  575. length += UA_ByteString_calcSizeBinary(&p->body);
  576. break;
  577. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  578. length += UA_XmlElement_calcSizeBinary((UA_XmlElement *)&p->body);
  579. break;
  580. }
  581. }
  582. return length;
  583. }
  584. UA_TYPE_ENCODEBINARY(UA_ExtensionObject,
  585. retval |= UA_NodeId_encodeBinary(&src->typeId, dst, offset);
  586. retval |= UA_Byte_encodeBinary(&src->encoding, dst, offset);
  587. switch(src->encoding) {
  588. case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
  589. break;
  590. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  591. // FIXME: This code is valid for numeric nodeIds in ns0 only!
  592. retval |=
  593. UA_.types[UA_ns0ToVTableIndex(&src->typeId)].encodings[0].encode(src->body.data, dst,
  594. offset);
  595. break;
  596. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  597. retval |= UA_ByteString_encodeBinary(&src->body, dst, offset);
  598. break;
  599. }
  600. )
  601. UA_Int32 UA_ExtensionObject_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_ExtensionObject *dst) {
  602. UA_Int32 retval = UA_SUCCESS;
  603. UA_ExtensionObject_init(dst);
  604. CHECKED_DECODE(UA_NodeId_decodeBinary(src, offset, &dst->typeId), UA_ExtensionObject_deleteMembers(dst));
  605. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encoding), UA_ExtensionObject_deleteMembers(dst));
  606. CHECKED_DECODE(UA_String_copy(&UA_STRING_NULL, (UA_String *)&dst->body), UA_ExtensionObject_deleteMembers(dst));
  607. switch(dst->encoding) {
  608. case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
  609. break;
  610. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  611. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  612. CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->body), UA_ExtensionObject_deleteMembers(dst));
  613. break;
  614. }
  615. return retval;
  616. }
  617. /* DataValue */
  618. //TODO: place this define at the server configuration
  619. #define MAX_PICO_SECONDS 1000
  620. UA_Int32 UA_DataValue_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_DataValue *dst) {
  621. UA_Int32 retval = UA_SUCCESS;
  622. UA_DataValue_init(dst);
  623. retval |= UA_Byte_decodeBinary(src, offset, &dst->encodingMask);
  624. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
  625. CHECKED_DECODE(UA_Variant_decodeBinary(src, offset, &dst->value), UA_DataValue_deleteMembers(dst));
  626. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  627. CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->status), UA_DataValue_deleteMembers(dst));
  628. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  629. CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->sourceTimestamp), UA_DataValue_deleteMembers(dst));
  630. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS) {
  631. CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->sourcePicoseconds), UA_DataValue_deleteMembers(dst));
  632. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  633. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  634. }
  635. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  636. CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->serverTimestamp), UA_DataValue_deleteMembers(dst));
  637. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS) {
  638. CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->serverPicoseconds), UA_DataValue_deleteMembers(dst));
  639. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  640. dst->serverPicoseconds = MAX_PICO_SECONDS;
  641. }
  642. return retval;
  643. }
  644. UA_TYPE_ENCODEBINARY(UA_DataValue,
  645. retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
  646. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
  647. retval |= UA_Variant_encodeBinary(&src->value, dst, offset);
  648. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  649. retval |= UA_StatusCode_encodeBinary(&src->status, dst, offset);
  650. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  651. retval |= UA_DateTime_encodeBinary(&src->sourceTimestamp, dst, offset);
  652. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
  653. retval |= UA_Int16_encodeBinary(&src->sourcePicoseconds, dst, offset);
  654. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  655. retval |= UA_DateTime_encodeBinary(&src->serverTimestamp, dst, offset);
  656. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
  657. retval |= UA_Int16_encodeBinary(&src->serverPicoseconds, dst, offset);
  658. )
  659. UA_Int32 UA_DataValue_calcSizeBinary(UA_DataValue const *p) {
  660. UA_Int32 length = 0;
  661. if(p == UA_NULL) // get static storage size
  662. length = sizeof(UA_DataValue);
  663. else { // get decoding size
  664. length = sizeof(UA_Byte);
  665. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT) {
  666. // FIXME: this one can return with an error value instead of a size
  667. length += UA_Variant_calcSizeBinary(&p->value);
  668. }
  669. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  670. length += sizeof(UA_UInt32); //dataValue->status
  671. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  672. length += sizeof(UA_DateTime); //dataValue->sourceTimestamp
  673. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
  674. length += sizeof(UA_Int64); //dataValue->sourcePicoseconds
  675. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  676. length += sizeof(UA_DateTime); //dataValue->serverTimestamp
  677. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
  678. length += sizeof(UA_Int64); //dataValue->serverPicoseconds
  679. }
  680. return length;
  681. }
  682. /* Variant */
  683. /* We can store all data types in a variant internally. But for communication we
  684. * encode them in an ExtensionObject if they are not one of the built in types.
  685. * Officially, only builtin types are contained in a variant.
  686. *
  687. * Every ExtensionObject incurrs an overhead of 4 byte (nodeid) + 1 byte (encoding) */
  688. UA_Int32 UA_Variant_calcSizeBinary(UA_Variant const *p) {
  689. UA_Int32 arrayLength, length;
  690. UA_Boolean isArray, hasDimensions, isBuiltin;
  691. if(p == UA_NULL)
  692. return sizeof(UA_Variant);
  693. if(p->vt == UA_NULL)
  694. return UA_ERR_INCONSISTENT;
  695. arrayLength = p->arrayLength;
  696. if(p->data == UA_NULL)
  697. arrayLength = -1;
  698. isArray = arrayLength != 1; // a single element is not an array
  699. hasDimensions = isArray && p->arrayDimensions != UA_NULL;
  700. isBuiltin = is_builtin(&p->vt->typeId);
  701. length = sizeof(UA_Byte); //p->encodingMask
  702. if(isArray) {
  703. // array length + the array itself
  704. length += UA_Array_calcSizeBinary(arrayLength, p->vt, p->data);
  705. } else {
  706. length += p->vt->encodings[UA_ENCODING_BINARY].calcSize(p->data);
  707. if(!isBuiltin)
  708. length += 9; // 4 byte nodeid + 1 byte encoding + 4 byte bytestring length
  709. }
  710. if(hasDimensions) {
  711. if(isBuiltin)
  712. length += UA_Array_calcSizeBinary(p->arrayDimensionsLength, &UA_.types[UA_INT32], p->arrayDimensions);
  713. else
  714. length += UA_Array_calcSizeBinary_asExtensionObject(p->arrayDimensionsLength, &UA_.types[UA_INT32],
  715. p->arrayDimensions);
  716. }
  717. return length;
  718. }
  719. UA_TYPE_ENCODEBINARY(UA_Variant,
  720. UA_Byte encodingByte;
  721. UA_Boolean isArray;
  722. UA_Boolean hasDimensions;
  723. UA_Boolean isBuiltin;
  724. if(src == UA_NULL || src->vt == UA_NULL || src->vt->typeId.namespace != 0)
  725. return UA_ERROR;
  726. isArray = src->arrayLength != 1; // a single element is not an array
  727. hasDimensions = isArray && src->arrayDimensions != UA_NULL;
  728. isBuiltin = is_builtin(&src->vt->typeId);
  729. encodingByte = 0;
  730. if(isArray) {
  731. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  732. if(hasDimensions)
  733. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  734. }
  735. if(isBuiltin) {
  736. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)src->vt->typeId.identifier.numeric;
  737. } else
  738. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)22; // ExtensionObject
  739. retval |= UA_Byte_encodeBinary(&encodingByte, dst, offset);
  740. if(isArray)
  741. retval |= UA_Array_encodeBinary(src->data, src->arrayLength, src->vt, dst, offset);
  742. else if(src->data == UA_NULL)
  743. retval = UA_ERROR; // an array can be empty. a single element must be present.
  744. else {
  745. if(!isBuiltin) {
  746. // print the extensionobject header
  747. UA_NodeId_encodeBinary(&src->vt->typeId, dst, offset);
  748. UA_Byte eoEncoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
  749. UA_Byte_encodeBinary(&eoEncoding, dst, offset);
  750. UA_Int32 eoEncodingLength = src->vt->encodings[UA_ENCODING_BINARY].calcSize(src->data);
  751. UA_Int32_encodeBinary(&eoEncodingLength, dst, offset);
  752. }
  753. retval |= src->vt->encodings[UA_ENCODING_BINARY].encode(src->data, dst, offset);
  754. }
  755. if(hasDimensions) {
  756. if(isBuiltin)
  757. retval |= UA_Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsLength,
  758. &UA_.types[UA_INT32], dst, offset);
  759. else
  760. retval |= UA_Array_encodeBinary_asExtensionObject(src->arrayDimensions,
  761. src->arrayDimensionsLength,
  762. &UA_.types[UA_INT32], dst, offset);
  763. })
  764. /* For decoding, we read extensionobects as is. */
  765. UA_Int32 UA_Variant_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_Variant * dst) {
  766. UA_Int32 retval = UA_SUCCESS;
  767. UA_Variant_init(dst);
  768. UA_Byte encodingByte;
  769. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingByte),; );
  770. UA_Boolean isArray = encodingByte & (0x01 << 7); // Bit 7
  771. UA_Boolean hasDimensions = isArray && (encodingByte & (0x01 << 6)); // Bit 6
  772. UA_NodeId typeid = { .nodeIdType = UA_NODEIDTYPE_NUMERIC, .namespace= 0,
  773. .identifier.numeric = encodingByte & 0x3F };
  774. UA_Int32 typeNs0Id = UA_ns0ToVTableIndex(&typeid );
  775. dst->vt = &UA_.types[typeNs0Id];
  776. if(isArray) {
  777. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->arrayLength),; );
  778. CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, dst->vt,
  779. &dst->data), UA_Variant_deleteMembers(dst));
  780. }else {
  781. dst->arrayLength = 1;
  782. UA_alloc(&dst->data, dst->vt->memSize);
  783. dst->vt->encodings[UA_ENCODING_BINARY].decode(src, offset, dst->data);
  784. }
  785. //decode the dimension field array if present
  786. if(hasDimensions) {
  787. UA_Int32_decodeBinary(src, offset, &dst->arrayDimensionsLength);
  788. CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayDimensionsLength,
  789. &UA_.types[UA_INT32],
  790. &dst->data), UA_Variant_deleteMembers(dst));
  791. }
  792. return retval;
  793. }
  794. /* DiagnosticInfo */
  795. UA_Int32 UA_DiagnosticInfo_calcSizeBinary(UA_DiagnosticInfo const *ptr) {
  796. UA_Int32 length = 0;
  797. if(ptr == UA_NULL)
  798. length = sizeof(UA_DiagnosticInfo);
  799. else {
  800. UA_Byte mask;
  801. length += sizeof(UA_Byte); // EncodingMask
  802. for(mask = 0x01;mask <= 0x40;mask *= 2) {
  803. switch(mask & (ptr->encodingMask)) {
  804. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  805. // puts("diagnosticInfo symbolic id");
  806. length += sizeof(UA_Int32);
  807. break;
  808. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  809. length += sizeof(UA_Int32);
  810. break;
  811. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  812. length += sizeof(UA_Int32);
  813. break;
  814. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  815. length += sizeof(UA_Int32);
  816. break;
  817. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  818. length += UA_String_calcSizeBinary(&ptr->additionalInfo);
  819. break;
  820. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  821. length += sizeof(UA_StatusCode);
  822. break;
  823. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  824. length += UA_DiagnosticInfo_calcSizeBinary(ptr->innerDiagnosticInfo);
  825. break;
  826. }
  827. }
  828. }
  829. return length;
  830. }
  831. UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset,
  832. UA_DiagnosticInfo *dst) {
  833. UA_Int32 retval = UA_SUCCESS;
  834. UA_DiagnosticInfo_init(dst);
  835. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingMask),; );
  836. for(UA_Int32 i = 0;i < 7;i++) {
  837. switch( (0x01 << i) & dst->encodingMask) {
  838. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  839. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->symbolicId),; );
  840. break;
  841. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  842. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->namespaceUri),; );
  843. break;
  844. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  845. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->localizedText),; );
  846. break;
  847. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  848. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->locale),; );
  849. break;
  850. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  851. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->additionalInfo),; );
  852. break;
  853. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  854. CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->innerStatusCode),; );
  855. break;
  856. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  857. // innerDiagnosticInfo is a pointer to struct, therefore allocate
  858. CHECKED_DECODE(UA_alloc((void **)&dst->innerDiagnosticInfo,
  859. UA_DiagnosticInfo_calcSizeBinary(UA_NULL)),; );
  860. CHECKED_DECODE(UA_DiagnosticInfo_decodeBinary(src, offset,
  861. dst->innerDiagnosticInfo),
  862. UA_DiagnosticInfo_deleteMembers(dst));
  863. break;
  864. }
  865. }
  866. return retval;
  867. }
  868. UA_TYPE_ENCODEBINARY(UA_DiagnosticInfo,
  869. retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
  870. for(UA_Int32 i = 0;i < 7;i++) {
  871. switch( (0x01 << i) & src->encodingMask) {
  872. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  873. retval |= UA_Int32_encodeBinary(&src->symbolicId, dst, offset);
  874. break;
  875. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  876. retval |=
  877. UA_Int32_encodeBinary( &src->namespaceUri, dst, offset);
  878. break;
  879. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  880. retval |= UA_Int32_encodeBinary(&src->localizedText, dst, offset);
  881. break;
  882. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  883. retval |= UA_Int32_encodeBinary(&src->locale, dst, offset);
  884. break;
  885. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  886. retval |=
  887. UA_String_encodeBinary(&src->additionalInfo, dst, offset);
  888. break;
  889. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  890. retval |=
  891. UA_StatusCode_encodeBinary(&src->innerStatusCode, dst,
  892. offset);
  893. break;
  894. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  895. retval |=
  896. UA_DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, dst,
  897. offset);
  898. break;
  899. }
  900. }
  901. )
  902. /* InvalidType */
  903. UA_Int32 UA_InvalidType_calcSizeBinary(UA_InvalidType const *p) {
  904. return 0;
  905. }
  906. UA_TYPE_ENCODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )
  907. UA_TYPE_DECODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )