| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| * |
| * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| * Copyright 2018 (c) Fraunhofer IOSB (Author: Lukas Meling) |
| */ |
| |
| #ifndef UA_TYPES_ENCODING_JSON_H_ |
| #define UA_TYPES_ENCODING_JSON_H_ |
| |
| #include <open62541/types.h> |
| |
| #include "ua_types_encoding_binary.h" |
| #include "ua_types_encoding_json.h" |
| #include "ua_util_internal.h" |
| |
| #include "../deps/jsmn/jsmn.h" |
| |
| _UA_BEGIN_DECLS |
| |
| #define UA_JSON_MAXTOKENCOUNT 1000 |
| |
| size_t |
| UA_calcSizeJson(const void *src, const UA_DataType *type, |
| UA_String *namespaces, size_t namespaceSize, |
| UA_String *serverUris, size_t serverUriSize, |
| UA_Boolean useReversible) UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| |
| UA_StatusCode |
| UA_encodeJson(const void *src, const UA_DataType *type, |
| uint8_t **bufPos, const uint8_t **bufEnd, |
| UA_String *namespaces, size_t namespaceSize, |
| UA_String *serverUris, size_t serverUriSize, |
| UA_Boolean useReversible) UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| |
| UA_StatusCode |
| UA_decodeJson(const UA_ByteString *src, void *dst, |
| const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| |
| /* Interal Definitions |
| * |
| * For future by the PubSub encoding */ |
| |
| #define UA_JSON_ENCODING_MAX_RECURSION 100 |
| typedef struct { |
| uint8_t *pos; |
| const uint8_t *end; |
| |
| uint16_t depth; /* How often did we en-/decoding recurse? */ |
| UA_Boolean commaNeeded[UA_JSON_ENCODING_MAX_RECURSION]; |
| UA_Boolean useReversible; |
| UA_Boolean calcOnly; /* Only compute the length of the decoding */ |
| |
| size_t namespacesSize; |
| UA_String *namespaces; |
| |
| size_t serverUrisSize; |
| UA_String *serverUris; |
| } CtxJson; |
| |
| UA_StatusCode writeJsonObjStart(CtxJson *ctx); |
| UA_StatusCode writeJsonObjElm(CtxJson *ctx, const char *key, |
| const void *value, const UA_DataType *type); |
| UA_StatusCode writeJsonObjEnd(CtxJson *ctx); |
| |
| UA_StatusCode writeJsonArrStart(CtxJson *ctx); |
| UA_StatusCode writeJsonArrElm(CtxJson *ctx, const void *value, |
| const UA_DataType *type); |
| UA_StatusCode writeJsonArrEnd(CtxJson *ctx); |
| |
| UA_StatusCode writeJsonKey(CtxJson *ctx, const char* key); |
| UA_StatusCode writeJsonCommaIfNeeded(CtxJson *ctx); |
| UA_StatusCode writeJsonNull(CtxJson *ctx); |
| |
| /* The encoding length is returned in ctx->pos */ |
| static UA_INLINE UA_StatusCode |
| calcJsonObjStart(CtxJson *ctx) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonObjStart(ctx); |
| } |
| |
| static UA_INLINE UA_StatusCode |
| calcJsonObjElm(CtxJson *ctx, const char *key, |
| const void *value, const UA_DataType *type) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonObjElm(ctx, key, value, type); |
| } |
| |
| static UA_INLINE UA_StatusCode |
| calcJsonObjEnd(CtxJson *ctx) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonObjEnd(ctx); |
| } |
| |
| static UA_INLINE UA_StatusCode |
| calcJsonArrStart(CtxJson *ctx) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonArrStart(ctx); |
| } |
| |
| static UA_INLINE UA_StatusCode |
| calcJsonArrElm(CtxJson *ctx, const void *value, |
| const UA_DataType *type) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonArrElm(ctx, value, type); |
| } |
| |
| static UA_INLINE UA_StatusCode |
| calcJsonArrEnd(CtxJson *ctx) { |
| UA_assert(ctx->calcOnly); |
| return writeJsonArrEnd(ctx); |
| } |
| |
| status |
| encodeJsonInternal(const void *src, const UA_DataType *type, CtxJson *ctx); |
| |
| typedef struct { |
| jsmntok_t *tokenArray; |
| UA_Int32 tokenCount; |
| UA_UInt16 index; |
| |
| /* Additonal data for special cases such as networkmessage/datasetmessage |
| * Currently only used for dataSetWriterIds */ |
| size_t numCustom; |
| void * custom; |
| size_t* currentCustomIndex; |
| } ParseCtx; |
| |
| typedef UA_StatusCode |
| (*encodeJsonSignature)(const void *src, const UA_DataType *type, CtxJson *ctx); |
| |
| typedef UA_StatusCode |
| (*decodeJsonSignature)(void *dst, const UA_DataType *type, CtxJson *ctx, |
| ParseCtx *parseCtx, UA_Boolean moveToken); |
| |
| /* Map for decoding a Json Object. An array of this is passed to the |
| * decodeFields function. If the key "fieldName" is found in the json object |
| * (mark as found and) decode the value with the "function" and write result |
| * into "fieldPointer" (destination). */ |
| typedef struct { |
| const char * fieldName; |
| void * fieldPointer; |
| decodeJsonSignature function; |
| UA_Boolean found; |
| const UA_DataType *type; |
| } DecodeEntry; |
| |
| UA_StatusCode |
| decodeFields(CtxJson *ctx, ParseCtx *parseCtx, |
| DecodeEntry *entries, size_t entryCount, |
| const UA_DataType *type); |
| |
| UA_StatusCode |
| decodeJsonInternal(void *dst, const UA_DataType *type, |
| CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken); |
| |
| /* workaround: TODO generate functions for UA_xxx_decodeJson */ |
| decodeJsonSignature getDecodeSignature(u8 index); |
| UA_StatusCode lookAheadForKey(const char* search, CtxJson *ctx, ParseCtx *parseCtx, size_t *resultIndex); |
| jsmntype_t getJsmnType(const ParseCtx *parseCtx); |
| UA_StatusCode tokenize(ParseCtx *parseCtx, CtxJson *ctx, const UA_ByteString *src); |
| UA_Boolean isJsonNull(const CtxJson *ctx, const ParseCtx *parseCtx); |
| |
| _UA_END_DECLS |
| |
| #endif /* UA_TYPES_ENCODING_JSON_H_ */ |