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