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/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