From 47631c3b43b6877f42617fa61bf9aad3647ae709 Mon Sep 17 00:00:00 2001 From: xijianjun Date: Tue, 21 Jul 2020 19:18:11 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0summary=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E6=A0=87=E8=AE=B0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=B8=AD=E7=A2=B0=E5=88=B0=E7=9A=84=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E7=82=B9=E4=BB=A5=E5=8F=8A=E7=96=91=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 224 +++++++++++++++++++++++++------------------------ cJSON.c | 10 +++ cJSON.h | 2 + summary | 10 +++ test.c | 166 ++++++++++++++++++------------------ 5 files changed, 219 insertions(+), 193 deletions(-) create mode 100644 summary diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a73a2c27..8da9046e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,85 +20,87 @@ option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON) if (ENABLE_CUSTOM_COMPILER_FLAGS) if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) list(APPEND custom_compiler_flags - -std=c89 - -pedantic - -Wall - -Wextra - -Werror - -Wstrict-prototypes - -Wwrite-strings - -Wshadow - -Winit-self - -Wcast-align - -Wformat=2 - -Wmissing-prototypes - -Wstrict-overflow=2 - -Wcast-qual - -Wundef - -Wswitch-default - -Wconversion - -Wc++-compat - -fstack-protector-strong - -Wcomma - -Wdouble-promotion - -Wparentheses - -Wformat-overflow - -Wunused-macros - -Wmissing-variable-declarations - -Wused-but-marked-unused - -Wswitch-enum - ) - elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") + -std=c99 + -pedantic + -Wall + -Wextra + -Werror=unused-variable + -Werror + -Wstrict-prototypes + -Wwrite-strings + -Wshadow + -Winit-self + -Wcast-align + -Wformat=2 + -Wmissing-prototypes + -Wstrict-overflow=2 + -Wcast-qual + -Wundef + -Wswitch-default + -Wconversion + -Wc++-compat + -fstack-protector-strong + -Wcomma + -Wdouble-promotion + -Wparentheses + -Wformat-overflow + -Wunused-macros + -Wmissing-variable-declarations + -Wused-but-marked-unused + -Wswitch-enum + + ) + elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") # Disable warning c4001 - nonstandard extension 'single line comment' was used # Define _CRT_SECURE_NO_WARNINGS to disable deprecation warnings for "insecure" C library functions list(APPEND custom_compiler_flags - /GS - /Za - /sdl - /W4 - /wd4001 - /D_CRT_SECURE_NO_WARNINGS - ) - endif() -endif() + /GS + /Za + /sdl + /W4 + /wd4001 + /D_CRT_SECURE_NO_WARNINGS + ) + endif () +endif () option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF) if (ENABLE_SANITIZERS) list(APPEND custom_compiler_flags - -fno-omit-frame-pointer - -fsanitize=address - -fsanitize=undefined - -fsanitize=float-divide-by-zero - -fsanitize=float-cast-overflow - -fsanitize-address-use-after-scope - -fsanitize=integer - -01 - -fno-sanitize-recover - ) -endif() + -fno-omit-frame-pointer + -fsanitize=address + -fsanitize=undefined + -fsanitize=float-divide-by-zero + -fsanitize=float-cast-overflow + -fsanitize-address-use-after-scope + -fsanitize=integer + -01 + -fno-sanitize-recover + ) +endif () option(ENABLE_SAFE_STACK "Enables the SafeStack instrumentation pass by the Code Pointer Integrity Project" OFF) if (ENABLE_SAFE_STACK) if (ENABLE_SANITIZERS) message(FATAL_ERROR "ENABLE_SAFE_STACK cannot be used in combination with ENABLE_SANITIZERS") - endif() + endif () list(APPEND custom_compiler_flags - -fsanitize=safe-stack - ) -endif() + -fsanitize=safe-stack + ) +endif () option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On) if (ENABLE_PUBLIC_SYMBOLS) list(APPEND custom_compiler_flags -fvisibility=hidden) add_definitions(-DCJSON_EXPORT_SYMBOLS -DCJSON_API_VISIBILITY) -endif() +endif () option(ENABLE_HIDDEN_SYMBOLS "Hide library symbols." Off) if (ENABLE_HIDDEN_SYMBOLS) add_definitions(-DCJSON_HIDE_SYMBOLS -UCJSON_API_VISIBILITY) -endif() +endif () # apply custom compiler flags -foreach(compiler_flag ${custom_compiler_flags}) +foreach (compiler_flag ${custom_compiler_flags}) #remove problematic characters string(REGEX REPLACE "[^a-zA-Z0-9]" "" current_variable ${compiler_flag}) @@ -106,8 +108,8 @@ foreach(compiler_flag ${custom_compiler_flags}) if (FLAG_SUPPORTED_${current_variable}) list(APPEND supported_compiler_flags) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}") - endif() -endforeach() + endif () +endforeach () set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}") @@ -126,52 +128,52 @@ option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BU if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS)) set(CJSON_LIBRARY_TYPE SHARED) -else() +else () set(CJSON_LIBRARY_TYPE STATIC) -endif() +endif () if (NOT BUILD_SHARED_AND_STATIC_LIBS) add_library("${CJSON_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS}" "${SOURCES}") -else() +else () # See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}") add_library("${CJSON_LIB}-static" STATIC "${HEADERS}" "${SOURCES}") set_target_properties("${CJSON_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_LIB}") set_target_properties("${CJSON_LIB}-static" PROPERTIES PREFIX "lib") -endif() +endif () if (NOT WIN32) target_link_libraries("${CJSON_LIB}" m) -endif() +endif () configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY) + "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY) install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") -install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") install(TARGETS "${CJSON_LIB}" - EXPORT "${CJSON_LIB}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" - INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" -) + EXPORT "${CJSON_LIB}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" + ) if (BUILD_SHARED_AND_STATIC_LIBS) install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") -endif() -if(ENABLE_TARGET_EXPORT) +endif () +if (ENABLE_TARGET_EXPORT) # export library information for CMake projects install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") -endif() +endif () set_target_properties("${CJSON_LIB}" - PROPERTIES + PROPERTIES SOVERSION "${CJSON_VERSION_SO}" VERSION "${PROJECT_VERSION}") #cJSON_Utils option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF) -if(ENABLE_CJSON_UTILS) +if (ENABLE_CJSON_UTILS) set(CJSON_UTILS_LIB cjson_utils) file(GLOB HEADERS_UTILS cJSON_Utils.h) @@ -180,58 +182,58 @@ if(ENABLE_CJSON_UTILS) if (NOT BUILD_SHARED_AND_STATIC_LIBS) add_library("${CJSON_UTILS_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS_UTILS}" "${SOURCES_UTILS}") target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}") - else() + else () add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}") target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}") add_library("${CJSON_UTILS_LIB}-static" STATIC "${HEADERS_UTILS}" "${SOURCES_UTILS}") target_link_libraries("${CJSON_UTILS_LIB}-static" "${CJSON_LIB}-static") set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_UTILS_LIB}") set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES PREFIX "lib") - endif() + endif () configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY) + "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY) install(TARGETS "${CJSON_UTILS_LIB}" - EXPORT "${CJSON_UTILS_LIB}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" - INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" - ) + EXPORT "${CJSON_UTILS_LIB}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" + ) if (BUILD_SHARED_AND_STATIC_LIBS) install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") - endif() + endif () install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") - install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") - if(ENABLE_TARGET_EXPORT) - # export library information for CMake projects - install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") - endif() + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") + if (ENABLE_TARGET_EXPORT) + # export library information for CMake projects + install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") + endif () set_target_properties("${CJSON_UTILS_LIB}" - PROPERTIES + PROPERTIES SOVERSION "${CJSON_UTILS_VERSION_SO}" VERSION "${PROJECT_VERSION}") -endif() +endif () # create the other package config files configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfig.cmake.in" - ${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY) + "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfig.cmake.in" + ${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in" - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY) + "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in" + ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY) -if(ENABLE_TARGET_EXPORT) +if (ENABLE_TARGET_EXPORT) # Install package config files install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake - ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake - DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") -endif() + ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake + DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") +endif () option(ENABLE_CJSON_TEST "Enable building cJSON test" ON) -if(ENABLE_CJSON_TEST) +if (ENABLE_CJSON_TEST) enable_testing() set(TEST_CJSON cJSON_test) @@ -244,25 +246,25 @@ if(ENABLE_CJSON_TEST) if (FLAG_SUPPORTED_fsanitizefloatdividebyzero) if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero") - else() + else () target_compile_options(${TEST_CJSON} PRIVATE "-fno-sanitize=float-divide-by-zero") - endif() - endif() + endif () + endif () #"check" target that automatically builds everything and runs the tests add_custom_target(check - COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure - DEPENDS ${TEST_CJSON}) -endif() + COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure + DEPENDS ${TEST_CJSON}) +endif () #Create the uninstall target add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake") # Enable the use of locales option(ENABLE_LOCALES "Enable the use of locales" ON) -if(ENABLE_LOCALES) - add_definitions(-DENABLE_LOCALES) -endif() +if (ENABLE_LOCALES) + add_definitions(-DENABLE_LOCALES) +endif () add_subdirectory(tests) add_subdirectory(fuzzing) diff --git a/cJSON.c b/cJSON.c index 3cdc8fa54..187cf25f3 100644 --- a/cJSON.c +++ b/cJSON.c @@ -179,6 +179,7 @@ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) /* strlen of character literals resolved at compile time */ #define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) +/** 方法 */ static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) @@ -191,7 +192,10 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h return NULL; } + //sizeof("") == 1 length = strlen((const char*)string) + sizeof(""); +// printf("%s len: const char* len %lu\n",string, strlen((const char*)string)); + //realloc copy = (unsigned char*)hooks->allocate(length); if (copy == NULL) { @@ -2028,6 +2032,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st } else { + //一个指向 只读变量 的指针 string means a pointer to const unsigned char new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); if (new_key == NULL) { @@ -2037,8 +2042,10 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st new_type = item->type & ~cJSON_StringIsConst; } + //todo ??? if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { + //free hooks->deallocate(item->string); } @@ -2048,6 +2055,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st return add_item_to_array(object, item); } +/** 键值对 string - item */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) { return add_item_to_object(object, string, item, &global_hooks, false); @@ -2457,6 +2465,8 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { item->type = cJSON_String; item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + + // if(!item->valuestring) { cJSON_Delete(item); diff --git a/cJSON.h b/cJSON.h index b5ceb290b..003552f99 100644 --- a/cJSON.h +++ b/cJSON.h @@ -102,6 +102,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* The cJSON structure: */ typedef struct cJSON { + /** 双向链表 */ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; @@ -118,6 +119,7 @@ typedef struct cJSON /* The item's number, if type==cJSON_Number */ double valuedouble; + /** 键 */ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ char *string; } cJSON; diff --git a/summary b/summary new file mode 100644 index 000000000..2f7b14e9a --- /dev/null +++ b/summary @@ -0,0 +1,10 @@ +1. struct global_hooks +2. sizeof("") == 1 +3. C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。 +4. 宏 + +---------------------------------- + + +定义 cJSON_CreateObject(void) +调用 cJSON_CreateObject() \ No newline at end of file diff --git a/test.c b/test.c index 986fc6eb3..a9a7b65c6 100644 --- a/test.c +++ b/test.c @@ -111,13 +111,13 @@ static void create_objects(void) /* declare a few. */ cJSON *root = NULL; cJSON *fmt = NULL; - cJSON *img = NULL; - cJSON *thm = NULL; - cJSON *fld = NULL; - int i = 0; + cJSON *img __attribute__((unused)) = NULL; + cJSON *thm __attribute__((unused)) = NULL; + cJSON *fld __attribute__((unused)) = NULL; + int i __attribute__((unused)) = 0; /* Our "days of the week" array: */ - const char *strings[7] = + const char *strings[7] __attribute__((unused)) = { "Sunday", "Monday", @@ -128,16 +128,16 @@ static void create_objects(void) "Saturday" }; /* Our matrix: */ - int numbers[3][3] = + int numbers[3][3] __attribute__((unused)) = { {0, -1, 0}, {1, 0, 0}, {0 ,0, 1} }; /* Our "gallery" item: */ - int ids[4] = { 116, 943, 234, 38793 }; + int ids[4] __attribute__((unused)) = { 116, 943, 234, 38793 }; /* Our array of "records": */ - struct record fields[2] = + struct record fields[2] __attribute__((unused)) = { { "zip", @@ -160,11 +160,13 @@ static void create_objects(void) "US" } }; - volatile double zero = 0.0; + volatile double __attribute__((unused)) zero = 0.0; /* Here we construct some JSON standards, from the JSON site. */ - /* Our "Video" datatype: */ + /* Our "Video" datatype: Video数据类型 */ + + root = cJSON_CreateObject(); cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); @@ -182,78 +184,78 @@ static void create_objects(void) cJSON_Delete(root); /* Our "days of the week" array: */ - root = cJSON_CreateStringArray(strings, 7); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our matrix: */ - root = cJSON_CreateArray(); - for (i = 0; i < 3; i++) - { - cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); - } - - /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our "gallery" item: */ - root = cJSON_CreateObject(); - cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); - cJSON_AddNumberToObject(img, "Width", 800); - cJSON_AddNumberToObject(img, "Height", 600); - cJSON_AddStringToObject(img, "Title", "View from 15th Floor"); - cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject()); - cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); - cJSON_AddNumberToObject(thm, "Height", 125); - cJSON_AddStringToObject(thm, "Width", "100"); - cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4)); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - /* Our array of "records": */ - root = cJSON_CreateArray(); - for (i = 0; i < 2; i++) - { - cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); - cJSON_AddStringToObject(fld, "precision", fields[i].precision); - cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); - cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); - cJSON_AddStringToObject(fld, "Address", fields[i].address); - cJSON_AddStringToObject(fld, "City", fields[i].city); - cJSON_AddStringToObject(fld, "State", fields[i].state); - cJSON_AddStringToObject(fld, "Zip", fields[i].zip); - cJSON_AddStringToObject(fld, "Country", fields[i].country); - } - - /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); - - root = cJSON_CreateObject(); - cJSON_AddNumberToObject(root, "number", 1.0 / zero); - - if (print_preallocated(root) != 0) { - cJSON_Delete(root); - exit(EXIT_FAILURE); - } - cJSON_Delete(root); +// root = cJSON_CreateStringArray(strings, 7); +// +// if (print_preallocated(root) != 0) { +// cJSON_Delete(root); +// exit(EXIT_FAILURE); +// } +// cJSON_Delete(root); +// +// /* Our matrix: */ +// root = cJSON_CreateArray(); +// for (i = 0; i < 3; i++) +// { +// cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); +// } +// +// /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ +// +// if (print_preallocated(root) != 0) { +// cJSON_Delete(root); +// exit(EXIT_FAILURE); +// } +// cJSON_Delete(root); +// +// /* Our "gallery" item: */ +// root = cJSON_CreateObject(); +// cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); +// cJSON_AddNumberToObject(img, "Width", 800); +// cJSON_AddNumberToObject(img, "Height", 600); +// cJSON_AddStringToObject(img, "Title", "View from 15th Floor"); +// cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject()); +// cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); +// cJSON_AddNumberToObject(thm, "Height", 125); +// cJSON_AddStringToObject(thm, "Width", "100"); +// cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4)); +// +// if (print_preallocated(root) != 0) { +// cJSON_Delete(root); +// exit(EXIT_FAILURE); +// } +// cJSON_Delete(root); +// +// /* Our array of "records": */ +// root = cJSON_CreateArray(); +// for (i = 0; i < 2; i++) +// { +// cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); +// cJSON_AddStringToObject(fld, "precision", fields[i].precision); +// cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); +// cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); +// cJSON_AddStringToObject(fld, "Address", fields[i].address); +// cJSON_AddStringToObject(fld, "City", fields[i].city); +// cJSON_AddStringToObject(fld, "State", fields[i].state); +// cJSON_AddStringToObject(fld, "Zip", fields[i].zip); +// cJSON_AddStringToObject(fld, "Country", fields[i].country); +// } +// +// /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ +// +// if (print_preallocated(root) != 0) { +// cJSON_Delete(root); +// exit(EXIT_FAILURE); +// } +// cJSON_Delete(root); +// +// root = cJSON_CreateObject(); +// cJSON_AddNumberToObject(root, "number", 1.0 / zero); +// +// if (print_preallocated(root) != 0) { +// cJSON_Delete(root); +// exit(EXIT_FAILURE); +// } +// cJSON_Delete(root); } int CJSON_CDECL main(void) From 3bdc7f727de8c4531756c6de0a4076e5a2fee1dc Mon Sep 17 00:00:00 2001 From: xijianjun Date: Sat, 25 Jul 2020 21:09:59 +0800 Subject: [PATCH 2/9] =?UTF-8?q?Object=E7=B1=BB=E5=9E=8B=20add=20detach?= =?UTF-8?q?=E6=A2=B3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- cJSON.c | 26 ++++++---- summary | 10 ---- summary.md | 52 +++++++++++++++++++ test.c | 9 ++-- tests/unity/auto/stylize_as_junit.rb | 2 +- .../example_1/test/TestProductionCode.c | 2 +- .../example_2/test/TestProductionCode.c | 2 +- .../example_3/test/TestProductionCode.c | 2 +- tests/unity/src/unity.h | 2 +- tests/unity/test/targets/hitech_picc18.yml | 6 +-- 11 files changed, 81 insertions(+), 34 deletions(-) delete mode 100644 summary create mode 100644 summary.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 8da9046e3..d52d1e505 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS) -Wmissing-variable-declarations -Wused-but-marked-unused -Wswitch-enum - + -Werror=unused-function ) elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") # Disable warning c4001 - nonstandard extension 'single line comment' was used diff --git a/cJSON.c b/cJSON.c index 187cf25f3..8c3005097 100644 --- a/cJSON.c +++ b/cJSON.c @@ -151,6 +151,8 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned typedef struct internal_hooks { + // todo CJSON_CDECL ?? + //declare allocate as pointer to function (size_t) returning pointer to void void *(CJSON_CDECL *allocate)(size_t size); void (CJSON_CDECL *deallocate)(void *pointer); void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); @@ -192,10 +194,8 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h return NULL; } - //sizeof("") == 1 length = strlen((const char*)string) + sizeof(""); // printf("%s len: const char* len %lu\n",string, strlen((const char*)string)); - //realloc copy = (unsigned char*)hooks->allocate(length); if (copy == NULL) { @@ -427,9 +427,9 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) typedef struct { unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ + size_t length; // buffer大小 + size_t offset; // 偏移量? 是如何变化的 + size_t depth; /* current nesting depth (for formatted printing) */ /** object嵌套深度 */ cJSON_bool noalloc; cJSON_bool format; /* is this print a formatted print */ internal_hooks hooks; @@ -461,6 +461,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) needed += p->offset + 1; if (needed <= p->length) { + //todo 理解不了 return p->buffer + p->offset; } @@ -1050,6 +1051,7 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) buffer->offset++; } + //todo ?? if (buffer->offset == buffer->length) { buffer->offset--; @@ -1337,12 +1339,12 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf input_buffer->offset += 4; return true; } - /* string */ + /* string */ //"" if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); } - /* number */ + /* number */ // '-'表示负数 if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { return parse_number(item, input_buffer); @@ -1740,6 +1742,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out { if (output_buffer->format) { + //格式化拼接 size_t i; output_pointer = ensure(output_buffer, output_buffer->depth); if (output_pointer == NULL) @@ -1753,7 +1756,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out output_buffer->offset += output_buffer->depth; } - /* print key */ + /* print key 输出键 */ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) { return false; @@ -1773,7 +1776,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out } output_buffer->offset += length; - /* print value */ + /* print value 输出值 */ if (!print_value(current_item, output_buffer)) { return false; @@ -1977,6 +1980,7 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) if (child->prev) { suffix_object(child->prev, item); + //确定最后一个item array->child->prev = item; } else @@ -2039,10 +2043,10 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st return false; } - new_type = item->type & ~cJSON_StringIsConst; + new_type = item->type & ~cJSON_StringIsConst; // 10 00000000 & 00000001 } - //todo ??? + //todo ??? 非常量字符串 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { //free diff --git a/summary b/summary deleted file mode 100644 index 2f7b14e9a..000000000 --- a/summary +++ /dev/null @@ -1,10 +0,0 @@ -1. struct global_hooks -2. sizeof("") == 1 -3. C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。 -4. 宏 - ----------------------------------- - - -定义 cJSON_CreateObject(void) -调用 cJSON_CreateObject() \ No newline at end of file diff --git a/summary.md b/summary.md new file mode 100644 index 000000000..3967b1827 --- /dev/null +++ b/summary.md @@ -0,0 +1,52 @@ +1. struct global_hooks +2. sizeof("") == 1 +3. C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。 +4. 宏 +5. cJSON.c line 185 global_hooks的定义 + +6. struct 的初始化 +```` + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; +```` +7. whitespace and cr/lf https://www.jianshu.com/p/8d33019d1c69 + + +---------------------------------- + + + +|符号|意义| +|----|----| +|%d|    有符号10进制整数(%ld 长整型,%hd短整型 )| +|%hu|    无符号短整形(%u无符号整形,%lu无符号长整形)| +|%i|    有符号10进制整数 (%i 和%d 没有区别,%i 是老式写法,都是整型格式)| +|%o|    无符号8进制整数| +|%u|    无符号10进制整数| +|%x|    无符号的16进制数字,并以小写abcdef表示| +|%X|    无符号的16进制数字,并以大写ABCDEF表示| +|%f|   输入输出为浮点型 (%lf双精度浮点型)| +|%E/e|    用科学表示格式的浮点数| +|%c|    输入输出为单个字符| +|%s|    输入输出为字符串| + + +---------------------------------- + + +cJSON数据结构 + +```` +video + child -> name + +name + prev -> name + next -> format + +format + prev -> name + next -> null + +```` +定义 cJSON_CreateObject(void) +调用 cJSON_CreateObject() \ No newline at end of file diff --git a/test.c b/test.c index a9a7b65c6..ecb2a41bc 100644 --- a/test.c +++ b/test.c @@ -171,10 +171,10 @@ static void create_objects(void) cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); cJSON_AddStringToObject(fmt, "type", "rect"); - cJSON_AddNumberToObject(fmt, "width", 1920); - cJSON_AddNumberToObject(fmt, "height", 1080); - cJSON_AddFalseToObject (fmt, "interlace"); - cJSON_AddNumberToObject(fmt, "frame rate", 24); +// cJSON_AddNumberToObject(fmt, "width", 1920); +// cJSON_AddNumberToObject(fmt, "height", 1080); +// cJSON_AddFalseToObject (fmt, "interlace"); +// cJSON_AddNumberToObject(fmt, "frame rate", 24); /* Print to text */ if (print_preallocated(root) != 0) { @@ -183,6 +183,7 @@ static void create_objects(void) } cJSON_Delete(root); + /* Our "days of the week" array: */ // root = cJSON_CreateStringArray(strings, 7); // diff --git a/tests/unity/auto/stylize_as_junit.rb b/tests/unity/auto/stylize_as_junit.rb index b3d8f4097..046685fa8 100755 --- a/tests/unity/auto/stylize_as_junit.rb +++ b/tests/unity/auto/stylize_as_junit.rb @@ -151,7 +151,7 @@ def get_details(_result_file, lines) end def parse_test_summary(summary) - raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + raise "Couldn't parse test results: #{summary.md}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] end diff --git a/tests/unity/examples/example_1/test/TestProductionCode.c b/tests/unity/examples/example_1/test/TestProductionCode.c index 806088625..b43bbb956 100644 --- a/tests/unity/examples/example_1/test/TestProductionCode.c +++ b/tests/unity/examples/example_1/test/TestProductionCode.c @@ -29,7 +29,7 @@ void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWork void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) { - /* You should see this line fail in your test summary */ + /* You should see this line fail in your test summary.md */ TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); /* Notice the rest of these didn't get a chance to run because the line above failed. diff --git a/tests/unity/examples/example_2/test/TestProductionCode.c b/tests/unity/examples/example_2/test/TestProductionCode.c index ff318abbb..4aca078ba 100644 --- a/tests/unity/examples/example_2/test/TestProductionCode.c +++ b/tests/unity/examples/example_2/test/TestProductionCode.c @@ -31,7 +31,7 @@ TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInLis TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken) { - // You should see this line fail in your test summary + // You should see this line fail in your test summary.md TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); // Notice the rest of these didn't get a chance to run because the line above failed. diff --git a/tests/unity/examples/example_3/test/TestProductionCode.c b/tests/unity/examples/example_3/test/TestProductionCode.c index 28a55812c..70b732b33 100644 --- a/tests/unity/examples/example_3/test/TestProductionCode.c +++ b/tests/unity/examples/example_3/test/TestProductionCode.c @@ -29,7 +29,7 @@ void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWork void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) { - // You should see this line fail in your test summary + // You should see this line fail in your test summary.md TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); // Notice the rest of these didn't get a chance to run because the line above failed. diff --git a/tests/unity/src/unity.h b/tests/unity/src/unity.h index 32ff0e6df..938c137dc 100644 --- a/tests/unity/src/unity.h +++ b/tests/unity/src/unity.h @@ -79,7 +79,7 @@ int suiteTearDown(int num_failures); * Output * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired - * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary.md - for automated search for failure * Optimization * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge diff --git a/tests/unity/test/targets/hitech_picc18.yml b/tests/unity/test/targets/hitech_picc18.yml index 2fd4aa366..f63eb1f10 100644 --- a/tests/unity/test/targets/hitech_picc18.yml +++ b/tests/unity/test/targets/hitech_picc18.yml @@ -56,9 +56,9 @@ linker: - --cp=24 # 24-bit pointers. Is this needed for linker?? - --double=24 # Is this needed for linker?? - -Lw # Scan the pic87*w.lib in the lib/ of the compiler installation directory - - --summary=mem,file # info listing - - --summary=+psect - - --summary=+hex + - --summary.md=mem,file # info listing + - --summary.md=+psect + - --summary.md=+hex - --output=+intel - --output=+mcof - --runtime=+init # Directs startup code to copy idata, ibigdata and ifardata psects from ROM to RAM. From 5603b557ea392828aa6a2c28c35f8e929adccf08 Mon Sep 17 00:00:00 2001 From: ProgrammerCharles <11960604+ProgrammerCharles@users.noreply.github.com> Date: Sat, 25 Jul 2020 22:55:41 +0800 Subject: [PATCH 3/9] Added Untitled Diagram.drawio --- Untitled Diagram.drawio | 1 + 1 file changed, 1 insertion(+) create mode 100644 Untitled Diagram.drawio diff --git a/Untitled Diagram.drawio b/Untitled Diagram.drawio new file mode 100644 index 000000000..733272940 --- /dev/null +++ b/Untitled Diagram.drawio @@ -0,0 +1 @@ +7Vttb5s6GP01SHcfVoEJSfuxYckmLbmr2m77eOWCA9YIRsZ526+fDTaEOGlhd2m8JlLUwMMTg59zfGyfJpbrz9cfKcziKQlRYgE7XFvuBwsABwCXv4nIpowMbgZlIKI4lEl14AH/RDJoy+gChyhvJDJCEoazZjAgaYoC1ohBSsmqmTYjSfOuGYyQFngIYKJHv+OQxWX02rPr+CeEo1jd2bHllTlUyTKQxzAkq0YIrdmYpEw+4h2ic5iilPErU0h/IGp5o5gx0dNbC4z5ayayryJCogTBDOdXAZnzcJDzlPEMznEiyrzV0FA2xG/njizXp4Sw8mi+9lEisFIwlM80PnC1qgMV7bb4gP9+uZn8sFn6aeV+Y9NpdDd4ei9bWcJkIesra8M2quAo5PWXp/xWmG3uUQIZJumovjJEaXgr0OVJo/ufiJJHMoUp7/wwZ5Cy+hpJZfoY88dzPzgqRZ7b/FzvmnzOnCxogJ7pD+hJSkIaIfZMYl8CHjbYJiv3EZE5YnTDE1Y1xyomxdv8UkFaFGXZZCmUTIqqBqt73BFcEEsOTLcn21HDUlFSNVF2XX5qG+adhno7DfV3GypLozXED7Y6XocKFnVhFHhjlHJbMsoZGEapnt1kgnP9u5TqNxsCtveqlNIZ9YWGiOYar7iiZ+KQwaeCQQUJ5BTmChbwSYlBnHL9LVkSkCSBWY6L9DIS4yScwA1ZMNWQOhvO8BqF9+UMJnI5/ya8sVxSTMwFitXiMkxwlPLjgFNO3HFIUc6fZQJzJjMOknKJKEPrZ1mksPF2QFbDfYtlwNvHMtc+TKgGgl3hcl8WAAUU7zrDMLnnCwWYRgVmTUhEXUNKskc1+kQgE0RDdLRE5VRdFJ8PdZ8kRCCbloJQpBWd84b8xbvr21ee5fEH8Pm5U5/zl0inzCdpzijEBRyIA7VCAqwhI5m8T4Jm6jGoLKY4fiKM8Zn/EKzP0vplrCW2bktoj4ZsT0P27nMXbAnv6ywpVDvGYYjSckiKdSKs8d4D5d76VzXfBWN3ILbEw22NxxYA7mvW39PqT4QQ/sc/5APr1i5V+98vj+Lv18nEqpa6JsGjdLHMHeYZDHAaTcpP9nfw846B39o6OJ7Aa+LZP2el3L8q+zNK2T+1Ug40ZMefnS7gvtJYbAlAvzUAp5LGa63gwSLnfS7VEeyRRuOweFEX/zhYpujgzUUHj6ODN6fWQeUa/ia0ZqngTevyn0oFHd3PK1eIIWSIx+XbWchge7RMkUFH3zk/xDibF6J18To0rwNct5S343kdjr4lPqOpq8Pm2mm/OzPF7XD07fZbsjsq6ho8nekb5FwK4sXz6AqiMbOcvjc+I8nssNzsLpkntz0cfRv+V/seFVcN1kh981yZwmdle3TAyhQpBP9vd3yRQoOdD6BvxQ0cfC3rXxHVXB1U5d23VjxD96MDYsaooW5/+NLDv9gf1tZXOzp/1cM+GmQX+6PlcPz77A/wtu0PYL79AXT746V/ap6T99EBQWOmuIv3cSy9PLn3AXTvw8DB2Lb+5hsfQDc+KnVM4Vys9IMY0n88+93ZLPpNskD4af3jlvKr4PUvktzRLw== \ No newline at end of file From 0f0fd7ad1e3d3e020895ae65464a1860fb5c3adb Mon Sep 17 00:00:00 2001 From: xijianjun Date: Tue, 28 Jul 2020 21:01:59 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cJSON.c | 21 ++++++++++---------- summary.md | 11 ++++++++++- test.c | 56 +++++++++++++++++++++++++++--------------------------- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/cJSON.c b/cJSON.c index 8c3005097..2003d1a1f 100644 --- a/cJSON.c +++ b/cJSON.c @@ -461,7 +461,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) needed += p->offset + 1; if (needed <= p->length) { - //todo 理解不了 + //todo 理解不了 (char * + size_t) return p->buffer + p->offset; } @@ -484,6 +484,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } else { + // needed * 2 newsize = needed * 2; } @@ -1291,6 +1292,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) { + //准备 printbuffer printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; if ((length < 0) || (buffer == NULL)) @@ -1969,22 +1971,22 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) */ if (child == NULL) { - /* list is empty, start new one */ + /* 数组是空的 */ array->child = item; item->prev = item; item->next = NULL; } else { - /* append to the end */ + /* 数组非空 */ if (child->prev) { suffix_object(child->prev, item); - //确定最后一个item + //prev指定当前Array中的最后一个item array->child->prev = item; } else - { + {//todo 怎么理解 什么情况下 child -> prev为NULL while (child->next) { child = child->next; @@ -1993,7 +1995,6 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) array->child->prev = item; } } - return true; } @@ -2575,12 +2576,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) cJSON_Delete(a); return NULL; } - if(!i) - { + + if(!i){// i = 0 & !0为真 a->child = n; - } - else - { + }else{ suffix_object(p, n); } p = n; diff --git a/summary.md b/summary.md index 3967b1827..a511aea3f 100644 --- a/summary.md +++ b/summary.md @@ -49,4 +49,13 @@ format ```` 定义 cJSON_CreateObject(void) -调用 cJSON_CreateObject() \ No newline at end of file +调用 cJSON_CreateObject() + +已跟源代码 +------------------------------------ +cJSON_PrintPreallocated +#### 数组 +- cJSON_CreateArray +- cJSON_CreateIntArray +- add_item_to_array +- add_item_to_array NOTE line 1989 \ No newline at end of file diff --git a/test.c b/test.c index ecb2a41bc..c1fa060b0 100644 --- a/test.c +++ b/test.c @@ -111,13 +111,13 @@ static void create_objects(void) /* declare a few. */ cJSON *root = NULL; cJSON *fmt = NULL; - cJSON *img __attribute__((unused)) = NULL; - cJSON *thm __attribute__((unused)) = NULL; + cJSON * __attribute__((unused)) img = NULL; + cJSON * __attribute__((unused)) thm = NULL; cJSON *fld __attribute__((unused)) = NULL; int i __attribute__((unused)) = 0; /* Our "days of the week" array: */ - const char *strings[7] __attribute__((unused)) = + const char __attribute__((unused)) *strings[7] = { "Sunday", "Monday", @@ -128,14 +128,14 @@ static void create_objects(void) "Saturday" }; /* Our matrix: */ - int numbers[3][3] __attribute__((unused)) = + int numbers[3][3] = { {0, -1, 0}, {1, 0, 0}, {0 ,0, 1} }; /* Our "gallery" item: */ - int ids[4] __attribute__((unused)) = { 116, 943, 234, 38793 }; + int __attribute__((unused)) ids[4] = { 116, 943, 234, 38793 }; /* Our array of "records": */ struct record fields[2] __attribute__((unused)) = { @@ -171,10 +171,10 @@ static void create_objects(void) cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); cJSON_AddStringToObject(fmt, "type", "rect"); -// cJSON_AddNumberToObject(fmt, "width", 1920); -// cJSON_AddNumberToObject(fmt, "height", 1080); -// cJSON_AddFalseToObject (fmt, "interlace"); -// cJSON_AddNumberToObject(fmt, "frame rate", 24); + cJSON_AddNumberToObject(fmt, "width", 1920); + cJSON_AddNumberToObject(fmt, "height", 1080); + cJSON_AddFalseToObject (fmt, "interlace"); + cJSON_AddNumberToObject(fmt, "frame rate", 24); /* Print to text */ if (print_preallocated(root) != 0) { @@ -192,23 +192,23 @@ static void create_objects(void) // exit(EXIT_FAILURE); // } // cJSON_Delete(root); -// -// /* Our matrix: */ -// root = cJSON_CreateArray(); -// for (i = 0; i < 3; i++) -// { -// cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); -// } -// -// /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ -// -// if (print_preallocated(root) != 0) { -// cJSON_Delete(root); -// exit(EXIT_FAILURE); -// } -// cJSON_Delete(root); -// -// /* Our "gallery" item: */ + + /* Our matrix: */ + root = cJSON_CreateArray(); + for (i = 0; i < 3; i++) + { + cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); + } + + /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ + + if (print_preallocated(root) != 0) { + cJSON_Delete(root); + exit(EXIT_FAILURE); + } + cJSON_Delete(root); + + /* Our "gallery" item: */ // root = cJSON_CreateObject(); // cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); // cJSON_AddNumberToObject(img, "Width", 800); @@ -225,8 +225,8 @@ static void create_objects(void) // exit(EXIT_FAILURE); // } // cJSON_Delete(root); -// -// /* Our array of "records": */ + + /* Our array of "records": */ // root = cJSON_CreateArray(); // for (i = 0; i < 2; i++) // { From 5647b6a0cd540e7efe667ad3b881f5f673fbeecf Mon Sep 17 00:00:00 2001 From: xijianjun Date: Thu, 30 Jul 2020 20:37:42 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0summary;=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E4=B8=80=E4=BA=9B=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cJSON.c | 4 +++- summary.md | 40 ++++++++++++++++++++++++++++++++++++++-- tests/parse_array.c | 3 ++- tests/parse_examples.c | 6 ++++-- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/cJSON.c b/cJSON.c index 2003d1a1f..5c8a17972 100644 --- a/cJSON.c +++ b/cJSON.c @@ -1049,10 +1049,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { + // 32在ascii码表中为空格,空格之前的符号都忽略 buffer->offset++; } - //todo ?? + //offset 取值范围[0, length-1] if (buffer->offset == buffer->length) { buffer->offset--; @@ -1511,6 +1512,7 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { + // 字符串最后出错 goto fail; /* expected end of array */ } diff --git a/summary.md b/summary.md index a511aea3f..a0e9cc151 100644 --- a/summary.md +++ b/summary.md @@ -8,7 +8,8 @@ ```` parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; ```` -7. whitespace and cr/lf https://www.jianshu.com/p/8d33019d1c69 +1. whitespace and cr/lf https://www.jianshu.com/p/8d33019d1c69 +2. 文件读取 标准库 fopen fread ---------------------------------- @@ -47,6 +48,35 @@ format prev -> name next -> null + +typedef struct +{ + const unsigned char *content; //将要解析的字符串 + size_t length; //字符串长度 + size_t offset; //从0开始; 步长1; 字符串偏移量 范围 0 -- length-1 + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + + +typedef struct +{ + unsigned char *buffer; + size_t length; // buffer大小 + size_t offset; // 偏移量 + size_t depth; /* current nesting depth (for formatted printing) */ /** object嵌套深度 */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; //printbuffer 属性参照parse_buffer + + +C标准 +---------------------------- +fseek(file, 0, SEEK_END) +ftell(file) +配合,可知文件内容大小,单位:字节 + ```` 定义 cJSON_CreateObject(void) 调用 cJSON_CreateObject() @@ -58,4 +88,10 @@ cJSON_PrintPreallocated - cJSON_CreateArray - cJSON_CreateIntArray - add_item_to_array -- add_item_to_array NOTE line 1989 \ No newline at end of file +- add_item_to_array NOTE line 1989 +- parse_array + + +附 +--------------- +\t属于转义字符。是水平制表符,相当于键盘上的TAB按键du。通常宽度相当于8个空格的位置, \ No newline at end of file diff --git a/tests/parse_array.c b/tests/parse_array.c index d013f2247..6f9f6c73c 100644 --- a/tests/parse_array.c +++ b/tests/parse_array.c @@ -155,9 +155,10 @@ static void parse_array_should_not_parse_non_arrays(void) int CJSON_CDECL main(void) { +// printf("size of string is %lu\n", sizeof("")); +// printf("len of string is %lu", strlen("")); /* initialize cJSON item */ memset(item, 0, sizeof(cJSON)); - UNITY_BEGIN(); RUN_TEST(parse_array_should_parse_empty_arrays); RUN_TEST(parse_array_should_parse_arrays_with_one_element); diff --git a/tests/parse_examples.c b/tests/parse_examples.c index 95a095903..3bbc37ea5 100644 --- a/tests/parse_examples.c +++ b/tests/parse_examples.c @@ -43,6 +43,7 @@ static cJSON *parse_file(const char *filename) return parsed; } +//看下I/O static void do_test(const char *test_name) { char *expected = NULL; @@ -57,8 +58,9 @@ static void do_test(const char *test_name) test_name_length = strlen(test_name); - /* allocate file paths */ -#define TEST_DIR_PATH "inputs/" + /* allocate file paths 方法里也可以定义宏 */ + #define TEST_DIR_PATH "inputs/" + test_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length); TEST_ASSERT_NOT_NULL_MESSAGE(test_path, "Failed to allocate test_path buffer."); expected_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length + sizeof(".expected")); From c56e626e55c2e861ebcc1142a5ba9934de99f578 Mon Sep 17 00:00:00 2001 From: xijianjun <897808402@qq.com> Date: Wed, 30 Sep 2020 10:36:20 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0summary.md=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E5=8C=85=E6=8B=AC=E5=B7=B2=E7=9C=8B=E6=BA=90?= =?UTF-8?q?=E7=A0=81=E3=80=81C=E8=AF=AD=E8=A8=80=E7=9F=A5=E8=AF=86?= =?UTF-8?q?=E7=82=B9=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- cJSON.c | 27 +- cJSON.h | 10 +- summary.md | 20 + tests/compare_tests.c | 18 +- tests/json-patch-tests/tests (copy).json | 464 +++++++++++++++++++++++ tests/json-patch-tests/tests.json | 34 +- tests/json_patch_tests.c | 7 +- tests/minify_tests.c | 24 +- 9 files changed, 538 insertions(+), 68 deletions(-) create mode 100644 tests/json-patch-tests/tests (copy).json diff --git a/CMakeLists.txt b/CMakeLists.txt index d52d1e505..924c95b89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(custom_compiler_flags) include(CheckCCompilerFlag) option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON) if (ENABLE_CUSTOM_COMPILER_FLAGS) - if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) + if (("${CMAKE_C_COMPILER_ID}" STREQUAL "GCC") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) list(APPEND custom_compiler_flags -std=c99 -pedantic diff --git a/cJSON.c b/cJSON.c index 5c8a17972..3e7f01fc9 100644 --- a/cJSON.c +++ b/cJSON.c @@ -256,10 +256,13 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) while (item != NULL) { next = item->next; + // item->child != null 表示 An array or object item will have a child pointer if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); } + + // item->valuestring != null 表示 string 或 json raw if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); @@ -1882,26 +1885,26 @@ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) return get_array_item(array, (size_t)index); } -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +static cJSON *get_object_item(const cJSON * const object, const char * const attr, const cJSON_bool case_sensitive) { cJSON *current_element = NULL; - if ((object == NULL) || (name == NULL)) + if ((object == NULL) || (attr == NULL)) { return NULL; } current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + if (case_sensitive)//true + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(attr, current_element->string) != 0)) { current_element = current_element->next; } } else { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)attr, (const unsigned char*)(current_element->string)) != 0)) { current_element = current_element->next; } @@ -1919,9 +1922,9 @@ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char return get_object_item(object, string, false); } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const attr) { - return get_object_item(object, string, true); + return get_object_item(object, attr, true); } CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) @@ -2721,6 +2724,8 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) newitem->type = item->type & (~cJSON_IsReference); newitem->valueint = item->valueint; newitem->valuedouble = item->valuedouble; + + //【注意】引用要duplicate if (item->valuestring) { newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); @@ -2827,6 +2832,7 @@ static void minify_string(char **input, char **output) { } } +//【字符串指针操作】 CJSON_PUBLIC(void) cJSON_Minify(char *json) { char *into = json; @@ -2850,10 +2856,12 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) case '/': if (json[1] == '/') { + //单行注释 skip_oneline_comment(&json); } else if (json[1] == '*') { + //多行注释 skip_multiline_comment(&json); } else { json++; @@ -3014,6 +3022,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return true; case cJSON_Number: + //note double类型的比较 if (compare_double(a->valuedouble, b->valuedouble)) { return true; @@ -3022,6 +3031,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons case cJSON_String: case cJSON_Raw: + //原生json串或字符串直接调用 strcmp 比较即可 if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; @@ -3063,6 +3073,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons cJSON *b_element = NULL; cJSON_ArrayForEach(a_element, a) { + /* 对象的属性比较的时间复杂度O(n^2),比较糟糕 */ /* TODO This has O(n^2) runtime, which is horrible! */ b_element = get_object_item(b, a_element->string, case_sensitive); if (b_element == NULL) diff --git a/cJSON.h b/cJSON.h index 003552f99..a56cacb97 100644 --- a/cJSON.h +++ b/cJSON.h @@ -94,7 +94,8 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ #define cJSON_String (1 << 4) #define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ +/* raw json译为 原生json串 */ +#define cJSON_Raw (1 << 7) #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 @@ -281,8 +282,11 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) +/* Macro for iterating over an array or object */ // 注意宏换行 +#define cJSON_ArrayForEach(element, array) for(\ +element = (array != NULL) ? (array)->child : NULL; \ +element != NULL; \ +element = element->next) /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); diff --git a/summary.md b/summary.md index a0e9cc151..a8c3a50a6 100644 --- a/summary.md +++ b/summary.md @@ -10,6 +10,8 @@ ```` 1. whitespace and cr/lf https://www.jianshu.com/p/8d33019d1c69 2. 文件读取 标准库 fopen fread +3. char '\0' === int 0 +4. 调了allocate 就要调free ---------------------------------- @@ -89,8 +91,26 @@ cJSON_PrintPreallocated - cJSON_CreateIntArray - add_item_to_array - add_item_to_array NOTE line 1989 + +Parse +- cJSON_Parse + - parse_array +Compare +- cJSON_Compare +- compare_from_string + +get_object_item +- get_object_item +- cJSON_IsString +- cJSON_IsArray + +cJSON_Duplicate + + +cJson_Utils +- decode_patch_operation 附 --------------- diff --git a/tests/compare_tests.c b/tests/compare_tests.c index 797c7740c..52e00f3d6 100644 --- a/tests/compare_tests.c +++ b/tests/compare_tests.c @@ -37,6 +37,7 @@ static cJSON_bool compare_from_string(const char * const a, const char * const b result = cJSON_Compare(a_json, b_json, case_sensitive); + //【注意】仔细想一想,这里为什么要调cJSON_Delete cJSON_Delete(a_json); cJSON_Delete(b_json); @@ -52,6 +53,7 @@ static void cjson_compare_should_compare_null_pointer_as_not_equal(void) static void cjson_compare_should_compare_invalid_as_not_equal(void) { cJSON invalid[1]; + //【C习惯】C里对结构体初始化0值,其实就是空值 memset(invalid, '\0', sizeof(invalid)); TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false)); @@ -109,7 +111,7 @@ static void cjson_compare_should_not_accept_invalid_types(void) TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false)); } -static void cjson_compare_should_compare_strings(void) +__attribute__((unused)) static void cjson_compare_should_compare_strings(void) { TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", true)); TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", false)); @@ -118,7 +120,7 @@ static void cjson_compare_should_compare_strings(void) TEST_ASSERT_FALSE(compare_from_string("\"ABCDEFG\"", "\"abcdefg\"", false)); } -static void cjson_compare_should_compare_raw(void) +__attribute__((unused)) static void cjson_compare_should_compare_raw(void) { cJSON *raw1 = NULL; cJSON *raw2 = NULL; @@ -138,7 +140,7 @@ static void cjson_compare_should_compare_raw(void) cJSON_Delete(raw2); } -static void cjson_compare_should_compare_arrays(void) +__attribute__((unused)) static void cjson_compare_should_compare_arrays(void) { TEST_ASSERT_TRUE(compare_from_string("[]", "[]", true)); TEST_ASSERT_TRUE(compare_from_string("[]", "[]", false)); @@ -157,7 +159,7 @@ static void cjson_compare_should_compare_arrays(void) TEST_ASSERT_FALSE(compare_from_string("[1,2,3]", "[1,2]", false)); } -static void cjson_compare_should_compare_objects(void) +__attribute__((unused)) static void cjson_compare_should_compare_objects(void) { TEST_ASSERT_TRUE(compare_from_string("{}", "{}", true)); TEST_ASSERT_TRUE(compare_from_string("{}", "{}", false)); @@ -199,10 +201,10 @@ int CJSON_CDECL main(void) RUN_TEST(cjson_compare_should_compare_booleans); RUN_TEST(cjson_compare_should_compare_null); RUN_TEST(cjson_compare_should_not_accept_invalid_types); - RUN_TEST(cjson_compare_should_compare_strings); - RUN_TEST(cjson_compare_should_compare_raw); - RUN_TEST(cjson_compare_should_compare_arrays); - RUN_TEST(cjson_compare_should_compare_objects); + // RUN_TEST(cjson_compare_should_compare_strings); + // RUN_TEST(cjson_compare_should_compare_raw); + // RUN_TEST(cjson_compare_should_compare_arrays); + // RUN_TEST(cjson_compare_should_compare_objects); return UNITY_END(); } diff --git a/tests/json-patch-tests/tests (copy).json b/tests/json-patch-tests/tests (copy).json new file mode 100644 index 000000000..255407810 --- /dev/null +++ b/tests/json-patch-tests/tests (copy).json @@ -0,0 +1,464 @@ +[ + { "comment": "empty list, empty docs", + "doc": {}, + "patch": [], + "expected": {} }, + + { "comment": "empty patch list", + "doc": {"foo": 1}, + "patch": [], + "expected": {"foo": 1} }, + + { "comment": "rearrangements OK?", + "doc": {"foo": 1, "bar": 2}, + "patch": [], + "expected": {"bar":2, "foo": 1} }, + + { "comment": "rearrangements OK? How about one level down ... array", + "doc": [{"foo": 1, "bar": 2}], + "patch": [], + "expected": [{"bar":2, "foo": 1}] }, + + { "comment": "rearrangements OK? How about one level down...", + "doc": {"foo":{"foo": 1, "bar": 2}}, + "patch": [], + "expected": {"foo":{"bar":2, "foo": 1}} }, + + { "comment": "add replaces any existing field", + "doc": {"foo": null}, + "patch": [{"op": "add", "path": "/foo", "value":1}], + "expected": {"foo": 1} }, + + { "comment": "toplevel array", + "doc": [], + "patch": [{"op": "add", "path": "/0", "value": "foo"}], + "expected": ["foo"] }, + + { "comment": "toplevel array, no change", + "doc": ["foo"], + "patch": [], + "expected": ["foo"] }, + + { "comment": "toplevel object, numeric string", + "doc": {}, + "patch": [{"op": "add", "path": "/foo", "value": "1"}], + "expected": {"foo":"1"} }, + + { "comment": "toplevel object, integer", + "doc": {}, + "patch": [{"op": "add", "path": "/foo", "value": 1}], + "expected": {"foo":1} }, + + { "comment": "Toplevel scalar values OK?", + "doc": "foo", + "patch": [{"op": "replace", "path": "", "value": "bar"}], + "expected": "bar", + "disabled": true }, + + { "comment": "replace object document with array document?", + "doc": {}, + "patch": [{"op": "add", "path": "", "value": []}], + "expected": [] }, + + { "comment": "replace array document with object document?", + "doc": [], + "patch": [{"op": "add", "path": "", "value": {}}], + "expected": {} }, + + { "comment": "append to root array document?", + "doc": [], + "patch": [{"op": "add", "path": "/-", "value": "hi"}], + "expected": ["hi"] }, + + { "comment": "Add, / target", + "doc": {}, + "patch": [ {"op": "add", "path": "/", "value":1 } ], + "expected": {"":1} }, + + { "comment": "Add, /foo/ deep target (trailing slash)", + "doc": {"foo": {}}, + "patch": [ {"op": "add", "path": "/foo/", "value":1 } ], + "expected": {"foo":{"": 1}} }, + + { "comment": "Add composite value at top level", + "doc": {"foo": 1}, + "patch": [{"op": "add", "path": "/bar", "value": [1, 2]}], + "expected": {"foo": 1, "bar": [1, 2]} }, + + { "comment": "Add into composite value", + "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, + "patch": [{"op": "add", "path": "/baz/0/foo", "value": "world"}], + "expected": {"foo": 1, "baz": [{"qux": "hello", "foo": "world"}]} }, + + { "doc": {"bar": [1, 2]}, + "patch": [{"op": "add", "path": "/bar/8", "value": "5"}], + "error": "Out of bounds (upper)" }, + + { "doc": {"bar": [1, 2]}, + "patch": [{"op": "add", "path": "/bar/-1", "value": "5"}], + "error": "Out of bounds (lower)" }, + + { "doc": {"foo": 1}, + "patch": [{"op": "add", "path": "/bar", "value": true}], + "expected": {"foo": 1, "bar": true} }, + + { "doc": {"foo": 1}, + "patch": [{"op": "add", "path": "/bar", "value": false}], + "expected": {"foo": 1, "bar": false} }, + + { "doc": {"foo": 1}, + "patch": [{"op": "add", "path": "/bar", "value": null}], + "expected": {"foo": 1, "bar": null} }, + + { "comment": "0 can be an array index or object element name", + "doc": {"foo": 1}, + "patch": [{"op": "add", "path": "/0", "value": "bar"}], + "expected": {"foo": 1, "0": "bar" } }, + + { "doc": ["foo"], + "patch": [{"op": "add", "path": "/1", "value": "bar"}], + "expected": ["foo", "bar"] }, + + { "doc": ["foo", "sil"], + "patch": [{"op": "add", "path": "/1", "value": "bar"}], + "expected": ["foo", "bar", "sil"] }, + + { "doc": ["foo", "sil"], + "patch": [{"op": "add", "path": "/0", "value": "bar"}], + "expected": ["bar", "foo", "sil"] }, + + { "comment": "push item to array via last index + 1", + "doc": ["foo", "sil"], + "patch": [{"op":"add", "path": "/2", "value": "bar"}], + "expected": ["foo", "sil", "bar"] }, + + { "comment": "add item to array at index > length should fail", + "doc": ["foo", "sil"], + "patch": [{"op":"add", "path": "/3", "value": "bar"}], + "error": "index is greater than number of items in array" }, + + { "comment": "test against implementation-specific numeric parsing", + "doc": {"1e0": "foo"}, + "patch": [{"op": "test", "path": "/1e0", "value": "foo"}], + "expected": {"1e0": "foo"} }, + + { "comment": "test with bad number should fail", + "doc": ["foo", "bar"], + "patch": [{"op": "test", "path": "/1e0", "value": "bar"}], + "error": "test op shouldn't get array element 1" }, + + { "doc": ["foo", "sil"], + "patch": [{"op": "add", "path": "/bar", "value": 42}], + "error": "Object operation on array target" }, + + { "doc": ["foo", "sil"], + "patch": [{"op": "add", "path": "/1", "value": ["bar", "baz"]}], + "expected": ["foo", ["bar", "baz"], "sil"], + "comment": "value in array add not flattened" }, + + { "doc": {"foo": 1, "bar": [1, 2, 3, 4]}, + "patch": [{"op": "remove", "path": "/bar"}], + "expected": {"foo": 1} }, + + { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, + "patch": [{"op": "remove", "path": "/baz/0/qux"}], + "expected": {"foo": 1, "baz": [{}]} }, + + { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, + "patch": [{"op": "replace", "path": "/foo", "value": [1, 2, 3, 4]}], + "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]} }, + + { "doc": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}]}, + "patch": [{"op": "replace", "path": "/baz/0/qux", "value": "world"}], + "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "world"}]} }, + + { "doc": ["foo"], + "patch": [{"op": "replace", "path": "/0", "value": "bar"}], + "expected": ["bar"] }, + + { "doc": [""], + "patch": [{"op": "replace", "path": "/0", "value": 0}], + "expected": [0] }, + + { "doc": [""], + "patch": [{"op": "replace", "path": "/0", "value": true}], + "expected": [true] }, + + { "doc": [""], + "patch": [{"op": "replace", "path": "/0", "value": false}], + "expected": [false] }, + + { "doc": [""], + "patch": [{"op": "replace", "path": "/0", "value": null}], + "expected": [null] }, + + { "doc": ["foo", "sil"], + "patch": [{"op": "replace", "path": "/1", "value": ["bar", "baz"]}], + "expected": ["foo", ["bar", "baz"]], + "comment": "value in array replace not flattened" }, + + { "comment": "replace whole document", + "doc": {"foo": "bar"}, + "patch": [{"op": "replace", "path": "", "value": {"baz": "qux"}}], + "expected": {"baz": "qux"} }, + + { "comment": "test replace with missing parent key should fail", + "doc": {"bar": "baz"}, + "patch": [{"op": "replace", "path": "/foo/bar", "value": false}], + "error": "replace op should fail with missing parent key" }, + + { "comment": "spurious patch properties", + "doc": {"foo": 1}, + "patch": [{"op": "test", "path": "/foo", "value": 1, "spurious": 1}], + "expected": {"foo": 1} }, + + { "doc": {"foo": null}, + "patch": [{"op": "test", "path": "/foo", "value": null}], + "expected": {"foo": null}, + "comment": "null value should be valid obj property" }, + + { "doc": {"foo": null}, + "patch": [{"op": "replace", "path": "/foo", "value": "truthy"}], + "expected": {"foo": "truthy"}, + "comment": "null value should be valid obj property to be replaced with something truthy" }, + + { "doc": {"foo": null}, + "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], + "expected": {"bar": null}, + "comment": "null value should be valid obj property to be moved" }, + + { "doc": {"foo": null}, + "patch": [{"op": "copy", "from": "/foo", "path": "/bar"}], + "expected": {"foo": null, "bar": null}, + "comment": "null value should be valid obj property to be copied" }, + + { "doc": {"foo": null}, + "patch": [{"op": "remove", "path": "/foo"}], + "expected": {}, + "comment": "null value should be valid obj property to be removed" }, + + { "doc": {"foo": "bar"}, + "patch": [{"op": "replace", "path": "/foo", "value": null}], + "expected": {"foo": null}, + "comment": "null value should still be valid obj property replace other value" }, + + { "doc": {"foo": {"foo": 1, "bar": 2}}, + "patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}], + "expected": {"foo": {"foo": 1, "bar": 2}}, + "comment": "test should pass despite rearrangement" }, + + { "doc": {"foo": [{"foo": 1, "bar": 2}]}, + "patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}], + "expected": {"foo": [{"foo": 1, "bar": 2}]}, + "comment": "test should pass despite (nested) rearrangement" }, + + { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, + "patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}], + "expected": {"foo": {"bar": [1, 2, 5, 4]}}, + "comment": "test should pass - no error" }, + + { "doc": {"foo": {"bar": [1, 2, 5, 4]}}, + "patch": [{"op": "test", "path": "/foo", "value": [1, 2]}], + "error": "test op should fail" }, + + { "comment": "Whole document", + "doc": { "foo": 1 }, + "patch": [{"op": "test", "path": "", "value": {"foo": 1}}], + "disabled": true }, + + { "comment": "Empty-string element", + "doc": { "": 1 }, + "patch": [{"op": "test", "path": "/", "value": 1}], + "expected": { "": 1 } }, + + { "doc": { + "foo": ["bar", "baz"], + "": 0, + "a/b": 1, + "c%d": 2, + "e^f": 3, + "g|h": 4, + "i\\j": 5, + "k\"l": 6, + " ": 7, + "m~n": 8 + }, + "patch": [{"op": "test", "path": "/foo", "value": ["bar", "baz"]}, + {"op": "test", "path": "/foo/0", "value": "bar"}, + {"op": "test", "path": "/", "value": 0}, + {"op": "test", "path": "/a~1b", "value": 1}, + {"op": "test", "path": "/c%d", "value": 2}, + {"op": "test", "path": "/e^f", "value": 3}, + {"op": "test", "path": "/g|h", "value": 4}, + {"op": "test", "path": "/i\\j", "value": 5}, + {"op": "test", "path": "/k\"l", "value": 6}, + {"op": "test", "path": "/ ", "value": 7}, + {"op": "test", "path": "/m~0n", "value": 8}], + "expected": { + "": 0, + " ": 7, + "a/b": 1, + "c%d": 2, + "e^f": 3, + "foo": [ + "bar", + "baz" + ], + "g|h": 4, + "i\\j": 5, + "k\"l": 6, + "m~n": 8 + } + }, + { "comment": "Move to same location has no effect", + "doc": {"foo": 1}, + "patch": [{"op": "move", "from": "/foo", "path": "/foo"}], + "expected": {"foo": 1} }, + + { "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, + "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], + "expected": {"baz": [{"qux": "hello"}], "bar": 1} }, + + { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, + "patch": [{"op": "move", "from": "/baz/0/qux", "path": "/baz/1"}], + "expected": {"baz": [{}, "hello"], "bar": 1} }, + + { "doc": {"baz": [{"qux": "hello"}], "bar": 1}, + "patch": [{"op": "copy", "from": "/baz/0", "path": "/boo"}], + "expected": {"baz":[{"qux":"hello"}],"bar":1,"boo":{"qux":"hello"}} }, + + { "comment": "replacing the root of the document is possible with add", + "doc": {"foo": "bar"}, + "patch": [{"op": "add", "path": "", "value": {"baz": "qux"}}], + "expected": {"baz":"qux"}}, + + { "comment": "Adding to \"/-\" adds to the end of the array", + "doc": [ 1, 2 ], + "patch": [ { "op": "add", "path": "/-", "value": { "foo": [ "bar", "baz" ] } } ], + "expected": [ 1, 2, { "foo": [ "bar", "baz" ] } ]}, + + { "comment": "Adding to \"/-\" adds to the end of the array, even n levels down", + "doc": [ 1, 2, [ 3, [ 4, 5 ] ] ], + "patch": [ { "op": "add", "path": "/2/1/-", "value": { "foo": [ "bar", "baz" ] } } ], + "expected": [ 1, 2, [ 3, [ 4, 5, { "foo": [ "bar", "baz" ] } ] ] ]}, + + { "comment": "test remove with bad number should fail", + "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, + "patch": [{"op": "remove", "path": "/baz/1e0/qux"}], + "error": "remove op shouldn't remove from array with bad number" }, + + { "comment": "test remove on array", + "doc": [1, 2, 3, 4], + "patch": [{"op": "remove", "path": "/0"}], + "expected": [2, 3, 4] }, + + { "comment": "test repeated removes", + "doc": [1, 2, 3, 4], + "patch": [{ "op": "remove", "path": "/1" }, + { "op": "remove", "path": "/2" }], + "expected": [1, 3] }, + + { "comment": "test remove with bad index should fail", + "doc": [1, 2, 3, 4], + "patch": [{"op": "remove", "path": "/1e0"}], + "error": "remove op shouldn't remove from array with bad number" }, + + { "comment": "test replace with bad number should fail", + "doc": [""], + "patch": [{"op": "replace", "path": "/1e0", "value": false}], + "error": "replace op shouldn't replace in array with bad number" }, + + { "comment": "test copy with bad number should fail", + "doc": {"baz": [1,2,3], "bar": 1}, + "patch": [{"op": "copy", "from": "/baz/1e0", "path": "/boo"}], + "error": "copy op shouldn't work with bad number" }, + + { "comment": "test move with bad number should fail", + "doc": {"foo": 1, "baz": [1,2,3,4]}, + "patch": [{"op": "move", "from": "/baz/1e0", "path": "/foo"}], + "error": "move op shouldn't work with bad number" }, + + { "comment": "test add with bad number should fail", + "doc": ["foo", "sil"], + "patch": [{"op": "add", "path": "/1e0", "value": "bar"}], + "error": "add op shouldn't add to array with bad number" }, + + { "comment": "missing 'value' parameter to add", + "doc": [ 1 ], + "patch": [ { "op": "add", "path": "/-" } ], + "error": "missing 'value' parameter" }, + + { "comment": "missing 'value' parameter to replace", + "doc": [ 1 ], + "patch": [ { "op": "replace", "path": "/0" } ], + "error": "missing 'value' parameter" }, + + { "comment": "missing 'value' parameter to test", + "doc": [ null ], + "patch": [ { "op": "test", "path": "/0" } ], + "error": "missing 'value' parameter" }, + + { "comment": "missing value parameter to test - where undef is falsy", + "doc": [ false ], + "patch": [ { "op": "test", "path": "/0" } ], + "error": "missing 'value' parameter" }, + + { "comment": "missing from parameter to copy", + "doc": [ 1 ], + "patch": [ { "op": "copy", "path": "/-" } ], + "error": "missing 'from' parameter" }, + + { "comment": "missing from location to copy", + "doc": { "foo": 1 }, + "patch": [ { "op": "copy", "from": "/bar", "path": "/foo" } ], + "error": "missing 'from' location" }, + + { "comment": "missing from parameter to move", + "doc": { "foo": 1 }, + "patch": [ { "op": "move", "path": "" } ], + "error": "missing 'from' parameter" }, + + { "comment": "missing from location to move", + "doc": { "foo": 1 }, + "patch": [ { "op": "move", "from": "/bar", "path": "/foo" } ], + "error": "missing 'from' location" }, + + { "comment": "duplicate ops", + "doc": { "foo": "bar" }, + "patch": [ { "op": "add", "path": "/baz", "value": "qux", + "op": "move", "from":"/foo" } ], + "error": "patch has two 'op' members", + "disabled": true }, + + { "comment": "unrecognized op should fail", + "doc": {"foo": 1}, + "patch": [{"op": "spam", "path": "/foo", "value": 1}], + "error": "Unrecognized op 'spam'" }, + + { "comment": "test with bad array number that has leading zeros", + "doc": ["foo", "bar"], + "patch": [{"op": "test", "path": "/00", "value": "foo"}], + "error": "test op should reject the array value, it has leading zeros" }, + + { "comment": "test with bad array number that has leading zeros", + "doc": ["foo", "bar"], + "patch": [{"op": "test", "path": "/01", "value": "bar"}], + "error": "test op should reject the array value, it has leading zeros" }, + + { "comment": "Removing nonexistent field", + "doc": {"foo" : "bar"}, + "patch": [{"op": "remove", "path": "/baz"}], + "error": "removing a nonexistent field should fail" }, + + { "comment": "Removing nonexistent index", + "doc": ["foo", "bar"], + "patch": [{"op": "remove", "path": "/2"}], + "error": "removing a nonexistent index should fail" }, + + { "comment": "Patch with different capitalisation than doc", + "doc": {"foo":"bar"}, + "patch": [{"op": "add", "path": "/FOO", "value": "BAR"}], + "expected": {"foo": "bar", "FOO": "BAR"} + } + +] diff --git a/tests/json-patch-tests/tests.json b/tests/json-patch-tests/tests.json index 255407810..8c9da38a2 100644 --- a/tests/json-patch-tests/tests.json +++ b/tests/json-patch-tests/tests.json @@ -1,28 +1,7 @@ [ - { "comment": "empty list, empty docs", - "doc": {}, - "patch": [], - "expected": {} }, - - { "comment": "empty patch list", - "doc": {"foo": 1}, - "patch": [], - "expected": {"foo": 1} }, - { "comment": "rearrangements OK?", - "doc": {"foo": 1, "bar": 2}, - "patch": [], - "expected": {"bar":2, "foo": 1} }, - { "comment": "rearrangements OK? How about one level down ... array", - "doc": [{"foo": 1, "bar": 2}], - "patch": [], - "expected": [{"bar":2, "foo": 1}] }, - { "comment": "rearrangements OK? How about one level down...", - "doc": {"foo":{"foo": 1, "bar": 2}}, - "patch": [], - "expected": {"foo":{"bar":2, "foo": 1}} }, { "comment": "add replaces any existing field", "doc": {"foo": null}, @@ -34,10 +13,7 @@ "patch": [{"op": "add", "path": "/0", "value": "foo"}], "expected": ["foo"] }, - { "comment": "toplevel array, no change", - "doc": ["foo"], - "patch": [], - "expected": ["foo"] }, + { "comment": "toplevel object, numeric string", "doc": {}, @@ -55,15 +31,7 @@ "expected": "bar", "disabled": true }, - { "comment": "replace object document with array document?", - "doc": {}, - "patch": [{"op": "add", "path": "", "value": []}], - "expected": [] }, - { "comment": "replace array document with object document?", - "doc": [], - "patch": [{"op": "add", "path": "", "value": {}}], - "expected": {} }, { "comment": "append to root array document?", "doc": [], diff --git a/tests/json_patch_tests.c b/tests/json_patch_tests.c index c2c88a4f5..20356ddd7 100644 --- a/tests/json_patch_tests.c +++ b/tests/json_patch_tests.c @@ -41,6 +41,7 @@ static cJSON *parse_test_file(const char * const filename) TEST_ASSERT_NOT_NULL_MESSAGE(json, "Failed to parse test json."); TEST_ASSERT_TRUE_MESSAGE(cJSON_IsArray(json), "Json is not an array."); + //注意file的类型 不是File* !!! free(file); return json; @@ -88,7 +89,7 @@ static cJSON_bool test_apply_patch(const cJSON * const test) error_element = cJSON_GetObjectItemCaseSensitive(test, "error"); if (error_element != NULL) { - /* excepting an error */ + /* excepting an error */ //【ignore】 TEST_ASSERT_TRUE_MESSAGE(0 != cJSONUtils_ApplyPatchesCaseSensitive(object, patch), "Test didn't fail as it's supposed to."); successful = true; @@ -236,8 +237,8 @@ int main(void) UNITY_BEGIN(); RUN_TEST(cjson_utils_should_pass_json_patch_test_tests); - RUN_TEST(cjson_utils_should_pass_json_patch_test_spec_tests); - RUN_TEST(cjson_utils_should_pass_json_patch_test_cjson_utils_tests); + //RUN_TEST(cjson_utils_should_pass_json_patch_test_spec_tests); + //RUN_TEST(cjson_utils_should_pass_json_patch_test_cjson_utils_tests); return UNITY_END(); } diff --git a/tests/minify_tests.c b/tests/minify_tests.c index 000821dbf..73024f666 100644 --- a/tests/minify_tests.c +++ b/tests/minify_tests.c @@ -29,7 +29,7 @@ #include "common.h" -static void cjson_minify_should_not_overflow_buffer(void) +__attribute__((unused)) static void cjson_minify_should_not_overflow_buffer(void) { char unclosed_multiline_comment[] = "/* bla"; char pending_escape[] = "\"\\"; @@ -41,7 +41,7 @@ static void cjson_minify_should_not_overflow_buffer(void) TEST_ASSERT_EQUAL_STRING("\"\\", pending_escape); } -static void cjson_minify_should_remove_single_line_comments(void) +__attribute__((unused)) static void cjson_minify_should_remove_single_line_comments(void) { const char to_minify[] = "{// this is {} \"some kind\" of [] comment /*, don't you see\n}"; @@ -55,7 +55,7 @@ static void cjson_minify_should_remove_single_line_comments(void) free(minified); } -static void cjson_minify_should_remove_spaces(void) +__attribute__((unused)) static void cjson_minify_should_remove_spaces(void) { const char to_minify[] = "{ \"key\":\ttrue\r\n }"; @@ -69,7 +69,7 @@ static void cjson_minify_should_remove_spaces(void) free(minified); } -static void cjson_minify_should_remove_multiline_comments(void) +__attribute__((unused)) static void cjson_minify_should_remove_multiline_comments(void) { const char to_minify[] = "{/* this is\n a /* multi\n //line \n {comment \"\\\" */}"; @@ -83,7 +83,7 @@ static void cjson_minify_should_remove_multiline_comments(void) free(minified); } -static void cjson_minify_should_not_modify_strings(void) +__attribute__((unused)) static void cjson_minify_should_not_modify_strings(void) { const char to_minify[] = "\"this is a string \\\" \\t bla\""; @@ -152,7 +152,7 @@ static void cjson_minify_should_minify_json(void) { free(buffer); } -static void cjson_minify_should_not_loop_infinitely(void) { +__attribute__((unused)) static void cjson_minify_should_not_loop_infinitely(void) { char string[] = { '8', ' ', '/', ' ', '5', '\n', '\0' }; /* this should not be an infinite loop */ cJSON_Minify(string); @@ -162,13 +162,13 @@ int CJSON_CDECL main(void) { UNITY_BEGIN(); - RUN_TEST(cjson_minify_should_not_overflow_buffer); + // RUN_TEST(cjson_minify_should_not_overflow_buffer); RUN_TEST(cjson_minify_should_minify_json); - RUN_TEST(cjson_minify_should_remove_single_line_comments); - RUN_TEST(cjson_minify_should_remove_multiline_comments); - RUN_TEST(cjson_minify_should_remove_spaces); - RUN_TEST(cjson_minify_should_not_modify_strings); - RUN_TEST(cjson_minify_should_not_loop_infinitely); + // RUN_TEST(cjson_minify_should_remove_single_line_comments); + // RUN_TEST(cjson_minify_should_remove_multiline_comments); + // RUN_TEST(cjson_minify_should_remove_spaces); + // RUN_TEST(cjson_minify_should_not_modify_strings); + // RUN_TEST(cjson_minify_should_not_loop_infinitely); return UNITY_END(); } From cfade1409b18d70c10d93cf7b73e69911894589b Mon Sep 17 00:00:00 2001 From: xijianjun Date: Wed, 30 Sep 2020 10:44:36 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=B3=A8=E9=87=8A=EF=BC=9B=E6=9B=B4=E6=96=B0=E4=BA=86?= =?UTF-8?q?summary=E6=96=87=E4=BB=B6=E7=9A=84=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cJSON.c | 52 ++++++++++++++++++++++++++--------------- summary.md | 25 ++++++++++++++++++-- test.c | 44 ++++++++++++++++++++++++++++++++++ tests/common.h | 2 +- tests/compare_tests.c | 22 ++++++++++++++++- tests/parse_examples.c | 7 ++++++ tests/readme_examples.c | 37 ++++++++++++++--------------- 7 files changed, 146 insertions(+), 43 deletions(-) diff --git a/cJSON.c b/cJSON.c index 5c8a17972..bb7708022 100644 --- a/cJSON.c +++ b/cJSON.c @@ -541,6 +541,7 @@ static void update_offset(printbuffer * const buffer) /* securely comparison of floating-point variables */ static cJSON_bool compare_double(double a, double b) { + // double类型比较大小 double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); return (fabs(a - b) <= maxVal * DBL_EPSILON); } @@ -778,6 +779,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu unsigned char *output = NULL; /* not a string */ + //这个判断是不是有点多余 if (buffer_at_offset(input_buffer)[0] != '\"') { goto fail; @@ -787,9 +789,13 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* calculate approximate size of the output (overestimate) */ size_t allocation_length = 0; size_t skipped_bytes = 0; + +// size_t ret1 = (size_t) (input_end - input_buffer->content); +// printf("%lu minus %lu, equals %lu\n", (size_t)input_end, (size_t)input_buffer->content, ret1); + //todo 疑问 input_end这样的字符指针强转为size_t类型的值,该值表示什么? while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { - /* is escape sequence */ + /* is escape sequence 转义字符串 */ if (input_end[0] == '\\') { if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) @@ -800,8 +806,9 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu skipped_bytes++; input_end++; } - input_end++; + input_end++;//算input_end呗 } +// printf("input_end is %lu\n", (size_t)input_end); if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { goto fail; /* string ended unexpectedly */ @@ -1034,7 +1041,7 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); -/* Utility to jump whitespace and cr/lf */ +/* Utility to jump whitespace and cr/lf 跳过空格符 换行符 */ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) { if ((buffer == NULL) || (buffer->content == NULL)) @@ -1096,7 +1103,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return /* Parse an object - create a new root, and populate. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) { - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + parse_buffer buffer = {0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; /* reset error position */ @@ -1321,7 +1328,10 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf /* parse the different types of values */ /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + + //can_read means offset + size < length + //strlen("null") == 4 + if (can_read(input_buffer, strlen("null")) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) { item->type = cJSON_NULL; input_buffer->offset += 4; @@ -1342,7 +1352,8 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf input_buffer->offset += 4; return true; } - /* string */ //"" + /* string */ + // 字符串是以'\"'开头 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); @@ -1357,7 +1368,7 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf { return parse_array(item, input_buffer); } - /* object */ + /* object */ // '{' if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); @@ -1882,27 +1893,28 @@ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) return get_array_item(array, (size_t)index); } +/** + * 在object中查找名称为name的属性 + * @param object + * @param name + * @param case_sensitive + * @return + */ static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) { cJSON *current_element = NULL; - if ((object == NULL) || (name == NULL)) - { + if ((object == NULL) || (name == NULL)){ return NULL; } current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) - { + if(case_sensitive){ + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)){ current_element = current_element->next; } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { + }else{ + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)){ current_element = current_element->next; } } @@ -2442,6 +2454,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { cJSON *item = cJSON_New_Item(&global_hooks); + if(item) { item->type = cJSON_Number; @@ -3034,7 +3047,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return false; case cJSON_Array: - { + { // 数组元素依次比对 cJSON *a_element = a->child; cJSON *b_element = b->child; @@ -3050,6 +3063,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons } /* one of the arrays is longer than the other */ + // 数组长度不同 if (a_element != b_element) { return false; } diff --git a/summary.md b/summary.md index a0e9cc151..05eeb2385 100644 --- a/summary.md +++ b/summary.md @@ -9,7 +9,8 @@ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; ```` 1. whitespace and cr/lf https://www.jianshu.com/p/8d33019d1c69 -2. 文件读取 标准库 fopen fread +2. 文件读取 标准库 fopen fread fseek获取文件内容长度 ftell +3. 宏 (...) 可变参数 ---------------------------------- @@ -77,6 +78,9 @@ fseek(file, 0, SEEK_END) ftell(file) 配合,可知文件内容大小,单位:字节 +int sprintf(char *str, const char *format, ...) +发送格式化输出到 str 所指向的字符串。 + ```` 定义 cJSON_CreateObject(void) 调用 cJSON_CreateObject() @@ -92,6 +96,23 @@ cJSON_PrintPreallocated - parse_array +CJSON +----------------------------------------- +方法 +- cJSON_GetObjectItemCaseSensitive + - get_object_item + +- cJSON_Parse + - cJSON_ParseWithOpts + - parse_value + - parse_string +- cJSON_Compare + + +#### 对象 + 附 --------------- -\t属于转义字符。是水平制表符,相当于键盘上的TAB按键du。通常宽度相当于8个空格的位置, \ No newline at end of file +\t属于转义字符。是水平制表符,相当于键盘上的TAB按键。通常宽度相当于8个空格的位置, + +input_end这样的字符指针强转为size_t类型的值,该值表示什么? \ No newline at end of file diff --git a/test.c b/test.c index c1fa060b0..39f923613 100644 --- a/test.c +++ b/test.c @@ -24,6 +24,7 @@ #include #include #include "cJSON.h" +#include /* Used by some code below as an example datatype. */ struct record @@ -259,6 +260,46 @@ static void create_objects(void) // cJSON_Delete(root); } +//void testDataTypeRange(){ + // printf("char min: %d, char max: %d\n" , CHAR_MIN, CHAR_MAX); // 占用 1byte + // printf("short int min: %d, short int max: %d\n" , SHRT_MIN, SHRT_MAX);// short 占用 2byte + // printf("int min: %d, int max: %d\n" , INT_MIN, INT_MAX); // 占用 4byte + // printf("long int min: %ld, long int max: %ld\n" , LONG_MIN, LONG_MAX); +//} + +//error: function declaration isn't a prototype +static void test_print(void){ +// const char* printMsg = "hello, world"; + + int integer = 1234; + + // %[-]字段宽度.精度[转换字符] +// printf(":%s:\n", printMsg); + printf("------------\n"); + + //可以比较 +// printf(":%15s:\n", printMsg); +// printf(":%-15s:\n", printMsg); +// +// printf("------------\n"); +// printf(":%.10s:\n", printMsg); +// printf(":%.15s:\n", printMsg); +// +// printf("------------\n"); +// printf(":%15.10s:\n", printMsg); +// printf(":%-15.10s:\n", printMsg); + + /* 整型 精度小于长度,不会出现整型截断 */ + printf(":%5d:\n", integer); + printf(":%-5d:\n", integer); + + printf(":%.5d:\n", integer); + printf(":%.3d:\n", integer); + + printf(":%5.3d:\n", integer); + printf(":%-5.3d:\n", integer); +} + int CJSON_CDECL main(void) { /* print the version */ @@ -267,5 +308,8 @@ int CJSON_CDECL main(void) /* Now some samplecode for building objects concisely: */ create_objects(); + printf("-----------------------------\n"); + test_print(); + return 0; } diff --git a/tests/common.h b/tests/common.h index 4db6bf8c2..fb66aca34 100644 --- a/tests/common.h +++ b/tests/common.h @@ -57,7 +57,7 @@ char* read_file(const char *filename) { goto cleanup; } - /* get the length */ + /* get the length 文件长度不为0,表示文件内容不为空*/ if (fseek(file, 0, SEEK_END) != 0) { goto cleanup; diff --git a/tests/compare_tests.c b/tests/compare_tests.c index 797c7740c..a33f61d25 100644 --- a/tests/compare_tests.c +++ b/tests/compare_tests.c @@ -24,12 +24,14 @@ #include "unity/src/unity.h" #include "common.h" +// static cJSON_bool compare_from_string(const char * const a, const char * const b, const cJSON_bool case_sensitive) { cJSON *a_json = NULL; cJSON *b_json = NULL; cJSON_bool result = false; + //a [] && b [] a_json = cJSON_Parse(a); TEST_ASSERT_NOT_NULL_MESSAGE(a_json, "Failed to parse a."); b_json = cJSON_Parse(b); @@ -125,7 +127,7 @@ static void cjson_compare_should_compare_raw(void) raw1 = cJSON_Parse("\"[true, false]\""); TEST_ASSERT_NOT_NULL(raw1); - raw2 = cJSON_Parse("\"[true, false]\""); + raw2 = cJSON_Parse("\"[True, false]\""); TEST_ASSERT_NOT_NULL(raw2); raw1->type = cJSON_Raw; @@ -189,6 +191,8 @@ static void cjson_compare_should_compare_objects(void) false)) } +int interger; + int CJSON_CDECL main(void) { UNITY_BEGIN(); @@ -204,5 +208,21 @@ int CJSON_CDECL main(void) RUN_TEST(cjson_compare_should_compare_arrays); RUN_TEST(cjson_compare_should_compare_objects); + printf("------------------------------\n"); +// char *pointer = 0; +// printf("pointer is NULL? %d", pointer == NULL); + +// size_t strLength = strlen("null"); +// printf("null length is %lu\n", strLength); +// +// size_t strLength1 = strlen("false"); +// printf("false length is %lu\n", strLength1); +// +// size_t strLength2 = strlen("true"); +// printf("true length is %lu\n", strLength2); + +// int i = 0; + printf("the uninit i value is %d", interger); + return UNITY_END(); } diff --git a/tests/parse_examples.c b/tests/parse_examples.c index 3bbc37ea5..5f0457b7b 100644 --- a/tests/parse_examples.c +++ b/tests/parse_examples.c @@ -46,6 +46,7 @@ static cJSON *parse_file(const char *filename) //看下I/O static void do_test(const char *test_name) { + //从test文件读出内容,转为json字符串,与expected文件中的内容进行比对 char *expected = NULL; char *actual = NULL; cJSON *tree = NULL; @@ -61,8 +62,12 @@ static void do_test(const char *test_name) /* allocate file paths 方法里也可以定义宏 */ #define TEST_DIR_PATH "inputs/" + // "inputs/test1" test_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length); + + // 单元测试怎么完成的? TEST_ASSERT_NOT_NULL_MESSAGE(test_path, "Failed to allocate test_path buffer."); + expected_path = (char*)malloc(sizeof(TEST_DIR_PATH) + test_name_length + sizeof(".expected")); TEST_ASSERT_NOT_NULL_MESSAGE(expected_path, "Failed to allocate expected_path buffer."); @@ -254,6 +259,8 @@ static void test14_should_not_be_parsed(void) int CJSON_CDECL main(void) { + #define ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + UNITY_BEGIN(); RUN_TEST(file_test1_should_be_parsed_and_printed); RUN_TEST(file_test2_should_be_parsed_and_printed); diff --git a/tests/readme_examples.c b/tests/readme_examples.c index 80ea8aa11..9a6497ad9 100644 --- a/tests/readme_examples.c +++ b/tests/readme_examples.c @@ -42,6 +42,7 @@ static const char *json = "{\n\ \t\t}]\n\ }"; +//创建 resolutions 数组 static char* create_monitor(void) { const unsigned int resolution_numbers[3][2] = { @@ -58,46 +59,42 @@ static char* create_monitor(void) size_t index = 0; cJSON *monitor = cJSON_CreateObject(); - if (monitor == NULL) - { + if (monitor == NULL){ goto end; } name = cJSON_CreateString("Awesome 4K"); - if (name == NULL) - { + if (name == NULL){ goto end; } + + //Object(name) /* after creation was successful, immediately add it to the monitor, * thereby transfering ownership of the pointer to it */ cJSON_AddItemToObject(monitor, "name", name); resolutions = cJSON_CreateArray(); - if (resolutions == NULL) - { + if (resolutions == NULL){ goto end; } + //Object(name resolutions) cJSON_AddItemToObject(monitor, "resolutions", resolutions); - for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index) - { + for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index){ resolution = cJSON_CreateObject(); - if (resolution == NULL) - { + if (resolution == NULL){ goto end; } cJSON_AddItemToArray(resolutions, resolution); width = cJSON_CreateNumber(resolution_numbers[index][0]); - if (width == NULL) - { + if (width == NULL){ goto end; } cJSON_AddItemToObject(resolution, "width", width); height = cJSON_CreateNumber(resolution_numbers[index][1]); - if (height == NULL) - { + if (height == NULL){ goto end; } cJSON_AddItemToObject(resolution, "height", height); @@ -114,6 +111,7 @@ static char* create_monitor(void) return string; } +//Object(name resolutions) static char *create_monitor_with_helpers(void) { const unsigned int resolution_numbers[3][2] = { @@ -125,16 +123,16 @@ static char *create_monitor_with_helpers(void) cJSON *resolutions = NULL; size_t index = 0; + //Object cJSON *monitor = cJSON_CreateObject(); - if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL) - { + //Object(name) + if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL){ goto end; } resolutions = cJSON_AddArrayToObject(monitor, "resolutions"); - if (resolutions == NULL) - { + if (resolutions == NULL){ goto end; } @@ -185,8 +183,7 @@ static int supports_full_hd(const char * const monitor) } name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name"); - if (cJSON_IsString(name) && (name->valuestring != NULL)) - { + if (cJSON_IsString(name) && (name->valuestring != NULL)){ printf("Checking monitor \"%s\"\n", name->valuestring); } From fe4cf94dda3408383675c57241be577147bef0f9 Mon Sep 17 00:00:00 2001 From: xijianjun Date: Wed, 4 Nov 2020 15:06:25 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E3=80=90=E5=8F=88=E3=80=91=E6=9B=B4?= =?UTF-8?q?=E6=96=B0summary;=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cJSON.c | 53 +++++++++++++++++++++++++++++++++------- summary.md | 11 +++++++-- tests/minify_tests.c | 18 ++++++++------ tests/misc_tests.c | 57 ++++++++++++++++++++++++++++++++------------ 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/cJSON.c b/cJSON.c index a0be64329..c9d90ec54 100644 --- a/cJSON.c +++ b/cJSON.c @@ -200,6 +200,7 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h { return NULL; } + //todo memcpy 和 strcpy 区别 memcpy(copy, string, length); return copy; @@ -438,8 +439,15 @@ typedef struct } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) +/** + * + * @param p + * @param needed 必须为可能的分配准备充足的空间 + * @return + */ +static unsigned char* ensure(printbuffer * const p, size_t needed)// 200 { + //printbuffer->buffer->length = 100, needed = 200, length = 10, offset = 0 unsigned char *newbuffer = NULL; size_t newsize = 0; @@ -448,7 +456,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) return NULL; } - if ((p->length > 0) && (p->offset >= p->length)) + if ((p->length > 0) && (p->offset >= p->length))// 已到print_buffer->buffer末端 { /* make sure that offset is valid */ return NULL; @@ -463,7 +471,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) needed += p->offset + 1; if (needed <= p->length) { - //todo 理解不了 (char * + size_t) + //todo done 理解不了 (char * + size_t) A:就是数组常规操作,见书 return p->buffer + p->offset; } @@ -486,7 +494,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } else { - // needed * 2 + // needed * 2 //扩容 newsize = needed * 2; } @@ -794,7 +802,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu // size_t ret1 = (size_t) (input_end - input_buffer->content); // printf("%lu minus %lu, equals %lu\n", (size_t)input_end, (size_t)input_buffer->content, ret1); - //todo 疑问 input_end这样的字符指针强转为size_t类型的值,该值表示什么? + //todo 疑问 input_end这样的字符指针强转为size_t类型的值,该值表示什么? A:地址做运算 while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { /* is escape sequence 转义字符串 */ @@ -1201,6 +1209,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i printbuffer buffer[1]; unsigned char *printed = NULL; + //内存初始化 memset(buffer, 0, sizeof(buffer)); /* create buffer */ @@ -1370,6 +1379,8 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf { return parse_array(item, input_buffer); } + +// "{\"one\":1, \"Two\":2, \"tHree\":3}" /* object */ // '{' if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { @@ -1614,7 +1625,7 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp return true; } -/* Build an object from the text. */ +/* Build an object from the text. */ // NOTE 指向常量的指针 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) { cJSON *head = NULL; /* linked list head */ @@ -1624,6 +1635,8 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu { return false; /* to deeply nested */ } + + //object嵌套深度+1 input_buffer->depth++; if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) @@ -1631,6 +1644,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu goto fail; /* not an object */ } + //{} input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) @@ -1645,11 +1659,13 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu goto fail; } + // "{\"one\":1, \"Two\":2, \"tHree\":3}" /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ do { + /* do while每循环一次,解析一下key:value */ /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) @@ -2034,6 +2050,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) #pragma GCC diagnostic ignored "-Wcast-qual" #endif /* helper function to cast away const */ +// 去除const关键词 static void* cast_away_const(const void* string) { return (void*)string; @@ -2043,7 +2060,8 @@ static void* cast_away_const(const void* string) #endif -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, + const internal_hooks * const hooks, const cJSON_bool constant_key) { char *new_key = NULL; int new_type = cJSON_Invalid; @@ -2053,6 +2071,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st return false; } + //false if (constant_key) { new_key = (char*)cast_away_const(string); @@ -2061,6 +2080,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st else { //一个指向 只读变量 的指针 string means a pointer to const unsigned char + //todo 为甚么要调memcpy new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); if (new_key == NULL) { @@ -2213,6 +2233,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) { + //新建数组 cJSON *array = cJSON_CreateArray(); if (add_item_to_object(object, name, array, &global_hooks, false)) { @@ -2223,6 +2244,12 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c return NULL; } +/** + * 删除属性 + * @param parent + * @param item + * @return + */ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) { if ((parent == NULL) || (item == NULL)) @@ -2230,6 +2257,9 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it return NULL; } + // 是否为链表特性 + //分四种情况 第一个item 最后一个item 非第一个item 非最后一个item + if (item != parent->child) { /* not the first element */ @@ -2512,6 +2542,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) if (item != NULL) { item->type = cJSON_String | cJSON_IsReference; + //指针强转 const char * -> const void* -> void* -> char* item->valuestring = (char*)cast_away_const(string); } @@ -2821,6 +2852,7 @@ static void skip_oneline_comment(char **input) /** * 处理多行注释 */ +//"{/* this is\n a /* multi\n //line \n {comment \"\\\" */}" static void skip_multiline_comment(char **input) { *input += static_strlen("/*"); @@ -2835,6 +2867,8 @@ static void skip_multiline_comment(char **input) } } + + static void minify_string(char **input, char **output) { (*output)[0] = (*input)[0]; *input += static_strlen("\""); @@ -2844,7 +2878,7 @@ static void minify_string(char **input, char **output) { for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { (*output)[0] = (*input)[0]; - if ((*input)[0] == '\"') { + if ((*input)[0] == '\"') {//结束 (*output)[0] = '\"'; *input += static_strlen("\""); *output += static_strlen("\""); @@ -2889,6 +2923,7 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) { //多行注释 skip_multiline_comment(&json); + printf("json left %s\n", json);// } } else { // char* ++操作 json++; @@ -2900,7 +2935,7 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) break; default: - into[0] = json[0]; + into[0] = json[0];//todo KEY ---> json++; into++; } diff --git a/summary.md b/summary.md index acf3f4b6c..c158f2754 100644 --- a/summary.md +++ b/summary.md @@ -20,6 +20,9 @@ 4. char '\0' === int 0 5. 调了allocate 就要调free 6. '\0'为ASCII码表第一个表项,为空字符串NUL +7. \"\\\" +8. goto关键词 +9. 数值字面值占几个字节 int 4个? 关于二次指针的理解 @@ -128,8 +131,7 @@ cJSON_Duplicate cJson_Utils - decode_patch_operation -CJSON ------------------------------------------ + 方法 - cJSON_GetObjectItemCaseSensitive - get_object_item @@ -142,7 +144,12 @@ CJSON - cJSON_Minify - skip_oneline_comment - skip_multiline_comment + - minify_string +其中,minify_tests值得重新看一次 + +- cJSON_ReplaceItemViaPointer +- cJSON_DetachItemViaPointer #### 对象 diff --git a/tests/minify_tests.c b/tests/minify_tests.c index 1bba2a989..40df26f1c 100644 --- a/tests/minify_tests.c +++ b/tests/minify_tests.c @@ -79,7 +79,7 @@ __attribute__((unused)) static void cjson_minify_should_remove_multiline_comment TEST_ASSERT_NOT_NULL(minified); strcpy(minified, to_minify); - cJSON_Minify(minified); + cJSON_Minify(minified);// minified = {} TEST_ASSERT_EQUAL_STRING("{}", minified); free(minified); @@ -100,7 +100,7 @@ __attribute__((unused)) static void cjson_minify_should_not_modify_strings(void) } /** minify效果 去除:\n comment 缩进 */ -static void cjson_minify_should_minify_json(void) { +__attribute__((unused)) static void cjson_minify_should_minify_json(void) { const char to_minify[] = "{\n" " \"glossary\": { // comment\n" @@ -156,10 +156,14 @@ static void cjson_minify_should_minify_json(void) { free(buffer); } -__attribute__((unused)) static void cjson_minify_should_not_loop_infinitely(void) { +static void cjson_minify_should_not_loop_infinitely(void) { + + // todo 为什么这组数据测试 loop infinitely char string[] = { '8', ' ', '/', ' ', '5', '\n', '\0' }; /* this should not be an infinite loop */ cJSON_Minify(string); + + printf("string is %s\n", string); } int CJSON_CDECL main(void) @@ -167,12 +171,12 @@ int CJSON_CDECL main(void) UNITY_BEGIN(); // RUN_TEST(cjson_minify_should_not_overflow_buffer); - RUN_TEST(cjson_minify_should_minify_json); +// RUN_TEST(cjson_minify_should_minify_json); // RUN_TEST(cjson_minify_should_remove_single_line_comments); - // RUN_TEST(cjson_minify_should_remove_multiline_comments); +// RUN_TEST(cjson_minify_should_remove_multiline_comments); // RUN_TEST(cjson_minify_should_remove_spaces); - // RUN_TEST(cjson_minify_should_not_modify_strings); - // RUN_TEST(cjson_minify_should_not_loop_infinitely); +// RUN_TEST(cjson_minify_should_not_modify_strings); + RUN_TEST(cjson_minify_should_not_loop_infinitely); return UNITY_END(); } diff --git a/tests/misc_tests.c b/tests/misc_tests.c index d544a2917..7b72257dd 100644 --- a/tests/misc_tests.c +++ b/tests/misc_tests.c @@ -31,6 +31,7 @@ static void cjson_array_foreach_should_loop_over_arrays(void) { + // 一个数组里的子项包含elements数组 cJSON array[1]; // 双向链表 cJSON elements[10]; @@ -81,6 +82,9 @@ static void cjson_get_object_item_should_get_object_items(void) found = cJSON_GetObjectItem(item, "one"); TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); + //todo 为什么parse为double类型 done + int valu1e= found->valueint; + printf("intvalue is %d\n", valu1e); TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1); found = cJSON_GetObjectItem(item, "tWo"); @@ -152,13 +156,19 @@ static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(voi static void typecheck_functions_should_check_type(void) { + //todo 假设都为int整型时,做位运算。C中数值字面量占用几个字节 cJSON invalid[1]; cJSON item[1]; invalid->type = cJSON_Invalid; invalid->type |= cJSON_StringIsConst; + + printf("invalid->type: %d\n", invalid->type); item->type = cJSON_False; item->type |= cJSON_StringIsConst; + int _type = (invalid->type & 0xff); + printf("invalid->type & 0xff: %d\n", _type); + TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL)); TEST_ASSERT_FALSE(cJSON_IsInvalid(item)); TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid)); @@ -224,7 +234,7 @@ static void cjson_set_number_value_should_set_numbers(void) { cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}}; - cJSON_SetNumberValue(number, 1.5); + cJSON_SetNumberValue(number, 1.5);// 强转类型了 TEST_ASSERT_EQUAL(1, number->valueint); TEST_ASSERT_EQUAL_DOUBLE(1.5, number->valuedouble); @@ -248,6 +258,9 @@ static void cjson_detach_item_via_pointer_should_detach_items(void) memset(list, '\0', sizeof(list)); + // parent | + // \|/ + // [3] <- [0] <-> [1] <-> [2] <-> [3] /* link the list */ list[0].next = &(list[1]); list[1].next = &(list[2]); @@ -526,6 +539,7 @@ static void cjson_create_object_reference_should_create_an_object_reference(void TEST_ASSERT_TRUE(number_reference->child == number); TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type); + //todo 为什么没有 cJSON_Delete(number) cJSON_Delete(number_object); cJSON_Delete(number_reference); } @@ -584,13 +598,15 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al static void cjson_delete_item_from_array_should_not_broken_list_structure(void) { - const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}"; + //object {rd : array} + const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}"; //object 其中rd属性为数组 const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}"; const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}"; char *str1 = NULL; char *str2 = NULL; char *str3 = NULL; + //empty object cJSON *root = cJSON_Parse("{}"); cJSON *array = cJSON_AddArrayToObject(root, "rd"); @@ -655,31 +671,42 @@ int CJSON_CDECL main(void) { UNITY_BEGIN(); - RUN_TEST(cjson_array_foreach_should_loop_over_arrays); - RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer); - RUN_TEST(cjson_get_object_item_should_get_object_items); - RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items); - RUN_TEST(cjson_get_object_item_should_not_crash_with_array); + + RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array); RUN_TEST(typecheck_functions_should_check_type); RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons); RUN_TEST(cjson_set_number_value_should_set_numbers); RUN_TEST(cjson_detach_item_via_pointer_should_detach_items); RUN_TEST(cjson_replace_item_via_pointer_should_replace_items); - RUN_TEST(cjson_replace_item_in_object_should_preserve_name); - RUN_TEST(cjson_functions_should_not_crash_with_null_pointers); - RUN_TEST(ensure_should_fail_on_failed_realloc); - RUN_TEST(skip_utf8_bom_should_skip_bom); - RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning); RUN_TEST(cjson_get_string_value_should_get_a_string); RUN_TEST(cjson_get_number_value_should_get_a_number); RUN_TEST(cjson_create_string_reference_should_create_a_string_reference); - RUN_TEST(cjson_create_object_reference_should_create_an_object_reference); + RUN_TEST(ensure_should_fail_on_failed_realloc); + + //todo 基本覆盖cJSON所有方法的NULL检测 + RUN_TEST(cjson_functions_should_not_crash_with_null_pointers); + + RUN_TEST(skip_utf8_bom_should_skip_bom); + RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning); + + //array test + RUN_TEST(cjson_array_foreach_should_loop_over_arrays); + RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer); RUN_TEST(cjson_create_array_reference_should_create_an_array_reference); - RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself); - RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased); + RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure); + + //object test + RUN_TEST(cjson_get_object_item_should_get_object_items); + RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items); + RUN_TEST(cjson_get_object_item_should_not_crash_with_array); + + RUN_TEST(cjson_create_object_reference_should_create_an_object_reference); RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory); + RUN_TEST(cjson_replace_item_in_object_should_preserve_name); + RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself); + RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased); return UNITY_END(); } From 51e773526be3638db1c9c3984a4d13ba7e848076 Mon Sep 17 00:00:00 2001 From: xijianjun Date: Thu, 5 Nov 2020 11:28:35 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E3=80=90=E5=8F=88=E3=80=91=E6=9B=B4?= =?UTF-8?q?=E6=96=B0summary;=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cJSON.c | 21 ++++++++++++++++----- summary.md | 6 ++++++ tests/misc_tests.c | 11 +++++------ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/cJSON.c b/cJSON.c index c9d90ec54..4ddccabb6 100644 --- a/cJSON.c +++ b/cJSON.c @@ -249,14 +249,17 @@ static cJSON *cJSON_New_Item(const internal_hooks * const hooks) return node; } -/* Delete a cJSON structure. */ +/* Delete a cJSON structure. 递归 */ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { cJSON *next = NULL; while (item != NULL) { next = item->next; - // item->child != null 表示 An array or object item will have a child pointer + // item->child != null 表示 An array or object item will have a child pointer + // todo !(item->type & cJSON_IsReference) 怎么理解 为什么这样处理 + // A: 非引用类型 可以熟悉一下cJSON_IsReference,cJSON_IsReference的结构都比较简单, + // 不像Object(包含属性) Array(包含子项) if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); @@ -271,6 +274,8 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { global_hooks.deallocate(item->string); } + + //引用类型直接 free global_hooks.deallocate(item); item = next; } @@ -1994,7 +1999,13 @@ static cJSON *create_reference(const cJSON *item, const internal_hooks * const h reference->next = reference->prev = NULL; return reference; } - +/** + * |---| + * 结构 array -> child -> prev -> item3 -item1 <-> item2 <--> item3 + * @param array + * @param item + * @return + */ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; @@ -2017,7 +2028,7 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) } else { - /* 数组非空 */ + /* child->prev 始终指向child链表中最后一个item */ if (child->prev) { suffix_object(child->prev, item); @@ -2499,7 +2510,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) item->type = cJSON_Number; item->valuedouble = num; - /* use saturation in case of overflow */ + /* use saturation in case of overflow 考虑越界问题*/ if (num >= INT_MAX) { item->valueint = INT_MAX; diff --git a/summary.md b/summary.md index c158f2754..95420836b 100644 --- a/summary.md +++ b/summary.md @@ -23,6 +23,8 @@ 7. \"\\\" 8. goto关键词 9. 数值字面值占几个字节 int 4个? +10.NOTE 学习一下单元测试,测试包含了什么内容 + 关于二次指针的理解 @@ -150,6 +152,10 @@ cJson_Utils - cJSON_ReplaceItemViaPointer - cJSON_DetachItemViaPointer + +misc_tests +- cJSON_AddArrayToObject +- cJSON_Delete #### 对象 diff --git a/tests/misc_tests.c b/tests/misc_tests.c index 7b72257dd..10b4f4f12 100644 --- a/tests/misc_tests.c +++ b/tests/misc_tests.c @@ -535,11 +535,12 @@ static void cjson_create_object_reference_should_create_an_object_reference(void TEST_ASSERT_TRUE(cJSON_IsObject(number_object)); cJSON_AddItemToObjectCS(number_object, key, number); + // ObjectReference的 child 赋值 number_reference = cJSON_CreateObjectReference(number); TEST_ASSERT_TRUE(number_reference->child == number); TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type); - //todo 为什么没有 cJSON_Delete(number) + //todo 为什么没有 cJSON_Delete(number) A: 有的,cJSON_Delete方法中递归 cJSON_Delete(number_object); cJSON_Delete(number_reference); } @@ -670,9 +671,7 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void) int CJSON_CDECL main(void) { UNITY_BEGIN(); - - - + // RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array); RUN_TEST(typecheck_functions_should_check_type); RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons); @@ -694,15 +693,15 @@ int CJSON_CDECL main(void) RUN_TEST(cjson_array_foreach_should_loop_over_arrays); RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer); RUN_TEST(cjson_create_array_reference_should_create_an_array_reference); - RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure); //object test RUN_TEST(cjson_get_object_item_should_get_object_items); RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items); RUN_TEST(cjson_get_object_item_should_not_crash_with_array); - RUN_TEST(cjson_create_object_reference_should_create_an_object_reference); + + //给object设置valuestring为什么会发生memory leak RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory); RUN_TEST(cjson_replace_item_in_object_should_preserve_name); RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);