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.
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, *opts)
28
- v = parse_opts(opts)
13
+ def to_s( base = 10, opts = {} )
14
+ if !opts[ :padding ] && !opts[ :style_formatting ]
15
+ return _rdoba_to_s( base ); end
29
16
 
30
- return _rdoba_to_s(base) unless v[:padding] or v[:style_formatting]
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 = if value < 0
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
- end
45
- res += "0" * (v[:padding].to_i - res.size) if res.size < v[:padding].to_i
46
- res += 'x0' if v[:style_formatting] and base == 16
47
- res += '-' if minus
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(*opts)
54
- v = parse_opts(opts)
55
-
42
+ def to_p( opts = {} )
56
43
  value = self
57
- minus = if value < 0
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
- end
64
+ "\0"; end
65
+
66
+ if res.size < ( padding = opts[ :padding ].to_i )
67
+ res += pad_char * ( padding - res.size ); end
85
68
 
86
- res += pad_char * (v[:padding].to_i - res.size) if res.size < v[:padding].to_i
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
- plain = (v[:be] ? res.reverse(String::ByteByByte) : res).to_p
89
- plain
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 :__reverse__ :reverse
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
- __reverse__
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
- module Rdoba
2
- VERSION = "0.1"
3
- end
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
+