rmtools 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +15 -0
- data/Manifest.txt +37 -0
- data/README.txt +10 -0
- data/Rakefile +39 -0
- data/ext/extconf.rb +12 -0
- data/ext/rmtools.cpp +529 -0
- data/ext/rmtools.h +161 -0
- data/lib/rmtools.rb +53 -0
- data/lib/rmtools/arguments.rb +24 -0
- data/lib/rmtools/array.rb +189 -0
- data/lib/rmtools/binding.rb +23 -0
- data/lib/rmtools/boolean.rb +57 -0
- data/lib/rmtools/coloring.rb +82 -0
- data/lib/rmtools/cyr-time.rb +49 -0
- data/lib/rmtools/cyrilic.rb +124 -0
- data/lib/rmtools/dumps.rb +192 -0
- data/lib/rmtools/enum.rb +90 -0
- data/lib/rmtools/hash.rb +40 -0
- data/lib/rmtools/io.rb +303 -0
- data/lib/rmtools/js.rb +25 -0
- data/lib/rmtools/limited_string.rb +17 -0
- data/lib/rmtools/logging.rb +158 -0
- data/lib/rmtools/module.rb +113 -0
- data/lib/rmtools/numeric.rb +82 -0
- data/lib/rmtools/object.rb +74 -0
- data/lib/rmtools/printing.rb +41 -0
- data/lib/rmtools/proc.rb +25 -0
- data/lib/rmtools/random.rb +195 -0
- data/lib/rmtools/range.rb +100 -0
- data/lib/rmtools/setup.rb +21 -0
- data/lib/rmtools/string.rb +276 -0
- data/lib/rmtools/string_to_proc.rb +113 -0
- data/lib/rmtools/stringscanner.rb +58 -0
- data/lib/rmtools/time.rb +32 -0
- data/lib/rmtools/traceback.rb +106 -0
- data/lib/rmtools/tree.rb +71 -0
- metadata +191 -0
data/ext/rmtools.h
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
#ifndef __RUBY_INTERNALS_HH__
|
2
|
+
#define __RUBY_INTERNALS_HH__
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
|
6
|
+
#ifdef RUBY_IS_19
|
7
|
+
|
8
|
+
#include <ruby/intern.h>
|
9
|
+
#include <ruby/defines.h>
|
10
|
+
#include <ruby/re.h>
|
11
|
+
#include <assert.h>
|
12
|
+
|
13
|
+
# define ARY_EMBED_P(ary) \
|
14
|
+
(assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
|
15
|
+
FL_TEST(ary, RARRAY_EMBED_FLAG))
|
16
|
+
#define ARY_SET_EMBED_LEN(ary, n) do { \
|
17
|
+
long tmp_n = n; \
|
18
|
+
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
|
19
|
+
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
|
20
|
+
} while (0)
|
21
|
+
#define ARY_SET_HEAP_LEN(ary, n) do { \
|
22
|
+
RARRAY(ary)->as.heap.len = n; \
|
23
|
+
} while (0)
|
24
|
+
#define ARY_SET_LEN(ary, n) do { \
|
25
|
+
if (ARY_EMBED_P(ary)) { \
|
26
|
+
ARY_SET_EMBED_LEN(ary, n); \
|
27
|
+
} \
|
28
|
+
else { \
|
29
|
+
ARY_SET_HEAP_LEN(ary, n); \
|
30
|
+
} \
|
31
|
+
} while (0)
|
32
|
+
|
33
|
+
#define BDIGITS(x) ((BDIGIT*)RBIGNUM_DIGITS(x))
|
34
|
+
|
35
|
+
// copied from utilrb gem
|
36
|
+
typedef struct RNode {
|
37
|
+
unsigned long flags;
|
38
|
+
char *nd_file;
|
39
|
+
union {
|
40
|
+
struct RNode *node;
|
41
|
+
ID id;
|
42
|
+
VALUE value;
|
43
|
+
VALUE (*cfunc)(ANYARGS);
|
44
|
+
ID *tbl;
|
45
|
+
} u1;
|
46
|
+
union {
|
47
|
+
struct RNode *node;
|
48
|
+
ID id;
|
49
|
+
long argc;
|
50
|
+
VALUE value;
|
51
|
+
} u2;
|
52
|
+
union {
|
53
|
+
struct RNode *node;
|
54
|
+
ID id;
|
55
|
+
long state;
|
56
|
+
struct global_entry *entry;
|
57
|
+
long cnt;
|
58
|
+
VALUE value;
|
59
|
+
} u3;
|
60
|
+
} NODE;
|
61
|
+
|
62
|
+
typedef struct RVALUE {
|
63
|
+
union {
|
64
|
+
struct {
|
65
|
+
VALUE flags; /* always 0 for freed obj */
|
66
|
+
struct RVALUE *next;
|
67
|
+
} free;
|
68
|
+
struct RBasic basic;
|
69
|
+
struct RObject object;
|
70
|
+
struct RClass klass;
|
71
|
+
struct RFloat flonum;
|
72
|
+
struct RString string;
|
73
|
+
struct RArray array;
|
74
|
+
struct RRegexp regexp;
|
75
|
+
struct RHash hash;
|
76
|
+
struct RData data;
|
77
|
+
struct RStruct rstruct;
|
78
|
+
struct RBignum bignum;
|
79
|
+
struct RFile file;
|
80
|
+
struct RNode node;
|
81
|
+
struct RMatch match;
|
82
|
+
struct RRational rational;
|
83
|
+
struct RComplex complex;
|
84
|
+
} as;
|
85
|
+
} RVALUE;
|
86
|
+
|
87
|
+
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
88
|
+
|
89
|
+
#else
|
90
|
+
|
91
|
+
#include <intern.h>
|
92
|
+
#include <node.h>
|
93
|
+
#include <env.h>
|
94
|
+
#include <re.h>
|
95
|
+
|
96
|
+
# define STR_SET_LEN(x, i) (RSTRING(x)->len = (i))
|
97
|
+
|
98
|
+
# define RFLOAT_VALUE(f) (RFLOAT(f)->value)
|
99
|
+
|
100
|
+
# define RBIGNUM_DIGITS(f) (RBIGNUM(f)->digits)
|
101
|
+
# define RBIGNUM_LEN(f) (RBIGNUM(f)->len)
|
102
|
+
|
103
|
+
# define ARY_SET_LEN(x, i) (RARRAY(x)->len = (i))
|
104
|
+
|
105
|
+
# define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
|
106
|
+
|
107
|
+
// copied from utilrb gem
|
108
|
+
typedef struct RVALUE {
|
109
|
+
union {
|
110
|
+
struct {
|
111
|
+
unsigned long flags; /* always 0 for freed obj */
|
112
|
+
struct RVALUE *next;
|
113
|
+
} free;
|
114
|
+
struct RBasic basic;
|
115
|
+
struct RObject object;
|
116
|
+
struct RClass klass;
|
117
|
+
struct RFloat flonum;
|
118
|
+
struct RString string;
|
119
|
+
struct RArray array;
|
120
|
+
struct RRegexp regexp;
|
121
|
+
struct RHash hash;
|
122
|
+
struct RData data;
|
123
|
+
struct RStruct rstruct;
|
124
|
+
struct RBignum bignum;
|
125
|
+
struct RFile file;
|
126
|
+
struct RNode node;
|
127
|
+
struct RMatch match;
|
128
|
+
struct RVarmap varmap;
|
129
|
+
struct SCOPE scope;
|
130
|
+
} as;
|
131
|
+
#ifdef GC_DEBUG
|
132
|
+
char *file;
|
133
|
+
int line;
|
134
|
+
#endif
|
135
|
+
} RVALUE;
|
136
|
+
static const size_t SLOT_SIZE = sizeof(RVALUE);
|
137
|
+
|
138
|
+
|
139
|
+
#endif // 1.9
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
// shortcuts for debug r_r
|
144
|
+
extern void rb_log_std(const char* str)
|
145
|
+
{
|
146
|
+
rb_funcall(rb_gv_get("$log"), rb_intern("debug"), 1, rb_str_new2(str));
|
147
|
+
}
|
148
|
+
extern void rb_log_obj_std(VALUE obj)
|
149
|
+
{
|
150
|
+
rb_funcall(rb_gv_get("$log"), rb_intern("debug"), 1, obj);
|
151
|
+
}
|
152
|
+
extern void rb_log_file(const char* str)
|
153
|
+
{
|
154
|
+
rb_funcall(rb_gv_get("$log"), rb_intern("log"), 1, rb_str_new2(str));
|
155
|
+
}
|
156
|
+
extern void rb_log_file_obj(VALUE obj)
|
157
|
+
{
|
158
|
+
rb_funcall(rb_gv_get("$log"), rb_intern("log"), 1, obj);
|
159
|
+
}
|
160
|
+
|
161
|
+
#endif
|
data/lib/rmtools.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'iconv'
|
3
|
+
require 'cgi'
|
4
|
+
require 'set'
|
5
|
+
require 'strscan'
|
6
|
+
|
7
|
+
# why did I put it in here?
|
8
|
+
# require "bundler/setup"
|
9
|
+
|
10
|
+
# being required *after* rmtools/random it overrides some of a functions and then whine about they are "deprecated", huh
|
11
|
+
require 'activesupport' rescue nil
|
12
|
+
|
13
|
+
module RMTools
|
14
|
+
rmtools = File.expand_path(__FILE__)[0..-4]
|
15
|
+
require "#{rmtools}/string_to_proc"
|
16
|
+
[ 'string_to_proc',
|
17
|
+
'string', 'object', 'module', 'enum', 'array', 'hash',
|
18
|
+
'numeric', 'stringscanner', 'proc', 'io', 'range',
|
19
|
+
|
20
|
+
'js', # js hash getter/setter and string concat logic
|
21
|
+
|
22
|
+
'boolean', # {obj.b -> self or false} with python logic
|
23
|
+
# and native boolean #to_i and #<=>
|
24
|
+
# Since 2.3.8 active_support has analogue: #presence
|
25
|
+
# BTW, why so slow?
|
26
|
+
|
27
|
+
'logging', 'coloring', # lazy logger
|
28
|
+
# with caller processing and highlighting
|
29
|
+
# 'traceback', # python-like traceback for exceptions
|
30
|
+
# uses ANSI coloring; kinda buggy, so better
|
31
|
+
# require 'rmtools/traceback' separately
|
32
|
+
|
33
|
+
|
34
|
+
'printing', # transparent print: print text (or object info) and erase it
|
35
|
+
'limited_string', # for compact string inspecting
|
36
|
+
|
37
|
+
'binding', # binding inspect
|
38
|
+
'arguments', # arguments parsing and types validation
|
39
|
+
|
40
|
+
'cyrilic', 'cyr-time', # String & Regexp methods for Russian processing
|
41
|
+
|
42
|
+
# some bicycles just for convenience
|
43
|
+
'dumps', 'time', 'random'
|
44
|
+
].each {|f| require "#{rmtools}/#{f}"}
|
45
|
+
end
|
46
|
+
|
47
|
+
require "#{rmtools}/rmtools.so" rescue nil
|
48
|
+
|
49
|
+
$log = RMTools::RMLogger.new
|
50
|
+
|
51
|
+
# Comment out in case of any method conflicts
|
52
|
+
# Library methods use module functions explicitly
|
53
|
+
class Object; include RMTools end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
def fetch_opts(defaults=[], opts={})
|
4
|
+
if opts and self[-1].is(Hash) and !defaults[size-1].is(Hash)
|
5
|
+
opts = opts.merge pop
|
6
|
+
end
|
7
|
+
each_index {|i| import(defaults, i) if self[i] == :def}
|
8
|
+
defaults.slice! 0, size
|
9
|
+
concat defaults << opts
|
10
|
+
end
|
11
|
+
alias :get_opts :fetch_opts
|
12
|
+
|
13
|
+
def valid_types(pattern_ary)
|
14
|
+
each_with_index.find {|var, i|
|
15
|
+
pattern = pattern_ary[i]
|
16
|
+
if pattern.is Array
|
17
|
+
pattern.find {|j| !(pattern[j] === var[i])}
|
18
|
+
else !(pattern === var[i])
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Array
|
3
|
+
|
4
|
+
def avg
|
5
|
+
sum.to_f/size
|
6
|
+
end
|
7
|
+
|
8
|
+
def scale(top)
|
9
|
+
case top
|
10
|
+
when Numeric; ratio = max.to_f/top
|
11
|
+
when Array; ratio = zip(top).map {|a,b| b ? a.to_f/b : 0}.max
|
12
|
+
else raise TypeError, "number or array of numbers expceted, #{top.class} given"
|
13
|
+
end
|
14
|
+
map {|e| e/ratio}
|
15
|
+
end
|
16
|
+
|
17
|
+
def sorted_uniq_by(&block)
|
18
|
+
uniq_by(&block).sort_by(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def recursive_find(&b)
|
22
|
+
res = nil
|
23
|
+
each {|e|
|
24
|
+
return e if b[e]
|
25
|
+
if e.resto :recursive_find
|
26
|
+
res = e.recursive_find(&b)
|
27
|
+
return res if res
|
28
|
+
end
|
29
|
+
}
|
30
|
+
res
|
31
|
+
end
|
32
|
+
|
33
|
+
def recursive_find_all(&b)
|
34
|
+
res = []
|
35
|
+
each {|e|
|
36
|
+
res << e if b[e]
|
37
|
+
if e.resto :recursive_find
|
38
|
+
res.concat e.recursive_find_all(&b)
|
39
|
+
end
|
40
|
+
}
|
41
|
+
res.uniq
|
42
|
+
end
|
43
|
+
|
44
|
+
def set(value, &block)
|
45
|
+
return unless e = find(&block)
|
46
|
+
self[index(e)] = value
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_all(value, &block)
|
50
|
+
find_all(&block).each {|e| self[index(e)] = value}
|
51
|
+
end
|
52
|
+
|
53
|
+
def indice(&block)
|
54
|
+
return unless e = find(&block)
|
55
|
+
index(e)
|
56
|
+
end
|
57
|
+
alias :pos :indice
|
58
|
+
|
59
|
+
def indices(&block)
|
60
|
+
i = nil
|
61
|
+
find_all(&block).map {|e|
|
62
|
+
i = i ?
|
63
|
+
self[i+1..-1].index(e) + i + 1 :
|
64
|
+
index(e)
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def div(int, to_int_parts=nil)
|
69
|
+
len = int.to_i
|
70
|
+
return [self] if len <= 0
|
71
|
+
arr = dup
|
72
|
+
newarr = []
|
73
|
+
while arr.size > 0
|
74
|
+
newarr << arr.slice!(0, len)
|
75
|
+
end
|
76
|
+
newarr
|
77
|
+
end
|
78
|
+
|
79
|
+
def div!(int, to_int_parts=nil)
|
80
|
+
len = int.to_i
|
81
|
+
return [self] if len <= 0
|
82
|
+
arr = dup
|
83
|
+
clear
|
84
|
+
while arr.size > 0
|
85
|
+
self << arr.slice!(0, len)
|
86
|
+
end
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_dict
|
91
|
+
newhash = {}
|
92
|
+
list = dup
|
93
|
+
list.each {|gr|
|
94
|
+
desc = gr.shift
|
95
|
+
gr.each {|ex| newhash[ex] = desc}
|
96
|
+
}
|
97
|
+
newhash
|
98
|
+
end
|
99
|
+
|
100
|
+
def compile_int(base=10)
|
101
|
+
int = 0
|
102
|
+
pos = size
|
103
|
+
each {|i| int += base**(pos -= 1) * i}
|
104
|
+
int
|
105
|
+
end
|
106
|
+
|
107
|
+
def uniq?
|
108
|
+
uniq == self
|
109
|
+
end
|
110
|
+
|
111
|
+
def odds
|
112
|
+
newarr = []
|
113
|
+
each_with_index {|e, i| newarr << e if i%2 == 1}
|
114
|
+
newarr
|
115
|
+
end
|
116
|
+
|
117
|
+
def evens
|
118
|
+
newarr = []
|
119
|
+
each_with_index {|e, i| newarr << e if i%2 == 0}
|
120
|
+
newarr
|
121
|
+
end
|
122
|
+
|
123
|
+
def map_hash &b
|
124
|
+
Hash[map(&b)]
|
125
|
+
end
|
126
|
+
|
127
|
+
def flatmap &b
|
128
|
+
ary = []
|
129
|
+
each {|e| ary.concat yield e}
|
130
|
+
ary
|
131
|
+
end
|
132
|
+
|
133
|
+
# analogue to String#>>
|
134
|
+
def >>(ary)
|
135
|
+
ary.replace(self + ary)
|
136
|
+
end
|
137
|
+
|
138
|
+
alias :casecmp :===
|
139
|
+
# making multiple pattern matching possible:
|
140
|
+
# a, b = '3', '10'
|
141
|
+
# case [a, b]
|
142
|
+
# when [Integer, Integer]; a+b
|
143
|
+
# when [/\d/, '10']; '%*d'%[a, b]
|
144
|
+
# ...
|
145
|
+
# end
|
146
|
+
def ===(obj)
|
147
|
+
return true if casecmp(obj)
|
148
|
+
!!(if obj.kinda(Array) and obj.size == size
|
149
|
+
each_with_index {|e, i| e == :_ or e === obj[i] or return false}
|
150
|
+
end)
|
151
|
+
end
|
152
|
+
|
153
|
+
def sum(identity=0, &b) foldl(:+, &b) || identity end
|
154
|
+
|
155
|
+
# should override slower active support's method
|
156
|
+
def group_by(&b) count :group, &b end
|
157
|
+
|
158
|
+
if RUBY_VERSION < "1.8.7"
|
159
|
+
def map_with_index
|
160
|
+
a = []
|
161
|
+
each_with_index {|e, i| a << yield(e, i)}
|
162
|
+
a
|
163
|
+
end
|
164
|
+
else
|
165
|
+
def map_with_index(&block)
|
166
|
+
each_with_index.map(&block)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
if !defined? RMTools::Iterators
|
171
|
+
alias :throw_no :method_missing
|
172
|
+
RMTools::Iterators = %r{(#{(%w{select reject partition find_all find sum foldr min max flatmap}+instance_methods.grep(/_by$/))*'|'})_([\w\d\_]+[!?]?)}
|
173
|
+
|
174
|
+
def method_missing(method, *args, &block)
|
175
|
+
if match = (meth = method.to_s).match(RMTools::Iterators)
|
176
|
+
iterator, meth = match[1..2]
|
177
|
+
meth = meth.to_sym
|
178
|
+
return send(iterator) {|i| i.__send__ meth, *args, &block}
|
179
|
+
elsif meth.sub!(/sses([!?]?)$/, 'ss\1') or meth.sub!(/ies([!?]?)$/, 'y\1') or meth.sub!(/s([!?]?)$/, '\1')
|
180
|
+
return map {|i| i.__send__ meth.to_sym, *args, &block}
|
181
|
+
else
|
182
|
+
throw_no method
|
183
|
+
end
|
184
|
+
rescue NoMethodError
|
185
|
+
throw_no method
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Binding
|
2
|
+
|
3
|
+
def inspect_local_variables
|
4
|
+
vars = self.eval('local_variables') # ['a', 'b']
|
5
|
+
values = self.eval "[#{vars * ','}]" # ["a's value", "b's value"]
|
6
|
+
Hash[vars.zip(values)]
|
7
|
+
end
|
8
|
+
|
9
|
+
def inspect_instance_variables
|
10
|
+
vars = self.eval('instance_variables') # ['@a', '@b']
|
11
|
+
values = self.eval "[#{vars * ','}]" # ["@a's value", "@b's value"]
|
12
|
+
Hash[vars.zip(values)]
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect_env
|
16
|
+
self.eval("{'self' => self}").merge(inspect_local_variables).merge(inspect_instance_variables)
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid_types(pattern_ary)
|
20
|
+
self.eval("[#{self.eval('local_variables')*','}]").valid_types(pattern_ary)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|