json.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/byte_buf.h>
  6. #include <aws/common/string.h>
  7. #include <aws/common/json.h>
  8. #include <aws/common/private/json_impl.h>
  9. #include <aws/common/external/cJSON.h>
  10. static struct aws_allocator *s_aws_json_module_allocator = NULL;
  11. static bool s_aws_json_module_initialized = false;
  12. struct aws_json_value *aws_json_value_new_string(struct aws_allocator *allocator, struct aws_byte_cursor string) {
  13. struct aws_string *tmp = aws_string_new_from_cursor(allocator, &string);
  14. void *ret_val = cJSON_CreateString(aws_string_c_str(tmp));
  15. aws_string_destroy_secure(tmp);
  16. return ret_val;
  17. }
  18. struct aws_json_value *aws_json_value_new_number(struct aws_allocator *allocator, double number) {
  19. (void)allocator; // prevent warnings over unused parameter
  20. return (void *)cJSON_CreateNumber(number);
  21. }
  22. struct aws_json_value *aws_json_value_new_array(struct aws_allocator *allocator) {
  23. (void)allocator; // prevent warnings over unused parameter
  24. return (void *)cJSON_CreateArray();
  25. }
  26. struct aws_json_value *aws_json_value_new_boolean(struct aws_allocator *allocator, bool boolean) {
  27. (void)allocator; // prevent warnings over unused parameter
  28. return (void *)cJSON_CreateBool(boolean);
  29. }
  30. struct aws_json_value *aws_json_value_new_null(struct aws_allocator *allocator) {
  31. (void)allocator; // prevent warnings over unused parameter
  32. return (void *)cJSON_CreateNull();
  33. }
  34. struct aws_json_value *aws_json_value_new_object(struct aws_allocator *allocator) {
  35. (void)allocator; // prevent warnings over unused parameter
  36. return (void *)cJSON_CreateObject();
  37. }
  38. int aws_json_value_get_string(const struct aws_json_value *value, struct aws_byte_cursor *output) {
  39. const struct cJSON *cjson = (const struct cJSON *)value;
  40. if (!cJSON_IsString(cjson)) {
  41. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  42. }
  43. *output = aws_byte_cursor_from_c_str(cJSON_GetStringValue(cjson));
  44. return AWS_OP_SUCCESS;
  45. }
  46. int aws_json_value_get_number(const struct aws_json_value *value, double *output) {
  47. const struct cJSON *cjson = (const struct cJSON *)value;
  48. if (!cJSON_IsNumber(cjson)) {
  49. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  50. }
  51. *output = cjson->valuedouble;
  52. return AWS_OP_SUCCESS;
  53. }
  54. int aws_json_value_get_boolean(const struct aws_json_value *value, bool *output) {
  55. const struct cJSON *cjson = (const struct cJSON *)value;
  56. if (!cJSON_IsBool(cjson)) {
  57. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  58. }
  59. *output = cjson->type == cJSON_True;
  60. return AWS_OP_SUCCESS;
  61. }
  62. int aws_json_value_add_to_object(
  63. struct aws_json_value *object,
  64. struct aws_byte_cursor key,
  65. struct aws_json_value *value) {
  66. int result = AWS_OP_ERR;
  67. struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key);
  68. struct cJSON *cjson = (struct cJSON *)object;
  69. if (!cJSON_IsObject(cjson)) {
  70. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  71. goto done;
  72. }
  73. struct cJSON *cjson_value = (struct cJSON *)value;
  74. if (cJSON_IsInvalid(cjson_value)) {
  75. result = aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  76. goto done;
  77. }
  78. if (cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) {
  79. goto done;
  80. }
  81. cJSON_AddItemToObject(cjson, aws_string_c_str(tmp), cjson_value);
  82. result = AWS_OP_SUCCESS;
  83. done:
  84. aws_string_destroy_secure(tmp);
  85. return result;
  86. }
  87. struct aws_json_value *aws_json_value_get_from_object(const struct aws_json_value *object, struct aws_byte_cursor key) {
  88. void *return_value = NULL;
  89. struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key);
  90. const struct cJSON *cjson = (const struct cJSON *)object;
  91. if (!cJSON_IsObject(cjson)) {
  92. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  93. goto done;
  94. }
  95. if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) {
  96. goto done;
  97. }
  98. return_value = (void *)cJSON_GetObjectItem(cjson, aws_string_c_str(tmp));
  99. done:
  100. aws_string_destroy_secure(tmp);
  101. return return_value;
  102. }
  103. bool aws_json_value_has_key(const struct aws_json_value *object, struct aws_byte_cursor key) {
  104. struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key);
  105. bool result = false;
  106. const struct cJSON *cjson = (const struct cJSON *)object;
  107. if (!cJSON_IsObject(cjson)) {
  108. goto done;
  109. }
  110. if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) {
  111. goto done;
  112. }
  113. result = true;
  114. done:
  115. aws_string_destroy_secure(tmp);
  116. return result;
  117. }
  118. int aws_json_value_remove_from_object(struct aws_json_value *object, struct aws_byte_cursor key) {
  119. int result = AWS_OP_ERR;
  120. struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key);
  121. struct cJSON *cjson = (struct cJSON *)object;
  122. if (!cJSON_IsObject(cjson)) {
  123. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  124. goto done;
  125. }
  126. if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) {
  127. goto done;
  128. }
  129. cJSON_DeleteItemFromObject(cjson, aws_string_c_str(tmp));
  130. result = AWS_OP_SUCCESS;
  131. done:
  132. aws_string_destroy_secure(tmp);
  133. return result;
  134. }
  135. int aws_json_const_iterate_object(
  136. const struct aws_json_value *object,
  137. aws_json_on_member_encountered_const_fn *on_member,
  138. void *user_data) {
  139. int result = AWS_OP_ERR;
  140. const struct cJSON *cjson = (const struct cJSON *)object;
  141. if (!cJSON_IsObject(cjson)) {
  142. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  143. goto done;
  144. }
  145. const cJSON *key = NULL;
  146. cJSON_ArrayForEach(key, cjson) {
  147. bool should_continue = true;
  148. struct aws_byte_cursor key_cur = aws_byte_cursor_from_c_str(key->string);
  149. if (on_member(&key_cur, (const struct aws_json_value *)key, &should_continue, user_data)) {
  150. goto done;
  151. }
  152. if (!should_continue) {
  153. break;
  154. }
  155. }
  156. result = AWS_OP_SUCCESS;
  157. done:
  158. return result;
  159. }
  160. int aws_json_value_add_array_element(struct aws_json_value *array, const struct aws_json_value *value) {
  161. struct cJSON *cjson = (struct cJSON *)array;
  162. if (!cJSON_IsArray(cjson)) {
  163. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  164. }
  165. struct cJSON *cjson_value = (struct cJSON *)value;
  166. if (cJSON_IsInvalid(cjson_value)) {
  167. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  168. }
  169. cJSON_AddItemToArray(cjson, cjson_value);
  170. return AWS_OP_SUCCESS;
  171. }
  172. struct aws_json_value *aws_json_get_array_element(const struct aws_json_value *array, size_t index) {
  173. const struct cJSON *cjson = (const struct cJSON *)array;
  174. if (!cJSON_IsArray(cjson)) {
  175. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  176. return NULL;
  177. }
  178. if (index > (size_t)cJSON_GetArraySize(cjson)) {
  179. aws_raise_error(AWS_ERROR_INVALID_INDEX);
  180. return NULL;
  181. }
  182. return (void *)cJSON_GetArrayItem(cjson, (int)index);
  183. }
  184. size_t aws_json_get_array_size(const struct aws_json_value *array) {
  185. const struct cJSON *cjson = (const struct cJSON *)array;
  186. if (!cJSON_IsArray(cjson)) {
  187. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  188. return 0;
  189. }
  190. return cJSON_GetArraySize(cjson);
  191. }
  192. int aws_json_value_remove_array_element(struct aws_json_value *array, size_t index) {
  193. struct cJSON *cjson = (struct cJSON *)array;
  194. if (!cJSON_IsArray(cjson)) {
  195. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  196. }
  197. if (index > (size_t)cJSON_GetArraySize(cjson)) {
  198. return aws_raise_error(AWS_ERROR_INVALID_INDEX);
  199. }
  200. cJSON_DeleteItemFromArray(cjson, (int)index);
  201. return AWS_OP_SUCCESS;
  202. }
  203. int aws_json_const_iterate_array(
  204. const struct aws_json_value *array,
  205. aws_json_on_value_encountered_const_fn *on_value,
  206. void *user_data) {
  207. int result = AWS_OP_ERR;
  208. const struct cJSON *cjson = (const struct cJSON *)array;
  209. if (!cJSON_IsArray(cjson)) {
  210. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  211. goto done;
  212. }
  213. size_t idx = 0;
  214. const cJSON *value = NULL;
  215. cJSON_ArrayForEach(value, cjson) {
  216. bool should_continue = true;
  217. if (on_value(idx, (const struct aws_json_value *)value, &should_continue, user_data)) {
  218. goto done;
  219. }
  220. if (!should_continue) {
  221. break;
  222. }
  223. ++idx;
  224. }
  225. result = AWS_OP_SUCCESS;
  226. done:
  227. return result;
  228. }
  229. bool aws_json_value_compare(const struct aws_json_value *a, const struct aws_json_value *b, bool is_case_sensitive) {
  230. const struct cJSON *cjson_a = (const struct cJSON *)a;
  231. const struct cJSON *cjson_b = (const struct cJSON *)b;
  232. return cJSON_Compare(cjson_a, cjson_b, is_case_sensitive);
  233. }
  234. struct aws_json_value *aws_json_value_duplicate(const struct aws_json_value *value) {
  235. const struct cJSON *cjson = (const struct cJSON *)value;
  236. if (cJSON_IsInvalid(cjson)) {
  237. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  238. return NULL;
  239. }
  240. struct cJSON *ret = cJSON_Duplicate(cjson, true);
  241. if (ret == NULL) {
  242. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  243. }
  244. return (void *)ret;
  245. }
  246. bool aws_json_value_is_string(const struct aws_json_value *value) {
  247. const struct cJSON *cjson = (const struct cJSON *)value;
  248. if (cJSON_IsInvalid(cjson)) {
  249. return false;
  250. }
  251. return cJSON_IsString(cjson);
  252. }
  253. bool aws_json_value_is_number(const struct aws_json_value *value) {
  254. const struct cJSON *cjson = (const struct cJSON *)value;
  255. if (cJSON_IsInvalid(cjson)) {
  256. return false;
  257. }
  258. return cJSON_IsNumber(cjson);
  259. }
  260. bool aws_json_value_is_array(const struct aws_json_value *value) {
  261. const struct cJSON *cjson = (const struct cJSON *)value;
  262. if (cJSON_IsInvalid(cjson)) {
  263. return false;
  264. }
  265. return cJSON_IsArray(cjson);
  266. }
  267. bool aws_json_value_is_boolean(const struct aws_json_value *value) {
  268. const struct cJSON *cjson = (const struct cJSON *)value;
  269. if (cJSON_IsInvalid(cjson)) {
  270. return false;
  271. }
  272. return cJSON_IsBool(cjson);
  273. }
  274. bool aws_json_value_is_null(const struct aws_json_value *value) {
  275. const struct cJSON *cjson = (const struct cJSON *)value;
  276. if (cJSON_IsInvalid(cjson)) {
  277. return false;
  278. }
  279. return cJSON_IsNull(cjson);
  280. }
  281. bool aws_json_value_is_object(const struct aws_json_value *value) {
  282. const struct cJSON *cjson = (const struct cJSON *)value;
  283. if (cJSON_IsInvalid(cjson)) {
  284. return false;
  285. }
  286. return cJSON_IsObject(cjson);
  287. }
  288. static void *s_aws_cJSON_alloc(size_t sz) {
  289. return aws_mem_acquire(s_aws_json_module_allocator, sz);
  290. }
  291. static void s_aws_cJSON_free(void *ptr) {
  292. aws_mem_release(s_aws_json_module_allocator, ptr);
  293. }
  294. void aws_json_module_init(struct aws_allocator *allocator) {
  295. if (!s_aws_json_module_initialized) {
  296. s_aws_json_module_allocator = allocator;
  297. struct cJSON_Hooks allocation_hooks = {
  298. .malloc_fn = s_aws_cJSON_alloc,
  299. .free_fn = s_aws_cJSON_free,
  300. };
  301. cJSON_InitHooks(&allocation_hooks);
  302. s_aws_json_module_initialized = true;
  303. }
  304. }
  305. void aws_json_module_cleanup(void) {
  306. if (s_aws_json_module_initialized) {
  307. s_aws_json_module_allocator = NULL;
  308. s_aws_json_module_initialized = false;
  309. }
  310. }
  311. void aws_json_value_destroy(struct aws_json_value *value) {
  312. struct cJSON *cjson = (struct cJSON *)value;
  313. /* Note: cJSON_IsInvalid returns false for NULL values, so we need explicit
  314. check for NULL to skip delete */
  315. if (cjson != NULL && !cJSON_IsInvalid(cjson)) {
  316. cJSON_Delete(cjson);
  317. }
  318. }
  319. int aws_byte_buf_append_json_string(const struct aws_json_value *value, struct aws_byte_buf *output) {
  320. const struct cJSON *cjson = (const struct cJSON *)value;
  321. if (cJSON_IsInvalid(cjson)) {
  322. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  323. }
  324. char *tmp = cJSON_PrintUnformatted(cjson);
  325. if (tmp == NULL) {
  326. return AWS_OP_ERR;
  327. }
  328. // Append the text to the byte buffer
  329. struct aws_byte_cursor tmp_cursor = aws_byte_cursor_from_c_str(tmp);
  330. int return_val = aws_byte_buf_append_dynamic_secure(output, &tmp_cursor);
  331. s_aws_cJSON_free(tmp); // free the char* now that we do not need it
  332. return return_val;
  333. }
  334. int aws_byte_buf_append_json_string_formatted(const struct aws_json_value *value, struct aws_byte_buf *output) {
  335. const struct cJSON *cjson = (const struct cJSON *)value;
  336. if (cJSON_IsInvalid(cjson)) {
  337. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  338. }
  339. char *tmp = cJSON_Print(cjson);
  340. if (tmp == NULL) {
  341. return AWS_OP_ERR;
  342. }
  343. // Append the text to the byte buffer
  344. struct aws_byte_cursor tmp_cursor = aws_byte_cursor_from_c_str(tmp);
  345. int return_val = aws_byte_buf_append_dynamic_secure(output, &tmp_cursor);
  346. s_aws_cJSON_free(tmp); // free the char* now that we do not need it
  347. return return_val;
  348. }
  349. struct aws_json_value *aws_json_value_new_from_string(struct aws_allocator *allocator, struct aws_byte_cursor string) {
  350. struct aws_string *tmp = aws_string_new_from_cursor(allocator, &string);
  351. struct cJSON *cjson = cJSON_Parse(aws_string_c_str(tmp));
  352. aws_string_destroy_secure(tmp);
  353. return (void *)cjson;
  354. }