A Lightweight SQL Database for Cloud Infrastructure and Web Applications

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

Proposed by Stewart Smith on 2011-05-04
Status: Merged
Approved by: Brian Aker on 2011-05-04
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
To merge this branch: bzr merge lp:~stewart/drizzle/json-interface
Reviewer Review Type Date Requested Status
Mark Atwood Needs Fixing on 2011-05-12
Drizzle Merge Team 2011-05-04 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.
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.

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.

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).

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.

Mark Atwood (fallenpegasus) wrote :

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

Brian and I are looking at it.

Preview Diff

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.