fjson 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }