├── .editorconfig ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── README_cn.md ├── json_parser.c ├── json_parser.h ├── list.h ├── test.c ├── test_speed.c └── xmake.lua /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # all files 5 | [*] 6 | indent_style = tab 7 | indent_size = 4 8 | [list.h] 9 | indent_style = tab 10 | indent_size = 8 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(json-parser VERSION 1.5.2) 3 | 4 | set(CMAKE_C_STANDARD 99) 5 | set(CMAKE_C_STANDARD_REQUIRED ON) 6 | set(CMAKE_C_EXTENSIONS OFF) 7 | 8 | if(NOT CMAKE_BUILD_TYPE) 9 | set(CMAKE_BUILD_TYPE "Release") 10 | endif() 11 | 12 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g") 13 | set(CMAKE_C_FLAGS_RELEASE "-O2") 14 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") 15 | set(CMAKE_C_FLAGS_MINSIZEREL "-Os") 16 | 17 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 18 | 19 | message(STATUS "Using C compiler: ${CMAKE_C_COMPILER_ID}") 20 | message(STATUS "Compiler path: ${CMAKE_C_COMPILER}") 21 | 22 | add_library(json-parser STATIC 23 | json_parser.c 24 | ) 25 | 26 | add_executable(parse_json 27 | test.c 28 | ) 29 | 30 | target_link_libraries(parse_json json-parser) 31 | 32 | add_executable(test_speed 33 | test_speed.c 34 | ) 35 | 36 | target_link_libraries(test_speed json-parser) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=c99 -Wall 2 | ifeq ($(DEBUG), y) 3 | CFLAGS += -O0 -g 4 | else 5 | CFLAGS += -O2 6 | endif 7 | 8 | LD = cc 9 | 10 | all: test_speed parse_json 11 | 12 | json_parser.o: json_parser.c json_parser.h list.h 13 | 14 | test_speed: json_parser.o test_speed.o 15 | $(LD) -o test_speed $^ 16 | 17 | parse_json: json_parser.o test.o 18 | $(LD) -o parse_json $^ 19 | 20 | clean: 21 | rm -f parse_json test_speed *.o 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [中文版说明](/README_cn.md) 2 | # Json Parser in Standard C (C99) 3 | This json parser was created for the project of [C++ Workflow](https://github.com/sogou/workflow). 4 | # Build tests 5 | ~~~bash 6 | $ make 7 | ~~~ 8 | # Run tests 9 | ### Parse and print json document: 10 | ~~~bash 11 | $ ./parse_json < xxx.json 12 | ~~~ 13 | ### Test parsing speed: 14 | ~~~bash 15 | $ time ./test_speed < xxx.json 16 | ~~~ 17 | # Main Interfaces 18 | 19 | ### JSON value related 20 | ~~~c 21 | /* Parse JSON text and create a JSON value. Returns NULL on parsing 22 | failures (Invalid JSON, nesting too deep, memory allocation failure). 23 | @text: JSON text string */ 24 | json_value_t *json_value_parse(const char *text); 25 | 26 | /* Destroy the JSON value 27 | @val: JSON value. Typically created by the parsing function. */ 28 | void json_value_destroy(json_value_t *val); 29 | 30 | /* Get JSON value's type 31 | Return values: 32 | JSON_VALUE_STRING: string 33 | JSON_VALUE_NUMBER: number 34 | JSON_VALUE_OBJECT: JSON object 35 | JSON_VALUE_ARRAY: JSON array 36 | JSON_VALUE_TRUE: true 37 | JSON_VALUE_FALSE: false 38 | JSON_VALUE_NULL: null 39 | @val: JSON value */ 40 | int json_value_type(const json_value_t *val); 41 | 42 | /* Obtain the JSON string. The function returns the string or 43 | returns NULL if the type of @val is not JSON_VALUE_STRING. 44 | @val: JSON value */ 45 | const char *json_value_string(const json_value_t *val); 46 | 47 | /* Obtain the JSON number. The function returns the number or 48 | returns NAN if the type of @val is not JSON_VALUE_NUMBER. 49 | @val: JSON value */ 50 | double json_value_number(const json_value_t *val); 51 | 52 | /* Obtain JSON object. The function returns the JSON object or 53 | returns NULL if the type of @val is not JSON_VALUE_OBJECT. 54 | @val: JSON value 55 | Note: The returned pointer to JSON object is not const. 56 | You may extend the object using buiding functions. */ 57 | json_object_t *json_value_object(const json_value_t *val); 58 | 59 | /* Obtain JSON arary. The function returns the JSON array or 60 | returns NULL if the type of @val is not JSON_VALUE_ARRAY. 61 | @val: JSON value 62 | Note: The returned pointer to the JSON array is not const and 63 | can been extended by using building functions. */ 64 | json_array_t *json_value_array(const json_value_t *val); 65 | 66 | ~~~ 67 | ### JSON object related 68 | ~~~c 69 | /* Get the size of the JSON object. 70 | @obj: JSON object */ 71 | size_t json_object_size(const json_object_t *obj); 72 | 73 | /* Find the JSON value under the key @name. Returns NULL if @name 74 | can not be found. The time complexity of this function is 75 | O(n), where n is the size of the JSON object. 76 | @name: The key to find 77 | @obj: JSON object 78 | Note: The returned pointer to JSON value is const. */ 79 | const json_value_t *json_object_find(const char *name, const json_object_t *obj); 80 | 81 | /* Traversing the JSON object forward or backward 82 | @name: Temporary (const char *) pointer for each key 83 | @val: Temporary (const json_value_t *) pointer for each JSON value 84 | @obj: JSON object 85 | NOTE: These are not functions, but macros of looping. */ 86 | json_object_for_each(name, val, obj) 87 | json_object_for_each_prev(name, val, obj) 88 | ~~~ 89 | 90 | ### JSON array related 91 | ~~~c 92 | /* Get the size of the JSON array. 93 | @arr:JSON array */ 94 | size_t json_array_size(const json_array_t *arr); 95 | 96 | /* Traversing the JSON array forward or backward 97 | @val: Temporary (const json_value_t *) pointer for each JSON value 98 | @arr: JSON array 99 | NOTE: These are not functions, but macros of looping. */ 100 | json_array_for_each(val, arr) 101 | json_array_for_each_prev(val, arr) 102 | ~~~ 103 | 104 | ### Building JSON 105 | All the following functions return NULL on failure of allocating memory. 106 | ~~~c 107 | /* Create a JSON value. 108 | @type: JSON value's type. 109 | Note: Variable argument. Example: 110 | v_str = json_value_create(JSON_VALUE_STRING, "hello"); 111 | v_num = json_value_create(JSON_VALUE_NUMBER, 3.14); 112 | v_int = json_value_create(JSON_VALUE_NUMBER, (double)100); 113 | v_obj = json_value_create(JSON_VALUE_OBJECT); 114 | v_arr = json_value_create(JSON_VALUE_ARRAY); 115 | v_true = json_value_create(JSON_VALUE_TRUE); 116 | The returned value is not const and has to be destroyed. */ 117 | json_value_t *json_value_create(int type, ...); 118 | 119 | /* Extend the JSON object. Returns the value that's added. 120 | @obj: JSON object 121 | @name: New member's name 122 | @type: New member's value type or zero which means another JSON value 123 | Note: Variable argument. Example: 124 | v_num = json_object_append(obj, "pi", JSON_VALUE_NUMBER, 3.14); 125 | v_obj = json_object_append(obj, "user", JSON_VALUE_OBJECT); 126 | v_from_doc = json_object_append(obj, "doc", 0, json_value_parse("{\"data\" : [1, 2, 3]}")); */ 127 | const json_value_t *json_object_append(json_object_t *obj, const char *name, 128 | int type, ...); 129 | 130 | /* Remove a JSON value from a JSON object and return the value. 131 | @val: JSON value to be removed. 132 | @obj: JSON object 133 | Note: The returned value is not const and need to be destroyed, 134 | or appended to another JSON object or JSON array. */ 135 | json_value_t *json_object_remove(const json_value_t *val, 136 | json_object_t *obj); 137 | 138 | /* Extend the JSON array. Return the value that's added. 139 | @arr: JSON array 140 | @type: New member's value type or zero which means another JSON value 141 | Note: Variable argument. Example: 142 | v_str = json_array_append(arr, JSON_VALUE_STRING, "hello"); 143 | equal to: 144 | v_str = json_array_append(arr, 0, json_value_create(JSON_VALUE_STRING, "hello")); */ 145 | const json_value_t *json_array_append(json_array_t *arr, int type, ...); 146 | 147 | /* Remove a JSON value from a JSON array and return the value. 148 | @val: JSON value to be removed 149 | @arr: JSON array 150 | Note: The returned value is not const and need to be destroyed, 151 | or appended to another JSON object or JSON array. */ 152 | json_value_t *json_array_remove(const json_value_t *val, 153 | json_object_t *arr); 154 | 155 | ~~~ 156 | # A beautiful C++ wrapper 157 | https://github.com/wfrest/Json 158 | -------------------------------------------------------------------------------- /README_cn.md: -------------------------------------------------------------------------------- 1 | [English version](/README.md) 2 | # 基于标准C(C99)的JSON解析器 3 | 项目最初是为[C++ Workflow](https://github.com/sogou/workflow)项目开发的JSON解析。 4 | # 编译项目测试代码 5 | ~~~sh 6 | $ make 7 | ~~~ 8 | # 运行测试代码 9 | ### JSON解析与JSON结构复制,序列化测试 10 | ~~~sh 11 | $ ./parse_json < xxx.json 12 | ~~~ 13 | ### 解析速度测试 14 | ~~~sh 15 | $ time ./test_speed <重复次数> < xxx.json 16 | ~~~ 17 | # 主要接口 18 | ### JSON value相关接口 19 | ~~~c 20 | /* 解析JSON文本产生JSON value。返回JSON value对象。返回NULL代表解析失败(格式不标准,嵌套过深,分配内存失败) 21 | @text:文本字符串 */ 22 | json_value_t *json_value_parse(const char *text); 23 | 24 | /* 销毁JSON value 25 | @val:由parse, create或copy生成的JSON value对象。*/ 26 | void json_value_destroy(json_value_t *val); 27 | 28 | /* 返回JSON value类型 29 | 可能的返回值: 30 | JSON_VALUE_STRING:字符串 31 | JSON_VALUE_NUMBER:数字 32 | JSON_VALUE_OBJECT:json对象 33 | JSON_VALUE_ARRAY:json数组 34 | JSON_VALUE_TRUE:true 35 | JSON_VALUE_FALSE:false 36 | JSON_VALUE_NULL:null 37 | @val:JSON value对象 */ 38 | int json_value_type(const json_value_t *val); 39 | 40 | /* 获得JSON string。如果返回NULL,代表value不是STRING型 41 | @val:JSON value对象 */ 42 | const char *json_value_string(const json_value_t *val); 43 | 44 | /* 获得JSON number。如果value不是NUMBER型,返回NAN(不存在的浮点数) 45 | @val:JSON value对象 */ 46 | double json_value_number(const json_value_t *val); 47 | 48 | /* 获得JSON object。如果value不是OBJECT类型,返回NULL 49 | @val:JSON value对象 50 | 注意返回的json_object_t指针并非const。可以通过build相关函数扩展object。*/ 51 | json_object_t *json_value_object(const json_value_t *val); 52 | 53 | /* 获得JSON array。如果value不是ARRAY类型,返回NULL 54 | @val:JSON value对象 55 | 同样,返回的json_array_t指针不带const。 */ 56 | json_array_t *json_value_array(const json_value_t *val); 57 | 58 | ~~~ 59 | ### JSON object相关接口 60 | ~~~c 61 | /* 返回object的大小。即object包含的name,value对数量 62 | @obj:JSON object对象 */ 63 | size_t json_object_size(const json_object_t *obj); 64 | 65 | /* 查找并返回name下的value。返回NULL代表找不到这个name。函数时间复杂度为O(log(size)) 66 | @name:要查找的名字 67 | @obj:JSON object对象 68 | 注意返回的json_value_t指针带const。*/ 69 | const json_value_t *json_object_find(const char *name, const json_object_t *obj); 70 | 71 | /* 向前或向后遍历JSON object 72 | @name:临时的const char *类型name字符串 73 | @val:临时的const json_value_t *类型的JSON value对象 74 | @obj:JSON object对象 75 | 这是两个宏,会被展开成for循环。 */ 76 | json_object_for_each(name, val, obj) 77 | json_object_for_each_prev(name, val, obj) 78 | ~~~ 79 | ### JSON array相关接口 80 | ~~~c 81 | /* 返回JSON array的大小,即元素个数 82 | @arr:JSON array对象 */ 83 | size_t json_array_size(const json_array_t *arr); 84 | 85 | /* 向前或向后遍历JSON array 86 | @val:临时的const json_value_t *类型的JSON value对象 87 | @arr:JSON array对象 88 | 同样,这是展开成for循环的宏。 */ 89 | json_array_for_each(val, arr) 90 | json_array_for_each_prev(val, arr) 91 | ~~~ 92 | 93 | ### JSON building相关接口 94 | 以下的函数用于JSON编辑,这些函数都可能返回NULL表示内存分配失败。 95 | ~~~c 96 | /* 新建一个JSON value 97 | @type: JSON value的类型 98 | 注意这是一个可变参数的函数,示例: 99 | v_str = json_value_create(JSON_VALUE_STRING, "hello"); 100 | v_num = json_value_create(JSON_VALUE_NUMBER, 3.14); 101 | v_int = json_value_create(JSON_VALUE_NUMBER, (double)100); 102 | v_obj = json_value_create(JSON_VALUE_OBJECT); 103 | v_arr = json_value_create(JSON_VALUE_ARRAY); 104 | v_true = json_value_create(JSON_VALUE_TRUE); 105 | 函数返回一个JSON value对象。非const,因此需要被销毁或转移。 */ 106 | json_value_t *json_value_create(int type, ...); 107 | 108 | /* 复制JSON value 109 | @val: 被复制的JSON value 110 | 函数返回一个JSON value对象。非const,因此需要被销毁或转移。 */ 111 | json_value_t *json_value_copy(const json_value_t *val); 112 | 113 | /* 扩展一个JSON object,返回被扩展的JSON value 114 | @obj: JSON object对象 115 | @name: 扩展的JSON member的name 116 | @type: 扩展的JSON member类型,或者传0代表转移进一个已有的JSON value 117 | 注意这是一个可变参数的函数,示例: 118 | v_num = json_object_append(obj, "pi", JSON_VALUE_NUMBER, 3.14); 119 | v_obj = json_object_append(obj, "user", JSON_VALUE_OBJECT); 120 | v_from_doc = json_object_append(obj, "doc", 0, json_value_parse("{\"data\" : [1, 2, 3]}")); */ 121 | const json_value_t *json_object_append(json_object_t *obj, const char *name, 122 | int type, ...); 123 | 124 | /* 从JSON object里移除一个value并返回 125 | @val: 要移除的JSON value 126 | @obj: JSON object对象 127 | 注意,函数不会自动销毁value,而是作为返回值返回让用户自行销毁或转移。 */ 128 | json_value_t *json_object_remove(const json_value_t *val, 129 | json_object_t *obj); 130 | 131 | /* 扩展JSON array,返回被扩展的JSON value 132 | @arr: JSON array对象 133 | @type: 扩展的JSON member类型,或者传0代表转移入一个已有的JSON value 134 | 注意这是一个可变参数的函数,示例: 135 | v_str = json_array_append(arr, JSON_VALUE_STRING, "hello"); 136 | 等价于: 137 | v_str = json_array_append(arr, 0, json_value_create(JSON_VALUE_STRING, "hello")); */ 138 | const json_value_t *json_array_append(json_array_t *arr, int type, ...); 139 | 140 | /* 从JSON array里移除一个JSON value并返回 141 | @val: 要移除的JSON value 142 | @arr: JSON array对象 143 | 注意,函数不会自动销毁value,而是作为返回值返回让用户自行销毁或转移。 */ 144 | json_value_t *json_array_remove(const json_value_t *val, 145 | json_object_t *arr); 146 | ~~~ 147 | 148 | # 一个优雅的第三方C++封装 149 | https://github.com/wfrest/Json 150 | -------------------------------------------------------------------------------- /json_parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "list.h" 7 | #include "json_parser.h" 8 | 9 | #define JSON_DEPTH_LIMIT 1024 10 | 11 | struct __json_object 12 | { 13 | struct list_head head; 14 | size_t size; 15 | }; 16 | 17 | struct __json_array 18 | { 19 | struct list_head head; 20 | size_t size; 21 | }; 22 | 23 | struct __json_value 24 | { 25 | union 26 | { 27 | char *string; 28 | double number; 29 | json_object_t object; 30 | json_array_t array; 31 | } value; 32 | int type; 33 | }; 34 | 35 | struct __json_member 36 | { 37 | struct list_head list; 38 | json_value_t value; 39 | char name[1]; 40 | }; 41 | 42 | struct __json_element 43 | { 44 | struct list_head list; 45 | json_value_t value; 46 | }; 47 | 48 | typedef struct __json_member json_member_t; 49 | typedef struct __json_element json_element_t; 50 | 51 | static const int __whitespace_map[256] = { 52 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 53 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54 | 1, 55 | }; 56 | 57 | static int __json_isspace(char c) 58 | { 59 | return __whitespace_map[(unsigned char)c]; 60 | } 61 | 62 | static int __json_isdigit(char c) 63 | { 64 | return c >= '0' && c <= '9'; 65 | } 66 | 67 | #define isspace(c) __json_isspace(c) 68 | #define isdigit(c) __json_isdigit(c) 69 | 70 | static const int __character_map[256] = { 71 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73 | 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 74 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 75 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 77 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 78 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 79 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 81 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 82 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 83 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 84 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 85 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 86 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 87 | }; 88 | 89 | static int __json_string_length(const char *cursor, size_t *len) 90 | { 91 | size_t n = 0; 92 | 93 | while (1) 94 | { 95 | while (__character_map[(unsigned char)*cursor]) 96 | { 97 | cursor++; 98 | n++; 99 | } 100 | 101 | if (*cursor == '\\') 102 | { 103 | cursor++; 104 | if (*cursor == '\0') 105 | return -2; 106 | 107 | cursor++; 108 | n++; 109 | } 110 | else if (*cursor == '\"') 111 | break; 112 | else 113 | return -2; 114 | } 115 | 116 | *len = n; 117 | return 0; 118 | } 119 | 120 | static int __parse_json_hex4(const char *cursor, const char **end, 121 | unsigned int *code) 122 | { 123 | int hex; 124 | int i; 125 | 126 | *code = 0; 127 | for (i = 0; i < 4; i++) 128 | { 129 | hex = *cursor; 130 | if (hex >= '0' && hex <= '9') 131 | hex = hex - '0'; 132 | else if (hex >= 'A' && hex <= 'F') 133 | hex = hex - 'A' + 10; 134 | else if (hex >= 'a' && hex <= 'f') 135 | hex = hex - 'a' + 10; 136 | else 137 | return -2; 138 | 139 | *code = (*code << 4) + hex; 140 | cursor++; 141 | } 142 | 143 | *end = cursor; 144 | return 0; 145 | } 146 | 147 | static int __parse_json_unicode(const char *cursor, const char **end, 148 | char *utf8) 149 | { 150 | unsigned int code; 151 | unsigned int next; 152 | int ret; 153 | 154 | ret = __parse_json_hex4(cursor, end, &code); 155 | if (ret < 0) 156 | return ret; 157 | 158 | if (code >= 0xdc00 && code <= 0xdfff) 159 | return -2; 160 | 161 | if (code >= 0xd800 && code <= 0xdbff) 162 | { 163 | cursor = *end; 164 | if (*cursor != '\\') 165 | return -2; 166 | 167 | cursor++; 168 | if (*cursor != 'u') 169 | return -2; 170 | 171 | cursor++; 172 | ret = __parse_json_hex4(cursor, end, &next); 173 | if (ret < 0) 174 | return ret; 175 | 176 | if (next < 0xdc00 || next > 0xdfff) 177 | return -2; 178 | 179 | code = (((code & 0x3ff) << 10) | (next & 0x3ff)) + 0x10000; 180 | } 181 | 182 | if (code <= 0x7f) 183 | { 184 | utf8[0] = code; 185 | return 1; 186 | } 187 | else if (code <= 0x7ff) 188 | { 189 | utf8[0] = 0xc0 | (code >> 6); 190 | utf8[1] = 0x80 | (code & 0x3f); 191 | return 2; 192 | } 193 | else if (code <= 0xffff) 194 | { 195 | utf8[0] = 0xe0 | (code >> 12); 196 | utf8[1] = 0x80 | ((code >> 6) & 0x3f); 197 | utf8[2] = 0x80 | (code & 0x3f); 198 | return 3; 199 | } 200 | else 201 | { 202 | utf8[0] = 0xf0 | (code >> 18); 203 | utf8[1] = 0x80 | ((code >> 12) & 0x3f); 204 | utf8[2] = 0x80 | ((code >> 6) & 0x3f); 205 | utf8[3] = 0x80 | (code & 0x3f); 206 | return 4; 207 | } 208 | } 209 | 210 | static int __parse_json_string(const char *cursor, const char **end, 211 | char *str) 212 | { 213 | int ret; 214 | 215 | while (1) 216 | { 217 | while (*cursor != '\\' && *cursor != '\"') 218 | { 219 | *str = *cursor; 220 | cursor++; 221 | str++; 222 | } 223 | 224 | if (*cursor == '\"') 225 | break; 226 | 227 | cursor++; 228 | switch (*cursor) 229 | { 230 | case '\"': 231 | *str = '\"'; 232 | break; 233 | case '\\': 234 | *str = '\\'; 235 | break; 236 | case '/': 237 | *str = '/'; 238 | break; 239 | case 'b': 240 | *str = '\b'; 241 | break; 242 | case 'f': 243 | *str = '\f'; 244 | break; 245 | case 'n': 246 | *str = '\n'; 247 | break; 248 | case 'r': 249 | *str = '\r'; 250 | break; 251 | case 't': 252 | *str = '\t'; 253 | break; 254 | case 'u': 255 | cursor++; 256 | ret = __parse_json_unicode(cursor, &cursor, str); 257 | if (ret < 0) 258 | return ret; 259 | 260 | str += ret; 261 | continue; 262 | 263 | default: 264 | return -2; 265 | } 266 | 267 | cursor++; 268 | str++; 269 | } 270 | 271 | *str = '\0'; 272 | *end = cursor + 1; 273 | return 0; 274 | } 275 | 276 | static const double __power_of_10[309] = { 277 | 1e0, 1e1, 1e2, 1e3, 1e4, 278 | 1e5, 1e6, 1e7, 1e8, 1e9, 279 | 1e10, 1e11, 1e12, 1e13, 1e14, 280 | 1e15, 1e16, 1e17, 1e18, 1e19, 281 | 1e20, 1e21, 1e22, 1e23, 1e24, 282 | 1e25, 1e26, 1e27, 1e28, 1e29, 283 | 1e30, 1e31, 1e32, 1e33, 1e34, 284 | 1e35, 1e36, 1e37, 1e38, 1e39, 285 | 1e40, 1e41, 1e42, 1e43, 1e44, 286 | 1e45, 1e46, 1e47, 1e48, 1e49, 287 | 1e50, 1e51, 1e52, 1e53, 1e54, 288 | 1e55, 1e56, 1e57, 1e58, 1e59, 289 | 1e60, 1e61, 1e62, 1e63, 1e64, 290 | 1e65, 1e66, 1e67, 1e68, 1e69, 291 | 1e70, 1e71, 1e72, 1e73, 1e74, 292 | 1e75, 1e76, 1e77, 1e78, 1e79, 293 | 1e80, 1e81, 1e82, 1e83, 1e84, 294 | 1e85, 1e86, 1e87, 1e88, 1e89, 295 | 1e90, 1e91, 1e92, 1e93, 1e94, 296 | 1e95, 1e96, 1e97, 1e98, 1e99, 297 | 1e100, 1e101, 1e102, 1e103, 1e104, 298 | 1e105, 1e106, 1e107, 1e108, 1e109, 299 | 1e110, 1e111, 1e112, 1e113, 1e114, 300 | 1e115, 1e116, 1e117, 1e118, 1e119, 301 | 1e120, 1e121, 1e122, 1e123, 1e124, 302 | 1e125, 1e126, 1e127, 1e128, 1e129, 303 | 1e130, 1e131, 1e132, 1e133, 1e134, 304 | 1e135, 1e136, 1e137, 1e138, 1e139, 305 | 1e140, 1e141, 1e142, 1e143, 1e144, 306 | 1e145, 1e146, 1e147, 1e148, 1e149, 307 | 1e150, 1e151, 1e152, 1e153, 1e154, 308 | 1e155, 1e156, 1e157, 1e158, 1e159, 309 | 1e160, 1e161, 1e162, 1e163, 1e164, 310 | 1e165, 1e166, 1e167, 1e168, 1e169, 311 | 1e170, 1e171, 1e172, 1e173, 1e174, 312 | 1e175, 1e176, 1e177, 1e178, 1e179, 313 | 1e180, 1e181, 1e182, 1e183, 1e184, 314 | 1e185, 1e186, 1e187, 1e188, 1e189, 315 | 1e190, 1e191, 1e192, 1e193, 1e194, 316 | 1e195, 1e196, 1e197, 1e198, 1e199, 317 | 1e200, 1e201, 1e202, 1e203, 1e204, 318 | 1e205, 1e206, 1e207, 1e208, 1e209, 319 | 1e210, 1e211, 1e212, 1e213, 1e214, 320 | 1e215, 1e216, 1e217, 1e218, 1e219, 321 | 1e220, 1e221, 1e222, 1e223, 1e224, 322 | 1e225, 1e226, 1e227, 1e228, 1e229, 323 | 1e230, 1e231, 1e232, 1e233, 1e234, 324 | 1e235, 1e236, 1e237, 1e238, 1e239, 325 | 1e240, 1e241, 1e242, 1e243, 1e244, 326 | 1e245, 1e246, 1e247, 1e248, 1e249, 327 | 1e250, 1e251, 1e252, 1e253, 1e254, 328 | 1e255, 1e256, 1e257, 1e258, 1e259, 329 | 1e260, 1e261, 1e262, 1e263, 1e264, 330 | 1e265, 1e266, 1e267, 1e268, 1e269, 331 | 1e270, 1e271, 1e272, 1e273, 1e274, 332 | 1e275, 1e276, 1e277, 1e278, 1e279, 333 | 1e280, 1e281, 1e282, 1e283, 1e284, 334 | 1e285, 1e286, 1e287, 1e288, 1e289, 335 | 1e290, 1e291, 1e292, 1e293, 1e294, 336 | 1e295, 1e296, 1e297, 1e298, 1e299, 337 | 1e300, 1e301, 1e302, 1e303, 1e304, 338 | 1e305, 1e306, 1e307, 1e308 339 | }; 340 | 341 | static int __parse_json_number(const char *cursor, const char **end, 342 | double *num) 343 | { 344 | const char *integer = cursor; 345 | long long mant = 0; 346 | int figures = 0; 347 | int exp = 0; 348 | double n; 349 | 350 | if (*cursor == '-') 351 | cursor++; 352 | 353 | if (*cursor >= '1' && *cursor <= '9') 354 | { 355 | mant = *cursor - '0'; 356 | figures = 1; 357 | cursor++; 358 | while (isdigit(*cursor) && figures < 18) 359 | { 360 | mant *= 10; 361 | mant += *cursor - '0'; 362 | figures++; 363 | cursor++; 364 | } 365 | 366 | while (isdigit(*cursor)) 367 | { 368 | exp++; 369 | cursor++; 370 | } 371 | } 372 | else if (*cursor == '0') 373 | cursor++; 374 | else 375 | return -2; 376 | 377 | if (*cursor == '.') 378 | { 379 | cursor++; 380 | if (!isdigit(*cursor)) 381 | return -2; 382 | 383 | if (figures == 0) 384 | { 385 | while (*cursor == '0') 386 | { 387 | exp--; 388 | cursor++; 389 | } 390 | } 391 | 392 | while (isdigit(*cursor) && figures < 18) 393 | { 394 | mant *= 10; 395 | mant += *cursor - '0'; 396 | figures++; 397 | exp--; 398 | cursor++; 399 | } 400 | 401 | while (isdigit(*cursor)) 402 | cursor++; 403 | } 404 | 405 | if (cursor - integer > 1000000) 406 | return -2; 407 | 408 | if (*cursor == 'E' || *cursor == 'e') 409 | { 410 | int neg; 411 | int e; 412 | 413 | cursor++; 414 | neg = (*cursor == '-'); 415 | if (neg || *cursor == '+') 416 | cursor++; 417 | 418 | if (!isdigit(*cursor)) 419 | return -2; 420 | 421 | e = *cursor - '0'; 422 | cursor++; 423 | while (isdigit(*cursor) && e < 2000000) 424 | { 425 | e *= 10; 426 | e += *cursor - '0'; 427 | cursor++; 428 | } 429 | 430 | while (isdigit(*cursor)) 431 | cursor++; 432 | 433 | if (neg) 434 | e = -e; 435 | 436 | exp += e; 437 | } 438 | 439 | if (exp != 0 && figures != 0) 440 | { 441 | while (exp > 0 && figures < 18) 442 | { 443 | mant *= 10; 444 | figures++; 445 | exp--; 446 | } 447 | 448 | while (exp < 0 && mant % 10 == 0) 449 | { 450 | mant /= 10; 451 | figures--; 452 | exp++; 453 | } 454 | } 455 | 456 | n = mant; 457 | if (exp != 0 && figures != 0) 458 | { 459 | if (exp > 291) 460 | n = INFINITY; 461 | else if (exp > 0) 462 | n *= __power_of_10[exp]; 463 | else if (exp > -309) 464 | n /= __power_of_10[-exp]; 465 | else if (exp > -324 - figures) 466 | { 467 | n /= __power_of_10[-exp - 308]; 468 | n /= __power_of_10[308]; 469 | } 470 | else 471 | n = 0.0; 472 | } 473 | 474 | if (*integer == '-') 475 | n = -n; 476 | 477 | *num = n; 478 | *end = cursor; 479 | return 0; 480 | } 481 | 482 | static int __parse_json_value(const char *cursor, const char **end, 483 | int depth, json_value_t *val); 484 | 485 | static void __destroy_json_value(json_value_t *val); 486 | 487 | static int __parse_json_member(const char *cursor, const char **end, 488 | int depth, json_member_t *memb) 489 | { 490 | int ret; 491 | 492 | ret = __parse_json_string(cursor, &cursor, memb->name); 493 | if (ret < 0) 494 | return ret; 495 | 496 | while (isspace(*cursor)) 497 | cursor++; 498 | 499 | if (*cursor != ':') 500 | return -2; 501 | 502 | cursor++; 503 | while (isspace(*cursor)) 504 | cursor++; 505 | 506 | ret = __parse_json_value(cursor, &cursor, depth, &memb->value); 507 | if (ret < 0) 508 | return ret; 509 | 510 | *end = cursor; 511 | return 0; 512 | } 513 | 514 | static int __parse_json_members(const char *cursor, const char **end, 515 | int depth, json_object_t *obj) 516 | { 517 | json_member_t *memb; 518 | size_t len; 519 | int ret; 520 | 521 | while (isspace(*cursor)) 522 | cursor++; 523 | 524 | if (*cursor == '}') 525 | { 526 | *end = cursor + 1; 527 | return 0; 528 | } 529 | 530 | while (1) 531 | { 532 | if (*cursor != '\"') 533 | return -2; 534 | 535 | cursor++; 536 | ret = __json_string_length(cursor, &len); 537 | if (ret < 0) 538 | return ret; 539 | 540 | memb = (json_member_t *)malloc(offsetof(json_member_t, name) + len + 1); 541 | if (!memb) 542 | return -1; 543 | 544 | ret = __parse_json_member(cursor, &cursor, depth, memb); 545 | if (ret < 0) 546 | { 547 | free(memb); 548 | return ret; 549 | } 550 | 551 | list_add_tail(&memb->list, &obj->head); 552 | obj->size++; 553 | 554 | while (isspace(*cursor)) 555 | cursor++; 556 | 557 | if (*cursor == ',') 558 | { 559 | cursor++; 560 | while (isspace(*cursor)) 561 | cursor++; 562 | } 563 | else if (*cursor == '}') 564 | break; 565 | else 566 | return -2; 567 | } 568 | 569 | *end = cursor + 1; 570 | return 0; 571 | } 572 | 573 | static void __destroy_json_members(json_object_t *obj) 574 | { 575 | struct list_head *pos, *tmp; 576 | json_member_t *memb; 577 | 578 | list_for_each_safe(pos, tmp, &obj->head) 579 | { 580 | memb = list_entry(pos, json_member_t, list); 581 | __destroy_json_value(&memb->value); 582 | free(memb); 583 | } 584 | } 585 | 586 | static int __parse_json_object(const char *cursor, const char **end, 587 | int depth, json_object_t *obj) 588 | { 589 | int ret; 590 | 591 | if (depth == JSON_DEPTH_LIMIT) 592 | return -3; 593 | 594 | INIT_LIST_HEAD(&obj->head); 595 | obj->size = 0; 596 | ret = __parse_json_members(cursor, end, depth + 1, obj); 597 | if (ret < 0) 598 | { 599 | __destroy_json_members(obj); 600 | return ret; 601 | } 602 | 603 | return 0; 604 | } 605 | 606 | static int __parse_json_elements(const char *cursor, const char **end, 607 | int depth, json_array_t *arr) 608 | { 609 | json_element_t *elem; 610 | int ret; 611 | 612 | while (isspace(*cursor)) 613 | cursor++; 614 | 615 | if (*cursor == ']') 616 | { 617 | *end = cursor + 1; 618 | return 0; 619 | } 620 | 621 | while (1) 622 | { 623 | elem = (json_element_t *)malloc(sizeof (json_element_t)); 624 | if (!elem) 625 | return -1; 626 | 627 | ret = __parse_json_value(cursor, &cursor, depth, &elem->value); 628 | if (ret < 0) 629 | { 630 | free(elem); 631 | return ret; 632 | } 633 | 634 | list_add_tail(&elem->list, &arr->head); 635 | arr->size++; 636 | 637 | while (isspace(*cursor)) 638 | cursor++; 639 | 640 | if (*cursor == ',') 641 | { 642 | cursor++; 643 | while (isspace(*cursor)) 644 | cursor++; 645 | } 646 | else if (*cursor == ']') 647 | break; 648 | else 649 | return -2; 650 | } 651 | 652 | *end = cursor + 1; 653 | return 0; 654 | } 655 | 656 | static void __destroy_json_elements(json_array_t *arr) 657 | { 658 | struct list_head *pos, *tmp; 659 | json_element_t *elem; 660 | 661 | list_for_each_safe(pos, tmp, &arr->head) 662 | { 663 | elem = list_entry(pos, json_element_t, list); 664 | __destroy_json_value(&elem->value); 665 | free(elem); 666 | } 667 | } 668 | 669 | static int __parse_json_array(const char *cursor, const char **end, 670 | int depth, json_array_t *arr) 671 | { 672 | int ret; 673 | 674 | if (depth == JSON_DEPTH_LIMIT) 675 | return -3; 676 | 677 | INIT_LIST_HEAD(&arr->head); 678 | arr->size = 0; 679 | ret = __parse_json_elements(cursor, end, depth + 1, arr); 680 | if (ret < 0) 681 | { 682 | __destroy_json_elements(arr); 683 | return ret; 684 | } 685 | 686 | return 0; 687 | } 688 | 689 | static int __parse_json_value(const char *cursor, const char **end, 690 | int depth, json_value_t *val) 691 | { 692 | size_t len; 693 | int ret; 694 | 695 | switch (*cursor) 696 | { 697 | case '\"': 698 | cursor++; 699 | ret = __json_string_length(cursor, &len); 700 | if (ret < 0) 701 | return ret; 702 | 703 | val->value.string = (char *)malloc(len + 1); 704 | if (!val->value.string) 705 | return -1; 706 | 707 | ret = __parse_json_string(cursor, end, val->value.string); 708 | if (ret < 0) 709 | { 710 | free(val->value.string); 711 | return ret; 712 | } 713 | 714 | val->type = JSON_VALUE_STRING; 715 | break; 716 | 717 | case '-': 718 | case '0': 719 | case '1': 720 | case '2': 721 | case '3': 722 | case '4': 723 | case '5': 724 | case '6': 725 | case '7': 726 | case '8': 727 | case '9': 728 | ret = __parse_json_number(cursor, end, &val->value.number); 729 | if (ret < 0) 730 | return ret; 731 | 732 | val->type = JSON_VALUE_NUMBER; 733 | break; 734 | 735 | case '{': 736 | cursor++; 737 | ret = __parse_json_object(cursor, end, depth, &val->value.object); 738 | if (ret < 0) 739 | return ret; 740 | 741 | val->type = JSON_VALUE_OBJECT; 742 | break; 743 | 744 | case '[': 745 | cursor++; 746 | ret = __parse_json_array(cursor, end, depth, &val->value.array); 747 | if (ret < 0) 748 | return ret; 749 | 750 | val->type = JSON_VALUE_ARRAY; 751 | break; 752 | 753 | case 't': 754 | if (strncmp(cursor, "true", 4) != 0) 755 | return -2; 756 | 757 | *end = cursor + 4; 758 | val->type = JSON_VALUE_TRUE; 759 | break; 760 | 761 | case 'f': 762 | if (strncmp(cursor, "false", 5) != 0) 763 | return -2; 764 | 765 | *end = cursor + 5; 766 | val->type = JSON_VALUE_FALSE; 767 | break; 768 | 769 | case 'n': 770 | if (strncmp(cursor, "null", 4) != 0) 771 | return -2; 772 | 773 | *end = cursor + 4; 774 | val->type = JSON_VALUE_NULL; 775 | break; 776 | 777 | default: 778 | return -2; 779 | } 780 | 781 | return 0; 782 | } 783 | 784 | static void __destroy_json_value(json_value_t *val) 785 | { 786 | switch (val->type) 787 | { 788 | case JSON_VALUE_STRING: 789 | free(val->value.string); 790 | break; 791 | 792 | case JSON_VALUE_OBJECT: 793 | __destroy_json_members(&val->value.object); 794 | break; 795 | 796 | case JSON_VALUE_ARRAY: 797 | __destroy_json_elements(&val->value.array); 798 | break; 799 | } 800 | } 801 | 802 | json_value_t *json_value_parse(const char *cursor) 803 | { 804 | json_value_t *val; 805 | 806 | val = (json_value_t *)malloc(sizeof (json_value_t)); 807 | if (!val) 808 | return NULL; 809 | 810 | while (isspace(*cursor)) 811 | cursor++; 812 | 813 | if (__parse_json_value(cursor, &cursor, 0, val) >= 0) 814 | { 815 | while (isspace(*cursor)) 816 | cursor++; 817 | 818 | if (*cursor == '\0') 819 | return val; 820 | 821 | __destroy_json_value(val); 822 | } 823 | 824 | free(val); 825 | return NULL; 826 | } 827 | 828 | static void __move_json_value(json_value_t *src, json_value_t *dest) 829 | { 830 | switch (src->type) 831 | { 832 | case JSON_VALUE_STRING: 833 | dest->value.string = src->value.string; 834 | break; 835 | 836 | case JSON_VALUE_NUMBER: 837 | dest->value.number = src->value.number; 838 | break; 839 | 840 | case JSON_VALUE_OBJECT: 841 | INIT_LIST_HEAD(&dest->value.object.head); 842 | list_splice(&src->value.object.head, &dest->value.object.head); 843 | dest->value.object.size = src->value.object.size; 844 | break; 845 | 846 | case JSON_VALUE_ARRAY: 847 | INIT_LIST_HEAD(&dest->value.array.head); 848 | list_splice(&src->value.array.head, &dest->value.array.head); 849 | dest->value.array.size = src->value.array.size; 850 | break; 851 | } 852 | 853 | dest->type = src->type; 854 | } 855 | 856 | static int __set_json_value(int type, va_list ap, json_value_t *val) 857 | { 858 | json_value_t *src; 859 | const char *str; 860 | size_t len; 861 | 862 | switch (type) 863 | { 864 | case 0: 865 | src = va_arg(ap, json_value_t *); 866 | __move_json_value(src, val); 867 | free(src); 868 | return 0; 869 | 870 | case JSON_VALUE_STRING: 871 | str = va_arg(ap, const char *); 872 | len = strlen(str); 873 | val->value.string = (char *)malloc(len + 1); 874 | if (!val->value.string) 875 | return -1; 876 | 877 | memcpy(val->value.string, str, len + 1); 878 | break; 879 | 880 | case JSON_VALUE_NUMBER: 881 | val->value.number = va_arg(ap, double); 882 | break; 883 | 884 | case JSON_VALUE_OBJECT: 885 | INIT_LIST_HEAD(&val->value.object.head); 886 | val->value.object.size = 0; 887 | break; 888 | 889 | case JSON_VALUE_ARRAY: 890 | INIT_LIST_HEAD(&val->value.array.head); 891 | val->value.array.size = 0; 892 | break; 893 | } 894 | 895 | val->type = type; 896 | return 0; 897 | } 898 | 899 | json_value_t *json_value_create(int type, ...) 900 | { 901 | json_value_t *val; 902 | va_list ap; 903 | int ret; 904 | 905 | val = (json_value_t *)malloc(sizeof (json_value_t)); 906 | if (!val) 907 | return NULL; 908 | 909 | va_start(ap, type); 910 | ret = __set_json_value(type, ap, val); 911 | va_end(ap); 912 | if (ret >= 0) 913 | return val; 914 | 915 | free(val); 916 | return NULL; 917 | } 918 | 919 | static int __copy_json_value(const json_value_t *src, json_value_t *dest); 920 | 921 | static int __copy_json_members(const json_object_t *src, json_object_t *dest) 922 | { 923 | struct list_head *pos; 924 | json_member_t *entry; 925 | json_member_t *memb; 926 | size_t len; 927 | int ret; 928 | 929 | list_for_each(pos, &src->head) 930 | { 931 | entry = list_entry(pos, json_member_t, list); 932 | len = strlen(entry->name); 933 | memb = (json_member_t *)malloc(offsetof(json_member_t, name) + len + 1); 934 | if (!memb) 935 | return -1; 936 | 937 | ret = __copy_json_value(&entry->value, &memb->value); 938 | if (ret < 0) 939 | { 940 | free(memb); 941 | return ret; 942 | } 943 | 944 | memcpy(memb->name, entry->name, len + 1); 945 | list_add_tail(&memb->list, &dest->head); 946 | dest->size++; 947 | } 948 | 949 | return 0; 950 | } 951 | 952 | static int __copy_json_elements(const json_array_t *src, json_array_t *dest) 953 | { 954 | struct list_head *pos; 955 | json_element_t *entry; 956 | json_element_t *elem; 957 | int ret; 958 | 959 | list_for_each(pos, &src->head) 960 | { 961 | elem = (json_element_t *)malloc(sizeof (json_element_t)); 962 | if (!elem) 963 | return -1; 964 | 965 | entry = list_entry(pos, json_element_t, list); 966 | ret = __copy_json_value(&entry->value, &elem->value); 967 | if (ret < 0) 968 | { 969 | free(elem); 970 | return ret; 971 | } 972 | 973 | list_add_tail(&elem->list, &dest->head); 974 | dest->size++; 975 | } 976 | 977 | return 0; 978 | } 979 | 980 | static int __copy_json_value(const json_value_t *src, json_value_t *dest) 981 | { 982 | size_t len; 983 | int ret; 984 | 985 | switch (src->type) 986 | { 987 | case JSON_VALUE_STRING: 988 | len = strlen(src->value.string); 989 | dest->value.string = (char *)malloc(len + 1); 990 | if (!dest->value.string) 991 | return -1; 992 | 993 | memcpy(dest->value.string, src->value.string, len + 1); 994 | break; 995 | 996 | case JSON_VALUE_NUMBER: 997 | dest->value.number = src->value.number; 998 | break; 999 | 1000 | case JSON_VALUE_OBJECT: 1001 | INIT_LIST_HEAD(&dest->value.object.head); 1002 | dest->value.object.size = 0; 1003 | ret = __copy_json_members(&src->value.object, &dest->value.object); 1004 | if (ret < 0) 1005 | { 1006 | __destroy_json_members(&dest->value.object); 1007 | return ret; 1008 | } 1009 | 1010 | break; 1011 | 1012 | case JSON_VALUE_ARRAY: 1013 | INIT_LIST_HEAD(&dest->value.array.head); 1014 | dest->value.array.size = 0; 1015 | ret = __copy_json_elements(&src->value.array, &dest->value.array); 1016 | if (ret < 0) 1017 | { 1018 | __destroy_json_elements(&dest->value.array); 1019 | return ret; 1020 | } 1021 | 1022 | break; 1023 | } 1024 | 1025 | dest->type = src->type; 1026 | return 0; 1027 | } 1028 | 1029 | json_value_t *json_value_copy(const json_value_t *val) 1030 | { 1031 | json_value_t *copy; 1032 | 1033 | copy = (json_value_t *)malloc(sizeof (json_value_t)); 1034 | if (!copy) 1035 | return NULL; 1036 | 1037 | if (__copy_json_value(val, copy) >= 0) 1038 | return copy; 1039 | 1040 | free(copy); 1041 | return NULL; 1042 | } 1043 | 1044 | void json_value_destroy(json_value_t *val) 1045 | { 1046 | __destroy_json_value(val); 1047 | free(val); 1048 | } 1049 | 1050 | int json_value_type(const json_value_t *val) 1051 | { 1052 | return val->type; 1053 | } 1054 | 1055 | const char *json_value_string(const json_value_t *val) 1056 | { 1057 | if (val->type != JSON_VALUE_STRING) 1058 | return NULL; 1059 | 1060 | return val->value.string; 1061 | } 1062 | 1063 | double json_value_number(const json_value_t *val) 1064 | { 1065 | if (val->type != JSON_VALUE_NUMBER) 1066 | return NAN; 1067 | 1068 | return val->value.number; 1069 | } 1070 | 1071 | json_object_t *json_value_object(const json_value_t *val) 1072 | { 1073 | if (val->type != JSON_VALUE_OBJECT) 1074 | return NULL; 1075 | 1076 | return (json_object_t *)&val->value.object; 1077 | } 1078 | 1079 | json_array_t *json_value_array(const json_value_t *val) 1080 | { 1081 | if (val->type != JSON_VALUE_ARRAY) 1082 | return NULL; 1083 | 1084 | return (json_array_t *)&val->value.array; 1085 | } 1086 | 1087 | const json_value_t *json_object_find(const char *name, 1088 | const json_object_t *obj) 1089 | { 1090 | struct list_head *pos; 1091 | json_member_t *memb; 1092 | 1093 | list_for_each(pos, &obj->head) 1094 | { 1095 | memb = list_entry(pos, json_member_t, list); 1096 | if (strcmp(name, memb->name) == 0) 1097 | return &memb->value; 1098 | } 1099 | 1100 | return NULL; 1101 | } 1102 | 1103 | size_t json_object_size(const json_object_t *obj) 1104 | { 1105 | return obj->size; 1106 | } 1107 | 1108 | const char *json_object_next_name(const char *name, 1109 | const json_object_t *obj) 1110 | { 1111 | const struct list_head *pos; 1112 | 1113 | if (name) 1114 | pos = &list_entry(name, json_member_t, name)->list; 1115 | else 1116 | pos = &obj->head; 1117 | 1118 | if (pos->next == &obj->head) 1119 | return NULL; 1120 | 1121 | return list_entry(pos->next, json_member_t, list)->name; 1122 | } 1123 | 1124 | const json_value_t *json_object_next_value(const json_value_t *val, 1125 | const json_object_t *obj) 1126 | { 1127 | const struct list_head *pos; 1128 | 1129 | if (val) 1130 | pos = &list_entry(val, json_member_t, value)->list; 1131 | else 1132 | pos = &obj->head; 1133 | 1134 | if (pos->next == &obj->head) 1135 | return NULL; 1136 | 1137 | return &list_entry(pos->next, json_member_t, list)->value; 1138 | } 1139 | 1140 | const char *json_object_prev_name(const char *name, 1141 | const json_object_t *obj) 1142 | { 1143 | const struct list_head *pos; 1144 | 1145 | if (name) 1146 | pos = &list_entry(name, json_member_t, name)->list; 1147 | else 1148 | pos = &obj->head; 1149 | 1150 | if (pos->prev == &obj->head) 1151 | return NULL; 1152 | 1153 | return list_entry(pos->prev, json_member_t, list)->name; 1154 | } 1155 | 1156 | const json_value_t *json_object_prev_value(const json_value_t *val, 1157 | const json_object_t *obj) 1158 | { 1159 | const struct list_head *pos; 1160 | 1161 | if (val) 1162 | pos = &list_entry(val, json_member_t, value)->list; 1163 | else 1164 | pos = &obj->head; 1165 | 1166 | if (pos->prev == &obj->head) 1167 | return NULL; 1168 | 1169 | return &list_entry(pos->prev, json_member_t, list)->value; 1170 | } 1171 | 1172 | const char *json_object_value_name(const json_value_t *val, 1173 | const json_object_t *obj) 1174 | { 1175 | return list_entry(val, json_member_t, value)->name; 1176 | } 1177 | 1178 | static const json_value_t *__json_object_insert(const char *name, 1179 | int type, va_list ap, 1180 | struct list_head *pos, 1181 | json_object_t *obj) 1182 | { 1183 | json_member_t *memb; 1184 | size_t len; 1185 | 1186 | len = strlen(name); 1187 | memb = (json_member_t *)malloc(offsetof(json_member_t, name) + len + 1); 1188 | if (!memb) 1189 | return NULL; 1190 | 1191 | memcpy(memb->name, name, len + 1); 1192 | if (__set_json_value(type, ap, &memb->value) < 0) 1193 | { 1194 | free(memb); 1195 | return NULL; 1196 | } 1197 | 1198 | list_add(&memb->list, pos); 1199 | obj->size++; 1200 | return &memb->value; 1201 | } 1202 | 1203 | const json_value_t *json_object_append(json_object_t *obj, 1204 | const char *name, 1205 | int type, ...) 1206 | { 1207 | const json_value_t *val; 1208 | va_list ap; 1209 | 1210 | va_start(ap, type); 1211 | val = __json_object_insert(name, type, ap, obj->head.prev, obj); 1212 | va_end(ap); 1213 | return val; 1214 | } 1215 | 1216 | const json_value_t *json_object_insert_after(const json_value_t *val, 1217 | json_object_t *obj, 1218 | const char *name, 1219 | int type, ...) 1220 | { 1221 | struct list_head *pos; 1222 | va_list ap; 1223 | 1224 | if (val) 1225 | pos = &list_entry(val, json_member_t, value)->list; 1226 | else 1227 | pos = &obj->head; 1228 | 1229 | va_start(ap, type); 1230 | val = __json_object_insert(name, type, ap, pos, obj); 1231 | va_end(ap); 1232 | return val; 1233 | } 1234 | 1235 | const json_value_t *json_object_insert_before(const json_value_t *val, 1236 | json_object_t *obj, 1237 | const char *name, 1238 | int type, ...) 1239 | { 1240 | struct list_head *pos; 1241 | va_list ap; 1242 | 1243 | if (val) 1244 | pos = &list_entry(val, json_member_t, value)->list; 1245 | else 1246 | pos = &obj->head; 1247 | 1248 | va_start(ap, type); 1249 | val = __json_object_insert(name, type, ap, pos->prev, obj); 1250 | va_end(ap); 1251 | return val; 1252 | } 1253 | 1254 | json_value_t *json_object_remove(const json_value_t *val, 1255 | json_object_t *obj) 1256 | { 1257 | json_member_t *memb = list_entry(val, json_member_t, value); 1258 | 1259 | val = (json_value_t *)malloc(sizeof (json_value_t)); 1260 | if (!val) 1261 | return NULL; 1262 | 1263 | list_del(&memb->list); 1264 | obj->size--; 1265 | 1266 | __move_json_value(&memb->value, (json_value_t *)val); 1267 | free(memb); 1268 | return (json_value_t *)val; 1269 | } 1270 | 1271 | size_t json_array_size(const json_array_t *arr) 1272 | { 1273 | return arr->size; 1274 | } 1275 | 1276 | const json_value_t *json_array_next_value(const json_value_t *val, 1277 | const json_array_t *arr) 1278 | { 1279 | const struct list_head *pos; 1280 | 1281 | if (val) 1282 | pos = &list_entry(val, json_element_t, value)->list; 1283 | else 1284 | pos = &arr->head; 1285 | 1286 | if (pos->next == &arr->head) 1287 | return NULL; 1288 | 1289 | return &list_entry(pos->next, json_element_t, list)->value; 1290 | } 1291 | 1292 | const json_value_t *json_array_prev_value(const json_value_t *val, 1293 | const json_array_t *arr) 1294 | { 1295 | const struct list_head *pos; 1296 | 1297 | if (val) 1298 | pos = &list_entry(val, json_element_t, value)->list; 1299 | else 1300 | pos = &arr->head; 1301 | 1302 | if (pos->prev == &arr->head) 1303 | return NULL; 1304 | 1305 | return &list_entry(pos->prev, json_element_t, list)->value; 1306 | } 1307 | 1308 | static const json_value_t *__json_array_insert(int type, va_list ap, 1309 | struct list_head *pos, 1310 | json_array_t *arr) 1311 | { 1312 | json_element_t *elem; 1313 | 1314 | elem = (json_element_t *)malloc(sizeof (json_element_t)); 1315 | if (!elem) 1316 | return NULL; 1317 | 1318 | if (__set_json_value(type, ap, &elem->value) < 0) 1319 | { 1320 | free(elem); 1321 | return NULL; 1322 | } 1323 | 1324 | list_add(&elem->list, pos); 1325 | arr->size++; 1326 | return &elem->value; 1327 | } 1328 | 1329 | const json_value_t *json_array_append(json_array_t *arr, 1330 | int type, ...) 1331 | { 1332 | const json_value_t *val; 1333 | va_list ap; 1334 | 1335 | va_start(ap, type); 1336 | val = __json_array_insert(type, ap, arr->head.prev, arr); 1337 | va_end(ap); 1338 | return val; 1339 | } 1340 | 1341 | const json_value_t *json_array_insert_after(const json_value_t *val, 1342 | json_array_t *arr, 1343 | int type, ...) 1344 | { 1345 | struct list_head *pos; 1346 | va_list ap; 1347 | 1348 | if (val) 1349 | pos = &list_entry(val, json_element_t, value)->list; 1350 | else 1351 | pos = &arr->head; 1352 | 1353 | va_start(ap, type); 1354 | val = __json_array_insert(type, ap, pos, arr); 1355 | va_end(ap); 1356 | return val; 1357 | } 1358 | 1359 | const json_value_t *json_array_insert_before(const json_value_t *val, 1360 | json_array_t *arr, 1361 | int type, ...) 1362 | { 1363 | struct list_head *pos; 1364 | va_list ap; 1365 | 1366 | if (val) 1367 | pos = &list_entry(val, json_element_t, value)->list; 1368 | else 1369 | pos = &arr->head; 1370 | 1371 | va_start(ap, type); 1372 | val = __json_array_insert(type, ap, pos->prev, arr); 1373 | va_end(ap); 1374 | return val; 1375 | } 1376 | 1377 | json_value_t *json_array_remove(const json_value_t *val, 1378 | json_array_t *arr) 1379 | { 1380 | json_element_t *elem = list_entry(val, json_element_t, value); 1381 | 1382 | val = (json_value_t *)malloc(sizeof (json_value_t)); 1383 | if (!val) 1384 | return NULL; 1385 | 1386 | list_del(&elem->list); 1387 | arr->size--; 1388 | 1389 | __move_json_value(&elem->value, (json_value_t *)val); 1390 | free(elem); 1391 | return (json_value_t *)val; 1392 | } 1393 | 1394 | -------------------------------------------------------------------------------- /json_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _JSON_PARSER_H_ 2 | #define _JSON_PARSER_H_ 3 | 4 | #include 5 | 6 | #define JSON_VALUE_STRING 1 7 | #define JSON_VALUE_NUMBER 2 8 | #define JSON_VALUE_OBJECT 3 9 | #define JSON_VALUE_ARRAY 4 10 | #define JSON_VALUE_TRUE 5 11 | #define JSON_VALUE_FALSE 6 12 | #define JSON_VALUE_NULL 7 13 | 14 | typedef struct __json_value json_value_t; 15 | typedef struct __json_object json_object_t; 16 | typedef struct __json_array json_array_t; 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | json_value_t *json_value_parse(const char *text); 24 | json_value_t *json_value_create(int type, ...); 25 | json_value_t *json_value_copy(const json_value_t *val); 26 | void json_value_destroy(json_value_t *val); 27 | 28 | int json_value_type(const json_value_t *val); 29 | const char *json_value_string(const json_value_t *val); 30 | double json_value_number(const json_value_t *val); 31 | json_object_t *json_value_object(const json_value_t *val); 32 | json_array_t *json_value_array(const json_value_t *val); 33 | 34 | const json_value_t *json_object_find(const char *name, 35 | const json_object_t *obj); 36 | size_t json_object_size(const json_object_t *obj); 37 | const char *json_object_next_name(const char *name, 38 | const json_object_t *obj); 39 | const json_value_t *json_object_next_value(const json_value_t *val, 40 | const json_object_t *obj); 41 | const char *json_object_prev_name(const char *name, 42 | const json_object_t *obj); 43 | const json_value_t *json_object_prev_value(const json_value_t *val, 44 | const json_object_t *obj); 45 | const char *json_object_value_name(const json_value_t *val, 46 | const json_object_t *obj); 47 | const json_value_t *json_object_append(json_object_t *obj, 48 | const char *name, 49 | int type, ...); 50 | const json_value_t *json_object_insert_after(const json_value_t *val, 51 | json_object_t *obj, 52 | const char *name, 53 | int type, ...); 54 | const json_value_t *json_object_insert_before(const json_value_t *val, 55 | json_object_t *obj, 56 | const char *name, 57 | int type, ...); 58 | json_value_t *json_object_remove(const json_value_t *val, 59 | json_object_t *obj); 60 | 61 | size_t json_array_size(const json_array_t *arr); 62 | const json_value_t *json_array_next_value(const json_value_t *val, 63 | const json_array_t *arr); 64 | const json_value_t *json_array_prev_value(const json_value_t *val, 65 | const json_array_t *arr); 66 | const json_value_t *json_array_append(json_array_t *arry, 67 | int type, ...); 68 | const json_value_t *json_array_insert_after(const json_value_t *val, 69 | json_array_t *arr, 70 | int type, ...); 71 | const json_value_t *json_array_insert_before(const json_value_t *val, 72 | json_array_t *arr, 73 | int type, ...); 74 | json_value_t *json_array_remove(const json_value_t *val, 75 | json_array_t *arr); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #define json_object_for_each(name, val, obj) \ 82 | for (name = NULL, val = NULL; \ 83 | name = json_object_next_name(name, obj), \ 84 | val = json_object_next_value(val, obj), val; ) 85 | 86 | #define json_object_for_each_prev(name, val, obj) \ 87 | for (name = NULL, val = NULL; \ 88 | name = json_object_prev_name(name, obj), \ 89 | val = json_object_prev_value(val, obj), val; ) 90 | 91 | #define json_array_for_each(val, arr) \ 92 | for (val = NULL; val = json_array_next_value(val, arr), val; ) 93 | 94 | #define json_array_for_each_prev(val, arr) \ 95 | for (val = NULL; val = json_array_prev_value(val, arr), val; ) 96 | 97 | #endif 98 | 99 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINUX_LIST_H 2 | #define _LINUX_LIST_H 3 | 4 | /* 5 | * Circular doubly linked list implementation. 6 | * 7 | * Some of the internal functions ("__xxx") are useful when 8 | * manipulating whole lists rather than single entries, as 9 | * sometimes we already know the next/prev entries and we can 10 | * generate better code by using them directly rather than 11 | * using the generic single-entry routines. 12 | */ 13 | 14 | struct list_head { 15 | struct list_head *next, *prev; 16 | }; 17 | 18 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 19 | 20 | #define LIST_HEAD(name) \ 21 | struct list_head name = LIST_HEAD_INIT(name) 22 | 23 | /** 24 | * INIT_LIST_HEAD - Initialize a list_head structure 25 | * @list: list_head structure to be initialized. 26 | * 27 | * Initializes the list_head to point to itself. If it is a list header, 28 | * the result is an empty list. 29 | */ 30 | static inline void INIT_LIST_HEAD(struct list_head *list) 31 | { 32 | list->next = list; 33 | list->prev = list; 34 | } 35 | 36 | /* 37 | * Insert a new entry between two known consecutive entries. 38 | * 39 | * This is only for internal list manipulation where we know 40 | * the prev/next entries already! 41 | */ 42 | static inline void __list_add(struct list_head *entry, 43 | struct list_head *prev, 44 | struct list_head *next) 45 | { 46 | next->prev = entry; 47 | entry->next = next; 48 | entry->prev = prev; 49 | prev->next = entry; 50 | } 51 | 52 | /** 53 | * list_add - add a new entry 54 | * @entry: new entry to be added 55 | * @head: list head to add it after 56 | * 57 | * Insert a new entry after the specified head. 58 | * This is good for implementing stacks. 59 | */ 60 | static inline void list_add(struct list_head *entry, struct list_head *head) 61 | { 62 | __list_add(entry, head, head->next); 63 | } 64 | 65 | /** 66 | * list_add_tail - add a new entry 67 | * @entry: new entry to be added 68 | * @head: list head to add it before 69 | * 70 | * Insert a new entry before the specified head. 71 | * This is useful for implementing queues. 72 | */ 73 | static inline void list_add_tail(struct list_head *entry, 74 | struct list_head *head) 75 | { 76 | __list_add(entry, head->prev, head); 77 | } 78 | 79 | /* 80 | * Delete a list entry by making the prev/next entries 81 | * point to each other. 82 | * 83 | * This is only for internal list manipulation where we know 84 | * the prev/next entries already! 85 | */ 86 | static inline void __list_del(struct list_head *prev, struct list_head *next) 87 | { 88 | next->prev = prev; 89 | prev->next = next; 90 | } 91 | 92 | /** 93 | * list_del - deletes entry from list. 94 | * @entry: the element to delete from the list. 95 | * Note: list_empty() on entry does not return true after this, the entry is 96 | * in an undefined state. 97 | */ 98 | static inline void list_del(struct list_head *entry) 99 | { 100 | __list_del(entry->prev, entry->next); 101 | } 102 | 103 | /** 104 | * list_move - delete from one list and add as another's head 105 | * @entry: the entry to move 106 | * @head: the head that will precede our entry 107 | */ 108 | static inline void list_move(struct list_head *entry, struct list_head *head) 109 | { 110 | __list_del(entry->prev, entry->next); 111 | list_add(entry, head); 112 | } 113 | 114 | /** 115 | * list_move_tail - delete from one list and add as another's tail 116 | * @entry: the entry to move 117 | * @head: the head that will follow our entry 118 | */ 119 | static inline void list_move_tail(struct list_head *entry, 120 | struct list_head *head) 121 | { 122 | __list_del(entry->prev, entry->next); 123 | list_add_tail(entry, head); 124 | } 125 | 126 | /** 127 | * list_empty - tests whether a list is empty 128 | * @head: the list to test. 129 | */ 130 | static inline int list_empty(const struct list_head *head) 131 | { 132 | return head->next == head; 133 | } 134 | 135 | static inline void __list_splice(const struct list_head *list, 136 | struct list_head *prev, 137 | struct list_head *next) 138 | { 139 | struct list_head *first = list->next; 140 | struct list_head *last = list->prev; 141 | 142 | first->prev = prev; 143 | prev->next = first; 144 | 145 | last->next = next; 146 | next->prev = last; 147 | } 148 | 149 | /** 150 | * list_splice - join two lists 151 | * @list: the new list to add. 152 | * @head: the place to add it in the first list. 153 | */ 154 | static inline void list_splice(const struct list_head *list, 155 | struct list_head *head) 156 | { 157 | if (!list_empty(list)) 158 | __list_splice(list, head, head->next); 159 | } 160 | 161 | /** 162 | * list_splice_init - join two lists and reinitialise the emptied list. 163 | * @list: the new list to add. 164 | * @head: the place to add it in the first list. 165 | * 166 | * The list at @list is reinitialised 167 | */ 168 | static inline void list_splice_init(struct list_head *list, 169 | struct list_head *head) 170 | { 171 | if (!list_empty(list)) { 172 | __list_splice(list, head, head->next); 173 | INIT_LIST_HEAD(list); 174 | } 175 | } 176 | 177 | /** 178 | * list_entry - get the struct for this entry 179 | * @ptr: the &struct list_head pointer. 180 | * @type: the type of the struct this is embedded in. 181 | * @member: the name of the list_struct within the struct. 182 | */ 183 | #define list_entry(ptr, type, member) \ 184 | ((type *)((char *)(ptr)-(size_t)(&((type *)0)->member))) 185 | 186 | /** 187 | * list_for_each - iterate over a list 188 | * @pos: the &struct list_head to use as a loop counter. 189 | * @head: the head for your list. 190 | */ 191 | #define list_for_each(pos, head) \ 192 | for (pos = (head)->next; pos != (head); pos = pos->next) 193 | 194 | /** 195 | * list_for_each_prev - iterate over a list backwards 196 | * @pos: the &struct list_head to use as a loop counter. 197 | * @head: the head for your list. 198 | */ 199 | #define list_for_each_prev(pos, head) \ 200 | for (pos = (head)->prev; pos != (head); pos = pos->prev) 201 | 202 | /** 203 | * list_for_each_safe - iterate over a list safe against removal of list entry 204 | * @pos: the &struct list_head to use as a loop counter. 205 | * @n: another &struct list_head to use as temporary storage 206 | * @head: the head for your list. 207 | */ 208 | #define list_for_each_safe(pos, n, head) \ 209 | for (pos = (head)->next, n = pos->next; pos != (head); \ 210 | pos = n, n = pos->next) 211 | 212 | /** 213 | * list_for_each_entry - iterate over list of given type 214 | * @pos: the type * to use as a loop counter. 215 | * @head: the head for your list. 216 | * @member: the name of the list_struct within the struct. 217 | */ 218 | #define list_for_each_entry(pos, head, member) \ 219 | for (pos = list_entry((head)->next, typeof (*pos), member); \ 220 | &pos->member != (head); \ 221 | pos = list_entry(pos->member.next, typeof (*pos), member)) 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "json_parser.h" 4 | 5 | #define BUFSIZE (64 * 1024 * 1024) 6 | 7 | void print_json_value(const json_value_t *val, int depth); 8 | 9 | void print_json_string(const char *str) 10 | { 11 | printf("\""); 12 | while (*str) 13 | { 14 | switch (*str) 15 | { 16 | case '\r': 17 | printf("\\r"); 18 | break; 19 | case '\n': 20 | printf("\\n"); 21 | break; 22 | case '\f': 23 | printf("\\f"); 24 | break; 25 | case '\b': 26 | printf("\\b"); 27 | break; 28 | case '\"': 29 | printf("\\\""); 30 | break; 31 | case '\t': 32 | printf("\\t"); 33 | break; 34 | case '\\': 35 | printf("\\\\"); 36 | break; 37 | default: 38 | if ((unsigned char)*str < 0x20) 39 | printf("\\u00%02x", *str); 40 | else 41 | printf("%c", *str); 42 | break; 43 | } 44 | str++; 45 | } 46 | printf("\""); 47 | } 48 | 49 | void print_json_object(const json_object_t *obj, int depth) 50 | { 51 | const char *name; 52 | const json_value_t *val; 53 | int n = 0; 54 | int i; 55 | 56 | if (json_object_size(obj) == 0) 57 | { 58 | printf("{}"); 59 | return; 60 | } 61 | 62 | printf("{\n"); 63 | json_object_for_each(name, val, obj) 64 | { 65 | if (n != 0) 66 | printf(",\n"); 67 | n++; 68 | for (i = 0; i < depth + 1; i++) 69 | printf(" "); 70 | print_json_string(name); 71 | printf(": "); 72 | print_json_value(val, depth + 1); 73 | } 74 | 75 | printf("\n"); 76 | for (i = 0; i < depth; i++) 77 | printf(" "); 78 | printf("}"); 79 | } 80 | 81 | void print_json_array(const json_array_t *arr, int depth) 82 | { 83 | const json_value_t *val; 84 | int n = 0; 85 | int i; 86 | 87 | if (json_array_size(arr) == 0) 88 | { 89 | printf("[]"); 90 | return; 91 | } 92 | 93 | printf("[\n"); 94 | json_array_for_each(val, arr) 95 | { 96 | if (n != 0) 97 | printf(",\n"); 98 | n++; 99 | for (i = 0; i < depth + 1; i++) 100 | printf(" "); 101 | print_json_value(val, depth + 1); 102 | } 103 | 104 | printf("\n"); 105 | for (i = 0; i < depth; i++) 106 | printf(" "); 107 | printf("]"); 108 | } 109 | 110 | void print_json_number(double number) 111 | { 112 | printf("%.15lg", number); 113 | } 114 | 115 | void print_json_value(const json_value_t *val, int depth) 116 | { 117 | switch (json_value_type(val)) 118 | { 119 | case JSON_VALUE_STRING: 120 | print_json_string(json_value_string(val)); 121 | break; 122 | case JSON_VALUE_NUMBER: 123 | print_json_number(json_value_number(val)); 124 | break; 125 | case JSON_VALUE_OBJECT: 126 | print_json_object(json_value_object(val), depth); 127 | break; 128 | case JSON_VALUE_ARRAY: 129 | print_json_array(json_value_array(val), depth); 130 | break; 131 | case JSON_VALUE_TRUE: 132 | printf("true"); 133 | break; 134 | case JSON_VALUE_FALSE: 135 | printf("false"); 136 | break; 137 | case JSON_VALUE_NULL: 138 | printf("null"); 139 | break; 140 | } 141 | } 142 | 143 | int main() 144 | { 145 | static char buf[BUFSIZE]; 146 | size_t n = fread(buf, 1, BUFSIZE, stdin); 147 | 148 | if (n > 0) 149 | { 150 | if (n == BUFSIZE) 151 | { 152 | fprintf(stderr, "File too large.\n"); 153 | exit(1); 154 | } 155 | 156 | buf[n] = '\0'; 157 | } 158 | else 159 | { 160 | perror("fread"); 161 | exit(1); 162 | } 163 | 164 | json_value_t *val = json_value_parse(buf); 165 | if (val) 166 | { 167 | json_value_t *val1 = json_value_copy(val); 168 | json_value_destroy(val); 169 | print_json_value(val1, 0); 170 | json_value_destroy(val1); 171 | } 172 | else 173 | fprintf(stderr, "Invalid JSON document.\n"); 174 | 175 | return 0; 176 | } 177 | 178 | -------------------------------------------------------------------------------- /test_speed.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "json_parser.h" 4 | 5 | #define BUFSIZE (64 * 1024 * 1024) 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | static char buf[BUFSIZE]; 10 | size_t n; 11 | 12 | if (argc != 2) 13 | { 14 | fprintf(stderr, "USAGE: %s \n", argv[0]); 15 | exit(1); 16 | } 17 | 18 | n = fread(buf, 1, BUFSIZE, stdin); 19 | if (n > 0) 20 | { 21 | if (n == BUFSIZE) 22 | { 23 | fprintf(stderr, "File too large.\n"); 24 | exit(1); 25 | } 26 | 27 | buf[n] = '\0'; 28 | } 29 | else 30 | { 31 | perror("fread"); 32 | exit(1); 33 | } 34 | 35 | int rep = atoi(argv[1]); 36 | int i; 37 | 38 | for (i = 0; i < rep; i++) 39 | { 40 | json_value_t *val = json_value_parse(buf); 41 | if (val) 42 | { 43 | json_value_destroy(val); 44 | } 45 | else 46 | { 47 | fprintf(stderr, "Invalid JSON document.\n"); 48 | exit(1); 49 | } 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /xmake.lua: -------------------------------------------------------------------------------- 1 | set_project("json-parser") 2 | set_version("1.5.2") 3 | 4 | if is_mode("release") then 5 | set_optimize("faster") 6 | set_strip("all") 7 | elseif is_mode("debug") then 8 | set_symbols("debug") 9 | set_optimize("none") 10 | end 11 | 12 | set_languages("c99") 13 | set_warnings("all") 14 | 15 | target("json-parser") 16 | set_kind("$(kind)") 17 | add_files("json_parser.c") 18 | 19 | target("test_speed") 20 | set_kind("binary") 21 | add_files("test_speed.c") 22 | add_deps("json-parser") 23 | 24 | target("parse_json") 25 | set_kind("binary") 26 | add_files("test.c") 27 | add_deps("json-parser") 28 | --------------------------------------------------------------------------------