Merge lp:~stewart/drizzle/json-interface into lp:~drizzle-trunk/drizzle/development

Proposed by Stewart Smith
Status: Merged
Approved by: Brian Aker
Approved revision: 2300
Merged at revision: 2310
Proposed branch: lp:~stewart/drizzle/json-interface
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 7884 lines (+7638/-3)
32 files modified
drizzled/plugin/client/cached.h (+1/-0)
drizzled/sql/result_set.h (+5/-0)
drizzled/sql/result_set_meta_data.h (+6/-1)
plugin/http_functions/http_functions.cc (+199/-0)
plugin/http_functions/plugin.ac (+4/-0)
plugin/http_functions/plugin.cnf (+2/-0)
plugin/http_functions/plugin.ini (+6/-0)
plugin/json_server/json/autolink.h (+58/-0)
plugin/json_server/json/config.h (+81/-0)
plugin/json_server/json/features.h (+80/-0)
plugin/json_server/json/forwards.h (+77/-0)
plugin/json_server/json/json.h (+48/-0)
plugin/json_server/json/json_batchallocator.h (+163/-0)
plugin/json_server/json/json_internalarray.inl (+486/-0)
plugin/json_server/json/json_internalmap.inl (+645/-0)
plugin/json_server/json/json_reader.cpp (+921/-0)
plugin/json_server/json/json_value.cpp (+1759/-0)
plugin/json_server/json/json_valueiterator.inl (+330/-0)
plugin/json_server/json/json_writer.cpp (+862/-0)
plugin/json_server/json/reader.h (+234/-0)
plugin/json_server/json/value.h (+1107/-0)
plugin/json_server/json/writer.h (+212/-0)
plugin/json_server/json_server.cc (+284/-0)
plugin/json_server/plugin.ac (+1/-0)
plugin/json_server/plugin.ini (+12/-0)
plugin/json_server/tests/r/basic.result (+35/-0)
plugin/json_server/tests/t/basic.test (+10/-0)
plugin/json_server/tests/t/master.opt (+1/-0)
po/POTFILES.in (+1/-0)
tests/lib/drizzle_test_run/dtr_test_execution.py (+1/-0)
tests/lib/server_mgmt/drizzled.py (+2/-2)
tests/test-run.pl (+5/-0)
To merge this branch: bzr merge lp:~stewart/drizzle/json-interface
Reviewer Review Type Date Requested Status
Mark Atwood Needs Fixing
Drizzle Merge Team Pending
Review via email: mp+59859@code.launchpad.net

This proposal supersedes a proposal from 2011-04-21.

Description of the change

Preliminary implementation of a HTTP interface to Drizzle.

Includes testing. Uses libevent http daemon. returns results as JSON.

includes brian's fixes.

To post a comment you must log in.
Revision history for this message
Stewart Smith (stewart) wrote : Posted in a previous version of this proposal

note that this includes http://jsoncpp.sourceforge.net/ code, which is in the public domain.

Revision history for this message
Stewart Smith (stewart) wrote : Posted in a previous version of this proposal

so a problem with this branch currently is that the tests use 'curl' to test the interface. Not all systems have curl installed however, so I either need to (for example) add HTTP_GET()/HTTP_POST() functions to the server (perhaps just using the interface that libevent provides) or we need to add curl as a build-dep.

Revision history for this message
Brian Aker (brianaker) wrote : Posted in a previous version of this proposal

We should put a comment on the code so that we know where it came from (and either our own license, or put public domain headers on it).

Revision history for this message
Stewart Smith (stewart) wrote : Posted in a previous version of this proposal

now fixed to have http_() functions in the tree that are used to test json_server. Can also be used to fetch URLs and the like.

This change means param-build passes on every system.

http://jsoncpp.sourceforge.net/LICENSE

is the other thing we should work out how to have in the soure files.

Revision history for this message
Stewart Smith (stewart) wrote : Posted in a previous version of this proposal
Revision history for this message
Mark Atwood (fallenpegasus) wrote :
review: Needs Fixing
Revision history for this message
Stewart Smith (stewart) wrote :
Revision history for this message
Mark Atwood (fallenpegasus) wrote :

>>
>
> looks like something from vj's sp branch, not mine.

Brian and I are looking at it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'drizzled/plugin/client/cached.h'
2--- drizzled/plugin/client/cached.h 2011-03-15 23:55:01 +0000
3+++ drizzled/plugin/client/cached.h 2011-05-04 01:52:37 +0000
4@@ -57,6 +57,7 @@
5 item->make_field(&field);
6 max_column++;
7 }
8+ _result_set->setColumnCount(max_column);
9 _result_set->createRow();
10
11 return false;
12
13=== modified file 'drizzled/sql/result_set.h'
14--- drizzled/sql/result_set.h 2011-03-29 12:45:08 +0000
15+++ drizzled/sql/result_set.h 2011-05-04 01:52:37 +0000
16@@ -101,6 +101,11 @@
17 {
18 }
19
20+ void setColumnCount(size_t fields)
21+ {
22+ _meta_data.setColumnCount(fields);
23+ }
24+
25 ~ResultSet();
26
27 void createRow();
28
29=== modified file 'drizzled/sql/result_set_meta_data.h'
30--- drizzled/sql/result_set_meta_data.h 2011-03-29 12:45:08 +0000
31+++ drizzled/sql/result_set_meta_data.h 2011-05-04 01:52:37 +0000
32@@ -53,10 +53,15 @@
33 {
34 }
35
36+ void setColumnCount(size_t fields)
37+ {
38+ _columns= fields;
39+ }
40+
41 private: // Member methods
42
43 private: // Member variables
44- const size_t _columns;
45+ size_t _columns;
46 };
47
48 std::ostream& operator<<(std::ostream& output, const ResultSetMetaData &result_set);
49
50=== added directory 'plugin/http_functions'
51=== added file 'plugin/http_functions/http_functions.cc'
52--- plugin/http_functions/http_functions.cc 1970-01-01 00:00:00 +0000
53+++ plugin/http_functions/http_functions.cc 2011-05-04 01:52:37 +0000
54@@ -0,0 +1,199 @@
55+/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
56+ * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
57+ *
58+ * Copyright (C) 2011 Stewart Smith
59+ *
60+ * This program is free software; you can redistribute it and/or modify
61+ * it under the terms of the GNU General Public License as published by
62+ * the Free Software Foundation; version 2 of the License.
63+ *
64+ * This program is distributed in the hope that it will be useful,
65+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
66+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67+ * GNU General Public License for more details.
68+ *
69+ * You should have received a copy of the GNU General Public License
70+ * along with this program; if not, write to the Free Software
71+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
72+ */
73+
74+#include <config.h>
75+
76+#include <drizzled/plugin/function.h>
77+#include <drizzled/function/str/strfunc.h>
78+#include <drizzled/charset.h>
79+#include <drizzled/error.h>
80+
81+#include <curl/curl.h>
82+
83+using namespace drizzled;
84+
85+class HttpGetFunction :public Item_str_func
86+{
87+ String result;
88+public:
89+ HttpGetFunction() :Item_str_func() {}
90+ String *val_str(String *);
91+ void fix_length_and_dec();
92+ const char *func_name() const { return "http_get"; }
93+
94+ bool check_argument_count(int n)
95+ {
96+ return n == 1;
97+ }
98+};
99+
100+extern "C" size_t
101+http_get_result_cb(void *ptr, size_t size, size_t nmemb, void *data);
102+
103+extern "C" size_t
104+http_get_result_cb(void *ptr, size_t size, size_t nmemb, void *data)
105+{
106+ size_t realsize= size * nmemb;
107+ String *result= (String *)data;
108+
109+ result->reserve(realsize + 1);
110+ result->append((const char*)ptr, realsize);
111+
112+ return realsize;
113+}
114+
115+
116+String *HttpGetFunction::val_str(String *str)
117+{
118+ assert(fixed == 1);
119+ String *url = args[0]->val_str(str);
120+ CURL *curl;
121+ CURLcode retref;
122+
123+ if ((null_value=args[0]->null_value))
124+ return NULL;
125+
126+ curl= curl_easy_init();
127+ curl_easy_setopt(curl, CURLOPT_URL, url->c_ptr_safe());
128+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_cb);
129+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&result);
130+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "drizzle-http-functions/1.0");
131+ retref= curl_easy_perform(curl);
132+ curl_easy_cleanup(curl);
133+
134+ if (retref != 0)
135+ my_error(ER_GET_ERRMSG, MYF(0), retref, curl_easy_strerror(retref),
136+ "http_get");
137+
138+ return &result;
139+}
140+
141+void HttpGetFunction::fix_length_and_dec()
142+{
143+ collation.set(args[0]->collation);
144+ max_length = ~0;
145+}
146+
147+class HttpPostFunction :public Item_str_func
148+{
149+ String result;
150+public:
151+ HttpPostFunction() :Item_str_func() {}
152+ String *val_str(String *);
153+ void fix_length_and_dec();
154+ const char *func_name() const { return "http_post"; }
155+
156+ bool check_argument_count(int n)
157+ {
158+ return n == 2;
159+ }
160+};
161+
162+class HttpPostData
163+{
164+private:
165+ String *data;
166+ size_t progress;
167+
168+public:
169+ HttpPostData(String* d) : data(d), progress(0) {}
170+
171+ size_t length() { return data->length(); }
172+
173+ size_t write(void* dest, size_t size)
174+ {
175+ size_t to_write= size;
176+
177+ if ((data->length() - progress) < to_write)
178+ to_write= data->length() - progress;
179+
180+ memcpy(dest, data->ptr() + progress, to_write);
181+
182+ progress+= to_write;
183+
184+ return to_write;
185+ }
186+};
187+
188+extern "C" size_t
189+http_post_readfunc(void *ptr, size_t size, size_t nmemb, void *data);
190+
191+extern "C" size_t
192+http_post_readfunc(void *ptr, size_t size, size_t nmemb, void *data)
193+{
194+ size_t realsize= size * nmemb;
195+ HttpPostData *post_data= (HttpPostData *)data;
196+
197+ return post_data->write(ptr, realsize);
198+}
199+
200+String *HttpPostFunction::val_str(String *str)
201+{
202+ assert(fixed == 1);
203+ String *url = args[0]->val_str(str);
204+ CURL *curl;
205+ CURLcode retref;
206+ String post_storage;
207+ HttpPostData post_data(args[1]->val_str(&post_storage));
208+
209+ if ((null_value=args[0]->null_value))
210+ return NULL;
211+
212+ curl= curl_easy_init();
213+ curl_easy_setopt(curl, CURLOPT_URL, url->c_ptr_safe());
214+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_cb);
215+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
216+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.length());
217+ curl_easy_setopt(curl, CURLOPT_READDATA, &post_data);
218+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, http_post_readfunc);
219+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&result);
220+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "drizzle-http-functions/1.0");
221+ retref= curl_easy_perform(curl);
222+ curl_easy_cleanup(curl);
223+
224+ return &result;
225+}
226+
227+void HttpPostFunction::fix_length_and_dec()
228+{
229+ collation.set(args[0]->collation);
230+ max_length = ~0;
231+}
232+
233+static int initialize(drizzled::module::Context &context)
234+{
235+ curl_global_init(CURL_GLOBAL_ALL);
236+ context.add(new plugin::Create_function<HttpGetFunction>("http_get"));
237+ context.add(new plugin::Create_function<HttpPostFunction>("http_post"));
238+ return 0;
239+}
240+
241+DRIZZLE_DECLARE_PLUGIN
242+{
243+ DRIZZLE_VERSION_ID,
244+ "http_functions",
245+ "1.0",
246+ "Stewart Smith",
247+ "HTTP functions",
248+ PLUGIN_LICENSE_GPL,
249+ initialize, /* Plugin Init */
250+ NULL, /* depends */
251+ NULL /* config options */
252+}
253+DRIZZLE_DECLARE_PLUGIN_END;
254
255=== added file 'plugin/http_functions/plugin.ac'
256--- plugin/http_functions/plugin.ac 1970-01-01 00:00:00 +0000
257+++ plugin/http_functions/plugin.ac 2011-05-04 01:52:37 +0000
258@@ -0,0 +1,4 @@
259+PANDORA_HAVE_LIBCURL
260+AS_IF([test "x$ac_cv_libcurl" = "xno"],
261+ AC_MSG_WARN([libcurl not found: not building http_functions]))
262+PANDORA_ADD_PLUGIN_DEP_LIB([${LIBCURL}])
263
264=== added file 'plugin/http_functions/plugin.cnf'
265--- plugin/http_functions/plugin.cnf 1970-01-01 00:00:00 +0000
266+++ plugin/http_functions/plugin.cnf 2011-05-04 01:52:37 +0000
267@@ -0,0 +1,2 @@
268+plugin-add=http_functions
269+
270
271=== added file 'plugin/http_functions/plugin.ini'
272--- plugin/http_functions/plugin.ini 1970-01-01 00:00:00 +0000
273+++ plugin/http_functions/plugin.ini 2011-05-04 01:52:37 +0000
274@@ -0,0 +1,6 @@
275+[plugin]
276+title=HTTP functions
277+description=HTTP functions: HTTP_GET() etc
278+sources=http_functions.cc
279+build_conditional="${ac_cv_libcurl}" = "yes"
280+ldflags=${LTLIBCURL}
281
282=== added directory 'plugin/json_server'
283=== added directory 'plugin/json_server/json'
284=== added file 'plugin/json_server/json/autolink.h'
285--- plugin/json_server/json/autolink.h 1970-01-01 00:00:00 +0000
286+++ plugin/json_server/json/autolink.h 2011-05-04 01:52:37 +0000
287@@ -0,0 +1,58 @@
288+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
289+ *
290+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
291+ *
292+ * Copyright (C) 2011 Stewart Smith
293+ * All rights reserved.
294+ *
295+ * Redistribution and use in source and binary forms, with or without
296+ * modification, are permitted provided that the following conditions are
297+ * met:
298+ *
299+ * * Redistributions of source code must retain the above copyright
300+ * notice, this list of conditions and the following disclaimer.
301+ *
302+ * * Redistributions in binary form must reproduce the above
303+ * copyright notice, this list of conditions and the following disclaimer
304+ * in the documentation and/or other materials provided with the
305+ * distribution.
306+ *
307+ * * The names of its contributors may not be used to endorse or
308+ * promote products derived from this software without specific prior
309+ * written permission.
310+ *
311+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
312+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
313+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
314+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
315+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
316+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
318+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
319+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
320+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
321+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322+ *
323+ */
324+
325+#pragma once
326+
327+#ifndef JSON_AUTOLINK_H_INCLUDED
328+# define JSON_AUTOLINK_H_INCLUDED
329+
330+# include "config.h"
331+
332+# ifdef JSON_IN_CPPTL
333+# include <cpptl/cpptl_autolink.h>
334+# endif
335+
336+# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
337+# define CPPTL_AUTOLINK_NAME "json"
338+# undef CPPTL_AUTOLINK_DLL
339+# ifdef JSON_DLL
340+# define CPPTL_AUTOLINK_DLL
341+# endif
342+# include "autolink.h"
343+# endif
344+
345+#endif // JSON_AUTOLINK_H_INCLUDED
346
347=== added file 'plugin/json_server/json/config.h'
348--- plugin/json_server/json/config.h 1970-01-01 00:00:00 +0000
349+++ plugin/json_server/json/config.h 2011-05-04 01:52:37 +0000
350@@ -0,0 +1,81 @@
351+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
352+ *
353+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
354+ *
355+ * Copyright (C) 2011 Stewart Smith
356+ * All rights reserved.
357+ *
358+ * Redistribution and use in source and binary forms, with or without
359+ * modification, are permitted provided that the following conditions are
360+ * met:
361+ *
362+ * * Redistributions of source code must retain the above copyright
363+ * notice, this list of conditions and the following disclaimer.
364+ *
365+ * * Redistributions in binary form must reproduce the above
366+ * copyright notice, this list of conditions and the following disclaimer
367+ * in the documentation and/or other materials provided with the
368+ * distribution.
369+ *
370+ * * The names of its contributors may not be used to endorse or
371+ * promote products derived from this software without specific prior
372+ * written permission.
373+ *
374+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
375+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
376+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
377+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
378+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
379+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
380+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
381+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
382+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
383+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
384+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
385+ *
386+ */
387+
388+#pragma once
389+#ifndef JSON_CONFIG_H_INCLUDED
390+# define JSON_CONFIG_H_INCLUDED
391+
392+/// If defined, indicates that json library is embedded in CppTL library.
393+//# define JSON_IN_CPPTL 1
394+
395+/// If defined, indicates that json may leverage CppTL library
396+//# define JSON_USE_CPPTL 1
397+/// If defined, indicates that cpptl vector based map should be used instead of std::map
398+/// as Value container.
399+//# define JSON_USE_CPPTL_SMALLMAP 1
400+/// If defined, indicates that Json specific container should be used
401+/// (hash table & simple deque container with customizable allocator).
402+/// THIS FEATURE IS STILL EXPERIMENTAL!
403+//# define JSON_VALUE_USE_INTERNAL_MAP 1
404+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
405+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
406+/// as if it was a POD) that may cause some validation tool to report errors.
407+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
408+//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
409+
410+/// If defined, indicates that Json use exception to report invalid type manipulation
411+/// instead of C assert macro.
412+# define JSON_USE_EXCEPTION 1
413+
414+# ifdef JSON_IN_CPPTL
415+# include <cpptl/config.h>
416+# ifndef JSON_USE_CPPTL
417+# define JSON_USE_CPPTL 1
418+# endif
419+# endif
420+
421+# ifdef JSON_IN_CPPTL
422+# define JSON_API CPPTL_API
423+# elif defined(JSON_DLL_BUILD)
424+# define JSON_API __declspec(dllexport)
425+# elif defined(JSON_DLL)
426+# define JSON_API __declspec(dllimport)
427+# else
428+# define JSON_API
429+# endif
430+
431+#endif // JSON_CONFIG_H_INCLUDED
432
433=== added file 'plugin/json_server/json/features.h'
434--- plugin/json_server/json/features.h 1970-01-01 00:00:00 +0000
435+++ plugin/json_server/json/features.h 2011-05-04 01:52:37 +0000
436@@ -0,0 +1,80 @@
437+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
438+ *
439+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
440+ *
441+ * Copyright (C) 2011 Stewart Smith
442+ * All rights reserved.
443+ *
444+ * Redistribution and use in source and binary forms, with or without
445+ * modification, are permitted provided that the following conditions are
446+ * met:
447+ *
448+ * * Redistributions of source code must retain the above copyright
449+ * notice, this list of conditions and the following disclaimer.
450+ *
451+ * * Redistributions in binary form must reproduce the above
452+ * copyright notice, this list of conditions and the following disclaimer
453+ * in the documentation and/or other materials provided with the
454+ * distribution.
455+ *
456+ * * The names of its contributors may not be used to endorse or
457+ * promote products derived from this software without specific prior
458+ * written permission.
459+ *
460+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
461+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
462+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
463+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
464+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
465+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
466+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
467+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
468+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
469+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
470+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
471+ *
472+ */
473+
474+#pragma once
475+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
476+# define CPPTL_JSON_FEATURES_H_INCLUDED
477+
478+# include "forwards.h"
479+
480+namespace Json {
481+
482+ /** \brief Configuration passed to reader and writer.
483+ * This configuration object can be used to force the Reader or Writer
484+ * to behave in a standard conforming way.
485+ */
486+ class JSON_API Features
487+ {
488+ public:
489+ /** \brief A configuration that allows all features and assumes all strings are UTF-8.
490+ * - C & C++ comments are allowed
491+ * - Root object can be any JSON value
492+ * - Assumes Value strings are encoded in UTF-8
493+ */
494+ static Features all();
495+
496+ /** \brief A configuration that is strictly compatible with the JSON specification.
497+ * - Comments are forbidden.
498+ * - Root object must be either an array or an object value.
499+ * - Assumes Value strings are encoded in UTF-8
500+ */
501+ static Features strictMode();
502+
503+ /** \brief Initialize the configuration like JsonConfig::allFeatures;
504+ */
505+ Features();
506+
507+ /// \c true if comments are allowed. Default: \c true.
508+ bool allowComments_;
509+
510+ /// \c true if root must be either an array or an object value. Default: \c false.
511+ bool strictRoot_;
512+ };
513+
514+} // namespace Json
515+
516+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
517
518=== added file 'plugin/json_server/json/forwards.h'
519--- plugin/json_server/json/forwards.h 1970-01-01 00:00:00 +0000
520+++ plugin/json_server/json/forwards.h 2011-05-04 01:52:37 +0000
521@@ -0,0 +1,77 @@
522+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
523+ *
524+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
525+ *
526+ * Copyright (C) 2011 Stewart Smith
527+ * All rights reserved.
528+ *
529+ * Redistribution and use in source and binary forms, with or without
530+ * modification, are permitted provided that the following conditions are
531+ * met:
532+ *
533+ * * Redistributions of source code must retain the above copyright
534+ * notice, this list of conditions and the following disclaimer.
535+ *
536+ * * Redistributions in binary form must reproduce the above
537+ * copyright notice, this list of conditions and the following disclaimer
538+ * in the documentation and/or other materials provided with the
539+ * distribution.
540+ *
541+ * * The names of its contributors may not be used to endorse or
542+ * promote products derived from this software without specific prior
543+ * written permission.
544+ *
545+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
546+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
547+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
548+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
549+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
550+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
551+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
552+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
553+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
554+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
555+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
556+ *
557+ */
558+
559+#pragma once
560+#ifndef JSON_FORWARDS_H_INCLUDED
561+# define JSON_FORWARDS_H_INCLUDED
562+
563+# include "config.h"
564+
565+namespace Json {
566+
567+ // writer.h
568+ class FastWriter;
569+ class StyledWriter;
570+
571+ // reader.h
572+ class Reader;
573+
574+ // features.h
575+ class Features;
576+
577+ // value.h
578+ typedef int Int;
579+ typedef unsigned int UInt;
580+ class StaticString;
581+ class Path;
582+ class PathArgument;
583+ class Value;
584+ class ValueIteratorBase;
585+ class ValueIterator;
586+ class ValueConstIterator;
587+#ifdef JSON_VALUE_USE_INTERNAL_MAP
588+ class ValueAllocator;
589+ class ValueMapAllocator;
590+ class ValueInternalLink;
591+ class ValueInternalArray;
592+ class ValueInternalMap;
593+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
594+
595+} // namespace Json
596+
597+
598+#endif // JSON_FORWARDS_H_INCLUDED
599
600=== added file 'plugin/json_server/json/json.h'
601--- plugin/json_server/json/json.h 1970-01-01 00:00:00 +0000
602+++ plugin/json_server/json/json.h 2011-05-04 01:52:37 +0000
603@@ -0,0 +1,48 @@
604+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
605+ *
606+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
607+ *
608+ * Copyright (C) 2011 Stewart Smith
609+ * All rights reserved.
610+ *
611+ * Redistribution and use in source and binary forms, with or without
612+ * modification, are permitted provided that the following conditions are
613+ * met:
614+ *
615+ * * Redistributions of source code must retain the above copyright
616+ * notice, this list of conditions and the following disclaimer.
617+ *
618+ * * Redistributions in binary form must reproduce the above
619+ * copyright notice, this list of conditions and the following disclaimer
620+ * in the documentation and/or other materials provided with the
621+ * distribution.
622+ *
623+ * * The names of its contributors may not be used to endorse or
624+ * promote products derived from this software without specific prior
625+ * written permission.
626+ *
627+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
628+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
629+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
630+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
631+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
632+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
633+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
634+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
635+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
636+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
637+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
638+ *
639+ */
640+
641+#pragma once
642+#ifndef JSON_JSON_H_INCLUDED
643+# define JSON_JSON_H_INCLUDED
644+
645+# include "autolink.h"
646+# include "value.h"
647+# include "reader.h"
648+# include "writer.h"
649+# include "features.h"
650+
651+#endif // JSON_JSON_H_INCLUDED
652
653=== added file 'plugin/json_server/json/json_batchallocator.h'
654--- plugin/json_server/json/json_batchallocator.h 1970-01-01 00:00:00 +0000
655+++ plugin/json_server/json/json_batchallocator.h 2011-05-04 01:52:37 +0000
656@@ -0,0 +1,163 @@
657+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
658+ *
659+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
660+ *
661+ * Copyright (C) 2011 Stewart Smith
662+ * All rights reserved.
663+ *
664+ * Redistribution and use in source and binary forms, with or without
665+ * modification, are permitted provided that the following conditions are
666+ * met:
667+ *
668+ * * Redistributions of source code must retain the above copyright
669+ * notice, this list of conditions and the following disclaimer.
670+ *
671+ * * Redistributions in binary form must reproduce the above
672+ * copyright notice, this list of conditions and the following disclaimer
673+ * in the documentation and/or other materials provided with the
674+ * distribution.
675+ *
676+ * * The names of its contributors may not be used to endorse or
677+ * promote products derived from this software without specific prior
678+ * written permission.
679+ *
680+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
681+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
682+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
683+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
684+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
685+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
686+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
687+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
688+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
689+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
690+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
691+ *
692+ */
693+
694+#pragma once
695+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
696+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
697+
698+# include <stdlib.h>
699+# include <assert.h>
700+
701+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
702+
703+namespace Json {
704+
705+/* Fast memory allocator.
706+ *
707+ * This memory allocator allocates memory for a batch of object (specified by
708+ * the page size, the number of object in each page).
709+ *
710+ * It does not allow the destruction of a single object. All the allocated objects
711+ * can be destroyed at once. The memory can be either released or reused for future
712+ * allocation.
713+ *
714+ * The in-place new operator must be used to construct the object using the pointer
715+ * returned by allocate.
716+ */
717+template<typename AllocatedType
718+ ,const unsigned int objectPerAllocation>
719+class BatchAllocator
720+{
721+public:
722+ typedef AllocatedType Type;
723+
724+ BatchAllocator( unsigned int objectsPerPage = 255 )
725+ : freeHead_( 0 )
726+ , objectsPerPage_( objectsPerPage )
727+ {
728+// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
729+ assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
730+ assert( objectsPerPage >= 16 );
731+ batches_ = allocateBatch( 0 ); // allocated a dummy page
732+ currentBatch_ = batches_;
733+ }
734+
735+ ~BatchAllocator()
736+ {
737+ for ( BatchInfo *batch = batches_; batch; )
738+ {
739+ BatchInfo *nextBatch = batch->next_;
740+ free( batch );
741+ batch = nextBatch;
742+ }
743+ }
744+
745+ /// allocate space for an array of objectPerAllocation object.
746+ /// @warning it is the responsability of the caller to call objects constructors.
747+ AllocatedType *allocate()
748+ {
749+ if ( freeHead_ ) // returns node from free list.
750+ {
751+ AllocatedType *object = freeHead_;
752+ freeHead_ = *(AllocatedType **)object;
753+ return object;
754+ }
755+ if ( currentBatch_->used_ == currentBatch_->end_ )
756+ {
757+ currentBatch_ = currentBatch_->next_;
758+ while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
759+ currentBatch_ = currentBatch_->next_;
760+
761+ if ( !currentBatch_ ) // no free batch found, allocate a new one
762+ {
763+ currentBatch_ = allocateBatch( objectsPerPage_ );
764+ currentBatch_->next_ = batches_; // insert at the head of the list
765+ batches_ = currentBatch_;
766+ }
767+ }
768+ AllocatedType *allocated = currentBatch_->used_;
769+ currentBatch_->used_ += objectPerAllocation;
770+ return allocated;
771+ }
772+
773+ /// Release the object.
774+ /// @warning it is the responsability of the caller to actually destruct the object.
775+ void release( AllocatedType *object )
776+ {
777+ assert( object != 0 );
778+ *(AllocatedType **)object = freeHead_;
779+ freeHead_ = object;
780+ }
781+
782+private:
783+ struct BatchInfo
784+ {
785+ BatchInfo *next_;
786+ AllocatedType *used_;
787+ AllocatedType *end_;
788+ AllocatedType buffer_[objectPerAllocation];
789+ };
790+
791+ // disabled copy constructor and assignement operator.
792+ BatchAllocator( const BatchAllocator & );
793+ void operator =( const BatchAllocator &);
794+
795+ static BatchInfo *allocateBatch( unsigned int objectsPerPage )
796+ {
797+ const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
798+ + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
799+ BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
800+ batch->next_ = 0;
801+ batch->used_ = batch->buffer_;
802+ batch->end_ = batch->buffer_ + objectsPerPage;
803+ return batch;
804+ }
805+
806+ BatchInfo *batches_;
807+ BatchInfo *currentBatch_;
808+ /// Head of a single linked list within the allocated space of freeed object
809+ AllocatedType *freeHead_;
810+ unsigned int objectsPerPage_;
811+};
812+
813+
814+} // namespace Json
815+
816+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
817+
818+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
819+
820
821=== added file 'plugin/json_server/json/json_internalarray.inl'
822--- plugin/json_server/json/json_internalarray.inl 1970-01-01 00:00:00 +0000
823+++ plugin/json_server/json/json_internalarray.inl 2011-05-04 01:52:37 +0000
824@@ -0,0 +1,486 @@
825+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
826+ *
827+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
828+ *
829+ * Copyright (C) 2011 Stewart Smith
830+ * All rights reserved.
831+ *
832+ * Redistribution and use in source and binary forms, with or without
833+ * modification, are permitted provided that the following conditions are
834+ * met:
835+ *
836+ * * Redistributions of source code must retain the above copyright
837+ * notice, this list of conditions and the following disclaimer.
838+ *
839+ * * Redistributions in binary form must reproduce the above
840+ * copyright notice, this list of conditions and the following disclaimer
841+ * in the documentation and/or other materials provided with the
842+ * distribution.
843+ *
844+ * * The names of its contributors may not be used to endorse or
845+ * promote products derived from this software without specific prior
846+ * written permission.
847+ *
848+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
849+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
850+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
851+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
852+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
853+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
854+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
855+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
856+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
857+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
858+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
859+ *
860+ */
861+
862+#pragma once
863+// included by json_value.cpp
864+// everything is within Json namespace
865+
866+// //////////////////////////////////////////////////////////////////
867+// //////////////////////////////////////////////////////////////////
868+// //////////////////////////////////////////////////////////////////
869+// class ValueInternalArray
870+// //////////////////////////////////////////////////////////////////
871+// //////////////////////////////////////////////////////////////////
872+// //////////////////////////////////////////////////////////////////
873+
874+ValueArrayAllocator::~ValueArrayAllocator()
875+{
876+}
877+
878+// //////////////////////////////////////////////////////////////////
879+// class DefaultValueArrayAllocator
880+// //////////////////////////////////////////////////////////////////
881+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
882+class DefaultValueArrayAllocator : public ValueArrayAllocator
883+{
884+public: // overridden from ValueArrayAllocator
885+ virtual ~DefaultValueArrayAllocator()
886+ {
887+ }
888+
889+ virtual ValueInternalArray *newArray()
890+ {
891+ return new ValueInternalArray();
892+ }
893+
894+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
895+ {
896+ return new ValueInternalArray( other );
897+ }
898+
899+ virtual void destructArray( ValueInternalArray *array )
900+ {
901+ delete array;
902+ }
903+
904+ virtual void reallocateArrayPageIndex( Value **&indexes,
905+ ValueInternalArray::PageIndex &indexCount,
906+ ValueInternalArray::PageIndex minNewIndexCount )
907+ {
908+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
909+ if ( minNewIndexCount > newIndexCount )
910+ newIndexCount = minNewIndexCount;
911+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
912+ if ( !newIndexes )
913+ throw std::bad_alloc();
914+ indexCount = newIndexCount;
915+ indexes = static_cast<Value **>( newIndexes );
916+ }
917+ virtual void releaseArrayPageIndex( Value **indexes,
918+ ValueInternalArray::PageIndex indexCount )
919+ {
920+ if ( indexes )
921+ free( indexes );
922+ }
923+
924+ virtual Value *allocateArrayPage()
925+ {
926+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
927+ }
928+
929+ virtual void releaseArrayPage( Value *value )
930+ {
931+ if ( value )
932+ free( value );
933+ }
934+};
935+
936+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
937+/// @todo make this thread-safe (lock when accessign batch allocator)
938+class DefaultValueArrayAllocator : public ValueArrayAllocator
939+{
940+public: // overridden from ValueArrayAllocator
941+ virtual ~DefaultValueArrayAllocator()
942+ {
943+ }
944+
945+ virtual ValueInternalArray *newArray()
946+ {
947+ ValueInternalArray *array = arraysAllocator_.allocate();
948+ new (array) ValueInternalArray(); // placement new
949+ return array;
950+ }
951+
952+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
953+ {
954+ ValueInternalArray *array = arraysAllocator_.allocate();
955+ new (array) ValueInternalArray( other ); // placement new
956+ return array;
957+ }
958+
959+ virtual void destructArray( ValueInternalArray *array )
960+ {
961+ if ( array )
962+ {
963+ array->~ValueInternalArray();
964+ arraysAllocator_.release( array );
965+ }
966+ }
967+
968+ virtual void reallocateArrayPageIndex( Value **&indexes,
969+ ValueInternalArray::PageIndex &indexCount,
970+ ValueInternalArray::PageIndex minNewIndexCount )
971+ {
972+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
973+ if ( minNewIndexCount > newIndexCount )
974+ newIndexCount = minNewIndexCount;
975+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
976+ if ( !newIndexes )
977+ throw std::bad_alloc();
978+ indexCount = newIndexCount;
979+ indexes = static_cast<Value **>( newIndexes );
980+ }
981+ virtual void releaseArrayPageIndex( Value **indexes,
982+ ValueInternalArray::PageIndex indexCount )
983+ {
984+ if ( indexes )
985+ free( indexes );
986+ }
987+
988+ virtual Value *allocateArrayPage()
989+ {
990+ return static_cast<Value *>( pagesAllocator_.allocate() );
991+ }
992+
993+ virtual void releaseArrayPage( Value *value )
994+ {
995+ if ( value )
996+ pagesAllocator_.release( value );
997+ }
998+private:
999+ BatchAllocator<ValueInternalArray,1> arraysAllocator_;
1000+ BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
1001+};
1002+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1003+
1004+static ValueArrayAllocator *&arrayAllocator()
1005+{
1006+ static DefaultValueArrayAllocator defaultAllocator;
1007+ static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
1008+ return arrayAllocator;
1009+}
1010+
1011+static struct DummyArrayAllocatorInitializer {
1012+ DummyArrayAllocatorInitializer()
1013+ {
1014+ arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
1015+ }
1016+} dummyArrayAllocatorInitializer;
1017+
1018+// //////////////////////////////////////////////////////////////////
1019+// class ValueInternalArray
1020+// //////////////////////////////////////////////////////////////////
1021+bool
1022+ValueInternalArray::equals( const IteratorState &x,
1023+ const IteratorState &other )
1024+{
1025+ return x.array_ == other.array_
1026+ && x.currentItemIndex_ == other.currentItemIndex_
1027+ && x.currentPageIndex_ == other.currentPageIndex_;
1028+}
1029+
1030+
1031+void
1032+ValueInternalArray::increment( IteratorState &it )
1033+{
1034+ JSON_ASSERT_MESSAGE( it.array_ &&
1035+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
1036+ != it.array_->size_,
1037+ "ValueInternalArray::increment(): moving iterator beyond end" );
1038+ ++(it.currentItemIndex_);
1039+ if ( it.currentItemIndex_ == itemsPerPage )
1040+ {
1041+ it.currentItemIndex_ = 0;
1042+ ++(it.currentPageIndex_);
1043+ }
1044+}
1045+
1046+
1047+void
1048+ValueInternalArray::decrement( IteratorState &it )
1049+{
1050+ JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
1051+ && it.currentItemIndex_ == 0,
1052+ "ValueInternalArray::decrement(): moving iterator beyond end" );
1053+ if ( it.currentItemIndex_ == 0 )
1054+ {
1055+ it.currentItemIndex_ = itemsPerPage-1;
1056+ --(it.currentPageIndex_);
1057+ }
1058+ else
1059+ {
1060+ --(it.currentItemIndex_);
1061+ }
1062+}
1063+
1064+
1065+Value &
1066+ValueInternalArray::unsafeDereference( const IteratorState &it )
1067+{
1068+ return (*(it.currentPageIndex_))[it.currentItemIndex_];
1069+}
1070+
1071+
1072+Value &
1073+ValueInternalArray::dereference( const IteratorState &it )
1074+{
1075+ JSON_ASSERT_MESSAGE( it.array_ &&
1076+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
1077+ < it.array_->size_,
1078+ "ValueInternalArray::dereference(): dereferencing invalid iterator" );
1079+ return unsafeDereference( it );
1080+}
1081+
1082+void
1083+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
1084+{
1085+ it.array_ = const_cast<ValueInternalArray *>( this );
1086+ it.currentItemIndex_ = 0;
1087+ it.currentPageIndex_ = pages_;
1088+}
1089+
1090+
1091+void
1092+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
1093+{
1094+ it.array_ = const_cast<ValueInternalArray *>( this );
1095+ it.currentItemIndex_ = index % itemsPerPage;
1096+ it.currentPageIndex_ = pages_ + index / itemsPerPage;
1097+}
1098+
1099+
1100+void
1101+ValueInternalArray::makeEndIterator( IteratorState &it ) const
1102+{
1103+ makeIterator( it, size_ );
1104+}
1105+
1106+
1107+ValueInternalArray::ValueInternalArray()
1108+ : pages_( 0 )
1109+ , size_( 0 )
1110+ , pageCount_( 0 )
1111+{
1112+}
1113+
1114+
1115+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
1116+ : pages_( 0 )
1117+ , pageCount_( 0 )
1118+ , size_( other.size_ )
1119+{
1120+ PageIndex minNewPages = other.size_ / itemsPerPage;
1121+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
1122+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
1123+ "ValueInternalArray::reserve(): bad reallocation" );
1124+ IteratorState itOther;
1125+ other.makeBeginIterator( itOther );
1126+ Value *value;
1127+ for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
1128+ {
1129+ if ( index % itemsPerPage == 0 )
1130+ {
1131+ PageIndex pageIndex = index / itemsPerPage;
1132+ value = arrayAllocator()->allocateArrayPage();
1133+ pages_[pageIndex] = value;
1134+ }
1135+ new (value) Value( dereference( itOther ) );
1136+ }
1137+}
1138+
1139+
1140+ValueInternalArray &
1141+ValueInternalArray::operator =( const ValueInternalArray &other )
1142+{
1143+ ValueInternalArray temp( other );
1144+ swap( temp );
1145+ return *this;
1146+}
1147+
1148+
1149+ValueInternalArray::~ValueInternalArray()
1150+{
1151+ // destroy all constructed items
1152+ IteratorState it;
1153+ IteratorState itEnd;
1154+ makeBeginIterator( it);
1155+ makeEndIterator( itEnd );
1156+ for ( ; !equals(it,itEnd); increment(it) )
1157+ {
1158+ Value *value = &dereference(it);
1159+ value->~Value();
1160+ }
1161+ // release all pages
1162+ PageIndex lastPageIndex = size_ / itemsPerPage;
1163+ for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
1164+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
1165+ // release pages index
1166+ arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
1167+}
1168+
1169+
1170+void
1171+ValueInternalArray::swap( ValueInternalArray &other )
1172+{
1173+ Value **tempPages = pages_;
1174+ pages_ = other.pages_;
1175+ other.pages_ = tempPages;
1176+ ArrayIndex tempSize = size_;
1177+ size_ = other.size_;
1178+ other.size_ = tempSize;
1179+ PageIndex tempPageCount = pageCount_;
1180+ pageCount_ = other.pageCount_;
1181+ other.pageCount_ = tempPageCount;
1182+}
1183+
1184+void
1185+ValueInternalArray::clear()
1186+{
1187+ ValueInternalArray dummy;
1188+ swap( dummy );
1189+}
1190+
1191+
1192+void
1193+ValueInternalArray::resize( ArrayIndex newSize )
1194+{
1195+ if ( newSize == 0 )
1196+ clear();
1197+ else if ( newSize < size_ )
1198+ {
1199+ IteratorState it;
1200+ IteratorState itEnd;
1201+ makeIterator( it, newSize );
1202+ makeIterator( itEnd, size_ );
1203+ for ( ; !equals(it,itEnd); increment(it) )
1204+ {
1205+ Value *value = &dereference(it);
1206+ value->~Value();
1207+ }
1208+ PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
1209+ PageIndex lastPageIndex = size_ / itemsPerPage;
1210+ for ( ; pageIndex < lastPageIndex; ++pageIndex )
1211+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
1212+ size_ = newSize;
1213+ }
1214+ else if ( newSize > size_ )
1215+ resolveReference( newSize );
1216+}
1217+
1218+
1219+void
1220+ValueInternalArray::makeIndexValid( ArrayIndex index )
1221+{
1222+ // Need to enlarge page index ?
1223+ if ( index >= pageCount_ * itemsPerPage )
1224+ {
1225+ PageIndex minNewPages = (index + 1) / itemsPerPage;
1226+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
1227+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
1228+ }
1229+
1230+ // Need to allocate new pages ?
1231+ ArrayIndex nextPageIndex =
1232+ (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
1233+ : size_;
1234+ if ( nextPageIndex <= index )
1235+ {
1236+ PageIndex pageIndex = nextPageIndex / itemsPerPage;
1237+ PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
1238+ for ( ; pageToAllocate-- > 0; ++pageIndex )
1239+ pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
1240+ }
1241+
1242+ // Initialize all new entries
1243+ IteratorState it;
1244+ IteratorState itEnd;
1245+ makeIterator( it, size_ );
1246+ size_ = index + 1;
1247+ makeIterator( itEnd, size_ );
1248+ for ( ; !equals(it,itEnd); increment(it) )
1249+ {
1250+ Value *value = &dereference(it);
1251+ new (value) Value(); // Construct a default value using placement new
1252+ }
1253+}
1254+
1255+Value &
1256+ValueInternalArray::resolveReference( ArrayIndex index )
1257+{
1258+ if ( index >= size_ )
1259+ makeIndexValid( index );
1260+ return pages_[index/itemsPerPage][index%itemsPerPage];
1261+}
1262+
1263+Value *
1264+ValueInternalArray::find( ArrayIndex index ) const
1265+{
1266+ if ( index >= size_ )
1267+ return 0;
1268+ return &(pages_[index/itemsPerPage][index%itemsPerPage]);
1269+}
1270+
1271+ValueInternalArray::ArrayIndex
1272+ValueInternalArray::size() const
1273+{
1274+ return size_;
1275+}
1276+
1277+int
1278+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
1279+{
1280+ return indexOf(y) - indexOf(x);
1281+}
1282+
1283+
1284+ValueInternalArray::ArrayIndex
1285+ValueInternalArray::indexOf( const IteratorState &iterator )
1286+{
1287+ if ( !iterator.array_ )
1288+ return ArrayIndex(-1);
1289+ return ArrayIndex(
1290+ (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
1291+ + iterator.currentItemIndex_ );
1292+}
1293+
1294+
1295+int
1296+ValueInternalArray::compare( const ValueInternalArray &other ) const
1297+{
1298+ int sizeDiff( size_ - other.size_ );
1299+ if ( sizeDiff != 0 )
1300+ return sizeDiff;
1301+
1302+ for ( ArrayIndex index =0; index < size_; ++index )
1303+ {
1304+ int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
1305+ other.pages_[index/itemsPerPage][index%itemsPerPage] );
1306+ if ( diff != 0 )
1307+ return diff;
1308+ }
1309+ return 0;
1310+}
1311
1312=== added file 'plugin/json_server/json/json_internalmap.inl'
1313--- plugin/json_server/json/json_internalmap.inl 1970-01-01 00:00:00 +0000
1314+++ plugin/json_server/json/json_internalmap.inl 2011-05-04 01:52:37 +0000
1315@@ -0,0 +1,645 @@
1316+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
1317+ *
1318+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
1319+ *
1320+ * Copyright (C) 2011 Stewart Smith
1321+ * All rights reserved.
1322+ *
1323+ * Redistribution and use in source and binary forms, with or without
1324+ * modification, are permitted provided that the following conditions are
1325+ * met:
1326+ *
1327+ * * Redistributions of source code must retain the above copyright
1328+ * notice, this list of conditions and the following disclaimer.
1329+ *
1330+ * * Redistributions in binary form must reproduce the above
1331+ * copyright notice, this list of conditions and the following disclaimer
1332+ * in the documentation and/or other materials provided with the
1333+ * distribution.
1334+ *
1335+ * * The names of its contributors may not be used to endorse or
1336+ * promote products derived from this software without specific prior
1337+ * written permission.
1338+ *
1339+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1340+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1341+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1342+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1343+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1344+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1345+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1346+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1347+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1348+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1349+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1350+ *
1351+ */
1352+
1353+#pragma once
1354+// included by json_value.cpp
1355+// everything is within Json namespace
1356+
1357+// //////////////////////////////////////////////////////////////////
1358+// //////////////////////////////////////////////////////////////////
1359+// //////////////////////////////////////////////////////////////////
1360+// class ValueInternalMap
1361+// //////////////////////////////////////////////////////////////////
1362+// //////////////////////////////////////////////////////////////////
1363+// //////////////////////////////////////////////////////////////////
1364+
1365+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
1366+ * This optimization is used by the fast allocator.
1367+ */
1368+ValueInternalLink::ValueInternalLink()
1369+ : previous_( 0 )
1370+ , next_( 0 )
1371+{
1372+}
1373+
1374+ValueInternalLink::~ValueInternalLink()
1375+{
1376+ for ( int index =0; index < itemPerLink; ++index )
1377+ {
1378+ if ( !items_[index].isItemAvailable() )
1379+ {
1380+ if ( !items_[index].isMemberNameStatic() )
1381+ free( keys_[index] );
1382+ }
1383+ else
1384+ break;
1385+ }
1386+}
1387+
1388+
1389+
1390+ValueMapAllocator::~ValueMapAllocator()
1391+{
1392+}
1393+
1394+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
1395+class DefaultValueMapAllocator : public ValueMapAllocator
1396+{
1397+public: // overridden from ValueMapAllocator
1398+ virtual ValueInternalMap *newMap()
1399+ {
1400+ return new ValueInternalMap();
1401+ }
1402+
1403+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
1404+ {
1405+ return new ValueInternalMap( other );
1406+ }
1407+
1408+ virtual void destructMap( ValueInternalMap *map )
1409+ {
1410+ delete map;
1411+ }
1412+
1413+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
1414+ {
1415+ return new ValueInternalLink[size];
1416+ }
1417+
1418+ virtual void releaseMapBuckets( ValueInternalLink *links )
1419+ {
1420+ delete [] links;
1421+ }
1422+
1423+ virtual ValueInternalLink *allocateMapLink()
1424+ {
1425+ return new ValueInternalLink();
1426+ }
1427+
1428+ virtual void releaseMapLink( ValueInternalLink *link )
1429+ {
1430+ delete link;
1431+ }
1432+};
1433+#else
1434+/// @todo make this thread-safe (lock when accessign batch allocator)
1435+class DefaultValueMapAllocator : public ValueMapAllocator
1436+{
1437+public: // overridden from ValueMapAllocator
1438+ virtual ValueInternalMap *newMap()
1439+ {
1440+ ValueInternalMap *map = mapsAllocator_.allocate();
1441+ new (map) ValueInternalMap(); // placement new
1442+ return map;
1443+ }
1444+
1445+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
1446+ {
1447+ ValueInternalMap *map = mapsAllocator_.allocate();
1448+ new (map) ValueInternalMap( other ); // placement new
1449+ return map;
1450+ }
1451+
1452+ virtual void destructMap( ValueInternalMap *map )
1453+ {
1454+ if ( map )
1455+ {
1456+ map->~ValueInternalMap();
1457+ mapsAllocator_.release( map );
1458+ }
1459+ }
1460+
1461+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
1462+ {
1463+ return new ValueInternalLink[size];
1464+ }
1465+
1466+ virtual void releaseMapBuckets( ValueInternalLink *links )
1467+ {
1468+ delete [] links;
1469+ }
1470+
1471+ virtual ValueInternalLink *allocateMapLink()
1472+ {
1473+ ValueInternalLink *link = linksAllocator_.allocate();
1474+ memset( link, 0, sizeof(ValueInternalLink) );
1475+ return link;
1476+ }
1477+
1478+ virtual void releaseMapLink( ValueInternalLink *link )
1479+ {
1480+ link->~ValueInternalLink();
1481+ linksAllocator_.release( link );
1482+ }
1483+private:
1484+ BatchAllocator<ValueInternalMap,1> mapsAllocator_;
1485+ BatchAllocator<ValueInternalLink,1> linksAllocator_;
1486+};
1487+#endif
1488+
1489+static ValueMapAllocator *&mapAllocator()
1490+{
1491+ static DefaultValueMapAllocator defaultAllocator;
1492+ static ValueMapAllocator *mapAllocator = &defaultAllocator;
1493+ return mapAllocator;
1494+}
1495+
1496+static struct DummyMapAllocatorInitializer {
1497+ DummyMapAllocatorInitializer()
1498+ {
1499+ mapAllocator(); // ensure mapAllocator() statics are initialized before main().
1500+ }
1501+} dummyMapAllocatorInitializer;
1502+
1503+
1504+
1505+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
1506+
1507+/*
1508+use linked list hash map.
1509+buckets array is a container.
1510+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
1511+value have extra state: valid, available, deleted
1512+*/
1513+
1514+
1515+ValueInternalMap::ValueInternalMap()
1516+ : buckets_( 0 )
1517+ , tailLink_( 0 )
1518+ , bucketsSize_( 0 )
1519+ , itemCount_( 0 )
1520+{
1521+}
1522+
1523+
1524+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
1525+ : buckets_( 0 )
1526+ , tailLink_( 0 )
1527+ , bucketsSize_( 0 )
1528+ , itemCount_( 0 )
1529+{
1530+ reserve( other.itemCount_ );
1531+ IteratorState it;
1532+ IteratorState itEnd;
1533+ other.makeBeginIterator( it );
1534+ other.makeEndIterator( itEnd );
1535+ for ( ; !equals(it,itEnd); increment(it) )
1536+ {
1537+ bool isStatic;
1538+ const char *memberName = key( it, isStatic );
1539+ const Value &aValue = value( it );
1540+ resolveReference(memberName, isStatic) = aValue;
1541+ }
1542+}
1543+
1544+
1545+ValueInternalMap &
1546+ValueInternalMap::operator =( const ValueInternalMap &other )
1547+{
1548+ ValueInternalMap dummy( other );
1549+ swap( dummy );
1550+ return *this;
1551+}
1552+
1553+
1554+ValueInternalMap::~ValueInternalMap()
1555+{
1556+ if ( buckets_ )
1557+ {
1558+ for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
1559+ {
1560+ ValueInternalLink *link = buckets_[bucketIndex].next_;
1561+ while ( link )
1562+ {
1563+ ValueInternalLink *linkToRelease = link;
1564+ link = link->next_;
1565+ mapAllocator()->releaseMapLink( linkToRelease );
1566+ }
1567+ }
1568+ mapAllocator()->releaseMapBuckets( buckets_ );
1569+ }
1570+}
1571+
1572+
1573+void
1574+ValueInternalMap::swap( ValueInternalMap &other )
1575+{
1576+ ValueInternalLink *tempBuckets = buckets_;
1577+ buckets_ = other.buckets_;
1578+ other.buckets_ = tempBuckets;
1579+ ValueInternalLink *tempTailLink = tailLink_;
1580+ tailLink_ = other.tailLink_;
1581+ other.tailLink_ = tempTailLink;
1582+ BucketIndex tempBucketsSize = bucketsSize_;
1583+ bucketsSize_ = other.bucketsSize_;
1584+ other.bucketsSize_ = tempBucketsSize;
1585+ BucketIndex tempItemCount = itemCount_;
1586+ itemCount_ = other.itemCount_;
1587+ other.itemCount_ = tempItemCount;
1588+}
1589+
1590+
1591+void
1592+ValueInternalMap::clear()
1593+{
1594+ ValueInternalMap dummy;
1595+ swap( dummy );
1596+}
1597+
1598+
1599+ValueInternalMap::BucketIndex
1600+ValueInternalMap::size() const
1601+{
1602+ return itemCount_;
1603+}
1604+
1605+bool
1606+ValueInternalMap::reserveDelta( BucketIndex growth )
1607+{
1608+ return reserve( itemCount_ + growth );
1609+}
1610+
1611+bool
1612+ValueInternalMap::reserve( BucketIndex newItemCount )
1613+{
1614+ if ( !buckets_ && newItemCount > 0 )
1615+ {
1616+ buckets_ = mapAllocator()->allocateMapBuckets( 1 );
1617+ bucketsSize_ = 1;
1618+ tailLink_ = &buckets_[0];
1619+ }
1620+// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
1621+ return true;
1622+}
1623+
1624+
1625+const Value *
1626+ValueInternalMap::find( const char *key ) const
1627+{
1628+ if ( !bucketsSize_ )
1629+ return 0;
1630+ HashKey hashedKey = hash( key );
1631+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
1632+ for ( const ValueInternalLink *current = &buckets_[bucketIndex];
1633+ current != 0;
1634+ current = current->next_ )
1635+ {
1636+ for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
1637+ {
1638+ if ( current->items_[index].isItemAvailable() )
1639+ return 0;
1640+ if ( strcmp( key, current->keys_[index] ) == 0 )
1641+ return &current->items_[index];
1642+ }
1643+ }
1644+ return 0;
1645+}
1646+
1647+
1648+Value *
1649+ValueInternalMap::find( const char *key )
1650+{
1651+ const ValueInternalMap *constThis = this;
1652+ return const_cast<Value *>( constThis->find( key ) );
1653+}
1654+
1655+
1656+Value &
1657+ValueInternalMap::resolveReference( const char *key,
1658+ bool isStatic )
1659+{
1660+ HashKey hashedKey = hash( key );
1661+ if ( bucketsSize_ )
1662+ {
1663+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
1664+ ValueInternalLink **previous = 0;
1665+ BucketIndex index;
1666+ for ( ValueInternalLink *current = &buckets_[bucketIndex];
1667+ current != 0;
1668+ previous = &current->next_, current = current->next_ )
1669+ {
1670+ for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
1671+ {
1672+ if ( current->items_[index].isItemAvailable() )
1673+ return setNewItem( key, isStatic, current, index );
1674+ if ( strcmp( key, current->keys_[index] ) == 0 )
1675+ return current->items_[index];
1676+ }
1677+ }
1678+ }
1679+
1680+ reserveDelta( 1 );
1681+ return unsafeAdd( key, isStatic, hashedKey );
1682+}
1683+
1684+
1685+void
1686+ValueInternalMap::remove( const char *key )
1687+{
1688+ HashKey hashedKey = hash( key );
1689+ if ( !bucketsSize_ )
1690+ return;
1691+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
1692+ for ( ValueInternalLink *link = &buckets_[bucketIndex];
1693+ link != 0;
1694+ link = link->next_ )
1695+ {
1696+ BucketIndex index;
1697+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
1698+ {
1699+ if ( link->items_[index].isItemAvailable() )
1700+ return;
1701+ if ( strcmp( key, link->keys_[index] ) == 0 )
1702+ {
1703+ doActualRemove( link, index, bucketIndex );
1704+ return;
1705+ }
1706+ }
1707+ }
1708+}
1709+
1710+void
1711+ValueInternalMap::doActualRemove( ValueInternalLink *link,
1712+ BucketIndex index,
1713+ BucketIndex bucketIndex )
1714+{
1715+ // find last item of the bucket and swap it with the 'removed' one.
1716+ // set removed items flags to 'available'.
1717+ // if last page only contains 'available' items, then desallocate it (it's empty)
1718+ ValueInternalLink *&lastLink = getLastLinkInBucket( index );
1719+ BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
1720+ for ( ;
1721+ lastItemIndex < ValueInternalLink::itemPerLink;
1722+ ++lastItemIndex ) // may be optimized with dicotomic search
1723+ {
1724+ if ( lastLink->items_[lastItemIndex].isItemAvailable() )
1725+ break;
1726+ }
1727+
1728+ BucketIndex lastUsedIndex = lastItemIndex - 1;
1729+ Value *valueToDelete = &link->items_[index];
1730+ Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
1731+ if ( valueToDelete != valueToPreserve )
1732+ valueToDelete->swap( *valueToPreserve );
1733+ if ( lastUsedIndex == 0 ) // page is now empty
1734+ { // remove it from bucket linked list and delete it.
1735+ ValueInternalLink *linkPreviousToLast = lastLink->previous_;
1736+ if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
1737+ {
1738+ mapAllocator()->releaseMapLink( lastLink );
1739+ linkPreviousToLast->next_ = 0;
1740+ lastLink = linkPreviousToLast;
1741+ }
1742+ }
1743+ else
1744+ {
1745+ Value dummy;
1746+ valueToPreserve->swap( dummy ); // restore deleted to default Value.
1747+ valueToPreserve->setItemUsed( false );
1748+ }
1749+ --itemCount_;
1750+}
1751+
1752+
1753+ValueInternalLink *&
1754+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
1755+{
1756+ if ( bucketIndex == bucketsSize_ - 1 )
1757+ return tailLink_;
1758+ ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
1759+ if ( !previous )
1760+ previous = &buckets_[bucketIndex];
1761+ return previous;
1762+}
1763+
1764+
1765+Value &
1766+ValueInternalMap::setNewItem( const char *key,
1767+ bool isStatic,
1768+ ValueInternalLink *link,
1769+ BucketIndex index )
1770+{
1771+ char *duplicatedKey = valueAllocator()->makeMemberName( key );
1772+ ++itemCount_;
1773+ link->keys_[index] = duplicatedKey;
1774+ link->items_[index].setItemUsed();
1775+ link->items_[index].setMemberNameIsStatic( isStatic );
1776+ return link->items_[index]; // items already default constructed.
1777+}
1778+
1779+
1780+Value &
1781+ValueInternalMap::unsafeAdd( const char *key,
1782+ bool isStatic,
1783+ HashKey hashedKey )
1784+{
1785+ JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
1786+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
1787+ ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
1788+ ValueInternalLink *link = previousLink;
1789+ BucketIndex index;
1790+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
1791+ {
1792+ if ( link->items_[index].isItemAvailable() )
1793+ break;
1794+ }
1795+ if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
1796+ {
1797+ ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
1798+ index = 0;
1799+ link->next_ = newLink;
1800+ previousLink = newLink;
1801+ link = newLink;
1802+ }
1803+ return setNewItem( key, isStatic, link, index );
1804+}
1805+
1806+
1807+ValueInternalMap::HashKey
1808+ValueInternalMap::hash( const char *key ) const
1809+{
1810+ HashKey hash = 0;
1811+ while ( *key )
1812+ hash += *key++ * 37;
1813+ return hash;
1814+}
1815+
1816+
1817+int
1818+ValueInternalMap::compare( const ValueInternalMap &other ) const
1819+{
1820+ int sizeDiff( itemCount_ - other.itemCount_ );
1821+ if ( sizeDiff != 0 )
1822+ return sizeDiff;
1823+ // Strict order guaranty is required. Compare all keys FIRST, then compare values.
1824+ IteratorState it;
1825+ IteratorState itEnd;
1826+ makeBeginIterator( it );
1827+ makeEndIterator( itEnd );
1828+ for ( ; !equals(it,itEnd); increment(it) )
1829+ {
1830+ if ( !other.find( key( it ) ) )
1831+ return 1;
1832+ }
1833+
1834+ // All keys are equals, let's compare values
1835+ makeBeginIterator( it );
1836+ for ( ; !equals(it,itEnd); increment(it) )
1837+ {
1838+ const Value *otherValue = other.find( key( it ) );
1839+ int valueDiff = value(it).compare( *otherValue );
1840+ if ( valueDiff != 0 )
1841+ return valueDiff;
1842+ }
1843+ return 0;
1844+}
1845+
1846+
1847+void
1848+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
1849+{
1850+ it.map_ = const_cast<ValueInternalMap *>( this );
1851+ it.bucketIndex_ = 0;
1852+ it.itemIndex_ = 0;
1853+ it.link_ = buckets_;
1854+}
1855+
1856+
1857+void
1858+ValueInternalMap::makeEndIterator( IteratorState &it ) const
1859+{
1860+ it.map_ = const_cast<ValueInternalMap *>( this );
1861+ it.bucketIndex_ = bucketsSize_;
1862+ it.itemIndex_ = 0;
1863+ it.link_ = 0;
1864+}
1865+
1866+
1867+bool
1868+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
1869+{
1870+ return x.map_ == other.map_
1871+ && x.bucketIndex_ == other.bucketIndex_
1872+ && x.link_ == other.link_
1873+ && x.itemIndex_ == other.itemIndex_;
1874+}
1875+
1876+
1877+void
1878+ValueInternalMap::incrementBucket( IteratorState &iterator )
1879+{
1880+ ++iterator.bucketIndex_;
1881+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
1882+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
1883+ if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
1884+ iterator.link_ = 0;
1885+ else
1886+ iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
1887+ iterator.itemIndex_ = 0;
1888+}
1889+
1890+
1891+void
1892+ValueInternalMap::increment( IteratorState &iterator )
1893+{
1894+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
1895+ ++iterator.itemIndex_;
1896+ if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
1897+ {
1898+ JSON_ASSERT_MESSAGE( iterator.link_ != 0,
1899+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
1900+ iterator.link_ = iterator.link_->next_;
1901+ if ( iterator.link_ == 0 )
1902+ incrementBucket( iterator );
1903+ }
1904+ else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
1905+ {
1906+ incrementBucket( iterator );
1907+ }
1908+}
1909+
1910+
1911+void
1912+ValueInternalMap::decrement( IteratorState &iterator )
1913+{
1914+ if ( iterator.itemIndex_ == 0 )
1915+ {
1916+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
1917+ if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
1918+ {
1919+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
1920+ --(iterator.bucketIndex_);
1921+ }
1922+ iterator.link_ = iterator.link_->previous_;
1923+ iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
1924+ }
1925+}
1926+
1927+
1928+const char *
1929+ValueInternalMap::key( const IteratorState &iterator )
1930+{
1931+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
1932+ return iterator.link_->keys_[iterator.itemIndex_];
1933+}
1934+
1935+const char *
1936+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
1937+{
1938+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
1939+ isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
1940+ return iterator.link_->keys_[iterator.itemIndex_];
1941+}
1942+
1943+
1944+Value &
1945+ValueInternalMap::value( const IteratorState &iterator )
1946+{
1947+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
1948+ return iterator.link_->items_[iterator.itemIndex_];
1949+}
1950+
1951+
1952+int
1953+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
1954+{
1955+ int offset = 0;
1956+ IteratorState it = x;
1957+ while ( !equals( it, y ) )
1958+ increment( it );
1959+ return offset;
1960+}
1961
1962=== added file 'plugin/json_server/json/json_reader.cpp'
1963--- plugin/json_server/json/json_reader.cpp 1970-01-01 00:00:00 +0000
1964+++ plugin/json_server/json/json_reader.cpp 2011-05-04 01:52:37 +0000
1965@@ -0,0 +1,921 @@
1966+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
1967+ *
1968+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
1969+ *
1970+ * Copyright (C) 2011 Stewart Smith
1971+ * All rights reserved.
1972+ *
1973+ * Redistribution and use in source and binary forms, with or without
1974+ * modification, are permitted provided that the following conditions are
1975+ * met:
1976+ *
1977+ * * Redistributions of source code must retain the above copyright
1978+ * notice, this list of conditions and the following disclaimer.
1979+ *
1980+ * * Redistributions in binary form must reproduce the above
1981+ * copyright notice, this list of conditions and the following disclaimer
1982+ * in the documentation and/or other materials provided with the
1983+ * distribution.
1984+ *
1985+ * * The names of its contributors may not be used to endorse or
1986+ * promote products derived from this software without specific prior
1987+ * written permission.
1988+ *
1989+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1990+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1991+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1992+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1993+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1994+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1995+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1996+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1997+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1998+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1999+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2000+ *
2001+ */
2002+
2003+#include <config.h>
2004+
2005+#include <plugin/json_server/json/reader.h>
2006+#include <plugin/json_server/json/value.h>
2007+
2008+#include <cassert>
2009+#include <cstdio>
2010+#include <cstring>
2011+#include <iostream>
2012+#include <stdexcept>
2013+#include <utility>
2014+
2015+namespace Json {
2016+
2017+// Implementation of class Features
2018+// ////////////////////////////////
2019+
2020+Features::Features()
2021+ : allowComments_( true )
2022+ , strictRoot_( false )
2023+{
2024+}
2025+
2026+
2027+Features
2028+Features::all()
2029+{
2030+ return Features();
2031+}
2032+
2033+
2034+Features
2035+Features::strictMode()
2036+{
2037+ Features features;
2038+ features.allowComments_ = false;
2039+ features.strictRoot_ = true;
2040+ return features;
2041+}
2042+
2043+// Implementation of class Reader
2044+// ////////////////////////////////
2045+
2046+
2047+static inline bool
2048+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
2049+{
2050+ return c == c1 || c == c2 || c == c3 || c == c4;
2051+}
2052+
2053+static inline bool
2054+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
2055+{
2056+ return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
2057+}
2058+
2059+
2060+static bool
2061+containsNewLine( Reader::Location begin,
2062+ Reader::Location end )
2063+{
2064+ for ( ;begin < end; ++begin )
2065+ if ( *begin == '\n' || *begin == '\r' )
2066+ return true;
2067+ return false;
2068+}
2069+
2070+static std::string codePointToUTF8(unsigned int cp)
2071+{
2072+ std::string result;
2073+
2074+ // based on description from http://en.wikipedia.org/wiki/UTF-8
2075+
2076+ if (cp <= 0x7f)
2077+ {
2078+ result.resize(1);
2079+ result[0] = static_cast<char>(cp);
2080+ }
2081+ else if (cp <= 0x7FF)
2082+ {
2083+ result.resize(2);
2084+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
2085+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
2086+ }
2087+ else if (cp <= 0xFFFF)
2088+ {
2089+ result.resize(3);
2090+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
2091+ result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
2092+ result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
2093+ }
2094+ else if (cp <= 0x10FFFF)
2095+ {
2096+ result.resize(4);
2097+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
2098+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
2099+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
2100+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
2101+ }
2102+
2103+ return result;
2104+}
2105+
2106+
2107+// Class Reader
2108+// //////////////////////////////////////////////////////////////////
2109+
2110+Reader::Reader()
2111+ : features_( Features::all() )
2112+{
2113+}
2114+
2115+
2116+Reader::Reader( const Features &features )
2117+ : features_( features )
2118+{
2119+}
2120+
2121+
2122+bool
2123+Reader::parse( const std::string &document,
2124+ Value &root,
2125+ bool collectComments )
2126+{
2127+ document_ = document;
2128+ const char *begin = document_.c_str();
2129+ const char *end = begin + document_.length();
2130+ return parse( begin, end, root, collectComments );
2131+}
2132+
2133+
2134+bool
2135+Reader::parse( std::istream& sin,
2136+ Value &root,
2137+ bool collectComments )
2138+{
2139+ //std::istream_iterator<char> begin(sin);
2140+ //std::istream_iterator<char> end;
2141+ // Those would allow streamed input from a file, if parse() were a
2142+ // template function.
2143+
2144+ // Since std::string is reference-counted, this at least does not
2145+ // create an extra copy.
2146+ std::string doc;
2147+ std::getline(sin, doc, (char)EOF);
2148+ return parse( doc, root, collectComments );
2149+}
2150+
2151+bool
2152+Reader::parse( const char *beginDoc, const char *endDoc,
2153+ Value &root,
2154+ bool collectComments )
2155+{
2156+ if ( !features_.allowComments_ )
2157+ {
2158+ collectComments = false;
2159+ }
2160+
2161+ begin_ = beginDoc;
2162+ end_ = endDoc;
2163+ collectComments_ = collectComments;
2164+ current_ = begin_;
2165+ lastValueEnd_ = 0;
2166+ lastValue_ = 0;
2167+ commentsBefore_ = "";
2168+ errors_.clear();
2169+ while ( !nodes_.empty() )
2170+ nodes_.pop();
2171+ nodes_.push( &root );
2172+
2173+ bool successful = readValue();
2174+ Token token;
2175+ skipCommentTokens( token );
2176+ if ( collectComments_ && !commentsBefore_.empty() )
2177+ root.setComment( commentsBefore_, commentAfter );
2178+ if ( features_.strictRoot_ )
2179+ {
2180+ if ( !root.isArray() && !root.isObject() )
2181+ {
2182+ // Set error location to start of doc, ideally should be first token found in doc
2183+ token.type_ = tokenError;
2184+ token.start_ = beginDoc;
2185+ token.end_ = endDoc;
2186+ addError( "A valid JSON document must be either an array or an object value.",
2187+ token );
2188+ return false;
2189+ }
2190+ }
2191+ return successful;
2192+}
2193+
2194+
2195+bool
2196+Reader::readValue()
2197+{
2198+ Token token;
2199+ skipCommentTokens( token );
2200+ bool successful = true;
2201+
2202+ if ( collectComments_ && !commentsBefore_.empty() )
2203+ {
2204+ currentValue().setComment( commentsBefore_, commentBefore );
2205+ commentsBefore_ = "";
2206+ }
2207+
2208+
2209+ switch ( token.type_ )
2210+ {
2211+ case tokenObjectBegin:
2212+ successful = readObject( token );
2213+ break;
2214+ case tokenArrayBegin:
2215+ successful = readArray( token );
2216+ break;
2217+ case tokenNumber:
2218+ successful = decodeNumber( token );
2219+ break;
2220+ case tokenString:
2221+ successful = decodeString( token );
2222+ break;
2223+ case tokenTrue:
2224+ currentValue() = true;
2225+ break;
2226+ case tokenFalse:
2227+ currentValue() = false;
2228+ break;
2229+ case tokenNull:
2230+ currentValue() = Value();
2231+ break;
2232+ default:
2233+ return addError( "Syntax error: value, object or array expected.", token );
2234+ }
2235+
2236+ if ( collectComments_ )
2237+ {
2238+ lastValueEnd_ = current_;
2239+ lastValue_ = &currentValue();
2240+ }
2241+
2242+ return successful;
2243+}
2244+
2245+
2246+void
2247+Reader::skipCommentTokens( Token &token )
2248+{
2249+ if ( features_.allowComments_ )
2250+ {
2251+ do
2252+ {
2253+ readToken( token );
2254+ }
2255+ while ( token.type_ == tokenComment );
2256+ }
2257+ else
2258+ {
2259+ readToken( token );
2260+ }
2261+}
2262+
2263+
2264+bool
2265+Reader::expectToken( TokenType type, Token &token, const char *message )
2266+{
2267+ readToken( token );
2268+ if ( token.type_ != type )
2269+ return addError( message, token );
2270+ return true;
2271+}
2272+
2273+
2274+bool
2275+Reader::readToken( Token &token )
2276+{
2277+ skipSpaces();
2278+ token.start_ = current_;
2279+ Char c = getNextChar();
2280+ bool ok = true;
2281+ switch ( c )
2282+ {
2283+ case '{':
2284+ token.type_ = tokenObjectBegin;
2285+ break;
2286+ case '}':
2287+ token.type_ = tokenObjectEnd;
2288+ break;
2289+ case '[':
2290+ token.type_ = tokenArrayBegin;
2291+ break;
2292+ case ']':
2293+ token.type_ = tokenArrayEnd;
2294+ break;
2295+ case '"':
2296+ token.type_ = tokenString;
2297+ ok = readString();
2298+ break;
2299+ case '/':
2300+ token.type_ = tokenComment;
2301+ ok = readComment();
2302+ break;
2303+ case '0':
2304+ case '1':
2305+ case '2':
2306+ case '3':
2307+ case '4':
2308+ case '5':
2309+ case '6':
2310+ case '7':
2311+ case '8':
2312+ case '9':
2313+ case '-':
2314+ token.type_ = tokenNumber;
2315+ readNumber();
2316+ break;
2317+ case 't':
2318+ token.type_ = tokenTrue;
2319+ ok = match( "rue", 3 );
2320+ break;
2321+ case 'f':
2322+ token.type_ = tokenFalse;
2323+ ok = match( "alse", 4 );
2324+ break;
2325+ case 'n':
2326+ token.type_ = tokenNull;
2327+ ok = match( "ull", 3 );
2328+ break;
2329+ case ',':
2330+ token.type_ = tokenArraySeparator;
2331+ break;
2332+ case ':':
2333+ token.type_ = tokenMemberSeparator;
2334+ break;
2335+ case 0:
2336+ token.type_ = tokenEndOfStream;
2337+ break;
2338+ default:
2339+ ok = false;
2340+ break;
2341+ }
2342+ if ( !ok )
2343+ token.type_ = tokenError;
2344+ token.end_ = current_;
2345+ return true;
2346+}
2347+
2348+
2349+void
2350+Reader::skipSpaces()
2351+{
2352+ while ( current_ != end_ )
2353+ {
2354+ Char c = *current_;
2355+ if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
2356+ ++current_;
2357+ else
2358+ break;
2359+ }
2360+}
2361+
2362+
2363+bool
2364+Reader::match( Location pattern,
2365+ int patternLength )
2366+{
2367+ if ( end_ - current_ < patternLength )
2368+ return false;
2369+ int index = patternLength;
2370+ while ( index-- )
2371+ if ( current_[index] != pattern[index] )
2372+ return false;
2373+ current_ += patternLength;
2374+ return true;
2375+}
2376+
2377+
2378+bool
2379+Reader::readComment()
2380+{
2381+ Location commentBegin = current_ - 1;
2382+ Char c = getNextChar();
2383+ bool successful = false;
2384+ if ( c == '*' )
2385+ successful = readCStyleComment();
2386+ else if ( c == '/' )
2387+ successful = readCppStyleComment();
2388+ if ( !successful )
2389+ return false;
2390+
2391+ if ( collectComments_ )
2392+ {
2393+ CommentPlacement placement = commentBefore;
2394+ if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
2395+ {
2396+ if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
2397+ placement = commentAfterOnSameLine;
2398+ }
2399+
2400+ addComment( commentBegin, current_, placement );
2401+ }
2402+ return true;
2403+}
2404+
2405+
2406+void
2407+Reader::addComment( Location begin,
2408+ Location end,
2409+ CommentPlacement placement )
2410+{
2411+ assert( collectComments_ );
2412+ if ( placement == commentAfterOnSameLine )
2413+ {
2414+ assert( lastValue_ != 0 );
2415+ lastValue_->setComment( std::string( begin, end ), placement );
2416+ }
2417+ else
2418+ {
2419+ if ( !commentsBefore_.empty() )
2420+ commentsBefore_ += "\n";
2421+ commentsBefore_ += std::string( begin, end );
2422+ }
2423+}
2424+
2425+
2426+bool
2427+Reader::readCStyleComment()
2428+{
2429+ while ( current_ != end_ )
2430+ {
2431+ Char c = getNextChar();
2432+ if ( c == '*' && *current_ == '/' )
2433+ break;
2434+ }
2435+ return getNextChar() == '/';
2436+}
2437+
2438+
2439+bool
2440+Reader::readCppStyleComment()
2441+{
2442+ while ( current_ != end_ )
2443+ {
2444+ Char c = getNextChar();
2445+ if ( c == '\r' || c == '\n' )
2446+ break;
2447+ }
2448+ return true;
2449+}
2450+
2451+
2452+void
2453+Reader::readNumber()
2454+{
2455+ while ( current_ != end_ )
2456+ {
2457+ if ( !(*current_ >= '0' && *current_ <= '9') &&
2458+ !in( *current_, '.', 'e', 'E', '+', '-' ) )
2459+ break;
2460+ ++current_;
2461+ }
2462+}
2463+
2464+bool
2465+Reader::readString()
2466+{
2467+ Char c = 0;
2468+ while ( current_ != end_ )
2469+ {
2470+ c = getNextChar();
2471+ if ( c == '\\' )
2472+ getNextChar();
2473+ else if ( c == '"' )
2474+ break;
2475+ }
2476+ return c == '"';
2477+}
2478+
2479+
2480+bool
2481+Reader::readObject( Token & )
2482+{
2483+ Token tokenName;
2484+ std::string name;
2485+ currentValue() = Value( objectValue );
2486+ while ( readToken( tokenName ) )
2487+ {
2488+ bool initialTokenOk = true;
2489+ while ( tokenName.type_ == tokenComment && initialTokenOk )
2490+ initialTokenOk = readToken( tokenName );
2491+ if ( !initialTokenOk )
2492+ break;
2493+ if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
2494+ return true;
2495+ if ( tokenName.type_ != tokenString )
2496+ break;
2497+
2498+ name = "";
2499+ if ( !decodeString( tokenName, name ) )
2500+ return recoverFromError( tokenObjectEnd );
2501+
2502+ Token colon;
2503+ if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
2504+ {
2505+ return addErrorAndRecover( "Missing ':' after object member name",
2506+ colon,
2507+ tokenObjectEnd );
2508+ }
2509+ Value &value = currentValue()[ name ];
2510+ nodes_.push( &value );
2511+ bool ok = readValue();
2512+ nodes_.pop();
2513+ if ( !ok ) // error already set
2514+ return recoverFromError( tokenObjectEnd );
2515+
2516+ Token comma;
2517+ if ( !readToken( comma )
2518+ || ( comma.type_ != tokenObjectEnd &&
2519+ comma.type_ != tokenArraySeparator &&
2520+ comma.type_ != tokenComment ) )
2521+ {
2522+ return addErrorAndRecover( "Missing ',' or '}' in object declaration",
2523+ comma,
2524+ tokenObjectEnd );
2525+ }
2526+ bool finalizeTokenOk = true;
2527+ while ( comma.type_ == tokenComment &&
2528+ finalizeTokenOk )
2529+ finalizeTokenOk = readToken( comma );
2530+ if ( comma.type_ == tokenObjectEnd )
2531+ return true;
2532+ }
2533+ return addErrorAndRecover( "Missing '}' or object member name",
2534+ tokenName,
2535+ tokenObjectEnd );
2536+}
2537+
2538+
2539+bool
2540+Reader::readArray( Token & )
2541+{
2542+ currentValue() = Value( arrayValue );
2543+ skipSpaces();
2544+ if ( *current_ == ']' ) // empty array
2545+ {
2546+ Token endArray;
2547+ readToken( endArray );
2548+ return true;
2549+ }
2550+ int index = 0;
2551+ while ( true )
2552+ {
2553+ Value &value = currentValue()[ index++ ];
2554+ nodes_.push( &value );
2555+ bool ok = readValue();
2556+ nodes_.pop();
2557+ if ( !ok ) // error already set
2558+ return recoverFromError( tokenArrayEnd );
2559+
2560+ Token token;
2561+ // Accept Comment after last item in the array.
2562+ ok = readToken( token );
2563+ while ( token.type_ == tokenComment && ok )
2564+ {
2565+ ok = readToken( token );
2566+ }
2567+ bool badTokenType = ( token.type_ == tokenArraySeparator &&
2568+ token.type_ == tokenArrayEnd );
2569+ if ( !ok || badTokenType )
2570+ {
2571+ return addErrorAndRecover( "Missing ',' or ']' in array declaration",
2572+ token,
2573+ tokenArrayEnd );
2574+ }
2575+ if ( token.type_ == tokenArrayEnd )
2576+ break;
2577+ }
2578+ return true;
2579+}
2580+
2581+
2582+bool
2583+Reader::decodeNumber( Token &token )
2584+{
2585+ bool isDouble = false;
2586+ for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
2587+ {
2588+ isDouble = isDouble
2589+ || in( *inspect, '.', 'e', 'E', '+' )
2590+ || ( *inspect == '-' && inspect != token.start_ );
2591+ }
2592+ if ( isDouble )
2593+ return decodeDouble( token );
2594+ Location current = token.start_;
2595+ bool isNegative = *current == '-';
2596+ if ( isNegative )
2597+ ++current;
2598+ Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
2599+ : Value::maxUInt) / 10;
2600+ Value::UInt value = 0;
2601+ while ( current < token.end_ )
2602+ {
2603+ Char c = *current++;
2604+ if ( c < '0' || c > '9' )
2605+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
2606+ if ( value >= threshold )
2607+ return decodeDouble( token );
2608+ value = value * 10 + Value::UInt(c - '0');
2609+ }
2610+ if ( isNegative )
2611+ currentValue() = -Value::Int( value );
2612+ else if ( value <= Value::UInt(Value::maxInt) )
2613+ currentValue() = Value::Int( value );
2614+ else
2615+ currentValue() = value;
2616+ return true;
2617+}
2618+
2619+
2620+bool
2621+Reader::decodeDouble( Token &token )
2622+{
2623+ double value = 0;
2624+ const int bufferSize = 32;
2625+ int count;
2626+ int length = int(token.end_ - token.start_);
2627+ if ( length <= bufferSize )
2628+ {
2629+ Char buffer[bufferSize];
2630+ memcpy( buffer, token.start_, length );
2631+ buffer[length] = 0;
2632+ count = sscanf( buffer, "%lf", &value );
2633+ }
2634+ else
2635+ {
2636+ std::string buffer( token.start_, token.end_ );
2637+ count = sscanf( buffer.c_str(), "%lf", &value );
2638+ }
2639+
2640+ if ( count != 1 )
2641+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
2642+ currentValue() = value;
2643+ return true;
2644+}
2645+
2646+
2647+bool
2648+Reader::decodeString( Token &token )
2649+{
2650+ std::string decoded;
2651+ if ( !decodeString( token, decoded ) )
2652+ return false;
2653+ currentValue() = decoded;
2654+ return true;
2655+}
2656+
2657+
2658+bool
2659+Reader::decodeString( Token &token, std::string &decoded )
2660+{
2661+ decoded.reserve( token.end_ - token.start_ - 2 );
2662+ Location current = token.start_ + 1; // skip '"'
2663+ Location end = token.end_ - 1; // do not include '"'
2664+ while ( current != end )
2665+ {
2666+ Char c = *current++;
2667+ if ( c == '"' )
2668+ break;
2669+ else if ( c == '\\' )
2670+ {
2671+ if ( current == end )
2672+ return addError( "Empty escape sequence in string", token, current );
2673+ Char escape = *current++;
2674+ switch ( escape )
2675+ {
2676+ case '"': decoded += '"'; break;
2677+ case '/': decoded += '/'; break;
2678+ case '\\': decoded += '\\'; break;
2679+ case 'b': decoded += '\b'; break;
2680+ case 'f': decoded += '\f'; break;
2681+ case 'n': decoded += '\n'; break;
2682+ case 'r': decoded += '\r'; break;
2683+ case 't': decoded += '\t'; break;
2684+ case 'u':
2685+ {
2686+ unsigned int unicode;
2687+ if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
2688+ return false;
2689+ decoded += codePointToUTF8(unicode);
2690+ }
2691+ break;
2692+ default:
2693+ return addError( "Bad escape sequence in string", token, current );
2694+ }
2695+ }
2696+ else
2697+ {
2698+ decoded += c;
2699+ }
2700+ }
2701+ return true;
2702+}
2703+
2704+bool
2705+Reader::decodeUnicodeCodePoint( Token &token,
2706+ Location &current,
2707+ Location end,
2708+ unsigned int &unicode )
2709+{
2710+
2711+ if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
2712+ return false;
2713+ if (unicode >= 0xD800 && unicode <= 0xDBFF)
2714+ {
2715+ // surrogate pairs
2716+ if (end - current < 6)
2717+ return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
2718+ unsigned int surrogatePair;
2719+ if (*(current++) == '\\' && *(current++)== 'u')
2720+ {
2721+ if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
2722+ {
2723+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
2724+ }
2725+ else
2726+ return false;
2727+ }
2728+ else
2729+ return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
2730+ }
2731+ return true;
2732+}
2733+
2734+bool
2735+Reader::decodeUnicodeEscapeSequence( Token &token,
2736+ Location &current,
2737+ Location end,
2738+ unsigned int &unicode )
2739+{
2740+ if ( end - current < 4 )
2741+ return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
2742+ unicode = 0;
2743+ for ( int index =0; index < 4; ++index )
2744+ {
2745+ Char c = *current++;
2746+ unicode *= 16;
2747+ if ( c >= '0' && c <= '9' )
2748+ unicode += c - '0';
2749+ else if ( c >= 'a' && c <= 'f' )
2750+ unicode += c - 'a' + 10;
2751+ else if ( c >= 'A' && c <= 'F' )
2752+ unicode += c - 'A' + 10;
2753+ else
2754+ return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
2755+ }
2756+ return true;
2757+}
2758+
2759+
2760+bool
2761+Reader::addError( const std::string &message,
2762+ Token &token,
2763+ Location extra )
2764+{
2765+ ErrorInfo info;
2766+ info.token_ = token;
2767+ info.message_ = message;
2768+ info.extra_ = extra;
2769+ errors_.push_back( info );
2770+ return false;
2771+}
2772+
2773+
2774+bool
2775+Reader::recoverFromError( TokenType skipUntilToken )
2776+{
2777+ int errorCount = int(errors_.size());
2778+ Token skip;
2779+ while ( true )
2780+ {
2781+ if ( !readToken(skip) )
2782+ errors_.resize( errorCount ); // discard errors caused by recovery
2783+ if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
2784+ break;
2785+ }
2786+ errors_.resize( errorCount );
2787+ return false;
2788+}
2789+
2790+
2791+bool
2792+Reader::addErrorAndRecover( const std::string &message,
2793+ Token &token,
2794+ TokenType skipUntilToken )
2795+{
2796+ addError( message, token );
2797+ return recoverFromError( skipUntilToken );
2798+}
2799+
2800+
2801+Value &
2802+Reader::currentValue()
2803+{
2804+ return *(nodes_.top());
2805+}
2806+
2807+
2808+Reader::Char
2809+Reader::getNextChar()
2810+{
2811+ if ( current_ == end_ )
2812+ return 0;
2813+ return *current_++;
2814+}
2815+
2816+
2817+void
2818+Reader::getLocationLineAndColumn( Location location,
2819+ int &line,
2820+ int &column ) const
2821+{
2822+ Location current = begin_;
2823+ Location lastLineStart = current;
2824+ line = 0;
2825+ while ( current < location && current != end_ )
2826+ {
2827+ Char c = *current++;
2828+ if ( c == '\r' )
2829+ {
2830+ if ( *current == '\n' )
2831+ ++current;
2832+ lastLineStart = current;
2833+ ++line;
2834+ }
2835+ else if ( c == '\n' )
2836+ {
2837+ lastLineStart = current;
2838+ ++line;
2839+ }
2840+ }
2841+ // column & line start at 1
2842+ column = int(location - lastLineStart) + 1;
2843+ ++line;
2844+}
2845+
2846+
2847+std::string
2848+Reader::getLocationLineAndColumn( Location location ) const
2849+{
2850+ int line, column;
2851+ getLocationLineAndColumn( location, line, column );
2852+ char buffer[18+16+16+1];
2853+ sprintf( buffer, "Line %d, Column %d", line, column );
2854+ return buffer;
2855+}
2856+
2857+
2858+std::string
2859+Reader::getFormatedErrorMessages() const
2860+{
2861+ std::string formattedMessage;
2862+ for ( Errors::const_iterator itError = errors_.begin();
2863+ itError != errors_.end();
2864+ ++itError )
2865+ {
2866+ const ErrorInfo &error = *itError;
2867+ formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
2868+ formattedMessage += " " + error.message_ + "\n";
2869+ if ( error.extra_ )
2870+ formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
2871+ }
2872+ return formattedMessage;
2873+}
2874+
2875+
2876+std::istream& operator>>( std::istream &sin, Value &root )
2877+{
2878+ Json::Reader reader;
2879+ bool ok = reader.parse(sin, root, true);
2880+ //JSON_ASSERT( ok );
2881+ if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
2882+ return sin;
2883+}
2884+
2885+
2886+} // namespace Json
2887
2888=== added file 'plugin/json_server/json/json_value.cpp'
2889--- plugin/json_server/json/json_value.cpp 1970-01-01 00:00:00 +0000
2890+++ plugin/json_server/json/json_value.cpp 2011-05-04 01:52:37 +0000
2891@@ -0,0 +1,1759 @@
2892+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2893+ *
2894+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
2895+ *
2896+ * Copyright (C) 2011 Stewart Smith
2897+ * All rights reserved.
2898+ *
2899+ * Redistribution and use in source and binary forms, with or without
2900+ * modification, are permitted provided that the following conditions are
2901+ * met:
2902+ *
2903+ * * Redistributions of source code must retain the above copyright
2904+ * notice, this list of conditions and the following disclaimer.
2905+ *
2906+ * * Redistributions in binary form must reproduce the above
2907+ * copyright notice, this list of conditions and the following disclaimer
2908+ * in the documentation and/or other materials provided with the
2909+ * distribution.
2910+ *
2911+ * * The names of its contributors may not be used to endorse or
2912+ * promote products derived from this software without specific prior
2913+ * written permission.
2914+ *
2915+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2916+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2917+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2918+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2919+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2920+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2921+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2922+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2923+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2924+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2925+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2926+ *
2927+ */
2928+
2929+#include <config.h>
2930+
2931+#include <plugin/json_server/json/value.h>
2932+#include <plugin/json_server/json/writer.h>
2933+
2934+#include <cassert>
2935+#include <cstring>
2936+#include <iostream>
2937+#include <stdexcept>
2938+#include <utility>
2939+
2940+#ifdef JSON_USE_CPPTL
2941+# include <cpptl/conststring.h>
2942+#endif
2943+#include <cstddef> // size_t
2944+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
2945+# include "json_batchallocator.h"
2946+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
2947+
2948+#define JSON_ASSERT_UNREACHABLE assert( false )
2949+#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
2950+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
2951+
2952+namespace Json {
2953+
2954+const Value Value::null;
2955+const Int Value::minInt = Int( ~(UInt(-1)/2) );
2956+const Int Value::maxInt = Int( UInt(-1)/2 );
2957+const UInt Value::maxUInt = UInt(-1);
2958+
2959+// A "safe" implementation of strdup. Allow null pointer to be passed.
2960+// Also avoid warning on msvc80.
2961+//
2962+//inline char *safeStringDup( const char *czstring )
2963+//{
2964+// if ( czstring )
2965+// {
2966+// const size_t length = (unsigned int)( strlen(czstring) + 1 );
2967+// char *newString = static_cast<char *>( malloc( length ) );
2968+// memcpy( newString, czstring, length );
2969+// return newString;
2970+// }
2971+// return 0;
2972+//}
2973+//
2974+//inline char *safeStringDup( const std::string &str )
2975+//{
2976+// if ( !str.empty() )
2977+// {
2978+// const size_t length = str.length();
2979+// char *newString = static_cast<char *>( malloc( length + 1 ) );
2980+// memcpy( newString, str.c_str(), length );
2981+// newString[length] = 0;
2982+// return newString;
2983+// }
2984+// return 0;
2985+//}
2986+
2987+ValueAllocator::~ValueAllocator()
2988+{
2989+}
2990+
2991+class DefaultValueAllocator : public ValueAllocator
2992+{
2993+public:
2994+ virtual ~DefaultValueAllocator()
2995+ {
2996+ }
2997+
2998+ virtual char *makeMemberName( const char *memberName )
2999+ {
3000+ return duplicateStringValue( memberName );
3001+ }
3002+
3003+ virtual void releaseMemberName( char *memberName )
3004+ {
3005+ releaseStringValue( memberName );
3006+ }
3007+
3008+ virtual char *duplicateStringValue( const char *value,
3009+ unsigned int length = unknown )
3010+ {
3011+ //@todo invesgate this old optimization
3012+ //if ( !value || value[0] == 0 )
3013+ // return 0;
3014+
3015+ if ( length == unknown )
3016+ length = (unsigned int)strlen(value);
3017+ char *newString = static_cast<char *>( malloc( length + 1 ) );
3018+ memcpy( newString, value, length );
3019+ newString[length] = 0;
3020+ return newString;
3021+ }
3022+
3023+ virtual void releaseStringValue( char *value )
3024+ {
3025+ if ( value )
3026+ free( value );
3027+ }
3028+};
3029+
3030+static ValueAllocator *&valueAllocator()
3031+{
3032+ static DefaultValueAllocator defaultAllocator;
3033+ static ValueAllocator *valueAllocator = &defaultAllocator;
3034+ return valueAllocator;
3035+}
3036+
3037+static struct DummyValueAllocatorInitializer {
3038+ DummyValueAllocatorInitializer()
3039+ {
3040+ valueAllocator(); // ensure valueAllocator() statics are initialized before main().
3041+ }
3042+} dummyValueAllocatorInitializer;
3043+
3044+
3045+
3046+// //////////////////////////////////////////////////////////////////
3047+// //////////////////////////////////////////////////////////////////
3048+// //////////////////////////////////////////////////////////////////
3049+// ValueInternals...
3050+// //////////////////////////////////////////////////////////////////
3051+// //////////////////////////////////////////////////////////////////
3052+// //////////////////////////////////////////////////////////////////
3053+#ifdef JSON_VALUE_USE_INTERNAL_MAP
3054+# include "json_internalarray.inl"
3055+# include "json_internalmap.inl"
3056+#endif // JSON_VALUE_USE_INTERNAL_MAP
3057+
3058+# include "json_valueiterator.inl"
3059+
3060+
3061+// //////////////////////////////////////////////////////////////////
3062+// //////////////////////////////////////////////////////////////////
3063+// //////////////////////////////////////////////////////////////////
3064+// class Value::CommentInfo
3065+// //////////////////////////////////////////////////////////////////
3066+// //////////////////////////////////////////////////////////////////
3067+// //////////////////////////////////////////////////////////////////
3068+
3069+
3070+Value::CommentInfo::CommentInfo()
3071+ : comment_( 0 )
3072+{
3073+}
3074+
3075+Value::CommentInfo::~CommentInfo()
3076+{
3077+ if ( comment_ )
3078+ valueAllocator()->releaseStringValue( comment_ );
3079+}
3080+
3081+
3082+void
3083+Value::CommentInfo::setComment( const char *text )
3084+{
3085+ if ( comment_ )
3086+ valueAllocator()->releaseStringValue( comment_ );
3087+ JSON_ASSERT( text );
3088+ JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
3089+ // It seems that /**/ style comments are acceptable as well.
3090+ comment_ = valueAllocator()->duplicateStringValue( text );
3091+}
3092+
3093+
3094+// //////////////////////////////////////////////////////////////////
3095+// //////////////////////////////////////////////////////////////////
3096+// //////////////////////////////////////////////////////////////////
3097+// class Value::CZString
3098+// //////////////////////////////////////////////////////////////////
3099+// //////////////////////////////////////////////////////////////////
3100+// //////////////////////////////////////////////////////////////////
3101+# ifndef JSON_VALUE_USE_INTERNAL_MAP
3102+
3103+// Notes: index_ indicates if the string was allocated when
3104+// a string is stored.
3105+
3106+Value::CZString::CZString( int index_arg )
3107+ : cstr_( 0 )
3108+ , index_( index_arg )
3109+{
3110+}
3111+
3112+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
3113+ : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
3114+ : cstr )
3115+ , index_( allocate )
3116+{
3117+}
3118+
3119+Value::CZString::CZString( const CZString &other )
3120+: cstr_( other.index_ != noDuplication && other.cstr_ != 0
3121+ ? valueAllocator()->makeMemberName( other.cstr_ )
3122+ : other.cstr_ )
3123+ , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
3124+ : other.index_ )
3125+{
3126+}
3127+
3128+Value::CZString::~CZString()
3129+{
3130+ if ( cstr_ && index_ == duplicate )
3131+ valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
3132+}
3133+
3134+void
3135+Value::CZString::swap( CZString &other )
3136+{
3137+ std::swap( cstr_, other.cstr_ );
3138+ std::swap( index_, other.index_ );
3139+}
3140+
3141+Value::CZString &
3142+Value::CZString::operator =( const CZString &other )
3143+{
3144+ CZString temp( other );
3145+ swap( temp );
3146+ return *this;
3147+}
3148+
3149+bool
3150+Value::CZString::operator<( const CZString &other ) const
3151+{
3152+ if ( cstr_ )
3153+ return strcmp( cstr_, other.cstr_ ) < 0;
3154+ return index_ < other.index_;
3155+}
3156+
3157+bool
3158+Value::CZString::operator==( const CZString &other ) const
3159+{
3160+ if ( cstr_ )
3161+ return strcmp( cstr_, other.cstr_ ) == 0;
3162+ return index_ == other.index_;
3163+}
3164+
3165+
3166+int
3167+Value::CZString::index() const
3168+{
3169+ return index_;
3170+}
3171+
3172+
3173+const char *
3174+Value::CZString::c_str() const
3175+{
3176+ return cstr_;
3177+}
3178+
3179+bool
3180+Value::CZString::isStaticString() const
3181+{
3182+ return index_ == noDuplication;
3183+}
3184+
3185+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
3186+
3187+
3188+// //////////////////////////////////////////////////////////////////
3189+// //////////////////////////////////////////////////////////////////
3190+// //////////////////////////////////////////////////////////////////
3191+// class Value::Value
3192+// //////////////////////////////////////////////////////////////////
3193+// //////////////////////////////////////////////////////////////////
3194+// //////////////////////////////////////////////////////////////////
3195+
3196+/*! \internal Default constructor initialization must be equivalent to:
3197+ * memset( this, 0, sizeof(Value) )
3198+ * This optimization is used in ValueInternalMap fast allocator.
3199+ */
3200+Value::Value( ValueType type_arg )
3201+ : type_( type_arg )
3202+ , allocated_( 0 )
3203+ , comments_( 0 )
3204+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3205+ , itemIsUsed_( 0 )
3206+#endif
3207+{
3208+ switch ( type_arg )
3209+ {
3210+ case nullValue:
3211+ break;
3212+ case intValue:
3213+ case uintValue:
3214+ value_.int_ = 0;
3215+ break;
3216+ case realValue:
3217+ value_.real_ = 0.0;
3218+ break;
3219+ case stringValue:
3220+ value_.string_ = 0;
3221+ break;
3222+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3223+ case arrayValue:
3224+ case objectValue:
3225+ value_.map_ = new ObjectValues();
3226+ break;
3227+#else
3228+ case arrayValue:
3229+ value_.array_ = arrayAllocator()->newArray();
3230+ break;
3231+ case objectValue:
3232+ value_.map_ = mapAllocator()->newMap();
3233+ break;
3234+#endif
3235+ case booleanValue:
3236+ value_.bool_ = false;
3237+ break;
3238+ default:
3239+ JSON_ASSERT_UNREACHABLE;
3240+ }
3241+}
3242+
3243+
3244+Value::Value( Int value )
3245+ : type_( intValue )
3246+ , comments_( 0 )
3247+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3248+ , itemIsUsed_( 0 )
3249+#endif
3250+{
3251+ value_.int_ = value;
3252+}
3253+
3254+
3255+Value::Value( UInt value )
3256+ : type_( uintValue )
3257+ , comments_( 0 )
3258+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3259+ , itemIsUsed_( 0 )
3260+#endif
3261+{
3262+ value_.uint_ = value;
3263+}
3264+
3265+Value::Value( double value )
3266+ : type_( realValue )
3267+ , comments_( 0 )
3268+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3269+ , itemIsUsed_( 0 )
3270+#endif
3271+{
3272+ value_.real_ = value;
3273+}
3274+
3275+Value::Value( const char *value )
3276+ : type_( stringValue )
3277+ , allocated_( true )
3278+ , comments_( NULL )
3279+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3280+ , itemIsUsed_( 0 )
3281+#endif
3282+{
3283+ value_.string_ = valueAllocator()->duplicateStringValue( value );
3284+}
3285+
3286+
3287+Value::Value( const char *beginValue,
3288+ const char *endValue )
3289+ : type_( stringValue )
3290+ , allocated_( true )
3291+ , comments_( NULL )
3292+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3293+ , itemIsUsed_( 0 )
3294+#endif
3295+{
3296+ value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
3297+ UInt(endValue - beginValue) );
3298+}
3299+
3300+
3301+Value::Value( const std::string &value )
3302+ : type_( stringValue )
3303+ , allocated_( true )
3304+ , comments_( 0 )
3305+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3306+ , itemIsUsed_( 0 )
3307+#endif
3308+{
3309+ value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
3310+ (unsigned int)value.length() );
3311+
3312+}
3313+
3314+Value::Value( const StaticString &value )
3315+ : type_( stringValue )
3316+ , allocated_( false )
3317+ , comments_( 0 )
3318+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3319+ , itemIsUsed_( 0 )
3320+#endif
3321+{
3322+ value_.string_ = const_cast<char *>( value.c_str() );
3323+}
3324+
3325+
3326+# ifdef JSON_USE_CPPTL
3327+Value::Value( const CppTL::ConstString &value )
3328+ : type_( stringValue )
3329+ , allocated_( true )
3330+ , comments_( 0 )
3331+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3332+ , itemIsUsed_( 0 )
3333+#endif
3334+{
3335+ value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
3336+}
3337+# endif
3338+
3339+Value::Value( bool value )
3340+ : type_( booleanValue )
3341+ , comments_( 0 )
3342+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3343+ , itemIsUsed_( 0 )
3344+#endif
3345+{
3346+ value_.bool_ = value;
3347+}
3348+
3349+
3350+Value::Value( const Value &other )
3351+ : type_( other.type_ )
3352+ , comments_( 0 )
3353+# ifdef JSON_VALUE_USE_INTERNAL_MAP
3354+ , itemIsUsed_( 0 )
3355+#endif
3356+{
3357+ switch ( type_ )
3358+ {
3359+ case nullValue:
3360+ case intValue:
3361+ case uintValue:
3362+ case realValue:
3363+ case booleanValue:
3364+ value_ = other.value_;
3365+ break;
3366+ case stringValue:
3367+ if ( other.value_.string_ )
3368+ {
3369+ value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
3370+ allocated_ = true;
3371+ }
3372+ else
3373+ value_.string_ = 0;
3374+ break;
3375+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3376+ case arrayValue:
3377+ case objectValue:
3378+ value_.map_ = new ObjectValues( *other.value_.map_ );
3379+ break;
3380+#else
3381+ case arrayValue:
3382+ value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
3383+ break;
3384+ case objectValue:
3385+ value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
3386+ break;
3387+#endif
3388+ default:
3389+ JSON_ASSERT_UNREACHABLE;
3390+ }
3391+ if ( other.comments_ )
3392+ {
3393+ comments_ = new CommentInfo[numberOfCommentPlacement];
3394+ for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
3395+ {
3396+ const CommentInfo &otherComment = other.comments_[comment];
3397+ if ( otherComment.comment_ )
3398+ comments_[comment].setComment( otherComment.comment_ );
3399+ }
3400+ }
3401+}
3402+
3403+
3404+Value::~Value()
3405+{
3406+ switch ( type_ )
3407+ {
3408+ case nullValue:
3409+ case intValue:
3410+ case uintValue:
3411+ case realValue:
3412+ case booleanValue:
3413+ break;
3414+ case stringValue:
3415+ if ( allocated_ )
3416+ valueAllocator()->releaseStringValue( value_.string_ );
3417+ break;
3418+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3419+ case arrayValue:
3420+ case objectValue:
3421+ delete value_.map_;
3422+ break;
3423+#else
3424+ case arrayValue:
3425+ arrayAllocator()->destructArray( value_.array_ );
3426+ break;
3427+ case objectValue:
3428+ mapAllocator()->destructMap( value_.map_ );
3429+ break;
3430+#endif
3431+ default:
3432+ JSON_ASSERT_UNREACHABLE;
3433+ }
3434+
3435+ if ( comments_ )
3436+ delete[] comments_;
3437+}
3438+
3439+Value &
3440+Value::operator=( const Value &other )
3441+{
3442+ Value temp( other );
3443+ swap( temp );
3444+ return *this;
3445+}
3446+
3447+void
3448+Value::swap( Value &other )
3449+{
3450+ ValueType temp = type_;
3451+ type_ = other.type_;
3452+ other.type_ = temp;
3453+ std::swap( value_, other.value_ );
3454+ int temp2 = allocated_;
3455+ allocated_ = other.allocated_;
3456+ other.allocated_ = temp2;
3457+}
3458+
3459+ValueType
3460+Value::type() const
3461+{
3462+ return type_;
3463+}
3464+
3465+
3466+int
3467+Value::compare( const Value & )
3468+{
3469+ /*
3470+ int typeDelta = other.type_ - type_;
3471+ switch ( type_ )
3472+ {
3473+ case nullValue:
3474+
3475+ return other.type_ == type_;
3476+ case intValue:
3477+ if ( other.type_.isNumeric()
3478+ case uintValue:
3479+ case realValue:
3480+ case booleanValue:
3481+ break;
3482+ case stringValue,
3483+ break;
3484+ case arrayValue:
3485+ delete value_.array_;
3486+ break;
3487+ case objectValue:
3488+ delete value_.map_;
3489+ default:
3490+ JSON_ASSERT_UNREACHABLE;
3491+ }
3492+ */
3493+ return 0; // unreachable
3494+}
3495+
3496+bool
3497+Value::operator <( const Value &other ) const
3498+{
3499+ int typeDelta = type_ - other.type_;
3500+ if ( typeDelta )
3501+ return typeDelta < 0 ? true : false;
3502+ switch ( type_ )
3503+ {
3504+ case nullValue:
3505+ return false;
3506+ case intValue:
3507+ return value_.int_ < other.value_.int_;
3508+ case uintValue:
3509+ return value_.uint_ < other.value_.uint_;
3510+ case realValue:
3511+ return value_.real_ < other.value_.real_;
3512+ case booleanValue:
3513+ return value_.bool_ < other.value_.bool_;
3514+ case stringValue:
3515+ return ( value_.string_ == 0 && other.value_.string_ )
3516+ || ( other.value_.string_
3517+ && value_.string_
3518+ && strcmp( value_.string_, other.value_.string_ ) < 0 );
3519+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3520+ case arrayValue:
3521+ case objectValue:
3522+ {
3523+ int delta = int( value_.map_->size() - other.value_.map_->size() );
3524+ if ( delta )
3525+ return delta < 0;
3526+ return (*value_.map_) < (*other.value_.map_);
3527+ }
3528+#else
3529+ case arrayValue:
3530+ return value_.array_->compare( *(other.value_.array_) ) < 0;
3531+ case objectValue:
3532+ return value_.map_->compare( *(other.value_.map_) ) < 0;
3533+#endif
3534+ default:
3535+ JSON_ASSERT_UNREACHABLE;
3536+ }
3537+ return 0; // unreachable
3538+}
3539+
3540+bool
3541+Value::operator <=( const Value &other ) const
3542+{
3543+ return !(other > *this);
3544+}
3545+
3546+bool
3547+Value::operator >=( const Value &other ) const
3548+{
3549+ return !(*this < other);
3550+}
3551+
3552+bool
3553+Value::operator >( const Value &other ) const
3554+{
3555+ return other < *this;
3556+}
3557+
3558+bool
3559+Value::operator ==( const Value &other ) const
3560+{
3561+ //if ( type_ != other.type_ )
3562+ // GCC 2.95.3 says:
3563+ // attempt to take address of bit-field structure member `Json::Value::type_'
3564+ // Beats me, but a temp solves the problem.
3565+ int temp = other.type_;
3566+ if ( type_ != temp )
3567+ return false;
3568+ switch ( type_ )
3569+ {
3570+ case nullValue:
3571+ return true;
3572+ case intValue:
3573+ return value_.int_ == other.value_.int_;
3574+ case uintValue:
3575+ return value_.uint_ == other.value_.uint_;
3576+ case realValue:
3577+ return value_.real_ == other.value_.real_;
3578+ case booleanValue:
3579+ return value_.bool_ == other.value_.bool_;
3580+ case stringValue:
3581+ return ( value_.string_ == other.value_.string_ )
3582+ || ( other.value_.string_
3583+ && value_.string_
3584+ && strcmp( value_.string_, other.value_.string_ ) == 0 );
3585+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3586+ case arrayValue:
3587+ case objectValue:
3588+ return value_.map_->size() == other.value_.map_->size()
3589+ && (*value_.map_) == (*other.value_.map_);
3590+#else
3591+ case arrayValue:
3592+ return value_.array_->compare( *(other.value_.array_) ) == 0;
3593+ case objectValue:
3594+ return value_.map_->compare( *(other.value_.map_) ) == 0;
3595+#endif
3596+ default:
3597+ JSON_ASSERT_UNREACHABLE;
3598+ }
3599+ return 0; // unreachable
3600+}
3601+
3602+bool
3603+Value::operator !=( const Value &other ) const
3604+{
3605+ return !( *this == other );
3606+}
3607+
3608+const char *
3609+Value::asCString() const
3610+{
3611+ JSON_ASSERT( type_ == stringValue );
3612+ return value_.string_;
3613+}
3614+
3615+
3616+std::string
3617+Value::asString() const
3618+{
3619+ switch ( type_ )
3620+ {
3621+ case nullValue:
3622+ return "";
3623+ case stringValue:
3624+ return value_.string_ ? value_.string_ : "";
3625+ case booleanValue:
3626+ return value_.bool_ ? "true" : "false";
3627+ case intValue:
3628+ case uintValue:
3629+ case realValue:
3630+ case arrayValue:
3631+ case objectValue:
3632+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
3633+ default:
3634+ JSON_ASSERT_UNREACHABLE;
3635+ }
3636+ return ""; // unreachable
3637+}
3638+
3639+# ifdef JSON_USE_CPPTL
3640+CppTL::ConstString
3641+Value::asConstString() const
3642+{
3643+ return CppTL::ConstString( asString().c_str() );
3644+}
3645+# endif
3646+
3647+Value::Int
3648+Value::asInt() const
3649+{
3650+ switch ( type_ )
3651+ {
3652+ case nullValue:
3653+ return 0;
3654+ case intValue:
3655+ return value_.int_;
3656+ case uintValue:
3657+ JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
3658+ return value_.uint_;
3659+ case realValue:
3660+ JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
3661+ return Int( value_.real_ );
3662+ case booleanValue:
3663+ return value_.bool_ ? 1 : 0;
3664+ case stringValue:
3665+ case arrayValue:
3666+ case objectValue:
3667+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
3668+ default:
3669+ JSON_ASSERT_UNREACHABLE;
3670+ }
3671+ return 0; // unreachable;
3672+}
3673+
3674+Value::UInt
3675+Value::asUInt() const
3676+{
3677+ switch ( type_ )
3678+ {
3679+ case nullValue:
3680+ return 0;
3681+ case intValue:
3682+ JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
3683+ return value_.int_;
3684+ case uintValue:
3685+ return value_.uint_;
3686+ case realValue:
3687+ JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
3688+ return UInt( value_.real_ );
3689+ case booleanValue:
3690+ return value_.bool_ ? 1 : 0;
3691+ case stringValue:
3692+ case arrayValue:
3693+ case objectValue:
3694+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
3695+ default:
3696+ JSON_ASSERT_UNREACHABLE;
3697+ }
3698+ return 0; // unreachable;
3699+}
3700+
3701+double
3702+Value::asDouble() const
3703+{
3704+ switch ( type_ )
3705+ {
3706+ case nullValue:
3707+ return 0.0;
3708+ case intValue:
3709+ return value_.int_;
3710+ case uintValue:
3711+ return value_.uint_;
3712+ case realValue:
3713+ return value_.real_;
3714+ case booleanValue:
3715+ return value_.bool_ ? 1.0 : 0.0;
3716+ case stringValue:
3717+ case arrayValue:
3718+ case objectValue:
3719+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
3720+ default:
3721+ JSON_ASSERT_UNREACHABLE;
3722+ }
3723+ return 0; // unreachable;
3724+}
3725+
3726+bool
3727+Value::asBool() const
3728+{
3729+ switch ( type_ )
3730+ {
3731+ case nullValue:
3732+ return false;
3733+ case intValue:
3734+ case uintValue:
3735+ return value_.int_ != 0;
3736+ case realValue:
3737+ return value_.real_ != 0.0;
3738+ case booleanValue:
3739+ return value_.bool_;
3740+ case stringValue:
3741+ return value_.string_ && value_.string_[0] != 0;
3742+ case arrayValue:
3743+ case objectValue:
3744+ return value_.map_->size() != 0;
3745+ default:
3746+ JSON_ASSERT_UNREACHABLE;
3747+ }
3748+ return false; // unreachable;
3749+}
3750+
3751+
3752+bool
3753+Value::isConvertibleTo( ValueType other ) const
3754+{
3755+ switch ( type_ )
3756+ {
3757+ case nullValue:
3758+ return true;
3759+ case intValue:
3760+ return ( other == nullValue && value_.int_ == 0 )
3761+ || other == intValue
3762+ || ( other == uintValue && value_.int_ >= 0 )
3763+ || other == realValue
3764+ || other == stringValue
3765+ || other == booleanValue;
3766+ case uintValue:
3767+ return ( other == nullValue && value_.uint_ == 0 )
3768+ || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
3769+ || other == uintValue
3770+ || other == realValue
3771+ || other == stringValue
3772+ || other == booleanValue;
3773+ case realValue:
3774+ return ( other == nullValue && value_.real_ == 0.0 )
3775+ || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
3776+ || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
3777+ || other == realValue
3778+ || other == stringValue
3779+ || other == booleanValue;
3780+ case booleanValue:
3781+ return ( other == nullValue && value_.bool_ == false )
3782+ || other == intValue
3783+ || other == uintValue
3784+ || other == realValue
3785+ || other == stringValue
3786+ || other == booleanValue;
3787+ case stringValue:
3788+ return other == stringValue
3789+ || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
3790+ case arrayValue:
3791+ return other == arrayValue
3792+ || ( other == nullValue && value_.map_->size() == 0 );
3793+ case objectValue:
3794+ return other == objectValue
3795+ || ( other == nullValue && value_.map_->size() == 0 );
3796+ default:
3797+ JSON_ASSERT_UNREACHABLE;
3798+ }
3799+ return false; // unreachable;
3800+}
3801+
3802+
3803+/// Number of values in array or object
3804+Value::UInt
3805+Value::size() const
3806+{
3807+ switch ( type_ )
3808+ {
3809+ case nullValue:
3810+ case intValue:
3811+ case uintValue:
3812+ case realValue:
3813+ case booleanValue:
3814+ case stringValue:
3815+ return 0;
3816+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3817+ case arrayValue: // size of the array is highest index + 1
3818+ if ( !value_.map_->empty() )
3819+ {
3820+ ObjectValues::const_iterator itLast = value_.map_->end();
3821+ --itLast;
3822+ return (*itLast).first.index()+1;
3823+ }
3824+ return 0;
3825+ case objectValue:
3826+ return Int( value_.map_->size() );
3827+#else
3828+ case arrayValue:
3829+ return Int( value_.array_->size() );
3830+ case objectValue:
3831+ return Int( value_.map_->size() );
3832+#endif
3833+ default:
3834+ JSON_ASSERT_UNREACHABLE;
3835+ }
3836+ return 0; // unreachable;
3837+}
3838+
3839+
3840+bool
3841+Value::empty() const
3842+{
3843+ if ( isNull() || isArray() || isObject() )
3844+ return size() == 0u;
3845+ else
3846+ return false;
3847+}
3848+
3849+
3850+bool
3851+Value::operator!() const
3852+{
3853+ return isNull();
3854+}
3855+
3856+
3857+void
3858+Value::clear()
3859+{
3860+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
3861+
3862+ switch ( type_ )
3863+ {
3864+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3865+ case arrayValue:
3866+ case objectValue:
3867+ value_.map_->clear();
3868+ break;
3869+#else
3870+ case arrayValue:
3871+ value_.array_->clear();
3872+ break;
3873+ case objectValue:
3874+ value_.map_->clear();
3875+ break;
3876+#endif
3877+ default:
3878+ break;
3879+ }
3880+}
3881+
3882+void
3883+Value::resize( UInt newSize )
3884+{
3885+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
3886+ if ( type_ == nullValue )
3887+ *this = Value( arrayValue );
3888+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3889+ UInt oldSize = size();
3890+ if ( newSize == 0 )
3891+ clear();
3892+ else if ( newSize > oldSize )
3893+ (*this)[ newSize - 1 ];
3894+ else
3895+ {
3896+ for ( UInt index = newSize; index < oldSize; ++index )
3897+ value_.map_->erase( index );
3898+ assert( size() == newSize );
3899+ }
3900+#else
3901+ value_.array_->resize( newSize );
3902+#endif
3903+}
3904+
3905+
3906+Value &
3907+Value::operator[]( UInt index )
3908+{
3909+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
3910+ if ( type_ == nullValue )
3911+ *this = Value( arrayValue );
3912+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3913+ CZString key( index );
3914+ ObjectValues::iterator it = value_.map_->lower_bound( key );
3915+ if ( it != value_.map_->end() && (*it).first == key )
3916+ return (*it).second;
3917+
3918+ ObjectValues::value_type defaultValue( key, null );
3919+ it = value_.map_->insert( it, defaultValue );
3920+ return (*it).second;
3921+#else
3922+ return value_.array_->resolveReference( index );
3923+#endif
3924+}
3925+
3926+
3927+const Value &
3928+Value::operator[]( UInt index ) const
3929+{
3930+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
3931+ if ( type_ == nullValue )
3932+ return null;
3933+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3934+ CZString key( index );
3935+ ObjectValues::const_iterator it = value_.map_->find( key );
3936+ if ( it == value_.map_->end() )
3937+ return null;
3938+ return (*it).second;
3939+#else
3940+ Value *value = value_.array_->find( index );
3941+ return value ? *value : null;
3942+#endif
3943+}
3944+
3945+
3946+Value &
3947+Value::operator[]( const char *key )
3948+{
3949+ return resolveReference( key, false );
3950+}
3951+
3952+
3953+Value &
3954+Value::resolveReference( const char *key,
3955+ bool isStatic )
3956+{
3957+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
3958+ if ( type_ == nullValue )
3959+ *this = Value( objectValue );
3960+#ifndef JSON_VALUE_USE_INTERNAL_MAP
3961+ CZString actualKey( key, isStatic ? CZString::noDuplication
3962+ : CZString::duplicateOnCopy );
3963+ ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
3964+ if ( it != value_.map_->end() && (*it).first == actualKey )
3965+ return (*it).second;
3966+
3967+ ObjectValues::value_type defaultValue( actualKey, null );
3968+ it = value_.map_->insert( it, defaultValue );
3969+ Value &value = (*it).second;
3970+ return value;
3971+#else
3972+ return value_.map_->resolveReference( key, isStatic );
3973+#endif
3974+}
3975+
3976+
3977+Value
3978+Value::get( UInt index,
3979+ const Value &defaultValue ) const
3980+{
3981+ const Value *value = &((*this)[index]);
3982+ return value == &null ? defaultValue : *value;
3983+}
3984+
3985+
3986+bool
3987+Value::isValidIndex( UInt index ) const
3988+{
3989+ return index < size();
3990+}
3991+
3992+
3993+
3994+const Value &
3995+Value::operator[]( const char *key ) const
3996+{
3997+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
3998+ if ( type_ == nullValue )
3999+ return null;
4000+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4001+ CZString actualKey( key, CZString::noDuplication );
4002+ ObjectValues::const_iterator it = value_.map_->find( actualKey );
4003+ if ( it == value_.map_->end() )
4004+ return null;
4005+ return (*it).second;
4006+#else
4007+ const Value *value = value_.map_->find( key );
4008+ return value ? *value : null;
4009+#endif
4010+}
4011+
4012+
4013+Value &
4014+Value::operator[]( const std::string &key )
4015+{
4016+ return (*this)[ key.c_str() ];
4017+}
4018+
4019+
4020+const Value &
4021+Value::operator[]( const std::string &key ) const
4022+{
4023+ return (*this)[ key.c_str() ];
4024+}
4025+
4026+Value &
4027+Value::operator[]( const StaticString &key )
4028+{
4029+ return resolveReference( key, true );
4030+}
4031+
4032+
4033+# ifdef JSON_USE_CPPTL
4034+Value &
4035+Value::operator[]( const CppTL::ConstString &key )
4036+{
4037+ return (*this)[ key.c_str() ];
4038+}
4039+
4040+
4041+const Value &
4042+Value::operator[]( const CppTL::ConstString &key ) const
4043+{
4044+ return (*this)[ key.c_str() ];
4045+}
4046+# endif
4047+
4048+
4049+Value &
4050+Value::append( const Value &value )
4051+{
4052+ return (*this)[size()] = value;
4053+}
4054+
4055+
4056+Value
4057+Value::get( const char *key,
4058+ const Value &defaultValue ) const
4059+{
4060+ const Value *value = &((*this)[key]);
4061+ return value == &null ? defaultValue : *value;
4062+}
4063+
4064+
4065+Value
4066+Value::get( const std::string &key,
4067+ const Value &defaultValue ) const
4068+{
4069+ return get( key.c_str(), defaultValue );
4070+}
4071+
4072+Value
4073+Value::removeMember( const char* key )
4074+{
4075+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
4076+ if ( type_ == nullValue )
4077+ return null;
4078+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4079+ CZString actualKey( key, CZString::noDuplication );
4080+ ObjectValues::iterator it = value_.map_->find( actualKey );
4081+ if ( it == value_.map_->end() )
4082+ return null;
4083+ Value old(it->second);
4084+ value_.map_->erase(it);
4085+ return old;
4086+#else
4087+ Value *value = value_.map_->find( key );
4088+ if (value){
4089+ Value old(*value);
4090+ value_.map_.remove( key );
4091+ return old;
4092+ } else {
4093+ return null;
4094+ }
4095+#endif
4096+}
4097+
4098+Value
4099+Value::removeMember( const std::string &key )
4100+{
4101+ return removeMember( key.c_str() );
4102+}
4103+
4104+# ifdef JSON_USE_CPPTL
4105+Value
4106+Value::get( const CppTL::ConstString &key,
4107+ const Value &defaultValue ) const
4108+{
4109+ return get( key.c_str(), defaultValue );
4110+}
4111+# endif
4112+
4113+bool
4114+Value::isMember( const char *key ) const
4115+{
4116+ const Value *value = &((*this)[key]);
4117+ return value != &null;
4118+}
4119+
4120+
4121+bool
4122+Value::isMember( const std::string &key ) const
4123+{
4124+ return isMember( key.c_str() );
4125+}
4126+
4127+
4128+# ifdef JSON_USE_CPPTL
4129+bool
4130+Value::isMember( const CppTL::ConstString &key ) const
4131+{
4132+ return isMember( key.c_str() );
4133+}
4134+#endif
4135+
4136+Value::Members
4137+Value::getMemberNames() const
4138+{
4139+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
4140+ if ( type_ == nullValue )
4141+ return Value::Members();
4142+ Members members;
4143+ members.reserve( value_.map_->size() );
4144+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4145+ ObjectValues::const_iterator it = value_.map_->begin();
4146+ ObjectValues::const_iterator itEnd = value_.map_->end();
4147+ for ( ; it != itEnd; ++it )
4148+ members.push_back( std::string( (*it).first.c_str() ) );
4149+#else
4150+ ValueInternalMap::IteratorState it;
4151+ ValueInternalMap::IteratorState itEnd;
4152+ value_.map_->makeBeginIterator( it );
4153+ value_.map_->makeEndIterator( itEnd );
4154+ for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
4155+ members.push_back( std::string( ValueInternalMap::key( it ) ) );
4156+#endif
4157+ return members;
4158+}
4159+//
4160+//# ifdef JSON_USE_CPPTL
4161+//EnumMemberNames
4162+//Value::enumMemberNames() const
4163+//{
4164+// if ( type_ == objectValue )
4165+// {
4166+// return CppTL::Enum::any( CppTL::Enum::transform(
4167+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
4168+// MemberNamesTransform() ) );
4169+// }
4170+// return EnumMemberNames();
4171+//}
4172+//
4173+//
4174+//EnumValues
4175+//Value::enumValues() const
4176+//{
4177+// if ( type_ == objectValue || type_ == arrayValue )
4178+// return CppTL::Enum::anyValues( *(value_.map_),
4179+// CppTL::Type<const Value &>() );
4180+// return EnumValues();
4181+//}
4182+//
4183+//# endif
4184+
4185+
4186+bool
4187+Value::isNull() const
4188+{
4189+ return type_ == nullValue;
4190+}
4191+
4192+
4193+bool
4194+Value::isBool() const
4195+{
4196+ return type_ == booleanValue;
4197+}
4198+
4199+
4200+bool
4201+Value::isInt() const
4202+{
4203+ return type_ == intValue;
4204+}
4205+
4206+
4207+bool
4208+Value::isUInt() const
4209+{
4210+ return type_ == uintValue;
4211+}
4212+
4213+
4214+bool
4215+Value::isIntegral() const
4216+{
4217+ return type_ == intValue
4218+ || type_ == uintValue
4219+ || type_ == booleanValue;
4220+}
4221+
4222+
4223+bool
4224+Value::isDouble() const
4225+{
4226+ return type_ == realValue;
4227+}
4228+
4229+
4230+bool
4231+Value::isNumeric() const
4232+{
4233+ return isIntegral() || isDouble();
4234+}
4235+
4236+
4237+bool
4238+Value::isString() const
4239+{
4240+ return type_ == stringValue;
4241+}
4242+
4243+
4244+bool
4245+Value::isArray() const
4246+{
4247+ return type_ == nullValue || type_ == arrayValue;
4248+}
4249+
4250+
4251+bool
4252+Value::isObject() const
4253+{
4254+ return type_ == nullValue || type_ == objectValue;
4255+}
4256+
4257+
4258+void
4259+Value::setComment( const char *comment,
4260+ CommentPlacement placement )
4261+{
4262+ if ( !comments_ )
4263+ comments_ = new CommentInfo[numberOfCommentPlacement];
4264+ comments_[placement].setComment( comment );
4265+}
4266+
4267+
4268+void
4269+Value::setComment( const std::string &comment,
4270+ CommentPlacement placement )
4271+{
4272+ setComment( comment.c_str(), placement );
4273+}
4274+
4275+
4276+bool
4277+Value::hasComment( CommentPlacement placement ) const
4278+{
4279+ return comments_ != 0 && comments_[placement].comment_ != 0;
4280+}
4281+
4282+std::string
4283+Value::getComment( CommentPlacement placement ) const
4284+{
4285+ if ( hasComment(placement) )
4286+ return comments_[placement].comment_;
4287+ return "";
4288+}
4289+
4290+
4291+std::string
4292+Value::toStyledString() const
4293+{
4294+ StyledWriter writer;
4295+ return writer.write( *this );
4296+}
4297+
4298+
4299+Value::const_iterator
4300+Value::begin() const
4301+{
4302+ switch ( type_ )
4303+ {
4304+#ifdef JSON_VALUE_USE_INTERNAL_MAP
4305+ case arrayValue:
4306+ if ( value_.array_ )
4307+ {
4308+ ValueInternalArray::IteratorState it;
4309+ value_.array_->makeBeginIterator( it );
4310+ return const_iterator( it );
4311+ }
4312+ break;
4313+ case objectValue:
4314+ if ( value_.map_ )
4315+ {
4316+ ValueInternalMap::IteratorState it;
4317+ value_.map_->makeBeginIterator( it );
4318+ return const_iterator( it );
4319+ }
4320+ break;
4321+#else
4322+ case arrayValue:
4323+ case objectValue:
4324+ if ( value_.map_ )
4325+ return const_iterator( value_.map_->begin() );
4326+ break;
4327+#endif
4328+ default:
4329+ break;
4330+ }
4331+ return const_iterator();
4332+}
4333+
4334+Value::const_iterator
4335+Value::end() const
4336+{
4337+ switch ( type_ )
4338+ {
4339+#ifdef JSON_VALUE_USE_INTERNAL_MAP
4340+ case arrayValue:
4341+ if ( value_.array_ )
4342+ {
4343+ ValueInternalArray::IteratorState it;
4344+ value_.array_->makeEndIterator( it );
4345+ return const_iterator( it );
4346+ }
4347+ break;
4348+ case objectValue:
4349+ if ( value_.map_ )
4350+ {
4351+ ValueInternalMap::IteratorState it;
4352+ value_.map_->makeEndIterator( it );
4353+ return const_iterator( it );
4354+ }
4355+ break;
4356+#else
4357+ case arrayValue:
4358+ case objectValue:
4359+ if ( value_.map_ )
4360+ return const_iterator( value_.map_->end() );
4361+ break;
4362+#endif
4363+ default:
4364+ break;
4365+ }
4366+ return const_iterator();
4367+}
4368+
4369+
4370+Value::iterator
4371+Value::begin()
4372+{
4373+ switch ( type_ )
4374+ {
4375+#ifdef JSON_VALUE_USE_INTERNAL_MAP
4376+ case arrayValue:
4377+ if ( value_.array_ )
4378+ {
4379+ ValueInternalArray::IteratorState it;
4380+ value_.array_->makeBeginIterator( it );
4381+ return iterator( it );
4382+ }
4383+ break;
4384+ case objectValue:
4385+ if ( value_.map_ )
4386+ {
4387+ ValueInternalMap::IteratorState it;
4388+ value_.map_->makeBeginIterator( it );
4389+ return iterator( it );
4390+ }
4391+ break;
4392+#else
4393+ case arrayValue:
4394+ case objectValue:
4395+ if ( value_.map_ )
4396+ return iterator( value_.map_->begin() );
4397+ break;
4398+#endif
4399+ default:
4400+ break;
4401+ }
4402+ return iterator();
4403+}
4404+
4405+Value::iterator
4406+Value::end()
4407+{
4408+ switch ( type_ )
4409+ {
4410+#ifdef JSON_VALUE_USE_INTERNAL_MAP
4411+ case arrayValue:
4412+ if ( value_.array_ )
4413+ {
4414+ ValueInternalArray::IteratorState it;
4415+ value_.array_->makeEndIterator( it );
4416+ return iterator( it );
4417+ }
4418+ break;
4419+ case objectValue:
4420+ if ( value_.map_ )
4421+ {
4422+ ValueInternalMap::IteratorState it;
4423+ value_.map_->makeEndIterator( it );
4424+ return iterator( it );
4425+ }
4426+ break;
4427+#else
4428+ case arrayValue:
4429+ case objectValue:
4430+ if ( value_.map_ )
4431+ return iterator( value_.map_->end() );
4432+ break;
4433+#endif
4434+ default:
4435+ break;
4436+ }
4437+ return iterator();
4438+}
4439+
4440+
4441+// class PathArgument
4442+// //////////////////////////////////////////////////////////////////
4443+
4444+PathArgument::PathArgument()
4445+ : kind_( kindNone )
4446+{
4447+}
4448+
4449+
4450+PathArgument::PathArgument( Value::UInt index )
4451+ : index_( index )
4452+ , kind_( kindIndex )
4453+{
4454+}
4455+
4456+
4457+PathArgument::PathArgument( const char *key )
4458+ : key_( key )
4459+ , kind_( kindKey )
4460+{
4461+}
4462+
4463+
4464+PathArgument::PathArgument( const std::string &key )
4465+ : key_( key.c_str() )
4466+ , kind_( kindKey )
4467+{
4468+}
4469+
4470+// class Path
4471+// //////////////////////////////////////////////////////////////////
4472+
4473+Path::Path( const std::string &path,
4474+ const PathArgument &a1,
4475+ const PathArgument &a2,
4476+ const PathArgument &a3,
4477+ const PathArgument &a4,
4478+ const PathArgument &a5 )
4479+{
4480+ InArgs in;
4481+ in.push_back( &a1 );
4482+ in.push_back( &a2 );
4483+ in.push_back( &a3 );
4484+ in.push_back( &a4 );
4485+ in.push_back( &a5 );
4486+ makePath( path, in );
4487+}
4488+
4489+
4490+void
4491+Path::makePath( const std::string &path,
4492+ const InArgs &in )
4493+{
4494+ const char *current = path.c_str();
4495+ const char *end = current + path.length();
4496+ InArgs::const_iterator itInArg = in.begin();
4497+ while ( current != end )
4498+ {
4499+ if ( *current == '[' )
4500+ {
4501+ ++current;
4502+ if ( *current == '%' )
4503+ addPathInArg( path, in, itInArg, PathArgument::kindIndex );
4504+ else
4505+ {
4506+ Value::UInt index = 0;
4507+ for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
4508+ index = index * 10 + Value::UInt(*current - '0');
4509+ args_.push_back( index );
4510+ }
4511+ if ( current == end || *current++ != ']' )
4512+ invalidPath( path, int(current - path.c_str()) );
4513+ }
4514+ else if ( *current == '%' )
4515+ {
4516+ addPathInArg( path, in, itInArg, PathArgument::kindKey );
4517+ ++current;
4518+ }
4519+ else if ( *current == '.' )
4520+ {
4521+ ++current;
4522+ }
4523+ else
4524+ {
4525+ const char *beginName = current;
4526+ while ( current != end && !strchr( "[.", *current ) )
4527+ ++current;
4528+ args_.push_back( std::string( beginName, current ) );
4529+ }
4530+ }
4531+}
4532+
4533+
4534+void
4535+Path::addPathInArg( const std::string &,
4536+ const InArgs &in,
4537+ InArgs::const_iterator &itInArg,
4538+ PathArgument::Kind kind )
4539+{
4540+ if ( itInArg == in.end() )
4541+ {
4542+ // Error: missing argument %d
4543+ }
4544+ else if ( (*itInArg)->kind_ != kind )
4545+ {
4546+ // Error: bad argument type
4547+ }
4548+ else
4549+ {
4550+ args_.push_back( **itInArg );
4551+ }
4552+}
4553+
4554+
4555+void
4556+Path::invalidPath( const std::string &,
4557+ int )
4558+{
4559+ // Error: invalid path.
4560+}
4561+
4562+
4563+const Value &
4564+Path::resolve( const Value &root ) const
4565+{
4566+ const Value *node = &root;
4567+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
4568+ {
4569+ const PathArgument &arg = *it;
4570+ if ( arg.kind_ == PathArgument::kindIndex )
4571+ {
4572+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
4573+ {
4574+ // Error: unable to resolve path (array value expected at position...
4575+ }
4576+ node = &((*node)[arg.index_]);
4577+ }
4578+ else if ( arg.kind_ == PathArgument::kindKey )
4579+ {
4580+ if ( !node->isObject() )
4581+ {
4582+ // Error: unable to resolve path (object value expected at position...)
4583+ }
4584+ node = &((*node)[arg.key_]);
4585+ if ( node == &Value::null )
4586+ {
4587+ // Error: unable to resolve path (object has no member named '' at position...)
4588+ }
4589+ }
4590+ }
4591+ return *node;
4592+}
4593+
4594+
4595+Value
4596+Path::resolve( const Value &root,
4597+ const Value &defaultValue ) const
4598+{
4599+ const Value *node = &root;
4600+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
4601+ {
4602+ const PathArgument &arg = *it;
4603+ if ( arg.kind_ == PathArgument::kindIndex )
4604+ {
4605+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
4606+ return defaultValue;
4607+ node = &((*node)[arg.index_]);
4608+ }
4609+ else if ( arg.kind_ == PathArgument::kindKey )
4610+ {
4611+ if ( !node->isObject() )
4612+ return defaultValue;
4613+ node = &((*node)[arg.key_]);
4614+ if ( node == &Value::null )
4615+ return defaultValue;
4616+ }
4617+ }
4618+ return *node;
4619+}
4620+
4621+
4622+Value &
4623+Path::make( Value &root ) const
4624+{
4625+ Value *node = &root;
4626+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
4627+ {
4628+ const PathArgument &arg = *it;
4629+ if ( arg.kind_ == PathArgument::kindIndex )
4630+ {
4631+ if ( !node->isArray() )
4632+ {
4633+ // Error: node is not an array at position ...
4634+ }
4635+ node = &((*node)[arg.index_]);
4636+ }
4637+ else if ( arg.kind_ == PathArgument::kindKey )
4638+ {
4639+ if ( !node->isObject() )
4640+ {
4641+ // Error: node is not an object at position...
4642+ }
4643+ node = &((*node)[arg.key_]);
4644+ }
4645+ }
4646+ return *node;
4647+}
4648+
4649+
4650+} // namespace Json
4651
4652=== added file 'plugin/json_server/json/json_valueiterator.inl'
4653--- plugin/json_server/json/json_valueiterator.inl 1970-01-01 00:00:00 +0000
4654+++ plugin/json_server/json/json_valueiterator.inl 2011-05-04 01:52:37 +0000
4655@@ -0,0 +1,330 @@
4656+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4657+ *
4658+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
4659+ *
4660+ * Copyright (C) 2011 Stewart Smith
4661+ * All rights reserved.
4662+ *
4663+ * Redistribution and use in source and binary forms, with or without
4664+ * modification, are permitted provided that the following conditions are
4665+ * met:
4666+ *
4667+ * * Redistributions of source code must retain the above copyright
4668+ * notice, this list of conditions and the following disclaimer.
4669+ *
4670+ * * Redistributions in binary form must reproduce the above
4671+ * copyright notice, this list of conditions and the following disclaimer
4672+ * in the documentation and/or other materials provided with the
4673+ * distribution.
4674+ *
4675+ * * The names of its contributors may not be used to endorse or
4676+ * promote products derived from this software without specific prior
4677+ * written permission.
4678+ *
4679+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4680+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4681+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4682+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4683+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4684+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4685+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4686+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4687+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4688+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4689+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4690+ *
4691+ */
4692+
4693+#pragma once
4694+// included by json_value.cpp
4695+// everything is within Json namespace
4696+
4697+
4698+// //////////////////////////////////////////////////////////////////
4699+// //////////////////////////////////////////////////////////////////
4700+// //////////////////////////////////////////////////////////////////
4701+// class ValueIteratorBase
4702+// //////////////////////////////////////////////////////////////////
4703+// //////////////////////////////////////////////////////////////////
4704+// //////////////////////////////////////////////////////////////////
4705+
4706+ValueIteratorBase::ValueIteratorBase()
4707+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4708+ : current_()
4709+ , isNull_( true )
4710+{
4711+}
4712+#else
4713+ : isArray_( true )
4714+ , isNull_( true )
4715+{
4716+ iterator_.array_ = ValueInternalArray::IteratorState();
4717+}
4718+#endif
4719+
4720+
4721+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4722+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
4723+ : current_( current )
4724+ , isNull_( false )
4725+{
4726+}
4727+#else
4728+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
4729+ : isArray_( true )
4730+{
4731+ iterator_.array_ = state;
4732+}
4733+
4734+
4735+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
4736+ : isArray_( false )
4737+{
4738+ iterator_.map_ = state;
4739+}
4740+#endif
4741+
4742+Value &
4743+ValueIteratorBase::deref() const
4744+{
4745+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4746+ return current_->second;
4747+#else
4748+ if ( isArray_ )
4749+ return ValueInternalArray::dereference( iterator_.array_ );
4750+ return ValueInternalMap::value( iterator_.map_ );
4751+#endif
4752+}
4753+
4754+
4755+void
4756+ValueIteratorBase::increment()
4757+{
4758+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4759+ ++current_;
4760+#else
4761+ if ( isArray_ )
4762+ ValueInternalArray::increment( iterator_.array_ );
4763+ ValueInternalMap::increment( iterator_.map_ );
4764+#endif
4765+}
4766+
4767+
4768+void
4769+ValueIteratorBase::decrement()
4770+{
4771+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4772+ --current_;
4773+#else
4774+ if ( isArray_ )
4775+ ValueInternalArray::decrement( iterator_.array_ );
4776+ ValueInternalMap::decrement( iterator_.map_ );
4777+#endif
4778+}
4779+
4780+
4781+ValueIteratorBase::difference_type
4782+ValueIteratorBase::computeDistance( const SelfType &other ) const
4783+{
4784+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4785+# ifdef JSON_USE_CPPTL_SMALLMAP
4786+ return current_ - other.current_;
4787+# else
4788+ // Iterator for null value are initialized using the default
4789+ // constructor, which initialize current_ to the default
4790+ // std::map::iterator. As begin() and end() are two instance
4791+ // of the default std::map::iterator, they can not be compared.
4792+ // To allow this, we handle this comparison specifically.
4793+ if ( isNull_ && other.isNull_ )
4794+ {
4795+ return 0;
4796+ }
4797+
4798+
4799+ // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
4800+ // which is the one used by default).
4801+ // Using a portable hand-made version for non random iterator instead:
4802+ // return difference_type( std::distance( current_, other.current_ ) );
4803+ difference_type myDistance = 0;
4804+ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
4805+ {
4806+ ++myDistance;
4807+ }
4808+ return myDistance;
4809+# endif
4810+#else
4811+ if ( isArray_ )
4812+ return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
4813+ return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
4814+#endif
4815+}
4816+
4817+
4818+bool
4819+ValueIteratorBase::isEqual( const SelfType &other ) const
4820+{
4821+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4822+ if ( isNull_ )
4823+ {
4824+ return other.isNull_;
4825+ }
4826+ return current_ == other.current_;
4827+#else
4828+ if ( isArray_ )
4829+ return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
4830+ return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
4831+#endif
4832+}
4833+
4834+
4835+void
4836+ValueIteratorBase::copy( const SelfType &other )
4837+{
4838+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4839+ current_ = other.current_;
4840+#else
4841+ if ( isArray_ )
4842+ iterator_.array_ = other.iterator_.array_;
4843+ iterator_.map_ = other.iterator_.map_;
4844+#endif
4845+}
4846+
4847+
4848+Value
4849+ValueIteratorBase::key() const
4850+{
4851+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4852+ const Value::CZString czstring = (*current_).first;
4853+ if ( czstring.c_str() )
4854+ {
4855+ if ( czstring.isStaticString() )
4856+ return Value( StaticString( czstring.c_str() ) );
4857+ return Value( czstring.c_str() );
4858+ }
4859+ return Value( czstring.index() );
4860+#else
4861+ if ( isArray_ )
4862+ return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
4863+ bool isStatic;
4864+ const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
4865+ if ( isStatic )
4866+ return Value( StaticString( memberName ) );
4867+ return Value( memberName );
4868+#endif
4869+}
4870+
4871+
4872+UInt
4873+ValueIteratorBase::index() const
4874+{
4875+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4876+ const Value::CZString czstring = (*current_).first;
4877+ if ( !czstring.c_str() )
4878+ return czstring.index();
4879+ return Value::UInt( -1 );
4880+#else
4881+ if ( isArray_ )
4882+ return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
4883+ return Value::UInt( -1 );
4884+#endif
4885+}
4886+
4887+
4888+const char *
4889+ValueIteratorBase::memberName() const
4890+{
4891+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4892+ const char *name = (*current_).first.c_str();
4893+ return name ? name : "";
4894+#else
4895+ if ( !isArray_ )
4896+ return ValueInternalMap::key( iterator_.map_ );
4897+ return "";
4898+#endif
4899+}
4900+
4901+
4902+// //////////////////////////////////////////////////////////////////
4903+// //////////////////////////////////////////////////////////////////
4904+// //////////////////////////////////////////////////////////////////
4905+// class ValueConstIterator
4906+// //////////////////////////////////////////////////////////////////
4907+// //////////////////////////////////////////////////////////////////
4908+// //////////////////////////////////////////////////////////////////
4909+
4910+ValueConstIterator::ValueConstIterator()
4911+{
4912+}
4913+
4914+
4915+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4916+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
4917+ : ValueIteratorBase( current )
4918+{
4919+}
4920+#else
4921+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
4922+ : ValueIteratorBase( state )
4923+{
4924+}
4925+
4926+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
4927+ : ValueIteratorBase( state )
4928+{
4929+}
4930+#endif
4931+
4932+ValueConstIterator &
4933+ValueConstIterator::operator =( const ValueIteratorBase &other )
4934+{
4935+ copy( other );
4936+ return *this;
4937+}
4938+
4939+
4940+// //////////////////////////////////////////////////////////////////
4941+// //////////////////////////////////////////////////////////////////
4942+// //////////////////////////////////////////////////////////////////
4943+// class ValueIterator
4944+// //////////////////////////////////////////////////////////////////
4945+// //////////////////////////////////////////////////////////////////
4946+// //////////////////////////////////////////////////////////////////
4947+
4948+ValueIterator::ValueIterator()
4949+{
4950+}
4951+
4952+
4953+#ifndef JSON_VALUE_USE_INTERNAL_MAP
4954+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
4955+ : ValueIteratorBase( current )
4956+{
4957+}
4958+#else
4959+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
4960+ : ValueIteratorBase( state )
4961+{
4962+}
4963+
4964+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
4965+ : ValueIteratorBase( state )
4966+{
4967+}
4968+#endif
4969+
4970+ValueIterator::ValueIterator( const ValueConstIterator &other )
4971+ : ValueIteratorBase( other )
4972+{
4973+}
4974+
4975+ValueIterator::ValueIterator( const ValueIterator &other )
4976+ : ValueIteratorBase( other )
4977+{
4978+}
4979+
4980+ValueIterator &
4981+ValueIterator::operator =( const SelfType &other )
4982+{
4983+ copy( other );
4984+ return *this;
4985+}
4986
4987=== added file 'plugin/json_server/json/json_writer.cpp'
4988--- plugin/json_server/json/json_writer.cpp 1970-01-01 00:00:00 +0000
4989+++ plugin/json_server/json/json_writer.cpp 2011-05-04 01:52:37 +0000
4990@@ -0,0 +1,862 @@
4991+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4992+ *
4993+ * JSON Library, originally from http://jsoncpp.sourceforge.net/
4994+ *
4995+ * Copyright (C) 2011 Stewart Smith
4996+ * All rights reserved.
4997+ *
4998+ * Redistribution and use in source and binary forms, with or without
4999+ * modification, are permitted provided that the following conditions are
5000+ * met:
The diff has been truncated for viewing.