fjson 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +0 -3
- data/Rakefile +43 -41
- data/ext/extensions/array_ext/array_ext.c +13 -81
- data/ext/extensions/array_ext/array_ext.h +4 -8
- data/ext/extensions/array_ext/extconf.mkmf.rb +3 -0
- data/ext/extensions/enumerable/enumerable.c +70 -0
- data/ext/extensions/enumerable/enumerable.h +9 -0
- data/ext/extensions/hash_ext/extconf.mkmf.rb +3 -0
- data/ext/extensions/hash_ext/hash_ext.c +13 -81
- data/ext/extensions/hash_ext/hash_ext.h +3 -8
- data/ext/json_ext/json_ext.c +12 -13
- data/ext/json_ext/json_ext.h +2 -0
- data/ext/state_ext/state_ext.c +16 -85
- data/ext/state_ext/state_ext.h +3 -7
- data/ext/state_ext/state_lib.c +107 -0
- data/ext/state_ext/state_lib.h +15 -0
- data/hash_benchmark.rb +0 -2
- data/hash_benchmark_action_support.rb +4 -0
- data/hash_benchmark_fjson.rb +3 -0
- data/hash_benchmark_json.rb +4 -0
- data/lib/json/editor.rb +1 -1
- data/mkmf_tasks.rb +99 -0
- data/rake_helper.rb +1 -1
- data/spec/array_spec.rb +12 -2
- data/spec/false_class_spec.rb +1 -1
- data/spec/float_spec.rb +1 -1
- data/spec/hash_spec.rb +13 -0
- data/spec/integer_spec.rb +1 -1
- data/spec/mkmf_tasks_spec.rb +110 -0
- data/spec/nil_class_spec.rb +1 -1
- data/spec/object_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -0
- data/spec/spec_suite.rb +3 -8
- data/spec/state_spec.rb +10 -11
- data/spec/string_spec.rb +1 -1
- data/spec/string_when_not_supporting_unicode_and_kcode_is_not_utf8_json_spec.rb +1 -1
- data/spec/string_when_supporting_unicode_and_kcode_is_not_utf8_json_spec.rb +1 -1
- data/spec/string_with_latin1_character_set_json_spec.rb +15 -15
- data/spec/string_with_utf8_values_when_supporting_unicode_json_spec.rb +12 -12
- data/spec/true_class_spec.rb +1 -1
- metadata +58 -53
- data/mkmf_rake_builder.rb +0 -170
- data/spec/mkmf_rake_builder_spec.rb +0 -217
- data/spec/rake_helper_spec.rb +0 -9
@@ -1,13 +1,8 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include <string.h>
|
3
|
-
#include "
|
4
|
-
#include "
|
3
|
+
#include "state_lib.h"
|
4
|
+
#include "enumerable.h"
|
5
5
|
|
6
|
-
static VALUE json_shift(VALUE, VALUE, VALUE, VALUE);
|
7
6
|
static VALUE generate_key_value_json(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
|
8
|
-
static VALUE process_internal_json(VALUE, VALUE, VALUE, VALUE, VALUE);
|
9
7
|
static VALUE json_transform(VALUE, VALUE, VALUE);
|
10
|
-
static VALUE
|
11
|
-
static VALUE json_check_circular_and_transform_ensure(VALUE);
|
12
|
-
static VALUE json_check_circular_and_transform(VALUE, VALUE, VALUE);
|
13
|
-
static VALUE to_json(int, VALUE*, VALUE);
|
8
|
+
static VALUE process_internal_json(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
|
data/ext/json_ext/json_ext.c
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#include "json_ext.h"
|
2
2
|
|
3
|
-
static VALUE mJSON;
|
4
3
|
static VALUE mJSONModuleMethods;
|
5
4
|
static VALUE cStandardError;
|
6
5
|
static VALUE cJSONError;
|
@@ -9,8 +8,8 @@ static VALUE cUnparserError;
|
|
9
8
|
static VALUE cCircularDatastructure;
|
10
9
|
|
11
10
|
void Init_json_ext() {
|
12
|
-
|
13
|
-
mJSONModuleMethods = rb_define_module_under(
|
11
|
+
rb_cJSON = rb_define_module("JSON");
|
12
|
+
mJSONModuleMethods = rb_define_module_under(rb_cJSON, "ModuleMethods");
|
14
13
|
|
15
14
|
_begin_setup_iconv();
|
16
15
|
|
@@ -21,22 +20,22 @@ void Init_json_ext() {
|
|
21
20
|
/**
|
22
21
|
* The base exception for JSON errors.
|
23
22
|
*/
|
24
|
-
cJSONError = rb_define_class_under(
|
23
|
+
cJSONError = rb_define_class_under(rb_cJSON, "JSONError", cStandardError);
|
25
24
|
|
26
25
|
/**
|
27
26
|
* This exception is raise, if a parser error occurs.
|
28
27
|
*/
|
29
|
-
cParserError = rb_define_class_under(
|
28
|
+
cParserError = rb_define_class_under(rb_cJSON, "ParserError", cJSONError);
|
30
29
|
|
31
30
|
/**
|
32
31
|
* This exception is raise, if a unparser error occurs.
|
33
32
|
*/
|
34
|
-
cUnparserError = rb_define_class_under(
|
33
|
+
cUnparserError = rb_define_class_under(rb_cJSON, "UnparserError", cJSONError);
|
35
34
|
|
36
35
|
/**
|
37
36
|
* If a circular data structure is encountered while unparsing this exception is raised.
|
38
37
|
*/
|
39
|
-
cCircularDatastructure = rb_define_class_under(
|
38
|
+
cCircularDatastructure = rb_define_class_under(rb_cJSON, "CircularDatastructure", cUnparserError);
|
40
39
|
}
|
41
40
|
|
42
41
|
/**
|
@@ -45,7 +44,7 @@ void Init_json_ext() {
|
|
45
44
|
static VALUE utf8_to_utf16(self, string)
|
46
45
|
VALUE self, string;
|
47
46
|
{
|
48
|
-
VALUE mUTF8toUTF16 = rb_const_get(
|
47
|
+
VALUE mUTF8toUTF16 = rb_const_get(rb_cJSON, rb_intern("UTF8toUTF16"));
|
49
48
|
VALUE packed_bytes = rb_funcall(mUTF8toUTF16, rb_intern("iconv"), 1, string);
|
50
49
|
VALUE unpacked_bytes = rb_funcall(packed_bytes, rb_intern("unpack"), 1, rb_str_new2("H*"));
|
51
50
|
return rb_ary_entry(unpacked_bytes, 0);
|
@@ -64,7 +63,7 @@ static VALUE utf8_to_json(self, input)
|
|
64
63
|
|
65
64
|
VALUE supports_utf8 = Qfalse;
|
66
65
|
if(
|
67
|
-
rb_funcall(
|
66
|
+
rb_funcall(rb_cJSON, rb_intern("support_unicode?"), 0) == Qtrue &&
|
68
67
|
rb_equal(rb_gv_get("KCODE"), rb_str_new2("UTF8"))
|
69
68
|
) {
|
70
69
|
supports_utf8 = Qtrue;
|
@@ -86,14 +85,14 @@ static void _begin_setup_iconv() {
|
|
86
85
|
|
87
86
|
VALUE mUTF8toUTF16 = rb_funcall(mIconv, rb_intern("new"), 2, rb_str_new2("utf-8"), rb_str_new2("utf-16be"));
|
88
87
|
rb_const_set(
|
89
|
-
|
88
|
+
rb_cJSON,
|
90
89
|
rb_intern("UTF16toUTF8"),
|
91
90
|
mUTF8toUTF16
|
92
91
|
);
|
93
92
|
|
94
93
|
VALUE mUTF16toUTF8 = rb_funcall(mIconv, rb_intern("new"), 2, rb_str_new2("utf-16be"), rb_str_new2("utf-8"));
|
95
94
|
rb_const_set(
|
96
|
-
|
95
|
+
rb_cJSON,
|
97
96
|
rb_intern("UTF8toUTF16"),
|
98
97
|
mUTF16toUTF8
|
99
98
|
);
|
@@ -170,7 +169,7 @@ static long _convert_utf8_char(input, i, result, supports_utf8)
|
|
170
169
|
}
|
171
170
|
else {
|
172
171
|
char* error_message = "Encountered unknown UTF-8 byte: ";
|
173
|
-
error_message
|
172
|
+
append(error_message, c_current);
|
174
173
|
strcat(error_message, "!");
|
175
174
|
rb_raise(rb_eRuntimeError, error_message);
|
176
175
|
}
|
@@ -184,7 +183,7 @@ static VALUE _convert_utf_8_string_part(result, input, i, length)
|
|
184
183
|
{
|
185
184
|
rb_str_cat2(result, "\\u");
|
186
185
|
VALUE utf_header = rb_funcall(input, rb_intern("[]"), 2, LONG2NUM(i), LONG2NUM(length));
|
187
|
-
rb_str_append(result, utf8_to_utf16(
|
186
|
+
rb_str_append(result, utf8_to_utf16(rb_cJSON, utf_header));
|
188
187
|
|
189
188
|
return Qnil;
|
190
189
|
}
|
data/ext/json_ext/json_ext.h
CHANGED
data/ext/state_ext/state_ext.c
CHANGED
@@ -1,61 +1,42 @@
|
|
1
1
|
#include "state_ext.h"
|
2
2
|
|
3
|
-
static VALUE cState;
|
4
|
-
static VALUE mClassMethods;
|
5
|
-
static VALUE mJSON;
|
6
|
-
|
7
3
|
/**
|
8
4
|
* This class is used to create State instances, that are used to hold data
|
9
5
|
* while unparsing a Ruby data structure into a JSON string.
|
10
6
|
*/
|
11
7
|
void Init_state_ext() {
|
12
|
-
mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
|
13
|
-
|
14
|
-
mClassMethods = rb_define_module_under(
|
8
|
+
VALUE mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
|
9
|
+
rb_cJsonState = rb_define_class_under(mJSON, "State", rb_cObject);
|
10
|
+
VALUE mClassMethods = rb_define_module_under(rb_cJsonState, "ClassMethods");
|
15
11
|
|
16
|
-
rb_define_method(mClassMethods, "from_state",
|
17
|
-
rb_extend_object(
|
12
|
+
rb_define_method(mClassMethods, "from_state", rb_json_from_state, 1);
|
13
|
+
rb_extend_object(rb_cJsonState, mClassMethods);
|
18
14
|
|
19
|
-
rb_define_method(
|
20
|
-
rb_define_method(
|
21
|
-
rb_define_method(
|
22
|
-
rb_define_method(
|
15
|
+
rb_define_method(rb_cJsonState, "initialize", initialize, -1);
|
16
|
+
rb_define_method(rb_cJsonState, "seen?", rb_json_state_seen, 1);
|
17
|
+
rb_define_method(rb_cJsonState, "remember", rb_json_state_remember, 1);
|
18
|
+
rb_define_method(rb_cJsonState, "forget", rb_json_state_forget, 1);
|
23
19
|
|
24
20
|
/*
|
25
21
|
* This string is used to indent levels in the JSON string.
|
26
22
|
*/
|
27
|
-
rb_define_method(
|
28
|
-
rb_define_method(
|
23
|
+
rb_define_method(rb_cJsonState, "indent", rb_json_state_get_intent, 0);
|
24
|
+
rb_define_method(rb_cJsonState, "indent=", rb_json_state_set_intent, 1);
|
29
25
|
|
30
26
|
/*
|
31
27
|
* This string is used to include a space between the tokens in a JSON string.
|
32
28
|
*/
|
33
|
-
rb_define_attr(
|
29
|
+
rb_define_attr(rb_cJsonState, "space", 1, 1);
|
34
30
|
|
35
31
|
/*
|
36
32
|
* This string is put at the end of a line that holds a JSON object (or Hash).
|
37
33
|
*/
|
38
|
-
rb_define_attr(
|
34
|
+
rb_define_attr(rb_cJsonState, "object_nl", 1, 1);
|
39
35
|
|
40
36
|
/*
|
41
37
|
* This string is put at the end of a line that holds a JSON array.
|
42
38
|
*/
|
43
|
-
rb_define_attr(
|
44
|
-
}
|
45
|
-
|
46
|
-
void rb_json_state_indent(state, json, depth)
|
47
|
-
VALUE state, json;
|
48
|
-
long depth;
|
49
|
-
{
|
50
|
-
VALUE indent = rb_funcall(state, rb_intern("indent"), 0);
|
51
|
-
char* c_indent = StringValueCStr(indent);
|
52
|
-
// Incrementing the depth
|
53
|
-
char* full_indent;
|
54
|
-
long i;
|
55
|
-
for(i=0; i<depth; i++) {
|
56
|
-
strcat(full_indent, c_indent);
|
57
|
-
}
|
58
|
-
rb_str_cat2(json, full_indent);
|
39
|
+
rb_define_attr(rb_cJsonState, "array_nl", 1, 1);
|
59
40
|
}
|
60
41
|
|
61
42
|
/** Static **/
|
@@ -92,68 +73,18 @@ static VALUE initialize(argc, argv, self)
|
|
92
73
|
rb_ivar_set(self, rb_intern("@seen"), rb_hash_new());
|
93
74
|
}
|
94
75
|
|
95
|
-
static VALUE
|
76
|
+
static VALUE rb_json_state_get_intent(self)
|
96
77
|
VALUE self;
|
97
78
|
{
|
98
79
|
return rb_ivar_get(self, rb_intern("@indent"));
|
99
80
|
}
|
100
81
|
|
101
|
-
static VALUE
|
82
|
+
static VALUE rb_json_state_set_intent(self, indent)
|
102
83
|
VALUE self, indent;
|
103
84
|
{
|
104
85
|
rb_ivar_set(self, rb_intern("@indent"), indent);
|
105
86
|
}
|
106
87
|
|
107
|
-
/**
|
108
|
-
* Creates a State object from _opts_, which ought to be Hash to create a
|
109
|
-
* new State instance configured by opts, something else to create an
|
110
|
-
* unconfigured instance. If _opts_ is a State object, it is just returned.
|
111
|
-
*/
|
112
|
-
static VALUE from_state(self, opts)
|
113
|
-
VALUE self, opts;
|
114
|
-
{
|
115
|
-
if(rb_obj_is_kind_of(opts, cState)) {
|
116
|
-
return opts;
|
117
|
-
}
|
118
|
-
else if(rb_obj_is_kind_of(opts, rb_cHash)) {
|
119
|
-
return rb_funcall(self, rb_intern("new"), 1, opts);
|
120
|
-
}
|
121
|
-
else {
|
122
|
-
return rb_funcall(self, rb_intern("new"), 0);
|
123
|
-
}
|
124
|
-
}
|
125
|
-
|
126
|
-
/**
|
127
|
-
* Returns _true_, if _object_ was already seen during this Unparsing run.
|
128
|
-
*/
|
129
|
-
static VALUE seen(self, object)
|
130
|
-
VALUE self, object;
|
131
|
-
{
|
132
|
-
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
133
|
-
return rb_hash_aref(seen_ivar, rb_obj_id(object));
|
134
|
-
}
|
135
|
-
|
136
|
-
/**
|
137
|
-
* Remember _object_, to find out if it was already encountered (to find out
|
138
|
-
* if a cyclic data structure is unparsed).
|
139
|
-
*/
|
140
|
-
static VALUE remember(self, object)
|
141
|
-
VALUE self, object;
|
142
|
-
{
|
143
|
-
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
144
|
-
rb_hash_aset(seen_ivar, rb_obj_id(object), Qtrue);
|
145
|
-
}
|
146
|
-
|
147
|
-
/**
|
148
|
-
* Forget _object_ for this Unparsing run.
|
149
|
-
*/
|
150
|
-
static VALUE forget(self, object)
|
151
|
-
VALUE self, object;
|
152
|
-
{
|
153
|
-
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
154
|
-
rb_hash_delete(seen_ivar, rb_obj_id(object));
|
155
|
-
}
|
156
|
-
|
157
88
|
/** private **/
|
158
89
|
static VALUE hash_value_or_empty_string_default(hash, cKey)
|
159
90
|
VALUE hash;
|
data/ext/state_ext/state_ext.h
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
#include "ruby.h"
|
2
|
+
#include "state_lib.h"
|
2
3
|
#include <string.h>
|
3
4
|
|
4
5
|
static VALUE initialize(int, VALUE*, VALUE);
|
5
6
|
static VALUE state_allocate(VALUE);
|
6
|
-
static VALUE from_state(VALUE, VALUE);
|
7
7
|
static VALUE hash_value_or_empty_string_default(VALUE, const char*);
|
8
|
-
static VALUE seen(VALUE, VALUE);
|
9
|
-
static VALUE remember(VALUE, VALUE);
|
10
|
-
static VALUE forget(VALUE, VALUE);
|
11
8
|
|
12
|
-
static VALUE
|
13
|
-
static VALUE
|
14
|
-
void rb_json_state_indent(VALUE, VALUE, long);
|
9
|
+
static VALUE rb_json_state_get_intent(VALUE);
|
10
|
+
static VALUE rb_json_state_set_intent(VALUE, VALUE);
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#include "state_lib.h"
|
2
|
+
|
3
|
+
void rb_json_state_indent(state, json, depth)
|
4
|
+
VALUE state, json;
|
5
|
+
long depth;
|
6
|
+
{
|
7
|
+
VALUE indent = rb_json_state_get_intent(state);
|
8
|
+
char* c_indent = StringValueCStr(indent);
|
9
|
+
// Incrementing the depth
|
10
|
+
char* full_indent;
|
11
|
+
long i;
|
12
|
+
for(i=0; i<depth; i++) {
|
13
|
+
strcat(full_indent, c_indent);
|
14
|
+
}
|
15
|
+
rb_str_cat2(json, full_indent);
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE rb_to_json(rb_target, rb_state, rb_indent)
|
19
|
+
VALUE rb_target, rb_state, rb_indent;
|
20
|
+
{
|
21
|
+
VALUE args = rb_ary_new2(3);
|
22
|
+
rb_ary_store (args, 0, rb_target);
|
23
|
+
rb_ary_store (args, 1, rb_state);
|
24
|
+
rb_ary_store (args, 2, rb_indent);
|
25
|
+
return rb_rescue(call_to_json, args, to_json_exception, rb_target);
|
26
|
+
}
|
27
|
+
|
28
|
+
VALUE rb_json_should_shift(state, object_nl)
|
29
|
+
VALUE state, object_nl;
|
30
|
+
{
|
31
|
+
if(state == Qnil) return Qfalse;
|
32
|
+
if(RSTRING(object_nl)->len == 0) return Qfalse;
|
33
|
+
return Qtrue;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Creates a State object from _opts_, which ought to be Hash to create a
|
38
|
+
* new State instance configured by opts, something else to create an
|
39
|
+
* unconfigured instance. If _opts_ is a State object, it is just returned.
|
40
|
+
*/
|
41
|
+
VALUE rb_json_from_state(self, opts)
|
42
|
+
VALUE self, opts;
|
43
|
+
{
|
44
|
+
if(rb_obj_is_kind_of(opts, rb_cJsonState)) {
|
45
|
+
return opts;
|
46
|
+
}
|
47
|
+
else if(rb_obj_is_kind_of(opts, rb_cHash)) {
|
48
|
+
return rb_funcall(self, rb_intern("new"), 1, opts);
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
return rb_funcall(self, rb_intern("new"), 0);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Returns _true_, if _object_ was already seen during this Unparsing run.
|
57
|
+
*/
|
58
|
+
VALUE rb_json_state_seen(self, object)
|
59
|
+
VALUE self, object;
|
60
|
+
{
|
61
|
+
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
62
|
+
return rb_hash_aref(seen_ivar, rb_obj_id(object));
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Remember _object_, to find out if it was already encountered (to find out
|
67
|
+
* if a cyclic data structure is unparsed).
|
68
|
+
*/
|
69
|
+
VALUE rb_json_state_remember(self, object)
|
70
|
+
VALUE self, object;
|
71
|
+
{
|
72
|
+
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
73
|
+
rb_hash_aset(seen_ivar, rb_obj_id(object), Qtrue);
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Forget _object_ for this Unparsing run.
|
78
|
+
*/
|
79
|
+
VALUE rb_json_state_forget(self, object)
|
80
|
+
VALUE self, object;
|
81
|
+
{
|
82
|
+
VALUE seen_ivar = rb_ivar_get(self, rb_intern("@seen"));
|
83
|
+
rb_hash_delete(seen_ivar, rb_obj_id(object));
|
84
|
+
}
|
85
|
+
|
86
|
+
/** Static **/
|
87
|
+
|
88
|
+
static VALUE call_to_json(args)
|
89
|
+
VALUE args;
|
90
|
+
{
|
91
|
+
VALUE rb_target = rb_ary_entry(args, 0);
|
92
|
+
VALUE rb_state = rb_ary_entry(args, 1);
|
93
|
+
VALUE rb_indent = rb_ary_entry(args, 2);
|
94
|
+
return rb_funcall(rb_target, rb_intern("to_json"), 2, rb_state, rb_indent);
|
95
|
+
}
|
96
|
+
|
97
|
+
static VALUE to_json_exception(rb_target, rb_error)
|
98
|
+
VALUE rb_target, rb_error;
|
99
|
+
{
|
100
|
+
VALUE rb_error_class = rb_obj_class(rb_error);
|
101
|
+
if(rb_error_class == rb_eArgError) {
|
102
|
+
return rb_funcall(rb_target, rb_intern("to_json"), 0);
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
rb_exc_raise(rb_error);
|
106
|
+
}
|
107
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include <string.h>
|
3
|
+
|
4
|
+
VALUE rb_json_from_state(VALUE, VALUE);
|
5
|
+
VALUE rb_json_state_seen(VALUE, VALUE);
|
6
|
+
VALUE rb_json_state_remember(VALUE, VALUE);
|
7
|
+
VALUE rb_json_state_forget(VALUE, VALUE);
|
8
|
+
VALUE rb_json_should_shift(VALUE, VALUE);
|
9
|
+
VALUE rb_to_json(VALUE, VALUE, VALUE);
|
10
|
+
void rb_json_state_indent(VALUE, VALUE, long);
|
11
|
+
|
12
|
+
static VALUE call_to_json(VALUE);
|
13
|
+
static VALUE to_json_exception(VALUE, VALUE);
|
14
|
+
|
15
|
+
VALUE rb_cJsonState;
|
data/hash_benchmark.rb
CHANGED
data/lib/json/editor.rb
CHANGED
data/mkmf_tasks.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
class MkmfTasks
|
2
|
+
attr_writer :extconf_file_name,
|
3
|
+
:project_dir,
|
4
|
+
:file_extension,
|
5
|
+
:extension_paths,
|
6
|
+
:extconf_arguments
|
7
|
+
|
8
|
+
def initialize(actor)
|
9
|
+
@actor = actor
|
10
|
+
end
|
11
|
+
|
12
|
+
def default
|
13
|
+
compile
|
14
|
+
end
|
15
|
+
|
16
|
+
def compile
|
17
|
+
@extension_paths.each do |extension|
|
18
|
+
dir = "ext/#{extension}"
|
19
|
+
extconf dir
|
20
|
+
make dir
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def spec
|
25
|
+
compile
|
26
|
+
install
|
27
|
+
dir = @project_dir
|
28
|
+
require File.expand_path("#{dir}/spec/spec_suite")
|
29
|
+
end
|
30
|
+
|
31
|
+
def lib
|
32
|
+
directory "lib"
|
33
|
+
end
|
34
|
+
|
35
|
+
def install
|
36
|
+
@extension_paths.each do |extension_path|
|
37
|
+
build_path = build_path(extension_path)
|
38
|
+
raise "File #{build_path} does not exist" unless File.exists?(build_path)
|
39
|
+
cp build_path, library_path(extension_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def cleanup
|
44
|
+
@extension_paths.each do |extension_path|
|
45
|
+
library_path = library_path(extension_path)
|
46
|
+
rm library_path if library_path && File.exists?(library_path)
|
47
|
+
|
48
|
+
build_file_path = build_path(extension_path)
|
49
|
+
rm build_file_path if build_file_path && File.exists?(build_file_path)
|
50
|
+
|
51
|
+
build_object_path = "#{build_path_without_file_extension(extension_path)}.o"
|
52
|
+
rm build_object_path if build_object_path && File.exists?(build_object_path)
|
53
|
+
|
54
|
+
build_dir = build_dir(extension_path)
|
55
|
+
make_file_path = "#{build_dir}/Makefile"
|
56
|
+
rm make_file_path if make_file_path && File.exists?(make_file_path)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def extconf(dir)
|
62
|
+
Dir.chdir(dir) do
|
63
|
+
sh("ruby #{@extconf_arguments} #{@extconf_file_name}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def make(makedir)
|
68
|
+
Dir.chdir(makedir) do
|
69
|
+
sh("make")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_dir(relative_extension_path)
|
74
|
+
"#{@project_dir}/ext/#{relative_extension_path}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def build_path(relative_extension_path)
|
78
|
+
basename = build_path_without_file_extension(relative_extension_path)
|
79
|
+
"#{basename}.#{@file_extension}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_path_without_file_extension(relative_extension_path)
|
83
|
+
"#{build_dir(relative_extension_path)}/#{File.basename(relative_extension_path)}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def library_path(relative_extension_path)
|
87
|
+
library_directory_path = File.expand_path("#{@project_dir}/lib/#{File.dirname(relative_extension_path)}")
|
88
|
+
binary_name = "#{File.basename(relative_extension_path)}.#{@file_extension}"
|
89
|
+
"#{library_directory_path}/#{binary_name}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def rm(path)
|
93
|
+
@actor.__send__ :rm, path
|
94
|
+
end
|
95
|
+
|
96
|
+
def sh(cmd)
|
97
|
+
@actor.__send__ :sh, cmd
|
98
|
+
end
|
99
|
+
end
|