rdoba 0.1 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -41
- data/LICENSE +5 -17
- data/README.md +9 -29
- data/Rakefile +38 -3
- data/features/bcd.feature +29 -0
- data/features/log.feature +206 -0
- data/features/step_definitions/bcd_steps.rb +69 -0
- data/features/step_definitions/log_steps.rb +164 -0
- data/features/support/env.rb +159 -0
- data/lib/rdoba.rb +31 -15
- data/lib/rdoba/_version_.rb +3 -0
- data/lib/rdoba/a.rb +50 -53
- data/lib/rdoba/bcd.rb +61 -0
- data/lib/rdoba/common.rb +42 -11
- data/lib/rdoba/debug.rb +4 -46
- data/lib/rdoba/{fenc.rb → fe.rb} +2 -1
- data/lib/rdoba/io.rb +47 -17
- data/lib/rdoba/log.rb +248 -0
- data/lib/rdoba/numeric.rb +59 -49
- data/lib/rdoba/strings.rb +4 -3
- data/lib/rdoba/version.rb +51 -3
- data/rdoba.gemspec +13 -9
- metadata +51 -19
data/lib/rdoba/log.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Rdoba
|
4
|
+
def self.log options = {}
|
5
|
+
# options: {
|
6
|
+
# :as - name of method to apply the log functions, default: self
|
7
|
+
# :in - name of class or namespace to implement to the log, default: Kernel
|
8
|
+
# :functions = [
|
9
|
+
# :basic
|
10
|
+
# :warn
|
11
|
+
# :info
|
12
|
+
# :enter
|
13
|
+
# :leave
|
14
|
+
# :extended
|
15
|
+
# :compat - enable old style log strings dbgXX
|
16
|
+
# ]
|
17
|
+
# :prefix = [
|
18
|
+
# :timestamp
|
19
|
+
# :pid
|
20
|
+
# :function_name
|
21
|
+
# :function_line
|
22
|
+
# ]
|
23
|
+
# :io - An IO object to send log output to, default is $stdout
|
24
|
+
# }
|
25
|
+
# if empty the default value (enter, leave) is applied
|
26
|
+
# format of log message is the following:
|
27
|
+
# [<timestamp>]{pid}(<function name>)<log type> <debug text>"
|
28
|
+
# TODO add enum of options hash to convert values to symbols
|
29
|
+
# TODO make common format, and format for each of methods >, >>, +, -, %, *
|
30
|
+
# TODO add syntax redefinition ability for the methods >, >>, +, -, %, *
|
31
|
+
# TODO add multiple output (to more than only the IO)
|
32
|
+
|
33
|
+
# options[ :io ] = File.new('txt.log','w+')
|
34
|
+
# STDERR.puts options.inspect
|
35
|
+
# STDERR.puts options[ :io ].method( :puts ).inspect
|
36
|
+
# options.map
|
37
|
+
funcname = ( options[ :as ] || :self ).to_s.to_sym
|
38
|
+
pfx = ';if true;(Rdoba::Log::log @@rdoba_log_io_method,"' #TODO remove if
|
39
|
+
io = options[ :io ] || $stdout
|
40
|
+
io_m = io.method :puts
|
41
|
+
if prefix = ( options[ :prefix ].is_a?( Array ) && options[ :prefix ] ||
|
42
|
+
[ options[ :prefix ] ] )
|
43
|
+
if prefix.include?( :timestamp )
|
44
|
+
pfx << '[#{Time.now.strftime( "%H:%M:%S.%N" )}]'; end
|
45
|
+
if prefix.include?( :pid )
|
46
|
+
pfx << '{#{Process.pid}}'; end
|
47
|
+
if prefix.include?( :function_name )
|
48
|
+
if prefix.include?( :function_line )
|
49
|
+
pfx << '(#{m,f,l=get_stack_function_data_at_level(2);f+":"+l})'
|
50
|
+
else
|
51
|
+
pfx << '(#{get_stack_function_data_at_level(2)[1]})'; end ; end ; end
|
52
|
+
|
53
|
+
target = options[ :in ] || Kernel
|
54
|
+
# STDERR.puts "self: #{self.to_s}"
|
55
|
+
# STDERR.puts "funcname: #{funcname.inspect}"
|
56
|
+
# STDERR.puts "target: #{target.inspect}"
|
57
|
+
|
58
|
+
initfunc = Proc.new do
|
59
|
+
self.class_variable_set :@@rdoba_log_prefix, pfx
|
60
|
+
self.class_variable_set :@@rdoba_log_io_method, io_m
|
61
|
+
extend Rdoba::Log::ClassFunctions
|
62
|
+
include Rdoba::Log::Functions
|
63
|
+
self <= options[ :functions ] ; end
|
64
|
+
|
65
|
+
if funcname == :self
|
66
|
+
if target.to_s != 'main'
|
67
|
+
# CASE: class Cls; def method; self > end; end
|
68
|
+
target.instance_eval &initfunc ; end
|
69
|
+
# CASE: main { self > }
|
70
|
+
# CASE: class Cls; self > end
|
71
|
+
target.class.instance_eval &initfunc
|
72
|
+
else
|
73
|
+
host = ( target.to_s == 'main' && Kernel || target ) ## TODO check and remove
|
74
|
+
if target.to_s != 'main'
|
75
|
+
# CASE: class Cls; log > end
|
76
|
+
target.class.class_eval "class RdobaDebug;end"
|
77
|
+
target.class.send :class_eval, "def #{funcname};@#{funcname}||=RdobaDebug.new;end"
|
78
|
+
target.class::RdobaDebug.class_eval &initfunc ; end
|
79
|
+
# CASE: main { log > }
|
80
|
+
# CASE: class Cls; def method; log > end; end
|
81
|
+
host.class_eval "class RdobaDebug;end"
|
82
|
+
host.send :class_eval, "def #{funcname};@#{funcname}||=RdobaDebug.new;end"
|
83
|
+
host::RdobaDebug.class_eval &initfunc ; end
|
84
|
+
|
85
|
+
# STDERR.puts 2
|
86
|
+
# STDERR.puts target.inspect
|
87
|
+
# STDERR.puts target.class.methods.sort.inspect
|
88
|
+
=begin
|
89
|
+
target.class.instance_eval do # main { self > }
|
90
|
+
# target.class_eval do # main { log > }
|
91
|
+
self.class_variable_set( :@@log_prefix, pfx )
|
92
|
+
self.class_variable_set( :@@log_io_method, io_m )
|
93
|
+
extend Rdoba::Log::ClassFunctions
|
94
|
+
include Rdoba::Log::Functions
|
95
|
+
STDERR.puts pfx
|
96
|
+
STDERR.puts io_m.inspect
|
97
|
+
self <= functions; end;
|
98
|
+
=end
|
99
|
+
end; end
|
100
|
+
|
101
|
+
module Rdoba
|
102
|
+
module Log
|
103
|
+
class Error < StandardError
|
104
|
+
def initialize options = {}
|
105
|
+
case options
|
106
|
+
when :compat
|
107
|
+
"Debug compatibility mode can't be enabled for " +
|
108
|
+
"the specified object"
|
109
|
+
when :main
|
110
|
+
"An :as option can't be default or set to 'self' value for " +
|
111
|
+
"a main application. Please set up it correctly"; end; end; end
|
112
|
+
|
113
|
+
module Functions
|
114
|
+
def <= functions = []
|
115
|
+
self.class <= functions; end
|
116
|
+
|
117
|
+
def >= functions = []
|
118
|
+
self.class >= functions; end
|
119
|
+
|
120
|
+
def e *args
|
121
|
+
io = case args.last
|
122
|
+
when IO
|
123
|
+
args.pop
|
124
|
+
else
|
125
|
+
$stderr ; end
|
126
|
+
e = $! || args.shift
|
127
|
+
dump = ( [ $@ || args.shift ] + args ).flatten.compact
|
128
|
+
io.send :puts, "#{e.class}:%> #{e}\n\t#{dump.join("\n\t")}"; end
|
129
|
+
|
130
|
+
def get_stack_function_data_at_level( level )
|
131
|
+
raise Exception
|
132
|
+
rescue Exception
|
133
|
+
#TODO check match a method containing '`'
|
134
|
+
$@[ level ] =~ /([^\/]+):(\d+):in `(.*?)'$/
|
135
|
+
[ $1, $3, $2 ]; end; end
|
136
|
+
|
137
|
+
module ClassFunctions
|
138
|
+
def <= functions
|
139
|
+
functions = Rdoba::Log::update_functions functions, self, :+
|
140
|
+
pfx = self.class_variable_get :@@rdoba_log_prefix
|
141
|
+
code = Rdoba::Log::make_code functions, pfx, self
|
142
|
+
self.class_eval code; end
|
143
|
+
|
144
|
+
def >= functions # TODO make check for instance log, not only for class
|
145
|
+
functions = Rdoba::Log::update_functions functions, self, :-
|
146
|
+
pfx = self.class_variable_get :@@rdoba_log_prefix
|
147
|
+
code = Rdoba::Log::make_code functions, pfx, self
|
148
|
+
self.class_eval code; end; end
|
149
|
+
|
150
|
+
def self.update_functions functions, obj, method
|
151
|
+
if functions.is_a?( Array ) && functions.include?( :* )
|
152
|
+
functions = [ :basic, :enter, :leave, :warn, :info, :extended, :compat ]
|
153
|
+
end
|
154
|
+
cf = begin
|
155
|
+
obj.class_variable_get :@@rdoba_log_functions
|
156
|
+
rescue NameError
|
157
|
+
[] ; end
|
158
|
+
functions = cf.send( method, functions.is_a?( Array ) && functions ||
|
159
|
+
functions.is_a?( NilClass) && [] || [ functions.to_s.to_sym ] )
|
160
|
+
obj.class_variable_set :@@rdoba_log_functions, functions
|
161
|
+
functions
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.make_code functions, pfx, obj
|
165
|
+
code = ''
|
166
|
+
psfx = ' ",params);end;end;'
|
167
|
+
if functions.include?( :enter )
|
168
|
+
code << 'def + *params' + pfx + '<<<' + psfx
|
169
|
+
else
|
170
|
+
code << 'def + *params;end;'; end
|
171
|
+
if functions.include?( :leave )
|
172
|
+
code << 'def - ev' + pfx + '>>> ",[[ev.inspect]]);end;ev;end;'
|
173
|
+
else
|
174
|
+
code << 'def - ev;ev;end;'; end
|
175
|
+
if functions.include?( :basic )
|
176
|
+
code << "def > *params#{pfx}>#{psfx}"
|
177
|
+
else
|
178
|
+
code << 'def > *params;end;'; end
|
179
|
+
if functions.include?( :extended )
|
180
|
+
code << 'def >> *params' + pfx + '>>' + psfx
|
181
|
+
else
|
182
|
+
code << 'def >> *params;end;'; end
|
183
|
+
if functions.include?( :warn )
|
184
|
+
code << "def % *params#{pfx}%%%#{psfx}"
|
185
|
+
else
|
186
|
+
code << 'def % *params;end;'; end
|
187
|
+
if functions.include?( :info )
|
188
|
+
code << "def * *params#{pfx}***#{psfx}"
|
189
|
+
else
|
190
|
+
code << 'def * *params;end;'; end
|
191
|
+
if functions.include?( :compat )
|
192
|
+
obj.send :include, Rdoba::Log::DebugCompat
|
193
|
+
code << "$dbgl_#{self.class}=0;"
|
194
|
+
(1..0xF).each do |x|
|
195
|
+
(1..0xF).each do |y|
|
196
|
+
idx = sprintf "%x%x", x, y
|
197
|
+
code << "def dbp#{idx}(text); dbp(0x#{idx},text); end;"
|
198
|
+
code << "def dbg#{idx}(text); dbg(0x#{idx},text); end;"; end; end; end
|
199
|
+
code; end
|
200
|
+
|
201
|
+
def self.log io_m, prefix, params
|
202
|
+
text = prefix
|
203
|
+
text << params.map do |prm|
|
204
|
+
case prm
|
205
|
+
when Hash
|
206
|
+
r = []
|
207
|
+
prm.each do |key, value| r << "#{key}: #{value.inspect}" end
|
208
|
+
r.join(", ")
|
209
|
+
when Array
|
210
|
+
prm.join(', ')
|
211
|
+
when String
|
212
|
+
prm
|
213
|
+
else
|
214
|
+
prm.inspect
|
215
|
+
end
|
216
|
+
end.join(', ')
|
217
|
+
# NOTE: the shell over text id requires to proper output
|
218
|
+
# in multiprocess environment
|
219
|
+
io_m.call "#{text}\n"; end
|
220
|
+
|
221
|
+
module DebugCompat
|
222
|
+
def dbgl
|
223
|
+
@dbgl; end
|
224
|
+
|
225
|
+
def dbgl= level
|
226
|
+
@dbgl = level; end
|
227
|
+
|
228
|
+
def dbc level
|
229
|
+
level = level.to_i
|
230
|
+
if level > 0
|
231
|
+
clevel = @dbgl || begin
|
232
|
+
eval "$dbgl_#{self.class}"
|
233
|
+
rescue
|
234
|
+
nil; end
|
235
|
+
clevel || ( clevel.to_i & level ) == level
|
236
|
+
else
|
237
|
+
false; end; end
|
238
|
+
|
239
|
+
def dbp level, text
|
240
|
+
if dbc level
|
241
|
+
Kernel.puts text; end; end
|
242
|
+
|
243
|
+
def dbg level, code, vars = {}
|
244
|
+
if dbc level
|
245
|
+
if vars
|
246
|
+
vars.each_pair do |var, value|
|
247
|
+
instance_variable_set( var, value ); end; end
|
248
|
+
eval code; end; end; end ;end; end
|
data/lib/rdoba/numeric.rb
CHANGED
@@ -4,65 +4,48 @@
|
|
4
4
|
require 'rdoba/common'
|
5
5
|
require 'rdoba/strings'
|
6
6
|
|
7
|
-
class String
|
8
|
-
alias :_rdoba_to_i :to_i
|
9
|
-
def to_i(base = 10, *opts)
|
10
|
-
v = parse_opts(opts)
|
11
|
-
if v[:be]
|
12
|
-
(str, sign, num) = (self.match /\s*(-?)([0-9a-fx]+)/u).to_a
|
13
|
-
if str
|
14
|
-
n = num.reverse._rdoba_to_i(base)
|
15
|
-
sign.empty? && n || -n
|
16
|
-
else
|
17
|
-
0
|
18
|
-
end
|
19
|
-
else
|
20
|
-
_rdoba_to_i(base)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
7
|
class Fixnum
|
8
|
+
NativeEndian = 0
|
9
|
+
LittleEndian = -1
|
10
|
+
BigEndian = -2
|
11
|
+
|
26
12
|
alias :_rdoba_to_s :to_s
|
27
|
-
def to_s(base = 10,
|
28
|
-
|
13
|
+
def to_s( base = 10, opts = {} )
|
14
|
+
if !opts[ :padding ] && !opts[ :style_formatting ]
|
15
|
+
return _rdoba_to_s( base ); end
|
29
16
|
|
30
|
-
|
17
|
+
if base <= 0
|
18
|
+
raise "Base of number can't be equal or less then zero"; end
|
19
|
+
if opts[ :padding ] <= 0
|
20
|
+
raise "Padding count numberr can't be equal or less then zero"; end
|
31
21
|
|
32
|
-
raise "Base of number can't be equal or less then zero" if base <= 0
|
33
|
-
raise "Padding count numberr can't be equal or less then zero" if v[:padding] <= 0
|
34
22
|
value = self
|
35
|
-
minus =
|
36
|
-
value = -value
|
37
|
-
true
|
38
|
-
end
|
23
|
+
minus = value < 0 && ( value = -value; true )
|
39
24
|
res = ''
|
40
25
|
while value != 0
|
41
26
|
value, rem = value.divmod(base)
|
42
27
|
rem += 0x40 - 0x39 if rem >= 10
|
43
|
-
res += (0x30 + rem).chr
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
28
|
+
res += (0x30 + rem).chr; end
|
29
|
+
|
30
|
+
if res.size < ( padding = opts[ :padding ].to_i )
|
31
|
+
res += "0" * ( padding - res.size ); end
|
32
|
+
if opts[ :style_formatting ] and base == 16
|
33
|
+
res += 'x0'; end
|
34
|
+
if minus
|
35
|
+
res += '-';end
|
36
|
+
|
48
37
|
res.reverse
|
49
38
|
end
|
50
39
|
end
|
51
40
|
|
52
41
|
class Numeric
|
53
|
-
def to_p(
|
54
|
-
v = parse_opts(opts)
|
55
|
-
|
42
|
+
def to_p( opts = {} )
|
56
43
|
value = self
|
57
|
-
minus =
|
58
|
-
value = -value
|
59
|
-
true
|
60
|
-
end
|
44
|
+
minus = value < 0 && ( value = -value; true )
|
61
45
|
res = ''
|
62
46
|
while value != 0
|
63
47
|
value, rem = value.divmod(256)
|
64
|
-
res += rem.chr
|
65
|
-
end
|
48
|
+
res += rem.chr; end
|
66
49
|
|
67
50
|
pad_char = if minus
|
68
51
|
negres += ''
|
@@ -74,19 +57,46 @@ class Numeric
|
|
74
57
|
0
|
75
58
|
else
|
76
59
|
over = 0
|
77
|
-
negbyte
|
78
|
-
end
|
79
|
-
end
|
60
|
+
negbyte; end; end
|
80
61
|
res = negres
|
81
62
|
"\xFF"
|
82
63
|
else
|
83
|
-
"\0"
|
84
|
-
|
64
|
+
"\0"; end
|
65
|
+
|
66
|
+
if res.size < ( padding = opts[ :padding ].to_i )
|
67
|
+
res += pad_char * ( padding - res.size ); end
|
85
68
|
|
86
|
-
|
69
|
+
#TODO add detection of endianness of current system
|
70
|
+
if ( endian = opts[ :endian ] || Fixnum::NativeEndian ) ==
|
71
|
+
Fixnum::NativeEndian
|
72
|
+
endian = Fixnum::LittleEndian; end
|
73
|
+
( ( endian == Fixnum::LittleEndian ) && res ||
|
74
|
+
res.reverse( String::ByteByByte ) ).to_p; end; end
|
87
75
|
|
88
|
-
|
89
|
-
|
76
|
+
class String
|
77
|
+
alias :_rdoba_to_i :to_i
|
78
|
+
def to_i( base = 10 )
|
79
|
+
return 0 if self.empty?
|
80
|
+
|
81
|
+
#TODO add detection of endianness of current system
|
82
|
+
if base == Fixnum::NativeEndian
|
83
|
+
base = Fixnum::LittleEndian; end
|
84
|
+
res = 0
|
85
|
+
if base == Fixnum::BigEndian
|
86
|
+
self.each_byte do |b|
|
87
|
+
res = ( res << 8 ) | b
|
88
|
+
end
|
89
|
+
res
|
90
|
+
elsif base == Fixnum::LittleEndian
|
91
|
+
size = self.size
|
92
|
+
(1..size).each do |i|
|
93
|
+
b = self.getbyte( size - i )
|
94
|
+
res = ( res << 8 ) | b
|
95
|
+
end
|
96
|
+
res
|
97
|
+
else
|
98
|
+
_rdoba_to_i base
|
99
|
+
end
|
90
100
|
end
|
91
101
|
end
|
92
102
|
|
data/lib/rdoba/strings.rb
CHANGED
@@ -92,15 +92,16 @@ class String
|
|
92
92
|
alias :to_p :to_s
|
93
93
|
|
94
94
|
ByteByByte = 0
|
95
|
-
alias :
|
96
|
-
def reverse(step = 1)
|
95
|
+
alias :of_rdoba_reverse :reverse
|
96
|
+
def reverse( step = 1 )
|
97
|
+
# of Plain
|
97
98
|
case step
|
98
99
|
when ByteByByte
|
99
100
|
arr = []
|
100
101
|
self.each_byte do |byte| arr << byte.chr end
|
101
102
|
arr.reverse.join
|
102
103
|
when 1
|
103
|
-
|
104
|
+
of_rdoba_reverse
|
104
105
|
else
|
105
106
|
res = ''
|
106
107
|
offset = (self.size + 1) / step * step - step
|
data/lib/rdoba/version.rb
CHANGED
@@ -1,3 +1,51 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
class Version
|
4
|
+
attr_reader :subminor, :minor, :major
|
5
|
+
|
6
|
+
def self.parse value
|
7
|
+
case version.is_a?
|
8
|
+
when self
|
9
|
+
value
|
10
|
+
when Array
|
11
|
+
Version.new version[ 0 ].to_i, version[ 1 ].to_i, version[ 2 ].to_i
|
12
|
+
when Numeric
|
13
|
+
Version.new version >> 8, ( version >> 4 ) & 0xF, version & 0xF
|
14
|
+
else
|
15
|
+
if version.to_s =~ /(\d+)\.(\d+)(?:\.(\d+))?/
|
16
|
+
Version.new $1.to_i, $2.to_i, $3.to_i
|
17
|
+
elsif version.to_s =~ /([\da-z][\da-z])([\da-z])([\da-z])/i
|
18
|
+
Version.new $1.to_i( 16 ), $2.to_i( 16 ), $3.to_i( 16 )
|
19
|
+
else
|
20
|
+
Version.new 0, 0, 0; end; end; end
|
21
|
+
|
22
|
+
def == value
|
23
|
+
v = self.parse value
|
24
|
+
@major == v.major && @minor == v.minor && @subminor == v.subminor
|
25
|
+
end
|
26
|
+
|
27
|
+
def < value
|
28
|
+
v = self.parse value
|
29
|
+
@major < v.major || @major == v.major &&
|
30
|
+
( @minor < v.minor || @minor == v.minor &&
|
31
|
+
@subminor < v.subminor ); end
|
32
|
+
|
33
|
+
def > value
|
34
|
+
v = self.parse value
|
35
|
+
@major > v.major || @major == v.major &&
|
36
|
+
( @minor > v.minor || @minor == v.minor &&
|
37
|
+
@subminor > v.subminor ); end
|
38
|
+
|
39
|
+
def to_a
|
40
|
+
[ @major, @minor, @subminor ]; end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"#{@major}.#{@minor}.#{@subminor}"; end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def initialize major, minor = 0, subminor = 0
|
48
|
+
@subminor = subminor
|
49
|
+
@minor = minor
|
50
|
+
@major = major; end; end
|
51
|
+
|