fjson 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/CHANGES +5 -5
  2. data/README +7 -8
  3. data/Rakefile +56 -17
  4. data/TODO +1 -0
  5. data/ext/extensions/array_ext/array_ext.c +118 -0
  6. data/ext/extensions/array_ext/array_ext.h +12 -0
  7. data/ext/extensions/array_ext/extconf.rb +7 -0
  8. data/ext/extensions/false_class_ext/extconf.rb +5 -0
  9. data/ext/extensions/false_class_ext/false_class_ext.c +19 -0
  10. data/ext/extensions/false_class_ext/false_class_ext.h +4 -0
  11. data/ext/extensions/float_ext/extconf.rb +5 -0
  12. data/ext/extensions/float_ext/float_ext.c +19 -0
  13. data/ext/extensions/float_ext/float_ext.h +4 -0
  14. data/ext/extensions/hash_ext/extconf.rb +7 -0
  15. data/ext/extensions/hash_ext/hash_ext.c +128 -0
  16. data/ext/extensions/hash_ext/hash_ext.h +13 -0
  17. data/ext/extensions/integer_ext/extconf.rb +5 -0
  18. data/ext/extensions/integer_ext/integer_ext.c +19 -0
  19. data/ext/extensions/integer_ext/integer_ext.h +4 -0
  20. data/ext/extensions/nil_class_ext/extconf.rb +5 -0
  21. data/ext/extensions/nil_class_ext/nil_class_ext.c +19 -0
  22. data/ext/extensions/nil_class_ext/nil_class_ext.h +4 -0
  23. data/ext/extensions/object_ext/extconf.rb +5 -0
  24. data/ext/extensions/object_ext/object_ext.c +21 -0
  25. data/ext/extensions/object_ext/object_ext.h +4 -0
  26. data/ext/extensions/string_ext/extconf.rb +5 -0
  27. data/ext/extensions/string_ext/string_ext.c +27 -0
  28. data/ext/extensions/string_ext/string_ext.h +4 -0
  29. data/ext/extensions/true_class_ext/extconf.rb +5 -0
  30. data/ext/extensions/true_class_ext/true_class_ext.c +19 -0
  31. data/ext/extensions/true_class_ext/true_class_ext.h +4 -0
  32. data/ext/json_ext/extconf.rb +5 -0
  33. data/ext/json_ext/json_ext.c +180 -0
  34. data/ext/json_ext/json_ext.h +9 -0
  35. data/ext/state_ext/extconf.rb +5 -0
  36. data/ext/state_ext/state_ext.c +169 -0
  37. data/ext/state_ext/state_ext.h +14 -0
  38. data/hash_benchmark.rb +15 -0
  39. data/install.rb +21 -0
  40. data/rake_helper.rb +34 -0
  41. metadata +52 -20
  42. data/VERSION +0 -1
  43. data/lib/extensions/array_ext.so +0 -0
  44. data/lib/extensions/false_class_ext.so +0 -0
  45. data/lib/extensions/float_ext.so +0 -0
  46. data/lib/extensions/hash_ext.so +0 -0
  47. data/lib/extensions/integer_ext.so +0 -0
  48. data/lib/extensions/nil_class_ext.so +0 -0
  49. data/lib/extensions/object_ext.so +0 -0
  50. data/lib/extensions/string_ext.so +0 -0
  51. data/lib/extensions/true_class_ext.so +0 -0
  52. data/lib/json_ext.so +0 -0
  53. data/lib/state_ext.so +0 -0
data/CHANGES CHANGED
@@ -1,5 +1,5 @@
1
- 2006-02-06 (0.4.1)
2
- * Fixed a bug concerning escaping with backslashes. Thanks for the report go
3
- to Florian Munz <surf@theflow.de>.
4
- 2005-09-23 (0.4.0)
5
- * Initial Rubyforge Version
1
+ 2006-10-16 (0.0.2)
2
+ * Gem now compiles the extension rather than just distribute the binary.
3
+
4
+ 2006-10-10 (0.0.1)
5
+ * Initial Rubyforge Version. Forked from ruby json library. http://json.rubyforge.org
data/README CHANGED
@@ -1,19 +1,19 @@
1
+ Project Site - http://fjson.rubyforge.org
2
+ Rubyforge Project - http://rubyforge.org/projects/fjson
3
+
1
4
  Installation
2
5
  ============
3
6
 
4
- Just type into the command line as root:
7
+ Install Fast Json as a gem.
5
8
 
6
- # ruby install.rb
9
+ gem install fjson
7
10
 
8
11
  Testing and Examples
9
12
  ====================
10
13
 
11
- To run the tests type:
12
-
13
- $ ruby -I lib tests/runner.rb
14
+ To run the specs type:
14
15
 
15
- To get an idea how this library is used also look at the tests (until I have
16
- time to better document it.)
16
+ $ ruby spec/spec_suite.rb
17
17
 
18
18
  Author
19
19
  ======
@@ -25,4 +25,3 @@ License
25
25
  =======
26
26
 
27
27
  GNU General Public License (GPL)
28
-
data/Rakefile CHANGED
@@ -7,7 +7,10 @@ require 'rake/testtask'
7
7
  require 'rake/rdoctask'
8
8
 
9
9
 
10
- task :default => [
10
+ task :default => [ :compile ] do
11
+ end
12
+
13
+ task :compile => [
11
14
  :json_ext,
12
15
  :state_ext,
13
16
  :object_ext,
@@ -18,12 +21,11 @@ task :default => [
18
21
  :false_class_ext,
19
22
  :nil_class_ext,
20
23
  :array_ext,
21
- :hash_ext,
22
- :spec
24
+ :hash_ext
23
25
  ] do
24
26
  end
25
27
 
26
- task :spec do
28
+ task :spec => [:compile, :install] do
27
29
  require File.expand_path("#{dir}/spec/spec_suite")
28
30
  end
29
31
 
@@ -31,25 +33,57 @@ task :lib do
31
33
  directory "lib"
32
34
  end
33
35
 
34
- setup_extension("json_ext")
35
- setup_extension("state_ext")
36
- setup_extension("extensions/object_ext")
37
- setup_extension("extensions/integer_ext")
38
- setup_extension("extensions/float_ext")
39
- setup_extension("extensions/string_ext")
40
- setup_extension("extensions/true_class_ext")
41
- setup_extension("extensions/false_class_ext")
42
- setup_extension("extensions/nil_class_ext")
43
- setup_extension("extensions/array_ext")
44
- setup_extension("extensions/hash_ext")
36
+ fjson_extensions = [
37
+ "json_ext",
38
+ "state_ext",
39
+ "extensions/object_ext",
40
+ "extensions/integer_ext",
41
+ "extensions/float_ext",
42
+ "extensions/string_ext",
43
+ "extensions/true_class_ext",
44
+ "extensions/false_class_ext",
45
+ "extensions/nil_class_ext",
46
+ "extensions/array_ext",
47
+ "extensions/hash_ext"
48
+ ]
49
+
50
+ fjson_extensions.each do |ext|
51
+ setup_extension ext
52
+ end
53
+
54
+ task :install do
55
+ dir = File.dirname(__FILE__)
56
+ fjson_extensions.each do |extension_path|
57
+ cp extension_binary_path(extension_path), "#{dir}/lib/#{extension_path}"
58
+ end
59
+ end
60
+
61
+ task :cleanup do
62
+ fjson_extensions.each do |extension_path|
63
+ rm extension_binary_path(extension_path)
64
+ rm "#{extension_directory_path(extension_path)}/Rakefile"
65
+ end
66
+ end
67
+
68
+ def extension_binary_path(relative_extension_path)
69
+ binary_name = File.basename(relative_extension_path) + ".so"
70
+ directory = extension_directory_path(relative_extension_path)
71
+ "#{directory}/#{binary_name}"
72
+ end
73
+
74
+ def extension_directory_path(relative_extension_path)
75
+ base_extension_path = File.dirname(__FILE__) + "/ext"
76
+ "#{base_extension_path}/#{relative_extension_path}"
77
+ end
45
78
 
46
79
  PKG_NAME = "fjson"
47
- PKG_VERSION = "0.0.1"
80
+ PKG_VERSION = "0.0.2"
48
81
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
49
82
  PKG_FILES = FileList[
50
83
  '[A-Z]*',
84
+ '*.rb',
51
85
  'lib/**/*.rb',
52
- 'lib/**/*.so',
86
+ 'ext/**/*.{h,c,rb}',
53
87
  'spec/**/*.rb'
54
88
  ]
55
89
 
@@ -67,6 +101,7 @@ spec = Gem::Specification.new do |s|
67
101
  s.require_path = 'lib'
68
102
 
69
103
  s.has_rdoc = true
104
+ s.extra_rdoc_files = [ "README" ]
70
105
 
71
106
  s.test_files = Dir.glob('spec/*_spec.rb')
72
107
  s.require_path = 'lib'
@@ -75,6 +110,10 @@ spec = Gem::Specification.new do |s|
75
110
  s.email = "brian.takita@gmail.com"
76
111
  s.homepage = "http://fjson.rubyforge.org"
77
112
  s.rubyforge_project = "fjson"
113
+
114
+ s.extensions = ["Rakefile"]
115
+
116
+ s.add_dependency "mkrf", ">=0.1.2"
78
117
  end
79
118
 
80
119
  Rake::GemPackageTask.new(spec) do |pkg|
data/TODO CHANGED
@@ -0,0 +1 @@
1
+ * Port the library to windows.
@@ -0,0 +1,118 @@
1
+ #include "array_ext.h"
2
+
3
+ static VALUE cArray;
4
+ static VALUE mJSON;
5
+ static VALUE cState;
6
+ static VALUE cCircularDatastructure;
7
+
8
+ void Init_array_ext() {
9
+ mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
10
+ cState = rb_const_get(mJSON, rb_intern("State"));
11
+ cArray = rb_const_get(rb_cObject, rb_intern("Array"));
12
+ cCircularDatastructure = rb_const_get(mJSON, rb_intern("CircularDatastructure"));
13
+ rb_define_method(cArray, "to_json", (VALUE(*)(ANYARGS)) &to_json, -1);
14
+ }
15
+
16
+ /**
17
+ * Returns a JSON string containing a JSON array, that is unparsed from
18
+ * this Array instance.
19
+ * _state_ is a JSON::State object, that can also be used to configure the
20
+ * produced JSON string output further.
21
+ * _depth_ is used to find out nesting depth, to indent accordingly.
22
+ */
23
+ static VALUE to_json(argc, argv, self)
24
+ int argc;
25
+ VALUE *argv;
26
+ VALUE self;
27
+ {
28
+ VALUE state, depth;
29
+ rb_scan_args(argc, argv, "02", &state, &depth);
30
+ if(depth == Qnil) depth = rb_int2inum(0);
31
+
32
+ state = rb_funcall(cState, rb_intern("from_state"), 1, state);
33
+ return json_check_circular_and_transform(self, state, depth);
34
+ }
35
+
36
+ /** Private **/
37
+
38
+ static VALUE json_check_circular_and_transform(self, state, depth)
39
+ VALUE self, state, depth;
40
+ {
41
+ VALUE call_args = rb_ary_new3(3, self, state, depth);
42
+ return rb_ensure(json_check_circular_and_transform_call, call_args, json_check_circular_and_transform_ensure, call_args);
43
+ }
44
+
45
+ static VALUE json_check_circular_and_transform_call(args)
46
+ VALUE args;
47
+ {
48
+ VALUE self = rb_ary_entry(args, 0);
49
+ VALUE state = rb_ary_entry(args, 1);
50
+ VALUE depth = rb_ary_entry(args, 2);
51
+ if(state != Qnil) {
52
+ if(rb_funcall(state, rb_intern("seen?"), 1, self) == Qtrue) {
53
+ rb_raise(
54
+ cCircularDatastructure,
55
+ "circular data structures not supported!"
56
+ );
57
+ }
58
+ rb_funcall(state, rb_intern("remember"), 1, self);
59
+ }
60
+ return json_transform(self, state, depth);
61
+ }
62
+
63
+ static VALUE json_check_circular_and_transform_ensure(args)
64
+ VALUE args;
65
+ {
66
+ VALUE self = rb_ary_entry(args, 0);
67
+ VALUE state = rb_ary_entry(args, 1);
68
+ if(state != Qnil) {
69
+ rb_funcall(state, rb_intern("forget"), 1, self);
70
+ }
71
+ }
72
+
73
+ static VALUE json_transform(self, state, depth)
74
+ VALUE self, state, depth;
75
+ {
76
+ VALUE delim = rb_str_new2(",");
77
+ VALUE array_nl = Qnil;
78
+ if(state != Qnil) array_nl = rb_funcall(state, rb_intern("array_nl"), 0);
79
+ if(array_nl != Qnil) rb_str_append(delim, array_nl);
80
+
81
+ VALUE json = rb_str_new2("[");
82
+ if(array_nl != Qnil) rb_str_append(json, array_nl);
83
+
84
+ process_internal_json(self, json, state, depth, delim);
85
+
86
+ if(array_nl != Qnil) rb_str_append(json, array_nl);
87
+ json_shift(self, json, state, depth);
88
+ rb_str_cat2(json, "]");
89
+ return json;
90
+ }
91
+
92
+ static VALUE process_internal_json(self, json, state, depth, delim)
93
+ VALUE self, json, state, depth, delim;
94
+ {
95
+ VALUE next_depth = LONG2NUM(NUM2LONG(depth) + 1);
96
+
97
+ VALUE current_value;
98
+ int i;
99
+ for(i = 0; i < RARRAY(self)->len; i++) {
100
+ if(i > 0) {
101
+ rb_str_concat(json, delim);
102
+ }
103
+ current_value = rb_ary_entry(self, i);
104
+ json_shift(self, json, state, depth);
105
+ rb_str_append(json, rb_funcall(current_value, rb_intern("to_json"), 2, state, next_depth));
106
+ }
107
+ }
108
+
109
+ static VALUE json_shift(self, json, state, depth)
110
+ VALUE self, json, state, depth;
111
+ {
112
+ if(state == Qnil) return Qnil;
113
+ VALUE array_nl = rb_funcall(state, rb_intern("array_nl"), 0);
114
+ if(RSTRING(array_nl)->len == 0) return Qnil;
115
+
116
+ rb_json_state_indent(state, json, NUM2LONG(depth) + 1);
117
+ return Qnil;
118
+ }
@@ -0,0 +1,12 @@
1
+ #include "ruby.h"
2
+ #include <string.h>
3
+ #include "../../state_ext/state_ext.h"
4
+ #include "../../state_ext/state_ext.c"
5
+
6
+ static VALUE to_json(int, VALUE*, VALUE);
7
+ static VALUE json_check_circular_and_transform_call(VALUE);
8
+ static VALUE json_check_circular_and_transform_ensure(VALUE);
9
+ static VALUE json_check_circular_and_transform(VALUE, VALUE, VALUE);
10
+ static VALUE json_transform(VALUE, VALUE, VALUE);
11
+ static VALUE json_shift(VALUE, VALUE, VALUE, VALUE);
12
+ static VALUE process_internal_json(VALUE, VALUE, VALUE, VALUE, VALUE);
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'mkrf'
3
+
4
+ dir = File.dirname(__FILE__)
5
+ Mkrf::Generator.new('array_ext', "#{dir}/*.c") do |g|
6
+ g.include_header File.expand_path("#{dir}/../../state_ext/state_ext.h")
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'mkrf'
3
+
4
+ dir = File.dirname(__FILE__)
5
+ Mkrf::Generator.new('false_class_ext', "#{dir}/*.c")
@@ -0,0 +1,19 @@
1
+ #include "false_class_ext.h"
2
+
3
+ static VALUE cFalseClass;
4
+
5
+ void Init_false_class_ext() {
6
+ cFalseClass = rb_const_get(rb_cObject, rb_intern("FalseClass"));
7
+ rb_define_method(cFalseClass, "to_json", (VALUE(*)(ANYARGS)) &to_json, -1);
8
+ }
9
+
10
+ /**
11
+ * Returns a JSON string for false: 'false'.
12
+ */
13
+ static VALUE to_json(argc, argv, self)
14
+ int argc;
15
+ VALUE *argv;
16
+ VALUE self;
17
+ {
18
+ return rb_funcall(self, rb_intern("to_s"), 0);
19
+ }
@@ -0,0 +1,4 @@
1
+ #include "ruby.h"
2
+ #include <string.h>
3
+
4
+ static VALUE to_json(int, VALUE*, VALUE);
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'mkrf'
3
+
4
+ dir = File.dirname(__FILE__)
5
+ Mkrf::Generator.new('float_ext', "#{dir}/*.c")
@@ -0,0 +1,19 @@
1
+ #include "float_ext.h"
2
+
3
+ static VALUE cFloat;
4
+
5
+ void Init_float_ext() {
6
+ cFloat = rb_const_get(rb_cObject, rb_intern("Float"));
7
+ rb_define_method(cFloat, "to_json", (VALUE(*)(ANYARGS)) &to_json, -1);
8
+ }
9
+
10
+ /**
11
+ * Returns a JSON string representation for this Float number.
12
+ */
13
+ static VALUE to_json(argc, argv, self)
14
+ int argc;
15
+ VALUE *argv;
16
+ VALUE self;
17
+ {
18
+ return rb_funcall(self, rb_intern("to_s"), 0);
19
+ }
@@ -0,0 +1,4 @@
1
+ #include "ruby.h"
2
+ #include <string.h>
3
+
4
+ static VALUE to_json(int, VALUE*, VALUE);
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'mkrf'
3
+
4
+ dir = File.dirname(__FILE__)
5
+ Mkrf::Generator.new('hash_ext', "#{dir}/*.c") do |g|
6
+ g.include_header File.expand_path("#{dir}/../../state_ext")
7
+ end
@@ -0,0 +1,128 @@
1
+ #include "hash_ext.h"
2
+
3
+ static VALUE cHash;
4
+ static VALUE mJSON;
5
+ static VALUE cState;
6
+ static VALUE cCircularDatastructure;
7
+
8
+ void Init_hash_ext() {
9
+ mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
10
+ cState = rb_const_get(mJSON, rb_intern("State"));
11
+ cHash = rb_const_get(rb_cObject, rb_intern("Hash"));
12
+ cCircularDatastructure = rb_const_get(mJSON, rb_intern("CircularDatastructure"));
13
+ rb_define_method(cHash, "to_json", (VALUE(*)(ANYARGS)) &to_json, -1);
14
+ }
15
+
16
+ /**
17
+ * Returns a JSON string containing a JSON hash, that is unparsed from
18
+ * this Hash instance.
19
+ * _state_ is a JSON::State object, that can also be used to configure the
20
+ * produced JSON string output further.
21
+ * _depth_ is used to find out nesting depth, to indent accordingly.
22
+ */
23
+ static VALUE to_json(argc, argv, self)
24
+ int argc;
25
+ VALUE *argv;
26
+ VALUE self;
27
+ {
28
+ VALUE state, depth;
29
+ rb_scan_args(argc, argv, "02", &state, &depth);
30
+ if(depth == Qnil) depth = INT2NUM(0);
31
+
32
+ state = rb_funcall(cState, rb_intern("from_state"), 1, state);
33
+ return json_check_circular_and_transform(self, state, depth);
34
+ }
35
+
36
+ /** private **/
37
+
38
+ static VALUE json_check_circular_and_transform(self, state, depth)
39
+ VALUE self, state, depth;
40
+ {
41
+ VALUE call_args = rb_ary_new3(3, self, state, depth);
42
+ return rb_ensure(json_check_circular_and_transform_call, call_args, json_check_circular_and_transform_ensure, call_args);
43
+ }
44
+
45
+ static VALUE json_check_circular_and_transform_ensure(args)
46
+ VALUE args;
47
+ {
48
+ VALUE self = rb_ary_entry(args, 0);
49
+ VALUE state = rb_ary_entry(args, 1);
50
+ if(state != Qnil) {
51
+ rb_funcall(state, rb_intern("forget"), 1, self);
52
+ }
53
+ }
54
+
55
+ static VALUE json_check_circular_and_transform_call(args)
56
+ VALUE args;
57
+ {
58
+ VALUE self = rb_ary_entry(args, 0);
59
+ VALUE state = rb_ary_entry(args, 1);
60
+ VALUE depth = rb_ary_entry(args, 2);
61
+ if(state != Qnil) {
62
+ if(rb_funcall(state, rb_intern("seen?"), 1, self) == Qtrue) {
63
+ rb_raise(
64
+ cCircularDatastructure,
65
+ "circular data structures not supported!"
66
+ );
67
+ }
68
+ rb_funcall(state, rb_intern("remember"), 1, self);
69
+ }
70
+ return json_transform(self, state, depth);
71
+ }
72
+
73
+ static VALUE json_transform(self, state, depth)
74
+ VALUE self, state, depth;
75
+ {
76
+ VALUE delim = rb_str_new2(",");
77
+ VALUE object_nl = Qnil;
78
+ if(state != Qnil) object_nl = rb_funcall(state, rb_intern("object_nl"), 0);
79
+ if(object_nl != Qnil) rb_str_append(delim, object_nl);
80
+
81
+ VALUE result = rb_str_new2("{");
82
+ if(object_nl != Qnil) rb_str_append(result, object_nl);
83
+
84
+ process_internal_json(self, result, state, depth, delim);
85
+
86
+ if(object_nl != Qnil) rb_str_append(result, object_nl);
87
+ json_shift(self, result, state, depth);
88
+ rb_str_append(result, rb_str_new2("}"));
89
+ return result;
90
+ }
91
+
92
+ static VALUE process_internal_json(self, json, state, depth, delim)
93
+ VALUE self, json, state, depth, delim;
94
+ {
95
+ // TODO: Use st_foreach for even better performance
96
+ VALUE key_value_pairs = rb_funcall(self, rb_intern("to_a"), 0);
97
+ VALUE new_depth = LONG2NUM(NUM2LONG(depth) + 1);
98
+ VALUE space = rb_funcall(state, rb_intern("space"), 0);
99
+
100
+ VALUE key_value = Qnil;
101
+ int i;
102
+ for(i = 0; i < RARRAY(key_value_pairs)->len; i++) {
103
+ if(i > 0) {
104
+ rb_str_concat(json, delim);
105
+ }
106
+ key_value = rb_ary_entry(key_value_pairs, i);
107
+ VALUE key = rb_ary_entry(key_value, 0);
108
+ VALUE value = rb_ary_entry(key_value, 1);
109
+
110
+ json_shift(self, json, state, depth);
111
+ VALUE key_string = rb_funcall(key, rb_intern("to_s"), 0);
112
+ rb_str_append(json, rb_funcall(key_string, rb_intern("to_json"), 2, state, new_depth));
113
+ rb_str_cat2(json, ":");
114
+ rb_str_append(json, space);
115
+ rb_str_append(json, rb_funcall(value, rb_intern("to_json"), 2, state, new_depth));
116
+ }
117
+ }
118
+
119
+ static VALUE json_shift(self, json, state, depth)
120
+ VALUE self, json, state, depth;
121
+ {
122
+ if(state == Qnil) return Qnil;
123
+ VALUE object_nl = rb_funcall(state, rb_intern("object_nl"), 0);
124
+ if(RSTRING(object_nl)->len == 0) return Qnil;
125
+
126
+ rb_json_state_indent(state, json, NUM2LONG(depth) + 1);
127
+ return Qnil;
128
+ }