utilrb 0.2.3 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes.txt +24 -0
- data/Manifest.txt +7 -3
- data/Rakefile +24 -1
- data/ext/faster.cc +57 -0
- data/ext/ruby_internals.h +72 -0
- data/ext/swap.cc +1 -35
- data/ext/value_set.cc +50 -11
- data/lib/utilrb/array/to_s.rb +2 -2
- data/lib/utilrb/common.rb +1 -1
- data/lib/utilrb/enumerable/sequence.rb +11 -3
- data/lib/utilrb/exception/full_message.rb +35 -3
- data/lib/utilrb/module/ancestor_p.rb +21 -2
- data/lib/utilrb/module/attr_predicate.rb +17 -0
- data/lib/utilrb/pkgconfig.rb +48 -0
- data/lib/utilrb/time/to_hms.rb +3 -3
- data/lib/utilrb/value_set.rb +18 -2
- data/test/data/test_pkgconfig.pc +9 -0
- data/test/test_enumerable.rb +12 -1
- data/test/test_exception.rb +38 -0
- data/test/test_module.rb +20 -0
- data/test/test_object.rb +19 -0
- data/test/test_pkgconfig.rb +35 -0
- data/test/test_proc.rb +28 -0
- metadata +14 -7
- data/lib/utilrb/queue/get.rb +0 -22
- data/lib/utilrb/queue.rb +0 -2
- data/patches/fastthread-queue-get.patch +0 -72
data/Changes.txt
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
=== Version 1.0
|
2
|
+
Bumped version number because of incompatible changes. Make it 1.0 since
|
3
|
+
having 0. version numbers for this kind of library is completely meaningless
|
4
|
+
|
5
|
+
* incompatible changes:
|
6
|
+
- Enumerable#+ acts on too many objects. Define it only on Enumerable::Enumerator
|
7
|
+
- remove automatic convertion into ValueSet for methods which were doing it
|
8
|
+
- removed Queue#get: fastthread is now the preferred threading library in
|
9
|
+
Ruby 1.8.6, so Queue#get cannot be implemented anymore
|
10
|
+
|
11
|
+
* new features:
|
12
|
+
- PkgConfig class
|
13
|
+
- define Proc#same_body?, Proc#file and Proc#line
|
14
|
+
- Module#attr_predicate
|
15
|
+
- 'since', 'until' and block parameters for Exception#full_message
|
16
|
+
- ValueSet#intersects? (more efficient than checking that the intersection
|
17
|
+
is empty)
|
18
|
+
|
19
|
+
* changes and fixes:
|
20
|
+
- properly handle singleton classes in has_ancestor?
|
21
|
+
- properly handle recursion in ValueSet#to_s and Array#to_s
|
22
|
+
- add the 'setup' task on the Rakefile to build the C extension
|
23
|
+
- make Module#has_ancestor? work event if the C extension is not built
|
24
|
+
|
1
25
|
=== Version 0.2.3
|
2
26
|
|
3
27
|
* new features:
|
data/Manifest.txt
CHANGED
@@ -7,6 +7,7 @@ bm/allocation.rb
|
|
7
7
|
bm/speed.rb
|
8
8
|
ext/extconf.rb
|
9
9
|
ext/faster.cc
|
10
|
+
ext/ruby_internals.h
|
10
11
|
ext/swap.cc
|
11
12
|
ext/value_set.cc
|
12
13
|
lib/utilrb.rb
|
@@ -38,6 +39,7 @@ lib/utilrb/logger/hierarchy.rb
|
|
38
39
|
lib/utilrb/module.rb
|
39
40
|
lib/utilrb/module/ancestor_p.rb
|
40
41
|
lib/utilrb/module/attr_enumerable.rb
|
42
|
+
lib/utilrb/module/attr_predicate.rb
|
41
43
|
lib/utilrb/module/define_method.rb
|
42
44
|
lib/utilrb/module/include.rb
|
43
45
|
lib/utilrb/module/inherited_enumerable.rb
|
@@ -46,8 +48,7 @@ lib/utilrb/object/address.rb
|
|
46
48
|
lib/utilrb/object/attribute.rb
|
47
49
|
lib/utilrb/object/singleton_class.rb
|
48
50
|
lib/utilrb/objectstats.rb
|
49
|
-
lib/utilrb/
|
50
|
-
lib/utilrb/queue/get.rb
|
51
|
+
lib/utilrb/pkgconfig.rb
|
51
52
|
lib/utilrb/set.rb
|
52
53
|
lib/utilrb/set/to_s.rb
|
53
54
|
lib/utilrb/time.rb
|
@@ -55,10 +56,11 @@ lib/utilrb/time/to_hms.rb
|
|
55
56
|
lib/utilrb/unbound_method.rb
|
56
57
|
lib/utilrb/unbound_method/call.rb
|
57
58
|
lib/utilrb/value_set.rb
|
58
|
-
|
59
|
+
test/data/test_pkgconfig.pc
|
59
60
|
test/test_array.rb
|
60
61
|
test/test_config.rb
|
61
62
|
test/test_enumerable.rb
|
63
|
+
test/test_exception.rb
|
62
64
|
test/test_gc.rb
|
63
65
|
test/test_hash.rb
|
64
66
|
test/test_kernel.rb
|
@@ -66,5 +68,7 @@ test/test_misc.rb
|
|
66
68
|
test/test_module.rb
|
67
69
|
test/test_object.rb
|
68
70
|
test/test_objectstats.rb
|
71
|
+
test/test_pkgconfig.rb
|
72
|
+
test/test_proc.rb
|
69
73
|
test/test_time.rb
|
70
74
|
test/test_unbound_method.rb
|
data/Rakefile
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
# FIX: Hoe always calls rdoc with -d, and diagram generation fails here
|
4
|
+
class Rake::RDocTask
|
5
|
+
alias __option_list__ option_list
|
6
|
+
def option_list
|
7
|
+
options = __option_list__
|
8
|
+
options.delete("-d")
|
9
|
+
options
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
1
13
|
require 'hoe'
|
2
14
|
require './lib/utilrb/common'
|
3
15
|
|
@@ -8,9 +20,20 @@ Hoe.new('utilrb', Utilrb::VERSION) do |p|
|
|
8
20
|
p.summary = 'Yet another Ruby toolkit'
|
9
21
|
p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
|
10
22
|
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
11
|
-
p.changes = p.paragraphs_of('Changes.txt', 0..
|
23
|
+
p.changes = p.paragraphs_of('Changes.txt', 0..3).join("\n\n")
|
12
24
|
|
13
25
|
p.extra_deps << 'facets'
|
26
|
+
p.rdoc_pattern = /(ext\/.*cc$|lib)|txt/
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "builds Utilrb's C extension"
|
30
|
+
task :setup do
|
31
|
+
Dir.chdir("ext") do
|
32
|
+
if !system("ruby extconf.rb") || !system("make")
|
33
|
+
raise "cannot build the C extension"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
FileUtils.ln_sf "../../ext/faster.so", "lib/utilrb/faster.so"
|
14
37
|
end
|
15
38
|
|
16
39
|
task :full_test do
|
data/ext/faster.cc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <set>
|
3
|
+
#include "ruby_internals.h"
|
3
4
|
|
4
5
|
using namespace std;
|
5
6
|
|
@@ -38,6 +39,59 @@ static VALUE kernel_is_singleton_p(VALUE self)
|
|
38
39
|
return Qfalse;
|
39
40
|
}
|
40
41
|
|
42
|
+
|
43
|
+
/* call-seq:
|
44
|
+
* proc.same_body?(other) => true or false
|
45
|
+
*
|
46
|
+
* Returns true if +self+ and +other+ have the same body
|
47
|
+
*/
|
48
|
+
static VALUE proc_same_body_p(VALUE self, VALUE other)
|
49
|
+
{
|
50
|
+
if (self == other) return Qtrue;
|
51
|
+
if (TYPE(other) != T_DATA) return Qfalse;
|
52
|
+
if (RDATA(other)->dmark != RDATA(self)->dmark) return Qfalse;
|
53
|
+
if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
|
54
|
+
|
55
|
+
struct BLOCK* data, *data2;
|
56
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
57
|
+
Data_Get_Struct(other, struct BLOCK, data2);
|
58
|
+
return (data->body == data2->body) ? Qtrue : Qfalse;
|
59
|
+
}
|
60
|
+
|
61
|
+
/* call-seq:
|
62
|
+
* proc.file
|
63
|
+
*
|
64
|
+
* Returns the file in which the proc body is defined, or nil
|
65
|
+
*/
|
66
|
+
static VALUE proc_file(VALUE self)
|
67
|
+
{
|
68
|
+
struct BLOCK *data;
|
69
|
+
NODE *node;
|
70
|
+
|
71
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
72
|
+
if ((node = data->frame.node) || (node = data->body))
|
73
|
+
return rb_str_new2(node->nd_file);
|
74
|
+
else
|
75
|
+
return Qnil;
|
76
|
+
}
|
77
|
+
|
78
|
+
/* call-seq:
|
79
|
+
* proc.file
|
80
|
+
*
|
81
|
+
* Returns the line at which the proc body is defined, or nil
|
82
|
+
*/
|
83
|
+
static VALUE proc_line(VALUE self)
|
84
|
+
{
|
85
|
+
struct BLOCK *data;
|
86
|
+
NODE *node;
|
87
|
+
|
88
|
+
Data_Get_Struct(self, struct BLOCK, data);
|
89
|
+
if ((node = data->frame.node) || (node = data->body))
|
90
|
+
return INT2FIX(nd_line(node));
|
91
|
+
else
|
92
|
+
return Qnil;
|
93
|
+
}
|
94
|
+
|
41
95
|
extern "C" void Init_value_set();
|
42
96
|
extern "C" void Init_swap();
|
43
97
|
|
@@ -45,6 +99,9 @@ extern "C" void Init_faster()
|
|
45
99
|
{
|
46
100
|
rb_define_method(rb_mEnumerable, "each_uniq", RUBY_METHOD_FUNC(enumerable_each_uniq), 0);
|
47
101
|
rb_define_method(rb_mKernel, "is_singleton?", RUBY_METHOD_FUNC(kernel_is_singleton_p), 0);
|
102
|
+
rb_define_method(rb_cProc, "same_body?", RUBY_METHOD_FUNC(proc_same_body_p), 1);
|
103
|
+
rb_define_method(rb_cProc, "file", RUBY_METHOD_FUNC(proc_file), 0);
|
104
|
+
rb_define_method(rb_cProc, "line", RUBY_METHOD_FUNC(proc_line), 0);
|
48
105
|
|
49
106
|
Init_value_set();
|
50
107
|
Init_swap();
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#ifndef __RUBY_INTERNALS_HH__
|
2
|
+
#define __RUBY_INTERNALS_HH__
|
3
|
+
|
4
|
+
/* WARNING: this file contains copies of internal Ruby structures. They are not supposed to be copied (I think ;-)), but I had to nonetheless.
|
5
|
+
* The following methods depend on these:
|
6
|
+
*
|
7
|
+
* Kernel.swap!
|
8
|
+
* Proc#same_body?
|
9
|
+
* Proc#file
|
10
|
+
* Proc#line
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include <ruby.h>
|
14
|
+
#include <intern.h>
|
15
|
+
#include <node.h>
|
16
|
+
#include <re.h>
|
17
|
+
#include <env.h>
|
18
|
+
|
19
|
+
typedef struct RVALUE {
|
20
|
+
union {
|
21
|
+
struct {
|
22
|
+
unsigned long flags; /* always 0 for freed obj */
|
23
|
+
struct RVALUE *next;
|
24
|
+
} free;
|
25
|
+
struct RBasic basic;
|
26
|
+
struct RObject object;
|
27
|
+
struct RClass klass;
|
28
|
+
struct RFloat flonum;
|
29
|
+
struct RString string;
|
30
|
+
struct RArray array;
|
31
|
+
struct RRegexp regexp;
|
32
|
+
struct RHash hash;
|
33
|
+
struct RData data;
|
34
|
+
struct RStruct rstruct;
|
35
|
+
struct RBignum bignum;
|
36
|
+
struct RFile file;
|
37
|
+
struct RNode node;
|
38
|
+
struct RMatch match;
|
39
|
+
struct RVarmap varmap;
|
40
|
+
struct SCOPE scope;
|
41
|
+
} as;
|
42
|
+
#ifdef GC_DEBUG
|
43
|
+
char *file;
|
44
|
+
int line;
|
45
|
+
#endif
|
46
|
+
} RVALUE;
|
47
|
+
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
48
|
+
|
49
|
+
/* This is a copy of Ruby 1.8.5 BLOCK structure. It sucks to copy it here,
|
50
|
+
* but it is not public in Ruby and it is needed to define same_body? */
|
51
|
+
struct BLOCK {
|
52
|
+
NODE *var;
|
53
|
+
NODE *body;
|
54
|
+
VALUE self;
|
55
|
+
struct FRAME frame;
|
56
|
+
struct SCOPE *scope;
|
57
|
+
VALUE klass;
|
58
|
+
NODE *cref;
|
59
|
+
int iter;
|
60
|
+
int vmode;
|
61
|
+
int flags;
|
62
|
+
int uniq;
|
63
|
+
struct RVarmap *dyna_vars;
|
64
|
+
VALUE orig_thread;
|
65
|
+
VALUE wrapper;
|
66
|
+
VALUE block_obj;
|
67
|
+
struct BLOCK *outer;
|
68
|
+
struct BLOCK *prev;
|
69
|
+
};
|
70
|
+
|
71
|
+
#endif
|
72
|
+
|
data/ext/swap.cc
CHANGED
@@ -1,38 +1,4 @@
|
|
1
|
-
#include
|
2
|
-
#include <intern.h>
|
3
|
-
#include <node.h>
|
4
|
-
#include <re.h>
|
5
|
-
#include <env.h>
|
6
|
-
|
7
|
-
typedef struct RVALUE {
|
8
|
-
union {
|
9
|
-
struct {
|
10
|
-
unsigned long flags; /* always 0 for freed obj */
|
11
|
-
struct RVALUE *next;
|
12
|
-
} free;
|
13
|
-
struct RBasic basic;
|
14
|
-
struct RObject object;
|
15
|
-
struct RClass klass;
|
16
|
-
struct RFloat flonum;
|
17
|
-
struct RString string;
|
18
|
-
struct RArray array;
|
19
|
-
struct RRegexp regexp;
|
20
|
-
struct RHash hash;
|
21
|
-
struct RData data;
|
22
|
-
struct RStruct rstruct;
|
23
|
-
struct RBignum bignum;
|
24
|
-
struct RFile file;
|
25
|
-
struct RNode node;
|
26
|
-
struct RMatch match;
|
27
|
-
struct RVarmap varmap;
|
28
|
-
struct SCOPE scope;
|
29
|
-
} as;
|
30
|
-
#ifdef GC_DEBUG
|
31
|
-
char *file;
|
32
|
-
int line;
|
33
|
-
#endif
|
34
|
-
} RVALUE;
|
35
|
-
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
1
|
+
#include "ruby_internals.h"
|
36
2
|
|
37
3
|
/*
|
38
4
|
* Kernel.swap!(obj1, obj2, *args)
|
data/ext/value_set.cc
CHANGED
@@ -9,7 +9,6 @@ using namespace std;
|
|
9
9
|
|
10
10
|
static VALUE cValueSet;
|
11
11
|
static ID id_new;
|
12
|
-
static ID id_to_value_set;
|
13
12
|
|
14
13
|
typedef std::set<VALUE> ValueSet;
|
15
14
|
static ValueSet& get_wrapped_set(VALUE self)
|
@@ -110,7 +109,9 @@ static VALUE value_set_to_value_set(VALUE self) { return self; }
|
|
110
109
|
static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
|
111
110
|
{
|
112
111
|
ValueSet const& self = get_wrapped_set(vself);
|
113
|
-
|
112
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
113
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
114
|
+
ValueSet const& other = get_wrapped_set(vother);
|
114
115
|
return std::includes(self.begin(), self.end(), other.begin(), other.end()) ? Qtrue : Qfalse;
|
115
116
|
}
|
116
117
|
|
@@ -124,7 +125,9 @@ static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
|
|
124
125
|
static VALUE value_set_union(VALUE vself, VALUE vother)
|
125
126
|
{
|
126
127
|
ValueSet const& self = get_wrapped_set(vself);
|
127
|
-
|
128
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
129
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
130
|
+
ValueSet const& other = get_wrapped_set(vother);
|
128
131
|
|
129
132
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
130
133
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -141,7 +144,9 @@ static VALUE value_set_union(VALUE vself, VALUE vother)
|
|
141
144
|
static VALUE value_set_merge(VALUE vself, VALUE vother)
|
142
145
|
{
|
143
146
|
ValueSet& self = get_wrapped_set(vself);
|
144
|
-
|
147
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
148
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
149
|
+
ValueSet const& other = get_wrapped_set(vother);
|
145
150
|
|
146
151
|
self.insert(other.begin(), other.end());
|
147
152
|
return vself;
|
@@ -157,7 +162,9 @@ static VALUE value_set_merge(VALUE vself, VALUE vother)
|
|
157
162
|
static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
158
163
|
{
|
159
164
|
ValueSet const& self = get_wrapped_set(vself);
|
160
|
-
|
165
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
166
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
167
|
+
ValueSet const& other = get_wrapped_set(vother);
|
161
168
|
|
162
169
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
163
170
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -165,6 +172,37 @@ static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
|
165
172
|
std::inserter(result, result.end()));
|
166
173
|
return vresult;
|
167
174
|
}
|
175
|
+
|
176
|
+
/* call-seq:
|
177
|
+
* set.intersects?(other) => true or false
|
178
|
+
*
|
179
|
+
* Returns true if there is elements in +set+ that are also in +other
|
180
|
+
*/
|
181
|
+
static VALUE value_set_intersects(VALUE vself, VALUE vother)
|
182
|
+
{
|
183
|
+
ValueSet const& self = get_wrapped_set(vself);
|
184
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
185
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
186
|
+
ValueSet const& other = get_wrapped_set(vother);
|
187
|
+
|
188
|
+
ValueSet::const_iterator
|
189
|
+
self_it = self.begin(),
|
190
|
+
self_end = self.end(),
|
191
|
+
other_it = other.begin(),
|
192
|
+
other_end = other.end();
|
193
|
+
|
194
|
+
while(self_it != self_end && other_it != other_end)
|
195
|
+
{
|
196
|
+
if (*self_it < *other_it)
|
197
|
+
++self_it;
|
198
|
+
else if (*other_it < *self_it)
|
199
|
+
++other_it;
|
200
|
+
else
|
201
|
+
return Qtrue;
|
202
|
+
}
|
203
|
+
return Qfalse;
|
204
|
+
}
|
205
|
+
|
168
206
|
/* call-seq:
|
169
207
|
* set.difference(other) => difference_set
|
170
208
|
* set - other => difference_set
|
@@ -175,7 +213,9 @@ static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
|
175
213
|
static VALUE value_set_difference(VALUE vself, VALUE vother)
|
176
214
|
{
|
177
215
|
ValueSet const& self = get_wrapped_set(vself);
|
178
|
-
|
216
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
217
|
+
rb_raise(rb_eArgError, "expected a ValueSet");
|
218
|
+
ValueSet const& other = get_wrapped_set(vother);
|
179
219
|
|
180
220
|
VALUE vresult = rb_funcall(cValueSet, id_new, 0);
|
181
221
|
ValueSet& result = get_wrapped_set(vresult);
|
@@ -219,10 +259,9 @@ static VALUE value_set_delete(VALUE vself, VALUE v)
|
|
219
259
|
static VALUE value_set_equal(VALUE vself, VALUE vother)
|
220
260
|
{
|
221
261
|
ValueSet const& self = get_wrapped_set(vself);
|
222
|
-
if (!
|
262
|
+
if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
|
223
263
|
return Qfalse;
|
224
|
-
|
225
|
-
ValueSet const& other = get_wrapped_set(rb_funcall(vother, id_to_value_set, 0));
|
264
|
+
ValueSet const& other = get_wrapped_set(vother);
|
226
265
|
return (self == other) ? Qtrue : Qfalse;
|
227
266
|
}
|
228
267
|
|
@@ -244,7 +283,7 @@ static VALUE value_set_clear(VALUE self)
|
|
244
283
|
*/
|
245
284
|
static VALUE value_set_initialize_copy(VALUE vself, VALUE vother)
|
246
285
|
{
|
247
|
-
ValueSet const& other = get_wrapped_set(
|
286
|
+
ValueSet const& other = get_wrapped_set(vother);
|
248
287
|
set<VALUE> new_set(other.begin(), other.end());
|
249
288
|
get_wrapped_set(vself).swap(new_set);
|
250
289
|
return vself;
|
@@ -292,13 +331,13 @@ extern "C" void Init_value_set()
|
|
292
331
|
|
293
332
|
cValueSet = rb_define_class("ValueSet", rb_cObject);
|
294
333
|
id_new = rb_intern("new");
|
295
|
-
id_to_value_set = rb_intern("to_value_set");
|
296
334
|
rb_define_alloc_func(cValueSet, value_set_alloc);
|
297
335
|
rb_define_method(cValueSet, "each", RUBY_METHOD_FUNC(value_set_each), 0);
|
298
336
|
rb_define_method(cValueSet, "include?", RUBY_METHOD_FUNC(value_set_include_p), 1);
|
299
337
|
rb_define_method(cValueSet, "include_all?", RUBY_METHOD_FUNC(value_set_include_all_p), 1);
|
300
338
|
rb_define_method(cValueSet, "union", RUBY_METHOD_FUNC(value_set_union), 1);
|
301
339
|
rb_define_method(cValueSet, "intersection", RUBY_METHOD_FUNC(value_set_intersection), 1);
|
340
|
+
rb_define_method(cValueSet, "intersects?", RUBY_METHOD_FUNC(value_set_intersects), 1);
|
302
341
|
rb_define_method(cValueSet, "difference", RUBY_METHOD_FUNC(value_set_difference), 1);
|
303
342
|
rb_define_method(cValueSet, "insert", RUBY_METHOD_FUNC(value_set_insert), 1);
|
304
343
|
rb_define_method(cValueSet, "merge", RUBY_METHOD_FUNC(value_set_merge), 1);
|
data/lib/utilrb/array/to_s.rb
CHANGED
@@ -3,11 +3,11 @@ class Array
|
|
3
3
|
# Unlike #inspect, it calls #to_s on the elements too
|
4
4
|
def to_s
|
5
5
|
stack = (Thread.current[:array_to_s] ||= [])
|
6
|
-
if stack.include?(
|
6
|
+
if stack.include?(object_id)
|
7
7
|
"..."
|
8
8
|
else
|
9
9
|
begin
|
10
|
-
stack.push
|
10
|
+
stack.push object_id
|
11
11
|
"[" << map { |obj| obj.to_s }.join(", ") << "]"
|
12
12
|
ensure
|
13
13
|
stack.pop
|
data/lib/utilrb/common.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
-
|
1
|
+
require 'enumerator'
|
2
|
+
|
3
|
+
# An enumerator which iterates on multiple iterators in sequence
|
4
|
+
#
|
5
|
+
# ([1, 2].enum_for + [2, 3].enum_for).each => 1, 2, 2, 3
|
6
|
+
#
|
7
|
+
# See also Enumerator#+
|
2
8
|
class SequenceEnumerator
|
3
9
|
def initialize; @sequence = Array.new end
|
10
|
+
|
11
|
+
def +(other); SequenceEnumerator.new << self << other end
|
4
12
|
# Adds +object+ at the back of the sequence
|
5
|
-
def <<(
|
13
|
+
def <<(other); @sequence << other; self end
|
6
14
|
|
7
15
|
def each
|
8
16
|
@sequence.each { |enum| enum.each { |o| yield(o) } } if block_given?
|
@@ -12,7 +20,7 @@ class SequenceEnumerator
|
|
12
20
|
include Enumerable
|
13
21
|
end
|
14
22
|
|
15
|
-
|
23
|
+
class Enumerable::Enumerator # :nodoc
|
16
24
|
# Builds a sequence of enumeration object.
|
17
25
|
# ([1, 2].enum_for + [2, 3]).each => 1, 2, 2, 3
|
18
26
|
def +(other_enumerator) # :nodoc
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'utilrb/kernel/options'
|
1
2
|
|
2
3
|
class Exception
|
3
4
|
# Returns the full exception message, with backtrace, like the one we get from
|
@@ -16,9 +17,40 @@ class Exception
|
|
16
17
|
# test.rb:3:in `test': this is a test (RuntimeError)
|
17
18
|
# from test.rb:7
|
18
19
|
#
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
# Two regular expressions can be given through the +options+ hash to filter the backtrace:
|
21
|
+
# since::
|
22
|
+
# Only the methods *below* the first matching line will be displayed. The matching
|
23
|
+
# line is included.
|
24
|
+
# until::
|
25
|
+
# Only the methods *above* the first matching line will be displayed. The matching
|
26
|
+
# line is *not* included
|
27
|
+
#
|
28
|
+
# If a block is given, each line of the backtrace are yield and only the lines for which
|
29
|
+
# the block returns true are displayed
|
30
|
+
#
|
31
|
+
def full_message(options = {}, &block)
|
32
|
+
options = validate_options options, [:since, :until]
|
33
|
+
since_matches, until_matches = options[:since], options[:until]
|
34
|
+
|
35
|
+
trace = backtrace
|
36
|
+
if since_matches || until_matches
|
37
|
+
found_beginning, found_end = !since_matches, false
|
38
|
+
trace = trace.find_all do |line|
|
39
|
+
found_beginning ||= (line =~ since_matches)
|
40
|
+
found_end ||= (line =~ until_matches) if until_matches
|
41
|
+
found_beginning && !found_end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
first, *remaining = if block_given? then trace.find_all(&block)
|
46
|
+
else trace
|
47
|
+
end
|
48
|
+
|
49
|
+
msg = "#{first}: #{message} (#{self.class})"
|
50
|
+
unless remaining.empty?
|
51
|
+
msg << "\n\tfrom " + remaining.join("\n\tfrom ")
|
52
|
+
end
|
53
|
+
msg
|
22
54
|
end
|
23
55
|
end
|
24
56
|
|
@@ -1,6 +1,25 @@
|
|
1
|
+
require 'utilrb/common'
|
1
2
|
class Module
|
2
|
-
|
3
|
-
|
3
|
+
Utilrb.if_faster do
|
4
|
+
# Check if +klass+ is an ancestor of this class/module
|
5
|
+
#
|
6
|
+
# It works for singleton classes as well:
|
7
|
+
#
|
8
|
+
# class MyClass; end
|
9
|
+
# obj = MyClass.new
|
10
|
+
# singleton = class << obj; obj end
|
11
|
+
#
|
12
|
+
# singleton.has_ancestor?(MyClass) # => true
|
13
|
+
#
|
14
|
+
def has_ancestor?(klass)
|
15
|
+
self == klass || self < klass || (is_singleton? && superclass.has_ancestor?(klass))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Utilrb.unless_faster do
|
19
|
+
def has_ancestor?(klass) # :nodoc:
|
20
|
+
self == klass || self < klass || superclass == klass || superclass < klass
|
21
|
+
end
|
22
|
+
end
|
4
23
|
end
|
5
24
|
|
6
25
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Module
|
2
|
+
# Defines a +name+ predicate (name should end with '?'), and if writable is true
|
3
|
+
# a writer method which is +name+ without '?'
|
4
|
+
#
|
5
|
+
# The predicate reads the instance variable which is +name+ without the '?'
|
6
|
+
def attr_predicate(name, writable = false)
|
7
|
+
attr_name = name.to_s.gsub(/\?$/, '')
|
8
|
+
attr_reader attr_name
|
9
|
+
alias_method "#{attr_name}?", attr_name
|
10
|
+
remove_method attr_name
|
11
|
+
|
12
|
+
if writable
|
13
|
+
class_eval "def #{attr_name}=(value); @#{attr_name} = !!value end"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Utilrb
|
2
|
+
# Access to information from pkg-config(1)
|
3
|
+
class PkgConfig
|
4
|
+
class NotFound < RuntimeError
|
5
|
+
attr_reader :name
|
6
|
+
def initialize(name); @name = name end
|
7
|
+
def to_s; "#{name} is not available to pkg-config" end
|
8
|
+
end
|
9
|
+
|
10
|
+
# The module name
|
11
|
+
attr_reader :name
|
12
|
+
# The module version
|
13
|
+
attr_reader :version
|
14
|
+
|
15
|
+
# Create a PkgConfig object for the package +name+
|
16
|
+
# Raises PkgConfig::NotFound if the module does not exist
|
17
|
+
def initialize(name)
|
18
|
+
if !system("pkg-config --exists #{name}")
|
19
|
+
raise NotFound.new(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
@name = name
|
23
|
+
@version = `pkg-config --modversion #{name}`.chomp.strip
|
24
|
+
@actions = Hash.new
|
25
|
+
@variables = Hash.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.define_action(action)
|
29
|
+
define_method(action.gsub(/-/, '_')) do
|
30
|
+
@actions[action] ||= `pkg-config --#{action} #{name}`.chomp.strip
|
31
|
+
end
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
ACTIONS = %w{cflags cflags-only-I cflags-only-other
|
36
|
+
libs libs-only-L libs-only-l libs-only-other static}
|
37
|
+
ACTIONS.each { |action| define_action(action) }
|
38
|
+
|
39
|
+
def method_missing(varname, *args, &proc)
|
40
|
+
if args.empty?
|
41
|
+
@variables[varname] ||= `pkg-config --variable=#{varname} #{name}`.chomp.strip
|
42
|
+
else
|
43
|
+
super(varname, *args, &proc)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/lib/utilrb/time/to_hms.rb
CHANGED
@@ -9,13 +9,13 @@ class Time
|
|
9
9
|
# s, s.ms, m:s, m:s.ms, h:m:s, h:m:s.ms
|
10
10
|
def self.from_hms(string)
|
11
11
|
unless string =~ /(?:^|:)(\d+)(?:$|\.)/
|
12
|
-
raise "
|
12
|
+
raise ArgumentError, "#{string} found, expected [[h:]m:]s[.ms]"
|
13
13
|
end
|
14
14
|
hm, ms = $`, $'
|
15
15
|
|
16
16
|
s = Integer($1)
|
17
17
|
unless hm =~ /^(?:(\d*):)?(?:(\d*))?$/
|
18
|
-
raise "
|
18
|
+
raise ArgumentError, "found #{hm}, expected nothing, m: or h:m:"
|
19
19
|
end
|
20
20
|
h, m = if $2.empty? then
|
21
21
|
if $1 then [0, Integer($1)]
|
@@ -27,7 +27,7 @@ class Time
|
|
27
27
|
ms = if ms.empty? then 0
|
28
28
|
else
|
29
29
|
unless ms =~ /^\d*$/
|
30
|
-
raise "
|
30
|
+
raise ArgumentError, "found #{string}, expected a number"
|
31
31
|
end
|
32
32
|
ms += "0" * (3 - ms.size)
|
33
33
|
Integer(ms)
|
data/lib/utilrb/value_set.rb
CHANGED
@@ -9,9 +9,25 @@ Utilrb.require_faster("ValueSet") do
|
|
9
9
|
include Enumerable
|
10
10
|
|
11
11
|
def to_s
|
12
|
-
|
13
|
-
|
12
|
+
stack = (Thread.current[:__value_set_stack__] ||= ValueSet.new)
|
13
|
+
if stack.include?(self)
|
14
|
+
"..."
|
15
|
+
else
|
16
|
+
stack << self
|
17
|
+
|
18
|
+
base = super[0..-2]
|
19
|
+
"#{base} { #{to_a.map { |o| o.to_s }.join(", ")} }"
|
20
|
+
end
|
21
|
+
ensure
|
22
|
+
stack.delete(self)
|
14
23
|
end
|
15
24
|
alias :inspect :to_s
|
25
|
+
|
26
|
+
def _dump(lvl = -1)
|
27
|
+
Marshal.dump(to_a)
|
28
|
+
end
|
29
|
+
def self._load(str)
|
30
|
+
Marshal.load(str).to_value_set
|
31
|
+
end
|
16
32
|
end
|
17
33
|
end
|
data/test/test_enumerable.rb
CHANGED
@@ -43,6 +43,7 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
43
43
|
c2 = [:d, :e, :f]
|
44
44
|
assert_equal([:a, :b, :c, :d, :e, :f], (c1.to_enum + c2.to_enum).to_a)
|
45
45
|
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(null_enum) { |a, b| a + b }.to_a)
|
46
|
+
assert_equal([:a, :b, :c, :d, :e, :f], [c1, c2].inject(SequenceEnumerator.new) { |a, b| a << b }.to_a)
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_random_element
|
@@ -66,9 +67,13 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
66
67
|
assert_equal(5, a.size)
|
67
68
|
assert_equal([1, 3, 4, 6, 8], a.to_a)
|
68
69
|
assert(a.include?(1))
|
69
|
-
assert(a.include_all?([4, 1, 8]))
|
70
|
+
assert(a.include_all?([4, 1, 8].to_value_set))
|
70
71
|
assert(!a.include_all?(b))
|
71
72
|
|
73
|
+
assert(a.intersects?(b))
|
74
|
+
assert(b.intersects?(a))
|
75
|
+
assert(!a.intersects?([2, 9, 12].to_value_set))
|
76
|
+
|
72
77
|
assert(a.object_id == a.to_value_set.object_id)
|
73
78
|
|
74
79
|
assert_equal([1, 2, 3, 4, 6, 8, 11], (a.union(b)).to_a)
|
@@ -87,6 +92,12 @@ class TC_Enumerable < Test::Unit::TestCase
|
|
87
92
|
|
88
93
|
assert_equal([1,3,5].to_value_set, [1, 2, 3, 4, 5, 6].to_value_set.delete_if { |v| v % 2 == 0 })
|
89
94
|
end
|
95
|
+
|
96
|
+
def test_value_set_recursive_to_s
|
97
|
+
v = [1, 2].to_value_set
|
98
|
+
v << v
|
99
|
+
assert_nothing_raised { v.to_s }
|
100
|
+
end
|
90
101
|
end
|
91
102
|
end
|
92
103
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_config'
|
2
|
+
require 'utilrb/exception'
|
3
|
+
require 'flexmock'
|
4
|
+
|
5
|
+
class TC_Exception < Test::Unit::TestCase
|
6
|
+
def test_full_message
|
7
|
+
FlexMock.use do |mock|
|
8
|
+
error = Exception.new
|
9
|
+
def error.message; "this is an error" end
|
10
|
+
def error.backtrace
|
11
|
+
(0..10).map { |i| i.to_s }
|
12
|
+
end
|
13
|
+
|
14
|
+
full = error.full_message.split("\n")
|
15
|
+
assert_equal(11, full.size)
|
16
|
+
|
17
|
+
filtered = error.full_message { |line| Integer(line) % 2 == 0 }.split("\n")
|
18
|
+
assert_equal(6, filtered.size)
|
19
|
+
assert_equal(full.values_at(0, 2, 4, 6, 8, 10), filtered)
|
20
|
+
|
21
|
+
since_matches = error.full_message(:since => /4/).split("\n")
|
22
|
+
assert_equal(7, since_matches.size)
|
23
|
+
assert_equal(full.values_at(*(5..10)), since_matches[1..-1])
|
24
|
+
|
25
|
+
until_matches = error.full_message(:until => /3/).split("\n")
|
26
|
+
assert_equal(3, until_matches.size)
|
27
|
+
assert_equal(full.values_at(1, 2), until_matches[1..-1])
|
28
|
+
|
29
|
+
since_and_until = error.full_message(:since => /3/, :until => /6/).split("\n")
|
30
|
+
assert_equal(3, since_and_until.size)
|
31
|
+
assert_equal(full.values_at(4, 5), since_and_until[1..-1])
|
32
|
+
|
33
|
+
all = error.full_message(:since => /3/, :until => /6/) { |line| Integer(line) % 2 == 0 }.split("\n")
|
34
|
+
assert_equal(1, all.size)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/test/test_module.rb
CHANGED
@@ -123,5 +123,25 @@ class TC_Module < Test::Unit::TestCase
|
|
123
123
|
assert_equal([[:base, 10], [:overriden, 20], [:overriden, 15], [:derived, 25]].to_set, derived.enum_for(:each_mapped, nil, false).to_set)
|
124
124
|
assert_equal([[:base, 10], [:overriden, 15], [:derived, 25]].to_set, derived.enum_for(:each_mapped, nil, true).to_set)
|
125
125
|
end
|
126
|
+
|
127
|
+
def test_has_ancestor
|
128
|
+
mod = Module.new
|
129
|
+
parent = Class.new do
|
130
|
+
include mod
|
131
|
+
end
|
132
|
+
child = Class.new(parent)
|
133
|
+
singleton = child.new.singleton_class
|
134
|
+
|
135
|
+
assert(child.has_ancestor?(parent))
|
136
|
+
assert(child.has_ancestor?(mod))
|
137
|
+
assert(parent.has_ancestor?(mod))
|
138
|
+
|
139
|
+
assert(singleton.has_ancestor?(parent), singleton.superclass)
|
140
|
+
assert(singleton.has_ancestor?(mod))
|
141
|
+
assert(singleton.has_ancestor?(child))
|
142
|
+
|
143
|
+
assert(!parent.has_ancestor?(child))
|
144
|
+
assert(!parent.has_ancestor?(singleton))
|
145
|
+
end
|
126
146
|
end
|
127
147
|
|
data/test/test_object.rb
CHANGED
@@ -61,5 +61,24 @@ class TC_Object < Test::Unit::TestCase
|
|
61
61
|
assert_equal(klass, object.singleton_class.superclass)
|
62
62
|
assert_equal([object.singleton_class, klass, Object], object.singleton_class.ancestors[0, 3])
|
63
63
|
end
|
64
|
+
|
65
|
+
def test_attr_predicate
|
66
|
+
klass = Class.new do
|
67
|
+
attr_predicate :working
|
68
|
+
attr_predicate :not_working, true
|
69
|
+
end
|
70
|
+
assert(klass.method_defined?(:working?))
|
71
|
+
assert(!klass.method_defined?(:working))
|
72
|
+
assert(!klass.method_defined?(:working=))
|
73
|
+
assert(klass.method_defined?(:not_working?))
|
74
|
+
assert(!klass.method_defined?(:not_working))
|
75
|
+
assert(klass.method_defined?(:not_working=))
|
76
|
+
|
77
|
+
object = klass.new
|
78
|
+
object.instance_eval { @working = true }
|
79
|
+
assert(object.working?)
|
80
|
+
object.not_working = 5
|
81
|
+
assert_equal(true, object.not_working?)
|
82
|
+
end
|
64
83
|
end
|
65
84
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'set'
|
3
|
+
require 'utilrb/pkgconfig'
|
4
|
+
|
5
|
+
class TC_PkgConfig < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@old_pkg_config_path = ENV['PKG_CONFIG_PATH']
|
8
|
+
ENV['PKG_CONFIG_PATH'] = File.join(File.expand_path(File.dirname(__FILE__)), 'data')
|
9
|
+
end
|
10
|
+
def teardown
|
11
|
+
ENV['PKG_CONFIG_PATH'] = @old_pkg_config_path
|
12
|
+
end
|
13
|
+
|
14
|
+
PkgConfig = Utilrb::PkgConfig
|
15
|
+
def test_find_package
|
16
|
+
STDERR.puts ENV['PKG_CONFIG_PATH']
|
17
|
+
assert_raises(PkgConfig::NotFound) { PkgConfig.new('does_not_exist') }
|
18
|
+
assert_nothing_raised { PkgConfig.new('test_pkgconfig') }
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_load
|
22
|
+
pkg = PkgConfig.new('test_pkgconfig')
|
23
|
+
assert_equal('test_pkgconfig', pkg.name)
|
24
|
+
assert_equal('4.2', pkg.version)
|
25
|
+
|
26
|
+
assert_equal('a_prefix', pkg.prefix)
|
27
|
+
assert_equal(%w{-Ia_prefix/include -O3}.to_set, pkg.cflags.split.to_set)
|
28
|
+
assert_equal('-Ia_prefix/include', pkg.cflags_only_I)
|
29
|
+
assert_equal('-O3', pkg.cflags_only_other)
|
30
|
+
|
31
|
+
assert_equal(%w{-ltest -lother -La_prefix/lib}.to_set, pkg.libs.split.to_set)
|
32
|
+
assert_equal('-La_prefix/lib', pkg.libs_only_L)
|
33
|
+
assert_equal(%w{-ltest -lother}.to_set, pkg.libs_only_l.split.to_set)
|
34
|
+
end
|
35
|
+
end
|
data/test/test_proc.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'utilrb'
|
3
|
+
|
4
|
+
Utilrb.require_faster('TC_Proc') do
|
5
|
+
class TC_Proc < Test::Unit::TestCase
|
6
|
+
def block_to_proc_helper(&block); block end
|
7
|
+
def block_to_proc
|
8
|
+
[block_to_proc_helper { blo }, block_to_proc_helper { bla }]
|
9
|
+
end
|
10
|
+
def test_same_body
|
11
|
+
a1, a2 = block_to_proc
|
12
|
+
b1, b2 = block_to_proc
|
13
|
+
assert(a1.same_body?(b1))
|
14
|
+
assert(a2.same_body?(b2))
|
15
|
+
assert(!a1.same_body?(b2))
|
16
|
+
assert(!a2.same_body?(b1))
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_line
|
20
|
+
assert_equal(8, block_to_proc.first.line)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_file
|
24
|
+
assert_equal(File.expand_path(__FILE__), File.expand_path(block_to_proc.first.file))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: utilrb
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0
|
7
|
-
date: 2007-
|
6
|
+
version: "1.0"
|
7
|
+
date: 2007-03-31 00:00:00 +02:00
|
8
8
|
summary: Yet another Ruby toolkit
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- bm/speed.rb
|
40
40
|
- ext/extconf.rb
|
41
41
|
- ext/faster.cc
|
42
|
+
- ext/ruby_internals.h
|
42
43
|
- ext/swap.cc
|
43
44
|
- ext/value_set.cc
|
44
45
|
- lib/utilrb.rb
|
@@ -70,6 +71,7 @@ files:
|
|
70
71
|
- lib/utilrb/module.rb
|
71
72
|
- lib/utilrb/module/ancestor_p.rb
|
72
73
|
- lib/utilrb/module/attr_enumerable.rb
|
74
|
+
- lib/utilrb/module/attr_predicate.rb
|
73
75
|
- lib/utilrb/module/define_method.rb
|
74
76
|
- lib/utilrb/module/include.rb
|
75
77
|
- lib/utilrb/module/inherited_enumerable.rb
|
@@ -78,8 +80,7 @@ files:
|
|
78
80
|
- lib/utilrb/object/attribute.rb
|
79
81
|
- lib/utilrb/object/singleton_class.rb
|
80
82
|
- lib/utilrb/objectstats.rb
|
81
|
-
- lib/utilrb/
|
82
|
-
- lib/utilrb/queue/get.rb
|
83
|
+
- lib/utilrb/pkgconfig.rb
|
83
84
|
- lib/utilrb/set.rb
|
84
85
|
- lib/utilrb/set/to_s.rb
|
85
86
|
- lib/utilrb/time.rb
|
@@ -87,10 +88,11 @@ files:
|
|
87
88
|
- lib/utilrb/unbound_method.rb
|
88
89
|
- lib/utilrb/unbound_method/call.rb
|
89
90
|
- lib/utilrb/value_set.rb
|
90
|
-
-
|
91
|
+
- test/data/test_pkgconfig.pc
|
91
92
|
- test/test_array.rb
|
92
93
|
- test/test_config.rb
|
93
94
|
- test/test_enumerable.rb
|
95
|
+
- test/test_exception.rb
|
94
96
|
- test/test_gc.rb
|
95
97
|
- test/test_hash.rb
|
96
98
|
- test/test_kernel.rb
|
@@ -98,9 +100,13 @@ files:
|
|
98
100
|
- test/test_module.rb
|
99
101
|
- test/test_object.rb
|
100
102
|
- test/test_objectstats.rb
|
103
|
+
- test/test_pkgconfig.rb
|
104
|
+
- test/test_proc.rb
|
101
105
|
- test/test_time.rb
|
102
106
|
- test/test_unbound_method.rb
|
103
107
|
test_files:
|
108
|
+
- test/test_proc.rb
|
109
|
+
- test/test_exception.rb
|
104
110
|
- test/test_time.rb
|
105
111
|
- test/test_misc.rb
|
106
112
|
- test/test_module.rb
|
@@ -113,6 +119,7 @@ test_files:
|
|
113
119
|
- test/test_enumerable.rb
|
114
120
|
- test/test_hash.rb
|
115
121
|
- test/test_objectstats.rb
|
122
|
+
- test/test_pkgconfig.rb
|
116
123
|
rdoc_options: []
|
117
124
|
|
118
125
|
extra_rdoc_files: []
|
@@ -140,5 +147,5 @@ dependencies:
|
|
140
147
|
requirements:
|
141
148
|
- - ">="
|
142
149
|
- !ruby/object:Gem::Version
|
143
|
-
version: 1.
|
150
|
+
version: 1.2.0
|
144
151
|
version:
|
data/lib/utilrb/queue/get.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
class Queue
|
2
|
-
# Returns all elements currently in the queue. If +non_block+ is true,
|
3
|
-
# returns an empty array if the queue is empty
|
4
|
-
#
|
5
|
-
# WARNING: this method is NOT compatible with fastthread's Queue implementation
|
6
|
-
# If you rely on Queue#get and want to use fastthread, you will have to patch
|
7
|
-
# fastthread with patches/fastthread-queue-get.patch
|
8
|
-
unless instance_methods.include?("get")
|
9
|
-
def get(non_block = false)
|
10
|
-
while (Thread.critical = true; @que.empty?)
|
11
|
-
return [] if non_block
|
12
|
-
@waiting.push Thread.current
|
13
|
-
Thread.stop
|
14
|
-
end
|
15
|
-
result = @que.dup
|
16
|
-
@que.clear
|
17
|
-
result
|
18
|
-
ensure
|
19
|
-
Thread.critical = false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/utilrb/queue.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
--- fastthread-0.6.2/ext/fastthread/fastthread.c 2007-01-25 12:09:54.956708000 +0100
|
2
|
-
+++ fastthread-0.6.2.new/ext/fastthread/fastthread.c 2007-01-25 11:49:49.151455000 +0100
|
3
|
-
@@ -737,6 +737,61 @@ rb_queue_marshal_load(self, data)
|
4
|
-
|
5
|
-
static VALUE rb_queue_marshal_dump _((VALUE));
|
6
|
-
|
7
|
-
+
|
8
|
-
+/* call-seq:
|
9
|
-
+ * Queue#get(non_block = false) => array
|
10
|
-
+ *
|
11
|
-
+ * Returns an array containing all elements currently in the queue. After a call
|
12
|
-
+ * to #get, the queue is empty. If non_block is false, the call will block until
|
13
|
-
+ * there is something in it. Otherwise, if the queue is empty, it returns an empty
|
14
|
-
+ * array.
|
15
|
-
+ */
|
16
|
-
+static VALUE
|
17
|
-
+rb_queue_get(argc, argv, self)
|
18
|
-
+ int argc;
|
19
|
-
+ VALUE *argv;
|
20
|
-
+ VALUE self;
|
21
|
-
+{
|
22
|
-
+ Queue *queue;
|
23
|
-
+ int should_block;
|
24
|
-
+ VALUE result;
|
25
|
-
+ Data_Get_Struct(self, Queue, queue);
|
26
|
-
+
|
27
|
-
+ if ( argc == 0 ) {
|
28
|
-
+ should_block = 1;
|
29
|
-
+ } else if ( argc == 1 ) {
|
30
|
-
+ should_block = !RTEST(argv[0]);
|
31
|
-
+ } else {
|
32
|
-
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
|
33
|
-
+ }
|
34
|
-
+
|
35
|
-
+ lock_mutex(&queue->mutex);
|
36
|
-
+ if ( !queue->values.entries ) {
|
37
|
-
+ /* NOTE: locking is not needed to check if the queue is empty
|
38
|
-
+ since AFAIK C extensions are never preempted. I do as in #pop
|
39
|
-
+ where it is done.
|
40
|
-
+ */
|
41
|
-
+ if ( !should_block ) {
|
42
|
-
+ unlock_mutex(&queue->mutex);
|
43
|
-
+ return rb_ary_new();
|
44
|
-
+ }
|
45
|
-
+ while (!queue->values.entries) {
|
46
|
-
+ wait_condvar(&queue->value_available, &queue->mutex);
|
47
|
-
+ }
|
48
|
-
+ }
|
49
|
-
+
|
50
|
-
+ result = rb_ary_new();
|
51
|
-
+ while ( queue->values.entries ) {
|
52
|
-
+ rb_ary_push(result, shift_list(&queue->values));
|
53
|
-
+ }
|
54
|
-
+ if ( queue->capacity ) {
|
55
|
-
+ signal_condvar(&queue->space_available);
|
56
|
-
+ }
|
57
|
-
+ unlock_mutex(&queue->mutex);
|
58
|
-
+
|
59
|
-
+ return result;
|
60
|
-
+}
|
61
|
-
+
|
62
|
-
static VALUE
|
63
|
-
rb_queue_marshal_dump(self)
|
64
|
-
VALUE self;
|
65
|
-
@@ -991,6 +1046,7 @@ static VALUE setup_classes(unused)
|
66
|
-
rb_define_method(rb_cQueue, "num_waiting", rb_queue_num_waiting, 0);
|
67
|
-
rb_define_method(rb_cQueue, "pop", rb_queue_pop, -1);
|
68
|
-
rb_define_method(rb_cQueue, "push", rb_queue_push, 1);
|
69
|
-
+ rb_define_method(rb_cQueue, "get", rb_queue_get, -1);
|
70
|
-
rb_alias(rb_cQueue, rb_intern("<<"), rb_intern("push"));
|
71
|
-
rb_alias(rb_cQueue, rb_intern("deq"), rb_intern("pop"));
|
72
|
-
rb_alias(rb_cQueue, rb_intern("shift"), rb_intern("pop"));
|