ua_types_encoding_binary.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "ua_util.h"
  5. #include "ua_types_encoding_binary.h"
  6. #include "ua_types_generated.h"
  7. #include "ua_types_generated_handling.h"
  8. /* Type Encoding
  9. * -------------
  10. * This file contains encoding functions for the builtin data types and generic
  11. * functions that operate on all types and arrays. This requires the type
  12. * description from a UA_DataType structure. Note that some internal (static)
  13. * deocidng functions may abort and leave the type in an inconsistent state. But
  14. * this is always handled in UA_decodeBinary, where the error is caught and the
  15. * type cleaned up.
  16. *
  17. * Breaking a message into chunks is integrated with the encoding. When the end
  18. * of a buffer is reached, a callback is executed that sends the current buffer
  19. * as a chunk and exchanges the encoding buffer "underneath" the ongoing
  20. * encoding. This enables fast sending of large messages as spurious copying is
  21. * avoided. */
  22. #if defined(__clang__)
  23. # pragma GCC diagnostic push
  24. # pragma GCC diagnostic warning "-W#warnings"
  25. #endif
  26. #ifndef UA_BINARY_OVERLAYABLE_INTEGER
  27. # warning Integer endianness could not be detected to be little endian. Use slow generic encoding.
  28. #endif
  29. /* There is no robust way to detect float endianness in clang. This warning can be removed
  30. * if the target is known to be little endian with floats in the IEEE 754 format. */
  31. #ifndef UA_BINARY_OVERLAYABLE_FLOAT
  32. # warning Float endianness could not be detected to be little endian in the IEEE 754 format. Use slow generic encoding.
  33. #endif
  34. #if defined(__clang__)
  35. # pragma GCC diagnostic pop
  36. #endif
  37. /* Jumptables for de-/encoding and computing the buffer length */
  38. typedef UA_StatusCode (*UA_encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type);
  39. extern const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  40. typedef UA_StatusCode (*UA_decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type);
  41. extern const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  42. typedef size_t (*UA_calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
  43. extern const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  44. /* Pointer to custom datatypes in the server or client. Set inside
  45. * UA_decodeBinary */
  46. UA_THREAD_LOCAL size_t customTypesArraySize;
  47. UA_THREAD_LOCAL const UA_DataType *customTypesArray;
  48. /* We give pointers to the current position and the last position in the buffer
  49. * instead of a string with an offset. */
  50. UA_THREAD_LOCAL UA_Byte * pos;
  51. UA_THREAD_LOCAL UA_Byte * end;
  52. /* The code UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED is returned only when the end of the
  53. * buffer is reached. When this StatusCode is received, we try to send the current chunk,
  54. * replace the buffer and continue encoding. That way, memory-constrained servers need to
  55. * allocate only the memory for the current chunk. And we avoid needless copying. Note:
  56. * The only place where this is used from is UA_SecureChannel_sendBinaryMessage. */
  57. /* Thread-local buffers used for exchanging the buffer for chunking */
  58. UA_THREAD_LOCAL UA_ByteString *encodeBuf; /* the original buffer */
  59. UA_THREAD_LOCAL UA_exchangeEncodeBuffer exchangeBufferCallback;
  60. UA_THREAD_LOCAL void *exchangeBufferCallbackHandle;
  61. /* Send the current chunk and replace the buffer */
  62. static UA_StatusCode
  63. exchangeBuffer(void) {
  64. if(!exchangeBufferCallback)
  65. return UA_STATUSCODE_BADENCODINGERROR;
  66. /* Store context variables since chunk-sending might call UA_encode itself */
  67. UA_ByteString *store_encodeBuf = encodeBuf;
  68. UA_exchangeEncodeBuffer store_exchangeBufferCallback = exchangeBufferCallback;
  69. void *store_exchangeBufferCallbackHandle = exchangeBufferCallbackHandle;
  70. size_t offset = ((uintptr_t)pos - (uintptr_t)encodeBuf->data) / sizeof(UA_Byte);
  71. UA_StatusCode retval = exchangeBufferCallback(exchangeBufferCallbackHandle, encodeBuf, offset);
  72. /* Restore context variables. This restores the pointer to the buffer, not the buffer
  73. * itself. This is required so that a call to UA_encode can be made from within the
  74. * exchangeBufferCallback. For example to encode the chunk header */
  75. encodeBuf = store_encodeBuf;
  76. exchangeBufferCallback = store_exchangeBufferCallback;
  77. exchangeBufferCallbackHandle = store_exchangeBufferCallbackHandle;
  78. /* Set pos and end in order to continue encoding */
  79. pos = encodeBuf->data;
  80. end = &encodeBuf->data[encodeBuf->length];
  81. return retval;
  82. }
  83. /*****************/
  84. /* Integer Types */
  85. /*****************/
  86. #if !UA_BINARY_OVERLAYABLE_INTEGER
  87. /* These en/decoding functions are only used when the architecture isn't little-endian. */
  88. static void
  89. UA_encode16(const UA_UInt16 v, UA_Byte buf[2]) {
  90. buf[0] = (UA_Byte)v;
  91. buf[1] = (UA_Byte)(v >> 8);
  92. }
  93. static void
  94. UA_decode16(const UA_Byte buf[2], UA_UInt16 *v) {
  95. *v = (UA_UInt16)((UA_UInt16)buf[0] + (((UA_UInt16)buf[1]) << 8));
  96. }
  97. static void
  98. UA_encode32(const UA_UInt32 v, UA_Byte buf[4]) {
  99. buf[0] = (UA_Byte)v;
  100. buf[1] = (UA_Byte)(v >> 8);
  101. buf[2] = (UA_Byte)(v >> 16);
  102. buf[3] = (UA_Byte)(v >> 24);
  103. }
  104. static void
  105. UA_decode32(const UA_Byte buf[4], UA_UInt32 *v) {
  106. *v = (UA_UInt32)((UA_UInt32)buf[0] +
  107. (((UA_UInt32)buf[1]) << 8) +
  108. (((UA_UInt32)buf[2]) << 16) +
  109. (((UA_UInt32)buf[3]) << 24));
  110. }
  111. static void
  112. UA_encode64(const UA_UInt64 v, UA_Byte buf[8]) {
  113. buf[0] = (UA_Byte)v;
  114. buf[1] = (UA_Byte)(v >> 8);
  115. buf[2] = (UA_Byte)(v >> 16);
  116. buf[3] = (UA_Byte)(v >> 24);
  117. buf[4] = (UA_Byte)(v >> 32);
  118. buf[5] = (UA_Byte)(v >> 40);
  119. buf[6] = (UA_Byte)(v >> 48);
  120. buf[7] = (UA_Byte)(v >> 56);
  121. }
  122. static void
  123. UA_decode64(const UA_Byte buf[8], UA_UInt64 *v) {
  124. *v = (UA_UInt64)((UA_UInt64)buf[0] +
  125. (((UA_UInt64)buf[1]) << 8) +
  126. (((UA_UInt64)buf[2]) << 16) +
  127. (((UA_UInt64)buf[3]) << 24) +
  128. (((UA_UInt64)buf[4]) << 32) +
  129. (((UA_UInt64)buf[5]) << 40) +
  130. (((UA_UInt64)buf[6]) << 48) +
  131. (((UA_UInt64)buf[7]) << 56));
  132. }
  133. #endif /* !UA_BINARY_OVERLAYABLE_INTEGER */
  134. /* Boolean */
  135. static UA_StatusCode
  136. Boolean_encodeBinary(const UA_Boolean *src, const UA_DataType *_) {
  137. if(pos + sizeof(UA_Boolean) > end)
  138. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  139. *pos = *(const UA_Byte*)src;
  140. ++pos;
  141. return UA_STATUSCODE_GOOD;
  142. }
  143. static UA_StatusCode
  144. Boolean_decodeBinary(UA_Boolean *dst, const UA_DataType *_) {
  145. if(pos + sizeof(UA_Boolean) > end)
  146. return UA_STATUSCODE_BADDECODINGERROR;
  147. *dst = (*pos > 0) ? true : false;
  148. ++pos;
  149. return UA_STATUSCODE_GOOD;
  150. }
  151. /* Byte */
  152. static UA_StatusCode
  153. Byte_encodeBinary(const UA_Byte *src, const UA_DataType *_) {
  154. if(pos + sizeof(UA_Byte) > end)
  155. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  156. *pos = *(const UA_Byte*)src;
  157. ++pos;
  158. return UA_STATUSCODE_GOOD;
  159. }
  160. static UA_StatusCode
  161. Byte_decodeBinary(UA_Byte *dst, const UA_DataType *_) {
  162. if(pos + sizeof(UA_Byte) > end)
  163. return UA_STATUSCODE_BADDECODINGERROR;
  164. *dst = *pos;
  165. ++pos;
  166. return UA_STATUSCODE_GOOD;
  167. }
  168. /* UInt16 */
  169. static UA_StatusCode
  170. UInt16_encodeBinary(UA_UInt16 const *src, const UA_DataType *_) {
  171. if(pos + sizeof(UA_UInt16) > end)
  172. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  173. #if UA_BINARY_OVERLAYABLE_INTEGER
  174. memcpy(pos, src, sizeof(UA_UInt16));
  175. #else
  176. UA_encode16(*src, pos);
  177. #endif
  178. pos += 2;
  179. return UA_STATUSCODE_GOOD;
  180. }
  181. static UA_INLINE UA_StatusCode
  182. Int16_encodeBinary(UA_Int16 const *src, const UA_DataType *_) {
  183. return UInt16_encodeBinary((const UA_UInt16*)src, NULL);
  184. }
  185. static UA_StatusCode
  186. UInt16_decodeBinary(UA_UInt16 *dst, const UA_DataType *_) {
  187. if(pos + sizeof(UA_UInt16) > end)
  188. return UA_STATUSCODE_BADDECODINGERROR;
  189. #if UA_BINARY_OVERLAYABLE_INTEGER
  190. memcpy(dst, pos, sizeof(UA_UInt16));
  191. #else
  192. UA_decode16(pos, dst);
  193. #endif
  194. pos += 2;
  195. return UA_STATUSCODE_GOOD;
  196. }
  197. static UA_INLINE UA_StatusCode
  198. Int16_decodeBinary(UA_Int16 *dst) {
  199. return UInt16_decodeBinary((UA_UInt16*)dst, NULL);
  200. }
  201. /* UInt32 */
  202. static UA_StatusCode
  203. UInt32_encodeBinary(UA_UInt32 const *src, const UA_DataType *_) {
  204. if(pos + sizeof(UA_UInt32) > end)
  205. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  206. #if UA_BINARY_OVERLAYABLE_INTEGER
  207. memcpy(pos, src, sizeof(UA_UInt32));
  208. #else
  209. UA_encode32(*src, pos);
  210. #endif
  211. pos += 4;
  212. return UA_STATUSCODE_GOOD;
  213. }
  214. static UA_INLINE UA_StatusCode
  215. Int32_encodeBinary(UA_Int32 const *src) {
  216. return UInt32_encodeBinary((const UA_UInt32*)src, NULL);
  217. }
  218. static UA_INLINE UA_StatusCode
  219. StatusCode_encodeBinary(UA_StatusCode const *src) {
  220. return UInt32_encodeBinary((const UA_UInt32*)src, NULL);
  221. }
  222. static UA_StatusCode
  223. UInt32_decodeBinary(UA_UInt32 *dst, const UA_DataType *_) {
  224. if(pos + sizeof(UA_UInt32) > end)
  225. return UA_STATUSCODE_BADDECODINGERROR;
  226. #if UA_BINARY_OVERLAYABLE_INTEGER
  227. memcpy(dst, pos, sizeof(UA_UInt32));
  228. #else
  229. UA_decode32(pos, dst);
  230. #endif
  231. pos += 4;
  232. return UA_STATUSCODE_GOOD;
  233. }
  234. static UA_INLINE UA_StatusCode
  235. Int32_decodeBinary(UA_Int32 *dst) {
  236. return UInt32_decodeBinary((UA_UInt32*)dst, NULL);
  237. }
  238. static UA_INLINE UA_StatusCode
  239. StatusCode_decodeBinary(UA_StatusCode *dst) {
  240. return UInt32_decodeBinary((UA_UInt32*)dst, NULL);
  241. }
  242. /* UInt64 */
  243. static UA_StatusCode
  244. UInt64_encodeBinary(UA_UInt64 const *src, const UA_DataType *_) {
  245. if(pos + sizeof(UA_UInt64) > end)
  246. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  247. #if UA_BINARY_OVERLAYABLE_INTEGER
  248. memcpy(pos, src, sizeof(UA_UInt64));
  249. #else
  250. UA_encode64(*src, pos);
  251. #endif
  252. pos += 8;
  253. return UA_STATUSCODE_GOOD;
  254. }
  255. static UA_INLINE UA_StatusCode
  256. Int64_encodeBinary(UA_Int64 const *src) {
  257. return UInt64_encodeBinary((const UA_UInt64*)src, NULL);
  258. }
  259. static UA_INLINE UA_StatusCode
  260. DateTime_encodeBinary(UA_DateTime const *src) {
  261. return UInt64_encodeBinary((const UA_UInt64*)src, NULL);
  262. }
  263. static UA_StatusCode
  264. UInt64_decodeBinary(UA_UInt64 *dst, const UA_DataType *_) {
  265. if(pos + sizeof(UA_UInt64) > end)
  266. return UA_STATUSCODE_BADDECODINGERROR;
  267. #if UA_BINARY_OVERLAYABLE_INTEGER
  268. memcpy(dst, pos, sizeof(UA_UInt64));
  269. #else
  270. UA_decode64(pos, dst);
  271. #endif
  272. pos += 8;
  273. return UA_STATUSCODE_GOOD;
  274. }
  275. static UA_INLINE UA_StatusCode
  276. Int64_decodeBinary(UA_Int64 *dst) {
  277. return UInt64_decodeBinary((UA_UInt64*)dst, NULL);
  278. }
  279. static UA_INLINE UA_StatusCode
  280. DateTime_decodeBinary(UA_DateTime *dst) {
  281. return UInt64_decodeBinary((UA_UInt64*)dst, NULL);
  282. }
  283. /************************/
  284. /* Floating Point Types */
  285. /************************/
  286. #if UA_BINARY_OVERLAYABLE_FLOAT
  287. # define Float_encodeBinary UInt32_encodeBinary
  288. # define Float_decodeBinary UInt32_decodeBinary
  289. # define Double_encodeBinary UInt64_encodeBinary
  290. # define Double_decodeBinary UInt64_decodeBinary
  291. #else
  292. #include <math.h>
  293. /* Handling of IEEE754 floating point values was taken from Beej's Guide to
  294. * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
  295. * edge cases +/-0, +/-inf and nan. */
  296. static uint64_t
  297. pack754(long double f, unsigned bits, unsigned expbits) {
  298. unsigned significandbits = bits - expbits - 1;
  299. long double fnorm;
  300. long long sign;
  301. if (f < 0) { sign = 1; fnorm = -f; }
  302. else { sign = 0; fnorm = f; }
  303. int shift = 0;
  304. while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
  305. while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
  306. fnorm = fnorm - 1.0;
  307. long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
  308. long long exponent = shift + ((1<<(expbits-1)) - 1);
  309. return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
  310. }
  311. static long double
  312. unpack754(uint64_t i, unsigned bits, unsigned expbits) {
  313. unsigned significandbits = bits - expbits - 1;
  314. long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
  315. result /= (1LL<<significandbits);
  316. result += 1.0f;
  317. unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
  318. long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
  319. while(shift > 0) { result *= 2.0; --shift; }
  320. while(shift < 0) { result /= 2.0; ++shift; }
  321. result *= ((i>>(bits-1))&1)? -1.0: 1.0;
  322. return result;
  323. }
  324. /* Float */
  325. #define FLOAT_NAN 0xffc00000
  326. #define FLOAT_INF 0x7f800000
  327. #define FLOAT_NEG_INF 0xff800000
  328. #define FLOAT_NEG_ZERO 0x80000000
  329. static UA_StatusCode
  330. Float_encodeBinary(UA_Float const *src, const UA_DataType *_) {
  331. UA_Float f = *src;
  332. UA_UInt32 encoded;
  333. //cppcheck-suppress duplicateExpression
  334. if(f != f) encoded = FLOAT_NAN;
  335. else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
  336. //cppcheck-suppress duplicateExpression
  337. else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
  338. else encoded = (UA_UInt32)pack754(f, 32, 8);
  339. return UInt32_encodeBinary(&encoded, NULL);
  340. }
  341. static UA_StatusCode
  342. Float_decodeBinary(UA_Float *dst, const UA_DataType *_) {
  343. UA_UInt32 decoded;
  344. UA_StatusCode retval = UInt32_decodeBinary(&decoded, NULL);
  345. if(retval != UA_STATUSCODE_GOOD)
  346. return retval;
  347. if(decoded == 0) *dst = 0.0f;
  348. else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
  349. else if(decoded == FLOAT_INF) *dst = INFINITY;
  350. else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
  351. if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
  352. (decoded >= 0xff800001 && decoded <= 0xffffffff)) *dst = NAN;
  353. else *dst = (UA_Float)unpack754(decoded, 32, 8);
  354. return UA_STATUSCODE_GOOD;
  355. }
  356. /* Double */
  357. #define DOUBLE_NAN 0xfff8000000000000L
  358. #define DOUBLE_INF 0x7ff0000000000000L
  359. #define DOUBLE_NEG_INF 0xfff0000000000000L
  360. #define DOUBLE_NEG_ZERO 0x8000000000000000L
  361. static UA_StatusCode
  362. Double_encodeBinary(UA_Double const *src, const UA_DataType *_) {
  363. UA_Double d = *src;
  364. UA_UInt64 encoded;
  365. //cppcheck-suppress duplicateExpression
  366. if(d != d) encoded = DOUBLE_NAN;
  367. else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
  368. //cppcheck-suppress duplicateExpression
  369. else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
  370. else encoded = pack754(d, 64, 11);
  371. return UInt64_encodeBinary(&encoded, NULL);
  372. }
  373. static UA_StatusCode
  374. Double_decodeBinary(UA_Double *dst, const UA_DataType *_) {
  375. UA_UInt64 decoded;
  376. UA_StatusCode retval = UInt64_decodeBinary(&decoded, NULL);
  377. if(retval != UA_STATUSCODE_GOOD)
  378. return retval;
  379. if(decoded == 0) *dst = 0.0;
  380. else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
  381. else if(decoded == DOUBLE_INF) *dst = INFINITY;
  382. else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
  383. //cppcheck-suppress redundantCondition
  384. if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
  385. (decoded >= 0xfff0000000000001L && decoded <= 0xffffffffffffffffL)) *dst = NAN;
  386. else *dst = (UA_Double)unpack754(decoded, 64, 11);
  387. return UA_STATUSCODE_GOOD;
  388. }
  389. #endif
  390. /******************/
  391. /* Array Handling */
  392. /******************/
  393. static UA_StatusCode
  394. Array_encodeBinaryOverlayable(uintptr_t ptr, size_t length, size_t elementMemSize) {
  395. /* Store the number of already encoded elements */
  396. size_t finished = 0;
  397. /* Loop as long as more elements remain than fit into the chunk */
  398. while(end < pos + (elementMemSize * (length-finished))) {
  399. size_t possible = ((uintptr_t)end - (uintptr_t)pos) / (sizeof(UA_Byte) * elementMemSize);
  400. size_t possibleMem = possible * elementMemSize;
  401. memcpy(pos, (void*)ptr, possibleMem);
  402. pos += possibleMem;
  403. ptr += possibleMem;
  404. finished += possible;
  405. UA_StatusCode retval = exchangeBuffer();
  406. if(retval != UA_STATUSCODE_GOOD)
  407. return retval;
  408. }
  409. /* Encode the remaining elements */
  410. memcpy(pos, (void*)ptr, elementMemSize * (length-finished));
  411. pos += elementMemSize * (length-finished);
  412. return UA_STATUSCODE_GOOD;
  413. }
  414. static UA_StatusCode
  415. Array_encodeBinaryComplex(uintptr_t ptr, size_t length, const UA_DataType *type) {
  416. /* Get the encoding function for the data type. The jumptable at
  417. * UA_BUILTIN_TYPES_COUNT points to the generic UA_encodeBinary method */
  418. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  419. UA_encodeBinarySignature encodeType = encodeBinaryJumpTable[encode_index];
  420. /* Encode every element */
  421. for(size_t i = 0; i < length; ++i) {
  422. UA_Byte *oldpos = pos;
  423. UA_StatusCode retval = encodeType((const void*)ptr, type);
  424. ptr += type->memSize;
  425. /* Encoding failed, switch to the next chunk when possible */
  426. if(retval != UA_STATUSCODE_GOOD) {
  427. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  428. pos = oldpos; /* Set buffer position to the end of the last encoded element */
  429. retval = exchangeBuffer();
  430. ptr -= type->memSize; /* Undo to retry encoding the ith element */
  431. --i;
  432. }
  433. if(retval != UA_STATUSCODE_GOOD)
  434. return retval; /* Unrecoverable fail */
  435. }
  436. }
  437. return UA_STATUSCODE_GOOD;
  438. }
  439. static UA_StatusCode
  440. Array_encodeBinary(const void *src, size_t length, const UA_DataType *type) {
  441. /* Check and convert the array length to int32 */
  442. UA_Int32 signed_length = -1;
  443. if(length > UA_INT32_MAX)
  444. return UA_STATUSCODE_BADINTERNALERROR;
  445. if(length > 0)
  446. signed_length = (UA_Int32)length;
  447. else if(src == UA_EMPTY_ARRAY_SENTINEL)
  448. signed_length = 0;
  449. /* Encode the array length */
  450. UA_StatusCode retval = Int32_encodeBinary(&signed_length);
  451. if(retval != UA_STATUSCODE_GOOD || length == 0)
  452. return retval;
  453. /* Encode the content */
  454. if(!type->overlayable)
  455. return Array_encodeBinaryComplex((uintptr_t)src, length, type);
  456. return Array_encodeBinaryOverlayable((uintptr_t)src, length, type->memSize);
  457. }
  458. static UA_StatusCode
  459. Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst,
  460. size_t *out_length, const UA_DataType *type) {
  461. /* Decode the length */
  462. UA_Int32 signed_length;
  463. UA_StatusCode retval = Int32_decodeBinary(&signed_length);
  464. if(retval != UA_STATUSCODE_GOOD)
  465. return retval;
  466. /* Return early for empty arrays */
  467. if(signed_length <= 0) {
  468. *out_length = 0;
  469. if(signed_length < 0)
  470. *dst = NULL;
  471. else
  472. *dst = UA_EMPTY_ARRAY_SENTINEL;
  473. return UA_STATUSCODE_GOOD;
  474. }
  475. /* Filter out arrays that can obviously not be decoded, because the message
  476. * is too small for the array length. This prevents the allocation of very
  477. * long arrays for bogus messages.*/
  478. size_t length = (size_t)signed_length;
  479. if(pos + ((type->memSize * length) / 32) > end)
  480. return UA_STATUSCODE_BADDECODINGERROR;
  481. /* Allocate memory */
  482. *dst = UA_calloc(length, type->memSize);
  483. if(!*dst)
  484. return UA_STATUSCODE_BADOUTOFMEMORY;
  485. if(type->overlayable) {
  486. /* memcpy overlayable array */
  487. if(end < pos + (type->memSize * length)) {
  488. UA_free(*dst);
  489. *dst = NULL;
  490. return UA_STATUSCODE_BADDECODINGERROR;
  491. }
  492. memcpy(*dst, pos, type->memSize * length);
  493. pos += type->memSize * length;
  494. } else {
  495. /* Decode array members */
  496. uintptr_t ptr = (uintptr_t)*dst;
  497. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  498. for(size_t i = 0; i < length; ++i) {
  499. retval = decodeBinaryJumpTable[decode_index]((void*)ptr, type);
  500. if(retval != UA_STATUSCODE_GOOD) {
  501. UA_Array_delete(*dst, i, type);
  502. *dst = NULL;
  503. return retval;
  504. }
  505. ptr += type->memSize;
  506. }
  507. }
  508. *out_length = length;
  509. return UA_STATUSCODE_GOOD;
  510. }
  511. /*****************/
  512. /* Builtin Types */
  513. /*****************/
  514. static UA_StatusCode
  515. String_encodeBinary(UA_String const *src, const UA_DataType *_) {
  516. return Array_encodeBinary(src->data, src->length, &UA_TYPES[UA_TYPES_BYTE]);
  517. }
  518. static UA_StatusCode
  519. String_decodeBinary(UA_String *dst, const UA_DataType *_) {
  520. return Array_decodeBinary((void**)&dst->data, &dst->length, &UA_TYPES[UA_TYPES_BYTE]);
  521. }
  522. static UA_INLINE UA_StatusCode
  523. ByteString_encodeBinary(UA_ByteString const *src) {
  524. return String_encodeBinary((const UA_String*)src, NULL);
  525. }
  526. static UA_INLINE UA_StatusCode
  527. ByteString_decodeBinary(UA_ByteString *dst) {
  528. return String_decodeBinary((UA_ByteString*)dst, NULL);
  529. }
  530. /* Guid */
  531. static UA_StatusCode
  532. Guid_encodeBinary(UA_Guid const *src, const UA_DataType *_) {
  533. UA_StatusCode retval = UInt32_encodeBinary(&src->data1, NULL);
  534. retval |= UInt16_encodeBinary(&src->data2, NULL);
  535. retval |= UInt16_encodeBinary(&src->data3, NULL);
  536. if(pos + (8*sizeof(UA_Byte)) > end)
  537. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  538. memcpy(pos, src->data4, 8*sizeof(UA_Byte));
  539. pos += 8;
  540. return retval;
  541. }
  542. static UA_StatusCode
  543. Guid_decodeBinary(UA_Guid *dst, const UA_DataType *_) {
  544. UA_StatusCode retval = UInt32_decodeBinary(&dst->data1, NULL);
  545. retval |= UInt16_decodeBinary(&dst->data2, NULL);
  546. retval |= UInt16_decodeBinary(&dst->data3, NULL);
  547. if(pos + (8*sizeof(UA_Byte)) > end)
  548. return UA_STATUSCODE_BADDECODINGERROR;
  549. memcpy(dst->data4, pos, 8*sizeof(UA_Byte));
  550. pos += 8;
  551. return retval;
  552. }
  553. /* NodeId */
  554. #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
  555. #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
  556. #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
  557. /* For ExpandedNodeId, we prefill the encoding mask */
  558. static UA_StatusCode
  559. NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, UA_Byte encoding) {
  560. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  561. switch (src->identifierType) {
  562. case UA_NODEIDTYPE_NUMERIC:
  563. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  564. encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE;
  565. retval |= Byte_encodeBinary(&encoding, NULL);
  566. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  567. retval |= UInt32_encodeBinary(&src->identifier.numeric, NULL);
  568. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  569. encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE;
  570. retval |= Byte_encodeBinary(&encoding, NULL);
  571. UA_Byte nsindex = (UA_Byte)src->namespaceIndex;
  572. retval |= Byte_encodeBinary(&nsindex, NULL);
  573. UA_UInt16 identifier16 = (UA_UInt16)src->identifier.numeric;
  574. retval |= UInt16_encodeBinary(&identifier16, NULL);
  575. } else {
  576. encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE;
  577. retval |= Byte_encodeBinary(&encoding, NULL);
  578. UA_Byte identifier8 = (UA_Byte)src->identifier.numeric;
  579. retval |= Byte_encodeBinary(&identifier8, NULL);
  580. }
  581. break;
  582. case UA_NODEIDTYPE_STRING:
  583. encoding |= UA_NODEIDTYPE_STRING;
  584. retval |= Byte_encodeBinary(&encoding, NULL);
  585. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  586. retval |= String_encodeBinary(&src->identifier.string, NULL);
  587. break;
  588. case UA_NODEIDTYPE_GUID:
  589. encoding |= UA_NODEIDTYPE_GUID;
  590. retval |= Byte_encodeBinary(&encoding, NULL);
  591. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  592. retval |= Guid_encodeBinary(&src->identifier.guid, NULL);
  593. break;
  594. case UA_NODEIDTYPE_BYTESTRING:
  595. encoding |= UA_NODEIDTYPE_BYTESTRING;
  596. retval |= Byte_encodeBinary(&encoding, NULL);
  597. retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL);
  598. retval |= ByteString_encodeBinary(&src->identifier.byteString);
  599. break;
  600. default:
  601. return UA_STATUSCODE_BADINTERNALERROR;
  602. }
  603. return retval;
  604. }
  605. static UA_StatusCode
  606. NodeId_encodeBinary(UA_NodeId const *src, const UA_DataType *_) {
  607. return NodeId_encodeBinaryWithEncodingMask(src, 0);
  608. }
  609. static UA_StatusCode
  610. NodeId_decodeBinary(UA_NodeId *dst, const UA_DataType *_) {
  611. UA_Byte dstByte = 0, encodingByte = 0;
  612. UA_UInt16 dstUInt16 = 0;
  613. UA_StatusCode retval = Byte_decodeBinary(&encodingByte, NULL);
  614. if(retval != UA_STATUSCODE_GOOD)
  615. return retval;
  616. switch (encodingByte) {
  617. case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
  618. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  619. retval = Byte_decodeBinary(&dstByte, NULL);
  620. dst->identifier.numeric = dstByte;
  621. dst->namespaceIndex = 0;
  622. break;
  623. case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
  624. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  625. retval |= Byte_decodeBinary(&dstByte, NULL);
  626. dst->namespaceIndex = dstByte;
  627. retval |= UInt16_decodeBinary(&dstUInt16, NULL);
  628. dst->identifier.numeric = dstUInt16;
  629. break;
  630. case UA_NODEIDTYPE_NUMERIC_COMPLETE:
  631. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  632. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  633. retval |= UInt32_decodeBinary(&dst->identifier.numeric, NULL);
  634. break;
  635. case UA_NODEIDTYPE_STRING:
  636. dst->identifierType = UA_NODEIDTYPE_STRING;
  637. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  638. retval |= String_decodeBinary(&dst->identifier.string, NULL);
  639. break;
  640. case UA_NODEIDTYPE_GUID:
  641. dst->identifierType = UA_NODEIDTYPE_GUID;
  642. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  643. retval |= Guid_decodeBinary(&dst->identifier.guid, NULL);
  644. break;
  645. case UA_NODEIDTYPE_BYTESTRING:
  646. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  647. retval |= UInt16_decodeBinary(&dst->namespaceIndex, NULL);
  648. retval |= ByteString_decodeBinary(&dst->identifier.byteString);
  649. break;
  650. default:
  651. retval |= UA_STATUSCODE_BADINTERNALERROR;
  652. break;
  653. }
  654. return retval;
  655. }
  656. /* ExpandedNodeId */
  657. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
  658. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
  659. static UA_StatusCode
  660. ExpandedNodeId_encodeBinary(UA_ExpandedNodeId const *src, const UA_DataType *_) {
  661. /* Set up the encoding mask */
  662. UA_Byte encoding = 0;
  663. if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
  664. encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
  665. if(src->serverIndex > 0)
  666. encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
  667. /* Encode the content */
  668. UA_StatusCode retval = NodeId_encodeBinaryWithEncodingMask(&src->nodeId, encoding);
  669. if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
  670. retval |= String_encodeBinary(&src->namespaceUri, NULL);
  671. if(src->serverIndex > 0)
  672. retval |= UInt32_encodeBinary(&src->serverIndex, NULL);
  673. return retval;
  674. }
  675. static UA_StatusCode
  676. ExpandedNodeId_decodeBinary(UA_ExpandedNodeId *dst, const UA_DataType *_) {
  677. /* Decode the encoding mask */
  678. if(pos >= end)
  679. return UA_STATUSCODE_BADDECODINGERROR;
  680. UA_Byte encoding = *pos;
  681. /* Mask out the encoding byte on the stream to decode the NodeId only */
  682. *pos = encoding & (UA_Byte)~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG |
  683. UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
  684. UA_StatusCode retval = NodeId_decodeBinary(&dst->nodeId, NULL);
  685. /* Decode the NamespaceUri */
  686. if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
  687. dst->nodeId.namespaceIndex = 0;
  688. retval |= String_decodeBinary(&dst->namespaceUri, NULL);
  689. }
  690. /* Decode the ServerIndex */
  691. if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
  692. retval |= UInt32_decodeBinary(&dst->serverIndex, NULL);
  693. return retval;
  694. }
  695. /* LocalizedText */
  696. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
  697. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
  698. static UA_StatusCode
  699. LocalizedText_encodeBinary(UA_LocalizedText const *src, const UA_DataType *_) {
  700. /* Set up the encoding mask */
  701. UA_Byte encoding = 0;
  702. if(src->locale.data)
  703. encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  704. if(src->text.data)
  705. encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  706. /* Encode the content */
  707. UA_StatusCode retval = Byte_encodeBinary(&encoding, NULL);
  708. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  709. retval |= String_encodeBinary(&src->locale, NULL);
  710. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  711. retval |= String_encodeBinary(&src->text, NULL);
  712. return retval;
  713. }
  714. static UA_StatusCode
  715. LocalizedText_decodeBinary(UA_LocalizedText *dst, const UA_DataType *_) {
  716. /* Decode the encoding mask */
  717. UA_Byte encoding = 0;
  718. UA_StatusCode retval = Byte_decodeBinary(&encoding, NULL);
  719. /* Decode the content */
  720. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  721. retval |= String_decodeBinary(&dst->locale, NULL);
  722. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  723. retval |= String_decodeBinary(&dst->text, NULL);
  724. return retval;
  725. }
  726. static UA_StatusCode
  727. findDataTypeByBinary(const UA_NodeId *typeId, const UA_DataType **findtype) {
  728. const UA_DataType *types = UA_TYPES;
  729. size_t typesSize = UA_TYPES_COUNT;
  730. if(typeId->namespaceIndex != 0) {
  731. types = customTypesArray;
  732. typesSize = customTypesArraySize;
  733. }
  734. for(size_t i = 0; i < typesSize; ++i) {
  735. if(types[i].binaryEncodingId == typeId->identifier.numeric) {
  736. // cppcheck-suppress autoVariables
  737. *findtype = &types[i];
  738. return UA_STATUSCODE_GOOD;
  739. }
  740. }
  741. return UA_STATUSCODE_BADNODEIDUNKNOWN;
  742. }
  743. /* ExtensionObject */
  744. static UA_StatusCode
  745. ExtensionObject_encodeBinary(UA_ExtensionObject const *src, const UA_DataType *_) {
  746. UA_Byte encoding = src->encoding;
  747. /* No content or already encoded content */
  748. if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
  749. UA_StatusCode retval = NodeId_encodeBinary(&src->content.encoded.typeId, NULL);
  750. retval |= Byte_encodeBinary(&encoding, NULL);
  751. switch (src->encoding) {
  752. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  753. break;
  754. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  755. case UA_EXTENSIONOBJECT_ENCODED_XML:
  756. retval |= ByteString_encodeBinary(&src->content.encoded.body);
  757. break;
  758. default:
  759. retval = UA_STATUSCODE_BADINTERNALERROR;
  760. }
  761. return retval;
  762. }
  763. /* Cannot encode with no data or no type description */
  764. if(!src->content.decoded.type || !src->content.decoded.data)
  765. return UA_STATUSCODE_BADENCODINGERROR;
  766. /* Write the NodeId for the binary encoded type */
  767. UA_NodeId typeId = src->content.decoded.type->typeId;
  768. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  769. return UA_STATUSCODE_BADENCODINGERROR;
  770. typeId.identifier.numeric = src->content.decoded.type->binaryEncodingId;
  771. UA_StatusCode retval = NodeId_encodeBinary(&typeId, NULL);
  772. /* Write the encoding byte */
  773. encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  774. retval |= Byte_encodeBinary(&encoding, NULL);
  775. /* Write the length of the following content */
  776. const UA_DataType *type = src->content.decoded.type;
  777. size_t len = UA_calcSizeBinary(src->content.decoded.data, type);
  778. if(len > UA_INT32_MAX)
  779. return UA_STATUSCODE_BADENCODINGERROR;
  780. UA_Int32 signed_len = (UA_Int32)len;
  781. retval |= Int32_encodeBinary(&signed_len);
  782. /* Encode the content */
  783. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  784. retval |= encodeBinaryJumpTable[encode_index](src->content.decoded.data, type);
  785. return retval;
  786. }
  787. static UA_StatusCode
  788. ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId) {
  789. /* Lookup the datatype */
  790. const UA_DataType *type = NULL;
  791. findDataTypeByBinary(typeId, &type);
  792. /* Unknown type, just take the binary content */
  793. if(!type) {
  794. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  795. dst->content.encoded.typeId = *typeId;
  796. return ByteString_decodeBinary(&dst->content.encoded.body);
  797. }
  798. /* Allocate memory */
  799. dst->content.decoded.data = UA_new(type);
  800. if(!dst->content.decoded.data)
  801. return UA_STATUSCODE_BADOUTOFMEMORY;
  802. /* Jump over the length field (TODO: check if the decoded length matches) */
  803. pos += 4;
  804. /* Decode */
  805. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  806. dst->content.decoded.type = type;
  807. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  808. return decodeBinaryJumpTable[decode_index](dst->content.decoded.data, type);
  809. }
  810. static UA_StatusCode
  811. ExtensionObject_decodeBinary(UA_ExtensionObject *dst, const UA_DataType *_) {
  812. UA_Byte encoding = 0;
  813. UA_NodeId typeId;
  814. UA_NodeId_init(&typeId);
  815. UA_StatusCode retval = NodeId_decodeBinary(&typeId, NULL);
  816. retval |= Byte_decodeBinary(&encoding, NULL);
  817. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  818. retval = UA_STATUSCODE_BADDECODINGERROR;
  819. if(retval != UA_STATUSCODE_GOOD) {
  820. UA_NodeId_deleteMembers(&typeId);
  821. return retval;
  822. }
  823. if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
  824. retval = ExtensionObject_decodeBinaryContent(dst, &typeId);
  825. } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
  826. dst->encoding = (UA_ExtensionObjectEncoding)encoding;
  827. dst->content.encoded.typeId = typeId;
  828. dst->content.encoded.body = UA_BYTESTRING_NULL;
  829. } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
  830. dst->encoding = (UA_ExtensionObjectEncoding)encoding;
  831. dst->content.encoded.typeId = typeId;
  832. retval = ByteString_decodeBinary(&dst->content.encoded.body);
  833. } else {
  834. retval = UA_STATUSCODE_BADDECODINGERROR;
  835. }
  836. return retval;
  837. }
  838. /* Variant */
  839. static UA_StatusCode
  840. Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src, const UA_Boolean isArray) {
  841. /* Default to 1 for a scalar. */
  842. size_t length = 1;
  843. /* Encode the array length if required */
  844. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  845. if(isArray) {
  846. if(src->arrayLength > UA_INT32_MAX)
  847. return UA_STATUSCODE_BADENCODINGERROR;
  848. length = src->arrayLength;
  849. UA_Int32 encodedLength = (UA_Int32)src->arrayLength;
  850. retval = Int32_encodeBinary(&encodedLength);
  851. }
  852. /* Set up the ExtensionObject */
  853. UA_ExtensionObject eo;
  854. UA_ExtensionObject_init(&eo);
  855. eo.encoding = UA_EXTENSIONOBJECT_DECODED;
  856. eo.content.decoded.type = src->type;
  857. const UA_UInt16 memSize = src->type->memSize;
  858. uintptr_t ptr = (uintptr_t)src->data;
  859. /* Iterate over the array */
  860. for(size_t i = 0; i < length && retval == UA_STATUSCODE_GOOD; ++i) {
  861. UA_Byte *oldpos = pos;
  862. eo.content.decoded.data = (void*)ptr;
  863. retval |= ExtensionObject_encodeBinary(&eo, NULL);
  864. ptr += memSize;
  865. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  866. /* exchange/send with the current buffer with chunking */
  867. pos = oldpos;
  868. retval = exchangeBuffer();
  869. /* encode the same element in the next iteration */
  870. --i;
  871. ptr -= memSize;
  872. }
  873. }
  874. return retval;
  875. }
  876. enum UA_VARIANT_ENCODINGMASKTYPE {
  877. UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F, // bits 0:5
  878. UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (0x01 << 6), // bit 6
  879. UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) // bit 7
  880. };
  881. static UA_StatusCode
  882. Variant_encodeBinary(const UA_Variant *src, const UA_DataType *_) {
  883. /* Quit early for the empty variant */
  884. UA_Byte encoding = 0;
  885. if(!src->type)
  886. return Byte_encodeBinary(&encoding, NULL);
  887. /* Set the content type in the encoding mask */
  888. const UA_Boolean isBuiltin = src->type->builtin;
  889. if(isBuiltin)
  890. encoding |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)(src->type->typeIndex + 1);
  891. else
  892. encoding |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte)(UA_TYPES_EXTENSIONOBJECT + 1);
  893. /* Set the array type in the encoding mask */
  894. const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  895. const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  896. if(isArray) {
  897. encoding |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  898. if(hasDimensions)
  899. encoding |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  900. }
  901. /* Encode the content */
  902. UA_StatusCode retval = Byte_encodeBinary(&encoding, NULL);
  903. if(!isBuiltin)
  904. retval |= Variant_encodeBinaryWrapExtensionObject(src, isArray);
  905. else if(!isArray)
  906. retval |= encodeBinaryJumpTable[src->type->typeIndex](src->data, src->type);
  907. else
  908. retval |= Array_encodeBinary(src->data, src->arrayLength, src->type);
  909. /* Encode the array dimensions */
  910. if(hasDimensions)
  911. retval |= Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  912. &UA_TYPES[UA_TYPES_INT32]);
  913. return retval;
  914. }
  915. static UA_StatusCode
  916. Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst) {
  917. /* Save the position in the ByteString */
  918. UA_Byte *old_pos = pos;
  919. /* Decode the DataType */
  920. UA_NodeId typeId;
  921. UA_NodeId_init(&typeId);
  922. UA_StatusCode retval = NodeId_decodeBinary(&typeId, NULL);
  923. if(retval != UA_STATUSCODE_GOOD)
  924. return retval;
  925. /* Decode the EncodingByte */
  926. UA_Byte encoding;
  927. retval = Byte_decodeBinary(&encoding, NULL);
  928. if(retval != UA_STATUSCODE_GOOD) {
  929. UA_NodeId_deleteMembers(&typeId);
  930. return retval;
  931. }
  932. /* Search for the datatype. Default to ExtensionObject. */
  933. if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
  934. typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
  935. findDataTypeByBinary(&typeId, &dst->type) == UA_STATUSCODE_GOOD) {
  936. /* Jump over the length field (TODO: check if length matches) */
  937. pos += 4;
  938. } else {
  939. /* Reset and decode as ExtensionObject */
  940. UA_assert(dst->type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
  941. pos = old_pos;
  942. UA_NodeId_deleteMembers(&typeId);
  943. }
  944. /* Allocate memory */
  945. dst->data = UA_new(dst->type);
  946. if(!dst->data)
  947. return UA_STATUSCODE_BADOUTOFMEMORY;
  948. /* Decode the content */
  949. size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  950. retval = decodeBinaryJumpTable[decode_index](dst->data, dst->type);
  951. if(retval != UA_STATUSCODE_GOOD) {
  952. UA_free(dst->data);
  953. dst->data = NULL;
  954. }
  955. return retval;
  956. }
  957. /* The resulting variant always has the storagetype UA_VARIANT_DATA. Currently,
  958. we only support ns0 types (todo: attach typedescriptions to datatypenodes) */
  959. static UA_StatusCode
  960. Variant_decodeBinary(UA_Variant *dst, const UA_DataType *_) {
  961. /* Decode the encoding byte */
  962. UA_Byte encodingByte;
  963. UA_StatusCode retval = Byte_decodeBinary(&encodingByte, NULL);
  964. if(retval != UA_STATUSCODE_GOOD)
  965. return retval;
  966. /* Return early for an empty variant (was already _inited) */
  967. if(encodingByte == 0)
  968. return UA_STATUSCODE_GOOD;
  969. /* Does the variant contain an array? */
  970. const UA_Boolean isArray = (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0;
  971. /* Get the datatype of the content. The type must be a builtin data type.
  972. * All not-builtin types are wrapped in an ExtensionObject. */
  973. size_t typeIndex = (size_t)((encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
  974. if(typeIndex > UA_TYPES_DIAGNOSTICINFO)
  975. return UA_STATUSCODE_BADDECODINGERROR;
  976. dst->type = &UA_TYPES[typeIndex];
  977. /* Decode the content */
  978. if(isArray) {
  979. retval = Array_decodeBinary(&dst->data, &dst->arrayLength, dst->type);
  980. } else if(typeIndex != UA_TYPES_EXTENSIONOBJECT) {
  981. dst->data = UA_new(dst->type);
  982. if(!dst->data)
  983. return UA_STATUSCODE_BADOUTOFMEMORY;
  984. retval = decodeBinaryJumpTable[typeIndex](dst->data, dst->type);
  985. } else {
  986. retval = Variant_decodeBinaryUnwrapExtensionObject(dst);
  987. }
  988. /* Decode array dimensions */
  989. if(isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
  990. retval |= Array_decodeBinary((void**)&dst->arrayDimensions,
  991. &dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
  992. return retval;
  993. }
  994. /* DataValue */
  995. static UA_StatusCode
  996. DataValue_encodeBinary(UA_DataValue const *src, const UA_DataType *_) {
  997. /* Set up the encoding mask */
  998. UA_Byte encodingMask = (UA_Byte)
  999. ((UA_Byte)src->hasValue |
  1000. ((UA_Byte)src->hasStatus << 1) |
  1001. ((UA_Byte)src->hasSourceTimestamp << 2) |
  1002. ((UA_Byte)src->hasServerTimestamp << 3) |
  1003. ((UA_Byte)src->hasSourcePicoseconds << 4) |
  1004. ((UA_Byte)src->hasServerPicoseconds << 5));
  1005. /* Encode the content */
  1006. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL);
  1007. if(src->hasValue)
  1008. retval |= Variant_encodeBinary(&src->value, NULL);
  1009. if(src->hasStatus)
  1010. retval |= StatusCode_encodeBinary(&src->status);
  1011. if(src->hasSourceTimestamp)
  1012. retval |= DateTime_encodeBinary(&src->sourceTimestamp);
  1013. if(src->hasSourcePicoseconds)
  1014. retval |= UInt16_encodeBinary(&src->sourcePicoseconds, NULL);
  1015. if(src->hasServerTimestamp)
  1016. retval |= DateTime_encodeBinary(&src->serverTimestamp);
  1017. if(src->hasServerPicoseconds)
  1018. retval |= UInt16_encodeBinary(&src->serverPicoseconds, NULL);
  1019. return retval;
  1020. }
  1021. #define MAX_PICO_SECONDS 9999
  1022. static UA_StatusCode
  1023. DataValue_decodeBinary(UA_DataValue *dst, const UA_DataType *_) {
  1024. /* Decode the encoding mask */
  1025. UA_Byte encodingMask;
  1026. UA_StatusCode retval = Byte_decodeBinary(&encodingMask, NULL);
  1027. if(retval != UA_STATUSCODE_GOOD)
  1028. return retval;
  1029. /* Decode the content */
  1030. if(encodingMask & 0x01) {
  1031. dst->hasValue = true;
  1032. retval |= Variant_decodeBinary(&dst->value, NULL);
  1033. }
  1034. if(encodingMask & 0x02) {
  1035. dst->hasStatus = true;
  1036. retval |= StatusCode_decodeBinary(&dst->status);
  1037. }
  1038. if(encodingMask & 0x04) {
  1039. dst->hasSourceTimestamp = true;
  1040. retval |= DateTime_decodeBinary(&dst->sourceTimestamp);
  1041. }
  1042. if(encodingMask & 0x10) {
  1043. dst->hasSourcePicoseconds = true;
  1044. retval |= UInt16_decodeBinary(&dst->sourcePicoseconds, NULL);
  1045. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  1046. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  1047. }
  1048. if(encodingMask & 0x08) {
  1049. dst->hasServerTimestamp = true;
  1050. retval |= DateTime_decodeBinary(&dst->serverTimestamp);
  1051. }
  1052. if(encodingMask & 0x20) {
  1053. dst->hasServerPicoseconds = true;
  1054. retval |= UInt16_decodeBinary(&dst->serverPicoseconds, NULL);
  1055. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  1056. dst->serverPicoseconds = MAX_PICO_SECONDS;
  1057. }
  1058. return retval;
  1059. }
  1060. /* DiagnosticInfo */
  1061. static UA_StatusCode
  1062. DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, const UA_DataType *_) {
  1063. /* Set up the encoding mask */
  1064. UA_Byte encodingMask = (UA_Byte)
  1065. ((UA_Byte)src->hasSymbolicId | ((UA_Byte)src->hasNamespaceUri << 1) |
  1066. ((UA_Byte)src->hasLocalizedText << 2) | ((UA_Byte)src->hasLocale << 3) |
  1067. ((UA_Byte)src->hasAdditionalInfo << 4) | ((UA_Byte)src->hasInnerDiagnosticInfo << 5));
  1068. /* Encode the content */
  1069. UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL);
  1070. if(src->hasSymbolicId)
  1071. retval |= Int32_encodeBinary(&src->symbolicId);
  1072. if(src->hasNamespaceUri)
  1073. retval |= Int32_encodeBinary(&src->namespaceUri);
  1074. if(src->hasLocalizedText)
  1075. retval |= Int32_encodeBinary(&src->localizedText);
  1076. if(src->hasLocale)
  1077. retval |= Int32_encodeBinary(&src->locale);
  1078. if(src->hasAdditionalInfo)
  1079. retval |= String_encodeBinary(&src->additionalInfo, NULL);
  1080. if(src->hasInnerStatusCode)
  1081. retval |= StatusCode_encodeBinary(&src->innerStatusCode);
  1082. if(src->hasInnerDiagnosticInfo)
  1083. retval |= DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, NULL);
  1084. return retval;
  1085. }
  1086. static UA_StatusCode
  1087. DiagnosticInfo_decodeBinary(UA_DiagnosticInfo *dst, const UA_DataType *_) {
  1088. /* Decode the encoding mask */
  1089. UA_Byte encodingMask;
  1090. UA_StatusCode retval = Byte_decodeBinary(&encodingMask, NULL);
  1091. if(retval != UA_STATUSCODE_GOOD)
  1092. return retval;
  1093. /* Decode the content */
  1094. if(encodingMask & 0x01) {
  1095. dst->hasSymbolicId = true;
  1096. retval |= Int32_decodeBinary(&dst->symbolicId);
  1097. }
  1098. if(encodingMask & 0x02) {
  1099. dst->hasNamespaceUri = true;
  1100. retval |= Int32_decodeBinary(&dst->namespaceUri);
  1101. }
  1102. if(encodingMask & 0x04) {
  1103. dst->hasLocalizedText = true;
  1104. retval |= Int32_decodeBinary(&dst->localizedText);
  1105. }
  1106. if(encodingMask & 0x08) {
  1107. dst->hasLocale = true;
  1108. retval |= Int32_decodeBinary(&dst->locale);
  1109. }
  1110. if(encodingMask & 0x10) {
  1111. dst->hasAdditionalInfo = true;
  1112. retval |= String_decodeBinary(&dst->additionalInfo, NULL);
  1113. }
  1114. if(encodingMask & 0x20) {
  1115. dst->hasInnerStatusCode = true;
  1116. retval |= StatusCode_decodeBinary(&dst->innerStatusCode);
  1117. }
  1118. if(encodingMask & 0x40) {
  1119. /* innerDiagnosticInfo is allocated on the heap */
  1120. dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)UA_calloc(1, sizeof(UA_DiagnosticInfo));
  1121. if(!dst->innerDiagnosticInfo)
  1122. return UA_STATUSCODE_BADOUTOFMEMORY;
  1123. dst->hasInnerDiagnosticInfo = true;
  1124. retval |= DiagnosticInfo_decodeBinary(dst->innerDiagnosticInfo, NULL);
  1125. }
  1126. return retval;
  1127. }
  1128. /********************/
  1129. /* Structured Types */
  1130. /********************/
  1131. static UA_StatusCode
  1132. UA_encodeBinaryInternal(const void *src, const UA_DataType *type);
  1133. static UA_StatusCode
  1134. UA_decodeBinaryInternal(void *dst, const UA_DataType *type);
  1135. const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1136. (UA_encodeBinarySignature)Boolean_encodeBinary,
  1137. (UA_encodeBinarySignature)Byte_encodeBinary, // SByte
  1138. (UA_encodeBinarySignature)Byte_encodeBinary,
  1139. (UA_encodeBinarySignature)UInt16_encodeBinary, // Int16
  1140. (UA_encodeBinarySignature)UInt16_encodeBinary,
  1141. (UA_encodeBinarySignature)UInt32_encodeBinary, // Int32
  1142. (UA_encodeBinarySignature)UInt32_encodeBinary,
  1143. (UA_encodeBinarySignature)UInt64_encodeBinary, // Int64
  1144. (UA_encodeBinarySignature)UInt64_encodeBinary,
  1145. (UA_encodeBinarySignature)Float_encodeBinary,
  1146. (UA_encodeBinarySignature)Double_encodeBinary,
  1147. (UA_encodeBinarySignature)String_encodeBinary,
  1148. (UA_encodeBinarySignature)UInt64_encodeBinary, // DateTime
  1149. (UA_encodeBinarySignature)Guid_encodeBinary,
  1150. (UA_encodeBinarySignature)String_encodeBinary, // ByteString
  1151. (UA_encodeBinarySignature)String_encodeBinary, // XmlElement
  1152. (UA_encodeBinarySignature)NodeId_encodeBinary,
  1153. (UA_encodeBinarySignature)ExpandedNodeId_encodeBinary,
  1154. (UA_encodeBinarySignature)UInt32_encodeBinary, // StatusCode
  1155. (UA_encodeBinarySignature)UA_encodeBinaryInternal, // QualifiedName
  1156. (UA_encodeBinarySignature)LocalizedText_encodeBinary,
  1157. (UA_encodeBinarySignature)ExtensionObject_encodeBinary,
  1158. (UA_encodeBinarySignature)DataValue_encodeBinary,
  1159. (UA_encodeBinarySignature)Variant_encodeBinary,
  1160. (UA_encodeBinarySignature)DiagnosticInfo_encodeBinary,
  1161. (UA_encodeBinarySignature)UA_encodeBinaryInternal,
  1162. };
  1163. static UA_StatusCode
  1164. UA_encodeBinaryInternal(const void *src, const UA_DataType *type) {
  1165. uintptr_t ptr = (uintptr_t)src;
  1166. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1167. UA_Byte membersSize = type->membersSize;
  1168. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1169. for(size_t i = 0; i < membersSize && retval == UA_STATUSCODE_GOOD; ++i) {
  1170. const UA_DataTypeMember *member = &type->members[i];
  1171. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1172. if(!member->isArray) {
  1173. ptr += member->padding;
  1174. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1175. size_t memSize = membertype->memSize;
  1176. UA_Byte *oldpos = pos;
  1177. retval |= encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
  1178. ptr += memSize;
  1179. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
  1180. /* exchange/send the buffer and try to encode the same type once more */
  1181. pos = oldpos;
  1182. retval = exchangeBuffer();
  1183. /* re-encode the same member on the new buffer */
  1184. ptr -= member->padding + memSize;
  1185. --i;
  1186. }
  1187. } else {
  1188. ptr += member->padding;
  1189. const size_t length = *((const size_t*)ptr);
  1190. ptr += sizeof(size_t);
  1191. retval |= Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1192. ptr += sizeof(void*);
  1193. }
  1194. }
  1195. return retval;
  1196. }
  1197. UA_StatusCode
  1198. UA_encodeBinary(const void *src, const UA_DataType *type,
  1199. UA_exchangeEncodeBuffer exchangeCallback, void *exchangeHandle,
  1200. UA_ByteString *dst, size_t *offset) {
  1201. /* Set the (thread-local) position and end pointers to save function
  1202. arguments */
  1203. pos = &dst->data[*offset];
  1204. end = &dst->data[dst->length];
  1205. /* Set the (thread-local) exchangeBufferCallbacks where the buffer is exchanged and the
  1206. current chunk sent out */
  1207. encodeBuf = dst;
  1208. exchangeBufferCallback = exchangeCallback;
  1209. exchangeBufferCallbackHandle = exchangeHandle;
  1210. /* Encode and clean up */
  1211. UA_StatusCode retval = UA_encodeBinaryInternal(src, type);
  1212. *offset = (size_t)(pos - dst->data) / sizeof(UA_Byte);
  1213. return retval;
  1214. }
  1215. const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1216. (UA_decodeBinarySignature)Boolean_decodeBinary,
  1217. (UA_decodeBinarySignature)Byte_decodeBinary, // SByte
  1218. (UA_decodeBinarySignature)Byte_decodeBinary,
  1219. (UA_decodeBinarySignature)UInt16_decodeBinary, // Int16
  1220. (UA_decodeBinarySignature)UInt16_decodeBinary,
  1221. (UA_decodeBinarySignature)UInt32_decodeBinary, // Int32
  1222. (UA_decodeBinarySignature)UInt32_decodeBinary,
  1223. (UA_decodeBinarySignature)UInt64_decodeBinary, // Int64
  1224. (UA_decodeBinarySignature)UInt64_decodeBinary,
  1225. (UA_decodeBinarySignature)Float_decodeBinary,
  1226. (UA_decodeBinarySignature)Double_decodeBinary,
  1227. (UA_decodeBinarySignature)String_decodeBinary,
  1228. (UA_decodeBinarySignature)UInt64_decodeBinary, // DateTime
  1229. (UA_decodeBinarySignature)Guid_decodeBinary,
  1230. (UA_decodeBinarySignature)String_decodeBinary, // ByteString
  1231. (UA_decodeBinarySignature)String_decodeBinary, // XmlElement
  1232. (UA_decodeBinarySignature)NodeId_decodeBinary,
  1233. (UA_decodeBinarySignature)ExpandedNodeId_decodeBinary,
  1234. (UA_decodeBinarySignature)UInt32_decodeBinary, // StatusCode
  1235. (UA_decodeBinarySignature)UA_decodeBinaryInternal, // QualifiedName
  1236. (UA_decodeBinarySignature)LocalizedText_decodeBinary,
  1237. (UA_decodeBinarySignature)ExtensionObject_decodeBinary,
  1238. (UA_decodeBinarySignature)DataValue_decodeBinary,
  1239. (UA_decodeBinarySignature)Variant_decodeBinary,
  1240. (UA_decodeBinarySignature)DiagnosticInfo_decodeBinary,
  1241. (UA_decodeBinarySignature)UA_decodeBinaryInternal
  1242. };
  1243. static UA_StatusCode
  1244. UA_decodeBinaryInternal(void *dst, const UA_DataType *type) {
  1245. uintptr_t ptr = (uintptr_t)dst;
  1246. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  1247. UA_Byte membersSize = type->membersSize;
  1248. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1249. for(size_t i = 0; i < membersSize; ++i) {
  1250. const UA_DataTypeMember *member = &type->members[i];
  1251. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1252. if(!member->isArray) {
  1253. ptr += member->padding;
  1254. size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1255. size_t memSize = membertype->memSize;
  1256. retval |= decodeBinaryJumpTable[fi]((void *UA_RESTRICT)ptr, membertype);
  1257. ptr += memSize;
  1258. } else {
  1259. ptr += member->padding;
  1260. size_t *length = (size_t*)ptr;
  1261. ptr += sizeof(size_t);
  1262. retval |= Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, membertype);
  1263. ptr += sizeof(void*);
  1264. }
  1265. }
  1266. return retval;
  1267. }
  1268. UA_StatusCode
  1269. UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
  1270. const UA_DataType *type, size_t customTypesSize,
  1271. const UA_DataType *customTypes) {
  1272. /* Initialize the destination */
  1273. memset(dst, 0, type->memSize);
  1274. /* Store the pointers to the custom datatypes. They might be needed during
  1275. * decoding of variants. */
  1276. customTypesArraySize = customTypesSize;
  1277. customTypesArray = customTypes;
  1278. /* Set the (thread-local) position and end pointers to save function
  1279. * arguments */
  1280. pos = &src->data[*offset];
  1281. end = &src->data[src->length];
  1282. /* Decode */
  1283. UA_StatusCode retval = UA_decodeBinaryInternal(dst, type);
  1284. /* Clean up */
  1285. if(retval == UA_STATUSCODE_GOOD)
  1286. *offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
  1287. else
  1288. UA_deleteMembers(dst, type);
  1289. return retval;
  1290. }
  1291. /******************/
  1292. /* CalcSizeBinary */
  1293. /******************/
  1294. static size_t
  1295. Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
  1296. size_t s = 4; // length
  1297. if(type->overlayable) {
  1298. s += type->memSize * length;
  1299. return s;
  1300. }
  1301. uintptr_t ptr = (uintptr_t)src;
  1302. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1303. for(size_t i = 0; i < length; ++i) {
  1304. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, type);
  1305. ptr += type->memSize;
  1306. }
  1307. return s;
  1308. }
  1309. static size_t
  1310. calcSizeBinaryMemSize(const void *UA_RESTRICT p, const UA_DataType *type) {
  1311. return type->memSize;
  1312. }
  1313. static size_t
  1314. String_calcSizeBinary(const UA_String *UA_RESTRICT p, const UA_DataType *_) {
  1315. return 4 + p->length;
  1316. }
  1317. static size_t
  1318. Guid_calcSizeBinary(const UA_Guid *UA_RESTRICT p, const UA_DataType *_) {
  1319. return 16;
  1320. }
  1321. static size_t
  1322. NodeId_calcSizeBinary(const UA_NodeId *UA_RESTRICT src, const UA_DataType *_) {
  1323. size_t s = 1; // encoding byte
  1324. switch (src->identifierType) {
  1325. case UA_NODEIDTYPE_NUMERIC:
  1326. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  1327. s += 6;
  1328. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  1329. s += 3;
  1330. } else {
  1331. s += 1;
  1332. }
  1333. break;
  1334. case UA_NODEIDTYPE_BYTESTRING:
  1335. case UA_NODEIDTYPE_STRING:
  1336. s += 2;
  1337. s += String_calcSizeBinary(&src->identifier.string, NULL);
  1338. break;
  1339. case UA_NODEIDTYPE_GUID:
  1340. s += 18;
  1341. break;
  1342. default:
  1343. return 0;
  1344. }
  1345. return s;
  1346. }
  1347. static size_t
  1348. ExpandedNodeId_calcSizeBinary(const UA_ExpandedNodeId *src, const UA_DataType *_) {
  1349. size_t s = NodeId_calcSizeBinary(&src->nodeId, NULL);
  1350. if(src->namespaceUri.length > 0)
  1351. s += String_calcSizeBinary(&src->namespaceUri, NULL);
  1352. if(src->serverIndex > 0)
  1353. s += 4;
  1354. return s;
  1355. }
  1356. static size_t
  1357. LocalizedText_calcSizeBinary(const UA_LocalizedText *src, UA_DataType *_) {
  1358. size_t s = 1; // encoding byte
  1359. if(src->locale.data)
  1360. s += String_calcSizeBinary(&src->locale, NULL);
  1361. if(src->text.data)
  1362. s += String_calcSizeBinary(&src->text, NULL);
  1363. return s;
  1364. }
  1365. static size_t
  1366. ExtensionObject_calcSizeBinary(const UA_ExtensionObject *src, UA_DataType *_) {
  1367. size_t s = 1; // encoding byte
  1368. if(src->encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
  1369. if(!src->content.decoded.type || !src->content.decoded.data)
  1370. return 0;
  1371. if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1372. return 0;
  1373. s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL);
  1374. s += 4; // length
  1375. const UA_DataType *type = src->content.decoded.type;
  1376. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1377. s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, type);
  1378. } else {
  1379. s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
  1380. switch (src->encoding) {
  1381. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  1382. break;
  1383. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  1384. case UA_EXTENSIONOBJECT_ENCODED_XML:
  1385. s += String_calcSizeBinary(&src->content.encoded.body, NULL);
  1386. break;
  1387. default:
  1388. return 0;
  1389. }
  1390. }
  1391. return s;
  1392. }
  1393. static size_t
  1394. Variant_calcSizeBinary(UA_Variant const *src, UA_DataType *_) {
  1395. size_t s = 1; /* encoding byte */
  1396. if(!src->type)
  1397. return s;
  1398. UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  1399. UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  1400. UA_Boolean isBuiltin = src->type->builtin;
  1401. UA_NodeId typeId;
  1402. UA_NodeId_init(&typeId);
  1403. size_t encode_index = src->type->typeIndex;
  1404. if(!isBuiltin) {
  1405. encode_index = UA_BUILTIN_TYPES_COUNT;
  1406. typeId = src->type->typeId;
  1407. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1408. return 0;
  1409. }
  1410. size_t length = src->arrayLength;
  1411. if(isArray)
  1412. s += 4;
  1413. else
  1414. length = 1;
  1415. uintptr_t ptr = (uintptr_t)src->data;
  1416. size_t memSize = src->type->memSize;
  1417. for(size_t i = 0; i < length; ++i) {
  1418. if(!isBuiltin) {
  1419. /* The type is wrapped inside an extensionobject */
  1420. s += NodeId_calcSizeBinary(&typeId, NULL);
  1421. s += 1 + 4; // encoding byte + length
  1422. }
  1423. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, src->type);
  1424. ptr += memSize;
  1425. }
  1426. if(hasDimensions)
  1427. s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  1428. &UA_TYPES[UA_TYPES_INT32]);
  1429. return s;
  1430. }
  1431. static size_t
  1432. DataValue_calcSizeBinary(const UA_DataValue *src, UA_DataType *_) {
  1433. size_t s = 1; // encoding byte
  1434. if(src->hasValue)
  1435. s += Variant_calcSizeBinary(&src->value, NULL);
  1436. if(src->hasStatus)
  1437. s += 4;
  1438. if(src->hasSourceTimestamp)
  1439. s += 8;
  1440. if(src->hasSourcePicoseconds)
  1441. s += 2;
  1442. if(src->hasServerTimestamp)
  1443. s += 8;
  1444. if(src->hasServerPicoseconds)
  1445. s += 2;
  1446. return s;
  1447. }
  1448. static size_t
  1449. DiagnosticInfo_calcSizeBinary(const UA_DiagnosticInfo *src, UA_DataType *_) {
  1450. size_t s = 1; // encoding byte
  1451. if(src->hasSymbolicId)
  1452. s += 4;
  1453. if(src->hasNamespaceUri)
  1454. s += 4;
  1455. if(src->hasLocalizedText)
  1456. s += 4;
  1457. if(src->hasLocale)
  1458. s += 4;
  1459. if(src->hasAdditionalInfo)
  1460. s += String_calcSizeBinary(&src->additionalInfo, NULL);
  1461. if(src->hasInnerStatusCode)
  1462. s += 4;
  1463. if(src->hasInnerDiagnosticInfo)
  1464. s += DiagnosticInfo_calcSizeBinary(src->innerDiagnosticInfo, NULL);
  1465. return s;
  1466. }
  1467. const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1468. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Boolean
  1469. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Byte
  1470. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1471. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int16
  1472. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1473. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int32
  1474. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1475. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int64
  1476. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
  1477. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Float
  1478. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Double
  1479. (UA_calcSizeBinarySignature)String_calcSizeBinary,
  1480. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // DateTime
  1481. (UA_calcSizeBinarySignature)Guid_calcSizeBinary,
  1482. (UA_calcSizeBinarySignature)String_calcSizeBinary, // ByteString
  1483. (UA_calcSizeBinarySignature)String_calcSizeBinary, // XmlElement
  1484. (UA_calcSizeBinarySignature)NodeId_calcSizeBinary,
  1485. (UA_calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
  1486. (UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // StatusCode
  1487. (UA_calcSizeBinarySignature)UA_calcSizeBinary, // QualifiedName
  1488. (UA_calcSizeBinarySignature)LocalizedText_calcSizeBinary,
  1489. (UA_calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
  1490. (UA_calcSizeBinarySignature)DataValue_calcSizeBinary,
  1491. (UA_calcSizeBinarySignature)Variant_calcSizeBinary,
  1492. (UA_calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
  1493. (UA_calcSizeBinarySignature)UA_calcSizeBinary
  1494. };
  1495. size_t
  1496. UA_calcSizeBinary(void *p, const UA_DataType *type) {
  1497. size_t s = 0;
  1498. uintptr_t ptr = (uintptr_t)p;
  1499. UA_Byte membersSize = type->membersSize;
  1500. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1501. for(size_t i = 0; i < membersSize; ++i) {
  1502. const UA_DataTypeMember *member = &type->members[i];
  1503. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1504. if(!member->isArray) {
  1505. ptr += member->padding;
  1506. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1507. s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
  1508. ptr += membertype->memSize;
  1509. } else {
  1510. ptr += member->padding;
  1511. const size_t length = *((const size_t*)ptr);
  1512. ptr += sizeof(size_t);
  1513. s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1514. ptr += sizeof(void*);
  1515. }
  1516. }
  1517. return s;
  1518. }