ua_types_encoding_binary.c 50 KB

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