aws-crt 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (322) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/VERSION +1 -1
  4. data/aws-crt-ffi/CMakeLists.txt +49 -41
  5. data/aws-crt-ffi/crt/aws-c-auth/CMakeLists.txt +0 -10
  6. data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/credentials.h +3 -2
  7. data/aws-crt-ffi/crt/aws-c-auth/include/aws/auth/private/credentials_utils.h +4 -4
  8. data/aws-crt-ffi/crt/aws-c-auth/source/auth.c +1 -14
  9. data/aws-crt-ffi/crt/aws-c-auth/source/aws_imds_client.c +206 -68
  10. data/aws-crt-ffi/crt/aws-c-auth/source/aws_signing.c +5 -0
  11. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_cached.c +6 -6
  12. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_default_chain.c +16 -1
  13. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_ecs.c +0 -1
  14. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_process.c +0 -1
  15. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_sts_web_identity.c +0 -1
  16. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_provider_x509.c +10 -7
  17. data/aws-crt-ffi/crt/aws-c-auth/source/credentials_utils.c +35 -26
  18. data/aws-crt-ffi/crt/aws-c-auth/source/signable_chunk.c +3 -2
  19. data/aws-crt-ffi/crt/aws-c-auth/tests/CMakeLists.txt +3 -2
  20. data/aws-crt-ffi/crt/aws-c-auth/tests/aws_imds_client_test.c +1 -0
  21. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_ecs_tests.c +3 -0
  22. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_provider_process_tests.c +65 -16
  23. data/aws-crt-ffi/crt/aws-c-auth/tests/credentials_tests.c +125 -0
  24. data/aws-crt-ffi/crt/aws-c-auth/tests/sigv4_signing_tests.c +68 -46
  25. data/aws-crt-ffi/crt/aws-c-cal/CMakeLists.txt +8 -3
  26. data/aws-crt-ffi/crt/aws-c-cal/bin/run_x_platform_fuzz_corpus/main.c +9 -0
  27. data/aws-crt-ffi/crt/aws-c-cal/builder.json +11 -3
  28. data/aws-crt-ffi/crt/aws-c-cal/cmake/aws-c-cal-config.cmake +14 -5
  29. data/aws-crt-ffi/crt/aws-c-cal/source/darwin/securityframework_ecc.c +6 -6
  30. data/aws-crt-ffi/crt/aws-c-cal/source/windows/bcrypt_ecc.c +12 -12
  31. data/aws-crt-ffi/crt/aws-c-cal/tests/test_case_helper.h +14 -14
  32. data/aws-crt-ffi/crt/aws-c-common/CMakeLists.txt +21 -1
  33. data/aws-crt-ffi/crt/aws-c-common/README.md +8 -0
  34. data/aws-crt-ffi/crt/aws-c-common/cmake/AwsCFlags.cmake +20 -5
  35. data/aws-crt-ffi/crt/aws-c-common/cmake/AwsFeatureTests.cmake +7 -1
  36. data/aws-crt-ffi/crt/aws-c-common/format-check.sh +1 -1
  37. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/byte_buf.h +14 -0
  38. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/config.h.in +1 -0
  39. data/aws-crt-ffi/crt/{aws-c-auth/include/aws/auth → aws-c-common/include/aws/common}/external/cJSON.h +82 -74
  40. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/json.h +335 -0
  41. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/logging.h +1 -0
  42. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/math.inl +2 -2
  43. data/aws-crt-ffi/crt/aws-c-common/include/aws/common/private/json_impl.h +22 -0
  44. data/aws-crt-ffi/crt/aws-c-common/include/aws/testing/aws_test_harness.h +2 -0
  45. data/aws-crt-ffi/crt/aws-c-common/source/byte_buf.c +36 -0
  46. data/aws-crt-ffi/crt/aws-c-common/source/common.c +5 -2
  47. data/aws-crt-ffi/crt/aws-c-common/source/external/cJSON.c +3113 -0
  48. data/aws-crt-ffi/crt/aws-c-common/source/file.c +9 -0
  49. data/aws-crt-ffi/crt/aws-c-common/source/json.c +348 -0
  50. data/aws-crt-ffi/crt/aws-c-common/source/logging.c +7 -2
  51. data/aws-crt-ffi/crt/aws-c-common/source/posix/system_info.c +8 -0
  52. data/aws-crt-ffi/crt/aws-c-common/source/ref_count.c +3 -1
  53. data/aws-crt-ffi/crt/aws-c-common/source/windows/file.c +47 -0
  54. data/aws-crt-ffi/crt/aws-c-common/source/windows/system_info.c +2 -1
  55. data/aws-crt-ffi/crt/aws-c-common/tests/CMakeLists.txt +5 -0
  56. data/aws-crt-ffi/crt/aws-c-common/tests/byte_buf_test.c +69 -0
  57. data/aws-crt-ffi/crt/aws-c-common/tests/json_test.c +134 -0
  58. data/aws-crt-ffi/crt/aws-c-common/tests/memtrace_test.c +6 -2
  59. data/aws-crt-ffi/crt/aws-c-event-stream/README.md +18 -35
  60. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream.h +21 -2
  61. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_client.h +14 -2
  62. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/event_stream_rpc_server.h +13 -0
  63. data/aws-crt-ffi/crt/aws-c-event-stream/include/aws/event-stream/private/event_stream_rpc_priv.h +7 -7
  64. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream.c +257 -141
  65. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_channel_handler.c +1 -1
  66. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_client.c +31 -8
  67. data/aws-crt-ffi/crt/aws-c-event-stream/source/event_stream_rpc_server.c +63 -10
  68. data/aws-crt-ffi/crt/aws-c-event-stream/tests/CMakeLists.txt +2 -0
  69. data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_client_connection_test.c +157 -106
  70. data/aws-crt-ffi/crt/aws-c-event-stream/tests/event_stream_rpc_server_connection_test.c +168 -1
  71. data/aws-crt-ffi/crt/aws-c-event-stream/tests/message_deserializer_test.c +4 -2
  72. data/aws-crt-ffi/crt/aws-c-http/CMakeLists.txt +1 -0
  73. data/aws-crt-ffi/crt/aws-c-http/README.md +8 -0
  74. data/aws-crt-ffi/crt/aws-c-http/bin/elasticurl/main.c +1 -1
  75. data/aws-crt-ffi/crt/aws-c-http/builder.json +4 -3
  76. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection.h +8 -1
  77. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/connection_manager.h +45 -1
  78. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/http2_stream_manager.h +63 -12
  79. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/connection_impl.h +2 -1
  80. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_connection.h +20 -2
  81. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_frames.h +1 -0
  82. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/h2_stream.h +42 -13
  83. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http2_stream_manager_impl.h +17 -0
  84. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/http_impl.h +3 -0
  85. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/random_access_set.h +10 -3
  86. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/private/request_response_impl.h +3 -17
  87. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/request_response.h +108 -4
  88. data/aws-crt-ffi/crt/aws-c-http/include/aws/http/statistics.h +22 -0
  89. data/aws-crt-ffi/crt/aws-c-http/source/connection.c +8 -3
  90. data/aws-crt-ffi/crt/aws-c-http/source/connection_manager.c +22 -3
  91. data/aws-crt-ffi/crt/aws-c-http/source/connection_monitor.c +32 -14
  92. data/aws-crt-ffi/crt/aws-c-http/source/h1_connection.c +14 -0
  93. data/aws-crt-ffi/crt/aws-c-http/source/h1_encoder.c +7 -4
  94. data/aws-crt-ffi/crt/aws-c-http/source/h2_connection.c +161 -45
  95. data/aws-crt-ffi/crt/aws-c-http/source/h2_decoder.c +37 -8
  96. data/aws-crt-ffi/crt/aws-c-http/source/h2_frames.c +13 -1
  97. data/aws-crt-ffi/crt/aws-c-http/source/h2_stream.c +345 -87
  98. data/aws-crt-ffi/crt/aws-c-http/source/hpack.c +3 -0
  99. data/aws-crt-ffi/crt/aws-c-http/source/http.c +3 -0
  100. data/aws-crt-ffi/crt/aws-c-http/source/http2_stream_manager.c +266 -39
  101. data/aws-crt-ffi/crt/aws-c-http/source/random_access_set.c +9 -3
  102. data/aws-crt-ffi/crt/aws-c-http/source/request_response.c +80 -20
  103. data/aws-crt-ffi/crt/aws-c-http/source/statistics.c +11 -0
  104. data/aws-crt-ffi/crt/aws-c-http/tests/CMakeLists.txt +28 -1
  105. data/aws-crt-ffi/crt/aws-c-http/tests/fuzz/fuzz_h2_decoder_correct.c +5 -3
  106. data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.c +133 -29
  107. data/aws-crt-ffi/crt/aws-c-http/tests/h2_test_helper.h +6 -0
  108. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/README.md +40 -0
  109. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/non_tls_server.py +56 -0
  110. data/aws-crt-ffi/crt/aws-c-http/tests/py_localhost/server.py +329 -0
  111. data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_manager.c +1 -1
  112. data/aws-crt-ffi/crt/aws-c-http/tests/test_connection_monitor.c +2 -2
  113. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_client.c +47 -34
  114. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_encoder.c +4 -4
  115. data/aws-crt-ffi/crt/aws-c-http/tests/test_h1_server.c +15 -12
  116. data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_client.c +582 -25
  117. data/aws-crt-ffi/crt/aws-c-http/tests/test_h2_encoder.c +3 -3
  118. data/aws-crt-ffi/crt/aws-c-http/tests/test_localhost_integ.c +530 -0
  119. data/aws-crt-ffi/crt/aws-c-http/tests/test_stream_manager.c +459 -67
  120. data/aws-crt-ffi/crt/aws-c-io/CMakeLists.txt +4 -0
  121. data/aws-crt-ffi/crt/aws-c-io/builder.json +3 -2
  122. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/channel.h +21 -0
  123. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/io.h +3 -0
  124. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/socket.h +6 -0
  125. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/stream.h +35 -5
  126. data/aws-crt-ffi/crt/aws-c-io/include/aws/io/tls_channel_handler.h +211 -15
  127. data/aws-crt-ffi/crt/aws-c-io/source/channel.c +56 -30
  128. data/aws-crt-ffi/crt/aws-c-io/source/darwin/secure_transport_tls_channel_handler.c +0 -24
  129. data/aws-crt-ffi/crt/aws-c-io/source/io.c +9 -0
  130. data/aws-crt-ffi/crt/aws-c-io/source/{pkcs11.c → pkcs11_lib.c} +162 -22
  131. data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_private.h +18 -20
  132. data/aws-crt-ffi/crt/aws-c-io/source/pkcs11_tls_op_handler.c +221 -0
  133. data/aws-crt-ffi/crt/aws-c-io/source/posix/socket.c +135 -81
  134. data/aws-crt-ffi/crt/aws-c-io/source/retry_strategy.c +12 -8
  135. data/aws-crt-ffi/crt/aws-c-io/source/s2n/s2n_tls_channel_handler.c +252 -215
  136. data/aws-crt-ffi/crt/aws-c-io/source/stream.c +65 -82
  137. data/aws-crt-ffi/crt/aws-c-io/source/tls_channel_handler.c +188 -57
  138. data/aws-crt-ffi/crt/aws-c-io/source/windows/iocp/socket.c +271 -256
  139. data/aws-crt-ffi/crt/aws-c-io/tests/CMakeLists.txt +21 -12
  140. data/aws-crt-ffi/crt/aws-c-io/tests/channel_test.c +32 -4
  141. data/aws-crt-ffi/crt/aws-c-io/tests/io_lib_test.c +37 -0
  142. data/aws-crt-ffi/crt/aws-c-io/tests/pkcs11_test.c +412 -93
  143. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.crt +15 -0
  144. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.key +5 -0
  145. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p12 +0 -0
  146. data/aws-crt-ffi/crt/aws-c-io/tests/resources/ec_unittests.p8 +5 -0
  147. data/aws-crt-ffi/crt/aws-c-io/tests/resources/generateCerts.sh +24 -15
  148. data/aws-crt-ffi/crt/aws-c-io/tests/socket_test.c +72 -1
  149. data/aws-crt-ffi/crt/s2n/CMakeLists.txt +6 -1
  150. data/aws-crt-ffi/crt/s2n/bindings/rust/Cargo.toml +1 -0
  151. data/aws-crt-ffi/crt/s2n/bindings/rust/generate/src/main.rs +105 -82
  152. data/aws-crt-ffi/crt/s2n/bindings/rust/generate.sh +1 -0
  153. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/Cargo.toml +2 -2
  154. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls/src/raw/config.rs +1 -1
  155. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/Cargo.toml +1 -1
  156. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/build.rs +84 -30
  157. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-sys/src/lib.rs +4 -0
  158. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/Cargo.toml +21 -0
  159. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/cert.pem +14 -0
  160. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/certs/key.pem +8 -0
  161. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/client.rs +45 -0
  162. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/examples/server.rs +60 -0
  163. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/src/lib.rs +150 -0
  164. data/aws-crt-ffi/crt/s2n/bindings/rust/s2n-tls-tokio/tests/handshake.rs +51 -0
  165. data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.c +98 -77
  166. data/aws-crt-ffi/crt/s2n/crypto/s2n_drbg.h +10 -7
  167. data/aws-crt-ffi/crt/s2n/crypto/s2n_openssl.h +2 -0
  168. data/aws-crt-ffi/crt/s2n/error/s2n_errno.c +1 -1
  169. data/aws-crt-ffi/crt/s2n/error/s2n_errno.h +1 -0
  170. data/aws-crt-ffi/crt/s2n/s2n.mk +7 -0
  171. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/repository.py +233 -0
  172. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup-proof.py +8 -7
  173. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/setup.py +17 -18
  174. data/aws-crt-ffi/crt/s2n/tests/cbmc/templates/scripts/util.py +41 -23
  175. data/aws-crt-ffi/crt/s2n/tests/fuzz/LD_PRELOAD/global_overrides.c +3 -3
  176. data/aws-crt-ffi/crt/s2n/tests/integration/s2n_client_endpoint_handshake_test.py +2 -2
  177. data/aws-crt-ffi/crt/s2n/tests/integrationv2/Makefile +13 -42
  178. data/aws-crt-ffi/crt/s2n/tests/integrationv2/README.md +6 -1
  179. data/aws-crt-ffi/crt/s2n/tests/integrationv2/common.py +118 -53
  180. data/aws-crt-ffi/crt/s2n/tests/integrationv2/configuration.py +108 -88
  181. data/aws-crt-ffi/crt/s2n/tests/integrationv2/conftest.py +6 -3
  182. data/aws-crt-ffi/crt/s2n/tests/integrationv2/constants.py +6 -4
  183. data/aws-crt-ffi/crt/s2n/tests/integrationv2/fixtures.py +21 -12
  184. data/aws-crt-ffi/crt/s2n/tests/integrationv2/global_flags.py +1 -0
  185. data/aws-crt-ffi/crt/s2n/tests/integrationv2/processes.py +62 -19
  186. data/aws-crt-ffi/crt/s2n/tests/integrationv2/providers.py +304 -48
  187. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_client_authentication.py +20 -11
  188. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_cross_compatibility.py +41 -17
  189. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_dynamic_record_sizes.py +6 -3
  190. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_early_data.py +105 -48
  191. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_external_psk.py +160 -76
  192. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_fragmentation.py +59 -26
  193. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_happy_path.py +42 -28
  194. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_hello_retry_requests.py +33 -13
  195. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_key_update.py +29 -11
  196. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_ocsp.py +138 -0
  197. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_pq_handshake.py +103 -36
  198. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_session_resumption.py +52 -25
  199. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_signature_algorithms.py +47 -21
  200. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sni_match.py +13 -9
  201. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_sslyze.py +88 -17
  202. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_version_negotiation.py +71 -22
  203. data/aws-crt-ffi/crt/s2n/tests/integrationv2/test_well_known_endpoints.py +4 -3
  204. data/aws-crt-ffi/crt/s2n/tests/integrationv2/tox.ini +1 -0
  205. data/aws-crt-ffi/crt/s2n/tests/integrationv2/utils.py +50 -15
  206. data/aws-crt-ffi/crt/s2n/tests/litani/CHANGELOG +131 -0
  207. data/aws-crt-ffi/crt/s2n/tests/litani/CONTRIBUTING.md +16 -0
  208. data/aws-crt-ffi/crt/s2n/tests/litani/README.md +36 -14
  209. data/aws-crt-ffi/crt/s2n/tests/litani/THIRD-PARTY +205 -41
  210. data/aws-crt-ffi/crt/s2n/tests/litani/doc/bin/build-html-doc +7 -7
  211. data/aws-crt-ffi/crt/s2n/tests/litani/doc/configure +27 -23
  212. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-add-job.scdoc +7 -0
  213. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-dump-run.scdoc +7 -5
  214. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani-transform-jobs.scdoc +248 -0
  215. data/aws-crt-ffi/crt/s2n/tests/litani/doc/src/man/litani.scdoc +2 -2
  216. data/aws-crt-ffi/crt/s2n/tests/litani/doc/templates/index.jinja.html +4 -0
  217. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/README +12 -0
  218. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/original-run.sh +52 -0
  219. data/aws-crt-ffi/crt/s2n/tests/litani/examples/add-root-node/run-all.py +71 -0
  220. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/README +13 -0
  221. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-1.sh +34 -0
  222. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-2.sh +35 -0
  223. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-3.sh +34 -0
  224. data/aws-crt-ffi/crt/s2n/tests/litani/examples/no-standalone-transform/run-all.py +60 -0
  225. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/README.md +10 -0
  226. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/assumptions.html +42 -0
  227. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/file.dat +7 -0
  228. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/histogram.dat +7 -0
  229. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-1.sh +41 -0
  230. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-2.sh +47 -0
  231. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-3.sh +41 -0
  232. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/run-all.py +34 -0
  233. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib-table.py +40 -0
  234. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.plt +5 -0
  235. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/fib.py +32 -0
  236. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin-output.py +40 -0
  237. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.plt +5 -0
  238. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/scripts/sin.py +30 -0
  239. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/fib-table.jinja.html +45 -0
  240. data/aws-crt-ffi/crt/s2n/tests/litani/examples/rich-output/templates/sin-output.jinja.html +30 -0
  241. data/aws-crt-ffi/crt/s2n/tests/litani/lib/add_job.py +55 -0
  242. data/aws-crt-ffi/crt/s2n/tests/litani/lib/graph.py +2 -2
  243. data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani.py +6 -1
  244. data/aws-crt-ffi/crt/s2n/tests/litani/lib/litani_report.py +18 -21
  245. data/aws-crt-ffi/crt/s2n/tests/litani/lib/ninja.py +2 -0
  246. data/aws-crt-ffi/crt/s2n/tests/litani/lib/run_printer.py +26 -7
  247. data/aws-crt-ffi/crt/s2n/tests/litani/lib/transform_jobs.py +84 -0
  248. data/aws-crt-ffi/crt/s2n/tests/litani/litani +28 -33
  249. data/aws-crt-ffi/crt/s2n/tests/litani/script/release +220 -0
  250. data/aws-crt-ffi/crt/s2n/tests/litani/templates/dashboard.jinja.html +78 -15
  251. data/aws-crt-ffi/crt/s2n/tests/litani/templates/pipeline.jinja.html +21 -5
  252. data/aws-crt-ffi/crt/s2n/tests/litani/test/README +15 -0
  253. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/run +56 -33
  254. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/custom_stages.py +1 -0
  255. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/cwd.py +1 -0
  256. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/dump_run.py +1 -0
  257. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/graph_line_break.py +1 -0
  258. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/html_node.py +1 -0
  259. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/job_id_env.py +1 -0
  260. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/multiproc_dump_run.py +1 -0
  261. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize.py +1 -0
  262. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_pool_serialize_graph.py +1 -0
  263. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out.py +1 -0
  264. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ignored.py +1 -0
  265. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/no_timed_out_timeout_ok.py +1 -0
  266. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pipeline_order.py +53 -0
  267. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize.py +1 -0
  268. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/pool_serialize_graph.py +1 -0
  269. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/single_pool.py +1 -0
  270. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out.py +1 -0
  271. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess.py +1 -0
  272. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_multi_shell.py +1 -0
  273. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_subprocess_shell.py +1 -0
  274. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ignored.py +1 -0
  275. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/timed_out_timeout_ok.py +1 -0
  276. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_delete_job.py +54 -0
  277. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_modify_job.py +46 -0
  278. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/transform_no_change_job.py +44 -0
  279. data/aws-crt-ffi/crt/s2n/tests/litani/test/e2e/tests/zero_pool.py +1 -0
  280. data/aws-crt-ffi/crt/s2n/tests/litani/test/run +82 -12
  281. data/aws-crt-ffi/crt/s2n/tests/s2n_test.h +58 -33
  282. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_key_schedule_testlib.c +18 -6
  283. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_pq_kat_test_utils.c +4 -4
  284. data/aws-crt-ffi/crt/s2n/tests/testlib/s2n_testlib.h +2 -0
  285. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_client_hello_retry_test.c +66 -2
  286. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_connection_test.c +1 -1
  287. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_drbg_test.c +34 -14
  288. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_fork_generation_number_test.c +28 -5
  289. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_mem_usage_test.c +6 -0
  290. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_override_openssl_random_test.c +1 -1
  291. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_random_test.c +60 -41
  292. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_self_talk_broken_pipe_test.c +2 -2
  293. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_handshake_early_data_test.c +3 -1
  294. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_hybrid_shared_secret_test.c +9 -1
  295. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_rfc8448_test.c +31 -130
  296. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_key_schedule_test.c +2 -4
  297. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_pq_handshake_test.c +11 -6
  298. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_rfc8448_test.c +19 -21
  299. data/aws-crt-ffi/crt/s2n/tests/unit/s2n_tls13_secrets_test.c +109 -60
  300. data/aws-crt-ffi/crt/s2n/tls/s2n_config.c +1 -0
  301. data/aws-crt-ffi/crt/s2n/tls/s2n_config.h +1 -1
  302. data/aws-crt-ffi/crt/s2n/tls/s2n_connection.c +29 -24
  303. data/aws-crt-ffi/crt/s2n/tls/s2n_connection.h +5 -5
  304. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_hashes.h +1 -7
  305. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_io.c +2 -0
  306. data/aws-crt-ffi/crt/s2n/tls/s2n_handshake_transcript.c +0 -44
  307. data/aws-crt-ffi/crt/s2n/tls/s2n_internal.h +0 -1
  308. data/aws-crt-ffi/crt/s2n/tls/s2n_quic_support.h +1 -1
  309. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_key_schedule.c +1 -2
  310. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.c +84 -44
  311. data/aws-crt-ffi/crt/s2n/tls/s2n_tls13_secrets.h +3 -9
  312. data/aws-crt-ffi/crt/s2n/utils/s2n_blob.h +15 -8
  313. data/aws-crt-ffi/crt/s2n/utils/s2n_fork_detection.c +2 -6
  314. data/aws-crt-ffi/crt/s2n/utils/s2n_random.c +9 -9
  315. data/aws-crt-ffi/src/input_stream.c +32 -15
  316. data/ext/compile.rb +13 -5
  317. data/lib/aws-crt/platforms.rb +14 -5
  318. data/lib/aws-crt/string_blob.rb +3 -3
  319. metadata +61 -7
  320. data/aws-crt-ffi/crt/aws-c-auth/source/external/cJSON.c +0 -2987
  321. data/aws-crt-ffi/crt/aws-c-auth/tests/external/cJSON.c +0 -2986
  322. data/aws-crt-ffi/crt/aws-c-io/tests/error_test.c +0 -20
@@ -0,0 +1,3113 @@
1
+ /*
2
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+ */
22
+
23
+ /* cJSON */
24
+ /* JSON parser in C. */
25
+
26
+ /* disable warnings about old C89 functions in MSVC */
27
+ #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
+ #define _CRT_SECURE_NO_DEPRECATE
29
+ #endif
30
+
31
+ #ifdef __GNUC__
32
+ #pragma GCC visibility push(default)
33
+ #endif
34
+ #if defined(_MSC_VER)
35
+ #pragma warning (push)
36
+ /* disable warning about single line comments in system headers */
37
+ #pragma warning (disable : 4001)
38
+ #endif
39
+
40
+ #include <string.h>
41
+ #include <stdio.h>
42
+ #include <math.h>
43
+ #include <stdlib.h>
44
+ #include <limits.h>
45
+ #include <ctype.h>
46
+ #include <float.h>
47
+
48
+ #ifdef ENABLE_LOCALES
49
+ #include <locale.h>
50
+ #endif
51
+
52
+ #if defined(_MSC_VER)
53
+ #pragma warning (pop)
54
+ #endif
55
+ #ifdef __GNUC__
56
+ #pragma GCC visibility pop
57
+ #endif
58
+
59
+ #include <aws/common/external/cJSON.h>
60
+
61
+ /* define our own boolean type */
62
+ #ifdef true
63
+ #undef true
64
+ #endif
65
+ #define true ((cJSON_bool)1)
66
+
67
+ #ifdef false
68
+ #undef false
69
+ #endif
70
+ #define false ((cJSON_bool)0)
71
+
72
+ /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73
+ #ifndef isinf
74
+ #define isinf(d) (isnan((d - d)) && !isnan(d))
75
+ #endif
76
+ #ifndef isnan
77
+ #define isnan(d) (d != d)
78
+ #endif
79
+
80
+ #ifndef NAN
81
+ #ifdef _WIN32
82
+ #define NAN sqrt(-1.0)
83
+ #else
84
+ #define NAN 0.0/0.0
85
+ #endif
86
+ #endif
87
+
88
+ typedef struct {
89
+ const unsigned char *json;
90
+ size_t position;
91
+ } error;
92
+ static error global_error = { NULL, 0 };
93
+
94
+ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
95
+ {
96
+ return (const char*) (global_error.json + global_error.position);
97
+ }
98
+
99
+ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
100
+ {
101
+ if (!cJSON_IsString(item))
102
+ {
103
+ return NULL;
104
+ }
105
+
106
+ return item->valuestring;
107
+ }
108
+
109
+ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
110
+ {
111
+ if (!cJSON_IsNumber(item))
112
+ {
113
+ return (double) NAN;
114
+ }
115
+
116
+ return item->valuedouble;
117
+ }
118
+
119
+ /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120
+ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
121
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
+ #endif
123
+
124
+ CJSON_PUBLIC(const char*) cJSON_Version(void)
125
+ {
126
+ static char version[15];
127
+ snprintf(version, sizeof(version) / sizeof(char), "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
128
+
129
+ return version;
130
+ }
131
+
132
+ /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133
+ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
134
+ {
135
+ if ((string1 == NULL) || (string2 == NULL))
136
+ {
137
+ return 1;
138
+ }
139
+
140
+ if (string1 == string2)
141
+ {
142
+ return 0;
143
+ }
144
+
145
+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
146
+ {
147
+ if (*string1 == '\0')
148
+ {
149
+ return 0;
150
+ }
151
+ }
152
+
153
+ return tolower(*string1) - tolower(*string2);
154
+ }
155
+
156
+ typedef struct internal_hooks
157
+ {
158
+ void *(CJSON_CDECL *allocate)(size_t size);
159
+ void (CJSON_CDECL *deallocate)(void *pointer);
160
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
161
+ } internal_hooks;
162
+
163
+ #if defined(_MSC_VER)
164
+ /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165
+ static void * CJSON_CDECL internal_malloc(size_t size)
166
+ {
167
+ return malloc(size);
168
+ }
169
+ static void CJSON_CDECL internal_free(void *pointer)
170
+ {
171
+ free(pointer);
172
+ }
173
+ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
174
+ {
175
+ return realloc(pointer, size);
176
+ }
177
+ #else
178
+ #define internal_malloc malloc
179
+ #define internal_free free
180
+ #define internal_realloc realloc
181
+ #endif
182
+
183
+ /* strlen of character literals resolved at compile time */
184
+ #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
185
+
186
+ static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; // NOLINT
187
+
188
+ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) // NOLINT
189
+ {
190
+ size_t length = 0;
191
+ unsigned char *copy = NULL;
192
+
193
+ if (string == NULL)
194
+ {
195
+ return NULL;
196
+ }
197
+
198
+ length = strlen((const char*)string) + sizeof("");
199
+ copy = (unsigned char*)hooks->allocate(length);
200
+ if (copy == NULL)
201
+ {
202
+ return NULL;
203
+ }
204
+ memcpy(copy, string, length);
205
+
206
+ return copy;
207
+ }
208
+
209
+ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) // NOLINT
210
+ {
211
+ if (hooks == NULL)
212
+ {
213
+ /* Reset hooks */
214
+ global_hooks.allocate = malloc;
215
+ global_hooks.deallocate = free;
216
+ global_hooks.reallocate = realloc;
217
+ return;
218
+ }
219
+
220
+ global_hooks.allocate = malloc;
221
+ if (hooks->malloc_fn != NULL)
222
+ {
223
+ global_hooks.allocate = hooks->malloc_fn;
224
+ }
225
+
226
+ global_hooks.deallocate = free;
227
+ if (hooks->free_fn != NULL)
228
+ {
229
+ global_hooks.deallocate = hooks->free_fn;
230
+ }
231
+
232
+ /* use realloc only if both free and malloc are used */
233
+ global_hooks.reallocate = NULL;
234
+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
235
+ {
236
+ global_hooks.reallocate = realloc;
237
+ }
238
+ }
239
+
240
+ /* Internal constructor. */
241
+ static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
242
+ {
243
+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
+ if (node)
245
+ {
246
+ memset(node, '\0', sizeof(cJSON));
247
+ }
248
+
249
+ return node;
250
+ }
251
+
252
+ /* Delete a cJSON structure. */
253
+ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
+ {
255
+ cJSON *next = NULL;
256
+ while (item != NULL)
257
+ {
258
+ next = item->next;
259
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
+ {
261
+ cJSON_Delete(item->child);
262
+ }
263
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
+ {
265
+ global_hooks.deallocate(item->valuestring);
266
+ }
267
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
268
+ {
269
+ global_hooks.deallocate(item->string);
270
+ }
271
+ global_hooks.deallocate(item);
272
+ item = next;
273
+ }
274
+ }
275
+
276
+ /* get the decimal point character of the current locale */
277
+ static unsigned char get_decimal_point(void)
278
+ {
279
+ #ifdef ENABLE_LOCALES
280
+ struct lconv *lconv = localeconv();
281
+ return (unsigned char) lconv->decimal_point[0];
282
+ #else
283
+ return '.';
284
+ #endif
285
+ }
286
+
287
+ typedef struct
288
+ {
289
+ const unsigned char *content;
290
+ size_t length;
291
+ size_t offset;
292
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
293
+ internal_hooks hooks;
294
+ } parse_buffer;
295
+
296
+ /* check if the given size is left to read in a given parse buffer (starting with 1) */
297
+ #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) // NOLINT
298
+ /* check if the buffer can be accessed at the given index (starting with 0) */
299
+ #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) // NOLINT
300
+ #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
301
+ /* get a pointer to the buffer at the position */
302
+ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
303
+
304
+ /* Parse the input text to generate a number, and populate the result into item. */
305
+ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) // NOLINT
306
+ {
307
+ double number = 0;
308
+ unsigned char *after_end = NULL;
309
+ unsigned char number_c_string[64];
310
+ unsigned char decimal_point = get_decimal_point(); // NOLINT
311
+ size_t i = 0;
312
+
313
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
314
+ {
315
+ return false; // NOLINT
316
+ }
317
+
318
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
319
+ * of the current locale (for strtod)
320
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
321
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
322
+ {
323
+ switch (buffer_at_offset(input_buffer)[i])
324
+ {
325
+ case '0':
326
+ case '1':
327
+ case '2':
328
+ case '3':
329
+ case '4':
330
+ case '5':
331
+ case '6':
332
+ case '7':
333
+ case '8':
334
+ case '9':
335
+ case '+':
336
+ case '-':
337
+ case 'e':
338
+ case 'E':
339
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
340
+ break;
341
+
342
+ case '.':
343
+ number_c_string[i] = decimal_point;
344
+ break;
345
+
346
+ default:
347
+ goto loop_end;
348
+ }
349
+ }
350
+ loop_end:
351
+ number_c_string[i] = '\0';
352
+
353
+ number = strtod((const char*)number_c_string, (char**)&after_end);
354
+ if (number_c_string == after_end)
355
+ {
356
+ return false; /* parse_error */ // NOLINT
357
+ }
358
+
359
+ item->valuedouble = number;
360
+
361
+ /* use saturation in case of overflow */
362
+ if (number >= INT_MAX)
363
+ { // NOLINT
364
+ item->valueint = INT_MAX;
365
+ }
366
+ else if (number <= (double)INT_MIN)
367
+ {
368
+ item->valueint = INT_MIN;
369
+ }
370
+ else
371
+ {
372
+ item->valueint = (int)number;
373
+ }
374
+
375
+ item->type = cJSON_Number; // NOLINT
376
+
377
+ input_buffer->offset += (size_t)(after_end - number_c_string);
378
+ return true; // NOLINT
379
+ }
380
+
381
+ /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
382
+ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) // NOLINT
383
+ {
384
+ if (number >= INT_MAX)
385
+ {
386
+ object->valueint = INT_MAX;
387
+ }
388
+ else if (number <= (double)INT_MIN)
389
+ {
390
+ object->valueint = INT_MIN;
391
+ }
392
+ else
393
+ {
394
+ object->valueint = (int)number;
395
+ }
396
+
397
+ return object->valuedouble = number;
398
+ }
399
+
400
+ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
401
+ {
402
+ char *copy = NULL;
403
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
404
+ if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
405
+ {
406
+ return NULL;
407
+ }
408
+ if (strlen(valuestring) <= strlen(object->valuestring))
409
+ {
410
+ size_t value_length = strlen(valuestring) + sizeof("");
411
+ memcpy(object->valuestring, valuestring, value_length);
412
+ return object->valuestring;
413
+ }
414
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
415
+ if (copy == NULL)
416
+ {
417
+ return NULL;
418
+ }
419
+ if (object->valuestring != NULL)
420
+ {
421
+ cJSON_free(object->valuestring);
422
+ }
423
+ object->valuestring = copy;
424
+
425
+ return copy;
426
+ }
427
+
428
+ typedef struct
429
+ {
430
+ unsigned char *buffer;
431
+ size_t length;
432
+ size_t offset;
433
+ size_t depth; /* current nesting depth (for formatted printing) */
434
+ cJSON_bool noalloc;
435
+ cJSON_bool format; /* is this print a formatted print */
436
+ internal_hooks hooks;
437
+ } printbuffer;
438
+
439
+ /* realloc printbuffer if necessary to have at least "needed" bytes more */
440
+ static unsigned char* ensure(printbuffer * const p, size_t needed) // NOLINT
441
+ {
442
+ unsigned char *newbuffer = NULL;
443
+ size_t newsize = 0;
444
+
445
+ if ((p == NULL) || (p->buffer == NULL))
446
+ {
447
+ return NULL;
448
+ }
449
+
450
+ if ((p->length > 0) && (p->offset >= p->length))
451
+ {
452
+ /* make sure that offset is valid */
453
+ return NULL;
454
+ }
455
+
456
+ if (needed > INT_MAX)
457
+ {
458
+ /* sizes bigger than INT_MAX are currently not supported */
459
+ return NULL;
460
+ }
461
+
462
+ needed += p->offset + 1;
463
+ if (needed <= p->length)
464
+ {
465
+ return p->buffer + p->offset;
466
+ }
467
+
468
+ if (p->noalloc) {
469
+ return NULL;
470
+ }
471
+
472
+ /* calculate new buffer size */
473
+ if (needed > (INT_MAX / 2))
474
+ {
475
+ /* overflow of int, use INT_MAX if possible */
476
+ if (needed <= INT_MAX)
477
+ {
478
+ newsize = INT_MAX;
479
+ }
480
+ else
481
+ {
482
+ return NULL;
483
+ }
484
+ }
485
+ else
486
+ {
487
+ newsize = needed * 2;
488
+ }
489
+
490
+ if (p->hooks.reallocate != NULL)
491
+ {
492
+ /* reallocate with realloc if available */
493
+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
494
+ if (newbuffer == NULL)
495
+ {
496
+ p->hooks.deallocate(p->buffer);
497
+ p->length = 0;
498
+ p->buffer = NULL;
499
+
500
+ return NULL;
501
+ }
502
+ }
503
+ else
504
+ {
505
+ /* otherwise reallocate manually */
506
+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
507
+ if (!newbuffer)
508
+ {
509
+ p->hooks.deallocate(p->buffer);
510
+ p->length = 0;
511
+ p->buffer = NULL;
512
+
513
+ return NULL;
514
+ }
515
+
516
+ memcpy(newbuffer, p->buffer, p->offset + 1);
517
+ p->hooks.deallocate(p->buffer);
518
+ }
519
+ p->length = newsize;
520
+ p->buffer = newbuffer;
521
+
522
+ return newbuffer + p->offset;
523
+ }
524
+
525
+ /* calculate the new length of the string in a printbuffer and update the offset */
526
+ static void update_offset(printbuffer * const buffer) // NOLINT
527
+ {
528
+ const unsigned char *buffer_pointer = NULL;
529
+ if ((buffer == NULL) || (buffer->buffer == NULL))
530
+ {
531
+ return;
532
+ }
533
+ buffer_pointer = buffer->buffer + buffer->offset;
534
+
535
+ buffer->offset += strlen((const char*)buffer_pointer);
536
+ }
537
+
538
+ /* securely comparison of floating-point variables */
539
+ static cJSON_bool compare_double(double a, double b) // NOLINT
540
+ {
541
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
542
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
543
+ }
544
+
545
+ /* Render the number nicely from the given item into a string. */
546
+ static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) // NOLINT
547
+ {
548
+ unsigned char *output_pointer = NULL;
549
+ double d = item->valuedouble;
550
+ int length = 0;
551
+ size_t i = 0;
552
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
553
+ unsigned char decimal_point = get_decimal_point(); // NOLINT
554
+ double test = 0.0;
555
+
556
+ if (output_buffer == NULL)
557
+ {
558
+ return false;
559
+ }
560
+
561
+ /* This checks for NaN and Infinity */
562
+ if (isnan(d) || isinf(d))
563
+ {
564
+ length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "null");
565
+ }
566
+ else
567
+ {
568
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
569
+ length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "%1.15g", d);
570
+
571
+ /* Check whether the original double can be recovered */
572
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
573
+ {
574
+ /* If not, print with 17 decimal places of precision */
575
+ length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "%1.17g", d);
576
+ }
577
+ }
578
+
579
+ /* sprintf failed or buffer overrun occurred */
580
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
581
+ {
582
+ return false;
583
+ }
584
+
585
+ /* reserve appropriate space in the output */
586
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
587
+ if (output_pointer == NULL)
588
+ {
589
+ return false;
590
+ }
591
+
592
+ /* copy the printed number to the output and replace locale
593
+ * dependent decimal point with '.' */
594
+ for (i = 0; i < ((size_t)length); i++)
595
+ {
596
+ if (number_buffer[i] == decimal_point)
597
+ {
598
+ output_pointer[i] = '.';
599
+ continue;
600
+ }
601
+
602
+ output_pointer[i] = number_buffer[i];
603
+ }
604
+ output_pointer[i] = '\0';
605
+
606
+ output_buffer->offset += (size_t)length;
607
+
608
+ return true;
609
+ }
610
+
611
+ /* parse 4 digit hexadecimal number */
612
+ static unsigned parse_hex4(const unsigned char * const input)
613
+ {
614
+ unsigned int h = 0;
615
+ size_t i = 0;
616
+
617
+ for (i = 0; i < 4; i++)
618
+ {
619
+ /* parse digit */
620
+ if ((input[i] >= '0') && (input[i] <= '9'))
621
+ {
622
+ h += (unsigned int) input[i] - '0';
623
+ }
624
+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
625
+ {
626
+ h += (unsigned int) 10 + input[i] - 'A';
627
+ }
628
+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
629
+ {
630
+ h += (unsigned int) 10 + input[i] - 'a';
631
+ }
632
+ else /* invalid */
633
+ {
634
+ return 0;
635
+ }
636
+
637
+ if (i < 3)
638
+ {
639
+ /* shift left to make place for the next nibble */
640
+ h = h << 4;
641
+ }
642
+ }
643
+
644
+ return h;
645
+ }
646
+
647
+ /* converts a UTF-16 literal to UTF-8
648
+ * A literal can be one or two sequences of the form \uXXXX */
649
+ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
650
+ {
651
+ long unsigned int codepoint = 0;
652
+ unsigned int first_code = 0;
653
+ const unsigned char *first_sequence = input_pointer;
654
+ unsigned char utf8_length = 0;
655
+ unsigned char utf8_position = 0;
656
+ unsigned char sequence_length = 0;
657
+ unsigned char first_byte_mark = 0;
658
+
659
+ if ((input_end - first_sequence) < 6)
660
+ {
661
+ /* input ends unexpectedly */
662
+ goto fail;
663
+ }
664
+
665
+ /* get the first utf16 sequence */
666
+ first_code = parse_hex4(first_sequence + 2);
667
+
668
+ /* check that the code is valid */
669
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
670
+ {
671
+ goto fail;
672
+ }
673
+
674
+ /* UTF16 surrogate pair */
675
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
676
+ {
677
+ const unsigned char *second_sequence = first_sequence + 6;
678
+ unsigned int second_code = 0;
679
+ sequence_length = 12; /* \uXXXX\uXXXX */
680
+
681
+ if ((input_end - second_sequence) < 6)
682
+ {
683
+ /* input ends unexpectedly */
684
+ goto fail;
685
+ }
686
+
687
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
688
+ {
689
+ /* missing second half of the surrogate pair */
690
+ goto fail;
691
+ }
692
+
693
+ /* get the second utf16 sequence */
694
+ second_code = parse_hex4(second_sequence + 2);
695
+ /* check that the code is valid */
696
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
697
+ {
698
+ /* invalid second half of the surrogate pair */
699
+ goto fail;
700
+ }
701
+
702
+
703
+ /* calculate the unicode codepoint from the surrogate pair */
704
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
705
+ }
706
+ else
707
+ {
708
+ sequence_length = 6; /* \uXXXX */
709
+ codepoint = first_code;
710
+ }
711
+
712
+ /* encode as UTF-8
713
+ * takes at maximum 4 bytes to encode:
714
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
715
+ if (codepoint < 0x80)
716
+ {
717
+ /* normal ascii, encoding 0xxxxxxx */
718
+ utf8_length = 1;
719
+ }
720
+ else if (codepoint < 0x800)
721
+ {
722
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
723
+ utf8_length = 2;
724
+ first_byte_mark = 0xC0; /* 11000000 */
725
+ }
726
+ else if (codepoint < 0x10000)
727
+ {
728
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
729
+ utf8_length = 3;
730
+ first_byte_mark = 0xE0; /* 11100000 */
731
+ }
732
+ else if (codepoint <= 0x10FFFF)
733
+ {
734
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
735
+ utf8_length = 4;
736
+ first_byte_mark = 0xF0; /* 11110000 */
737
+ }
738
+ else
739
+ {
740
+ /* invalid unicode codepoint */
741
+ goto fail;
742
+ }
743
+
744
+ /* encode as utf8 */
745
+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
746
+ {
747
+ /* 10xxxxxx */
748
+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
749
+ codepoint >>= 6;
750
+ }
751
+ /* encode first byte */
752
+ if (utf8_length > 1)
753
+ {
754
+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
755
+ }
756
+ else
757
+ {
758
+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
759
+ }
760
+
761
+ *output_pointer += utf8_length;
762
+
763
+ return sequence_length;
764
+
765
+ fail:
766
+ return 0;
767
+ }
768
+
769
+ /* Parse the input text into an unescaped cinput, and populate item. */
770
+ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) // NOLINT
771
+ {
772
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
773
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
774
+ unsigned char *output_pointer = NULL;
775
+ unsigned char *output = NULL;
776
+
777
+ /* not a string */
778
+ if (buffer_at_offset(input_buffer)[0] != '\"')
779
+ {
780
+ goto fail;
781
+ }
782
+
783
+ {
784
+ /* calculate approximate size of the output (overestimate) */
785
+ size_t allocation_length = 0;
786
+ size_t skipped_bytes = 0;
787
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
788
+ {
789
+ /* is escape sequence */
790
+ if (input_end[0] == '\\')
791
+ {
792
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
793
+ {
794
+ /* prevent buffer overflow when last input character is a backslash */
795
+ goto fail;
796
+ }
797
+ skipped_bytes++;
798
+ input_end++;
799
+ }
800
+ input_end++;
801
+ }
802
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
803
+ {
804
+ goto fail; /* string ended unexpectedly */
805
+ }
806
+
807
+ /* This is at most how much we need for the output */
808
+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
809
+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
810
+ if (output == NULL)
811
+ {
812
+ goto fail; /* allocation failure */
813
+ }
814
+ }
815
+
816
+ output_pointer = output;
817
+ /* loop through the string literal */
818
+ while (input_pointer < input_end)
819
+ {
820
+ if (*input_pointer != '\\')
821
+ {
822
+ *output_pointer++ = *input_pointer++;
823
+ }
824
+ /* escape sequence */
825
+ else
826
+ {
827
+ unsigned char sequence_length = 2;
828
+ if ((input_end - input_pointer) < 1)
829
+ {
830
+ goto fail;
831
+ }
832
+
833
+ switch (input_pointer[1])
834
+ {
835
+ case 'b':
836
+ *output_pointer++ = '\b';
837
+ break;
838
+ case 'f':
839
+ *output_pointer++ = '\f';
840
+ break;
841
+ case 'n':
842
+ *output_pointer++ = '\n';
843
+ break;
844
+ case 'r':
845
+ *output_pointer++ = '\r';
846
+ break;
847
+ case 't':
848
+ *output_pointer++ = '\t';
849
+ break;
850
+ case '\"':
851
+ case '\\':
852
+ case '/':
853
+ *output_pointer++ = input_pointer[1];
854
+ break;
855
+
856
+ /* UTF-16 literal */
857
+ case 'u':
858
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
859
+ if (sequence_length == 0)
860
+ {
861
+ /* failed to convert UTF16-literal to UTF-8 */
862
+ goto fail;
863
+ }
864
+ break;
865
+
866
+ default:
867
+ goto fail;
868
+ }
869
+ input_pointer += sequence_length;
870
+ }
871
+ }
872
+
873
+ /* zero terminate the output */
874
+ *output_pointer = '\0';
875
+
876
+ item->type = cJSON_String;
877
+ item->valuestring = (char*)output;
878
+
879
+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
880
+ input_buffer->offset++;
881
+
882
+ return true;
883
+
884
+ fail:
885
+ if (output != NULL)
886
+ {
887
+ input_buffer->hooks.deallocate(output);
888
+ }
889
+
890
+ if (input_pointer != NULL)
891
+ {
892
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
893
+ }
894
+
895
+ return false;
896
+ }
897
+
898
+ /* Render the cstring provided to an escaped version that can be printed. */
899
+ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) // NOLINT
900
+ {
901
+ const unsigned char *input_pointer = NULL;
902
+ unsigned char *output = NULL;
903
+ unsigned char *output_pointer = NULL;
904
+ size_t output_length = 0;
905
+ /* numbers of additional characters needed for escaping */
906
+ size_t escape_characters = 0;
907
+
908
+ if (output_buffer == NULL)
909
+ {
910
+ return false;
911
+ }
912
+
913
+ /* empty string */
914
+ if (input == NULL)
915
+ {
916
+ output = ensure(output_buffer, sizeof("\"\""));
917
+ if (output == NULL)
918
+ {
919
+ return false;
920
+ }
921
+ memcpy(output, "\"\"", 3); /* NOLINT */
922
+
923
+ return true;
924
+ }
925
+
926
+ /* set "flag" to 1 if something needs to be escaped */
927
+ for (input_pointer = input; *input_pointer; input_pointer++)
928
+ {
929
+ switch (*input_pointer)
930
+ {
931
+ case '\"':
932
+ case '\\':
933
+ case '\b':
934
+ case '\f':
935
+ case '\n':
936
+ case '\r':
937
+ case '\t':
938
+ /* one character escape sequence */
939
+ escape_characters++;
940
+ break;
941
+ default:
942
+ if (*input_pointer < 32)
943
+ {
944
+ /* UTF-16 escape sequence uXXXX */
945
+ escape_characters += 5;
946
+ }
947
+ break;
948
+ }
949
+ }
950
+ output_length = (size_t)(input_pointer - input) + escape_characters;
951
+
952
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
953
+ if (output == NULL)
954
+ {
955
+ return false;
956
+ }
957
+
958
+ /* no characters have to be escaped */
959
+ if (escape_characters == 0)
960
+ {
961
+ output[0] = '\"';
962
+ memcpy(output + 1, input, output_length);
963
+ output[output_length + 1] = '\"';
964
+ output[output_length + 2] = '\0';
965
+
966
+ return true;
967
+ }
968
+
969
+ output[0] = '\"';
970
+ output_pointer = output + 1;
971
+ /* copy the string */
972
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
973
+ {
974
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
975
+ {
976
+ /* normal character, copy */
977
+ *output_pointer = *input_pointer;
978
+ }
979
+ else
980
+ {
981
+ /* character needs to be escaped */
982
+ *output_pointer++ = '\\';
983
+ switch (*input_pointer)
984
+ {
985
+ case '\\':
986
+ *output_pointer = '\\';
987
+ break;
988
+ case '\"':
989
+ *output_pointer = '\"';
990
+ break;
991
+ case '\b':
992
+ *output_pointer = 'b';
993
+ break;
994
+ case '\f':
995
+ *output_pointer = 'f';
996
+ break;
997
+ case '\n':
998
+ *output_pointer = 'n';
999
+ break;
1000
+ case '\r':
1001
+ *output_pointer = 'r';
1002
+ break;
1003
+ case '\t':
1004
+ *output_pointer = 't';
1005
+ break;
1006
+ default:
1007
+ /* escape and print as unicode codepoint */
1008
+ snprintf((char*)output_pointer, 6 * sizeof(char), "u%04x", *input_pointer);
1009
+ output_pointer += 4;
1010
+ break;
1011
+ }
1012
+ }
1013
+ }
1014
+ output[output_length + 1] = '\"';
1015
+ output[output_length + 2] = '\0';
1016
+
1017
+ return true;
1018
+ }
1019
+
1020
+ /* Invoke print_string_ptr (which is useful) on an item. */
1021
+ static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1022
+ {
1023
+ return print_string_ptr((unsigned char*)item->valuestring, p);
1024
+ }
1025
+
1026
+ /* Predeclare these prototypes. */
1027
+ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1028
+ static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1029
+ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1030
+ static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1031
+ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1032
+ static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1033
+
1034
+ /* Utility to jump whitespace and cr/lf */
1035
+ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) // NOLINT
1036
+ {
1037
+ if ((buffer == NULL) || (buffer->content == NULL))
1038
+ {
1039
+ return NULL;
1040
+ }
1041
+
1042
+ if (cannot_access_at_index(buffer, 0))
1043
+ {
1044
+ return buffer;
1045
+ }
1046
+
1047
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1048
+ {
1049
+ buffer->offset++;
1050
+ }
1051
+
1052
+ if (buffer->offset == buffer->length)
1053
+ {
1054
+ buffer->offset--;
1055
+ }
1056
+
1057
+ return buffer;
1058
+ }
1059
+
1060
+ /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1061
+ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) // NOLINT
1062
+ {
1063
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1064
+ {
1065
+ return NULL;
1066
+ }
1067
+
1068
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1069
+ {
1070
+ buffer->offset += 3;
1071
+ }
1072
+
1073
+ return buffer;
1074
+ }
1075
+
1076
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1077
+ {
1078
+ size_t buffer_length;
1079
+
1080
+ if (NULL == value)
1081
+ {
1082
+ return NULL;
1083
+ }
1084
+
1085
+ /* Adding null character size due to require_null_terminated. */
1086
+ buffer_length = strlen(value) + sizeof("");
1087
+
1088
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1089
+ }
1090
+
1091
+ /* Parse an object - create a new root, and populate. */
1092
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1093
+ {
1094
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1095
+ cJSON *item = NULL;
1096
+
1097
+ /* reset error position */
1098
+ global_error.json = NULL;
1099
+ global_error.position = 0;
1100
+
1101
+ if (value == NULL || 0 == buffer_length)
1102
+ {
1103
+ goto fail;
1104
+ }
1105
+
1106
+ buffer.content = (const unsigned char*)value;
1107
+ buffer.length = buffer_length;
1108
+ buffer.offset = 0;
1109
+ buffer.hooks = global_hooks;
1110
+
1111
+ item = cJSON_New_Item(&global_hooks);
1112
+ if (item == NULL) /* memory fail */
1113
+ {
1114
+ goto fail;
1115
+ }
1116
+
1117
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1118
+ {
1119
+ /* parse failure. ep is set. */
1120
+ goto fail;
1121
+ }
1122
+
1123
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1124
+ if (require_null_terminated)
1125
+ {
1126
+ buffer_skip_whitespace(&buffer);
1127
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1128
+ {
1129
+ goto fail;
1130
+ }
1131
+ }
1132
+ if (return_parse_end)
1133
+ {
1134
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
1135
+ }
1136
+
1137
+ return item;
1138
+
1139
+ fail:
1140
+ if (item != NULL)
1141
+ {
1142
+ cJSON_Delete(item);
1143
+ }
1144
+
1145
+ if (value != NULL)
1146
+ {
1147
+ error local_error;
1148
+ local_error.json = (const unsigned char*)value;
1149
+ local_error.position = 0;
1150
+
1151
+ if (buffer.offset < buffer.length)
1152
+ {
1153
+ local_error.position = buffer.offset;
1154
+ }
1155
+ else if (buffer.length > 0)
1156
+ {
1157
+ local_error.position = buffer.length - 1;
1158
+ }
1159
+
1160
+ if (return_parse_end != NULL)
1161
+ {
1162
+ *return_parse_end = (const char*)local_error.json + local_error.position;
1163
+ }
1164
+
1165
+ global_error = local_error;
1166
+ }
1167
+
1168
+ return NULL;
1169
+ }
1170
+
1171
+ /* Default options for cJSON_Parse */
1172
+ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1173
+ {
1174
+ return cJSON_ParseWithOpts(value, 0, 0);
1175
+ }
1176
+
1177
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1178
+ {
1179
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1180
+ }
1181
+
1182
+ #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1183
+
1184
+ static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1185
+ {
1186
+ static const size_t default_buffer_size = 256;
1187
+ printbuffer buffer[1];
1188
+ unsigned char *printed = NULL;
1189
+
1190
+ memset(buffer, 0, sizeof(buffer));
1191
+
1192
+ /* create buffer */
1193
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1194
+ buffer->length = default_buffer_size;
1195
+ buffer->format = format;
1196
+ buffer->hooks = *hooks;
1197
+ if (buffer->buffer == NULL)
1198
+ {
1199
+ goto fail;
1200
+ }
1201
+
1202
+ /* print the value */
1203
+ if (!print_value(item, buffer))
1204
+ {
1205
+ goto fail;
1206
+ }
1207
+ update_offset(buffer);
1208
+
1209
+ /* check if reallocate is available */
1210
+ if (hooks->reallocate != NULL)
1211
+ {
1212
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1213
+ if (printed == NULL) {
1214
+ goto fail;
1215
+ }
1216
+ buffer->buffer = NULL;
1217
+ }
1218
+ else /* otherwise copy the JSON over to a new buffer */
1219
+ {
1220
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1221
+ if (printed == NULL)
1222
+ {
1223
+ goto fail;
1224
+ }
1225
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1226
+ printed[buffer->offset] = '\0'; /* just to be sure */
1227
+
1228
+ /* free the buffer */
1229
+ hooks->deallocate(buffer->buffer);
1230
+ }
1231
+
1232
+ return printed;
1233
+
1234
+ fail:
1235
+ if (buffer->buffer != NULL)
1236
+ {
1237
+ hooks->deallocate(buffer->buffer);
1238
+ }
1239
+
1240
+ if (printed != NULL)
1241
+ {
1242
+ hooks->deallocate(printed);
1243
+ }
1244
+
1245
+ return NULL;
1246
+ }
1247
+
1248
+ /* Render a cJSON item/entity/structure to text. */
1249
+ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1250
+ {
1251
+ return (char*)print(item, true, &global_hooks);
1252
+ }
1253
+
1254
+ CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1255
+ {
1256
+ return (char*)print(item, false, &global_hooks);
1257
+ }
1258
+
1259
+ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1260
+ {
1261
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1262
+
1263
+ if (prebuffer < 0)
1264
+ {
1265
+ return NULL;
1266
+ }
1267
+
1268
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1269
+ if (!p.buffer)
1270
+ {
1271
+ return NULL;
1272
+ }
1273
+
1274
+ p.length = (size_t)prebuffer;
1275
+ p.offset = 0;
1276
+ p.noalloc = false;
1277
+ p.format = fmt;
1278
+ p.hooks = global_hooks;
1279
+
1280
+ if (!print_value(item, &p))
1281
+ {
1282
+ global_hooks.deallocate(p.buffer);
1283
+ return NULL;
1284
+ }
1285
+
1286
+ return (char*)p.buffer;
1287
+ }
1288
+
1289
+ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1290
+ {
1291
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1292
+
1293
+ if ((length < 0) || (buffer == NULL))
1294
+ {
1295
+ return false;
1296
+ }
1297
+
1298
+ p.buffer = (unsigned char*)buffer;
1299
+ p.length = (size_t)length;
1300
+ p.offset = 0;
1301
+ p.noalloc = true;
1302
+ p.format = format;
1303
+ p.hooks = global_hooks;
1304
+
1305
+ return print_value(item, &p);
1306
+ }
1307
+
1308
+ /* Parser core - when encountering text, process appropriately. */
1309
+ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1310
+ {
1311
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
1312
+ {
1313
+ return false; /* no input */
1314
+ }
1315
+
1316
+ /* parse the different types of values */
1317
+ /* null */
1318
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1319
+ {
1320
+ item->type = cJSON_NULL;
1321
+ input_buffer->offset += 4;
1322
+ return true;
1323
+ }
1324
+ /* false */
1325
+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1326
+ {
1327
+ item->type = cJSON_False;
1328
+ input_buffer->offset += 5;
1329
+ return true;
1330
+ }
1331
+ /* true */
1332
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1333
+ {
1334
+ item->type = cJSON_True;
1335
+ item->valueint = 1;
1336
+ input_buffer->offset += 4;
1337
+ return true;
1338
+ }
1339
+ /* string */
1340
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1341
+ {
1342
+ return parse_string(item, input_buffer);
1343
+ }
1344
+ /* number */
1345
+ 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'))))
1346
+ {
1347
+ return parse_number(item, input_buffer);
1348
+ }
1349
+ /* array */
1350
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1351
+ {
1352
+ return parse_array(item, input_buffer);
1353
+ }
1354
+ /* object */
1355
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1356
+ {
1357
+ return parse_object(item, input_buffer);
1358
+ }
1359
+
1360
+ return false;
1361
+ }
1362
+
1363
+ /* Render a value to text. */
1364
+ static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1365
+ {
1366
+ unsigned char *output = NULL;
1367
+
1368
+ if ((item == NULL) || (output_buffer == NULL))
1369
+ {
1370
+ return false;
1371
+ }
1372
+
1373
+ switch ((item->type) & 0xFF)
1374
+ {
1375
+ case cJSON_NULL:
1376
+ output = ensure(output_buffer, 5);
1377
+ if (output == NULL)
1378
+ {
1379
+ return false;
1380
+ }
1381
+ memcpy(output, "null", 5); /* NOLINT */
1382
+ return true;
1383
+
1384
+ case cJSON_False:
1385
+ output = ensure(output_buffer, 6);
1386
+ if (output == NULL)
1387
+ {
1388
+ return false;
1389
+ }
1390
+ memcpy(output, "false", 6); /* NOLINT */
1391
+ return true;
1392
+
1393
+ case cJSON_True:
1394
+ output = ensure(output_buffer, 5);
1395
+ if (output == NULL)
1396
+ {
1397
+ return false;
1398
+ }
1399
+ memcpy(output, "true", 5); /* NOLINT */
1400
+ return true;
1401
+
1402
+ case cJSON_Number:
1403
+ return print_number(item, output_buffer);
1404
+
1405
+ case cJSON_Raw:
1406
+ {
1407
+ size_t raw_length = 0;
1408
+ if (item->valuestring == NULL)
1409
+ {
1410
+ return false;
1411
+ }
1412
+
1413
+ raw_length = strlen(item->valuestring) + sizeof("");
1414
+ output = ensure(output_buffer, raw_length);
1415
+ if (output == NULL)
1416
+ {
1417
+ return false;
1418
+ }
1419
+ memcpy(output, item->valuestring, raw_length);
1420
+ return true;
1421
+ }
1422
+
1423
+ case cJSON_String:
1424
+ return print_string(item, output_buffer);
1425
+
1426
+ case cJSON_Array:
1427
+ return print_array(item, output_buffer);
1428
+
1429
+ case cJSON_Object:
1430
+ return print_object(item, output_buffer);
1431
+
1432
+ default:
1433
+ return false;
1434
+ }
1435
+ }
1436
+
1437
+ /* Build an array from input text. */
1438
+ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1439
+ {
1440
+ cJSON *head = NULL; /* head of the linked list */
1441
+ cJSON *current_item = NULL;
1442
+
1443
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1444
+ {
1445
+ return false; /* to deeply nested */
1446
+ }
1447
+ input_buffer->depth++;
1448
+
1449
+ if (buffer_at_offset(input_buffer)[0] != '[')
1450
+ {
1451
+ /* not an array */
1452
+ goto fail;
1453
+ }
1454
+
1455
+ input_buffer->offset++;
1456
+ buffer_skip_whitespace(input_buffer);
1457
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1458
+ {
1459
+ /* empty array */
1460
+ goto success;
1461
+ }
1462
+
1463
+ /* check if we skipped to the end of the buffer */
1464
+ if (cannot_access_at_index(input_buffer, 0))
1465
+ {
1466
+ input_buffer->offset--;
1467
+ goto fail;
1468
+ }
1469
+
1470
+ /* step back to character in front of the first element */
1471
+ input_buffer->offset--;
1472
+ /* loop through the comma separated array elements */
1473
+ do
1474
+ {
1475
+ /* allocate next item */
1476
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1477
+ if (new_item == NULL)
1478
+ {
1479
+ goto fail; /* allocation failure */
1480
+ }
1481
+
1482
+ /* attach next item to list */
1483
+ if (head == NULL)
1484
+ {
1485
+ /* start the linked list */
1486
+ current_item = head = new_item;
1487
+ }
1488
+ else
1489
+ {
1490
+ /* add to the end and advance */
1491
+ current_item->next = new_item;
1492
+ new_item->prev = current_item;
1493
+ current_item = new_item;
1494
+ }
1495
+
1496
+ /* parse next value */
1497
+ input_buffer->offset++;
1498
+ buffer_skip_whitespace(input_buffer);
1499
+ if (!parse_value(current_item, input_buffer))
1500
+ {
1501
+ goto fail; /* failed to parse value */
1502
+ }
1503
+ buffer_skip_whitespace(input_buffer);
1504
+ }
1505
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1506
+
1507
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1508
+ {
1509
+ goto fail; /* expected end of array */
1510
+ }
1511
+
1512
+ success:
1513
+ input_buffer->depth--;
1514
+
1515
+ if (head != NULL) {
1516
+ head->prev = current_item;
1517
+ }
1518
+
1519
+ item->type = cJSON_Array;
1520
+ item->child = head;
1521
+
1522
+ input_buffer->offset++;
1523
+
1524
+ return true;
1525
+
1526
+ fail:
1527
+ if (head != NULL)
1528
+ {
1529
+ cJSON_Delete(head);
1530
+ }
1531
+
1532
+ return false;
1533
+ }
1534
+
1535
+ /* Render an array to text */
1536
+ static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1537
+ {
1538
+ unsigned char *output_pointer = NULL;
1539
+ size_t length = 0;
1540
+ cJSON *current_element = item->child;
1541
+
1542
+ if (output_buffer == NULL)
1543
+ {
1544
+ return false;
1545
+ }
1546
+
1547
+ /* Compose the output array. */
1548
+ /* opening square bracket */
1549
+ output_pointer = ensure(output_buffer, 1);
1550
+ if (output_pointer == NULL)
1551
+ {
1552
+ return false;
1553
+ }
1554
+
1555
+ *output_pointer = '[';
1556
+ output_buffer->offset++;
1557
+ output_buffer->depth++;
1558
+
1559
+ while (current_element != NULL)
1560
+ {
1561
+ if (!print_value(current_element, output_buffer))
1562
+ {
1563
+ return false;
1564
+ }
1565
+ update_offset(output_buffer);
1566
+ if (current_element->next)
1567
+ {
1568
+ length = (size_t) (output_buffer->format ? 2 : 1);
1569
+ output_pointer = ensure(output_buffer, length + 1);
1570
+ if (output_pointer == NULL)
1571
+ {
1572
+ return false;
1573
+ }
1574
+ *output_pointer++ = ',';
1575
+ if(output_buffer->format)
1576
+ {
1577
+ *output_pointer++ = ' ';
1578
+ }
1579
+ *output_pointer = '\0';
1580
+ output_buffer->offset += length;
1581
+ }
1582
+ current_element = current_element->next;
1583
+ }
1584
+
1585
+ output_pointer = ensure(output_buffer, 2);
1586
+ if (output_pointer == NULL)
1587
+ {
1588
+ return false;
1589
+ }
1590
+ *output_pointer++ = ']';
1591
+ *output_pointer = '\0';
1592
+ output_buffer->depth--;
1593
+
1594
+ return true;
1595
+ }
1596
+
1597
+ /* Build an object from the text. */
1598
+ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1599
+ {
1600
+ cJSON *head = NULL; /* linked list head */
1601
+ cJSON *current_item = NULL;
1602
+
1603
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1604
+ {
1605
+ return false; /* to deeply nested */
1606
+ }
1607
+ input_buffer->depth++;
1608
+
1609
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1610
+ {
1611
+ goto fail; /* not an object */
1612
+ }
1613
+
1614
+ input_buffer->offset++;
1615
+ buffer_skip_whitespace(input_buffer);
1616
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1617
+ {
1618
+ goto success; /* empty object */
1619
+ }
1620
+
1621
+ /* check if we skipped to the end of the buffer */
1622
+ if (cannot_access_at_index(input_buffer, 0))
1623
+ {
1624
+ input_buffer->offset--;
1625
+ goto fail;
1626
+ }
1627
+
1628
+ /* step back to character in front of the first element */
1629
+ input_buffer->offset--;
1630
+ /* loop through the comma separated array elements */
1631
+ do
1632
+ {
1633
+ /* allocate next item */
1634
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1635
+ if (new_item == NULL)
1636
+ {
1637
+ goto fail; /* allocation failure */
1638
+ }
1639
+
1640
+ /* attach next item to list */
1641
+ if (head == NULL)
1642
+ {
1643
+ /* start the linked list */
1644
+ current_item = head = new_item;
1645
+ }
1646
+ else
1647
+ {
1648
+ /* add to the end and advance */
1649
+ current_item->next = new_item;
1650
+ new_item->prev = current_item;
1651
+ current_item = new_item;
1652
+ }
1653
+
1654
+ /* parse the name of the child */
1655
+ input_buffer->offset++;
1656
+ buffer_skip_whitespace(input_buffer);
1657
+ if (!parse_string(current_item, input_buffer))
1658
+ {
1659
+ goto fail; /* failed to parse name */
1660
+ }
1661
+ buffer_skip_whitespace(input_buffer);
1662
+
1663
+ /* swap valuestring and string, because we parsed the name */
1664
+ current_item->string = current_item->valuestring;
1665
+ current_item->valuestring = NULL;
1666
+
1667
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1668
+ {
1669
+ goto fail; /* invalid object */
1670
+ }
1671
+
1672
+ /* parse the value */
1673
+ input_buffer->offset++;
1674
+ buffer_skip_whitespace(input_buffer);
1675
+ if (!parse_value(current_item, input_buffer))
1676
+ {
1677
+ goto fail; /* failed to parse value */
1678
+ }
1679
+ buffer_skip_whitespace(input_buffer);
1680
+ }
1681
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1682
+
1683
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1684
+ {
1685
+ goto fail; /* expected end of object */
1686
+ }
1687
+
1688
+ success:
1689
+ input_buffer->depth--;
1690
+
1691
+ if (head != NULL) {
1692
+ head->prev = current_item;
1693
+ }
1694
+
1695
+ item->type = cJSON_Object;
1696
+ item->child = head;
1697
+
1698
+ input_buffer->offset++;
1699
+ return true;
1700
+
1701
+ fail:
1702
+ if (head != NULL)
1703
+ {
1704
+ cJSON_Delete(head);
1705
+ }
1706
+
1707
+ return false;
1708
+ }
1709
+
1710
+ /* Render an object to text. */
1711
+ static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1712
+ {
1713
+ unsigned char *output_pointer = NULL;
1714
+ size_t length = 0;
1715
+ cJSON *current_item = item->child;
1716
+
1717
+ if (output_buffer == NULL)
1718
+ {
1719
+ return false;
1720
+ }
1721
+
1722
+ /* Compose the output: */
1723
+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1724
+ output_pointer = ensure(output_buffer, length + 1);
1725
+ if (output_pointer == NULL)
1726
+ {
1727
+ return false;
1728
+ }
1729
+
1730
+ *output_pointer++ = '{';
1731
+ output_buffer->depth++;
1732
+ if (output_buffer->format)
1733
+ {
1734
+ *output_pointer++ = '\n';
1735
+ }
1736
+ output_buffer->offset += length;
1737
+
1738
+ while (current_item)
1739
+ {
1740
+ if (output_buffer->format)
1741
+ {
1742
+ size_t i;
1743
+ output_pointer = ensure(output_buffer, output_buffer->depth);
1744
+ if (output_pointer == NULL)
1745
+ {
1746
+ return false;
1747
+ }
1748
+ for (i = 0; i < output_buffer->depth; i++)
1749
+ {
1750
+ *output_pointer++ = '\t';
1751
+ }
1752
+ output_buffer->offset += output_buffer->depth;
1753
+ }
1754
+
1755
+ /* print key */
1756
+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1757
+ {
1758
+ return false;
1759
+ }
1760
+ update_offset(output_buffer);
1761
+
1762
+ length = (size_t) (output_buffer->format ? 2 : 1);
1763
+ output_pointer = ensure(output_buffer, length);
1764
+ if (output_pointer == NULL)
1765
+ {
1766
+ return false;
1767
+ }
1768
+ *output_pointer++ = ':';
1769
+ if (output_buffer->format)
1770
+ {
1771
+ *output_pointer++ = '\t';
1772
+ }
1773
+ output_buffer->offset += length;
1774
+
1775
+ /* print value */
1776
+ if (!print_value(current_item, output_buffer))
1777
+ {
1778
+ return false;
1779
+ }
1780
+ update_offset(output_buffer);
1781
+
1782
+ /* print comma if not last */
1783
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1784
+ output_pointer = ensure(output_buffer, length + 1);
1785
+ if (output_pointer == NULL)
1786
+ {
1787
+ return false;
1788
+ }
1789
+ if (current_item->next)
1790
+ {
1791
+ *output_pointer++ = ',';
1792
+ }
1793
+
1794
+ if (output_buffer->format)
1795
+ {
1796
+ *output_pointer++ = '\n';
1797
+ }
1798
+ *output_pointer = '\0';
1799
+ output_buffer->offset += length;
1800
+
1801
+ current_item = current_item->next;
1802
+ }
1803
+
1804
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1805
+ if (output_pointer == NULL)
1806
+ {
1807
+ return false;
1808
+ }
1809
+ if (output_buffer->format)
1810
+ {
1811
+ size_t i;
1812
+ for (i = 0; i < (output_buffer->depth - 1); i++)
1813
+ {
1814
+ *output_pointer++ = '\t';
1815
+ }
1816
+ }
1817
+ *output_pointer++ = '}';
1818
+ *output_pointer = '\0';
1819
+ output_buffer->depth--;
1820
+
1821
+ return true;
1822
+ }
1823
+
1824
+ /* Get Array size/item / object item. */
1825
+ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1826
+ {
1827
+ cJSON *child = NULL;
1828
+ size_t size = 0;
1829
+
1830
+ if (array == NULL)
1831
+ {
1832
+ return 0;
1833
+ }
1834
+
1835
+ child = array->child;
1836
+
1837
+ while(child != NULL)
1838
+ {
1839
+ size++;
1840
+ child = child->next;
1841
+ }
1842
+
1843
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1844
+
1845
+ return (int)size;
1846
+ }
1847
+
1848
+ static cJSON* get_array_item(const cJSON *array, size_t index)
1849
+ {
1850
+ cJSON *current_child = NULL;
1851
+
1852
+ if (array == NULL)
1853
+ {
1854
+ return NULL;
1855
+ }
1856
+
1857
+ current_child = array->child;
1858
+ while ((current_child != NULL) && (index > 0))
1859
+ {
1860
+ index--;
1861
+ current_child = current_child->next;
1862
+ }
1863
+
1864
+ return current_child;
1865
+ }
1866
+
1867
+ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1868
+ {
1869
+ if (index < 0)
1870
+ {
1871
+ return NULL;
1872
+ }
1873
+
1874
+ return get_array_item(array, (size_t)index);
1875
+ }
1876
+
1877
+ static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1878
+ {
1879
+ cJSON *current_element = NULL;
1880
+
1881
+ if ((object == NULL) || (name == NULL))
1882
+ {
1883
+ return NULL;
1884
+ }
1885
+
1886
+ current_element = object->child;
1887
+ if (case_sensitive)
1888
+ {
1889
+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1890
+ {
1891
+ current_element = current_element->next;
1892
+ }
1893
+ }
1894
+ else
1895
+ {
1896
+ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1897
+ {
1898
+ current_element = current_element->next;
1899
+ }
1900
+ }
1901
+
1902
+ if ((current_element == NULL) || (current_element->string == NULL)) {
1903
+ return NULL;
1904
+ }
1905
+
1906
+ return current_element;
1907
+ }
1908
+
1909
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1910
+ {
1911
+ return get_object_item(object, string, false);
1912
+ }
1913
+
1914
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1915
+ {
1916
+ return get_object_item(object, string, true);
1917
+ }
1918
+
1919
+ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1920
+ {
1921
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
1922
+ }
1923
+
1924
+ /* Utility for array list handling. */
1925
+ static void suffix_object(cJSON *prev, cJSON *item)
1926
+ {
1927
+ prev->next = item;
1928
+ item->prev = prev;
1929
+ }
1930
+
1931
+ /* Utility for handling references. */
1932
+ static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1933
+ {
1934
+ cJSON *reference = NULL;
1935
+ if (item == NULL)
1936
+ {
1937
+ return NULL;
1938
+ }
1939
+
1940
+ reference = cJSON_New_Item(hooks);
1941
+ if (reference == NULL)
1942
+ {
1943
+ return NULL;
1944
+ }
1945
+
1946
+ memcpy(reference, item, sizeof(cJSON));
1947
+ reference->string = NULL;
1948
+ reference->type |= cJSON_IsReference;
1949
+ reference->next = reference->prev = NULL;
1950
+ return reference;
1951
+ }
1952
+
1953
+ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1954
+ {
1955
+ cJSON *child = NULL;
1956
+
1957
+ if ((item == NULL) || (array == NULL) || (array == item))
1958
+ {
1959
+ return false;
1960
+ }
1961
+
1962
+ child = array->child;
1963
+ /*
1964
+ * To find the last item in array quickly, we use prev in array
1965
+ */
1966
+ if (child == NULL)
1967
+ {
1968
+ /* list is empty, start new one */
1969
+ array->child = item;
1970
+ item->prev = item;
1971
+ item->next = NULL;
1972
+ }
1973
+ else
1974
+ {
1975
+ /* append to the end */
1976
+ if (child->prev)
1977
+ {
1978
+ suffix_object(child->prev, item);
1979
+ array->child->prev = item;
1980
+ }
1981
+ }
1982
+
1983
+ return true;
1984
+ }
1985
+
1986
+ /* Add item to array/object. */
1987
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1988
+ {
1989
+ return add_item_to_array(array, item);
1990
+ }
1991
+
1992
+ #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1993
+ #pragma GCC diagnostic push
1994
+ #endif
1995
+ #ifdef __GNUC__
1996
+ #if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)))
1997
+ #pragma GCC diagnostic ignored "-Wcast-qual"
1998
+ #endif
1999
+ #endif
2000
+ /* helper function to cast away const */
2001
+ static void* cast_away_const(const void* string)
2002
+ {
2003
+ return (void*)string;
2004
+ }
2005
+ #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2006
+ #pragma GCC diagnostic pop
2007
+ #endif
2008
+
2009
+
2010
+ 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)
2011
+ {
2012
+ char *new_key = NULL;
2013
+ int new_type = cJSON_Invalid;
2014
+
2015
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2016
+ {
2017
+ return false;
2018
+ }
2019
+
2020
+ if (constant_key)
2021
+ {
2022
+ new_key = (char*)cast_away_const(string);
2023
+ new_type = item->type | cJSON_StringIsConst;
2024
+ }
2025
+ else
2026
+ {
2027
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2028
+ if (new_key == NULL)
2029
+ {
2030
+ return false;
2031
+ }
2032
+
2033
+ new_type = item->type & ~cJSON_StringIsConst;
2034
+ }
2035
+
2036
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2037
+ {
2038
+ hooks->deallocate(item->string);
2039
+ }
2040
+
2041
+ item->string = new_key;
2042
+ item->type = new_type;
2043
+
2044
+ return add_item_to_array(object, item);
2045
+ }
2046
+
2047
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2048
+ {
2049
+ return add_item_to_object(object, string, item, &global_hooks, false);
2050
+ }
2051
+
2052
+ /* Add an item to an object with constant string as key */
2053
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2054
+ {
2055
+ return add_item_to_object(object, string, item, &global_hooks, true);
2056
+ }
2057
+
2058
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2059
+ {
2060
+ if (array == NULL)
2061
+ {
2062
+ return false;
2063
+ }
2064
+
2065
+ return add_item_to_array(array, create_reference(item, &global_hooks));
2066
+ }
2067
+
2068
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2069
+ {
2070
+ if ((object == NULL) || (string == NULL))
2071
+ {
2072
+ return false;
2073
+ }
2074
+
2075
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2076
+ }
2077
+
2078
+ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2079
+ {
2080
+ cJSON *null = cJSON_CreateNull();
2081
+ if (add_item_to_object(object, name, null, &global_hooks, false))
2082
+ {
2083
+ return null;
2084
+ }
2085
+
2086
+ cJSON_Delete(null);
2087
+ return NULL;
2088
+ }
2089
+
2090
+ CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2091
+ {
2092
+ cJSON *true_item = cJSON_CreateTrue();
2093
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
2094
+ {
2095
+ return true_item;
2096
+ }
2097
+
2098
+ cJSON_Delete(true_item);
2099
+ return NULL;
2100
+ }
2101
+
2102
+ CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2103
+ {
2104
+ cJSON *false_item = cJSON_CreateFalse();
2105
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
2106
+ {
2107
+ return false_item;
2108
+ }
2109
+
2110
+ cJSON_Delete(false_item);
2111
+ return NULL;
2112
+ }
2113
+
2114
+ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2115
+ {
2116
+ cJSON *bool_item = cJSON_CreateBool(boolean);
2117
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2118
+ {
2119
+ return bool_item;
2120
+ }
2121
+
2122
+ cJSON_Delete(bool_item);
2123
+ return NULL;
2124
+ }
2125
+
2126
+ CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2127
+ {
2128
+ cJSON *number_item = cJSON_CreateNumber(number);
2129
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
2130
+ {
2131
+ return number_item;
2132
+ }
2133
+
2134
+ cJSON_Delete(number_item);
2135
+ return NULL;
2136
+ }
2137
+
2138
+ CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2139
+ {
2140
+ cJSON *string_item = cJSON_CreateString(string);
2141
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
2142
+ {
2143
+ return string_item;
2144
+ }
2145
+
2146
+ cJSON_Delete(string_item);
2147
+ return NULL;
2148
+ }
2149
+
2150
+ CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2151
+ {
2152
+ cJSON *raw_item = cJSON_CreateRaw(raw);
2153
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2154
+ {
2155
+ return raw_item;
2156
+ }
2157
+
2158
+ cJSON_Delete(raw_item);
2159
+ return NULL;
2160
+ }
2161
+
2162
+ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2163
+ {
2164
+ cJSON *object_item = cJSON_CreateObject();
2165
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
2166
+ {
2167
+ return object_item;
2168
+ }
2169
+
2170
+ cJSON_Delete(object_item);
2171
+ return NULL;
2172
+ }
2173
+
2174
+ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2175
+ {
2176
+ cJSON *array = cJSON_CreateArray();
2177
+ if (add_item_to_object(object, name, array, &global_hooks, false))
2178
+ {
2179
+ return array;
2180
+ }
2181
+
2182
+ cJSON_Delete(array);
2183
+ return NULL;
2184
+ }
2185
+
2186
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2187
+ {
2188
+ if ((parent == NULL) || (item == NULL))
2189
+ {
2190
+ return NULL;
2191
+ }
2192
+
2193
+ if (item != parent->child)
2194
+ {
2195
+ /* not the first element */
2196
+ item->prev->next = item->next;
2197
+ }
2198
+ if (item->next != NULL)
2199
+ {
2200
+ /* not the last element */
2201
+ item->next->prev = item->prev;
2202
+ }
2203
+
2204
+ if (item == parent->child)
2205
+ {
2206
+ /* first element */
2207
+ parent->child = item->next;
2208
+ }
2209
+ else if (item->next == NULL)
2210
+ {
2211
+ /* last element */
2212
+ parent->child->prev = item->prev;
2213
+ }
2214
+
2215
+ /* make sure the detached item doesn't point anywhere anymore */
2216
+ item->prev = NULL;
2217
+ item->next = NULL;
2218
+
2219
+ return item;
2220
+ }
2221
+
2222
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2223
+ {
2224
+ if (which < 0)
2225
+ {
2226
+ return NULL;
2227
+ }
2228
+
2229
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2230
+ }
2231
+
2232
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2233
+ {
2234
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2235
+ }
2236
+
2237
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2238
+ {
2239
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
2240
+
2241
+ return cJSON_DetachItemViaPointer(object, to_detach);
2242
+ }
2243
+
2244
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2245
+ {
2246
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2247
+
2248
+ return cJSON_DetachItemViaPointer(object, to_detach);
2249
+ }
2250
+
2251
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2252
+ {
2253
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2254
+ }
2255
+
2256
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2257
+ {
2258
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2259
+ }
2260
+
2261
+ /* Replace array/object items with new ones. */
2262
+ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2263
+ {
2264
+ cJSON *after_inserted = NULL;
2265
+
2266
+ if (which < 0)
2267
+ {
2268
+ return false;
2269
+ }
2270
+
2271
+ after_inserted = get_array_item(array, (size_t)which);
2272
+ if (after_inserted == NULL)
2273
+ {
2274
+ return add_item_to_array(array, newitem);
2275
+ }
2276
+
2277
+ newitem->next = after_inserted;
2278
+ newitem->prev = after_inserted->prev;
2279
+ after_inserted->prev = newitem;
2280
+ if (after_inserted == array->child)
2281
+ {
2282
+ array->child = newitem;
2283
+ }
2284
+ else
2285
+ {
2286
+ newitem->prev->next = newitem;
2287
+ }
2288
+ return true;
2289
+ }
2290
+
2291
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2292
+ {
2293
+ if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2294
+ {
2295
+ return false;
2296
+ }
2297
+
2298
+ if (replacement == item)
2299
+ {
2300
+ return true;
2301
+ }
2302
+
2303
+ replacement->next = item->next;
2304
+ replacement->prev = item->prev;
2305
+
2306
+ if (replacement->next != NULL)
2307
+ {
2308
+ replacement->next->prev = replacement;
2309
+ }
2310
+ if (parent->child == item)
2311
+ {
2312
+ if (parent->child->prev == parent->child)
2313
+ {
2314
+ replacement->prev = replacement;
2315
+ }
2316
+ parent->child = replacement;
2317
+ }
2318
+ else
2319
+ { /*
2320
+ * To find the last item in array quickly, we use prev in array.
2321
+ * We can't modify the last item's next pointer where this item was the parent's child
2322
+ */
2323
+ if (replacement->prev != NULL)
2324
+ {
2325
+ replacement->prev->next = replacement;
2326
+ }
2327
+ if (replacement->next == NULL)
2328
+ {
2329
+ parent->child->prev = replacement;
2330
+ }
2331
+ }
2332
+
2333
+ item->next = NULL;
2334
+ item->prev = NULL;
2335
+ cJSON_Delete(item);
2336
+
2337
+ return true;
2338
+ }
2339
+
2340
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2341
+ {
2342
+ if (which < 0)
2343
+ {
2344
+ return false;
2345
+ }
2346
+
2347
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2348
+ }
2349
+
2350
+ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2351
+ {
2352
+ if ((replacement == NULL) || (string == NULL))
2353
+ {
2354
+ return false;
2355
+ }
2356
+
2357
+ /* replace the name in the replacement */
2358
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2359
+ {
2360
+ cJSON_free(replacement->string);
2361
+ }
2362
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2363
+ replacement->type &= ~cJSON_StringIsConst;
2364
+
2365
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2366
+ }
2367
+
2368
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2369
+ {
2370
+ return replace_item_in_object(object, string, newitem, false);
2371
+ }
2372
+
2373
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2374
+ {
2375
+ return replace_item_in_object(object, string, newitem, true);
2376
+ }
2377
+
2378
+ /* Create basic types: */
2379
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2380
+ {
2381
+ cJSON *item = cJSON_New_Item(&global_hooks);
2382
+ if(item)
2383
+ {
2384
+ item->type = cJSON_NULL;
2385
+ }
2386
+
2387
+ return item;
2388
+ }
2389
+
2390
+ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2391
+ {
2392
+ cJSON *item = cJSON_New_Item(&global_hooks);
2393
+ if(item)
2394
+ {
2395
+ item->type = cJSON_True;
2396
+ }
2397
+
2398
+ return item;
2399
+ }
2400
+
2401
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2402
+ {
2403
+ cJSON *item = cJSON_New_Item(&global_hooks);
2404
+ if(item)
2405
+ {
2406
+ item->type = cJSON_False;
2407
+ }
2408
+
2409
+ return item;
2410
+ }
2411
+
2412
+ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2413
+ {
2414
+ cJSON *item = cJSON_New_Item(&global_hooks);
2415
+ if(item)
2416
+ {
2417
+ item->type = boolean ? cJSON_True : cJSON_False;
2418
+ }
2419
+
2420
+ return item;
2421
+ }
2422
+
2423
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2424
+ {
2425
+ cJSON *item = cJSON_New_Item(&global_hooks);
2426
+ if(item)
2427
+ {
2428
+ item->type = cJSON_Number;
2429
+ item->valuedouble = num;
2430
+
2431
+ /* use saturation in case of overflow */
2432
+ if (num >= INT_MAX)
2433
+ {
2434
+ item->valueint = INT_MAX;
2435
+ }
2436
+ else if (num <= (double)INT_MIN)
2437
+ {
2438
+ item->valueint = INT_MIN;
2439
+ }
2440
+ else
2441
+ {
2442
+ item->valueint = (int)num;
2443
+ }
2444
+ }
2445
+
2446
+ return item;
2447
+ }
2448
+
2449
+ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2450
+ {
2451
+ cJSON *item = cJSON_New_Item(&global_hooks);
2452
+ if(item)
2453
+ {
2454
+ item->type = cJSON_String;
2455
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2456
+ if(!item->valuestring)
2457
+ {
2458
+ cJSON_Delete(item);
2459
+ return NULL;
2460
+ }
2461
+ }
2462
+
2463
+ return item;
2464
+ }
2465
+
2466
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2467
+ {
2468
+ cJSON *item = cJSON_New_Item(&global_hooks);
2469
+ if (item != NULL)
2470
+ {
2471
+ item->type = cJSON_String | cJSON_IsReference;
2472
+ item->valuestring = (char*)cast_away_const(string);
2473
+ }
2474
+
2475
+ return item;
2476
+ }
2477
+
2478
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2479
+ {
2480
+ cJSON *item = cJSON_New_Item(&global_hooks);
2481
+ if (item != NULL) {
2482
+ item->type = cJSON_Object | cJSON_IsReference;
2483
+ item->child = (cJSON*)cast_away_const(child);
2484
+ }
2485
+
2486
+ return item;
2487
+ }
2488
+
2489
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2490
+ cJSON *item = cJSON_New_Item(&global_hooks);
2491
+ if (item != NULL) {
2492
+ item->type = cJSON_Array | cJSON_IsReference;
2493
+ item->child = (cJSON*)cast_away_const(child);
2494
+ }
2495
+
2496
+ return item;
2497
+ }
2498
+
2499
+ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2500
+ {
2501
+ cJSON *item = cJSON_New_Item(&global_hooks);
2502
+ if(item)
2503
+ {
2504
+ item->type = cJSON_Raw;
2505
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2506
+ if(!item->valuestring)
2507
+ {
2508
+ cJSON_Delete(item);
2509
+ return NULL;
2510
+ }
2511
+ }
2512
+
2513
+ return item;
2514
+ }
2515
+
2516
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2517
+ {
2518
+ cJSON *item = cJSON_New_Item(&global_hooks);
2519
+ if(item)
2520
+ {
2521
+ item->type=cJSON_Array;
2522
+ }
2523
+
2524
+ return item;
2525
+ }
2526
+
2527
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2528
+ {
2529
+ cJSON *item = cJSON_New_Item(&global_hooks);
2530
+ if (item)
2531
+ {
2532
+ item->type = cJSON_Object;
2533
+ }
2534
+
2535
+ return item;
2536
+ }
2537
+
2538
+ /* Create Arrays: */
2539
+ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2540
+ {
2541
+ size_t i = 0;
2542
+ cJSON *n = NULL;
2543
+ cJSON *p = NULL;
2544
+ cJSON *a = NULL;
2545
+
2546
+ if ((count < 0) || (numbers == NULL))
2547
+ {
2548
+ return NULL;
2549
+ }
2550
+
2551
+ a = cJSON_CreateArray();
2552
+
2553
+ for(i = 0; a && (i < (size_t)count); i++)
2554
+ {
2555
+ n = cJSON_CreateNumber(numbers[i]);
2556
+ if (!n)
2557
+ {
2558
+ cJSON_Delete(a);
2559
+ return NULL;
2560
+ }
2561
+ if(!i)
2562
+ {
2563
+ a->child = n;
2564
+ }
2565
+ else
2566
+ {
2567
+ suffix_object(p, n);
2568
+ }
2569
+ p = n;
2570
+ }
2571
+
2572
+ if (a && a->child) {
2573
+ a->child->prev = n;
2574
+ }
2575
+
2576
+ return a;
2577
+ }
2578
+
2579
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2580
+ {
2581
+ size_t i = 0;
2582
+ cJSON *n = NULL;
2583
+ cJSON *p = NULL;
2584
+ cJSON *a = NULL;
2585
+
2586
+ if ((count < 0) || (numbers == NULL))
2587
+ {
2588
+ return NULL;
2589
+ }
2590
+
2591
+ a = cJSON_CreateArray();
2592
+
2593
+ for(i = 0; a && (i < (size_t)count); i++)
2594
+ {
2595
+ n = cJSON_CreateNumber((double)numbers[i]);
2596
+ if(!n)
2597
+ {
2598
+ cJSON_Delete(a);
2599
+ return NULL;
2600
+ }
2601
+ if(!i)
2602
+ {
2603
+ a->child = n;
2604
+ }
2605
+ else
2606
+ {
2607
+ suffix_object(p, n);
2608
+ }
2609
+ p = n;
2610
+ }
2611
+
2612
+ if (a && a->child) {
2613
+ a->child->prev = n;
2614
+ }
2615
+
2616
+ return a;
2617
+ }
2618
+
2619
+ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2620
+ {
2621
+ size_t i = 0;
2622
+ cJSON *n = NULL;
2623
+ cJSON *p = NULL;
2624
+ cJSON *a = NULL;
2625
+
2626
+ if ((count < 0) || (numbers == NULL))
2627
+ {
2628
+ return NULL;
2629
+ }
2630
+
2631
+ a = cJSON_CreateArray();
2632
+
2633
+ for(i = 0; a && (i < (size_t)count); i++)
2634
+ {
2635
+ n = cJSON_CreateNumber(numbers[i]);
2636
+ if(!n)
2637
+ {
2638
+ cJSON_Delete(a);
2639
+ return NULL;
2640
+ }
2641
+ if(!i)
2642
+ {
2643
+ a->child = n;
2644
+ }
2645
+ else
2646
+ {
2647
+ suffix_object(p, n);
2648
+ }
2649
+ p = n;
2650
+ }
2651
+
2652
+ if (a && a->child) {
2653
+ a->child->prev = n;
2654
+ }
2655
+
2656
+ return a;
2657
+ }
2658
+
2659
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2660
+ {
2661
+ size_t i = 0;
2662
+ cJSON *n = NULL;
2663
+ cJSON *p = NULL;
2664
+ cJSON *a = NULL;
2665
+
2666
+ if ((count < 0) || (strings == NULL))
2667
+ {
2668
+ return NULL;
2669
+ }
2670
+
2671
+ a = cJSON_CreateArray();
2672
+
2673
+ for (i = 0; a && (i < (size_t)count); i++)
2674
+ {
2675
+ n = cJSON_CreateString(strings[i]);
2676
+ if(!n)
2677
+ {
2678
+ cJSON_Delete(a);
2679
+ return NULL;
2680
+ }
2681
+ if(!i)
2682
+ {
2683
+ a->child = n;
2684
+ }
2685
+ else
2686
+ {
2687
+ suffix_object(p,n);
2688
+ }
2689
+ p = n;
2690
+ }
2691
+
2692
+ if (a && a->child) {
2693
+ a->child->prev = n;
2694
+ }
2695
+
2696
+ return a;
2697
+ }
2698
+
2699
+ /* Duplication */
2700
+ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2701
+ {
2702
+ cJSON *newitem = NULL;
2703
+ cJSON *child = NULL;
2704
+ cJSON *next = NULL;
2705
+ cJSON *newchild = NULL;
2706
+
2707
+ /* Bail on bad ptr */
2708
+ if (!item)
2709
+ {
2710
+ goto fail;
2711
+ }
2712
+ /* Create new item */
2713
+ newitem = cJSON_New_Item(&global_hooks);
2714
+ if (!newitem)
2715
+ {
2716
+ goto fail;
2717
+ }
2718
+ /* Copy over all vars */
2719
+ newitem->type = item->type & (~cJSON_IsReference);
2720
+ newitem->valueint = item->valueint;
2721
+ newitem->valuedouble = item->valuedouble;
2722
+ if (item->valuestring)
2723
+ {
2724
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2725
+ if (!newitem->valuestring)
2726
+ {
2727
+ goto fail;
2728
+ }
2729
+ }
2730
+ if (item->string)
2731
+ {
2732
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2733
+ if (!newitem->string)
2734
+ {
2735
+ goto fail;
2736
+ }
2737
+ }
2738
+ /* If non-recursive, then we're done! */
2739
+ if (!recurse)
2740
+ {
2741
+ return newitem;
2742
+ }
2743
+ /* Walk the ->next chain for the child. */
2744
+ child = item->child;
2745
+ while (child != NULL)
2746
+ {
2747
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2748
+ if (!newchild)
2749
+ {
2750
+ goto fail;
2751
+ }
2752
+ if (next != NULL)
2753
+ {
2754
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2755
+ next->next = newchild;
2756
+ newchild->prev = next;
2757
+ next = newchild;
2758
+ }
2759
+ else
2760
+ {
2761
+ /* Set newitem->child and move to it */
2762
+ newitem->child = newchild;
2763
+ next = newchild;
2764
+ }
2765
+ child = child->next;
2766
+ }
2767
+ if (newitem && newitem->child)
2768
+ {
2769
+ newitem->child->prev = newchild;
2770
+ }
2771
+
2772
+ return newitem;
2773
+
2774
+ fail:
2775
+ if (newitem != NULL)
2776
+ {
2777
+ cJSON_Delete(newitem);
2778
+ }
2779
+
2780
+ return NULL;
2781
+ }
2782
+
2783
+ static void skip_oneline_comment(char **input)
2784
+ {
2785
+ *input += static_strlen("//");
2786
+
2787
+ for (; (*input)[0] != '\0'; ++(*input))
2788
+ {
2789
+ if ((*input)[0] == '\n') {
2790
+ *input += static_strlen("\n");
2791
+ return;
2792
+ }
2793
+ }
2794
+ }
2795
+
2796
+ static void skip_multiline_comment(char **input)
2797
+ {
2798
+ *input += static_strlen("/*");
2799
+
2800
+ for (; (*input)[0] != '\0'; ++(*input))
2801
+ {
2802
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
2803
+ {
2804
+ *input += static_strlen("*/");
2805
+ return;
2806
+ }
2807
+ }
2808
+ }
2809
+
2810
+ static void minify_string(char **input, char **output) {
2811
+ (*output)[0] = (*input)[0];
2812
+ *input += static_strlen("\"");
2813
+ *output += static_strlen("\"");
2814
+
2815
+
2816
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2817
+ (*output)[0] = (*input)[0];
2818
+
2819
+ if ((*input)[0] == '\"') {
2820
+ (*output)[0] = '\"';
2821
+ *input += static_strlen("\"");
2822
+ *output += static_strlen("\"");
2823
+ return;
2824
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2825
+ (*output)[1] = (*input)[1];
2826
+ *input += static_strlen("\"");
2827
+ *output += static_strlen("\"");
2828
+ }
2829
+ }
2830
+ }
2831
+
2832
+ CJSON_PUBLIC(void) cJSON_Minify(char *json)
2833
+ {
2834
+ char *into = json;
2835
+
2836
+ if (json == NULL)
2837
+ {
2838
+ return;
2839
+ }
2840
+
2841
+ while (json[0] != '\0')
2842
+ {
2843
+ switch (json[0])
2844
+ {
2845
+ case ' ':
2846
+ case '\t':
2847
+ case '\r':
2848
+ case '\n':
2849
+ json++;
2850
+ break;
2851
+
2852
+ case '/':
2853
+ if (json[1] == '/')
2854
+ {
2855
+ skip_oneline_comment(&json);
2856
+ }
2857
+ else if (json[1] == '*')
2858
+ {
2859
+ skip_multiline_comment(&json);
2860
+ } else {
2861
+ json++;
2862
+ }
2863
+ break;
2864
+
2865
+ case '\"':
2866
+ minify_string(&json, (char**)&into);
2867
+ break;
2868
+
2869
+ default:
2870
+ into[0] = json[0];
2871
+ json++;
2872
+ into++;
2873
+ }
2874
+ }
2875
+
2876
+ /* and null-terminate. */
2877
+ *into = '\0';
2878
+ }
2879
+
2880
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2881
+ {
2882
+ if (item == NULL)
2883
+ {
2884
+ return false;
2885
+ }
2886
+
2887
+ return (item->type & 0xFF) == cJSON_Invalid;
2888
+ }
2889
+
2890
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2891
+ {
2892
+ if (item == NULL)
2893
+ {
2894
+ return false;
2895
+ }
2896
+
2897
+ return (item->type & 0xFF) == cJSON_False;
2898
+ }
2899
+
2900
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2901
+ {
2902
+ if (item == NULL)
2903
+ {
2904
+ return false;
2905
+ }
2906
+
2907
+ return (item->type & 0xff) == cJSON_True;
2908
+ }
2909
+
2910
+
2911
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2912
+ {
2913
+ if (item == NULL)
2914
+ {
2915
+ return false;
2916
+ }
2917
+
2918
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
2919
+ }
2920
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2921
+ {
2922
+ if (item == NULL)
2923
+ {
2924
+ return false;
2925
+ }
2926
+
2927
+ return (item->type & 0xFF) == cJSON_NULL;
2928
+ }
2929
+
2930
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2931
+ {
2932
+ if (item == NULL)
2933
+ {
2934
+ return false;
2935
+ }
2936
+
2937
+ return (item->type & 0xFF) == cJSON_Number;
2938
+ }
2939
+
2940
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2941
+ {
2942
+ if (item == NULL)
2943
+ {
2944
+ return false;
2945
+ }
2946
+
2947
+ return (item->type & 0xFF) == cJSON_String;
2948
+ }
2949
+
2950
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2951
+ {
2952
+ if (item == NULL)
2953
+ {
2954
+ return false;
2955
+ }
2956
+
2957
+ return (item->type & 0xFF) == cJSON_Array;
2958
+ }
2959
+
2960
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2961
+ {
2962
+ if (item == NULL)
2963
+ {
2964
+ return false;
2965
+ }
2966
+
2967
+ return (item->type & 0xFF) == cJSON_Object;
2968
+ }
2969
+
2970
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2971
+ {
2972
+ if (item == NULL)
2973
+ {
2974
+ return false;
2975
+ }
2976
+
2977
+ return (item->type & 0xFF) == cJSON_Raw;
2978
+ }
2979
+
2980
+ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2981
+ {
2982
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
2983
+ {
2984
+ return false;
2985
+ }
2986
+
2987
+ /* check if type is valid */
2988
+ switch (a->type & 0xFF)
2989
+ {
2990
+ case cJSON_False:
2991
+ case cJSON_True:
2992
+ case cJSON_NULL:
2993
+ case cJSON_Number:
2994
+ case cJSON_String:
2995
+ case cJSON_Raw:
2996
+ case cJSON_Array:
2997
+ case cJSON_Object:
2998
+ break;
2999
+
3000
+ default:
3001
+ return false;
3002
+ }
3003
+
3004
+ /* identical objects are equal */
3005
+ if (a == b)
3006
+ {
3007
+ return true;
3008
+ }
3009
+
3010
+ switch (a->type & 0xFF)
3011
+ {
3012
+ /* in these cases and equal type is enough */
3013
+ case cJSON_False:
3014
+ case cJSON_True:
3015
+ case cJSON_NULL:
3016
+ return true;
3017
+
3018
+ case cJSON_Number:
3019
+ if (compare_double(a->valuedouble, b->valuedouble))
3020
+ {
3021
+ return true;
3022
+ }
3023
+ return false;
3024
+
3025
+ case cJSON_String:
3026
+ case cJSON_Raw:
3027
+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
3028
+ {
3029
+ return false;
3030
+ }
3031
+ if (strcmp(a->valuestring, b->valuestring) == 0)
3032
+ {
3033
+ return true;
3034
+ }
3035
+
3036
+ return false;
3037
+
3038
+ case cJSON_Array:
3039
+ {
3040
+ cJSON *a_element = a->child;
3041
+ cJSON *b_element = b->child;
3042
+
3043
+ for (; (a_element != NULL) && (b_element != NULL);)
3044
+ {
3045
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3046
+ {
3047
+ return false;
3048
+ }
3049
+
3050
+ a_element = a_element->next;
3051
+ b_element = b_element->next;
3052
+ }
3053
+
3054
+ /* one of the arrays is longer than the other */
3055
+ if (a_element != b_element) {
3056
+ return false;
3057
+ }
3058
+
3059
+ return true;
3060
+ }
3061
+
3062
+ case cJSON_Object:
3063
+ {
3064
+ cJSON *a_element = NULL;
3065
+ cJSON *b_element = NULL;
3066
+ cJSON_ArrayForEach(a_element, a)
3067
+ {
3068
+ /* TODO This has O(n^2) runtime, which is horrible! */
3069
+ b_element = get_object_item(b, a_element->string, case_sensitive);
3070
+ if (b_element == NULL)
3071
+ {
3072
+ return false;
3073
+ }
3074
+
3075
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3076
+ {
3077
+ return false;
3078
+ }
3079
+ }
3080
+
3081
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
3082
+ * TODO: Do this the proper way, this is just a fix for now */
3083
+ cJSON_ArrayForEach(b_element, b)
3084
+ {
3085
+ a_element = get_object_item(a, b_element->string, case_sensitive);
3086
+ if (a_element == NULL)
3087
+ {
3088
+ return false;
3089
+ }
3090
+
3091
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
3092
+ {
3093
+ return false;
3094
+ }
3095
+ }
3096
+
3097
+ return true;
3098
+ }
3099
+
3100
+ default:
3101
+ return false;
3102
+ }
3103
+ }
3104
+
3105
+ CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3106
+ {
3107
+ return global_hooks.allocate(size);
3108
+ }
3109
+
3110
+ CJSON_PUBLIC(void) cJSON_free(void *object)
3111
+ {
3112
+ global_hooks.deallocate(object);
3113
+ }