diff --git a/contrib/library/text/parser/json/.gitattributes b/contrib/library/text/parser/json/.gitattributes index 15e47090..4d7d0158 100644 --- a/contrib/library/text/parser/json/.gitattributes +++ b/contrib/library/text/parser/json/.gitattributes @@ -7,3 +7,4 @@ *.ecf text *.bat text *.json text +*.txt text diff --git a/contrib/library/text/parser/json/.gitignore b/contrib/library/text/parser/json/.gitignore index a1ff1e86..3702d5e1 100644 --- a/contrib/library/text/parser/json/.gitignore +++ b/contrib/library/text/parser/json/.gitignore @@ -1,2 +1,2 @@ *.swp -EIFGENs +EIFGENs/ diff --git a/contrib/library/text/parser/json/History.txt b/contrib/library/text/parser/json/History.txt index 5cf7f2ec..96ec4ab0 100644 --- a/contrib/library/text/parser/json/History.txt +++ b/contrib/library/text/parser/json/History.txt @@ -1,10 +1,12 @@ -History file for EJSON +History file for EJSON ====================== team: "" date: "2011-07-06" revision: "0.3.0" +WARNING: THIS FILE IS NOT UP TO DATE + +++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++ @@ -23,4 +25,4 @@ implementation. *Added converters and factory classes -*Added new top level directories; library, test, build and example \ No newline at end of file +*Added new top level directories; library, test, build and example diff --git a/contrib/library/text/parser/json/License.txt b/contrib/library/text/parser/json/License.txt index 1c17b708..36d303a0 100644 --- a/contrib/library/text/parser/json/License.txt +++ b/contrib/library/text/parser/json/License.txt @@ -1,4 +1,5 @@ -Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch +Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others, +https://github.com/eiffelhub/json . Permission is hereby granted, free of charge, to any person obtaining a copy @@ -6,10 +7,10 @@ of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -17,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/contrib/library/text/parser/json/Readme.txt b/contrib/library/text/parser/json/Readme.txt index c0085d5d..44f30cb7 100644 --- a/contrib/library/text/parser/json/Readme.txt +++ b/contrib/library/text/parser/json/Readme.txt @@ -1,21 +1,26 @@ Readme file for eJSON ===================== -team: "Javier Velilla,Jocelyn Fiat, Paul Cohen" -date: "$Date$" -revision: "$Revision$" +team: "Javier Velilla, Jocelyn Fiat" +previous contributors: "Paul Cohen" +date: "2014-nov-17" 1. Introduction --------------- eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing -with the JSON format. The objective of the library is to provide two basic -features Eiffel2JSON and JSON2Eiffel. +with the JSON format. This library provides a JSON parser and visitors, +including a pretty printer. + +The converters part is now obsolete and not recommended (remember: the +objective of converters were to provide two basic features Eiffel2JSON and +JSON2Eiffel). There will be a new design for converters as a standalone +library on top of Current json library. 2. Legal stuff -------------- -eJSON is copyrighted by the author Javier Velilla and others. It is licensed +eJSON is copyrighted by the author Javier Velilla, Jocelyn Fiat and others. It is licensed under the MIT License. See the file license.txt in the same directory as this readme file. @@ -46,18 +51,18 @@ Currently the only documentation on eJSON is available at: EJSON requires that you have: -1. Gobo 3.9 installed or later -2. One of the following compiler combinations installed: - * ISE Eiffel 6.5 or later. +1. One of the following compiler combinations installed: + * ISE Eiffel 13.11 or later. * gec [try to test] - * tecomp [try to test] eJSON probably works fine with other versions of the above compilers. There are no known platform dependencies (Windows, Linux). To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate place on your hard disk. There are no requirements on environment variables or -registry variables. +registry variables. +Note eJSON is also delivered within EiffelStudio release, under +$ISE_LIBRARY/contrib/library/text/parser/json To verify that everything works you should compile the example programs and/or the test program. @@ -70,18 +75,18 @@ installation. Directory Description --------- ----------- -doc Contains the eJSON.pdf documentation file. -examples Contains the two example programs. -ejson Contains the actual eJSON library classes. -test Contains a test program for eJSON. +doc Contains documentation file. +examples Contains example codes. +library Contains the actual eJSON library classes. +test Contains test suite for eJSON. 7. Contacting the Team ---------------------- Contact the team: + https://github.com/eiffelhub/json/issues Javier Velilla «javier.hector@gmail.com» - Paul Cohen «paco@seibostudios.se» Jocelyn Fiat «jfiat@eiffel.com» 8. Releases @@ -92,8 +97,16 @@ history.txt. Version Date Description ------- ---- ----------- +0.6.0 2014-11-17 Fixed various issue with parsing string (such as \t and related), + Implemented escaping of slash '/' only in case of ' + Many feature renaming to match Eiffel style and naming convention, + kept previous feature as obsolete. + Restructured the library to make easy extraction of "converter" + classes if needed in the future. + Marked converters classes as obsolete. 0.5.0 2013-11-dd Added JSON_ITERATOR, simplified JSON_OBJECT 0.4.0 2012-12-12 Updated documentation URI 0.3.0 2011-07-06 JSON Factory Converters 0.2.0 2010-02-07 Adapted to EiffelStudio 6.4 or later, supports void-safety -0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous \ No newline at end of file +0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous diff --git a/contrib/library/text/parser/json/doc/user_guide.mediawiki b/contrib/library/text/parser/json/doc/user_guide.mediawiki new file mode 100644 index 00000000..c4ab9b3e --- /dev/null +++ b/contrib/library/text/parser/json/doc/user_guide.mediawiki @@ -0,0 +1,295 @@ +== Preface == + +This document is a living document! As always read and try out the code to understand what's really going on. + +=== About the project === + +The eJSON project was started by Javier Velilla in 2008. The aim was simply to +provide JSON support to Eiffel programmers. A couple of other people have been +involved to various extent since the start; Berend de Boer, Jocelyn Fiat and +Manu Stapf. In 2009 Paul Cohen joined the project as an active developer and +later Jocelyn Fiat. + +The current active maintainers: +- Javier Velilla +- Jocelyn Fiat + +The formal name of the project is “eJSON”. + +For questions regarding eJSON please contact +- +- +- or directly on [https://github.com/eiffelhub/json/issues] + +=== Current version and status === + +The latest release is 0.6.0. eJSON has been improved and cleaned. +The converters are not obsolete. + + +== Introduction == + +=== What is JSON? === + +JSON (JavaScript Object Notation) is a lightweight computer data interchange format. It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects). See the [http://en.wikipedia.org/wiki/JSON Wikipedia article on JSON], [http://www.json.org www.json.org] and [http://www.json.com www.json.com] for more information. + +The JSON format is specified in [http://www.ietf.org/rfc/rfc4627.txt IETF RFC 4627] by Douglas Crockford. The official [http://www.iana.org/assignments/media-types Internet MIME media type] for JSON is "application/json". The recommended file name extension for JSON files is ".json". + +=== Advantages === + +1. Lightweight data-interchange format. +2. Easy for humans to read and write. +3. Enables easy integration with AJAX/JavaScript web applications. See the article [http://www.developer.com/lang/jscript/article.php/3596836 Speeding Up AJAX with JSON] for a good short discussion on this subject. +4. JSON data structures translate with ease into the native data structures universal to almost all programming languages used today. + +=== Use in Eiffel applications === + +JSON can be used as a general serialization format for Eiffel objects. As such it could be used as a: + +* Data representation format in REST-based web service applications written in Eiffel. +* Serialization format for Eiffel objects in persistence solutions. +* File format for configuration files in Eiffel systems. + +=== Prerequisites === + +eJSON works today with EiffelStudio 13.11 +There is an optional extension that requires the latest snapshot of the Gobo Eiffel libraries (a working snapshot is distributed with EiffelStudio). The depencencies on Gobo are on Gobo's unicode +and regex libraries and for some of the extra features in eJSON, on Gobos structure classes DS_HASH_TABLE and DS_LINKED_LIST. + +eJSON is intended to work with all ECMA compliant Eiffel compilers. + +=== Installation === + +You can either download a given release and install on your machine or you can get the latest snapshot of the code. +To download go to the [http://ejson.origo.ethz.ch/download download page]. +To get the latest snapshot of the code do: + +: $ git clone https://github.com/eiffelhub/json.git json + +*[https://github.com/eiffelhub/json/releases download page] +*[https://github.com/eiffelhub/json github project] + +Note that the latest json release is also delivered with EiffelStudio installation under $ISE_LIBRARY/contrib/library/text/parser/json. + + +=== Cluster and directory layout === + + json/ + library/ (Root directory for eJSON library classes) + kernel/ (All classes in this cluster should eventually only depend on ECMA Eiffel and FreeELKS). + json_array.e + json_boolean.e + json_null.e + json_number.e + json_object.e + json_string.e + json_value.e + parser/ + json_parser.e + json_parser_access.e + json_reader.e + json_tokens.e + utility/ + file/ + json_file_reader.e + visitor/ + json_visitor.e + json_iterator.e + json_pretty_string_visitor.e + print_json_visitor.e + converters/ (JSON core converter classes !OBSOLETE!) + json_converter.e + json_hash_table_converter.e + json_list_converter.e + json_linked_list_converter.e + json_arrayed_list_converter.e + support/ + ejson.e + shared_ejson.e + gobo_converters/ (JSON core converter classes support for GOBO !OBSOLETE!) + converters/ + json_ds_hash_table_converter.e + json_ds_linked_list_converter.e + shared_gobo_ejson.e + test/ (Contains autotest suite) + autotest/ (AutoTest based unit test). + examples/ (Example code) + +=== Future development === + +Here is a list of suggestions for future development of eJSON. +* Ongoing: Provide a JSON_FACTORY class for easy conversion between arbitrary JSON and Eiffel values. +* Ongoing: Provide a mechanism for users to add custom converters between JSON values and user space Eiffel classes. +* Ongoing: Implement a full test framework for eJSON. +* Suggestion: Investigate performance and improve it if neccessary. +* Suggestion: Support JSON references. See [http://www.json.com/2007/10/19/json-referencing-proposal-and-library JSON Referencing Proposal and Library] and [http://www.sitepen.com/blog/2008/06/17/json-referencing-in-dojo JSON referencing in Dojo] for more information. +* Suggestion: Support JSON path. See [http://goessner.net/articles/JsonPath JSONPath - XPath for JSON] for more information. +* Suggestion: Support JSON schema validation. See [http://json-schema.org JSON Schema Proposal] for more information. +* Suggestion: Support RDF JSON serialization. See [http://n2.talis.com/wiki/RDF_JSON_Specification RDF JSON Specification] for more information. +* Suggestion: Add support to JSON classes for conversion from Eiffel manifest values. So one can write things like: + +== A simple example == + +There are two basic approaches to using eJSON; either you use the basic JSON_VALUE classes, converting to and from JSON values to corresponding Eiffel instances or you use the high level eJSON interface class SHARED_EJSON. Of course you can use a mix of both approaches if you find it appropriate! + +Here is an example of how to create a JSON number value from an INTEGER and then obtain the JSON representation for that value. + + simple_example is + local + i: INTEGER + jn: JSON_NUMBER + s: STRING + do + i := 42 + create jn.make_integer (i) + s := jn.representation -- s.is_equal ("42") + end + +== Mapping of JSON values to Eiffel values == + +=== JSON number === + +JSON numbers are represented by the class JSON_NUMBER. JSON number values can be converted to/from NATURAL_*, INTEGER_* and REAL_64 values. For floating point values REAL_* is used. The complete mapping is as follows: + +JSON number -> Eiffel: +* -128 <= n <= +127 -> INTEGER_8 +* n can't be represented by INTEGER_8 and -32768 <= n <= +32767 -> INTEGER_16 +* n can't be represented by INTEGER_16 and -2147483648 <= n <= +2147483647 -> INTEGER_32 +* n can't be represented by INTEGER_32 and -9223372036854775808 <= n <= +9223372036854775807 -> INTEGER_64 +* n can't be represented by INTEGER_64 and 9223372036854775808 <= n <= 18446744073709551615 -> NATURAL_64 +* n has fractional dot '.' -> REAL_64. +* n -> eJSON exception if number can't be represented by a INTEGER_64, NATURAL_64 or REAL_64. + +Eiffel -> JSON number: +* NATURAL_8, NATURAL_16, NATURAL_32, NATURAL_64, NATURAL -> JSON number +* INTEGER_8, INTEGER_16, INTEGER_32, INTEGER_64, INTEGER -> JSON number +* REAL_32, REAL_64, REAL -> JSON number + +You can use the following creation routines to create JSON_NUMBER instances: + +* JSON_NUMBER.make_integer +* JSON_NUMBER.make_real +* JSON_NUMBER.make_natural + + eiffel_to_json_number_representation is + local + i: INTEGER + r: REAL + jn: JSON_NUMBER + do + print ("JSON representation of Eiffel INTEGER: '") + i := 123 + create jn.make_integer (i) + print (jn.representation) + print ("'%N") + print ("JSON representation of Eiffel REAL: '") + r := 12.3 + create jn.make_real (r) + print (jn.representation) + print ("'%N") + end + +The output of the above code will be: + + JSON representation of Eiffel INTEGER: '123' + JSON representation of Eiffel REAL: '12.300000190734863' + +=== JSON boolean === + +JSON boolean values are represented by the class JSON_BOOLEAN. The JSON boolean value "true" is converted to/from the BOOLEAN value "True" and the JSON boolean value "false is converted to/from the BOOLEAN value "False". + + eiffel_to_json_boolean_representation is + local + b: BOOLEAN + jb: JSON_BOOLEAN + do + print ("JSON representation of Eiffel BOOLEAN: '") + b := True + create jb.make (b) + print (jb.representation) + print ("'%N") + print("JSON representation of Eiffel BOOLEAN: '") + b := False + create jb.make (b) + print (jb.representation) + print ("'%N") + end + +The output of the above code will be: + + JSON representation of Eiffel BOOLEAN: 'true' + JSON representation of Eiffel BOOLEAN: 'false' + +=== JSON string === + +JSON strings are represented by the class JSON_STRING. JSON string values can be converted to/from STRING_32, STRING and CHARACTER values. The complete mapping is as follows: + +JSON string -> Eiffel: +* All JSON strings -> STRING or STRING_32 + +Eiffel -> JSON string: +* STRING_32 -> JSON string +* STRING -> JSON string +* CHARACTER -> JSON string + + eiffel_to_json_string_representation is + local + s: STRING + js: JSON_STRING + do + print ("JSON representation of Eiffel STRING: '") + s := "JSON rocks!" + create js.make_from_string (s) + print (js.representation) + print ("'%N") + end + +The output of the above code will be: + + JSON representation of Eiffel STRING: '"JSON rocks!"' + +Note: JSON escape unicode characters, as well a other specific characters, to get the unescaped string value, use either 'unescaped_string_8' or 'unescaped_string_32'. + +=== JSON null === + +The JSON null value is represented by the class JSON_NULL. The JSON null value can be converted to/from Void. + + eiffel_to_json_null_representation is + local + a: ANY + jn: JSON_NULL + do + create jn + print ("JSON representation for JSON null value: '") + print (jn.representation) + print ("'%N") + a := Void + if attached {JSON_NULL} json.value (a) as l_jn then -- json from SHARED_EJSON! + print ("JSON representation of Eiffel Void reference: '") + print (l_jn.representation) + print ("'%N") + end + end + +The output of the above code will be: + + JSON representation for JSON null value: 'null' + JSON representation of Eiffel Void reference: 'null' + +=== JSON array === + +JSON array is represented by the class JSON_ARRAY. + +=== JSON object === + +JSON object is represented by the class JSON_OBJECT. + + +== The eJSON visitor pattern == + +TBD. See examples. + +== The eJSON file reader class == + +TBD. + diff --git a/contrib/library/text/parser/json/examples/basic/basic.e b/contrib/library/text/parser/json/examples/basic/basic.e new file mode 100644 index 00000000..52520394 --- /dev/null +++ b/contrib/library/text/parser/json/examples/basic/basic.e @@ -0,0 +1,83 @@ +class + BASIC + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize `Current'. + local + parser: JSON_PARSER + printer: JSON_PRETTY_STRING_VISITOR + s: STRING_32 + do + -- Create parser for content `json_content' + create parser.make_with_string (json_content) + -- Parse the content + parser.parse_content + if + parser.is_valid and then + attached parser.parsed_json_value as jv + then + -- Json content is valid, and well parser. + -- and the parsed json value is `jv' + + -- Let's access the glossary/title value + if + attached {JSON_OBJECT} jv as j_object and then + attached {JSON_OBJECT} j_object.item ("glossary") as j_glossary and then + attached {JSON_STRING} j_glossary.item ("title") as j_title + then + print ("The glossary title is %"" + j_title.unescaped_string_8 + "%".%N") + else + print ("The glossary title was not found!%N") + end + + -- Pretty print the parsed JSON + create s.make_empty + create printer.make (s) + jv.accept (printer) + print ("The JSON formatted using a pretty printer:%N") + print (s) + end + end + +feature -- Status + +feature -- Access + + json_content: STRING = "[ +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } +} + ]" + +feature -- Change + +feature {NONE} -- Implementation + +invariant +-- invariant_clause: True + +end diff --git a/contrib/library/text/parser/json/examples/basic/basic.ecf b/contrib/library/text/parser/json/examples/basic/basic.ecf new file mode 100644 index 00000000..17ceee6f --- /dev/null +++ b/contrib/library/text/parser/json/examples/basic/basic.ecf @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/contrib/library/text/parser/json/library/kernel/converters/json_arrayed_list_converter.e b/contrib/library/text/parser/json/library/converter/json_arrayed_list_converter.e similarity index 52% rename from contrib/library/text/parser/json/library/kernel/converters/json_arrayed_list_converter.e rename to contrib/library/text/parser/json/library/converter/json_arrayed_list_converter.e index da089f7b..154c1717 100644 --- a/contrib/library/text/parser/json/library/kernel/converters/json_arrayed_list_converter.e +++ b/contrib/library/text/parser/json/library/converter/json_arrayed_list_converter.e @@ -5,20 +5,25 @@ note revision: "$Revision$" file: "$HeadURL: $" -class JSON_ARRAYED_LIST_CONVERTER +class + JSON_ARRAYED_LIST_CONVERTER + +obsolete + "This JSON converter design has issues [Sept/2014]." inherit - JSON_LIST_CONVERTER + + JSON_LIST_CONVERTER redefine object end create - make + make feature -- Access - object: ARRAYED_LIST [detachable ANY] + object: ARRAYED_LIST [detachable ANY] feature {NONE} -- Factory @@ -27,4 +32,7 @@ feature {NONE} -- Factory create Result.make (nb) end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end -- class JSON_ARRAYED_LIST_CONVERTER diff --git a/contrib/library/text/parser/json/library/converter/json_converter.e b/contrib/library/text/parser/json/library/converter/json_converter.e new file mode 100644 index 00000000..987c116a --- /dev/null +++ b/contrib/library/text/parser/json/library/converter/json_converter.e @@ -0,0 +1,44 @@ +note + description: "A JSON converter" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision$" + file: "$HeadURL: $" + +deferred class + JSON_CONVERTER + +obsolete + "This JSON converter design has issues [Sept/2014]." + +inherit + + SHARED_EJSON + +feature -- Access + + object: ANY + -- Eiffel object + deferred + end + +feature -- Conversion + + from_json (j: attached like to_json): detachable like object + -- Convert from JSON value. + -- Returns Void if unable to convert + deferred + end + + to_json (o: like object): detachable JSON_VALUE + -- Convert to JSON value + deferred + end + +invariant + has_eiffel_object: object /= Void -- An empty object must be created at creation time! + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end diff --git a/contrib/library/text/parser/json/library/converter/json_hash_table_converter.e b/contrib/library/text/parser/json/library/converter/json_hash_table_converter.e new file mode 100644 index 00000000..5787246b --- /dev/null +++ b/contrib/library/text/parser/json/library/converter/json_hash_table_converter.e @@ -0,0 +1,88 @@ +note + description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]" + author: "Paul Cohen" + date: "$Date: 2014-01-30 15:27:41 +0100 (jeu., 30 janv. 2014) $" + revision: "$Revision: 94128 $" + file: "$HeadURL: $" + +class + JSON_HASH_TABLE_CONVERTER + +obsolete + "This JSON converter design has issues [Sept/2014]." + +inherit + + JSON_CONVERTER + +create + make + +feature {NONE} -- Initialization + + make + do + create object.make (0) + end + +feature -- Access + + object: HASH_TABLE [ANY, HASHABLE] + +feature -- Conversion + + from_json (j: attached like to_json): like object + do + create Result.make (j.count) + across + j as ic + loop + if attached json.object (ic.item, Void) as l_object then + if attached {HASHABLE} json.object (ic.key, Void) as h then + Result.put (l_object, h) + else + check + key_is_hashable: False + end + end + else + check + object_attached: False + end + end + end + end + + to_json (o: like object): detachable JSON_OBJECT + local + js: JSON_STRING + failed: BOOLEAN + do + create Result.make + across + o as c + loop + if attached {JSON_STRING} json.value (c.key) as l_key then + js := l_key + else + if attached {READABLE_STRING_GENERAL} c.key as s_key then + create js.make_from_string_general (s_key) + else + create js.make_from_string (c.key.out) + end + end + if attached json.value (c.item) as jv then + Result.put (jv, js) + else + failed := True + end + end + if failed then + Result := Void + end + end + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end -- class JSON_HASH_TABLE_CONVERTER diff --git a/contrib/library/text/parser/json/library/kernel/converters/json_linked_list_converter.e b/contrib/library/text/parser/json/library/converter/json_linked_list_converter.e similarity index 51% rename from contrib/library/text/parser/json/library/kernel/converters/json_linked_list_converter.e rename to contrib/library/text/parser/json/library/converter/json_linked_list_converter.e index 42a1c2c4..82fc5041 100644 --- a/contrib/library/text/parser/json/library/kernel/converters/json_linked_list_converter.e +++ b/contrib/library/text/parser/json/library/converter/json_linked_list_converter.e @@ -5,20 +5,25 @@ note revision: "$Revision$" file: "$HeadURL: $" -class JSON_LINKED_LIST_CONVERTER +class + JSON_LINKED_LIST_CONVERTER + +obsolete + "This JSON converter design has issues [Sept/2014]." inherit - JSON_LIST_CONVERTER + + JSON_LIST_CONVERTER redefine object end create - make + make feature -- Access - object: LINKED_LIST [detachable ANY] + object: LINKED_LIST [detachable ANY] feature {NONE} -- Factory @@ -27,4 +32,7 @@ feature {NONE} -- Factory create Result.make end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end -- class JSON_LINKED_LIST_CONVERTER diff --git a/contrib/library/text/parser/json/library/converter/json_list_converter.e b/contrib/library/text/parser/json/library/converter/json_list_converter.e new file mode 100644 index 00000000..aa3f596b --- /dev/null +++ b/contrib/library/text/parser/json/library/converter/json_list_converter.e @@ -0,0 +1,80 @@ +note + description: "A JSON converter for LIST [ANY]" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision$" + file: "$HeadURL: $" + +deferred class + JSON_LIST_CONVERTER + +obsolete + "This JSON converter design has issues [Sept/2014]." + +inherit + + JSON_CONVERTER + +feature {NONE} -- Initialization + + make + do + object := new_object (0) + end + +feature -- Access + + object: LIST [detachable ANY] + +feature {NONE} -- Factory + + new_object (nb: INTEGER): like object + deferred + ensure + Result /= Void + end + +feature -- Conversion + + from_json (j: attached like to_json): detachable like object + local + i: INTEGER + do + Result := new_object (j.count) + from + i := 1 + until + i > j.count + loop + Result.extend (json.object (j [i], Void)) + i := i + 1 + end + end + + to_json (o: like object): detachable JSON_ARRAY + local + c: ITERATION_CURSOR [detachable ANY] + failed: BOOLEAN + do + create Result.make (o.count) + from + c := o.new_cursor + until + c.after + loop + if attached json.value (c.item) as jv then + Result.add (jv) + else + failed := True + end + c.forth + end + if failed then + Result := Void + end + end + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end -- class JSON_ARRAYED_LIST_CONVERTER diff --git a/contrib/library/text/parser/json/library/kernel/ejson.e b/contrib/library/text/parser/json/library/converter/support/ejson.e similarity index 86% rename from contrib/library/text/parser/json/library/kernel/ejson.e rename to contrib/library/text/parser/json/library/converter/support/ejson.e index cb5ed967..1d15a28d 100644 --- a/contrib/library/text/parser/json/library/kernel/ejson.e +++ b/contrib/library/text/parser/json/library/converter/support/ejson.e @@ -5,9 +5,14 @@ note revision: "$Revision$" file: "$HeadURL: $" -class EJSON +class + EJSON + +obsolete + "This JSON converter design has issues [Sept/2014]." inherit + EXCEPTIONS feature -- Access @@ -19,13 +24,13 @@ feature -- Access i: INTEGER ja: JSON_ARRAY do - -- Try to convert from basic Eiffel types. Note that we check with - -- `conforms_to' since the client may have subclassed the base class - -- that these basic types are derived from. + -- Try to convert from basic Eiffel types. Note that we check with + -- `conforms_to' since the client may have subclassed the base class + -- that these basic types are derived from. if an_object = Void then create {JSON_NULL} Result elseif attached {BOOLEAN} an_object as b then - create {JSON_BOOLEAN} Result.make_boolean (b) + create {JSON_BOOLEAN} Result.make (b) elseif attached {INTEGER_8} an_object as i8 then create {JSON_NUMBER} Result.make_integer (i8) elseif attached {INTEGER_16} an_object as i16 then @@ -47,7 +52,7 @@ feature -- Access elseif attached {REAL_64} an_object as r64 then create {JSON_NUMBER} Result.make_real (r64) elseif attached {ARRAY [detachable ANY]} an_object as a then - create ja.make_array + create ja.make (a.count) from i := a.lower until @@ -56,24 +61,24 @@ feature -- Access if attached value (a @ i) as v then ja.add (v) else - check value_attached: False end + check + value_attached: False + end end i := i + 1 end Result := ja elseif attached {CHARACTER_8} an_object as c8 then - create {JSON_STRING} Result.make_json (c8.out) + create {JSON_STRING} Result.make_from_string (c8.out) elseif attached {CHARACTER_32} an_object as c32 then - create {JSON_STRING} Result.make_json (c32.out) - + create {JSON_STRING} Result.make_from_string_32 (create {STRING_32}.make_filled (c32, 1)) elseif attached {STRING_8} an_object as s8 then - create {JSON_STRING} Result.make_json (s8) + create {JSON_STRING} Result.make_from_string (s8) elseif attached {STRING_32} an_object as s32 then - create {JSON_STRING} Result.make_json_from_string_32 (s32) + create {JSON_STRING} Result.make_from_string_32 (s32) end - if Result = Void then - -- Now check the converters + -- Now check the converters if an_object /= Void and then attached converter_for (an_object) as jc then Result := jc.to_json (an_object) else @@ -84,7 +89,7 @@ feature -- Access object (a_value: detachable JSON_VALUE; base_class: detachable STRING): detachable ANY -- Eiffel object from JSON value. If `base_class' /= Void an eiffel - -- object based on `base_class' will be returned. Raises an "eJSON + -- object based on `base_class' will be returned. Raises an "eJSON -- exception" if unable to convert value. local i: INTEGER @@ -160,12 +165,10 @@ feature -- Access -- "eJSON exception" if unable to convert value. require json_not_void: json /= Void - local - jv: detachable JSON_VALUE do json_parser.set_representation (json) - jv := json_parser.parse - if jv /= Void then + json_parser.parse_content + if json_parser.is_valid and then attached json_parser.parsed_json_value as jv then Result := object (jv, base_class) end end @@ -190,8 +193,8 @@ feature -- Access js_key, js_value: JSON_STRING do create Result.make - create js_key.make_json ("$ref") - create js_value.make_json (s) + create js_key.make_from_string ("$ref") + create js_value.make_from_string (s) Result.put (js_value, js_key) end @@ -205,7 +208,7 @@ feature -- Access local c: ITERATION_CURSOR [STRING] do - create Result.make_array + create Result.make (l.count) from c := l.new_cursor until @@ -262,7 +265,10 @@ feature {NONE} -- Implementation (JSON parser) json_parser: JSON_PARSER once - create Result.make_parser ("") + create Result.make_with_string ("{}") end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end -- class EJSON diff --git a/contrib/library/text/parser/json/library/converter/support/shared_ejson.e b/contrib/library/text/parser/json/library/converter/support/shared_ejson.e new file mode 100644 index 00000000..4d0b5a50 --- /dev/null +++ b/contrib/library/text/parser/json/library/converter/support/shared_ejson.e @@ -0,0 +1,43 @@ +note + description: "[ + Shared factory class for creating JSON objects. Maps JSON + objects to ELKS HASH_TABLEs and JSON arrays to ELKS + LINKED_LISTs. Use non-conforming inheritance from this + class to ensure that your classes share the same + JSON_FACTORY instance. + ]" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision: 89185 $" + file: "$HeadURL: $" + +class + SHARED_EJSON + +obsolete + "This JSON converter design has issues [Sept/2014]." + +feature -- Access + + json: EJSON + -- A shared EJSON instance with default converters for + --LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE] + local + jalc: JSON_ARRAYED_LIST_CONVERTER + jllc: JSON_LINKED_LIST_CONVERTER + jhtc: JSON_HASH_TABLE_CONVERTER + once + create Result + create jalc.make + Result.add_converter (jalc) + create jllc.make + Result.add_converter (jllc) + create jhtc.make + Result.add_converter (jhtc) + end + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" + +end -- class SHARED_EJSON diff --git a/contrib/library/text/parser/json/library/extras/file/json_file_reader.e b/contrib/library/text/parser/json/library/extras/file/json_file_reader.e deleted file mode 100644 index a7c60481..00000000 --- a/contrib/library/text/parser/json/library/extras/file/json_file_reader.e +++ /dev/null @@ -1,37 +0,0 @@ -note - description: "Objects that ..." - date: "$Date$" - revision: "$Revision$" - -class - JSON_FILE_READER - -feature -- Access - - read_json_from (a_path: STRING): detachable STRING - local - l_file: PLAIN_TEXT_FILE - template_content: STRING - l_last_string: detachable STRING - do - create l_file.make_with_name (a_path) - -- We perform several checks until we make a real attempt to open the file. - if not l_file.exists then - print ("error: '" + a_path + "' does not exist%N") - else - if not l_file.is_readable then - print ("error: '" + a_path + "' is not readable.%N") - else - l_file.open_read - create template_content.make_empty - l_file.read_stream (l_file.count) - l_last_string := l_file.last_string - check l_last_string /= Void end -- implied by postcondition of `l_file.read_stream' - template_content.append (l_last_string.string) - Result := template_content - l_file.close - end - end - end - -end diff --git a/contrib/library/text/parser/json/library/gobo/converters/json_ds_hash_table_converter.e b/contrib/library/text/parser/json/library/gobo_converter/converters/json_ds_hash_table_converter.e similarity index 100% rename from contrib/library/text/parser/json/library/gobo/converters/json_ds_hash_table_converter.e rename to contrib/library/text/parser/json/library/gobo_converter/converters/json_ds_hash_table_converter.e diff --git a/contrib/library/text/parser/json/library/gobo/converters/json_ds_linked_list_converter.e b/contrib/library/text/parser/json/library/gobo_converter/converters/json_ds_linked_list_converter.e similarity index 100% rename from contrib/library/text/parser/json/library/gobo/converters/json_ds_linked_list_converter.e rename to contrib/library/text/parser/json/library/gobo_converter/converters/json_ds_linked_list_converter.e diff --git a/contrib/library/text/parser/json/library/gobo/shared_gobo_ejson.e b/contrib/library/text/parser/json/library/gobo_converter/shared_gobo_ejson.e similarity index 100% rename from contrib/library/text/parser/json/library/gobo/shared_gobo_ejson.e rename to contrib/library/text/parser/json/library/gobo_converter/shared_gobo_ejson.e diff --git a/contrib/library/text/parser/json/library/json-safe.ecf b/contrib/library/text/parser/json/library/json-safe.ecf index d1936431..db3f30dc 100644 --- a/contrib/library/text/parser/json/library/json-safe.ecf +++ b/contrib/library/text/parser/json/library/json-safe.ecf @@ -9,20 +9,13 @@ - - - ^/gobo$ - ^/kernel$ - ^/extras$ - - - + + + + + diff --git a/contrib/library/text/parser/json/library/json.ecf b/contrib/library/text/parser/json/library/json.ecf index 8d6dc612..e9e114fd 100644 --- a/contrib/library/text/parser/json/library/json.ecf +++ b/contrib/library/text/parser/json/library/json.ecf @@ -9,20 +9,13 @@ - - - ^/gobo$ - ^/kernel$ - ^/extras$ - - - + + + + + diff --git a/contrib/library/text/parser/json/library/json.rc b/contrib/library/text/parser/json/library/json.rc deleted file mode 100644 index 8b137891..00000000 --- a/contrib/library/text/parser/json/library/json.rc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/contrib/library/text/parser/json/library/json_gobo_extension.ecf b/contrib/library/text/parser/json/library/json_gobo_extension.ecf index dd5f9b75..48449915 100644 --- a/contrib/library/text/parser/json/library/json_gobo_extension.ecf +++ b/contrib/library/text/parser/json/library/json_gobo_extension.ecf @@ -12,6 +12,6 @@ - + diff --git a/contrib/library/text/parser/json/library/kernel/converters/json_converter.e b/contrib/library/text/parser/json/library/kernel/converters/json_converter.e deleted file mode 100644 index 796ef4eb..00000000 --- a/contrib/library/text/parser/json/library/kernel/converters/json_converter.e +++ /dev/null @@ -1,36 +0,0 @@ -note - description: "A JSON converter" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision$" - file: "$HeadURL: $" - -deferred class JSON_CONVERTER - -inherit - SHARED_EJSON - -feature -- Access - - object: ANY - -- Eiffel object - deferred - end - -feature -- Conversion - - from_json (j: attached like to_json): detachable like object - -- Convert from JSON value. - -- Returns Void if unable to convert - deferred - end - - to_json (o: like object): detachable JSON_VALUE - -- Convert to JSON value - deferred - end - -invariant - has_eiffel_object: object /= Void -- An empty object must be created at creation time! - -end diff --git a/contrib/library/text/parser/json/library/kernel/converters/json_hash_table_converter.e b/contrib/library/text/parser/json/library/kernel/converters/json_hash_table_converter.e deleted file mode 100644 index e1264de7..00000000 --- a/contrib/library/text/parser/json/library/kernel/converters/json_hash_table_converter.e +++ /dev/null @@ -1,76 +0,0 @@ -note - description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]" - author: "Paul Cohen" - date: "$Date: 2014-01-30 15:27:41 +0100 (jeu., 30 janv. 2014) $" - revision: "$Revision: 94128 $" - file: "$HeadURL: $" - -class JSON_HASH_TABLE_CONVERTER - -inherit - JSON_CONVERTER - -create - make - -feature {NONE} -- Initialization - - make - do - create object.make (0) - end - -feature -- Access - - object: HASH_TABLE [ANY, HASHABLE] - -feature -- Conversion - - from_json (j: attached like to_json): like object - do - create Result.make (j.count) - across - j as ic - loop - if attached json.object (ic.item, Void) as l_object then - if attached {HASHABLE} json.object (ic.key, Void) as h then - Result.put (l_object, h) - else - check key_is_hashable: False end - end - else - check object_attached: False end - end - end - end - - to_json (o: like object): detachable JSON_OBJECT - local - c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE] - js: JSON_STRING - failed: BOOLEAN - do - create Result.make - from - c := o.new_cursor - until - c.after - loop - if attached {JSON_STRING} json.value (c.key) as l_key then - js := l_key - else - create js.make_json (c.key.out) - end - if attached json.value (c.item) as jv then - Result.put (jv, js) - else - failed := True - end - c.forth - end - if failed then - Result := Void - end - end - -end -- class JSON_HASH_TABLE_CONVERTER diff --git a/contrib/library/text/parser/json/library/kernel/converters/json_list_converter.e b/contrib/library/text/parser/json/library/kernel/converters/json_list_converter.e deleted file mode 100644 index 75e0f848..00000000 --- a/contrib/library/text/parser/json/library/kernel/converters/json_list_converter.e +++ /dev/null @@ -1,74 +0,0 @@ -note - description: "A JSON converter for LIST [ANY]" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision$" - file: "$HeadURL: $" - -deferred class JSON_LIST_CONVERTER - -inherit - JSON_CONVERTER - -feature {NONE} -- Initialization - - make - do - object := new_object (0) - end - -feature -- Access - - object: LIST [detachable ANY] - -feature {NONE} -- Factory - - new_object (nb: INTEGER): like object - deferred - ensure - Result /= Void - end - -feature -- Conversion - - from_json (j: attached like to_json): detachable like object - local - i: INTEGER - do - Result := new_object (j.count) - from - i := 1 - until - i > j.count - loop - Result.extend (json.object (j [i], Void)) - i := i + 1 - end - end - - to_json (o: like object): detachable JSON_ARRAY - local - c: ITERATION_CURSOR [detachable ANY] - jv: detachable JSON_VALUE - failed: BOOLEAN - do - create Result.make_array - from - c := o.new_cursor - until - c.after - loop - jv := json.value (c.item) - if jv /= Void then - Result.add (jv) - else - failed := True - end - c.forth - end - if failed then - Result := Void - end - end - -end -- class JSON_ARRAYED_LIST_CONVERTER diff --git a/contrib/library/text/parser/json/library/kernel/json_array.e b/contrib/library/text/parser/json/library/kernel/json_array.e index cd693f5c..6b30b8fd 100644 --- a/contrib/library/text/parser/json/library/kernel/json_array.e +++ b/contrib/library/text/parser/json/library/kernel/json_array.e @@ -1,178 +1,192 @@ note - description: "[ - JSON_ARRAY represent an array in JSON. - An array in JSON is an ordered set of names. - Examples - array - [] - [elements] - ]" - - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" + description: "[ + JSON_ARRAY represent an array in JSON. + An array in JSON is an ordered set of names. + Examples + array + [] + [elements] + ]" + author: "$Author$" + date: "$date$" + revision: "$Revision$" class - JSON_ARRAY + JSON_ARRAY inherit - JSON_VALUE + + JSON_VALUE ITERABLE [JSON_VALUE] DEBUG_OUTPUT create - make_array + make, make_empty, + make_array feature {NONE} -- Initialization - make_array - -- Initialize JSON Array - do - create values.make (10) - end + make (nb: INTEGER) + -- Initialize JSON array with capacity of `nb' items. + do + create items.make (nb) + end + + make_empty + -- Initialize empty JSON array. + do + make (0) + end + + make_array + -- Initialize JSON Array + obsolete + "Use `make' Sept/2014" + do + make (10) + end feature -- Access - i_th alias "[]" (i: INTEGER): JSON_VALUE - -- Item at `i'-th position - require - is_valid_index: valid_index (i) - do - Result := values.i_th (i) - end + i_th alias "[]" (i: INTEGER): JSON_VALUE + -- Item at `i'-th position + require + is_valid_index: valid_index (i) + do + Result := items.i_th (i) + end - representation: STRING - local - i: INTEGER - do - Result := "[" - from - i := 1 - until - i > count - loop - Result.append (i_th (i).representation) - i := i + 1 - if i <= count then - Result.append_character (',') - end - end - Result.append_character (']') - end + representation: STRING + do + Result := "[" + across + items as ic + loop + if Result.count > 1 then + Result.append_character (',') + end + Result.append (ic.item.representation) + end + Result.append_character (']') + end feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_json_array' procedure on `a_visitor'.) - do - a_visitor.visit_json_array (Current) - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_json_array' procedure on `a_visitor'.) + do + a_visitor.visit_json_array (Current) + end feature -- Access new_cursor: ITERATION_CURSOR [JSON_VALUE] -- Fresh cursor associated with current structure do - Result := values.new_cursor + Result := items.new_cursor end feature -- Mesurement - count: INTEGER - -- Number of items. - do - Result := values.count - end + count: INTEGER + -- Number of items. + do + Result := items.count + end feature -- Status report - valid_index (i: INTEGER): BOOLEAN - -- Is `i' a valid index? - do - Result := (1 <= i) and (i <= count) - end + valid_index (i: INTEGER): BOOLEAN + -- Is `i' a valid index? + do + Result := (1 <= i) and (i <= count) + end feature -- Change Element put_front (v: JSON_VALUE) - require - v_not_void: v /= Void - do - values.put_front (v) - ensure - has_new_value: old values.count + 1 = values.count and - values.first = v - end + require + v_not_void: v /= Void + do + items.put_front (v) + ensure + has_new_value: old items.count + 1 = items.count and items.first = v + end - add, extend (v: JSON_VALUE) - require - v_not_void: v /= Void - do - values.extend (v) - ensure - has_new_value: old values.count + 1 = values.count and - values.has (v) - end + add, extend (v: JSON_VALUE) + require + v_not_void: v /= Void + do + items.extend (v) + ensure + has_new_value: old items.count + 1 = items.count and items.has (v) + end prune_all (v: JSON_VALUE) -- Remove all occurrences of `v'. - require - v_not_void: v /= Void - do - values.prune_all (v) - ensure - not_has_new_value: not values.has (v) - end + require + v_not_void: v /= Void + do + items.prune_all (v) + ensure + not_has_new_value: not items.has (v) + end wipe_out -- Remove all items. - do - values.wipe_out - end + do + items.wipe_out + end feature -- Report - hash_code: INTEGER - -- Hash code value - do - from - values.start - Result := values.item.hash_code - until - values.off - loop - Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code - values.forth - end - Result := Result \\ values.count - end + hash_code: INTEGER + -- Hash code value + local + l_started: BOOLEAN + do + across + items as ic + loop + if l_started then + Result := ((Result \\ 8388593) |<< 8) + ic.item.hash_code + else + Result := ic.item.hash_code + l_started := True + end + end + Result := Result \\ items.count + end feature -- Conversion - array_representation: ARRAYED_LIST [JSON_VALUE] - -- Representation as a sequences of values - -- be careful, modifying the return object may have impact on the original JSON_ARRAY object - do - Result := values - end + array_representation: ARRAYED_LIST [JSON_VALUE] + -- Representation as a sequences of values. + -- be careful, modifying the return object may have impact on the original JSON_ARRAY object. + do + Result := items + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := count.out + " item(s)" - end + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := count.out + " item(s)" + end feature {NONE} -- Implementation - values: ARRAYED_LIST [JSON_VALUE] - -- Value container + items: ARRAYED_LIST [JSON_VALUE] + -- Value container invariant - value_not_void: values /= Void + items_not_void: items /= Void +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_boolean.e b/contrib/library/text/parser/json/library/kernel/json_boolean.e index cc17681c..47b49979 100644 --- a/contrib/library/text/parser/json/library/kernel/json_boolean.e +++ b/contrib/library/text/parser/json/library/kernel/json_boolean.e @@ -1,61 +1,87 @@ note - description: "JSON Truth values" - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" + description: "JSON Boolean values" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" class - JSON_BOOLEAN + JSON_BOOLEAN inherit - JSON_VALUE + + JSON_VALUE create - make_boolean + make, + make_true, make_false, + make_boolean feature {NONE} -- Initialization - make_boolean (an_item: BOOLEAN) - --Initialize. - do - item := an_item - end + make (a_value: BOOLEAN) + -- Initialize Current JSON boolean with `a_boolean'. + do + item := a_value + end + + make_true + -- Initialize Current JSON boolean with True. + do + make (True) + end + + make_false + -- Initialize Current JSON boolean with False. + do + make (False) + end + + make_boolean (a_item: BOOLEAN) + -- Initialize. + obsolete + "Use `make' Sept/2014" + do + make (a_item) + end feature -- Access - item: BOOLEAN - -- Content + item: BOOLEAN + -- Content - hash_code: INTEGER - -- Hash code value - do - Result := item.hash_code - end + hash_code: INTEGER + -- Hash code value + do + Result := item.hash_code + end + + representation: STRING + do + if item then + Result := "true" + else + Result := "false" + end + end - representation: STRING - do - if item then - Result := "true" - else - Result := "false" - end - end - feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_json_boolean' procedure on `a_visitor'.) - do - a_visitor.visit_json_boolean (Current) - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_json_boolean' procedure on `a_visitor'.) + do + a_visitor.visit_json_boolean (Current) + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := item.out - end + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := item.out + end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_null.e b/contrib/library/text/parser/json/library/kernel/json_null.e index 9c6f4ed7..ad0a85fe 100644 --- a/contrib/library/text/parser/json/library/kernel/json_null.e +++ b/contrib/library/text/parser/json/library/kernel/json_null.e @@ -1,47 +1,51 @@ note - description: "JSON Null Values" - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" + description: "JSON Null Values" + author: "Javier Velilla" + date: "2008/08/24" + revision: "Revision 0.1" class - JSON_NULL + JSON_NULL inherit - JSON_VALUE + + JSON_VALUE feature --Access - hash_code: INTEGER - -- Hash code value - do - Result := null_value.hash_code - end + hash_code: INTEGER + -- Hash code value + do + Result := null_value.hash_code + end + + representation: STRING + do + Result := "null" + end - representation: STRING - do - Result := "null" - end - feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_element_a' procedure on `a_visitor'.) - do - a_visitor.visit_json_null (Current) - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_element_a' procedure on `a_visitor'.) + do + a_visitor.visit_json_null (Current) + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := null_value - end + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := null_value + end -feature {NONE}-- Implementation +feature {NONE} -- Implementation - null_value: STRING = "null" + null_value: STRING = "null" +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_number.e b/contrib/library/text/parser/json/library/kernel/json_number.e index 5f8ea60f..84ccbf8f 100644 --- a/contrib/library/text/parser/json/library/kernel/json_number.e +++ b/contrib/library/text/parser/json/library/kernel/json_number.e @@ -1,99 +1,149 @@ note - - description: "JSON Numbers, octal and hexadecimal formats are not used." - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + description: "JSON Numbers, octal and hexadecimal formats are not used." + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" class - JSON_NUMBER + JSON_NUMBER inherit - JSON_VALUE - redefine - is_equal - end + + JSON_VALUE + redefine + is_equal + end create - make_integer, - make_natural, - make_real + make_integer, make_natural, make_real feature {NONE} -- initialization - make_integer (an_argument: INTEGER_64) - -- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'. - do - item := an_argument.out - numeric_type := INTEGER_TYPE - end + make_integer (an_argument: INTEGER_64) + -- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'. + do + item := an_argument.out + numeric_type := integer_type + end - make_natural (an_argument: NATURAL_64) - -- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'. - do - item := an_argument.out - numeric_type := NATURAL_TYPE - end + make_natural (an_argument: NATURAL_64) + -- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'. + do + item := an_argument.out + numeric_type := natural_type + end - make_real (an_argument: DOUBLE) - -- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'. - do - item := an_argument.out - numeric_type := DOUBLE_TYPE - end + make_real (an_argument: REAL_64) + -- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'. + do + item := an_argument.out + numeric_type := double_type + end feature -- Access - item: STRING - -- Content + item: STRING + -- Content - hash_code: INTEGER - --Hash code value - do - Result := item.hash_code - end + numeric_type: INTEGER + -- Type of number (integer, natural or real). - representation: STRING - do - Result := item - end - -feature -- Visitor pattern + hash_code: INTEGER + --Hash code value + do + Result := item.hash_code + end - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_json_number' procedure on `a_visitor'.) - do - a_visitor.visit_json_number (Current) - end + representation: STRING + do + Result := item + end -feature -- Status +feature -- Conversion - is_equal (other: like Current): BOOLEAN - -- Is `other' attached to an object of the same type - -- as current object and identical to it? - do - Result := item.is_equal (other.item) - end + integer_64_item: INTEGER_64 + -- Associated integer value. + require + is_integer: is_integer + do + Result := item.to_integer_64 + end + + natural_64_item: NATURAL_64 + -- Associated natural value. + require + is_natural: is_natural + do + Result := item.to_natural_64 + end + + double_item, real_64_item: REAL_64 + -- Associated real value. + require + is_real: is_real + do + Result := item.to_real_64 + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := item - end + is_integer: BOOLEAN + -- Is Current an integer number? + do + Result := numeric_type = integer_type + end + + is_natural: BOOLEAN + -- Is Current a natural number? + do + Result := numeric_type = natural_type + end + + is_double, is_real: BOOLEAN + -- Is Current a real number? + do + Result := numeric_type = real_type + end + +feature -- Visitor pattern + + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_json_number' procedure on `a_visitor'.) + do + a_visitor.visit_json_number (Current) + end + +feature -- Status + + is_equal (other: like Current): BOOLEAN + -- Is `other' attached to an object of the same type + -- as current object and identical to it? + do + Result := item.is_equal (other.item) + end + +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := item + end feature -- Implementation - INTEGER_TYPE: INTEGER = 1 - DOUBLE_TYPE: INTEGER = 2 - NATURAL_TYPE: INTEGER = 3 + integer_type: INTEGER = 1 - numeric_type: INTEGER + double_type, real_type: INTEGER = 2 + + natural_type: INTEGER = 3 invariant - item_not_void: item /= Void + item_not_void: item /= Void +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_object.e b/contrib/library/text/parser/json/library/kernel/json_object.e index 8a13c64c..7b37ea1e 100644 --- a/contrib/library/text/parser/json/library/kernel/json_object.e +++ b/contrib/library/text/parser/json/library/kernel/json_object.e @@ -1,250 +1,261 @@ note - - description: "[ - An JSON_OBJECT represent an object in JSON. - An object is an unordered set of name/value pairs - - Examples: - - object - {} - {"key": "value"} - - ]" - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + description: "[ + An JSON_OBJECT represent an object in JSON. + An object is an unordered set of name/value pairs + + Examples: + object + {} + {"key": value} + {"key": "value"} + ]" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" class - JSON_OBJECT + JSON_OBJECT inherit - JSON_VALUE - TABLE_ITERABLE [JSON_VALUE, JSON_STRING] + JSON_VALUE - DEBUG_OUTPUT + TABLE_ITERABLE [JSON_VALUE, JSON_STRING] + + DEBUG_OUTPUT create - make + make_empty, make_with_capacity, make feature {NONE} -- Initialization - make - -- Initialize - do - create object.make (10) - end + make_with_capacity (nb: INTEGER) + -- Initialize with a capacity of `nb' items. + do + create items.make (nb) + end + + make_empty + -- Initialize as empty object. + do + make_with_capacity (0) + end + + make + -- Initialize with default capacity. + do + make_with_capacity (3) + end feature -- Change Element - put (value: detachable JSON_VALUE; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: like value - do - l_value := value - if l_value = Void then - create {JSON_NULL} l_value - end - object.extend (l_value, key) - end - - put_string (value: READABLE_STRING_GENERAL; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: JSON_STRING - do - create l_value.make_json_from_string_32 (value.as_string_32) - put (l_value, key) - end - - - put_integer (value: INTEGER_64; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: JSON_NUMBER - do - create l_value.make_integer (value) - put (l_value, key) - end - - put_natural (value: NATURAL_64; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: JSON_NUMBER - do - create l_value.make_natural (value) - put (l_value, key) - end - - put_real (value: DOUBLE; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: JSON_NUMBER - do - create l_value.make_real (value) - put (l_value, key) - end - - put_boolean (value: BOOLEAN; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - require - key_not_present: not has_key (key) - local - l_value: JSON_BOOLEAN - do - create l_value.make_boolean (value) - put (l_value, key) - end - - replace (value: detachable JSON_VALUE; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: like value - do - l_value := value - if l_value = Void then - create {JSON_NULL} l_value - end - object.force (l_value, key) - end - - replace_with_string (value: READABLE_STRING_GENERAL; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: JSON_STRING - do - create l_value.make_json_from_string_32 (value.as_string_32) - replace (l_value, key) - end - - replace_with_integer (value: INTEGER_64; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: JSON_NUMBER - do - create l_value.make_integer (value) - replace (l_value, key) - end - - replace_with_with_natural (value: NATURAL_64; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: JSON_NUMBER - do - create l_value.make_natural (value) - replace (l_value, key) - end - - replace_with_real (value: DOUBLE; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: JSON_NUMBER - do - create l_value.make_real (value) - replace (l_value, key) - end - - replace_with_boolean (value: BOOLEAN; key: JSON_STRING) - -- Assuming there is no item of key `key', - -- insert `value' with `key'. - local - l_value: JSON_BOOLEAN - do - create l_value.make_boolean (value) - replace (l_value, key) - end - - remove (key: JSON_STRING) - -- Remove item indexed by `key' if any. + put (a_value: detachable JSON_VALUE; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + a_key_not_present: not has_key (a_key) do - object.remove (key) + if a_value = Void then + items.extend (create {JSON_NULL}, a_key) + else + items.extend (a_value, a_key) + end + end + + put_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + key_not_present: not has_key (a_key) + local + l_value: JSON_STRING + do + if attached {READABLE_STRING_8} a_value as s then + create l_value.make_from_string (s) + else + create l_value.make_from_string_32 (a_value.as_string_32) + end + put (l_value, a_key) + end + + put_integer (a_value: INTEGER_64; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + key_not_present: not has_key (a_key) + local + l_value: JSON_NUMBER + do + create l_value.make_integer (a_value) + put (l_value, a_key) + end + + put_natural (a_value: NATURAL_64; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + key_not_present: not has_key (a_key) + local + l_value: JSON_NUMBER + do + create l_value.make_natural (a_value) + put (l_value, a_key) + end + + put_real (a_value: DOUBLE; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + key_not_present: not has_key (a_key) + local + l_value: JSON_NUMBER + do + create l_value.make_real (a_value) + put (l_value, a_key) + end + + put_boolean (a_value: BOOLEAN; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + require + key_not_present: not has_key (a_key) + local + l_value: JSON_BOOLEAN + do + create l_value.make (a_value) + put (l_value, a_key) + end + + replace (a_value: detachable JSON_VALUE; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + do + if a_value = Void then + items.force (create {JSON_NULL}, a_key) + else + items.force (a_value, a_key) + end + end + + replace_with_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + local + l_value: JSON_STRING + do + if attached {READABLE_STRING_8} a_value as s then + create l_value.make_from_string (s) + else + create l_value.make_from_string_32 (a_value.as_string_32) + end + replace (l_value, a_key) + end + + replace_with_integer (a_value: INTEGER_64; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + local + l_value: JSON_NUMBER + do + create l_value.make_integer (a_value) + replace (l_value, a_key) + end + + replace_with_with_natural (a_value: NATURAL_64; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + local + l_value: JSON_NUMBER + do + create l_value.make_natural (a_value) + replace (l_value, a_key) + end + + replace_with_real (a_value: DOUBLE; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + local + l_value: JSON_NUMBER + do + create l_value.make_real (a_value) + replace (l_value, a_key) + end + + replace_with_boolean (a_value: BOOLEAN; a_key: JSON_STRING) + -- Assuming there is no item of key `a_key', + -- insert `a_value' with `a_key'. + local + l_value: JSON_BOOLEAN + do + create l_value.make (a_value) + replace (l_value, a_key) + end + + remove (a_key: JSON_STRING) + -- Remove item indexed by `a_key' if any. + do + items.remove (a_key) end wipe_out - -- Reset all items to default values; reset status. + -- Reset all items to default values; reset status. do - object.wipe_out + items.wipe_out + end + +feature -- Status report + + has_key (a_key: JSON_STRING): BOOLEAN + -- has the JSON_OBJECT contains a specific key `a_key'. + do + Result := items.has (a_key) + end + + has_item (a_value: JSON_VALUE): BOOLEAN + -- has the JSON_OBJECT contain a specfic item `a_value' + do + Result := items.has_item (a_value) end feature -- Access - has_key (key: JSON_STRING): BOOLEAN - -- has the JSON_OBJECT contains a specific key 'key'. - do - Result := object.has (key) - end + item (a_key: JSON_STRING): detachable JSON_VALUE + -- the json_value associated with a key `a_key'. + do + Result := items.item (a_key) + end - has_item (value: JSON_VALUE): BOOLEAN - -- has the JSON_OBJECT contain a specfic item 'value' - do - Result := object.has_item (value) - end + current_keys: ARRAY [JSON_STRING] + -- Array containing actually used keys. + do + Result := items.current_keys + end - item (key: JSON_STRING): detachable JSON_VALUE - -- the json_value associated with a key. - do - Result := object.item (key) - end - - current_keys: ARRAY [JSON_STRING] - -- array containing actually used keys - do - Result := object.current_keys - end - - representation: STRING - local - t: HASH_TABLE [JSON_VALUE, JSON_STRING] - do - create Result.make (2) - Result.append_character ('{') - from - t := map_representation - t.start - until - t.after - loop - Result.append (t.key_for_iteration.representation) - Result.append_character (':') - Result.append (t.item_for_iteration.representation) - t.forth - if not t.after then - Result.append_character (',') - end - end - Result.append_character ('}') - end + representation: STRING + -- + do + create Result.make (2) + Result.append_character ('{') + across + items as ic + loop + if Result.count > 1 then + Result.append_character (',') + end + Result.append (ic.key.representation) + Result.append_character (':') + Result.append (ic.item.representation) + end + Result.append_character ('}') + end feature -- Mesurement count: INTEGER - -- Number of field + -- Number of field. do - Result := object.count + Result := items.count end feature -- Access @@ -252,7 +263,7 @@ feature -- Access new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING] -- Fresh cursor associated with current structure do - Result := object.new_cursor + Result := items.new_cursor end feature -- Status report @@ -260,58 +271,61 @@ feature -- Status report is_empty: BOOLEAN -- Is empty object? do - Result := object.is_empty + Result := items.is_empty end feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_json_object' procedure on `a_visitor'.) - do - a_visitor.visit_json_object (Current) - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_json_object' procedure on `a_visitor'.) + do + a_visitor.visit_json_object (Current) + end feature -- Conversion - map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING] - --A representation that maps keys to values - do - Result := object - end + map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING] + -- A representation that maps keys to values + do + Result := items + end feature -- Report - hash_code: INTEGER - -- Hash code value - do - from - object.start - Result := object.out.hash_code - until - object.off - loop - Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code - object.forth - end - -- Ensure it is a positive value. - Result := Result.hash_code - end + hash_code: INTEGER + -- Hash code value + do + from + items.start + Result := items.out.hash_code + until + items.off + loop + Result := ((Result \\ 8388593) |<< 8) + items.item_for_iteration.hash_code + items.forth + end + -- Ensure it is a positive value. + Result := Result.hash_code + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := count.out + " item(s)" - end + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := count.out + "item(s)" + end feature {NONE} -- Implementation - object: HASH_TABLE [JSON_VALUE, JSON_STRING] - -- Value container + items: HASH_TABLE [JSON_VALUE, JSON_STRING] + -- Value container invariant - object_not_void: object /= Void + items_not_void: items /= Void +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_string.e b/contrib/library/text/parser/json/library/kernel/json_string.e index 89ec4648..bf246f6a 100644 --- a/contrib/library/text/parser/json/library/kernel/json_string.e +++ b/contrib/library/text/parser/json/library/kernel/json_string.e @@ -1,70 +1,117 @@ note - - description: "[ - A JSON_STRING represent a string in JSON. - A string is a collection of zero or more Unicodes characters, wrapped in double - quotes, using blackslash espaces. - ]" - - author: "Javier Velilla" - date: "2008/08/24" - revision: "Revision 0.1" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" - + description: "[ + A JSON_STRING represent a string in JSON. + A string is a collection of zero or more Unicodes characters, wrapped in double + quotes, using blackslash espaces. + ]" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" class - JSON_STRING + JSON_STRING inherit - JSON_VALUE - redefine - is_equal - end + + JSON_VALUE + redefine + is_equal + end create - make_json, - make_json_from_string_32, - make_with_escaped_json + make_from_string, make_from_string_32, make_from_string_general, + make_from_escaped_json_string, + make_with_escaped_json, make_json, make_json_from_string_32 convert - make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}), - make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32}) + make_from_string ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}), + make_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32}), + make_from_string_general ({READABLE_STRING_GENERAL, STRING_GENERAL, IMMUTABLE_STRING_GENERAL}) feature {NONE} -- Initialization - make_json (s: READABLE_STRING_8) - -- Initialize. - require - item_not_void: s /= Void - do - make_with_escaped_json (escaped_json_string (s)) - end + make_from_string (s: READABLE_STRING_8) + -- Initialize from ascii string `s'. + require + s_not_void: s /= Void + do + make_from_escaped_json_string (escaped_json_string (s)) + end - make_json_from_string_32 (s: READABLE_STRING_32) - -- Initialize from STRING_32 `s'. - require - item_not_void: s /= Void - do - make_with_escaped_json (escaped_json_string_32 (s)) - end + make_from_string_32 (s: READABLE_STRING_32) + -- Initialize from unicode string `s'. + require + s_not_void: s /= Void + do + make_from_escaped_json_string (escaped_json_string (s)) + end - make_with_escaped_json (s: READABLE_STRING_8) - -- Initialize with an_item already escaped - require - item_not_void: s /= Void - do - item := s - end + make_from_string_general (s: READABLE_STRING_GENERAL) + -- Initialize from string `s'. + require + s_not_void: s /= Void + do + if attached {READABLE_STRING_8} s as s8 then + make_from_string (s8) + else + make_from_string_32 (s.as_string_32) + end + end + + make_from_escaped_json_string (a_escaped_string: READABLE_STRING_8) + -- Initialize with `a_escaped_string' already JSON escaped. + require + a_escaped_string_not_void: a_escaped_string /= Void + do + item := a_escaped_string + end + + make_with_escaped_json (a_escaped_string: READABLE_STRING_8) + -- Initialize with `a_escaped_string' already JSON escaped. + obsolete + "Use `make_from_escaped_json_string' Sept/2014" + require + a_escaped_string_not_void: a_escaped_string /= Void + do + make_from_escaped_json_string (a_escaped_string) + end + + make_from_json_string (a_json: JSON_STRING) + -- Initialize with `a_json' string value. + do + make_from_escaped_json_string (a_json.item) + end + + make_json (s: READABLE_STRING_8) + -- Initialize. + obsolete + "Use `make_from_string' Sept/2014" + require + item_not_void: s /= Void + do + make_with_escaped_json (escaped_json_string (s)) + end + + make_json_from_string_32 (s: READABLE_STRING_32) + -- Initialize from STRING_32 `s'. + obsolete + "Use `make_from_string_32' Sept/2014" + require + item_not_void: s /= Void + do + make_with_escaped_json (escaped_json_string (s)) + end feature -- Access - item: STRING - -- Contents with escaped entities if any + item: STRING + -- Contents with escaped entities if any feature -- Conversion unescaped_string_8: STRING_8 - -- Unescaped string from `item'. + -- Unescaped ascii string from `item'. --| note: valid only if `item' does not encode any unicode character. local s: like item @@ -75,7 +122,7 @@ feature -- Conversion end unescaped_string_32: STRING_32 - -- Unescaped string 32 from `item' + -- Unescaped uncode string from `item' --| some encoders uses UTF-8 , and not the recommended pure json encoding --| thus, let's support the UTF-8 encoding during decoding. local @@ -86,14 +133,14 @@ feature -- Conversion unescape_to_string_32 (Result) end - representation: STRING - -- String representation of `item' with escaped entities if any - do - create Result.make (item.count + 2) - Result.append_character ('%"') - Result.append (item) - Result.append_character ('%"') - end + representation: STRING + -- String representation of `item' with escaped entities if any. + do + create Result.make (item.count + 2) + Result.append_character ('%"') + Result.append (item) + Result.append_character ('%"') + end unescape_to_string_8 (a_output: STRING_8) -- Unescape string `item' into `a_output'. @@ -105,16 +152,23 @@ feature -- Conversion do s := item n := s.count - from i := 1 until i > n loop - c := s[i] + from + i := 1 + until + i > n + loop + c := s [i] if c = '\' then if i < n then - inspect s[i+1] + inspect s [i + 1] + when '%"' then + a_output.append_character ('%"') + i := i + 2 when '\' then a_output.append_character ('\') i := i + 2 - when '%"' then - a_output.append_character ('%"') + when '/' then + a_output.append_character ('/') i := i + 2 when 'b' then a_output.append_character ('%B') @@ -132,15 +186,15 @@ feature -- Conversion a_output.append_character ('%T') i := i + 2 when 'u' then - --| Leave Unicode \uXXXX unescaped - a_output.append_character ('\') + --| Leave unicode \uXXXX unescaped + a_output.append_character (c) -- '\' i := i + 1 else - a_output.append_character ('\') + a_output.append_character (c) -- '\' i := i + 1 end else - a_output.append_character ('\') + a_output.append_character (c) -- '\' i := i + 1 end else @@ -163,16 +217,23 @@ feature -- Conversion do s := item n := s.count - from i := 1 until i > n loop + from + i := 1 + until + i > n + loop ch := s.item (i) if ch = '\' then if i < n then - inspect s[i+1] + inspect s [i + 1] + when '%"' then + a_output.append_character ('%"') + i := i + 2 when '\' then a_output.append_character ('\') i := i + 2 - when '%"' then - a_output.append_character ('%"') + when '/' then + a_output.append_character ('/') i := i + 2 when 'b' then a_output.append_character ('%B') @@ -194,50 +255,40 @@ feature -- Conversion if hex.count = 4 then a_output.append_code (hexadecimal_to_natural_32 (hex)) end - i := i + 6 -- i +2 +4 + i := i + 6 -- i+2+4 else - a_output.append_character ('\') + a_output.append_character (ch) -- '\' i := i + 1 end else - a_output.append_character ('\') + a_output.append_character (ch) -- '\' i := i + 1 end else c := ch.natural_32_code if c <= 0x7F then -- 0xxxxxxx - check ch = c.to_character_32 end + check + ch = c.to_character_32 + end a_output.append_character (ch) elseif c <= 0xDF then -- 110xxxxx 10xxxxxx i := i + 1 if i <= n then - a_output.append_code ( - ((c & 0x1F) |<< 6) | - (s.code (i) & 0x3F) - ) + a_output.append_code (((c & 0x1F) |<< 6) | (s.code (i) & 0x3F)) end elseif c <= 0xEF then -- 1110xxxx 10xxxxxx 10xxxxxx i := i + 2 if i <= n then - a_output.append_code ( - ((c & 0xF) |<< 12) | - ((s.code (i - 1) & 0x3F) |<< 6) | - (s.code (i) & 0x3F) - ) + a_output.append_code (((c & 0xF) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F)) end elseif c <= 0xF7 then -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx i := i + 3 if i <= n then - a_output.append_code ( - ((c & 0x7) |<< 18) | - ((s.code (i - 2) & 0x3F) |<< 12) | - ((s.code (i - 1) & 0x3F) |<< 6) | - (s.code (i) & 0x3F) - ) + a_output.append_code (((c & 0x7) |<< 18) | ((s.code (i - 2) & 0x3F) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F)) end end i := i + 1 @@ -247,65 +298,101 @@ feature -- Conversion feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_json_string' procedure on `a_visitor'.) - do - a_visitor.visit_json_string (Current) - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_json_string' procedure on `a_visitor'.) + do + a_visitor.visit_json_string (Current) + end feature -- Comparison - is_equal (other: like Current): BOOLEAN - -- Is JSON_STRING made of same character sequence as `other' - -- (possibly with a different capacity)? - do - Result := item.same_string (other.item) - end + is_equal (other: like Current): BOOLEAN + -- Is JSON_STRING made of same character sequence as `other' + -- (possibly with a different capacity)? + do + Result := item.same_string (other.item) + end feature -- Change Element - append (a_string: STRING) - -- Add a_string - require - a_string_not_void: a_string /= Void - do - item.append_string (a_string) - end + append (a_escaped_string: READABLE_STRING_8) + -- Add JSON escaped string `a_escaped_string' + require + a_escaped_string_not_void: a_escaped_string /= Void + do + item.append_string (a_escaped_string) + end + + append_json_string (a_json_string: JSON_STRING) + -- Add JSON string `a_json_string' + require + a_json_string_not_void: a_json_string /= Void + do + append (a_json_string.item) + end + + append_string (s: READABLE_STRING_8) + -- Add ascii string `s' + require + s_not_void: s /= Void + do + append (escaped_json_string (s)) + end + + append_string_32 (s: READABLE_STRING_32) + -- Add unicode string `s' + require + s_not_void: s /= Void + do + append (escaped_json_string (s)) + end + + append_string_general (s: READABLE_STRING_GENERAL) + -- Add unicode string `s' + require + s_not_void: s /= Void + do + if attached {READABLE_STRING_8} s as s8 then + append_string (s.as_string_8) + else + append_string_32 (s.as_string_32) + end + end feature -- Status report - hash_code: INTEGER - -- Hash code value - do - Result := item.hash_code - end + hash_code: INTEGER + -- Hash code value + do + Result := item.hash_code + end feature -- Status report - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - Result := item - end + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := item + end feature {NONE} -- Implementation - is_hexadecimal (s: READABLE_STRING_8): BOOLEAN - -- Is `s' an hexadecimal value? + is_hexadecimal (s: READABLE_STRING_8): BOOLEAN + -- Is `s' an hexadecimal value? local i: INTEGER - do + do from Result := True i := 1 until i > s.count or not Result loop - Result := s[i].is_hexa_digit + Result := s [i].is_hexa_digit i := i + 1 end - end + end hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32 -- Hexadecimal string `s' converted to NATURAL_32 value @@ -317,13 +404,11 @@ feature {NONE} -- Implementation char: CHARACTER do nb := s.count - if nb >= 2 and then s.item (2) = 'x' then i := 3 else i := 1 end - from until i > nb @@ -339,37 +424,10 @@ feature {NONE} -- Implementation end end - escaped_json_string (s: READABLE_STRING_8): STRING_8 - -- JSON string with '"' and '\' characters escaped - require - s_not_void: s /= Void - local - i, n: INTEGER - c: CHARACTER_8 - do - n := s.count - create Result.make (n + n // 10) - from i := 1 until i > n loop - c := s.item (i) - inspect c - when '%"' then Result.append_string ("\%"") - when '\' then Result.append_string ("\\") - when '%B' then Result.append_string ("\b") - when '%F' then Result.append_string ("\f") - when '%N' then Result.append_string ("\n") - when '%R' then Result.append_string ("\r") - when '%T' then Result.append_string ("\t") - else - Result.extend (c) - end - i := i + 1 - end - end - - escaped_json_string_32 (s: READABLE_STRING_32): STRING_8 - -- JSON string with '"' and '\' characters and Unicode escaped - require - s_not_void: s /= Void + escaped_json_string (s: READABLE_STRING_GENERAL): STRING_8 + -- JSON string with '"' and '\' characters and unicode escaped + require + s_not_void: s /= Void local i, j, n: INTEGER uc: CHARACTER_32 @@ -378,25 +436,44 @@ feature {NONE} -- Implementation do n := s.count create Result.make (n + n // 10) - from i := 1 until i > n loop + from + i := 1 + until + i > n + loop uc := s.item (i) if uc.is_character_8 then c := uc.to_character_8 inspect c - when '%"' then Result.append_string ("\%"") - when '\' then Result.append_string ("\\") - when '%B' then Result.append_string ("\b") - when '%F' then Result.append_string ("\f") - when '%N' then Result.append_string ("\n") - when '%R' then Result.append_string ("\r") - when '%T' then Result.append_string ("\t") + when '%"' then + Result.append_string ("\%"") + when '\' then + Result.append_string ("\\") + when '/' then + -- To avoid issue with Javascript ... + -- escape only = 4 loop h.prepend_integer (0) end - check h.count = 4 end + check + hexastring_has_4_chars: h.count = 4 + end Result.append (h) end i := i + 1 @@ -420,6 +498,9 @@ feature {NONE} -- Implementation end invariant - item_not_void: item /= Void + item_not_void: item /= Void +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/json_value.e b/contrib/library/text/parser/json/library/kernel/json_value.e index bbf47c7c..a7fb0f43 100644 --- a/contrib/library/text/parser/json/library/kernel/json_value.e +++ b/contrib/library/text/parser/json/library/kernel/json_value.e @@ -1,43 +1,46 @@ note - description:"[ - JSON_VALUE represent a value in JSON. - A value can be - * a string in double quotes - * a number - * boolean value(true, false ) - * null - * an object - * an array - ]" - author: "Javier Velilla" - date: "2008/05/19" - revision: "Revision 0.1" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" - + description: "[ + JSON_VALUE represent a value in JSON. + A value can be + * a string in double quotes + * a number + * boolean value(true, false ) + * null + * an object + * an array + ]" + author: "Javier Velilla" + date: "2008/05/19" + revision: "Revision 0.1" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" deferred class - JSON_VALUE + JSON_VALUE inherit - HASHABLE - DEBUG_OUTPUT - + HASHABLE + + DEBUG_OUTPUT + feature -- Access - representation: STRING - -- UTF-8 encoded Unicode string representation of Current - deferred - end + representation: STRING + -- UTF-8 encoded Unicode string representation of Current + deferred + end feature -- Visitor pattern - accept (a_visitor: JSON_VISITOR) - -- Accept `a_visitor'. - -- (Call `visit_*' procedure on `a_visitor'.) - require - a_visitor_not_void: a_visitor /= Void - deferred - end + accept (a_visitor: JSON_VISITOR) + -- Accept `a_visitor'. + -- (Call `visit_*' procedure on `a_visitor'.) + require + a_visitor_not_void: a_visitor /= Void + deferred + end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/kernel/scanner/json_parser.e b/contrib/library/text/parser/json/library/kernel/scanner/json_parser.e deleted file mode 100644 index a3bf29f3..00000000 --- a/contrib/library/text/parser/json/library/kernel/scanner/json_parser.e +++ /dev/null @@ -1,513 +0,0 @@ -note - - description: "Parse serialized JSON data" - author: "jvelilla" - date: "2008/08/24" - revision: "Revision 0.1" - -class - JSON_PARSER - -inherit - JSON_READER - JSON_TOKENS - -create - make_parser - -feature {NONE} -- Initialize - - make_parser (a_json: STRING) - -- Initialize. - require - json_not_empty: a_json /= Void and then not a_json.is_empty - do - make (a_json) - is_parsed := True - create errors.make - end - -feature -- Status report - - is_parsed: BOOLEAN - -- Is parsed? - - errors: LINKED_LIST [STRING] - -- Current errors - - current_errors: STRING - -- Current errors as string - do - create Result.make_empty - from - errors.start - until - errors.after - loop - Result.append_string (errors.item + "%N") - errors.forth - end - end - -feature -- Element change - - report_error (e: STRING) - -- Report error `e' - require - e_not_void: e /= Void - do - errors.force (e) - end - -feature -- Commands - - parse_json: detachable JSON_VALUE - -- Parse JSON data `representation' - -- start ::= object | array - do - if is_valid_start_symbol then - Result := parse - if extra_elements then - is_parsed := False - end - else - is_parsed := False - report_error ("Syntax error unexpected token, expecting `{' or `['") - end - end - - parse: detachable JSON_VALUE - -- Parse JSON data `representation' - local - c: CHARACTER - do - if is_parsed then - skip_white_spaces - c := actual - inspect c - when j_OBJECT_OPEN then - Result := parse_object - when j_STRING then - Result := parse_string - when j_ARRAY_OPEN then - Result := parse_array - else - if c.is_digit or c = j_MINUS then - Result := parse_number - elseif is_null then - Result := create {JSON_NULL} - next - next - next - elseif is_true then - Result := create {JSON_BOOLEAN}.make_boolean (True) - next - next - next - elseif is_false then - Result := create {JSON_BOOLEAN}.make_boolean (False) - next - next - next - next - else - is_parsed := False - report_error ("JSON is not well formed in parse") - Result := Void - end - end - end - ensure - is_parsed_implies_result_not_void: is_parsed implies Result /= Void - end - - parse_object: JSON_OBJECT - -- object - -- {} - -- {"key" : "value" [,]} - local - has_more: BOOLEAN - l_json_string: detachable JSON_STRING - l_value: detachable JSON_VALUE - do - create Result.make - -- check if is an empty object {} - next - skip_white_spaces - if actual = j_OBJECT_CLOSE then - --is an empty object - else - -- a complex object {"key" : "value"} - previous - from has_more := True until not has_more loop - next - skip_white_spaces - l_json_string := parse_string - next - skip_white_spaces - if actual = ':' then - next - skip_white_spaces - else - is_parsed := False - report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out) - has_more := False - end - - l_value := parse - if is_parsed and then (l_value /= Void and l_json_string /= Void) then - Result.put (l_value, l_json_string) - next - skip_white_spaces - if actual = j_OBJECT_CLOSE then - has_more := False - elseif actual /= ',' then - has_more := False - is_parsed := False - report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]") - end - else - has_more := False - -- explain the error - end - end - end - end - - parse_string: detachable JSON_STRING - -- Parsed string - local - has_more: BOOLEAN - l_json_string: STRING - l_unicode: STRING - c: like actual - do - create l_json_string.make_empty - if actual = j_STRING then - from - has_more := True - until - not has_more - loop - next - c := actual - if c = j_STRING then - has_more := False - elseif c = '%H' then - next - c := actual - if c = 'u' then - create l_unicode.make_from_string ("\u") - l_unicode.append (read_unicode) - c := actual - if is_valid_unicode (l_unicode) then - l_json_string.append (l_unicode) - else - has_more := False - is_parsed := False - report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]") - end - elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then - has_more := False - is_parsed := False - report_error ("Input String is not well formed JSON, found [" + c.out + " ]") - else - l_json_string.append_character ('\') - l_json_string.append_character (c) - end - else - if is_special_character (c) and c /= '/' then - has_more := False - is_parsed := False - report_error ("Input String is not well formed JSON, found [" + c.out + " ]") - else - l_json_string.append_character (c) - end - end - end - create Result.make_with_escaped_json (l_json_string) - else - Result := Void - end - end - - parse_array: JSON_ARRAY - -- array - -- [] - -- [elements [,]] - local - flag: BOOLEAN - l_value: detachable JSON_VALUE - c: like actual - do - create Result.make_array - --check if is an empty array [] - next - skip_white_spaces - if actual = j_array_close then - --is an empty array - else - previous - from - flag := True - until - not flag - loop - next - skip_white_spaces - l_value := parse - if is_parsed and then l_value /= Void then - Result.add (l_value) - next - skip_white_spaces - c := actual - if c = j_ARRAY_CLOSE then - flag := False - elseif c /= ',' then - flag := False - is_parsed := False - report_error ("Array is not well formed JSON, found [" + c.out + " ]") - end - else - flag := False - report_error ("Array is not well formed JSON, found [" + actual.out + " ]") - end - end - end - end - - parse_number: detachable JSON_NUMBER - -- Parsed number - local - sb: STRING - flag: BOOLEAN - is_integer: BOOLEAN - c: like actual - do - create sb.make_empty - sb.append_character (actual) - - from - flag := True - until - not flag - loop - next - c := actual - if not has_next or is_close_token (c) - or c = ',' or c = '%N' or c = '%R' - then - flag := False - previous - else - sb.append_character (c) - end - end - - if is_valid_number (sb) then - if sb.is_integer then - create Result.make_integer (sb.to_integer) - is_integer := True - elseif sb.is_double and not is_integer then - create Result.make_real (sb.to_double) - end - else - is_parsed := False - report_error ("Expected a number, found: [ " + sb + " ]") - end - end - - is_null: BOOLEAN - -- Word at index represents null? - local - l_null: STRING - l_string: STRING - do - l_null := null_id - l_string := json_substring (index,index + l_null.count - 1) - if l_string.is_equal (l_null) then - Result := True - end - end - - is_false: BOOLEAN - -- Word at index represents false? - local - l_false: STRING - l_string: STRING - do - l_false := false_id - l_string := json_substring (index, index + l_false.count - 1) - if l_string.is_equal (l_false) then - Result := True - end - end - - is_true: BOOLEAN - -- Word at index represents true? - local - l_true: STRING - l_string: STRING - do - l_true := true_id - l_string := json_substring (index,index + l_true.count - 1) - if l_string.is_equal (l_true) then - Result := True - end - end - - read_unicode: STRING - -- Read Unicode and return value - local - i: INTEGER - do - create Result.make_empty - from - i := 1 - until - i > 4 or not has_next - loop - next - Result.append_character (actual) - i := i + 1 - end - end - -feature {NONE} -- Implementation - - is_valid_number (a_number: STRING): BOOLEAN - -- is 'a_number' a valid number based on this regular expression - -- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"? - local - s: detachable STRING - c: CHARACTER - i,n: INTEGER - do - create s.make_empty - n := a_number.count - if n = 0 then - Result := False - else - Result := True - i := 1 - --| "-?" - c := a_number[i] - if c = '-' then - s.extend (c); i := i + 1; c := a_number[i] - end - --| "0|[1-9]\d* - if c.is_digit then - if c = '0' then - --| "0" - s.extend (c); i := i + 1; c := a_number[i] - else - --| "[1-9]" - s.extend (c); i := i + 1; c := a_number[i] - --| "\d*" - from until i > n or not c.is_digit loop - s.extend (c); i := i + 1; c := a_number[i] - end - end - end - end - if Result then - --| "(\.\d+)?" - if c = '.' then - --| "\.\d+" = "\.\d\d*" - s.extend (c); i := i + 1; c := a_number[i] - if c.is_digit then - from until i > n or not c.is_digit loop - s.extend (c); i := i + 1; c := a_number[i] - end - else - Result := False --| expecting digit - end - end - end - if Result then --| "(?:[eE][+-]?\d+)?\b" - if c = 'e' or c = 'E' then - --| "[eE][+-]?\d+" - s.extend (c); i := i + 1; c := a_number[i] - if c = '+' or c = '-' then - s.extend (c); i := i + 1; c := a_number[i] - end - if c.is_digit then - from until i > n or not c.is_digit loop - s.extend (c); i := i + 1; c := a_number[i] - end - else - Result := False --| expecting digit - end - end - end - if Result then --| "\b" - from until i > n or not c.is_space loop - s.extend (c); i := i + 1; c := a_number[i] - end - Result := i > n and then s.same_string (a_number) - end - end - - is_valid_unicode (a_unicode: STRING): BOOLEAN - -- is 'a_unicode' a valid Unicode based on this regular expression - -- "\\u[0-9a-fA-F]{4}" - local - i: INTEGER - do - if - a_unicode.count = 6 and then - a_unicode[1] = '\' and then - a_unicode[2] = 'u' - then - from - Result := True - i := 3 - until - i > 6 or Result = False - loop - inspect a_unicode[i] - when '0'..'9', 'a'..'f', 'A'..'F' then - else - Result := False - end - i := i + 1 - end - end - end - - extra_elements: BOOLEAN - -- has more elements? - local - c: like actual - do - if has_next then - next - end - from - c := actual - until - c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next - loop - next - end - Result := has_next - end - - is_valid_start_symbol : BOOLEAN - -- expecting `{' or `[' as start symbol - do - if attached representation as s and then s.count > 0 then - Result := s[1] = '{' or s[1] = '[' - end - end - -feature {NONE} -- Constants - - false_id: STRING = "false" - - true_id: STRING = "true" - - null_id: STRING = "null" - - -end diff --git a/contrib/library/text/parser/json/library/kernel/scanner/json_tokens.e b/contrib/library/text/parser/json/library/kernel/scanner/json_tokens.e deleted file mode 100644 index 86f86ba3..00000000 --- a/contrib/library/text/parser/json/library/kernel/scanner/json_tokens.e +++ /dev/null @@ -1,77 +0,0 @@ -note - description: "" - author: "jvelilla" - date: "2008/08/24" - revision: "0.1" - -class - JSON_TOKENS - -feature -- Access - - j_OBJECT_OPEN: CHARACTER = '{' - j_ARRAY_OPEN: CHARACTER = '[' - j_OBJECT_CLOSE: CHARACTER = '}' - j_ARRAY_CLOSE: CHARACTER = ']' - - j_STRING: CHARACTER = '"' - j_PLUS: CHARACTER = '+' - j_MINUS: CHARACTER = '-' - j_DOT: CHARACTER = '.' - -feature -- Status report - - is_open_token (c: CHARACTER): BOOLEAN - -- Characters which open a type - do - inspect c - when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then - Result := True - else - - end - end - - is_close_token (c: CHARACTER): BOOLEAN - -- Characters which close a type - do - inspect c - when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then - Result := True - else - - end - end - - is_special_character (c: CHARACTER): BOOLEAN - -- Control Characters - -- %F Form feed - -- %H backslasH - -- %N Newline - -- %R carriage Return - -- %T horizontal Tab - -- %B Backspace - -- / Solidus - -- " Quotation - do - inspect c - when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then - Result := True - else - - end - end - - is_special_control (c: CHARACTER): BOOLEAN - --Control Characters - -- \b\f\n\r\t - do - inspect c - when 'b', 'f', 'n', 'r', 't' then - Result := True - else - - end - end - -end diff --git a/contrib/library/text/parser/json/library/kernel/shared_ejson.e b/contrib/library/text/parser/json/library/kernel/shared_ejson.e deleted file mode 100644 index 421b83a4..00000000 --- a/contrib/library/text/parser/json/library/kernel/shared_ejson.e +++ /dev/null @@ -1,38 +0,0 @@ -note - description: "[ - Shared factory class for creating JSON objects. Maps JSON - objects to ELKS HASH_TABLEs and JSON arrays to ELKS - LINKED_LISTs. Use non-conforming inheritance from this - class to ensure that your classes share the same - JSON_FACTORY instance. - ]" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision: 89185 $" - file: "$HeadURL: $" - -class SHARED_EJSON - -feature - - json: EJSON - -- A shared EJSON instance with default converters for - --LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE] - local - jalc: JSON_ARRAYED_LIST_CONVERTER - jllc: JSON_LINKED_LIST_CONVERTER - jhtc: JSON_HASH_TABLE_CONVERTER - once - create Result - - create jalc.make - Result.add_converter (jalc) - - create jllc.make - Result.add_converter (jllc) - - create jhtc.make - Result.add_converter (jhtc) - end - -end -- class SHARED_EJSON diff --git a/contrib/library/text/parser/json/library/license.lic b/contrib/library/text/parser/json/library/license.lic new file mode 100644 index 00000000..4d58ac79 --- /dev/null +++ b/contrib/library/text/parser/json/library/license.lic @@ -0,0 +1,4 @@ +${NOTE_KEYWORD} + copyright: "2010-${YEAR}, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" + diff --git a/contrib/library/text/parser/json/library/parser/json_parser.e b/contrib/library/text/parser/json/library/parser/json_parser.e new file mode 100644 index 00000000..c016da22 --- /dev/null +++ b/contrib/library/text/parser/json/library/parser/json_parser.e @@ -0,0 +1,679 @@ +note + description: "Parse serialized JSON data" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + +class + JSON_PARSER + +inherit + JSON_READER + rename + make as make_reader, + reset as reset_reader + end + + JSON_TOKENS + +create + make_with_string, + make_parser + +feature {NONE} -- Initialize + + make_with_string (a_content: STRING) + -- Initialize parser with JSON content `a_content'. + require + a_content_not_empty: a_content /= Void and then not a_content.is_empty + do + create errors.make + make_reader (a_content) + reset + end + + make_parser (a_json: STRING) + -- Initialize. + obsolete + "Use `make_with_string' [sept/2014]." + do + make_with_string (a_json) + end + +feature -- Status report + + is_parsed: BOOLEAN + -- Is parsed ? + + is_valid: BOOLEAN + -- Is valid? + do + Result := not has_error + end + + has_error: BOOLEAN + -- Has error? + + errors: LINKED_LIST [STRING] + -- Current errors + + errors_as_string: STRING + -- String representation of `errors'. + do + create Result.make_empty + across + errors as ic + loop + Result.append_string (ic.item) + Result.append_character ('%N') + end + end + + current_errors: STRING + -- Current errors as string + obsolete + "USe errors_as_string [sept/2014]" + do + Result := errors_as_string + end + +feature -- Access + + parsed_json_value: detachable JSON_VALUE + -- Parsed json value if any. + require + is_parsed: is_parsed + attribute + ensure + attached_result_if_valid: is_valid implies Result /= Void + end + + parsed_json_object: detachable JSON_OBJECT + -- parsed json value as a JSON_OBJECT if it is an object. + require + is_parsed: is_parsed + do + if attached {JSON_OBJECT} parsed_json_value as j_object then + Result := j_object + end + end + + parsed_json_array: detachable JSON_ARRAY + -- parsed json value as a JSON_OBJECT if it is an array. + require + is_parsed: is_parsed + do + if attached {JSON_ARRAY} parsed_json_value as j_array then + Result := j_array + end + end + +feature -- Commands + + reset + -- Reset parsing values. + do + parsed_json_value := Void + errors.wipe_out + has_error := False + is_parsed := False + end + + parse_content + -- Parse JSON content `representation'. + -- start ::= object | array + do + reset + reset_reader + + if is_valid_start_symbol then + parsed_json_value := next_json_value + if extra_elements then + report_error ("Remaining element outside the main json value!") + end + else + report_error ("Syntax error unexpected token, expecting `{' or `['") + end + is_parsed := is_valid + end + + +feature -- Element change + + report_error (e: STRING) + -- Report error `e' + require + e_not_void: e /= Void + do + has_error := True + errors.force (e) + ensure + has_error: has_error + is_not_valid: not is_valid + end + +feature -- Obsolete commands + + parse_json: detachable JSON_VALUE + -- Parse JSON data `representation' + -- start ::= object | array + obsolete + "Use `parse_content' and `parsed_json_value' [sept/2014]." + do + parse_content + if is_parsed then + Result := parsed_json_value + end + end + + parse_object: detachable JSON_OBJECT + -- Parse JSON data `representation' + -- start ::= object | array + obsolete + "Use `parse_content' and `parsed_json_value' [nov/2014]." + do + parse_content + if is_parsed and then attached {JSON_OBJECT} parsed_json_value as jo then + Result := jo + end + end + + parse: detachable JSON_VALUE + -- Next JSON value from current position on `representation'. + obsolete + "Use restricted `next_parsed_json_value' [sept/2014]." + do + Result := next_parsed_json_value + is_parsed := is_valid + end + +feature {JSON_PARSER_ACCESS} -- Obsolete commands: restricted area + + next_parsed_json_value: detachable JSON_VALUE + -- Return next json value from current position. + --| this does not call `reset_reader'. + do + reset + Result := next_json_value + end + +feature {NONE} -- Implementation: parsing + + next_json_value: detachable JSON_VALUE + -- Next JSON value from current position on `representation'. + local + c: CHARACTER + do + if not has_error then + skip_white_spaces + c := actual + inspect c + when token_object_open then + Result := next_json_object + when token_double_quote then + Result := parse_string + when token_array_open then + Result := parse_array + else + if c.is_digit or c = token_minus then + Result := parse_number + elseif is_null then + Result := create {JSON_NULL} + next + next + next + elseif is_true then + Result := create {JSON_BOOLEAN}.make_true + next + next + next + elseif is_false then + Result := create {JSON_BOOLEAN}.make_false + next + next + next + next + else + report_error ("JSON is not well formed in parse") + Result := Void + end + end + end + ensure + is_parsed_implies_result_not_void: not has_error implies Result /= Void + end + + next_json_object: JSON_OBJECT + -- object + -- {} + -- {"key" : "value" [,]} + local + has_more: BOOLEAN + l_json_string: detachable JSON_STRING + l_value: detachable JSON_VALUE + do + create Result.make + --| check if is an empty object {} + next + skip_white_spaces + if actual = token_object_close then + --| is an empty object + else + --| a complex object {"key" : "value"} + previous + from + has_more := True + until + not has_more + loop + next + skip_white_spaces + l_json_string := parse_string + next + skip_white_spaces + if actual = token_colon then --| token_colon = ':' + next + skip_white_spaces + else + report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out) + has_more := False + end + l_value := next_json_value + if not has_error and then (l_value /= Void and l_json_string /= Void) then + Result.put (l_value, l_json_string) + next + skip_white_spaces + if actual = token_object_close then + has_more := False + elseif actual /= token_comma then + has_more := False + report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]") + end + else + has_more := False + -- explain the error + end + end + end + end + + parse_string: detachable JSON_STRING + -- Parsed string + local + has_more: BOOLEAN + l_json_string: STRING + l_unicode: STRING + c: like actual + do + create l_json_string.make_empty + if actual = token_double_quote then + from + has_more := True + until + not has_more + loop + next + c := actual + if c = token_double_quote then + has_more := False + elseif c = '%H' then -- '%H' = '\' = reverse solidus + next + c := actual + if c = 'u' then + create l_unicode.make_from_string ("\u") + l_unicode.append (read_unicode) + c := actual + if is_valid_unicode (l_unicode) then + l_json_string.append (l_unicode) + else + has_more := False + report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]") + end + elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then + has_more := False + report_error ("Input String is not well formed JSON, found [" + c.out + " ]") + else + l_json_string.append_character ('\') + l_json_string.append_character (c) + end + else + if is_special_character (c) and c /= '/' then + has_more := False + report_error ("Input String is not well formed JSON, found [" + c.out + " ]") + else + l_json_string.append_character (c) + end + end + end + create Result.make_from_escaped_json_string (l_json_string) + else + Result := Void + end + end + + parse_array: JSON_ARRAY + -- array + -- [] + -- [elements [,]] + local + flag: BOOLEAN + l_value: detachable JSON_VALUE + c: like actual + do + create Result.make_empty + -- check if is an empty array [] + next + skip_white_spaces + if actual = token_array_close then + -- is an empty array + else + previous + from + flag := True + until + not flag + loop + next + skip_white_spaces + l_value := next_json_value + if not has_error and then l_value /= Void then + Result.add (l_value) + next + skip_white_spaces + c := actual + if c = token_array_close then + flag := False + elseif c /= token_comma then + flag := False + report_error ("Array is not well formed JSON, found [" + c.out + " ]") + end + else + flag := False + report_error ("Array is not well formed JSON, found [" + actual.out + " ]") + end + end + end + end + + parse_number: detachable JSON_NUMBER + -- Parsed number + local + sb: STRING + flag: BOOLEAN + is_integer: BOOLEAN + c: like actual + do + create sb.make_empty + sb.append_character (actual) + from + flag := True + until + not flag + loop + next + c := actual + if not has_next or is_close_token (c) or c = token_comma or c = '%N' or c = '%R' then + flag := False + previous + else + sb.append_character (c) + end + end + if is_valid_number (sb) then + if sb.is_integer then + create Result.make_integer (sb.to_integer) + is_integer := True + elseif sb.is_double and not is_integer then + create Result.make_real (sb.to_double) + end + else + report_error ("Expected a number, found: [ " + sb + " ]") + end + end + + is_null: BOOLEAN + -- Word at index represents null? + local + l_null: STRING + l_string: STRING + do + l_null := null_id + l_string := json_substring (index, index + l_null.count - 1) + if l_string.is_equal (l_null) then + Result := True + end + end + + is_false: BOOLEAN + -- Word at index represents false? + local + l_false: STRING + l_string: STRING + do + l_false := false_id + l_string := json_substring (index, index + l_false.count - 1) + if l_string.is_equal (l_false) then + Result := True + end + end + + is_true: BOOLEAN + -- Word at index represents true? + local + l_true: STRING + l_string: STRING + do + l_true := true_id + l_string := json_substring (index, index + l_true.count - 1) + if l_string.is_equal (l_true) then + Result := True + end + end + + read_unicode: STRING + -- Read unicode and return value. + local + i: INTEGER + do + create Result.make_empty + from + i := 1 + until + i > 4 or not has_next + loop + next + Result.append_character (actual) + i := i + 1 + end + end + +feature {NONE} -- Implementation + + is_valid_number (a_number: STRING): BOOLEAN + -- is 'a_number' a valid number based on this regular expression + -- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"? + local + s: detachable STRING + c: CHARACTER + i, n: INTEGER + do + create s.make_empty + n := a_number.count + if n = 0 then + Result := False + else + Result := True + i := 1 + --| "-?" + c := a_number [i] + if c = token_minus then + s.extend (c) + i := i + 1 + if i > n then + Result := False + else + c := a_number [i] + end + end + --| "0|[1-9]\d* + if Result and c.is_digit then + if c = '0' then + --| "0" + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + else + --| "[1-9]" + s.extend (c) + + --| "\d*" + i := i + 1 + if i <= n then + c := a_number [i] + from + until + i > n or not c.is_digit + loop + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + end + end + end + end + end + if i > n then + -- Exit + else + if Result then + --| "(\.\d+)?" + if c = token_dot then + --| "\.\d+" = "\.\d\d*" + s.extend (c) + i := i + 1 + c := a_number [i] + if c.is_digit then + from + until + i > n or not c.is_digit + loop + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + end + else + Result := False --| expecting digit + end + end + end + if Result then --| "(?:[eE][+-]?\d+)?\b" + if is_exp_token (c) then + --| "[eE][+-]?\d+" + s.extend (c) + i := i + 1 + c := a_number [i] + if c = token_plus or c = token_minus then + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + end + if c.is_digit then + from + until + i > n or not c.is_digit + loop + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + end + else + Result := False --| expecting digit + end + end + end + if Result then --| "\b" + from + until + i > n or not c.is_space + loop + s.extend (c) + i := i + 1 + if i <= n then + c := a_number [i] + end + end + Result := i > n and then s.same_string (a_number) + end + end + end + + is_valid_unicode (a_unicode: STRING): BOOLEAN + -- is 'a_unicode' a valid unicode based on the regular expression "\\u[0-9a-fA-F]{4}" . + local + i: INTEGER + do + if a_unicode.count = 6 and then a_unicode [1] = '\' and then a_unicode [2] = 'u' then + from + Result := True + i := 3 + until + i > 6 or Result = False + loop + inspect a_unicode [i] + when '0'..'9', 'a'..'f', 'A'..'F' then + else + Result := False + end + i := i + 1 + end + end + end + + extra_elements: BOOLEAN + -- has more elements? + local + c: like actual + do + if has_next then + next + end + from + c := actual + until + c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next + loop + next + end + Result := has_next + end + + is_valid_start_symbol: BOOLEAN + -- expecting `{' or `[' as start symbol + do + if attached representation as s and then s.count > 0 then + Result := s [1] = token_object_open or s [1] = token_array_open + end + end + +feature {NONE} -- Constants + + false_id: STRING = "false" + + true_id: STRING = "true" + + null_id: STRING = "null" + +note + copyright: "2010-2015, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end diff --git a/contrib/library/text/parser/json/library/parser/json_parser_access.e b/contrib/library/text/parser/json/library/parser/json_parser_access.e new file mode 100644 index 00000000..ffc32d6e --- /dev/null +++ b/contrib/library/text/parser/json/library/parser/json_parser_access.e @@ -0,0 +1,12 @@ +note + description: "Inherit to access restricted feature from {JSON_PARSER}." + date: "$Date$" + revision: "$Revision$" + +deferred class + JSON_PARSER_ACCESS + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end diff --git a/contrib/library/text/parser/json/library/kernel/scanner/json_reader.e b/contrib/library/text/parser/json/library/parser/json_reader.e similarity index 79% rename from contrib/library/text/parser/json/library/kernel/scanner/json_reader.e rename to contrib/library/text/parser/json/library/parser/json_reader.e index 977e91ae..3869ee9f 100644 --- a/contrib/library/text/parser/json/library/kernel/scanner/json_reader.e +++ b/contrib/library/text/parser/json/library/parser/json_reader.e @@ -12,22 +12,28 @@ create feature {NONE} -- Initialization - make (a_json: STRING) - -- Initialize Reader - do - set_representation (a_json) - end + make (a_json: STRING) + -- Initialize Reader + do + set_representation (a_json) + end feature -- Commands - set_representation (a_json: STRING) - -- Set `representation'. - do - a_json.left_adjust - a_json.right_adjust + reset + -- Reset reader + do + index := 1 + end + + set_representation (a_json: STRING) + -- Set `representation'. + do + a_json.left_adjust + a_json.right_adjust representation := a_json - index := 1 - end + reset + end read: CHARACTER -- Read character @@ -65,7 +71,7 @@ feature -- Commands from c := actual until - (c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next + (c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T') or not has_next loop next c := actual @@ -115,4 +121,7 @@ feature {NONE} -- Implementation invariant representation_not_void: representation /= Void +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/parser/json_tokens.e b/contrib/library/text/parser/json/library/parser/json_tokens.e new file mode 100644 index 00000000..0374330f --- /dev/null +++ b/contrib/library/text/parser/json/library/parser/json_tokens.e @@ -0,0 +1,90 @@ +note + description: "Token used by the JSON_PARSER" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + +class + JSON_TOKENS + +feature -- Access + + token_object_open: CHARACTER = '{' + token_object_close: CHARACTER = '}' + + token_array_open: CHARACTER = '[' + token_array_close: CHARACTER = ']' + + token_double_quote: CHARACTER = '"' + token_plus: CHARACTER = '+' + token_minus: CHARACTER = '-' + token_dot: CHARACTER = '.' + token_exp: CHARACTER = 'e' + token_comma: CHARACTER = ',' + token_colon: CHARACTER = ':' + +feature -- Status report + + is_open_token (c: CHARACTER): BOOLEAN + -- Characters which open a type + do + inspect c + when token_object_open, token_array_open, token_double_quote, token_plus, token_minus, token_dot then + Result := True + else + + end + end + + is_close_token (c: CHARACTER): BOOLEAN + -- Characters which close a type + do + inspect c + when token_object_close, token_array_close, token_double_quote then + Result := True + else + + end + end + + is_special_character (c: CHARACTER): BOOLEAN + -- Control Characters + -- %F Form feed + -- %H backslasH + -- %N Newline + -- %R carriage Return + -- %T horizontal Tab + -- %B Backspace + -- / Solidus + -- " Quotation + do + inspect c + when '"', '%H' , '/', '%B', '%F', '%N', '%R', '%T' then -- '%H' = '\' = reverse solidus + Result := True + else + + end + end + + is_special_control (c: CHARACTER): BOOLEAN + -- Control Characters + -- \b\f\n\r\t + do + inspect c + when 'b', 'f', 'n', 'r', 't' then + Result := True + else + + end + end + + is_exp_token (c: CHARACTER): BOOLEAN + -- Is number exposant token? + do + Result := c = token_exp or else c.as_lower = token_exp + end + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end diff --git a/contrib/library/text/parser/json/library/utility/file/json_file_reader.e b/contrib/library/text/parser/json/library/utility/file/json_file_reader.e new file mode 100644 index 00000000..53085adc --- /dev/null +++ b/contrib/library/text/parser/json/library/utility/file/json_file_reader.e @@ -0,0 +1,49 @@ +note + description: "Objects that ..." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + JSON_FILE_READER + +feature -- Access + + read_json_from (a_path: READABLE_STRING_GENERAL): detachable STRING + local + l_file: PLAIN_TEXT_FILE + l_last_string: detachable STRING + l_file_count: INTEGER + l_fetch_done: BOOLEAN + do + create l_file.make_with_name (a_path) + -- We perform several checks until we make a real attempt to open the file. + if not l_file.exists then + print ("error: '" + a_path.out + "' does not exist%N") -- FIXME: unicode may be truncated + else + if not l_file.is_readable then + print ("error: '" + a_path.out + "' is not readable.%N") -- FIXME: unicode may be truncated + else + l_file_count := l_file.count + l_file.open_read + from + create Result.make (l_file_count) + until + l_fetch_done + loop + l_file.read_stream (1_024) + l_last_string := l_file.last_string + l_fetch_done := l_file.exhausted or l_file.end_of_file or l_last_string.count < 1_024 + if not l_last_string.is_empty then + Result.append (l_last_string) + end + end + l_file.close + end + end + end + +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" +end diff --git a/contrib/library/text/parser/json/library/extras/visitor/json_iterator.e b/contrib/library/text/parser/json/library/utility/visitor/json_iterator.e similarity index 72% rename from contrib/library/text/parser/json/library/extras/visitor/json_iterator.e rename to contrib/library/text/parser/json/library/utility/visitor/json_iterator.e index dae48dd1..9f09ee92 100644 --- a/contrib/library/text/parser/json/library/extras/visitor/json_iterator.e +++ b/contrib/library/text/parser/json/library/utility/visitor/json_iterator.e @@ -1,11 +1,8 @@ note - description: - - "JSON Iterator" - + description: "JSON Iterator" pattern: "Iterator visitor" author: "Jocelyn Fiat" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" date: "2013/08/01" revision: "Revision 0.1" @@ -13,6 +10,7 @@ deferred class JSON_ITERATOR inherit + JSON_VISITOR feature -- Visitor Pattern @@ -52,9 +50,12 @@ feature -- Visitor Pattern end end - visit_json_string (a_json_string: JSON_STRING) + visit_json_string (a_json_string: JSON_STRING) -- Visit `a_json_string'. do end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/extras/visitor/json_pretty_string_visitor.e b/contrib/library/text/parser/json/library/utility/visitor/json_pretty_string_visitor.e similarity index 58% rename from contrib/library/text/parser/json/library/extras/visitor/json_pretty_string_visitor.e rename to contrib/library/text/parser/json/library/utility/visitor/json_pretty_string_visitor.e index 98b17c81..e89c215c 100644 --- a/contrib/library/text/parser/json/library/extras/visitor/json_pretty_string_visitor.e +++ b/contrib/library/text/parser/json/library/utility/visitor/json_pretty_string_visitor.e @@ -6,6 +6,7 @@ class JSON_PRETTY_STRING_VISITOR inherit + JSON_VISITOR create @@ -26,21 +27,58 @@ feature -- Initialization output := a_output create indentation.make_empty indentation_step := "%T" - object_count_inlining := a_object_count_inlining array_count_inlining := a_array_count_inlining end feature -- Access - output: STRING_32 - -- JSON representation + output: STRING_GENERAL + -- JSON representation - indentation: like output +feature -- Settings - indentation_step: like indentation + indentation_step: STRING + -- Text used for indentation. + --| by default a tabulation "%T" - line_number: INTEGER + object_count_inlining: INTEGER + -- Inline where object item count is under `object_count_inlining'. + --| ex 3: + --| { "a", "b", "c" } + --| ex 2: + --| { + --| "a", + --| "b", + --| "c" + --| } + + array_count_inlining: INTEGER + -- Inline where array item count is under `object_count_inlining'. + +feature -- Element change + + set_indentation_step (a_step: STRING) + -- Set `indentation_step' to `a_step'. + do + indentation_step := a_step + end + + set_object_count_inlining (a_nb: INTEGER) + -- Set `object_count_inlining' to `a_nb'. + do + object_count_inlining := a_nb + end + + set_array_count_inlining (a_nb: INTEGER) + -- Set `array_count_inlining' to `a_nb'. + do + array_count_inlining := a_nb + end + +feature {NONE} -- Implementation + + indentation: STRING indent do @@ -59,8 +97,7 @@ feature -- Access line_number := line_number + 1 end - object_count_inlining: INTEGER - array_count_inlining: INTEGER + line_number: INTEGER feature -- Visitor Pattern @@ -71,10 +108,14 @@ feature -- Visitor Pattern l_json_array: ARRAYED_LIST [JSON_VALUE] l_line: like line_number l_multiple_lines: BOOLEAN + l_output: like output do + l_output := output l_json_array := a_json_array.array_representation - l_multiple_lines := l_json_array.count >= array_count_inlining or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end - output.append ("[") + l_multiple_lines := l_json_array.count >= array_count_inlining + or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end + l_output.append_code (91) -- '[' : 91 + l_line := line_number indent from @@ -82,27 +123,21 @@ feature -- Visitor Pattern until l_json_array.off loop - if - line_number > l_line or - l_multiple_lines - then + if line_number > l_line or l_multiple_lines then new_line end value := l_json_array.item value.accept (Current) l_json_array.forth if not l_json_array.after then - output.append (", ") + l_output.append (", ") end end exdent - if - line_number > l_line or - l_json_array.count >= array_count_inlining - then + if line_number > l_line or l_json_array.count >= array_count_inlining then new_line end - output.append ("]") + l_output.append_code (93) -- ']' : 93 end visit_json_boolean (a_json_boolean: JSON_BOOLEAN) @@ -129,10 +164,12 @@ feature -- Visitor Pattern l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING] l_line: like line_number l_multiple_lines: BOOLEAN + l_output: like output do + l_output := output l_pairs := a_json_object.map_representation l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end - output.append ("{") + l_output.append_code (123) -- '{' : 123 l_line := line_number indent from @@ -140,36 +177,36 @@ feature -- Visitor Pattern until l_pairs.off loop - if - line_number > l_line or - l_multiple_lines - then + if line_number > l_line or l_multiple_lines then new_line end l_pairs.key_for_iteration.accept (Current) - output.append (": ") + l_output.append (": ") l_pairs.item_for_iteration.accept (Current) l_pairs.forth if not l_pairs.after then - output.append (", ") + l_output.append (", ") end end exdent - if - line_number > l_line or - l_pairs.count >= object_count_inlining - then + if line_number > l_line or l_pairs.count >= object_count_inlining then new_line end - output.append ("}") + l_output.append_code (125) -- '}' : 125 end - visit_json_string (a_json_string: JSON_STRING) + visit_json_string (a_json_string: JSON_STRING) -- Visit `a_json_string'. + local + l_output: like output do - output.append ("%"") - output.append (a_json_string.item) - output.append ("%"") + l_output := output + l_output.append_code (34) -- '%"' : 34 + l_output.append (a_json_string.item) + l_output.append_code (34) -- '%"' : 34 end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/extras/visitor/json_visitor.e b/contrib/library/text/parser/json/library/utility/visitor/json_visitor.e similarity index 76% rename from contrib/library/text/parser/json/library/extras/visitor/json_visitor.e rename to contrib/library/text/parser/json/library/utility/visitor/json_visitor.e index f032b564..c1ae4031 100644 --- a/contrib/library/text/parser/json/library/extras/visitor/json_visitor.e +++ b/contrib/library/text/parser/json/library/utility/visitor/json_visitor.e @@ -1,11 +1,8 @@ note - description: - - "JSON Visitor" - + description: "JSON Visitor" pattern: "Visitor" author: "Javier Velilla" - license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + license: "MIT (see http://www.opensource.org/licenses/mit-license.php)" date: "2008/08/24" revision: "Revision 0.1" @@ -49,11 +46,14 @@ feature -- Visitor Pattern deferred end - visit_json_string (a_json_string: JSON_STRING) + visit_json_string (a_json_string: JSON_STRING) -- Visit `a_json_string'. require a_json_string_not_void: a_json_string /= Void deferred end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/library/extras/visitor/print_json_visitor.e b/contrib/library/text/parser/json/library/utility/visitor/print_json_visitor.e similarity index 82% rename from contrib/library/text/parser/json/library/extras/visitor/print_json_visitor.e rename to contrib/library/text/parser/json/library/utility/visitor/print_json_visitor.e index 6072769b..4265413e 100644 --- a/contrib/library/text/parser/json/library/extras/visitor/print_json_visitor.e +++ b/contrib/library/text/parser/json/library/utility/visitor/print_json_visitor.e @@ -8,9 +8,11 @@ class PRINT_JSON_VISITOR inherit + JSON_VISITOR -create make +create + make feature -- Initialization @@ -23,7 +25,7 @@ feature -- Initialization feature -- Access to_json: STRING - -- JSON representation + -- JSON representation feature -- Visitor Pattern @@ -33,7 +35,7 @@ feature -- Visitor Pattern value: JSON_VALUE l_json_array: ARRAYED_LIST [JSON_VALUE] do - l_json_array:=a_json_array.array_representation + l_json_array := a_json_array.array_representation to_json.append ("[") from l_json_array.start @@ -44,7 +46,7 @@ feature -- Visitor Pattern value.accept (Current) l_json_array.forth if not l_json_array.after then - to_json.append(",") + to_json.append (",") end end to_json.append ("]") @@ -71,7 +73,7 @@ feature -- Visitor Pattern visit_json_object (a_json_object: JSON_OBJECT) -- Visit `a_json_object'. local - l_pairs: HASH_TABLE[JSON_VALUE,JSON_STRING] + l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING] do l_pairs := a_json_object.map_representation to_json.append ("{") @@ -91,7 +93,7 @@ feature -- Visitor Pattern to_json.append ("}") end - visit_json_string (a_json_string: JSON_STRING) + visit_json_string (a_json_string: JSON_STRING) -- Visit `a_json_string'. do to_json.append ("%"") @@ -99,4 +101,7 @@ feature -- Visitor Pattern to_json.append ("%"") end +note + copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json." + license: "https://github.com/eiffelhub/json/blob/master/License.txt" end diff --git a/contrib/library/text/parser/json/package.iron b/contrib/library/text/parser/json/package.iron new file mode 100644 index 00000000..90cfb9c9 --- /dev/null +++ b/contrib/library/text/parser/json/package.iron @@ -0,0 +1,16 @@ +package json + +project + json_safe = "library/json-safe.ecf" + json = "library/json.ecf" + json_gobo_extension = "library/json_gobo_extension.ecf" + +note + title: Eiffel JSON + description: Eiffel JSON parser and visitors + tags: json,parser,text + license: MIT + copyright: Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others, + link[github]: "project" https://github.com/eiffelhub/json + +end diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/application.e b/contrib/library/text/parser/json/test/autotest/test_suite/application.e index 77d42fe7..01160cbe 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/application.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/application.e @@ -1,12 +1,13 @@ note - description : "test_suite application root class" - date : "$Date$" - revision : "$Revision$" + description: "test_suite application root class" + date: "$Date$" + revision: "$Revision$" class APPLICATION inherit + ARGUMENTS create @@ -17,7 +18,7 @@ feature {NONE} -- Initialization make -- Run application. do - --| Add your code here + --| Add your code here print ("Hello Eiffel World!%N") end diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/author.e b/contrib/library/text/parser/json/test/autotest/test_suite/author.e index 9df55bf7..35118404 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/author.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/author.e @@ -1,24 +1,32 @@ -class AUTHOR +class + AUTHOR create - make + make feature {NONE} -- Initialization - make (a_name: STRING_32) - do - set_name (a_name) - end + make (a_name: STRING_32) + -- Create an author with `a_name' as `name'. + do + set_name (a_name) + ensure + name_set: name = a_name + end feature -- Access - name: STRING_32 + name: STRING_32 + -- Author name -feature -- Status setting +feature -- Change - set_name (a_name: STRING_32) - do - name := a_name - end + set_name (a_name: STRING_32) + -- Set `name' with `a_name'. + do + name := a_name + ensure + name_set: name = a_name + end end -- class AUTHOR diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/book.e b/contrib/library/text/parser/json/test/autotest/test_suite/book.e index 414036db..96670f16 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/book.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/book.e @@ -1,40 +1,59 @@ -class BOOK +class + BOOK create - make + make feature {NONE} -- Initialization - make (a_title: STRING_32; an_author: AUTHOR; an_isbn: STRING_32) - do - set_title (a_title) - set_author (an_author) - set_isbn (an_isbn) - end + make (a_title: STRING_32; a_author: AUTHOR; a_isbn: STRING_32) + -- Create a book with `a_title' as `title', + -- `a_author' as `author', and `a_isbn' as `isbn'. + do + set_title (a_title) + set_author (a_author) + set_isbn (a_isbn) + ensure + title_set: title = a_title + author_set: author = a_author + isbn_set: isbn = a_isbn + end feature -- Access - title: STRING_32 + title: STRING_32 + -- Main title. - isbn: STRING_32 + isbn: STRING_32 + -- ISBN. - author: AUTHOR + author: AUTHOR + -- Author. -feature -- Status setting +feature -- Change - set_title (a_title: STRING_32) - do - title := a_title - end + set_title (a_title: STRING_32) + -- Set `title' with `a_title'. + do + title := a_title + ensure + title_set: title = a_title + end - set_author (an_author: AUTHOR) - do - author := an_author - end + set_author (a_author: AUTHOR) + -- Set `author' with `a_author'. + do + author := a_author + ensure + author_set: author = a_author + end - set_isbn (an_isbn: STRING_32) - do - isbn := an_isbn - end + set_isbn (a_isbn: STRING_32) + -- Set `isbn' with `a_isbn'. + do + isbn := a_isbn + ensure + isbn_set: isbn = a_isbn + end end -- class BOOK diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/book_collection.e b/contrib/library/text/parser/json/test/autotest/test_suite/book_collection.e index 5ee0b0dd..8959455a 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/book_collection.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/book_collection.e @@ -1,80 +1,82 @@ -class BOOK_COLLECTION +class + BOOK_COLLECTION create - make + make feature {NONE} -- Initialization - make (a_name: STRING_32) - do - set_name (a_name) - create book_index.make (10) - end + make (a_name: STRING_32) + -- Create a book collection with `a_name' as `name'. + do + set_name (a_name) + create book_index.make (10) + ensure + name_set: name = a_name + end feature -- Access - name: STRING_32 + name: STRING_32 + -- Name. - books: LIST [BOOK] - do - from - create {LINKED_LIST [BOOK]} Result.make - book_index.start - until - book_index.after - loop - Result.append (book_index.item_for_iteration) - book_index.forth - end - end + books: LIST [BOOK] + -- collection of book. + do + create {LINKED_LIST [BOOK]} Result.make + across + book_index as it + loop + Result.append (it.item) + end + end - books_by_author (an_author: STRING_32): detachable LIST [BOOK] - do - if book_index.has (an_author) then - Result := book_index @ an_author - else - create {LINKED_LIST [BOOK]} Result.make - end - end + books_by_author (a_author: STRING_32): LIST [BOOK] + -- Books wrote by `a_author' in this collection. + do + if attached book_index [a_author] as l_result then + Result := l_result + else + create {LINKED_LIST [BOOK]} Result.make + end + end -feature -- Status setting +feature -- Change - set_name (a_name: STRING_32) - do - name := a_name - end + set_name (a_name: STRING_32) + -- Set `name' with `a_name'. + do + name := a_name + ensure + name_set: name = a_name + end - add_book (a_book: BOOK) - local - l: detachable LIST [BOOK] - do - if book_index.has (a_book.author.name) then - l := book_index.at ( a_book.author.name ) - else - create {LINKED_LIST [BOOK]} l.make - book_index.put (l, a_book.author.name) - end - if attached l as la then - la.force (a_book) - end + add_book (a_book: BOOK) + -- Extend collection with `a_book'. + local + l: detachable LIST [BOOK] + do + l := book_index.at (a_book.author.name) + if l = Void then + create {LINKED_LIST [BOOK]} l.make + book_index.put (l, a_book.author.name) + end + l.force (a_book) + end - end - - add_books (book_list: like books) - - do - from - book_list.start - until - book_list.after - loop - add_book (book_list.item) - book_list.forth - end - end + add_books (book_list: like books) + -- Append collection with `book_list'. + do + across + book_list as it + loop + add_book (it.item) + end + end feature {NONE} -- Implementation - book_index: HASH_TABLE [LIST [BOOK], STRING_32] + book_index: HASH_TABLE [LIST [BOOK], STRING_32] + -- Association of author name and its books. end -- class BOOK_COLLECTION diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/json_author_converter.e b/contrib/library/text/parser/json/test/autotest/test_suite/json_author_converter.e index c8f9e6d0..c097b8b3 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/json_author_converter.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/json_author_converter.e @@ -1,53 +1,54 @@ note - description: "A JSON converter for AUTHOR" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision$" + description: "A JSON converter for AUTHOR" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision$" -class JSON_AUTHOR_CONVERTER +class + JSON_AUTHOR_CONVERTER inherit - JSON_CONVERTER + + JSON_CONVERTER create - make + make feature {NONE} -- Initialization - make - local - ucs: STRING_32 - do - create ucs.make_from_string ("") - create object.make (ucs) - end + make + local + ucs: STRING_32 + do + create ucs.make_from_string ("") + create object.make (ucs) + end feature -- Access - object: AUTHOR + object: AUTHOR feature -- Conversion - from_json (j: like to_json): detachable like object - local - ucs: detachable STRING_32 - do - ucs ?= json.object (j.item (name_key), Void) - check ucs /= Void end - create Result.make (ucs) - end + from_json (j: like to_json): detachable like object + do + if attached {STRING_32} json.object (j.item (name_key), Void) as l_name then + create Result.make (l_name) + end + end - to_json (o: like object): JSON_OBJECT - do - create Result.make - Result.put (json.value (o.name), name_key) - end + to_json (o: like object): JSON_OBJECT + do + create Result.make + Result.put (json.value (o.name), name_key) + end -feature {NONE} -- Implementation +feature {NONE} -- Implementation - name_key: JSON_STRING - once - create Result.make_json ("name") - end + name_key: JSON_STRING + -- Author's name label. + once + create Result.make_from_string ("name") + end end -- class JSON_AUTHOR_CONVERTER diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/json_book_collection_converter.e b/contrib/library/text/parser/json/test/autotest/test_suite/json_book_collection_converter.e index 1c569ce3..0a36de26 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/json_book_collection_converter.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/json_book_collection_converter.e @@ -1,78 +1,82 @@ note - description: "A JSON converter for BOOK_COLLECTION" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision$" + description: "A JSON converter for BOOK_COLLECTION" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision$" -class JSON_BOOK_COLLECTION_CONVERTER +class + JSON_BOOK_COLLECTION_CONVERTER inherit - JSON_CONVERTER + + JSON_CONVERTER create - make + make feature {NONE} -- Initialization - make - local - ucs: STRING_32 - do - create ucs.make_from_string ("") - create object.make (ucs) - end + make + local + ucs: STRING_32 + do + create ucs.make_from_string ("") + create object.make (ucs) + end feature -- Access - object: BOOK_COLLECTION + object: BOOK_COLLECTION feature -- Conversion - from_json (j: like to_json): detachable like object - local - ucs: detachable STRING_32 - ll: LINKED_LIST [BOOK] - b: detachable BOOK - ja: detachable JSON_ARRAY - i: INTEGER - do - ucs ?= json.object (j.item (name_key), Void) - check ucs /= Void end - create Result.make (ucs) - ja ?= j.item (books_key) - check ja /= Void end - from - i := 1 - create ll.make - until - i > ja.count - loop - b ?= json.object (ja [i], "BOOK") - check b /= Void end - ll.force (b) - i := i + 1 - end - check ll /= Void end - Result.add_books (ll) - end + from_json (j: like to_json): detachable like object + local + l_books: LINKED_LIST [BOOK] + do + if + attached {STRING_32} json.object (j.item (name_key), Void) as l_name and + attached {JSON_ARRAY} j.item (books_key) as l_json_array + then + create Result.make (l_name) + create l_books.make + across + l_json_array as it + until + Result = Void + loop + if attached {BOOK} json.object (it.item, "BOOK") as l_book then + l_books.extend (l_book) + else + Result := Void + -- Failed + end + end + if Result /= Void then + Result.add_books (l_books) + end + end + end - to_json (o: like object): JSON_OBJECT - do - create Result.make - Result.put (json.value (o.name), name_key) - Result.put (json.value (o.books), books_key) - end + to_json (o: like object): JSON_OBJECT + do + create Result.make_with_capacity (2) + Result.put (json.value (o.name), name_key) + Result.put (json.value (o.books), books_key) + end -feature {NONE} -- Implementation +feature {NONE} -- Implementation - name_key: JSON_STRING - once - create Result.make_json ("name") - end + name_key: JSON_STRING + -- Collection's name label. + once + create Result.make_from_string ("name") + end - books_key: JSON_STRING - once - create Result.make_json ("books") - end + books_key: JSON_STRING + -- Book list label. + once + create Result.make_from_string ("books") + end end -- class JSON_BOOK_COLLECTION_CONVERTER diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/json_book_converter.e b/contrib/library/text/parser/json/test/autotest/test_suite/json_book_converter.e index de31f79e..dec02971 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/json_book_converter.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/json_book_converter.e @@ -1,72 +1,74 @@ note - description: "A JSON converter for BOOK" - author: "Paul Cohen" - date: "$Date$" - revision: "$Revision$" + description: "A JSON converter for BOOK" + author: "Paul Cohen" + date: "$Date$" + revision: "$Revision$" -class JSON_BOOK_CONVERTER +class + JSON_BOOK_CONVERTER inherit - JSON_CONVERTER + + JSON_CONVERTER create - make + make feature {NONE} -- Initialization - make - local - ucs: STRING_32 - a: AUTHOR - do - create ucs.make_from_string ("") - create a.make (ucs) - create object.make (ucs, a, ucs) - end + make + local + ucs: STRING_32 + a: AUTHOR + do + create ucs.make_from_string ("") + create a.make (ucs) + create object.make (ucs, a, ucs) + end feature -- Access - object: BOOK + object: BOOK feature -- Conversion - from_json (j: like to_json): detachable like object - local - ucs1, ucs2: detachable STRING_32 - a: detachable AUTHOR - do - ucs1 ?= json.object (j.item (title_key), Void) - check ucs1 /= Void end - ucs2 ?= json.object (j.item (isbn_key), Void) - check ucs2 /= Void end - a ?= json.object (j.item (author_key), "AUTHOR") - check a /= Void end - create Result.make (ucs1, a, ucs2) - end + from_json (j: like to_json): detachable like object + do + if + attached {STRING_32} json.object (j.item (title_key), Void) as l_title and + attached {STRING_32} json.object (j.item (isbn_key), Void) as l_isbn and + attached {AUTHOR} json.object (j.item (author_key), "AUTHOR") as l_author + then + create Result.make (l_title, l_author, l_isbn) + end + end - to_json (o: like object): JSON_OBJECT - do - create Result.make - Result.put (json.value (o.title), title_key) - Result.put (json.value (o.isbn), isbn_key) - Result.put (json.value (o.author), author_key) - end + to_json (o: like object): JSON_OBJECT + do + create Result.make_with_capacity (3) + Result.put (json.value (o.title), title_key) + Result.put (json.value (o.isbn), isbn_key) + Result.put (json.value (o.author), author_key) + end -feature {NONE} -- Implementation +feature {NONE} -- Implementation - title_key: JSON_STRING - once - create Result.make_json ("title") - end + title_key: JSON_STRING + -- Book's title label. + once + create Result.make_from_string ("title") + end - isbn_key: JSON_STRING - once - create Result.make_json ("isbn") - end + isbn_key: JSON_STRING + -- Book ISBN label. + once + create Result.make_from_string ("isbn") + end - author_key: JSON_STRING - once - create Result.make_json ("author") - end + author_key: JSON_STRING + -- Author label. + once + create Result.make_from_string ("author") + end end -- class JSON_BOOK_CONVERTER diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/test_ds.e b/contrib/library/text/parser/json/test/autotest/test_suite/test_ds.e index 1cccd4b1..34d8f0aa 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/test_ds.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/test_ds.e @@ -1,74 +1,72 @@ -class TEST_DS +note + description: "Linked list and hash table converters test." + date: "$Date$" + revision: "$Revision$" + +class + TEST_DS inherit - SHARED_EJSON - rename default_create as shared_default_create end - EQA_TEST_SET - select default_create end + SHARED_EJSON + undefine + default_create + end + + EQA_TEST_SET feature -- Test - test_linked_list_converter - local - jc: JSON_LINKED_LIST_CONVERTER - l: LINKED_LIST [STRING] - l2: detachable LINKED_LIST [detachable ANY] - s: STRING - jv: detachable JSON_VALUE - do - create jc.make - json.add_converter (jc) - create l.make - s := "foo" - l.force (s) - s := "bar" - l.force (s) - jv := json.value (l) - assert ("jv /= Void", jv /= Void) - if attached jv as l_jv then - s := jv.representation - l2 ?= json.object (jv, "LINKED_LIST") - assert ("l2 /= Void", l2 /= Void) - end - end + test_linked_list_converter + -- Convert a linked list to a json value and + -- convert this one to a linked list. + local + l: LINKED_LIST [STRING] + s: STRING + do + create l.make + l.force ("foo") + l.force ("bar") + if attached json.value (l) as l_value then + s := l_value.representation + assert ("JSON array converted to LINKED_LIST", attached {LINKED_LIST [detachable ANY]} json.object (l_value, "LINKED_LIST")) + else + assert ("LINKED_LIST converted to a JSON value", False) + end + end - test_hash_table_converter - local - tc: JSON_HASH_TABLE_CONVERTER - t: HASH_TABLE [STRING, STRING] - t2: detachable HASH_TABLE [ANY, HASHABLE] - s: STRING - ucs_key, ucs_value: detachable STRING_32 - jv: detachable JSON_VALUE - do - create tc.make - json.add_converter (tc) - create t.make (2) - t.put ("foo", "1") - t.put ("bar", "2") - jv := json.value (t) - assert ("jv /= Void", jv /= Void) - if attached jv as l_jv then - s := l_jv.representation - t2 ?= json.object (l_jv, "HASH_TABLE") - assert ("t2 /= Void", t2 /= Void) - end - create ucs_key.make_from_string ("1") - if attached t2 as l_t2 then - ucs_value ?= t2 @ ucs_key - assert ("ucs_value /= Void", ucs_value /= Void) - if attached ucs_value as l_ucs_value then - assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.string.is_equal ("foo")) - end - create ucs_key.make_from_string ("2") - ucs_value ?= t2 @ ucs_key - assert ("ucs_value /= Void", ucs_value /= Void) - if attached ucs_value as l_ucs_value then - assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.string.is_equal ("bar")) - end - - end - end + test_hash_table_converter + -- Convert a hash table to a json value and + -- convert this one to a hash table. + local + t: HASH_TABLE [STRING, STRING] + s: STRING + l_ucs_key: detachable STRING_32 + do + create t.make (2) + t.put ("foo", "1") + t.put ("bar", "2") + if attached json.value (t) as l_value then + s := l_value.representation + if attached {HASH_TABLE [ANY, HASHABLE]} json.object (l_value, "HASH_TABLE") as t2 then + create l_ucs_key.make_from_string ("1") + if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then + assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.same_string_general ("foo")) + else + assert ("ucs_value /= Void", False) + end + create l_ucs_key.make_from_string ("2") + if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then + assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.same_string_general ("bar")) + else + assert ("ucs_value /= Void", False) + end + else + assert ("JSON object converted to HASH_TABLE", False); + end + else + assert ("HASH_TABLE converted to a JSON value", False) + end + end end -- class TEST_DS diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_core.e b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_core.e index 9c2febac..93eeb4fc 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_core.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_core.e @@ -1,833 +1,888 @@ -class TEST_JSON_CORE +class + TEST_JSON_CORE inherit - SHARED_EJSON - rename default_create as shared_default_create end + + SHARED_EJSON + undefine + default_create + end + EQA_TEST_SET - select default_create end + + JSON_PARSER_ACCESS + undefine + default_create + end feature -- Test - test_json_number_and_integer - local - i: INTEGER - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - i := 42 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_integer (i) - assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (i) as l_jn then - assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) + test_json_number_and_integer + local + i: INTEGER + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + i := 42 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_integer (i) + assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (i) as l_jn then + assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) else assert ("json.value (i) is a JSON_NUMBER", False) - end + end - -- JSON representation-> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_8 since the value is 42 - jrep := "42" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_8} json.object (jn, Void) as l_i8 then + -- JSON representation-> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_8 since the value is 42 + jrep := "42" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_8} json.object (jn, Void) as l_i8 then assert ("l_i8 = 42", l_i8 = 42) else assert ("json.object (jn, Void) is a INTEGER_8", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_integer_8 - local - i8: INTEGER_8 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - i8 := 42 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_integer (i8) - assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (i8) as l_jn then - assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) + test_json_number_and_integer_8 + local + i8: INTEGER_8 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + i8 := 42 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_integer (i8) + assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (i8) as l_jn then + assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42")) else assert ("json.value (i8) is a JSON_NUMBER", False) - end + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_8 since the value is 42 - jrep := "42" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_8} json.object (jn, Void) as l_i8 then + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_8 since the value is 42 + jrep := "42" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_8} json.object (jn, Void) as l_i8 then assert ("l_i8 = 42", l_i8 = 42) else assert ("json.object (jn, Void) is a INTEGER_8", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_integer_16 - local - i16: INTEGER_16 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - i16 := 300 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_integer (i16) - assert ("jn.representation.same_string (%"300%")", jn.representation.same_string ("300")) - -- Eiffel value -> JSON with factory - if attached {JSON_NUMBER} json.value (i16) as l_jn then - assert ("l_jn.representation.same_string (%"300%")", l_jn.representation.same_string ("300")) + test_json_number_and_integer_16 + local + i16: INTEGER_16 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + i16 := 300 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_integer (i16) + assert ("jn.representation.same_string (%"300%")", jn.representation.same_string ("300")) + -- Eiffel value -> JSON with factory + if attached {JSON_NUMBER} json.value (i16) as l_jn then + assert ("l_jn.representation.same_string (%"300%")", l_jn.representation.same_string ("300")) else assert ("json.value (i16) is a JSON_NUMBER", False) - end + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_16 since the value is 300 - jrep := "300" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_16} json.object (jn, Void) as l_i16 then + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_16 since the value is 300 + jrep := "300" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_16} json.object (jn, Void) as l_i16 then assert ("l_i16 = 300", l_i16 = 300) else assert ("json.object (jn, Void) is a INTEGER_16", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_integer_32 - local - i32: INTEGER_32 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - i32 := 100000 - -- Eiffel value -> JSON representation -> JSON value - create jn.make_integer (i32) - assert ("jn.representation.same_string (%"100000%")", jn.representation.same_string ("100000")) - -- Eiffel value -> JSON representation -> JSON value with factory - if attached {JSON_NUMBER} json.value (i32) as l_jn then - assert ("l_jn.representation.same_string (%"100000%")", l_jn.representation.same_string ("100000")) + test_json_number_and_integer_32 + local + i32: INTEGER_32 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + i32 := 100000 + -- Eiffel value -> JSON representation -> JSON value + create jn.make_integer (i32) + assert ("jn.representation.same_string (%"100000%")", jn.representation.same_string ("100000")) + -- Eiffel value -> JSON representation -> JSON value with factory + if attached {JSON_NUMBER} json.value (i32) as l_jn then + assert ("l_jn.representation.same_string (%"100000%")", l_jn.representation.same_string ("100000")) else assert ("json.value (i32) is a JSON_NUMBER", False) - end + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_32 since the value is 100000 - jrep := "100000" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_32} json.object (jn, Void) as l_i32 then + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_32 since the value is 100000 + jrep := "100000" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_32} json.object (jn, Void) as l_i32 then assert ("l_i32 = 100000", l_i32 = 100000) else assert ("json.object (jn, Void) is a INTEGER_32", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_integer_64 - local - i64: INTEGER_64 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - i64 := 42949672960 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_integer (i64) - assert ("jn.representation.same_string (%"42949672960%")", jn.representation.same_string ("42949672960")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (i64) as l_jn then - assert ("l_jn.representation.same_string (%"42949672960%")", l_jn.representation.same_string ("42949672960")) + test_json_number_and_integer_64 + local + i64: INTEGER_64 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + i64 := 42949672960 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_integer (i64) + assert ("jn.representation.same_string (%"42949672960%")", jn.representation.same_string ("42949672960")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (i64) as l_jn then + assert ("l_jn.representation.same_string (%"42949672960%")", l_jn.representation.same_string ("42949672960")) else assert ("json.value (i64) is a JSON_NUMBER", False) - end + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_32 since the value is 42949672960 - jrep := "42949672960" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_64} json.object (jn, Void) as l_i64 then + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_32 since the value is 42949672960 + jrep := "42949672960" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_64} json.object (jn, Void) as l_i64 then assert ("l_i64 = 42949672960", l_i64 = 42949672960) else assert ("json.object (jn, Void) is a INTEGER_64", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_natural_8 - local - n8: NATURAL_8 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - n8 := 200 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_natural (n8) - assert ("jn.representation.same_string (%"200%")", jn.representation.same_string ("200")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (n8) as l_jn then - assert ("l_jn.representation.same_string (%"200%")", l_jn.representation.same_string ("200")) - else - assert ("json.value (n8) is a JSON_NUMBER}", False) - end - - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_16 since the value is 200 - jrep := "200" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_16} json.object (jn, Void) as i16 then - assert ("i16 = 200", i16 = 200) - else - assert ("json.object (jn, Void) is an INTEGER_16", False) - end + test_json_number_and_natural_8 + local + n8: NATURAL_8 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + n8 := 200 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_natural (n8) + assert ("jn.representation.same_string (%"200%")", jn.representation.same_string ("200")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (n8) as l_jn then + assert ("l_jn.representation.same_string (%"200%")", l_jn.representation.same_string ("200")) else - assert ("parser.parse is a JSON_NUMBER", False) - end - end + assert ("json.value (n8) is a JSON_NUMBER}", False) + end - test_json_number_and_natural_16 - local - n16: NATURAL_16 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - n16 := 32768 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_natural (n16) - assert ("jn.representation.same_string (%"32768%")", jn.representation.same_string ("32768")) - -- Eiffel value -> JSON value -> JSON representation with factory + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_16 since the value is 200 + jrep := "200" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_16} json.object (jn, Void) as i16 then + assert ("i16 = 200", i16 = 200) + else + assert ("json.object (jn, Void) is an INTEGER_16", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end + + test_json_number_and_natural_16 + local + n16: NATURAL_16 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + n16 := 32768 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_natural (n16) + assert ("jn.representation.same_string (%"32768%")", jn.representation.same_string ("32768")) + -- Eiffel value -> JSON value -> JSON representation with factory if attached {JSON_NUMBER} json.value (n16) as l_jn then - assert ("l_jn.representation.same_string (%"32768%")", l_jn.representation.same_string ("32768")) - else - assert ("json.value (n16) is a JSON_NUMBER", False) - end + assert ("l_jn.representation.same_string (%"32768%")", l_jn.representation.same_string ("32768")) + else + assert ("json.value (n16) is a JSON_NUMBER", False) + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_32 since the value is 32768 - jrep := "32768" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_32} json.object (jn, Void) as i32 then + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_32 since the value is 32768 + jrep := "32768" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_32} json.object (jn, Void) as i32 then assert ("i32 = 32768", i32 = 32768) else assert ("json.object (jn, Void) is a INTEGER_32", False) end else - assert ("parser.parse is a JSON_NUMBER", False) + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) end - end + end - test_json_number_and_natural_32 - local - n32: NATURAL_32 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - n32 := 2147483648 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_natural (n32) - assert ("jn.representation.same_string (%"2147483648%")", jn.representation.same_string ("2147483648")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached json.value (n32) as l_jn then - assert ("l_jn.representation.same_string (%"2147483648%")", l_jn.representation.same_string ("2147483648")) - else - assert ("json.value (n32) is a JSON_NUMBER", False) - end + test_json_number_and_natural_32 + local + n32: NATURAL_32 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + n32 := 2147483648 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_natural (n32) + assert ("jn.representation.same_string (%"2147483648%")", jn.representation.same_string ("2147483648")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached json.value (n32) as l_jn then + assert ("l_jn.representation.same_string (%"2147483648%")", l_jn.representation.same_string ("2147483648")) + else + assert ("json.value (n32) is a JSON_NUMBER", False) + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_64 since the value is 2147483648 - jrep := "2147483648" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {INTEGER_64} json.object (jn, Void) as i64 then - assert ("i64 = 2147483648", i64 = 2147483648) - else - assert ("json.object (jn, Void) is a INTEGER_64", False) - end - else - assert ("parser.parse is a JSON_NUMBER", False) - end - end + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_64 since the value is 2147483648 + jrep := "2147483648" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {INTEGER_64} json.object (jn, Void) as i64 then + assert ("i64 = 2147483648", i64 = 2147483648) + else + assert ("json.object (jn, Void) is a INTEGER_64", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end - test_json_number_and_large_integers - local - jrep: STRING - n64: NATURAL_64 - jn: JSON_NUMBER - parser: JSON_PARSER - do - n64 := 9223372036854775808 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_natural (n64) - assert ("jn.representation.same_string (%"9223372036854775808%")", jn.representation.same_string ("9223372036854775808")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (n64) as l_jn then - assert ("l_jn.representation.same_string (%"9223372036854775808%")", l_jn.representation.same_string ("9223372036854775808")) - else - assert ("json.value (n64) is a JSON_NUMBER", False) - end + test_json_number_and_large_integers + local + jrep: STRING + n64: NATURAL_64 + jn: JSON_NUMBER + parser: JSON_PARSER + do + n64 := 9223372036854775808 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_natural (n64) + assert ("jn.representation.same_string (%"9223372036854775808%")", jn.representation.same_string ("9223372036854775808")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (n64) as l_jn then + assert ("l_jn.representation.same_string (%"9223372036854775808%")", l_jn.representation.same_string ("9223372036854775808")) + else + assert ("json.value (n64) is a JSON_NUMBER", False) + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- we know it is INTEGER_32 since the value is 42949672960 - jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64 - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {NATURAL_64} json.object (jn, Void) as l_n64 then - assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808) - else - assert ("json.object (jn, Void) is a NATURAL_64", False) - end - else - assert ("parser.parse is a JSON_NUMBER", False) - end - end + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- we know it is INTEGER_32 since the value is 42949672960 + jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64 + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {NATURAL_64} json.object (jn, Void) as l_n64 then + assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808) + else + assert ("json.object (jn, Void) is a NATURAL_64", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end - test_json_number_and_eiffel_real - local - r: REAL - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - r := 3.14 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_real (r) - assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (r) as l_jn then - assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748")) - else - assert ("json.value (r) is a JSON_NUMBER", False) - end + test_json_number_and_eiffel_real + local + r: REAL + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + r := 3.14 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_real (r) + assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (r) as l_jn then + assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748")) + else + assert ("json.value (r) is a JSON_NUMBER", False) + end - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will always return a REAL_64 if the value - -- of the JSON number is a floating point number - jrep := "3.14" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {REAL_64} json.object (jn, Void) as r64 then - assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141) - else - assert ("json.object (jn, Void) is a REAL_64", False) - end - else - assert ("parser.parse is a JSON_NUMBER", False) - end - end + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will always return a REAL_64 if the value + -- of the JSON number is a floating point number + jrep := "3.14" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {REAL_64} json.object (jn, Void) as r64 then + assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141) + else + assert ("json.object (jn, Void) is a REAL_64", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end - test_json_number_and_eiffel_real_32 - local - r32: REAL_32 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - r32 := 3.14 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_real (r32) - assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (r32) as l_jn then - assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748")) + test_json_number_and_eiffel_real_32 + local + r32: REAL_32 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + r32 := 3.14 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_real (r32) + assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (r32) as l_jn then + assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748")) else assert ("json.value (r32) is a JSON_NUMBER", False) - end + end - -- JSON representation -> JSON value -> Eiffel value - jrep := "3.1400001049041748" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {REAL_64} json.object (l_jn, Void) as r64 then - assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748) - else - assert ("json.object (l_jn, Void) is a REAL_64", False) - end + -- JSON representation -> JSON value -> Eiffel value + jrep := "3.1400001049041748" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {REAL_64} json.object (l_jn, Void) as r64 then + assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748) + else + assert ("json.object (l_jn, Void) is a REAL_64", False) + end else - assert ("parser.parse is a JSON_NUMBER", False) - end - end + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end - test_json_number_and_eiffel_real_64 - local - r64: REAL_64 - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - r64 := 3.1415926535897931 - -- Eiffel value -> JSON value -> JSON representation - create jn.make_real (r64) - assert ("jn.representation.same_string (%"3.1415926535897931%")", jn.representation.same_string ("3.1415926535897931")) + test_json_number_and_eiffel_real_64 + local + r64: REAL_64 + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + r64 := 3.1415926535897931 + -- Eiffel value -> JSON value -> JSON representation + create jn.make_real (r64) + assert ("jn.representation.same_string (%"3.1415926535897931%")", jn.representation.same_string ("3.1415926535897931")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_NUMBER} json.value (r64) as l_jn then + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NUMBER} json.value (r64) as l_jn then assert ("l_jn.representation.same_string (%"3.1415926535897931%")", l_jn.representation.same_string ("3.1415926535897931")) - else - assert ("json.value (r64) is a JSON_NUMBER", False) - end - - -- JSON representation -> JSON value -> Eiffel value - jrep := "3.1415926535897931" - create parser.make_parser (jrep) - if attached {JSON_NUMBER} parser.parse as l_jn then - if attached {REAL_64} json.object (jn, Void) as l_r64 then - assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931) - else - assert ("json.object (jn, Void) is a REAL_64", False) - end - else - assert ("parser.parse is a JSON_NUMBER", False) - end - end - - test_json_boolean - local - parser: JSON_PARSER - jb: JSON_BOOLEAN - b: BOOLEAN - do - -- Eiffel value -> JSON value -> JSON representation - b := True - create jb.make_boolean (b) - assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_BOOLEAN} json.value (b) as l_jb then - assert ("l_jb.representation.same_string (%"true%")", l_jb.representation.same_string ("true")) - else - assert ("l_jb /= Void", False) - end - - -- JSON representation -> JSON value -> Eiffel value - create parser.make_parser ("true") - if attached {JSON_BOOLEAN} parser.parse as l_jb then - if attached {BOOLEAN} json.object (l_jb, Void) as l_b then - assert ("l_b = True", l_b = True) - else - assert ("json.object (l_jb, Void) is BOOLEAN", False) - end else - assert ("parser.parse is a JSON_BOOLEAN", False) - end + assert ("json.value (r64) is a JSON_NUMBER", False) + end - -- Eiffel value -> JSON value -> JSON representation - b := False - create jb.make_boolean (b) - assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false")) - -- Eiffel value -> JSON value -> JSON representation with factory - if attached {JSON_BOOLEAN} json.value (b) as l_jb then - assert ("l_jb.representation.same_string (%"false%")", l_jb.representation.same_string ("false")) - else - assert ("json.value (b) is a JSON_BOOLEAN", False) - end + -- JSON representation -> JSON value -> Eiffel value + jrep := "3.1415926535897931" + create parser.make_with_string (jrep) + if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then + if attached {REAL_64} json.object (jn, Void) as l_r64 then + assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931) + else + assert ("json.object (jn, Void) is a REAL_64", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_NUMBER", False) + end + end - -- JSON representation -> JSON value -> Eiffel value - create parser.make_parser ("false") - if attached {JSON_BOOLEAN} parser.parse as l_jb then - if attached {BOOLEAN} json.object (l_jb, Void) as l_b then - assert ("l_b = False", l_b = False) + test_json_boolean + local + parser: JSON_PARSER + jb: JSON_BOOLEAN + b: BOOLEAN + do + -- Eiffel value -> JSON value -> JSON representation + b := True + create jb.make (b) + assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_BOOLEAN} json.value (b) as l_jb then + assert ("l_jb.representation.same_string (%"true%")", l_jb.representation.same_string ("true")) + else + assert ("l_jb /= Void", False) + end + + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string ("true") + if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then + if attached {BOOLEAN} json.object (l_jb, Void) as l_b then + assert ("l_b = True", l_b = True) + else + assert ("json.object (l_jb, Void) is BOOLEAN", False) + end + else + assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False) + end + + -- Eiffel value -> JSON value -> JSON representation + b := False + create jb.make (b) + assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_BOOLEAN} json.value (b) as l_jb then + assert ("l_jb.representation.same_string (%"false%")", l_jb.representation.same_string ("false")) + else + assert ("json.value (b) is a JSON_BOOLEAN", False) + end + + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string ("false") + if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then + if attached {BOOLEAN} json.object (l_jb, Void) as l_b then + assert ("l_b = False", l_b = False) else assert ("json.object (l_jb, Void) is a BOOLEAN", False) end - else - assert ("parser.parse is a JSON_BOOLEAN", False) - end - end + else + assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False) + end + end - test_json_null - local - a: detachable ANY - dummy_object: STRING - jn: detachable JSON_NULL - jrep: STRING - parser: JSON_PARSER - do - -- Eiffel value -> JSON value -> JSON representation - create jn - assert ("jn /= Void", jn /= Void) - assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null")) - -- Eiffel value -> JSON value -> JSON representation with factory - jn ?= json.value (Void) - assert ("jn /= Void", jn /= Void) - if attached jn as l_jn then - assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null")) - end + test_json_null + local + jrep: STRING + jn: JSON_NULL + parser: JSON_PARSER + do + -- Eiffel value -> JSON value -> JSON representation + create jn + jrep := "null" + assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal (jrep)) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_NULL} json.value (Void) as l_json_null then + assert ("jn.representation.is_equal (%"null%")", l_json_null.representation.is_equal ("null")) + else + assert ("json.value (Void) /= Void", False) + end - -- JSON representation -> JSON value -> Eiffel value - jrep := "null" - create parser.make_parser (jrep) - jn := Void - jn ?= parser.parse - assert ("jn /= Void", jn /= Void) - create dummy_object.make_empty - a := dummy_object - a ?= json.object (jn, Void) - assert ("a = Void", a = Void) - end + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string (jrep) + if attached parser.next_parsed_json_value as l_json_null then + assert ("a = Void", json.object (l_json_null, Void) = Void) + else + assert ("parser.next_parsed_json_value /= Void", False) + end + end - test_json_string_and_character - local - c: CHARACTER - js: detachable JSON_STRING - jrep: STRING - parser: JSON_PARSER - do - c := 'a' - -- Eiffel value -> JSON value -> JSON representation - create js.make_json (c.out) - assert ("js /= Void", js /= Void) - assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%"")) - -- Eiffel value -> JSON value -> JSON representation with factory - js ?= json.value (c) - assert ("js /= Void", js /= Void) - if attached js as l_js then - assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%"")) - end + test_json_string_and_character + local + c: CHARACTER + jrep: STRING + js: JSON_STRING + parser: JSON_PARSER + do + c := 'a' + -- Eiffel value -> JSON value -> JSON representation + create js.make_from_string (c.out) + assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%"")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_STRING} json.value (c) as l_json_str then + assert ("js.representation.is_equal (%"%"a%"%")", l_json_str.representation.is_equal ("%"a%"")) + else + assert ("json.value (c) /= Void", False) + end - -- JSON representation -> JSON value -> Eiffel value - jrep := "%"a%"" - create parser.make_parser (jrep) - js := Void - js ?= parser.parse - assert ("js /= Void", js /= Void) - if attached {STRING_32} json.object (js, Void) as ucs then - assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a")) - end + -- JSON representation -> JSON value -> Eiffel value + jrep := "%"a%"" + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as l_json_str then + if attached {STRING_32} json.object (l_json_str, Void) as ucs then + assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a")) + end + else + assert ("parser.next_parsed_json_value /= Void", False) + end + end - end + test_json_string_and_string + local + s: STRING + js: detachable JSON_STRING + jrep: STRING + parser: JSON_PARSER + do + s := "foobar" + jrep := "%"foobar%"" - test_json_string_and_string - local - s: STRING - js: detachable JSON_STRING - jrep: STRING - parser: JSON_PARSER - do - s := "foobar" - -- Eiffel value -> JSON value -> JSON representation - create js.make_json (s) - assert ("js /= Void", js /= Void) - assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%"")) - -- Eiffel value -> JSON value -> JSON representation with factory - js ?= json.value (s) - assert ("js /= Void", js /= Void) - if attached js as l_js then - assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%"")) - end + -- Eiffel value -> JSON value -> JSON representation + create js.make_from_string (s) + assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep)) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_STRING} json.value (s) as l_js then + assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep)) + else + assert ("json.value (s) /= Void", False) + end - -- JSON representation -> JSON value -> Eiffel value - jrep := "%"foobar%"" - create parser.make_parser (jrep) - js := Void - js ?= parser.parse - assert ("js /= Void", js /= Void) - if attached {STRING_32} json.object (js, Void) as l_ucs then - assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar")) - end - end + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as l_js then + if attached {STRING_32} json.object (l_js, Void) as l_ucs then + assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s)) + end + else + assert ("parser.next_parsed_json_value /= Void", False) + end + end - test_json_string_and_uc_string - local - js: detachable JSON_STRING - ucs: detachable STRING_32 - jrep: STRING - parser: JSON_PARSER - do - create ucs.make_from_string ("foobar") - -- Eiffel value -> JSON value -> JSON representation - create js.make_json (ucs) - assert ("js /= Void", js /= Void) - assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%"")) - -- Eiffel value -> JSON value -> JSON representation with factory - js ?= json.value (ucs) - assert ("js /= Void", js /= Void) - if attached js as l_js then - assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%"")) - end + test_json_string_and_uc_string + local + js: detachable JSON_STRING + ucs: detachable STRING_32 + jrep, s: STRING + parser: JSON_PARSER + do + s := "foobar" + jrep := "%"foobar%"" + create ucs.make_from_string (s) - -- JSON representation -> JSON value -> Eiffel value - jrep := "%"foobar%"" - create parser.make_parser (jrep) - js := Void - js ?= parser.parse - assert ("js /= Void", js /= Void) - ucs := Void - ucs ?= json.object (js, Void) - if attached ucs as l_ucs then - assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar")) - end - end + -- Eiffel value -> JSON value -> JSON representation + create js.make_from_string (ucs) + assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep)) - test_json_string_and_special_characters - local - js: detachable JSON_STRING - s: detachable STRING_8 - ucs: detachable STRING_32 - jrep: STRING - parser: JSON_PARSER - do - create s.make_from_string ("foo\bar") - create js.make_json (s) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_STRING} json.value (ucs) as l_js then + assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal (jrep)) + else + assert ("json.value (ucs) /= Void", False) + end - assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%"")) + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as l_js then + if attached {STRING_32} json.object (l_js, Void) as l_ucs then + assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s)) + else + assert ("json.object (js, Void) /= Void", False) + end + else + assert ("parser.next_parsed_json_value /= Void", False) + end + end - -- Eiffel value -> JSON value -> JSON representation with factory - js ?= json.value (s) - assert ("js /= Void", js /= Void) - if js /= Void then - assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%"")) - end + test_json_string_and_special_characters + local + js: detachable JSON_STRING + s: detachable STRING_8 + jrep: STRING + parser: JSON_PARSER + do + jrep := "%"foo\\bar%"" + create s.make_from_string ("foo\bar") + create js.make_from_string (s) + assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string (jrep)) - -- JSON representation -> JSON value -> Eiffel value - jrep := "%"foo\\bar%"" - create parser.make_parser (jrep) - js ?= parser.parse - assert ("js /= Void", js /= Void) - ucs ?= json.object (js, Void) - if ucs /= Void then - assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar")) - end + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_STRING} json.value (s) as l_js then + assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.same_string (jrep)) + else + assert ("json.value (s) /= Void", False) + end - jrep := "%"foo\\bar%"" - create parser.make_parser (jrep) - if attached {JSON_STRING} parser.parse as jstring then + -- JSON representation -> JSON value -> Eiffel value + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as l_js then + if attached {STRING_32} json.object (l_js, Void) as l_ucs then + assert ("ucs.same_string (%"foo\bar%")", l_ucs.same_string ("foo\bar")) + end + else + assert ("parser.next_parsed_json_value /= Void", False) + end + jrep := "%"foo\\bar%"" + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as jstring then assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar")) + else + assert ("parser.next_parsed_json_value /= Void", False) + end + create js.make_from_string_32 ({STRING_32} "你好") + assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D")) + jrep := "%"\u4F60\u597D%"" --| Ni hao + create parser.make_with_string (jrep) + if attached {JSON_STRING} parser.next_parsed_json_value as jstring then + assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32} "你好")) + else + assert ("parser.next_parsed_json_value /= Void", False) + end + end + + test_json_string_and_special_characters_2 + local + js: detachable JSON_STRING + s,j: STRING + do + s := "foo%Tbar" + j := "foo\tbar" + create js.make_from_string (s) + assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j)) + create js.make_from_escaped_json_string (js.item) + assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s)) + + s := "tab=%T cr=%R newline=%N backslash=%H slash=/ end" + j := "tab=\t cr=\r newline=\n backslash=\\ slash=/ end" + create js.make_from_string (s) + assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j)) + create js.make_from_escaped_json_string (js.item) + assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s)) + + s := "" + j := "%")", js.unescaped_string_8.same_string ("")) + + create js.make_from_escaped_json_string (js.item) + assert ("js.item.same_string (%"%")", js.unescaped_string_8.same_string ("")) + + -- + create js.make_from_escaped_json_string ("") + assert ("js.item.same_string (%"%")", js.item.same_string ("")) + assert ("js.unescaped_string_8.same_string (%"%")", js.unescaped_string_8.same_string ("")) + + create js.make_from_escaped_json_string (js.item) + assert ("js.item.same_string (%"")) + assert ("js.unescaped_string_8.same_string (%"%")", js.unescaped_string_8.same_string ("")) + + end + + test_json_array + local + ll: LINKED_LIST [INTEGER_8] + ja: detachable JSON_ARRAY + jn: JSON_NUMBER + jrep: STRING + parser: JSON_PARSER + do + -- Eiffel value -> JSON value -> JSON representation + create ll.make + ll.extend (0) + ll.extend (1) + ll.extend (1) + ll.extend (2) + ll.extend (3) + ll.extend (5) + -- Note: Currently there is no simple way of creating a JSON_ARRAY + -- from an LINKED_LIST. + create ja.make (ll.count) + from + ll.start + until + ll.after + loop + create jn.make_integer (ll.item) + ja.add (jn) + ll.forth + end + assert ("ja /= Void", ja /= Void) + assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]")) + -- Eiffel value -> JSON value -> JSON representation with factory + if attached {JSON_ARRAY} json.value (ll) as l_ja then + assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]")) + else + assert ("json.value (ll) /= Void", False) end - create js.make_json_from_string_32 ({STRING_32}"%/20320/%/22909/") - assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D")) - - jrep := "%"\u4F60\u597D%"" --| Ni hao - create parser.make_parser (jrep) - if attached {JSON_STRING} parser.parse as jstring then - assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/")) + -- JSON representation -> JSON value -> Eiffel value + -- Note: The JSON_FACTORY will return the smallest INTEGER_* object + -- that can represent the value of the JSON number, in this case + -- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8 + -- values 0, 1, 1, 2, 3, 5 + jrep := "[0,1,1,2,3,5]" + create parser.make_with_string (jrep) + if attached {JSON_ARRAY} parser.next_parsed_json_value as l_ja then + if attached {LINKED_LIST [detachable ANY]} json.object (ja, Void) as l_ll2 then + assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll)) + else + assert ("json.object (ja, Void) /= Void", False) + end + else + assert ("parser.next_parsed_json_value /= Void", False) end - end + end - test_json_array - local - ll: LINKED_LIST [INTEGER_8] - ll2: detachable LINKED_LIST [detachable ANY] - ja: detachable JSON_ARRAY - jn: JSON_NUMBER - jrep: STRING - parser: JSON_PARSER - do - -- Eiffel value -> JSON value -> JSON representation - create ll.make - ll.extend (0) - ll.extend (1) - ll.extend (1) - ll.extend (2) - ll.extend (3) - ll.extend (5) - -- Note: Currently there is no simple way of creating a JSON_ARRAY - -- from an LINKED_LIST. - create ja.make_array - from - ll.start - until - ll.after - loop - create jn.make_integer (ll.item) - ja.add (jn) - ll.forth - end - assert ("ja /= Void", ja /= Void) - assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]")) - -- Eiffel value -> JSON value -> JSON representation with factory - ja := Void - ja ?= json.value (ll) - assert ("ja /= Void", ja /= Void) - if attached ja as l_ja then - assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]")) - end + test_json_object + local + t: detachable HASH_TABLE [detachable ANY, STRING_GENERAL] + i: INTEGER + ucs_key, ucs: STRING_32 + a: ARRAY [INTEGER] + jo: detachable JSON_OBJECT + jn: JSON_NUMBER + js_key, js: JSON_STRING + ja: JSON_ARRAY + jrep: STRING + parser: JSON_PARSER + do + -- Eiffel value -> JSON value -> JSON representation + -- Note: Currently there is now way of creating a JSON_OBJECT from + -- a HASH_TABLE, so we do it manually. + -- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]} + create jo.make + create js_key.make_from_string ("name") + create js.make_from_string ("foobar") + jo.put (js, js_key) + create js_key.make_from_string ("size") + create jn.make_integer (42) + jo.put (jn, js_key) + create js_key.make_from_string ("contents") + create ja.make (6) + create jn.make_integer (0) + ja.add (jn) + create jn.make_integer (1) + ja.add (jn) + create jn.make_integer (1) + ja.add (jn) + create jn.make_integer (2) + ja.add (jn) + create jn.make_integer (3) + ja.add (jn) + create jn.make_integer (5) + ja.add (jn) + jo.put (ja, js_key) + assert ("jo /= Void", jo /= Void) + assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}")) - -- JSON representation -> JSON value -> Eiffel value - -- Note: The JSON_FACTORY will return the smallest INTEGER_* object - -- that can represent the value of the JSON number, in this case - -- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8 - -- values 0, 1, 1, 2, 3, 5 - jrep := "[0,1,1,2,3,5]" - create parser.make_parser (jrep) - ja := Void - ja ?= parser.parse - assert ("ja /= Void", ja /= Void) - ll2 ?= json.object (ja, Void) - assert ("ll2 /= Void", ll2 /= Void) - --ll.compare_objects - --ll2.compare_objects - if attached ll2 as l_ll2 then - assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll)) - end - - end - - test_json_object - local - t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL] - i: INTEGER - ucs_key, ucs: STRING_32 - a: ARRAY [INTEGER] - jo: detachable JSON_OBJECT - jn: JSON_NUMBER - js_key, js: JSON_STRING - ja: JSON_ARRAY - jrep: STRING - parser: JSON_PARSER - do - -- Eiffel value -> JSON value -> JSON representation - -- Note: Currently there is now way of creating a JSON_OBJECT from - -- a HASH_TABLE, so we do it manually. - -- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]} - create jo.make - create js_key.make_json ("name") - create js.make_json ("foobar") - jo.put (js, js_key) - create js_key.make_json ("size") - create jn.make_integer (42) - jo.put (jn, js_key) - create js_key.make_json ("contents") - create ja.make_array - create jn.make_integer (0) - ja.add (jn) - create jn.make_integer (1) - ja.add (jn) - create jn.make_integer (1) - ja.add (jn) - create jn.make_integer (2) - ja.add (jn) - create jn.make_integer (3) - ja.add (jn) - create jn.make_integer (5) - ja.add (jn) - jo.put (ja, js_key) - assert ("jo /= Void", jo /= Void) - assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}")) - -- Eiffel value -> JSON value -> JSON representation with factory - create t.make (3) - create ucs_key.make_from_string ("name") - create ucs.make_from_string ("foobar") - t.put (ucs, ucs_key) - create ucs_key.make_from_string ("size") - i := 42 - t.put (i, ucs_key) - create ucs_key.make_from_string ("contents") - a := <<0, 1, 1, 2, 3, 5>> - t.put (a, ucs_key) - jo := Void - jo ?= json.value (t) - assert ("jo /= Void", jo /= Void) - if attached jo as l_jo then + -- Eiffel value -> JSON value -> JSON representation with factory + create t.make (3) + create ucs_key.make_from_string ("name") + create ucs.make_from_string ("foobar") + t.put (ucs, ucs_key) + create ucs_key.make_from_string ("size") + i := 42 + t.put (i, ucs_key) + create ucs_key.make_from_string ("contents") + a := <<0, 1, 1, 2, 3, 5>> + t.put (a, ucs_key) + if attached {JSON_OBJECT} json.value (t) as l_jo then assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", l_jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}")) - end - -- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation - jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}" - create parser.make_parser (jrep) - jo := Void - jo ?= parser.parse - assert ("jo /= Void", jo /= Void) - t2 ?= json.object (jo, Void) - assert ("t2 /= Void", t2 /= Void) - jo ?= json.value (t2) - assert ("jo /= Void", jo /= Void) - if attached jo as l_jo then - assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation)) - end + else + assert ("json.value (t) /= Void", False) + end - end + -- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation + jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}" + create parser.make_with_string (jrep) + if attached {JSON_OBJECT} parser.next_parsed_json_value as l_jo then + if attached {HASH_TABLE [detachable ANY, STRING_GENERAL]} json.object (l_jo, Void) as l_t2 then + if attached json.value (l_t2) as l_jo_2 then + assert ("jrep.is_equal (jo.representation)", jrep.is_equal (l_jo_2.representation)) + else + assert ("json.value (t2) /= Void", False) + end + else + assert ("json.object (jo, Void) /= Void", False) + end + else + assert ("parser.next_parsed_json_value /= Void", jo /= Void) + end + end - test_json_object_hash_code - local - ht: HASH_TABLE [ANY, JSON_VALUE] - jo: JSON_OBJECT - do - create ht.make (1) - create jo.make - ht.force ("", jo) - assert ("ht.has_key (jo)", ht.has_key (jo)) - end + test_json_object_hash_code + local + ht: HASH_TABLE [ANY, JSON_VALUE] + jo: JSON_OBJECT + do + create ht.make (1) + create jo.make + ht.force ("", jo) + assert ("ht.has_key (jo)", ht.has_key (jo)) + end - test_json_failed_json_conversion - -- Test converting an Eiffel object to JSON that is based on a class - -- for which no JSON converter has been registered. - local - gv: OPERATING_ENVIRONMENT - jv: detachable JSON_VALUE - exception: BOOLEAN - do - if not exception then - create gv - jv := json.value (gv) - else - assert ("exceptions.is_developer_exception", json.is_developer_exception) --- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: OPERATING_ENVIRONMENT")) - end - rescue - exception := True - retry - end + test_json_failed_json_conversion + -- Test converting an Eiffel object to JSON that is based on a class + -- for which no JSON converter has been registered. + local + gv: OPERATING_ENVIRONMENT + jv: detachable JSON_VALUE + exception: BOOLEAN + do + if not exception then + create gv + jv := json.value (gv) + else + assert ("exceptions.is_developer_exception", json.is_developer_exception) + end + rescue + exception := True + retry + end - test_json_failed_eiffel_conversion - -- Test converting from a JSON value to an Eiffel object based on a - -- class for which no JSON converter has been registered. - local - gv : detachable OPERATING_ENVIRONMENT - jo: JSON_OBJECT - exception: BOOLEAN - do - if not exception then - create jo.make - gv ?= json.object (jo, "OPERATING_ENVIRONMENT") - else - assert ("exceptions.is_developer_exception", json.is_developer_exception) --- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> OPERATING_ENVIRONMENT")) - - end - rescue - exception := True - retry - end + test_json_failed_eiffel_conversion + -- Test converting from a JSON value to an Eiffel object based on a + -- class for which no JSON converter has been registered. + local + gv: detachable ANY + jo: JSON_OBJECT + exception: BOOLEAN + do + if not exception then + create jo.make + gv := json.object (jo, "OPERATING_ENVIRONMENT") + else + assert ("exceptions.is_developer_exception", json.is_developer_exception) + end + rescue + exception := True + retry + end end -- class TEST_JSON_CORE diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_custom_classes.e b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_custom_classes.e index fc7957bc..7db1df10 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_custom_classes.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_custom_classes.e @@ -1,42 +1,52 @@ -class TEST_JSON_CUSTOM_CLASSES +note + description: "Parsing and converter of book collection test." + date: "$Date$" + revision: "$Revision$" + +class + TEST_JSON_CUSTOM_CLASSES inherit - SHARED_EJSON - rename default_create as shared_default_create end + + SHARED_EJSON + undefine + default_create + end + EQA_TEST_SET - select default_create end + feature -- Test - test_custom_classes - local - bc: detachable BOOK_COLLECTION - jbc: JSON_BOOK_CONVERTER - jbcc: JSON_BOOK_COLLECTION_CONVERTER - jac: JSON_AUTHOR_CONVERTER - jo: detachable JSON_OBJECT - parser: JSON_PARSER - jrep: STRING - do - create jbc.make - json.add_converter (jbc) - create jbcc.make - json.add_converter (jbcc) - create jac.make - json.add_converter (jac) - jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}" - create parser.make_parser (jrep) - jo := Void - jo ?= parser.parse - assert ("jo /= Void", jo /= Void) - bc := Void - bc ?= json.object (jo, "BOOK_COLLECTION") - assert ("bc /= Void", bc /= Void) - jo ?= json.value (bc) - assert ("jo /= Void", jo /= Void) - if attached jo as l_jo then - assert ("JSON representation is correct", l_jo.representation.same_string ("{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}")) - end - - end + test_custom_classes + -- Parse JSON representation to JSON_OBJECT and test book collection converter. + local + jbc: JSON_BOOK_CONVERTER + jbcc: JSON_BOOK_COLLECTION_CONVERTER + jac: JSON_AUTHOR_CONVERTER + parser: JSON_PARSER + jrep: STRING + do + create jbc.make + json.add_converter (jbc) + create jbcc.make + json.add_converter (jbcc) + create jac.make + json.add_converter (jac) + jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}" + create parser.make_parser (jrep) + if attached {JSON_OBJECT} parser.parse as l_json_object then + if attached {BOOK_COLLECTION} json.object (l_json_object, "BOOK_COLLECTION") as l_collection then + if attached {JSON_OBJECT} json.value (l_collection) as l_json_object_2 then + assert ("JSON representation is correct", l_json_object_2.representation.same_string (jrep)) + else + assert ("BOOK_COLLECTION converted to JSON_OBJECT", False) + end + else + assert ("JSON_OBJECT converted to BOOK_COLLECTION", False) + end + else + assert ("JSON object representation to JSON_OBJECT", False) + end + end end -- class TEST_JSON_CUSTOM_CLASS diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_suite.e b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_suite.e index c2a66b71..649366d1 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/test_json_suite.e +++ b/contrib/library/text/parser/json/test/autotest/test_suite/test_json_suite.e @@ -1,4 +1,4 @@ -note +note description: "[ Eiffel tests that can be executed by testing tool. ]" @@ -33,8 +33,8 @@ feature -- Tests Pass do if attached json_file_from ("pass1.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("pass1.json",parse_json.is_parsed = True) + parse_json.parse_content + assert ("pass1.json", parse_json.is_valid) end end @@ -45,8 +45,8 @@ feature -- Tests Pass do if attached json_file_from ("pass2.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("pass2.json",parse_json.is_parsed = True) + parse_json.parse_content + assert ("pass2.json",parse_json.is_valid) end end @@ -57,8 +57,8 @@ feature -- Tests Pass do if attached json_file_from ("pass3.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("pass3.json",parse_json.is_parsed = True) + parse_json.parse_content + assert ("pass3.json",parse_json.is_valid) end end @@ -68,20 +68,16 @@ feature -- Tests Pass utf: UTF_CONVERTER s: READABLE_STRING_32 do - s := {STRING_32} "{ %"nihaoma%": %"你好吗\t?%" }" - + s := {STRING_32} "{ %"nihaoma%": %"你好吗\t?%" }" parse_json := new_json_parser (utf.string_32_to_utf_8_string_8 (s)) - json_value := parse_json.parse_json - assert ("utf8.pass1.json", parse_json.is_parsed = True) - if - attached {JSON_OBJECT} json_value as jo and then - attached {JSON_STRING} jo.item ("nihaoma") as js - then - assert ("utf8.nihaoma", js.unescaped_string_32.same_string ({STRING_32} "你好吗%T?")) + parse_json.parse_content + assert ("utf8.pass1.json", parse_json.is_valid) + if attached {JSON_OBJECT} parse_json.parsed_json_value as jo and then attached {JSON_STRING} jo.item ("nihaoma") as js then + assert ("utf8.nihaoma", js.unescaped_string_32.same_string ({STRING_32} "你好吗%T?")) else assert ("utf8.nihaoma", False) - end - end + end + end feature -- Tests Failures test_json_fail1 @@ -91,8 +87,8 @@ feature -- Tests Failures do if attached json_file_from ("fail1.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail1.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail1.json", parse_json.is_valid = False) end end @@ -103,8 +99,8 @@ feature -- Tests Failures do if attached json_file_from ("fail2.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail2.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail2.json",parse_json.is_valid = False) end end @@ -115,8 +111,8 @@ feature -- Tests Failures do if attached json_file_from ("fail3.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail3.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail3.json",parse_json.is_valid = False) end end @@ -127,8 +123,8 @@ feature -- Tests Failures do if attached json_file_from ("fail4.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail4.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail4.json",parse_json.is_valid = False) end end @@ -139,8 +135,8 @@ feature -- Tests Failures do if attached json_file_from ("fail5.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail5.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail5.json",parse_json.is_valid = False) end end @@ -152,8 +148,8 @@ feature -- Tests Failures do if attached json_file_from ("fail6.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail6.json",parse_json.is_parsed = False ) + parse_json.parse_content + assert ("fail6.json",parse_json.is_valid = False ) end end @@ -164,8 +160,8 @@ feature -- Tests Failures do if attached json_file_from ("fail7.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail7.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail7.json",parse_json.is_valid = False) end end @@ -176,8 +172,8 @@ feature -- Tests Failures do if attached json_file_from ("fail8.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail8.json",parse_json.is_parsed = False ) + parse_json.parse_content + assert ("fail8.json",parse_json.is_valid = False ) end end @@ -189,8 +185,8 @@ feature -- Tests Failures do if attached json_file_from ("fail9.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail9.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail9.json",parse_json.is_valid = False) end end @@ -202,8 +198,8 @@ feature -- Tests Failures do if attached json_file_from ("fail10.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail10.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail10.json",parse_json.is_valid = False) end end @@ -214,8 +210,8 @@ feature -- Tests Failures do if attached json_file_from ("fail11.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail11.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail11.json",parse_json.is_valid = False) end end @@ -226,8 +222,8 @@ feature -- Tests Failures do if attached json_file_from ("fail12.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail12.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail12.json",parse_json.is_valid = False) end end @@ -238,8 +234,8 @@ feature -- Tests Failures do if attached json_file_from ("fail13.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail13.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail13.json",parse_json.is_valid = False) end end @@ -250,8 +246,8 @@ feature -- Tests Failures do if attached json_file_from ("fail14.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail14.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail14.json",parse_json.is_valid = False) end end @@ -262,8 +258,8 @@ feature -- Tests Failures do if attached json_file_from ("fail15.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail15.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail15.json",parse_json.is_valid = False) end end @@ -274,8 +270,8 @@ feature -- Tests Failures do if attached json_file_from ("fail16.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail16.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail16.json",parse_json.is_valid = False) end end @@ -286,8 +282,8 @@ feature -- Tests Failures do if attached json_file_from ("fail17.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail17.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail17.json",parse_json.is_valid = False) end end @@ -298,8 +294,8 @@ feature -- Tests Failures do if attached json_file_from ("fail18.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail18.json",parse_json.is_parsed = True) + parse_json.parse_content + assert ("fail18.json",parse_json.is_valid = True) end end @@ -310,8 +306,8 @@ feature -- Tests Failures do if attached json_file_from ("fail19.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail19.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail19.json",parse_json.is_valid = False) end end @@ -322,8 +318,8 @@ feature -- Tests Failures do if attached json_file_from ("fail20.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail20.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail20.json",parse_json.is_valid = False) end end @@ -334,8 +330,8 @@ feature -- Tests Failures do if attached json_file_from ("fail21.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail21.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail21.json",parse_json.is_valid = False) end end @@ -347,8 +343,8 @@ feature -- Tests Failures do if attached json_file_from ("fail22.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail22.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail22.json",parse_json.is_valid = False) end end @@ -359,8 +355,8 @@ feature -- Tests Failures do if attached json_file_from ("fail23.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail23.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail23.json",parse_json.is_valid = False) end end @@ -371,8 +367,8 @@ feature -- Tests Failures do if attached json_file_from ("fail24.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail24.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail24.json",parse_json.is_valid = False) end end @@ -383,8 +379,8 @@ feature -- Tests Failures do if attached json_file_from ("fail25.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail25.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail25.json",parse_json.is_valid = False) end end @@ -396,8 +392,8 @@ feature -- Tests Failures do if attached json_file_from ("fail26.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail26.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail26.json",parse_json.is_valid = False) end end @@ -409,8 +405,8 @@ feature -- Tests Failures do if attached json_file_from ("fail27.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail27.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail27.json",parse_json.is_valid = False) end end @@ -422,8 +418,8 @@ feature -- Tests Failures do if attached json_file_from ("fail28.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail28.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail28.json",parse_json.is_valid = False) end end @@ -435,8 +431,8 @@ feature -- Tests Failures do if attached json_file_from ("fail29.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail29.json",parse_json.is_parsed = False ) + parse_json.parse_content + assert ("fail29.json",parse_json.is_valid = False ) end end @@ -448,8 +444,8 @@ feature -- Tests Failures do if attached json_file_from ("fail30.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail30.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail30.json",parse_json.is_valid = False) end end @@ -460,8 +456,8 @@ feature -- Tests Failures do if attached json_file_from ("fail31.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail31.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail31.json",parse_json.is_valid = False) end end @@ -472,8 +468,8 @@ feature -- Tests Failures do if attached json_file_from ("fail32.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail32.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail32.json",parse_json.is_valid = False) end end @@ -484,8 +480,8 @@ feature -- Tests Failures do if attached json_file_from ("fail33.json") as json_file then parse_json := new_json_parser (json_file) - json_value := parse_json.parse_json - assert ("fail33.json",parse_json.is_parsed = False) + parse_json.parse_content + assert ("fail33.json",parse_json.is_valid = False) end end @@ -493,52 +489,47 @@ feature -- JSON_FROM_FILE file_reader: JSON_FILE_READER - json_value: detachable JSON_VALUE - - json_file_from (fn: STRING): detachable STRING - local - f: RAW_FILE - l_path: STRING - test_dir: STRING + json_file_from (fn: READABLE_STRING_GENERAL): detachable STRING + local + f: RAW_FILE + l_path: PATH + test_dir: PATH i: INTEGER do - test_dir := (create {EXECUTION_ENVIRONMENT}).current_working_directory - test_dir.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator) - - l_path := test_dir + fn - create f.make_with_name (l_path) + test_dir := (create {EXECUTION_ENVIRONMENT}).current_working_path + l_path := test_dir.extended (fn) + create f.make_with_path (l_path) if f.exists then -- Found json file else - -- before EiffelStudio 7.3 , the current dir of autotest execution was not the parent dir of ecf but something like - -- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json + -- before EiffelStudio 7.3 , the current dir of autotest execution was not the parent dir of ecf but something like + -- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json from i := 5 until i = 0 loop - test_dir.append_character ('.') - test_dir.append_character ('.') - test_dir.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator) + test_dir := test_dir.extended ("..") i := i - 1 end - l_path := test_dir + fn + l_path := test_dir.extended (fn) end - create f.make_with_name (l_path) + create f.make_with_path (l_path) if f.exists then - Result := file_reader.read_json_from (l_path) + Result := file_reader.read_json_from (l_path.name) end - assert ("File contains json data", Result /= Void) - end + assert ("File contains json data", Result /= Void) + end + new_json_parser (a_string: STRING): JSON_PARSER do - create Result.make_parser (a_string) + create Result.make_with_string (a_string) end - invariant file_reader /= Void end + diff --git a/contrib/library/text/parser/json/test/autotest/test_suite/test_suite-safe.ecf b/contrib/library/text/parser/json/test/autotest/test_suite/test_suite-safe.ecf index 541c8d9e..0b10a63e 100644 --- a/contrib/library/text/parser/json/test/autotest/test_suite/test_suite-safe.ecf +++ b/contrib/library/text/parser/json/test/autotest/test_suite/test_suite-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,11 +7,11 @@ /CVS$ /.svn$ - - +