commit 308fa7f2e7c3602917641e81162b1ff3bf4bfdfe Author: jvelilla Date: Sat May 24 14:23:27 2008 +0000 eJson initial import diff --git a/json/json.ecf b/json/json.ecf new file mode 100644 index 00000000..0ffcebc7 --- /dev/null +++ b/json/json.ecf @@ -0,0 +1,23 @@ + + + + + + + + + /EIFGENs$ + /.svn$ + /CVS$ + + + ^/scanner$ + + + + + + + + diff --git a/json/json.rc b/json/json.rc new file mode 100644 index 00000000..d3f5a12f --- /dev/null +++ b/json/json.rc @@ -0,0 +1 @@ + diff --git a/json/json_array.e b/json/json_array.e new file mode 100644 index 00000000..e9924815 --- /dev/null +++ b/json/json_array.e @@ -0,0 +1,87 @@ +indexing + 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: "$Date$" + revision: "$Revision$" + +class + JSON_ARRAY + inherit + JSON_VALUE + +create + make_array + +feature -- Initialization + make_array is + -- + do + create values.make (10) + end + +feature -- Access + +feature -- Change Element + add(value:JSON_VALUE) is + require + not_null:value /= void + local + l_json_value:JSON_VALUE + do + values.extend(value) + ensure + has_new_value:old values.count + 1 = values.count + end + + + to_json:STRING is + --Printable json representation + -- [] or [elements] + local + value:JSON_VALUE + do + create Result.make_empty + Result.append("[") + from + values.start + until + values.off + loop + value:=values.item + Result.append(value.to_json) + values.forth + if not values.after then + Result.append(",") + end + end + Result.append("]") + end + + hash_code:INTEGER is + -- + 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 +feature {NONE} --Implementation + values:ARRAYED_LIST[JSON_VALUE] + + +end diff --git a/json/json_boolean.e b/json/json_boolean.e new file mode 100644 index 00000000..6327246c --- /dev/null +++ b/json/json_boolean.e @@ -0,0 +1,39 @@ +indexing + description: "JSON Truth values" + author: "Javier Velilla" + date: "$Date$" + revision: "$Revision$" + +class + JSON_BOOLEAN + inherit + JSON_VALUE + +create + make_boolean +feature -- Initialization + + make_boolean(a_value:BOOLEAN) is + -- + do + value:=a_value + end + +feature -- Access + + to_json:STRING is + -- + do + Result:=value.out + end + + hash_code:INTEGER is + -- + do + Result:=value.hash_code + end + + + value:BOOLEAN + +end diff --git a/json/json_file_reader.e b/json/json_file_reader.e new file mode 100644 index 00000000..6633cd69 --- /dev/null +++ b/json/json_file_reader.e @@ -0,0 +1,35 @@ +indexing + description: "Objects that ..." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + JSON_FILE_READER + +feature -- Access +read_json_from(a_path:STRING):STRING is + local + l_file: PLAIN_TEXT_FILE + template_content:STRING + do + + create l_file.make (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) + template_content.append (l_file.last_string.twin) + Result := template_content + l_file.close + end + end + end + +end diff --git a/json/json_null.e b/json/json_null.e new file mode 100644 index 00000000..58d25c5c --- /dev/null +++ b/json/json_null.e @@ -0,0 +1,27 @@ +indexing + description: "JSON Null Values" + author: "Javier Velilla" + date: "$Date$" + revision: "$Revision$" + +class + JSON_NULL + inherit + JSON_VALUE + +feature --Access + to_json:STRING is + -- + do + Result:=null_value + end + + hash_code:INTEGER is + -- + do + Result:= null_value.hash_code + end + +feature -- Implementation + null_value:STRING is "null" +end diff --git a/json/json_number.e b/json/json_number.e new file mode 100644 index 00000000..0ca65ebb --- /dev/null +++ b/json/json_number.e @@ -0,0 +1,59 @@ +indexing + description: "JSON Numbers, octal and hexadecimal formats are not used." + author: "Javier Velilla" + date: "$Date$" + revision: "$Revision$" + license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + +class + JSON_NUMBER + inherit + JSON_VALUE + rename is_equal as is_equal_json_value + end +create + make_integer, + make_real + +feature -- initialization + make_integer(argument:INTEGER) is + do + value:= argument.out + internal_hash_code:=argument.hash_code + numeric_type:="INTEGER" + end + + make_real(argument:REAL) is + do + value:= argument.out + internal_hash_code:=argument.hash_code + numeric_type:="REAL" + end + + +feature -- Access + to_json:STRING is + -- + do + Result:=value + end + + hash_code:INTEGER is + -- + do + Result:=internal_hash_code + end + + + is_equal (other: like Current): BOOLEAN is + -- Is `other' attached to an object of the same type + -- as current object and identical to it? + do + Result:=value.is_equal(other.to_json) + end + +feature -- Implementation + value:STRING + internal_hash_code:INTEGER + numeric_type:STRING -- REAL or INTEGER +end diff --git a/json/json_object.e b/json/json_object.e new file mode 100644 index 00000000..8de7d8b0 --- /dev/null +++ b/json/json_object.e @@ -0,0 +1,100 @@ +indexing + 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: "$Date$" + revision: "$Revision$" + license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + + +class + JSON_OBJECT + +inherit + JSON_VALUE + +create + make + +feature -- Initialization + make is + -- + do + create object.make (10) + end + +feature -- Change Element + + + put(key:JSON_STRING; value:JSON_VALUE) is + -- + local + l_json_null:JSON_NULL + l_value:JSON_VALUE + do + l_value:=value + if value = void then + create l_json_null + l_value:=l_json_null + end + object.extend(key, l_value) + end + + +feature -- Report + to_json:STRING is + -- Printable json representation + -- {} or {member} + -- see documentation + do + create Result.make_empty + Result.append ("{") + from + object.start + until + object.off + loop + Result.append (object.item_for_iteration.to_json) + Result.append (":") + Result.append (object.key_for_iteration.to_json) + object.forth + if not object.after then + Result.append (",") + end + end + Result.append ("}") + end + + + + hash_code: INTEGER is + -- Hash code value + local + do + from + object.start + Result := object.item_for_iteration.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 + + +feature -- Implementation + object:HASH_TABLE[JSON_STRING,JSON_VALUE] +end diff --git a/json/json_string.e b/json/json_string.e new file mode 100644 index 00000000..583a844c --- /dev/null +++ b/json/json_string.e @@ -0,0 +1,63 @@ +indexing + 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: "$Date$" + revision: "$Revision$" + license:"MIT (see http://www.opensource.org/licenses/mit-license.php)" + +class + JSON_STRING + inherit + JSON_VALUE + rename + is_equal as is_equal_json + end + + create + make_json +feature -- Initialization + make_json(value:STRING) is + -- + do + create buffer.make(256) + buffer.append (value) + end + + +feature -- Access + +feature -- Change Element + append(value:STRING)is + -- + do + buffer.append (value) + end + + +feature -- Status report + to_json:STRING is + -- + do + create Result.make_empty + Result.append ("%"") + Result.append (buffer) + Result.append ("%"") + end + + hash_code:INTEGER is + -- + do + Result:= buffer.hash_code + buffer.count + end + +feature {NONE} -- Implementation + buffer:STRING +invariant + invariant_clause: True -- Your invariant here + +end diff --git a/json/json_value.e b/json/json_value.e new file mode 100644 index 00000000..8b3d255d --- /dev/null +++ b/json/json_value.e @@ -0,0 +1,32 @@ +indexing + 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 + inherit + HASHABLE + +feature -- Access + to_json:STRING is + -- Generate the JSON String for this value object + -- return a correct JSON-STRING + deferred + end + +end diff --git a/json/scanner/json_parser.e b/json/scanner/json_parser.e new file mode 100644 index 00000000..d6dc313d --- /dev/null +++ b/json/scanner/json_parser.e @@ -0,0 +1,258 @@ +indexing + description: "Objects that ..." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + JSON_PARSER + inherit + JSON_READER + JSON_TOKENS + +create + make_parser +feature -- Access + + make_parser(a_json:STRING) is + -- + do + make(a_json) + end + + parse:JSON_VALUE is + -- + local + c:CHARACTER + do + skip_withe_spaces + c:=actual + if c.is_equal (j_object_open) then + Result:=parse_object + elseif c.is_equal (j_string) then + Result:=parse_string + elseif c.is_equal (j_array_open) then + Result:=parse_array + elseif c.is_digit or c.is_equal (j_minus) or + c.is_equal (j_plus) or c.is_equal (j_dot) 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 + + Result:=void + end + rescue + handle_syntax_exception + retry + end + + parse_object:JSON_OBJECT is + -- object + -- {} + -- {"key" : "value" [,]} + + local + has_more:BOOLEAN + l_json_string:JSON_STRING + l_value:JSON_VALUE + do + create Result.make + -- check if is an empty object {} + next + skip_withe_spaces + if actual.is_equal (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_withe_spaces + l_json_string:=parse_string + next + skip_withe_spaces + if actual.is_equal (':') then + next + skip_withe_spaces + else + excpetions.raise("%N Input string is a not well formed JSON, expected: %":%", found:" +actual.out +"%N") + has_more:=false + end + + l_value:=parse + Result.put (l_json_string, l_value) + next + skip_withe_spaces + if actual.is_equal (j_object_close) then + has_more:=false + elseif not actual.is_equal (',') then + has_more:=false + excpetions.raise("JSON Object sintactically malformed expected :%"'%" ") + end + end + end + end + + parse_string:JSON_STRING is + -- + local + has_more:BOOLEAN + l_json_string:STRING + do + create l_json_string.make_empty + if actual.is_equal (j_string) then + from + has_more:=true + until not has_more + + loop + next + if actual.is_equal (j_string) then + has_more:=false + elseif close_tokens.has (actual) then + has_more:=false + excpetions.raise("Input String is not well formed JSON, expected %"") + else + l_json_string.append (actual.out) + end + end + create Result.make_json (l_json_string) + else + Result := void + end + end + + parse_array:JSON_ARRAY is + -- array + -- [] + -- [elements [,]] + local + flag:BOOLEAN + l_value:JSON_VALUE + do + create Result.make_array + --check if is an empty array [] + next + skip_withe_spaces + if actual.is_equal (j_array_close) then + --is an empty array + else + previous + from + flag:=true + until + not flag + loop + next + skip_withe_spaces + l_value := parse + Result.add (l_value) + next + skip_withe_spaces + + if not actual.is_equal (j_array_close) and not actual.is_equal (',')then + flag:=false + excpetions.raise("%NInput string is not well formed JSON, expected: ',' or ']', and found: " +actual.out+"%N") + elseif actual.is_equal (j_array_close) then + flag:= false + end + end + end + end + + parse_number:JSON_NUMBER is + -- + local + sb:STRING + flag:BOOLEAN + do + create sb.make_empty + if not actual.is_equal (j_plus) then + sb.append (actual.out) + end + + from + flag:=true + until not flag + loop + next + if not has_next or close_tokens.has (actual) or actual.is_equal (',') + or actual.is_equal ('%N') or actual.is_equal ('%R') then + flag:=false + previous + else + sb.append (actual.out) + end + end + + if sb.is_double then + create Result.make_real (sb.to_double) + elseif sb.is_integer then + create Result.make_integer (sb.to_integer) + else + excpetions.raise ("Input string is an not well formed JSON") + -- print ("Input string is an not well formed JSON") + end + end + + + is_null:BOOLEAN is + -- + local + l_null:STRING + l_string:STRING + do + l_null:="null" + 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 is + -- + local + l_false:STRING + l_string:STRING + do + l_false:="false" + 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 is + -- + local + l_true:STRING + l_string:STRING + do + l_true:="true" + l_string:=json_substring (index,index + l_true.count - 1) + if l_string.is_equal (l_true) then + Result := true + end + end +feature {NONE} + handle_syntax_exception is + -- + do + next + end + + excpetions:EXCEPTIONS once + create Result + end + +end diff --git a/json/scanner/json_reader.e b/json/scanner/json_reader.e new file mode 100644 index 00000000..2f0521b8 --- /dev/null +++ b/json/scanner/json_reader.e @@ -0,0 +1,97 @@ +indexing + description: "Objects that ..." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + JSON_READER + +create + make +feature -- Access + make(a_json:STRING) is + -- + do + representation:=a_json + index:=1 + end + + read:CHARACTER is + -- + do + if not representation.is_empty then + Result:= representation.item (index) + end + + end + + + actual:CHARACTER is + -- + do + Result:=representation.item (index) + end + + has_next:BOOLEAN is + -- + do + if index <= representation.count then + Result:=True + end + end + + has_previous:BOOLEAN is + -- + do + if index >=1 then + Result:=True + end + end + next is + -- + require + has_more_elements: has_next + do + index:=index + 1 + ensure + incremented: old index + 1 = index + end + + previous is + -- + require + not_is_first: has_previous + do + index:=index - 1 + ensure + incremented: old index - 1 = index + end + + + skip_withe_spaces is + -- Remove withe spaces + do + from + until not actual.is_space and has_next + loop + next + end + end + + json_substring (start_index, end_index: INTEGER_32):STRING is + -- + do + Result:=representation.substring (start_index, end_index) + end + + + + +feature -- Implementation + representation:STRING + --linear representation of the original json string + index:INTEGER + --actual index + +end diff --git a/json/scanner/json_tokens.e b/json/scanner/json_tokens.e new file mode 100644 index 00000000..8bf27ac1 --- /dev/null +++ b/json/scanner/json_tokens.e @@ -0,0 +1,33 @@ +indexing + description: "Objects that ..." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + JSON_TOKENS + +feature -- Access + J_OBJECT_OPEN:CHARACTER is '{' + J_ARRAY_OPEN:CHARACTER is '[' + J_OBJECT_CLOSE:CHARACTER is '}' + J_ARRAY_CLOSE:CHARACTER is ']' + + J_STRING:CHARACTER is '"' + J_PLUS:CHARACTER is '+' + J_MINUS:CHARACTER is '-' + J_DOT:CHARACTER is '.' + + open_tokens:ARRAY[CHARACTER] is + -- Characters wich open a type + once + Result:=<> + end + + close_tokens:ARRAY[CHARACTER] is + -- Characters wich close a type + once + Result:=<> + end + +end