--- /dev/null
+/** @file\r
+ APIs for JSON operations.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#ifndef JSON_LIB_H_\r
+#define JSON_LIB_H_\r
+\r
+typedef VOID* EDKII_JSON_VALUE;\r
+typedef VOID* EDKII_JSON_ARRAY;\r
+typedef VOID* EDKII_JSON_OBJECT;\r
+\r
+///\r
+/// Map to json_int_t in jansson.h\r
+///\r
+typedef INT64 EDKII_JSON_INT_T; // #JSON_INTEGER_IS_LONG_LONG is set to 1\r
+ // in jansson_Config.h\r
+\r
+///\r
+/// Map to the definitions in jansson.h\r
+/// See below URI for the JSON encoding flags reference.\r
+/// https://jansson.readthedocs.io/en/2.13/apiref.html#encoding\r
+///\r
+#define EDKII_JSON_MAX_INDENT 0x1F\r
+#define EDKII_JSON_INDENT(n) ((n) & EDKII_JSON_MAX_INDENT)\r
+\r
+#define EDKII_JSON_COMPACT 0x20\r
+#define EDKII_JSON_ENSURE_ASCII 0x40\r
+#define EDKII_JSON_SORT_KEYS 0x80\r
+#define EDKII_JSON_PRESERVE_ORDER 0x100\r
+#define EDKII_JSON_ENCODE_ANY 0x200\r
+#define EDKII_JSON_ESCAPE_SLASH 0x400\r
+#define EDKII_JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)\r
+#define EDKII_JSON_EMBED 0x10000\r
+\r
+///\r
+/// Map to the definitions in jansson.h\r
+/// See below URI for the JSON decoding flags reference.\r
+/// https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding\r
+///\r
+#define EDKII_JSON_REJECT_DUPLICATES 0x1\r
+#define EDKII_JSON_DISABLE_EOF_CHECK 0x2\r
+#define EDKII_JSON_DECODE_ANY 0x4\r
+#define EDKII_JSON_DECODE_INT_AS_REAL 0x8\r
+#define EDKII_JSON_ALLOW_NUL 0x10\r
+\r
+#define EDKII_JSON_ARRAY_FOREACH(Array, Index, Value) \\r
+ for(Index = 0; \\r
+ Index < JsonArrayCount(Array) && (Value = JsonArrayGetValue(Array, Index)); \\r
+ Index++)\r
+\r
+///\r
+/// Map to the json_error_t in jansson.h\r
+///\r
+#define EDKII_JSON_ERROR_TEXT_LENGTH 160\r
+#define EDKII_JSON_ERROR_SOURCE_LENGTH 80\r
+typedef struct {\r
+ INTN Line;\r
+ INTN Column;\r
+ INTN Position;\r
+ CHAR8 Source [EDKII_JSON_ERROR_SOURCE_LENGTH];\r
+ CHAR8 Text [EDKII_JSON_ERROR_TEXT_LENGTH];\r
+} EDKII_JSON_ERROR;\r
+\r
+///\r
+/// Map to the json_type in jansson.h\r
+///\r
+typedef enum {\r
+ EdkiiJsonTypeObject,\r
+ EdkiiJsonTypeArray,\r
+ EdkiiJsonTypeString,\r
+ EdkiiJsonTypeInteger,\r
+ EdkiiJsonTypeReal,\r
+ EdkiiJsonTypeTrue,\r
+ EdkiiJsonTypeFalse,\r
+ EdkiiJsonTypeNull\r
+} EDKII_JSON_TYPE;\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON array,\r
+ or NULL on error. Initially, the array is empty.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array\r
+ is failed.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitArray (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON object,\r
+ or NULL on error. Initially, the object is empty.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object\r
+ is failed.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitObject (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON string,\r
+ or NULL on error.\r
+\r
+ The input string must be NULL terminated Ascii format, non-Ascii characters will\r
+ be processed as an error. Unicode characters can also be represented by Ascii string\r
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] String The Ascii string to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON string or NULL. Select a\r
+ Getter API for a specific encoding format.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitAsciiString (\r
+ IN CONST CHAR8 *String\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON string,\r
+ or NULL on error.\r
+\r
+ The input must be a NULL terminated UCS2 format Unicode string.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] String The Unicode string to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON string or NULL. Select a\r
+ Getter API for a specific encoding format.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitUnicodeString (\r
+ IN CHAR16 *String\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON integer,\r
+ or NULL on error.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] Value The integer to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON number or NULL.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitNumber (\r
+ IN INT64 Value\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON boolean,\r
+ or NULL on error.\r
+\r
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.\r
+\r
+ @param[in] Value The boolean value to initialize.\r
+\r
+ @retval The created JSON value which contains a JSON boolean or NULL.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitBoolean (\r
+ IN BOOLEAN Value\r
+ );\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON NULL,\r
+ or NULL on error.\r
+\r
+ NULL JSON value is kept as static value, and no need to do any cleanup work.\r
+\r
+ @retval The created NULL JSON value.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitNull (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ The function is used to decrease the reference count of a JSON value by one, and once\r
+ this reference count drops to zero, the value is destroyed and it can no longer be used.\r
+ If this destroyed value is object type or array type, reference counts for all containing\r
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed\r
+ since they are static values kept in memory.\r
+\r
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still\r
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a\r
+ value is kept for use, its reference count is incremented, and when the value is no longer\r
+ needed, the reference count is decremented. When the reference count drops to zero, there are\r
+ no references left, and the value can be destroyed.\r
+\r
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message\r
+ to inform caller the NULL value is passed in.\r
+\r
+ @param[in] Json The JSON value to be freed. json_decref may return without any\r
+ changes if Json is NULL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+JsonValueFree (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to create a fresh copy of a JSON value, and all child values are deep\r
+ copied in a recursive fashion. It should be called when this JSON value might be modified\r
+ in later use, but the original still wants to be used in somewhere else.\r
+\r
+ Reference counts of the returned root JSON value and all child values will be set to 1, and\r
+ caller needs to cleanup the root value by calling JsonValueFree().\r
+\r
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some\r
+ performance issues, user should avoid unnecessary calls to this function unless it is really\r
+ needed.\r
+\r
+ @param[in] Json The JSON value to be cloned.\r
+\r
+ @retval Return the cloned JSON value, or NULL on error.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueClone (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON array.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON array.\r
+ @retval FALSE The JSON value doesn't contain a JSON array.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsArray (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON object.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON object.\r
+ @retval FALSE The JSON value doesn't contain a JSON object.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsObject (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON Value contains a string, Ascii or\r
+ Unicode format is not differentiated.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON string.\r
+ @retval FALSE The JSON value doesn't contain a JSON string.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsString (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON number.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value is contains JSON number.\r
+ @retval FALSE The JSON value doesn't contain a JSON number.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsNumber (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON boolean.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON boolean.\r
+ @retval FALSE The JSON value doesn't contain a JSON boolean.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsBoolean (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON NULL.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON NULL.\r
+ @retval FALSE The JSON value doesn't contain a JSON NULL.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsNull (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated array in an array type JSON value.\r
+\r
+ Any changes to the returned array will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated array in JSON value or NULL.\r
+\r
+**/\r
+EDKII_JSON_ARRAY\r
+EFIAPI\r
+JsonValueGetArray (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated object in an object type JSON value.\r
+\r
+ Any changes to the returned object will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated object in JSON value or NULL.\r
+\r
+**/\r
+EDKII_JSON_OBJECT\r
+EFIAPI\r
+JsonValueGetObject (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated Ascii string in a string type JSON value.\r
+\r
+ Any changes to the returned string will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Ascii string in JSON value or NULL.\r
+\r
+**/\r
+CONST CHAR8 *\r
+EFIAPI\r
+JsonValueGetAsciiString (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated Unicode string in a string type JSON value.\r
+\r
+ Caller can do any changes to the returned string without any impact to the original JSON\r
+ value, and caller needs to free the returned string using FreePool().\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Unicode string in JSON value or NULL.\r
+\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+JsonValueGetUnicodeString (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated integer in a number type JSON value.\r
+\r
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will\r
+ ASSERT() and return 0.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated number in JSON value.\r
+\r
+**/\r
+INT64\r
+EFIAPI\r
+JsonValueGetNumber (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated boolean in a boolean type JSON value.\r
+\r
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will\r
+ ASSERT() and return FALSE.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated value of JSON boolean.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueGetBoolean (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to retrieve the associated string in a string type JSON value.\r
+\r
+ Any changes to the returned string will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Ascii string in JSON value or NULL on errors.\r
+\r
+**/\r
+CONST CHAR8*\r
+EFIAPI\r
+JsonValueGetString (\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or\r
+ not a JSON object.\r
+\r
+ @param[in] JsonObject The provided JSON object.\r
+\r
+ @retval Return the number of elements in this JSON object or 0.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+JsonObjectSize (\r
+ IN EDKII_JSON_OBJECT JsonObject\r
+ );\r
+\r
+/**\r
+ The function is used to enumerate all keys in a JSON object.\r
+\r
+ Caller should be responsible to free the returned key array reference using\r
+ FreePool(). But contained keys are read only and must not be modified or freed.\r
+\r
+ @param[in] JsonObj The provided JSON object for enumeration.\r
+ @param[out] KeyCount The count of keys in this JSON object.\r
+\r
+ @retval Return an array of the enumerated keys in this JSON object or NULL if\r
+ JsonObj is not an JSON object, key count is zero or on other errors.\r
+\r
+**/\r
+CHAR8**\r
+JsonObjectGetKeys (\r
+ IN EDKII_JSON_OBJECT JsonObj,\r
+ OUT UINTN *KeyCount\r
+ );\r
+\r
+/**\r
+ The function is used to get a JSON value corresponding to the input key from a JSON object.\r
+\r
+ It only returns a reference to this value and any changes on this value will impact the\r
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to\r
+ use.\r
+\r
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when\r
+ Key-Value is not found in this JSON object.\r
+\r
+ @param[in] JsonObj The provided JSON object.\r
+ @param[in] Key The key of the JSON value to be retrieved.\r
+\r
+ @retval Return the corresponding JSON value to key, or NULL on error.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonObjectGetValue (\r
+ IN CONST EDKII_JSON_OBJECT JsonObj,\r
+ IN CONST CHAR8 *Key\r
+ );\r
+\r
+/**\r
+ The function is used to set a JSON value corresponding to the input key from a JSON object,\r
+ and the reference count of this value will be increased by 1.\r
+\r
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for\r
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed\r
+ from this object and thus its' reference count will be decreased by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonObj The provided JSON object.\r
+ @param[in] Key The key of the JSON value to be set.\r
+ @param[in] Json The JSON value to set to this JSON object mapped by key.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonObjectSetValue (\r
+ IN EDKII_JSON_OBJECT JsonObj,\r
+ IN CONST CHAR8 *Key,\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray\r
+ is NULL or not a JSON array.\r
+\r
+ @param[in] JsonArray The provided JSON array.\r
+\r
+ @retval Return the number of elements in this JSON array or 0.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+JsonArrayCount (\r
+ IN EDKII_JSON_ARRAY JsonArray\r
+ );\r
+\r
+/**\r
+ The function is used to return the JSON value in the array at position index. The valid range\r
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.\r
+\r
+ It only returns a reference to this value and any changes on this value will impact the\r
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to\r
+ use.\r
+\r
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.\r
+\r
+ @param[in] JsonArray The provided JSON Array.\r
+\r
+ @retval Return the JSON value located in the Index position or\r
+ NULL if JsonArray is not an array or no items in the array.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonArrayGetValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN UINTN Index\r
+ );\r
+\r
+/**\r
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of\r
+ array by 1. The reference count of this value will be increased by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonArray The provided JSON object.\r
+ @param[in] Json The JSON value to append.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonArrayAppendValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN EDKII_JSON_VALUE Json\r
+ );\r
+\r
+/**\r
+ The function is used to remove a JSON value at position index, shifting the elements after index\r
+ one position towards the start of the array. The reference count of this value will be decreased\r
+ by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonArray The provided JSON array.\r
+ @param[in] Index The Index position before removement.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS The JSON array has been removed at position index.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonArrayRemoveValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN UINTN Index\r
+ );\r
+\r
+/**\r
+ Dump JSON to a buffer.\r
+\r
+ @param[in] JsonValue The provided JSON value.\r
+ @param[in] Flags The Index position before removement. The value\r
+ could be the combination of below flags.\r
+ - EDKII_JSON_INDENT(n)\r
+ - EDKII_JSON_COMPACT\r
+ - EDKII_JSON_ENSURE_ASCII\r
+ - EDKII_JSON_SORT_KEYS\r
+ - EDKII_JSON_PRESERVE_ORDER\r
+ - EDKII_JSON_ENCODE_ANY\r
+ - EDKII_JSON_ESCAPE_SLASH\r
+ - EDKII_JSON_REAL_PRECISION(n)\r
+ - EDKII_JSON_EMBED\r
+ See below URI for the JSON encoding flags reference.\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding\r
+\r
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer\r
+ contain JSON paylaod in ASCII string. The return\r
+ value must be freed by the caller FreePool().\r
+**/\r
+CHAR8 *\r
+EFIAPI\r
+JsonDumpString (\r
+ IN EDKII_JSON_VALUE JsonValue,\r
+ IN UINTN Flags\r
+ );\r
+\r
+/**\r
+ Load JSON from a buffer.\r
+\r
+ @param[in] Buffer Bufffer to the JSON payload\r
+ @param[in] BufferLen Length of the buffer\r
+ @param[in] Flags Flag of loading JSON buffer, the value\r
+ could be the combination of below flags.\r
+ - EDKII_JSON_REJECT_DUPLICATES\r
+ - EDKII_JSON_DISABLE_EOF_CHECK\r
+ - EDKII_JSON_DECODE_ANY\r
+ - EDKII_JSON_DECODE_INT_AS_REAL\r
+ - EDKII_JSON_ALLOW_NUL\r
+ See below URI for the JSON encoding flags reference.\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding\r
+\r
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure\r
+\r
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonLoadBuffer (\r
+ IN CONST CHAR8 *Buffer,\r
+ IN UINTN BufferLen,\r
+ IN UINTN Flags,\r
+ IN OUT EDKII_JSON_ERROR *Error\r
+ );\r
+\r
+/**\r
+ The reference count is used to track whether a value is still in use or not.\r
+ When a value is created, it's reference count is set to 1.\r
+ when the value is no longer needed, the reference count is decremented.\r
+ When the reference count drops to zero, there are no references left and the\r
+ value can be destroyed.\r
+\r
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as\r
+ a call to json_decref() drops the reference count to zero, the value is\r
+ destroyed and it can no longer be used.\r
+\r
+ @param[in] JsonValue JSON value\r
+**/\r
+VOID\r
+EFIAPI\r
+JsonDecreaseReference (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ );\r
+\r
+/**\r
+ The reference count is used to track whether a value is still in use or not.\r
+ When a value is created, it's reference count is set to 1.\r
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),\r
+ its reference count is incremented.\r
+\r
+ This function increment the reference count of json if it's not NULL.\r
+ Returns EDKII_JSON_VALUE.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @retval EDKII_JSON_VALUE of itself\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonIncreaseReference (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ );\r
+/**\r
+ Returns an opaque iterator which can be used to iterate over all key-value pairs\r
+ in object, or NULL if object is empty\r
+\r
+ @param[in] JsonValue JSON value\r
+**/\r
+VOID *\r
+EFIAPI\r
+JsonObjectIterator (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ );\r
+\r
+/**\r
+ Extract the associated value from iterator.\r
+\r
+ @param[in] Iterator Iterator pointer\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonObjectIteratorValue (\r
+ IN VOID *Iterator\r
+ );\r
+\r
+/**\r
+ Returns an iterator pointing to the next key-value pair in object after iter,\r
+ or NULL if the whole object has been iterated through.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @param[in] Iterator Iterator pointer\r
+ @retval Iterator pointer\r
+**/\r
+VOID *\r
+JsonObjectIteratorNext (\r
+ IN EDKII_JSON_VALUE JsonValue,\r
+ IN VOID *Iterator\r
+ );\r
+\r
+/**\r
+ Returns the json type of this json value\r
+\r
+ @param[in] JsonValue JSON value\r
+ @retval JSON type returned\r
+**/\r
+EDKII_JSON_TYPE\r
+EFIAPI\r
+JsonGetType(\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ );\r
+#endif\r
--- /dev/null
+/** @file\r
+ APIs for JSON operations. The fuctions provided by this library are the\r
+ wrapper to native open source jansson library. See below document for\r
+ the API reference.\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html\r
+\r
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/JsonLib.h>\r
+#include <Library/BaseUcs2Utf8Lib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include "jansson.h"\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON array,\r
+ or NULL on error. Initially, the array is empty.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array\r
+ is failed.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitArray (\r
+ VOID\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_array();\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON object,\r
+ or NULL on error. Initially, the object is empty.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object\r
+ is failed.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitObject (\r
+ VOID\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_object();\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON string,\r
+ or NULL on error.\r
+\r
+ The input string must be NULL terminated Ascii format, non-Ascii characters will\r
+ be processed as an error. Unicode characters can also be represented by Ascii string\r
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] String The Ascii string to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON string or NULL. Select a\r
+ Getter API for a specific encoding format.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitAsciiString (\r
+ IN CONST CHAR8 *String\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Index = 0;\r
+ while (*(String + Index) != '\0') {\r
+ if (((*(String + Index)) & 0x80) != 0x00) {\r
+ return NULL;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ return (EDKII_JSON_VALUE)json_string (String);\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON string,\r
+ or NULL on error.\r
+\r
+ The input must be a NULL terminated UCS2 format Unicode string.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] String The Unicode string to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON string or NULL. Select a\r
+ Getter API for a specific encoding format.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitUnicodeString (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *Utf8Str;\r
+\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Utf8Str = NULL;\r
+ Status = UCS2StrToUTF8 (String, &Utf8Str);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ return (EDKII_JSON_VALUE)json_string (Utf8Str);\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON integer,\r
+ or NULL on error.\r
+\r
+ The reference count of this value will be set to 1, and caller needs to cleanup the\r
+ value by calling JsonValueFree().\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] Value The integer to initialize to JSON value\r
+\r
+ @retval The created JSON value which contains a JSON number or NULL.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitNumber (\r
+ IN INT64 Value\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_integer (Value);\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON boolean,\r
+ or NULL on error.\r
+\r
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.\r
+\r
+ @param[in] Value The boolean value to initialize.\r
+\r
+ @retval The created JSON value which contains a JSON boolean or NULL.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitBoolean (\r
+ IN BOOLEAN Value\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_boolean (Value);\r
+}\r
+\r
+/**\r
+ The function is used to initialize a JSON value which contains a new JSON NULL,\r
+ or NULL on error.\r
+\r
+ NULL JSON value is kept as static value, and no need to do any cleanup work.\r
+\r
+ @retval The created NULL JSON value.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueInitNull (\r
+ VOID\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_null();\r
+}\r
+\r
+/**\r
+ The function is used to decrease the reference count of a JSON value by one, and once\r
+ this reference count drops to zero, the value is destroyed and it can no longer be used.\r
+ If this destroyed value is object type or array type, reference counts for all containing\r
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed\r
+ since they are static values kept in memory.\r
+\r
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still\r
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a\r
+ value is kept for use, its reference count is incremented, and when the value is no longer\r
+ needed, the reference count is decremented. When the reference count drops to zero, there are\r
+ no references left, and the value can be destroyed.\r
+\r
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message\r
+ to inform caller the NULL value is passed in.\r
+\r
+ @param[in] Json The JSON value to be freed. json_decref may return without any\r
+ changes if Json is NULL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+JsonValueFree (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ json_decref((json_t *)Json);\r
+}\r
+\r
+/**\r
+ The function is used to create a fresh copy of a JSON value, and all child values are deep\r
+ copied in a recursive fashion. It should be called when this JSON value might be modified\r
+ in later use, but the original still wants to be used in somewhere else.\r
+\r
+ Reference counts of the returned root JSON value and all child values will be set to 1, and\r
+ caller needs to cleanup the root value by calling JsonValueFree().\r
+\r
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some\r
+ performance issues, user should avoid unnecessary calls to this function unless it is really\r
+ needed.\r
+\r
+ @param[in] Json The JSON value to be cloned.\r
+\r
+ @retval Return the cloned JSON value, or NULL on error.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonValueClone (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_deep_copy ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON array.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON array.\r
+ @retval FALSE The JSON value doesn't contain a JSON array.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsArray (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_array ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON object.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON object.\r
+ @retval FALSE The JSON value doesn't contain a JSON object.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsObject (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_object ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON Value contains a string, Ascii or\r
+ Unicode format is not differentiated.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON string.\r
+ @retval FALSE The JSON value doesn't contain a JSON string.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsString (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_string ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON number.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value is contains JSON number.\r
+ @retval FALSE The JSON value doesn't contain a JSON number.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsNumber (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_integer ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON boolean.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON boolean.\r
+ @retval FALSE The JSON value doesn't contain a JSON boolean.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsBoolean (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_boolean ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to return if the provided JSON value contains a JSON NULL.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval TRUE The JSON value contains a JSON NULL.\r
+ @retval FALSE The JSON value doesn't contain a JSON NULL.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueIsNull (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_is_null ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated array in an array type JSON value.\r
+\r
+ Any changes to the returned array will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated array in JSON value or NULL.\r
+\r
+**/\r
+EDKII_JSON_ARRAY\r
+EFIAPI\r
+JsonValueGetArray (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ if (Json == NULL || !JsonValueIsArray (Json)) {\r
+ return NULL;\r
+ }\r
+\r
+ return (EDKII_JSON_ARRAY)Json;\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated object in an object type JSON value.\r
+\r
+ Any changes to the returned object will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated object in JSON value or NULL.\r
+\r
+**/\r
+EDKII_JSON_OBJECT\r
+EFIAPI\r
+JsonValueGetObject (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ if (Json == NULL || !JsonValueIsObject (Json)) {\r
+ return NULL;\r
+ }\r
+\r
+ return (EDKII_JSON_OBJECT)Json;\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated Ascii string in a string type JSON value.\r
+\r
+ Any changes to the returned string will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Ascii string in JSON value or NULL.\r
+\r
+**/\r
+CONST CHAR8 *\r
+EFIAPI\r
+JsonValueGetAsciiString (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ CHAR8 *AsciiStr;\r
+ UINTN Index;\r
+\r
+ AsciiStr = (CHAR8 *) ((json_t *) Json);\r
+ if (AsciiStr == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Index = 0;\r
+ while (*(AsciiStr + Index) != '\0') {\r
+ if (((*(AsciiStr + Index)) & 0x80) != 0x00) {\r
+ return NULL;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ return AsciiStr;\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated Unicode string in a string type JSON value.\r
+\r
+ Caller can do any changes to the returned string without any impact to the original JSON\r
+ value, and caller needs to free the returned string using FreePool().\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Unicode string in JSON value or NULL.\r
+\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+JsonValueGetUnicodeString (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CONST CHAR8 *Utf8Str;\r
+ CHAR16 *Ucs2Str;\r
+\r
+ Utf8Str = json_string_value ((json_t *) Json);\r
+ if (Utf8Str == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = UTF8StrToUCS2 ((CHAR8*)Utf8Str, &Ucs2Str);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ return Ucs2Str;\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated integer in a number type JSON value.\r
+\r
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will\r
+ ASSERT() and return 0.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated number in JSON value.\r
+\r
+**/\r
+INT64\r
+EFIAPI\r
+JsonValueGetNumber (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ ASSERT (Json != NULL && JsonValueIsNumber (Json));\r
+ if (Json == NULL || !JsonValueIsNumber (Json)) {\r
+ return 0;\r
+ }\r
+\r
+ return json_integer_value ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated boolean in a boolean type JSON value.\r
+\r
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will\r
+ ASSERT() and return FALSE.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated value of JSON boolean.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+JsonValueGetBoolean (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ ASSERT (Json != NULL && JsonValueIsBoolean (Json));\r
+ if (Json == NULL || !JsonValueIsBoolean (Json)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return json_is_true ((json_t *) Json);\r
+}\r
+\r
+/**\r
+ The function is used to retrieve the associated string in a string type JSON value.\r
+\r
+ Any changes to the returned string will impact the original JSON value.\r
+\r
+ @param[in] Json The provided JSON value.\r
+\r
+ @retval Return the associated Ascii string in JSON value or NULL on errors.\r
+\r
+**/\r
+CONST CHAR8*\r
+EFIAPI\r
+JsonValueGetString (\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ return json_string_value ((const json_t *)Json);\r
+}\r
+\r
+/**\r
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or\r
+ not a JSON object.\r
+\r
+ @param[in] JsonObject The provided JSON object.\r
+\r
+ @retval Return the number of elements in this JSON object or 0.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+JsonObjectSize (\r
+ IN EDKII_JSON_OBJECT JsonObject\r
+ )\r
+{\r
+ return json_object_size ((json_t *) JsonObject);\r
+}\r
+\r
+/**\r
+ The function is used to enumerate all keys in a JSON object.\r
+\r
+ Caller should be responsible to free the returned key array reference using\r
+ FreePool(). But contained keys are read only and must not be modified or freed.\r
+\r
+ @param[in] JsonObj The provided JSON object for enumeration.\r
+ @param[out] KeyCount The count of keys in this JSON object.\r
+\r
+ @retval Return an array of the enumerated keys in this JSON object or NULL if\r
+ JsonObj is not an JSON object, key count is zero or on other errors.\r
+\r
+**/\r
+CHAR8**\r
+JsonObjectGetKeys (\r
+ IN EDKII_JSON_OBJECT JsonObj,\r
+ OUT UINTN *KeyCount\r
+ )\r
+{\r
+\r
+ UINTN Index;\r
+ CONST CHAR8 **KeyArray;\r
+ CONST CHAR8 *Key;\r
+ EDKII_JSON_VALUE Value;\r
+\r
+ if (JsonObj == NULL || KeyCount == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Index = 0;\r
+ json_object_foreach(JsonObj, Key, Value) {\r
+ Index++;\r
+ }\r
+ if (Index == 0) {\r
+ *KeyCount = 0;\r
+ return NULL;\r
+ }\r
+\r
+ *KeyCount = Index;\r
+ KeyArray = (CONST CHAR8 **) AllocateZeroPool (*KeyCount * sizeof (CHAR8 *));\r
+ if (KeyArray == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Key = NULL;\r
+ Value = NULL;\r
+ Index = 0;\r
+ json_object_foreach((json_t *) JsonObj, Key, Value) {\r
+ KeyArray[Index] = Key;\r
+ Index++;\r
+ }\r
+\r
+ return (CHAR8 **)KeyArray;\r
+}\r
+\r
+/**\r
+ The function is used to get a JSON value corresponding to the input key from a JSON object.\r
+\r
+ It only returns a reference to this value and any changes on this value will impact the\r
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to\r
+ use.\r
+\r
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when\r
+ Key-Value is not found in this JSON object.\r
+\r
+ @param[in] JsonObj The provided JSON object.\r
+ @param[in] Key The key of the JSON value to be retrieved.\r
+\r
+ @retval Return the corresponding JSON value to key, or NULL on error.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonObjectGetValue (\r
+ IN CONST EDKII_JSON_OBJECT JsonObj,\r
+ IN CONST CHAR8 *Key\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_object_get ((const json_t *)JsonObj, (const char *)Key);\r
+}\r
+\r
+/**\r
+ The function is used to set a JSON value corresponding to the input key from a JSON object,\r
+ and the reference count of this value will be increased by 1.\r
+\r
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for\r
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed\r
+ from this object and thus its' reference count will be decreased by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonObj The provided JSON object.\r
+ @param[in] Key The key of the JSON value to be set.\r
+ @param[in] Json The JSON value to set to this JSON object mapped by key.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonObjectSetValue (\r
+ IN EDKII_JSON_OBJECT JsonObj,\r
+ IN CONST CHAR8 *Key,\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ if (json_object_set ((json_t *) JsonObj, Key, (json_t *) Json) != 0) {\r
+ return EFI_ABORTED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray\r
+ is NULL or not a JSON array.\r
+\r
+ @param[in] JsonArray The provided JSON array.\r
+\r
+ @retval Return the number of elements in this JSON array or 0.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+JsonArrayCount (\r
+ IN EDKII_JSON_ARRAY JsonArray\r
+ )\r
+{\r
+ return json_array_size ((json_t *) JsonArray);\r
+}\r
+\r
+/**\r
+ The function is used to return the JSON value in the array at position index. The valid range\r
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.\r
+\r
+ It only returns a reference to this value and any changes on this value will impact the\r
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to\r
+ use.\r
+\r
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.\r
+\r
+ @param[in] JsonArray The provided JSON Array.\r
+\r
+ @retval Return the JSON value located in the Index position or\r
+ NULL if JsonArray is not an array or no items in the array.\r
+\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonArrayGetValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ return (EDKII_JSON_VALUE)json_array_get ((json_t *) JsonArray, Index);\r
+}\r
+\r
+/**\r
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of\r
+ array by 1. The reference count of this value will be increased by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonArray The provided JSON object.\r
+ @param[in] Json The JSON value to append.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonArrayAppendValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN EDKII_JSON_VALUE Json\r
+ )\r
+{\r
+ if (json_array_append ((json_t *) JsonArray, (json_t *) Json) != 0) {\r
+ return EFI_ABORTED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ The function is used to remove a JSON value at position index, shifting the elements after index\r
+ one position towards the start of the array. The reference count of this value will be decreased\r
+ by 1.\r
+\r
+ More details for reference count strategy can refer to the API description for JsonValueFree().\r
+\r
+ @param[in] JsonArray The provided JSON array.\r
+ @param[in] Index The Index position before removement.\r
+\r
+ @retval EFI_ABORTED Some error occur and operation aborted.\r
+ @retval EFI_SUCCESS The JSON array has been removed at position index.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+JsonArrayRemoveValue (\r
+ IN EDKII_JSON_ARRAY JsonArray,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ if (json_array_remove ((json_t *) JsonArray, Index) != 0) {\r
+ return EFI_ABORTED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Dump JSON to a buffer.\r
+\r
+ @param[in] JsonValue The provided JSON value.\r
+ @param[in] Flags The Index position before removement. The value\r
+ could be the combination of below flags.\r
+ - EDKII_JSON_INDENT(n)\r
+ - EDKII_JSON_COMPACT\r
+ - EDKII_JSON_ENSURE_ASCII\r
+ - EDKII_JSON_SORT_KEYS\r
+ - EDKII_JSON_PRESERVE_ORDER\r
+ - EDKII_JSON_ENCODE_ANY\r
+ - EDKII_JSON_ESCAPE_SLASH\r
+ - EDKII_JSON_REAL_PRECISION(n)\r
+ - EDKII_JSON_EMBED\r
+ See below URI for the JSON encoding flags reference.\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding\r
+\r
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer\r
+ contain JSON paylaod in ASCII string. The return\r
+ value must be freed by the caller using FreePool().\r
+**/\r
+CHAR8 *\r
+EFIAPI\r
+JsonDumpString (\r
+ IN EDKII_JSON_VALUE JsonValue,\r
+ IN UINTN Flags\r
+ )\r
+{\r
+ if (JsonValue == NULL) {\r
+ return NULL;\r
+ }\r
+ return json_dumps((json_t *)JsonValue, Flags);\r
+}\r
+\r
+/**\r
+ Load JSON from a buffer.\r
+\r
+ @param[in] Buffer Bufffer to the JSON payload\r
+ @param[in] BufferLen Length of the buffer\r
+ @param[in] Flags Flag of loading JSON buffer, the value\r
+ could be the combination of below flags.\r
+ - EDKII_JSON_REJECT_DUPLICATES\r
+ - EDKII_JSON_DISABLE_EOF_CHECK\r
+ - EDKII_JSON_DECODE_ANY\r
+ - EDKII_JSON_DECODE_INT_AS_REAL\r
+ - EDKII_JSON_ALLOW_NUL\r
+ See below URI for the JSON encoding flags reference.\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding\r
+\r
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure\r
+\r
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonLoadBuffer (\r
+ IN CONST CHAR8 *Buffer,\r
+ IN UINTN BufferLen,\r
+ IN UINTN Flags,\r
+ IN OUT EDKII_JSON_ERROR *Error\r
+ )\r
+{\r
+ return json_loadb(Buffer, BufferLen, Flags, (json_error_t *)Error);\r
+}\r
+\r
+/**\r
+ The reference count is used to track whether a value is still in use or not.\r
+ When a value is created, it's reference count is set to 1.\r
+ when the value is no longer needed, the reference count is decremented.\r
+ When the reference count drops to zero, there are no references left and the\r
+ value can be destroyed.\r
+\r
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as\r
+ a call to json_decref() drops the reference count to zero, the value is\r
+ destroyed and it can no longer be used.\r
+\r
+ @param[in] JsonValue JSON value\r
+**/\r
+VOID\r
+EFIAPI\r
+JsonDecreaseReference (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ )\r
+{\r
+ json_decref (JsonValue);\r
+}\r
+\r
+/**\r
+ The reference count is used to track whether a value is still in use or not.\r
+ When a value is created, it's reference count is set to 1.\r
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),\r
+ its reference count is incremented.\r
+\r
+ This function increment the reference count of json if it's not NULL.\r
+ Returns EDKII_JSON_VALUE.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @retval EDKII_JSON_VALUE of itself\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonIncreaseReference (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ )\r
+{\r
+ return json_incref (JsonValue);\r
+}\r
+\r
+/**\r
+ Returns an opaque iterator which can be used to iterate over all key-value pairs\r
+ in object, or NULL if object is empty.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @retval Iterator pointer\r
+**/\r
+VOID *\r
+EFIAPI\r
+JsonObjectIterator (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ )\r
+{\r
+ return json_object_iter (JsonValue);\r
+}\r
+\r
+/**\r
+ Extract the associated value from iterator.\r
+\r
+ @param[in] Iterator Iterator pointer\r
+ @retval EDKII_JSON_VALUE\r
+**/\r
+EDKII_JSON_VALUE\r
+EFIAPI\r
+JsonObjectIteratorValue (\r
+ IN VOID *Iterator\r
+ )\r
+{\r
+ return json_object_iter_value(Iterator);\r
+}\r
+\r
+/**\r
+ Returns an iterator pointing to the next key-value pair in object after iter,\r
+ or NULL if the whole object has been iterated through.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @param[in] Iterator Iterator pointer\r
+ @retval Iterator pointer\r
+**/\r
+VOID *\r
+JsonObjectIteratorNext (\r
+ IN EDKII_JSON_VALUE JsonValue,\r
+ IN VOID *Iterator\r
+ )\r
+{\r
+ return json_object_iter_next(JsonValue, Iterator);\r
+}\r
+\r
+/**\r
+ Returns the json type of this json value.\r
+\r
+ @param[in] JsonValue JSON value\r
+ @retval JSON type returned\r
+**/\r
+EDKII_JSON_TYPE\r
+EFIAPI\r
+JsonGetType (\r
+ IN EDKII_JSON_VALUE JsonValue\r
+ )\r
+{\r
+ return ((json_t *)JsonValue)->type;\r
+}\r
--- /dev/null
+## @file\r
+# Thirty party Jansson library for JSON operations.\r
+#\r
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x0001001b\r
+ BASE_NAME = JsonLib\r
+ FILE_GUID = F5E36815-305A-4C5A-9D75-4F2149E45255\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = JsonLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64\r
+#\r
+\r
+[Sources]\r
+ #\r
+ # Below are the source code of third\r
+ # party jansson library.\r
+ #\r
+ jansson/src/dump.c\r
+ jansson/src/error.c\r
+ jansson/src/hashtable.c\r
+ jansson/src/hashtable_seed.c\r
+ jansson/src/memory.c\r
+ jansson/src/pack_unpack.c\r
+ jansson/src/strbuffer.c\r
+ jansson/src/strconv.c\r
+ jansson/src/utf.c\r
+ jansson/src/value.c\r
+ jansson/src/version.c\r
+ #\r
+ # Below are the source of edk2 JsonLib.\r
+ #\r
+ JsonLib.c\r
+ jansson_config.h\r
+ jansson_private_config.h\r
+ #\r
+ # Below is the source code override to fix the build issue.\r
+ # Add code in load.c to conditionally use stdin according\r
+ # to HAVE_UNISTD_H macro. The PR is submitted to jansson\r
+ # open source community.\r
+ # https://github.com/akheron/jansson/pull/558\r
+ #\r
+ load.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ RedfishPkg/RedfishPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ Ucs2Utf8Lib\r
+ RedfishCrtLib\r
+ DebugLib\r
+ MemoryAllocationLib\r
+ PrintLib\r
+ UefiRuntimeServicesTableLib\r
+ UefiLib\r
+\r
+[BuildOptions]\r
+ #\r
+ # Disables the following Visual Studio compiler warnings\r
+ # so we do not break the build with /WX option:\r
+ # C4090: 'function' : different 'const' qualifiers\r
+ # C4244: conversion from type1 to type2, possible loss of data\r
+ # C4334: 32-bit shift implicitly converted to 64-bit\r
+ # C4204: nonstandard extension used: non-constant aggregate initializer\r
+ #\r
+ # Define macro HAVE_CONFIG_H to include jansson_private_config.h to build.\r
+ # Undefined _WIN32, WIN64, _MSC_VER macros\r
+ # On GCC, no error on the unused-function and unused-but-set-variable.\r
+ #\r
+ MSFT:*_*_X64_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4334 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER\r
+ MSFT:*_*_IA32_CC_FLAGS = /wd4204 /wd4244 /wd4090 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER\r
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable\r
+\r
--- /dev/null
+=============================================================================\r
+ Introduction\r
+=============================================================================\r
+ Jansson is a C library for encoding, decoding and manipulating JSON data.\r
+Its main features and design principles are:\r
+\r
+ - Simple and intuitive API and data model\r
+ - Comprehensive documentation\r
+ - No dependencies on other libraries\r
+ - Full Unicode support (UTF-8)\r
+ - Extensive test suite\r
+\r
+ Jansson is licensed under the MIT license(refer to ReadMe.rst under edk2).\r
+It is used in production and its API is stable. It works on numerous\r
+platforms, including numerous Unix like systems and Windows. It's suitable\r
+for use on any system, including desktop, server, and small embedded systems.\r
+\r
+ In UEFI/EDKII environment, Redfish project consumes jansson to achieve JSON\r
+operations.\r
+\r
+* Jansson version on edk2: 2.13.1, API reference is on the below URL,\r
+ https://jansson.readthedocs.io/en/2.13/apiref.html\r
+\r
+* EDKII jansson library wrapper:\r
+ - JsonLib.h:\r
+ This is the denifitions of EDKII JSON APIs which are mapped to\r
+ jannson funcitons accordingly.\r
+\r
+*Known issue:\r
+ Build fail with jansson/src/load.c, add code in load.c to conditionally\r
+ use stdin according to HAVE_UNISTD_H macro. The PR is submitted to\r
+ jansson open source community.\r
+ https://github.com/akheron/jansson/pull/558\r
+\r
+\r
--- /dev/null
+/** @file This is the configuration file for building jansson library.\r
+\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ **/\r
+\r
+#ifndef JANSSON_CONFIG_H_\r
+#define JANSSON_CONFIG_H_\r
+\r
+///\r
+/// We don't support inline JSON on edk2\r
+///\r
+#define JSON_INLINE\r
+\r
+///\r
+/// We support long long on edk2\r
+///\r
+#define JSON_INTEGER_IS_LONG_LONG 1\r
+\r
+///\r
+/// We don't support locale on edk2\r
+///\r
+#define JSON_HAVE_LOCALECONV 0\r
+\r
+///\r
+/// We don't support atomic builtins on edk2\r
+///\r
+#define JSON_HAVE_ATOMIC_BUILTINS 0\r
+\r
+///\r
+/// We don't support sync builtins on edk2\r
+///\r
+#define JSON_HAVE_SYNC_BUILTINS 0\r
+\r
+///\r
+/// Mzximum deepth is set to 2048\r
+///\r
+#define JSON_PARSER_MAX_DEPTH 2048\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Jansson private configurations for UEFI support.\r
+\r
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef JANSSON_PRIVATE_CONFIG_H_\r
+#define JANSSON_PRIVATE_CONFIG_H_\r
+\r
+#define HAVE_SYS_TIME_H 1\r
+#define HAVE_SYS_TYPES_H 1\r
+\r
+#define INITIAL_HASHTABLE_ORDER 3\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>\r
+ *\r
+ * Jansson is free software; you can redistribute it and/or modify\r
+ * it under the terms of the MIT license. See LICENSE for details.\r
+\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent AND MIT\r
+ */\r
+\r
+#ifndef _GNU_SOURCE\r
+#define _GNU_SOURCE\r
+#endif\r
+\r
+#include "jansson_private.h"\r
+\r
+#include <assert.h>\r
+#include <errno.h>\r
+#include <limits.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#ifdef HAVE_UNISTD_H\r
+#include <unistd.h>\r
+#endif\r
+\r
+#include "jansson.h"\r
+#include "strbuffer.h"\r
+#include "utf.h"\r
+\r
+#define STREAM_STATE_OK 0\r
+#define STREAM_STATE_EOF -1\r
+#define STREAM_STATE_ERROR -2\r
+\r
+#define TOKEN_INVALID -1\r
+#define TOKEN_EOF 0\r
+#define TOKEN_STRING 256\r
+#define TOKEN_INTEGER 257\r
+#define TOKEN_REAL 258\r
+#define TOKEN_TRUE 259\r
+#define TOKEN_FALSE 260\r
+#define TOKEN_NULL 261\r
+\r
+/* Locale independent versions of isxxx() functions */\r
+#define l_isupper(c) ('A' <= (c) && (c) <= 'Z')\r
+#define l_islower(c) ('a' <= (c) && (c) <= 'z')\r
+#define l_isalpha(c) (l_isupper(c) || l_islower(c))\r
+#define l_isdigit(c) ('0' <= (c) && (c) <= '9')\r
+#define l_isxdigit(c) \\r
+ (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))\r
+\r
+/* Read one byte from stream, convert to unsigned char, then int, and\r
+ return. return EOF on end of file. This corresponds to the\r
+ behaviour of fgetc(). */\r
+typedef int (*get_func)(void *data);\r
+\r
+typedef struct {\r
+ get_func get;\r
+ void *data;\r
+ char buffer[5];\r
+ size_t buffer_pos;\r
+ int state;\r
+ int line;\r
+ int column, last_column;\r
+ size_t position;\r
+} stream_t;\r
+\r
+typedef struct {\r
+ stream_t stream;\r
+ strbuffer_t saved_text;\r
+ size_t flags;\r
+ size_t depth;\r
+ int token;\r
+ union {\r
+ struct {\r
+ char *val;\r
+ size_t len;\r
+ } string;\r
+ json_int_t integer;\r
+ double real;\r
+ } value;\r
+} lex_t;\r
+\r
+#define stream_to_lex(stream) container_of(stream, lex_t, stream)\r
+\r
+/*** error reporting ***/\r
+\r
+static void error_set(json_error_t *error, const lex_t *lex, enum json_error_code code,\r
+ const char *msg, ...) {\r
+ va_list ap;\r
+ char msg_text[JSON_ERROR_TEXT_LENGTH];\r
+ char msg_with_context[JSON_ERROR_TEXT_LENGTH];\r
+\r
+ int line = -1, col = -1;\r
+ size_t pos = 0;\r
+ const char *result = msg_text;\r
+\r
+ if (!error)\r
+ return;\r
+\r
+ va_start(ap, msg);\r
+ vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);\r
+ msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';\r
+ va_end(ap);\r
+\r
+ if (lex) {\r
+ const char *saved_text = strbuffer_value(&lex->saved_text);\r
+\r
+ line = lex->stream.line;\r
+ col = lex->stream.column;\r
+ pos = lex->stream.position;\r
+\r
+ if (saved_text && saved_text[0]) {\r
+ if (lex->saved_text.length <= 20) {\r
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'",\r
+ msg_text, saved_text);\r
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';\r
+ result = msg_with_context;\r
+ }\r
+ } else {\r
+ if (code == json_error_invalid_syntax) {\r
+ /* More specific error code for premature end of file. */\r
+ code = json_error_premature_end_of_input;\r
+ }\r
+ if (lex->stream.state == STREAM_STATE_ERROR) {\r
+ /* No context for UTF-8 decoding errors */\r
+ result = msg_text;\r
+ } else {\r
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file",\r
+ msg_text);\r
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';\r
+ result = msg_with_context;\r
+ }\r
+ }\r
+ }\r
+\r
+ jsonp_error_set(error, line, col, pos, code, "%s", result);\r
+}\r
+\r
+/*** lexical analyzer ***/\r
+\r
+static void stream_init(stream_t *stream, get_func get, void *data) {\r
+ stream->get = get;\r
+ stream->data = data;\r
+ stream->buffer[0] = '\0';\r
+ stream->buffer_pos = 0;\r
+\r
+ stream->state = STREAM_STATE_OK;\r
+ stream->line = 1;\r
+ stream->column = 0;\r
+ stream->position = 0;\r
+}\r
+\r
+static int stream_get(stream_t *stream, json_error_t *error) {\r
+ int c;\r
+\r
+ if (stream->state != STREAM_STATE_OK)\r
+ return stream->state;\r
+\r
+ if (!stream->buffer[stream->buffer_pos]) {\r
+ c = stream->get(stream->data);\r
+ if (c == EOF) {\r
+ stream->state = STREAM_STATE_EOF;\r
+ return STREAM_STATE_EOF;\r
+ }\r
+\r
+ stream->buffer[0] = c;\r
+ stream->buffer_pos = 0;\r
+\r
+ if (0x80 <= c && c <= 0xFF) {\r
+ /* multi-byte UTF-8 sequence */\r
+ size_t i, count;\r
+\r
+ count = utf8_check_first(c);\r
+ if (!count)\r
+ goto out;\r
+\r
+ assert(count >= 2);\r
+\r
+ for (i = 1; i < count; i++)\r
+ stream->buffer[i] = stream->get(stream->data);\r
+\r
+ if (!utf8_check_full(stream->buffer, count, NULL))\r
+ goto out;\r
+\r
+ stream->buffer[count] = '\0';\r
+ } else\r
+ stream->buffer[1] = '\0';\r
+ }\r
+\r
+ c = stream->buffer[stream->buffer_pos++];\r
+\r
+ stream->position++;\r
+ if (c == '\n') {\r
+ stream->line++;\r
+ stream->last_column = stream->column;\r
+ stream->column = 0;\r
+ } else if (utf8_check_first(c)) {\r
+ /* track the Unicode character column, so increment only if\r
+ this is the first character of a UTF-8 sequence */\r
+ stream->column++;\r
+ }\r
+\r
+ return c;\r
+\r
+out:\r
+ stream->state = STREAM_STATE_ERROR;\r
+ error_set(error, stream_to_lex(stream), json_error_invalid_utf8,\r
+ "unable to decode byte 0x%x", c);\r
+ return STREAM_STATE_ERROR;\r
+}\r
+\r
+static void stream_unget(stream_t *stream, int c) {\r
+ if (c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)\r
+ return;\r
+\r
+ stream->position--;\r
+ if (c == '\n') {\r
+ stream->line--;\r
+ stream->column = stream->last_column;\r
+ } else if (utf8_check_first(c))\r
+ stream->column--;\r
+\r
+ assert(stream->buffer_pos > 0);\r
+ stream->buffer_pos--;\r
+ assert(stream->buffer[stream->buffer_pos] == c);\r
+}\r
+\r
+static int lex_get(lex_t *lex, json_error_t *error) {\r
+ return stream_get(&lex->stream, error);\r
+}\r
+\r
+static void lex_save(lex_t *lex, int c) { strbuffer_append_byte(&lex->saved_text, c); }\r
+\r
+static int lex_get_save(lex_t *lex, json_error_t *error) {\r
+ int c = stream_get(&lex->stream, error);\r
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)\r
+ lex_save(lex, c);\r
+ return c;\r
+}\r
+\r
+static void lex_unget(lex_t *lex, int c) { stream_unget(&lex->stream, c); }\r
+\r
+static void lex_unget_unsave(lex_t *lex, int c) {\r
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {\r
+/* Since we treat warnings as errors, when assertions are turned\r
+ * off the "d" variable would be set but never used. Which is\r
+ * treated as an error by GCC.\r
+ */\r
+#ifndef NDEBUG\r
+ char d;\r
+#endif\r
+ stream_unget(&lex->stream, c);\r
+#ifndef NDEBUG\r
+ d =\r
+#endif\r
+ strbuffer_pop(&lex->saved_text);\r
+ assert(c == d);\r
+ }\r
+}\r
+\r
+static void lex_save_cached(lex_t *lex) {\r
+ while (lex->stream.buffer[lex->stream.buffer_pos] != '\0') {\r
+ lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);\r
+ lex->stream.buffer_pos++;\r
+ lex->stream.position++;\r
+ }\r
+}\r
+\r
+static void lex_free_string(lex_t *lex) {\r
+ jsonp_free(lex->value.string.val);\r
+ lex->value.string.val = NULL;\r
+ lex->value.string.len = 0;\r
+}\r
+\r
+/* assumes that str points to 'u' plus at least 4 valid hex digits */\r
+static int32_t decode_unicode_escape(const char *str) {\r
+ int i;\r
+ int32_t value = 0;\r
+\r
+ assert(str[0] == 'u');\r
+\r
+ for (i = 1; i <= 4; i++) {\r
+ char c = str[i];\r
+ value <<= 4;\r
+ if (l_isdigit(c))\r
+ value += c - '0';\r
+ else if (l_islower(c))\r
+ value += c - 'a' + 10;\r
+ else if (l_isupper(c))\r
+ value += c - 'A' + 10;\r
+ else\r
+ return -1;\r
+ }\r
+\r
+ return value;\r
+}\r
+\r
+static void lex_scan_string(lex_t *lex, json_error_t *error) {\r
+ int c;\r
+ const char *p;\r
+ char *t;\r
+ int i;\r
+\r
+ lex->value.string.val = NULL;\r
+ lex->token = TOKEN_INVALID;\r
+\r
+ c = lex_get_save(lex, error);\r
+\r
+ while (c != '"') {\r
+ if (c == STREAM_STATE_ERROR)\r
+ goto out;\r
+\r
+ else if (c == STREAM_STATE_EOF) {\r
+ error_set(error, lex, json_error_premature_end_of_input,\r
+ "premature end of input");\r
+ goto out;\r
+ }\r
+\r
+ else if (0 <= c && c <= 0x1F) {\r
+ /* control character */\r
+ lex_unget_unsave(lex, c);\r
+ if (c == '\n')\r
+ error_set(error, lex, json_error_invalid_syntax, "unexpected newline");\r
+ else\r
+ error_set(error, lex, json_error_invalid_syntax, "control character 0x%x",\r
+ c);\r
+ goto out;\r
+ }\r
+\r
+ else if (c == '\\') {\r
+ c = lex_get_save(lex, error);\r
+ if (c == 'u') {\r
+ c = lex_get_save(lex, error);\r
+ for (i = 0; i < 4; i++) {\r
+ if (!l_isxdigit(c)) {\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid escape");\r
+ goto out;\r
+ }\r
+ c = lex_get_save(lex, error);\r
+ }\r
+ } else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' ||\r
+ c == 'n' || c == 'r' || c == 't')\r
+ c = lex_get_save(lex, error);\r
+ else {\r
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");\r
+ goto out;\r
+ }\r
+ } else\r
+ c = lex_get_save(lex, error);\r
+ }\r
+\r
+ /* the actual value is at most of the same length as the source\r
+ string, because:\r
+ - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte\r
+ - a single \uXXXX escape (length 6) is converted to at most 3 bytes\r
+ - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair\r
+ are converted to 4 bytes\r
+ */\r
+ t = jsonp_malloc(lex->saved_text.length + 1);\r
+ if (!t) {\r
+ /* this is not very nice, since TOKEN_INVALID is returned */\r
+ goto out;\r
+ }\r
+ lex->value.string.val = t;\r
+\r
+ /* + 1 to skip the " */\r
+ p = strbuffer_value(&lex->saved_text) + 1;\r
+\r
+ while (*p != '"') {\r
+ if (*p == '\\') {\r
+ p++;\r
+ if (*p == 'u') {\r
+ size_t length;\r
+ int32_t value;\r
+\r
+ value = decode_unicode_escape(p);\r
+ if (value < 0) {\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid Unicode escape '%.6s'", p - 1);\r
+ goto out;\r
+ }\r
+ p += 5;\r
+\r
+ if (0xD800 <= value && value <= 0xDBFF) {\r
+ /* surrogate pair */\r
+ if (*p == '\\' && *(p + 1) == 'u') {\r
+ int32_t value2 = decode_unicode_escape(++p);\r
+ if (value2 < 0) {\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid Unicode escape '%.6s'", p - 1);\r
+ goto out;\r
+ }\r
+ p += 5;\r
+\r
+ if (0xDC00 <= value2 && value2 <= 0xDFFF) {\r
+ /* valid second surrogate */\r
+ value =\r
+ ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;\r
+ } else {\r
+ /* invalid second surrogate */\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid Unicode '\\u%04X\\u%04X'", value, value2);\r
+ goto out;\r
+ }\r
+ } else {\r
+ /* no second surrogate */\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid Unicode '\\u%04X'", value);\r
+ goto out;\r
+ }\r
+ } else if (0xDC00 <= value && value <= 0xDFFF) {\r
+ error_set(error, lex, json_error_invalid_syntax,\r
+ "invalid Unicode '\\u%04X'", value);\r
+ goto out;\r
+ }\r
+\r
+ if (utf8_encode(value, t, &length))\r
+ assert(0);\r
+ t += length;\r
+ } else {\r
+ switch (*p) {\r
+ case '"':\r
+ case '\\':\r
+ case '/':\r
+ *t = *p;\r
+ break;\r
+ case 'b':\r
+ *t = '\b';\r
+ break;\r
+ case 'f':\r
+ *t = '\f';\r
+ break;\r
+ case 'n':\r
+ *t = '\n';\r
+ break;\r
+ case 'r':\r
+ *t = '\r';\r
+ break;\r
+ case 't':\r
+ *t = '\t';\r
+ break;\r
+ default:\r
+ assert(0);\r
+ }\r
+ t++;\r
+ p++;\r
+ }\r
+ } else\r
+ *(t++) = *(p++);\r
+ }\r
+ *t = '\0';\r
+ lex->value.string.len = t - lex->value.string.val;\r
+ lex->token = TOKEN_STRING;\r
+ return;\r
+\r
+out:\r
+ lex_free_string(lex);\r
+}\r
+\r
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */\r
+#if JSON_INTEGER_IS_LONG_LONG\r
+#ifdef _MSC_VER /* Microsoft Visual Studio */\r
+#define json_strtoint _strtoi64\r
+#else\r
+#define json_strtoint strtoll\r
+#endif\r
+#else\r
+#define json_strtoint strtol\r
+#endif\r
+#endif\r
+\r
+static int lex_scan_number(lex_t *lex, int c, json_error_t *error) {\r
+ const char *saved_text;\r
+ char *end;\r
+ double doubleval;\r
+\r
+ lex->token = TOKEN_INVALID;\r
+\r
+ if (c == '-')\r
+ c = lex_get_save(lex, error);\r
+\r
+ if (c == '0') {\r
+ c = lex_get_save(lex, error);\r
+ if (l_isdigit(c)) {\r
+ lex_unget_unsave(lex, c);\r
+ goto out;\r
+ }\r
+ } else if (l_isdigit(c)) {\r
+ do\r
+ c = lex_get_save(lex, error);\r
+ while (l_isdigit(c));\r
+ } else {\r
+ lex_unget_unsave(lex, c);\r
+ goto out;\r
+ }\r
+\r
+ if (!(lex->flags & JSON_DECODE_INT_AS_REAL) && c != '.' && c != 'E' && c != 'e') {\r
+ json_int_t intval;\r
+\r
+ lex_unget_unsave(lex, c);\r
+\r
+ saved_text = strbuffer_value(&lex->saved_text);\r
+\r
+ errno = 0;\r
+ intval = json_strtoint(saved_text, &end, 10);\r
+ if (errno == ERANGE) {\r
+ if (intval < 0)\r
+ error_set(error, lex, json_error_numeric_overflow,\r
+ "too big negative integer");\r
+ else\r
+ error_set(error, lex, json_error_numeric_overflow, "too big integer");\r
+ goto out;\r
+ }\r
+\r
+ assert(end == saved_text + lex->saved_text.length);\r
+\r
+ lex->token = TOKEN_INTEGER;\r
+ lex->value.integer = intval;\r
+ return 0;\r
+ }\r
+\r
+ if (c == '.') {\r
+ c = lex_get(lex, error);\r
+ if (!l_isdigit(c)) {\r
+ lex_unget(lex, c);\r
+ goto out;\r
+ }\r
+ lex_save(lex, c);\r
+\r
+ do\r
+ c = lex_get_save(lex, error);\r
+ while (l_isdigit(c));\r
+ }\r
+\r
+ if (c == 'E' || c == 'e') {\r
+ c = lex_get_save(lex, error);\r
+ if (c == '+' || c == '-')\r
+ c = lex_get_save(lex, error);\r
+\r
+ if (!l_isdigit(c)) {\r
+ lex_unget_unsave(lex, c);\r
+ goto out;\r
+ }\r
+\r
+ do\r
+ c = lex_get_save(lex, error);\r
+ while (l_isdigit(c));\r
+ }\r
+\r
+ lex_unget_unsave(lex, c);\r
+\r
+ if (jsonp_strtod(&lex->saved_text, &doubleval)) {\r
+ error_set(error, lex, json_error_numeric_overflow, "real number overflow");\r
+ goto out;\r
+ }\r
+\r
+ lex->token = TOKEN_REAL;\r
+ lex->value.real = doubleval;\r
+ return 0;\r
+\r
+out:\r
+ return -1;\r
+}\r
+\r
+static int lex_scan(lex_t *lex, json_error_t *error) {\r
+ int c;\r
+\r
+ strbuffer_clear(&lex->saved_text);\r
+\r
+ if (lex->token == TOKEN_STRING)\r
+ lex_free_string(lex);\r
+\r
+ do\r
+ c = lex_get(lex, error);\r
+ while (c == ' ' || c == '\t' || c == '\n' || c == '\r');\r
+\r
+ if (c == STREAM_STATE_EOF) {\r
+ lex->token = TOKEN_EOF;\r
+ goto out;\r
+ }\r
+\r
+ if (c == STREAM_STATE_ERROR) {\r
+ lex->token = TOKEN_INVALID;\r
+ goto out;\r
+ }\r
+\r
+ lex_save(lex, c);\r
+\r
+ if (c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',')\r
+ lex->token = c;\r
+\r
+ else if (c == '"')\r
+ lex_scan_string(lex, error);\r
+\r
+ else if (l_isdigit(c) || c == '-') {\r
+ if (lex_scan_number(lex, c, error))\r
+ goto out;\r
+ }\r
+\r
+ else if (l_isalpha(c)) {\r
+ /* eat up the whole identifier for clearer error messages */\r
+ const char *saved_text;\r
+\r
+ do\r
+ c = lex_get_save(lex, error);\r
+ while (l_isalpha(c));\r
+ lex_unget_unsave(lex, c);\r
+\r
+ saved_text = strbuffer_value(&lex->saved_text);\r
+\r
+ if (strcmp(saved_text, "true") == 0)\r
+ lex->token = TOKEN_TRUE;\r
+ else if (strcmp(saved_text, "false") == 0)\r
+ lex->token = TOKEN_FALSE;\r
+ else if (strcmp(saved_text, "null") == 0)\r
+ lex->token = TOKEN_NULL;\r
+ else\r
+ lex->token = TOKEN_INVALID;\r
+ }\r
+\r
+ else {\r
+ /* save the rest of the input UTF-8 sequence to get an error\r
+ message of valid UTF-8 */\r
+ lex_save_cached(lex);\r
+ lex->token = TOKEN_INVALID;\r
+ }\r
+\r
+out:\r
+ return lex->token;\r
+}\r
+\r
+static char *lex_steal_string(lex_t *lex, size_t *out_len) {\r
+ char *result = NULL;\r
+ if (lex->token == TOKEN_STRING) {\r
+ result = lex->value.string.val;\r
+ *out_len = lex->value.string.len;\r
+ lex->value.string.val = NULL;\r
+ lex->value.string.len = 0;\r
+ }\r
+ return result;\r
+}\r
+\r
+static int lex_init(lex_t *lex, get_func get, size_t flags, void *data) {\r
+ stream_init(&lex->stream, get, data);\r
+ if (strbuffer_init(&lex->saved_text))\r
+ return -1;\r
+\r
+ lex->flags = flags;\r
+ lex->token = TOKEN_INVALID;\r
+ return 0;\r
+}\r
+\r
+static void lex_close(lex_t *lex) {\r
+ if (lex->token == TOKEN_STRING)\r
+ lex_free_string(lex);\r
+ strbuffer_close(&lex->saved_text);\r
+}\r
+\r
+/*** parser ***/\r
+\r
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error);\r
+\r
+static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) {\r
+ json_t *object = json_object();\r
+ if (!object)\r
+ return NULL;\r
+\r
+ lex_scan(lex, error);\r
+ if (lex->token == '}')\r
+ return object;\r
+\r
+ while (1) {\r
+ char *key;\r
+ size_t len;\r
+ json_t *value;\r
+\r
+ if (lex->token != TOKEN_STRING) {\r
+ error_set(error, lex, json_error_invalid_syntax, "string or '}' expected");\r
+ goto error;\r
+ }\r
+\r
+ key = lex_steal_string(lex, &len);\r
+ if (!key)\r
+ return NULL;\r
+ if (memchr(key, '\0', len)) {\r
+ jsonp_free(key);\r
+ error_set(error, lex, json_error_null_byte_in_key,\r
+ "NUL byte in object key not supported");\r
+ goto error;\r
+ }\r
+\r
+ if (flags & JSON_REJECT_DUPLICATES) {\r
+ if (json_object_get(object, key)) {\r
+ jsonp_free(key);\r
+ error_set(error, lex, json_error_duplicate_key, "duplicate object key");\r
+ goto error;\r
+ }\r
+ }\r
+\r
+ lex_scan(lex, error);\r
+ if (lex->token != ':') {\r
+ jsonp_free(key);\r
+ error_set(error, lex, json_error_invalid_syntax, "':' expected");\r
+ goto error;\r
+ }\r
+\r
+ lex_scan(lex, error);\r
+ value = parse_value(lex, flags, error);\r
+ if (!value) {\r
+ jsonp_free(key);\r
+ goto error;\r
+ }\r
+\r
+ if (json_object_set_new_nocheck(object, key, value)) {\r
+ jsonp_free(key);\r
+ goto error;\r
+ }\r
+\r
+ jsonp_free(key);\r
+\r
+ lex_scan(lex, error);\r
+ if (lex->token != ',')\r
+ break;\r
+\r
+ lex_scan(lex, error);\r
+ }\r
+\r
+ if (lex->token != '}') {\r
+ error_set(error, lex, json_error_invalid_syntax, "'}' expected");\r
+ goto error;\r
+ }\r
+\r
+ return object;\r
+\r
+error:\r
+ json_decref(object);\r
+ return NULL;\r
+}\r
+\r
+static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error) {\r
+ json_t *array = json_array();\r
+ if (!array)\r
+ return NULL;\r
+\r
+ lex_scan(lex, error);\r
+ if (lex->token == ']')\r
+ return array;\r
+\r
+ while (lex->token) {\r
+ json_t *elem = parse_value(lex, flags, error);\r
+ if (!elem)\r
+ goto error;\r
+\r
+ if (json_array_append_new(array, elem)) {\r
+ goto error;\r
+ }\r
+\r
+ lex_scan(lex, error);\r
+ if (lex->token != ',')\r
+ break;\r
+\r
+ lex_scan(lex, error);\r
+ }\r
+\r
+ if (lex->token != ']') {\r
+ error_set(error, lex, json_error_invalid_syntax, "']' expected");\r
+ goto error;\r
+ }\r
+\r
+ return array;\r
+\r
+error:\r
+ json_decref(array);\r
+ return NULL;\r
+}\r
+\r
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) {\r
+ json_t *json;\r
+\r
+ lex->depth++;\r
+ if (lex->depth > JSON_PARSER_MAX_DEPTH) {\r
+ error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached");\r
+ return NULL;\r
+ }\r
+\r
+ switch (lex->token) {\r
+ case TOKEN_STRING: {\r
+ const char *value = lex->value.string.val;\r
+ size_t len = lex->value.string.len;\r
+\r
+ if (!(flags & JSON_ALLOW_NUL)) {\r
+ if (memchr(value, '\0', len)) {\r
+ error_set(error, lex, json_error_null_character,\r
+ "\\u0000 is not allowed without JSON_ALLOW_NUL");\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ json = jsonp_stringn_nocheck_own(value, len);\r
+ lex->value.string.val = NULL;\r
+ lex->value.string.len = 0;\r
+ break;\r
+ }\r
+\r
+ case TOKEN_INTEGER: {\r
+ json = json_integer(lex->value.integer);\r
+ break;\r
+ }\r
+\r
+ case TOKEN_REAL: {\r
+ json = json_real(lex->value.real);\r
+ break;\r
+ }\r
+\r
+ case TOKEN_TRUE:\r
+ json = json_true();\r
+ break;\r
+\r
+ case TOKEN_FALSE:\r
+ json = json_false();\r
+ break;\r
+\r
+ case TOKEN_NULL:\r
+ json = json_null();\r
+ break;\r
+\r
+ case '{':\r
+ json = parse_object(lex, flags, error);\r
+ break;\r
+\r
+ case '[':\r
+ json = parse_array(lex, flags, error);\r
+ break;\r
+\r
+ case TOKEN_INVALID:\r
+ error_set(error, lex, json_error_invalid_syntax, "invalid token");\r
+ return NULL;\r
+\r
+ default:\r
+ error_set(error, lex, json_error_invalid_syntax, "unexpected token");\r
+ return NULL;\r
+ }\r
+\r
+ if (!json)\r
+ return NULL;\r
+\r
+ lex->depth--;\r
+ return json;\r
+}\r
+\r
+static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) {\r
+ json_t *result;\r
+\r
+ lex->depth = 0;\r
+\r
+ lex_scan(lex, error);\r
+ if (!(flags & JSON_DECODE_ANY)) {\r
+ if (lex->token != '[' && lex->token != '{') {\r
+ error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected");\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ result = parse_value(lex, flags, error);\r
+ if (!result)\r
+ return NULL;\r
+\r
+ if (!(flags & JSON_DISABLE_EOF_CHECK)) {\r
+ lex_scan(lex, error);\r
+ if (lex->token != TOKEN_EOF) {\r
+ error_set(error, lex, json_error_end_of_input_expected,\r
+ "end of file expected");\r
+ json_decref(result);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ if (error) {\r
+ /* Save the position even though there was no error */\r
+ error->position = (int)lex->stream.position;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+typedef struct {\r
+ const char *data;\r
+ size_t pos;\r
+} string_data_t;\r
+\r
+static int string_get(void *data) {\r
+ char c;\r
+ string_data_t *stream = (string_data_t *)data;\r
+ c = stream->data[stream->pos];\r
+ if (c == '\0')\r
+ return EOF;\r
+ else {\r
+ stream->pos++;\r
+ return (unsigned char)c;\r
+ }\r
+}\r
+\r
+json_t *json_loads(const char *string, size_t flags, json_error_t *error) {\r
+ lex_t lex;\r
+ json_t *result;\r
+ string_data_t stream_data;\r
+\r
+ jsonp_error_init(error, "<string>");\r
+\r
+ if (string == NULL) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ stream_data.data = string;\r
+ stream_data.pos = 0;\r
+\r
+ if (lex_init(&lex, string_get, flags, (void *)&stream_data))\r
+ return NULL;\r
+\r
+ result = parse_json(&lex, flags, error);\r
+\r
+ lex_close(&lex);\r
+ return result;\r
+}\r
+\r
+typedef struct {\r
+ const char *data;\r
+ size_t len;\r
+ size_t pos;\r
+} buffer_data_t;\r
+\r
+static int buffer_get(void *data) {\r
+ char c;\r
+ buffer_data_t *stream = data;\r
+ if (stream->pos >= stream->len)\r
+ return EOF;\r
+\r
+ c = stream->data[stream->pos];\r
+ stream->pos++;\r
+ return (unsigned char)c;\r
+}\r
+\r
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) {\r
+ lex_t lex;\r
+ json_t *result;\r
+ buffer_data_t stream_data;\r
+\r
+ jsonp_error_init(error, "<buffer>");\r
+\r
+ if (buffer == NULL) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ stream_data.data = buffer;\r
+ stream_data.pos = 0;\r
+ stream_data.len = buflen;\r
+\r
+ if (lex_init(&lex, buffer_get, flags, (void *)&stream_data))\r
+ return NULL;\r
+\r
+ result = parse_json(&lex, flags, error);\r
+\r
+ lex_close(&lex);\r
+ return result;\r
+}\r
+\r
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) {\r
+ lex_t lex;\r
+ const char *source;\r
+ json_t *result;\r
+#ifdef HAVE_UNISTD_H\r
+ if (input == stdin)\r
+ source = "<stdin>";\r
+ else\r
+#endif\r
+ source = "<stream>";\r
+\r
+ jsonp_error_init(error, source);\r
+\r
+ if (input == NULL) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ if (lex_init(&lex, (get_func)fgetc, flags, input))\r
+ return NULL;\r
+\r
+ result = parse_json(&lex, flags, error);\r
+\r
+ lex_close(&lex);\r
+ return result;\r
+}\r
+\r
+static int fd_get_func(int *fd) {\r
+#ifdef HAVE_UNISTD_H\r
+ uint8_t c;\r
+ if (read(*fd, &c, 1) == 1)\r
+ return c;\r
+#endif\r
+ return EOF;\r
+}\r
+\r
+json_t *json_loadfd(int input, size_t flags, json_error_t *error) {\r
+ lex_t lex;\r
+ const char *source;\r
+ json_t *result;\r
+\r
+#ifdef HAVE_UNISTD_H\r
+ if (input == STDIN_FILENO)\r
+ source = "<stdin>";\r
+ else\r
+#endif\r
+ source = "<stream>";\r
+\r
+ jsonp_error_init(error, source);\r
+\r
+ if (input < 0) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ if (lex_init(&lex, (get_func)fd_get_func, flags, &input))\r
+ return NULL;\r
+\r
+ result = parse_json(&lex, flags, error);\r
+\r
+ lex_close(&lex);\r
+ return result;\r
+}\r
+\r
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error) {\r
+ json_t *result;\r
+ FILE *fp;\r
+\r
+ jsonp_error_init(error, path);\r
+\r
+ if (path == NULL) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ fp = fopen(path, "rb");\r
+ if (!fp) {\r
+ error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s", path,\r
+ strerror(errno));\r
+ return NULL;\r
+ }\r
+\r
+ result = json_loadf(fp, flags, error);\r
+\r
+ fclose(fp);\r
+ return result;\r
+}\r
+\r
+#define MAX_BUF_LEN 1024\r
+\r
+typedef struct {\r
+ char data[MAX_BUF_LEN];\r
+ size_t len;\r
+ size_t pos;\r
+ json_load_callback_t callback;\r
+ void *arg;\r
+} callback_data_t;\r
+\r
+static int callback_get(void *data) {\r
+ char c;\r
+ callback_data_t *stream = data;\r
+\r
+ if (stream->pos >= stream->len) {\r
+ stream->pos = 0;\r
+ stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg);\r
+ if (stream->len == 0 || stream->len == (size_t)-1)\r
+ return EOF;\r
+ }\r
+\r
+ c = stream->data[stream->pos];\r
+ stream->pos++;\r
+ return (unsigned char)c;\r
+}\r
+\r
+json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags,\r
+ json_error_t *error) {\r
+ lex_t lex;\r
+ json_t *result;\r
+\r
+ callback_data_t stream_data;\r
+\r
+ memset(&stream_data, 0, sizeof(stream_data));\r
+ stream_data.callback = callback;\r
+ stream_data.arg = arg;\r
+\r
+ jsonp_error_init(error, "<callback>");\r
+\r
+ if (callback == NULL) {\r
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");\r
+ return NULL;\r
+ }\r
+\r
+ if (lex_init(&lex, (get_func)callback_get, flags, &stream_data))\r
+ return NULL;\r
+\r
+ result = parse_json(&lex, flags, error);\r
+\r
+ lex_close(&lex);\r
+ return result;\r
+}\r
"PrivateInclude/Crt/string.h",\r
"PrivateInclude/Crt/time.h",\r
"PrivateInclude/Library/RedfishCrtLib.h",\r
- "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c"\r
+ "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c",\r
+ ##\r
+ ## For jansson library open source\r
+ ## load.c is overrided from open source.\r
+ "Library/JsonLib/load.c",\r
+ "Library/JsonLib/jansson_config.h",\r
+ "Library/JsonLib/jansson_private_config.h"\r
]\r
},\r
"CompilerPlugin": {\r
[Includes.Common.Private]\r
PrivateInclude # Private header files for C RTL.\r
PrivateInclude/Crt # Private header files for C RTL.\r
+ Library/JsonLib # Private header files for jansson\r
+ # configuration files.\r
+ # - jansson_config.h\r
+ # - jansson_private_config.h\r
+ # jansson.h refers to above two configuration\r
+ # files for building platform jansson library.\r
+ Library/JsonLib/jansson/src # For referring to jannson.h\r
\r
[LibraryClasses]\r
## @libraryclass Platform Redfish Host Interface Library\r
# This library is only intended to be used by UEFI network stack modules.\r
RestExLib|Include/Library/RestExLib.h\r
\r
+ ## @libraryclass Provides the library functions based on third party\r
+ # jansson library to manipulate JSON data structure.\r
+ #\r
+ JsonLib|Include/Library/JsonLib.h\r
+\r
[LibraryClasses.Common.Private]\r
## @libraryclass Provides the private C runtime library functions.\r
# CRT library is currently used by edk2 JsonLib (open source\r