Merge branch 'master' of https://github.com/eiffelhub/json
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for ARRAYED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_ARRAYED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_LIST_CONVERTER
|
||||
redefine
|
||||
object
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: ARRAYED_LIST [detachable ANY]
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_object (nb: INTEGER): like object
|
||||
do
|
||||
create Result.make (nb)
|
||||
end
|
||||
|
||||
end -- class JSON_ARRAYED_LIST_CONVERTER
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,30 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for LINKED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_LINKED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_LIST_CONVERTER
|
||||
redefine
|
||||
object
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: LINKED_LIST [detachable ANY]
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_object (nb: INTEGER): like object
|
||||
do
|
||||
create Result.make
|
||||
end
|
||||
|
||||
end -- class JSON_LINKED_LIST_CONVERTER
|
||||
@@ -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
|
||||
@@ -1,268 +0,0 @@
|
||||
note
|
||||
description: "Core factory class for creating JSON objects and corresponding Eiffel objects."
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class EJSON
|
||||
|
||||
inherit
|
||||
EXCEPTIONS
|
||||
|
||||
feature -- Access
|
||||
|
||||
value (an_object: detachable ANY): detachable JSON_VALUE
|
||||
-- JSON value from Eiffel object. Raises an "eJSON exception" if
|
||||
-- unable to convert value.
|
||||
local
|
||||
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.
|
||||
if an_object = Void then
|
||||
create {JSON_NULL} Result
|
||||
elseif attached {BOOLEAN} an_object as b then
|
||||
create {JSON_BOOLEAN} Result.make_boolean (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
|
||||
create {JSON_NUMBER} Result.make_integer (i16)
|
||||
elseif attached {INTEGER_32} an_object as i32 then
|
||||
create {JSON_NUMBER} Result.make_integer (i32)
|
||||
elseif attached {INTEGER_64} an_object as i64 then
|
||||
create {JSON_NUMBER} Result.make_integer (i64)
|
||||
elseif attached {NATURAL_8} an_object as n8 then
|
||||
create {JSON_NUMBER} Result.make_natural (n8)
|
||||
elseif attached {NATURAL_16} an_object as n16 then
|
||||
create {JSON_NUMBER} Result.make_natural (n16)
|
||||
elseif attached {NATURAL_32} an_object as n32 then
|
||||
create {JSON_NUMBER} Result.make_natural (n32)
|
||||
elseif attached {NATURAL_64} an_object as n64 then
|
||||
create {JSON_NUMBER} Result.make_natural (n64)
|
||||
elseif attached {REAL_32} an_object as r32 then
|
||||
create {JSON_NUMBER} Result.make_real (r32)
|
||||
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
|
||||
from
|
||||
i := a.lower
|
||||
until
|
||||
i > a.upper
|
||||
loop
|
||||
if attached value (a @ i) as v then
|
||||
ja.add (v)
|
||||
else
|
||||
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)
|
||||
elseif attached {CHARACTER_32} an_object as c32 then
|
||||
create {JSON_STRING} Result.make_json (c32.out)
|
||||
|
||||
elseif attached {STRING_8} an_object as s8 then
|
||||
create {JSON_STRING} Result.make_json (s8)
|
||||
elseif attached {STRING_32} an_object as s32 then
|
||||
create {JSON_STRING} Result.make_json_from_string_32 (s32)
|
||||
end
|
||||
|
||||
if Result = Void then
|
||||
-- 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
|
||||
raise (exception_failed_to_convert_to_json (an_object))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
-- exception" if unable to convert value.
|
||||
local
|
||||
i: INTEGER
|
||||
ll: LINKED_LIST [detachable ANY]
|
||||
t: HASH_TABLE [detachable ANY, STRING_GENERAL]
|
||||
keys: ARRAY [JSON_STRING]
|
||||
do
|
||||
if a_value = Void then
|
||||
Result := Void
|
||||
else
|
||||
if base_class = Void then
|
||||
if a_value = Void then
|
||||
Result := Void
|
||||
elseif attached {JSON_NULL} a_value then
|
||||
Result := Void
|
||||
elseif attached {JSON_BOOLEAN} a_value as jb then
|
||||
Result := jb.item
|
||||
elseif attached {JSON_NUMBER} a_value as jn then
|
||||
if jn.item.is_integer_8 then
|
||||
Result := jn.item.to_integer_8
|
||||
elseif jn.item.is_integer_16 then
|
||||
Result := jn.item.to_integer_16
|
||||
elseif jn.item.is_integer_32 then
|
||||
Result := jn.item.to_integer_32
|
||||
elseif jn.item.is_integer_64 then
|
||||
Result := jn.item.to_integer_64
|
||||
elseif jn.item.is_natural_64 then
|
||||
Result := jn.item.to_natural_64
|
||||
elseif jn.item.is_double then
|
||||
Result := jn.item.to_double
|
||||
end
|
||||
elseif attached {JSON_STRING} a_value as js then
|
||||
create {STRING_32} Result.make_from_string (js.unescaped_string_32)
|
||||
elseif attached {JSON_ARRAY} a_value as ja then
|
||||
from
|
||||
create ll.make
|
||||
i := 1
|
||||
until
|
||||
i > ja.count
|
||||
loop
|
||||
ll.extend (object (ja [i], Void))
|
||||
i := i + 1
|
||||
end
|
||||
Result := ll
|
||||
elseif attached {JSON_OBJECT} a_value as jo then
|
||||
keys := jo.current_keys
|
||||
create t.make (keys.count)
|
||||
from
|
||||
i := keys.lower
|
||||
until
|
||||
i > keys.upper
|
||||
loop
|
||||
if attached {STRING_GENERAL} object (keys [i], Void) as s then
|
||||
t.put (object (jo.item (keys [i]), Void), s)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
Result := t
|
||||
end
|
||||
else
|
||||
if converters.has_key (base_class) and then attached converters.found_item as jc then
|
||||
Result := jc.from_json (a_value)
|
||||
else
|
||||
raise (exception_failed_to_convert_to_eiffel (a_value, base_class))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
object_from_json (json: STRING; base_class: detachable STRING): detachable ANY
|
||||
-- Eiffel object from JSON representation. If `base_class' /= Void an
|
||||
-- Eiffel object based on `base_class' will be returned. Raises an
|
||||
-- "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
|
||||
Result := object (jv, base_class)
|
||||
end
|
||||
end
|
||||
|
||||
converter_for (an_object: ANY): detachable JSON_CONVERTER
|
||||
-- Converter for objects. Returns Void if none found.
|
||||
require
|
||||
an_object_not_void: an_object /= Void
|
||||
do
|
||||
if converters.has_key (an_object.generator) then
|
||||
Result := converters.found_item
|
||||
end
|
||||
end
|
||||
|
||||
json_reference (s: STRING): JSON_OBJECT
|
||||
-- A JSON (Dojo style) reference object using `s' as the
|
||||
-- reference value. The caller is responsable for ensuring
|
||||
-- the validity of `s' as a json reference.
|
||||
require
|
||||
s_not_void: s /= Void
|
||||
local
|
||||
js_key, js_value: JSON_STRING
|
||||
do
|
||||
create Result.make
|
||||
create js_key.make_json ("$ref")
|
||||
create js_value.make_json (s)
|
||||
Result.put (js_value, js_key)
|
||||
end
|
||||
|
||||
json_references (l: LIST [STRING]): JSON_ARRAY
|
||||
-- A JSON array of JSON (Dojo style) reference objects using the
|
||||
-- strings in `l' as reference values. The caller is responsable
|
||||
-- for ensuring the validity of all strings in `l' as json
|
||||
-- references.
|
||||
require
|
||||
l_not_void: l /= Void
|
||||
local
|
||||
c: ITERATION_CURSOR [STRING]
|
||||
do
|
||||
create Result.make_array
|
||||
from
|
||||
c := l.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
Result.add (json_reference (c.item))
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
add_converter (jc: JSON_CONVERTER)
|
||||
-- Add the converter `jc'.
|
||||
require
|
||||
jc_not_void: jc /= Void
|
||||
do
|
||||
converters.force (jc, jc.object.generator)
|
||||
ensure
|
||||
has_converter: converter_for (jc.object) /= Void
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
converters: HASH_TABLE [JSON_CONVERTER, STRING]
|
||||
-- Converters hashed by generator (base class)
|
||||
once
|
||||
create Result.make (10)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation (Exceptions)
|
||||
|
||||
exception_prefix: STRING = "eJSON exception: "
|
||||
|
||||
exception_failed_to_convert_to_eiffel (a_value: JSON_VALUE; base_class: detachable STRING): STRING
|
||||
-- Exception message for failing to convert a JSON_VALUE to an instance of `a'.
|
||||
do
|
||||
Result := exception_prefix + "Failed to convert JSON_VALUE to an Eiffel object: " + a_value.generator
|
||||
if base_class /= Void then
|
||||
Result.append (" -> {" + base_class + "}")
|
||||
end
|
||||
end
|
||||
|
||||
exception_failed_to_convert_to_json (an_object: detachable ANY): STRING
|
||||
-- Exception message for failing to convert `a' to a JSON_VALUE.
|
||||
do
|
||||
Result := exception_prefix + "Failed to convert Eiffel object to a JSON_VALUE"
|
||||
if an_object /= Void then
|
||||
Result.append (" : {" + an_object.generator + "}")
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation (JSON parser)
|
||||
|
||||
json_parser: JSON_PARSER
|
||||
once
|
||||
create Result.make_parser ("")
|
||||
end
|
||||
|
||||
end -- class EJSON
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
-- <Precursor>
|
||||
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
|
||||
|
||||
@@ -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 </script> ...
|
||||
-- escape only </ to <\/
|
||||
if s.valid_index (i - 1) and then s.item (i - 1) = '<' then
|
||||
Result.append_string ("\/")
|
||||
else
|
||||
Result.append_string ("/")
|
||||
end
|
||||
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
|
||||
else
|
||||
Result.append ("\u")
|
||||
h := uc.code.to_hex_string
|
||||
-- Remove first 0 and keep 4 hexa digit
|
||||
-- Remove first 0 and keep 4 hexa digit
|
||||
from
|
||||
j := 1
|
||||
until
|
||||
@@ -405,14 +482,15 @@ feature {NONE} -- Implementation
|
||||
j := j + 1
|
||||
end
|
||||
h := h.substring (j, h.count)
|
||||
|
||||
from
|
||||
until
|
||||
h.count >= 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -1,118 +0,0 @@
|
||||
note
|
||||
description: "Objects that ..."
|
||||
author: "jvelilla"
|
||||
date: "2008/08/24"
|
||||
revision: "0.1"
|
||||
|
||||
class
|
||||
JSON_READER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
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
|
||||
representation := a_json
|
||||
index := 1
|
||||
end
|
||||
|
||||
read: CHARACTER
|
||||
-- Read character
|
||||
do
|
||||
if not representation.is_empty then
|
||||
Result := representation.item (index)
|
||||
end
|
||||
end
|
||||
|
||||
next
|
||||
-- Move to next index
|
||||
require
|
||||
has_more_elements: has_next
|
||||
do
|
||||
index := index + 1
|
||||
ensure
|
||||
incremented: old index + 1 = index
|
||||
end
|
||||
|
||||
previous
|
||||
-- Move to previous index
|
||||
require
|
||||
not_is_first: has_previous
|
||||
do
|
||||
index := index - 1
|
||||
ensure
|
||||
incremented: old index - 1 = index
|
||||
end
|
||||
|
||||
skip_white_spaces
|
||||
-- Remove white spaces
|
||||
local
|
||||
c: like actual
|
||||
do
|
||||
from
|
||||
c := actual
|
||||
until
|
||||
(c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next
|
||||
loop
|
||||
next
|
||||
c := actual
|
||||
end
|
||||
end
|
||||
|
||||
json_substring (start_index, end_index: INTEGER_32): STRING
|
||||
-- JSON representation between `start_index' and `end_index'
|
||||
do
|
||||
Result := representation.substring (start_index, end_index)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_next: BOOLEAN
|
||||
-- Has a next character?
|
||||
do
|
||||
Result := index <= representation.count
|
||||
end
|
||||
|
||||
has_previous: BOOLEAN
|
||||
-- Has a previous character?
|
||||
do
|
||||
Result := index >= 1
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
representation: STRING
|
||||
-- Serialized representation of the original JSON string
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
actual: CHARACTER
|
||||
-- Current character or '%U' if none
|
||||
do
|
||||
if index > representation.count then
|
||||
Result := '%U'
|
||||
else
|
||||
Result := representation.item (index)
|
||||
end
|
||||
end
|
||||
|
||||
index: INTEGER
|
||||
-- Actual index
|
||||
|
||||
invariant
|
||||
representation_not_void: representation /= Void
|
||||
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user