diff --git a/cmake/FindJSONC.cmake b/cmake/FindJSONC.cmake deleted file mode 100644 index 68ccc7359..000000000 --- a/cmake/FindJSONC.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# - Try to find JSON-C -# Once done this will define -# -# JSONC_FOUND - JSON-C was found -# JSONC_INCLUDE_DIRS - JSON-C include directories -# JSONC_LIBRARIES - libraries needed for linking - -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_JSONC json-c) -endif() - -find_path(JSONC_INCLUDE_DIR NAMES json.h HINTS ${PC_JSONC_INCLUDE_DIRS} PATH_SUFFIXES json-c) -find_library(JSONC_LIBRARY NAMES json-c HINTS ${PC_JSONC_LIBRARY_DIRS}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(JSONC DEFAULT_MSG JSONC_LIBRARY JSONC_INCLUDE_DIR) - -if(JSONC_FOUND) - set(JSONC_LIBRARIES ${JSONC_LIBRARY}) - set(JSONC_INCLUDE_DIRS ${JSONC_INCLUDE_DIR}) -endif() - -mark_as_advanced(JSONC_LIBRARY JSONC_INCLUDE_DIR) diff --git a/cmake/JsonDetect.cmake b/cmake/JsonDetect.cmake index 6625b6f71..4bbb5e8de 100644 --- a/cmake/JsonDetect.cmake +++ b/cmake/JsonDetect.cmake @@ -1,59 +1,83 @@ +function(detect_package name pkgconf cmake-target) + set(options REQUIRED) + cmake_parse_arguments(PARSE_ARGV 0 arg "${options}" "${oneValueArgs}" "${multiValueArgs}") + + find_package(${name}) + if(NOT ${name}_FOUND) + # Fallback detection: + # older ubuntu releases did not ship CMake or pkg-config files + # for ${pkgconf}. Be optimistic and try pkg-config and as last resort + # try manual detection + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(${name} ${pkgconf}) + + if(${name}_FOUND) + # Create imported target cjson + add_library(${cmake-target} SHARED IMPORTED) + set_property(TARGET ${cmake-target} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG) + set_target_properties( + ${cmake-target} + PROPERTIES IMPORTED_CONFIGURATIONS NOCONFIG IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C" + IMPORTED_LOCATION_NOCONFIG "${${name}_LINK_LIBRARIES}" IMPORTED_SONAME_NOCONFIG + "${${name}_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${${name}_INCLUDE_DIRS}" + ) + endif() + endif() + endif() + + if(NOT ${name}_FOUND AND arg_REQUIRED) + message(FATAL_ERROR "${name} was REQUIRED but not found") + endif() + + if(${${name}_FOUND}) + set(${name}_FOUND ${${name}_FOUND} CACHE INTERNAL "internal") + else() + unset(${name}_FOUND CACHE) + endif() +endfunction() + include(CMakeDependentOption) option(WITH_JSON_DISABLED "Build without any JSON support" OFF) cmake_dependent_option( - WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF "NOT WITH_JSON_DISABLED;NOT WITH_JSONC_REQUIRED" OFF + WITH_CJSON_REQUIRED "Build with cJSON (fail if not found)" OFF + "NOT WITH_JSON_DISABLED;NOT WITH_JSONC_REQUIRED;NOT WITH_JANSSON_REQUIRED" OFF ) cmake_dependent_option( - WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF "NOT WITH_JSON_DISABLED;NOT WITH_CJSON_REQUIRED" OFF + WITH_JSONC_REQUIRED "Build with JSON-C (fail if not found)" OFF + "NOT WITH_JSON_DISABLED;NOT WITH_CJSON_REQUIRED;NOT WITH_JANSSON_REQUIRED" OFF ) +cmake_dependent_option( + WITH_JANSSON_REQUIRED "Build with JANSSON (fail if not found)" OFF + "NOT WITH_JSON_DISABLED;NOT WITH_CJSON_REQUIRED;NOT WITH_JSONC_REQUIRED" OFF +) + +# ensure no package is enabled before the detection starts +unset(json-c_FOUND CACHE) +unset(cJSON_FOUND CACHE) +unset(jansson_FOUND CACHE) if(NOT WITH_JSON_DISABLED) - if(NOT WITH_JSONC_REQUIRED) - find_package(cJSON) - - # Fallback detection: - # older ubuntu releases did not ship CMake or pkg-config files - # for cJSON. Be optimistic and try pkg-config and as last resort - # try manual detection - if(NOT CJSON_FOUND) - find_package(PkgConfig) - if(PKG_CONFIG_FOUND) - pkg_check_modules(CJSON libcjson) - endif() - - if(NOT CJSON_FOUND) - find_path(CJSON_INCLUDE_DIRS NAMES cjson/cJSON.h) - find_library(CJSON_LIBRARIES NAMES cjson) - if(NOT "${CJSON_LIBRARIES}" STREQUAL "CJSON_LIBRARIES-NOTFOUND" AND NOT "${CJSON_INCLUDE_DIRS}" STREQUAL - "CJSON_INCLUDE_DIRS-NOTFOUND" - ) - set(CJSON_FOUND ON) - endif() - endif() - endif() - - if(WITH_CJSON_REQUIRED) - if(NOT CJSON_FOUND) - message(FATAL_ERROR "cJSON was requested but not found") - endif() - endif() + if(WITH_JANSSON_REQUIRED) + detect_package(jansson jansson jansson::jansson REQUIRED) + elseif(WITH_JSONC_REQUIRED) + detect_package(json-c json-c json-c::json-c REQUIRED) + elseif(WITH_CJSON_REQUIRED) + detect_package(cJSON libcjson cjson REQUIRED) else() - unset(CJSON_FOUND) + # nothing required, so do a non fatal check for all + detect_package(jansson jansson jansson::jansson) + detect_package(json-c json-c json-c::json-c) + detect_package(cJSON libcjson cjson) endif() - if(WITH_JSONC_REQUIRED) - find_package(JSONC REQUIRED) - elseif(NOT WITH_CJSON_REQUIRED) - find_package(JSONC) - endif() - - if(WITH_CJSON_REQUIRED) - unset(JSONC_FOUND) - endif() - - if(NOT JSONC_FOUND AND NOT CJSON_FOUND) - if(WITH_CJSON_REQUIRED OR WITH_JSONC_REQUIRED) - message(FATAL_ERROR "cJSON (${WITH_CJSON_REQUIRED}) or json-c (${WITH_JSONC_REQUIRED}) required but not found") + if(NOT json-c_FOUND AND NOT cJSON_FOUND AND NOT jansson_FOUND) + if(WITH_CJSON_REQUIRED OR WITH_JSONC_REQUIRED OR WITH_JANSSON_REQUIRED) + message( + FATAL_ERROR + "cJSON (${WITH_CJSON_REQUIRED}) or json-c (${WITH_JSONC_REQUIRED}) or jansson (${WITH_JANSSON_REQUIRED}) required but not found" + ) endif() set(WITH_WINPR_JSON OFF CACHE INTERNAL "internal") message("compiling without JSON support. Install cJSON or json-c to enable") diff --git a/winpr/include/winpr/json.h b/winpr/include/winpr/json.h index a765161c5..c06296ba6 100644 --- a/winpr/include/winpr/json.h +++ b/winpr/include/winpr/json.h @@ -27,7 +27,7 @@ /** @defgroup WINPR_JSON WinPR JSON wrapper * @since version 3.6.0 - * @brief Wrapper around cJSON or JSONC libraries + * @brief Wrapper around cJSON, JSONC or jansson libraries * @{ */ diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 4b856b2c0..a4692a3ac 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -186,21 +186,30 @@ if(WINPR_HAVE_UNWIND_H) endif() endif() -include(JsonDetect) if(NOT WITH_JSON_DISABLED) - if(JSONC_FOUND AND NOT WITH_CJSON_REQUIRED) - winpr_library_add_private(${JSONC_LIBRARIES}) + if(jansson_FOUND) + winpr_library_add_private(jansson::jansson) + winpr_pc_add_requires_private("jansson") + winpr_definition_add(WITH_JANSSON) + winpr_module_add(json/jansson.c) + set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") + elseif(json-c_FOUND) + winpr_library_add_private(json-c::json-c) winpr_pc_add_requires_private("json-c") - winpr_system_include_directory_add(${JSONC_INCLUDE_DIRS}) winpr_definition_add(WITH_JSONC) + winpr_module_add(json/json-c.c) set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") - elseif(CJSON_FOUND) - winpr_library_add_private(${CJSON_LIBRARIES}) + elseif(cJSON_FOUND) + winpr_library_add_private(cjson) winpr_pc_add_requires_private("libcjson") - winpr_system_include_directory_add(${CJSON_INCLUDE_DIRS}) winpr_definition_add(WITH_CJSON) + winpr_module_add(json/c-json.c) set(WITH_WINPR_JSON ON CACHE INTERNAL "internal") + else() + winpr_module_add(json/json-stub.c) endif() +else() + winpr_module_add(json/json-stub.c) endif() winpr_module_add(json/json.c) diff --git a/winpr/libwinpr/utils/json/c-json.c b/winpr/libwinpr/utils/json/c-json.c new file mode 100644 index 000000000..bd95d77e7 --- /dev/null +++ b/winpr/libwinpr/utils/json/c-json.c @@ -0,0 +1,297 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2024 Armin Novak + * Copyright 2024 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include + +#if !defined(WITH_CJSON) +#error "This file must only be compiled when cJSON is enabled" +#endif +#include + +#if defined(WITH_CJSON) +#if CJSON_VERSION_MAJOR == 1 +#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13)) +#define USE_CJSON_COMPAT +#endif +#endif +#endif + +#if defined(USE_CJSON_COMPAT) +static double cJSON_GetNumberValue(const cJSON* prop) +{ +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#define COMPAT_NAN_UNDEF +#else +#define NAN 0.0 / 0.0 +#define COMPAT_NAN_UNDEF +#endif +#endif + + if (!cJSON_IsNumber(prop)) + return NAN; + char* val = cJSON_GetStringValue(prop); + if (!val) + return NAN; + + errno = 0; + char* endptr = NULL; + double dval = strtod(val, &endptr); + if (val == endptr) + return NAN; + if (endptr != NULL) + return NAN; + if (errno != 0) + return NAN; + return dval; + +#ifdef COMPAT_NAN_UNDEF +#undef NAN +#endif +} + +static cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length) +{ + // Check for string '\0' termination. + const size_t slen = strnlen(value, buffer_length); + if (slen >= buffer_length) + { + if (value[buffer_length] != '\0') + return NULL; + } + return cJSON_Parse(value); +} +#endif + +int WINPR_JSON_version(char* buffer, size_t len) +{ + return _snprintf(buffer, len, "cJSON %s", cJSON_Version()); +} + +WINPR_JSON* WINPR_JSON_Parse(const char* value) +{ + return cJSON_Parse(value); +} + +WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) +{ + return cJSON_ParseWithLength(value, buffer_length); +} + +void WINPR_JSON_Delete(WINPR_JSON* item) +{ + cJSON_Delete((cJSON*)item); +} + +WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) +{ + WINPR_ASSERT(index <= INT_MAX); + return cJSON_GetArrayItem((const cJSON*)array, (INT)index); +} + +size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) +{ + const int rc = cJSON_GetArraySize((const cJSON*)array); + if (rc <= 0) + return 0; + return (size_t)rc; +} + +WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string) +{ + return cJSON_GetObjectItem((const cJSON*)object, string); +} + +WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string) +{ + return cJSON_GetObjectItemCaseSensitive((const cJSON*)object, string); +} + +BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) +{ + return cJSON_HasObjectItem((const cJSON*)object, string); +} + +const char* WINPR_JSON_GetErrorPtr(void) +{ + return cJSON_GetErrorPtr(); +} + +const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) +{ + return cJSON_GetStringValue((cJSON*)item); +} + +double WINPR_JSON_GetNumberValue(const WINPR_JSON* item) +{ + return cJSON_GetNumberValue((const cJSON*)item); +} + +BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item) +{ + return cJSON_IsInvalid((const cJSON*)item); +} + +BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item) +{ + return cJSON_IsFalse((const cJSON*)item); +} + +BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item) +{ + return cJSON_IsTrue((const cJSON*)item); +} + +BOOL WINPR_JSON_IsBool(const WINPR_JSON* item) +{ + return cJSON_IsBool((const cJSON*)item); +} + +BOOL WINPR_JSON_IsNull(const WINPR_JSON* item) +{ + return cJSON_IsNull((const cJSON*)item); +} + +BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item) +{ + return cJSON_IsNumber((const cJSON*)item); +} + +BOOL WINPR_JSON_IsString(const WINPR_JSON* item) +{ + return cJSON_IsString((const cJSON*)item); +} + +BOOL WINPR_JSON_IsArray(const WINPR_JSON* item) +{ + return cJSON_IsArray((const cJSON*)item); +} + +BOOL WINPR_JSON_IsObject(const WINPR_JSON* item) +{ + return cJSON_IsObject((const cJSON*)item); +} + +WINPR_JSON* WINPR_JSON_CreateNull(void) +{ + return cJSON_CreateNull(); +} + +WINPR_JSON* WINPR_JSON_CreateTrue(void) +{ + return cJSON_CreateTrue(); +} + +WINPR_JSON* WINPR_JSON_CreateFalse(void) +{ + return cJSON_CreateFalse(); +} + +WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) +{ + return cJSON_CreateBool(boolean); +} + +WINPR_JSON* WINPR_JSON_CreateNumber(double num) +{ + return cJSON_CreateNumber(num); +} + +WINPR_JSON* WINPR_JSON_CreateString(const char* string) +{ + return cJSON_CreateString(string); +} + +WINPR_JSON* WINPR_JSON_CreateArray(void) +{ + return cJSON_CreateArray(); +} + +WINPR_JSON* WINPR_JSON_CreateObject(void) +{ + return cJSON_CreateObject(); +} + +WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name) +{ + return cJSON_AddNullToObject((cJSON*)object, name); +} + +WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name) +{ + return cJSON_AddTrueToObject((cJSON*)object, name); +} + +WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name) +{ + return cJSON_AddFalseToObject((cJSON*)object, name); +} + +WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean) +{ + return cJSON_AddBoolToObject((cJSON*)object, name, boolean); +} + +WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number) +{ + return cJSON_AddNumberToObject((cJSON*)object, name, number); +} + +WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) +{ + return cJSON_AddStringToObject((cJSON*)object, name, string); +} + +WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name) +{ + return cJSON_AddObjectToObject((cJSON*)object, name); +} + +BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item) +{ +#if defined(USE_CJSON_COMPAT) + if ((array == NULL) || (item == NULL)) + return FALSE; + cJSON_AddItemToArray((cJSON*)array, (cJSON*)item); + return TRUE; +#else + return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item); +#endif +} + +WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name) +{ + return cJSON_AddArrayToObject((cJSON*)object, name); +} + +char* WINPR_JSON_Print(WINPR_JSON* item) +{ + return cJSON_Print((const cJSON*)item); +} + +char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) +{ + return cJSON_PrintUnformatted((const cJSON*)item); +} diff --git a/winpr/libwinpr/utils/json/jansson.c b/winpr/libwinpr/utils/json/jansson.c new file mode 100644 index 000000000..501d3fe72 --- /dev/null +++ b/winpr/libwinpr/utils/json/jansson.c @@ -0,0 +1,266 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2025 Armin Novak + * Copyright 2025 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +#if !defined(WITH_JANSSON) +#error "This file must only be compiled if jansson library is linked in" +#endif +#include + +int WINPR_JSON_version(char* buffer, size_t len) +{ + return _snprintf(buffer, len, "jansson %s", jansson_version_str()); +} + +WINPR_JSON* WINPR_JSON_Parse(const char* value) +{ + json_error_t error = { 0 }; + return json_loads(value, JSON_DECODE_ANY, &error); +} + +WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) +{ + json_error_t error = { 0 }; + return json_loadb(value, buffer_length, JSON_DECODE_ANY, &error); +} + +void WINPR_JSON_Delete(WINPR_JSON* item) +{ + json_delete((json_t*)item); +} + +WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) +{ + return json_array_get(array, index); +} + +size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) +{ + return json_array_size(array); +} + +WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string) +{ + void* it = json_object_iter((json_t*)object); + while (it) + { + const char* name = json_object_iter_key(it); + if (_stricmp(name, string) == 0) + return json_object_iter_value(it); + it = json_object_iter_next((json_t*)object, it); + } + return NULL; +} + +WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string) +{ + return json_object_get(object, string); +} + +BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) +{ + return json_object_get(object, string) != NULL; +} + +const char* WINPR_JSON_GetErrorPtr(void) +{ + return NULL; +} + +const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) +{ + return json_string_value(item); +} + +double WINPR_JSON_GetNumberValue(const WINPR_JSON* item) +{ + return json_real_value((const json_t*)item); +} + +BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item) +{ + if (WINPR_JSON_IsArray(item)) + return FALSE; + if (WINPR_JSON_IsObject(item)) + return FALSE; + if (WINPR_JSON_IsNull(item)) + return FALSE; + if (WINPR_JSON_IsNumber(item)) + return FALSE; + if (WINPR_JSON_IsBool(item)) + return FALSE; + if (WINPR_JSON_IsString(item)) + return FALSE; + return TRUE; +} + +BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item) +{ + return json_is_false((const json_t*)item); +} + +BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item) +{ + return json_is_true((const json_t*)item); +} + +BOOL WINPR_JSON_IsBool(const WINPR_JSON* item) +{ + return json_is_boolean((const json_t*)item); +} + +BOOL WINPR_JSON_IsNull(const WINPR_JSON* item) +{ + return json_is_null((const json_t*)item); +} + +BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item) +{ + return json_is_number((const json_t*)item); +} + +BOOL WINPR_JSON_IsString(const WINPR_JSON* item) +{ + return json_is_string((const json_t*)item); +} + +BOOL WINPR_JSON_IsArray(const WINPR_JSON* item) +{ + return json_is_array((const json_t*)item); +} + +BOOL WINPR_JSON_IsObject(const WINPR_JSON* item) +{ + return json_is_array((const json_t*)item); +} + +WINPR_JSON* WINPR_JSON_CreateNull(void) +{ + return json_null(); +} + +WINPR_JSON* WINPR_JSON_CreateTrue(void) +{ + return json_true(); +} + +WINPR_JSON* WINPR_JSON_CreateFalse(void) +{ + return json_false(); +} + +WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) +{ + return json_boolean(boolean); +} + +WINPR_JSON* WINPR_JSON_CreateNumber(double num) +{ + return json_real(num); +} + +WINPR_JSON* WINPR_JSON_CreateString(const char* string) +{ + return json_string(string); +} + +WINPR_JSON* WINPR_JSON_CreateArray(void) +{ + return json_array(); +} + +WINPR_JSON* WINPR_JSON_CreateObject(void) +{ + return json_object(); +} + +static WINPR_JSON* add_to_object(WINPR_JSON* object, const char* name, json_t* obj) +{ + if (!obj) + return NULL; + if (json_object_set_new(object, name, obj) != 0) + return NULL; + return obj; +} + +WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name) +{ + json_t* obj = json_null(); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name) +{ + json_t* obj = json_true(); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name) +{ + json_t* obj = json_false(); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean) +{ + json_t* obj = json_boolean(boolean); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number) +{ + json_t* obj = json_real(number); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) +{ + json_t* obj = json_string(string); + return add_to_object(object, name, obj); +} + +WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name) +{ + json_t* obj = json_object(); + return add_to_object(object, name, obj); +} + +BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item) +{ + return json_array_append(array, item) == 0; +} + +WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name) +{ + json_t* obj = json_array(); + return add_to_object(object, name, obj); +} + +char* WINPR_JSON_Print(WINPR_JSON* item) +{ + return json_dumps(item, JSON_INDENT(2) | JSON_ENSURE_ASCII | JSON_SORT_KEYS); +} + +char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) +{ + return json_dumps(item, JSON_COMPACT | JSON_ENSURE_ASCII | JSON_SORT_KEYS); +} diff --git a/winpr/libwinpr/utils/json/json-c.c b/winpr/libwinpr/utils/json/json-c.c new file mode 100644 index 000000000..1fde41331 --- /dev/null +++ b/winpr/libwinpr/utils/json/json-c.c @@ -0,0 +1,332 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2024 Armin Novak + * Copyright 2024 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include + +#if !defined(WITH_JSONC) +#error "This file must only be compiled when json-c is enabled" +#endif +#include + +#if JSON_C_MAJOR_VERSION == 0 +#if JSON_C_MINOR_VERSION < 14 +static struct json_object* json_object_new_null(void) +{ + return NULL; +} +#endif +#endif + +int WINPR_JSON_version(char* buffer, size_t len) +{ + return _snprintf(buffer, len, "json-c %s", json_c_version()); +} + +WINPR_JSON* WINPR_JSON_Parse(const char* value) +{ + return json_tokener_parse(value); +} + +WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) +{ + WINPR_ASSERT(buffer_length <= INT_MAX); + json_tokener* tok = json_tokener_new(); + if (!tok) + return NULL; + json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length); + json_tokener_free(tok); + return obj; +} + +void WINPR_JSON_Delete(WINPR_JSON* item) +{ + json_object_put((json_object*)item); +} + +WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) +{ + return json_object_array_get_idx((const json_object*)array, index); +} + +size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) +{ + return json_object_array_length((const json_object*)array); +} + +WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string) +{ + struct json_object_iterator it = json_object_iter_begin((const json_object*)object); + struct json_object_iterator itEnd = json_object_iter_end((const json_object*)object); + while (!json_object_iter_equal(&it, &itEnd)) + { + const char* key = json_object_iter_peek_name(&it); + if (_stricmp(key, string) == 0) + { + return json_object_iter_peek_value(&it); + } + json_object_iter_next(&it); + } + return NULL; +} + +WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string) +{ + return json_object_object_get((const json_object*)object, string); +} + +BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) +{ + return json_object_object_get_ex((const json_object*)object, string, NULL); +} + +const char* WINPR_JSON_GetErrorPtr(void) +{ + return json_util_get_last_err(); +} + +const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) +{ + return json_object_get_string((json_object*)item); +} + +double WINPR_JSON_GetNumberValue(const WINPR_JSON* item) +{ + return json_object_get_double((const json_object*)item); +} + +BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item) +{ + if (WINPR_JSON_IsArray(item)) + return FALSE; + if (WINPR_JSON_IsObject(item)) + return FALSE; + if (WINPR_JSON_IsNull(item)) + return FALSE; + if (WINPR_JSON_IsNumber(item)) + return FALSE; + if (WINPR_JSON_IsBool(item)) + return FALSE; + if (WINPR_JSON_IsString(item)) + return FALSE; + return TRUE; +} + +BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item) +{ + if (!json_object_is_type((const json_object*)item, json_type_boolean)) + return FALSE; + json_bool val = json_object_get_boolean((const json_object*)item); + return val == 0; +} + +BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item) +{ + if (!json_object_is_type((const json_object*)item, json_type_boolean)) + return FALSE; + json_bool val = json_object_get_boolean((const json_object*)item); + return val != 0; +} + +BOOL WINPR_JSON_IsBool(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_boolean); +} + +BOOL WINPR_JSON_IsNull(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_null); +} + +BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_int) || + json_object_is_type((const json_object*)item, json_type_double); +} + +BOOL WINPR_JSON_IsString(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_string); +} + +BOOL WINPR_JSON_IsArray(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_array); +} + +BOOL WINPR_JSON_IsObject(const WINPR_JSON* item) +{ + return json_object_is_type((const json_object*)item, json_type_object); +} + +WINPR_JSON* WINPR_JSON_CreateNull(void) +{ + return json_object_new_null(); +} + +WINPR_JSON* WINPR_JSON_CreateTrue(void) +{ + return json_object_new_boolean(TRUE); +} + +WINPR_JSON* WINPR_JSON_CreateFalse(void) +{ + return json_object_new_boolean(FALSE); +} + +WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) +{ + return json_object_new_boolean(boolean); +} + +WINPR_JSON* WINPR_JSON_CreateNumber(double num) +{ + return json_object_new_double(num); +} + +WINPR_JSON* WINPR_JSON_CreateString(const char* string) +{ + return json_object_new_string(string); +} + +WINPR_JSON* WINPR_JSON_CreateArray(void) +{ + return json_object_new_array(); +} + +WINPR_JSON* WINPR_JSON_CreateObject(void) +{ + return json_object_new_object(); +} + +WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name) +{ + struct json_object* obj = json_object_new_null(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name) +{ + struct json_object* obj = json_object_new_boolean(TRUE); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name) +{ + struct json_object* obj = json_object_new_boolean(FALSE); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean) +{ + struct json_object* obj = json_object_new_boolean(boolean); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number) +{ + struct json_object* obj = json_object_new_double(number); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) +{ + struct json_object* obj = json_object_new_string(string); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name) +{ + struct json_object* obj = json_object_new_object(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item) +{ + const int rc = json_object_array_add((json_object*)array, (json_object*)item); + if (rc != 0) + return FALSE; + return TRUE; +} + +WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name) +{ + struct json_object* obj = json_object_new_array(); + if (json_object_object_add((json_object*)object, name, obj) != 0) + { + json_object_put(obj); + return NULL; + } + return obj; +} + +char* WINPR_JSON_Print(WINPR_JSON* item) +{ + const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY); + if (!str) + return NULL; + return _strdup(str); +} + +char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) +{ + const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN); + if (!str) + return NULL; + return _strdup(str); +} diff --git a/winpr/libwinpr/utils/json/json-stub.c b/winpr/libwinpr/utils/json/json-stub.c new file mode 100644 index 000000000..cb4bad1f8 --- /dev/null +++ b/winpr/libwinpr/utils/json/json-stub.c @@ -0,0 +1,275 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * JSON parser wrapper + * + * Copyright 2024 Armin Novak + * Copyright 2024 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include + +int WINPR_JSON_version(char* buffer, size_t len) +{ + (void)_snprintf(buffer, len, "JSON support not available"); + return -1; +} + +WINPR_JSON* WINPR_JSON_Parse(const char* value) +{ + WINPR_UNUSED(value); + return NULL; +} + +WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) +{ + WINPR_UNUSED(value); + WINPR_UNUSED(buffer_length); + return NULL; +} + +void WINPR_JSON_Delete(WINPR_JSON* item) +{ + WINPR_UNUSED(item); +} + +WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) +{ + WINPR_UNUSED(array); + WINPR_UNUSED(index); + return NULL; +} + +size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) +{ + WINPR_UNUSED(array); + return 0; +} + +WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return NULL; +} + +WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return NULL; +} + +BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(string); + return FALSE; +} + +const char* WINPR_JSON_GetErrorPtr(void) +{ + return NULL; +} + +const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return NULL; +} + +double WINPR_JSON_GetNumberValue(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return nan(""); +} + +BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return TRUE; +} + +BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsBool(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsNull(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsString(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsArray(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +BOOL WINPR_JSON_IsObject(const WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return FALSE; +} + +WINPR_JSON* WINPR_JSON_CreateNull(void) +{ + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateTrue(void) +{ + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateFalse(void) +{ + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) +{ + WINPR_UNUSED(boolean); + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateNumber(double num) +{ + WINPR_UNUSED(num); + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateString(const char* string) +{ + WINPR_UNUSED(string); + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateArray(void) +{ + return NULL; +} + +WINPR_JSON* WINPR_JSON_CreateObject(void) +{ + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(boolean); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(number); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + WINPR_UNUSED(string); + return NULL; +} + +WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +} + +BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item) +{ + WINPR_UNUSED(array); + WINPR_UNUSED(item); + return FALSE; +} + +WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name) +{ + WINPR_UNUSED(object); + WINPR_UNUSED(name); + return NULL; +} + +char* WINPR_JSON_Print(WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return NULL; +} + +char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) +{ + WINPR_UNUSED(item); + return NULL; +} diff --git a/winpr/libwinpr/utils/json/json.c b/winpr/libwinpr/utils/json/json.c index 62f08f2df..c92b25d33 100644 --- a/winpr/libwinpr/utils/json/json.c +++ b/winpr/libwinpr/utils/json/json.c @@ -24,674 +24,6 @@ #include #include -#if defined(WITH_CJSON) -#include -#endif -#if defined(WITH_JSONC) -#include -#endif - -#if defined(WITH_CJSON) -#if CJSON_VERSION_MAJOR == 1 -#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13)) -#define USE_CJSON_COMPAT -#endif -#endif -#endif - -#if defined(WITH_JSONC) -#if JSON_C_MAJOR_VERSION == 0 -#if JSON_C_MINOR_VERSION < 14 -static struct json_object* json_object_new_null(void) -{ - return NULL; -} -#endif -#endif -#endif - -#if defined(USE_CJSON_COMPAT) -static double cJSON_GetNumberValue(const cJSON* prop) -{ -#ifndef NAN -#ifdef _WIN32 -#define NAN sqrt(-1.0) -#define COMPAT_NAN_UNDEF -#else -#define NAN 0.0 / 0.0 -#define COMPAT_NAN_UNDEF -#endif -#endif - - if (!cJSON_IsNumber(prop)) - return NAN; - char* val = cJSON_GetStringValue(prop); - if (!val) - return NAN; - - errno = 0; - char* endptr = NULL; - double dval = strtod(val, &endptr); - if (val == endptr) - return NAN; - if (endptr != NULL) - return NAN; - if (errno != 0) - return NAN; - return dval; - -#ifdef COMPAT_NAN_UNDEF -#undef NAN -#endif -} - -static cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length) -{ - // Check for string '\0' termination. - const size_t slen = strnlen(value, buffer_length); - if (slen >= buffer_length) - { - if (value[buffer_length] != '\0') - return NULL; - } - return cJSON_Parse(value); -} -#endif - -int WINPR_JSON_version(char* buffer, size_t len) -{ -#if defined(WITH_JSONC) - return _snprintf(buffer, len, "json-c %s", json_c_version()); -#elif defined(WITH_CJSON) - return _snprintf(buffer, len, "cJSON %s", cJSON_Version()); -#else - (void)_snprintf(buffer, len, "JSON support not available"); - return -1; -#endif -} - -WINPR_JSON* WINPR_JSON_Parse(const char* value) -{ -#if defined(WITH_JSONC) - return json_tokener_parse(value); -#elif defined(WITH_CJSON) - return cJSON_Parse(value); -#else - WINPR_UNUSED(value); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length) -{ -#if defined(WITH_JSONC) - WINPR_ASSERT(buffer_length <= INT_MAX); - json_tokener* tok = json_tokener_new(); - if (!tok) - return NULL; - json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length); - json_tokener_free(tok); - return obj; -#elif defined(WITH_CJSON) - return cJSON_ParseWithLength(value, buffer_length); -#else - WINPR_UNUSED(value); - WINPR_UNUSED(buffer_length); - return NULL; -#endif -} - -void WINPR_JSON_Delete(WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - json_object_put((json_object*)item); -#elif defined(WITH_CJSON) - cJSON_Delete((cJSON*)item); -#else - WINPR_UNUSED(item); -#endif -} - -WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index) -{ -#if defined(WITH_JSONC) - return json_object_array_get_idx((const json_object*)array, index); -#elif defined(WITH_CJSON) - WINPR_ASSERT(index <= INT_MAX); - return cJSON_GetArrayItem((const cJSON*)array, (INT)index); -#else - WINPR_UNUSED(array); - WINPR_UNUSED(index); - return NULL; -#endif -} - -size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array) -{ -#if defined(WITH_JSONC) - return json_object_array_length((const json_object*)array); -#elif defined(WITH_CJSON) - const int rc = cJSON_GetArraySize((const cJSON*)array); - if (rc <= 0) - return 0; - return (size_t)rc; -#else - WINPR_UNUSED(array); - return 0; -#endif -} - -WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string) -{ -#if defined(WITH_JSONC) - struct json_object_iterator it = json_object_iter_begin((const json_object*)object); - struct json_object_iterator itEnd = json_object_iter_end((const json_object*)object); - while (!json_object_iter_equal(&it, &itEnd)) - { - const char* key = json_object_iter_peek_name(&it); - if (_stricmp(key, string) == 0) - { - return json_object_iter_peek_value(&it); - } - json_object_iter_next(&it); - } - return NULL; -#elif defined(WITH_CJSON) - return cJSON_GetObjectItem((const cJSON*)object, string); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(string); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string) -{ -#if defined(WITH_JSONC) - return json_object_object_get((const json_object*)object, string); -#elif defined(WITH_CJSON) - return cJSON_GetObjectItemCaseSensitive((const cJSON*)object, string); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(string); - return NULL; -#endif -} - -BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string) -{ -#if defined(WITH_JSONC) - return json_object_object_get_ex((const json_object*)object, string, NULL); -#elif defined(WITH_CJSON) - return cJSON_HasObjectItem((const cJSON*)object, string); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(string); - return FALSE; -#endif -} - -const char* WINPR_JSON_GetErrorPtr(void) -{ -#if defined(WITH_JSONC) - return json_util_get_last_err(); -#elif defined(WITH_CJSON) - return cJSON_GetErrorPtr(); -#else - return NULL; -#endif -} - -const char* WINPR_JSON_GetStringValue(WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_get_string((json_object*)item); -#elif defined(WITH_CJSON) - return cJSON_GetStringValue((cJSON*)item); -#else - WINPR_UNUSED(item); - return NULL; -#endif -} - -double WINPR_JSON_GetNumberValue(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_get_double((const json_object*)item); -#elif defined(WITH_CJSON) - return cJSON_GetNumberValue((const cJSON*)item); -#else - WINPR_UNUSED(item); - return nan(""); -#endif -} - -BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - if (WINPR_JSON_IsArray(item)) - return FALSE; - if (WINPR_JSON_IsObject(item)) - return FALSE; - if (WINPR_JSON_IsNull(item)) - return FALSE; - if (WINPR_JSON_IsNumber(item)) - return FALSE; - if (WINPR_JSON_IsBool(item)) - return FALSE; - if (WINPR_JSON_IsString(item)) - return FALSE; - return TRUE; -#elif defined(WITH_CJSON) - return cJSON_IsInvalid((const cJSON*)item); -#else - WINPR_UNUSED(item); - return TRUE; -#endif -} - -BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - if (!json_object_is_type((const json_object*)item, json_type_boolean)) - return FALSE; - json_bool val = json_object_get_boolean((const json_object*)item); - return val == 0; -#elif defined(WITH_CJSON) - return cJSON_IsFalse((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - if (!json_object_is_type((const json_object*)item, json_type_boolean)) - return FALSE; - json_bool val = json_object_get_boolean((const json_object*)item); - return val != 0; -#elif defined(WITH_CJSON) - return cJSON_IsTrue((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsBool(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_boolean); -#elif defined(WITH_CJSON) - return cJSON_IsBool((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsNull(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_null); -#elif defined(WITH_CJSON) - return cJSON_IsNull((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_int) || - json_object_is_type((const json_object*)item, json_type_double); -#elif defined(WITH_CJSON) - return cJSON_IsNumber((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsString(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_string); -#elif defined(WITH_CJSON) - return cJSON_IsString((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsArray(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_array); -#elif defined(WITH_CJSON) - return cJSON_IsArray((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -BOOL WINPR_JSON_IsObject(const WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - return json_object_is_type((const json_object*)item, json_type_object); -#elif defined(WITH_CJSON) - return cJSON_IsObject((const cJSON*)item); -#else - WINPR_UNUSED(item); - return FALSE; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateNull(void) -{ -#if defined(WITH_JSONC) - return json_object_new_null(); -#elif defined(WITH_CJSON) - return cJSON_CreateNull(); -#else - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateTrue(void) -{ -#if defined(WITH_JSONC) - return json_object_new_boolean(TRUE); -#elif defined(WITH_CJSON) - return cJSON_CreateTrue(); -#else - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateFalse(void) -{ -#if defined(WITH_JSONC) - return json_object_new_boolean(FALSE); -#elif defined(WITH_CJSON) - return cJSON_CreateFalse(); -#else - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean) -{ -#if defined(WITH_JSONC) - return json_object_new_boolean(boolean); -#elif defined(WITH_CJSON) - return cJSON_CreateBool(boolean); -#else - WINPR_UNUSED(boolean); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateNumber(double num) -{ -#if defined(WITH_JSONC) - return json_object_new_double(num); -#elif defined(WITH_CJSON) - return cJSON_CreateNumber(num); -#else - WINPR_UNUSED(num); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateString(const char* string) -{ -#if defined(WITH_JSONC) - return json_object_new_string(string); -#elif defined(WITH_CJSON) - return cJSON_CreateString(string); -#else - WINPR_UNUSED(string); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateArray(void) -{ -#if defined(WITH_JSONC) - return json_object_new_array(); -#elif defined(WITH_CJSON) - return cJSON_CreateArray(); -#else - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_CreateObject(void) -{ -#if defined(WITH_JSONC) - return json_object_new_object(); -#elif defined(WITH_CJSON) - return cJSON_CreateObject(); -#else - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_null(); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddNullToObject((cJSON*)object, name); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_boolean(TRUE); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddTrueToObject((cJSON*)object, name); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_boolean(FALSE); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddFalseToObject((cJSON*)object, name); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_boolean(boolean); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddBoolToObject((cJSON*)object, name, boolean); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - WINPR_UNUSED(boolean); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_double(number); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddNumberToObject((cJSON*)object, name, number); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - WINPR_UNUSED(number); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_string(string); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddStringToObject((cJSON*)object, name, string); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - WINPR_UNUSED(string); - return NULL; -#endif -} - -WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_object(); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddObjectToObject((cJSON*)object, name); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - return NULL; -#endif -} - -BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - const int rc = json_object_array_add((json_object*)array, (json_object*)item); - if (rc != 0) - return FALSE; - return TRUE; -#elif defined(WITH_CJSON) -#if defined(USE_CJSON_COMPAT) - if ((array == NULL) || (item == NULL)) - return FALSE; - cJSON_AddItemToArray((cJSON*)array, (cJSON*)item); - return TRUE; -#else - return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item); -#endif -#else - WINPR_UNUSED(array); - WINPR_UNUSED(item); - return FALSE; -#endif -} - -WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name) -{ -#if defined(WITH_JSONC) - struct json_object* obj = json_object_new_array(); - if (json_object_object_add((json_object*)object, name, obj) != 0) - { - json_object_put(obj); - return NULL; - } - return obj; -#elif defined(WITH_CJSON) - return cJSON_AddArrayToObject((cJSON*)object, name); -#else - WINPR_UNUSED(object); - WINPR_UNUSED(name); - return NULL; -#endif -} - -char* WINPR_JSON_Print(WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY); - if (!str) - return NULL; - return _strdup(str); -#elif defined(WITH_CJSON) - return cJSON_Print((const cJSON*)item); -#else - WINPR_UNUSED(item); - return NULL; -#endif -} - -char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) -{ -#if defined(WITH_JSONC) - const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN); - if (!str) - return NULL; - return _strdup(str); -#elif defined(WITH_CJSON) - return cJSON_PrintUnformatted((const cJSON*)item); -#else - WINPR_UNUSED(item); - return NULL; -#endif -} - WINPR_JSON* WINPR_JSON_ParseFromFile(const char* filename) { FILE* fp = winpr_fopen(filename, "r");