utilrb 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -3
- data/Rakefile +3 -3
- data/ext/extconf.rb +1 -1
- data/ext/ruby_internals-1.9.h +28 -5
- data/ext/utilrb_ext.cc +8 -18
- data/ext/value_set.cc +19 -16
- data/ext/weakref.cc +30 -29
- data/lib/utilrb/column_formatter.rb +59 -14
- data/lib/utilrb/common.rb +1 -1
- data/lib/utilrb/enumerable/sequence.rb +8 -2
- data/lib/utilrb/enumerable/uniq.rb +7 -1
- data/lib/utilrb/pkgconfig.rb +72 -4
- data/lib/utilrb/weakref.rb +3 -3
- data/test/test_pkgconfig.rb +14 -0
- data/test/test_weakref.rb +28 -2
- metadata +24 -8
data/History.txt
CHANGED
@@ -1,12 +1,22 @@
|
|
1
|
-
=== Version 1.3.
|
1
|
+
=== Version 1.3.3
|
2
|
+
|
3
|
+
* fixed a problem with WeakRef crashing on 1.8.7p172. This version of weakref
|
4
|
+
should now work on every versions of 1.8.6 and 1.8.7
|
5
|
+
* made ColumnFormatter more configurable
|
6
|
+
* made the Rakefile callable with ruby's binaries that are not called 'ruby'
|
7
|
+
|
8
|
+
=== Version 1.3.2
|
2
9
|
|
3
10
|
* make utilrb depend only on standard C++, no boost
|
4
|
-
|
11
|
+
|
12
|
+
=== Version 1.3.1
|
13
|
+
|
14
|
+
* quickfix release: update the Manifest file for Hoe
|
5
15
|
|
6
16
|
=== Version 1.3
|
7
17
|
|
8
18
|
* added Utilrb::WeakRef, a much leaner version of the standard WeakRef:
|
9
|
-
implemented in C++, not a subclass of Delegate (delegate is very costly)
|
19
|
+
implemented in C++, not a subclass of Delegate (delegate is very costly).
|
10
20
|
|
11
21
|
=== Version 1.2
|
12
22
|
|
data/Rakefile
CHANGED
@@ -20,11 +20,10 @@ begin
|
|
20
20
|
|
21
21
|
p.summary = 'Yet another Ruby toolkit'
|
22
22
|
p.description = p.paragraphs_of('README.txt', 3..6).join("\n\n")
|
23
|
-
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
23
|
+
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1].map { |l| l.strip }
|
24
24
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
25
25
|
|
26
26
|
p.extra_deps << ['facets', '>= 2.4.0'] << 'rake'
|
27
|
-
p.rdoc_pattern = /(ext\/.*cc$|lib)|txt/
|
28
27
|
end
|
29
28
|
config.spec.extensions << 'ext/extconf.rb'
|
30
29
|
rescue LoadError
|
@@ -34,10 +33,11 @@ rescue Exception => e
|
|
34
33
|
STDERR.puts "error message is: #{e.message}"
|
35
34
|
end
|
36
35
|
|
36
|
+
RUBY = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
37
37
|
desc "builds Utilrb's C extension"
|
38
38
|
task :setup do
|
39
39
|
Dir.chdir("ext") do
|
40
|
-
if !system("
|
40
|
+
if !system("#{RUBY} extconf.rb") || !system("make")
|
41
41
|
raise "cannot build the C extension"
|
42
42
|
end
|
43
43
|
end
|
data/ext/extconf.rb
CHANGED
data/ext/ruby_internals-1.9.h
CHANGED
@@ -12,9 +12,34 @@
|
|
12
12
|
|
13
13
|
#include <ruby.h>
|
14
14
|
#include <ruby/intern.h>
|
15
|
-
#include <ruby/node.h>
|
16
15
|
#include <ruby/re.h>
|
17
16
|
|
17
|
+
typedef struct RNode {
|
18
|
+
unsigned long flags;
|
19
|
+
char *nd_file;
|
20
|
+
union {
|
21
|
+
struct RNode *node;
|
22
|
+
ID id;
|
23
|
+
VALUE value;
|
24
|
+
VALUE (*cfunc)(ANYARGS);
|
25
|
+
ID *tbl;
|
26
|
+
} u1;
|
27
|
+
union {
|
28
|
+
struct RNode *node;
|
29
|
+
ID id;
|
30
|
+
long argc;
|
31
|
+
VALUE value;
|
32
|
+
} u2;
|
33
|
+
union {
|
34
|
+
struct RNode *node;
|
35
|
+
ID id;
|
36
|
+
long state;
|
37
|
+
struct global_entry *entry;
|
38
|
+
long cnt;
|
39
|
+
VALUE value;
|
40
|
+
} u3;
|
41
|
+
} NODE;
|
42
|
+
|
18
43
|
typedef struct RVALUE {
|
19
44
|
union {
|
20
45
|
struct {
|
@@ -35,11 +60,9 @@ typedef struct RVALUE {
|
|
35
60
|
struct RFile file;
|
36
61
|
struct RNode node;
|
37
62
|
struct RMatch match;
|
63
|
+
struct RRational rational;
|
64
|
+
struct RComplex complex;
|
38
65
|
} as;
|
39
|
-
#ifdef GC_DEBUG
|
40
|
-
char *file;
|
41
|
-
int line;
|
42
|
-
#endif
|
43
66
|
} RVALUE;
|
44
67
|
|
45
68
|
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
data/ext/utilrb_ext.cc
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <set>
|
3
3
|
|
4
|
+
#ifndef RUBINIUS
|
4
5
|
#ifdef RUBY_IS_19
|
5
6
|
#include "ruby_internals-1.9.h"
|
6
7
|
#else
|
7
|
-
#include <rubyio.h>
|
8
8
|
#include "ruby_internals-1.8.h"
|
9
9
|
#endif
|
10
|
+
#endif
|
10
11
|
|
11
12
|
static VALUE mUtilrb;
|
12
13
|
|
13
14
|
using namespace std;
|
14
15
|
|
16
|
+
#ifndef RUBINIUS
|
15
17
|
static VALUE enumerable_each_uniq_i(VALUE i, VALUE* memo)
|
16
18
|
{
|
17
19
|
set<VALUE>& seen = *reinterpret_cast< set<VALUE>* >(memo);
|
@@ -34,21 +36,6 @@ static VALUE enumerable_each_uniq(VALUE self)
|
|
34
36
|
return self;
|
35
37
|
}
|
36
38
|
|
37
|
-
#ifndef RUBY_IS_19
|
38
|
-
/* call-seq:
|
39
|
-
* io.clearerr => nil
|
40
|
-
*
|
41
|
-
* Clear all error flags on the IO
|
42
|
-
*/
|
43
|
-
static VALUE io_clearerr(VALUE self)
|
44
|
-
{
|
45
|
-
OpenFile* file;
|
46
|
-
file = RFILE(self)->fptr;
|
47
|
-
clearerr(file->f);
|
48
|
-
return Qnil;
|
49
|
-
}
|
50
|
-
#endif
|
51
|
-
|
52
39
|
/* call-seq:
|
53
40
|
* Kernel.is_singleton?(object)
|
54
41
|
*
|
@@ -120,6 +107,7 @@ static VALUE proc_line(VALUE self)
|
|
120
107
|
|
121
108
|
static VALUE kernel_is_immediate(VALUE klass, VALUE object)
|
122
109
|
{ return IMMEDIATE_P(object) ? Qtrue : Qfalse; }
|
110
|
+
#endif
|
123
111
|
|
124
112
|
extern "C" void Init_value_set();
|
125
113
|
extern "C" void Init_swap();
|
@@ -129,19 +117,21 @@ extern "C" void Init_utilrb_ext()
|
|
129
117
|
{
|
130
118
|
mUtilrb = rb_define_module("Utilrb");
|
131
119
|
|
120
|
+
#ifndef RUBINIUS
|
132
121
|
rb_define_method(rb_mEnumerable, "each_uniq", RUBY_METHOD_FUNC(enumerable_each_uniq), 0);
|
133
122
|
rb_define_method(rb_mKernel, "is_singleton?", RUBY_METHOD_FUNC(kernel_is_singleton_p), 0);
|
134
123
|
#ifndef RUBY_IS_19
|
135
124
|
rb_define_method(rb_cProc, "same_body?", RUBY_METHOD_FUNC(proc_same_body_p), 1);
|
136
125
|
rb_define_method(rb_cProc, "file", RUBY_METHOD_FUNC(proc_file), 0);
|
137
126
|
rb_define_method(rb_cProc, "line", RUBY_METHOD_FUNC(proc_line), 0);
|
138
|
-
rb_define_method(rb_cIO, "clearerr", RUBY_METHOD_FUNC(io_clearerr), 0);
|
139
127
|
#endif
|
140
128
|
|
141
129
|
rb_define_singleton_method(rb_mKernel, "immediate?", RUBY_METHOD_FUNC(kernel_is_immediate), 1);
|
142
130
|
|
143
|
-
Init_value_set();
|
144
131
|
Init_swap();
|
145
132
|
Init_weakref(mUtilrb);
|
133
|
+
#endif
|
134
|
+
|
135
|
+
Init_value_set();
|
146
136
|
}
|
147
137
|
|
data/ext/value_set.cc
CHANGED
@@ -106,7 +106,7 @@ static VALUE value_set_to_value_set(VALUE self) { return self; }
|
|
106
106
|
static VALUE value_set_dup(VALUE vself, VALUE vother)
|
107
107
|
{
|
108
108
|
ValueSet const& self = get_wrapped_set(vself);
|
109
|
-
VALUE vresult =
|
109
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
110
110
|
ValueSet& result = get_wrapped_set(vresult);
|
111
111
|
for (ValueSet::const_iterator it = self.begin(); it != self.end(); ++it)
|
112
112
|
result.insert(result.end(), *it);
|
@@ -142,7 +142,7 @@ static VALUE value_set_union(VALUE vself, VALUE vother)
|
|
142
142
|
rb_raise(rb_eArgError, "expected a ValueSet");
|
143
143
|
ValueSet const& other = get_wrapped_set(vother);
|
144
144
|
|
145
|
-
VALUE vresult =
|
145
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
146
146
|
ValueSet& result = get_wrapped_set(vresult);
|
147
147
|
std::set_union(self.begin(), self.end(), other.begin(), other.end(),
|
148
148
|
std::inserter(result, result.end()));
|
@@ -179,7 +179,7 @@ static VALUE value_set_intersection(VALUE vself, VALUE vother)
|
|
179
179
|
rb_raise(rb_eArgError, "expected a ValueSet");
|
180
180
|
ValueSet const& other = get_wrapped_set(vother);
|
181
181
|
|
182
|
-
VALUE vresult =
|
182
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
183
183
|
ValueSet& result = get_wrapped_set(vresult);
|
184
184
|
std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
|
185
185
|
std::inserter(result, result.end()));
|
@@ -230,7 +230,7 @@ static VALUE value_set_difference(VALUE vself, VALUE vother)
|
|
230
230
|
rb_raise(rb_eArgError, "expected a ValueSet");
|
231
231
|
ValueSet const& other = get_wrapped_set(vother);
|
232
232
|
|
233
|
-
VALUE vresult =
|
233
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
234
234
|
ValueSet& result = get_wrapped_set(vresult);
|
235
235
|
std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
|
236
236
|
std::inserter(result, result.end()));
|
@@ -307,13 +307,6 @@ static VALUE value_set_initialize_copy(VALUE vself, VALUE vother)
|
|
307
307
|
|
308
308
|
|
309
309
|
|
310
|
-
static VALUE enumerable_to_value_set_i(VALUE i, VALUE* memo)
|
311
|
-
{
|
312
|
-
ValueSet& result = *reinterpret_cast<ValueSet*>(memo);
|
313
|
-
result.insert(i);
|
314
|
-
return Qnil;
|
315
|
-
}
|
316
|
-
|
317
310
|
/* call-seq:
|
318
311
|
* to_value_set => value_set
|
319
312
|
*
|
@@ -321,17 +314,24 @@ static VALUE enumerable_to_value_set_i(VALUE i, VALUE* memo)
|
|
321
314
|
*/
|
322
315
|
static VALUE array_to_value_set(VALUE self)
|
323
316
|
{
|
324
|
-
VALUE vresult =
|
317
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
325
318
|
ValueSet& result = get_wrapped_set(vresult);
|
326
319
|
|
327
|
-
|
328
|
-
long size = RARRAY(self)->len;
|
320
|
+
long size = RARRAY_LEN(self);
|
329
321
|
for (int i = 0; i < size; ++i)
|
330
|
-
result.insert(
|
322
|
+
result.insert(rb_ary_entry(self, i));
|
331
323
|
|
332
324
|
return vresult;
|
333
325
|
}
|
334
326
|
|
327
|
+
#ifndef RUBINIUS
|
328
|
+
static VALUE enumerable_to_value_set_i(VALUE i, VALUE* memo)
|
329
|
+
{
|
330
|
+
ValueSet& result = *reinterpret_cast<ValueSet*>(memo);
|
331
|
+
result.insert(i);
|
332
|
+
return Qnil;
|
333
|
+
}
|
334
|
+
|
335
335
|
/* call-seq:
|
336
336
|
* enum.to_value_set => value_set
|
337
337
|
*
|
@@ -339,12 +339,13 @@ static VALUE array_to_value_set(VALUE self)
|
|
339
339
|
*/
|
340
340
|
static VALUE enumerable_to_value_set(VALUE self)
|
341
341
|
{
|
342
|
-
VALUE vresult =
|
342
|
+
VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
|
343
343
|
ValueSet& result = get_wrapped_set(vresult);
|
344
344
|
|
345
345
|
rb_iterate(rb_each, self, RUBY_METHOD_FUNC(enumerable_to_value_set_i), reinterpret_cast<VALUE>(&result));
|
346
346
|
return vresult;
|
347
347
|
}
|
348
|
+
#endif
|
348
349
|
|
349
350
|
/*
|
350
351
|
* Document-class: ValueSet
|
@@ -357,7 +358,9 @@ static VALUE enumerable_to_value_set(VALUE self)
|
|
357
358
|
|
358
359
|
extern "C" void Init_value_set()
|
359
360
|
{
|
361
|
+
#ifndef RUBINIUS
|
360
362
|
rb_define_method(rb_mEnumerable, "to_value_set", RUBY_METHOD_FUNC(enumerable_to_value_set), 0);
|
363
|
+
#endif
|
361
364
|
rb_define_method(rb_cArray, "to_value_set", RUBY_METHOD_FUNC(array_to_value_set), 0);
|
362
365
|
|
363
366
|
cValueSet = rb_define_class("ValueSet", rb_cObject);
|
data/ext/weakref.cc
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
#include <set>
|
2
2
|
#include <map>
|
3
3
|
#include <ruby.h>
|
4
|
+
#ifdef RUBY_IS_19
|
5
|
+
#include <ruby/intern.h>
|
6
|
+
#else
|
4
7
|
#include <intern.h>
|
8
|
+
#endif
|
5
9
|
|
6
10
|
using std::set;
|
7
11
|
using std::map;
|
@@ -12,6 +16,7 @@ static VALUE cRefError;
|
|
12
16
|
/* Weakref internal structure. +obj+ is Qnil before initialization and Qundef
|
13
17
|
* after finalization */
|
14
18
|
struct WeakRef {
|
19
|
+
VALUE ruby_ref;
|
15
20
|
VALUE obj;
|
16
21
|
};
|
17
22
|
|
@@ -22,12 +27,25 @@ typedef map< VALUE, VALUE > ObjFromRefID;
|
|
22
27
|
RefFromObjID from_obj_id;
|
23
28
|
ObjFromRefID from_ref_id;
|
24
29
|
|
25
|
-
static void weakref_free(WeakRef const*
|
30
|
+
static void weakref_free(WeakRef const* ref)
|
31
|
+
{
|
32
|
+
VALUE ref_id = rb_obj_id(ref->ruby_ref);
|
33
|
+
ObjFromRefID::iterator obj_it = from_ref_id.find(ref_id);
|
34
|
+
if (obj_it != from_ref_id.end())
|
35
|
+
{
|
36
|
+
VALUE obj_id = rb_obj_id(obj_it->second);
|
37
|
+
RefFromObjID::iterator ref_set = from_obj_id.find(obj_id);
|
38
|
+
ref_set->second.erase(ref->ruby_ref);
|
39
|
+
from_ref_id.erase(obj_it);
|
40
|
+
}
|
41
|
+
delete ref;
|
42
|
+
}
|
26
43
|
static VALUE weakref_alloc(VALUE klass)
|
27
44
|
{
|
28
45
|
WeakRef* ref = new WeakRef;
|
29
46
|
ref->obj = Qnil;
|
30
|
-
|
47
|
+
ref->ruby_ref = Data_Wrap_Struct(klass, NULL, weakref_free, ref);
|
48
|
+
return ref->ruby_ref;
|
31
49
|
}
|
32
50
|
|
33
51
|
static WeakRef& get_weakref(VALUE self)
|
@@ -46,40 +64,24 @@ static VALUE do_object_finalize(VALUE mod, VALUE obj_id)
|
|
46
64
|
ObjSet::iterator const end = ref_set->second.end();
|
47
65
|
for (; it != end; ++it)
|
48
66
|
{
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
ref.obj = Qundef;
|
59
|
-
}
|
67
|
+
// Do NOT use Data_Wrap_Struct here, it would break on recent Ruby
|
68
|
+
// interpreters. The reason is that the object type is reset during
|
69
|
+
// GC -- and the call to free functions is deferred.
|
70
|
+
//
|
71
|
+
// So, at this point, we're sure we have a RDATA in *it (otherwise
|
72
|
+
// weakref_free would have been called), but we can't use
|
73
|
+
// Data_Wrap_Struct because that would crash.
|
74
|
+
WeakRef& ref = *reinterpret_cast<WeakRef*>(RDATA(*it)->data);;
|
75
|
+
ref.obj = Qundef;
|
60
76
|
from_ref_id.erase(rb_obj_id(*it));
|
61
77
|
}
|
62
|
-
|
63
78
|
from_obj_id.erase(obj_id);
|
64
79
|
}
|
65
80
|
return Qnil;
|
66
81
|
}
|
67
82
|
|
68
|
-
static VALUE do_weakref_finalize(VALUE mod, VALUE ref_id)
|
69
|
-
{
|
70
|
-
ObjFromRefID::iterator obj_it = from_ref_id.find(ref_id);
|
71
|
-
if (obj_it != from_ref_id.end())
|
72
|
-
{
|
73
|
-
VALUE obj_id = rb_obj_id(obj_it->second);
|
74
|
-
RefFromObjID::iterator ref_set = from_obj_id.find(obj_id);
|
75
|
-
ref_set->second.erase(ref_id & ~FIXNUM_FLAG);
|
76
|
-
from_ref_id.erase(obj_it);
|
77
|
-
}
|
78
|
-
return Qnil;
|
79
|
-
}
|
80
|
-
|
81
83
|
// Note: the Ruby code has already registered +do_object_finalize+ as the
|
82
|
-
// finalizer for +obj
|
84
|
+
// finalizer for +obj+.
|
83
85
|
//
|
84
86
|
// It is forbidden to make a weakref-of-weakref or a weakref of an immediate
|
85
87
|
// object
|
@@ -134,7 +136,6 @@ extern "C" void Init_weakref(VALUE mUtilrb)
|
|
134
136
|
rb_define_alloc_func(cWeakRef, weakref_alloc);
|
135
137
|
|
136
138
|
rb_define_singleton_method(cWeakRef, "do_object_finalize", RUBY_METHOD_FUNC(do_object_finalize), 1);
|
137
|
-
rb_define_singleton_method(cWeakRef, "do_weakref_finalize", RUBY_METHOD_FUNC(do_weakref_finalize), 1);
|
138
139
|
rb_define_singleton_method(cWeakRef, "refcount", RUBY_METHOD_FUNC(refcount), 1);
|
139
140
|
rb_define_method(cWeakRef, "do_initialize", RUBY_METHOD_FUNC(weakref_do_initialize), 1);
|
140
141
|
rb_define_method(cWeakRef, "get", RUBY_METHOD_FUNC(weakref_get), 0);
|
@@ -1,16 +1,53 @@
|
|
1
1
|
# Displays a set of data into a column-formatted table
|
2
2
|
class ColumnFormatter
|
3
|
-
MARGIN =
|
4
|
-
SCREEN_WIDTH =
|
3
|
+
MARGIN = 1
|
4
|
+
SCREEN_WIDTH = 80
|
5
5
|
|
6
|
-
#
|
7
|
-
# a hash being a column_name => value data set. The special 'label' column
|
8
|
-
# name is used to give a name to each line.
|
6
|
+
# Formats the given array of hash column-wise.
|
9
7
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
8
|
+
# +data+ is an array of hash. In this array, each element is a sample. The
|
9
|
+
# column names are defined from the hash keys. If one hash does not have a
|
10
|
+
# value for a column, "-" is displayed instead.
|
11
|
+
#
|
12
|
+
# In the output, the columns are ordered alphabetically by default.
|
13
|
+
# Alternatively, they can be ordered by giving an :order option which is an
|
14
|
+
# array of string:
|
15
|
+
#
|
16
|
+
# from_hashes(data, STDOUT, :order => %w{Col0 Col1 Col2})
|
17
|
+
#
|
18
|
+
# Finally, the method can yield the set of available columns to a block (if
|
19
|
+
# given), and this block should return an ordered array of string.
|
20
|
+
#
|
21
|
+
# In both cases, columns not listed in the ordering array are not displayed.
|
22
|
+
#
|
23
|
+
# The formatting can be controlled by the following options:
|
24
|
+
# header_delimiter::
|
25
|
+
# if true, displays a line of dashes between the header
|
26
|
+
# and the rest of the table
|
27
|
+
# column_delimiter::
|
28
|
+
# a string that is inserted between columns
|
29
|
+
# left_padding::
|
30
|
+
# a string that is inserted in front of each line
|
31
|
+
# order::
|
32
|
+
# an array of column names, defining which columns should be displayed,
|
33
|
+
# and in which order they should be displayed. See above for more
|
34
|
+
# explanations.
|
35
|
+
# screen_width::
|
36
|
+
# if the table is wider than this count of characters, it is split into
|
37
|
+
# multiple tables.
|
38
|
+
# margin::
|
39
|
+
# defines how many spaces are inserted between two columns.
|
40
|
+
def self.from_hashes(data, io = STDOUT, options = Hash.new)
|
41
|
+
options = validate_options options, :margin => MARGIN,
|
42
|
+
:screen_width => SCREEN_WIDTH,
|
43
|
+
:header_delimiter => false,
|
44
|
+
:column_delimiter => "",
|
45
|
+
:left_padding => "",
|
46
|
+
:order => nil
|
47
|
+
|
48
|
+
margin = options[:margin]
|
49
|
+
screen_width = options[:screen_width]
|
50
|
+
|
14
51
|
width = Hash.new
|
15
52
|
|
16
53
|
# First, determine the columns width and height, and
|
@@ -35,7 +72,8 @@ class ColumnFormatter
|
|
35
72
|
# Then ask the user to sort the keys for us
|
36
73
|
names = width.keys.dup
|
37
74
|
names.delete('label')
|
38
|
-
names = if
|
75
|
+
names = if options[:order] then options[:order]
|
76
|
+
elsif block_given? then yield(names)
|
39
77
|
else names.sort
|
40
78
|
end
|
41
79
|
|
@@ -45,7 +83,7 @@ class ColumnFormatter
|
|
45
83
|
if width.has_key?('label')
|
46
84
|
line_n = ['label']
|
47
85
|
line_w = width['label']
|
48
|
-
format = ["
|
86
|
+
format = ["%-#{line_w}s"]
|
49
87
|
else
|
50
88
|
line_n = []
|
51
89
|
line_w = 0
|
@@ -57,11 +95,18 @@ class ColumnFormatter
|
|
57
95
|
col_w = width[col_n] || 0
|
58
96
|
line_n << col_n
|
59
97
|
line_w += col_w
|
60
|
-
format << "
|
98
|
+
format << "%-#{col_w}s"
|
61
99
|
end
|
62
100
|
|
63
|
-
format = format.join(" " * margin)
|
64
|
-
|
101
|
+
format = format.join(" " * margin + options[:column_delimiter] + " " * margin)
|
102
|
+
header_line = format % line_n
|
103
|
+
io.puts options[:left_padding] + header_line
|
104
|
+
if options[:header_delimiter]
|
105
|
+
io.puts options[:left_padding] + "-" * header_line.length
|
106
|
+
end
|
107
|
+
|
108
|
+
format = options[:left_padding] + format
|
109
|
+
|
65
110
|
data.each do |line_data|
|
66
111
|
line_data = line_data.values_at(*line_n)
|
67
112
|
line_data.map! { |v| v || '-' }
|
data/lib/utilrb/common.rb
CHANGED
@@ -20,11 +20,17 @@ class SequenceEnumerator
|
|
20
20
|
include Enumerable
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
enumerator = if defined?(Enumerable::Enumerator)
|
24
|
+
Enumerable::Enumerator
|
25
|
+
else
|
26
|
+
Enumerator
|
27
|
+
end
|
28
|
+
|
29
|
+
enumerator.class_eval do # :nodoc
|
24
30
|
# Builds a sequence of enumeration object.
|
25
31
|
# ([1, 2].enum_for + [2, 3].enum_for).to_a # => [1, 2, 2, 3]
|
26
32
|
def +(other_enumerator) # :nodoc
|
27
|
-
|
33
|
+
SequenceEnumerator.new << self << other_enumerator
|
28
34
|
end
|
29
35
|
end
|
30
36
|
|
@@ -2,9 +2,15 @@ require 'utilrb/common'
|
|
2
2
|
require 'enumerator'
|
3
3
|
require 'set'
|
4
4
|
|
5
|
+
enumerator = if defined?(Enumerable::Enumerator)
|
6
|
+
Enumerable::Enumerator
|
7
|
+
else
|
8
|
+
Enumerator
|
9
|
+
end
|
10
|
+
|
5
11
|
# Enumerator object which removes duplicate entries.
|
6
12
|
# See also Object#enum_uniq and Enumerable#each_uniq
|
7
|
-
class UniqEnumerator <
|
13
|
+
class UniqEnumerator < enumerator
|
8
14
|
# Creates the enumerator on +obj+ using the method +enum_with+ to
|
9
15
|
# enumerate. The method will be called with the arguments in +args+.
|
10
16
|
#
|
data/lib/utilrb/pkgconfig.rb
CHANGED
@@ -1,10 +1,44 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
1
3
|
module Utilrb
|
2
4
|
# Access to information from pkg-config(1)
|
5
|
+
#
|
6
|
+
# This class allows to enumerate the pkg-config packages available, and
|
7
|
+
# create a PkgConfig object that allows to get access to the pkgconfig
|
8
|
+
# information.
|
9
|
+
#
|
10
|
+
# Create a new pkgconfig object with
|
11
|
+
#
|
12
|
+
# pkg = PkgConfig.new(name)
|
13
|
+
#
|
14
|
+
# It raises PkgConfig::NotFound if the package is not available.
|
15
|
+
#
|
16
|
+
# Then, the classical include directory and library directory flags can be
|
17
|
+
# listed with
|
18
|
+
#
|
19
|
+
# pkg.include_dirs
|
20
|
+
# pkg.library_dirs
|
21
|
+
#
|
22
|
+
# Standard fields are available with
|
23
|
+
#
|
24
|
+
# pkg.cflags
|
25
|
+
# pkg.cflags_only_I
|
26
|
+
# pkg.cflags_only_other
|
27
|
+
# pkg.libs
|
28
|
+
# pkg.libs_only_L
|
29
|
+
# pkg.libs_only_l
|
30
|
+
# pkg.libs_only_other
|
31
|
+
# pkg.static
|
32
|
+
#
|
33
|
+
# Arbitrary variables defined in the .pc file can be accessed with
|
34
|
+
#
|
35
|
+
# pkg.prefix
|
36
|
+
# pkg.libdir
|
37
|
+
#
|
3
38
|
class PkgConfig
|
4
39
|
class NotFound < RuntimeError
|
5
40
|
attr_reader :name
|
6
41
|
def initialize(name); @name = name end
|
7
|
-
def to_s; "#{name} is not available to pkg-config" end
|
8
42
|
end
|
9
43
|
|
10
44
|
# The module name
|
@@ -16,7 +50,7 @@ module Utilrb
|
|
16
50
|
# Raises PkgConfig::NotFound if the module does not exist
|
17
51
|
def initialize(name)
|
18
52
|
if !system("pkg-config --exists #{name}")
|
19
|
-
raise NotFound.new(name)
|
53
|
+
raise NotFound.new(name), "#{name} is not available to pkg-config"
|
20
54
|
end
|
21
55
|
|
22
56
|
@name = name
|
@@ -25,24 +59,58 @@ module Utilrb
|
|
25
59
|
@variables = Hash.new
|
26
60
|
end
|
27
61
|
|
28
|
-
def self.define_action(action)
|
62
|
+
def self.define_action(action) # :nodoc:
|
29
63
|
define_method(action.gsub(/-/, '_')) do
|
30
64
|
@actions[action] ||= `pkg-config --#{action} #{name}`.chomp.strip
|
31
65
|
end
|
32
66
|
nil
|
33
67
|
end
|
34
68
|
|
69
|
+
# Returns the list of include directories listed in the Cflags: section
|
70
|
+
# of the pkgconfig file
|
71
|
+
def include_dirs
|
72
|
+
Shellwords.shellsplit(cflags_only_I).map { |v| v[2..-1] }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the list of library directories listed in the Libs: section
|
76
|
+
# of the pkgconfig file
|
77
|
+
def library_dirs
|
78
|
+
Shellwords.shellsplit(libs_only_L).map { |v| v[2..-1] }
|
79
|
+
end
|
80
|
+
|
35
81
|
ACTIONS = %w{cflags cflags-only-I cflags-only-other
|
36
82
|
libs libs-only-L libs-only-l libs-only-other static}
|
37
83
|
ACTIONS.each { |action| define_action(action) }
|
38
84
|
|
39
|
-
def method_missing(varname, *args, &proc)
|
85
|
+
def method_missing(varname, *args, &proc) # :nodoc:
|
40
86
|
if args.empty?
|
41
87
|
@variables[varname] ||= `pkg-config --variable=#{varname} #{name}`.chomp.strip
|
42
88
|
else
|
43
89
|
super(varname, *args, &proc)
|
44
90
|
end
|
45
91
|
end
|
92
|
+
|
93
|
+
# Returns true if there is a package with this name
|
94
|
+
def self.has_package?(name)
|
95
|
+
enum_for(:each_package, name).find { true }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Yields the package names of available packages. If +regex+ is given,
|
99
|
+
# lists only the names that match the regular expression.
|
100
|
+
def self.each_package(regex = nil)
|
101
|
+
`pkg-config --list-all`.chomp.split.
|
102
|
+
each do |line|
|
103
|
+
line =~ /^([^\s]+)/
|
104
|
+
name = $1
|
105
|
+
if regex
|
106
|
+
if regex === name
|
107
|
+
yield(name)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
yield(name)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
46
114
|
end
|
47
115
|
end
|
48
116
|
|
data/lib/utilrb/weakref.rb
CHANGED
@@ -7,9 +7,9 @@ Utilrb.require_ext("Utilrb::WeakRef") do
|
|
7
7
|
if obj.kind_of?(WeakRef)
|
8
8
|
raise ArgumentError, "cannot create a weakref of a weakref"
|
9
9
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
unless WeakRef.refcount(obj)
|
11
|
+
ObjectSpace.define_finalizer(obj, self.class.method(:do_object_finalize))
|
12
|
+
end
|
13
13
|
do_initialize(obj)
|
14
14
|
end
|
15
15
|
end
|
data/test/test_pkgconfig.rb
CHANGED
@@ -26,9 +26,23 @@ class TC_PkgConfig < Test::Unit::TestCase
|
|
26
26
|
assert_equal(%w{-Ia_prefix/include -O3}.to_set, pkg.cflags.split.to_set)
|
27
27
|
assert_equal('-Ia_prefix/include', pkg.cflags_only_I)
|
28
28
|
assert_equal('-O3', pkg.cflags_only_other)
|
29
|
+
assert_equal(['a_prefix/include'], pkg.include_dirs)
|
29
30
|
|
30
31
|
assert_equal(%w{-ltest -lother -La_prefix/lib}.to_set, pkg.libs.split.to_set)
|
31
32
|
assert_equal('-La_prefix/lib', pkg.libs_only_L)
|
32
33
|
assert_equal(%w{-ltest -lother}.to_set, pkg.libs_only_l.split.to_set)
|
34
|
+
assert_equal(['a_prefix/lib'], pkg.library_dirs)
|
35
|
+
|
36
|
+
pkg = PkgConfig.new('test_pkgconfig_empty')
|
37
|
+
assert_equal('a_prefix', pkg.prefix)
|
38
|
+
assert_equal("", pkg.cflags)
|
39
|
+
assert_equal('', pkg.cflags_only_I)
|
40
|
+
assert_equal('', pkg.cflags_only_other)
|
41
|
+
assert_equal([], pkg.include_dirs)
|
42
|
+
|
43
|
+
assert_equal('', pkg.libs)
|
44
|
+
assert_equal('', pkg.libs_only_L)
|
45
|
+
assert_equal('', pkg.libs_only_l)
|
46
|
+
assert_equal([], pkg.library_dirs)
|
33
47
|
end
|
34
48
|
end
|
data/test/test_weakref.rb
CHANGED
@@ -19,6 +19,18 @@ Utilrb.require_ext('TC_WeakRef') do
|
|
19
19
|
assert_raises(ArgumentError) { Utilrb::WeakRef.new(ref) }
|
20
20
|
end
|
21
21
|
|
22
|
+
def create_deep_pair(lvl)
|
23
|
+
if lvl == 0
|
24
|
+
100.times do
|
25
|
+
obj = Object.new
|
26
|
+
WeakRef.new(obj)
|
27
|
+
obj = nil
|
28
|
+
end
|
29
|
+
else
|
30
|
+
create_deep_pair(lvl - 1)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
22
34
|
def create_deep_ref(lvl)
|
23
35
|
if lvl == 0
|
24
36
|
obj = Object.new
|
@@ -38,17 +50,31 @@ Utilrb.require_ext('TC_WeakRef') do
|
|
38
50
|
end
|
39
51
|
end
|
40
52
|
|
41
|
-
def
|
53
|
+
def test_finalized_objects
|
42
54
|
refs, obj_id = create_deep_ref(100)
|
55
|
+
create_deep_ref(200) # erase the stack ...
|
43
56
|
GC.start
|
44
57
|
for ref in refs
|
45
58
|
assert_raises(WeakRef::RefError) { ref.get }
|
46
59
|
end
|
47
60
|
assert_equal(nil, WeakRef.refcount(obj_id))
|
61
|
+
end
|
48
62
|
|
63
|
+
def test_finalized_refs
|
49
64
|
obj, ref_id = create_deep_obj(100)
|
65
|
+
create_deep_ref(100) # erase the stack ...
|
66
|
+
GC.start
|
67
|
+
assert_raises(RangeError) do
|
68
|
+
ref = ObjectSpace._id2ref(ref_id)
|
69
|
+
if !ref.kind_of?(WeakRef)
|
70
|
+
raise RangeError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_finalization_ordering_crash
|
76
|
+
create_deep_pair(100)
|
50
77
|
GC.start
|
51
|
-
assert_raises(RangeError) { ObjectSpace._id2ref(ref_id) }
|
52
78
|
end
|
53
79
|
end
|
54
80
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utilrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Joyeux
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-06-22 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -34,15 +34,29 @@ dependencies:
|
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: hoe
|
37
|
-
type: :
|
37
|
+
type: :development
|
38
38
|
version_requirement:
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 1.
|
43
|
+
version: 1.12.2
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: |-
|
46
|
+
== What is Utilrb ?
|
47
|
+
Utilrb is yet another Ruby toolkit, in the spirit of facets. It includes all
|
48
|
+
the standard class extensions I use in my own projects like Genom.rb.
|
49
|
+
|
50
|
+
== Installation
|
51
|
+
The only dependency Utilrb has is flexmock if you want to run tests. It is
|
52
|
+
available as a gem, so you can run
|
53
|
+
|
54
|
+
gem install flexmock
|
55
|
+
|
56
|
+
== Utilrb's C extension
|
57
|
+
Utilrb includes a C extension in ext/. It is optional, but some of the
|
58
|
+
functionalities will be disabled if it is not present. Trying to require
|
59
|
+
a file in which there is a C-only feature will yield a warning on STDOUT.
|
46
60
|
email:
|
47
61
|
- sylvain.joyeux@m4x.org
|
48
62
|
executables: []
|
@@ -145,7 +159,9 @@ files:
|
|
145
159
|
- test/test_unbound_method.rb
|
146
160
|
- test/test_weakref.rb
|
147
161
|
has_rdoc: true
|
148
|
-
homepage:
|
162
|
+
homepage: http://utilrb.rubyforge.org
|
163
|
+
licenses: []
|
164
|
+
|
149
165
|
post_install_message:
|
150
166
|
rdoc_options:
|
151
167
|
- --main
|
@@ -168,9 +184,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
184
|
requirements: []
|
169
185
|
|
170
186
|
rubyforge_project: utilrb
|
171
|
-
rubygems_version: 1.
|
187
|
+
rubygems_version: 1.3.4
|
172
188
|
signing_key:
|
173
|
-
specification_version:
|
189
|
+
specification_version: 3
|
174
190
|
summary: Yet another Ruby toolkit
|
175
191
|
test_files:
|
176
192
|
- test/test_time.rb
|