ua_types_encoding_binary.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  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 <= 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->identifierType) {
  342. case UA_NODEIDTYPE_NUMERIC:
  343. if(p->identifier.numeric > UA_UINT16_MAX || p->namespaceIndex > UA_BYTE_MAX)
  344. length = sizeof(UA_Byte) + sizeof(UA_UInt16) + sizeof(UA_UInt32);
  345. else if(p->identifier.numeric > UA_BYTE_MAX || p->namespaceIndex > 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. UA_assert(UA_FALSE); // this must never happen
  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->identifierType) {
  371. case UA_NODEIDTYPE_NUMERIC:
  372. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  373. srcByte = UA_NODEIDTYPE_NUMERIC;
  374. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  375. retval |= UA_UInt16_encodeBinary(&src->namespaceIndex, dst, offset);
  376. retval |= UA_UInt32_encodeBinary(&src->identifier.numeric, dst, offset);
  377. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) { /* UA_NODEIDTYPE_FOURBYTE */
  378. srcByte = UA_NODEIDTYPE_FOURBYTE;
  379. retval |= UA_Byte_encodeBinary(&srcByte, dst, offset);
  380. srcByte = src->namespaceIndex;
  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->namespaceIndex, 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->namespaceIndex, 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->namespaceIndex, dst, offset);
  407. retval |= UA_ByteString_encodeBinary(&src->identifier.byteString, dst, offset);
  408. break;
  409. default:
  410. UA_assert(UA_FALSE); // must never happen
  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->identifierType = UA_NODEIDTYPE_NUMERIC;
  424. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
  425. dst->identifier.numeric = dstByte;
  426. dst->namespaceIndex = 0; // default namespace
  427. break;
  428. case UA_NODEIDTYPE_FOURBYTE: // Table 8
  429. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  430. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dstByte),; );
  431. dst->namespaceIndex = 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->identifierType = UA_NODEIDTYPE_NUMERIC;
  437. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
  438. CHECKED_DECODE(UA_UInt32_decodeBinary(src, offset, &dst->identifier.numeric),; );
  439. break;
  440. case UA_NODEIDTYPE_STRING: // Table 6, second entry
  441. dst->identifierType = UA_NODEIDTYPE_STRING;
  442. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
  443. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->identifier.string),; );
  444. break;
  445. case UA_NODEIDTYPE_GUID: // Table 6, third entry
  446. dst->identifierType = UA_NODEIDTYPE_GUID;
  447. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
  448. CHECKED_DECODE(UA_Guid_decodeBinary(src, offset, &dst->identifier.guid),; );
  449. break;
  450. case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
  451. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  452. CHECKED_DECODE(UA_UInt16_decodeBinary(src, offset, &dst->namespaceIndex),; );
  453. CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->identifier.byteString),; );
  454. break;
  455. default:
  456. retval = UA_ERROR; // the client sends an encodingByte we do not recognize
  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.namespaceIndex = 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. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
  532. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
  533. UA_Int32 UA_LocalizedText_calcSizeBinary(UA_LocalizedText const *p) {
  534. UA_Int32 length = 1; // for encodingMask
  535. if(p == UA_NULL)
  536. return sizeof(UA_LocalizedText);
  537. if(p->locale.data != UA_NULL)
  538. length += UA_String_calcSizeBinary(&p->locale);
  539. if(p->text.data != UA_NULL)
  540. length += UA_String_calcSizeBinary(&p->text);
  541. return length;
  542. }
  543. UA_TYPE_ENCODEBINARY(UA_LocalizedText,
  544. UA_Byte encodingMask = 0;
  545. if(src->locale.data != UA_NULL)
  546. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  547. if(src->text.data != UA_NULL)
  548. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  549. retval |= UA_Byte_encodeBinary(&encodingMask, dst, offset);
  550. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  551. retval |= UA_String_encodeBinary(&src->locale, dst, offset);
  552. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  553. retval |= UA_String_encodeBinary(&src->text, dst, offset); )
  554. UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_LocalizedText *dst) {
  555. UA_Int32 retval = UA_SUCCESS;
  556. retval |= UA_LocalizedText_init(dst);
  557. UA_Byte encodingMask = 0;
  558. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingMask),; );
  559. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  560. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->locale),
  561. UA_LocalizedText_deleteMembers(dst));
  562. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  563. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->text),
  564. UA_LocalizedText_deleteMembers(dst));
  565. return retval;
  566. }
  567. /* ExtensionObject */
  568. UA_Int32 UA_ExtensionObject_calcSizeBinary(UA_ExtensionObject const *p) {
  569. UA_Int32 length = 0;
  570. if(p == UA_NULL)
  571. return sizeof(UA_ExtensionObject);
  572. length += UA_NodeId_calcSizeBinary(&p->typeId);
  573. length += 1; // encoding
  574. switch(p->encoding) {
  575. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  576. length += UA_ByteString_calcSizeBinary(&p->body);
  577. break;
  578. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  579. length += UA_XmlElement_calcSizeBinary((UA_XmlElement *)&p->body);
  580. break;
  581. default:
  582. break;
  583. }
  584. return length;
  585. }
  586. UA_TYPE_ENCODEBINARY(UA_ExtensionObject,
  587. retval |= UA_NodeId_encodeBinary(&src->typeId, dst, offset);
  588. UA_Byte encoding = src->encoding;
  589. retval |= UA_Byte_encodeBinary(&encoding, dst, offset);
  590. switch(src->encoding) {
  591. case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
  592. break;
  593. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  594. // FIXME: This code is valid for numeric nodeIds in ns0 only!
  595. retval |= UA_.types[UA_ns0ToVTableIndex(&src->typeId)].encodings[UA_ENCODING_BINARY].encode(src->body.data, dst, offset);
  596. break;
  597. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  598. retval |= UA_ByteString_encodeBinary(&src->body, dst, offset);
  599. break;
  600. default:
  601. UA_assert(UA_FALSE);
  602. }
  603. )
  604. UA_Int32 UA_ExtensionObject_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_ExtensionObject *dst) {
  605. UA_Int32 retval = UA_SUCCESS;
  606. UA_Byte encoding;
  607. UA_ExtensionObject_init(dst);
  608. CHECKED_DECODE(UA_NodeId_decodeBinary(src, offset, &dst->typeId), UA_ExtensionObject_deleteMembers(dst));
  609. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encoding), UA_ExtensionObject_deleteMembers(dst));
  610. dst->encoding = encoding;
  611. CHECKED_DECODE(UA_String_copy(&UA_STRING_NULL, (UA_String *)&dst->body), UA_ExtensionObject_deleteMembers(dst));
  612. switch(dst->encoding) {
  613. case UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED:
  614. break;
  615. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
  616. case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
  617. CHECKED_DECODE(UA_ByteString_decodeBinary(src, offset, &dst->body), UA_ExtensionObject_deleteMembers(dst));
  618. break;
  619. default:
  620. UA_ExtensionObject_deleteMembers(dst);
  621. return UA_ERROR;
  622. }
  623. return retval;
  624. }
  625. /* DataValue */
  626. //TODO: place this define at the server configuration
  627. #define MAX_PICO_SECONDS 1000
  628. UA_Int32 UA_DataValue_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_DataValue *dst) {
  629. UA_Int32 retval = UA_SUCCESS;
  630. UA_DataValue_init(dst);
  631. retval |= UA_Byte_decodeBinary(src, offset, &dst->encodingMask);
  632. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
  633. CHECKED_DECODE(UA_Variant_decodeBinary(src, offset, &dst->value), UA_DataValue_deleteMembers(dst));
  634. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  635. CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->status), UA_DataValue_deleteMembers(dst));
  636. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  637. CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->sourceTimestamp), UA_DataValue_deleteMembers(dst));
  638. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS) {
  639. CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->sourcePicoseconds), UA_DataValue_deleteMembers(dst));
  640. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  641. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  642. }
  643. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  644. CHECKED_DECODE(UA_DateTime_decodeBinary(src, offset, &dst->serverTimestamp), UA_DataValue_deleteMembers(dst));
  645. if(dst->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS) {
  646. CHECKED_DECODE(UA_Int16_decodeBinary(src, offset, &dst->serverPicoseconds), UA_DataValue_deleteMembers(dst));
  647. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  648. dst->serverPicoseconds = MAX_PICO_SECONDS;
  649. }
  650. return retval;
  651. }
  652. UA_TYPE_ENCODEBINARY(UA_DataValue,
  653. retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
  654. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
  655. retval |= UA_Variant_encodeBinary(&src->value, dst, offset);
  656. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  657. retval |= UA_StatusCode_encodeBinary(&src->status, dst, offset);
  658. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  659. retval |= UA_DateTime_encodeBinary(&src->sourceTimestamp, dst, offset);
  660. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
  661. retval |= UA_Int16_encodeBinary(&src->sourcePicoseconds, dst, offset);
  662. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  663. retval |= UA_DateTime_encodeBinary(&src->serverTimestamp, dst, offset);
  664. if(src->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
  665. retval |= UA_Int16_encodeBinary(&src->serverPicoseconds, dst, offset);
  666. )
  667. UA_Int32 UA_DataValue_calcSizeBinary(UA_DataValue const *p) {
  668. UA_Int32 length = 0;
  669. if(p == UA_NULL) // get static storage size
  670. length = sizeof(UA_DataValue);
  671. else { // get decoding size
  672. length = sizeof(UA_Byte);
  673. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_VARIANT)
  674. length += UA_Variant_calcSizeBinary(&p->value);
  675. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_STATUSCODE)
  676. length += sizeof(UA_UInt32); //dataValue->status
  677. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP)
  678. length += sizeof(UA_DateTime); //dataValue->sourceTimestamp
  679. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS)
  680. length += sizeof(UA_Int64); //dataValue->sourcePicoseconds
  681. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP)
  682. length += sizeof(UA_DateTime); //dataValue->serverTimestamp
  683. if(p->encodingMask & UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS)
  684. length += sizeof(UA_Int64); //dataValue->serverPicoseconds
  685. }
  686. return length;
  687. }
  688. /* Variant */
  689. /* We can store all data types in a variant internally. But for communication we
  690. * encode them in an ExtensionObject if they are not one of the built in types.
  691. * Officially, only builtin types are contained in a variant.
  692. *
  693. * Every ExtensionObject incurrs an overhead of 4 byte (nodeid) + 1 byte (encoding) */
  694. UA_Int32 UA_Variant_calcSizeBinary(UA_Variant const *p) {
  695. UA_Int32 arrayLength, length;
  696. UA_Boolean isArray, hasDimensions, isBuiltin;
  697. if(p == UA_NULL)
  698. return sizeof(UA_Variant);
  699. if(p->vt == UA_NULL)
  700. return UA_ERR_INCONSISTENT;
  701. arrayLength = p->arrayLength;
  702. if(p->data == UA_NULL)
  703. arrayLength = -1;
  704. isArray = arrayLength != 1; // a single element is not an array
  705. hasDimensions = isArray && p->arrayDimensions != UA_NULL;
  706. isBuiltin = is_builtin(&p->vt->typeId);
  707. length = sizeof(UA_Byte); //p->encodingMask
  708. if(isArray) {
  709. // array length + the array itself
  710. length += UA_Array_calcSizeBinary(arrayLength, p->vt, p->data);
  711. } else {
  712. length += p->vt->encodings[UA_ENCODING_BINARY].calcSize(p->data);
  713. if(!isBuiltin)
  714. length += 9; // 4 byte nodeid + 1 byte encoding + 4 byte bytestring length
  715. }
  716. if(hasDimensions) {
  717. if(isBuiltin)
  718. length += UA_Array_calcSizeBinary(p->arrayDimensionsLength, &UA_.types[UA_INT32], p->arrayDimensions);
  719. else
  720. length += UA_Array_calcSizeBinary_asExtensionObject(p->arrayDimensionsLength, &UA_.types[UA_INT32],
  721. p->arrayDimensions);
  722. }
  723. return length;
  724. }
  725. UA_TYPE_ENCODEBINARY(UA_Variant,
  726. UA_Byte encodingByte;
  727. UA_Boolean isArray;
  728. UA_Boolean hasDimensions;
  729. UA_Boolean isBuiltin;
  730. if(src == UA_NULL || src->vt == UA_NULL || src->vt->typeId.namespaceIndex != 0)
  731. return UA_ERROR;
  732. isArray = src->arrayLength != 1; // a single element is not an array
  733. hasDimensions = isArray && src->arrayDimensions != UA_NULL;
  734. isBuiltin = is_builtin(&src->vt->typeId);
  735. encodingByte = 0;
  736. if(isArray) {
  737. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  738. if(hasDimensions)
  739. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  740. }
  741. if(isBuiltin) {
  742. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)src->vt->typeId.identifier.numeric;
  743. } else
  744. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)22; // ExtensionObject
  745. retval |= UA_Byte_encodeBinary(&encodingByte, dst, offset);
  746. if(isArray)
  747. retval |= UA_Array_encodeBinary(src->data, src->arrayLength, src->vt, dst, offset);
  748. else if(src->data == UA_NULL)
  749. retval = UA_ERROR; // an array can be empty. a single element must be present.
  750. else {
  751. if(!isBuiltin) {
  752. // print the extensionobject header
  753. UA_NodeId_encodeBinary(&src->vt->typeId, dst, offset);
  754. UA_Byte eoEncoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
  755. UA_Byte_encodeBinary(&eoEncoding, dst, offset);
  756. UA_Int32 eoEncodingLength = src->vt->encodings[UA_ENCODING_BINARY].calcSize(src->data);
  757. UA_Int32_encodeBinary(&eoEncodingLength, dst, offset);
  758. }
  759. retval |= src->vt->encodings[UA_ENCODING_BINARY].encode(src->data, dst, offset);
  760. }
  761. if(hasDimensions) {
  762. if(isBuiltin)
  763. retval |= UA_Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsLength,
  764. &UA_.types[UA_INT32], dst, offset);
  765. else
  766. retval |= UA_Array_encodeBinary_asExtensionObject(src->arrayDimensions,
  767. src->arrayDimensionsLength,
  768. &UA_.types[UA_INT32], dst, offset);
  769. })
  770. /* For decoding, we read extensionobects as is. */
  771. UA_Int32 UA_Variant_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_Variant * dst) {
  772. UA_Int32 retval = UA_SUCCESS;
  773. UA_Variant_init(dst);
  774. UA_Byte encodingByte;
  775. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &encodingByte),; );
  776. UA_Boolean isArray = encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  777. UA_Boolean hasDimensions = isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS);
  778. UA_NodeId typeid = { .namespaceIndex= 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  779. .identifier.numeric = encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK };
  780. UA_Int32 typeNs0Id = UA_ns0ToVTableIndex(&typeid );
  781. dst->vt = &UA_.types[typeNs0Id];
  782. if(isArray) {
  783. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->arrayLength),; );
  784. CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayLength, dst->vt, &dst->data), UA_Variant_deleteMembers(dst));
  785. } else {
  786. dst->arrayLength = 1;
  787. UA_alloc(&dst->data, dst->vt->memSize);
  788. dst->vt->encodings[UA_ENCODING_BINARY].decode(src, offset, dst->data);
  789. }
  790. //decode the dimension field array if present
  791. if(hasDimensions) {
  792. UA_Int32_decodeBinary(src, offset, &dst->arrayDimensionsLength);
  793. CHECKED_DECODE(UA_Array_decodeBinary(src, offset, dst->arrayDimensionsLength,
  794. &UA_.types[UA_INT32],
  795. &dst->data), UA_Variant_deleteMembers(dst));
  796. }
  797. return retval;
  798. }
  799. /* DiagnosticInfo */
  800. UA_Int32 UA_DiagnosticInfo_calcSizeBinary(UA_DiagnosticInfo const *ptr) {
  801. UA_Int32 length = 0;
  802. if(ptr == UA_NULL)
  803. length = sizeof(UA_DiagnosticInfo);
  804. else {
  805. UA_Byte mask;
  806. length += sizeof(UA_Byte); // EncodingMask
  807. for(mask = 0x01;mask <= 0x40;mask *= 2) {
  808. switch(mask & (ptr->encodingMask)) {
  809. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  810. // puts("diagnosticInfo symbolic id");
  811. length += sizeof(UA_Int32);
  812. break;
  813. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  814. length += sizeof(UA_Int32);
  815. break;
  816. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  817. length += sizeof(UA_Int32);
  818. break;
  819. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  820. length += sizeof(UA_Int32);
  821. break;
  822. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  823. length += UA_String_calcSizeBinary(&ptr->additionalInfo);
  824. break;
  825. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  826. length += sizeof(UA_StatusCode);
  827. break;
  828. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  829. length += UA_DiagnosticInfo_calcSizeBinary(ptr->innerDiagnosticInfo);
  830. break;
  831. }
  832. }
  833. }
  834. return length;
  835. }
  836. UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset,
  837. UA_DiagnosticInfo *dst) {
  838. UA_Int32 retval = UA_SUCCESS;
  839. UA_DiagnosticInfo_init(dst);
  840. CHECKED_DECODE(UA_Byte_decodeBinary(src, offset, &dst->encodingMask),; );
  841. for(UA_Int32 i = 0;i < 7;i++) {
  842. switch( (0x01 << i) & dst->encodingMask) {
  843. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  844. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->symbolicId),; );
  845. break;
  846. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  847. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->namespaceUri),; );
  848. break;
  849. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  850. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->localizedText),; );
  851. break;
  852. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  853. CHECKED_DECODE(UA_Int32_decodeBinary(src, offset, &dst->locale),; );
  854. break;
  855. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  856. CHECKED_DECODE(UA_String_decodeBinary(src, offset, &dst->additionalInfo),; );
  857. break;
  858. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  859. CHECKED_DECODE(UA_StatusCode_decodeBinary(src, offset, &dst->innerStatusCode),; );
  860. break;
  861. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  862. // innerDiagnosticInfo is a pointer to struct, therefore allocate
  863. CHECKED_DECODE(UA_alloc((void **)&dst->innerDiagnosticInfo,
  864. UA_DiagnosticInfo_calcSizeBinary(UA_NULL)),; );
  865. CHECKED_DECODE(UA_DiagnosticInfo_decodeBinary(src, offset,
  866. dst->innerDiagnosticInfo),
  867. UA_DiagnosticInfo_deleteMembers(dst));
  868. break;
  869. }
  870. }
  871. return retval;
  872. }
  873. UA_TYPE_ENCODEBINARY(UA_DiagnosticInfo,
  874. retval |= UA_Byte_encodeBinary(&src->encodingMask, dst, offset);
  875. for(UA_Int32 i = 0;i < 7;i++) {
  876. switch( (0x01 << i) & src->encodingMask) {
  877. case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
  878. retval |= UA_Int32_encodeBinary(&src->symbolicId, dst, offset);
  879. break;
  880. case UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE:
  881. retval |=
  882. UA_Int32_encodeBinary( &src->namespaceUri, dst, offset);
  883. break;
  884. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT:
  885. retval |= UA_Int32_encodeBinary(&src->localizedText, dst, offset);
  886. break;
  887. case UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE:
  888. retval |= UA_Int32_encodeBinary(&src->locale, dst, offset);
  889. break;
  890. case UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO:
  891. retval |=
  892. UA_String_encodeBinary(&src->additionalInfo, dst, offset);
  893. break;
  894. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE:
  895. retval |=
  896. UA_StatusCode_encodeBinary(&src->innerStatusCode, dst,
  897. offset);
  898. break;
  899. case UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO:
  900. retval |=
  901. UA_DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, dst,
  902. offset);
  903. break;
  904. }
  905. }
  906. )
  907. /* InvalidType */
  908. UA_Int32 UA_InvalidType_calcSizeBinary(UA_InvalidType const *p) {
  909. return 0;
  910. }
  911. UA_TYPE_ENCODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )
  912. UA_TYPE_DECODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )