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