rdoba 0.1 → 0.9
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.
- 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
|
+
|