Merge lp:~zorba-coders/zorba/feature-json_parser into lp:zorba

Proposed by Sorin Marian Nasoi
Status: Superseded
Proposed branch: lp:~zorba-coders/zorba/feature-json_parser
Merge into: lp:zorba
Diff against target: 5924 lines (+5008/-67)
113 files modified
include/zorba/diagnostic.h (+4/-1)
include/zorba/pregenerated/diagnostic_list.h (+32/-0)
modules/com/zorba-xquery/www/modules/CMakeLists.txt (+4/-0)
modules/com/zorba-xquery/www/modules/converters/json-options.xsd (+60/-0)
modules/com/zorba-xquery/www/modules/converters/json.xq (+175/-0)
modules/com/zorba-xquery/www/modules/pregenerated/errors.xq (+65/-1)
src/context/static_context.cpp (+5/-0)
src/context/static_context.h (+1/-0)
src/diagnostics/diagnostic.cpp (+3/-0)
src/diagnostics/diagnostic_en.xml (+62/-0)
src/diagnostics/pregenerated/diagnostic_list.cpp (+48/-0)
src/diagnostics/pregenerated/dict_en.cpp (+18/-0)
src/diagnostics/qname.cpp (+6/-0)
src/functions/library.cpp (+2/-0)
src/functions/pregenerated/func_json.cpp (+87/-0)
src/functions/pregenerated/func_json.h (+79/-0)
src/functions/pregenerated/function_enum.h (+2/-0)
src/runtime/CMakeLists.txt (+3/-0)
src/runtime/full_text/ft_match.cpp (+2/-3)
src/runtime/json/common.cpp (+62/-0)
src/runtime/json/common.h (+118/-0)
src/runtime/json/json_impl.cpp (+216/-0)
src/runtime/json/jsonml_array.cpp (+281/-0)
src/runtime/json/jsonml_array.h (+41/-0)
src/runtime/json/pregenerated/json.cpp (+94/-0)
src/runtime/json/pregenerated/json.h (+114/-0)
src/runtime/json/snelson.cpp (+498/-0)
src/runtime/json/snelson.h (+41/-0)
src/runtime/spec/json/json.xml (+52/-0)
src/runtime/spec/mappings.xml (+4/-0)
src/runtime/visitors/pregenerated/planiter_visitor.h (+10/-0)
src/runtime/visitors/pregenerated/printer_visitor.cpp (+29/-0)
src/runtime/visitors/pregenerated/printer_visitor.h (+6/-0)
src/unit_tests/CMakeLists.txt (+1/-0)
src/unit_tests/json_parser.cpp (+636/-0)
src/unit_tests/unit_test_list.h (+1/-0)
src/unit_tests/unit_tests.cpp (+1/-0)
src/util/CMakeLists.txt (+2/-0)
src/util/json_parser.cpp (+653/-0)
src/util/json_parser.h (+561/-0)
src/util/mem_streambuf.cpp (+119/-0)
src/util/mem_streambuf.h (+108/-0)
src/util/omanip.h (+205/-57)
src/util/oseparator.h (+17/-5)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-parse-01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-parse-02.xml.res (+4/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-parse-03.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-parse-wikipedia.xml.res (+10/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-02.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-03.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-indent-wikipedia.xml.res (+11/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-none-wikipedia.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-jsonml_array-serialize-some-wikipedia.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-array-01.xml.res (+3/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-array-02.xml.res (+3/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-array-03.xml.res (+3/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-array-04.xml.res (+3/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-array-05.xml.res (+4/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-example.xml.res (+14/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-object-01.xml.res (+3/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-parse-object-02.xml.res (+4/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-array-01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-array-02.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-array-03.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-array-04.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-array-05.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-indent-example.xml.res (+11/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-none-example.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-object-01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-object-02.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/json/json-snelson-serialize-some-example.xml.res (+1/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-parse-01.xq (+9/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-parse-02.xq (+14/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-parse-03.xq (+18/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-parse-wikipedia.xq (+23/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-01.xq (+10/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-02.xq (+13/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-03.xq (+10/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-indent-wikipedia.xq (+20/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-none-wikipedia.xq (+19/-0)
test/rbkt/Queries/zorba/json/json-jsonml_array-serialize-some-wikipedia.xq (+20/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-array-01.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-array-02.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-array-03.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-array-04.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-array-05.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-example.xq (+20/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-object-01.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-parse-object-02.xq (+5/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-01.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-02.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-03.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-04.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-05.xq (+9/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-06.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-06.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-07.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-07.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-08.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-08.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-09.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-09.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-10.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-10.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-11.spec (+1/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-array-11.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-indent-example.xq (+24/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-none-example.xq (+19/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-object-01.xq (+8/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-object-02.xq (+9/-0)
test/rbkt/Queries/zorba/json/json-snelson-serialize-some-example.xq (+24/-0)
test/unit/CMakeLists.txt (+1/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/feature-json_parser
Reviewer Review Type Date Requested Status
William Candillon Needs Fixing
Paul J. Lucas Pending
Sorin Marian Nasoi Pending
Review via email: mp+89008@code.launchpad.net

This proposal has been superseded by a proposal from 2012-01-23.

Commit message

New JSON parser and module.
Fixed the missing quote in the documentation.

Description of the change

New JSON parser and module.
Fixed the missing quote in the documentation.

To post a comment you must log in.
Revision history for this message
Sorin Marian Nasoi (sorin.marian.nasoi) wrote :

I have resubmitted the merge proposal after committing the fix for the JSON tests.

Revision history for this message
William Candillon (wcandillon) wrote :

The documentation is missing some examples.
The example section at http://docs.basex.org/wiki/JSON_Module is a good place to get inspired.

Why A chars have a backslash in error code descriptions:
ZJSE0001 if \a $xml is not a document or element node.
ZJSE0002 if \a $xml contains an element that is missing a required attribute.
ZJSE0003 if \a $xml contains an attribute having an illegal value.
ZJSE0004 if \a $xml contains an illegal element.
ZJSE0005 if \a $xml contains an illegal child element for a JSON type.
ZJSE0006 if \a $xml contains an illegal child element.
ZJSE0007 if \a $xml contains an illegal text node.
ZJSE0008 if \a $xml contains an illegal value for a JSON type.

review: Needs Fixing
Revision history for this message
Paul J. Lucas (paul-lucas) wrote :

The \a is the doxygen way to say the following thing is an argument and should be italicized.

Revision history for this message
William Candillon (wcandillon) wrote :

Doesn't seem to work for xqdoc

10614. By Paul J. Lucas

Removed \a and \c.

10615. By Paul J. Lucas

Added checking of stream state.

10616. By Paul J. Lucas

Merge from trunk.

10617. By Paul J. Lucas

1. Added yet more documentation.
2. Added %ann:streamable.

10618. By Sorin Marian Nasoi <email address hidden>

Added some tests that are marked as EXPECTED_FAILURES with their corresponding Launchpad bugs.

10619. By Sorin Marian Nasoi <email address hidden>

Fixed the following XQDoc issues:
- added module Author
- added correct category
- added examples for all 4 functions
- added zerr:ZJPE0006

10620. By Paul J. Lucas

Merge from trunk.

10621. By Paul J. Lucas

Removed virtually useless and potentially wrong EXPECTED_FAILURES.

10622. By Paul J. Lucas

Added missing "return".

10623. By Paul J. Lucas

Added missing "return".

10624. By Paul J. Lucas

Renamed tests to conform to rest; fixed missing "return" (again).

10625. By Paul J. Lucas

Merge from trunk.

10626. By Paul J. Lucas

Re-enabled test.

10627. By Paul J. Lucas

Updated test for new JSON module options schema.

10628. By Paul J. Lucas

1. Added ZJPE0009 error ("illegal empty string").
2. Now checking for empty strings in module parse() functions.
3. Added json::parser::peek().

10629. By Paul J. Lucas

Test clean-up.

10630. By Paul J. Lucas

Fixed more bugs.

10631. By Paul J. Lucas

Merge from trunk.

10632. By Paul J. Lucas

Added T_const_ptr.

10633. By Paul J. Lucas

s/optimal_arg/call_traits/

10634. By Paul J. Lucas

Added T_const_ptr.

10635. By Sorin Marian Nasoi <email address hidden>

The new core JSON module version 2.0 also fixes a bug reported against the deprecated version 1.0 external JSON module:
lp:878508.

10636. By Paul J. Lucas

Merge from trunk.

10637. By Markos Zaharioudakis

fixed bug #920717

10638. By Paul J. Lucas

Clean-up.

10639. By Paul J. Lucas

Merge from trunk.

10640. By Paul J. Lucas

Yet another fix.

10641. By Paul J. Lucas

Yet another bug fixed.

10642. By Paul J. Lucas

Merge from trunk.

10643. By Paul J. Lucas

Merge from trunk.

10644. By Paul J. Lucas

More documentation.

10645. By Paul J. Lucas

Merge from trunk.

10646. By Paul J. Lucas

Added yet more examples to JSON documentation.

10647. By Paul J. Lucas

Clean-up; new test.

10648. By Paul J. Lucas

Fixed bug 930573.

10649. By Paul J. Lucas

Merge from trunk.

10650. By Paul J. Lucas

Removed data-converters tag.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/zorba/diagnostic.h'
2--- include/zorba/diagnostic.h 2011-07-01 16:07:54 +0000
3+++ include/zorba/diagnostic.h 2012-01-23 00:53:24 +0000
4@@ -239,7 +239,10 @@
5 ZORBA_DEBUGGER, // Zorba Debugger
6 ZORBA_OS, // Operating System
7 ZORBA_SERIALIZATION,
8- ZORBA_STORE
9+ ZORBA_STORE,
10+
11+ JSON_PARSER,
12+ JSON_SERIALIZATION
13 };
14
15 /**
16
17=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
18--- include/zorba/pregenerated/diagnostic_list.h 2011-12-21 14:40:33 +0000
19+++ include/zorba/pregenerated/diagnostic_list.h 2012-01-23 00:53:24 +0000
20@@ -746,6 +746,38 @@
21
22 extern ZORBA_DLL_PUBLIC ZorbaErrorCode XSST0010;
23
24+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0001_ILLEGAL_CHARACTER;
25+
26+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0002_ILLEGAL_CODEPOINT;
27+
28+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0003_ILLEGAL_ESCAPE;
29+
30+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0004_ILLEGAL_LITERAL;
31+
32+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0005_ILLEGAL_NUMBER;
33+
34+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0006_UNEXPECTED_TOKEN;
35+
36+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0007_UNTERMINATED_STRING;
37+
38+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0008_ILLEGAL_QNAME;
39+
40+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0001_NOT_DOCUMENT_OR_ELEMENT_NODE;
41+
42+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0002_ELEMENT_MISSING_ATTRIBUTE;
43+
44+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0003_BAD_ATTRIBUTE_VALUE;
45+
46+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0004_BAD_ELEMENT;
47+
48+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0005_BAD_CHILD_ELEMENT;
49+
50+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0006_NO_ELEMENT_CHILD;
51+
52+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0007_NO_TEXT_CHILD;
53+
54+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJSE0008_BAD_VALUE;
55+
56 } // namespace zerr
57
58 namespace zwarn {
59
60=== modified file 'modules/com/zorba-xquery/www/modules/CMakeLists.txt'
61--- modules/com/zorba-xquery/www/modules/CMakeLists.txt 2012-01-11 17:30:25 +0000
62+++ modules/com/zorba-xquery/www/modules/CMakeLists.txt 2012-01-23 00:53:24 +0000
63@@ -68,6 +68,10 @@
64 # Subdirectories
65 DECLARE_ZORBA_MODULE(FILE converters/base64.xq VERSION 2.0
66 URI "http://www.zorba-xquery.com/modules/converters/base64")
67+DECLARE_ZORBA_MODULE(FILE converters/json.xq VERSION 2.0
68+ URI "http://www.zorba-xquery.com/modules/converters/json")
69+DECLARE_ZORBA_SCHEMA(FILE converters/json-options.xsd
70+ URI "http://www.zorba-xquery.com/modules/converters/json-options")
71 DECLARE_ZORBA_MODULE(FILE introspection/sctx.xq VERSION 2.0
72 URI "http://www.zorba-xquery.com/modules/introspection/sctx")
73 DECLARE_ZORBA_MODULE(FILE xqdoc2xhtml/error.xq VERSION 2.0
74
75=== added file 'modules/com/zorba-xquery/www/modules/converters/json-options.xsd'
76--- modules/com/zorba-xquery/www/modules/converters/json-options.xsd 1970-01-01 00:00:00 +0000
77+++ modules/com/zorba-xquery/www/modules/converters/json-options.xsd 2012-01-23 00:53:24 +0000
78@@ -0,0 +1,60 @@
79+<!--
80+ ! Copyright 2006-2008 The FLWOR Foundation.
81+ !
82+ ! Licensed under the Apache License, Version 2.0 (the "License");
83+ ! you may not use this file except in compliance with the License.
84+ ! You may obtain a copy of the License at
85+ !
86+ ! http://www.apache.org/licenses/LICENSE-2.0
87+ !
88+ ! Unless required by applicable law or agreed to in writing, software
89+ ! distributed under the License is distributed on an "AS IS" BASIS,
90+ ! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
91+ ! See the License for the specific language governing permissions and
92+ ! limitations under the License.
93+-->
94+
95+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
96+ xmlns:json="http://www.zorba-xquery.com/modules/converters/json-options"
97+ targetNamespace="http://www.zorba-xquery.com/modules/converters/json-options"
98+ elementFormDefault="qualified"
99+ attributeFormDefault="unqualified">
100+
101+ <xs:element name="options">
102+ <xs:complexType>
103+ <xs:all>
104+
105+ <xs:element name="json-format" minOccurs="1" maxOccurs="1">
106+ <xs:complexType>
107+ <xs:attribute name="value" use="required">
108+ <xs:simpleType>
109+ <xs:restriction base="xs:string">
110+ <xs:enumeration value="Snelson"/>
111+ <xs:enumeration value="JsonML-array"/>
112+ <xs:enumeration value="JsonML-object"/>
113+ </xs:restriction>
114+ </xs:simpleType>
115+ </xs:attribute>
116+ </xs:complexType>
117+ </xs:element>
118+
119+ <xs:element name="whitespace" minOccurs="0" maxOccurs="1">
120+ <xs:complexType>
121+ <xs:attribute name="value" use="required">
122+ <xs:simpleType>
123+ <xs:restriction base="xs:string">
124+ <xs:enumeration value="none"/>
125+ <xs:enumeration value="some"/>
126+ <xs:enumeration value="indent"/>
127+ </xs:restriction>
128+ </xs:simpleType>
129+ </xs:attribute>
130+ </xs:complexType>
131+ </xs:element>
132+
133+ </xs:all>
134+ </xs:complexType>
135+ </xs:element>
136+</xs:schema>
137+
138+<!-- vim:set et sw=2 ts=2: -->
139
140=== added file 'modules/com/zorba-xquery/www/modules/converters/json.xq'
141--- modules/com/zorba-xquery/www/modules/converters/json.xq 1970-01-01 00:00:00 +0000
142+++ modules/com/zorba-xquery/www/modules/converters/json.xq 2012-01-23 00:53:24 +0000
143@@ -0,0 +1,175 @@
144+(:
145+ : Copyright 2006-2009 The FLWOR Foundation.
146+ :
147+ : Licensed under the Apache License, Version 2.0 (the "License");
148+ : you may not use this file except in compliance with the License.
149+ : You may obtain a copy of the License at
150+ :
151+ : http://www.apache.org/licenses/LICENSE-2.0
152+ :
153+ : Unless required by applicable law or agreed to in writing, software
154+ : distributed under the License is distributed on an "AS IS" BASIS,
155+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
156+ : See the License for the specific language governing permissions and
157+ : limitations under the License.
158+ :)
159+
160+xquery version "3.0";
161+
162+ (:~
163+ : Using this module, you can parse JSON data into XML, manipulate it like any
164+ : other XML data using XQuery, and serialize the result back as JSON.
165+ :
166+ : There are many ways to represent JSON data in XML, some loss-less ("round
167+ : tripable") and some lossy ("one way"). Loss-less representations preserve
168+ : the JSON data types <i>boolean</i>, <i>number</i>, and <i>null</i>; lossy
169+ : representations convert all data to strings.
170+ :
171+ : For a loss-less representation, Zorba implements that proposed by
172+ : <a href="http://john.snelson.org.uk/parsing-json-into-xquery">John Snelson</a>;
173+ : for a lossy representation, Zorba implements
174+ : <a href="http://jsonml.org/">JsonML</a> (the array form).
175+ :)
176+
177+module namespace json = "http://www.zorba-xquery.com/modules/converters/json";
178+
179+import module namespace schema = "http://www.zorba-xquery.com/modules/schema";
180+
181+import schema namespace json-options =
182+ "http://www.zorba-xquery.com/modules/converters/json-options";
183+
184+declare namespace err = "http://www.w3.org/2005/xqt-errors";
185+
186+declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
187+declare option ver:module-version "2.0";
188+
189+(:~
190+ : Parses JSON data from a string and returns an XDM instance using one of the
191+ : representations described above.
192+ :
193+ : @param $json The JSON data to parse.
194+ : @param $options The parsing options.
195+ : @return said XDM instance.
196+ : @error err:XQDY0027 if $options can not be validated against the
197+ : json-options schema.
198+ : @error ZJPE0001 if $json contains an illegal JSON character.
199+ : @error ZJPE0002 if $json contains an illegal Unicode code-point.
200+ : @error ZJPE0003 if $json contains an illegal JSON character escape.
201+ : @error ZJPE0004 if $json contains an illegal JSON literal.
202+ : @error ZJPE0005 if $json contains an illegal JSON number.
203+ : @error ZJPE0007 if $json contains an unterminated string.
204+ : @error ZJPE0008 if $json contains an illegal QName.
205+ :)
206+declare function json:parse(
207+ $json as xs:string?,
208+ $options as element(json-options:options)
209+) as element(*,xs:untyped)*
210+{
211+ let $validated-options := if ( schema:is-validated( $options ) ) then
212+ $options
213+ else
214+ validate { $options }
215+ return json:parse-internal( $json, $validated-options )
216+};
217+
218+(:~
219+ : Parses JSON data from a string and returns an XDM instance using the Snelson
220+ : representation described above.
221+ :
222+ : @param $json The JSON data to parse.
223+ : @return said XDM instance.
224+ : @error ZJPE0001 if $json contains an illegal JSON character.
225+ : @error ZJPE0002 if $json contains an illegal Unicode code-point.
226+ : @error ZJPE0003 if $json contains an illegal JSON character escape.
227+ : @error ZJPE0004 if $json contains an illegal JSON literal.
228+ : @error ZJPE0005 if $json contains an illegal JSON number.
229+ : @error ZJPE0007 if $json contains an unterminated string.
230+ : @error ZJPE0008 if $json contains an illegal QName.
231+ :)
232+declare function json:parse(
233+ $json as xs:string?
234+) as element(*,xs:untyped)*
235+{
236+ json:parse-internal(
237+ $json,
238+ validate {
239+ <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options" >
240+ <json-format value="Snelson"/>
241+ </options>
242+ }
243+ )
244+};
245+
246+(:~
247+ : Serializes an XDM into JSON using one of the representations described
248+ : above.
249+ :
250+ : @param $xml The XDM to serialize.
251+ : @param $options The serializing options.
252+ : @return a JSON string.
253+ : @error err:XQDY0027 if $options can not be validated against the
254+ : json-options schema.
255+ : @error ZJSE0001 if $xml is not a document or element node.
256+ : @error ZJSE0002 if $xml contains an element that is missing a required
257+ : attribute.
258+ : @error ZJSE0003 if $xml contains an attribute having an illegal value.
259+ : @error ZJSE0004 if $xml contains an illegal element.
260+ : @error ZJSE0005 if $xml contains an illegal child element for a JSON type.
261+ : @error ZJSE0006 if $xml contains an illegal child element.
262+ : @error ZJSE0007 if $xml contains an illegal text node.
263+ : @error ZJSE0008 if $xml contains an illegal value for a JSON type.
264+ :)
265+declare function json:serialize(
266+ $xml as item()*,
267+ $options as element(json-options:options)
268+) as xs:string
269+{
270+ let $validated-options := if ( schema:is-validated( $options ) ) then
271+ $options
272+ else
273+ validate { $options }
274+ return json:serialize-internal( $xml, $validated-options )
275+};
276+
277+(:~
278+ : Serializes an XDM into JSON using one of the representations described
279+ : above.
280+ :
281+ : @param $xml The XDM to serialize.
282+ : @return a JSON string.
283+ : @error ZJSE0001 if $xml is not a document or element node.
284+ : @error ZJSE0002 if $xml contains an element that is missing a required
285+ : attribute.
286+ : @error ZJSE0003 if $xml contains an attribute having an illegal value.
287+ : @error ZJSE0004 if $xml contains an illegal element.
288+ : @error ZJSE0005 if $xml contains an illegal child element for a JSON type.
289+ : @error ZJSE0006 if $xml contains an illegal child element.
290+ : @error ZJSE0007 if $xml contains an illegal text node.
291+ : @error ZJSE0008 if $xml contains an illegal value for a JSON type.
292+ :)
293+declare function json:serialize(
294+ $xml as item()*
295+) as xs:string
296+{
297+ json:serialize-internal($xml,
298+ validate {
299+ <options xmlns="http://www.zorba-xquery.com/modules/converters/json-options" >
300+ <json-format value="Snelson"/>
301+ </options>
302+ }
303+ )
304+};
305+
306+(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
307+
308+declare %private function json:parse-internal(
309+ $json as xs:string,
310+ $options as item()?
311+) as element()* external;
312+
313+declare %private function json:serialize-internal(
314+ $xml as item()*,
315+ $options as item()?
316+) as xs:string external;
317+
318+(: vim:set et sw=2 ts=2: :)
319
320=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
321--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2011-12-21 14:40:33 +0000
322+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2012-01-23 00:53:24 +0000
323@@ -784,4 +784,68 @@
324
325 (:~
326 :)
327-declare variable $zerr:XSST0010 as xs:QName := fn:QName($zerr:NS, "zerr:XSST0010");
328\ No newline at end of file
329+declare variable $zerr:XSST0010 as xs:QName := fn:QName($zerr:NS, "zerr:XSST0010");
330+
331+(:~
332+:)
333+declare variable $zerr:ZJPE0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0001");
334+
335+(:~
336+:)
337+declare variable $zerr:ZJPE0002 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0002");
338+
339+(:~
340+:)
341+declare variable $zerr:ZJPE0003 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0003");
342+
343+(:~
344+:)
345+declare variable $zerr:ZJPE0004 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0004");
346+
347+(:~
348+:)
349+declare variable $zerr:ZJPE0005 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0005");
350+
351+(:~
352+:)
353+declare variable $zerr:ZJPE0006 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0006");
354+
355+(:~
356+:)
357+declare variable $zerr:ZJPE0007 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0007");
358+
359+(:~
360+:)
361+declare variable $zerr:ZJPE0008 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0008");
362+
363+(:~
364+:)
365+declare variable $zerr:ZJSE0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0001");
366+
367+(:~
368+:)
369+declare variable $zerr:ZJSE0002 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0002");
370+
371+(:~
372+:)
373+declare variable $zerr:ZJSE0003 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0003");
374+
375+(:~
376+:)
377+declare variable $zerr:ZJSE0004 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0004");
378+
379+(:~
380+:)
381+declare variable $zerr:ZJSE0005 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0005");
382+
383+(:~
384+:)
385+declare variable $zerr:ZJSE0006 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0006");
386+
387+(:~
388+:)
389+declare variable $zerr:ZJSE0007 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0007");
390+
391+(:~
392+:)
393+declare variable $zerr:ZJSE0008 as xs:QName := fn:QName($zerr:NS, "zerr:ZJSE0008");
394\ No newline at end of file
395
396=== modified file 'src/context/static_context.cpp'
397--- src/context/static_context.cpp 2012-01-11 17:30:25 +0000
398+++ src/context/static_context.cpp 2012-01-23 00:53:24 +0000
399@@ -349,6 +349,9 @@
400 static_context::ZORBA_STRING_FN_NS = NS_PRE + "modules/string";
401
402 const zstring
403+static_context::ZORBA_JSON_FN_NS = NS_PRE + "modules/converters/json";
404+
405+const zstring
406 static_context::ZORBA_FETCH_FN_NS = NS_PRE + "modules/fetch";
407
408 const zstring
409@@ -414,6 +417,7 @@
410 ns == ZORBA_REFLECTION_FN_NS ||
411 ns == ZORBA_SCRIPTING_FN_NS ||
412 ns == ZORBA_STRING_FN_NS ||
413+ ns == ZORBA_JSON_FN_NS ||
414 ns == ZORBA_FETCH_FN_NS ||
415 ns == ZORBA_NODE_FN_NS ||
416 ns == ZORBA_XML_FN_NS);
417@@ -460,6 +464,7 @@
418 {
419 return (ns == ZORBA_MATH_FN_NS ||
420 ns == ZORBA_INTROSP_SCTX_FN_NS ||
421+ ns == ZORBA_JSON_FN_NS ||
422 ns == ZORBA_RANDOM_FN_NS);
423 }
424
425
426=== modified file 'src/context/static_context.h'
427--- src/context/static_context.h 2012-01-11 17:30:25 +0000
428+++ src/context/static_context.h 2012-01-23 00:53:24 +0000
429@@ -464,6 +464,7 @@
430 static const zstring ZORBA_INTROSP_SCTX_FN_NS;
431 static const zstring ZORBA_REFLECTION_FN_NS;
432 static const zstring ZORBA_STRING_FN_NS;
433+ static const zstring ZORBA_JSON_FN_NS;
434 static const zstring ZORBA_FETCH_FN_NS;
435 static const zstring ZORBA_NODE_FN_NS;
436 static const zstring ZORBA_XML_FN_NS;
437
438=== modified file 'src/diagnostics/diagnostic.cpp'
439--- src/diagnostics/diagnostic.cpp 2011-07-11 21:01:20 +0000
440+++ src/diagnostics/diagnostic.cpp 2012-01-23 00:53:24 +0000
441@@ -134,6 +134,9 @@
442 case ZORBA_STORE : o << "Zorba store" ; break;
443 case ZORBA_XQP : o << "Zorba" ; break;
444
445+ case JSON_PARSER : o << "JSON parser" ; break;
446+ case JSON_SERIALIZATION : o << "JSON serialization" ; break;
447+
448 default : /* suppresses warning */ break;
449 }
450 return o;
451
452=== modified file 'src/diagnostics/diagnostic_en.xml'
453--- src/diagnostics/diagnostic_en.xml 2011-12-21 14:40:33 +0000
454+++ src/diagnostics/diagnostic_en.xml 2012-01-23 00:53:24 +0000
455@@ -2307,6 +2307,60 @@
456 <value>"continue loop" statement not inside while statement</value>
457 </diagnostic>
458
459+ <!--////////// JSON Parse Errors ////////////////////////////////////////-->
460+
461+ <diagnostic code="ZJPE0001" name="ILLEGAL_CHARACTER">
462+ <value>'$1': illegal JSON character</value>
463+ </diagnostic>
464+ <diagnostic code="ZJPE0002" name="ILLEGAL_CODEPOINT">
465+ <value>"$1": illegal Unicode code-point</value>
466+ </diagnostic>
467+ <diagnostic code="ZJPE0003" name="ILLEGAL_ESCAPE">
468+ <value>'\\$1': illegal JSON character escape</value>
469+ </diagnostic>
470+ <diagnostic code="ZJPE0004" name="ILLEGAL_LITERAL">
471+ <value>illegal JSON literal</value>
472+ </diagnostic>
473+ <diagnostic code="ZJPE0005" name="ILLEGAL_NUMBER">
474+ <value>illegal JSON number</value>
475+ </diagnostic>
476+ <diagnostic code="ZJPE0006" name="UNEXPECTED_TOKEN">
477+ <value>"$1": unexpected JSON token</value>
478+ </diagnostic>
479+ <diagnostic code="ZJPE0007" name="UNTERMINATED_STRING">
480+ <value>unterminated JSON string</value>
481+ </diagnostic>
482+ <diagnostic code="ZJPE0008" name="ILLEGAL_QNAME">
483+ <value>"$1": illegal QName</value>
484+ </diagnostic>
485+
486+ <!--////////// JSON Serialization Errors ////////////////////////////////-->
487+
488+ <diagnostic code="ZJSE0001" name="NOT_DOCUMENT_OR_ELEMENT_NODE">
489+ <value>JSON serialization requires document or element node</value>
490+ </diagnostic>
491+ <diagnostic code="ZJSE0002" name="ELEMENT_MISSING_ATTRIBUTE">
492+ <value>"$1" element missing required "$2" attribute</value>
493+ </diagnostic>
494+ <diagnostic code="ZJSE0003" name="BAD_ATTRIBUTE_VALUE">
495+ <value>"$1": illegal value for attribute "$2"</value>
496+ </diagnostic>
497+ <diagnostic code="ZJSE0004" name="BAD_ELEMENT">
498+ <value>"$1": illegal element${; must be "2"}${ or "3"}</value>
499+ </diagnostic>
500+ <diagnostic code="ZJSE0005" name="BAD_CHILD_ELEMENT">
501+ <value>"$1": illegal child element of "$2" type; must be "$3"</value>
502+ </diagnostic>
503+ <diagnostic code="ZJSE0006" name="NO_ELEMENT_CHILD">
504+ <value>JSON type "$1" can not have a child element node</value>
505+ </diagnostic>
506+ <diagnostic code="ZJSE0007" name="NO_TEXT_CHILD">
507+ <value>JSON type "$1" can not have a child text node</value>
508+ </diagnostic>
509+ <diagnostic code="ZJSE0008" name="BAD_VALUE">
510+ <value>"$1": illegal value for JSON type "$2"</value>
511+ </diagnostic>
512+
513 </namespace>
514
515 <!--////////// Zorba Warnings ////////////////////////////////////////////-->
516@@ -3264,6 +3318,14 @@
517 <value>Zorba warning</value>
518 </entry>
519
520+ <entry key="JSON parser error">
521+ <value>JSON parser error</value>
522+ </entry>
523+
524+ <entry key="JSON serialization error">
525+ <value>JSON serialization error</value>
526+ </entry>
527+
528 <entry key="dynamic error">
529 <value>dynamic error</value>
530 </entry>
531
532=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
533--- src/diagnostics/pregenerated/diagnostic_list.cpp 2011-12-21 14:40:33 +0000
534+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2012-01-23 00:53:24 +0000
535@@ -1097,6 +1097,54 @@
536 ZorbaErrorCode XSST0010( "XSST0010" );
537
538
539+ZorbaErrorCode ZJPE0001_ILLEGAL_CHARACTER( "ZJPE0001" );
540+
541+
542+ZorbaErrorCode ZJPE0002_ILLEGAL_CODEPOINT( "ZJPE0002" );
543+
544+
545+ZorbaErrorCode ZJPE0003_ILLEGAL_ESCAPE( "ZJPE0003" );
546+
547+
548+ZorbaErrorCode ZJPE0004_ILLEGAL_LITERAL( "ZJPE0004" );
549+
550+
551+ZorbaErrorCode ZJPE0005_ILLEGAL_NUMBER( "ZJPE0005" );
552+
553+
554+ZorbaErrorCode ZJPE0006_UNEXPECTED_TOKEN( "ZJPE0006" );
555+
556+
557+ZorbaErrorCode ZJPE0007_UNTERMINATED_STRING( "ZJPE0007" );
558+
559+
560+ZorbaErrorCode ZJPE0008_ILLEGAL_QNAME( "ZJPE0008" );
561+
562+
563+ZorbaErrorCode ZJSE0001_NOT_DOCUMENT_OR_ELEMENT_NODE( "ZJSE0001" );
564+
565+
566+ZorbaErrorCode ZJSE0002_ELEMENT_MISSING_ATTRIBUTE( "ZJSE0002" );
567+
568+
569+ZorbaErrorCode ZJSE0003_BAD_ATTRIBUTE_VALUE( "ZJSE0003" );
570+
571+
572+ZorbaErrorCode ZJSE0004_BAD_ELEMENT( "ZJSE0004" );
573+
574+
575+ZorbaErrorCode ZJSE0005_BAD_CHILD_ELEMENT( "ZJSE0005" );
576+
577+
578+ZorbaErrorCode ZJSE0006_NO_ELEMENT_CHILD( "ZJSE0006" );
579+
580+
581+ZorbaErrorCode ZJSE0007_NO_TEXT_CHILD( "ZJSE0007" );
582+
583+
584+ZorbaErrorCode ZJSE0008_BAD_VALUE( "ZJSE0008" );
585+
586+
587 } // namespace zerr
588
589 namespace zwarn {
590
591=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
592--- src/diagnostics/pregenerated/dict_en.cpp 2011-12-21 14:40:33 +0000
593+++ src/diagnostics/pregenerated/dict_en.cpp 2012-01-23 00:53:24 +0000
594@@ -332,6 +332,22 @@
595 #if defined(ZORBA_WITH_DEBUGGER)
596 { "ZGDB0001", "" },
597 #endif
598+ { "ZJPE0001", "'$1': illegal JSON character" },
599+ { "ZJPE0002", "\"$1\": illegal Unicode code-point" },
600+ { "ZJPE0003", "'\\$1': illegal JSON character escape" },
601+ { "ZJPE0004", "illegal JSON literal" },
602+ { "ZJPE0005", "illegal JSON number" },
603+ { "ZJPE0006", "\"$1\": unexpected JSON token" },
604+ { "ZJPE0007", "unterminated JSON string" },
605+ { "ZJPE0008", "\"$1\": illegal QName" },
606+ { "ZJSE0001", "JSON serialization requires document or element node" },
607+ { "ZJSE0002", "\"$1\" element missing required \"$2\" attribute" },
608+ { "ZJSE0003", "\"$1\": illegal value for attribute \"$2\"" },
609+ { "ZJSE0004", "\"$1\": illegal element${; must be \"2\"}${ or \"3\"}" },
610+ { "ZJSE0005", "\"$1\": illegal child element of \"$2\" type; must be \"$3\"" },
611+ { "ZJSE0006", "JSON type \"$1\" can not have a child element node" },
612+ { "ZJSE0007", "JSON type \"$1\" can not have a child text node" },
613+ { "ZJSE0008", "\"$1\": illegal value for JSON type \"$2\"" },
614 { "ZOSE0001", "\"$1\": file not found" },
615 { "ZOSE0002", "\"$1\": not plain file" },
616 { "ZOSE0003", "stream read failure" },
617@@ -494,6 +510,8 @@
618 { "~HexBinaryMustBeEven", "HexBinary value must contain an even number of characters" },
619 { "~IncompleteKeyInIndexBuild", "incomplete key during index build" },
620 { "~IncompleteKeyInIndexRefresh", "incomplete key during index refresh" },
621+ { "~JSON parser error", "JSON parser error" },
622+ { "~JSON serialization error", "JSON serialization error" },
623 { "~LibModVersionMismatch_3", "XQuery library version can not be imported by a $3 version module" },
624 { "~ModuleDeclNotInMain", "module declaration must not be in main module" },
625 { "~ModuleNotFound", "module not found" },
626
627=== modified file 'src/diagnostics/qname.cpp'
628--- src/diagnostics/qname.cpp 2011-07-01 16:07:54 +0000
629+++ src/diagnostics/qname.cpp 2012-01-23 00:53:24 +0000
630@@ -79,9 +79,15 @@
631 case 'C': return ZORBA_SERIALIZATION;
632 case 'D': return ZORBA_DDF;
633 case 'G': return ZORBA_DEBUGGER;
634+ case 'J': switch ( name[2] ) {
635+ case 'P': return JSON_PARSER;
636+ case 'S': return JSON_SERIALIZATION;
637+ default : ZORBA_ASSERT( false );
638+ }
639 case 'O': return ZORBA_OS;
640 case 'S': return ZORBA_STORE;
641 case 'X': return ZORBA_XQP;
642+
643 default : ZORBA_ASSERT( false );
644 }
645 }
646
647=== modified file 'src/functions/library.cpp'
648--- src/functions/library.cpp 2011-10-14 07:35:51 +0000
649+++ src/functions/library.cpp 2012-01-23 00:53:24 +0000
650@@ -57,6 +57,7 @@
651 #include "functions/func_sequences.h"
652 #include "functions/func_sequences_impl.h"
653 #include "functions/func_strings.h"
654+#include "functions/func_json.h"
655 #include "functions/func_var_decl.h"
656 #include "functions/func_xqdoc.h"
657 #include "functions/func_documents.h"
658@@ -107,6 +108,7 @@
659 populate_context_fnput(sctx);
660 populate_context_index_ddl(sctx);
661 populate_context_ic_ddl(sctx);
662+ populate_context_json(sctx);
663 populate_context_maths(sctx);
664 populate_context_nodes(sctx);
665 populate_context_node_position(sctx);
666
667=== added file 'src/functions/pregenerated/func_json.cpp'
668--- src/functions/pregenerated/func_json.cpp 1970-01-01 00:00:00 +0000
669+++ src/functions/pregenerated/func_json.cpp 2012-01-23 00:53:24 +0000
670@@ -0,0 +1,87 @@
671+/*
672+ * Copyright 2006-2008 The FLWOR Foundation.
673+ *
674+ * Licensed under the Apache License, Version 2.0 (the "License");
675+ * you may not use this file except in compliance with the License.
676+ * You may obtain a copy of the License at
677+ *
678+ * http://www.apache.org/licenses/LICENSE-2.0
679+ *
680+ * Unless required by applicable law or agreed to in writing, software
681+ * distributed under the License is distributed on an "AS IS" BASIS,
682+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
683+ * See the License for the specific language governing permissions and
684+ * limitations under the License.
685+ */
686+
687+// ******************************************
688+// * *
689+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
690+// * SEE .xml FILE WITH SAME NAME *
691+// * *
692+// ******************************************
693+
694+
695+#include "stdafx.h"
696+#include "runtime/json/json.h"
697+#include "functions/func_json.h"
698+
699+
700+namespace zorba{
701+
702+
703+
704+PlanIter_t fn_zorba_json_parse_internal::codegen(
705+ CompilerCB*,
706+ static_context* sctx,
707+ const QueryLoc& loc,
708+ std::vector<PlanIter_t>& argv,
709+ AnnotationHolder& ann) const
710+{
711+ return new JSONParseInternal(sctx, loc, argv);
712+}
713+
714+PlanIter_t fn_zorba_json_serialize_internal::codegen(
715+ CompilerCB*,
716+ static_context* sctx,
717+ const QueryLoc& loc,
718+ std::vector<PlanIter_t>& argv,
719+ AnnotationHolder& ann) const
720+{
721+ return new JSONSerializeInternal(sctx, loc, argv);
722+}
723+
724+void populate_context_json(static_context* sctx)
725+{
726+ {
727+
728+
729+ DECL_WITH_KIND(sctx, fn_zorba_json_parse_internal,
730+ (createQName("http://www.zorba-xquery.com/modules/converters/json","","parse-internal"),
731+ GENV_TYPESYSTEM.STRING_TYPE_ONE,
732+ GENV_TYPESYSTEM.ITEM_TYPE_QUESTION,
733+ GENV_TYPESYSTEM.ELEMENT_TYPE_STAR),
734+ FunctionConsts::FN_ZORBA_JSON_PARSE_INTERNAL_2);
735+
736+ }
737+
738+
739+ {
740+
741+
742+ DECL_WITH_KIND(sctx, fn_zorba_json_serialize_internal,
743+ (createQName("http://www.zorba-xquery.com/modules/converters/json","","serialize-internal"),
744+ GENV_TYPESYSTEM.ITEM_TYPE_STAR,
745+ GENV_TYPESYSTEM.ITEM_TYPE_QUESTION,
746+ GENV_TYPESYSTEM.STRING_TYPE_ONE),
747+ FunctionConsts::FN_ZORBA_JSON_SERIALIZE_INTERNAL_2);
748+
749+ }
750+
751+}
752+
753+
754+}
755+
756+
757+
758
759=== added file 'src/functions/pregenerated/func_json.h'
760--- src/functions/pregenerated/func_json.h 1970-01-01 00:00:00 +0000
761+++ src/functions/pregenerated/func_json.h 2012-01-23 00:53:24 +0000
762@@ -0,0 +1,79 @@
763+/*
764+ * Copyright 2006-2008 The FLWOR Foundation.
765+ *
766+ * Licensed under the Apache License, Version 2.0 (the "License");
767+ * you may not use this file except in compliance with the License.
768+ * You may obtain a copy of the License at
769+ *
770+ * http://www.apache.org/licenses/LICENSE-2.0
771+ *
772+ * Unless required by applicable law or agreed to in writing, software
773+ * distributed under the License is distributed on an "AS IS" BASIS,
774+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
775+ * See the License for the specific language governing permissions and
776+ * limitations under the License.
777+ */
778+
779+// ******************************************
780+// * *
781+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
782+// * SEE .xml FILE WITH SAME NAME *
783+// * *
784+// ******************************************
785+
786+
787+#ifndef ZORBA_FUNCTIONS_JSON_H
788+#define ZORBA_FUNCTIONS_JSON_H
789+
790+
791+#include "common/shared_types.h"
792+#include "functions/function_impl.h"
793+
794+
795+namespace zorba {
796+
797+
798+void populate_context_json(static_context* sctx);
799+
800+
801+
802+
803+//fn-zorba-json:parse-internal
804+class fn_zorba_json_parse_internal : public function
805+{
806+public:
807+ fn_zorba_json_parse_internal(const signature& sig, FunctionConsts::FunctionKind kind)
808+ :
809+ function(sig, kind)
810+ {
811+
812+ }
813+
814+ CODEGEN_DECL();
815+};
816+
817+
818+//fn-zorba-json:serialize-internal
819+class fn_zorba_json_serialize_internal : public function
820+{
821+public:
822+ fn_zorba_json_serialize_internal(const signature& sig, FunctionConsts::FunctionKind kind)
823+ :
824+ function(sig, kind)
825+ {
826+
827+ }
828+
829+ CODEGEN_DECL();
830+};
831+
832+
833+} //namespace zorba
834+
835+
836+#endif
837+/*
838+ * Local variables:
839+ * mode: c++
840+ * End:
841+ */
842
843=== modified file 'src/functions/pregenerated/function_enum.h'
844--- src/functions/pregenerated/function_enum.h 2012-01-11 17:30:25 +0000
845+++ src/functions/pregenerated/function_enum.h 2012-01-23 00:53:24 +0000
846@@ -166,6 +166,8 @@
847 FN_ZORBA_INTROSPECT_SCTX_IN_SCOPE_ATTRIBUTE_GROUPS_0,
848 FN_ZORBA_INTROSPECT_SCTX_OPTION_1,
849 FN_ZORBA_INTROSPECT_SCTX_FUNCTION_ANNOTATIONS_2,
850+ FN_ZORBA_JSON_PARSE_INTERNAL_2,
851+ FN_ZORBA_JSON_SERIALIZE_INTERNAL_2,
852 MATH_SQRT_1,
853 MATH_EXP_1,
854 MATH_EXP10_1,
855
856=== modified file 'src/runtime/CMakeLists.txt'
857--- src/runtime/CMakeLists.txt 2011-06-01 13:16:28 +0000
858+++ src/runtime/CMakeLists.txt 2012-01-23 00:53:24 +0000
859@@ -115,6 +115,9 @@
860 durations_dates_times/DurationsDatesTimesImpl.cpp
861 indexing/doc_indexer.cpp
862 indexing/index_ddl.cpp
863+ json/common.cpp
864+ json/jsonml_array.cpp
865+ json/snelson.cpp
866 numerics/NumericsImpl.cpp
867 numerics/format_integer_impl.cpp
868 sequences/SequencesImpl.cpp
869
870=== modified file 'src/runtime/full_text/ft_match.cpp'
871--- src/runtime/full_text/ft_match.cpp 2011-06-14 17:26:33 +0000
872+++ src/runtime/full_text/ft_match.cpp 2012-01-23 00:53:24 +0000
873@@ -31,7 +31,7 @@
874 return o << "0x" << hex << reinterpret_cast<unsigned long>( obj ) << dec;
875 }
876
877-DEF_OMANIP1( print_addr, void const*, obj )
878+DEF_OMANIP1( print_addr, void const* )
879
880 ostream& operator<<( ostream &o, ft_string_match const &sm ) {
881 return o << "{SM: "
882@@ -52,8 +52,7 @@
883 return o;
884 }
885
886-DEF_OMANIP2( print_string_matches, char const*, label,
887- ft_string_matches const&, sms )
888+DEF_OMANIP2( print_string_matches, char const*, ft_string_matches const& )
889
890 ostream& operator<<( ostream &o, ft_match const &m ) {
891 return o << indent << "ft_match @ " << print_addr( &m ) << '\n'
892
893=== added directory 'src/runtime/json'
894=== added file 'src/runtime/json/common.cpp'
895--- src/runtime/json/common.cpp 1970-01-01 00:00:00 +0000
896+++ src/runtime/json/common.cpp 2012-01-23 00:53:24 +0000
897@@ -0,0 +1,62 @@
898+/*
899+ * Copyright 2006-2011 The FLWOR Foundation.
900+ *
901+ * Licensed under the Apache License, Version 2.0 (the "License");
902+ * you may not use this file except in compliance with the License.
903+ * You may obtain a copy of the License at
904+ *
905+ * http://www.apache.org/licenses/LICENSE-2.0
906+ *
907+ * Unless required by applicable law or agreed to in writing, software
908+ * distributed under the License is distributed on an "AS IS" BASIS,
909+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
910+ * See the License for the specific language governing permissions and
911+ * limitations under the License.
912+ */
913+#include "stdafx.h"
914+
915+#include "store/api/iterator.h"
916+
917+#include "common.h"
918+
919+using namespace std;
920+
921+namespace zorba {
922+
923+///////////////////////////////////////////////////////////////////////////////
924+
925+bool get_attribute_value( store::Item_t const &element, char const *att_name,
926+ zstring *att_value ) {
927+ store::Iterator_t i( element->getAttributes() );
928+ bool found = false;
929+ i->open();
930+ store::Item_t att_item;
931+ while ( i->next( att_item ) ) {
932+ if ( att_item->getNodeName()->getStringValue() == att_name ) {
933+ att_item->getStringValue2( *att_value );
934+ found = true;
935+ break;
936+ }
937+ }
938+ i->close();
939+ return found;
940+}
941+
942+///////////////////////////////////////////////////////////////////////////////
943+
944+#if ZORBA_DEBUG_JSON
945+
946+ostream& operator<<( ostream &o, parse_state s ) {
947+ static char const *const string_of[] = {
948+ "in_array",
949+ "in_object"
950+ };
951+ return o << string_of[ s ];
952+}
953+
954+#endif /* ZORBA_DEBUG_JSON */
955+
956+///////////////////////////////////////////////////////////////////////////////
957+
958+} // namespace zorba
959+/* vim:set et sw=2 ts=2: */
960
961=== added file 'src/runtime/json/common.h'
962--- src/runtime/json/common.h 1970-01-01 00:00:00 +0000
963+++ src/runtime/json/common.h 2012-01-23 00:53:24 +0000
964@@ -0,0 +1,118 @@
965+/*
966+ * Copyright 2006-2011 The FLWOR Foundation.
967+ *
968+ * Licensed under the Apache License, Version 2.0 (the "License");
969+ * you may not use this file except in compliance with the License.
970+ * You may obtain a copy of the License at
971+ *
972+ * http://www.apache.org/licenses/LICENSE-2.0
973+ *
974+ * Unless required by applicable law or agreed to in writing, software
975+ * distributed under the License is distributed on an "AS IS" BASIS,
976+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
977+ * See the License for the specific language governing permissions and
978+ * limitations under the License.
979+ */
980+
981+#ifndef ZORBA_RUNTIME_JSON_COMMON_H
982+#define ZORBA_RUNTIME_JSON_COMMON_H
983+
984+#include <iostream>
985+#include <stack>
986+
987+#include "store/api/item.h"
988+#include "store/api/item_factory.h"
989+#include "util/indent.h"
990+#include "util/omanip.h"
991+#include "zorbatypes/zstring.h"
992+
993+#define ZORBA_DEBUG_JSON 0
994+
995+namespace zorba {
996+
997+///////////////////////////////////////////////////////////////////////////////
998+
999+typedef std::stack<store::Item*> item_stack_type;
1000+
1001+enum parse_state {
1002+ in_array,
1003+ in_object
1004+};
1005+
1006+typedef std::stack<int> state_stack_type;
1007+
1008+namespace whitespace {
1009+ enum type {
1010+ none,
1011+ some,
1012+ indent
1013+ };
1014+}
1015+
1016+///////////////////////////////////////////////////////////////////////////////
1017+
1018+bool get_attribute_value( store::Item_t const &element, char const *att_name,
1019+ zstring *att_value );
1020+
1021+typedef std::ostream& (*std_omanip_type)(std::ostream&);
1022+
1023+inline std::ostream& if_do( std::ostream &o, bool expr, std_omanip_type fn ) {
1024+ if ( expr )
1025+ o << fn;
1026+ return o;
1027+}
1028+DEF_OMANIP2( if_do, bool, std_omanip_type )
1029+
1030+#define if_indent(WS,FN) if_do( (WS) == whitespace::indent, FN )
1031+
1032+inline std::ostream& if_emit( std::ostream &o, bool expr, char c ) {
1033+ if ( expr )
1034+ o << c;
1035+ return o;
1036+}
1037+DEF_OMANIP2( if_emit, bool, char )
1038+
1039+///////////////////////////////////////////////////////////////////////////////
1040+
1041+#if ZORBA_DEBUG_JSON
1042+
1043+std::ostream& operator<<( std::ostream &o, parse_state s );
1044+
1045+# define PUSH_ITEM(I) \
1046+ do { \
1047+ cout << __LINE__ << ":PUSH_ITEM( " << (I)->show() << " )" << endl; \
1048+ item_stack.push( (I).getp() ); \
1049+ } while (0)
1050+
1051+# define POP_ITEM() \
1052+ do { \
1053+ cout << __LINE__ << ":POP_ITEM()" << endl; \
1054+ cur_item = ztd::pop_stack( item_stack ); \
1055+ } while (0)
1056+
1057+# define PUSH_STATE(S) \
1058+ do { \
1059+ cout << __LINE__ << ":PUSH_STATE( " << (S) << " )" << endl; \
1060+ state_stack.push( S ); \
1061+ } while (0)
1062+
1063+# define POP_STATE() \
1064+ do { \
1065+ cout << __LINE__ << ":POP_STATE()" << endl; \
1066+ state_stack.pop(); \
1067+ } while (0) \
1068+
1069+#else
1070+
1071+# define PUSH_ITEM(I) item_stack.push( (I).getp() )
1072+# define POP_ITEM() cur_item = ztd::pop_stack( item_stack )
1073+# define PUSH_STATE(S) state_stack.push( S )
1074+# define POP_STATE() state_stack.pop()
1075+
1076+#endif /* ZORBA_DEBUG_JSON */
1077+
1078+///////////////////////////////////////////////////////////////////////////////
1079+
1080+} // namespace zorba
1081+#endif /* ZORBA_RUNTIME_JSON_COMMON_H */
1082+/* vim:set et sw=2 ts=2: */
1083
1084=== added file 'src/runtime/json/json_impl.cpp'
1085--- src/runtime/json/json_impl.cpp 1970-01-01 00:00:00 +0000
1086+++ src/runtime/json/json_impl.cpp 2012-01-23 00:53:24 +0000
1087@@ -0,0 +1,216 @@
1088+/*
1089+ * Copyright 2006-2011 The FLWOR Foundation.
1090+ *
1091+ * Licensed under the Apache License, Version 2.0 (the "License");
1092+ * you may not use this file except in compliance with the License.
1093+ * You may obtain a copy of the License at
1094+ *
1095+ * http://www.apache.org/licenses/LICENSE-2.0
1096+ *
1097+ * Unless required by applicable law or agreed to in writing, software
1098+ * distributed under the License is distributed on an "AS IS" BASIS,
1099+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1100+ * See the License for the specific language governing permissions and
1101+ * limitations under the License.
1102+ */
1103+#include "stdafx.h"
1104+
1105+#include <map>
1106+#include <sstream>
1107+
1108+#include <zorba/diagnostic_list.h>
1109+
1110+#include "runtime/json/json.h"
1111+#include "store/api/item_factory.h"
1112+#include "system/globalenv.h"
1113+#include "util/mem_streambuf.h"
1114+
1115+#include "jsonml_array.h"
1116+#include "snelson.h"
1117+
1118+using namespace std;
1119+
1120+namespace zorba {
1121+
1122+///////////////////////////////////////////////////////////////////////////////
1123+
1124+typedef map<zstring,zstring> options_type;
1125+
1126+static void get_options( store::Item_t const &options_element,
1127+ options_type *options ) {
1128+ ZORBA_ASSERT( options_element->getNodeKind() ==
1129+ store::StoreConsts::elementNode );
1130+ store::Iterator_t i = options_element->getChildren();
1131+ i->open();
1132+ store::Item_t option_item;
1133+ while ( i->next( option_item ) ) {
1134+ if ( option_item->getNodeKind() == store::StoreConsts::elementNode ) {
1135+ zstring const name( option_item->getNodeName()->getStringValue() );
1136+ zstring value;
1137+ get_attribute_value( option_item, "value", &value );
1138+ (*options)[ name ] = value;
1139+ }
1140+ }
1141+ i->close();
1142+}
1143+
1144+///////////////////////////////////////////////////////////////////////////////
1145+
1146+bool JSONParseInternal::nextImpl( store::Item_t& result,
1147+ PlanState &planState ) const {
1148+ store::Item_t cur_item;
1149+ options_type options;
1150+ istringstream iss;
1151+ mem_streambuf buf;
1152+
1153+ PlanIteratorState *state;
1154+ DEFAULT_STACK_INIT( PlanIteratorState, state, planState );
1155+
1156+ ZORBA_ASSERT( theChildren.size() == 2 );
1157+ ZORBA_ASSERT( consumeNext( cur_item, theChildren[1], planState ) );
1158+ get_options( cur_item, &options );
1159+
1160+ if ( consumeNext( cur_item, theChildren[0], planState ) ) {
1161+ istream *is;
1162+ if ( cur_item->isStreamable() ) {
1163+ is = &cur_item->getStream();
1164+ } else {
1165+ zstring s;
1166+ cur_item->getStringValue2( s );
1167+ // Doing it this way uses the string data in-place with no copy.
1168+ buf.set( s.data(), s.size() );
1169+ iss.ios::rdbuf( &buf );
1170+ is = &iss;
1171+ }
1172+
1173+ try {
1174+ json::parser p( *is );
1175+ p.set_loc(
1176+ loc.getFilename().c_str(), loc.getLineBegin(), loc.getColumnBegin()
1177+ );
1178+
1179+ options_type::mapped_type const &format = options[ "json-format" ];
1180+ ZORBA_ASSERT( !format.empty() );
1181+ if ( format == "Snelson" )
1182+ snelson::parse( p, &result );
1183+ else if ( format == "JsonML-array" )
1184+ jsonml_array::parse( p, &result );
1185+ else
1186+ ZORBA_ASSERT( false );
1187+ }
1188+ catch ( json::illegal_character const &e ) {
1189+ throw XQUERY_EXCEPTION(
1190+ zerr::ZJPE0001_ILLEGAL_CHARACTER,
1191+ ERROR_PARAMS( e.get_char() ),
1192+ ERROR_LOC( e.get_loc() )
1193+ );
1194+ }
1195+ catch ( json::illegal_codepoint const &e ) {
1196+ throw XQUERY_EXCEPTION(
1197+ zerr::ZJPE0002_ILLEGAL_CODEPOINT,
1198+ ERROR_PARAMS( e.get_codepoint() ),
1199+ ERROR_LOC( e.get_loc() )
1200+ );
1201+ }
1202+ catch ( json::illegal_escape const &e ) {
1203+ throw XQUERY_EXCEPTION(
1204+ zerr::ZJPE0003_ILLEGAL_ESCAPE,
1205+ ERROR_PARAMS( e.get_escape() ),
1206+ ERROR_LOC( e.get_loc() )
1207+ );
1208+ }
1209+ catch ( json::illegal_literal const &e ) {
1210+ throw XQUERY_EXCEPTION(
1211+ zerr::ZJPE0004_ILLEGAL_LITERAL,
1212+ ERROR_LOC( e.get_loc() )
1213+ );
1214+ }
1215+ catch ( json::illegal_number const &e ) {
1216+ throw XQUERY_EXCEPTION(
1217+ zerr::ZJPE0005_ILLEGAL_NUMBER,
1218+ ERROR_LOC( e.get_loc() )
1219+ );
1220+ }
1221+ catch ( json::unexpected_token const &e ) {
1222+ throw XQUERY_EXCEPTION(
1223+ zerr::ZJPE0006_UNEXPECTED_TOKEN,
1224+ ERROR_PARAMS( e.get_token() ),
1225+ ERROR_LOC( e.get_loc() )
1226+ );
1227+ }
1228+ catch ( json::unterminated_string const &e ) {
1229+ throw XQUERY_EXCEPTION(
1230+ zerr::ZJPE0007_UNTERMINATED_STRING,
1231+ ERROR_LOC( e.get_loc() )
1232+ );
1233+ }
1234+
1235+ STACK_PUSH( !!result, state );
1236+ } // if ( consumeNext( ...
1237+ STACK_END( state );
1238+}
1239+
1240+///////////////////////////////////////////////////////////////////////////////
1241+
1242+bool JSONSerializeInternal::nextImpl( store::Item_t& result,
1243+ PlanState &planState ) const {
1244+ store::Item_t cur_item;
1245+ options_type options;
1246+
1247+ PlanIteratorState *state;
1248+ DEFAULT_STACK_INIT( PlanIteratorState, state, planState );
1249+
1250+ ZORBA_ASSERT( theChildren.size() == 2 );
1251+ ZORBA_ASSERT( consumeNext( cur_item, theChildren[1], planState ) );
1252+ get_options( cur_item, &options );
1253+
1254+ if ( consumeNext( cur_item, theChildren[0], planState ) ) {
1255+ try {
1256+ options_type::mapped_type const &format_opt = options[ "json-format" ];
1257+ ZORBA_ASSERT( !format_opt.empty() );
1258+
1259+ whitespace::type ws;
1260+ options_type::mapped_type const &whitespace_opt = options[ "whitespace" ];
1261+ if ( whitespace_opt.empty() || whitespace_opt == "none" )
1262+ ws = whitespace::none;
1263+ else if ( whitespace_opt == "some" )
1264+ ws = whitespace::some;
1265+ else if ( whitespace_opt == "indent" )
1266+ ws = whitespace::indent;
1267+ else
1268+ ZORBA_ASSERT( false );
1269+
1270+ ostringstream oss;
1271+ switch ( cur_item->getNodeKind() ) {
1272+ case store::StoreConsts::documentNode:
1273+ case store::StoreConsts::elementNode:
1274+ if ( format_opt == "Snelson" )
1275+ snelson::serialize( oss, cur_item, ws );
1276+ else if ( format_opt == "JsonML-array" )
1277+ jsonml_array::serialize( oss, cur_item, ws );
1278+ else
1279+ ZORBA_ASSERT( false );
1280+ break;
1281+ default:
1282+ throw XQUERY_EXCEPTION(
1283+ zerr::ZJSE0001_NOT_DOCUMENT_OR_ELEMENT_NODE,
1284+ ERROR_LOC( loc )
1285+ );
1286+ }
1287+ // This string copying is inefficient, but I can't see another way.
1288+ zstring temp( oss.str() );
1289+ GENV_ITEMFACTORY->createString( result, temp );
1290+ }
1291+ catch ( ZorbaException &e ) {
1292+ set_source( e, loc );
1293+ throw;
1294+ }
1295+ } // if ( consumeNext( ...
1296+ STACK_PUSH( !!result, state );
1297+ STACK_END( state );
1298+}
1299+
1300+///////////////////////////////////////////////////////////////////////////////
1301+
1302+} // namespace zorba
1303+/* vim:set et sw=2 ts=2: */
1304
1305=== added file 'src/runtime/json/jsonml_array.cpp'
1306--- src/runtime/json/jsonml_array.cpp 1970-01-01 00:00:00 +0000
1307+++ src/runtime/json/jsonml_array.cpp 2012-01-23 00:53:24 +0000
1308@@ -0,0 +1,281 @@
1309+/*
1310+ * Copyright 2006-2011 The FLWOR Foundation.
1311+ *
1312+ * Licensed under the Apache License, Version 2.0 (the "License");
1313+ * you may not use this file except in compliance with the License.
1314+ * You may obtain a copy of the License at
1315+ *
1316+ * http://www.apache.org/licenses/LICENSE-2.0
1317+ *
1318+ * Unless required by applicable law or agreed to in writing, software
1319+ * distributed under the License is distributed on an "AS IS" BASIS,
1320+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321+ * See the License for the specific language governing permissions and
1322+ * limitations under the License.
1323+ */
1324+#include "stdafx.h"
1325+
1326+#include <sstream>
1327+
1328+#include <zorba/diagnostic_list.h>
1329+
1330+#include "runtime/json/json.h"
1331+#include "store/api/item_factory.h"
1332+#include "system/globalenv.h"
1333+#include "types/root_typemanager.h"
1334+#include "util/ascii_util.h"
1335+#include "util/cxx_util.h"
1336+#include "util/json_parser.h"
1337+#include "util/mem_streambuf.h"
1338+#include "util/omanip.h"
1339+#include "util/oseparator.h"
1340+#include "util/stl_util.h"
1341+
1342+#include "jsonml_array.h"
1343+
1344+using namespace std;
1345+
1346+namespace zorba {
1347+
1348+///////////////////////////////////////////////////////////////////////////////
1349+
1350+static void split_name( zstring const &name, zstring *prefix, zstring *local ) {
1351+ zstring::size_type const colon = name.find( ':' );
1352+ if ( colon != zstring::npos ) {
1353+ *prefix = name.substr( 0, colon );
1354+ *local = name.substr( colon + 1 );
1355+ if ( prefix->empty() || local->empty() )
1356+ throw XQUERY_EXCEPTION(
1357+ zerr::ZJPE0008_ILLEGAL_QNAME,
1358+ ERROR_PARAMS( name )
1359+ );
1360+ } else {
1361+ prefix->clear();
1362+ *local = name;
1363+ }
1364+}
1365+
1366+namespace expect {
1367+ enum type {
1368+ none,
1369+ element_name,
1370+ attribute_name,
1371+ attribute_value
1372+ };
1373+}
1374+
1375+///////////////////////////////////////////////////////////////////////////////
1376+
1377+namespace jsonml_array {
1378+
1379+void parse( json::parser &p, store::Item_t *result ) {
1380+ ZORBA_ASSERT( result );
1381+
1382+ state_stack_type state_stack;
1383+
1384+ store::Item_t cur_item, junk_item, value_item;
1385+ store::Item_t att_name, element_name, type_name;
1386+
1387+ zstring base_uri;
1388+ item_stack_type item_stack;
1389+ expect::type expect_what = expect::none;
1390+ store::NsBindings ns_bindings;
1391+ zstring value;
1392+
1393+ json::token token;
1394+ while ( p.next( &token ) ) {
1395+ switch ( token.get_type() ) {
1396+
1397+ case '[':
1398+ PUSH_STATE( in_array );
1399+ expect_what = expect::element_name;
1400+ break;
1401+
1402+ case '{':
1403+ PUSH_STATE( in_object );
1404+ expect_what = expect::attribute_name;
1405+ break;
1406+
1407+ case ']':
1408+ POP_ITEM();
1409+ // no break;
1410+ case '}':
1411+ POP_STATE();
1412+ expect_what = expect::none;
1413+ break;
1414+
1415+ case ',':
1416+ expect_what = state_stack.top() == in_object ?
1417+ expect::attribute_name : expect::none;
1418+ break;
1419+
1420+ case ':':
1421+ expect_what = expect::attribute_value;
1422+ break;
1423+
1424+ case json::token::number:
1425+ case 'F':
1426+ case 'T':
1427+ case json::token::json_null:
1428+ case json::token::string: {
1429+ value = token.get_value();
1430+ zstring prefix, local;
1431+ switch ( expect_what ) {
1432+ case expect::element_name:
1433+ split_name( value, &prefix, &local );
1434+ GENV_ITEMFACTORY->createQName( element_name, "", prefix, local );
1435+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
1436+ GENV_ITEMFACTORY->createElementNode(
1437+ cur_item,
1438+ item_stack.empty() ? nullptr : item_stack.top(),
1439+ element_name, type_name, false, false, ns_bindings, base_uri
1440+ );
1441+ PUSH_ITEM( cur_item );
1442+ if ( !*result )
1443+ *result = cur_item;
1444+ break;
1445+ case expect::attribute_name:
1446+ split_name( value, &prefix, &local );
1447+ GENV_ITEMFACTORY->createQName( att_name, "", prefix, local );
1448+ break;
1449+ case expect::attribute_value:
1450+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
1451+ GENV_ITEMFACTORY->createString( value_item, value );
1452+ GENV_ITEMFACTORY->createAttributeNode(
1453+ junk_item, cur_item, att_name, type_name, value_item
1454+ );
1455+ break;
1456+ case expect::none:
1457+ GENV_ITEMFACTORY->createTextNode( junk_item, cur_item, value );
1458+ break;
1459+ }
1460+ break;
1461+ }
1462+
1463+ case json::token::none:
1464+ break;
1465+
1466+ default:
1467+ assert( false );
1468+ } // switch
1469+ } // while
1470+}
1471+
1472+} // namespace jsonml_array
1473+
1474+///////////////////////////////////////////////////////////////////////////////
1475+
1476+static ostream& serialize_attributes( ostream &o, store::Item_t const &element,
1477+ oseparator &sep, whitespace::type ws ) {
1478+ bool emitted_attributes = false;
1479+ oseparator att_sep;
1480+ switch ( ws ) {
1481+ case whitespace::none : att_sep.sep( "," ); break;
1482+ case whitespace::some : att_sep.sep( ", " ); break;
1483+ case whitespace::indent: att_sep.sep( ",\n" ); break;
1484+ }
1485+
1486+ store::Iterator_t i( element->getAttributes() );
1487+ i->open();
1488+ store::Item_t att_item;
1489+ while ( i->next( att_item ) ) {
1490+ zstring const att_name( att_item->getNodeName()->getStringValue() );
1491+ if ( att_name == "xmlns" )
1492+ continue;
1493+ if ( !emitted_attributes ) {
1494+ o << sep
1495+ << if_emit( ws == whitespace::indent, '\n' )
1496+ << if_indent( ws, indent ) << '{'
1497+ << if_indent( ws, inc_indent );
1498+ emitted_attributes = true;
1499+ }
1500+ bool const was_printing = att_sep.printing();
1501+ o << att_sep;
1502+ if ( was_printing )
1503+ o << if_indent( ws, indent );
1504+ else
1505+ o << if_emit( ws, ' ' );
1506+
1507+ o << '"' << att_name << '"'
1508+ << if_emit( ws, ' ' ) << ':' << if_emit( ws, ' ' )
1509+ << '"' << att_item->getStringValue() << '"';
1510+ }
1511+ i->close();
1512+ if ( emitted_attributes )
1513+ o << if_emit( ws, ' ' ) << '}' << if_indent( ws, dec_indent );
1514+ return o;
1515+}
1516+DEF_OMANIP3( serialize_attributes, store::Item_t const&, oseparator&,
1517+ whitespace::type )
1518+
1519+static ostream& serialize_children( ostream&, store::Item_t const &parent,
1520+ oseparator&, whitespace::type );
1521+DEF_OMANIP3( serialize_children, store::Item_t const&, oseparator&,
1522+ whitespace::type )
1523+
1524+static ostream& serialize_element( ostream &o, store::Item_t const &element,
1525+ oseparator &sep, whitespace::type ws ) {
1526+ if ( sep.printing() )
1527+ o << if_emit( ws == whitespace::indent, '\n' );
1528+ sep.printing( true );
1529+ o << if_indent( ws, indent ) << '[' << if_emit( ws, ' ' )
1530+ << '"' << element->getNodeName()->getStringValue() << '"'
1531+ << if_indent( ws, inc_indent )
1532+ << serialize_attributes( element, sep, ws )
1533+ << serialize_children( element, sep, ws )
1534+ << if_emit( ws, ' ' ) << ']'
1535+ << if_indent( ws, dec_indent );
1536+ return o;
1537+}
1538+DEF_OMANIP3( serialize_element, store::Item_t const&, oseparator&,
1539+ whitespace::type )
1540+
1541+static ostream& serialize_children( ostream &o, store::Item_t const &parent,
1542+ oseparator &sep, whitespace::type ws ) {
1543+ store::Iterator_t i( parent->getChildren() );
1544+ i->open();
1545+ store::Item_t child;
1546+ while ( i->next( child ) ) {
1547+ switch ( child->getNodeKind() ) {
1548+ case store::StoreConsts::elementNode:
1549+ o << sep << serialize_element( child, sep, ws );
1550+ break;
1551+ case store::StoreConsts::textNode:
1552+ o << sep << '"' << child->getStringValue() << '"';
1553+ break;
1554+ default:
1555+ break;
1556+ }
1557+ }
1558+ i->close();
1559+ return o;
1560+}
1561+
1562+///////////////////////////////////////////////////////////////////////////////
1563+
1564+namespace jsonml_array {
1565+
1566+void serialize( ostream &o, store::Item_t const &item, whitespace::type ws ) {
1567+ oseparator sep;
1568+ if ( ws )
1569+ sep.sep( ", " );
1570+ else
1571+ sep.sep( "," );
1572+ switch ( item->getNodeKind() ) {
1573+ case store::StoreConsts::documentNode:
1574+ o << serialize_children( item, sep, ws );
1575+ break;
1576+ case store::StoreConsts::elementNode:
1577+ o << serialize_element( item, sep, ws );
1578+ break;
1579+ default:
1580+ throw XQUERY_EXCEPTION( zerr::ZJSE0001_NOT_DOCUMENT_OR_ELEMENT_NODE );
1581+ }
1582+}
1583+
1584+} // namespace jsonml_array
1585+
1586+///////////////////////////////////////////////////////////////////////////////
1587+
1588+} // namespace zorba
1589+/* vim:set et sw=2 ts=2: */
1590
1591=== added file 'src/runtime/json/jsonml_array.h'
1592--- src/runtime/json/jsonml_array.h 1970-01-01 00:00:00 +0000
1593+++ src/runtime/json/jsonml_array.h 2012-01-23 00:53:24 +0000
1594@@ -0,0 +1,41 @@
1595+/*
1596+ * Copyright 2006-2011 The FLWOR Foundation.
1597+ *
1598+ * Licensed under the Apache License, Version 2.0 (the "License");
1599+ * you may not use this file except in compliance with the License.
1600+ * You may obtain a copy of the License at
1601+ *
1602+ * http://www.apache.org/licenses/LICENSE-2.0
1603+ *
1604+ * Unless required by applicable law or agreed to in writing, software
1605+ * distributed under the License is distributed on an "AS IS" BASIS,
1606+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1607+ * See the License for the specific language governing permissions and
1608+ * limitations under the License.
1609+ */
1610+#include "stdafx.h"
1611+
1612+#ifndef ZORBA_RUNTIME_JSON_JSONML_ARRAY_H
1613+#define ZORBA_RUNTIME_JSON_JSONML_ARRAY_H
1614+
1615+#include <iostream>
1616+
1617+#include "store/api/item.h"
1618+#include "util/json_parser.h"
1619+
1620+#include "common.h"
1621+
1622+namespace zorba {
1623+namespace jsonml_array {
1624+
1625+///////////////////////////////////////////////////////////////////////////////
1626+
1627+void parse( json::parser &p, store::Item_t *result );
1628+void serialize( std::ostream&, store::Item_t const &item, whitespace::type );
1629+
1630+///////////////////////////////////////////////////////////////////////////////
1631+
1632+} // namespace jsonml_array
1633+} // namespace zorba
1634+#endif /* ZORBA_RUNTIME_JSON_JSONML_ARRAY_H */
1635+/* vim:set et sw=2 ts=2: */
1636
1637=== added directory 'src/runtime/json/pregenerated'
1638=== added file 'src/runtime/json/pregenerated/json.cpp'
1639--- src/runtime/json/pregenerated/json.cpp 1970-01-01 00:00:00 +0000
1640+++ src/runtime/json/pregenerated/json.cpp 2012-01-23 00:53:24 +0000
1641@@ -0,0 +1,94 @@
1642+/*
1643+ * Copyright 2006-2008 The FLWOR Foundation.
1644+ *
1645+ * Licensed under the Apache License, Version 2.0 (the "License");
1646+ * you may not use this file except in compliance with the License.
1647+ * You may obtain a copy of the License at
1648+ *
1649+ * http://www.apache.org/licenses/LICENSE-2.0
1650+ *
1651+ * Unless required by applicable law or agreed to in writing, software
1652+ * distributed under the License is distributed on an "AS IS" BASIS,
1653+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1654+ * See the License for the specific language governing permissions and
1655+ * limitations under the License.
1656+ */
1657+
1658+// ******************************************
1659+// * *
1660+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
1661+// * SEE .xml FILE WITH SAME NAME *
1662+// * *
1663+// ******************************************
1664+
1665+#include "stdafx.h"
1666+#include "zorbatypes/rchandle.h"
1667+#include "zorbatypes/zstring.h"
1668+#include "runtime/visitors/planiter_visitor.h"
1669+#include "runtime/json/json.h"
1670+#include "system/globalenv.h"
1671+
1672+
1673+
1674+namespace zorba {
1675+
1676+// <JSONParseInternal>
1677+const char* JSONParseInternal::class_name_str = "JSONParseInternal";
1678+JSONParseInternal::class_factory<JSONParseInternal>
1679+JSONParseInternal::g_class_factory;
1680+
1681+const serialization::ClassVersion
1682+JSONParseInternal::class_versions[] ={{ 1, 0x000905, false}};
1683+
1684+const int JSONParseInternal::class_versions_count =
1685+sizeof(JSONParseInternal::class_versions)/sizeof(struct serialization::ClassVersion);
1686+
1687+void JSONParseInternal::accept(PlanIterVisitor& v) const {
1688+ v.beginVisit(*this);
1689+
1690+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
1691+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
1692+ for ( ; lIter != lEnd; ++lIter ){
1693+ (*lIter)->accept(v);
1694+ }
1695+
1696+ v.endVisit(*this);
1697+}
1698+
1699+JSONParseInternal::~JSONParseInternal() {}
1700+
1701+// </JSONParseInternal>
1702+
1703+
1704+// <JSONSerializeInternal>
1705+const char* JSONSerializeInternal::class_name_str = "JSONSerializeInternal";
1706+JSONSerializeInternal::class_factory<JSONSerializeInternal>
1707+JSONSerializeInternal::g_class_factory;
1708+
1709+const serialization::ClassVersion
1710+JSONSerializeInternal::class_versions[] ={{ 1, 0x000905, false}};
1711+
1712+const int JSONSerializeInternal::class_versions_count =
1713+sizeof(JSONSerializeInternal::class_versions)/sizeof(struct serialization::ClassVersion);
1714+
1715+void JSONSerializeInternal::accept(PlanIterVisitor& v) const {
1716+ v.beginVisit(*this);
1717+
1718+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
1719+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
1720+ for ( ; lIter != lEnd; ++lIter ){
1721+ (*lIter)->accept(v);
1722+ }
1723+
1724+ v.endVisit(*this);
1725+}
1726+
1727+JSONSerializeInternal::~JSONSerializeInternal() {}
1728+
1729+// </JSONSerializeInternal>
1730+
1731+
1732+
1733+}
1734+
1735+
1736
1737=== added file 'src/runtime/json/pregenerated/json.h'
1738--- src/runtime/json/pregenerated/json.h 1970-01-01 00:00:00 +0000
1739+++ src/runtime/json/pregenerated/json.h 2012-01-23 00:53:24 +0000
1740@@ -0,0 +1,114 @@
1741+/*
1742+ * Copyright 2006-2008 The FLWOR Foundation.
1743+ *
1744+ * Licensed under the Apache License, Version 2.0 (the "License");
1745+ * you may not use this file except in compliance with the License.
1746+ * You may obtain a copy of the License at
1747+ *
1748+ * http://www.apache.org/licenses/LICENSE-2.0
1749+ *
1750+ * Unless required by applicable law or agreed to in writing, software
1751+ * distributed under the License is distributed on an "AS IS" BASIS,
1752+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1753+ * See the License for the specific language governing permissions and
1754+ * limitations under the License.
1755+ */
1756+
1757+// ******************************************
1758+// * *
1759+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
1760+// * SEE .xml FILE WITH SAME NAME *
1761+// * *
1762+// ******************************************
1763+#ifndef ZORBA_RUNTIME_JSON_JSON_H
1764+#define ZORBA_RUNTIME_JSON_JSON_H
1765+
1766+
1767+#include "common/shared_types.h"
1768+
1769+
1770+
1771+#include "runtime/base/narybase.h"
1772+
1773+
1774+namespace zorba {
1775+
1776+/**
1777+ *
1778+ * function for parsing strings into json-xdm
1779+ *
1780+ * Author: Zorba Team
1781+ */
1782+class JSONParseInternal : public NaryBaseIterator<JSONParseInternal, PlanIteratorState>
1783+{
1784+public:
1785+ SERIALIZABLE_CLASS(JSONParseInternal);
1786+
1787+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(JSONParseInternal,
1788+ NaryBaseIterator<JSONParseInternal, PlanIteratorState>);
1789+
1790+ void serialize( ::zorba::serialization::Archiver& ar)
1791+ {
1792+ serialize_baseclass(ar,
1793+ (NaryBaseIterator<JSONParseInternal, PlanIteratorState>*)this);
1794+ }
1795+
1796+ JSONParseInternal(
1797+ static_context* sctx,
1798+ const QueryLoc& loc,
1799+ std::vector<PlanIter_t>& children)
1800+ :
1801+ NaryBaseIterator<JSONParseInternal, PlanIteratorState>(sctx, loc, children)
1802+ {}
1803+
1804+ virtual ~JSONParseInternal();
1805+
1806+ void accept(PlanIterVisitor& v) const;
1807+
1808+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
1809+};
1810+
1811+
1812+/**
1813+ *
1814+ * Function to serialize json/jsonml xdm to string
1815+ *
1816+ * Author: Zorba Team
1817+ */
1818+class JSONSerializeInternal : public NaryBaseIterator<JSONSerializeInternal, PlanIteratorState>
1819+{
1820+public:
1821+ SERIALIZABLE_CLASS(JSONSerializeInternal);
1822+
1823+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(JSONSerializeInternal,
1824+ NaryBaseIterator<JSONSerializeInternal, PlanIteratorState>);
1825+
1826+ void serialize( ::zorba::serialization::Archiver& ar)
1827+ {
1828+ serialize_baseclass(ar,
1829+ (NaryBaseIterator<JSONSerializeInternal, PlanIteratorState>*)this);
1830+ }
1831+
1832+ JSONSerializeInternal(
1833+ static_context* sctx,
1834+ const QueryLoc& loc,
1835+ std::vector<PlanIter_t>& children)
1836+ :
1837+ NaryBaseIterator<JSONSerializeInternal, PlanIteratorState>(sctx, loc, children)
1838+ {}
1839+
1840+ virtual ~JSONSerializeInternal();
1841+
1842+ void accept(PlanIterVisitor& v) const;
1843+
1844+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
1845+};
1846+
1847+
1848+}
1849+#endif
1850+/*
1851+ * Local variables:
1852+ * mode: c++
1853+ * End:
1854+ */
1855
1856=== added file 'src/runtime/json/snelson.cpp'
1857--- src/runtime/json/snelson.cpp 1970-01-01 00:00:00 +0000
1858+++ src/runtime/json/snelson.cpp 2012-01-23 00:53:24 +0000
1859@@ -0,0 +1,498 @@
1860+/*
1861+ * Copyright 2006-2011 The FLWOR Foundation.
1862+ *
1863+ * Licensed under the Apache License, Version 2.0 (the "License");
1864+ * you may not use this file except in compliance with the License.
1865+ * You may obtain a copy of the License at
1866+ *
1867+ * http://www.apache.org/licenses/LICENSE-2.0
1868+ *
1869+ * Unless required by applicable law or agreed to in writing, software
1870+ * distributed under the License is distributed on an "AS IS" BASIS,
1871+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1872+ * See the License for the specific language governing permissions and
1873+ * limitations under the License.
1874+ */
1875+#include "stdafx.h"
1876+
1877+#include <sstream>
1878+
1879+#include <zorba/diagnostic_list.h>
1880+
1881+#include "runtime/json/json.h"
1882+#include "store/api/item_factory.h"
1883+#include "system/globalenv.h"
1884+#include "types/root_typemanager.h"
1885+#include "util/ascii_util.h"
1886+#include "util/cxx_util.h"
1887+#include "util/indent.h"
1888+#include "util/json_parser.h"
1889+#include "util/mem_streambuf.h"
1890+#include "util/omanip.h"
1891+#include "util/oseparator.h"
1892+#include "util/stl_util.h"
1893+
1894+#include "snelson.h"
1895+
1896+#define SNELSON_NS "http://john.snelson.org.uk/parsing-json-into-xquery"
1897+
1898+using namespace std;
1899+
1900+namespace zorba {
1901+
1902+///////////////////////////////////////////////////////////////////////////////
1903+
1904+static void add_type_attribute( store::Item *parent, char const *value ) {
1905+ store::Item_t junk_item, att_name, type_name, value_item;
1906+ GENV_ITEMFACTORY->createQName( att_name, "", "", "type" );
1907+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
1908+ zstring value_string( value );
1909+ GENV_ITEMFACTORY->createString( value_item, value_string );
1910+ GENV_ITEMFACTORY->createAttributeNode(
1911+ junk_item, parent, att_name, type_name, value_item
1912+ );
1913+}
1914+
1915+#define ADD_TYPE_ATTRIBUTE(T) \
1916+ do { \
1917+ if ( needs_type_attribute ) { \
1918+ add_type_attribute( cur_item, T ); \
1919+ needs_type_attribute = false; \
1920+ } \
1921+ } while (0)
1922+
1923+static void add_item_element( item_stack_type &item_stack,
1924+ state_stack_type &state_stack,
1925+ store::Item_t &cur_item,
1926+ char const *type ) {
1927+ if ( !state_stack.empty() && state_stack.top() == in_array ) {
1928+ store::Item_t element_name, type_name;
1929+ zstring base_uri;
1930+ store::NsBindings ns_bindings;
1931+ GENV_ITEMFACTORY->createQName( element_name, SNELSON_NS, "", "item" );
1932+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
1933+ GENV_ITEMFACTORY->createElementNode(
1934+ cur_item, item_stack.top(),
1935+ element_name, type_name, false, false, ns_bindings, base_uri
1936+ );
1937+ add_type_attribute( cur_item.getp(), type );
1938+ }
1939+}
1940+
1941+#define ADD_ITEM_ELEMENT(T) \
1942+ add_item_element( item_stack, state_stack, cur_item, T );
1943+
1944+static void escape_json_chars( zstring *s ) {
1945+ ascii::replace_all( *s, "\"", 1, "\\\"", 2 );
1946+ ascii::replace_all( *s, "\\", 1, "\\\\", 2 );
1947+ ascii::replace_all( *s, "\b", 1, "\\b", 2 );
1948+ ascii::replace_all( *s, "\f", 1, "\\f", 2 );
1949+ ascii::replace_all( *s, "\n", 1, "\\n", 2 );
1950+ ascii::replace_all( *s, "\r", 1, "\\r", 2 );
1951+ ascii::replace_all( *s, "\t", 1, "\\t", 2 );
1952+}
1953+
1954+///////////////////////////////////////////////////////////////////////////////
1955+
1956+namespace snelson {
1957+
1958+void parse( json::parser &p, store::Item_t *result ) {
1959+ ZORBA_ASSERT( result );
1960+
1961+ state_stack_type state_stack;
1962+
1963+ store::Item_t cur_item, junk_item, value_item;
1964+ store::Item_t att_name, element_name, type_name;
1965+
1966+ zstring base_uri;
1967+ item_stack_type item_stack;
1968+ bool needs_type_attribute = false;
1969+ bool next_string_is_key = false;
1970+ store::NsBindings ns_bindings;
1971+ zstring value;
1972+
1973+ json::token token;
1974+ while ( p.next( &token ) ) {
1975+ if ( !*result ) {
1976+ GENV_ITEMFACTORY->createQName( element_name, SNELSON_NS, "", "json" );
1977+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
1978+ GENV_ITEMFACTORY->createElementNode(
1979+ cur_item, nullptr,
1980+ element_name, type_name, false, false, ns_bindings, base_uri
1981+ );
1982+ *result = cur_item;
1983+ needs_type_attribute = true;
1984+ }
1985+
1986+ switch ( token.get_type() ) {
1987+
1988+ case '[':
1989+ PUSH_ITEM( cur_item );
1990+ ADD_TYPE_ATTRIBUTE( "array" );
1991+ ADD_ITEM_ELEMENT( "array" );
1992+ PUSH_STATE( in_array );
1993+ break;
1994+
1995+ case '{':
1996+ PUSH_ITEM( cur_item );
1997+ ADD_TYPE_ATTRIBUTE( "object" );
1998+ ADD_ITEM_ELEMENT( "object" );
1999+ PUSH_STATE( in_object );
2000+ next_string_is_key = true;
2001+ break;
2002+
2003+ case ']':
2004+ case '}':
2005+ POP_ITEM();
2006+ POP_STATE();
2007+ break;
2008+
2009+ case ',':
2010+ next_string_is_key = (state_stack.top() == in_object);
2011+ break;
2012+
2013+ case json::token::number:
2014+ ADD_TYPE_ATTRIBUTE( "number" );
2015+ ADD_ITEM_ELEMENT( "number" );
2016+ value = token.get_value();
2017+ GENV_ITEMFACTORY->createTextNode( junk_item, cur_item, value );
2018+ break;
2019+
2020+ case json::token::string:
2021+ ADD_TYPE_ATTRIBUTE( "string" );
2022+ value = token.get_value();
2023+#if 0
2024+ escape_json_chars( &value );
2025+#endif
2026+
2027+ if ( next_string_is_key ) {
2028+ // <pair name="..." ...>
2029+ GENV_ITEMFACTORY->createQName( element_name, SNELSON_NS, "", "pair" );
2030+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
2031+ GENV_ITEMFACTORY->createElementNode(
2032+ cur_item, item_stack.top(),
2033+ element_name, type_name, false, false, ns_bindings, base_uri
2034+ );
2035+
2036+ GENV_ITEMFACTORY->createQName( att_name, "", "", "name" );
2037+ type_name = GENV_TYPESYSTEM.XS_UNTYPED_QNAME;
2038+ GENV_ITEMFACTORY->createString( value_item, value );
2039+ GENV_ITEMFACTORY->createAttributeNode(
2040+ junk_item, cur_item, att_name, type_name, value_item
2041+ );
2042+
2043+ needs_type_attribute = true;
2044+ next_string_is_key = false;
2045+ } else {
2046+ ADD_ITEM_ELEMENT( "string" );
2047+ GENV_ITEMFACTORY->createTextNode( junk_item, cur_item, value );
2048+ }
2049+ break;
2050+
2051+ case 'F':
2052+ case 'T':
2053+ ADD_TYPE_ATTRIBUTE( "boolean" );
2054+ ADD_ITEM_ELEMENT( "boolean" );
2055+ value = token.get_type() == 'F' ? "false" : "true";
2056+ GENV_ITEMFACTORY->createTextNode( junk_item, cur_item, value );
2057+ break;
2058+
2059+ case json::token::json_null:
2060+ ADD_TYPE_ATTRIBUTE( "null" );
2061+ ADD_ITEM_ELEMENT( "null" );
2062+ break;
2063+
2064+ case ':':
2065+ case json::token::none:
2066+ break;
2067+
2068+ default:
2069+ assert( false );
2070+ } // switch
2071+ } // while
2072+}
2073+
2074+} // namespace snelson
2075+
2076+///////////////////////////////////////////////////////////////////////////////
2077+
2078+static void assert_json_type( json::type t, zstring const &s ) {
2079+ // Doing it this way uses the string data in-place with no copy.
2080+ mem_streambuf::char_type *const p =
2081+ const_cast<mem_streambuf::char_type*>( s.data() );
2082+ mem_streambuf buf( p, s.size() );
2083+ istringstream iss;
2084+ iss.ios::rdbuf( &buf );
2085+
2086+ json::lexer lex( iss );
2087+ json::token token;
2088+ try {
2089+ if ( lex.next( &token ) && json::map_type( token.get_type() ) == t )
2090+ return;
2091+ }
2092+ catch ( json::exception const& ) {
2093+ // do nothing
2094+ }
2095+ throw XQUERY_EXCEPTION(
2096+ zerr::ZJSE0008_BAD_VALUE,
2097+ ERROR_PARAMS( s, t )
2098+ );
2099+}
2100+
2101+static void require_attribute_value( store::Item_t const &element,
2102+ char const *att_name,
2103+ zstring *att_value ) {
2104+ if ( !get_attribute_value( element, att_name, att_value ) )
2105+ throw XQUERY_EXCEPTION(
2106+ zerr::ZJSE0002_ELEMENT_MISSING_ATTRIBUTE,
2107+ ERROR_PARAMS( element->getNodeName()->getStringValue(), att_name )
2108+ );
2109+}
2110+
2111+static json::type get_json_type( store::Item_t const &element,
2112+ bool allow_all_types = true ) {
2113+ zstring att_value;
2114+ require_attribute_value( element, "type", &att_value );
2115+ if ( att_value == "array" )
2116+ return json::array;
2117+ if ( att_value == "object" )
2118+ return json::object;
2119+ if ( allow_all_types ) {
2120+ if ( att_value == "boolean" )
2121+ return json::boolean;
2122+ if ( att_value == "null" )
2123+ return json::null;
2124+ if ( att_value == "number" )
2125+ return json::number;
2126+ if ( att_value == "string" )
2127+ return json::string;
2128+ }
2129+ throw XQUERY_EXCEPTION(
2130+ zerr::ZJSE0003_BAD_ATTRIBUTE_VALUE,
2131+ ERROR_PARAMS( att_value, "type" )
2132+ );
2133+}
2134+
2135+inline std::ostream& if_space_or_newline( std::ostream &o,
2136+ whitespace::type ws ) {
2137+ if ( ws == whitespace::some )
2138+ o << ' ';
2139+ else
2140+ o << if_emit( ws == whitespace::indent, '\n' );
2141+ return o;
2142+}
2143+DEF_OMANIP1( if_space_or_newline, whitespace::type )
2144+
2145+static ostream& serialize_begin( ostream &o, json::type t,
2146+ whitespace::type ws ) {
2147+ switch ( t ) {
2148+ case json::array :
2149+ o << '[' << if_emit( ws, ' ' );
2150+ break;
2151+ case json::object:
2152+ o << '{' << if_space_or_newline( ws ) << if_indent( ws, inc_indent );
2153+ break;
2154+ default:
2155+ /* suppress warning */;
2156+ }
2157+ return o;
2158+}
2159+DEF_OMANIP2( serialize_begin, json::type, whitespace::type )
2160+
2161+static ostream& serialize_end( ostream &o, json::type t, whitespace::type ws ) {
2162+ switch ( t ) {
2163+ case json::array:
2164+ o << if_emit( ws, ' ' ) << ']';
2165+ break;
2166+ case json::object:
2167+ o << if_space_or_newline( ws ) << if_indent( ws, dec_indent )
2168+ << if_indent( ws, indent ) << '}';
2169+ break;
2170+ default:
2171+ /* suppress warning */;
2172+ }
2173+ return o;
2174+}
2175+DEF_OMANIP2( serialize_end, json::type, whitespace::type )
2176+
2177+static ostream& serialize_boolean( ostream &o, zstring const &s ) {
2178+ assert_json_type( json::boolean, s );
2179+ return o << s;
2180+}
2181+DEF_OMANIP1( serialize_boolean, zstring const& )
2182+
2183+static ostream& serialize_number( ostream &o, zstring const &s ) {
2184+ assert_json_type( json::number, s );
2185+ return o << s;
2186+}
2187+DEF_OMANIP1( serialize_number, zstring const& )
2188+
2189+static ostream& serialize_string( ostream &o, zstring const &s ) {
2190+ zstring temp( s );
2191+ escape_json_chars( &temp );
2192+ temp.insert( (zstring::size_type)0, 1, '"' );
2193+ temp.append( 1, '"' );
2194+ assert_json_type( json::string, temp );
2195+ return o << temp;
2196+}
2197+DEF_OMANIP1( serialize_string, zstring const& )
2198+
2199+static ostream& serialize_children( ostream&, store::Item_t const&, json::type,
2200+ whitespace::type );
2201+DEF_OMANIP3( serialize_children, store::Item_t const&, json::type,
2202+ whitespace::type )
2203+
2204+static ostream& serialize_json_element( ostream &o,
2205+ store::Item_t const &element,
2206+ whitespace::type ws ) {
2207+ zstring const element_name( element->getNodeName()->getStringValue() );
2208+ if ( element_name != "json" )
2209+ throw XQUERY_EXCEPTION(
2210+ zerr::ZJSE0004_BAD_ELEMENT,
2211+ ERROR_PARAMS( element_name, "json" )
2212+ );
2213+
2214+ json::type const t = get_json_type( element, false );
2215+
2216+ return o
2217+ << serialize_begin( t, ws )
2218+ << serialize_children( element, t, ws )
2219+ << serialize_end( t, ws );
2220+}
2221+DEF_OMANIP2( serialize_json_element, store::Item_t const&, whitespace::type )
2222+
2223+static ostream& serialize_item_element( ostream &o,
2224+ store::Item_t const &element,
2225+ whitespace::type ws ) {
2226+ zstring const element_name( element->getNodeName()->getStringValue() );
2227+ if ( element_name != "item" )
2228+ throw XQUERY_EXCEPTION(
2229+ zerr::ZJSE0005_BAD_CHILD_ELEMENT,
2230+ ERROR_PARAMS( element_name, "array", "item" )
2231+ );
2232+
2233+ json::type const t = get_json_type( element );
2234+
2235+ return o
2236+ << serialize_begin( t, ws )
2237+ << serialize_children( element, t, ws )
2238+ << serialize_end( t, ws );
2239+}
2240+DEF_OMANIP2( serialize_item_element, store::Item_t const&, whitespace::type )
2241+
2242+static ostream& serialize_pair_element( ostream &o,
2243+ store::Item_t const &element,
2244+ whitespace::type ws ) {
2245+ zstring const element_name( element->getNodeName()->getStringValue() );
2246+ if ( element_name != "pair" )
2247+ throw XQUERY_EXCEPTION(
2248+ zerr::ZJSE0005_BAD_CHILD_ELEMENT,
2249+ ERROR_PARAMS( element_name, "object", "pair" )
2250+ );
2251+
2252+ zstring name_att_value;
2253+ require_attribute_value( element, "name", &name_att_value );
2254+ json::type const t = get_json_type( element );
2255+
2256+ return o
2257+ << if_indent( ws, indent ) << serialize_string( name_att_value )
2258+ << if_emit( ws, ' ' ) << ':' << if_emit( ws, ' ' )
2259+ << serialize_begin( t, ws )
2260+ << serialize_children( element, t, ws )
2261+ << serialize_end( t, ws );
2262+}
2263+DEF_OMANIP2( serialize_pair_element, store::Item_t const&, whitespace::type )
2264+
2265+static ostream& serialize_children( ostream &o, store::Item_t const &parent,
2266+ json::type parent_type,
2267+ whitespace::type ws ) {
2268+ if ( parent_type == json::null )
2269+ o << "null";
2270+ else {
2271+ oseparator sep;
2272+ if ( ws == whitespace::none )
2273+ sep.sep( "," );
2274+ else if ( ws == whitespace::some || parent_type == json::array )
2275+ sep.sep( ", " );
2276+ else
2277+ sep.sep( ",\n" );
2278+
2279+ store::Iterator_t i = parent->getChildren();
2280+ i->open();
2281+ store::Item_t child;
2282+ while ( i->next( child ) ) {
2283+ o << sep;
2284+
2285+ switch ( child->getNodeKind() ) {
2286+
2287+ case store::StoreConsts::elementNode:
2288+ switch ( parent_type ) {
2289+ case json::none:
2290+ o << serialize_json_element( child, ws );
2291+ break;
2292+ case json::array:
2293+ o << serialize_item_element( child, ws );
2294+ break;
2295+ case json::object:
2296+ o << serialize_pair_element( child, ws );
2297+ break;
2298+ default:
2299+ throw XQUERY_EXCEPTION(
2300+ zerr::ZJSE0006_NO_ELEMENT_CHILD,
2301+ ERROR_PARAMS( json::type_string_of[ parent_type ] )
2302+ );
2303+ }
2304+ break;
2305+
2306+ case store::StoreConsts::textNode:
2307+ switch ( parent_type ) {
2308+ case json::boolean:
2309+ o << serialize_boolean( child->getStringValue() );
2310+ break;
2311+ case json::number:
2312+ o << serialize_number( child->getStringValue() );
2313+ break;
2314+ case json::string:
2315+ o << serialize_string( child->getStringValue() );
2316+ break;
2317+ default:
2318+ throw XQUERY_EXCEPTION(
2319+ zerr::ZJSE0007_NO_TEXT_CHILD,
2320+ ERROR_PARAMS( json::type_string_of[ parent_type ] )
2321+ );
2322+ }
2323+ break;
2324+
2325+ default:
2326+ // do nothing
2327+ break;
2328+ } // switch
2329+ } // while
2330+ i->close();
2331+ }
2332+ return o;
2333+}
2334+
2335+///////////////////////////////////////////////////////////////////////////////
2336+
2337+namespace snelson {
2338+
2339+void serialize( ostream &o, store::Item_t const &item, whitespace::type ws ) {
2340+ switch ( item->getNodeKind() ) {
2341+ case store::StoreConsts::documentNode:
2342+ o << serialize_children( item, json::none, ws );
2343+ break;
2344+ case store::StoreConsts::elementNode:
2345+ o << serialize_json_element( item, ws );
2346+ break;
2347+ default:
2348+ throw XQUERY_EXCEPTION( zerr::ZJSE0001_NOT_DOCUMENT_OR_ELEMENT_NODE );
2349+ }
2350+}
2351+
2352+} // namespace snelson
2353+
2354+///////////////////////////////////////////////////////////////////////////////
2355+
2356+} // namespace zorba
2357+/* vim:set et sw=2 ts=2: */
2358
2359=== added file 'src/runtime/json/snelson.h'
2360--- src/runtime/json/snelson.h 1970-01-01 00:00:00 +0000
2361+++ src/runtime/json/snelson.h 2012-01-23 00:53:24 +0000
2362@@ -0,0 +1,41 @@
2363+/*
2364+ * Copyright 2006-2011 The FLWOR Foundation.
2365+ *
2366+ * Licensed under the Apache License, Version 2.0 (the "License");
2367+ * you may not use this file except in compliance with the License.
2368+ * You may obtain a copy of the License at
2369+ *
2370+ * http://www.apache.org/licenses/LICENSE-2.0
2371+ *
2372+ * Unless required by applicable law or agreed to in writing, software
2373+ * distributed under the License is distributed on an "AS IS" BASIS,
2374+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2375+ * See the License for the specific language governing permissions and
2376+ * limitations under the License.
2377+ */
2378+#include "stdafx.h"
2379+
2380+#ifndef ZORBA_RUNTIME_JSON_SNELSON_H
2381+#define ZORBA_RUNTIME_JSON_SNELSON_H
2382+
2383+#include <iostream>
2384+
2385+#include "store/api/item.h"
2386+#include "util/json_parser.h"
2387+
2388+#include "common.h"
2389+
2390+namespace zorba {
2391+namespace snelson {
2392+
2393+///////////////////////////////////////////////////////////////////////////////
2394+
2395+void parse( json::parser &p, store::Item_t *result );
2396+void serialize( std::ostream&, store::Item_t const &item, whitespace::type );
2397+
2398+///////////////////////////////////////////////////////////////////////////////
2399+
2400+} // namespace snelson
2401+} // namespace zorba
2402+#endif /* ZORBA_RUNTIME_JSON_SNELSON_H */
2403+/* vim:set et sw=2 ts=2: */
2404
2405=== added directory 'src/runtime/spec/json'
2406=== added file 'src/runtime/spec/json/json.xml'
2407--- src/runtime/spec/json/json.xml 1970-01-01 00:00:00 +0000
2408+++ src/runtime/spec/json/json.xml 2012-01-23 00:53:24 +0000
2409@@ -0,0 +1,52 @@
2410+<?xml version="1.0" encoding="UTF-8"?>
2411+
2412+<!--
2413+////////////////////////////////////////////////////////////////////////////////
2414+////////////////////////////////////////////////////////////////////////////////
2415+-->
2416+<zorba:iterators
2417+ xmlns:zorba="http://www.zorba-xquery.com"
2418+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2419+ xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd">
2420+
2421+<!--
2422+/*******************************************************************************
2423+*******************************************************************************/
2424+-->
2425+<zorba:iterator name="JSONParseInternal" arity="nary">
2426+
2427+ <zorba:description author="Zorba Team">
2428+ function for parsing strings into json-xdm
2429+ </zorba:description>
2430+
2431+ <zorba:function isDeterministic="true">
2432+ <zorba:signature localname="parse-internal" prefix="fn-zorba-json">
2433+ <zorba:param>xs:string</zorba:param>
2434+ <zorba:param>item()?</zorba:param>
2435+ <zorba:output>element()*</zorba:output>
2436+ </zorba:signature>
2437+ </zorba:function>
2438+
2439+</zorba:iterator>
2440+
2441+<!--
2442+/*******************************************************************************
2443+*******************************************************************************/
2444+-->
2445+<zorba:iterator name="JSONSerializeInternal" arity="nary">
2446+
2447+ <zorba:description author="Zorba Team">
2448+ Function to serialize json/jsonml xdm to string
2449+ </zorba:description>
2450+
2451+ <zorba:function isDeterministic="true">
2452+ <zorba:signature localname="serialize-internal" prefix="fn-zorba-json">
2453+ <zorba:param>item()*</zorba:param>
2454+ <zorba:param>item()?</zorba:param>
2455+ <zorba:output>xs:string</zorba:output>
2456+ </zorba:signature>
2457+ </zorba:function>
2458+
2459+</zorba:iterator>
2460+
2461+</zorba:iterators>
2462
2463=== modified file 'src/runtime/spec/mappings.xml'
2464--- src/runtime/spec/mappings.xml 2011-10-14 07:35:51 +0000
2465+++ src/runtime/spec/mappings.xml 2012-01-23 00:53:24 +0000
2466@@ -106,6 +106,10 @@
2467 define="ZORBA_STRING_FN_NS"
2468 prefix="fn-zorba-string"/>
2469
2470+ <zorba:namespace uri="http://www.zorba-xquery.com/modules/converters/json"
2471+ define="ZORBA_JSON_FN_NS"
2472+ prefix="fn-zorba-json"/>
2473+
2474 <zorba:namespace uri="http://www.zorba-xquery.com/modules/fetch"
2475 define="ZORBA_FETCH_FN_NS"
2476 prefix="fn-zorba-fetch"/>
2477
2478=== modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h'
2479--- src/runtime/visitors/pregenerated/planiter_visitor.h 2012-01-11 17:30:25 +0000
2480+++ src/runtime/visitors/pregenerated/planiter_visitor.h 2012-01-23 00:53:24 +0000
2481@@ -251,6 +251,10 @@
2482
2483 class FunctionAnnotationsIterator;
2484
2485+ class JSONParseInternal;
2486+
2487+ class JSONSerializeInternal;
2488+
2489 class SqrtIterator;
2490
2491 class ExpIterator;
2492@@ -929,6 +933,12 @@
2493 virtual void beginVisit ( const FunctionAnnotationsIterator& ) = 0;
2494 virtual void endVisit ( const FunctionAnnotationsIterator& ) = 0;
2495
2496+ virtual void beginVisit ( const JSONParseInternal& ) = 0;
2497+ virtual void endVisit ( const JSONParseInternal& ) = 0;
2498+
2499+ virtual void beginVisit ( const JSONSerializeInternal& ) = 0;
2500+ virtual void endVisit ( const JSONSerializeInternal& ) = 0;
2501+
2502 virtual void beginVisit ( const SqrtIterator& ) = 0;
2503 virtual void endVisit ( const SqrtIterator& ) = 0;
2504
2505
2506=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp'
2507--- src/runtime/visitors/pregenerated/printer_visitor.cpp 2012-01-11 17:30:25 +0000
2508+++ src/runtime/visitors/pregenerated/printer_visitor.cpp 2012-01-23 00:53:24 +0000
2509@@ -50,6 +50,7 @@
2510 #include "runtime/function_item/function_item_iter.h"
2511 #include "runtime/indexing/ic_ddl.h"
2512 #include "runtime/introspection/sctx.h"
2513+#include "runtime/json/json.h"
2514 #include "runtime/maths/maths.h"
2515 #include "runtime/nodes/node_position.h"
2516 #include "runtime/nodes/nodes.h"
2517@@ -1650,6 +1651,34 @@
2518 // </FunctionAnnotationsIterator>
2519
2520
2521+// <JSONParseInternal>
2522+void PrinterVisitor::beginVisit ( const JSONParseInternal& a) {
2523+ thePrinter.startBeginVisit("JSONParseInternal", ++theId);
2524+ printCommons( &a, theId );
2525+ thePrinter.endBeginVisit( theId );
2526+}
2527+
2528+void PrinterVisitor::endVisit ( const JSONParseInternal& ) {
2529+ thePrinter.startEndVisit();
2530+ thePrinter.endEndVisit();
2531+}
2532+// </JSONParseInternal>
2533+
2534+
2535+// <JSONSerializeInternal>
2536+void PrinterVisitor::beginVisit ( const JSONSerializeInternal& a) {
2537+ thePrinter.startBeginVisit("JSONSerializeInternal", ++theId);
2538+ printCommons( &a, theId );
2539+ thePrinter.endBeginVisit( theId );
2540+}
2541+
2542+void PrinterVisitor::endVisit ( const JSONSerializeInternal& ) {
2543+ thePrinter.startEndVisit();
2544+ thePrinter.endEndVisit();
2545+}
2546+// </JSONSerializeInternal>
2547+
2548+
2549 // <SqrtIterator>
2550 void PrinterVisitor::beginVisit ( const SqrtIterator& a) {
2551 thePrinter.startBeginVisit("SqrtIterator", ++theId);
2552
2553=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.h'
2554--- src/runtime/visitors/pregenerated/printer_visitor.h 2012-01-11 17:30:25 +0000
2555+++ src/runtime/visitors/pregenerated/printer_visitor.h 2012-01-23 00:53:24 +0000
2556@@ -379,6 +379,12 @@
2557 void beginVisit( const FunctionAnnotationsIterator& );
2558 void endVisit ( const FunctionAnnotationsIterator& );
2559
2560+ void beginVisit( const JSONParseInternal& );
2561+ void endVisit ( const JSONParseInternal& );
2562+
2563+ void beginVisit( const JSONSerializeInternal& );
2564+ void endVisit ( const JSONSerializeInternal& );
2565+
2566 void beginVisit( const SqrtIterator& );
2567 void endVisit ( const SqrtIterator& );
2568
2569
2570=== modified file 'src/unit_tests/CMakeLists.txt'
2571--- src/unit_tests/CMakeLists.txt 2011-12-21 14:40:33 +0000
2572+++ src/unit_tests/CMakeLists.txt 2012-01-23 00:53:24 +0000
2573@@ -16,4 +16,5 @@
2574 SET(UNIT_TEST_SRCS
2575 unit_tests.cpp
2576 test_uri.cpp
2577+ json_parser.cpp
2578 )
2579
2580=== added file 'src/unit_tests/json_parser.cpp'
2581--- src/unit_tests/json_parser.cpp 1970-01-01 00:00:00 +0000
2582+++ src/unit_tests/json_parser.cpp 2012-01-23 00:53:24 +0000
2583@@ -0,0 +1,636 @@
2584+/*
2585+ * Copyright 2006-2008 The FLWOR Foundation.
2586+ *
2587+ * Licensed under the Apache License, Version 2.0 (the "License");
2588+ * you may not use this file except in compliance with the License.
2589+ * You may obtain a copy of the License at
2590+ *
2591+ * http://www.apache.org/licenses/LICENSE-2.0
2592+ *
2593+ * Unless required by applicable law or agreed to in writing, software
2594+ * distributed under the License is distributed on an "AS IS" BASIS,
2595+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2596+ * See the License for the specific language governing permissions and
2597+ * limitations under the License.
2598+ */
2599+
2600+#include <sstream>
2601+
2602+#include "util/json_parser.h"
2603+
2604+using namespace std;
2605+using namespace zorba;
2606+using namespace zorba::json;
2607+
2608+///////////////////////////////////////////////////////////////////////////////
2609+
2610+static int failures;
2611+
2612+static bool assert_true( char const *expr, int line, bool result ) {
2613+ if ( !result ) {
2614+ cout << "FAILED, line " << line << ": " << expr << endl;
2615+ ++failures;
2616+ }
2617+ return result;
2618+}
2619+
2620+static void print_exception( char const *expr, int line,
2621+ std::exception const &e ) {
2622+ assert_true( expr, line, false );
2623+ cout << "+ exception: ";
2624+ if ( json::exception const *j = dynamic_cast<json::exception const*>( &e ) ) {
2625+ json::location const &loc = j->get_loc();
2626+ if ( loc.file() && *loc.file() )
2627+ cout << '"' << loc.file() << "\": ";
2628+ cout << loc.line();
2629+ if ( loc.column() )
2630+ cout << ',' << loc.column();
2631+ cout << ": ";
2632+ }
2633+ cout << e.what() << endl;
2634+}
2635+
2636+#define ASSERT_TRUE( EXPR ) assert_true( #EXPR, __LINE__, !!(EXPR) )
2637+
2638+#define ASSERT_EXCEPTION( EXPR, EXCEPTION ) \
2639+ try { EXPR; assert_true( #EXPR, __LINE__, false ); } \
2640+ catch ( EXCEPTION const& ) { }
2641+
2642+#define ASSERT_NO_EXCEPTION( EXPR ) \
2643+ try { EXPR; } \
2644+ catch ( std::exception const &e ) { print_exception( #EXPR, __LINE__, e ); } \
2645+ catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
2646+
2647+#define ASSERT_TRUE_AND_NO_EXCEPTION( EXPR ) \
2648+ try { ASSERT_TRUE( EXPR ); } \
2649+ catch ( std::exception const &e ) { print_exception( #EXPR, __LINE__, e ); } \
2650+ catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
2651+
2652+///////////////////////////////////////////////////////////////////////////////
2653+
2654+static void test_empty_stream() {
2655+ char const source[] = "";
2656+ istringstream iss( source );
2657+ parser p( iss );
2658+ token t;
2659+ ASSERT_NO_EXCEPTION( p.next( &t ) );
2660+}
2661+
2662+static void test_illegal_character() {
2663+ char const source[] = " x ";
2664+ istringstream iss( source );
2665+ lexer lex( iss );
2666+ token t;
2667+ ASSERT_EXCEPTION( lex.next( &t ), illegal_character );
2668+}
2669+
2670+static void test_illegal_codepoint() {
2671+ static char const *const sources[] = {
2672+ " \" \\u \" ",
2673+ " \" \\u0 \" ",
2674+ " \" \\u00 \" ",
2675+ " \" \\u000 \" ",
2676+ " \" \\uG \" ",
2677+ " \" \\u\" ",
2678+ 0
2679+ };
2680+
2681+ for ( char const *const *s = sources; *s; ++s ) {
2682+ istringstream iss( *s );
2683+ lexer lex( iss );
2684+ token t;
2685+ ASSERT_EXCEPTION( lex.next( &t ), illegal_codepoint );
2686+ }
2687+}
2688+
2689+static void test_illegal_escape() {
2690+ char const source[] = " \" \\x \" ";
2691+ istringstream iss( source );
2692+ lexer lex( iss );
2693+ token t;
2694+ ASSERT_EXCEPTION( lex.next( &t ), illegal_escape );
2695+}
2696+
2697+static void test_illegal_literal() {
2698+ static char const *const sources[] = {
2699+ " f ",
2700+ " fa ",
2701+ " fal ",
2702+ " fals ",
2703+ " falsee ",
2704+ " t ",
2705+ " tr ",
2706+ " tru ",
2707+ " truee ",
2708+ " n ",
2709+ " nu ",
2710+ " nul ",
2711+ " nulll ",
2712+ 0
2713+ };
2714+
2715+ for ( char const *const *s = sources; *s; ++s ) {
2716+ istringstream iss( *s );
2717+ lexer lex( iss );
2718+ token t;
2719+ ASSERT_EXCEPTION( lex.next( &t ), illegal_literal );
2720+ }
2721+}
2722+
2723+static void test_illegal_number() {
2724+}
2725+
2726+static void test_json_org_example() {
2727+ char const source[] =
2728+/* 1 */ "{" "\n"
2729+/* 2 */ " \"glossary\": {" "\n"
2730+/* 3 */ " \"title\": \"example glossary\"," "\n"
2731+/* 4 */ " \"GlossDiv\": {" "\n"
2732+/* 5 */ " \"title\": \"S\"," "\n"
2733+/* 6 */ " \"GlossList\": {" "\n"
2734+/* 7 */ " \"GlossEntry\": {" "\n"
2735+/* 8 */ " \"ID\": \"SGML\"," "\n"
2736+/* 9 */ " \"SortAs\": \"SGML\"," "\n"
2737+/* 10 */ " \"GlossTerm\": \"Standard Generalized Markup Language\"," "\n"
2738+/* 11 */ " \"Acronym\": \"SGML\"," "\n"
2739+/* 12 */ " \"Abbrev\": \"ISO 8879:1986\"," "\n"
2740+/* 13 */ " \"GlossDef\": {" "\n"
2741+/* 14 */ " \"para\": \"A meta-markup language, used to create markup languages such as DocBook.\"," "\n"
2742+/* 15 */ " \"GlossSeeAlso\": [\"GML\", \"XML\"]" "\n"
2743+/* 16 */ " }," "\n"
2744+/* 17 */ " \"GlossSee\": \"markup\"" "\n"
2745+/* 18 */ " }" "\n"
2746+/* 19 */ " }" "\n"
2747+/* 20 */ " }" "\n"
2748+/* 21 */ " }" "\n"
2749+/* 22 */ "}" "\n" ;
2750+
2751+ istringstream iss( source );
2752+ parser p( iss );
2753+ token t;
2754+
2755+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 1: {
2756+ ASSERT_TRUE( t == token::begin_object );
2757+
2758+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 2: "glossary"
2759+ ASSERT_TRUE( t == token::string );
2760+
2761+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 2: :
2762+ ASSERT_TRUE( t == token::name_separator );
2763+
2764+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 2: {
2765+ ASSERT_TRUE( t == token::begin_object );
2766+
2767+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 3: "title"
2768+ ASSERT_TRUE( t == token::string );
2769+
2770+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 3: :
2771+ ASSERT_TRUE( t == token::name_separator );
2772+
2773+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 3: "example glossary"
2774+ ASSERT_TRUE( t == token::string );
2775+
2776+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 3: ,
2777+ ASSERT_TRUE( t == token::value_separator );
2778+
2779+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 4: "GlossDiv"
2780+ ASSERT_TRUE( t == token::string );
2781+
2782+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 4: :
2783+ ASSERT_TRUE( t == token::name_separator );
2784+
2785+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 4: {
2786+ ASSERT_TRUE( t == token::begin_object );
2787+
2788+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 5: "title"
2789+ ASSERT_TRUE( t == token::string );
2790+
2791+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 5: :
2792+ ASSERT_TRUE( t == token::name_separator );
2793+
2794+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 5: "S"
2795+ ASSERT_TRUE( t == token::string );
2796+
2797+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 5: ,
2798+ ASSERT_TRUE( t == token::value_separator );
2799+
2800+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 6: "GlossList"
2801+ ASSERT_TRUE( t == token::string );
2802+
2803+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 6: :
2804+ ASSERT_TRUE( t == token::name_separator );
2805+
2806+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 6: {
2807+ ASSERT_TRUE( t == token::begin_object );
2808+
2809+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 7: "GlossEntry"
2810+ ASSERT_TRUE( t == token::string );
2811+
2812+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 7: :
2813+ ASSERT_TRUE( t == token::name_separator );
2814+
2815+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 7: {
2816+ ASSERT_TRUE( t == token::begin_object );
2817+
2818+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 8: "ID"
2819+ ASSERT_TRUE( t == token::string );
2820+
2821+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 8: :
2822+ ASSERT_TRUE( t == token::name_separator );
2823+
2824+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 8: "SGML"
2825+ ASSERT_TRUE( t == token::string );
2826+
2827+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 8: ,
2828+ ASSERT_TRUE( t == token::value_separator );
2829+
2830+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 9: "SortAs"
2831+ ASSERT_TRUE( t == token::string );
2832+
2833+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 9: :
2834+ ASSERT_TRUE( t == token::name_separator );
2835+
2836+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 9: "SGML"
2837+ ASSERT_TRUE( t == token::string );
2838+
2839+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 9: ,
2840+ ASSERT_TRUE( t == token::value_separator );
2841+
2842+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 10: "GlossTerm"
2843+ ASSERT_TRUE( t == token::string );
2844+
2845+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 10: :
2846+ ASSERT_TRUE( t == token::name_separator );
2847+
2848+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 10: "Standard ..."
2849+ ASSERT_TRUE( t == token::string );
2850+
2851+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 10: ,
2852+ ASSERT_TRUE( t == token::value_separator );
2853+
2854+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 11: "Acronym"
2855+ ASSERT_TRUE( t == token::string );
2856+
2857+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 11: :
2858+ ASSERT_TRUE( t == token::name_separator );
2859+
2860+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 11: "SGML"
2861+ ASSERT_TRUE( t == token::string );
2862+
2863+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 11: ,
2864+ ASSERT_TRUE( t == token::value_separator );
2865+
2866+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 12: "Abbrev"
2867+ ASSERT_TRUE( t == token::string );
2868+
2869+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 12: :
2870+ ASSERT_TRUE( t == token::name_separator );
2871+
2872+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 12: "ISO 8879:1986"
2873+ ASSERT_TRUE( t == token::string );
2874+
2875+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 12: ,
2876+ ASSERT_TRUE( t == token::value_separator );
2877+
2878+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 13: "GlossDef"
2879+ ASSERT_TRUE( t == token::string );
2880+
2881+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 13: :
2882+ ASSERT_TRUE( t == token::name_separator );
2883+
2884+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 13: {
2885+ ASSERT_TRUE( t == token::begin_object );
2886+
2887+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 14: "para"
2888+ ASSERT_TRUE( t == token::string );
2889+
2890+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 14: :
2891+ ASSERT_TRUE( t == token::name_separator );
2892+
2893+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 14: "A meta-markup ..."
2894+ ASSERT_TRUE( t == token::string );
2895+
2896+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 14: ,
2897+ ASSERT_TRUE( t == token::value_separator );
2898+
2899+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: "GlossSeeAlso"
2900+ ASSERT_TRUE( t == token::string );
2901+
2902+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: :
2903+ ASSERT_TRUE( t == token::name_separator );
2904+
2905+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: [
2906+ ASSERT_TRUE( t == token::begin_array );
2907+
2908+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: "GML"
2909+ ASSERT_TRUE( t == token::string );
2910+
2911+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: ,
2912+ ASSERT_TRUE( t == token::value_separator );
2913+
2914+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: "XML"
2915+ ASSERT_TRUE( t == token::string );
2916+
2917+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 15: ]
2918+ ASSERT_TRUE( t == token::end_array );
2919+
2920+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 16: }
2921+ ASSERT_TRUE( t == token::end_object );
2922+
2923+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 16: ,
2924+ ASSERT_TRUE( t == token::value_separator );
2925+
2926+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 17: "GlossSee"
2927+ ASSERT_TRUE( t == token::string );
2928+
2929+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 17: :
2930+ ASSERT_TRUE( t == token::name_separator );
2931+
2932+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 17: "markup"
2933+ ASSERT_TRUE( t == token::string );
2934+
2935+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 18: }
2936+ ASSERT_TRUE( t == token::end_object );
2937+
2938+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 19: }
2939+ ASSERT_TRUE( t == token::end_object );
2940+
2941+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 20: }
2942+ ASSERT_TRUE( t == token::end_object );
2943+
2944+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 21: }
2945+ ASSERT_TRUE( t == token::end_object );
2946+
2947+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) ); // 22: }
2948+ ASSERT_TRUE( t == token::end_object );
2949+
2950+ ASSERT_TRUE( !p.next( &t ) );
2951+}
2952+
2953+static void test_lexer_array() {
2954+ char const source[] = "[ 1, \"2\", false, true, null ]";
2955+ istringstream iss( source );
2956+ lexer lex( iss );
2957+ token t;
2958+
2959+ ASSERT_TRUE( lex.next( &t ) );
2960+ ASSERT_TRUE( t == token::begin_array );
2961+
2962+ ASSERT_TRUE( lex.next( &t ) );
2963+ ASSERT_TRUE( t == token::number );
2964+ ASSERT_TRUE( t.get_value() == "1" );
2965+
2966+ ASSERT_TRUE( lex.next( &t ) );
2967+ ASSERT_TRUE( t == token::value_separator );
2968+
2969+ ASSERT_TRUE( lex.next( &t ) );
2970+ ASSERT_TRUE( t == token::string );
2971+ ASSERT_TRUE( t.get_value() == "2" );
2972+
2973+ ASSERT_TRUE( lex.next( &t ) );
2974+ ASSERT_TRUE( t == token::value_separator );
2975+
2976+ ASSERT_TRUE( lex.next( &t ) );
2977+ ASSERT_TRUE( t == token::json_false );
2978+
2979+ ASSERT_TRUE( lex.next( &t ) );
2980+ ASSERT_TRUE( t == token::value_separator );
2981+
2982+ ASSERT_TRUE( lex.next( &t ) );
2983+ ASSERT_TRUE( t == token::json_true );
2984+
2985+ ASSERT_TRUE( lex.next( &t ) );
2986+ ASSERT_TRUE( t == token::value_separator );
2987+
2988+ ASSERT_TRUE( lex.next( &t ) );
2989+ ASSERT_TRUE( t == token::json_null );
2990+
2991+ ASSERT_TRUE( lex.next( &t ) );
2992+ ASSERT_TRUE( t == token::end_array );
2993+
2994+ ASSERT_TRUE( !lex.next( &t ) );
2995+}
2996+
2997+static void test_lexer_object() {
2998+ char const source[] = "{ \"a\" : 1, \"b\" : \"2\" }";
2999+ istringstream iss( source );
3000+ lexer lex( iss );
3001+ token t;
3002+
3003+ ASSERT_TRUE( lex.next( &t ) );
3004+ ASSERT_TRUE( t == token::begin_object );
3005+
3006+ ASSERT_TRUE( lex.next( &t ) );
3007+ ASSERT_TRUE( t == token::string );
3008+
3009+ ASSERT_TRUE( lex.next( &t ) );
3010+ ASSERT_TRUE( t == token::name_separator );
3011+
3012+ ASSERT_TRUE( lex.next( &t ) );
3013+ ASSERT_TRUE( t == token::number );
3014+
3015+ ASSERT_TRUE( lex.next( &t ) );
3016+ ASSERT_TRUE( t == token::value_separator );
3017+
3018+ ASSERT_TRUE( lex.next( &t ) );
3019+ ASSERT_TRUE( t == token::string );
3020+
3021+ ASSERT_TRUE( lex.next( &t ) );
3022+ ASSERT_TRUE( t == token::name_separator );
3023+
3024+ ASSERT_TRUE( lex.next( &t ) );
3025+ ASSERT_TRUE( t == token::string );
3026+
3027+ ASSERT_TRUE( lex.next( &t ) );
3028+ ASSERT_TRUE( t == token::end_object );
3029+
3030+ ASSERT_TRUE( !lex.next( &t ) );
3031+}
3032+
3033+static void test_parser_array() {
3034+ char const source[] = "[ 1, \"2\", false, true, null ]";
3035+ istringstream iss( source );
3036+ parser p( iss );
3037+ token t;
3038+
3039+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3040+ ASSERT_TRUE( t == token::begin_array );
3041+
3042+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3043+ ASSERT_TRUE( t == token::number );
3044+ ASSERT_TRUE( t.get_value() == "1" );
3045+
3046+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3047+ ASSERT_TRUE( t == token::value_separator );
3048+
3049+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3050+ ASSERT_TRUE( t == token::string );
3051+ ASSERT_TRUE( t.get_value() == "2" );
3052+
3053+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3054+ ASSERT_TRUE( t == token::value_separator );
3055+
3056+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3057+ ASSERT_TRUE( t == token::json_false );
3058+
3059+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3060+ ASSERT_TRUE( t == token::value_separator );
3061+
3062+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3063+ ASSERT_TRUE( t == token::json_true );
3064+
3065+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3066+ ASSERT_TRUE( t == token::value_separator );
3067+
3068+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3069+ ASSERT_TRUE( t == token::json_null );
3070+
3071+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3072+ ASSERT_TRUE( t == token::end_array );
3073+
3074+ ASSERT_TRUE( !p.next( &t ) );
3075+}
3076+
3077+static void test_parser_object() {
3078+ char const source[] = "{ \"a\" : 1, \"b\" : \"2\" }";
3079+ istringstream iss( source );
3080+ parser p( iss );
3081+ token t;
3082+
3083+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3084+ ASSERT_TRUE( t == token::begin_object );
3085+
3086+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3087+ ASSERT_TRUE( t == token::string );
3088+
3089+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3090+ ASSERT_TRUE( t == token::name_separator );
3091+
3092+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3093+ ASSERT_TRUE( t == token::number );
3094+
3095+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3096+ ASSERT_TRUE( t == token::value_separator );
3097+
3098+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3099+ ASSERT_TRUE( t == token::string );
3100+
3101+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3102+ ASSERT_TRUE( t == token::name_separator );
3103+
3104+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3105+ ASSERT_TRUE( t == token::string );
3106+
3107+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3108+ ASSERT_TRUE( t == token::end_object );
3109+
3110+ ASSERT_TRUE( !p.next( &t ) );
3111+}
3112+
3113+static void test_unexpected_token() {
3114+ token t;
3115+ {
3116+ char const source[] = "{ 1 }";
3117+ istringstream iss( source );
3118+ parser p( iss );
3119+
3120+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3121+ ASSERT_TRUE( t == token::begin_object );
3122+ ASSERT_EXCEPTION( p.next( &t ), unexpected_token );
3123+ }
3124+ {
3125+ char const source[] = "{ \"a\" : 1, }";
3126+ istringstream iss( source );
3127+ parser p( iss );
3128+
3129+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3130+ ASSERT_TRUE( t == token::begin_object );
3131+
3132+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3133+ ASSERT_TRUE( t == token::string );
3134+
3135+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3136+ ASSERT_TRUE( t == token::name_separator );
3137+
3138+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3139+ ASSERT_TRUE( t == token::number );
3140+
3141+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3142+ ASSERT_TRUE( t == token::value_separator );
3143+
3144+ ASSERT_EXCEPTION( p.next( &t ), unexpected_token );
3145+ }
3146+ {
3147+ char const source[] = "{ \"t\" : true \"f\" : false }";
3148+ istringstream iss( source );
3149+ parser p( iss );
3150+
3151+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3152+ ASSERT_TRUE( t == token::begin_object );
3153+
3154+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3155+ ASSERT_TRUE( t == token::string );
3156+
3157+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3158+ ASSERT_TRUE( t == token::name_separator );
3159+
3160+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3161+ ASSERT_TRUE( t == token::json_true );
3162+
3163+ ASSERT_EXCEPTION( p.next( &t ), unexpected_token );
3164+ }
3165+ {
3166+ char const source[] = "[ 1";
3167+ istringstream iss( source );
3168+ parser p( iss );
3169+
3170+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3171+ ASSERT_TRUE( t == token::begin_array );
3172+
3173+ ASSERT_TRUE_AND_NO_EXCEPTION( p.next( &t ) );
3174+ ASSERT_TRUE( t == token::number );
3175+
3176+ ASSERT_EXCEPTION( p.next( &t ), unexpected_token );
3177+ }
3178+}
3179+
3180+static void test_unterminated_string() {
3181+ char const source[] = " \"hello ";
3182+ istringstream iss( source );
3183+ lexer lex( iss );
3184+ token t;
3185+
3186+ ASSERT_EXCEPTION( lex.next( &t ), unterminated_string );
3187+}
3188+
3189+///////////////////////////////////////////////////////////////////////////////
3190+
3191+namespace zorba {
3192+namespace UnitTests {
3193+
3194+int json_parser( int, char*[] ) {
3195+
3196+ // lexer-only tests
3197+ test_lexer_array();
3198+ test_lexer_object();
3199+ test_illegal_character();
3200+ test_illegal_codepoint();
3201+ test_illegal_escape();
3202+ test_illegal_literal();
3203+ test_illegal_number();
3204+ test_unterminated_string();
3205+
3206+ // parser tests
3207+ test_empty_stream();
3208+ test_parser_array();
3209+ test_parser_object();
3210+ test_unexpected_token();
3211+ test_json_org_example();
3212+
3213+ cout << failures << " test(s) failed\n";
3214+ return failures ? 1 : 0;
3215+}
3216+
3217+} // namespace UnitTests
3218+} // namespace zorba
3219+/* vim:set et sw=2 ts=2: */
3220
3221=== modified file 'src/unit_tests/unit_test_list.h'
3222--- src/unit_tests/unit_test_list.h 2011-06-14 17:26:33 +0000
3223+++ src/unit_tests/unit_test_list.h 2012-01-23 00:53:24 +0000
3224@@ -28,6 +28,7 @@
3225 /**
3226 * ADD NEW UNIT TESTS HERE
3227 */
3228+ int json_parser( int, char*[] );
3229
3230
3231 void initializeTestList();
3232
3233=== modified file 'src/unit_tests/unit_tests.cpp'
3234--- src/unit_tests/unit_tests.cpp 2011-06-14 17:26:33 +0000
3235+++ src/unit_tests/unit_tests.cpp 2012-01-23 00:53:24 +0000
3236@@ -38,6 +38,7 @@
3237 */
3238 void initializeTestList() {
3239 libunittests["uri"] = runUriTest;
3240+ libunittests["json_parser"] = json_parser;
3241 #ifdef ZORBA_WITH_DEBUGGER
3242 // libunittests["debugger_protocol"] = runDebuggerProtocolTest;
3243 #endif
3244
3245=== modified file 'src/util/CMakeLists.txt'
3246--- src/util/CMakeLists.txt 2011-07-18 14:25:21 +0000
3247+++ src/util/CMakeLists.txt 2012-01-23 00:53:24 +0000
3248@@ -20,6 +20,8 @@
3249 dir.cpp
3250 fs_util.cpp
3251 indent.cpp
3252+ json_parser.cpp
3253+ mem_streambuf.cpp
3254 regex.cpp
3255 string_util.cpp
3256 unicode_util.cpp
3257
3258=== added file 'src/util/json_parser.cpp'
3259--- src/util/json_parser.cpp 1970-01-01 00:00:00 +0000
3260+++ src/util/json_parser.cpp 2012-01-23 00:53:24 +0000
3261@@ -0,0 +1,653 @@
3262+/*
3263+ * Copyright 2006-2008 The FLWOR Foundation.
3264+ *
3265+ * Licensed under the Apache License, Version 2.0 (the "License");
3266+ * you may not use this file except in compliance with the License.
3267+ * You may obtain a copy of the License at
3268+ *
3269+ * http://www.apache.org/licenses/LICENSE-2.0
3270+ *
3271+ * Unless required by applicable law or agreed to in writing, software
3272+ * distributed under the License is distributed on an "AS IS" BASIS,
3273+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3274+ * See the License for the specific language governing permissions and
3275+ * limitations under the License.
3276+ */
3277+
3278+#include "diagnostics/assert.h"
3279+
3280+#include "ascii_util.h"
3281+#include "stl_util.h"
3282+#include "string_util.h"
3283+#include "utf8_util.h"
3284+
3285+#define DEBUG_JSON_PARSER 0
3286+
3287+#if DEBUG_JSON_PARSER
3288+# include "indent.h"
3289+#endif /* DEBUG_JSON_PARSER */
3290+
3291+#include "json_parser.h"
3292+
3293+using namespace std;
3294+
3295+namespace zorba {
3296+namespace json {
3297+
3298+///////////////////////////////////////////////////////////////////////////////
3299+
3300+char const *const type_string_of[] = {
3301+ "none",
3302+ "array",
3303+ "boolean",
3304+ "null",
3305+ "number",
3306+ "object",
3307+ "string"
3308+};
3309+
3310+type map_type( token::type tt ) {
3311+ switch ( tt ) {
3312+ case token::string:
3313+ return string;
3314+ case token::number:
3315+ return number;
3316+ case token::json_false:
3317+ case token::json_true:
3318+ return boolean;
3319+ case token::json_null:
3320+ return null;
3321+ default:
3322+ return none;
3323+ }
3324+}
3325+
3326+///////////////////////////////////////////////////////////////////////////////
3327+
3328+exception::exception( location const &loc, std::string const &message ) :
3329+ loc_( loc ), message_( message )
3330+{
3331+}
3332+
3333+exception::~exception() throw() {
3334+ // out-of-line since it's virtual
3335+}
3336+
3337+char const* exception::what() const throw() {
3338+ return message_.c_str();
3339+}
3340+
3341+illegal_character::illegal_character( location const &loc, char c ) :
3342+ exception( loc, BUILD_STRING( '\'', c, "': illegal character" ) ),
3343+ c_( c )
3344+{
3345+}
3346+
3347+illegal_character::~illegal_character() throw() {
3348+ // out-of-line since it's virtual
3349+}
3350+
3351+illegal_codepoint::illegal_codepoint( location const &loc,
3352+ token::value_type const &cp ) :
3353+ exception( loc, BUILD_STRING( '"', cp, "\": illegal codepoint" ) ),
3354+ codepoint_( cp )
3355+{
3356+}
3357+
3358+illegal_codepoint::~illegal_codepoint() throw() {
3359+ // out-of-line since it's virtual
3360+}
3361+
3362+illegal_escape::illegal_escape( location const &loc, char c ) :
3363+ exception( loc, BUILD_STRING( "\"\\", c, "\": illegal character escape" ) ),
3364+ esc_( c )
3365+{
3366+}
3367+
3368+illegal_escape::~illegal_escape() throw() {
3369+ // out-of-line since it's virtual
3370+}
3371+
3372+illegal_literal::illegal_literal( location const &loc ) :
3373+ exception( loc, "illegal literal" )
3374+{
3375+}
3376+
3377+illegal_literal::~illegal_literal() throw() {
3378+ // out-of-line since it's virtual
3379+}
3380+
3381+illegal_number::illegal_number( location const &loc ) :
3382+ exception( loc, "illegal number" )
3383+{
3384+}
3385+
3386+illegal_number::~illegal_number() throw() {
3387+ // out-of-line since it's virtual
3388+}
3389+
3390+unexpected_token::unexpected_token( token const &t ) :
3391+ exception( t.get_loc(), BUILD_STRING( '"', t, "\": unexpected token" ) ),
3392+ token_( t )
3393+{
3394+}
3395+
3396+unexpected_token::~unexpected_token() throw() {
3397+ // out-of-line since it's virtual
3398+}
3399+
3400+unterminated_string::unterminated_string( location const &loc ) :
3401+ exception( loc, "unterminated string" )
3402+{
3403+}
3404+
3405+unterminated_string::~unterminated_string() throw() {
3406+ // out-of-line since it's virtual
3407+}
3408+
3409+///////////////////////////////////////////////////////////////////////////////
3410+
3411+token::token() :
3412+ type_( none )
3413+{
3414+}
3415+
3416+ostream& operator<<( ostream &o, token::type tt ) {
3417+ switch ( tt ) {
3418+ case token::string : o << "string"; break;
3419+ case token::number : o << "number"; break;
3420+ case token::json_false: o << "false" ; break;
3421+ case token::json_null : o << "null" ; break;
3422+ case token::json_true : o << "true" ; break;
3423+ case token::none : o << "<none>"; break;
3424+ default : o << static_cast<char>( tt );
3425+ }
3426+ return o;
3427+}
3428+
3429+ostream& operator<<( ostream &o, token const &t ) {
3430+ switch ( t.get_type() ) {
3431+ case token::string: o << '"' << t.get_value() << '"'; break;
3432+ case token::number: o << t.get_value() ; break;
3433+ default : o << t.get_type() ;
3434+ }
3435+ return o;
3436+}
3437+
3438+///////////////////////////////////////////////////////////////////////////////
3439+
3440+lexer::lexer( istream &in ) :
3441+ in_( &in ),
3442+ line_( 1 ),
3443+ col_( 1 )
3444+{
3445+}
3446+
3447+bool lexer::get_char( char *c ) {
3448+ char const temp = in_->get();
3449+ if ( in_->good() ) {
3450+ if ( temp == '\n' )
3451+ ++line_, col_ = 1;
3452+ else
3453+ ++col_;
3454+ if ( c )
3455+ *c = temp;
3456+ return true;
3457+ }
3458+ return false;
3459+}
3460+
3461+bool lexer::peek_char( char *c ) {
3462+ *c = in_->peek();
3463+ return in_->good();
3464+}
3465+
3466+bool lexer::next( token *t ) {
3467+ while ( true ) {
3468+ cur_loc_ = cur_loc();
3469+ char c;
3470+ if ( !get_char( &c ) )
3471+ return false;
3472+ switch ( c ) {
3473+ case ' ':
3474+ case '\n':
3475+ case '\r':
3476+ case '\t':
3477+ continue;
3478+ case '"':
3479+ t->type_ = token::string;
3480+ t->loc_ = cur_loc_;
3481+ parse_string( &t->value_ );
3482+ return true;
3483+ case '-':
3484+ case '0':
3485+ case '1':
3486+ case '2':
3487+ case '3':
3488+ case '4':
3489+ case '5':
3490+ case '6':
3491+ case '7':
3492+ case '8':
3493+ case '9':
3494+ t->type_ = token::number;
3495+ t->loc_ = cur_loc_;
3496+ parse_number( c, &t->value_ );
3497+ return true;
3498+ case 'f':
3499+ case 'n':
3500+ case 't':
3501+ t->type_ = parse_literal( c, &t->value_ );
3502+ t->loc_ = cur_loc_;
3503+ return true;
3504+ case '[':
3505+ case '{':
3506+ case ']':
3507+ case '}':
3508+ case ':':
3509+ case ',':
3510+ t->type_ = static_cast<token::type>( c );
3511+ t->loc_ = cur_loc_;
3512+ return true;
3513+ default:
3514+ throw illegal_character( cur_loc_, c );
3515+ }
3516+ } // while
3517+}
3518+
3519+unicode::code_point lexer::parse_codepoint() {
3520+ static char const hex_digits[] = "0123456789ABCDEF";
3521+
3522+ zstring cp_string( "\\u" ); // needed only for error message
3523+
3524+ unicode::code_point cp = 0;
3525+ for ( int i = 1; i <= 4; ++i ) {
3526+ char c;
3527+ if ( !get_char( &c ) || !ascii::is_xdigit( c ) )
3528+ throw illegal_codepoint( cur_loc_, cp_string );
3529+ cp_string += c;
3530+ c = ascii::to_upper( c );
3531+ char const *const p = std::strchr( hex_digits, c );
3532+ assert( p );
3533+ cp = (cp << 4) | (p - hex_digits);
3534+ }
3535+ return cp;
3536+}
3537+
3538+token::type lexer::parse_literal( char first_c, token::value_type *value ) {
3539+ static token::value_type const false_value( "false" );
3540+ static token::value_type const null_value ( "null" );
3541+ static token::value_type const true_value ( "true" );
3542+
3543+ token::type tt;
3544+ switch ( first_c ) {
3545+ case 'f': *value = false_value; tt = token::json_false; break;
3546+ case 'n': *value = null_value ; tt = token::json_null ; break;
3547+ case 't': *value = true_value ; tt = token::json_true ; break;
3548+ default : assert( false );
3549+ }
3550+
3551+ char c;
3552+ for ( char const *s = value->c_str(); *++s; ) {
3553+ if ( !get_char( &c ) || c != *s )
3554+ throw illegal_literal( cur_loc_ );
3555+ }
3556+ if ( peek_char( &c ) && ascii::is_alnum( c ) )
3557+ throw illegal_literal( cur_loc_ );
3558+
3559+ return tt;
3560+}
3561+
3562+void lexer::parse_number( char first_c, token::value_type *value ) {
3563+ value->clear();
3564+
3565+ // <number> ::= [-] <int> [<frac>] [<exp>]
3566+ char c = first_c;
3567+ if ( c == '-' ) {
3568+ *value += c;
3569+ if ( !get_char( &c ) )
3570+ throw illegal_number( cur_loc_ );
3571+ }
3572+
3573+ // <int> := '0' | <1-9> <digit>*
3574+ if ( !ascii::is_digit( c ) )
3575+ throw illegal_number( cur_loc_ );
3576+ *value += c;
3577+ if ( c == '0' ) {
3578+ if ( !get_char( &c ) )
3579+ return;
3580+ } else {
3581+ while ( true ) {
3582+ if ( !get_char( &c ) )
3583+ return;
3584+ if ( !ascii::is_digit( c ) )
3585+ break;
3586+ *value += c;
3587+ }
3588+ }
3589+
3590+ // <frac> ::= '.' <digit>+
3591+ if ( c == '.' ) {
3592+ *value += c;
3593+ if ( !get_char( &c ) || !ascii::is_digit( c ) )
3594+ throw illegal_number( cur_loc_ );
3595+ *value += c;
3596+ while ( true ) {
3597+ if ( !get_char( &c ) )
3598+ return;
3599+ if ( !ascii::is_digit( c ) )
3600+ break;
3601+ *value += c;
3602+ }
3603+ }
3604+
3605+ // <exp> ::= <e> [<sign>] <digit>+
3606+ // <e> ::= 'e' | 'E'
3607+ // <sign> ::= '-' | '+'
3608+ if ( c == 'e' || c == 'E' ) {
3609+ *value += c;
3610+ if ( !get_char( &c ) )
3611+ throw illegal_number( cur_loc_ );
3612+ if ( c == '+' || c == '-' ) {
3613+ *value += c;
3614+ if ( !get_char( &c ) )
3615+ throw illegal_number( cur_loc_ );
3616+ }
3617+ if ( !ascii::is_digit( c ) )
3618+ throw illegal_number( cur_loc_ );
3619+ *value += c;
3620+ while ( true ) {
3621+ if ( !get_char( &c ) )
3622+ return;
3623+ if ( !ascii::is_digit( c ) )
3624+ break;
3625+ *value += c;
3626+ }
3627+ }
3628+
3629+ in_->putback( c );
3630+}
3631+
3632+void lexer::parse_string( token::value_type *value ) {
3633+ value->clear();
3634+ bool got_backslash = false;
3635+ location const start_loc( cur_loc_ );
3636+
3637+ while ( true ) {
3638+ cur_loc_ = cur_loc();
3639+ char c;
3640+ if ( !get_char( &c ) )
3641+ throw unterminated_string( start_loc );
3642+ if ( got_backslash ) {
3643+ got_backslash = false;
3644+ switch ( c ) {
3645+ case '"':
3646+ case '/':
3647+ case '\\':
3648+ *value += c;
3649+ break;
3650+ case 'b':
3651+ *value += '\b';
3652+ break;
3653+ case 'f':
3654+ *value += '\f';
3655+ break;
3656+ case 'n':
3657+ *value += '\n';
3658+ break;
3659+ case 'r':
3660+ *value += '\r';
3661+ break;
3662+ case 't':
3663+ *value += '\t';
3664+ break;
3665+ case 'u':
3666+ utf8::encode( parse_codepoint(), value );
3667+ break;
3668+ default:
3669+ throw illegal_escape( cur_loc_, c );
3670+ }
3671+ continue;
3672+ }
3673+
3674+ switch ( c ) {
3675+ case '\\':
3676+ got_backslash = true;
3677+ break;
3678+ case '"':
3679+ return;
3680+ default:
3681+ *value += c;
3682+ }
3683+ } // while
3684+}
3685+
3686+void lexer::set_loc( char const *file, line_type line, column_type col ) {
3687+ if ( file )
3688+ file_ = file;
3689+ line_ = line;
3690+ col_ = col;
3691+}
3692+
3693+///////////////////////////////////////////////////////////////////////////////
3694+
3695+#if DEBUG_JSON_PARSER
3696+
3697+ostream& operator<<( ostream &o, parser::state s ) {
3698+ static char const *const string_of[] = {
3699+ "A0", "A1", "A2",
3700+ "E0", "E1",
3701+ "J0", "J1",
3702+ "M0", "M1",
3703+ "O0", "O1", "O2",
3704+ "P0", "P1",
3705+ "V0"
3706+ };
3707+ return o << string_of[ s ];
3708+}
3709+
3710+static void throw_unexpected_token( int line, token const &t ) {
3711+ try {
3712+ throw unexpected_token( t );
3713+ }
3714+ catch ( exception const &e ) {
3715+ cerr << line << ": " << e.what() << endl;
3716+ throw;
3717+ }
3718+}
3719+
3720+bool parser::get_token_debug( int line, token *t ) {
3721+ bool const got_token = get_token( t );
3722+ cout << line << ": get_token => " << *t << endl;
3723+ return got_token;
3724+}
3725+
3726+bool parser::matches_token_debug( int line, token::type tt, token *t ) {
3727+ bool const matched = matches_token( tt, t );
3728+ cout << line << ": token " << *t << " matches " << tt << " => " << (matched ? 'T' : 'F') << endl;
3729+ return matched;
3730+}
3731+
3732+token::type parser::peek_token_debug( int line ) {
3733+ token::type const tt = peek_token();
3734+ cout << line << ": peek_token => " << peeked_token_ << endl;
3735+ return tt;
3736+}
3737+
3738+void parser::require_token_debug( int line, token::type tt, token *t ) {
3739+ if ( !get_token_debug( line, t ) || t->get_type() != tt )
3740+ throw_unexpected_token( line, *t );
3741+}
3742+
3743+# define GET_TOKEN(T) get_token_debug( __LINE__, T )
3744+# define MATCHES_TOKEN(TT,T) matches_token_debug( __LINE__, TT, T )
3745+# define PEEK_TOKEN() peek_token_debug( __LINE__ )
3746+# define REQUIRE_TOKEN(TT,T) require_token_debug( __LINE__, TT, T )
3747+# define THROW_UNEXPECTED_TOKEN(T) throw_unexpected_token( __LINE__, T )
3748+
3749+# define GOTO_STATE(S) \
3750+ if (0) ; else { \
3751+ state_ = (S); \
3752+ cout << __LINE__ << ':' << indent << "GOTO_STATE( " << state_ << " )" << endl; \
3753+ continue; \
3754+ }
3755+
3756+# define PUSH_STATE(S) \
3757+ if (0) ; else { \
3758+ state_stack_.push(S); \
3759+ cout << __LINE__ << ':' << indent << "PUSH_STATE( " << (S) << " )" << endl << inc_indent; \
3760+ }
3761+
3762+# define POP_STATE() \
3763+ if (0) ; else { \
3764+ state_ = ztd::pop_stack( state_stack_ ); \
3765+ cout << __LINE__ << ':' << indent << "POP_STATE() => " << state_ << endl << dec_indent; \
3766+ }
3767+
3768+#else
3769+
3770+# define GET_TOKEN(T) get_token( T )
3771+# define MATCHES_TOKEN(TT,T) matches_token( TT, T )
3772+# define PEEK_TOKEN() peek_token()
3773+# define REQUIRE_TOKEN(TT,T) require_token( TT, T )
3774+# define THROW_UNEXPECTED_TOKEN(T) throw unexpected_token( T )
3775+
3776+# define GOTO_STATE(S) { state_ = (S); continue; }
3777+# define PUSH_STATE(S) state_stack_.push(S)
3778+# define POP_STATE() state_ = ztd::pop_stack( state_stack_ )
3779+
3780+#endif /* DEBUG_JSON_PARSER */
3781+
3782+///////////////////////////////////////////////////////////////////////////////
3783+
3784+parser::parser( istream &in ) : lexer_( in ) {
3785+#if DEBUG_JSON_PARSER
3786+ get_indent( cout ) = 0;
3787+#endif /* DEBUG_JSON_PARSER */
3788+ PUSH_STATE( J0 );
3789+}
3790+
3791+bool parser::get_token( token *t ) {
3792+ if ( peeked_token_ ) {
3793+ *t = peeked_token_;
3794+ peeked_token_.clear();
3795+ return true;
3796+ }
3797+ t->clear();
3798+ return lexer_.next( t );
3799+}
3800+
3801+bool parser::matches_token( token::type tt, token *t ) {
3802+ if ( peek_token() == tt )
3803+ return get_token( t );
3804+ *t = peeked_token_;
3805+ return false;
3806+}
3807+
3808+token::type parser::peek_token() {
3809+ if ( !peeked_token_ )
3810+ lexer_.next( &peeked_token_ );
3811+ return peeked_token_.get_type();
3812+}
3813+
3814+#if ! DEBUG_JSON_PARSER
3815+void parser::require_token( token::type tt, token *t ) {
3816+ if ( !get_token( t ) || t->get_type() != tt )
3817+ THROW_UNEXPECTED_TOKEN( *t );
3818+}
3819+#endif /* DEBUG_JSON_PARSER */
3820+
3821+bool parser::next( token *t ) {
3822+ if ( state_stack_.empty() )
3823+ return false;
3824+ POP_STATE();
3825+ while ( true ) {
3826+ switch ( state_ ) {
3827+
3828+ // <JSON> ::= <Array> | <Object>
3829+ case J0: PUSH_STATE( J1 );
3830+ switch ( PEEK_TOKEN() ) {
3831+ case token::begin_array : GOTO_STATE( A0 );
3832+ case token::begin_object: GOTO_STATE( O0 );
3833+ case token::none : break;
3834+ default: THROW_UNEXPECTED_TOKEN( peeked_token_ );
3835+ }
3836+ case J1: return false;
3837+
3838+ // <Array> ::= '[' <Element>* ']'
3839+ case A0: REQUIRE_TOKEN( token::begin_array, t );
3840+ PUSH_STATE( A1 );
3841+ return true;
3842+ case A1: if ( MATCHES_TOKEN( token::end_array, t ) )
3843+ return true;
3844+ PUSH_STATE( A2 );
3845+ GOTO_STATE( E0 );
3846+ case A2: REQUIRE_TOKEN( token::end_array, t );
3847+ return true;
3848+
3849+ // <Element> ::= <Value> [ ',' <Element> ]
3850+ case E0: PUSH_STATE( E1 );
3851+ GOTO_STATE( V0 );
3852+ case E1: if ( MATCHES_TOKEN( token::value_separator, t ) ) {
3853+ PUSH_STATE( E0 );
3854+ return true;
3855+ }
3856+ POP_STATE();
3857+ continue;
3858+
3859+ // <Object> ::= '{' <Member>* '}'
3860+ case O0: REQUIRE_TOKEN( token::begin_object, t );
3861+ PUSH_STATE( O1 );
3862+ return true;
3863+ case O1: if ( MATCHES_TOKEN( token::end_object, t ) )
3864+ return true;
3865+ PUSH_STATE( O2 );
3866+ GOTO_STATE( M0 );
3867+ case O2: REQUIRE_TOKEN( token::end_object, t );
3868+ return true;
3869+
3870+ // <Member> ::= <Pair> [ ',' <Member> ]
3871+ case M0: PUSH_STATE( M1 );
3872+ GOTO_STATE( P0 );
3873+ case M1: if ( MATCHES_TOKEN( token::value_separator, t ) ) {
3874+ PUSH_STATE( M0 );
3875+ return true;
3876+ }
3877+ POP_STATE();
3878+ continue;
3879+
3880+ // <Pair> ::= <String> ':' <Value>
3881+ case P0: REQUIRE_TOKEN( token::string, t );
3882+ PUSH_STATE( P1 );
3883+ return true;
3884+ case P1: REQUIRE_TOKEN( token::name_separator, t );
3885+ PUSH_STATE( V0 );
3886+ return true;
3887+
3888+ // <Value> ::= <Array> | <Object> | <String> | <Number>
3889+ // | false | null | true
3890+ case V0: switch ( PEEK_TOKEN() ) {
3891+ case token::begin_array:
3892+ GOTO_STATE( A0 );
3893+ case token::begin_object:
3894+ GOTO_STATE( O0 );
3895+ case token::string:
3896+ case token::number:
3897+ case token::json_false:
3898+ case token::json_null:
3899+ case token::json_true:
3900+ GET_TOKEN( t );
3901+ return true;
3902+ default:
3903+ THROW_UNEXPECTED_TOKEN( peeked_token_ );
3904+ }
3905+ } // switch ( state_ )
3906+ } // while
3907+}
3908+
3909+///////////////////////////////////////////////////////////////////////////////
3910+
3911+} // namespace json
3912+} // namespace zorba
3913+
3914+/* vim:set et sw=2 ts=2: */
3915
3916=== added file 'src/util/json_parser.h'
3917--- src/util/json_parser.h 1970-01-01 00:00:00 +0000
3918+++ src/util/json_parser.h 2012-01-23 00:53:24 +0000
3919@@ -0,0 +1,561 @@
3920+/*
3921+ * Copyright 2006-2008 The FLWOR Foundation.
3922+ *
3923+ * Licensed under the Apache License, Version 2.0 (the "License");
3924+ * you may not use this file except in compliance with the License.
3925+ * You may obtain a copy of the License at
3926+ *
3927+ * http://www.apache.org/licenses/LICENSE-2.0
3928+ *
3929+ * Unless required by applicable law or agreed to in writing, software
3930+ * distributed under the License is distributed on an "AS IS" BASIS,
3931+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3932+ * See the License for the specific language governing permissions and
3933+ * limitations under the License.
3934+ */
3935+
3936+#ifndef ZORBA_JSON_PARSER_H
3937+#define ZORBA_JSON_PARSER_H
3938+
3939+#include <zorba/config.h>
3940+
3941+#include <exception>
3942+#include <iostream>
3943+#include <stack>
3944+#include <string>
3945+
3946+#include <zorba/internal/diagnostic.h>
3947+
3948+#include "zorbatypes/zstring.h"
3949+
3950+#include "cxx_util.h"
3951+#include "unicode_util.h"
3952+
3953+namespace zorba {
3954+namespace json {
3955+
3956+///////////////////////////////////////////////////////////////////////////////
3957+
3958+typedef internal::diagnostic::location location;
3959+
3960+///////////////////////////////////////////////////////////////////////////////
3961+
3962+/**
3963+ * A JSON %type is the type of JSON data. This isn't used by the lexer or
3964+ * parser implementation at all, but it's handy.
3965+ */
3966+enum type {
3967+ none, // meaning "not set" as opposed to "null"
3968+ array,
3969+ boolean,
3970+ null,
3971+ number,
3972+ object,
3973+ string
3974+};
3975+extern char const *const type_string_of[];
3976+
3977+inline std::ostream& operator<<( std::ostream &o, type t ) {
3978+ return o << type_string_of[ t ];
3979+}
3980+
3981+/**
3982+ * A JSON %token. Tokens have a type, location at which they were found, and
3983+ * sometimes a value.
3984+ *
3985+ * See: "RFC 4627: The application/json Media Type for JavaScript Object
3986+ * Notation (JSON)."
3987+ */
3988+class token {
3989+ // see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2333.html
3990+ struct pointer_conversion { int valid; };
3991+ typedef int pointer_conversion::*explicit_bool;
3992+public:
3993+ typedef zstring value_type;
3994+
3995+ /**
3996+ * The types of tokens in JSON. The first 6 constants have values that
3997+ * correspond to the actual structural characters used by JSON; the rest were
3998+ * assigned non-standard, mnemonic values for convenience.
3999+ */
4000+ enum type {
4001+ none,
4002+ begin_array = '[',
4003+ begin_object = '{',
4004+ end_array = ']',
4005+ end_object = '}',
4006+ name_separator = ':',
4007+ value_separator = ',',
4008+ string = 'S',
4009+ number = 'N',
4010+ json_false = 'F',
4011+ json_null = '0',
4012+ json_true = 'T',
4013+ };
4014+
4015+ /**
4016+ * Default constructor.
4017+ */
4018+ token();
4019+
4020+ /**
4021+ * Clears this %token.
4022+ */
4023+ void clear() {
4024+ type_ = none;
4025+ value_.clear();
4026+ }
4027+
4028+ /**
4029+ * Gets the location at which this %token was found.
4030+ *
4031+ * @return Returns said location.
4032+ */
4033+ location const& get_loc() const {
4034+ return loc_;
4035+ }
4036+
4037+ /**
4038+ * Gets the type of this %token.
4039+ *
4040+ * @return Returns said type.
4041+ */
4042+ type get_type() const {
4043+ return type_;
4044+ }
4045+
4046+ /**
4047+ * Gets the value of this %token, if any. Only %token types string, number,
4048+ * false, null, and true have a value.
4049+ *
4050+ * @return Returns said value or the empty string.
4051+ */
4052+ value_type const& get_value() const {
4053+ return value_;
4054+ }
4055+
4056+ /**
4057+ * Conversion to \c bool.
4058+ *
4059+ * @return Returns \c true only if this token's type is not \c none.
4060+ */
4061+ operator explicit_bool() const {
4062+ return type_ ? &pointer_conversion::valid : nullptr;
4063+ }
4064+
4065+private:
4066+ location loc_;
4067+ type type_;
4068+ value_type value_;
4069+
4070+ friend class lexer;
4071+};
4072+
4073+/**
4074+ * Map a token's type to a JSON type.
4075+ *
4076+ * @param tt The token::type to map.
4077+ * @return Returns the corresponding JSON type or \c none if \a tt doesn't map.
4078+ */
4079+type map_type( token::type tt );
4080+
4081+/**
4082+ * Emits the given token type to an ostream.
4083+ *
4084+ * @param o The ostream to emit to.
4085+ * @param tt The token type to emit.
4086+ * @return Returns \a o.
4087+ */
4088+std::ostream& operator<<( std::ostream &o, token::type tt );
4089+
4090+/**
4091+ * Emits the given token to an ostream.
4092+ *
4093+ * @param o The ostream to emit to.
4094+ * @param t The token to emit.
4095+ * @return Returns \a o.
4096+ */
4097+std::ostream& operator<<( std::ostream &o, token const &t );
4098+
4099+/**
4100+ * Compares two tokens for equality.
4101+ *
4102+ * @param t1 The first token.
4103+ * @param t2 The second token.
4104+ * @return Returns \c true only if the two tokens' types and values are equal.
4105+ */
4106+inline bool operator==( token const &t1, token const &t2 ) {
4107+ return t1.get_type() == t2.get_type() && t1.get_value() == t2.get_value();
4108+}
4109+
4110+/**
4111+ * Compares a token's type to another type for equality.
4112+ *
4113+ * @param t The token whose type to compare.
4114+ * @param tt The type to compare to.
4115+ * @return Returns \c true only if the token's type equals \a tt.
4116+ */
4117+inline bool operator==( token const &t, token::type tt ) {
4118+ return t.get_type() == tt;
4119+}
4120+
4121+/**
4122+ * Compares a token's type to another type for equality.
4123+ *
4124+ * @param tt The type to compare.
4125+ * @param t The token whose type to compare to.
4126+ * @return Returns \c true only if \a tt equals the token's type.
4127+ */
4128+inline bool operator==( token::type tt, token const &t ) {
4129+ return t == tt;
4130+}
4131+
4132+/**
4133+ * Compares a token's value to a C string for equality.
4134+ *
4135+ * @param t The token whose value to compare.
4136+ * @param value The value to compare to.
4137+ * @return Returns \c true only if the token's value equals \a value.
4138+ */
4139+inline bool operator==( token const &t, char const *value ) {
4140+ return t.get_value() == value;
4141+}
4142+
4143+/**
4144+ * Compares a C string to a token's value for equality.
4145+ *
4146+ * @param value The value to compare.
4147+ * @param t The token whose value to compare to.
4148+ * @return Returns \c true only if \a value equals the token's value.
4149+ */
4150+inline bool operator==( char const *value, token const &t ) {
4151+ return t == value;
4152+}
4153+
4154+/**
4155+ * Compares two tokens for inequality.
4156+ *
4157+ * @param t1 The first token.
4158+ * @param t2 The second token.
4159+ * @return Returns \c true if either the two tokens' types or values are not
4160+ * equal.
4161+ */
4162+inline bool operator!=( token const &t1, token const &t2 ) {
4163+ return !(t1 == t2);
4164+}
4165+
4166+/**
4167+ * Compares a token's type to another type for inequality.
4168+ *
4169+ * @param t The token whose type to compare.
4170+ * @param tt The type to compare to.
4171+ * @return Returns \c true only if the token's type is not equal to \a tt.
4172+ */
4173+inline bool operator!=( token const &t, token::type tt ) {
4174+ return !(t == tt);
4175+}
4176+
4177+/**
4178+ * Compares a token's type to another type for inequality.
4179+ *
4180+ * @param tt The type to compare.
4181+ * @param t The token whose type to compare to.
4182+ * @return Returns \c true only if \a tt is not equal to the token's type.
4183+ */
4184+inline bool operator!=( token::type tt, token const &t ) {
4185+ return !(tt == t);
4186+}
4187+
4188+/**
4189+ * Compares a token's value to a C string for inequality.
4190+ *
4191+ * @param t The token whose value to compare.
4192+ * @param value The value to compare to.
4193+ * @return Returns \c true only if the token's value is not equal to \a value.
4194+ */
4195+inline bool operator!=( token const &t, char const *value ) {
4196+ return !(t == value);
4197+}
4198+
4199+/**
4200+ * Compares a token's value to a C string for inequality.
4201+ *
4202+ * @param value The value to compare.
4203+ * @param t The token whose value to compare to.
4204+ * @return Returns \c true only if \a value is not equal to the token's value.
4205+ */
4206+inline bool operator!=( char const *value, token const &t ) {
4207+ return !(value == t);
4208+}
4209+
4210+///////////////////////////////////////////////////////////////////////////////
4211+
4212+/**
4213+ * An %exception is the root of the JSON %exception hierarchy.
4214+ */
4215+class exception : public std::exception {
4216+public:
4217+ ~exception() throw();
4218+
4219+ /**
4220+ * Gets the location in the JSON source whence this exception was thrown.
4221+ */
4222+ location const& get_loc() const {
4223+ return loc_;
4224+ }
4225+
4226+ // inherited
4227+ char const* what() const throw();
4228+
4229+protected:
4230+ exception( location const &loc, std::string const &message );
4231+
4232+private:
4233+ location loc_;
4234+ std::string message_;
4235+};
4236+
4237+/**
4238+ * This exception is thrown when an illegal character is encountered in a JSON
4239+ * data stream.
4240+ */
4241+class illegal_character : public exception {
4242+public:
4243+ illegal_character( location const &loc, char c );
4244+ ~illegal_character() throw();
4245+
4246+ /**
4247+ * Gets the illegal character.
4248+ *
4249+ * @return Returns said character.
4250+ */
4251+ char get_char() const {
4252+ return c_;
4253+ }
4254+
4255+private:
4256+ char c_;
4257+};
4258+
4259+/**
4260+ * This exception is thrown when an illegal Unicode code-point escape sequence
4261+ * (\uHHHH) is encountered.
4262+ */
4263+class illegal_codepoint : public exception {
4264+public:
4265+ illegal_codepoint( location const &loc, token::value_type const &cp );
4266+ ~illegal_codepoint() throw();
4267+
4268+ /**
4269+ * Gets the illegal code-point.
4270+ *
4271+ * @return Returns said code-point.
4272+ */
4273+ token::value_type get_codepoint() const {
4274+ return codepoint_;
4275+ }
4276+
4277+private:
4278+ token::value_type codepoint_;
4279+};
4280+
4281+/**
4282+ * This exception is thrown when an illegal character follows a backslash
4283+ * (escape) within a string literal. The legal escape characters are:
4284+ * ["/\bfnrtu].
4285+ */
4286+class illegal_escape : public exception {
4287+public:
4288+ illegal_escape( location const &loc, char escape );
4289+ ~illegal_escape() throw();
4290+
4291+ /**
4292+ * Gets the illegal escape character.
4293+ *
4294+ * @return Returns said character.
4295+ */
4296+ char get_escape() const {
4297+ return esc_;
4298+ }
4299+
4300+private:
4301+ char esc_;
4302+};
4303+
4304+/**
4305+ * This exception is thrown when a literal other than \c false, \c null, or
4306+ * \c true is encountered.
4307+ */
4308+class illegal_literal : public exception {
4309+public:
4310+ illegal_literal( location const &loc );
4311+ ~illegal_literal() throw();
4312+};
4313+
4314+/**
4315+ * This exception is thrown when an illegal number is encountered.
4316+ */
4317+class illegal_number : public exception {
4318+public:
4319+ illegal_number( location const &loc );
4320+ ~illegal_number() throw();
4321+};
4322+
4323+/**
4324+ * This exception is thrown when an unexpected token is encountered.
4325+ */
4326+class unexpected_token : public exception {
4327+public:
4328+ unexpected_token( token const &t );
4329+ ~unexpected_token() throw();
4330+
4331+ /**
4332+ * Gets the unexpected token
4333+ *
4334+ * @return Returns said token.
4335+ */
4336+ token const& get_token() const {
4337+ return token_;
4338+ }
4339+
4340+private:
4341+ token token_;
4342+};
4343+
4344+/**
4345+ * This exception is thrown when an EOF is encountered before a string's
4346+ * terminating quote.
4347+ */
4348+class unterminated_string : public exception {
4349+public:
4350+ unterminated_string( location const &loc );
4351+ ~unterminated_string() throw();
4352+};
4353+
4354+///////////////////////////////////////////////////////////////////////////////
4355+
4356+/**
4357+ * A %lexer extracts JSON tokens from an istream.
4358+ */
4359+class lexer {
4360+public:
4361+ typedef location::line_type line_type;
4362+ typedef location::column_type column_type;
4363+
4364+ /**
4365+ * Constructs a %lexer on the given istream.
4366+ *
4367+ * @param in The istream to read from.
4368+ */
4369+ lexer( std::istream &in );
4370+
4371+ /**
4372+ * Gets the next token, if any.
4373+ *
4374+ * @param result A pointer to the token to get into.
4375+ * @return Returns \c true only if there was a next token.
4376+ * @throws exception upon error.
4377+ */
4378+ bool next( token *result );
4379+
4380+ /**
4381+ * Sets the file location.
4382+ *
4383+ * @param file The source file name.
4384+ * @param line The source line number.
4385+ * @param col The source column number.
4386+ */
4387+ void set_loc( char const *file, line_type line, column_type col );
4388+
4389+private:
4390+ location cur_loc() const {
4391+ return location( file_, line_, col_ );
4392+ }
4393+
4394+ bool get_char( char* = nullptr );
4395+ bool peek_char( char* );
4396+ unicode::code_point parse_codepoint();
4397+ token::type parse_literal( char, token::value_type* );
4398+ void parse_number( char, token::value_type* );
4399+ void parse_string( token::value_type* );
4400+
4401+ std::istream *in_;
4402+ std::string file_;
4403+ line_type line_;
4404+ column_type col_;
4405+ location cur_loc_;
4406+};
4407+
4408+///////////////////////////////////////////////////////////////////////////////
4409+
4410+/**
4411+ * A %parser extracts JSON tokens from an istream while checking to ensure the
4412+ * token sequence is valid.
4413+ */
4414+class parser {
4415+public:
4416+ typedef lexer::line_type line_type;
4417+ typedef lexer::column_type column_type;
4418+
4419+ /**
4420+ * Constructs a %parser on the given istream.
4421+ *
4422+ * @param in The istream to read from.
4423+ */
4424+ parser( std::istream &in );
4425+
4426+ /**
4427+ * Gets the next token, if any.
4428+ *
4429+ * @param result A pointer to the token to get into.
4430+ * @return Returns \c true only if there was a next token.
4431+ * @throws exception upon error.
4432+ */
4433+ bool next( token *result );
4434+
4435+ /**
4436+ * Sets the file location.
4437+ *
4438+ * @param file The source file name.
4439+ * @param line The source line number.
4440+ * @param col The source column number.
4441+ */
4442+ void set_loc( char const *file, line_type line, column_type col ) {
4443+ lexer_.set_loc( file, line, col );
4444+ }
4445+
4446+private:
4447+ enum state {
4448+ A0, A1, A2, // Array
4449+ E0, E1, // Element
4450+ J0, J1, // JSON
4451+ M0, M1, // Member
4452+ O0, O1, O2, // Object
4453+ P0, P1, // Pair
4454+ V0 // Value
4455+ };
4456+
4457+ friend std::ostream& operator<<( std::ostream&, state );
4458+
4459+ bool get_token( token* );
4460+ bool get_token_debug( int, token* );
4461+ bool matches_token( token::type, token* );
4462+ bool matches_token_debug( int, token::type, token* );
4463+ token::type peek_token();
4464+ token::type peek_token_debug( int );
4465+ void require_token( token::type, token* );
4466+ void require_token_debug( int, token::type, token* );
4467+
4468+ lexer lexer_;
4469+ token peeked_token_;
4470+ std::stack<state> state_stack_;
4471+ state state_;
4472+};
4473+
4474+///////////////////////////////////////////////////////////////////////////////
4475+
4476+} // namespace json
4477+} // namespace zorba
4478+
4479+#endif /* ZORBA_JSON_PARSER_H */
4480+/* vim:set et sw=2 ts=2: */
4481
4482=== added file 'src/util/mem_streambuf.cpp'
4483--- src/util/mem_streambuf.cpp 1970-01-01 00:00:00 +0000
4484+++ src/util/mem_streambuf.cpp 2012-01-23 00:53:24 +0000
4485@@ -0,0 +1,119 @@
4486+/*
4487+ * Copyright 2006-2008 The FLWOR Foundation.
4488+ *
4489+ * Licensed under the Apache License, Version 2.0 (the "License");
4490+ * you may not use this file except in compliance with the License.
4491+ * You may obtain a copy of the License at
4492+ *
4493+ * http://www.apache.org/licenses/LICENSE-2.0
4494+ *
4495+ * Unless required by applicable law or agreed to in writing, software
4496+ * distributed under the License is distributed on an "AS IS" BASIS,
4497+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4498+ * See the License for the specific language governing permissions and
4499+ * limitations under the License.
4500+ */
4501+
4502+#include <cstring> /* for memcpy(3) */
4503+
4504+#include "diagnostics/assert.h"
4505+
4506+#include "cxx_util.h"
4507+#include "mem_streambuf.h"
4508+
4509+using namespace std;
4510+
4511+namespace zorba {
4512+
4513+///////////////////////////////////////////////////////////////////////////////
4514+
4515+mem_streambuf::mem_streambuf() {
4516+ set( nullptr, nullptr );
4517+}
4518+
4519+mem_streambuf::mem_streambuf( char_type *begin, char_type *end ) {
4520+ set( begin, end );
4521+}
4522+
4523+mem_streambuf::mem_streambuf( char_type *begin, off_type size ) {
4524+ set( begin, size );
4525+}
4526+
4527+mem_streambuf::int_type mem_streambuf::overflow( int_type c ) {
4528+ if ( traits_type::eq_int_type( c, traits_type::eof() ) )
4529+ return traits_type::not_eof( c );
4530+ if ( pptr() >= epptr() )
4531+ return traits_type::eof();
4532+ *pptr() = traits_type::to_char_type( c );
4533+ pbump( 1 );
4534+ return c;
4535+}
4536+
4537+mem_streambuf::int_type mem_streambuf::pbackfail( int_type c ) {
4538+ if ( !traits_type::eq_int_type( c, traits_type::eof() ) ) {
4539+ *pptr() = traits_type::to_int_type( c );
4540+ pbump( -1 );
4541+ }
4542+ return traits_type::to_int_type( *pptr() );
4543+}
4544+
4545+mem_streambuf::pos_type mem_streambuf::seekoff( off_type off,
4546+ ios_base::seekdir dir,
4547+ ios_base::openmode ) {
4548+ switch ( dir ) {
4549+ case ios_base::beg:
4550+ our_setg( begin_ + off );
4551+ break;
4552+ case ios_base::cur:
4553+ our_setg( gptr() + off );
4554+ break;
4555+ case ios_base::end:
4556+ our_setg( end_ + off );
4557+ break;
4558+ default:
4559+ ZORBA_ASSERT( false );
4560+ }
4561+ return off;
4562+}
4563+
4564+mem_streambuf::pos_type mem_streambuf::seekpos( pos_type pos,
4565+ ios_base::openmode mode ) {
4566+ return seekoff( pos, ios_base::beg, mode );
4567+}
4568+
4569+void mem_streambuf::set( char_type *begin, char_type *end ) {
4570+ begin_ = begin;
4571+ end_ = end;
4572+ our_setg( begin );
4573+ our_setp( end );
4574+}
4575+
4576+streamsize mem_streambuf::showmanyc() {
4577+ return egptr() - gptr();
4578+}
4579+
4580+mem_streambuf::int_type mem_streambuf::underflow() {
4581+ return gptr() < egptr() ?
4582+ traits_type::to_int_type( *gptr() ) : traits_type::eof();
4583+}
4584+
4585+streamsize mem_streambuf::xsgetn( char_type *buf, std::streamsize size ) {
4586+ streamsize const remaining = showmanyc();
4587+ if ( size > remaining )
4588+ size = remaining;
4589+ ::memcpy( buf, gptr(), size );
4590+ return size;
4591+}
4592+
4593+streamsize mem_streambuf::xsputn( char_type const *buf, streamsize size ) {
4594+ streamsize const remaining = epptr() - pptr();
4595+ if ( size > remaining )
4596+ size = remaining;
4597+ ::memcpy( pptr(), buf, size );
4598+ return size;
4599+}
4600+
4601+///////////////////////////////////////////////////////////////////////////////
4602+
4603+} // namespace zorba
4604+/* vim:set et sw=2 ts=2: */
4605
4606=== added file 'src/util/mem_streambuf.h'
4607--- src/util/mem_streambuf.h 1970-01-01 00:00:00 +0000
4608+++ src/util/mem_streambuf.h 2012-01-23 00:53:24 +0000
4609@@ -0,0 +1,108 @@
4610+/*
4611+ * Copyright 2006-2008 The FLWOR Foundation.
4612+ *
4613+ * Licensed under the Apache License, Version 2.0 (the "License");
4614+ * you may not use this file except in compliance with the License.
4615+ * You may obtain a copy of the License at
4616+ *
4617+ * http://www.apache.org/licenses/LICENSE-2.0
4618+ *
4619+ * Unless required by applicable law or agreed to in writing, software
4620+ * distributed under the License is distributed on an "AS IS" BASIS,
4621+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4622+ * See the License for the specific language governing permissions and
4623+ * limitations under the License.
4624+ */
4625+
4626+#ifndef ZORBA_MMAP_STREAMBUF_H
4627+#define ZORBA_MMAP_STREAMBUF_H
4628+
4629+#include <streambuf>
4630+
4631+namespace zorba {
4632+
4633+///////////////////////////////////////////////////////////////////////////////
4634+
4635+/**
4636+ * A %mem_streambuf is-a std::streambuf for a fixed-size chunk of memory.
4637+ */
4638+class mem_streambuf : public std::streambuf {
4639+public:
4640+ typedef std::streambuf::char_type char_type;
4641+ typedef std::streambuf::int_type int_type;
4642+ typedef std::streambuf::off_type off_type;
4643+ typedef std::streambuf::pos_type pos_type;
4644+ typedef std::streambuf::traits_type traits_type;
4645+
4646+ /**
4647+ * Default constructor.
4648+ */
4649+ mem_streambuf();
4650+
4651+ /**
4652+ * Constructs a %mem_streambuf.
4653+ *
4654+ * @param begin A pointer to the beginning of the memory chunk.
4655+ * @param end A pointer to one past the end of the memory chunk.
4656+ */
4657+ mem_streambuf( char_type *begin, char_type *end );
4658+
4659+ /**
4660+ * Constructs a %mem_streambuf.
4661+ *
4662+ * @param begin A pointer to the beginning of the memory chunk.
4663+ * @param size The size of the memory chunk.
4664+ */
4665+ mem_streambuf( char_type *begin, off_type size );
4666+
4667+ /**
4668+ * Sets the memory chunk.
4669+ *
4670+ * @param begin A pointer to the beginning of the memory chunk.
4671+ * @param end A pointer to one past the end of the memory chunk.
4672+ */
4673+ void set( char_type *begin, char_type *end );
4674+
4675+ /**
4676+ * Sets the memory chunk.
4677+ *
4678+ * @param begin A pointer to the beginning of the memory chunk.
4679+ * @param size The size of the memory chunk.
4680+ */
4681+ void set( char_type *begin, off_type size );
4682+
4683+protected:
4684+ int_type overflow( int_type c );
4685+ int_type pbackfail( int_type c );
4686+ pos_type seekoff( off_type, std::ios_base::seekdir, std::ios_base::openmode );
4687+ pos_type seekpos( pos_type, std::ios_base::openmode );
4688+ std::streamsize showmanyc();
4689+ int_type underflow();
4690+ std::streamsize xsgetn( char_type*, std::streamsize );
4691+ std::streamsize xsputn( char_type const*, std::streamsize );
4692+
4693+private:
4694+ char_type *begin_, *end_;
4695+
4696+ void our_setg( char_type *ptr ) {
4697+ setg( begin_, ptr, end_ );
4698+ }
4699+
4700+ void our_setp( char_type *ptr ) {
4701+ setp( ptr, end_ );
4702+ }
4703+
4704+ // forbid
4705+ mem_streambuf( mem_streambuf const& );
4706+ mem_streambuf& operator=( mem_streambuf const& );
4707+};
4708+
4709+inline void mem_streambuf::set( char_type *begin, off_type size ) {
4710+ set( begin, begin + size );
4711+}
4712+
4713+///////////////////////////////////////////////////////////////////////////////
4714+
4715+} // namespace zorba
4716+#endif /* ZORBA_MMAP_STREAMBUF_H */
4717+/* vim:set et sw=2 ts=2: */
4718
4719=== modified file 'src/util/omanip.h'
4720--- src/util/omanip.h 2011-06-14 17:26:33 +0000
4721+++ src/util/omanip.h 2012-01-23 00:53:24 +0000
4722@@ -25,127 +25,275 @@
4723 ///////////////////////////////////////////////////////////////////////////////
4724
4725 /**
4726- * An omanip1 is a class for assisting in the creation of ostream manipulators
4727+ * An %omanip1 is a class for assisting in the creation of ostream manipulators
4728 * by storing a pointer to a function and its argument to be called later via
4729 * operator<<().
4730 *
4731 * See also: "Standard C++ IOStreams and Locales," Angelika Langer and Klaus
4732 * Kreft, Addison-Wesley, pp. 179-191.
4733 */
4734-template<typename Arg1Type> class omanip1 {
4735+template<typename Arg1Type>
4736+class omanip1 {
4737 public:
4738
4739 /**
4740- * The signature of functions this omanip1 can handle.
4741+ * The signature of functions this %omanip1 can handle.
4742 */
4743 typedef std::ostream& (*func_type)( std::ostream&, Arg1Type );
4744
4745 /**
4746- * Constructs an omanip1.
4747+ * Constructs an %omanip1.
4748 *
4749- * @param f The function to call when this omanip1 is inserted into an
4750- * ostream.
4751- * @param arg1 The argument to be passed to the function.
4752+ * @param f The function to call when this %omanip1 is inserted into an
4753+ * ostream.
4754+ * @param a1 The argument to be passed to the function.
4755 */
4756- omanip1( func_type f, Arg1Type arg1 ) :
4757- f_( f ), arg1_( arg1 )
4758+ omanip1( func_type f, Arg1Type a1 ) :
4759+ f_( f ), a1_( a1 )
4760 {
4761 }
4762
4763 /**
4764- * Inserts the given omanip1 into the given ostream. This has the effect of
4765- * calling the function and argument bound to the omanip1 at the time of its
4766+ * Inserts the given %omanip1 into the given ostream. This has the effect of
4767+ * calling the function and argument bound to the %omanip1 at the time of its
4768 * construction.
4769 *
4770 * @param o The ostream to insert into.
4771- * @param m The omanip1 to insert.
4772+ * @param m The %omanip1 to insert.
4773 */
4774 friend std::ostream& operator<<( std::ostream &o, omanip1 const &m ) {
4775- return (*m.f_)( o, m.arg1_ );
4776+ if ( o.good() )
4777+ (*m.f_)( o, m.a1_ );
4778+ return o;
4779 }
4780
4781 private:
4782 func_type const f_;
4783- Arg1Type const arg1_;
4784+ Arg1Type const a1_;
4785 };
4786
4787 /**
4788 * Defines an ostream manipulator "thunk" function that calls an existing
4789 * non-manipulator function having the same name.
4790 *
4791- * @param FN_NAME The name of the existing function.
4792- * @param ARG1_TYPE The type of the non-ostream argument.
4793- * @param ARG1_NAME The name of the non-ostream argument.
4794+ * @param FN_NAME The name of the existing function.
4795+ * @param ARG1_T The type of the non-ostream argument.
4796 */
4797-#define DEF_OMANIP1(FN_NAME,ARG1_TYPE,ARG1_NAME) \
4798- inline omanip1<ARG1_TYPE> \
4799- FN_NAME( ARG1_TYPE ARG1_NAME ) { \
4800- return omanip1<ARG1_TYPE>( FN_NAME, ARG1_NAME ); \
4801+#define DEF_OMANIP1(FN_NAME,ARG1_T) \
4802+ inline omanip1<ARG1_T> \
4803+ FN_NAME( ARG1_T a1 ) { \
4804+ return omanip1<ARG1_T>( FN_NAME, a1 ); \
4805 }
4806
4807 ///////////////////////////////////////////////////////////////////////////////
4808
4809 /**
4810- * An omanip2 is a class for assisting in the creation of ostream manipulators
4811+ * An %omanip2 is a class for assisting in the creation of ostream manipulators
4812 * by storing a pointer to a function and its arguments to be called later via
4813 * operator<<().
4814 *
4815 * See also: "Standard C++ IOStreams and Locales," Angelika Langer and Klaus
4816 * Kreft, Addison-Wesley, pp. 179-191.
4817 */
4818-template<typename Arg1Type, typename Arg2Type> class omanip2 {
4819+template<typename Arg1Type,typename Arg2Type>
4820+class omanip2 {
4821 public:
4822
4823 /**
4824- * The signature of functions this omanip2 can handle.
4825+ * The signature of functions this %omanip2 can handle.
4826 */
4827 typedef std::ostream& (*func_type)( std::ostream&, Arg1Type, Arg2Type );
4828
4829 /**
4830- * Constructs an omanip2.
4831+ * Constructs an %omanip2.
4832 *
4833- * @param f The function to call when this omanip2 is inserted into an
4834- * ostream.
4835- * @param arg1 The first argument to be passed to the function.
4836- * @param arg2 The second argument to be passed to the function.
4837+ * @param f The function to call when this %omanip2 is inserted into an
4838+ * ostream.
4839+ * @param a1 The first argument to be passed to the function.
4840+ * @param a2 The second argument to be passed to the function.
4841 */
4842- omanip2( func_type f, Arg1Type arg1, Arg2Type arg2 ) :
4843- f_( f ), arg1_( arg1 ), arg2_( arg2 )
4844+ omanip2( func_type f, Arg1Type a1, Arg2Type a2 ) :
4845+ f_( f ), a1_( a1 ), a2_( a2 )
4846 {
4847 }
4848
4849 /**
4850- * Inserts the given omanip2 into the given ostream. This has the effect of
4851- * calling the function and argument bound to the omanip2 at the time of its
4852+ * Inserts the given %omanip2 into the given ostream. This has the effect of
4853+ * calling the function and argument bound to the %omanip2 at the time of its
4854 * construction.
4855 *
4856 * @param o The ostream to insert into.
4857- * @param m The omanip2 to insert.
4858+ * @param m The %omanip2 to insert.
4859 */
4860 friend std::ostream& operator<<( std::ostream &o, omanip2 const &m ) {
4861- return (*m.f_)( o, m.arg1_, m.arg2_ );
4862- }
4863-
4864-private:
4865- func_type const f_;
4866- Arg1Type const arg1_;
4867- Arg2Type const arg2_;
4868-};
4869-
4870-/**
4871- * Defines an ostream manipulator "thunk" function that calls an existing
4872- * non-manipulator function having the same name.
4873- *
4874- * @param FN_NAME The name of the existing function.
4875- * @param ARG1_TYPE The type of the first non-ostream argument.
4876- * @param ARG1_NAME The name of the first non-ostream argument.
4877- * @param ARG2_TYPE The type of the second non-ostream argument.
4878- * @param ARG2_NAME The name of the second non-ostream argument.
4879- */
4880-#define DEF_OMANIP2(FN_NAME,ARG1_TYPE,ARG1_NAME,ARG2_TYPE,ARG2_NAME) \
4881- inline omanip2<ARG1_TYPE,ARG2_TYPE> \
4882- FN_NAME( ARG1_TYPE ARG1_NAME, ARG2_TYPE ARG2_NAME ) { \
4883- return omanip2<ARG1_TYPE,ARG2_TYPE>( FN_NAME, ARG1_NAME, ARG2_NAME ); \
4884+ if ( o.good() )
4885+ (*m.f_)( o, m.a1_, m.a2_ );
4886+ return o;
4887+ }
4888+
4889+private:
4890+ func_type const f_;
4891+ Arg1Type const a1_;
4892+ Arg2Type const a2_;
4893+};
4894+
4895+/**
4896+ * Defines an ostream manipulator "thunk" function that calls an existing
4897+ * non-manipulator function having the same name.
4898+ *
4899+ * @param FN_NAME The name of the existing function.
4900+ * @param ARG1_T The type of the first non-ostream argument.
4901+ * @param ARG2_T The type of the second non-ostream argument.
4902+ */
4903+#define DEF_OMANIP2(FN_NAME,ARG1_T,ARG2_T) \
4904+ inline omanip2<ARG1_T,ARG2_T> \
4905+ FN_NAME( ARG1_T a1, ARG2_T a2 ) { \
4906+ return omanip2<ARG1_T,ARG2_T>( FN_NAME, a1, a2 ); \
4907+ }
4908+
4909+///////////////////////////////////////////////////////////////////////////////
4910+
4911+/**
4912+ * An %omanip3 is a class for assisting in the creation of ostream manipulators
4913+ * by storing a pointer to a function and its arguments to be called later via
4914+ * operator<<().
4915+ *
4916+ * See also: "Standard C++ IOStreams and Locales," Angelika Langer and Klaus
4917+ * Kreft, Addison-Wesley, pp. 179-191.
4918+ */
4919+template<typename Arg1Type,typename Arg2Type,typename Arg3Type>
4920+class omanip3 {
4921+public:
4922+
4923+ /**
4924+ * The signature of functions this %omanip3 can handle.
4925+ */
4926+ typedef std::ostream& (*func_type)( std::ostream&, Arg1Type, Arg2Type,
4927+ Arg3Type );
4928+
4929+ /**
4930+ * Constructs an %omanip3.
4931+ *
4932+ * @param f The function to call when this %omanip3 is inserted into an
4933+ * ostream.
4934+ * @param a1 The first argument to be passed to the function.
4935+ * @param a2 The second argument to be passed to the function.
4936+ * @param a3 The third argument to be passed to the function.
4937+ */
4938+ omanip3( func_type f, Arg1Type a1, Arg2Type a2, Arg3Type a3 ) :
4939+ f_( f ), a1_( a1 ), a2_( a2 ), a3_( a3 )
4940+ {
4941+ }
4942+
4943+ /**
4944+ * Inserts the given %omanip3 into the given ostream. This has the effect of
4945+ * calling the function and argument bound to the %omanip3 at the time of its
4946+ * construction.
4947+ *
4948+ * @param o The ostream to insert into.
4949+ * @param m The %omanip3 to insert.
4950+ */
4951+ friend std::ostream& operator<<( std::ostream &o, omanip3 const &m ) {
4952+ if ( o.good() )
4953+ (*m.f_)( o, m.a1_, m.a2_, m.a3_ );
4954+ return o;
4955+ }
4956+
4957+private:
4958+ func_type const f_;
4959+ Arg1Type const a1_;
4960+ Arg2Type const a2_;
4961+ Arg3Type const a3_;
4962+};
4963+
4964+/**
4965+ * Defines an ostream manipulator "thunk" function that calls an existing
4966+ * non-manipulator function having the same name.
4967+ *
4968+ * @param FN_NAME The name of the existing function.
4969+ * @param ARG1_T The type of the first non-ostream argument.
4970+ * @param ARG2_T The type of the second non-ostream argument.
4971+ * @param ARG3_T The type of the third non-ostream argument.
4972+ */
4973+#define DEF_OMANIP3(FN_NAME,ARG1_T,ARG2_T,ARG3_T) \
4974+ inline omanip3<ARG1_T,ARG2_T,ARG3_T> \
4975+ FN_NAME( ARG1_T a1, ARG2_T a2, ARG3_T a3 ) { \
4976+ return omanip3<ARG1_T,ARG2_T,ARG3_T>( FN_NAME, a1, a2, a3 ); \
4977+ }
4978+
4979+///////////////////////////////////////////////////////////////////////////////
4980+
4981+/**
4982+ * An %omanip4 is a class for assisting in the creation of ostream manipulators
4983+ * by storing a pointer to a function and its arguments to be called later via
4984+ * operator<<().
4985+ *
4986+ * See also: "Standard C++ IOStreams and Locales," Angelika Langer and Klaus
4987+ * Kreft, Addison-Wesley, pp. 179-191.
4988+ */
4989+template<
4990+ typename Arg1Type,typename Arg2Type,typename Arg3Type,typename Arg4Type
4991+>
4992+class omanip4 {
4993+public:
4994+
4995+ /**
4996+ * The signature of functions this %omanip4 can handle.
4997+ */
4998+ typedef std::ostream& (*func_type)( std::ostream&, Arg1Type, Arg2Type,
4999+ Arg3Type, Arg4Type );
5000+
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches