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/a.rb
CHANGED
@@ -2,6 +2,55 @@
|
|
2
2
|
#<Encoding:UTF-8>
|
3
3
|
|
4
4
|
require 'rdoba/debug'
|
5
|
+
require 'rdoba/common'
|
6
|
+
|
7
|
+
class Object
|
8
|
+
def seta(index, value, options = {}) #TODO => [] + class Index
|
9
|
+
raise "Invalid class #{self.class} to set a value" unless
|
10
|
+
self.class == Hash or self.class == Array
|
11
|
+
dbp11 "[seta] <<< index: #{index.inspect}, value: #{value.inspect}, options: #{options.inspect}"
|
12
|
+
options[:сокр] ||= @сокр
|
13
|
+
|
14
|
+
return self[index] = value if index.class != Array # TODO spec index
|
15
|
+
|
16
|
+
back = 0
|
17
|
+
index = index.reverse.map do |x|
|
18
|
+
if x.empty?
|
19
|
+
back += 1
|
20
|
+
nil
|
21
|
+
elsif back > 0
|
22
|
+
back -= 1
|
23
|
+
nil
|
24
|
+
else
|
25
|
+
x
|
26
|
+
end
|
27
|
+
end.compact.reverse
|
28
|
+
dbp12 "[seta]> result index: #{index.inspect}"
|
29
|
+
|
30
|
+
par = self
|
31
|
+
par_idx = index.shift
|
32
|
+
index.each do |idx|
|
33
|
+
dbp14 "[seta]>> parent #{par.class} with idx: #{par_idx.inspect}"
|
34
|
+
obj = par[par_idx]
|
35
|
+
if not obj
|
36
|
+
obj = idx.to_s =~ /^\d+$/ && [] || {}
|
37
|
+
par[par_idx] = obj
|
38
|
+
dbp14 "[seta]>> new object #{obj.class}"
|
39
|
+
elsif obj.class != Hash and obj.class != Array
|
40
|
+
raise "Invalid class #{obj.class} for indexing"
|
41
|
+
end
|
42
|
+
|
43
|
+
par = obj
|
44
|
+
par_idx = idx
|
45
|
+
end
|
46
|
+
|
47
|
+
dbp14 "[seta]>> object #{par.class} with idx: #{par_idx.inspect}"
|
48
|
+
|
49
|
+
par[par_idx] = value
|
50
|
+
dbp11 "[seta] >>> #{self.inspect}"
|
51
|
+
self
|
52
|
+
end
|
53
|
+
end
|
5
54
|
|
6
55
|
class Array
|
7
56
|
def geta(index, options = {}) #TODO => [] + class Index
|
@@ -11,13 +60,12 @@ class Array
|
|
11
60
|
if index.class == Array
|
12
61
|
return self if index == [] or index == ['']
|
13
62
|
index = index.clone
|
14
|
-
value = self[index.shift]
|
63
|
+
value = self[index.shift.to_i]
|
15
64
|
(value.class == Hash or value.class == Array) ? value.geta(index, options) : value
|
16
65
|
else
|
17
66
|
geta_value(index, options)
|
18
67
|
end
|
19
68
|
end
|
20
|
-
|
21
69
|
end
|
22
70
|
|
23
71
|
|
@@ -59,56 +107,5 @@ public
|
|
59
107
|
geta_value(index, options)
|
60
108
|
end
|
61
109
|
end
|
62
|
-
|
63
|
-
def seta(index, value, options = {}) #TODO => [] + class Index
|
64
|
-
dbp11 "[seta] <<< index: #{index.inspect}, value: #{value.inspect}, options: #{options.inspect}"
|
65
|
-
options[:сокр] ||= @сокр
|
66
|
-
|
67
|
-
return self[index] = value if index.class != Array # TODO spec index
|
68
|
-
|
69
|
-
back = 0
|
70
|
-
index = index.reverse.map do |x|
|
71
|
-
if x.empty?
|
72
|
-
back += 1
|
73
|
-
nil
|
74
|
-
elsif back > 0
|
75
|
-
back -= 1
|
76
|
-
nil
|
77
|
-
else
|
78
|
-
x
|
79
|
-
end
|
80
|
-
end.compact.reverse
|
81
|
-
dbp12 "[seta]> result index: #{index.inspect}"
|
82
|
-
|
83
|
-
obj = nil
|
84
|
-
o = self
|
85
|
-
dbp14 "[seta]>> self: #{o.inspect}"
|
86
|
-
set_idx = index.pop
|
87
|
-
par_class = set_idx =~ /^\d+$/ ? Array : Hash
|
88
|
-
par_idx = nil
|
89
|
-
index.each do |idx|
|
90
|
-
unless o
|
91
|
-
dbp14 "[seta]>> parent idx: #{par_idx.inspect}, idx: #{idx.inspect}, parent obj: #{o.inspect}"
|
92
|
-
o = idx =~ /^\d+$/ && [] || {}
|
93
|
-
obj[par_idx] = o
|
94
|
-
end
|
95
|
-
obj = o
|
96
|
-
o = (obj.class == Hash) ? obj.geta_value(idx, options) : obj[idx]
|
97
|
-
dbp14 "[seta]>> cur idx: #{idx.inspect}, parent obj: #{obj.inspect}, obj: #{o.inspect}"
|
98
|
-
unless o
|
99
|
-
if idx == index.last
|
100
|
-
o = par_class.new
|
101
|
-
obj[idx] = o
|
102
|
-
else
|
103
|
-
par_idx = idx =~ /^\d+$/ && idx.to_i || idx
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
raise "Invalid path" unless o # TODO special exception
|
109
|
-
|
110
|
-
o[set_idx] = value
|
111
|
-
end
|
112
|
-
|
113
110
|
end
|
114
111
|
|
data/lib/rdoba/bcd.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
#
|
3
|
+
|
4
|
+
module BCD
|
5
|
+
class ParseError < Exception
|
6
|
+
def initialize msg = "Invalid positive integer value"; end; end
|
7
|
+
|
8
|
+
class ConvertError < Exception
|
9
|
+
def initialize msg = "Invalid number has given"; end; end
|
10
|
+
|
11
|
+
def to_i
|
12
|
+
res = 0
|
13
|
+
mul = 1
|
14
|
+
self.each_byte do |c|
|
15
|
+
def pow value, mul
|
16
|
+
if value >= 10
|
17
|
+
raise ConvertError; end
|
18
|
+
value * mul
|
19
|
+
end
|
20
|
+
res += pow( c.ord & 0xF, mul )
|
21
|
+
mul *= 10
|
22
|
+
res += pow( c.ord >> 4, mul )
|
23
|
+
mul *= 10
|
24
|
+
end
|
25
|
+
res; end
|
26
|
+
|
27
|
+
def self.parse value
|
28
|
+
if value < 0
|
29
|
+
raise ParseError; end
|
30
|
+
res = BCDString.new
|
31
|
+
if res.respond_to? :force_encoding
|
32
|
+
res.force_encoding( 'ASCII-8BIT' ); end
|
33
|
+
if value > 0
|
34
|
+
part = nil
|
35
|
+
while value > 0
|
36
|
+
( value, mod ) = value.divmod 10
|
37
|
+
if part
|
38
|
+
res << ( ( mod << 4 ) | part ).chr
|
39
|
+
part = nil
|
40
|
+
else
|
41
|
+
part = mod; end; end
|
42
|
+
if part
|
43
|
+
res << part.chr; end
|
44
|
+
else
|
45
|
+
res << 0.chr; end
|
46
|
+
res; end; end
|
47
|
+
|
48
|
+
class BCDString < String
|
49
|
+
include BCD
|
50
|
+
|
51
|
+
def initialize value = nil
|
52
|
+
if value.is_a? Numeric
|
53
|
+
self.replace BCD.parse( value )
|
54
|
+
else
|
55
|
+
super value.to_s; end; end; end
|
56
|
+
|
57
|
+
class Numeric
|
58
|
+
def to_bcd
|
59
|
+
# NOTE: return as plain LSB string
|
60
|
+
BCD.parse value; end; end
|
61
|
+
|
data/lib/rdoba/common.rb
CHANGED
@@ -38,17 +38,15 @@ class Object
|
|
38
38
|
end
|
39
39
|
|
40
40
|
module Kernel
|
41
|
-
|
42
|
-
require 'timeout'
|
41
|
+
require 'timeout'
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
true
|
49
|
-
rescue Timeout::Error
|
50
|
-
false
|
43
|
+
def if_wait(timeout = 30)
|
44
|
+
Timeout::timeout(timeout) do
|
45
|
+
while yield(); end
|
51
46
|
end
|
47
|
+
true
|
48
|
+
rescue Timeout::Error
|
49
|
+
false
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
@@ -104,6 +102,17 @@ class Array
|
|
104
102
|
return __set__(index.to_i, value, *args) if index.class == String and index =~ /^\d+$/
|
105
103
|
__set__(index, value, *args)
|
106
104
|
end
|
105
|
+
|
106
|
+
def glue!(inval)
|
107
|
+
self.each_index do |i|
|
108
|
+
begin
|
109
|
+
self[i] |= inval[i]
|
110
|
+
rescue
|
111
|
+
self[i] = inval[i]
|
112
|
+
end if inval[i]
|
113
|
+
end
|
114
|
+
self
|
115
|
+
end
|
107
116
|
end
|
108
117
|
|
109
118
|
class String
|
@@ -148,14 +157,36 @@ class String
|
|
148
157
|
end
|
149
158
|
|
150
159
|
class Hash
|
160
|
+
def glue!(inval)
|
161
|
+
self.replace self.glue(inval)
|
162
|
+
end
|
163
|
+
|
164
|
+
def glue(inval)
|
165
|
+
res = self.dup
|
166
|
+
inval.each_pair do |key, val|
|
167
|
+
if val.class == res[key].class
|
168
|
+
if val.class == Hash
|
169
|
+
res[key].glue! val
|
170
|
+
elsif val.class == Array
|
171
|
+
res[key].glue! val
|
172
|
+
else
|
173
|
+
res[key] = val
|
174
|
+
end
|
175
|
+
else
|
176
|
+
res[key] = val
|
177
|
+
end
|
178
|
+
end
|
179
|
+
res
|
180
|
+
end
|
181
|
+
|
151
182
|
def |(inval)
|
152
183
|
res = self.dup
|
153
184
|
inval.each_pair do |key, val|
|
154
185
|
if val.class == res[key].class
|
155
186
|
if val.class == Hash
|
156
|
-
res[key] |=
|
187
|
+
res[key] |= val
|
157
188
|
elsif val.class == Array
|
158
|
-
res[key]
|
189
|
+
res[key] |= val
|
159
190
|
else
|
160
191
|
res[key] = val
|
161
192
|
end
|
data/lib/rdoba/debug.rb
CHANGED
@@ -1,48 +1,6 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
@debug = nil
|
7
|
-
eval "$debug_#{self.class} = 0"
|
8
|
-
|
9
|
-
public
|
10
|
-
|
11
|
-
def debug=(level)
|
12
|
-
@debug = level
|
13
|
-
end
|
14
|
-
|
15
|
-
def dbc(level)
|
16
|
-
level = level.to_i
|
17
|
-
if level > 0
|
18
|
-
clevel = @debug || begin; eval "$debug_#{self.class}"; rescue; nil; end
|
19
|
-
clevel ? (clevel.to_i & level) == level : false
|
20
|
-
else
|
21
|
-
false
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def dbp(level, text)
|
26
|
-
Kernel.puts text if dbc(level)
|
27
|
-
end
|
28
|
-
|
29
|
-
def dbg(level, code, vars = {})
|
30
|
-
if dbc(level)
|
31
|
-
if vars
|
32
|
-
vars.each_pair do |var, value|
|
33
|
-
instance_variable_set(var, value)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
eval code
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
(1..0xF).each do |x|
|
41
|
-
(1..0xF).each do |y|
|
42
|
-
idx = sprintf "%x%x", x, y
|
43
|
-
eval "def dbp#{idx}(text); dbp(0x#{idx},text); end"
|
44
|
-
eval "def dbg#{idx}(text); dbg(0x#{idx},text); end"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
3
|
+
STDERR.puts "Warning: the module has kept only for backward compatibility\n" +
|
4
|
+
"Please use 'rdoba :log' form instead"
|
5
|
+
require 'rdoba/log'
|
48
6
|
|
data/lib/rdoba/{fenc.rb → fe.rb}
RENAMED
data/lib/rdoba/io.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
3
|
|
4
4
|
require 'strscan'
|
5
5
|
require 'rdoba/re'
|
@@ -11,6 +11,7 @@ module Kernel
|
|
11
11
|
def sprintf(format, *args)
|
12
12
|
nargs = []
|
13
13
|
nformat = ''
|
14
|
+
oargs = args.dup
|
14
15
|
|
15
16
|
fmt = format.split('%')
|
16
17
|
nformat = fmt.shift
|
@@ -18,23 +19,46 @@ module Kernel
|
|
18
19
|
while (not fmt.empty?)
|
19
20
|
part = fmt.shift
|
20
21
|
part = '%' + fmt.shift unless part
|
21
|
-
if part =~ /([0-9 #+\-*.]*)([
|
22
|
+
if part =~ /([0-9 #+\-*.]*)([csXx])(.*)/ # other keys bdEefGgiopu
|
22
23
|
keys = $1 || ''
|
23
|
-
|
24
|
-
|
24
|
+
rest = $3 || ''
|
25
|
+
char = $2
|
26
|
+
if keys =~ /(?:([0-9*]*)\.([0-9*]+)([+-])?|(-)?)/
|
27
|
+
indent = ( $1 == '*' && args.shift || $1 ).to_i
|
28
|
+
padding_size = $2 == '*' && args.shift.to_i || $2
|
25
29
|
value = args.shift
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
def convert( value, char, *args )
|
31
|
+
case char
|
32
|
+
when 'c'
|
33
|
+
endian = args[ 1 ] == '+' && Fixnum::BigEndian ||
|
34
|
+
args[ 1 ] == '-' && Fixnum::LittleEndian ||
|
35
|
+
Fixnum::NativeEndian
|
36
|
+
value.to_i.to_p( :padding => ( args[ 0 ] && args[ 0 ].to_i || 1 ),
|
37
|
+
:endian => endian )
|
38
|
+
when 's'
|
39
|
+
rs = value.to_s
|
40
|
+
pad = args[ 0 ] && args[ 0 ].to_i || 0
|
41
|
+
padl = rs.size >= pad && '' || ( "\0" * ( pad - rs.size ) )
|
42
|
+
args[ 1 ] && ( padl + rs ) || ( rs + padl )
|
43
|
+
when /(x|X)/
|
44
|
+
rs = value.ord.to_s( 16 )
|
45
|
+
rs = rs.upcase if $1 == 'X'
|
46
|
+
pad = args[ 0 ] && args[ 0 ].to_i || 0
|
47
|
+
( rs.size >= pad && '' || ( '0' * ( pad - rs.size ) ) ) + rs
|
48
|
+
end.gsub( Regexp.new( '%', Regexp::EXTENDED | Regexp::MULTILINE ),
|
49
|
+
'%%' )
|
50
|
+
end
|
51
|
+
plain = value && convert( value, char, padding_size, $3 ) || ''
|
52
|
+
indent = indent > plain.size && ( indent - plain.size ) || 0
|
53
|
+
nformat += ( $4 && ( plain + ' ' * indent ) ||
|
54
|
+
( ' ' * indent + plain ) ) + rest
|
31
55
|
else
|
32
|
-
nformat += '%' + keys +
|
56
|
+
nformat += '%' + keys + char + rest
|
33
57
|
nargs.push args.shift
|
34
58
|
end
|
35
59
|
else
|
36
60
|
nformat += '%' + part
|
37
|
-
l = $1 =~ /\*/
|
61
|
+
l = $1 =~ /\*/ && 2 || 1
|
38
62
|
while l > 0
|
39
63
|
nargs.push args.shift
|
40
64
|
l -= 1
|
@@ -42,8 +66,11 @@ module Kernel
|
|
42
66
|
end
|
43
67
|
end
|
44
68
|
__sprintf__(nformat, *nargs).to_p
|
69
|
+
rescue ArgumentError
|
70
|
+
Kernel.puts "[sprintf] #{$!.class}: #{$!}\n\t" + $@.join("\n\t") +
|
71
|
+
"\n\tNew format string = #{nformat.inspect}, params = #{nargs.inspect}" +
|
72
|
+
"\n\tOld format string = #{format.inspect}, params = #{oargs.inspect}"
|
45
73
|
end
|
46
|
-
|
47
74
|
end
|
48
75
|
|
49
76
|
class String
|
@@ -53,7 +80,7 @@ class String
|
|
53
80
|
|
54
81
|
pos = 0
|
55
82
|
argfs = []
|
56
|
-
while fss.scan_until(/%([0-9 #+\-*]*)(?:\.([0-9]+)(
|
83
|
+
while fss.scan_until(/%([0-9 #+\-*]*)(?:\.([0-9]+)([-+])?)?([bcdefgiosuxr])/)
|
57
84
|
argfs << [ fss[1], fss[2], fss[3], fss[4] ]
|
58
85
|
# TODO add performing the special case in fss[1]
|
59
86
|
nformat += fss.pre_match[pos..-1].to_res + case fss[4]
|
@@ -70,7 +97,7 @@ class String
|
|
70
97
|
when 'g'
|
71
98
|
'([+\-]?[0-9]+(?:[eE][+\-]?[0-9]+|\.[0-9]*))'
|
72
99
|
when 'c'
|
73
|
-
fss[2] ? "(.{
|
100
|
+
fss[2] ? "(.{#{fss[2]},#{fss[2]}})" : "(.)"
|
74
101
|
when 'b'
|
75
102
|
'([01]+)b?'
|
76
103
|
when 'o'
|
@@ -88,7 +115,7 @@ class String
|
|
88
115
|
|
89
116
|
nformat += fss.rest
|
90
117
|
|
91
|
-
[
|
118
|
+
[ r3 = Regexp.new(nformat, Regexp::EXTENDED | Regexp::MULTILINE), argfs ]
|
92
119
|
end
|
93
120
|
|
94
121
|
(alias :__scanf__ :scanf) if self.instance_methods(false).include?(:scanf)
|
@@ -110,7 +137,10 @@ class String
|
|
110
137
|
when /[efg]/
|
111
138
|
value.to_f
|
112
139
|
when 'c'
|
113
|
-
|
140
|
+
endian = argf[2] == '+' && Fixnum::BigEndian ||
|
141
|
+
argf[2] == '-' && Fixnum::LittleEndian ||
|
142
|
+
Fixnum::NativeEndian
|
143
|
+
value.to_i( endian )
|
114
144
|
when 'b'
|
115
145
|
value.to_i(2)
|
116
146
|
when 'o'
|