rdoba 0.1 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
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
+