libcouchbase 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +11 -8
  3. data/ext/libcouchbase/CMakeLists.txt +1 -1
  4. data/ext/libcouchbase/README.markdown +38 -6
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +151 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -2
  7. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  8. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  9. data/ext/libcouchbase/contrib/cJSON/cJSON.c +686 -288
  10. data/ext/libcouchbase/contrib/cJSON/cJSON.h +0 -0
  11. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +17 -17
  12. data/ext/libcouchbase/contrib/cliopts/cliopts.c +76 -0
  13. data/ext/libcouchbase/contrib/cliopts/cliopts.h +66 -15
  14. data/ext/libcouchbase/contrib/genhash/genhash.c +1 -2
  15. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4 -3
  16. data/ext/libcouchbase/example/instancepool/main.cc +12 -2
  17. data/ext/libcouchbase/example/libeventdirect/main.c +99 -25
  18. data/ext/libcouchbase/example/minimal/minimal.c +7 -5
  19. data/ext/libcouchbase/example/observe/durability.c +102 -0
  20. data/ext/libcouchbase/example/observe/observe.c +19 -6
  21. data/ext/libcouchbase/example/subdoc/subdoc-xattrs.c +1 -2
  22. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +6 -8
  23. data/ext/libcouchbase/include/libcouchbase/cntl.h +84 -64
  24. data/ext/libcouchbase/include/libcouchbase/couchbase.h +295 -78
  25. data/ext/libcouchbase/include/libcouchbase/deprecated.h +2 -2
  26. data/ext/libcouchbase/include/libcouchbase/error.h +1 -1
  27. data/ext/libcouchbase/include/libcouchbase/iops.h +9 -9
  28. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +2 -2
  29. data/ext/libcouchbase/include/libcouchbase/n1ql.h +69 -7
  30. data/ext/libcouchbase/include/libcouchbase/vbucket.h +17 -0
  31. data/ext/libcouchbase/include/libcouchbase/views.h +3 -3
  32. data/ext/libcouchbase/include/memcached/protocol_binary.h +62 -1
  33. data/ext/libcouchbase/packaging/deb/control +1 -1
  34. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +37 -36
  35. data/ext/libcouchbase/src/bootstrap.cc +22 -8
  36. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +1 -1
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +0 -1
  38. data/ext/libcouchbase/src/bucketconfig/confmon.cc +13 -8
  39. data/ext/libcouchbase/src/callbacks.c +2 -0
  40. data/ext/libcouchbase/src/cntl.cc +28 -17
  41. data/ext/libcouchbase/src/dns-srv.cc +1 -2
  42. data/ext/libcouchbase/src/dump.cc +4 -0
  43. data/ext/libcouchbase/src/errmap.h +89 -16
  44. data/ext/libcouchbase/src/handler.cc +28 -11
  45. data/ext/libcouchbase/src/http/http-priv.h +4 -1
  46. data/ext/libcouchbase/src/http/http.cc +3 -0
  47. data/ext/libcouchbase/src/instance.cc +1 -1
  48. data/ext/libcouchbase/src/internal.h +1 -0
  49. data/ext/libcouchbase/src/lcbio/connect.cc +2 -3
  50. data/ext/libcouchbase/src/lcbio/manager.cc +2 -2
  51. data/ext/libcouchbase/src/lcbio/ssl.h +10 -0
  52. data/ext/libcouchbase/src/mc/mcreq.c +8 -0
  53. data/ext/libcouchbase/src/mcserver/mcserver.cc +14 -1
  54. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +0 -3
  55. data/ext/libcouchbase/src/n1ql/n1ql.cc +22 -29
  56. data/ext/libcouchbase/src/n1ql/params.cc +46 -1
  57. data/ext/libcouchbase/src/newconfig.cc +4 -4
  58. data/ext/libcouchbase/src/operations/durability-seqno.cc +4 -0
  59. data/ext/libcouchbase/src/operations/durability.cc +3 -0
  60. data/ext/libcouchbase/src/operations/ping.cc +315 -0
  61. data/ext/libcouchbase/src/operations/stats.cc +10 -0
  62. data/ext/libcouchbase/src/operations/subdoc.cc +13 -1
  63. data/ext/libcouchbase/src/retrychk.cc +1 -0
  64. data/ext/libcouchbase/src/settings.c +2 -0
  65. data/ext/libcouchbase/src/settings.h +13 -7
  66. data/ext/libcouchbase/src/ssl/ssl_c.c +28 -2
  67. data/ext/libcouchbase/src/ssl/ssl_common.c +3 -0
  68. data/ext/libcouchbase/src/ssl/ssl_e.c +15 -1
  69. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +3 -1
  70. data/ext/libcouchbase/src/timings.c +0 -1
  71. data/ext/libcouchbase/src/vbucket/vbucket.c +49 -1
  72. data/ext/libcouchbase/tests/iotests/mock-environment.cc +58 -40
  73. data/ext/libcouchbase/tests/iotests/mock-environment.h +23 -4
  74. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +8 -8
  75. data/ext/libcouchbase/tests/iotests/t_behavior.cc +5 -5
  76. data/ext/libcouchbase/tests/iotests/t_durability.cc +50 -0
  77. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +4 -2
  78. data/ext/libcouchbase/tests/iotests/t_errmap.cc +6 -3
  79. data/ext/libcouchbase/tests/iotests/t_lock.cc +5 -6
  80. data/ext/libcouchbase/tests/iotests/t_misc.cc +44 -0
  81. data/ext/libcouchbase/tests/iotests/t_serverops.cc +1 -0
  82. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +28 -0
  83. data/ext/libcouchbase/tests/iotests/t_views.cc +22 -10
  84. data/ext/libcouchbase/tools/CMakeLists.txt +21 -1
  85. data/ext/libcouchbase/tools/cbc-handlers.h +23 -3
  86. data/ext/libcouchbase/tools/cbc-n1qlback.cc +1 -1
  87. data/ext/libcouchbase/tools/cbc-pillowfight.cc +126 -26
  88. data/ext/libcouchbase/tools/cbc-proxy.cc +403 -0
  89. data/ext/libcouchbase/tools/cbc-subdoc.cc +826 -0
  90. data/ext/libcouchbase/tools/cbc.cc +149 -37
  91. data/ext/libcouchbase/tools/common/options.h +5 -2
  92. data/ext/libcouchbase/tools/linenoise/linenoise.c +15 -15
  93. data/lib/libcouchbase.rb +4 -0
  94. data/lib/libcouchbase/bucket.rb +51 -0
  95. data/lib/libcouchbase/connection.rb +100 -13
  96. data/lib/libcouchbase/ext/libcouchbase.rb +40 -0
  97. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +13 -1
  98. data/lib/libcouchbase/ext/libcouchbase/enums.rb +2 -1
  99. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +5 -0
  100. data/lib/libcouchbase/subdoc_request.rb +129 -0
  101. data/lib/libcouchbase/version.rb +1 -1
  102. data/spec/bucket_spec.rb +15 -1
  103. data/spec/connection_spec.rb +1 -1
  104. data/spec/subdoc_spec.rb +192 -0
  105. metadata +13 -4
  106. data/ext/libcouchbase/.travis.yml +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35fe6cdbdb5c9b531318676b7d84d6f82dfc7a5c
4
- data.tar.gz: 4140f1a10bce79401304ed15794dbdabab7ae979
3
+ metadata.gz: be988dba6fcc3cad2ae5e6b5ee57be6382fab952
4
+ data.tar.gz: 7eba0fd2d3ec665e9373e308bd78405766670769
5
5
  SHA512:
6
- metadata.gz: b0f1994bd9ee6195b33419c7bfce7b5e0c2a46b9c5aa3126ca7e1e7663fa14d2b0764037a7b51d02f5228f36cd1667671746d2cda58a7a9849e62da553d35fde
7
- data.tar.gz: 1ae07ed59cfb4c90286e870b70b0d0c3cb18a7a74b41d98773646325fcfaf7727fb65cceb283ffada8a3959fa850f74c9f745b21c64d55fd42bf86bb64f27ecd
6
+ metadata.gz: 386f1456c6853cae5766041ee2ee988703cf1f71d4d4d5974ebbc00ee887f44f6b0a8689144b83bc2b9c13df573b262ecd281cc1fa57e817904544ef96576889
7
+ data.tar.gz: 7a37eecb3b1bbb3c761fc21f68a4eb6c5a7974e32624642f49de9a89b3e84581444cb40e13f970f66774c57fee977f3d4215a9bbefd4577ade7f4e867d8d1784
data/.travis.yml CHANGED
@@ -1,28 +1,30 @@
1
1
  language: ruby
2
2
  rvm:
3
- - ruby-2.4.1
4
- - ruby-2.3.4
3
+ - ruby-2.4.2
4
+ - ruby-2.3.5
5
5
  - ruby-head
6
- - jruby-9.1.10.0
6
+ - jruby-9.1.13.0
7
7
  - jruby-head
8
8
  - rubinius
9
- - rubinius-3.78
9
+ - rubinius-3.86
10
10
  branches:
11
11
  only:
12
12
  - master
13
13
  before_install:
14
14
  - git submodule update --init --recursive
15
15
  - gem install ffi
16
- - sudo apt-get install libev-dev
17
- - sudo wget https://packages.couchbase.com/releases/4.6.2/couchbase-server-enterprise_4.6.2-ubuntu14.04_amd64.deb
18
- - sudo dpkg -i couchbase-server-enterprise_4.6.2-ubuntu14.04_amd64.deb
16
+ - sudo apt-get install libev-dev python-httplib2
17
+ - sudo wget https://packages.couchbase.com/releases/5.0.0/couchbase-server-enterprise_5.0.0-ubuntu14.04_amd64.deb
18
+ - sudo dpkg -i couchbase-server-enterprise_5.0.0-ubuntu14.04_amd64.deb
19
19
  - sleep 4
20
20
  - sudo service couchbase-server status
21
21
  - /opt/couchbase/bin/couchbase-cli cluster-init -c 127.0.0.1:8091 --cluster-username=admin --cluster-password=password --cluster-ramsize=320 --cluster-index-ramsize=256 --cluster-fts-ramsize=256 --services=data,index,query,fts
22
22
  - sleep 4
23
23
  - /opt/couchbase/bin/couchbase-cli server-info -c 127.0.0.1:8091 -u admin -p password
24
24
  - /opt/couchbase/bin/couchbase-cli bucket-create -c 127.0.0.1:8091 -u admin -p password --bucket=default --bucket-type=couchbase --bucket-ramsize=160 --bucket-replica=0 --wait
25
- - /opt/couchbase/bin/couchbase-cli bucket-create -c 127.0.0.1:8091 -u admin -p password --bucket=test --bucket-type=couchbase --bucket-ramsize=160 --bucket-replica=0 --bucket-password=password123 --enable-flush=1 --wait
25
+ - /opt/couchbase/bin/couchbase-cli bucket-create -c 127.0.0.1:8091 -u admin -p password --bucket=test --bucket-type=couchbase --bucket-ramsize=160 --bucket-replica=0 --enable-flush=1 --wait
26
+ - sleep 1
27
+ - /opt/couchbase/bin/couchbase-cli user-manage -c 127.0.0.1:8091 -u admin -p password --set --rbac-username tester --rbac-password password123 --rbac-name "Auto Tester" --roles admin --auth-domain local
26
28
  - /opt/couchbase/bin/cbrestore -x rehash=1 -b default -B default -u admin -p password ./spec/seed http://127.0.0.1:8091
27
29
  before_script:
28
30
  - rake compile
@@ -31,5 +33,6 @@ matrix:
31
33
  - rvm: jruby-head
32
34
  - rvm: ruby-head
33
35
  - rvm: rubinius
36
+ - rvm: rubinius-3.86
34
37
  sudo: required
35
38
  dist: trusty
@@ -21,7 +21,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.9)
21
21
  # These variables can be modified as needed
22
22
 
23
23
  # Couchbase mock path to download
24
- SET(COUCHBASE_MOCK_VERSION CouchbaseMock-LATEST.jar)
24
+ SET(COUCHBASE_MOCK_VERSION CouchbaseMock-1.5.12.jar)
25
25
  # Maven repository where ${COUCHBASE_MOCK_VERSION} is to be found
26
26
  SET(COUCHBASE_MOCK_DLSERVER http://packages.couchbase.com/clients/c/mock)
27
27
  project(libcouchbase)
@@ -1,7 +1,5 @@
1
1
  # Couchbase C Client
2
2
 
3
- [![Build Status](https://travis-ci.org/couchbase/libcouchbase.png?branch=master)](https://travis-ci.org/couchbase/libcouchbase)
4
-
5
3
  This is the C client library for [Couchbase](http://www.couchbase.com)
6
4
  It communicates with the cluster and speaks the relevant protocols
7
5
  necessary to connect to the cluster and execute data operations.
@@ -23,7 +21,7 @@ necessary to connect to the cluster and execute data operations.
23
21
  ## Building
24
22
 
25
23
  Before you build from this repository, please check the
26
- [installation page](http://developer.couchbase.com/server/other-products/release-notes-archives/c-sdk)
24
+ [installation page](https://developer.couchbase.com/server/other-products/release-notes-archives/c-sdk)
27
25
  to see if there is a binary or release tarball available for your needs. Since the code here is
28
26
  not part of an official release it has therefore not gone through our
29
27
  release testing process.
@@ -76,6 +74,40 @@ If you wish to link against OpenSSL, you should set the value of
76
74
  `OPENSSL_ROOT_DIR` to the location of the installation path, as described
77
75
  [here](https://github.com/Kitware/CMake/blob/master/Modules/FindOpenSSL.cmake)
78
76
 
77
+ ## Running tests
78
+
79
+ To run tests, you can use either ctest directly or generated build targets.
80
+ For Unix-like:
81
+
82
+ ```shell
83
+ make test
84
+ ```
85
+
86
+ For windows:
87
+
88
+ ```batchfile
89
+ cmake --build . --target alltests
90
+ ctest -C debug
91
+ ```
92
+
93
+ By default tests will use [CouchbaseMock](https://github.com/couchbase/CouchbaseMock) project to simulate the Couchbase
94
+ Cluster. It allows to cover more different failure scenarios, although does not implement all kinds of APIs provided
95
+ by real server.
96
+
97
+ If you need to test against real server, you have to provide comma-separated configuration in `LCB_TEST_CLUSTER_CONF`
98
+ environment variable. For example, the following command will run tests against local cluster and bucket `default` using
99
+ administrator credentials:
100
+
101
+ ```shell
102
+ export LCB_TEST_CLUSTER_CONF=couchbase://localhost,default,Administrator,password
103
+ make test
104
+ ```
105
+ Note that specifying username will automatically switch to RBAC mode, which supported by Couchbase Server 5.0+. For old
106
+ servers the spec will look like `couchbase://localhost,default` or `couchbase://localhost,protected,,secret`.
107
+
108
+ Also tests expecting `beer-sample` bucket loaded. It comes with the server. Look at "Sample buckets" section of Admin
109
+ Console.
110
+
79
111
  ## Bugs, Support, Issues
80
112
  You may report issues in the library in our issue tracked at
81
113
  <https://issues.couchbase.com>. Sign up for an account and file an issue
@@ -91,18 +123,18 @@ irc.freenode.net.
91
123
  * Official client libraries using libcouchbase
92
124
  * [node.js](http://github.com/couchbase/couchnode)
93
125
  * [Python](http://github.com/couchbase/couchbase-python-client)
94
- * [Ruby](http://github.com/couchbase/couchbase-ruby-client) (uses the old < 2.6 API)
95
- * [PHP](http://github.com/couchbase/php-couchbase) (uses the old < 2.6 API)
126
+ * [PHP](http://github.com/couchbase/php-couchbase)
96
127
  * Community projects using libcouchbase
97
128
  * [C++11 wrapper](https://github.com/couchbaselabs/libcouchbase-cxx)
98
129
  * [cberl - Couchbase NIF](https://github.com/wcummings/cberl)
99
130
  * [Perl client](https://github.com/mnunberg/perl-Couchbase-Client)
131
+ * [Ruby](http://github.com/couchbase/couchbase-ruby-client) (uses the old < 2.6 API)
100
132
 
101
133
  ## Documentation
102
134
 
103
135
  Documentation is available in guide format (introducing the basic concepts of
104
136
  Couchbase and the library). It is recommended for first-time users, and can
105
- be accessed at our [Documentation Site](http://developer.couchbase.com/documentation/server/4.5/sdk/c/start-using-sdk.html).
137
+ be accessed at our [Documentation Site](https://developer.couchbase.com/documentation/server/current/sdk/c/start-using-sdk.html).
106
138
 
107
139
  API documentation is also available and is generated from the library's headers.
108
140
  It may contain references to more advanced features not found in the guide.
@@ -1,5 +1,156 @@
1
1
  # Release Notes
2
2
 
3
+ ## 2.8.2 (October 17 2017)
4
+
5
+ * [CCBC-833](https://issues.couchbase.com/browse/CCBC-833), [CCBC-834](https://issues.couchbase.com/browse/CCBC-834):
6
+ Update real cluster integration in the test suite.
7
+
8
+ * [CCBC-860](https://issues.couchbase.com/browse/CCBC-860): cbc-connstr: Do not zero out C++ instances.
9
+
10
+ * [CCBC-859](https://issues.couchbase.com/browse/CCBC-859): Fix libm shared object detection on Debian 9.
11
+
12
+ * Bugs reported by [clang analyzer](http://clang-analyzer.llvm.org/):
13
+
14
+ * [CCBC-858](https://issues.couchbase.com/browse/CCBC-858): Fix memory leak for compressed packet.
15
+ * [CCBC-857](https://issues.couchbase.com/browse/CCBC-857): Fix possible NULL pointer dereference in `mcreq_reserve_key`.
16
+ * [CCBC-856](https://issues.couchbase.com/browse/CCBC-856): Initialize response struct in `H_config`.
17
+ * [CCBC-855](https://issues.couchbase.com/browse/CCBC-855): Fix dead assignments in `contrib/genhash`.
18
+ * [CCBC-854](https://issues.couchbase.com/browse/CCBC-854): Init vbguess array before entry lookup.
19
+ * [CCBC-853](https://issues.couchbase.com/browse/CCBC-853): cbc-proxy: do not use client object after free.
20
+ * [CCBC-852](https://issues.couchbase.com/browse/CCBC-852): Do not free memory twice in N1QL index manager.
21
+
22
+ ## 2.8.1 (September 20 2017)
23
+
24
+ * Check nodes number for durability checks. The store with durability
25
+ requirements will report more specific error when the library cannot
26
+ fulfill the condition during failover.
27
+ * Issues: [CCBC-817](https://issues.couchbase.com/browse/CCBC-817)
28
+
29
+ * Handle enhanced error messages for subdoc operations. The subdoc
30
+ responses will now expose context and reference ID if present.
31
+ * Issues: [CCBC-846](https://issues.couchbase.com/browse/CCBC-846)
32
+
33
+ * Discover and bootstrap analytics service from cluster configuration.
34
+ * Issues: [CCBC-840](https://issues.couchbase.com/browse/CCBC-840)
35
+
36
+ * Improve documentation of configuration parameters.
37
+ * Issues: [CCBC-835](https://issues.couchbase.com/browse/CCBC-835)
38
+
39
+ * Enable Error Map feature by default.
40
+ * Issues: [CCBC-838](https://issues.couchbase.com/browse/CCBC-838)
41
+
42
+ * Cleanup and extend `minimal`, `libeventdirect`, `instancepool` examples
43
+
44
+ * Tools:
45
+ * improve error reporting
46
+ * experimental subcommand `cbc-proxy`
47
+ * fix memory leaks
48
+ * retry store operations during population phase in `cbc-pillowfight`
49
+
50
+ ## 2.8.0 (August 31 2017)
51
+
52
+ * Add support for OpenSSL-1.1.
53
+ * Issues: [CCBC-814](https://issues.couchbase.com/browse/CCBC-814)
54
+
55
+ * Mask `LOCKED` status code for backward compatibility. This code
56
+ (as well as others possible codes with 'item-locked' attribute)
57
+ replaced with `LCB_KEY_EEXISTS` for `SET`, `REPLACE` and `DELETE`
58
+ operations, and with `LCB_ETMPFAIL` for the rest.
59
+ * Issues: [CCBC-832](https://issues.couchbase.com/browse/CCBC-832)
60
+
61
+ * Stop enumerating bootstrap nodes and mechanisms when the server
62
+ returns authentication error.
63
+ * Issues: [CCBC-825](https://issues.couchbase.com/browse/CCBC-825)
64
+
65
+ * Fixed double free error with `lcb_ping3`.
66
+ * Issues: [CCBC-826](https://issues.couchbase.com/browse/CCBC-826)
67
+
68
+ * Exposed additional N1QL query parameters: `lcb_n1p_readonly`,
69
+ `lcb_n1p_scancap`, `lcb_n1p_pipelinecap`.
70
+ * Issues: [CCBC-823](https://issues.couchbase.com/browse/CCBC-823)
71
+
72
+ * Fixed `cbc-subdoc/upsert` without XATTR.
73
+ * Issues: [CCBC-823](https://issues.couchbase.com/browse/CCBC-823)
74
+
75
+ * XERROR attributes synchronized with recent list on server.
76
+ * Issues: [CCBC-828](https://issues.couchbase.com/browse/CCBC-828)
77
+
78
+ * Add missing documentation, and update stability of the API.
79
+ * Issues:
80
+ [CCBC-830](https://issues.couchbase.com/browse/CCBC-830),
81
+ [CCBC-831](https://issues.couchbase.com/browse/CCBC-831),
82
+ [CCBC-827](https://issues.couchbase.com/browse/CCBC-827)
83
+
84
+ * Do not throttle background configuration polling by throttle interval
85
+ of configuration error handler.
86
+ * Issues: [CCBC-829](https://issues.couchbase.com/browse/CCBC-829)
87
+
88
+ * Turn on background polling by default. The library will try
89
+ to schedule configuration update every 2.5 seconds. To disable it
90
+ use `config_poll_interval=0`.
91
+ * Issues: [CCBC-836](https://issues.couchbase.com/browse/CCBC-836)
92
+
93
+ ## 2.7.7 (August 17 2017)
94
+
95
+ * Implement new function `lcb_ping3`, which sends NOOP-like message to
96
+ each service in the cluster and allows to measure latency along with
97
+ health status of the connection. Might be useful for application-side
98
+ keep-alive mechanisms.
99
+ * Issues: [CCBC-801](https://issues.couchbase.com/browse/CCBC-801)
100
+
101
+ * Detect and expose bucket type through `LCB_CNTL_BUCKETTYPE`:
102
+
103
+ lcb_BTYPE type;
104
+ lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_BUCKETTYPE, &type);
105
+
106
+ * Issues: [CCBC-790](https://issues.couchbase.com/browse/CCBC-790)
107
+
108
+ * Fixed setting expiration in subdoc mutations.
109
+ * Issues: [CCBC-799](https://issues.couchbase.com/browse/CCBC-816)
110
+
111
+ * Fixed DNS SRV support of Fedora 26 and FreeBSD.
112
+ * Issues: [CCBC-816](https://issues.couchbase.com/browse/CCBC-816)
113
+
114
+ * Fixed DNS SRV with SSL connections.
115
+ * Issues: [CCBC-794](https://issues.couchbase.com/browse/CCBC-794)
116
+
117
+ * Define EREMOTEIO in libuv
118
+ * Issues: [CCBC-812](https://issues.couchbase.com/browse/CCBC-812)
119
+
120
+ * New subdocument command to remove whole document
121
+ * Issues: [CCBC-811](https://issues.couchbase.com/browse/CCBC-811)
122
+
123
+ * New cbc command: `cbc-subdoc`. It provides interactive shell, where
124
+ all subdocument commands accessible to inspect and modify documents
125
+ in the cluster.
126
+
127
+ * New cbc command: `cbc-ping`. It sends NOOP-like messages to all accessible
128
+ services in the cluster, and displays the status along with latency.
129
+ * Issues: [CCBC-801](https://issues.couchbase.com/browse/CCBC-801)
130
+
131
+ * Fix `cbc-cat --replica`, which now allows reading documents from replicas.
132
+ * Issues: [CCBC-820](https://issues.couchbase.com/browse/CCBC-820)
133
+
134
+ * Implement NOOP command and `cbc-pillowfight --noop`, which sends NOOP
135
+ instead of data manipulation commands.
136
+ * Issues: [CCBC-801](https://issues.couchbase.com/browse/CCBC-801)
137
+
138
+ * Clarify errors found in `.cbcrc`. Now it will display configuration path
139
+ along with error message.
140
+ * Issues: [CCBC-759](https://issues.couchbase.com/browse/CCBC-759]
141
+
142
+ * Update examples:
143
+ * Support username/password in subdoc and libeventdirect examples
144
+ * Added example for subdoc XATTRs
145
+
146
+ * Integrate fix for parallel build with dtrace on FreeBSD
147
+ https://github.com/freebsd/freebsd-ports/commit/a71e1a86b851d42cd08319d9b28a4424e508e216
148
+
149
+ * Make enhanced errors API public
150
+ * Issues: [CCBC-803](https://issues.couchbase.com/browse/CCBC-803)
151
+
152
+ * Fixed various compiler and cppcheck warnings and documentation update.
153
+
3
154
  ## 2.7.6 (July 11 2017)
4
155
 
5
156
  * Expose enhanced errors for data commands. Couchbase Server 5 might return
@@ -9,7 +9,7 @@ IF(UNIX)
9
9
  CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME)
10
10
  CHECK_FUNCTION_EXISTS(setitimer HAVE_SETITIMER)
11
11
  CHECK_SYMBOL_EXISTS(htonll arpa/inet.h HAVE_HTONLL)
12
- CHECK_SYMBOL_EXISTS(res_search resolv.h HAVE_RES_SEARCH)
12
+ CHECK_SYMBOL_EXISTS(res_search "netinet/in.h;resolv.h" HAVE_RES_SEARCH)
13
13
  CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H)
14
14
  CHECK_INCLUDE_FILES(netdb.h HAVE_NETDB_H)
15
15
  CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H)
@@ -36,7 +36,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux")
36
36
  OUTPUT_VARIABLE LIBM_SO_TRACE
37
37
  ERROR_QUIET
38
38
  OUTPUT_STRIP_TRAILING_WHITESPACE)
39
- STRING(REGEX MATCH [a-z0-9/]+libm.so[.0-9]* LIBM_SO_PATH ${LIBM_SO_TRACE})
39
+ STRING(REGEX MATCH [-_a-z0-9/]+libm.so[.0-9]* LIBM_SO_PATH ${LIBM_SO_TRACE})
40
40
  IF (EXISTS "${LIBM_SO_PATH}")
41
41
  GET_FILENAME_COMPONENT(CMAKE_TEST_SHARED_OBJECT ${LIBM_SO_PATH} NAME)
42
42
  ENDIF()
@@ -42,13 +42,13 @@ ENDIF()
42
42
 
43
43
  IF (NOT LCB_VERSION)
44
44
  SET(LCB_NOGITVERSION ON)
45
- SET(LCB_VERSION "2.7.6")
45
+ SET(LCB_VERSION "2.8.2")
46
46
  ENDIF()
47
47
  IF (NOT LCB_VERSION_CHANGESET)
48
48
  SET(LCB_VERSION_CHANGESET "0xdeadbeef")
49
49
  ENDIF()
50
50
  IF (NOT LCB_VERSION_HEX)
51
- SET(LCB_VERSION_HEX 0x020706)
51
+ SET(LCB_VERSION_HEX 0x020802)
52
52
  ENDIF()
53
53
 
54
54
  # Now parse the version string
@@ -63,7 +63,7 @@ IF(APPLE)
63
63
  ELSE()
64
64
  SET(LCB_SONAME_MAJOR "2")
65
65
  ENDIF()
66
- SET(LCB_SONAME_FULL "${LCB_SONAME_MAJOR}.0.46")
66
+ SET(LCB_SONAME_FULL "${LCB_SONAME_MAJOR}.0.50")
67
67
 
68
68
  MESSAGE(STATUS
69
69
  "libcouchbase ${LCB_VERSION_MAJOR},${LCB_VERSION_MINOR},${LCB_VERSION_PATCH}")
@@ -84,6 +84,7 @@ SET(LCB_CORE_CXXSRC
84
84
  src/operations/store.cc
85
85
  src/operations/subdoc.cc
86
86
  src/operations/touch.cc
87
+ src/operations/ping.cc
87
88
  src/mcserver/mcserver.cc
88
89
  src/mcserver/negotiate.cc
89
90
  src/retrychk.cc
@@ -33,28 +33,34 @@
33
33
  #include <assert.h>
34
34
  #include "cJSON.h"
35
35
 
36
- static int cJSON_strcasecmp(const char *s1,const char *s2)
36
+ static int cJSON_strcasecmp(const char *s1, const char *s2)
37
37
  {
38
- if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
39
- for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
38
+ if (!s1)
39
+ return (s1 == s2) ? 0 : 1;
40
+ if (!s2)
41
+ return 1;
42
+ for (; tolower(*s1) == tolower(*s2); ++s1, ++s2)
43
+ if (*s1 == 0)
44
+ return 0;
40
45
  return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
41
46
  }
42
47
 
43
48
  static void *(*cJSON_malloc)(size_t sz) = malloc;
44
49
  static void (*cJSON_free)(void *ptr) = free;
45
50
 
46
- static char* cJSON_strdup(const char* str)
51
+ static char *cJSON_strdup(const char *str)
47
52
  {
48
- size_t len;
49
- char* copy;
53
+ size_t len;
54
+ char *copy;
50
55
 
51
- len = strlen(str) + 1;
52
- if (!(copy = (char*)cJSON_malloc(len))) return 0;
53
- memcpy(copy,str,len);
54
- return copy;
56
+ len = strlen(str) + 1;
57
+ if (!(copy = (char *)cJSON_malloc(len)))
58
+ return 0;
59
+ memcpy(copy, str, len);
60
+ return copy;
55
61
  }
56
62
 
57
- void cJSON_InitHooks(cJSON_Hooks* hooks)
63
+ void cJSON_InitHooks(cJSON_Hooks *hooks)
58
64
  {
59
65
  if (!hooks) { /* Reset hooks */
60
66
  cJSON_malloc = malloc;
@@ -62,8 +68,8 @@ void cJSON_InitHooks(cJSON_Hooks* hooks)
62
68
  return;
63
69
  }
64
70
 
65
- cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
66
- cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
71
+ cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
72
+ cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
67
73
  }
68
74
 
69
75
  /* The size of pool allocation groups. Note that the allocation
@@ -72,7 +78,7 @@ void cJSON_InitHooks(cJSON_Hooks* hooks)
72
78
  evidence of best performance with Couchbase configuration
73
79
  data */
74
80
  #ifndef CJSON_POOL_ALLOC_SIZE
75
- #define CJSON_POOL_ALLOC_SIZE 1024
81
+ #define CJSON_POOL_ALLOC_SIZE 1024
76
82
  #endif
77
83
 
78
84
  /* Creates a new allocation pool. */
@@ -86,21 +92,19 @@ static cJSON_PoolBlock *cJSON_New_PoolBlock(cJSON_Pool *pool)
86
92
  return 0;
87
93
  }
88
94
 
89
- new_block = (cJSON_PoolBlock*)cJSON_malloc(
90
- sizeof(cJSON_PoolBlock) + sizeof(cJSON)*CJSON_POOL_ALLOC_SIZE);
95
+ new_block = (cJSON_PoolBlock *)cJSON_malloc(sizeof(cJSON_PoolBlock) + sizeof(cJSON) * CJSON_POOL_ALLOC_SIZE);
91
96
  if (!new_block) {
92
97
  return 0;
93
98
  }
94
99
 
95
- new_alloc = (cJSON*)(new_block+1);
100
+ new_alloc = (cJSON *)(new_block + 1);
96
101
 
97
- memset(new_block, 0,
98
- sizeof(cJSON_PoolBlock) + sizeof(cJSON)*CJSON_POOL_ALLOC_SIZE);
102
+ memset(new_block, 0, sizeof(cJSON_PoolBlock) + sizeof(cJSON) * CJSON_POOL_ALLOC_SIZE);
99
103
 
100
104
  new_block->next = pool->blocks;
101
105
  pool->blocks = new_block;
102
106
 
103
- for (i=0, item=new_alloc; i<CJSON_POOL_ALLOC_SIZE; ++i, ++item) {
107
+ for (i = 0, item = new_alloc; i < CJSON_POOL_ALLOC_SIZE; ++i, ++item) {
104
108
  item->next = pool->free_items;
105
109
  pool->free_items = item;
106
110
  }
@@ -109,12 +113,12 @@ static cJSON_PoolBlock *cJSON_New_PoolBlock(cJSON_Pool *pool)
109
113
  }
110
114
 
111
115
  /* This will create an allocation pool */
112
- static cJSON_Pool * cJSON_New_Pool(void)
116
+ static cJSON_Pool *cJSON_New_Pool(void)
113
117
  {
114
118
  if (CJSON_POOL_ALLOC_SIZE <= 0) {
115
119
  return 0;
116
120
  } else {
117
- cJSON_Pool * pool = (cJSON_Pool*)cJSON_malloc(sizeof(cJSON_Pool));
121
+ cJSON_Pool *pool = (cJSON_Pool *)cJSON_malloc(sizeof(cJSON_Pool));
118
122
  if (!pool) {
119
123
  return 0;
120
124
  }
@@ -175,14 +179,14 @@ static void cJSON_Pool_Free_Item(cJSON_Pool *pool, cJSON *node)
175
179
  /* Internal constructor. */
176
180
  static cJSON *cJSON_New_Item(cJSON *parent)
177
181
  {
178
- cJSON* node = 0;
182
+ cJSON *node = 0;
179
183
  if (parent && parent->alloc_pool) {
180
184
  node = cJSON_Pool_New_Item(parent->alloc_pool);
181
185
  }
182
186
  if (!node) {
183
- node = (cJSON*)cJSON_malloc(sizeof(cJSON));
187
+ node = (cJSON *)cJSON_malloc(sizeof(cJSON));
184
188
  if (node) {
185
- memset(node,0,sizeof(cJSON));
189
+ memset(node, 0, sizeof(cJSON));
186
190
  }
187
191
  }
188
192
  return node;
@@ -202,37 +206,56 @@ static void cJSON_Free_Item(cJSON *node)
202
206
  void cJSON_Delete(cJSON *c)
203
207
  {
204
208
  cJSON *next;
205
- while (c)
206
- {
207
- next=c->next;
208
- if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
209
- if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
210
- if (c->string) cJSON_free(c->string);
209
+ while (c) {
210
+ next = c->next;
211
+ if (!(c->type & cJSON_IsReference) && c->child)
212
+ cJSON_Delete(c->child);
213
+ if (!(c->type & cJSON_IsReference) && c->valuestring)
214
+ cJSON_free(c->valuestring);
215
+ if (c->string)
216
+ cJSON_free(c->string);
211
217
  cJSON_Free_Item(c);
212
- c=next;
218
+ c = next;
213
219
  }
214
220
  }
215
221
 
216
222
  /* Parse the input text to generate a number, and populate the result into item. */
217
- static const char *parse_number(cJSON *item,const char *num)
223
+ static const char *parse_number(cJSON *item, const char *num)
218
224
  {
219
- double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
225
+ double n = 0, sign = 1, scale = 0;
226
+ int subscale = 0, signsubscale = 1;
220
227
 
221
228
  /* Could use sscanf for this? */
222
- if (*num=='-') sign=-1,num++; /* Has sign? */
223
- if (*num=='0') num++; /* is zero */
224
- if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
225
- if (*num=='.') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
226
- if (*num=='e' || *num=='E') /* Exponent? */
227
- { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
228
- while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
229
+ if (*num == '-')
230
+ sign = -1, num++; /* Has sign? */
231
+ if (*num == '0')
232
+ num++; /* is zero */
233
+ if (*num >= '1' && *num <= '9')
234
+ do
235
+ n = (n * 10.0) + (*num++ - '0');
236
+ while (*num >= '0' && *num <= '9'); /* Number? */
237
+ if (*num == '.') {
238
+ num++;
239
+ do
240
+ n = (n * 10.0) + (*num++ - '0'), scale--;
241
+ while (*num >= '0' && *num <= '9');
242
+ } /* Fractional part? */
243
+ if (*num == 'e' || *num == 'E') /* Exponent? */
244
+ {
245
+ num++;
246
+ if (*num == '+')
247
+ num++;
248
+ else if (*num == '-')
249
+ signsubscale = -1, num++; /* With sign? */
250
+ while (*num >= '0' && *num <= '9')
251
+ subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
229
252
  }
230
253
 
231
- n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
254
+ n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
232
255
 
233
- item->valuedouble=n;
234
- item->valueint=(int)n;
235
- item->type=cJSON_Number;
256
+ item->valuedouble = n;
257
+ item->valueint = (int)n;
258
+ item->type = cJSON_Number;
236
259
  return num;
237
260
  }
238
261
 
@@ -240,117 +263,180 @@ static const char *parse_number(cJSON *item,const char *num)
240
263
  static char *print_number(cJSON *item)
241
264
  {
242
265
  char *str;
243
- double d=item->valuedouble;
244
- if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
245
- {
246
- str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
247
- sprintf(str,"%d",item->valueint);
248
- }
249
- else
250
- {
251
- str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
252
- if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
253
- else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
254
- else sprintf(str,"%f",d);
266
+ double d = item->valuedouble;
267
+ if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
268
+ str = (char *)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
269
+ sprintf(str, "%d", item->valueint);
270
+ } else {
271
+ str = (char *)cJSON_malloc(64); /* This is a nice tradeoff. */
272
+ if (fabs(floor(d) - d) <= DBL_EPSILON)
273
+ sprintf(str, "%.0f", d);
274
+ else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
275
+ sprintf(str, "%e", d);
276
+ else
277
+ sprintf(str, "%f", d);
255
278
  }
256
279
  return str;
257
280
  }
258
281
 
259
282
  /* Parse the input text into an unescaped cstring, and populate item. */
260
- static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
261
- static const char *parse_string(cJSON *item,const char *str)
283
+ static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
284
+ static const char *parse_string(cJSON *item, const char *str)
262
285
  {
263
- const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
264
- if (*str!='\"') return 0; /* not a string! */
265
-
266
- while (*ptr!='\"' && (unsigned char)*ptr>31 && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
267
-
268
- out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
269
- if (!out) return 0;
286
+ const char *ptr = str + 1;
287
+ char *ptr2;
288
+ char *out;
289
+ int len = 0;
290
+ unsigned uc;
291
+ if (*str != '\"')
292
+ return 0; /* not a string! */
293
+
294
+ while (*ptr != '\"' && (unsigned char)*ptr > 31 && ++len)
295
+ if (*ptr++ == '\\')
296
+ ptr++; /* Skip escaped quotes. */
297
+
298
+ out = (char *)cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */
299
+ if (!out)
300
+ return 0;
270
301
 
271
- ptr=str+1;ptr2=out;
272
- while (*ptr!='\"' && (unsigned char)*ptr>31)
273
- {
274
- if (*ptr!='\\') *ptr2++=*ptr++;
275
- else
276
- {
302
+ ptr = str + 1;
303
+ ptr2 = out;
304
+ while (*ptr != '\"' && (unsigned char)*ptr > 31) {
305
+ if (*ptr != '\\')
306
+ *ptr2++ = *ptr++;
307
+ else {
277
308
  ptr++;
278
- switch (*ptr)
279
- {
280
- case 'b': *ptr2++='\b'; break;
281
- case 'f': *ptr2++='\f'; break;
282
- case 'n': *ptr2++='\n'; break;
283
- case 'r': *ptr2++='\r'; break;
284
- case 't': *ptr2++='\t'; break;
285
- case 'u': /* transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. */
286
- sscanf(ptr+1,"%4x",&uc); /* get the unicode char. */
287
- len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
309
+ switch (*ptr) {
310
+ case 'b':
311
+ *ptr2++ = '\b';
312
+ break;
313
+ case 'f':
314
+ *ptr2++ = '\f';
315
+ break;
316
+ case 'n':
317
+ *ptr2++ = '\n';
318
+ break;
319
+ case 'r':
320
+ *ptr2++ = '\r';
321
+ break;
322
+ case 't':
323
+ *ptr2++ = '\t';
324
+ break;
325
+ case 'u': /* transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. */
326
+ sscanf(ptr + 1, "%4x", &uc); /* get the unicode char. */
327
+ len = 3;
328
+ if (uc < 0x80)
329
+ len = 1;
330
+ else if (uc < 0x800)
331
+ len = 2;
332
+ ptr2 += len;
288
333
 
289
334
  switch (len) {
290
- case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
291
- case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
292
- case 1: *--ptr2 =(uc | firstByteMark[len]);
335
+ case 3:
336
+ *--ptr2 = ((uc | 0x80) & 0xBF);
337
+ uc >>= 6; /* fall through */
338
+ case 2:
339
+ *--ptr2 = ((uc | 0x80) & 0xBF);
340
+ uc >>= 6; /* fall through */
341
+ case 1:
342
+ *--ptr2 = (uc | firstByteMark[len]); /* fall through */
293
343
  }
294
- ptr2+=len;ptr+=4;
344
+ ptr2 += len;
345
+ ptr += 4;
346
+ break;
347
+ default:
348
+ *ptr2++ = *ptr;
295
349
  break;
296
- default: *ptr2++=*ptr; break;
297
350
  }
298
351
  ptr++;
299
352
  }
300
353
  }
301
- *ptr2=0;
302
- if (*ptr=='\"') ptr++;
303
- item->valuestring=out;
304
- item->type=cJSON_String;
354
+ *ptr2 = 0;
355
+ if (*ptr == '\"')
356
+ ptr++;
357
+ item->valuestring = out;
358
+ item->type = cJSON_String;
305
359
  return ptr;
306
360
  }
307
361
 
308
362
  /* Render the cstring provided to an escaped version that can be printed. */
309
363
  static char *print_string_ptr(const char *str)
310
364
  {
311
- const char *ptr;char *ptr2,*out;int len=0;
312
-
313
- if (!str) return cJSON_strdup("");
314
- ptr=str;while (*ptr && ++len) {if ((unsigned char)*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
365
+ const char *ptr;
366
+ char *ptr2, *out;
367
+ int len = 0;
368
+
369
+ if (!str)
370
+ return cJSON_strdup("");
371
+ ptr = str;
372
+ while (*ptr && ++len) {
373
+ if ((unsigned char)*ptr < 32 || *ptr == '\"' || *ptr == '\\')
374
+ len++;
375
+ ptr++;
376
+ }
315
377
 
316
- out=(char*)cJSON_malloc(len+3);
317
- ptr2=out;ptr=str;
318
- *ptr2++='\"';
319
- while (*ptr)
320
- {
321
- if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
322
- else
323
- {
324
- *ptr2++='\\';
325
- switch (*ptr++)
326
- {
327
- case '\\': *ptr2++='\\'; break;
328
- case '\"': *ptr2++='\"'; break;
329
- case '\b': *ptr2++='b'; break;
330
- case '\f': *ptr2++='f'; break;
331
- case '\n': *ptr2++='n'; break;
332
- case '\r': *ptr2++='r'; break;
333
- case '\t': *ptr2++='t'; break;
334
- default: ptr2--; break; /* eviscerate with prejudice. */
378
+ out = (char *)cJSON_malloc(len + 3);
379
+ ptr2 = out;
380
+ ptr = str;
381
+ *ptr2++ = '\"';
382
+ while (*ptr) {
383
+ if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
384
+ *ptr2++ = *ptr++;
385
+ else {
386
+ *ptr2++ = '\\';
387
+ switch (*ptr++) {
388
+ case '\\':
389
+ *ptr2++ = '\\';
390
+ break;
391
+ case '\"':
392
+ *ptr2++ = '\"';
393
+ break;
394
+ case '\b':
395
+ *ptr2++ = 'b';
396
+ break;
397
+ case '\f':
398
+ *ptr2++ = 'f';
399
+ break;
400
+ case '\n':
401
+ *ptr2++ = 'n';
402
+ break;
403
+ case '\r':
404
+ *ptr2++ = 'r';
405
+ break;
406
+ case '\t':
407
+ *ptr2++ = 't';
408
+ break;
409
+ default:
410
+ ptr2--;
411
+ break; /* eviscerate with prejudice. */
335
412
  }
336
413
  }
337
414
  }
338
- *ptr2++='\"';*ptr2++=0;
415
+ *ptr2++ = '\"';
416
+ *ptr2++ = 0;
339
417
  return out;
340
418
  }
341
419
  /* Invote print_string_ptr (which is useful) on an item. */
342
- static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
420
+ static char *print_string(cJSON *item)
421
+ {
422
+ return print_string_ptr(item->valuestring);
423
+ }
343
424
 
344
425
  /* Predeclare these prototypes. */
345
- static const char *parse_value(cJSON *item,const char *value);
346
- static char *print_value(cJSON *item,int depth,int fmt);
347
- static const char *parse_array(cJSON *item,const char *value);
348
- static char *print_array(cJSON *item,int depth,int fmt);
349
- static const char *parse_object(cJSON *item,const char *value);
350
- static char *print_object(cJSON *item,int depth,int fmt);
426
+ static const char *parse_value(cJSON *item, const char *value);
427
+ static char *print_value(cJSON *item, int depth, int fmt);
428
+ static const char *parse_array(cJSON *item, const char *value);
429
+ static char *print_array(cJSON *item, int depth, int fmt);
430
+ static const char *parse_object(cJSON *item, const char *value);
431
+ static char *print_object(cJSON *item, int depth, int fmt);
351
432
 
352
433
  /* Utility to jump whitespace and cr/lf */
353
- static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
434
+ static const char *skip(const char *in)
435
+ {
436
+ while (in && *in && (unsigned char)*in <= 32)
437
+ in++;
438
+ return in;
439
+ }
354
440
 
355
441
  /* Parse an object - create a new root, and populate. */
356
442
  cJSON *cJSON_Parse(const char *value)
@@ -363,262 +449,574 @@ cJSON *cJSON_Parse(const char *value)
363
449
  if (!c) {
364
450
  c = cJSON_New_Item(0);
365
451
  }
366
- if (!c) return 0; /* memory fail */
452
+ if (!c)
453
+ return 0; /* memory fail */
367
454
 
368
455
  c->alloc_pool = pool;
369
456
 
370
- if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
457
+ if (!parse_value(c, skip(value))) {
458
+ cJSON_Delete(c);
459
+ return 0;
460
+ }
371
461
  return c;
372
462
  }
373
463
 
374
464
  /* Render a cJSON item/entity/structure to text. */
375
- char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
376
- char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
465
+ char *cJSON_Print(cJSON *item)
466
+ {
467
+ return print_value(item, 0, 1);
468
+ }
469
+ char *cJSON_PrintUnformatted(cJSON *item)
470
+ {
471
+ return print_value(item, 0, 0);
472
+ }
377
473
 
378
474
  /* Parser core - when encountering text, process appropriately. */
379
- static const char *parse_value(cJSON *item,const char *value)
475
+ static const char *parse_value(cJSON *item, const char *value)
380
476
  {
381
- if (!value) return 0; /* Fail on null. */
382
- if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
383
- if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
384
- if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
385
- if (*value=='\"') { return parse_string(item,value); }
386
- if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
387
- if (*value=='[') { return parse_array(item,value); }
388
- if (*value=='{') { return parse_object(item,value); }
477
+ if (!value)
478
+ return 0; /* Fail on null. */
479
+ if (!strncmp(value, "null", 4)) {
480
+ item->type = cJSON_NULL;
481
+ return value + 4;
482
+ }
483
+ if (!strncmp(value, "false", 5)) {
484
+ item->type = cJSON_False;
485
+ return value + 5;
486
+ }
487
+ if (!strncmp(value, "true", 4)) {
488
+ item->type = cJSON_True;
489
+ item->valueint = 1;
490
+ return value + 4;
491
+ }
492
+ if (*value == '\"') {
493
+ return parse_string(item, value);
494
+ }
495
+ if (*value == '-' || (*value >= '0' && *value <= '9')) {
496
+ return parse_number(item, value);
497
+ }
498
+ if (*value == '[') {
499
+ return parse_array(item, value);
500
+ }
501
+ if (*value == '{') {
502
+ return parse_object(item, value);
503
+ }
389
504
 
390
- return 0; /* failure. */
505
+ return 0; /* failure. */
391
506
  }
392
507
 
393
508
  /* Render a value to text. */
394
- static char *print_value(cJSON *item,int depth,int fmt)
509
+ static char *print_value(cJSON *item, int depth, int fmt)
395
510
  {
396
- char *out=0;
397
- if (!item) return 0;
398
- switch ((item->type)&255)
399
- {
400
- case cJSON_NULL: out=cJSON_strdup("null"); break;
401
- case cJSON_False: out=cJSON_strdup("false");break;
402
- case cJSON_True: out=cJSON_strdup("true"); break;
403
- case cJSON_Number: out=print_number(item);break;
404
- case cJSON_String: out=print_string(item);break;
405
- case cJSON_Array: out=print_array(item,depth,fmt);break;
406
- case cJSON_Object: out=print_object(item,depth,fmt);break;
511
+ char *out = 0;
512
+ if (!item)
513
+ return 0;
514
+ switch ((item->type) & 255) {
515
+ case cJSON_NULL:
516
+ out = cJSON_strdup("null");
517
+ break;
518
+ case cJSON_False:
519
+ out = cJSON_strdup("false");
520
+ break;
521
+ case cJSON_True:
522
+ out = cJSON_strdup("true");
523
+ break;
524
+ case cJSON_Number:
525
+ out = print_number(item);
526
+ break;
527
+ case cJSON_String:
528
+ out = print_string(item);
529
+ break;
530
+ case cJSON_Array:
531
+ out = print_array(item, depth, fmt);
532
+ break;
533
+ case cJSON_Object:
534
+ out = print_object(item, depth, fmt);
535
+ break;
407
536
  }
408
537
  return out;
409
538
  }
410
539
 
411
540
  /* Build an array from input text. */
412
- static const char *parse_array(cJSON *item,const char *value)
541
+ static const char *parse_array(cJSON *item, const char *value)
413
542
  {
414
543
  cJSON *child;
415
- if (*value!='[') return 0; /* not an array! */
416
-
417
- item->type=cJSON_Array;
418
- value=skip(value+1);
419
- if (*value==']') return value+1; /* empty array. */
420
-
421
- item->child=child=cJSON_New_Item(item);
422
- if (!item->child) return 0; /* memory fail */
423
- value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
424
- if (!value) return 0;
544
+ if (*value != '[')
545
+ return 0; /* not an array! */
546
+
547
+ item->type = cJSON_Array;
548
+ value = skip(value + 1);
549
+ if (*value == ']')
550
+ return value + 1; /* empty array. */
551
+
552
+ item->child = child = cJSON_New_Item(item);
553
+ if (!item->child)
554
+ return 0; /* memory fail */
555
+ value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
556
+ if (!value)
557
+ return 0;
425
558
 
426
- while (*value==',')
427
- {
559
+ while (*value == ',') {
428
560
  cJSON *new_item;
429
- if (!(new_item=cJSON_New_Item(item))) return 0; /* memory fail */
430
- child->next=new_item;new_item->prev=child;child=new_item;
431
- value=skip(parse_value(child,skip(value+1)));
432
- if (!value) return 0; /* memory fail */
561
+ if (!(new_item = cJSON_New_Item(item)))
562
+ return 0; /* memory fail */
563
+ child->next = new_item;
564
+ new_item->prev = child;
565
+ child = new_item;
566
+ value = skip(parse_value(child, skip(value + 1)));
567
+ if (!value)
568
+ return 0; /* memory fail */
433
569
  }
434
570
 
435
- if (*value==']') return value+1; /* end of array */
436
- return 0; /* malformed. */
571
+ if (*value == ']')
572
+ return value + 1; /* end of array */
573
+ return 0; /* malformed. */
437
574
  }
438
575
 
439
576
  /* Render an array to text */
440
- static char *print_array(cJSON *item,int depth,int fmt)
577
+ static char *print_array(cJSON *item, int depth, int fmt)
441
578
  {
442
579
  char **entries;
443
- char *out=0,*ptr,*ret;size_t len=5;
444
- cJSON *child=item->child;
445
- int numentries=0,i=0,fail=0;
580
+ char *out = 0, *ptr, *ret;
581
+ size_t len = 5;
582
+ cJSON *child = item->child;
583
+ int numentries = 0, i = 0, fail = 0;
446
584
 
447
585
  /* How many entries in the array? */
448
- while (child) numentries++,child=child->next;
586
+ while (child)
587
+ numentries++, child = child->next;
449
588
  /* Allocate an array to hold the values for each */
450
- entries=(char**)cJSON_malloc(numentries*sizeof(char*));
451
- if (!entries) return 0;
452
- memset(entries,0,numentries*sizeof(char*));
589
+ entries = (char **)cJSON_malloc(numentries * sizeof(char *));
590
+ if (!entries)
591
+ return 0;
592
+ memset(entries, 0, numentries * sizeof(char *));
453
593
  /* Retrieve all the results: */
454
- child=item->child;
455
- while (child && !fail)
456
- {
457
- ret=print_value(child,depth+1,fmt);
458
- entries[i++]=ret;
459
- if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
460
- child=child->next;
594
+ child = item->child;
595
+ while (child && !fail) {
596
+ ret = print_value(child, depth + 1, fmt);
597
+ entries[i++] = ret;
598
+ if (ret)
599
+ len += strlen(ret) + 2 + (fmt ? 1 : 0);
600
+ else
601
+ fail = 1;
602
+ child = child->next;
461
603
  }
462
604
 
463
605
  /* If we didn't fail, try to malloc the output string */
464
- if (!fail) out=cJSON_malloc(len);
606
+ if (!fail)
607
+ out = cJSON_malloc(len);
465
608
  /* If that fails, we fail. */
466
- if (!out) fail=1;
609
+ if (!out)
610
+ fail = 1;
467
611
 
468
612
  /* Handle failure. */
469
- if (fail)
470
- {
471
- for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
613
+ if (fail) {
614
+ for (i = 0; i < numentries; i++)
615
+ if (entries[i])
616
+ cJSON_free(entries[i]);
472
617
  cJSON_free(entries);
473
618
  return 0;
474
619
  }
475
620
 
476
621
  /* Compose the output array. */
477
- *out='[';
478
- ptr=out+1;*ptr=0;
479
- for (i=0;i<numentries;i++)
480
- {
481
- strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
482
- if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
622
+ *out = '[';
623
+ ptr = out + 1;
624
+ *ptr = 0;
625
+ for (i = 0; i < numentries; i++) {
626
+ strcpy(ptr, entries[i]);
627
+ ptr += strlen(entries[i]);
628
+ if (i != numentries - 1) {
629
+ *ptr++ = ',';
630
+ if (fmt)
631
+ *ptr++ = ' ';
632
+ *ptr = 0;
633
+ }
483
634
  cJSON_free(entries[i]);
484
635
  }
485
636
  cJSON_free(entries);
486
- *ptr++=']';*ptr++=0;
637
+ *ptr++ = ']';
638
+ *ptr++ = 0;
487
639
  return out;
488
640
  }
489
641
 
490
642
  /* Build an object from the text. */
491
- static const char *parse_object(cJSON *item,const char *value)
643
+ static const char *parse_object(cJSON *item, const char *value)
492
644
  {
493
645
  cJSON *child;
494
- if (*value!='{') return 0; /* not an object! */
646
+ if (*value != '{')
647
+ return 0; /* not an object! */
495
648
 
496
- item->type=cJSON_Object;
497
- value=skip(value+1);
498
- if (*value=='}') return value+1; /* empty array. */
649
+ item->type = cJSON_Object;
650
+ value = skip(value + 1);
651
+ if (*value == '}')
652
+ return value + 1; /* empty array. */
499
653
 
500
- item->child=child=cJSON_New_Item(item);
501
- value=skip(parse_string(child,skip(value)));
502
- if (!value) return 0;
503
- child->string=child->valuestring;child->valuestring=0;
504
- if (*value!=':') return 0; /* fail! */
505
- value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
506
- if (!value) return 0;
654
+ item->child = child = cJSON_New_Item(item);
655
+ value = skip(parse_string(child, skip(value)));
656
+ if (!value)
657
+ return 0;
658
+ child->string = child->valuestring;
659
+ child->valuestring = 0;
660
+ if (*value != ':')
661
+ return 0; /* fail! */
662
+ value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
663
+ if (!value)
664
+ return 0;
507
665
 
508
- while (*value==',')
509
- {
666
+ while (*value == ',') {
510
667
  cJSON *new_item;
511
- if (!(new_item=cJSON_New_Item(item))) return 0; /* memory fail */
512
- child->next=new_item;new_item->prev=child;child=new_item;
513
- value=skip(parse_string(child,skip(value+1)));
514
- if (!value) return 0;
515
- child->string=child->valuestring;child->valuestring=0;
516
- if (*value!=':') return 0; /* fail! */
517
- value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
518
- if (!value) return 0;
668
+ if (!(new_item = cJSON_New_Item(item)))
669
+ return 0; /* memory fail */
670
+ child->next = new_item;
671
+ new_item->prev = child;
672
+ child = new_item;
673
+ value = skip(parse_string(child, skip(value + 1)));
674
+ if (!value)
675
+ return 0;
676
+ child->string = child->valuestring;
677
+ child->valuestring = 0;
678
+ if (*value != ':')
679
+ return 0; /* fail! */
680
+ value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
681
+ if (!value)
682
+ return 0;
519
683
  }
520
684
 
521
- if (*value=='}') return value+1; /* end of array */
522
- return 0; /* malformed. */
685
+ if (*value == '}')
686
+ return value + 1; /* end of array */
687
+ return 0; /* malformed. */
523
688
  }
524
689
 
525
690
  /* Render an object to text. */
526
- static char *print_object(cJSON *item,int depth,int fmt)
691
+ static char *print_object(cJSON *item, int depth, int fmt)
527
692
  {
528
- char **entries=0,**names=0;
529
- char *out=0,*ptr,*ret,*str;size_t len=7; int i=0,j;
530
- cJSON *child=item->child;
531
- int numentries=0,fail=0;
693
+ char **entries = 0, **names = 0;
694
+ char *out = 0, *ptr, *ret, *str;
695
+ size_t len = 7;
696
+ int i = 0, j;
697
+ cJSON *child = item->child;
698
+ int numentries = 0, fail = 0;
532
699
  /* Count the number of entries. */
533
- while (child) numentries++,child=child->next;
700
+ while (child)
701
+ numentries++, child = child->next;
534
702
  /* Allocate space for the names and the objects */
535
- entries=(char**)cJSON_malloc(numentries*sizeof(char*));
536
- if (!entries) return 0;
537
- names=(char**)cJSON_malloc(numentries*sizeof(char*));
538
- if (!names) {cJSON_free(entries);return 0;}
539
- memset(entries,0,sizeof(char*)*numentries);
540
- memset(names,0,sizeof(char*)*numentries);
703
+ entries = (char **)cJSON_malloc(numentries * sizeof(char *));
704
+ if (!entries)
705
+ return 0;
706
+ names = (char **)cJSON_malloc(numentries * sizeof(char *));
707
+ if (!names) {
708
+ cJSON_free(entries);
709
+ return 0;
710
+ }
711
+ memset(entries, 0, sizeof(char *) * numentries);
712
+ memset(names, 0, sizeof(char *) * numentries);
541
713
 
542
714
  /* Collect all the results into our arrays: */
543
- child=item->child;depth++;if (fmt) len+=depth;
544
- while (child)
545
- {
546
- names[i]=str=print_string_ptr(child->string);
547
- entries[i++]=ret=print_value(child,depth,fmt);
548
- if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
549
- child=child->next;
715
+ child = item->child;
716
+ depth++;
717
+ if (fmt)
718
+ len += depth;
719
+ while (child) {
720
+ names[i] = str = print_string_ptr(child->string);
721
+ entries[i++] = ret = print_value(child, depth, fmt);
722
+ if (str && ret)
723
+ len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
724
+ else
725
+ fail = 1;
726
+ child = child->next;
550
727
  }
551
728
 
552
729
  /* Try to allocate the output string */
553
- if (!fail) out=(char*)cJSON_malloc(len);
554
- if (!out) fail=1;
730
+ if (!fail)
731
+ out = (char *)cJSON_malloc(len);
732
+ if (!out)
733
+ fail = 1;
555
734
 
556
735
  /* Handle failure */
557
- if (fail)
558
- {
559
- for (i=0;i<numentries;i++) {if (names[i]) free(names[i]);if (entries[i]) free(entries[i]);}
560
- free(names);free(entries);
736
+ if (fail) {
737
+ for (i = 0; i < numentries; i++) {
738
+ if (names[i])
739
+ free(names[i]);
740
+ if (entries[i])
741
+ free(entries[i]);
742
+ }
743
+ free(names);
744
+ free(entries);
561
745
  return 0;
562
746
  }
563
747
 
564
748
  /* Compose the output: */
565
- *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
566
- for (i=0;i<numentries;i++)
567
- {
568
- if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
569
- strcpy(ptr,names[i]);ptr+=strlen(names[i]);
570
- *ptr++=':';if (fmt) *ptr++='\t';
571
- strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
572
- if (i!=numentries-1) *ptr++=',';
573
- if (fmt) *ptr++='\n';*ptr=0;
574
- cJSON_free(names[i]);cJSON_free(entries[i]);
575
- }
576
-
577
- cJSON_free(names);cJSON_free(entries);
578
- if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
579
- *ptr++='}';*ptr++=0;
749
+ *out = '{';
750
+ ptr = out + 1;
751
+ if (fmt)
752
+ *ptr++ = '\n';
753
+ *ptr = 0;
754
+ for (i = 0; i < numentries; i++) {
755
+ if (fmt)
756
+ for (j = 0; j < depth; j++)
757
+ *ptr++ = '\t';
758
+ strcpy(ptr, names[i]);
759
+ ptr += strlen(names[i]);
760
+ *ptr++ = ':';
761
+ if (fmt)
762
+ *ptr++ = '\t';
763
+ strcpy(ptr, entries[i]);
764
+ ptr += strlen(entries[i]);
765
+ if (i != numentries - 1)
766
+ *ptr++ = ',';
767
+ if (fmt)
768
+ *ptr++ = '\n';
769
+ *ptr = 0;
770
+ cJSON_free(names[i]);
771
+ cJSON_free(entries[i]);
772
+ }
773
+
774
+ cJSON_free(names);
775
+ cJSON_free(entries);
776
+ if (fmt)
777
+ for (i = 0; i < depth - 1; i++)
778
+ *ptr++ = '\t';
779
+ *ptr++ = '}';
780
+ *ptr++ = 0;
580
781
  return out;
581
782
  }
582
783
 
583
784
  /* Get Array size/item / object item. */
584
- int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
585
- cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
586
- cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
785
+ int cJSON_GetArraySize(cJSON *array)
786
+ {
787
+ cJSON *c = array->child;
788
+ int i = 0;
789
+ while (c)
790
+ i++, c = c->next;
791
+ return i;
792
+ }
793
+ cJSON *cJSON_GetArrayItem(cJSON *array, int item)
794
+ {
795
+ cJSON *c = array->child;
796
+ while (c && item > 0)
797
+ item--, c = c->next;
798
+ return c;
799
+ }
800
+ cJSON *cJSON_GetObjectItem(cJSON *object, const char *string)
801
+ {
802
+ cJSON *c = object->child;
803
+ while (c && cJSON_strcasecmp(c->string, string))
804
+ c = c->next;
805
+ return c;
806
+ }
587
807
 
588
808
  /* Utility for array list handling. */
589
- static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
809
+ static void suffix_object(cJSON *prev, cJSON *item)
810
+ {
811
+ prev->next = item;
812
+ item->prev = prev;
813
+ }
590
814
  /* Utility for handling references. */
591
- static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item(item);memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
815
+ static cJSON *create_reference(cJSON *item)
816
+ {
817
+ cJSON *ref = cJSON_New_Item(item);
818
+ memcpy(ref, item, sizeof(cJSON));
819
+ ref->string = 0;
820
+ ref->type |= cJSON_IsReference;
821
+ ref->next = ref->prev = 0;
822
+ return ref;
823
+ }
592
824
 
593
825
  /* Add item to array/object. */
594
- void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
595
- void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
596
- void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
597
- void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
826
+ void cJSON_AddItemToArray(cJSON *array, cJSON *item)
827
+ {
828
+ cJSON *c = array->child;
829
+ if (!c) {
830
+ array->child = item;
831
+ } else {
832
+ while (c && c->next)
833
+ c = c->next;
834
+ suffix_object(c, item);
835
+ }
836
+ }
837
+ void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
838
+ {
839
+ if (item->string)
840
+ cJSON_free(item->string);
841
+ item->string = cJSON_strdup(string);
842
+ cJSON_AddItemToArray(object, item);
843
+ }
844
+ void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
845
+ {
846
+ cJSON_AddItemToArray(array, create_reference(item));
847
+ }
848
+ void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
849
+ {
850
+ cJSON_AddItemToObject(object, string, create_reference(item));
851
+ }
598
852
 
599
- cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
600
- if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
601
- void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
602
- cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
603
- void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
853
+ cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
854
+ {
855
+ cJSON *c = array->child;
856
+ while (c && which > 0)
857
+ c = c->next, which--;
858
+ if (!c)
859
+ return 0;
860
+ if (c->prev)
861
+ c->prev->next = c->next;
862
+ if (c->next)
863
+ c->next->prev = c->prev;
864
+ if (c == array->child)
865
+ array->child = c->next;
866
+ c->prev = c->next = 0;
867
+ return c;
868
+ }
869
+ void cJSON_DeleteItemFromArray(cJSON *array, int which)
870
+ {
871
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
872
+ }
873
+ cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
874
+ {
875
+ int i = 0;
876
+ cJSON *c = object->child;
877
+ while (c && cJSON_strcasecmp(c->string, string))
878
+ i++, c = c->next;
879
+ if (c)
880
+ return cJSON_DetachItemFromArray(object, i);
881
+ return 0;
882
+ }
883
+ void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
884
+ {
885
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
886
+ }
604
887
 
605
888
  /* Replace array/object items with new ones. */
606
- void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
607
- newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
608
- if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
609
- void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
889
+ void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
890
+ {
891
+ cJSON *c = array->child;
892
+ while (c && which > 0)
893
+ c = c->next, which--;
894
+ if (!c)
895
+ return;
896
+ newitem->next = c->next;
897
+ newitem->prev = c->prev;
898
+ if (newitem->next)
899
+ newitem->next->prev = newitem;
900
+ if (c == array->child)
901
+ array->child = newitem;
902
+ else
903
+ newitem->prev->next = newitem;
904
+ c->next = c->prev = 0;
905
+ cJSON_Delete(c);
906
+ }
907
+ void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
908
+ {
909
+ int i = 0;
910
+ cJSON *c = object->child;
911
+ while (c && cJSON_strcasecmp(c->string, string))
912
+ i++, c = c->next;
913
+ if (c) {
914
+ newitem->string = cJSON_strdup(string);
915
+ cJSON_ReplaceItemInArray(object, i, newitem);
916
+ }
917
+ }
610
918
 
611
919
  /* Create basic types: */
612
- cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item(0);item->type=cJSON_NULL;return item;}
613
- cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item(0);item->type=cJSON_True;return item;}
614
- cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item(0);item->type=cJSON_False;return item;}
615
- cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item(0);item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;return item;}
616
- cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item(0);item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;}
617
- cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item(0);item->type=cJSON_Array;return item;}
618
- cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item(0);item->type=cJSON_Object;return item;}
920
+ cJSON *cJSON_CreateNull()
921
+ {
922
+ cJSON *item = cJSON_New_Item(0);
923
+ item->type = cJSON_NULL;
924
+ return item;
925
+ }
926
+ cJSON *cJSON_CreateTrue()
927
+ {
928
+ cJSON *item = cJSON_New_Item(0);
929
+ item->type = cJSON_True;
930
+ return item;
931
+ }
932
+ cJSON *cJSON_CreateFalse()
933
+ {
934
+ cJSON *item = cJSON_New_Item(0);
935
+ item->type = cJSON_False;
936
+ return item;
937
+ }
938
+ cJSON *cJSON_CreateNumber(double num)
939
+ {
940
+ cJSON *item = cJSON_New_Item(0);
941
+ item->type = cJSON_Number;
942
+ item->valuedouble = num;
943
+ item->valueint = (int)num;
944
+ return item;
945
+ }
946
+ cJSON *cJSON_CreateString(const char *string)
947
+ {
948
+ cJSON *item = cJSON_New_Item(0);
949
+ item->type = cJSON_String;
950
+ item->valuestring = cJSON_strdup(string);
951
+ return item;
952
+ }
953
+ cJSON *cJSON_CreateArray()
954
+ {
955
+ cJSON *item = cJSON_New_Item(0);
956
+ item->type = cJSON_Array;
957
+ return item;
958
+ }
959
+ cJSON *cJSON_CreateObject()
960
+ {
961
+ cJSON *item = cJSON_New_Item(0);
962
+ item->type = cJSON_Object;
963
+ return item;
964
+ }
619
965
 
620
966
  /* Create Arrays: */
621
- cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
622
- cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
623
- cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
624
- cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
967
+ cJSON *cJSON_CreateIntArray(int *numbers, int count)
968
+ {
969
+ int i;
970
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
971
+ for (i = 0; i < count; i++) {
972
+ n = cJSON_CreateNumber(numbers[i]);
973
+ if (!i)
974
+ a->child = n;
975
+ else
976
+ suffix_object(p, n);
977
+ p = n;
978
+ }
979
+ return a;
980
+ }
981
+ cJSON *cJSON_CreateFloatArray(float *numbers, int count)
982
+ {
983
+ int i;
984
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
985
+ for (i = 0; i < count; i++) {
986
+ n = cJSON_CreateNumber(numbers[i]);
987
+ if (!i)
988
+ a->child = n;
989
+ else
990
+ suffix_object(p, n);
991
+ p = n;
992
+ }
993
+ return a;
994
+ }
995
+ cJSON *cJSON_CreateDoubleArray(double *numbers, int count)
996
+ {
997
+ int i;
998
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
999
+ for (i = 0; i < count; i++) {
1000
+ n = cJSON_CreateNumber(numbers[i]);
1001
+ if (!i)
1002
+ a->child = n;
1003
+ else
1004
+ suffix_object(p, n);
1005
+ p = n;
1006
+ }
1007
+ return a;
1008
+ }
1009
+ cJSON *cJSON_CreateStringArray(const char **strings, int count)
1010
+ {
1011
+ int i;
1012
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1013
+ for (i = 0; i < count; i++) {
1014
+ n = cJSON_CreateString(strings[i]);
1015
+ if (!i)
1016
+ a->child = n;
1017
+ else
1018
+ suffix_object(p, n);
1019
+ p = n;
1020
+ }
1021
+ return a;
1022
+ }