ua_types_encoding_binary.c 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. #include "ua_util.h"
  2. #include "ua_types_generated.h"
  3. #include "ua_types_encoding_binary.h"
  4. /* All de- and encoding functions have the same signature up to the pointer type.
  5. So we can use a jump-table to switch into member types. */
  6. typedef UA_Byte * UA_RESTRICT * const bufpos;
  7. typedef const UA_Byte * const bufend;
  8. typedef UA_StatusCode (*UA_encodeBinarySignature)(const void *UA_RESTRICT src, bufpos pos, bufend end);
  9. static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  10. typedef UA_StatusCode (*UA_decodeBinarySignature)(bufpos pos, bufend end, void *UA_RESTRICT dst);
  11. static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  12. typedef size_t (*UA_calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
  13. static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  14. UA_THREAD_LOCAL const UA_DataType *type; // used to pass the datatype into the jumptable
  15. /*****************/
  16. /* Integer Types */
  17. /*****************/
  18. static void UA_encode16(const UA_UInt16 v, UA_Byte buf[2]) {
  19. buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
  20. }
  21. static void UA_decode16(const UA_Byte buf[2], UA_UInt16 *v) {
  22. *v = (UA_UInt16)((UA_UInt16)buf[0] + (((UA_UInt16)buf[1]) << 8));
  23. }
  24. static void UA_encode32(const UA_UInt32 v, UA_Byte buf[4]) {
  25. buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
  26. buf[2] = (UA_Byte)(v >> 16); buf[3] = (UA_Byte)(v >> 24);
  27. }
  28. static void UA_decode32(const UA_Byte buf[4], UA_UInt32 *v) {
  29. *v = (UA_UInt32)((UA_UInt32)buf[0] + (((UA_UInt32)buf[1]) << 8) +
  30. (((UA_UInt32)buf[2]) << 16) + (((UA_UInt32)buf[3]) << 24));
  31. }
  32. static void UA_encode64(const UA_UInt64 v, UA_Byte buf[8]) {
  33. buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
  34. buf[2] = (UA_Byte)(v >> 16); buf[3] = (UA_Byte)(v >> 24);
  35. buf[4] = (UA_Byte)(v >> 32); buf[5] = (UA_Byte)(v >> 40);
  36. buf[6] = (UA_Byte)(v >> 48); buf[7] = (UA_Byte)(v >> 56);
  37. }
  38. static void UA_decode64(const UA_Byte buf[8], UA_UInt64 *v) {
  39. *v = (UA_UInt64)((UA_UInt64)buf[0] + (((UA_UInt64)buf[1]) << 8) +
  40. (((UA_UInt64)buf[2]) << 16) + (((UA_UInt64)buf[3]) << 24) +
  41. (((UA_UInt64)buf[4]) << 32) + (((UA_UInt64)buf[5]) << 40) +
  42. (((UA_UInt64)buf[6]) << 48) + (((UA_UInt64)buf[7]) << 56));
  43. }
  44. /* Boolean */
  45. static UA_StatusCode
  46. Boolean_encodeBinary(const UA_Boolean *src, bufpos pos, bufend end) {
  47. if(*pos + sizeof(UA_Boolean) > end)
  48. return UA_STATUSCODE_BADENCODINGERROR;
  49. **pos = *(const UA_Byte*)src;
  50. (*pos)++;
  51. return UA_STATUSCODE_GOOD;
  52. }
  53. static UA_StatusCode
  54. Boolean_decodeBinary(bufpos pos, bufend end, UA_Boolean *dst) {
  55. if(*pos + sizeof(UA_Boolean) > end)
  56. return UA_STATUSCODE_BADDECODINGERROR;
  57. *dst = (**pos > 0) ? true : false;
  58. (*pos)++;
  59. return UA_STATUSCODE_GOOD;
  60. }
  61. /* Byte */
  62. static UA_StatusCode
  63. Byte_encodeBinary(const UA_Byte *src, bufpos pos, bufend end) {
  64. if(*pos + sizeof(UA_Byte) > end)
  65. return UA_STATUSCODE_BADENCODINGERROR;
  66. **pos = *(const UA_Byte*)src;
  67. (*pos)++;
  68. return UA_STATUSCODE_GOOD;
  69. }
  70. static UA_StatusCode
  71. Byte_decodeBinary(bufpos pos, bufend end, UA_Byte *dst) {
  72. if(*pos + sizeof(UA_Byte) > end)
  73. return UA_STATUSCODE_BADDECODINGERROR;
  74. *dst = **pos;
  75. (*pos)++;
  76. return UA_STATUSCODE_GOOD;
  77. }
  78. /* UInt16 */
  79. static UA_StatusCode
  80. UInt16_encodeBinary(UA_UInt16 const *src, bufpos pos, bufend end) {
  81. if(*pos + sizeof(UA_UInt16) > end)
  82. return UA_STATUSCODE_BADENCODINGERROR;
  83. #if UA_BINARY_OVERLAYABLE_INTEGER
  84. memcpy(*pos, src, sizeof(UA_UInt16));
  85. #else
  86. UA_encode16(*src, *pos);
  87. #endif
  88. (*pos) += 2;
  89. return UA_STATUSCODE_GOOD;
  90. }
  91. static UA_INLINE UA_StatusCode
  92. Int16_encodeBinary(UA_Int16 const *src, bufpos pos, bufend end) {
  93. return UInt16_encodeBinary((const UA_UInt16*)src, pos, end);
  94. }
  95. static UA_StatusCode
  96. UInt16_decodeBinary(bufpos pos, bufend end, UA_UInt16 *dst) {
  97. if(*pos + sizeof(UA_UInt16) > end)
  98. return UA_STATUSCODE_BADDECODINGERROR;
  99. #if UA_BINARY_OVERLAYABLE_INTEGER
  100. memcpy(dst, *pos, sizeof(UA_UInt16));
  101. #else
  102. UA_decode16(*pos, dst);
  103. #endif
  104. (*pos) += 2;
  105. return UA_STATUSCODE_GOOD;
  106. }
  107. static UA_INLINE UA_StatusCode
  108. Int16_decodeBinary(bufpos pos, bufend end, UA_Int16 *dst) {
  109. return UInt16_decodeBinary(pos, end, (UA_UInt16*)dst);
  110. }
  111. /* UInt32 */
  112. static UA_StatusCode
  113. UInt32_encodeBinary(UA_UInt32 const *src, bufpos pos, bufend end) {
  114. if(*pos + sizeof(UA_UInt32) > end)
  115. return UA_STATUSCODE_BADENCODINGERROR;
  116. #if UA_BINARY_OVERLAYABLE_INTEGER
  117. memcpy(*pos, src, sizeof(UA_UInt32));
  118. #else
  119. UA_encode32(*src, *pos);
  120. #endif
  121. (*pos) += 4;
  122. return UA_STATUSCODE_GOOD;
  123. }
  124. static UA_INLINE UA_StatusCode
  125. Int32_encodeBinary(UA_Int32 const *src, bufpos pos, bufend end) {
  126. return UInt32_encodeBinary((const UA_UInt32*)src, pos, end);
  127. }
  128. static UA_INLINE UA_StatusCode
  129. StatusCode_encodeBinary(UA_StatusCode const *src, bufpos pos, bufend end) {
  130. return UInt32_encodeBinary((const UA_UInt32*)src, pos, end);
  131. }
  132. static UA_StatusCode
  133. UInt32_decodeBinary(bufpos pos, bufend end, UA_UInt32 *dst) {
  134. if(*pos + sizeof(UA_UInt32) > end)
  135. return UA_STATUSCODE_BADDECODINGERROR;
  136. #if UA_BINARY_OVERLAYABLE_INTEGER
  137. memcpy(dst, *pos, sizeof(UA_UInt32));
  138. #else
  139. UA_decode32(*pos, dst);
  140. #endif
  141. (*pos) += 4;
  142. return UA_STATUSCODE_GOOD;
  143. }
  144. static UA_INLINE UA_StatusCode
  145. Int32_decodeBinary(bufpos pos, bufend end, UA_Int32 *dst) {
  146. return UInt32_decodeBinary(pos, end, (UA_UInt32*)dst);
  147. }
  148. static UA_INLINE UA_StatusCode
  149. StatusCode_decodeBinary(bufpos pos, bufend end, UA_StatusCode *dst) {
  150. return UInt32_decodeBinary(pos, end, (UA_UInt32*)dst);
  151. }
  152. /* UInt64 */
  153. static UA_StatusCode
  154. UInt64_encodeBinary(UA_UInt64 const *src, bufpos pos, bufend end) {
  155. if(*pos + sizeof(UA_UInt64) > end)
  156. return UA_STATUSCODE_BADENCODINGERROR;
  157. #if UA_BINARY_OVERLAYABLE_INTEGER
  158. memcpy(*pos, src, sizeof(UA_UInt64));
  159. #else
  160. UA_encode64(*src, *pos);
  161. #endif
  162. (*pos) += 8;
  163. return UA_STATUSCODE_GOOD;
  164. }
  165. static UA_INLINE UA_StatusCode
  166. Int64_encodeBinary(UA_Int64 const *src, bufpos pos, bufend end) {
  167. return UInt64_encodeBinary((const UA_UInt64*)src, pos, end);
  168. }
  169. static UA_INLINE UA_StatusCode
  170. DateTime_encodeBinary(UA_DateTime const *src, bufpos pos, bufend end) {
  171. return UInt64_encodeBinary((const UA_UInt64*)src, pos, end);
  172. }
  173. static UA_StatusCode
  174. UInt64_decodeBinary(bufpos pos, bufend end, UA_UInt64 *dst) {
  175. if(*pos + sizeof(UA_UInt64) > end)
  176. return UA_STATUSCODE_BADDECODINGERROR;
  177. #if UA_BINARY_OVERLAYABLE_INTEGER
  178. memcpy(dst, *pos, sizeof(UA_UInt64));
  179. #else
  180. UA_decode64(*pos, dst);
  181. #endif
  182. (*pos) += 8;
  183. return UA_STATUSCODE_GOOD;
  184. }
  185. static UA_INLINE UA_StatusCode
  186. Int64_decodeBinary(bufpos pos, bufend end, UA_Int64 *dst) {
  187. return UInt64_decodeBinary(pos, end, (UA_UInt64*)dst);
  188. }
  189. static UA_INLINE UA_StatusCode
  190. DateTime_decodeBinary(bufpos pos, bufend end, UA_DateTime *dst) {
  191. return UInt64_decodeBinary(pos, end, (UA_UInt64*)dst);
  192. }
  193. /************************/
  194. /* Floating Point Types */
  195. /************************/
  196. #if UA_BINARY_OVERLAYABLE_FLOAT
  197. # define Float_encodeBinary UInt32_encodeBinary
  198. # define Float_decodeBinary UInt32_decodeBinary
  199. # define Double_encodeBinary UInt64_encodeBinary
  200. # define Double_decodeBinary UInt64_decodeBinary
  201. #else
  202. #include <math.h>
  203. /* Handling of IEEE754 floating point values was taken from Beej's Guide to
  204. Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
  205. edge cases +/-0, +/-inf and nan. */
  206. static uint64_t pack754(long double f, unsigned bits, unsigned expbits) {
  207. unsigned significandbits = bits - expbits - 1;
  208. long double fnorm;
  209. long long sign;
  210. if (f < 0) { sign = 1; fnorm = -f; }
  211. else { sign = 0; fnorm = f; }
  212. int shift = 0;
  213. while(fnorm >= 2.0) { fnorm /= 2.0; shift++; }
  214. while(fnorm < 1.0) { fnorm *= 2.0; shift--; }
  215. fnorm = fnorm - 1.0;
  216. long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
  217. long long exp = shift + ((1<<(expbits-1)) - 1);
  218. return (uint64_t)((sign<<(bits-1)) | (exp<<(bits-expbits-1)) | significand);
  219. }
  220. static long double unpack754(uint64_t i, unsigned bits, unsigned expbits) {
  221. unsigned significandbits = bits - expbits - 1;
  222. long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
  223. result /= (1LL<<significandbits);
  224. result += 1.0f;
  225. unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
  226. long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
  227. while(shift > 0) { result *= 2.0; shift--; }
  228. while(shift < 0) { result /= 2.0; shift++; }
  229. result *= (i>>(bits-1))&1? -1.0: 1.0;
  230. return result;
  231. }
  232. /* Float */
  233. #define FLOAT_NAN 0xffc00000
  234. #define FLOAT_INF 0x7f800000
  235. #define FLOAT_NEG_INF 0xff800000
  236. #define FLOAT_NEG_ZERO 0x80000000
  237. static UA_StatusCode
  238. Float_encodeBinary(UA_Float const *src, bufpos pos, bufend end) {
  239. UA_Float f = *src;
  240. UA_UInt32 encoded;
  241. if(f != f) encoded = FLOAT_NAN;
  242. else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
  243. else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
  244. else encoded = (UA_UInt32)pack754(f, 32, 8);
  245. return UInt32_encodeBinary(&encoded, pos, end);
  246. }
  247. static UA_StatusCode
  248. Float_decodeBinary(bufpos pos, bufend end, UA_Float *dst) {
  249. UA_UInt32 decoded;
  250. UA_StatusCode retval = UInt32_decodeBinary(pos, end, &decoded);
  251. if(retval != UA_STATUSCODE_GOOD)
  252. return retval;
  253. if(decoded == 0) *dst = 0.0f;
  254. else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
  255. else if(decoded == FLOAT_INF) *dst = INFINITY;
  256. else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
  257. if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
  258. (decoded >= 0xff800001 && decoded <= 0xffffffff)) *dst = NAN;
  259. else *dst = (UA_Float)unpack754(decoded, 32, 8);
  260. return UA_STATUSCODE_GOOD;
  261. }
  262. /* Double */
  263. #define DOUBLE_NAN 0xfff8000000000000L
  264. #define DOUBLE_INF 0x7ff0000000000000L
  265. #define DOUBLE_NEG_INF 0xfff0000000000000L
  266. #define DOUBLE_NEG_ZERO 0x8000000000000000L
  267. static UA_StatusCode
  268. Double_encodeBinary(UA_Double const *src, bufpos pos, bufend end) {
  269. UA_Double d = *src;
  270. UA_UInt64 encoded;
  271. if(d != d) encoded = DOUBLE_NAN;
  272. else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
  273. else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
  274. else encoded = pack754(d, 64, 11);
  275. return UInt64_encodeBinary(&encoded, pos, end);
  276. }
  277. static UA_StatusCode
  278. Double_decodeBinary(bufpos pos, bufend end, UA_Double *dst) {
  279. UA_UInt64 decoded;
  280. UA_StatusCode retval = UInt64_decodeBinary(pos, end, &decoded);
  281. if(retval != UA_STATUSCODE_GOOD)
  282. return retval;
  283. if(decoded == 0) *dst = 0.0;
  284. else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
  285. else if(decoded == DOUBLE_INF) *dst = INFINITY;
  286. else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
  287. if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
  288. (decoded >= 0xfff0000000000001L && decoded <= 0xffffffffffffffffL)) *dst = NAN;
  289. else *dst = (UA_Double)unpack754(decoded, 64, 11);
  290. return UA_STATUSCODE_GOOD;
  291. }
  292. #endif
  293. /******************/
  294. /* Array Handling */
  295. /******************/
  296. static UA_StatusCode
  297. Array_encodeBinary(const void *src, size_t length, const UA_DataType *contenttype, bufpos pos, bufend end) {
  298. UA_Int32 signed_length = -1;
  299. if(length > UA_INT32_MAX)
  300. return UA_STATUSCODE_BADINTERNALERROR;
  301. if(length > 0)
  302. signed_length = (UA_Int32)length;
  303. else if(src == UA_EMPTY_ARRAY_SENTINEL)
  304. signed_length = 0;
  305. UA_StatusCode retval = Int32_encodeBinary(&signed_length, pos, end);
  306. if(retval != UA_STATUSCODE_GOOD || length == 0)
  307. return retval;
  308. if(contenttype->overlayable) {
  309. if(end < *pos + (contenttype->memSize * length))
  310. return UA_STATUSCODE_BADENCODINGERROR;
  311. memcpy(*pos, src, contenttype->memSize * length);
  312. (*pos) += contenttype->memSize * length;
  313. return retval;
  314. }
  315. uintptr_t ptr = (uintptr_t)src;
  316. size_t encode_index = contenttype->builtin ? contenttype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  317. for(size_t i = 0; i < length && retval == UA_STATUSCODE_GOOD; i++) {
  318. type = contenttype;
  319. retval = encodeBinaryJumpTable[encode_index]((const void*)ptr, pos, end);
  320. ptr += contenttype->memSize;
  321. }
  322. return retval;
  323. }
  324. static UA_StatusCode
  325. Array_decodeBinary(bufpos pos, bufend end, UA_Int32 signed_length, void *UA_RESTRICT *UA_RESTRICT dst,
  326. size_t *out_length, const UA_DataType *contenttype) {
  327. *out_length = 0;
  328. if(signed_length <= 0) {
  329. *dst = NULL;
  330. if(signed_length == 0)
  331. *dst = UA_EMPTY_ARRAY_SENTINEL;
  332. return UA_STATUSCODE_GOOD;
  333. }
  334. size_t length = (size_t)signed_length;
  335. /* filter out arrays that can obviously not be parsed, because the message
  336. is too small */
  337. if(*pos + ((contenttype->memSize * length) / 32) > end)
  338. return UA_STATUSCODE_BADDECODINGERROR;
  339. *dst = UA_calloc(1, contenttype->memSize * length);
  340. if(!*dst)
  341. return UA_STATUSCODE_BADOUTOFMEMORY;
  342. if(contenttype->overlayable) {
  343. if(end < *pos + (contenttype->memSize * length))
  344. return UA_STATUSCODE_BADDECODINGERROR;
  345. memcpy(*dst, *pos, contenttype->memSize * length);
  346. (*pos) += contenttype->memSize * length;
  347. *out_length = length;
  348. return UA_STATUSCODE_GOOD;
  349. }
  350. uintptr_t ptr = (uintptr_t)*dst;
  351. size_t decode_index = contenttype->builtin ? contenttype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  352. for(size_t i = 0; i < length; i++) {
  353. type = contenttype;
  354. UA_StatusCode retval = decodeBinaryJumpTable[decode_index](pos, end, (void*)ptr);
  355. if(retval != UA_STATUSCODE_GOOD) {
  356. UA_Array_delete(*dst, i, contenttype);
  357. *dst = NULL;
  358. return retval;
  359. }
  360. ptr += contenttype->memSize;
  361. }
  362. *out_length = length;
  363. return UA_STATUSCODE_GOOD;
  364. }
  365. /*****************/
  366. /* Builtin Types */
  367. /*****************/
  368. static UA_StatusCode
  369. String_encodeBinary(UA_String const *src, bufpos pos, bufend end) {
  370. if(*pos + sizeof(UA_Int32) + src->length > end)
  371. return UA_STATUSCODE_BADENCODINGERROR;
  372. if(src->length > UA_INT32_MAX)
  373. return UA_STATUSCODE_BADINTERNALERROR;
  374. UA_StatusCode retval;
  375. if((void*)src->data <= UA_EMPTY_ARRAY_SENTINEL) {
  376. UA_Int32 signed_length = -1;
  377. if(src->data == UA_EMPTY_ARRAY_SENTINEL)
  378. signed_length = 0;
  379. retval = Int32_encodeBinary(&signed_length, pos, end);
  380. } else {
  381. UA_Int32 signed_length = (UA_Int32)src->length;
  382. retval = Int32_encodeBinary(&signed_length, pos, end);
  383. memcpy(*pos, src->data, src->length);
  384. *pos += src->length;
  385. }
  386. return retval;
  387. }
  388. static UA_INLINE UA_StatusCode
  389. ByteString_encodeBinary(UA_ByteString const *src, bufpos pos, bufend end) {
  390. return String_encodeBinary((const UA_String*)src, pos, end);
  391. }
  392. static UA_StatusCode
  393. String_decodeBinary(bufpos pos, bufend end, UA_String *dst) {
  394. UA_Int32 signed_length;
  395. UA_StatusCode retval = Int32_decodeBinary(pos, end, &signed_length);
  396. if(retval != UA_STATUSCODE_GOOD)
  397. return UA_STATUSCODE_BADINTERNALERROR;
  398. if(signed_length <= 0) {
  399. if(signed_length == 0)
  400. dst->data = UA_EMPTY_ARRAY_SENTINEL;
  401. else
  402. dst->data = NULL;
  403. return UA_STATUSCODE_GOOD;
  404. }
  405. size_t length = (size_t)signed_length;
  406. if(*pos + length > end)
  407. return UA_STATUSCODE_BADDECODINGERROR;
  408. dst->data = UA_malloc(length);
  409. if(!dst->data)
  410. return UA_STATUSCODE_BADOUTOFMEMORY;
  411. memcpy(dst->data, *pos, length);
  412. dst->length = length;
  413. *pos += length;
  414. return UA_STATUSCODE_GOOD;
  415. }
  416. static UA_INLINE UA_StatusCode
  417. ByteString_decodeBinary(bufpos pos, bufend end, UA_ByteString *dst) {
  418. return String_decodeBinary(pos, end, (UA_ByteString*)dst);
  419. }
  420. /* Guid */
  421. static UA_StatusCode
  422. Guid_encodeBinary(UA_Guid const *src, bufpos pos, bufend end) {
  423. UA_StatusCode retval = UInt32_encodeBinary(&src->data1, pos, end);
  424. retval |= UInt16_encodeBinary(&src->data2, pos, end);
  425. retval |= UInt16_encodeBinary(&src->data3, pos, end);
  426. for(UA_Int32 i = 0; i < 8; i++)
  427. retval |= Byte_encodeBinary(&src->data4[i], pos, end);
  428. return retval;
  429. }
  430. static UA_StatusCode
  431. Guid_decodeBinary(bufpos pos, bufend end, UA_Guid *dst) {
  432. UA_StatusCode retval = UInt32_decodeBinary(pos, end, &dst->data1);
  433. retval |= UInt16_decodeBinary(pos, end, &dst->data2);
  434. retval |= UInt16_decodeBinary(pos, end, &dst->data3);
  435. for(size_t i = 0; i < 8; i++)
  436. retval |= Byte_decodeBinary(pos, end, &dst->data4[i]);
  437. if(retval != UA_STATUSCODE_GOOD)
  438. UA_Guid_deleteMembers(dst);
  439. return retval;
  440. }
  441. /* NodeId */
  442. #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
  443. #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
  444. #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
  445. static UA_StatusCode
  446. NodeId_encodeBinary(UA_NodeId const *src, bufpos pos, bufend end) {
  447. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  448. // temporary variables for endian-save code
  449. UA_Byte srcByte;
  450. UA_UInt16 srcUInt16;
  451. UA_UInt32 srcUInt32;
  452. switch (src->identifierType) {
  453. case UA_NODEIDTYPE_NUMERIC:
  454. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  455. srcByte = UA_NODEIDTYPE_NUMERIC_COMPLETE;
  456. retval |= Byte_encodeBinary(&srcByte, pos, end);
  457. retval |= UInt16_encodeBinary(&src->namespaceIndex, pos, end);
  458. srcUInt32 = src->identifier.numeric;
  459. retval |= UInt32_encodeBinary(&srcUInt32, pos, end);
  460. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  461. srcByte = UA_NODEIDTYPE_NUMERIC_FOURBYTE;
  462. retval |= Byte_encodeBinary(&srcByte, pos, end);
  463. srcByte = (UA_Byte)src->namespaceIndex;
  464. srcUInt16 = (UA_UInt16)src->identifier.numeric;
  465. retval |= Byte_encodeBinary(&srcByte, pos, end);
  466. retval |= UInt16_encodeBinary(&srcUInt16, pos, end);
  467. } else {
  468. srcByte = UA_NODEIDTYPE_NUMERIC_TWOBYTE;
  469. retval |= Byte_encodeBinary(&srcByte, pos, end);
  470. srcByte = (UA_Byte)src->identifier.numeric;
  471. retval |= Byte_encodeBinary(&srcByte, pos, end);
  472. }
  473. break;
  474. case UA_NODEIDTYPE_STRING:
  475. srcByte = UA_NODEIDTYPE_STRING;
  476. retval |= Byte_encodeBinary(&srcByte, pos, end);
  477. retval |= UInt16_encodeBinary(&src->namespaceIndex, pos, end);
  478. retval |= String_encodeBinary(&src->identifier.string, pos, end);
  479. break;
  480. case UA_NODEIDTYPE_GUID:
  481. srcByte = UA_NODEIDTYPE_GUID;
  482. retval |= Byte_encodeBinary(&srcByte, pos, end);
  483. retval |= UInt16_encodeBinary(&src->namespaceIndex, pos, end);
  484. retval |= Guid_encodeBinary(&src->identifier.guid, pos, end);
  485. break;
  486. case UA_NODEIDTYPE_BYTESTRING:
  487. srcByte = UA_NODEIDTYPE_BYTESTRING;
  488. retval |= Byte_encodeBinary(&srcByte, pos, end);
  489. retval |= UInt16_encodeBinary(&src->namespaceIndex, pos, end);
  490. retval |= ByteString_encodeBinary(&src->identifier.byteString, pos, end);
  491. break;
  492. default:
  493. return UA_STATUSCODE_BADINTERNALERROR;
  494. }
  495. return retval;
  496. }
  497. static UA_StatusCode
  498. NodeId_decodeBinary(bufpos pos, bufend end, UA_NodeId *dst) {
  499. UA_Byte dstByte = 0, encodingByte = 0;
  500. UA_UInt16 dstUInt16 = 0;
  501. UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingByte);
  502. if(retval != UA_STATUSCODE_GOOD)
  503. return retval;
  504. switch (encodingByte) {
  505. case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
  506. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  507. retval = Byte_decodeBinary(pos, end, &dstByte);
  508. dst->identifier.numeric = dstByte;
  509. dst->namespaceIndex = 0;
  510. break;
  511. case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
  512. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  513. retval |= Byte_decodeBinary(pos, end, &dstByte);
  514. dst->namespaceIndex = dstByte;
  515. retval |= UInt16_decodeBinary(pos, end, &dstUInt16);
  516. dst->identifier.numeric = dstUInt16;
  517. break;
  518. case UA_NODEIDTYPE_NUMERIC_COMPLETE:
  519. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  520. retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex);
  521. retval |= UInt32_decodeBinary(pos, end, &dst->identifier.numeric);
  522. break;
  523. case UA_NODEIDTYPE_STRING:
  524. dst->identifierType = UA_NODEIDTYPE_STRING;
  525. retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex);
  526. retval |= String_decodeBinary(pos, end, &dst->identifier.string);
  527. break;
  528. case UA_NODEIDTYPE_GUID:
  529. dst->identifierType = UA_NODEIDTYPE_GUID;
  530. retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex);
  531. retval |= Guid_decodeBinary(pos, end, &dst->identifier.guid);
  532. break;
  533. case UA_NODEIDTYPE_BYTESTRING:
  534. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  535. retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex);
  536. retval |= ByteString_decodeBinary(pos, end, &dst->identifier.byteString);
  537. break;
  538. default:
  539. retval |= UA_STATUSCODE_BADINTERNALERROR; // the client sends an encodingByte we do not recognize
  540. break;
  541. }
  542. if(retval != UA_STATUSCODE_GOOD)
  543. UA_NodeId_deleteMembers(dst);
  544. return retval;
  545. }
  546. /* ExpandedNodeId */
  547. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
  548. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
  549. static UA_StatusCode
  550. ExpandedNodeId_encodeBinary(UA_ExpandedNodeId const *src, bufpos pos, bufend end) {
  551. UA_Byte *start = *pos;
  552. UA_StatusCode retval = NodeId_encodeBinary(&src->nodeId, pos, end);
  553. if(src->namespaceUri.length > 0) {
  554. retval |= String_encodeBinary(&src->namespaceUri, pos, end);
  555. *start |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
  556. }
  557. if(src->serverIndex > 0) {
  558. retval |= UInt32_encodeBinary(&src->serverIndex, pos, end);
  559. *start |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
  560. }
  561. return retval;
  562. }
  563. static UA_StatusCode
  564. ExpandedNodeId_decodeBinary(bufpos pos, bufend end, UA_ExpandedNodeId *dst) {
  565. if(*pos >= end)
  566. return UA_STATUSCODE_BADDECODINGERROR;
  567. UA_Byte encodingByte = **pos;
  568. **pos = encodingByte & (UA_Byte)~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG | UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
  569. UA_StatusCode retval = NodeId_decodeBinary(pos, end, &dst->nodeId);
  570. if(encodingByte & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
  571. dst->nodeId.namespaceIndex = 0;
  572. retval |= String_decodeBinary(pos, end, &dst->namespaceUri);
  573. }
  574. if(encodingByte & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
  575. retval |= UInt32_decodeBinary(pos, end, &dst->serverIndex);
  576. if(retval != UA_STATUSCODE_GOOD)
  577. UA_ExpandedNodeId_deleteMembers(dst);
  578. return retval;
  579. }
  580. /* LocalizedText */
  581. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
  582. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
  583. static UA_StatusCode
  584. LocalizedText_encodeBinary(UA_LocalizedText const *src, bufpos pos, bufend end) {
  585. UA_Byte encodingMask = 0;
  586. if(src->locale.data)
  587. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  588. if(src->text.data)
  589. encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  590. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, pos, end);
  591. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  592. retval |= String_encodeBinary(&src->locale, pos, end);
  593. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  594. retval |= String_encodeBinary(&src->text, pos, end);
  595. return retval;
  596. }
  597. static UA_StatusCode
  598. LocalizedText_decodeBinary(bufpos pos, bufend end, UA_LocalizedText *dst) {
  599. UA_Byte encodingMask = 0;
  600. UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask);
  601. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  602. retval |= String_decodeBinary(pos, end, &dst->locale);
  603. if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  604. retval |= String_decodeBinary(pos, end, &dst->text);
  605. if(retval != UA_STATUSCODE_GOOD)
  606. UA_LocalizedText_deleteMembers(dst);
  607. return retval;
  608. }
  609. /* ExtensionObject */
  610. static UA_StatusCode
  611. ExtensionObject_encodeBinary(UA_ExtensionObject const *src, bufpos pos, bufend end) {
  612. UA_StatusCode retval;
  613. UA_Byte encoding = src->encoding;
  614. if(encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
  615. if(!src->content.decoded.type || !src->content.decoded.data)
  616. return UA_STATUSCODE_BADENCODINGERROR;
  617. UA_NodeId typeId = src->content.decoded.type->typeId;
  618. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  619. return UA_STATUSCODE_BADENCODINGERROR;
  620. typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
  621. encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  622. retval = NodeId_encodeBinary(&typeId, pos, end);
  623. retval |= Byte_encodeBinary(&encoding, pos, end);
  624. UA_Byte *old_pos = *pos; // jump back to encode the length
  625. (*pos) += 4;
  626. type = src->content.decoded.type;
  627. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  628. retval |= encodeBinaryJumpTable[encode_index](src->content.decoded.data, pos, end);
  629. UA_Int32 length = (UA_Int32)(((uintptr_t)*pos - (uintptr_t)old_pos) / sizeof(UA_Byte)) - 4;
  630. retval |= Int32_encodeBinary(&length, &old_pos, end);
  631. } else {
  632. retval = NodeId_encodeBinary(&src->content.encoded.typeId, pos, end);
  633. retval |= Byte_encodeBinary(&encoding, pos, end);
  634. switch (src->encoding) {
  635. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  636. break;
  637. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  638. case UA_EXTENSIONOBJECT_ENCODED_XML:
  639. retval |= ByteString_encodeBinary(&src->content.encoded.body, pos, end);
  640. break;
  641. default:
  642. return UA_STATUSCODE_BADINTERNALERROR;
  643. }
  644. }
  645. return retval;
  646. }
  647. static UA_StatusCode findDataType(const UA_NodeId *typeId, const UA_DataType **findtype) {
  648. for(size_t i = 0; i < UA_TYPES_COUNT; i++) {
  649. if(UA_NodeId_equal(typeId, &UA_TYPES[i].typeId)) {
  650. *findtype = &UA_TYPES[i];
  651. return UA_STATUSCODE_GOOD;
  652. }
  653. }
  654. return UA_STATUSCODE_BADNODEIDUNKNOWN;
  655. }
  656. static UA_StatusCode
  657. ExtensionObject_decodeBinary(bufpos pos, bufend end, UA_ExtensionObject *dst) {
  658. UA_Byte encoding = 0;
  659. UA_NodeId typeId;
  660. UA_NodeId_init(&typeId);
  661. UA_StatusCode retval = NodeId_decodeBinary(pos, end, &typeId);
  662. retval |= Byte_decodeBinary(pos, end, &encoding);
  663. if(typeId.namespaceIndex != 0 || typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  664. retval = UA_STATUSCODE_BADDECODINGERROR;
  665. if(retval != UA_STATUSCODE_GOOD) {
  666. UA_NodeId_deleteMembers(&typeId);
  667. return retval;
  668. }
  669. if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
  670. dst->encoding = encoding;
  671. dst->content.encoded.typeId = typeId;
  672. dst->content.encoded.body = UA_BYTESTRING_NULL;
  673. } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
  674. dst->encoding = encoding;
  675. dst->content.encoded.typeId = typeId;
  676. retval = ByteString_decodeBinary(pos, end, &dst->content.encoded.body);
  677. } else {
  678. /* try to decode the content */
  679. type = NULL;
  680. UA_assert(typeId.identifier.byteString.data == NULL); //helping clang analyzer, typeId is numeric
  681. UA_assert(typeId.identifier.string.data == NULL); //helping clang analyzer, typeId is numeric
  682. typeId.identifier.numeric -= UA_ENCODINGOFFSET_BINARY;
  683. findDataType(&typeId, &type);
  684. if(type) {
  685. /* UA_Int32 length = 0; */
  686. /* retval |= Int32_decodeBinary(pos, end, &length); */
  687. /* if(retval != UA_STATUSCODE_GOOD) */
  688. /* return retval; */
  689. (*pos) += 4; // jump over the length
  690. dst->content.decoded.data = UA_new(type);
  691. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  692. if(dst->content.decoded.data) {
  693. dst->content.decoded.type = type;
  694. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  695. retval = decodeBinaryJumpTable[decode_index](pos, end, dst->content.decoded.data);
  696. } else
  697. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  698. } else {
  699. retval = ByteString_decodeBinary(pos, end, &dst->content.encoded.body);
  700. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  701. dst->content.encoded.typeId = typeId;
  702. }
  703. }
  704. if(retval != UA_STATUSCODE_GOOD)
  705. UA_ExtensionObject_deleteMembers(dst);
  706. return retval;
  707. }
  708. /* Variant */
  709. /* Types that are not builtin get wrapped in an ExtensionObject */
  710. enum UA_VARIANT_ENCODINGMASKTYPE {
  711. UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F, // bits 0:5
  712. UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (0x01 << 6), // bit 6
  713. UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) // bit 7
  714. };
  715. static UA_StatusCode
  716. Variant_encodeBinary(UA_Variant const *src, bufpos pos, bufend end) {
  717. if(!src->type)
  718. return UA_STATUSCODE_BADINTERNALERROR;
  719. const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  720. const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  721. const UA_Boolean isBuiltin = src->type->builtin;
  722. UA_Byte encodingByte = 0;
  723. if(isArray) {
  724. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  725. if(hasDimensions)
  726. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  727. }
  728. UA_NodeId typeId;
  729. UA_NodeId_init(&typeId);
  730. size_t encode_index = src->type->typeIndex;
  731. if(isBuiltin) {
  732. /* Do an extra lookup. Enums are encoded as UA_UInt32. */
  733. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK &
  734. (UA_Byte) (src->type->typeIndex + 1);
  735. } else {
  736. encode_index = UA_BUILTIN_TYPES_COUNT;
  737. /* wrap the datatype in an extensionobject */
  738. encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte) 22;
  739. typeId = src->type->typeId;
  740. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  741. return UA_STATUSCODE_BADINTERNALERROR;
  742. typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
  743. }
  744. UA_StatusCode retval = Byte_encodeBinary(&encodingByte, pos, end);
  745. size_t length = src->arrayLength;
  746. if(!isArray) {
  747. length = 1;
  748. } else {
  749. if(src->arrayDimensionsSize > UA_INT32_MAX)
  750. return UA_STATUSCODE_BADINTERNALERROR;
  751. UA_Int32 encodeLength = -1;
  752. if(src->arrayLength > 0)
  753. encodeLength = (UA_Int32)src->arrayLength;
  754. else if(src->data == UA_EMPTY_ARRAY_SENTINEL)
  755. encodeLength = 0;
  756. retval |= Int32_encodeBinary(&encodeLength, pos, end);
  757. }
  758. uintptr_t ptr = (uintptr_t)src->data;
  759. const UA_UInt16 memSize = src->type->memSize;
  760. for(size_t i = 0; i < length; i++) {
  761. UA_Byte *old_pos; // before encoding the actual content
  762. if(!isBuiltin) {
  763. /* The type is wrapped inside an extensionobject */
  764. retval |= NodeId_encodeBinary(&typeId, pos, end);
  765. UA_Byte eoEncoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  766. retval |= Byte_encodeBinary(&eoEncoding, pos, end);
  767. (*pos) += 4;
  768. old_pos = *pos;
  769. }
  770. type = src->type;
  771. retval |= encodeBinaryJumpTable[encode_index]((const void*)ptr, pos, end);
  772. if(!isBuiltin) {
  773. /* Jump back and print the length of the extension object */
  774. UA_Int32 encodingLength = (UA_Int32)(((uintptr_t)*pos - (uintptr_t)old_pos) / sizeof(UA_Byte));
  775. old_pos -= 4;
  776. retval |= Int32_encodeBinary(&encodingLength, &old_pos, end);
  777. }
  778. ptr += memSize;
  779. }
  780. if(hasDimensions)
  781. retval |= Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  782. &UA_TYPES[UA_TYPES_INT32], pos, end);
  783. return retval;
  784. }
  785. /* The resulting variant always has the storagetype UA_VARIANT_DATA. Currently,
  786. we only support ns0 types (todo: attach typedescriptions to datatypenodes) */
  787. static UA_StatusCode
  788. Variant_decodeBinary(bufpos pos, bufend end, UA_Variant *dst) {
  789. UA_Byte encodingByte;
  790. UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingByte);
  791. if(retval != UA_STATUSCODE_GOOD)
  792. return retval;
  793. UA_Boolean isArray = encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  794. size_t typeIndex = (size_t)((encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
  795. if(typeIndex > 24) /* the type must be builtin (maybe wrapped in an extensionobject) */
  796. return UA_STATUSCODE_BADDECODINGERROR;
  797. if(isArray) {
  798. /* an array */
  799. dst->type = &UA_TYPES[typeIndex];
  800. UA_Int32 signedLength = 0;
  801. retval |= Int32_decodeBinary(pos, end, &signedLength);
  802. if(retval != UA_STATUSCODE_GOOD)
  803. return retval;
  804. retval = Array_decodeBinary(pos, end, signedLength, &dst->data, &dst->arrayLength, dst->type);
  805. } else if (typeIndex != UA_TYPES_EXTENSIONOBJECT) {
  806. /* a builtin type */
  807. dst->type = &UA_TYPES[typeIndex];
  808. retval = Array_decodeBinary(pos, end, 1, &dst->data, &dst->arrayLength, dst->type);
  809. dst->arrayLength = 0;
  810. } else {
  811. /* a single extensionobject */
  812. UA_Byte *old_pos = *pos;
  813. UA_NodeId typeId;
  814. UA_NodeId_init(&typeId);
  815. retval = NodeId_decodeBinary(pos, end, &typeId);
  816. if(retval != UA_STATUSCODE_GOOD)
  817. return retval;
  818. UA_Byte eo_encoding;
  819. retval = Byte_decodeBinary(pos, end, &eo_encoding);
  820. if(retval != UA_STATUSCODE_GOOD) {
  821. UA_NodeId_deleteMembers(&typeId);
  822. return retval;
  823. }
  824. /* search for the datatype. use extensionobject if nothing is found */
  825. dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
  826. if(typeId.namespaceIndex == 0 && eo_encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
  827. findDataType(&typeId, &dst->type) == UA_STATUSCODE_GOOD)
  828. *pos = old_pos;
  829. UA_NodeId_deleteMembers(&typeId);
  830. /* decode the type */
  831. dst->data = UA_calloc(1, dst->type->memSize);
  832. if(dst->data) {
  833. size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  834. type = dst->type;
  835. retval = decodeBinaryJumpTable[decode_index](pos, end, dst->data);
  836. if(retval != UA_STATUSCODE_GOOD) {
  837. UA_free(dst->data);
  838. dst->data = NULL;
  839. }
  840. } else
  841. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  842. }
  843. /* array dimensions */
  844. if(isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS)) {
  845. UA_Int32 signed_length = 0;
  846. retval |= Int32_decodeBinary(pos, end, &signed_length);
  847. if(retval == UA_STATUSCODE_GOOD)
  848. retval = Array_decodeBinary(pos, end, signed_length, (void**)&dst->arrayDimensions,
  849. &dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
  850. }
  851. if(retval != UA_STATUSCODE_GOOD)
  852. UA_Variant_deleteMembers(dst);
  853. return retval;
  854. }
  855. /* DataValue */
  856. static UA_StatusCode
  857. DataValue_encodeBinary(UA_DataValue const *src, bufpos pos, bufend end) {
  858. UA_Byte encodingMask = (UA_Byte)
  859. (src->hasValue | (src->hasStatus << 1) | (src->hasSourceTimestamp << 2) |
  860. (src->hasServerTimestamp << 3) | (src->hasSourcePicoseconds << 4) |
  861. (src->hasServerPicoseconds << 5));
  862. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, pos, end);
  863. if(src->hasValue)
  864. retval |= Variant_encodeBinary(&src->value, pos, end);
  865. if(src->hasStatus)
  866. retval |= StatusCode_encodeBinary(&src->status, pos, end);
  867. if(src->hasSourceTimestamp)
  868. retval |= DateTime_encodeBinary(&src->sourceTimestamp, pos, end);
  869. if(src->hasSourcePicoseconds)
  870. retval |= UInt16_encodeBinary(&src->sourcePicoseconds, pos, end);
  871. if(src->hasServerTimestamp)
  872. retval |= DateTime_encodeBinary(&src->serverTimestamp, pos, end);
  873. if(src->hasServerPicoseconds)
  874. retval |= UInt16_encodeBinary(&src->serverPicoseconds, pos, end);
  875. return retval;
  876. }
  877. #define MAX_PICO_SECONDS 999
  878. static UA_StatusCode
  879. DataValue_decodeBinary(bufpos pos, bufend end, UA_DataValue *dst) {
  880. UA_Byte encodingMask;
  881. UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask);
  882. if(retval != UA_STATUSCODE_GOOD)
  883. return retval;
  884. if(encodingMask & 0x01) {
  885. dst->hasValue = true;
  886. retval |= Variant_decodeBinary(pos, end, &dst->value);
  887. }
  888. if(encodingMask & 0x02) {
  889. dst->hasStatus = true;
  890. retval |= StatusCode_decodeBinary(pos, end, &dst->status);
  891. }
  892. if(encodingMask & 0x04) {
  893. dst->hasSourceTimestamp = true;
  894. retval |= DateTime_decodeBinary(pos, end, &dst->sourceTimestamp);
  895. }
  896. if(encodingMask & 0x08) {
  897. dst->hasServerTimestamp = true;
  898. retval |= DateTime_decodeBinary(pos, end, &dst->serverTimestamp);
  899. }
  900. if(encodingMask & 0x10) {
  901. dst->hasSourcePicoseconds = true;
  902. retval |= UInt16_decodeBinary(pos, end, &dst->sourcePicoseconds);
  903. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  904. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  905. }
  906. if(encodingMask & 0x20) {
  907. dst->hasServerPicoseconds = true;
  908. retval |= UInt16_decodeBinary(pos, end, &dst->serverPicoseconds);
  909. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  910. dst->serverPicoseconds = MAX_PICO_SECONDS;
  911. }
  912. if(retval != UA_STATUSCODE_GOOD)
  913. UA_DataValue_deleteMembers(dst);
  914. return retval;
  915. }
  916. /* DiagnosticInfo */
  917. static UA_StatusCode
  918. DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, bufpos pos, bufend end) {
  919. UA_Byte encodingMask = (UA_Byte)
  920. (src->hasSymbolicId | (src->hasNamespaceUri << 1) | (src->hasLocalizedText << 2) |
  921. (src->hasLocale << 3) | (src->hasAdditionalInfo << 4) | (src->hasInnerDiagnosticInfo << 5));
  922. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, pos, end);
  923. if(src->hasSymbolicId)
  924. retval |= Int32_encodeBinary(&src->symbolicId, pos, end);
  925. if(src->hasNamespaceUri)
  926. retval |= Int32_encodeBinary(&src->namespaceUri, pos, end);
  927. if(src->hasLocalizedText)
  928. retval |= Int32_encodeBinary(&src->localizedText, pos, end);
  929. if(src->hasLocale)
  930. retval |= Int32_encodeBinary(&src->locale, pos, end);
  931. if(src->hasAdditionalInfo)
  932. retval |= String_encodeBinary(&src->additionalInfo, pos, end);
  933. if(src->hasInnerStatusCode)
  934. retval |= StatusCode_encodeBinary(&src->innerStatusCode, pos, end);
  935. if(src->hasInnerDiagnosticInfo)
  936. retval |= DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, pos, end);
  937. return retval;
  938. }
  939. static UA_StatusCode
  940. DiagnosticInfo_decodeBinary(bufpos pos, bufend end, UA_DiagnosticInfo *dst) {
  941. UA_Byte encodingMask;
  942. UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask);
  943. if(retval != UA_STATUSCODE_GOOD)
  944. return retval;
  945. if(encodingMask & 0x01) {
  946. dst->hasSymbolicId = true;
  947. retval |= Int32_decodeBinary(pos, end, &dst->symbolicId);
  948. }
  949. if(encodingMask & 0x02) {
  950. dst->hasNamespaceUri = true;
  951. retval |= Int32_decodeBinary(pos, end, &dst->namespaceUri);
  952. }
  953. if(encodingMask & 0x04) {
  954. dst->hasLocalizedText = true;
  955. retval |= Int32_decodeBinary(pos, end, &dst->localizedText);
  956. }
  957. if(encodingMask & 0x08) {
  958. dst->hasLocale = true;
  959. retval |= Int32_decodeBinary(pos, end, &dst->locale);
  960. }
  961. if(encodingMask & 0x10) {
  962. dst->hasAdditionalInfo = true;
  963. retval |= String_decodeBinary(pos, end, &dst->additionalInfo);
  964. }
  965. if(encodingMask & 0x20) {
  966. dst->hasInnerStatusCode = true;
  967. retval |= StatusCode_decodeBinary(pos, end, &dst->innerStatusCode);
  968. }
  969. if(encodingMask & 0x40) {
  970. dst->hasInnerDiagnosticInfo = true;
  971. /* innerDiagnosticInfo is a pointer to struct, therefore allocate */
  972. dst->innerDiagnosticInfo = UA_calloc(1, sizeof(UA_DiagnosticInfo));
  973. if(dst->innerDiagnosticInfo)
  974. retval |= DiagnosticInfo_decodeBinary(pos, end, dst->innerDiagnosticInfo);
  975. else {
  976. dst->hasInnerDiagnosticInfo = false;
  977. retval |= UA_STATUSCODE_BADOUTOFMEMORY;
  978. }
  979. }
  980. if(retval != UA_STATUSCODE_GOOD)
  981. UA_DiagnosticInfo_deleteMembers(dst);
  982. return retval;
  983. }
  984. /********************/
  985. /* Structured Types */
  986. /********************/
  987. static UA_StatusCode
  988. UA_encodeBinaryInternal(const void *src, bufpos pos, bufend end) {
  989. uintptr_t ptr = (uintptr_t)src;
  990. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  991. UA_Byte membersSize = type->membersSize;
  992. const UA_DataType *localtype = type;
  993. const UA_DataType *typelists[2] = { UA_TYPES, &localtype[-localtype->typeIndex] };
  994. for(size_t i = 0; i < membersSize; i++) {
  995. const UA_DataTypeMember *member = &localtype->members[i];
  996. type = &typelists[!member->namespaceZero][member->memberTypeIndex];
  997. if(!member->isArray) {
  998. ptr += member->padding;
  999. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1000. size_t memSize = type->memSize;
  1001. retval |= encodeBinaryJumpTable[encode_index]((const void*)ptr, pos, end);
  1002. ptr += memSize;
  1003. } else {
  1004. ptr += member->padding;
  1005. const size_t length = *((const size_t*)ptr);
  1006. ptr += sizeof(size_t);
  1007. retval |= Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, type, pos, end);
  1008. ptr += sizeof(void*);
  1009. }
  1010. }
  1011. return retval;
  1012. }
  1013. static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1014. (UA_encodeBinarySignature)Boolean_encodeBinary,
  1015. (UA_encodeBinarySignature)Byte_encodeBinary, // SByte
  1016. (UA_encodeBinarySignature)Byte_encodeBinary,
  1017. (UA_encodeBinarySignature)UInt16_encodeBinary, // Int16
  1018. (UA_encodeBinarySignature)UInt16_encodeBinary,
  1019. (UA_encodeBinarySignature)UInt32_encodeBinary, // Int32
  1020. (UA_encodeBinarySignature)UInt32_encodeBinary,
  1021. (UA_encodeBinarySignature)UInt64_encodeBinary, // Int64
  1022. (UA_encodeBinarySignature)UInt64_encodeBinary,
  1023. (UA_encodeBinarySignature)Float_encodeBinary,
  1024. (UA_encodeBinarySignature)Double_encodeBinary,
  1025. (UA_encodeBinarySignature)String_encodeBinary,
  1026. (UA_encodeBinarySignature)UInt64_encodeBinary, // DateTime
  1027. (UA_encodeBinarySignature)Guid_encodeBinary,
  1028. (UA_encodeBinarySignature)String_encodeBinary, // ByteString
  1029. (UA_encodeBinarySignature)String_encodeBinary, // XmlElement
  1030. (UA_encodeBinarySignature)NodeId_encodeBinary,
  1031. (UA_encodeBinarySignature)ExpandedNodeId_encodeBinary,
  1032. (UA_encodeBinarySignature)UInt32_encodeBinary, // StatusCode
  1033. (UA_encodeBinarySignature)UA_encodeBinaryInternal, // QualifiedName
  1034. (UA_encodeBinarySignature)LocalizedText_encodeBinary,
  1035. (UA_encodeBinarySignature)ExtensionObject_encodeBinary,
  1036. (UA_encodeBinarySignature)DataValue_encodeBinary,
  1037. (UA_encodeBinarySignature)Variant_encodeBinary,
  1038. (UA_encodeBinarySignature)DiagnosticInfo_encodeBinary,
  1039. (UA_encodeBinarySignature)UA_encodeBinaryInternal,
  1040. };
  1041. UA_StatusCode UA_encodeBinary(const void *src, const UA_DataType *localtype, UA_ByteString *dst, size_t *offset) {
  1042. UA_Byte *pos = &dst->data[*offset];
  1043. UA_Byte *end = &dst->data[dst->length];
  1044. type = localtype;
  1045. UA_StatusCode retval = UA_encodeBinaryInternal(src, &pos, end);
  1046. *offset = (size_t)(pos - dst->data) / sizeof(UA_Byte);
  1047. return retval;
  1048. }
  1049. static UA_StatusCode
  1050. UA_decodeBinaryInternal(bufpos pos, bufend end, void *dst) {
  1051. uintptr_t ptr = (uintptr_t)dst;
  1052. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1053. UA_Byte membersSize = type->membersSize;
  1054. const UA_DataType *localtype = type;
  1055. const UA_DataType *typelists[2] = { UA_TYPES, &localtype[-localtype->typeIndex] };
  1056. for(size_t i = 0; i < membersSize; i++) {
  1057. const UA_DataTypeMember *member = &localtype->members[i];
  1058. type = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1059. if(!member->isArray) {
  1060. ptr += member->padding;
  1061. size_t fi = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1062. size_t memSize = type->memSize;
  1063. retval |= decodeBinaryJumpTable[fi](pos, end, (void *UA_RESTRICT)ptr);
  1064. ptr += memSize;
  1065. } else {
  1066. ptr += member->padding;
  1067. size_t *length = (size_t*)ptr;
  1068. ptr += sizeof(size_t);
  1069. UA_Int32 slength = -1;
  1070. retval |= Int32_decodeBinary(pos, end, &slength);
  1071. retval |= Array_decodeBinary(pos, end, slength, (void *UA_RESTRICT *UA_RESTRICT)ptr, length, type);
  1072. ptr += sizeof(void*);
  1073. }
  1074. }
  1075. if(retval != UA_STATUSCODE_GOOD)
  1076. UA_deleteMembers(dst, localtype);
  1077. return retval;
  1078. }
  1079. static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1080. (UA_decodeBinarySignature)Boolean_decodeBinary,
  1081. (UA_decodeBinarySignature)Byte_decodeBinary, // SByte
  1082. (UA_decodeBinarySignature)Byte_decodeBinary,
  1083. (UA_decodeBinarySignature)UInt16_decodeBinary, // Int16
  1084. (UA_decodeBinarySignature)UInt16_decodeBinary,
  1085. (UA_decodeBinarySignature)UInt32_decodeBinary, // Int32
  1086. (UA_decodeBinarySignature)UInt32_decodeBinary,
  1087. (UA_decodeBinarySignature)UInt64_decodeBinary, // Int64
  1088. (UA_decodeBinarySignature)UInt64_decodeBinary,
  1089. (UA_decodeBinarySignature)Float_decodeBinary,
  1090. (UA_decodeBinarySignature)Double_decodeBinary,
  1091. (UA_decodeBinarySignature)String_decodeBinary,
  1092. (UA_decodeBinarySignature)UInt64_decodeBinary, // DateTime
  1093. (UA_decodeBinarySignature)Guid_decodeBinary,
  1094. (UA_decodeBinarySignature)String_decodeBinary, // ByteString
  1095. (UA_decodeBinarySignature)String_decodeBinary, // XmlElement
  1096. (UA_decodeBinarySignature)NodeId_decodeBinary,
  1097. (UA_decodeBinarySignature)ExpandedNodeId_decodeBinary,
  1098. (UA_decodeBinarySignature)UInt32_decodeBinary, // StatusCode
  1099. (UA_decodeBinarySignature)UA_decodeBinaryInternal, // QualifiedName
  1100. (UA_decodeBinarySignature)LocalizedText_decodeBinary,
  1101. (UA_decodeBinarySignature)ExtensionObject_decodeBinary,
  1102. (UA_decodeBinarySignature)DataValue_decodeBinary,
  1103. (UA_decodeBinarySignature)Variant_decodeBinary,
  1104. (UA_decodeBinarySignature)DiagnosticInfo_decodeBinary,
  1105. (UA_decodeBinarySignature)UA_decodeBinaryInternal
  1106. };
  1107. UA_StatusCode
  1108. UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst, const UA_DataType *localtype) {
  1109. memset(dst, 0, localtype->memSize); // init
  1110. UA_Byte *pos = &src->data[*offset];
  1111. UA_Byte *end = &src->data[src->length];
  1112. type = localtype;
  1113. UA_StatusCode retval = UA_decodeBinaryInternal(&pos, end, dst);
  1114. *offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
  1115. return retval;
  1116. }
  1117. /******************/
  1118. /* CalcSizeBinary */
  1119. /******************/
  1120. static size_t
  1121. Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *contenttype) {
  1122. size_t s = 4; // length
  1123. if(contenttype->overlayable) {
  1124. s += contenttype->memSize * length;
  1125. return s;
  1126. }
  1127. uintptr_t ptr = (uintptr_t)src;
  1128. size_t encode_index = contenttype->builtin ? contenttype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1129. for(size_t i = 0; i < length; i++) {
  1130. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, contenttype);
  1131. ptr += contenttype->memSize;
  1132. }
  1133. return s;
  1134. }
  1135. static size_t calcSizeBinaryMemSize(const void *UA_RESTRICT p, const UA_DataType *datatype) {
  1136. return datatype->memSize;
  1137. }
  1138. static size_t String_calcSizeBinary(const UA_String *UA_RESTRICT p, const UA_DataType *_) {
  1139. return 4 + p->length;
  1140. }
  1141. static size_t Guid_calcSizeBinary(const UA_Guid *UA_RESTRICT p, const UA_DataType *_) {
  1142. return 16;
  1143. }
  1144. static size_t
  1145. NodeId_calcSizeBinary(const UA_NodeId *UA_RESTRICT src, const UA_DataType *_) {
  1146. size_t s = 1; // encoding byte
  1147. switch (src->identifierType) {
  1148. case UA_NODEIDTYPE_NUMERIC:
  1149. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  1150. s += 6;
  1151. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  1152. s += 3;
  1153. } else {
  1154. s += 1;
  1155. }
  1156. break;
  1157. case UA_NODEIDTYPE_BYTESTRING:
  1158. case UA_NODEIDTYPE_STRING:
  1159. s += 2;
  1160. s += String_calcSizeBinary(&src->identifier.string, NULL);
  1161. break;
  1162. case UA_NODEIDTYPE_GUID:
  1163. s += 18;
  1164. break;
  1165. default:
  1166. return 0;
  1167. }
  1168. return s;
  1169. }
  1170. static size_t
  1171. ExpandedNodeId_calcSizeBinary(const UA_ExpandedNodeId *src, const UA_DataType *_) {
  1172. size_t s = NodeId_calcSizeBinary(&src->nodeId, NULL);
  1173. if(src->namespaceUri.length > 0)
  1174. s += String_calcSizeBinary(&src->namespaceUri, NULL);
  1175. if(src->serverIndex > 0)
  1176. s += 4;
  1177. return s;
  1178. }
  1179. static size_t
  1180. LocalizedText_calcSizeBinary(const UA_LocalizedText *src, UA_DataType *_) {
  1181. size_t s = 1; // encoding byte
  1182. if(src->locale.data)
  1183. s += String_calcSizeBinary(&src->locale, NULL);
  1184. if(src->text.data)
  1185. s += String_calcSizeBinary(&src->text, NULL);
  1186. return s;
  1187. }
  1188. static size_t
  1189. ExtensionObject_calcSizeBinary(const UA_ExtensionObject *src, UA_DataType *_) {
  1190. size_t s = 1; // encoding byte
  1191. if(src->encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
  1192. if(!src->content.decoded.type || !src->content.decoded.data)
  1193. return 0;
  1194. if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1195. return 0;
  1196. s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL);
  1197. s += 4; // length
  1198. size_t encode_index = src->content.decoded.type->builtin ?
  1199. src->content.decoded.type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1200. s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, src->content.decoded.type);
  1201. } else {
  1202. s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
  1203. switch (src->encoding) {
  1204. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  1205. break;
  1206. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  1207. case UA_EXTENSIONOBJECT_ENCODED_XML:
  1208. s += String_calcSizeBinary(&src->content.encoded.body, NULL);
  1209. break;
  1210. default:
  1211. return 0;
  1212. }
  1213. }
  1214. return s;
  1215. }
  1216. static size_t
  1217. Variant_calcSizeBinary(UA_Variant const *src, UA_DataType *_) {
  1218. size_t s = 1; // encoding byte
  1219. if(!src->type)
  1220. return 0;
  1221. UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  1222. UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  1223. UA_Boolean isBuiltin = src->type->builtin;
  1224. UA_NodeId typeId;
  1225. UA_NodeId_init(&typeId);
  1226. size_t encode_index = src->type->typeIndex;
  1227. if(!isBuiltin) {
  1228. encode_index = UA_BUILTIN_TYPES_COUNT;
  1229. typeId = src->type->typeId;
  1230. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1231. return 0;
  1232. }
  1233. size_t length = src->arrayLength;
  1234. if(isArray) {
  1235. s += 4;
  1236. } else
  1237. length = 1;
  1238. uintptr_t ptr = (uintptr_t)src->data;
  1239. size_t memSize = src->type->memSize;
  1240. for(size_t i = 0; i < length; i++) {
  1241. if(!isBuiltin) {
  1242. /* The type is wrapped inside an extensionobject */
  1243. s += NodeId_calcSizeBinary(&typeId, NULL);
  1244. s += 1 + 4; // encoding byte + length
  1245. }
  1246. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, src->type);
  1247. ptr += memSize;
  1248. }
  1249. if(hasDimensions)
  1250. s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  1251. &UA_TYPES[UA_TYPES_INT32]);
  1252. return s;
  1253. }
  1254. static size_t
  1255. DataValue_calcSizeBinary(const UA_DataValue *src, UA_DataType *_) {
  1256. size_t s = 1; // encoding byte
  1257. if(src->hasValue)
  1258. s += Variant_calcSizeBinary(&src->value, NULL);
  1259. if(src->hasStatus)
  1260. s += 4;
  1261. if(src->hasSourceTimestamp)
  1262. s += 8;
  1263. if(src->hasSourcePicoseconds)
  1264. s += 2;
  1265. if(src->hasServerTimestamp)
  1266. s += 8;
  1267. if(src->hasServerPicoseconds)
  1268. s += 2;
  1269. return s;
  1270. }
  1271. static size_t
  1272. DiagnosticInfo_calcSizeBinary(const UA_DiagnosticInfo *src, UA_DataType *_) {
  1273. size_t s = 1; // encoding byte
  1274. if(src->hasSymbolicId)
  1275. s += 4;
  1276. if(src->hasNamespaceUri)
  1277. s += 4;
  1278. if(src->hasLocalizedText)
  1279. s += 4;
  1280. if(src->hasLocale)
  1281. s += 4;
  1282. if(src->hasAdditionalInfo)
  1283. s += String_calcSizeBinary(&src->additionalInfo, NULL);
  1284. if(src->hasInnerStatusCode)
  1285. s += 4;
  1286. if(src->hasInnerDiagnosticInfo)
  1287. s += DiagnosticInfo_calcSizeBinary(src->innerDiagnosticInfo, NULL);
  1288. return s;
  1289. }
  1290. static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1291. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Boolean
  1292. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Byte
  1293. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1294. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int16
  1295. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1296. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int32
  1297. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1298. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int64
  1299. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1300. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Float
  1301. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Double
  1302. (UA_calcSizeBinarySignature)String_calcSizeBinary,
  1303. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // DateTime
  1304. (UA_calcSizeBinarySignature)Guid_calcSizeBinary,
  1305. (UA_calcSizeBinarySignature)String_calcSizeBinary, // ByteString
  1306. (UA_calcSizeBinarySignature)String_calcSizeBinary, // XmlElement
  1307. (UA_calcSizeBinarySignature)NodeId_calcSizeBinary,
  1308. (UA_calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
  1309. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // StatusCode
  1310. (UA_calcSizeBinarySignature)UA_calcSizeBinary, // QualifiedName
  1311. (UA_calcSizeBinarySignature)LocalizedText_calcSizeBinary,
  1312. (UA_calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
  1313. (UA_calcSizeBinarySignature)DataValue_calcSizeBinary,
  1314. (UA_calcSizeBinarySignature)Variant_calcSizeBinary,
  1315. (UA_calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
  1316. (UA_calcSizeBinarySignature)UA_calcSizeBinary
  1317. };
  1318. size_t UA_calcSizeBinary(void *p, const UA_DataType *contenttype) {
  1319. size_t s = 0;
  1320. uintptr_t ptr = (uintptr_t)p;
  1321. UA_Byte membersSize = contenttype->membersSize;
  1322. const UA_DataType *typelists[2] = { UA_TYPES, &contenttype[-contenttype->typeIndex] };
  1323. for(size_t i = 0; i < membersSize; i++) {
  1324. const UA_DataTypeMember *member = &contenttype->members[i];
  1325. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1326. if(!member->isArray) {
  1327. ptr += member->padding;
  1328. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1329. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
  1330. ptr += membertype->memSize;
  1331. } else {
  1332. ptr += member->padding;
  1333. const size_t length = *((const size_t*)ptr);
  1334. ptr += sizeof(size_t);
  1335. s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1336. ptr += sizeof(void*);
  1337. }
  1338. }
  1339. return s;
  1340. }