ua_types_encoding_json.c 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355
  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. *
  5. * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2018 (c) Fraunhofer IOSB (Author: Lukas Meling)
  7. */
  8. #include "ua_types_encoding_json.h"
  9. #include "ua_types_encoding_binary.h"
  10. #include "ua_types_generated.h"
  11. #include "ua_types_generated_handling.h"
  12. #include "ua_plugin_log.h"
  13. #include <math.h>
  14. #include <float.h>
  15. #ifdef UA_ENABLE_CUSTOM_LIBC
  16. #include "../deps/musl/floatscan.h"
  17. #include "../deps/musl/vfprintf.h"
  18. #endif
  19. #include "../deps/itoa.h"
  20. #include "../deps/atoi.h"
  21. #include "../deps/string_escape.h"
  22. #include "../deps/base64.h"
  23. #include "../deps/libc_time.h"
  24. #if defined(_MSC_VER)
  25. # define strtoll _strtoi64
  26. # define strtoull _strtoui64
  27. #endif
  28. /* vs2008 does not have INFINITY and NAN defined */
  29. #ifndef INFINITY
  30. # define INFINITY ((UA_Double)(DBL_MAX+DBL_MAX))
  31. #endif
  32. #ifndef NAN
  33. # define NAN ((UA_Double)(INFINITY-INFINITY))
  34. #endif
  35. #if defined(_MSC_VER)
  36. # pragma warning(disable: 4756)
  37. # pragma warning(disable: 4056)
  38. #endif
  39. #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
  40. #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
  41. #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
  42. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
  43. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
  44. #define UA_JSON_DATETIME_LENGTH 24
  45. /* Max length of numbers for the allocation of temp buffers. Don't forget that
  46. * printf adds an additional \0 at the end!
  47. *
  48. * Sources:
  49. * https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
  50. *
  51. * UInt16: 3 + 1
  52. * SByte: 3 + 1
  53. * UInt32:
  54. * Int32:
  55. * UInt64:
  56. * Int64:
  57. * Float: 149 + 1
  58. * Double: 767 + 1
  59. */
  60. /************/
  61. /* Encoding */
  62. /************/
  63. #define ENCODE_JSON(TYPE) static status \
  64. TYPE##_encodeJson(const UA_##TYPE *src, const UA_DataType *type, CtxJson *ctx)
  65. #define ENCODE_DIRECT_JSON(SRC, TYPE) \
  66. TYPE##_encodeJson((const UA_##TYPE*)SRC, NULL, ctx)
  67. extern const encodeJsonSignature encodeJsonJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  68. extern const decodeJsonSignature decodeJsonJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
  69. /* Forward declarations */
  70. UA_String UA_DateTime_toJSON(UA_DateTime t);
  71. ENCODE_JSON(ByteString);
  72. static status UA_FUNC_ATTR_WARN_UNUSED_RESULT
  73. writeChar(CtxJson *ctx, char c) {
  74. if(ctx->pos >= ctx->end)
  75. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  76. if(!ctx->calcOnly)
  77. *ctx->pos = (UA_Byte)c;
  78. ctx->pos++;
  79. return UA_STATUSCODE_GOOD;
  80. }
  81. #define WRITE_JSON_ELEMENT(ELEM) \
  82. UA_FUNC_ATTR_WARN_UNUSED_RESULT status \
  83. writeJson##ELEM(CtxJson *ctx)
  84. static WRITE_JSON_ELEMENT(Quote) {
  85. return writeChar(ctx, '\"');
  86. }
  87. WRITE_JSON_ELEMENT(ObjStart) {
  88. /* increase depth, save: before first key-value no comma needed. */
  89. ctx->depth++;
  90. ctx->commaNeeded[ctx->depth] = false;
  91. return writeChar(ctx, '{');
  92. }
  93. WRITE_JSON_ELEMENT(ObjEnd) {
  94. ctx->depth--; //decrease depth
  95. ctx->commaNeeded[ctx->depth] = true;
  96. return writeChar(ctx, '}');
  97. }
  98. WRITE_JSON_ELEMENT(ArrStart) {
  99. /* increase depth, save: before first array entry no comma needed. */
  100. ctx->commaNeeded[++ctx->depth] = false;
  101. return writeChar(ctx, '[');
  102. }
  103. WRITE_JSON_ELEMENT(ArrEnd) {
  104. ctx->depth--; //decrease depth
  105. ctx->commaNeeded[ctx->depth] = true;
  106. return writeChar(ctx, ']');
  107. }
  108. WRITE_JSON_ELEMENT(CommaIfNeeded) {
  109. if(ctx->commaNeeded[ctx->depth])
  110. return writeChar(ctx, ',');
  111. return UA_STATUSCODE_GOOD;
  112. }
  113. status
  114. writeJsonArrElm(CtxJson *ctx, const void *value,
  115. const UA_DataType *type) {
  116. status ret = writeJsonCommaIfNeeded(ctx);
  117. ctx->commaNeeded[ctx->depth] = true;
  118. ret |= encodeJsonInternal(value, type, ctx);
  119. return ret;
  120. }
  121. status writeJsonObjElm(CtxJson *ctx, UA_String *key,
  122. const void *value, const UA_DataType *type){
  123. UA_STACKARRAY(char, out, key->length + 1);
  124. memcpy(out, key->data, key->length);
  125. out[key->length] = 0;
  126. status ret = writeJsonKey(ctx, out);
  127. ret |= encodeJsonInternal(value, type, ctx);
  128. return ret;
  129. }
  130. status writeJsonNull(CtxJson *ctx) {
  131. if(ctx->pos + 4 > ctx->end)
  132. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  133. if(ctx->calcOnly) {
  134. ctx->pos += 4;
  135. } else {
  136. *(ctx->pos++) = 'n';
  137. *(ctx->pos++) = 'u';
  138. *(ctx->pos++) = 'l';
  139. *(ctx->pos++) = 'l';
  140. }
  141. return UA_STATUSCODE_GOOD;
  142. }
  143. #define UA_STRING_TO_CSTRING(in,out) \
  144. UA_STACKARRAY(char, out, in->length + 1); \
  145. memcpy(out, in->data, in->length); \
  146. out[in->length] = 0;
  147. #define NULL_TERMINATE(in, inlength, out) \
  148. UA_STACKARRAY(char, out, inlength + 1); \
  149. memcpy(out, in, inlength); \
  150. out[inlength] = 0;
  151. /* Keys for JSON */
  152. /* LocalizedText */
  153. static const char* UA_JSONKEY_LOCALE = "Locale";
  154. static const char* UA_JSONKEY_TEXT = "Text";
  155. /* QualifiedName */
  156. static const char* UA_JSONKEY_NAME = "Name";
  157. static const char* UA_JSONKEY_URI = "Uri";
  158. /* NodeId */
  159. static const char* UA_JSONKEY_ID = "Id";
  160. static const char* UA_JSONKEY_IDTYPE = "IdType";
  161. static const char* UA_JSONKEY_NAMESPACE = "Namespace";
  162. /* ExpandedNodeId */
  163. static const char* UA_JSONKEY_SERVERURI = "ServerUri";
  164. /* Variant */
  165. static const char* UA_JSONKEY_TYPE = "Type";
  166. static const char* UA_JSONKEY_BODY = "Body";
  167. static const char* UA_JSONKEY_DIMENSION = "Dimension";
  168. /* DataValue */
  169. static const char* UA_JSONKEY_VALUE = "Value";
  170. static const char* UA_JSONKEY_STATUS = "Status";
  171. static const char* UA_JSONKEY_SOURCETIMESTAMP = "SourceTimestamp";
  172. static const char* UA_JSONKEY_SOURCEPICOSECONDS = "SourcePicoseconds";
  173. static const char* UA_JSONKEY_SERVERTIMESTAMP = "ServerTimestamp";
  174. static const char* UA_JSONKEY_SERVERPICOSECONDS = "ServerPicoseconds";
  175. /* ExtensionObject */
  176. static const char* UA_JSONKEY_ENCODING = "Encoding";
  177. static const char* UA_JSONKEY_TYPEID = "TypeId";
  178. /* StatusCode */
  179. static const char* UA_JSONKEY_CODE = "Code";
  180. static const char* UA_JSONKEY_SYMBOL = "Symbol";
  181. /* DiagnosticInfo */
  182. static const char* UA_JSONKEY_SYMBOLICID = "SymbolicId";
  183. static const char* UA_JSONKEY_NAMESPACEURI = "NamespaceUri";
  184. static const char* UA_JSONKEY_LOCALIZEDTEXT = "LocalizedText";
  185. static const char* UA_JSONKEY_ADDITIONALINFO = "AdditionalInfo";
  186. static const char* UA_JSONKEY_INNERSTATUSCODE = "InnerStatusCode";
  187. static const char* UA_JSONKEY_INNERDIAGNOSTICINFO = "InnerDiagnosticInfo";
  188. /* Writes null terminated string to output buffer (current ctx->pos). Writes
  189. * comma in front of key if needed. Encapsulates key in quotes. */
  190. status UA_FUNC_ATTR_WARN_UNUSED_RESULT
  191. writeJsonKey(CtxJson *ctx, const char* key) {
  192. size_t size = strlen(key);
  193. if(ctx->pos + size + 4 > ctx->end) /* +4 because of " " : and , */
  194. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  195. status ret = writeJsonCommaIfNeeded(ctx);
  196. ctx->commaNeeded[ctx->depth] = true;
  197. if(ctx->calcOnly) {
  198. ctx->commaNeeded[ctx->depth] = true;
  199. ctx->pos += 3;
  200. ctx->pos += size;
  201. return ret;
  202. }
  203. ret |= writeChar(ctx, '\"');
  204. for(size_t i = 0; i < size; i++) {
  205. *(ctx->pos++) = (u8)key[i];
  206. }
  207. ret |= writeChar(ctx, '\"');
  208. ret |= writeChar(ctx, ':');
  209. return ret;
  210. }
  211. /* Boolean */
  212. ENCODE_JSON(Boolean) {
  213. size_t sizeOfJSONBool;
  214. if(*src == true) {
  215. sizeOfJSONBool = 4; /*"true"*/
  216. } else {
  217. sizeOfJSONBool = 5; /*"false"*/
  218. }
  219. if(ctx->calcOnly) {
  220. ctx->pos += sizeOfJSONBool;
  221. return UA_STATUSCODE_GOOD;
  222. }
  223. if(ctx->pos + sizeOfJSONBool > ctx->end)
  224. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  225. if(*src) {
  226. *(ctx->pos++) = 't';
  227. *(ctx->pos++) = 'r';
  228. *(ctx->pos++) = 'u';
  229. *(ctx->pos++) = 'e';
  230. } else {
  231. *(ctx->pos++) = 'f';
  232. *(ctx->pos++) = 'a';
  233. *(ctx->pos++) = 'l';
  234. *(ctx->pos++) = 's';
  235. *(ctx->pos++) = 'e';
  236. }
  237. return UA_STATUSCODE_GOOD;
  238. }
  239. /*****************/
  240. /* Integer Types */
  241. /*****************/
  242. /* Byte */
  243. ENCODE_JSON(Byte) {
  244. char buf[4];
  245. UA_UInt16 digits = itoaUnsigned(*src, buf, 10);
  246. /* Ensure destination can hold the data- */
  247. if(ctx->pos + digits > ctx->end)
  248. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  249. /* Copy digits to the output string/buffer. */
  250. if(!ctx->calcOnly)
  251. memcpy(ctx->pos, buf, digits);
  252. ctx->pos += digits;
  253. return UA_STATUSCODE_GOOD;
  254. }
  255. /* signed Byte */
  256. ENCODE_JSON(SByte) {
  257. char buf[5];
  258. UA_UInt16 digits = itoaSigned(*src, buf);
  259. if(ctx->pos + digits > ctx->end)
  260. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  261. if(!ctx->calcOnly)
  262. memcpy(ctx->pos, buf, digits);
  263. ctx->pos += digits;
  264. return UA_STATUSCODE_GOOD;
  265. }
  266. /* UInt16 */
  267. ENCODE_JSON(UInt16) {
  268. char buf[6];
  269. UA_UInt16 digits = itoaUnsigned(*src, buf, 10);
  270. if(ctx->pos + digits > ctx->end)
  271. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  272. if(!ctx->calcOnly)
  273. memcpy(ctx->pos, buf, digits);
  274. ctx->pos += digits;
  275. return UA_STATUSCODE_GOOD;
  276. }
  277. /* Int16 */
  278. ENCODE_JSON(Int16) {
  279. char buf[7];
  280. UA_UInt16 digits = itoaSigned(*src, buf);
  281. if(ctx->pos + digits > ctx->end)
  282. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  283. if(!ctx->calcOnly)
  284. memcpy(ctx->pos, buf, digits);
  285. ctx->pos += digits;
  286. return UA_STATUSCODE_GOOD;
  287. }
  288. /* UInt32 */
  289. ENCODE_JSON(UInt32) {
  290. char buf[11];
  291. UA_UInt16 digits = itoaUnsigned(*src, buf, 10);
  292. if(ctx->pos + digits > ctx->end)
  293. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  294. if(!ctx->calcOnly)
  295. memcpy(ctx->pos, buf, digits);
  296. ctx->pos += digits;
  297. return UA_STATUSCODE_GOOD;
  298. }
  299. /* Int32 */
  300. ENCODE_JSON(Int32) {
  301. char buf[12];
  302. UA_UInt16 digits = itoaSigned(*src, buf);
  303. if(ctx->pos + digits > ctx->end)
  304. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  305. if(!ctx->calcOnly)
  306. memcpy(ctx->pos, buf, digits);
  307. ctx->pos += digits;
  308. return UA_STATUSCODE_GOOD;
  309. }
  310. /* UInt64 */
  311. ENCODE_JSON(UInt64) {
  312. char buf[21];
  313. UA_UInt16 digits = itoaUnsigned(*src, buf, 10);
  314. if(ctx->pos + digits > ctx->end)
  315. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  316. if(!ctx->calcOnly)
  317. memcpy(ctx->pos, buf, digits);
  318. ctx->pos += digits;
  319. return UA_STATUSCODE_GOOD;
  320. }
  321. /* Int64 */
  322. ENCODE_JSON(Int64) {
  323. char buf[21];
  324. UA_UInt16 digits = itoaSigned(*src, buf);
  325. if(ctx->pos + digits > ctx->end)
  326. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  327. if(!ctx->calcOnly)
  328. memcpy(ctx->pos, buf, digits);
  329. ctx->pos += digits;
  330. return UA_STATUSCODE_GOOD;
  331. }
  332. /************************/
  333. /* Floating Point Types */
  334. /************************/
  335. /* Convert special numbers to string
  336. * - fmt_fp gives NAN, nan,-NAN, -nan, inf, INF, -inf, -INF
  337. * - Special floating-point numbers such as positive infinity (INF), negative
  338. * infinity (-INF) and not-a-number (NaN) shall be represented by the values
  339. * “Infinity”, “-Infinity” and “NaN” encoded as a JSON string. */
  340. static status
  341. checkAndEncodeSpecialFloatingPoint(char *buffer, size_t *len) {
  342. /*nan and NaN*/
  343. if(*len == 3 &&
  344. (buffer[0] == 'n' || buffer[0] == 'N') &&
  345. (buffer[1] == 'a' || buffer[1] == 'A') &&
  346. (buffer[2] == 'n' || buffer[2] == 'N')) {
  347. *len = 5;
  348. memcpy(buffer, "\"NaN\"", *len);
  349. return UA_STATUSCODE_GOOD;
  350. }
  351. /*-nan and -NaN*/
  352. if(*len == 4 && buffer[0] == '-' &&
  353. (buffer[1] == 'n' || buffer[1] == 'N') &&
  354. (buffer[2] == 'a' || buffer[2] == 'A') &&
  355. (buffer[3] == 'n' || buffer[3] == 'N')) {
  356. *len = 6;
  357. memcpy(buffer, "\"-NaN\"", *len);
  358. return UA_STATUSCODE_GOOD;
  359. }
  360. /*inf*/
  361. if(*len == 3 &&
  362. (buffer[0] == 'i' || buffer[0] == 'I') &&
  363. (buffer[1] == 'n' || buffer[1] == 'N') &&
  364. (buffer[2] == 'f' || buffer[2] == 'F')) {
  365. *len = 10;
  366. memcpy(buffer, "\"Infinity\"", *len);
  367. return UA_STATUSCODE_GOOD;
  368. }
  369. /*-inf*/
  370. if(*len == 4 && buffer[0] == '-' &&
  371. (buffer[1] == 'i' || buffer[1] == 'I') &&
  372. (buffer[2] == 'n' || buffer[2] == 'N') &&
  373. (buffer[3] == 'f' || buffer[3] == 'F')) {
  374. *len = 11;
  375. memcpy(buffer, "\"-Infinity\"", *len);
  376. return UA_STATUSCODE_GOOD;
  377. }
  378. return UA_STATUSCODE_GOOD;
  379. }
  380. ENCODE_JSON(Float) {
  381. char buffer[200];
  382. if(*src == *src) {
  383. #ifdef UA_ENABLE_CUSTOM_LIBC
  384. fmt_fp(buffer, *src, 0, -1, 0, 'g');
  385. #else
  386. UA_snprintf(buffer, 200, "%.149g", (UA_Double)*src);
  387. #endif
  388. } else {
  389. strcpy(buffer, "NaN");
  390. }
  391. size_t len = strlen(buffer);
  392. if(len == 0)
  393. return UA_STATUSCODE_BADENCODINGERROR;
  394. checkAndEncodeSpecialFloatingPoint(buffer, &len);
  395. if(ctx->pos + len > ctx->end)
  396. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  397. if(!ctx->calcOnly)
  398. memcpy(ctx->pos, buffer, len);
  399. ctx->pos += len;
  400. return UA_STATUSCODE_GOOD;
  401. }
  402. ENCODE_JSON(Double) {
  403. char buffer[2000];
  404. if(*src == *src) {
  405. #ifdef UA_ENABLE_CUSTOM_LIBC
  406. fmt_fp(buffer, *src, 0, 17, 0, 'g');
  407. #else
  408. UA_snprintf(buffer, 2000, "%.1074g", *src);
  409. #endif
  410. } else {
  411. strcpy(buffer, "NaN");
  412. }
  413. size_t len = strlen(buffer);
  414. checkAndEncodeSpecialFloatingPoint(buffer, &len);
  415. if(ctx->pos + len > ctx->end)
  416. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  417. if(!ctx->calcOnly)
  418. memcpy(ctx->pos, buffer, len);
  419. ctx->pos += len;
  420. return UA_STATUSCODE_GOOD;
  421. }
  422. static status
  423. encodeJsonArray(CtxJson *ctx, const void *ptr, size_t length,
  424. const UA_DataType *type) {
  425. size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  426. encodeJsonSignature encodeType = encodeJsonJumpTable[encode_index];
  427. status ret = writeJsonArrStart(ctx);
  428. uintptr_t uptr = (uintptr_t)ptr;
  429. for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
  430. ret |= writeJsonCommaIfNeeded(ctx);
  431. ret |= encodeType((const void*)uptr, type, ctx);
  432. ctx->commaNeeded[ctx->depth] = true;
  433. uptr += type->memSize;
  434. }
  435. ret |= writeJsonArrEnd(ctx);
  436. return ret;
  437. }
  438. /*****************/
  439. /* Builtin Types */
  440. /*****************/
  441. static const u8 hexmapLower[16] =
  442. {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  443. static const u8 hexmapUpper[16] =
  444. {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  445. ENCODE_JSON(String) {
  446. if(!src->data)
  447. return writeJsonNull(ctx);
  448. if(src->length == 0)
  449. return writeJsonQuote(ctx) | writeJsonQuote(ctx);
  450. UA_StatusCode ret = writeJsonQuote(ctx);
  451. /* Escaping adapted from https://github.com/akheron/jansson dump.c */
  452. const char *str = (char*)src->data;
  453. const char *pos = str;
  454. const char *end = str;
  455. const char *lim = str + src->length;
  456. UA_Int32 codepoint = 0;
  457. while(1) {
  458. const char *text;
  459. u8 seq[13];
  460. size_t length;
  461. while(end < lim) {
  462. end = utf8_iterate(pos, (size_t)(lim - pos), &codepoint);
  463. if(!end)
  464. return UA_STATUSCODE_BADENCODINGERROR;
  465. /* mandatory escape or control char */
  466. if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20)
  467. break;
  468. /* slash
  469. if((flags & JSON_ESCAPE_SLASH) && codepoint == '/')
  470. break;*/
  471. /* non-ASCII
  472. if((flags & JSON_ENSURE_ASCII) && codepoint > 0x7F)
  473. break;*/
  474. pos = end;
  475. }
  476. if(pos != str) {
  477. if(ctx->pos + (pos - str) > ctx->end)
  478. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  479. if(!ctx->calcOnly)
  480. memcpy(ctx->pos, str, (size_t)(pos - str));
  481. ctx->pos += pos - str;
  482. }
  483. if(end == pos)
  484. break;
  485. /* handle \, /, ", and control codes */
  486. length = 2;
  487. switch(codepoint) {
  488. case '\\': text = "\\\\"; break;
  489. case '\"': text = "\\\""; break;
  490. case '\b': text = "\\b"; break;
  491. case '\f': text = "\\f"; break;
  492. case '\n': text = "\\n"; break;
  493. case '\r': text = "\\r"; break;
  494. case '\t': text = "\\t"; break;
  495. case '/': text = "\\/"; break;
  496. default:
  497. if(codepoint < 0x10000) {
  498. /* codepoint is in BMP */
  499. seq[0] = '\\';
  500. seq[1] = 'u';
  501. UA_Byte b1 = (UA_Byte)(codepoint >> 8);
  502. UA_Byte b2 = (UA_Byte)(codepoint >> 0);
  503. seq[2] = hexmapLower[(b1 & 0xF0) >> 4];
  504. seq[3] = hexmapLower[b1 & 0x0F];
  505. seq[4] = hexmapLower[(b2 & 0xF0) >> 4];
  506. seq[5] = hexmapLower[b2 & 0x0F];
  507. length = 6;
  508. } else {
  509. /* not in BMP -> construct a UTF-16 surrogate pair */
  510. codepoint -= 0x10000;
  511. UA_Int32 first = 0xD800 | ((codepoint & 0xffc00) >> 10);
  512. UA_Int32 last = 0xDC00 | (codepoint & 0x003ff);
  513. UA_Byte fb1 = (UA_Byte)(first >> 8);
  514. UA_Byte fb2 = (UA_Byte)(first >> 0);
  515. UA_Byte lb1 = (UA_Byte)(last >> 8);
  516. UA_Byte lb2 = (UA_Byte)(last >> 0);
  517. seq[0] = '\\';
  518. seq[1] = 'u';
  519. seq[2] = hexmapLower[(fb1 & 0xF0) >> 4];
  520. seq[3] = hexmapLower[fb1 & 0x0F];
  521. seq[4] = hexmapLower[(fb2 & 0xF0) >> 4];
  522. seq[5] = hexmapLower[fb2 & 0x0F];
  523. seq[6] = '\\';
  524. seq[7] = 'u';
  525. seq[8] = hexmapLower[(lb1 & 0xF0) >> 4];
  526. seq[9] = hexmapLower[lb1 & 0x0F];
  527. seq[10] = hexmapLower[(lb2 & 0xF0) >> 4];
  528. seq[11] = hexmapLower[lb2 & 0x0F];
  529. length = 12;
  530. }
  531. text = (char*)seq;
  532. break;
  533. }
  534. if(ctx->pos + length > ctx->end)
  535. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  536. if(!ctx->calcOnly)
  537. memcpy(ctx->pos, text, length);
  538. ctx->pos += length;
  539. str = pos = end;
  540. }
  541. ret |= writeJsonQuote(ctx);
  542. return ret;
  543. }
  544. ENCODE_JSON(ByteString) {
  545. if(!src->data)
  546. return writeJsonNull(ctx);
  547. if(src->length == 0)
  548. return writeJsonQuote(ctx) | writeJsonQuote(ctx);
  549. status ret = writeJsonQuote(ctx);
  550. int flen;
  551. char *b64 = UA_base64(src->data, (int)src->length, &flen);
  552. /* Not converted, no mem */
  553. if(!b64)
  554. return UA_STATUSCODE_BADENCODINGERROR;
  555. /* Check if negative... (TODO: Why is base64 3rd argument type int?) */
  556. if(flen < 0) {
  557. free(b64);
  558. return UA_STATUSCODE_BADENCODINGERROR;
  559. }
  560. if(ctx->pos + flen > ctx->end) {
  561. free(b64);
  562. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  563. }
  564. /* Copy flen bytes to output stream. */
  565. if(!ctx->calcOnly)
  566. memcpy(ctx->pos, b64, (size_t)flen);
  567. ctx->pos += flen;
  568. /* Base64 result no longer needed */
  569. free(b64);
  570. ret |= writeJsonQuote(ctx);
  571. return ret;
  572. }
  573. /* Converts Guid to a hexadecimal represenation */
  574. static void UA_Guid_to_hex(const UA_Guid *guid, u8* out) {
  575. /*
  576. 16 byte
  577. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  578. | data1 |data2|data3| data4 |
  579. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  580. |aa aa aa aa-bb bb-cc cc-dd dd-ee ee ee ee ee ee|
  581. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  582. 36 character
  583. */
  584. #ifdef hexCharlowerCase
  585. const u8 *hexmap = hexmapLower;
  586. #else
  587. const u8 *hexmap = hexmapUpper;
  588. #endif
  589. size_t i = 0, j = 28;
  590. for(; i<8;i++,j-=4) /* pos 0-7, 4byte, (a) */
  591. out[i] = hexmap[(guid->data1 >> j) & 0x0F];
  592. out[i++] = '-'; /* pos 8 */
  593. for(j=12; i<13;i++,j-=4) /* pos 9-12, 2byte, (b) */
  594. out[i] = hexmap[(guid->data2 >> j) & 0x0F];
  595. out[i++] = '-'; /* pos 13 */
  596. for(j=12; i<18;i++,j-=4) /* pos 14-17, 2byte (c) */
  597. out[i] = hexmap[(guid->data3 >> j) & 0x0F];
  598. out[i++] = '-'; /* pos 18 */
  599. for(j=0;i<23;i+=2,j++) { /* pos 19-22, 2byte (d) */
  600. out[i] = hexmap[(guid->data4[j] & 0xF0) >> 4];
  601. out[i+1] = hexmap[guid->data4[j] & 0x0F];
  602. }
  603. out[i++] = '-'; /* pos 23 */
  604. for(j=2; i<36;i+=2,j++) { /* pos 24-35, 6byte (e) */
  605. out[i] = hexmap[(guid->data4[j] & 0xF0) >> 4];
  606. out[i+1] = hexmap[guid->data4[j] & 0x0F];
  607. }
  608. }
  609. /* Guid */
  610. ENCODE_JSON(Guid) {
  611. if(ctx->pos + 38 > ctx->end) /* 36 + 2 (") */
  612. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  613. status ret = writeJsonQuote(ctx);
  614. u8 *buf = ctx->pos;
  615. if(!ctx->calcOnly)
  616. UA_Guid_to_hex(src, buf);
  617. ctx->pos += 36;
  618. ret |= writeJsonQuote(ctx);
  619. return ret;
  620. }
  621. static void
  622. printNumber(u16 n, u8 *pos, size_t digits) {
  623. for(size_t i = digits; i > 0; --i) {
  624. pos[i - 1] = (u8) ((n % 10) + '0');
  625. n = n / 10;
  626. }
  627. }
  628. UA_String
  629. UA_DateTime_toJSON(UA_DateTime t) {
  630. UA_DateTimeStruct tSt = UA_DateTime_toStruct(t);
  631. /* Format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z' is used. 24 bytes.*/
  632. UA_String str = {UA_JSON_DATETIME_LENGTH,
  633. (u8*) UA_malloc(UA_JSON_DATETIME_LENGTH)};
  634. if(!str.data)
  635. return UA_STRING_NULL;
  636. printNumber(tSt.year, str.data, 4);
  637. str.data[4] = '-';
  638. printNumber(tSt.month, &str.data[5], 2);
  639. str.data[7] = '-';
  640. printNumber(tSt.day, &str.data[8], 2);
  641. str.data[10] = 'T';
  642. printNumber(tSt.hour, &str.data[11], 2);
  643. str.data[13] = ':';
  644. printNumber(tSt.min, &str.data[14], 2);
  645. str.data[16] = ':';
  646. printNumber(tSt.sec, &str.data[17], 2);
  647. str.data[19] = '.';
  648. printNumber(tSt.milliSec, &str.data[20], 3);
  649. str.data[23] = 'Z';
  650. return str;
  651. }
  652. ENCODE_JSON(DateTime) {
  653. if(ctx->pos + UA_JSON_DATETIME_LENGTH > ctx->end)
  654. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  655. UA_String str = UA_DateTime_toJSON(*src);
  656. UA_StatusCode ret = ENCODE_DIRECT_JSON(&str, String);
  657. UA_String_deleteMembers(&str);
  658. return ret;
  659. }
  660. /* NodeId */
  661. static status
  662. NodeId_encodeJsonInternal(UA_NodeId const *src, CtxJson *ctx) {
  663. status ret = UA_STATUSCODE_GOOD;
  664. switch (src->identifierType) {
  665. case UA_NODEIDTYPE_NUMERIC:
  666. ret |= writeJsonKey(ctx, UA_JSONKEY_ID);
  667. ret |= ENCODE_DIRECT_JSON(&src->identifier.numeric, UInt32);
  668. break;
  669. case UA_NODEIDTYPE_STRING:
  670. ret |= writeJsonKey(ctx, UA_JSONKEY_IDTYPE);
  671. ret |= writeChar(ctx, '1');
  672. ret |= writeJsonKey(ctx, UA_JSONKEY_ID);
  673. ret |= ENCODE_DIRECT_JSON(&src->identifier.string, String);
  674. break;
  675. case UA_NODEIDTYPE_GUID:
  676. ret |= writeJsonKey(ctx, UA_JSONKEY_IDTYPE);
  677. ret |= writeChar(ctx, '2');
  678. ret |= writeJsonKey(ctx, UA_JSONKEY_ID); /* Id */
  679. ret |= ENCODE_DIRECT_JSON(&src->identifier.guid, Guid);
  680. break;
  681. case UA_NODEIDTYPE_BYTESTRING:
  682. ret |= writeJsonKey(ctx, UA_JSONKEY_IDTYPE);
  683. ret |= writeChar(ctx, '3');
  684. ret |= writeJsonKey(ctx, UA_JSONKEY_ID); /* Id */
  685. ret |= ENCODE_DIRECT_JSON(&src->identifier.byteString, ByteString);
  686. break;
  687. default:
  688. return UA_STATUSCODE_BADINTERNALERROR;
  689. }
  690. return ret;
  691. }
  692. ENCODE_JSON(NodeId) {
  693. UA_StatusCode ret = writeJsonObjStart(ctx);
  694. ret |= NodeId_encodeJsonInternal(src, ctx);
  695. if(ctx->useReversible) {
  696. if(src->namespaceIndex > 0) {
  697. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  698. ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16);
  699. }
  700. } else {
  701. /* For the non-reversible encoding, the field is the NamespaceUri
  702. * associated with the NamespaceIndex, encoded as a JSON string.
  703. * A NamespaceIndex of 1 is always encoded as a JSON number. */
  704. if(src->namespaceIndex == 1) {
  705. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  706. ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16);
  707. } else {
  708. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  709. /* Check if Namespace given and in range */
  710. if(src->namespaceIndex < ctx->namespacesSize && ctx->namespaces != NULL) {
  711. UA_String namespaceEntry = ctx->namespaces[src->namespaceIndex];
  712. ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String);
  713. } else {
  714. return UA_STATUSCODE_BADNOTFOUND;
  715. }
  716. }
  717. }
  718. ret = writeJsonObjEnd(ctx);
  719. return ret;
  720. }
  721. /* ExpandedNodeId */
  722. ENCODE_JSON(ExpandedNodeId) {
  723. status ret = writeJsonObjStart(ctx);
  724. /* Encode the NodeId */
  725. ret |= NodeId_encodeJsonInternal(&src->nodeId, ctx);
  726. if(ctx->useReversible) {
  727. if(src->namespaceUri.data != NULL && src->namespaceUri.length != 0 &&
  728. (void*) src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) {
  729. /* If the NamespaceUri is specified it is encoded as a JSON string in this field. */
  730. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  731. ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, String);
  732. } else {
  733. /* If the NamespaceUri is not specified, the NamespaceIndex is encoded with these rules:
  734. * The field is encoded as a JSON number for the reversible encoding.
  735. * The field is omitted if the NamespaceIndex equals 0. */
  736. if(src->nodeId.namespaceIndex > 0) {
  737. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  738. ret |= ENCODE_DIRECT_JSON(&src->nodeId.namespaceIndex, UInt16);
  739. }
  740. }
  741. /* Encode the serverIndex/Url
  742. * This field is encoded as a JSON number for the reversible encoding.
  743. * This field is omitted if the ServerIndex equals 0. */
  744. if(src->serverIndex > 0) {
  745. ret |= writeJsonKey(ctx, UA_JSONKEY_SERVERURI);
  746. ret |= ENCODE_DIRECT_JSON(&src->serverIndex, UInt32);
  747. }
  748. ret |= writeJsonObjEnd(ctx);
  749. return ret;
  750. }
  751. /* NON-Reversible Case */
  752. /* If the NamespaceUri is not specified, the NamespaceIndex is encoded with these rules:
  753. * For the non-reversible encoding the field is the NamespaceUri associated with the
  754. * NamespaceIndex encoded as a JSON string.
  755. * A NamespaceIndex of 1 is always encoded as a JSON number. */
  756. if(src->namespaceUri.data != NULL && src->namespaceUri.length != 0) {
  757. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  758. ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, String);
  759. if(ret != UA_STATUSCODE_GOOD)
  760. return ret;
  761. } else {
  762. if(src->nodeId.namespaceIndex == 1) {
  763. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  764. ret |= ENCODE_DIRECT_JSON(&src->nodeId.namespaceIndex, UInt16);
  765. if(ret != UA_STATUSCODE_GOOD)
  766. return ret;
  767. } else {
  768. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACE);
  769. /* Check if Namespace given and in range */
  770. if(src->nodeId.namespaceIndex < ctx->namespacesSize
  771. && ctx->namespaces != NULL) {
  772. UA_String namespaceEntry = ctx->namespaces[src->nodeId.namespaceIndex];
  773. ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String);
  774. if(ret != UA_STATUSCODE_GOOD)
  775. return ret;
  776. } else {
  777. return UA_STATUSCODE_BADNOTFOUND;
  778. }
  779. }
  780. }
  781. /* For the non-reversible encoding, this field is the ServerUri associated
  782. * with the ServerIndex portion of the ExpandedNodeId, encoded as a JSON
  783. * string. */
  784. /* Check if Namespace given and in range */
  785. if(src->serverIndex < ctx->serverUrisSize && ctx->serverUris != NULL) {
  786. UA_String serverUriEntry = ctx->serverUris[src->serverIndex];
  787. ret |= writeJsonKey(ctx, UA_JSONKEY_SERVERURI);
  788. ret |= ENCODE_DIRECT_JSON(&serverUriEntry, String);
  789. } else {
  790. return UA_STATUSCODE_BADNOTFOUND;
  791. }
  792. ret |= writeJsonObjEnd(ctx);
  793. return ret;
  794. }
  795. /* LocalizedText */
  796. ENCODE_JSON(LocalizedText) {
  797. if(ctx->useReversible) {
  798. status ret = writeJsonObjStart(ctx);
  799. ret |= writeJsonKey(ctx, UA_JSONKEY_LOCALE);
  800. ret |= ENCODE_DIRECT_JSON(&src->locale, String);
  801. ret |= writeJsonKey(ctx, UA_JSONKEY_TEXT);
  802. ret |= ENCODE_DIRECT_JSON(&src->text, String);
  803. ret |= writeJsonObjEnd(ctx);
  804. return ret;
  805. }
  806. /* For the non-reversible form, LocalizedText value shall be encoded as a
  807. * JSON string containing the Text component.*/
  808. return ENCODE_DIRECT_JSON(&src->text, String);
  809. }
  810. ENCODE_JSON(QualifiedName) {
  811. status ret = writeJsonObjStart(ctx);
  812. ret |= writeJsonKey(ctx, UA_JSONKEY_NAME);
  813. ret |= ENCODE_DIRECT_JSON(&src->name, String);
  814. if(ctx->useReversible) {
  815. if(src->namespaceIndex != 0) {
  816. ret |= writeJsonKey(ctx, UA_JSONKEY_URI);
  817. ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16);
  818. }
  819. } else {
  820. /* For the non-reversible form, the NamespaceUri associated with the
  821. * NamespaceIndex portion of the QualifiedName is encoded as JSON string
  822. * unless the NamespaceIndex is 1 or if NamespaceUri is unknown. In
  823. * these cases, the NamespaceIndex is encoded as a JSON number. */
  824. if(src->namespaceIndex == 1) {
  825. ret |= writeJsonKey(ctx, UA_JSONKEY_URI);
  826. ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16);
  827. } else {
  828. ret |= writeJsonKey(ctx, UA_JSONKEY_URI);
  829. /* Check if Namespace given and in range */
  830. if(src->namespaceIndex < ctx->namespacesSize && ctx->namespaces != NULL) {
  831. UA_String namespaceEntry = ctx->namespaces[src->namespaceIndex];
  832. ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String);
  833. } else {
  834. /* If not encode as number */
  835. ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16);
  836. }
  837. }
  838. }
  839. return ret | writeJsonObjEnd(ctx);
  840. }
  841. ENCODE_JSON(StatusCode) {
  842. if(!src)
  843. return writeJsonNull(ctx);
  844. if(ctx->useReversible)
  845. return ENCODE_DIRECT_JSON(src, UInt32);
  846. if(*src == UA_STATUSCODE_GOOD)
  847. return writeJsonNull(ctx);
  848. status ret = UA_STATUSCODE_GOOD;
  849. ret |= writeJsonObjStart(ctx);
  850. ret |= writeJsonKey(ctx, UA_JSONKEY_CODE);
  851. ret |= ENCODE_DIRECT_JSON(src, UInt32);
  852. ret |= writeJsonKey(ctx, UA_JSONKEY_SYMBOL);
  853. const char *codename = UA_StatusCode_name(*src);
  854. UA_String statusDescription = UA_STRING((char*)(uintptr_t)codename);
  855. ret |= ENCODE_DIRECT_JSON(&statusDescription, String);
  856. ret |= writeJsonObjEnd(ctx);
  857. return ret;
  858. }
  859. /* ExtensionObject */
  860. ENCODE_JSON(ExtensionObject) {
  861. u8 encoding = (u8) src->encoding;
  862. if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY)
  863. return writeJsonNull(ctx);
  864. status ret = UA_STATUSCODE_GOOD;
  865. /* already encoded content.*/
  866. if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
  867. ret |= writeJsonObjStart(ctx);
  868. if(ctx->useReversible) {
  869. ret |= writeJsonKey(ctx, UA_JSONKEY_TYPEID);
  870. ret |= ENCODE_DIRECT_JSON(&src->content.encoded.typeId, NodeId);
  871. if(ret != UA_STATUSCODE_GOOD)
  872. return ret;
  873. }
  874. switch (src->encoding) {
  875. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  876. {
  877. if(ctx->useReversible) {
  878. ret |= writeJsonKey(ctx, UA_JSONKEY_ENCODING);
  879. ret |= writeChar(ctx, '1');
  880. }
  881. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  882. ret |= ENCODE_DIRECT_JSON(&src->content.encoded.body, String);
  883. break;
  884. }
  885. case UA_EXTENSIONOBJECT_ENCODED_XML:
  886. {
  887. if(ctx->useReversible) {
  888. ret |= writeJsonKey(ctx, UA_JSONKEY_ENCODING);
  889. ret |= writeChar(ctx, '2');
  890. }
  891. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  892. ret |= ENCODE_DIRECT_JSON(&src->content.encoded.body, String);
  893. break;
  894. }
  895. default:
  896. ret = UA_STATUSCODE_BADINTERNALERROR;
  897. }
  898. ret |= writeJsonObjEnd(ctx);
  899. return ret;
  900. } /* encoding <= UA_EXTENSIONOBJECT_ENCODED_XML */
  901. /* Cannot encode with no type description */
  902. if(!src->content.decoded.type)
  903. return UA_STATUSCODE_BADENCODINGERROR;
  904. if(!src->content.decoded.data)
  905. return writeJsonNull(ctx);
  906. UA_NodeId typeId = src->content.decoded.type->typeId;
  907. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  908. return UA_STATUSCODE_BADENCODINGERROR;
  909. ret |= writeJsonObjStart(ctx);
  910. const UA_DataType *contentType = src->content.decoded.type;
  911. if(ctx->useReversible) {
  912. /* REVERSIBLE */
  913. ret |= writeJsonKey(ctx, UA_JSONKEY_TYPEID);
  914. ret |= ENCODE_DIRECT_JSON(&typeId, NodeId);
  915. /* Encode the content */
  916. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  917. ret |= encodeJsonInternal(src->content.decoded.data, contentType, ctx);
  918. } else {
  919. /* NON-REVERSIBLE
  920. * For the non-reversible form, ExtensionObject values
  921. * shall be encoded as a JSON object containing only the
  922. * value of the Body field. The TypeId and Encoding fields are dropped.
  923. *
  924. * TODO: UA_JSONKEY_BODY key in the ExtensionObject?
  925. */
  926. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  927. ret |= encodeJsonInternal(src->content.decoded.data, contentType, ctx);
  928. }
  929. ret |= writeJsonObjEnd(ctx);
  930. return ret;
  931. }
  932. static status
  933. Variant_encodeJsonWrapExtensionObject(const UA_Variant *src, const bool isArray, CtxJson *ctx) {
  934. size_t length = 1;
  935. status ret = UA_STATUSCODE_GOOD;
  936. if(isArray) {
  937. if(src->arrayLength > UA_INT32_MAX)
  938. return UA_STATUSCODE_BADENCODINGERROR;
  939. length = src->arrayLength;
  940. }
  941. /* Set up the ExtensionObject */
  942. UA_ExtensionObject eo;
  943. UA_ExtensionObject_init(&eo);
  944. eo.encoding = UA_EXTENSIONOBJECT_DECODED;
  945. eo.content.decoded.type = src->type;
  946. const u16 memSize = src->type->memSize;
  947. uintptr_t ptr = (uintptr_t) src->data;
  948. if(isArray) {
  949. ret |= writeJsonArrStart(ctx);
  950. ctx->commaNeeded[ctx->depth] = false;
  951. /* Iterate over the array */
  952. for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
  953. eo.content.decoded.data = (void*) ptr;
  954. ret |= writeJsonArrElm(ctx, &eo, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
  955. ptr += memSize;
  956. }
  957. ret |= writeJsonArrEnd(ctx);
  958. return ret;
  959. }
  960. eo.content.decoded.data = (void*) ptr;
  961. return encodeJsonInternal(&eo, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
  962. }
  963. static status
  964. addMultiArrayContentJSON(CtxJson *ctx, void* array, const UA_DataType *type,
  965. size_t *index, UA_UInt32 *arrayDimensions, size_t dimensionIndex,
  966. size_t dimensionSize) {
  967. /* Check the recursion limit */
  968. if(ctx->depth > UA_JSON_ENCODING_MAX_RECURSION)
  969. return UA_STATUSCODE_BADENCODINGERROR;
  970. /* Stop recursion: The inner Arrays are written */
  971. status ret;
  972. if(dimensionIndex == (dimensionSize - 1)) {
  973. ret = encodeJsonArray(ctx, ((u8*)array) + (type->memSize * *index),
  974. arrayDimensions[dimensionIndex], type);
  975. (*index) += arrayDimensions[dimensionIndex];
  976. return ret;
  977. }
  978. /* Recurse to the next dimension */
  979. ret = writeJsonArrStart(ctx);
  980. for(size_t i = 0; i < arrayDimensions[dimensionIndex]; i++) {
  981. ret |= writeJsonCommaIfNeeded(ctx);
  982. ret |= addMultiArrayContentJSON(ctx, array, type, index, arrayDimensions,
  983. dimensionIndex + 1, dimensionSize);
  984. ctx->commaNeeded[ctx->depth] = true;
  985. if(ret != UA_STATUSCODE_GOOD)
  986. return ret;
  987. }
  988. ret |= writeJsonArrEnd(ctx);
  989. return ret;
  990. }
  991. ENCODE_JSON(Variant) {
  992. /* If type is 0 (NULL) the Variant contains a NULL value and the containing
  993. * JSON object shall be omitted or replaced by the JSON literal ‘null’ (when
  994. * an element of a JSON array). */
  995. if(!src->type) {
  996. return writeJsonNull(ctx);
  997. }
  998. /* Set the content type in the encoding mask */
  999. const bool isBuiltin = src->type->builtin;
  1000. const bool isAlias = src->type->membersSize == 1
  1001. && UA_TYPES[src->type->members[0].memberTypeIndex].builtin;
  1002. /* Set the array type in the encoding mask */
  1003. const bool isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  1004. const bool hasDimensions = isArray && src->arrayDimensionsSize > 0;
  1005. status ret = UA_STATUSCODE_GOOD;
  1006. if(ctx->useReversible) {
  1007. ret |= writeJsonObjStart(ctx);
  1008. if(ret != UA_STATUSCODE_GOOD)
  1009. return ret;
  1010. /* Encode the content */
  1011. if(!isBuiltin && !isAlias) {
  1012. /* REVERSIBLE: NOT BUILTIN, can it be encoded? Wrap in extension object.*/
  1013. ret |= writeJsonKey(ctx, UA_JSONKEY_TYPE);
  1014. ret |= ENCODE_DIRECT_JSON(&UA_TYPES[UA_TYPES_EXTENSIONOBJECT].typeId.identifier.numeric, UInt32);
  1015. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1016. ret |= Variant_encodeJsonWrapExtensionObject(src, isArray, ctx);
  1017. } else if(!isArray) {
  1018. /*REVERSIBLE: BUILTIN, single value.*/
  1019. ret |= writeJsonKey(ctx, UA_JSONKEY_TYPE);
  1020. ret |= ENCODE_DIRECT_JSON(&src->type->typeId.identifier.numeric, UInt32);
  1021. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1022. ret |= encodeJsonInternal(src->data, src->type, ctx);
  1023. } else {
  1024. /*REVERSIBLE: BUILTIN, array.*/
  1025. ret |= writeJsonKey(ctx, UA_JSONKEY_TYPE);
  1026. ret |= ENCODE_DIRECT_JSON(&src->type->typeId.identifier.numeric, UInt32);
  1027. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1028. ret |= encodeJsonArray(ctx, src->data, src->arrayLength, src->type);
  1029. }
  1030. if(ret != UA_STATUSCODE_GOOD)
  1031. return ret;
  1032. /* REVERSIBLE: Encode the array dimensions */
  1033. if(hasDimensions && ret == UA_STATUSCODE_GOOD) {
  1034. ret |= writeJsonKey(ctx, UA_JSONKEY_DIMENSION);
  1035. ret |= encodeJsonArray(ctx, src->arrayDimensions, src->arrayDimensionsSize,
  1036. &UA_TYPES[UA_TYPES_INT32]);
  1037. if(ret != UA_STATUSCODE_GOOD)
  1038. return ret;
  1039. }
  1040. ret |= writeJsonObjEnd(ctx);
  1041. return ret;
  1042. } /* reversible */
  1043. /* NON-REVERSIBLE
  1044. * For the non-reversible form, Variant values shall be encoded as a JSON object containing only
  1045. * the value of the Body field. The Type and Dimensions fields are dropped. Multi-dimensional
  1046. * arrays are encoded as a multi dimensional JSON array as described in 5.4.5.
  1047. */
  1048. ret |= writeJsonObjStart(ctx);
  1049. if(!isBuiltin && !isAlias) {
  1050. /*NON REVERSIBLE: NOT BUILTIN, can it be encoded? Wrap in extension object.*/
  1051. if(src->arrayDimensionsSize > 1) {
  1052. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  1053. }
  1054. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1055. ret |= Variant_encodeJsonWrapExtensionObject(src, isArray, ctx);
  1056. } else if(!isArray) {
  1057. /*NON REVERSIBLE: BUILTIN, single value.*/
  1058. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1059. ret |= encodeJsonInternal(src->data, src->type, ctx);
  1060. } else {
  1061. /*NON REVERSIBLE: BUILTIN, array.*/
  1062. ret |= writeJsonKey(ctx, UA_JSONKEY_BODY);
  1063. size_t dimensionSize = src->arrayDimensionsSize;
  1064. if(dimensionSize > 1) {
  1065. /*nonreversible multidimensional array*/
  1066. size_t index = 0; size_t dimensionIndex = 0;
  1067. void *ptr = src->data;
  1068. const UA_DataType *arraytype = src->type;
  1069. ret |= addMultiArrayContentJSON(ctx, ptr, arraytype, &index,
  1070. src->arrayDimensions, dimensionIndex, dimensionSize);
  1071. } else {
  1072. /*nonreversible simple array*/
  1073. ret |= encodeJsonArray(ctx, src->data, src->arrayLength, src->type);
  1074. }
  1075. }
  1076. ret |= writeJsonObjEnd(ctx);
  1077. return ret;
  1078. }
  1079. /* DataValue */
  1080. ENCODE_JSON(DataValue) {
  1081. if(!src->hasServerPicoseconds && !src->hasServerTimestamp &&
  1082. !src->hasSourcePicoseconds && !src->hasSourceTimestamp &&
  1083. !src->hasStatus && !src->hasValue) {
  1084. return writeJsonNull(ctx); /*no element, encode as null*/
  1085. }
  1086. status ret = UA_STATUSCODE_GOOD;
  1087. ret |= writeJsonObjStart(ctx);
  1088. if(src->hasValue) {
  1089. ret |= writeJsonKey(ctx, UA_JSONKEY_VALUE);
  1090. ret |= ENCODE_DIRECT_JSON(&src->value, Variant);
  1091. if(ret != UA_STATUSCODE_GOOD)
  1092. return ret;
  1093. }
  1094. if(src->hasStatus) {
  1095. ret |= writeJsonKey(ctx, UA_JSONKEY_STATUS);
  1096. ret |= ENCODE_DIRECT_JSON(&src->status, StatusCode);
  1097. if(ret != UA_STATUSCODE_GOOD)
  1098. return ret;
  1099. }
  1100. if(src->hasSourceTimestamp) {
  1101. ret |= writeJsonKey(ctx, UA_JSONKEY_SOURCETIMESTAMP);
  1102. ret |= ENCODE_DIRECT_JSON(&src->sourceTimestamp, DateTime);
  1103. if(ret != UA_STATUSCODE_GOOD)
  1104. return ret;
  1105. }
  1106. if(src->hasSourcePicoseconds) {
  1107. ret |= writeJsonKey(ctx, UA_JSONKEY_SOURCEPICOSECONDS);
  1108. ret |= ENCODE_DIRECT_JSON(&src->sourcePicoseconds, UInt16);
  1109. if(ret != UA_STATUSCODE_GOOD)
  1110. return ret;
  1111. }
  1112. if(src->hasServerTimestamp) {
  1113. ret |= writeJsonKey(ctx, UA_JSONKEY_SERVERTIMESTAMP);
  1114. ret |= ENCODE_DIRECT_JSON(&src->serverTimestamp, DateTime);
  1115. if(ret != UA_STATUSCODE_GOOD)
  1116. return ret;
  1117. }
  1118. if(src->hasServerPicoseconds) {
  1119. ret |= writeJsonKey(ctx, UA_JSONKEY_SERVERPICOSECONDS);
  1120. ret |= ENCODE_DIRECT_JSON(&src->serverPicoseconds, UInt16);
  1121. if(ret != UA_STATUSCODE_GOOD)
  1122. return ret;
  1123. }
  1124. ret |= writeJsonObjEnd(ctx);
  1125. return ret;
  1126. }
  1127. /* DiagnosticInfo */
  1128. ENCODE_JSON(DiagnosticInfo) {
  1129. status ret = UA_STATUSCODE_GOOD;
  1130. if(!src->hasSymbolicId && !src->hasNamespaceUri && !src->hasLocalizedText &&
  1131. !src->hasLocale && !src->hasAdditionalInfo && !src->hasInnerDiagnosticInfo &&
  1132. !src->hasInnerStatusCode) {
  1133. return writeJsonNull(ctx); /*no element present, encode as null.*/
  1134. }
  1135. ret |= writeJsonObjStart(ctx);
  1136. if(src->hasSymbolicId) {
  1137. ret |= writeJsonKey(ctx, UA_JSONKEY_SYMBOLICID);
  1138. ret |= ENCODE_DIRECT_JSON(&src->symbolicId, UInt32);
  1139. if(ret != UA_STATUSCODE_GOOD)
  1140. return ret;
  1141. }
  1142. if(src->hasNamespaceUri) {
  1143. ret |= writeJsonKey(ctx, UA_JSONKEY_NAMESPACEURI);
  1144. ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, UInt32);
  1145. if(ret != UA_STATUSCODE_GOOD)
  1146. return ret;
  1147. }
  1148. if(src->hasLocalizedText) {
  1149. ret |= writeJsonKey(ctx, UA_JSONKEY_LOCALIZEDTEXT);
  1150. ret |= ENCODE_DIRECT_JSON(&src->localizedText, UInt32);
  1151. if(ret != UA_STATUSCODE_GOOD)
  1152. return ret;
  1153. }
  1154. if(src->hasLocale) {
  1155. ret |= writeJsonKey(ctx, UA_JSONKEY_LOCALE);
  1156. ret |= ENCODE_DIRECT_JSON(&src->locale, UInt32);
  1157. if(ret != UA_STATUSCODE_GOOD)
  1158. return ret;
  1159. }
  1160. if(src->hasAdditionalInfo) {
  1161. ret |= writeJsonKey(ctx, UA_JSONKEY_ADDITIONALINFO);
  1162. ret |= ENCODE_DIRECT_JSON(&src->additionalInfo, String);
  1163. if(ret != UA_STATUSCODE_GOOD)
  1164. return ret;
  1165. }
  1166. if(src->hasInnerStatusCode) {
  1167. ret |= writeJsonKey(ctx, UA_JSONKEY_INNERSTATUSCODE);
  1168. ret |= ENCODE_DIRECT_JSON(&src->innerStatusCode, StatusCode);
  1169. if(ret != UA_STATUSCODE_GOOD)
  1170. return ret;
  1171. }
  1172. if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
  1173. ret |= writeJsonKey(ctx, UA_JSONKEY_INNERDIAGNOSTICINFO);
  1174. /* Check recursion depth in encodeJsonInternal */
  1175. ret |= encodeJsonInternal(src->innerDiagnosticInfo, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx);
  1176. if(ret != UA_STATUSCODE_GOOD)
  1177. return ret;
  1178. }
  1179. ret |= writeJsonObjEnd(ctx);
  1180. return ret;
  1181. }
  1182. const encodeJsonSignature encodeJsonJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  1183. (encodeJsonSignature) Boolean_encodeJson,
  1184. (encodeJsonSignature) SByte_encodeJson, /* SByte */
  1185. (encodeJsonSignature) Byte_encodeJson,
  1186. (encodeJsonSignature) Int16_encodeJson, /* Int16 */
  1187. (encodeJsonSignature) UInt16_encodeJson,
  1188. (encodeJsonSignature) Int32_encodeJson, /* Int32 */
  1189. (encodeJsonSignature) UInt32_encodeJson,
  1190. (encodeJsonSignature) Int64_encodeJson, /* Int64 */
  1191. (encodeJsonSignature) UInt64_encodeJson,
  1192. (encodeJsonSignature) Float_encodeJson,
  1193. (encodeJsonSignature) Double_encodeJson,
  1194. (encodeJsonSignature) String_encodeJson,
  1195. (encodeJsonSignature) DateTime_encodeJson, /* DateTime */
  1196. (encodeJsonSignature) Guid_encodeJson,
  1197. (encodeJsonSignature) ByteString_encodeJson, /* ByteString */
  1198. (encodeJsonSignature) String_encodeJson, /* XmlElement */
  1199. (encodeJsonSignature) NodeId_encodeJson,
  1200. (encodeJsonSignature) ExpandedNodeId_encodeJson,
  1201. (encodeJsonSignature) StatusCode_encodeJson, /* StatusCode */
  1202. (encodeJsonSignature) QualifiedName_encodeJson, /* QualifiedName */
  1203. (encodeJsonSignature) LocalizedText_encodeJson,
  1204. (encodeJsonSignature) ExtensionObject_encodeJson,
  1205. (encodeJsonSignature) DataValue_encodeJson,
  1206. (encodeJsonSignature) Variant_encodeJson,
  1207. (encodeJsonSignature) DiagnosticInfo_encodeJson,
  1208. (encodeJsonSignature) encodeJsonInternal,
  1209. };
  1210. status
  1211. encodeJsonInternal(const void *src, const UA_DataType *type, CtxJson *ctx) {
  1212. /* Check the recursion limit */
  1213. if(ctx->depth > UA_JSON_ENCODING_MAX_RECURSION)
  1214. return UA_STATUSCODE_BADENCODINGERROR;
  1215. ctx->depth++;
  1216. status ret = UA_STATUSCODE_GOOD;
  1217. if(!type->builtin)
  1218. ret |= writeJsonObjStart(ctx);
  1219. uintptr_t ptr = (uintptr_t) src;
  1220. u8 membersSize = type->membersSize;
  1221. const UA_DataType * typelists[2] = {UA_TYPES, &type[-type->typeIndex]};
  1222. for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
  1223. const UA_DataTypeMember *member = &type->members[i];
  1224. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1225. if(member->memberName != NULL && *member->memberName != 0)
  1226. ret |= writeJsonKey(ctx, member->memberName);
  1227. if(!member->isArray) {
  1228. ptr += member->padding;
  1229. size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  1230. size_t memSize = membertype->memSize;
  1231. ret = encodeJsonJumpTable[encode_index]((const void*) ptr, membertype, ctx);
  1232. ptr += memSize;
  1233. } else {
  1234. ptr += member->padding;
  1235. const size_t length = *((const size_t*) ptr);
  1236. ptr += sizeof (size_t);
  1237. ret = encodeJsonArray(ctx, *(void * const *) ptr, length, membertype);
  1238. ptr += sizeof (void*);
  1239. }
  1240. }
  1241. if(!type->builtin)
  1242. ret |= writeJsonObjEnd(ctx);
  1243. ctx->depth--;
  1244. return ret;
  1245. }
  1246. status UA_FUNC_ATTR_WARN_UNUSED_RESULT
  1247. UA_encodeJson(const void *src, const UA_DataType *type,
  1248. u8 **bufPos, const u8 **bufEnd, UA_String *namespaces,
  1249. size_t namespaceSize, UA_String *serverUris,
  1250. size_t serverUriSize, UA_Boolean useReversible) {
  1251. if(!src || !type)
  1252. return UA_STATUSCODE_BADINTERNALERROR;
  1253. /* Set up the context */
  1254. CtxJson ctx;
  1255. memset(&ctx, 0, sizeof(ctx));
  1256. ctx.pos = *bufPos;
  1257. ctx.end = *bufEnd;
  1258. ctx.depth = 0;
  1259. ctx.namespaces = namespaces;
  1260. ctx.namespacesSize = namespaceSize;
  1261. ctx.serverUris = serverUris;
  1262. ctx.serverUrisSize = serverUriSize;
  1263. ctx.useReversible = useReversible;
  1264. ctx.calcOnly = false;
  1265. /* Encode */
  1266. status ret = encodeJsonInternal(src, type, &ctx);
  1267. *bufPos = ctx.pos;
  1268. *bufEnd = ctx.end;
  1269. return ret;
  1270. }
  1271. /************/
  1272. /* CalcSize */
  1273. /************/
  1274. size_t
  1275. UA_calcSizeJson(const void *src, const UA_DataType *type,
  1276. UA_String *namespaces, size_t namespaceSize,
  1277. UA_String *serverUris, size_t serverUriSize,
  1278. UA_Boolean useReversible) {
  1279. if(!src || !type)
  1280. return UA_STATUSCODE_BADINTERNALERROR;
  1281. /* Set up the context */
  1282. CtxJson ctx;
  1283. memset(&ctx, 0, sizeof(ctx));
  1284. ctx.pos = 0;
  1285. ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX;
  1286. ctx.depth = 0;
  1287. ctx.namespaces = namespaces;
  1288. ctx.namespacesSize = namespaceSize;
  1289. ctx.serverUris = serverUris;
  1290. ctx.serverUrisSize = serverUriSize;
  1291. ctx.useReversible = useReversible;
  1292. ctx.calcOnly = true;
  1293. /* Encode */
  1294. status ret = encodeJsonInternal(src, type, &ctx);
  1295. if(ret != UA_STATUSCODE_GOOD)
  1296. return 0;
  1297. return (size_t)ctx.pos;
  1298. }
  1299. /**********/
  1300. /* Decode */
  1301. /**********/
  1302. /* Macro which gets current size and char pointer of current Token. Needs
  1303. * ParseCtx (parseCtx) and CtxJson (ctx). Does NOT increment index of Token. */
  1304. #define GET_TOKEN \
  1305. size_t tokenSize = (size_t)(parseCtx->tokenArray[parseCtx->index].end - parseCtx->tokenArray[parseCtx->index].start); \
  1306. char* tokenData = (char*)(ctx->pos + parseCtx->tokenArray[parseCtx->index].start);
  1307. #define CHECK_TOKEN_BOUNDS \
  1308. if(parseCtx->index >= parseCtx->tokenCount) \
  1309. return UA_STATUSCODE_BADDECODINGERROR;
  1310. #define CHECK_PRIMITIVE \
  1311. jsmntype_t tokenType = getJsmnType(parseCtx); \
  1312. if(tokenType != JSMN_PRIMITIVE) { \
  1313. return UA_STATUSCODE_BADDECODINGERROR; \
  1314. }
  1315. /* Forward declarations*/
  1316. #define DECODE_JSON(TYPE) static status \
  1317. TYPE##_decodeJson(UA_##TYPE *dst, const UA_DataType *type, \
  1318. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken)
  1319. /* decode without moving the token index */
  1320. #define DECODE_DIRECT_JSON(DST, TYPE) TYPE##_decodeJson((UA_##TYPE*)DST, NULL, ctx, parseCtx, false)
  1321. static status
  1322. Array_decodeJson(void *dst, const UA_DataType *type, CtxJson *ctx,
  1323. ParseCtx *parseCtx, UA_Boolean moveToken);
  1324. static status
  1325. Array_decodeJson_internal(void **dst, const UA_DataType *type,
  1326. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken);
  1327. static status
  1328. Variant_decodeJsonUnwrapExtensionObject(UA_Variant *dst, const UA_DataType *type,
  1329. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken);
  1330. /* Json decode Helper */
  1331. jsmntype_t
  1332. getJsmnType(const ParseCtx *parseCtx) {
  1333. if(parseCtx->index >= parseCtx->tokenCount)
  1334. return JSMN_UNDEFINED;
  1335. return parseCtx->tokenArray[parseCtx->index].type;
  1336. }
  1337. static UA_Boolean
  1338. isJsonTokenNull(const CtxJson *ctx, jsmntok_t *token) {
  1339. if(token->type != JSMN_PRIMITIVE)
  1340. return false;
  1341. char* elem = (char*)(ctx->pos + token->start);
  1342. return (elem[0] == 'n' && elem[1] == 'u' && elem[2] == 'l' && elem[3] == 'l');
  1343. }
  1344. UA_Boolean
  1345. isJsonNull(const CtxJson *ctx, const ParseCtx *parseCtx) {
  1346. if(parseCtx->index >= parseCtx->tokenCount)
  1347. return false;
  1348. if(parseCtx->tokenArray[parseCtx->index].type != JSMN_PRIMITIVE) {
  1349. return false;
  1350. }
  1351. char* elem = (char*)(ctx->pos + parseCtx->tokenArray[parseCtx->index].start);
  1352. return (elem[0] == 'n' && elem[1] == 'u' && elem[2] == 'l' && elem[3] == 'l');
  1353. }
  1354. static UA_SByte jsoneq(const char *json, jsmntok_t *tok, const char *searchKey) {
  1355. /* TODO: necessary?
  1356. if(json == NULL
  1357. || tok == NULL
  1358. || searchKey == NULL) {
  1359. return -1;
  1360. } */
  1361. if(tok->type == JSMN_STRING) {
  1362. if(strlen(searchKey) == (size_t)(tok->end - tok->start) ) {
  1363. if(strncmp(json + tok->start,
  1364. (const char*)searchKey, (size_t)(tok->end - tok->start)) == 0) {
  1365. return 0;
  1366. }
  1367. }
  1368. }
  1369. return -1;
  1370. }
  1371. DECODE_JSON(Boolean) {
  1372. if(isJsonNull(ctx, parseCtx)) {
  1373. /* Any value for a Built-In type that is NULL shall be encoded as the
  1374. * JSON literal ‘null’ if the value is an element of an array. If the
  1375. * NULL value is a field within a Structure or Union, the field shall
  1376. * not be encoded. */
  1377. parseCtx->index++;
  1378. return UA_STATUSCODE_GOOD;
  1379. }
  1380. jsmntype_t tokenType = getJsmnType(parseCtx);
  1381. if(tokenType != JSMN_PRIMITIVE)
  1382. return UA_STATUSCODE_BADDECODINGERROR;
  1383. CHECK_TOKEN_BOUNDS;
  1384. GET_TOKEN;
  1385. if(tokenSize == 4 &&
  1386. tokenData[0] == 't' && tokenData[1] == 'r' &&
  1387. tokenData[2] == 'u' && tokenData[3] == 'e') {
  1388. *dst = true;
  1389. } else if(tokenSize == 5 &&
  1390. tokenData[0] == 'f' && tokenData[1] == 'a' &&
  1391. tokenData[2] == 'l' && tokenData[3] == 's' &&
  1392. tokenData[4] == 'e') {
  1393. *dst = false;
  1394. } else {
  1395. return UA_STATUSCODE_BADDECODINGERROR;
  1396. }
  1397. if(moveToken)
  1398. parseCtx->index++;
  1399. return UA_STATUSCODE_GOOD;
  1400. }
  1401. #ifdef UA_ENABLE_CUSTOM_LIBC
  1402. static UA_StatusCode
  1403. parseUnsignedInteger(char* inputBuffer, size_t sizeOfBuffer,
  1404. UA_UInt64 *destinationOfNumber) {
  1405. UA_UInt64 d = 0;
  1406. atoiUnsigned(inputBuffer, sizeOfBuffer, &d);
  1407. if(!destinationOfNumber)
  1408. return UA_STATUSCODE_BADDECODINGERROR;
  1409. *destinationOfNumber = d;
  1410. return UA_STATUSCODE_GOOD;
  1411. }
  1412. static UA_StatusCode
  1413. parseSignedInteger(char* inputBuffer, size_t sizeOfBuffer,
  1414. UA_Int64 *destinationOfNumber) {
  1415. UA_Int64 d = 0;
  1416. atoiSigned(inputBuffer, sizeOfBuffer, &d);
  1417. if(!destinationOfNumber)
  1418. return UA_STATUSCODE_BADDECODINGERROR;
  1419. *destinationOfNumber = d;
  1420. return UA_STATUSCODE_GOOD;
  1421. }
  1422. #else
  1423. /* Safe strtol variant of unsigned string conversion.
  1424. * Returns UA_STATUSCODE_BADDECODINGERROR in case of overflows.
  1425. * Buffer limit is 20 digits. */
  1426. static UA_StatusCode
  1427. parseUnsignedInteger(char* inputBuffer, size_t sizeOfBuffer,
  1428. UA_UInt64 *destinationOfNumber) {
  1429. /* Check size to avoid huge malicious stack allocation.
  1430. * No UInt64 can have more digits than 20. */
  1431. if(sizeOfBuffer > 20) {
  1432. return UA_STATUSCODE_BADDECODINGERROR;
  1433. }
  1434. /* convert to null terminated string */
  1435. UA_STACKARRAY(char, string, sizeOfBuffer+1);
  1436. memcpy(string, inputBuffer, sizeOfBuffer);
  1437. string[sizeOfBuffer] = 0;
  1438. /* Conversion */
  1439. char *endptr, *str;
  1440. str = string;
  1441. errno = 0; /* To distinguish success/failure after call */
  1442. UA_UInt64 val = strtoull(str, &endptr, 10);
  1443. /* Check for various possible errors */
  1444. if((errno == ERANGE && (val == LLONG_MAX || val == 0))
  1445. || (errno != 0 )) {
  1446. return UA_STATUSCODE_BADDECODINGERROR;
  1447. }
  1448. /* Check if no digits were found */
  1449. if(endptr == str)
  1450. return UA_STATUSCODE_BADDECODINGERROR;
  1451. /* copy to destination */
  1452. *destinationOfNumber = val;
  1453. return UA_STATUSCODE_GOOD;
  1454. }
  1455. /* Safe strtol variant of unsigned string conversion.
  1456. * Returns UA_STATUSCODE_BADDECODINGERROR in case of overflows.
  1457. * Buffer limit is 20 digits. */
  1458. static UA_StatusCode
  1459. parseSignedInteger(char* inputBuffer, size_t sizeOfBuffer,
  1460. UA_Int64 *destinationOfNumber) {
  1461. /* Check size to avoid huge malicious stack allocation.
  1462. * No UInt64 can have more digits than 20. */
  1463. if(sizeOfBuffer > 20)
  1464. return UA_STATUSCODE_BADDECODINGERROR;
  1465. /* convert to null terminated string */
  1466. NULL_TERMINATE(inputBuffer, sizeOfBuffer, string);
  1467. /* Conversion */
  1468. char *endptr, *str;
  1469. str = string;
  1470. errno = 0; /* To distinguish success/failure after call */
  1471. UA_Int64 val = strtoll(str, &endptr, 10);
  1472. /* Check for various possible errors */
  1473. if((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
  1474. || (errno != 0 )) {
  1475. return UA_STATUSCODE_BADDECODINGERROR;
  1476. }
  1477. /* Check if no digits were found */
  1478. if(endptr == str)
  1479. return UA_STATUSCODE_BADDECODINGERROR;
  1480. /* copy to destination */
  1481. *destinationOfNumber = val;
  1482. return UA_STATUSCODE_GOOD;
  1483. }
  1484. #endif
  1485. DECODE_JSON(Byte) {
  1486. CHECK_TOKEN_BOUNDS;
  1487. CHECK_PRIMITIVE;
  1488. GET_TOKEN;
  1489. UA_UInt64 out = 0;
  1490. UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, &out);
  1491. *dst = (UA_Byte)out;
  1492. if(moveToken)
  1493. parseCtx->index++;
  1494. return s;
  1495. }
  1496. DECODE_JSON(UInt16) {
  1497. CHECK_TOKEN_BOUNDS;
  1498. CHECK_PRIMITIVE;
  1499. GET_TOKEN;
  1500. UA_UInt64 out = 0;
  1501. UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, &out);
  1502. *dst = (UA_UInt16)out;
  1503. if(moveToken)
  1504. parseCtx->index++;
  1505. return s;
  1506. }
  1507. DECODE_JSON(UInt32) {
  1508. CHECK_TOKEN_BOUNDS;
  1509. CHECK_PRIMITIVE;
  1510. GET_TOKEN;
  1511. UA_UInt64 out = 0;
  1512. UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, &out);
  1513. *dst = (UA_UInt32)out;
  1514. if(moveToken)
  1515. parseCtx->index++;
  1516. return s;
  1517. }
  1518. DECODE_JSON(UInt64) {
  1519. CHECK_TOKEN_BOUNDS;
  1520. CHECK_PRIMITIVE;
  1521. GET_TOKEN;
  1522. UA_UInt64 out = 0;
  1523. UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, &out);
  1524. *dst = (UA_UInt64)out;
  1525. if(moveToken)
  1526. parseCtx->index++;
  1527. return s;
  1528. }
  1529. DECODE_JSON(SByte) {
  1530. CHECK_TOKEN_BOUNDS;
  1531. CHECK_PRIMITIVE;
  1532. GET_TOKEN;
  1533. UA_Int64 out = 0;
  1534. UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, &out);
  1535. *dst = (UA_SByte)out;
  1536. if(moveToken)
  1537. parseCtx->index++;
  1538. return s;
  1539. }
  1540. DECODE_JSON(Int16) {
  1541. CHECK_TOKEN_BOUNDS;
  1542. CHECK_PRIMITIVE;
  1543. GET_TOKEN;
  1544. UA_Int64 out = 0;
  1545. UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, &out);
  1546. *dst = (UA_Int16)out;
  1547. if(moveToken)
  1548. parseCtx->index++;
  1549. return s;
  1550. }
  1551. DECODE_JSON(Int32) {
  1552. CHECK_TOKEN_BOUNDS;
  1553. CHECK_PRIMITIVE;
  1554. GET_TOKEN;
  1555. UA_Int64 out = 0;
  1556. UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, &out);
  1557. *dst = (UA_Int32)out;
  1558. if(moveToken)
  1559. parseCtx->index++;
  1560. return s;
  1561. }
  1562. DECODE_JSON(Int64) {
  1563. CHECK_TOKEN_BOUNDS;
  1564. CHECK_PRIMITIVE;
  1565. GET_TOKEN;
  1566. UA_Int64 out = 0;
  1567. UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, &out);
  1568. *dst = (UA_Int64)out;
  1569. if(moveToken)
  1570. parseCtx->index++;
  1571. return s;
  1572. }
  1573. static UA_UInt32 hex2int(char ch) {
  1574. if(ch >= '0' && ch <= '9')
  1575. return (UA_UInt32)(ch - '0');
  1576. if(ch >= 'A' && ch <= 'F')
  1577. return (UA_UInt32)(ch - 'A' + 10);
  1578. if(ch >= 'a' && ch <= 'f')
  1579. return (UA_UInt32)(ch - 'a' + 10);
  1580. return 0;
  1581. }
  1582. /* Float
  1583. * Either a JSMN_STRING or JSMN_PRIMITIVE
  1584. */
  1585. DECODE_JSON(Float) {
  1586. CHECK_TOKEN_BOUNDS;
  1587. GET_TOKEN;
  1588. /* https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
  1589. * Maximum digit counts for select IEEE floating-point formats: 149
  1590. * Sanity check. */
  1591. if(tokenSize > 150)
  1592. return UA_STATUSCODE_BADDECODINGERROR;
  1593. jsmntype_t tokenType = getJsmnType(parseCtx);
  1594. if(tokenType == JSMN_STRING) {
  1595. /*It could be a String with Nan, Infinity*/
  1596. if(tokenSize == 8 && memcmp(tokenData, "Infinity", 8) == 0) {
  1597. *dst = (UA_Float)INFINITY;
  1598. return UA_STATUSCODE_GOOD;
  1599. }
  1600. if(tokenSize == 9 && memcmp(tokenData, "-Infinity", 9) == 0) {
  1601. /* workaround an MSVC 2013 issue */
  1602. *dst = (UA_Float)-INFINITY;
  1603. return UA_STATUSCODE_GOOD;
  1604. }
  1605. if(tokenSize == 3 && memcmp(tokenData, "NaN", 3) == 0) {
  1606. *dst = (UA_Float)NAN;
  1607. return UA_STATUSCODE_GOOD;
  1608. }
  1609. if(tokenSize == 4 && memcmp(tokenData, "-NaN", 4) == 0) {
  1610. *dst = (UA_Float)NAN;
  1611. return UA_STATUSCODE_GOOD;
  1612. }
  1613. return UA_STATUSCODE_BADDECODINGERROR;
  1614. }
  1615. if(tokenType != JSMN_PRIMITIVE)
  1616. return UA_STATUSCODE_BADDECODINGERROR;
  1617. /* Null-Terminate for sscanf. */
  1618. UA_STACKARRAY(char, string, tokenSize+1);
  1619. memcpy(string, tokenData, tokenSize);
  1620. string[tokenSize] = 0;
  1621. UA_Float d = 0;
  1622. #ifdef UA_ENABLE_CUSTOM_LIBC
  1623. d = (UA_Float)__floatscan(string, 1, 0);
  1624. #else
  1625. char c = 0;
  1626. /* On success, the function returns the number of variables filled.
  1627. * In the case of an input failure before any data could be successfully read, EOF is returned. */
  1628. int ret = sscanf(string, "%f%c", &d, &c);
  1629. /* Exactly one var must be filled. %c acts as a guard for wrong input which is accepted by sscanf.
  1630. E.g. 1.23.45 is not accepted. */
  1631. if(ret == EOF || (ret != 1))
  1632. return UA_STATUSCODE_BADDECODINGERROR;
  1633. #endif
  1634. *dst = d;
  1635. parseCtx->index++;
  1636. return UA_STATUSCODE_GOOD;
  1637. }
  1638. /* Either a JSMN_STRING or JSMN_PRIMITIVE */
  1639. DECODE_JSON(Double) {
  1640. CHECK_TOKEN_BOUNDS;
  1641. GET_TOKEN;
  1642. /* https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
  1643. * Maximum digit counts for select IEEE floating-point formats: 1074
  1644. * Sanity check.
  1645. */
  1646. if(tokenSize > 1075)
  1647. return UA_STATUSCODE_BADDECODINGERROR;
  1648. jsmntype_t tokenType = getJsmnType(parseCtx);
  1649. if(tokenType == JSMN_STRING) {
  1650. /*It could be a String with Nan, Infinity*/
  1651. if(tokenSize == 8 && memcmp(tokenData, "Infinity", 8) == 0) {
  1652. *dst = INFINITY;
  1653. return UA_STATUSCODE_GOOD;
  1654. }
  1655. if(tokenSize == 9 && memcmp(tokenData, "-Infinity", 9) == 0) {
  1656. /* workaround an MSVC 2013 issue */
  1657. *dst = -INFINITY;
  1658. return UA_STATUSCODE_GOOD;
  1659. }
  1660. if(tokenSize == 3 && memcmp(tokenData, "NaN", 3) == 0) {
  1661. *dst = NAN;
  1662. return UA_STATUSCODE_GOOD;
  1663. }
  1664. if(tokenSize == 4 && memcmp(tokenData, "-NaN", 4) == 0) {
  1665. *dst = NAN;
  1666. return UA_STATUSCODE_GOOD;
  1667. }
  1668. return UA_STATUSCODE_BADDECODINGERROR;
  1669. }
  1670. if(tokenType != JSMN_PRIMITIVE)
  1671. return UA_STATUSCODE_BADDECODINGERROR;
  1672. /* Null-Terminate for sscanf. Should this better be handled on heap? Max
  1673. * 1075 input chars allowed. Not using heap. */
  1674. UA_STACKARRAY(char, string, tokenSize+1);
  1675. memcpy(string, tokenData, tokenSize);
  1676. string[tokenSize] = 0;
  1677. UA_Double d = 0;
  1678. #ifdef UA_ENABLE_CUSTOM_LIBC
  1679. d = (UA_Double)__floatscan(string, 2, 0);
  1680. #else
  1681. char c = 0;
  1682. /* On success, the function returns the number of variables filled.
  1683. * In the case of an input failure before any data could be successfully read, EOF is returned. */
  1684. int ret = sscanf(string, "%lf%c", &d, &c);
  1685. /* Exactly one var must be filled. %c acts as a guard for wrong input which is accepted by sscanf.
  1686. E.g. 1.23.45 is not accepted. */
  1687. if(ret == EOF || (ret != 1))
  1688. return UA_STATUSCODE_BADDECODINGERROR;
  1689. #endif
  1690. *dst = d;
  1691. parseCtx->index++;
  1692. return UA_STATUSCODE_GOOD;
  1693. }
  1694. /*
  1695. Expects 36 chars in format 00000003-0009-000A-0807-060504030201
  1696. | data1| |d2| |d3| |d4| | data4 |
  1697. */
  1698. static UA_Guid UA_Guid_fromChars(const char* chars) {
  1699. UA_Guid dst;
  1700. UA_Guid_init(&dst);
  1701. for(size_t i = 0; i < 8; i++)
  1702. dst.data1 |= (UA_UInt32)(hex2int(chars[i]) << (28 - (i*4)));
  1703. for(size_t i = 0; i < 4; i++) {
  1704. dst.data2 |= (UA_UInt16)(hex2int(chars[9+i]) << (12 - (i*4)));
  1705. dst.data3 |= (UA_UInt16)(hex2int(chars[14+i]) << (12 - (i*4)));
  1706. }
  1707. dst.data4[0] |= (UA_Byte)(hex2int(chars[19]) << 4);
  1708. dst.data4[0] |= (UA_Byte)(hex2int(chars[20]) << 0);
  1709. dst.data4[1] |= (UA_Byte)(hex2int(chars[21]) << 4);
  1710. dst.data4[1] |= (UA_Byte)(hex2int(chars[22]) << 0);
  1711. for(size_t i = 0; i < 6; i++) {
  1712. dst.data4[2+i] |= (UA_Byte)(hex2int(chars[24 + i*2]) << 4);
  1713. dst.data4[2+i] |= (UA_Byte)(hex2int(chars[25 + i*2]) << 0);
  1714. }
  1715. return dst;
  1716. }
  1717. DECODE_JSON(Guid) {
  1718. CHECK_TOKEN_BOUNDS;
  1719. if(isJsonNull(ctx, parseCtx)) {
  1720. parseCtx->index++;
  1721. return UA_STATUSCODE_GOOD;
  1722. }
  1723. jsmntype_t tokenType = getJsmnType(parseCtx);
  1724. if(tokenType != JSMN_STRING && tokenType != JSMN_PRIMITIVE)
  1725. return UA_STATUSCODE_BADDECODINGERROR;
  1726. GET_TOKEN;
  1727. if(tokenSize != 36)
  1728. return UA_STATUSCODE_BADDECODINGERROR;
  1729. /* check if incorrect chars are present */
  1730. for(size_t i = 0; i < tokenSize; i++) {
  1731. if(!(tokenData[i] == '-'
  1732. || (tokenData[i] >= '0' && tokenData[i] <= '9')
  1733. || (tokenData[i] >= 'A' && tokenData[i] <= 'F')
  1734. || (tokenData[i] >= 'a' && tokenData[i] <= 'f'))) {
  1735. return UA_STATUSCODE_BADDECODINGERROR;
  1736. }
  1737. }
  1738. *dst = UA_Guid_fromChars(tokenData);
  1739. if(moveToken)
  1740. parseCtx->index++;
  1741. return UA_STATUSCODE_GOOD;
  1742. }
  1743. DECODE_JSON(String) {
  1744. if(isJsonNull(ctx, parseCtx)) {
  1745. parseCtx->index++;
  1746. return UA_STATUSCODE_GOOD;
  1747. }
  1748. jsmntype_t tokenType = getJsmnType(parseCtx);
  1749. if(tokenType != JSMN_STRING)
  1750. return UA_STATUSCODE_BADDECODINGERROR;
  1751. GET_TOKEN;
  1752. CHECK_TOKEN_BOUNDS;
  1753. /* Empty string? */
  1754. if(tokenSize == 0) {
  1755. dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
  1756. dst->length = 0;
  1757. return UA_STATUSCODE_GOOD;
  1758. }
  1759. /* The actual value is at most of the same length as the source string:
  1760. * - Shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
  1761. * - A single \uXXXX escape (length 6) is converted to at most 3 bytes
  1762. * - Two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair are
  1763. * converted to 4 bytes */
  1764. char *outputBuffer = (char*)UA_malloc(tokenSize);
  1765. if(!outputBuffer)
  1766. return UA_STATUSCODE_BADOUTOFMEMORY;
  1767. const char *p = (char*)tokenData;
  1768. const char *end = (char*)&tokenData[tokenSize];
  1769. char *pos = outputBuffer;
  1770. while(p < end) {
  1771. /* No escaping */
  1772. if(*p != '\\') {
  1773. *(pos++) = *(p++);
  1774. continue;
  1775. }
  1776. /* Escape character */
  1777. p++;
  1778. if(p == end)
  1779. goto cleanup;
  1780. if(*p != 'u') {
  1781. switch(*p) {
  1782. case '"': case '\\': case '/': *pos = *p; break;
  1783. case 'b': *pos = '\b'; break;
  1784. case 'f': *pos = '\f'; break;
  1785. case 'n': *pos = '\n'; break;
  1786. case 'r': *pos = '\r'; break;
  1787. case 't': *pos = '\t'; break;
  1788. default: goto cleanup;
  1789. }
  1790. pos++;
  1791. p++;
  1792. continue;
  1793. }
  1794. /* Unicode */
  1795. if(p + 4 >= end)
  1796. goto cleanup;
  1797. int32_t value = decode_unicode_escape(p);
  1798. if(value < 0)
  1799. goto cleanup;
  1800. p += 5;
  1801. if(0xD800 <= value && value <= 0xDBFF) {
  1802. /* Surrogate pair */
  1803. if(p + 5 >= end)
  1804. goto cleanup;
  1805. if(*p != '\\' || *(p + 1) != 'u')
  1806. goto cleanup;
  1807. int32_t value2 = decode_unicode_escape(p+1);
  1808. if(value2 < 0xDC00 || value2 > 0xDFFF)
  1809. goto cleanup;
  1810. value = ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;
  1811. p += 6;
  1812. } else if(0xDC00 <= value && value <= 0xDFFF) {
  1813. /* Invalid Unicode '\\u%04X' */
  1814. goto cleanup;
  1815. }
  1816. size_t length;
  1817. if(utf8_encode(value, pos, &length))
  1818. goto cleanup;
  1819. pos += length;
  1820. }
  1821. dst->length = (size_t)(pos - outputBuffer);
  1822. if(dst->length > 0) {
  1823. dst->data = (UA_Byte*)outputBuffer;
  1824. } else {
  1825. dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
  1826. UA_free(outputBuffer);
  1827. }
  1828. if(moveToken)
  1829. parseCtx->index++;
  1830. return UA_STATUSCODE_GOOD;
  1831. cleanup:
  1832. UA_free(outputBuffer);
  1833. return UA_STATUSCODE_BADDECODINGERROR;
  1834. }
  1835. DECODE_JSON(ByteString) {
  1836. jsmntype_t tokenType = getJsmnType(parseCtx);
  1837. if(isJsonNull(ctx, parseCtx)) {
  1838. parseCtx->index++;
  1839. return UA_STATUSCODE_GOOD;
  1840. }
  1841. if(tokenType != JSMN_STRING && tokenType != JSMN_PRIMITIVE) {
  1842. return UA_STATUSCODE_BADDECODINGERROR;
  1843. }
  1844. GET_TOKEN;
  1845. /* Empty bytestring? */
  1846. if(tokenSize == 0) {
  1847. dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
  1848. dst->length = 0;
  1849. return UA_STATUSCODE_GOOD;
  1850. }
  1851. int flen;
  1852. unsigned char* unB64 = UA_unbase64(tokenData, (int)tokenSize, &flen);
  1853. if(unB64 == 0)
  1854. return UA_STATUSCODE_BADDECODINGERROR;
  1855. dst->data = (u8*)unB64;
  1856. dst->length = (size_t)flen;
  1857. if(moveToken)
  1858. parseCtx->index++;
  1859. return UA_STATUSCODE_GOOD;
  1860. }
  1861. DECODE_JSON(LocalizedText) {
  1862. if(getJsmnType(parseCtx) != JSMN_OBJECT) {
  1863. if(isJsonNull(ctx, parseCtx)) {
  1864. parseCtx->index++;
  1865. return UA_STATUSCODE_GOOD;
  1866. }
  1867. return UA_STATUSCODE_BADDECODINGERROR;
  1868. }
  1869. DecodeEntry entries[2] = {
  1870. {UA_JSONKEY_LOCALE, &dst->locale, (decodeJsonSignature) String_decodeJson, false, NULL},
  1871. {UA_JSONKEY_TEXT, &dst->text, (decodeJsonSignature) String_decodeJson, false, NULL}
  1872. };
  1873. return decodeFields(ctx, parseCtx, entries, 2, type);
  1874. }
  1875. DECODE_JSON(QualifiedName) {
  1876. if(getJsmnType(parseCtx) != JSMN_OBJECT) {
  1877. if(isJsonNull(ctx, parseCtx)) {
  1878. parseCtx->index++;
  1879. return UA_STATUSCODE_GOOD;
  1880. }
  1881. return UA_STATUSCODE_BADDECODINGERROR;
  1882. }
  1883. DecodeEntry entries[2] = {
  1884. {UA_JSONKEY_NAME, &dst->name, (decodeJsonSignature) String_decodeJson, false, NULL},
  1885. {UA_JSONKEY_URI, &dst->namespaceIndex, (decodeJsonSignature) UInt16_decodeJson, false, NULL}
  1886. };
  1887. return decodeFields(ctx, parseCtx, entries, 2, type);
  1888. }
  1889. /* Function for searching ahead of the current token. Used for retrieving the
  1890. * OPC UA type of a token */
  1891. static status
  1892. searchObjectForKeyRec(const char *searchKey, CtxJson *ctx,
  1893. ParseCtx *parseCtx, size_t *resultIndex, UA_UInt16 depth) {
  1894. UA_StatusCode ret = UA_STATUSCODE_BADNOTFOUND;
  1895. CHECK_TOKEN_BOUNDS;
  1896. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1897. size_t objectCount = (size_t)(parseCtx->tokenArray[parseCtx->index].size);
  1898. parseCtx->index++; /*Object to first Key*/
  1899. CHECK_TOKEN_BOUNDS;
  1900. size_t i;
  1901. for(i = 0; i < objectCount; i++) {
  1902. CHECK_TOKEN_BOUNDS;
  1903. if(depth == 0) { /* we search only on first layer */
  1904. if(jsoneq((char*)ctx->pos, &parseCtx->tokenArray[parseCtx->index], searchKey) == 0) {
  1905. /*found*/
  1906. parseCtx->index++; /*We give back a pointer to the value of the searched key!*/
  1907. *resultIndex = parseCtx->index;
  1908. ret = UA_STATUSCODE_GOOD;
  1909. break;
  1910. }
  1911. }
  1912. parseCtx->index++; /* value */
  1913. CHECK_TOKEN_BOUNDS;
  1914. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1915. ret = searchObjectForKeyRec(searchKey, ctx, parseCtx, resultIndex,
  1916. (UA_UInt16)(depth + 1));
  1917. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1918. ret = searchObjectForKeyRec(searchKey, ctx, parseCtx, resultIndex,
  1919. (UA_UInt16)(depth + 1));
  1920. } else {
  1921. /* Only Primitive or string */
  1922. parseCtx->index++;
  1923. }
  1924. }
  1925. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1926. size_t arraySize = (size_t)(parseCtx->tokenArray[parseCtx->index].size);
  1927. parseCtx->index++; /*Object to first element*/
  1928. CHECK_TOKEN_BOUNDS;
  1929. size_t i;
  1930. for(i = 0; i < arraySize; i++) {
  1931. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1932. ret = searchObjectForKeyRec(searchKey, ctx, parseCtx, resultIndex,
  1933. (UA_UInt16)(depth + 1));
  1934. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1935. ret = searchObjectForKeyRec(searchKey, ctx, parseCtx, resultIndex,
  1936. (UA_UInt16)(depth + 1));
  1937. } else {
  1938. /* Only Primitive or string */
  1939. parseCtx->index++;
  1940. }
  1941. }
  1942. }
  1943. return ret;
  1944. }
  1945. UA_FUNC_ATTR_WARN_UNUSED_RESULT status
  1946. lookAheadForKey(const char* search, CtxJson *ctx,
  1947. ParseCtx *parseCtx, size_t *resultIndex) {
  1948. UA_UInt16 oldIndex = parseCtx->index; /* Save index for later restore */
  1949. UA_UInt16 depth = 0;
  1950. UA_StatusCode ret = searchObjectForKeyRec(search, ctx, parseCtx, resultIndex, depth);
  1951. parseCtx->index = oldIndex; /* Restore index */
  1952. return ret;
  1953. }
  1954. /* Function used to jump over an object which cannot be parsed */
  1955. static status
  1956. jumpOverRec(CtxJson *ctx, ParseCtx *parseCtx,
  1957. size_t *resultIndex, UA_UInt16 depth) {
  1958. UA_StatusCode ret = UA_STATUSCODE_BADDECODINGERROR;
  1959. CHECK_TOKEN_BOUNDS;
  1960. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1961. size_t objectCount = (size_t)(parseCtx->tokenArray[parseCtx->index].size);
  1962. parseCtx->index++; /*Object to first Key*/
  1963. CHECK_TOKEN_BOUNDS;
  1964. size_t i;
  1965. for(i = 0; i < objectCount; i++) {
  1966. CHECK_TOKEN_BOUNDS;
  1967. parseCtx->index++; /*value*/
  1968. CHECK_TOKEN_BOUNDS;
  1969. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1970. jumpOverRec(ctx, parseCtx, resultIndex, (UA_UInt16)(depth + 1));
  1971. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1972. jumpOverRec(ctx, parseCtx, resultIndex, (UA_UInt16)(depth + 1));
  1973. } else {
  1974. /*Only Primitive or string*/
  1975. parseCtx->index++;
  1976. }
  1977. }
  1978. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1979. size_t arraySize = (size_t)(parseCtx->tokenArray[parseCtx->index].size);
  1980. parseCtx->index++; /*Object to first element*/
  1981. CHECK_TOKEN_BOUNDS;
  1982. size_t i;
  1983. for(i = 0; i < arraySize; i++) {
  1984. if(parseCtx->tokenArray[parseCtx->index].type == JSMN_OBJECT) {
  1985. jumpOverRec(ctx, parseCtx, resultIndex, (UA_UInt16)(depth + 1));
  1986. } else if(parseCtx->tokenArray[parseCtx->index].type == JSMN_ARRAY) {
  1987. jumpOverRec(ctx, parseCtx, resultIndex, (UA_UInt16)(depth + 1));
  1988. } else {
  1989. /*Only Primitive or string*/
  1990. parseCtx->index++;
  1991. }
  1992. }
  1993. }
  1994. return ret;
  1995. }
  1996. static status
  1997. jumpOverObject(CtxJson *ctx, ParseCtx *parseCtx, size_t *resultIndex) {
  1998. UA_UInt16 oldIndex = parseCtx->index; /* Save index for later restore */
  1999. UA_UInt16 depth = 0;
  2000. jumpOverRec(ctx, parseCtx, resultIndex, depth);
  2001. *resultIndex = parseCtx->index;
  2002. parseCtx->index = oldIndex; /* Restore index */
  2003. return UA_STATUSCODE_GOOD;
  2004. }
  2005. static status
  2006. prepareDecodeNodeIdJson(UA_NodeId *dst, CtxJson *ctx, ParseCtx *parseCtx,
  2007. u8 *fieldCount, DecodeEntry *entries) {
  2008. /* possible keys: Id, IdType*/
  2009. /* Id must always be present */
  2010. entries[*fieldCount].fieldName = UA_JSONKEY_ID;
  2011. entries[*fieldCount].found = false;
  2012. /* IdType */
  2013. UA_Boolean hasIdType = false;
  2014. size_t searchResult = 0;
  2015. status ret = lookAheadForKey(UA_JSONKEY_IDTYPE, ctx, parseCtx, &searchResult);
  2016. if(ret == UA_STATUSCODE_GOOD) { /*found*/
  2017. hasIdType = true;
  2018. }
  2019. if(hasIdType) {
  2020. size_t size = (size_t)(parseCtx->tokenArray[searchResult].end -
  2021. parseCtx->tokenArray[searchResult].start);
  2022. if(size < 1) {
  2023. return UA_STATUSCODE_BADDECODINGERROR;
  2024. }
  2025. char *idType = (char*)(ctx->pos + parseCtx->tokenArray[searchResult].start);
  2026. if(idType[0] == '2') {
  2027. dst->identifierType = UA_NODEIDTYPE_GUID;
  2028. entries[*fieldCount].fieldPointer = &dst->identifier.guid;
  2029. entries[*fieldCount].function = (decodeJsonSignature) Guid_decodeJson;
  2030. } else if(idType[0] == '1') {
  2031. dst->identifierType = UA_NODEIDTYPE_STRING;
  2032. entries[*fieldCount].fieldPointer = &dst->identifier.string;
  2033. entries[*fieldCount].function = (decodeJsonSignature) String_decodeJson;
  2034. } else if(idType[0] == '3') {
  2035. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  2036. entries[*fieldCount].fieldPointer = &dst->identifier.byteString;
  2037. entries[*fieldCount].function = (decodeJsonSignature) ByteString_decodeJson;
  2038. } else {
  2039. return UA_STATUSCODE_BADDECODINGERROR;
  2040. }
  2041. /* Id always present */
  2042. (*fieldCount)++;
  2043. entries[*fieldCount].fieldName = UA_JSONKEY_IDTYPE;
  2044. entries[*fieldCount].fieldPointer = NULL;
  2045. entries[*fieldCount].function = NULL;
  2046. entries[*fieldCount].found = false;
  2047. /* IdType */
  2048. (*fieldCount)++;
  2049. } else {
  2050. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  2051. entries[*fieldCount].fieldPointer = &dst->identifier.numeric;
  2052. entries[*fieldCount].function = (decodeJsonSignature) UInt32_decodeJson;
  2053. (*fieldCount)++;
  2054. }
  2055. return UA_STATUSCODE_GOOD;
  2056. }
  2057. DECODE_JSON(NodeId) {
  2058. if(isJsonNull(ctx, parseCtx)) {
  2059. parseCtx->index++;
  2060. return UA_STATUSCODE_GOOD;
  2061. }
  2062. if(getJsmnType(parseCtx) != JSMN_OBJECT)
  2063. return UA_STATUSCODE_BADDECODINGERROR;
  2064. /* NameSpace */
  2065. UA_Boolean hasNamespace = false;
  2066. size_t searchResultNamespace = 0;
  2067. status ret = lookAheadForKey(UA_JSONKEY_NAMESPACE, ctx, parseCtx, &searchResultNamespace);
  2068. if(ret != UA_STATUSCODE_GOOD) {
  2069. dst->namespaceIndex = 0;
  2070. } else {
  2071. hasNamespace = true;
  2072. }
  2073. /* Keep track over number of keys present, incremented if key found */
  2074. u8 fieldCount = 0;
  2075. DecodeEntry entries[3];
  2076. ret = prepareDecodeNodeIdJson(dst, ctx, parseCtx, &fieldCount, entries);
  2077. if(ret != UA_STATUSCODE_GOOD)
  2078. return ret;
  2079. if(hasNamespace) {
  2080. entries[fieldCount].fieldName = UA_JSONKEY_NAMESPACE;
  2081. entries[fieldCount].fieldPointer = &dst->namespaceIndex;
  2082. entries[fieldCount].function = (decodeJsonSignature) UInt16_decodeJson;
  2083. entries[fieldCount].found = false;
  2084. fieldCount++;
  2085. } else {
  2086. dst->namespaceIndex = 0;
  2087. }
  2088. ret = decodeFields(ctx, parseCtx, entries, fieldCount, type);
  2089. return ret;
  2090. }
  2091. DECODE_JSON(ExpandedNodeId) {
  2092. if(isJsonNull(ctx, parseCtx)) {
  2093. parseCtx->index++;
  2094. return UA_STATUSCODE_GOOD;
  2095. }
  2096. if(getJsmnType(parseCtx) != JSMN_OBJECT)
  2097. return UA_STATUSCODE_BADDECODINGERROR;
  2098. /* Keep track over number of keys present, incremented if key found */
  2099. u8 fieldCount = 0;
  2100. /* ServerUri */
  2101. UA_Boolean hasServerUri = false;
  2102. size_t searchResultServerUri = 0;
  2103. status ret = lookAheadForKey(UA_JSONKEY_SERVERURI, ctx, parseCtx, &searchResultServerUri);
  2104. if(ret != UA_STATUSCODE_GOOD) {
  2105. dst->serverIndex = 0;
  2106. } else {
  2107. hasServerUri = true;
  2108. }
  2109. /* NameSpace */
  2110. UA_Boolean hasNamespace = false;
  2111. UA_Boolean isNamespaceString = false;
  2112. size_t searchResultNamespace = 0;
  2113. ret = lookAheadForKey(UA_JSONKEY_NAMESPACE, ctx, parseCtx, &searchResultNamespace);
  2114. if(ret != UA_STATUSCODE_GOOD) {
  2115. dst->namespaceUri = UA_STRING_NULL;
  2116. } else {
  2117. hasNamespace = true;
  2118. jsmntok_t nsToken = parseCtx->tokenArray[searchResultNamespace];
  2119. if(nsToken.type == JSMN_STRING)
  2120. isNamespaceString = true;
  2121. }
  2122. DecodeEntry entries[4];
  2123. ret = prepareDecodeNodeIdJson(&dst->nodeId, ctx, parseCtx, &fieldCount, entries);
  2124. if(ret != UA_STATUSCODE_GOOD)
  2125. return ret;
  2126. if(hasNamespace) {
  2127. entries[fieldCount].fieldName = UA_JSONKEY_NAMESPACE;
  2128. if(isNamespaceString) {
  2129. entries[fieldCount].fieldPointer = &dst->namespaceUri;
  2130. entries[fieldCount].function = (decodeJsonSignature) String_decodeJson;
  2131. } else {
  2132. entries[fieldCount].fieldPointer = &dst->nodeId.namespaceIndex;
  2133. entries[fieldCount].function = (decodeJsonSignature) UInt16_decodeJson;
  2134. }
  2135. entries[fieldCount].found = false;
  2136. fieldCount++;
  2137. }
  2138. if(hasServerUri) {
  2139. entries[fieldCount].fieldName = UA_JSONKEY_SERVERURI;
  2140. entries[fieldCount].fieldPointer = &dst->serverIndex;
  2141. entries[fieldCount].function = (decodeJsonSignature) UInt32_decodeJson;
  2142. entries[fieldCount].found = false;
  2143. fieldCount++;
  2144. } else {
  2145. dst->serverIndex = 0;
  2146. }
  2147. return decodeFields(ctx, parseCtx, entries, fieldCount, type);
  2148. }
  2149. DECODE_JSON(DateTime) {
  2150. if(isJsonNull(ctx, parseCtx)) {
  2151. parseCtx->index++;
  2152. return UA_STATUSCODE_GOOD;
  2153. }
  2154. if(getJsmnType(parseCtx) != JSMN_STRING)
  2155. return UA_STATUSCODE_BADDECODINGERROR;
  2156. GET_TOKEN;
  2157. /* TODO: proper ISO 8601:2004 parsing, musl strptime!*/
  2158. /* DateTime ISO 8601:2004 without milli is 20 Characters, with millis 24 */
  2159. if(tokenSize != 20 && tokenSize != 24) {
  2160. return UA_STATUSCODE_BADDECODINGERROR;
  2161. }
  2162. /* sanity check */
  2163. if(tokenData[4] != '-' || tokenData[7] != '-' || tokenData[10] != 'T' ||
  2164. tokenData[13] != ':' || tokenData[16] != ':' ||
  2165. !(tokenData[19] == 'Z' || tokenData[19] == '.')) {
  2166. return UA_STATUSCODE_BADDECODINGERROR;
  2167. }
  2168. struct mytm dts;
  2169. memset(&dts, 0, sizeof(dts));
  2170. UA_UInt64 year = 0;
  2171. atoiUnsigned(&tokenData[0], 4, &year);
  2172. dts.tm_year = (UA_UInt16)year - 1900;
  2173. UA_UInt64 month = 0;
  2174. atoiUnsigned(&tokenData[5], 2, &month);
  2175. dts.tm_mon = (UA_UInt16)month - 1;
  2176. UA_UInt64 day = 0;
  2177. atoiUnsigned(&tokenData[8], 2, &day);
  2178. dts.tm_mday = (UA_UInt16)day;
  2179. UA_UInt64 hour = 0;
  2180. atoiUnsigned(&tokenData[11], 2, &hour);
  2181. dts.tm_hour = (UA_UInt16)hour;
  2182. UA_UInt64 min = 0;
  2183. atoiUnsigned(&tokenData[14], 2, &min);
  2184. dts.tm_min = (UA_UInt16)min;
  2185. UA_UInt64 sec = 0;
  2186. atoiUnsigned(&tokenData[17], 2, &sec);
  2187. dts.tm_sec = (UA_UInt16)sec;
  2188. UA_UInt64 msec = 0;
  2189. if(tokenSize == 24) {
  2190. atoiUnsigned(&tokenData[20], 3, &msec);
  2191. }
  2192. long long sinceunix = __tm_to_secs(&dts);
  2193. UA_DateTime dt = (UA_DateTime)((UA_UInt64)(sinceunix*UA_DATETIME_SEC +
  2194. UA_DATETIME_UNIX_EPOCH) +
  2195. (UA_UInt64)(UA_DATETIME_MSEC * msec));
  2196. *dst = dt;
  2197. if(moveToken)
  2198. parseCtx->index++;
  2199. return UA_STATUSCODE_GOOD;
  2200. }
  2201. DECODE_JSON(StatusCode) {
  2202. if(isJsonNull(ctx, parseCtx)) {
  2203. parseCtx->index++;
  2204. return UA_STATUSCODE_GOOD;
  2205. }
  2206. status ret = DECODE_DIRECT_JSON(dst, UInt32);
  2207. if(ret != UA_STATUSCODE_GOOD)
  2208. return ret;
  2209. if(moveToken)
  2210. parseCtx->index++;
  2211. return UA_STATUSCODE_GOOD;
  2212. }
  2213. static status
  2214. VariantDimension_decodeJson(void * dst, const UA_DataType *type,
  2215. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken) {
  2216. const UA_DataType *dimType = &UA_TYPES[UA_TYPES_UINT32];
  2217. return Array_decodeJson_internal((void**)dst, dimType, ctx, parseCtx, moveToken);
  2218. }
  2219. DECODE_JSON(Variant) {
  2220. status ret = UA_STATUSCODE_GOOD;
  2221. if(getJsmnType(parseCtx) != JSMN_OBJECT) {
  2222. /* If type is 0 (NULL) the Variant contains a NULL value and the
  2223. * containing JSON object shall be omitted or replaced by the JSON
  2224. * literal ‘null’ (when an element of a JSON array). */
  2225. if(isJsonNull(ctx, parseCtx)) {
  2226. /*set an empty Variant*/
  2227. UA_Variant_init(dst);
  2228. dst->type = NULL;
  2229. parseCtx->index++;
  2230. return UA_STATUSCODE_GOOD;
  2231. }
  2232. return UA_STATUSCODE_BADDECODINGERROR;
  2233. }
  2234. /* First search for the variant type in the json object. */
  2235. size_t searchResultType = 0;
  2236. ret = lookAheadForKey(UA_JSONKEY_TYPE, ctx, parseCtx, &searchResultType);
  2237. if(ret != UA_STATUSCODE_GOOD)
  2238. return UA_STATUSCODE_BADDECODINGERROR;
  2239. size_t size = (size_t)(parseCtx->tokenArray[searchResultType].end - parseCtx->tokenArray[searchResultType].start);
  2240. /* check if size is zero or the type is not a number */
  2241. if(size < 1 || parseCtx->tokenArray[searchResultType].type != JSMN_PRIMITIVE) {
  2242. return UA_STATUSCODE_BADDECODINGERROR;
  2243. }
  2244. /*Parse the type*/
  2245. UA_UInt64 idTypeDecoded = 0;
  2246. char *idTypeEncoded = (char*)(ctx->pos + parseCtx->tokenArray[searchResultType].start);
  2247. status typeDecodeStatus = atoiUnsigned(idTypeEncoded, size, &idTypeDecoded);
  2248. /* value is not a valid number */
  2249. if(typeDecodeStatus != UA_STATUSCODE_GOOD) {
  2250. return typeDecodeStatus;
  2251. }
  2252. /*Set the type, Get the Type by nodeID!*/
  2253. UA_NodeId typeNodeId = UA_NODEID_NUMERIC(0, (UA_UInt32)idTypeDecoded);
  2254. const UA_DataType *bodyType = UA_findDataType(&typeNodeId);
  2255. if(bodyType == NULL) {
  2256. return UA_STATUSCODE_BADDECODINGERROR;
  2257. }
  2258. /*Set the type*/
  2259. dst->type = bodyType;
  2260. /* LookAhead BODY */
  2261. /* Does the variant contain an array? */
  2262. UA_Boolean isArray = false;
  2263. UA_Boolean isBodyNull = false;
  2264. /* Search for body */
  2265. size_t searchResultBody = 0;
  2266. ret = lookAheadForKey(UA_JSONKEY_BODY, ctx, parseCtx, &searchResultBody);
  2267. if(ret == UA_STATUSCODE_GOOD) { /* body found */
  2268. /* get body token */
  2269. jsmntok_t bodyToken = parseCtx->tokenArray[searchResultBody];
  2270. /*BODY is null?*/
  2271. if(isJsonTokenNull(ctx, &bodyToken)) {
  2272. dst->data = NULL;
  2273. isBodyNull = true;
  2274. }
  2275. if(bodyToken.type == JSMN_ARRAY) {
  2276. isArray = true;
  2277. size_t arraySize = 0;
  2278. arraySize = (size_t)parseCtx->tokenArray[searchResultBody].size;
  2279. dst->arrayLength = arraySize;
  2280. }
  2281. } else {
  2282. /*TODO: no body? set value NULL?*/
  2283. return UA_STATUSCODE_BADDECODINGERROR;
  2284. }
  2285. /* LookAhead DIMENSION */
  2286. UA_Boolean hasDimension = false;
  2287. /* Has the variant dimension? */
  2288. size_t searchResultDim = 0;
  2289. ret = lookAheadForKey(UA_JSONKEY_DIMENSION, ctx, parseCtx, &searchResultDim);
  2290. if(ret == UA_STATUSCODE_GOOD) {
  2291. hasDimension = true;
  2292. size_t dimensionSize = 0;
  2293. dimensionSize = (size_t)parseCtx->tokenArray[searchResultDim].size;
  2294. dst->arrayDimensionsSize = dimensionSize;
  2295. }
  2296. /* no array but has dimension. error? */
  2297. if(!isArray && hasDimension)
  2298. return UA_STATUSCODE_BADDECODINGERROR;
  2299. /* Get the datatype of the content. The type must be a builtin data type.
  2300. * All not-builtin types are wrapped in an ExtensionObject. */
  2301. if(bodyType->typeIndex > UA_TYPES_DIAGNOSTICINFO)
  2302. return UA_STATUSCODE_BADDECODINGERROR;
  2303. /* A variant cannot contain a variant. But it can contain an array of
  2304. * variants */
  2305. if(bodyType->typeIndex == UA_TYPES_VARIANT && !isArray)
  2306. return UA_STATUSCODE_BADDECODINGERROR;
  2307. if(isArray) {
  2308. DecodeEntry entries[3] = {
  2309. {UA_JSONKEY_TYPE, NULL, NULL, false, NULL},
  2310. {UA_JSONKEY_BODY, &dst->data, (decodeJsonSignature) Array_decodeJson, false, NULL},
  2311. {UA_JSONKEY_DIMENSION, &dst->arrayDimensions,
  2312. (decodeJsonSignature) VariantDimension_decodeJson, false, NULL}};
  2313. if(!hasDimension) {
  2314. ret = decodeFields(ctx, parseCtx, entries, 2, bodyType); /*use first 2 fields*/
  2315. } else {
  2316. ret = decodeFields(ctx, parseCtx, entries, 3, bodyType); /*use all fields*/
  2317. }
  2318. } else if(bodyType->typeIndex != UA_TYPES_EXTENSIONOBJECT) {
  2319. /* Allocate Memory for Body */
  2320. if(!isBodyNull) {
  2321. dst->data = UA_new(bodyType);
  2322. if(!dst->data)
  2323. return UA_STATUSCODE_BADOUTOFMEMORY;
  2324. }
  2325. DecodeEntry entries[2] = {{UA_JSONKEY_TYPE, NULL, NULL, false, NULL},
  2326. {UA_JSONKEY_BODY, dst->data, (decodeJsonSignature) decodeJsonInternal, false, NULL}};
  2327. ret = decodeFields(ctx, parseCtx, entries, 2, bodyType);
  2328. } else { /* extensionObject */
  2329. DecodeEntry entries[2] = {{UA_JSONKEY_TYPE, NULL, NULL, false, NULL},
  2330. {UA_JSONKEY_BODY, dst,
  2331. (decodeJsonSignature) Variant_decodeJsonUnwrapExtensionObject, false, NULL}};
  2332. ret = decodeFields(ctx, parseCtx, entries, 2, bodyType);
  2333. }
  2334. return ret;
  2335. }
  2336. DECODE_JSON(DataValue) {
  2337. if(getJsmnType(parseCtx) != JSMN_OBJECT) {
  2338. if(isJsonNull(ctx, parseCtx)) {
  2339. dst = NULL;
  2340. parseCtx->index++;
  2341. return UA_STATUSCODE_GOOD;
  2342. }
  2343. return UA_STATUSCODE_BADDECODINGERROR;
  2344. }
  2345. DecodeEntry entries[6] = {
  2346. {UA_JSONKEY_VALUE, &dst->value, (decodeJsonSignature) Variant_decodeJson, false, NULL},
  2347. {UA_JSONKEY_STATUS, &dst->status, (decodeJsonSignature) StatusCode_decodeJson, false, NULL},
  2348. {UA_JSONKEY_SOURCETIMESTAMP, &dst->sourceTimestamp, (decodeJsonSignature) DateTime_decodeJson, false, NULL},
  2349. {UA_JSONKEY_SOURCEPICOSECONDS, &dst->sourcePicoseconds, (decodeJsonSignature) UInt16_decodeJson, false, NULL},
  2350. {UA_JSONKEY_SERVERTIMESTAMP, &dst->serverTimestamp, (decodeJsonSignature) DateTime_decodeJson, false, NULL},
  2351. {UA_JSONKEY_SERVERPICOSECONDS, &dst->serverPicoseconds, (decodeJsonSignature) UInt16_decodeJson, false, NULL}};
  2352. status ret = decodeFields(ctx, parseCtx, entries, 6, type);
  2353. dst->hasValue = entries[0].found; dst->hasStatus = entries[1].found;
  2354. dst->hasSourceTimestamp = entries[2].found; dst->hasSourcePicoseconds = entries[3].found;
  2355. dst->hasServerTimestamp = entries[4].found; dst->hasServerPicoseconds = entries[5].found;
  2356. return ret;
  2357. }
  2358. DECODE_JSON(ExtensionObject) {
  2359. if(isJsonNull(ctx, parseCtx)) {
  2360. /* If the Body is empty, the ExtensionObject is NULL and is omitted or
  2361. * encoded as a JSON null. */
  2362. parseCtx->index++;
  2363. return UA_STATUSCODE_GOOD;
  2364. }
  2365. if(getJsmnType(parseCtx) != JSMN_OBJECT)
  2366. return UA_STATUSCODE_BADDECODINGERROR;
  2367. /* Search for Encoding */
  2368. size_t searchEncodingResult = 0;
  2369. status ret = lookAheadForKey(UA_JSONKEY_ENCODING, ctx, parseCtx, &searchEncodingResult);
  2370. /* If no encoding found it is structure encoding */
  2371. if(ret != UA_STATUSCODE_GOOD) {
  2372. UA_NodeId typeId;
  2373. UA_NodeId_init(&typeId);
  2374. size_t searchTypeIdResult = 0;
  2375. ret = lookAheadForKey(UA_JSONKEY_TYPEID, ctx, parseCtx, &searchTypeIdResult);
  2376. if(ret != UA_STATUSCODE_GOOD) {
  2377. /* TYPEID not found, abort */
  2378. return UA_STATUSCODE_BADENCODINGERROR;
  2379. }
  2380. /* parse the nodeid */
  2381. /*for restore*/
  2382. UA_UInt16 index = parseCtx->index;
  2383. parseCtx->index = (UA_UInt16)searchTypeIdResult;
  2384. ret = NodeId_decodeJson(&typeId, &UA_TYPES[UA_TYPES_NODEID], ctx, parseCtx, true);
  2385. if(ret != UA_STATUSCODE_GOOD)
  2386. return ret;
  2387. /*restore*/
  2388. parseCtx->index = index;
  2389. const UA_DataType *typeOfBody = UA_findDataType(&typeId);
  2390. if(!typeOfBody) {
  2391. /*dont decode body: 1. save as bytestring, 2. jump over*/
  2392. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  2393. UA_NodeId_copy(&typeId, &dst->content.encoded.typeId);
  2394. /*Check if Object in Extentionobject*/
  2395. if(getJsmnType(parseCtx) != JSMN_OBJECT) {
  2396. UA_NodeId_deleteMembers(&typeId);
  2397. return UA_STATUSCODE_BADDECODINGERROR;
  2398. }
  2399. /*Search for Body to save*/
  2400. size_t searchBodyResult = 0;
  2401. ret = lookAheadForKey(UA_JSONKEY_BODY, ctx, parseCtx, &searchBodyResult);
  2402. if(ret != UA_STATUSCODE_GOOD) {
  2403. /*No Body*/
  2404. UA_NodeId_deleteMembers(&typeId);
  2405. return UA_STATUSCODE_BADDECODINGERROR;
  2406. }
  2407. if(searchBodyResult >= (size_t)parseCtx->tokenCount) {
  2408. /*index not in Tokenarray*/
  2409. UA_NodeId_deleteMembers(&typeId);
  2410. return UA_STATUSCODE_BADDECODINGERROR;
  2411. }
  2412. /* Get the size of the Object as a string, not the Object key count! */
  2413. UA_Int64 sizeOfJsonString =(parseCtx->tokenArray[searchBodyResult].end -
  2414. parseCtx->tokenArray[searchBodyResult].start);
  2415. char* bodyJsonString = (char*)(ctx->pos + parseCtx->tokenArray[searchBodyResult].start);
  2416. if(sizeOfJsonString <= 0) {
  2417. UA_NodeId_deleteMembers(&typeId);
  2418. return UA_STATUSCODE_BADDECODINGERROR;
  2419. }
  2420. /* Save encoded as bytestring. */
  2421. ret = UA_ByteString_allocBuffer(&dst->content.encoded.body, (size_t)sizeOfJsonString);
  2422. if(ret != UA_STATUSCODE_GOOD) {
  2423. UA_NodeId_deleteMembers(&typeId);
  2424. return ret;
  2425. }
  2426. memcpy(dst->content.encoded.body.data, bodyJsonString, (size_t)sizeOfJsonString);
  2427. size_t tokenAfteExtensionObject = 0;
  2428. jumpOverObject(ctx, parseCtx, &tokenAfteExtensionObject);
  2429. if(tokenAfteExtensionObject == 0) {
  2430. /*next object token not found*/
  2431. UA_NodeId_deleteMembers(&typeId);
  2432. UA_ByteString_deleteMembers(&dst->content.encoded.body);
  2433. return UA_STATUSCODE_BADDECODINGERROR;
  2434. }
  2435. parseCtx->index = (UA_UInt16)tokenAfteExtensionObject;
  2436. return UA_STATUSCODE_GOOD;
  2437. }
  2438. /*Type id not used anymore, typeOfBody has type*/
  2439. UA_NodeId_deleteMembers(&typeId);
  2440. /*Set Found Type*/
  2441. dst->content.decoded.type = typeOfBody;
  2442. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  2443. if(searchTypeIdResult != 0) {
  2444. dst->content.decoded.data = UA_new(typeOfBody);
  2445. if(!dst->content.decoded.data)
  2446. return UA_STATUSCODE_BADOUTOFMEMORY;
  2447. size_t decode_index = typeOfBody->builtin ? typeOfBody->typeIndex : UA_BUILTIN_TYPES_COUNT;
  2448. UA_NodeId typeId_dummy;
  2449. DecodeEntry entries[2] = {
  2450. {UA_JSONKEY_TYPEID, &typeId_dummy, (decodeJsonSignature) NodeId_decodeJson, false, NULL},
  2451. {UA_JSONKEY_BODY, dst->content.decoded.data, (decodeJsonSignature) decodeJsonJumpTable[decode_index], false, NULL}
  2452. };
  2453. return decodeFields(ctx, parseCtx, entries, 2, typeOfBody);
  2454. } else {
  2455. return UA_STATUSCODE_BADDECODINGERROR;
  2456. }
  2457. } else { /* UA_JSONKEY_ENCODING found */
  2458. /*Parse the encoding*/
  2459. UA_UInt64 encoding = 0;
  2460. char *extObjEncoding = (char*)(ctx->pos + parseCtx->tokenArray[searchEncodingResult].start);
  2461. size_t size = (size_t)(parseCtx->tokenArray[searchEncodingResult].end - parseCtx->tokenArray[searchEncodingResult].start);
  2462. atoiUnsigned(extObjEncoding, size, &encoding);
  2463. if(encoding == 1) {
  2464. /* BYTESTRING in Json Body */
  2465. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  2466. UA_UInt16 encodingTypeJson;
  2467. DecodeEntry entries[3] = {
  2468. {UA_JSONKEY_ENCODING, &encodingTypeJson, (decodeJsonSignature) UInt16_decodeJson, false, NULL},
  2469. {UA_JSONKEY_BODY, &dst->content.encoded.body, (decodeJsonSignature) String_decodeJson, false, NULL},
  2470. {UA_JSONKEY_TYPEID, &dst->content.encoded.typeId, (decodeJsonSignature) NodeId_decodeJson, false, NULL}
  2471. };
  2472. return decodeFields(ctx, parseCtx, entries, 3, type);
  2473. } else if(encoding == 2) {
  2474. /* XmlElement in Json Body */
  2475. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_XML;
  2476. UA_UInt16 encodingTypeJson;
  2477. DecodeEntry entries[3] = {
  2478. {UA_JSONKEY_ENCODING, &encodingTypeJson, (decodeJsonSignature) UInt16_decodeJson, false, NULL},
  2479. {UA_JSONKEY_BODY, &dst->content.encoded.body, (decodeJsonSignature) String_decodeJson, false, NULL},
  2480. {UA_JSONKEY_TYPEID, &dst->content.encoded.typeId, (decodeJsonSignature) NodeId_decodeJson, false, NULL}
  2481. };
  2482. return decodeFields(ctx, parseCtx, entries, 3, type);
  2483. } else {
  2484. return UA_STATUSCODE_BADDECODINGERROR;
  2485. }
  2486. }
  2487. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  2488. }
  2489. static status
  2490. Variant_decodeJsonUnwrapExtensionObject(UA_Variant *dst, const UA_DataType *type,
  2491. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken) {
  2492. /*EXTENSIONOBJECT POSITION!*/
  2493. UA_UInt16 old_index = parseCtx->index;
  2494. UA_Boolean typeIdFound = false;
  2495. /* Decode the DataType */
  2496. UA_NodeId typeId;
  2497. UA_NodeId_init(&typeId);
  2498. size_t searchTypeIdResult = 0;
  2499. status ret = lookAheadForKey(UA_JSONKEY_TYPEID, ctx, parseCtx, &searchTypeIdResult);
  2500. if(ret != UA_STATUSCODE_GOOD) {
  2501. /*No Typeid found*/
  2502. typeIdFound = false;
  2503. /*return UA_STATUSCODE_BADDECODINGERROR;*/
  2504. } else {
  2505. typeIdFound = true;
  2506. /* parse the nodeid */
  2507. parseCtx->index = (UA_UInt16)searchTypeIdResult;
  2508. ret = NodeId_decodeJson(&typeId, &UA_TYPES[UA_TYPES_NODEID], ctx, parseCtx, true);
  2509. if(ret != UA_STATUSCODE_GOOD) {
  2510. UA_NodeId_deleteMembers(&typeId);
  2511. return ret;
  2512. }
  2513. /*restore index, ExtensionObject position*/
  2514. parseCtx->index = old_index;
  2515. }
  2516. /* ---Decode the EncodingByte--- */
  2517. if(!typeIdFound)
  2518. return UA_STATUSCODE_BADDECODINGERROR;
  2519. UA_Boolean encodingFound = false;
  2520. /*Search for Encoding*/
  2521. size_t searchEncodingResult = 0;
  2522. ret = lookAheadForKey(UA_JSONKEY_ENCODING, ctx, parseCtx, &searchEncodingResult);
  2523. UA_UInt64 encoding = 0;
  2524. /*If no encoding found it is Structure encoding*/
  2525. if(ret == UA_STATUSCODE_GOOD) { /*FOUND*/
  2526. encodingFound = true;
  2527. char *extObjEncoding = (char*)(ctx->pos + parseCtx->tokenArray[searchEncodingResult].start);
  2528. size_t size = (size_t)(parseCtx->tokenArray[searchEncodingResult].end
  2529. - parseCtx->tokenArray[searchEncodingResult].start);
  2530. atoiUnsigned(extObjEncoding, size, &encoding);
  2531. }
  2532. const UA_DataType *typeOfBody = UA_findDataType(&typeId);
  2533. if(encoding == 0 || typeOfBody != NULL) {
  2534. /*This value is 0 if the body is Structure encoded as a JSON object (see 5.4.6).*/
  2535. /* Found a valid type and it is structure encoded so it can be unwrapped */
  2536. dst->type = typeOfBody;
  2537. /* Allocate memory for type*/
  2538. dst->data = UA_new(dst->type);
  2539. if(!dst->data) {
  2540. UA_NodeId_deleteMembers(&typeId);
  2541. return UA_STATUSCODE_BADOUTOFMEMORY;
  2542. }
  2543. /* Decode the content */
  2544. size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  2545. UA_NodeId nodeIddummy;
  2546. DecodeEntry entries[3] =
  2547. {
  2548. {UA_JSONKEY_TYPEID, &nodeIddummy, (decodeJsonSignature) NodeId_decodeJson, false, NULL},
  2549. {UA_JSONKEY_BODY, dst->data, (decodeJsonSignature) decodeJsonJumpTable[decode_index], false, NULL},
  2550. {UA_JSONKEY_ENCODING, NULL, NULL, false, NULL}};
  2551. ret = decodeFields(ctx, parseCtx, entries, encodingFound ? 3:2, typeOfBody);
  2552. if(ret != UA_STATUSCODE_GOOD) {
  2553. UA_free(dst->data);
  2554. }
  2555. } else if(encoding == 1 || encoding == 2 || typeOfBody == NULL) {
  2556. UA_NodeId_deleteMembers(&typeId);
  2557. /* decode as ExtensionObject */
  2558. dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
  2559. /* Allocate memory for extensionobject*/
  2560. dst->data = UA_new(dst->type);
  2561. if(!dst->data)
  2562. return UA_STATUSCODE_BADOUTOFMEMORY;
  2563. /* decode: Does not move tokenindex. */
  2564. ret = DECODE_DIRECT_JSON(dst->data, ExtensionObject);
  2565. if(ret != UA_STATUSCODE_GOOD)
  2566. UA_free(dst->data);
  2567. } else {
  2568. /*no recognized encoding type*/
  2569. return UA_STATUSCODE_BADDECODINGERROR;
  2570. }
  2571. return ret;
  2572. }
  2573. status DiagnosticInfoInner_decodeJson(void* dst, const UA_DataType* type,
  2574. CtxJson* ctx, ParseCtx* parseCtx, UA_Boolean moveToken);
  2575. DECODE_JSON(DiagnosticInfo) {
  2576. if(isJsonNull(ctx, parseCtx)) {
  2577. parseCtx->index++;
  2578. return UA_STATUSCODE_GOOD;
  2579. }
  2580. if(getJsmnType(parseCtx) != JSMN_OBJECT)
  2581. return UA_STATUSCODE_BADDECODINGERROR;
  2582. DecodeEntry entries[7] = {
  2583. {UA_JSONKEY_SYMBOLICID, &dst->symbolicId, (decodeJsonSignature) Int32_decodeJson, false, NULL},
  2584. {UA_JSONKEY_NAMESPACEURI, &dst->namespaceUri, (decodeJsonSignature) Int32_decodeJson, false, NULL},
  2585. {UA_JSONKEY_LOCALIZEDTEXT, &dst->localizedText, (decodeJsonSignature) Int32_decodeJson, false, NULL},
  2586. {UA_JSONKEY_LOCALE, &dst->locale, (decodeJsonSignature) Int32_decodeJson, false, NULL},
  2587. {UA_JSONKEY_ADDITIONALINFO, &dst->additionalInfo, (decodeJsonSignature) String_decodeJson, false, NULL},
  2588. {UA_JSONKEY_INNERSTATUSCODE, &dst->innerStatusCode, (decodeJsonSignature) StatusCode_decodeJson, false, NULL},
  2589. {UA_JSONKEY_INNERDIAGNOSTICINFO, &dst->innerDiagnosticInfo, (decodeJsonSignature) DiagnosticInfoInner_decodeJson, false, NULL}};
  2590. status ret = decodeFields(ctx, parseCtx, entries, 7, type);
  2591. dst->hasSymbolicId = entries[0].found; dst->hasNamespaceUri = entries[1].found;
  2592. dst->hasLocalizedText = entries[2].found; dst->hasLocale = entries[3].found;
  2593. dst->hasAdditionalInfo = entries[4].found; dst->hasInnerStatusCode = entries[5].found;
  2594. dst->hasInnerDiagnosticInfo = entries[6].found;
  2595. return ret;
  2596. }
  2597. status
  2598. DiagnosticInfoInner_decodeJson(void* dst, const UA_DataType* type,
  2599. CtxJson* ctx, ParseCtx* parseCtx, UA_Boolean moveToken) {
  2600. UA_DiagnosticInfo *inner = (UA_DiagnosticInfo*)UA_calloc(1, sizeof(UA_DiagnosticInfo));
  2601. if(inner == NULL) {
  2602. return UA_STATUSCODE_BADOUTOFMEMORY;
  2603. }
  2604. memcpy(dst, &inner, sizeof(UA_DiagnosticInfo*)); /* Copy new Pointer do dest */
  2605. return DiagnosticInfo_decodeJson(inner, type, ctx, parseCtx, moveToken);
  2606. }
  2607. status
  2608. decodeFields(CtxJson *ctx, ParseCtx *parseCtx, DecodeEntry *entries,
  2609. size_t entryCount, const UA_DataType *type) {
  2610. CHECK_TOKEN_BOUNDS;
  2611. size_t objectCount = (size_t)(parseCtx->tokenArray[parseCtx->index].size);
  2612. status ret = UA_STATUSCODE_GOOD;
  2613. if(entryCount == 1) {
  2614. if(*(entries[0].fieldName) == 0) { /*No MemberName*/
  2615. return entries[0].function(entries[0].fieldPointer, type,
  2616. ctx, parseCtx, true); /*ENCODE DIRECT*/
  2617. }
  2618. } else if(entryCount == 0) {
  2619. return UA_STATUSCODE_BADDECODINGERROR;
  2620. }
  2621. parseCtx->index++; /*go to first key*/
  2622. CHECK_TOKEN_BOUNDS;
  2623. for (size_t currentObjectCount = 0; currentObjectCount < objectCount &&
  2624. parseCtx->index < parseCtx->tokenCount; currentObjectCount++) {
  2625. /* start searching at the index of currentObjectCount */
  2626. for (size_t i = currentObjectCount; i < entryCount + currentObjectCount; i++) {
  2627. /* Search for KEY, if found outer loop will be one less. Best case
  2628. * is objectCount if in order! */
  2629. size_t index = i % entryCount;
  2630. CHECK_TOKEN_BOUNDS;
  2631. if(jsoneq((char*) ctx->pos, &parseCtx->tokenArray[parseCtx->index],
  2632. entries[index].fieldName) != 0)
  2633. continue;
  2634. if(entries[index].found) {
  2635. /*Duplicate Key found, abort.*/
  2636. return UA_STATUSCODE_BADDECODINGERROR;
  2637. }
  2638. entries[index].found = true;
  2639. parseCtx->index++; /*goto value*/
  2640. CHECK_TOKEN_BOUNDS;
  2641. /* Find the data type.
  2642. * TODO: get rid of parameter type. Only forward via DecodeEntry.
  2643. */
  2644. const UA_DataType *membertype = type;
  2645. if(entries[index].type)
  2646. membertype = entries[index].type;
  2647. if(entries[index].function != NULL) {
  2648. ret = entries[index].function(entries[index].fieldPointer,
  2649. membertype, ctx, parseCtx, true); /*Move Token True*/
  2650. if(ret != UA_STATUSCODE_GOOD)
  2651. return ret;
  2652. } else {
  2653. /*overstep single value, this will not work if object or array
  2654. Only used not to double parse pre looked up type, but it has to be overstepped*/
  2655. parseCtx->index++;
  2656. }
  2657. break;
  2658. }
  2659. }
  2660. return ret;
  2661. }
  2662. decodeJsonSignature getDecodeSignature(u8 index) {
  2663. return decodeJsonJumpTable[index];
  2664. }
  2665. const decodeJsonSignature decodeJsonJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
  2666. (decodeJsonSignature)Boolean_decodeJson,
  2667. (decodeJsonSignature)SByte_decodeJson, /* SByte */
  2668. (decodeJsonSignature)Byte_decodeJson,
  2669. (decodeJsonSignature)Int16_decodeJson, /* Int16 */
  2670. (decodeJsonSignature)UInt16_decodeJson,
  2671. (decodeJsonSignature)Int32_decodeJson, /* Int32 */
  2672. (decodeJsonSignature)UInt32_decodeJson,
  2673. (decodeJsonSignature)Int64_decodeJson, /* Int64 */
  2674. (decodeJsonSignature)UInt64_decodeJson,
  2675. (decodeJsonSignature)Float_decodeJson,
  2676. (decodeJsonSignature)Double_decodeJson,
  2677. (decodeJsonSignature)String_decodeJson,
  2678. (decodeJsonSignature)DateTime_decodeJson, /* DateTime */
  2679. (decodeJsonSignature)Guid_decodeJson,
  2680. (decodeJsonSignature)ByteString_decodeJson, /* ByteString */
  2681. (decodeJsonSignature)String_decodeJson, /* XmlElement */
  2682. (decodeJsonSignature)NodeId_decodeJson,
  2683. (decodeJsonSignature)ExpandedNodeId_decodeJson,
  2684. (decodeJsonSignature)StatusCode_decodeJson, /* StatusCode */
  2685. (decodeJsonSignature)QualifiedName_decodeJson, /* QualifiedName */
  2686. (decodeJsonSignature)LocalizedText_decodeJson,
  2687. (decodeJsonSignature)ExtensionObject_decodeJson,
  2688. (decodeJsonSignature)DataValue_decodeJson,
  2689. (decodeJsonSignature)Variant_decodeJson,
  2690. (decodeJsonSignature)DiagnosticInfo_decodeJson,
  2691. (decodeJsonSignature)decodeJsonInternal
  2692. };
  2693. static status
  2694. Array_decodeJson_internal(void **dst, const UA_DataType *type,
  2695. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken) {
  2696. status ret = UA_STATUSCODE_GOOD;
  2697. if(parseCtx->tokenArray[parseCtx->index].type != JSMN_ARRAY)
  2698. return UA_STATUSCODE_BADDECODINGERROR;
  2699. size_t length = (size_t)parseCtx->tokenArray[parseCtx->index].size;
  2700. /* Save the length of the array */
  2701. size_t *p = (size_t*) dst - 1;
  2702. *p = length;
  2703. /* Return early for empty arrays */
  2704. if(length == 0) {
  2705. *dst = UA_EMPTY_ARRAY_SENTINEL;
  2706. return UA_STATUSCODE_GOOD;
  2707. }
  2708. /* Allocate memory */
  2709. *dst = UA_calloc(length, type->memSize);
  2710. if(*dst == NULL)
  2711. return UA_STATUSCODE_BADOUTOFMEMORY;
  2712. parseCtx->index++; /* We go to first Array member!*/
  2713. /* Decode array members */
  2714. uintptr_t ptr = (uintptr_t)*dst;
  2715. size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
  2716. for(size_t i = 0; i < length; ++i) {
  2717. ret = decodeJsonJumpTable[decode_index]((void*)ptr, type, ctx, parseCtx, true);
  2718. if(ret != UA_STATUSCODE_GOOD) {
  2719. UA_Array_delete(*dst, i+1, type);
  2720. *dst = NULL;
  2721. return ret;
  2722. }
  2723. ptr += type->memSize;
  2724. }
  2725. return UA_STATUSCODE_GOOD;
  2726. }
  2727. /*Wrapper for array with valid decodingStructure.*/
  2728. static status
  2729. Array_decodeJson(void * dst, const UA_DataType *type, CtxJson *ctx,
  2730. ParseCtx *parseCtx, UA_Boolean moveToken) {
  2731. return Array_decodeJson_internal((void **)dst, type, ctx, parseCtx, moveToken);
  2732. }
  2733. status
  2734. decodeJsonInternal(void *dst, const UA_DataType *type, CtxJson *ctx,
  2735. ParseCtx *parseCtx, UA_Boolean moveToken) {
  2736. /* Check the recursion limit */
  2737. if(ctx->depth > UA_JSON_ENCODING_MAX_RECURSION)
  2738. return UA_STATUSCODE_BADENCODINGERROR;
  2739. ctx->depth++;
  2740. uintptr_t ptr = (uintptr_t)dst;
  2741. status ret = UA_STATUSCODE_GOOD;
  2742. u8 membersSize = type->membersSize;
  2743. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  2744. UA_STACKARRAY(DecodeEntry, entries, membersSize);
  2745. for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
  2746. const UA_DataTypeMember *member = &type->members[i];
  2747. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  2748. if(!member->isArray) {
  2749. ptr += member->padding;
  2750. size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
  2751. size_t memSize = membertype->memSize;
  2752. /*Setup the decoding functions, field names and destinations*/
  2753. entries[i].fieldName = member->memberName;
  2754. entries[i].fieldPointer = (void*)ptr;
  2755. entries[i].function = decodeJsonJumpTable[fi];
  2756. entries[i].found = false;
  2757. entries[i].type = membertype;
  2758. ptr += memSize;
  2759. } else {
  2760. ptr += member->padding;
  2761. ptr += sizeof(size_t); /* length is filled in Array_decodeJson */
  2762. entries[i].fieldName = member->memberName;
  2763. entries[i].fieldPointer = (void*)ptr;
  2764. entries[i].function = (decodeJsonSignature)Array_decodeJson;
  2765. entries[i].found = false;
  2766. entries[i].type = membertype;
  2767. ptr += sizeof(void*);
  2768. }
  2769. }
  2770. ret = decodeFields(ctx, parseCtx, entries, membersSize, type);
  2771. ctx->depth--;
  2772. return ret;
  2773. }
  2774. status
  2775. tokenize(ParseCtx *parseCtx, CtxJson *ctx, const UA_ByteString *src) {
  2776. /* Set up the context */
  2777. ctx->pos = &src->data[0];
  2778. ctx->end = &src->data[src->length];
  2779. ctx->depth = 0;
  2780. parseCtx->tokenCount = 0;
  2781. parseCtx->index = 0;
  2782. /*Set up tokenizer jsmn*/
  2783. jsmn_parser p;
  2784. jsmn_init(&p);
  2785. parseCtx->tokenCount = (UA_Int32)jsmn_parse(&p, (char*)src->data,
  2786. src->length, parseCtx->tokenArray, TOKENCOUNT);
  2787. if(parseCtx->tokenCount < 0) {
  2788. if(parseCtx->tokenCount == JSMN_ERROR_NOMEM)
  2789. return UA_STATUSCODE_BADOUTOFMEMORY;
  2790. return UA_STATUSCODE_BADDECODINGERROR;
  2791. }
  2792. return UA_STATUSCODE_GOOD;
  2793. }
  2794. status UA_FUNC_ATTR_WARN_UNUSED_RESULT
  2795. UA_decodeJson(const UA_ByteString *src, void *dst, const UA_DataType *type) {
  2796. #ifndef UA_ENABLE_TYPENAMES
  2797. return UA_STATUSCODE_BADNOTSUPPORTED;
  2798. #endif
  2799. if(dst == NULL || src == NULL || type == NULL) {
  2800. return UA_STATUSCODE_BADARGUMENTSMISSING;
  2801. }
  2802. /* Set up the context */
  2803. CtxJson ctx;
  2804. ParseCtx parseCtx;
  2805. parseCtx.tokenArray = (jsmntok_t*)UA_malloc(sizeof(jsmntok_t) * TOKENCOUNT);
  2806. if(!parseCtx.tokenArray)
  2807. return UA_STATUSCODE_BADOUTOFMEMORY;
  2808. status ret = tokenize(&parseCtx, &ctx, src);
  2809. if(ret != UA_STATUSCODE_GOOD)
  2810. goto cleanup;
  2811. /* Assume the top-level element is an object */
  2812. if(parseCtx.tokenCount < 1 || parseCtx.tokenArray[0].type != JSMN_OBJECT) {
  2813. if(parseCtx.tokenCount == 1) {
  2814. if(parseCtx.tokenArray[0].type == JSMN_PRIMITIVE ||
  2815. parseCtx.tokenArray[0].type == JSMN_STRING) {
  2816. /*Only a primitive to parse. Do it directly.*/
  2817. memset(dst, 0, type->memSize); /* Initialize the value */
  2818. ret = decodeJsonInternal(dst, type, &ctx, &parseCtx, true);
  2819. goto cleanup;
  2820. }
  2821. }
  2822. ret = UA_STATUSCODE_BADDECODINGERROR;
  2823. goto cleanup;
  2824. }
  2825. /* Decode */
  2826. memset(dst, 0, type->memSize); /* Initialize the value */
  2827. ret = decodeJsonInternal(dst, type, &ctx, &parseCtx, true);
  2828. cleanup:
  2829. free(parseCtx.tokenArray);
  2830. /* sanity check if all Tokens were processed */
  2831. if(!(parseCtx.index == parseCtx.tokenCount ||
  2832. parseCtx.index == parseCtx.tokenCount-1)) {
  2833. ret = UA_STATUSCODE_BADDECODINGERROR;
  2834. }
  2835. if(ret != UA_STATUSCODE_GOOD)
  2836. UA_deleteMembers(dst, type); /* Clean up */
  2837. return ret;
  2838. }