rmtools 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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