rdoba 0.0.3 → 0.1
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/.gitignore +43 -0
- data/CHANGES.md +28 -0
- data/Gemfile +2 -11
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +410 -0
- data/Rakefile +1 -51
- data/lib/rdoba/a.rb +114 -0
- data/lib/rdoba/combinations.rb +59 -0
- data/lib/rdoba/common.rb +190 -0
- data/lib/rdoba/debug.rb +48 -0
- data/lib/rdoba/deploy.rb +80 -0
- data/lib/rdoba/dup.rb +64 -0
- data/lib/rdoba/fenc.rb +17 -0
- data/lib/rdoba/hashorder.rb +66 -0
- data/lib/rdoba/io.rb +160 -0
- data/lib/rdoba/numeric.rb +93 -0
- data/lib/rdoba/re.rb +22 -0
- data/lib/rdoba/require.rb +62 -0
- data/lib/rdoba/roman.rb +45 -0
- data/lib/rdoba/strings.rb +149 -0
- data/lib/rdoba/version.rb +3 -0
- data/lib/rdoba/yaml.rb +48 -0
- data/lib/rdoba.rb +13 -1142
- data/rdoba.gemspec +18 -56
- metadata +38 -59
- data/README.rdoc +0 -19
- data/VERSION +0 -1
data/lib/rdoba.rb
CHANGED
@@ -1,1146 +1,17 @@
|
|
1
1
|
#!/usr/bin/ruby -KU
|
2
2
|
#<Encoding:UTF-8>
|
3
3
|
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def self.debug=(level)
|
18
|
-
@@debug = level
|
19
|
-
end
|
20
|
-
|
21
|
-
def debug=(level)
|
22
|
-
@debug = level
|
23
|
-
end
|
24
|
-
|
25
|
-
def dbc(level)
|
26
|
-
level = level.to_i
|
27
|
-
if level > 0
|
28
|
-
clevel = (
|
29
|
-
@debug || @@debug ||
|
30
|
-
begin; eval "$debug_#{self.class}"; rescue; nil; end ||
|
31
|
-
begin; eval "$debug"; rescue; nil; end
|
32
|
-
).to_i
|
33
|
-
(clevel & level) == level
|
34
|
-
else
|
35
|
-
false
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def dbp(level, text)
|
40
|
-
Kernel.puts text if dbc(level)
|
41
|
-
end
|
42
|
-
|
43
|
-
def dbg(level, code, vars = {})
|
44
|
-
if dbc(level)
|
45
|
-
if vars
|
46
|
-
vars.each_pair do |var, value|
|
47
|
-
instance_variable_set(var, value)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
eval code
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def dbp11(text)
|
55
|
-
dbp(0x11,text)
|
56
|
-
end
|
57
|
-
|
58
|
-
def dbp12(text)
|
59
|
-
dbp(0x12,text)
|
60
|
-
end
|
61
|
-
|
62
|
-
def dbp14(text)
|
63
|
-
dbp(0x14,text)
|
64
|
-
end
|
65
|
-
|
66
|
-
def dbp18(text)
|
67
|
-
dbp(0x18,text)
|
68
|
-
end
|
69
|
-
|
70
|
-
def dbp1C(text)
|
71
|
-
dbp(0x1C,text)
|
72
|
-
end
|
73
|
-
|
74
|
-
def dbp1F(text)
|
75
|
-
dbp(0x1F,text)
|
76
|
-
end
|
77
|
-
|
78
|
-
def dbp21(text)
|
79
|
-
dbp(0x21,text)
|
80
|
-
end
|
81
|
-
|
82
|
-
def dbp22(text)
|
83
|
-
dbp(0x22,text)
|
84
|
-
end
|
85
|
-
|
86
|
-
def dbp24(text)
|
87
|
-
dbp(0x24,text)
|
88
|
-
end
|
89
|
-
|
90
|
-
def dbp26(text)
|
91
|
-
dbp(0x26,text)
|
92
|
-
end
|
93
|
-
|
94
|
-
def dbp28(text)
|
95
|
-
dbp(0x28,text)
|
96
|
-
end
|
97
|
-
|
98
|
-
def dbp2C(text)
|
99
|
-
dbp(0x2C,text)
|
100
|
-
end
|
101
|
-
|
102
|
-
def dbp2F(text)
|
103
|
-
dbp(0x2F,text)
|
104
|
-
end
|
105
|
-
|
106
|
-
def dbp41(text)
|
107
|
-
dbp(0x41,text)
|
108
|
-
end
|
109
|
-
|
110
|
-
def dbp42(text)
|
111
|
-
dbp(0x42,text)
|
112
|
-
end
|
113
|
-
|
114
|
-
def dbp44(text)
|
115
|
-
dbp(0x44,text)
|
116
|
-
end
|
117
|
-
|
118
|
-
def dbp48(text)
|
119
|
-
dbp(0x48,text)
|
120
|
-
end
|
121
|
-
|
122
|
-
def dbp4F(text)
|
123
|
-
dbp(0x4F,text)
|
124
|
-
end
|
125
|
-
|
126
|
-
def dbg44(code, vars)
|
127
|
-
dbg(0x44,code,vars)
|
128
|
-
end
|
129
|
-
|
130
|
-
def dbc2F
|
131
|
-
dbc(0x2F)
|
132
|
-
end
|
133
|
-
|
134
|
-
alias :__method_missing__ :method_missing
|
135
|
-
def method_missing(symbol, *args)
|
136
|
-
if symbol.id2name =~ /^dbc([0-9a-fA-F]+)$/
|
137
|
-
dbc($1.to_i(16))
|
138
|
-
elsif not args.empty?
|
139
|
-
if symbol.id2name =~ /^dbg([0-9a-fA-F]+)$/
|
140
|
-
dbg($1.to_i(16), args.shift, args.shift)
|
141
|
-
elsif symbol.id2name =~ /^dbp([0-9a-fA-F]+)$/
|
142
|
-
dbp($1.to_i(16), args.join(','))
|
143
|
-
else __method_missing__(symbol, *args); end
|
144
|
-
else __method_missing__(symbol, *args); end
|
145
|
-
end
|
146
|
-
|
147
|
-
def xor(val1)
|
148
|
-
val0 = (not not self)
|
149
|
-
((val0) and (not val1)) or ((not val0) and (val1))
|
150
|
-
end
|
151
|
-
|
152
|
-
def co(method, *args) #calls any method
|
153
|
-
eval "#{method}(*args)"
|
154
|
-
end
|
155
|
-
|
156
|
-
def to_sym
|
157
|
-
to_s.to_sym
|
158
|
-
end
|
159
|
-
|
160
|
-
P = [
|
161
|
-
'слово',
|
162
|
-
'язык',
|
163
|
-
'часть речи',
|
164
|
-
'время',
|
165
|
-
'род',
|
166
|
-
'лицо',
|
167
|
-
'число',
|
168
|
-
'падеж',
|
169
|
-
'имя',
|
170
|
-
'залог',
|
171
|
-
'зрак',
|
172
|
-
'разряд',
|
173
|
-
'полнота',
|
174
|
-
'изменчивость',
|
175
|
-
'ограничение',
|
176
|
-
'притяжение',
|
177
|
-
'исток',
|
178
|
-
'образа',
|
179
|
-
'формы',
|
180
|
-
'близь',
|
181
|
-
'соответствия',
|
182
|
-
'наборы',
|
183
|
-
'чада',
|
184
|
-
'осмысления',
|
185
|
-
'примеры',
|
186
|
-
'значения',
|
187
|
-
'смысл',
|
188
|
-
'писмя',
|
189
|
-
'перевод',
|
190
|
-
'пояснение',
|
191
|
-
'отсылка',
|
192
|
-
'ссылки',
|
193
|
-
'сравнение',
|
194
|
-
]
|
195
|
-
|
196
|
-
def to_yml(level = 0)
|
197
|
-
res = ''
|
198
|
-
res += '---' if level == 0
|
199
|
-
res += case self.class.to_s.to_sym
|
200
|
-
when :Hash
|
201
|
-
rs = ''
|
202
|
-
self.keys.sort do |x,y|
|
203
|
-
ix = P.index(x) #TODO workaround
|
204
|
-
iy = P.index(y)
|
205
|
-
(ix and iy) ? ix <=> iy : (ix ? -1 : (iy ? 1 : x <=> y))
|
206
|
-
end.each do |key|
|
207
|
-
value = self[key]
|
208
|
-
rs += "\n" + ' ' * level * 2 + key.to_yml(level + 1)
|
209
|
-
rs += ': ' + value.to_yml(level + 1)
|
210
|
-
end
|
211
|
-
rs
|
212
|
-
when :Array
|
213
|
-
rs = ''
|
214
|
-
self.each do |value|
|
215
|
-
rs += "\n" + ' ' * level * 2 + '- ' + value.to_yml(level + 1)
|
216
|
-
end
|
217
|
-
rs
|
218
|
-
when :Fixnum
|
219
|
-
self.to_s
|
220
|
-
when :String
|
221
|
-
if self =~ /[-:\s]/
|
222
|
-
"\"#{self.gsub('"','\"')}\""
|
223
|
-
else
|
224
|
-
self
|
225
|
-
end
|
226
|
-
when :NilClass
|
227
|
-
''
|
228
|
-
else
|
229
|
-
begin
|
230
|
-
value.to_yaml
|
231
|
-
rescue NameError
|
232
|
-
raise "Unsupported class #{self.class}"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
res
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
module Kernel
|
240
|
-
private
|
241
|
-
def require_dir(dir, name)
|
242
|
-
dbp11 "[require_dir] <<< dir = #{dir}, name = #{name}"
|
243
|
-
begin
|
244
|
-
rdir = File.join(dir, name)
|
245
|
-
return false unless File.directory?(rdir)
|
246
|
-
rdir = File.join(dir, name)
|
247
|
-
$: << rdir unless $:.include?(rdir)
|
248
|
-
dbp14 "[require_dir]> Found dir #{rdir}"
|
249
|
-
Dir.foreach(rdir) do |file|
|
250
|
-
next unless file =~ /(.*)\.(rb|so)$/
|
251
|
-
dbp14 "[require_dir]> Loading ... #{$1}"
|
252
|
-
require $1
|
253
|
-
end
|
254
|
-
true
|
255
|
-
rescue
|
256
|
-
false
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def sub_require(name)
|
261
|
-
dbp11 "[sub_require] <<< name = #{name} "
|
262
|
-
$:.each do |dir|
|
263
|
-
begin
|
264
|
-
Dir.foreach(dir) do |file|
|
265
|
-
next unless file =~ /^#{name}\.(rb|so)$/
|
266
|
-
dbp14 "[sub_require]> Require Dir #{dir}/#{name} for #{file}"
|
267
|
-
r1 = require_dir(dir, name + '.modules')
|
268
|
-
r2 = require_dir(dir, name)
|
269
|
-
dbp14 "[sub_require]> Require Dir #{(r1 || r2) && 'passed' || 'failed'} ... #{name}"
|
270
|
-
end
|
271
|
-
rescue
|
272
|
-
end
|
273
|
-
end unless $".include?(name)
|
274
|
-
true
|
275
|
-
end
|
276
|
-
|
277
|
-
public
|
278
|
-
|
279
|
-
alias :__require__ :require
|
280
|
-
def require(name, options = {})
|
281
|
-
dbp11 "[require] <<< name = #{name}"
|
282
|
-
begin
|
283
|
-
res = __require__ name
|
284
|
-
rescue => bang
|
285
|
-
puts "Lib internal error: #{$!.class} -> #{$!}\n\t#{$@.join("\n\t")}"
|
286
|
-
exit
|
287
|
-
end
|
288
|
-
dbp14 "[require]> Loaded? #{name}... #{res}"
|
289
|
-
res = sub_require(name) if res and options[:recursive]
|
290
|
-
res
|
291
|
-
end
|
292
|
-
|
293
|
-
alias :__sprintf__ :sprintf
|
294
|
-
def sprintf(format, *args)
|
295
|
-
nargs = []
|
296
|
-
nformat = ''
|
297
|
-
|
298
|
-
fmt = format.split('%')
|
299
|
-
nformat = fmt.shift
|
300
|
-
|
301
|
-
while (not fmt.empty?)
|
302
|
-
part = fmt.shift
|
303
|
-
part = '%' + fmt.shift unless part
|
304
|
-
if part =~ /([0-9 #+\-*.]*)([bcdEefGgiopsuXx])(.*)/ and $2 == 'c'
|
305
|
-
keys = $1 || ''
|
306
|
-
str = $3 || ''
|
307
|
-
if keys =~ /(-)?([0-9*]*)(?:\.([0-9*]+)(\+))?/
|
308
|
-
value = args.shift
|
309
|
-
indent = ' ' * ($2 == '*' ? args.shift : $2).to_i
|
310
|
-
plain = value && value.to_p(($3 == '*' ? args.shift : $3 ? $3 : 1).to_i, $4) || ''
|
311
|
-
nformat += ($1 ? plain + indent : indent + plain) + str
|
312
|
-
else
|
313
|
-
nformat += '%' + keys + 'c' + str
|
314
|
-
nargs.push args.shift
|
315
|
-
end
|
316
|
-
else
|
317
|
-
nformat += '%' + part
|
318
|
-
l = $1 =~ /\*/ ? 2 : 1
|
319
|
-
while l > 0
|
320
|
-
nargs.push args.shift
|
321
|
-
l -= 1
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
__sprintf__(nformat, *nargs).to_p
|
326
|
-
end
|
327
|
-
|
328
|
-
def wait_if(timeout = 30)
|
329
|
-
begin
|
330
|
-
Timeout::timeout(timeout) do
|
331
|
-
while yield(); end
|
332
|
-
end
|
333
|
-
true
|
334
|
-
rescue Timeout::Error
|
335
|
-
false
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
class Class
|
341
|
-
=begin
|
342
|
-
@@inherited = {}
|
343
|
-
|
344
|
-
def self.inherited(child)
|
345
|
-
@@inherited[self] = [] unless @@inherited.key? self
|
346
|
-
@@inherited[self] << child
|
347
|
-
end
|
348
|
-
|
349
|
-
def new(*args, &block)
|
350
|
-
def match_inherited(cls, args)
|
351
|
-
@@inherited[cls].class != Array ? nil : (@@inherited[cls].each do |child|
|
352
|
-
begin
|
353
|
-
mm = child.method(:__match__)
|
354
|
-
return match_inherited(child, args) || child if mm.call(*args)
|
355
|
-
rescue
|
356
|
-
end
|
357
|
-
end; cls)
|
358
|
-
end
|
359
|
-
cls = match_inherited(self, args) || self
|
360
|
-
i = cls.allocate
|
361
|
-
i.method(:initialize).call(*args, &block)
|
362
|
-
i
|
363
|
-
end
|
364
|
-
=end
|
365
|
-
end
|
366
|
-
|
367
|
-
class NilClass
|
368
|
-
def =~(value)
|
369
|
-
value == nil
|
370
|
-
end
|
371
|
-
|
372
|
-
def +(value)
|
373
|
-
value
|
374
|
-
end
|
375
|
-
|
376
|
-
def <<(value)
|
377
|
-
[ value ]
|
378
|
-
end
|
379
|
-
|
380
|
-
def empty?
|
381
|
-
true
|
382
|
-
end
|
383
|
-
|
384
|
-
def to_i
|
385
|
-
0
|
386
|
-
end
|
387
|
-
alias :ord :to_i
|
388
|
-
|
389
|
-
def size
|
390
|
-
0
|
391
|
-
end
|
392
|
-
|
393
|
-
def <=>(value)
|
394
|
-
-1
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
|
399
|
-
class Array
|
400
|
-
|
401
|
-
private
|
402
|
-
|
403
|
-
def __comby(i, size)
|
404
|
-
s = "0#{sprintf("%.*b", size, i)}0"
|
405
|
-
v = { :res => [], :c0 => 0, :c1 => 0, :j => 0}
|
406
|
-
|
407
|
-
def up1(v)
|
408
|
-
sub_j = v[:j] + v[:c1] + 1
|
409
|
-
v[:res] << self[v[:j]...sub_j]
|
410
|
-
v[:j] = sub_j
|
411
|
-
v[:c1] = 0
|
412
|
-
end
|
413
|
-
|
414
|
-
def up0(v)
|
415
|
-
sub_j = v[:j] + v[:c0] - 1
|
416
|
-
self[v[:j]...sub_j].each do |x| v[:res] << [x] end
|
417
|
-
v[:j] = sub_j
|
418
|
-
end
|
419
|
-
|
420
|
-
s.each_char do |c|
|
421
|
-
if c == '1'
|
422
|
-
v[:c1] += 1
|
423
|
-
up0(v) if v[:c0] > 1
|
424
|
-
v[:c0] = 0
|
425
|
-
else
|
426
|
-
v[:c0] += 1
|
427
|
-
up1(v) if v[:c1] > 0
|
428
|
-
end
|
429
|
-
end
|
430
|
-
up0(v) if v[:c0] > 1
|
431
|
-
v[:res]
|
432
|
-
end
|
433
|
-
|
434
|
-
public
|
435
|
-
|
436
|
-
def purge
|
437
|
-
self.compact.delete_if {|x| x.empty? }
|
438
|
-
end
|
439
|
-
|
440
|
-
def >>(value = nil)
|
441
|
-
value ? delete(value) : shift
|
442
|
-
end
|
443
|
-
|
444
|
-
def each_comby(*args)
|
445
|
-
return self if self.empty? or not block_given?
|
446
|
-
if args.include?(:backward)
|
447
|
-
yield [ self.dup ]
|
448
|
-
((1 << (self.size - 1)) - 2).downto(0) do |i|
|
449
|
-
c = __comby(i, self.size - 1)
|
450
|
-
yield c
|
451
|
-
end
|
452
|
-
else
|
453
|
-
0.upto((1 << (self.size - 1)) - 2) do |i|
|
454
|
-
c = __comby(i, self.size - 1)
|
455
|
-
yield c
|
456
|
-
end
|
457
|
-
yield [ self.dup ]
|
458
|
-
end
|
459
|
-
|
460
|
-
return self
|
461
|
-
end
|
462
|
-
|
463
|
-
alias :__get__ :[]
|
464
|
-
def [](index, *args)
|
465
|
-
return __get__(index.to_i, *args) if index.class == String and index =~ /^\d+$/
|
466
|
-
__get__(index, *args)
|
467
|
-
end
|
468
|
-
|
469
|
-
alias :__set__ :[]=
|
470
|
-
def []=(index, value, *args)
|
471
|
-
return __set__(index.to_i, value, *args) if index.class == String and index =~ /^\d+$/
|
472
|
-
__set__(index, value, *args)
|
473
|
-
end
|
474
|
-
|
475
|
-
def geta(index, options = {}) #TODO => [] + class Index
|
476
|
-
dbp11 "[geta] <<< array = #{self.inspect}, index = #{index.inspect}, options = #{options.inspect}"
|
477
|
-
options[:сокр] ||= @сокр
|
478
|
-
|
479
|
-
if index.class == Array
|
480
|
-
return self if index == [] or index == ['']
|
481
|
-
index = index.clone
|
482
|
-
value = self[index.shift]
|
483
|
-
(value.class == Hash or value.class == Array) ? value.geta(index, options) : value
|
484
|
-
else
|
485
|
-
geta_value(index, options)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
end
|
490
|
-
|
491
|
-
class String
|
492
|
-
def -(str)
|
493
|
-
#TODO make smart search for match in the 'str', when only last subpart matched to 'self'
|
494
|
-
len = self.size
|
495
|
-
bc = ec = nil
|
496
|
-
(0...len).each do |idx|
|
497
|
-
break bc = idx if self[idx] == str[0]
|
498
|
-
end
|
499
|
-
((bc + 1)...len).each do |idx|
|
500
|
-
break ec = idx if self[idx] != str[idx - bc]
|
501
|
-
end if bc
|
502
|
-
(not bc) ? self.clone : (not ec) ? self[0, bc] : self[0, bc] + self[ec, len - ec]
|
503
|
-
end
|
504
|
-
|
505
|
-
alias :__match__ :=~
|
506
|
-
def =~(value)
|
507
|
-
if value.class == String
|
508
|
-
self == value
|
509
|
-
elsif value.class == Regexp
|
510
|
-
value =~ self
|
511
|
-
else
|
512
|
-
__match__(value)
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
def rmatch(value)
|
517
|
-
self == value || self =~ /^\/([^\/]+)/ && value =~ /#{$1}/
|
518
|
-
end
|
519
|
-
|
520
|
-
FirstChar = 0
|
521
|
-
alias :__set__ :[]=
|
522
|
-
def []=(*args)
|
523
|
-
index = args[0]
|
524
|
-
str = args[args.size > 2 ? 2 : 1]
|
525
|
-
if index.class == Fixnum
|
526
|
-
if str.class == String
|
527
|
-
a = self.split(//u)
|
528
|
-
if str.size == 1
|
529
|
-
a[index] = str
|
530
|
-
else
|
531
|
-
a[index] = str.split(//u)
|
532
|
-
a.flatten!
|
533
|
-
end
|
534
|
-
return self.replace(a.join)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
__set__(*args)
|
538
|
-
end
|
539
|
-
|
540
|
-
def get(*args)
|
541
|
-
index = args[0]
|
542
|
-
index.class == Fixnum ? self.split(//u)[index] : self[*args]
|
543
|
-
end
|
544
|
-
|
545
|
-
def ord
|
546
|
-
a = nil
|
547
|
-
self.each_byte do |b|
|
548
|
-
c = b & 0xC0
|
549
|
-
case c
|
550
|
-
when 0xc0
|
551
|
-
a = (b & 0x3F)
|
552
|
-
when 0x80
|
553
|
-
return (a << 6) + (b & 0x3F)
|
554
|
-
else
|
555
|
-
return b
|
556
|
-
end
|
557
|
-
end
|
558
|
-
end unless self.instance_methods(false).include?(:ord)
|
559
|
-
|
560
|
-
def setbyte(*args)
|
561
|
-
__set__(*args)
|
562
|
-
end unless self.instance_methods(false).include?(:setbyte)
|
563
|
-
|
564
|
-
def upcase_char(char)
|
565
|
-
chr = char.class == String ? char.ord : char.to_i
|
566
|
-
if chr >= 0x430 and chr < 0x450
|
567
|
-
chr -= 0x20
|
568
|
-
elsif chr >= 0x400 and chr < 0x410 or
|
569
|
-
chr >= 0x450 and chr < 0x482 or
|
570
|
-
chr >= 0x48A and chr < 0x524 or
|
571
|
-
chr >= 0xA642 and chr < 0xA668 or
|
572
|
-
chr >= 0xA680 and chr < 0xA698
|
573
|
-
chr -= 1 if (chr % 1) == 1
|
574
|
-
else
|
575
|
-
return chr.chr.__upcase__
|
576
|
-
end
|
577
|
-
chr.chr
|
578
|
-
end
|
579
|
-
|
580
|
-
alias :__upcase__ :upcase
|
581
|
-
def upcase(option = nil)
|
582
|
-
if option == FirstChar
|
583
|
-
r = self.dup
|
584
|
-
r[0] = upcase_char(self.ord)
|
585
|
-
r
|
586
|
-
elsif self.match(/[Ѐ-ҁҊ-ԣꙀ-ꙧꚀꚗ]/u)
|
587
|
-
self.split(//u).map do |chr| upcase_char(chr) end.join
|
588
|
-
else; __upcase__ end
|
589
|
-
end
|
590
|
-
|
591
|
-
def downcase_char(char)
|
592
|
-
chr = (char.class == String) ? char.ord : char.to_i
|
593
|
-
if chr >= 0x410 and chr < 0x430
|
594
|
-
chr += 0x20
|
595
|
-
elsif chr >= 0x400 and chr < 0x410 or
|
596
|
-
chr >= 0x450 and chr < 0x482 or
|
597
|
-
chr >= 0x48A and chr < 0x524 or
|
598
|
-
chr >= 0xA642 and chr < 0xA668 or
|
599
|
-
chr >= 0xA680 and chr < 0xA698
|
600
|
-
chr += 1 if (chr % 1) == 0
|
601
|
-
else
|
602
|
-
return chr.chr.__downcase__
|
603
|
-
end
|
604
|
-
chr.chr
|
605
|
-
end
|
606
|
-
|
607
|
-
alias :__downcase__ :downcase
|
608
|
-
def downcase(option = nil)
|
609
|
-
if option == FirstChar
|
610
|
-
r = self.dup
|
611
|
-
r[0] = downcase_char(self.ord)
|
612
|
-
r
|
613
|
-
elsif self.match(/[Ѐ-ҁҊ-ԣꙀ-ꙧꚀꚗ]/u)
|
614
|
-
self.split(//u).map do |chr| downcase_char(chr) end.join
|
615
|
-
else; __downcase__ end
|
616
|
-
end
|
617
|
-
|
618
|
-
alias :to_p :to_s
|
619
|
-
=begin
|
620
|
-
def to_p
|
621
|
-
force_encoding('BINARY')
|
622
|
-
end
|
623
|
-
|
624
|
-
def force_encoding(*args)
|
625
|
-
self
|
626
|
-
end unless self.instance_methods(false).include?(:force_encoding)
|
627
|
-
|
628
|
-
def encode(*args)
|
629
|
-
self
|
630
|
-
end unless self.instance_methods(false).include?(:encode)
|
631
|
-
|
632
|
-
def toutf8
|
633
|
-
return self if self.encoding.to_s == 'UTF-8'
|
634
|
-
res = ''.encode('UTF-8')
|
635
|
-
|
636
|
-
ss = StringScanner.new(self)
|
637
|
-
while ss.scan_until(/[\x80-\xFF]+/x)
|
638
|
-
same = (' ' * ss.matched_size).encode('UTF-8')
|
639
|
-
i = 0
|
640
|
-
ss.matched.each_byte do |byte|
|
641
|
-
same.setbyte(i, byte)
|
642
|
-
i += 1
|
643
|
-
end
|
644
|
-
self res += ss.pre_match[pos..-1].encode('UTF-8') + same
|
645
|
-
|
646
|
-
ss.pos += ss.matched_size + 1
|
647
|
-
end
|
648
|
-
|
649
|
-
res + ss.rest.encode('UTF-8')
|
650
|
-
end unless self.instance_methods(false).include?(:toutf8)
|
651
|
-
=end
|
652
|
-
|
653
|
-
ByteByByte = 0
|
654
|
-
alias :__reverse__ :reverse
|
655
|
-
def reverse(step = 1)
|
656
|
-
case step
|
657
|
-
when ByteByByte
|
658
|
-
arr = []
|
659
|
-
self.each_byte do |byte| arr << byte.chr end
|
660
|
-
arr.reverse.join
|
661
|
-
when 1
|
662
|
-
__reverse__
|
663
|
-
else
|
664
|
-
res = ''
|
665
|
-
offset = (self.size + 1) / step * step - step
|
666
|
-
(0..offset).step(step) do |shift|
|
667
|
-
res += self[offset - shift..offset - shift + 1]
|
668
|
-
end
|
669
|
-
res
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
|
-
BE = 0
|
674
|
-
LE = 1
|
675
|
-
|
676
|
-
alias :__to_i__ :to_i
|
677
|
-
def to_i(base = 10, be = true)
|
678
|
-
# TODO make a conversion of negative numbers
|
679
|
-
str = case base
|
680
|
-
when BE
|
681
|
-
self.reverse(ByteByByte)
|
682
|
-
when LE
|
683
|
-
self
|
684
|
-
else
|
685
|
-
return __to_i__(base)
|
686
|
-
end
|
687
|
-
|
688
|
-
mul = 1
|
689
|
-
res = 0
|
690
|
-
str.each_byte do |byte|
|
691
|
-
res += byte * mul
|
692
|
-
mul *= 256
|
693
|
-
end
|
694
|
-
|
695
|
-
res.to_i
|
696
|
-
end
|
697
|
-
|
698
|
-
def to_res
|
699
|
-
ostr = self.dup
|
700
|
-
res = ''
|
701
|
-
while true
|
702
|
-
m = ostr.match(/(?:([+\[\]\\().*?{}^$\/|])|«([^«]*)»)/u)
|
703
|
-
break unless m
|
704
|
-
res += m.pre_match + (m[2] || m[1] && ('\\' + m[1]))
|
705
|
-
ostr = m.post_match
|
706
|
-
end
|
707
|
-
|
708
|
-
res + ostr
|
709
|
-
end
|
710
|
-
|
711
|
-
def to_re
|
712
|
-
/#{to_res}/i
|
713
|
-
end
|
714
|
-
|
715
|
-
def scanf_re(format)
|
716
|
-
fss = StringScanner.new(format) # TODO remove scanner in favor of match
|
717
|
-
nformat = ''
|
718
|
-
|
719
|
-
pos = 0
|
720
|
-
argfs = []
|
721
|
-
while fss.scan_until(/%([0-9 #+\-*]*)(?:\.([0-9]+)(\+)?)?([bcdefgiosux])/)
|
722
|
-
argfs << [ fss[1], fss[2], fss[3], fss[4] ]
|
723
|
-
# TODO add performing the special case in fss[1]
|
724
|
-
nformat += fss.pre_match[pos..-1].to_res + case fss[4]
|
725
|
-
when 'x'
|
726
|
-
'(?:0[xX])?([a-fA-F0-9]+)'
|
727
|
-
when 'i'
|
728
|
-
'([+\-]?[0-9]+)'
|
729
|
-
when 'u'
|
730
|
-
'([0-9]+)'
|
731
|
-
when 'e'
|
732
|
-
'([+\-]?[0-9]+[eE][+\-]?[0-9]+)'
|
733
|
-
when 'f'
|
734
|
-
'([+\-]?[0-9]+\.[0-9]*)'
|
735
|
-
when 'g'
|
736
|
-
'([+\-]?[0-9]+(?:[eE][+\-]?[0-9]+|\.[0-9]*))'
|
737
|
-
when 'c'
|
738
|
-
fss[2] ? "(.{1,#{fss[2]}})" : "(.)"
|
739
|
-
when 'b'
|
740
|
-
'([01]+)b?'
|
741
|
-
when 'o'
|
742
|
-
'0([0-9]+)'
|
743
|
-
when 'd'
|
744
|
-
'([+\-]?(?:0X)?[A-F0-9.+]+)'
|
745
|
-
when 's'
|
746
|
-
'(.+)'
|
747
|
-
end
|
748
|
-
|
749
|
-
pos = fss.pos
|
750
|
-
end
|
751
|
-
|
752
|
-
nformat += fss.rest
|
753
|
-
|
754
|
-
[ /#{nformat}/, argfs ]
|
755
|
-
end
|
756
|
-
|
757
|
-
(alias :__scanf__ :scanf) if self.instance_methods(false).include?(:scanf)
|
758
|
-
def scanf(format, &block)
|
759
|
-
(re, argfs) = scanf_re(format)
|
760
|
-
|
761
|
-
ss = StringScanner.new(self)
|
762
|
-
res = []
|
763
|
-
rline = []
|
764
|
-
while ss.scan_until(re)
|
765
|
-
argfs.each_index do |i|
|
766
|
-
argf = argfs[i]
|
767
|
-
value = ss[i + 1]
|
768
|
-
rline << case argf[3]
|
769
|
-
when 'x'
|
770
|
-
value.to_i(16)
|
771
|
-
when /[diu]/
|
772
|
-
value.to_i
|
773
|
-
when /[efg]/
|
774
|
-
value.to_f
|
775
|
-
when 'c'
|
776
|
-
value.to_i(argf[2] ? BE : LE)
|
777
|
-
when 'b'
|
778
|
-
value.to_i(2)
|
779
|
-
when 'o'
|
780
|
-
value.to_i(8)
|
781
|
-
when 's'
|
782
|
-
value
|
783
|
-
end
|
784
|
-
end
|
785
|
-
|
786
|
-
if block_given?
|
787
|
-
pass = []
|
788
|
-
(1..block.arity).each do |i| pass << "rline[#{i}]" end
|
789
|
-
eval "yield(#{pass.join(', ')})"
|
790
|
-
end
|
791
|
-
|
792
|
-
res << rline
|
793
|
-
end
|
794
|
-
|
795
|
-
res
|
796
|
-
end
|
797
|
-
|
798
|
-
def consolize
|
799
|
-
ss = StringScanner.new(self)
|
800
|
-
res = ''
|
801
|
-
ostr = ''
|
802
|
-
pos = 0
|
803
|
-
|
804
|
-
while ss.scan_until(/\r/)
|
805
|
-
ostr[0...ss.pre_match.size - pos] = ss.pre_match[pos..-1]
|
806
|
-
pos = ss.pos
|
807
|
-
|
808
|
-
if ss.post_match[0] == "\n"[0]
|
809
|
-
res = ostr
|
810
|
-
pos += 1
|
811
|
-
ostr = ''
|
812
|
-
end
|
813
|
-
|
814
|
-
end
|
815
|
-
|
816
|
-
ostr[0...ss.rest.size] = ss.rest
|
817
|
-
res + ostr
|
818
|
-
end
|
819
|
-
|
820
|
-
def hexdump
|
821
|
-
res= ''
|
822
|
-
i = 0
|
823
|
-
self.each_byte do |byte|
|
824
|
-
res << sprintf("%.2X ", byte)
|
825
|
-
i += 1
|
826
|
-
res << "\n" if i % 16 == 0
|
827
|
-
end
|
828
|
-
res
|
829
|
-
end
|
830
|
-
|
831
|
-
alias :__compare__ :<=>
|
832
|
-
def <=>(value)
|
833
|
-
compare(value)
|
834
|
-
end
|
835
|
-
|
836
|
-
def compare(value, *opts)
|
837
|
-
if opts.include? :compare_diacritics
|
838
|
-
__compare__(value)
|
839
|
-
else
|
840
|
-
# TODO verify composite range
|
841
|
-
def crop_diacritics(x)
|
842
|
-
(x < 0x300 or
|
843
|
-
x > 0x36f and x < 0x483 or
|
844
|
-
x > 0x487 and x < 0xa57c or
|
845
|
-
x > 0xa67d) && x || nil
|
846
|
-
end
|
847
|
-
|
848
|
-
(self.unpack('U*').map do |x| crop_diacritics(x)
|
849
|
-
end.compact) <=> (value.unpack('U*').map do |x| crop_diacritics(x)
|
850
|
-
end.compact)
|
851
|
-
end
|
852
|
-
end
|
853
|
-
end
|
854
|
-
|
855
|
-
class Hash
|
856
|
-
|
857
|
-
protected
|
858
|
-
|
859
|
-
def geta_value(cid, options = {})
|
860
|
-
res = ((not cid) || cid.empty?) && self || self[cid] ||
|
861
|
-
(options[:сокр] && (self[options[:сокр][cid]] || self[options[:сокр].reverse[cid]]))
|
862
|
-
|
863
|
-
if not res and options[:try_regexp]
|
864
|
-
self.keys.each do |key|
|
865
|
-
break res = self[key] if key.rmatch(cid)
|
866
|
-
if options[:сокр]
|
867
|
-
options[:сокр].each_pair do |val1, val2|
|
868
|
-
break res = self[key] if key.rmatch(cid.gsub(/#{val1}/, val2)) or
|
869
|
-
key.rmatch(cid.gsub(/#{val2}/, val1))
|
870
|
-
end
|
871
|
-
end
|
872
|
-
end
|
873
|
-
end
|
874
|
-
|
875
|
-
res
|
876
|
-
end
|
877
|
-
|
878
|
-
public
|
879
|
-
|
880
|
-
def geta(index, options = {}) #TODO => [] + class Index
|
881
|
-
dbp11 "[geta] <<< hash = #{self.inspect}, index = #{index.inspect}, options = #{options.inspect}"
|
882
|
-
options[:сокр] ||= @сокр
|
883
|
-
|
884
|
-
if index.class == Array
|
885
|
-
return self if index == [] or index == ['']
|
886
|
-
index = index.clone
|
887
|
-
value = geta_value(index.shift, options)
|
888
|
-
(value.class == Hash or value.class == Array) ? value.geta(index, options) : value
|
889
|
-
else
|
890
|
-
geta_value(index, options)
|
891
|
-
end
|
892
|
-
end
|
893
|
-
|
894
|
-
def seta(index, value, options = {}) #TODO => [] + class Index
|
895
|
-
dbp11 "[seta] <<< index: #{index.inspect}, value: #{value.inspect}, options: #{options.inspect}"
|
896
|
-
options[:сокр] ||= @сокр
|
897
|
-
|
898
|
-
return self[index] = value if index.class != Array # TODO spec index
|
899
|
-
|
900
|
-
back = 0
|
901
|
-
index = index.reverse.map do |x|
|
902
|
-
if x.empty?
|
903
|
-
back += 1
|
904
|
-
nil
|
905
|
-
elsif back > 0
|
906
|
-
back -= 1
|
907
|
-
nil
|
908
|
-
else
|
909
|
-
x
|
910
|
-
end
|
911
|
-
end.compact.reverse
|
912
|
-
dbp12 "[seta]> result index: #{index.inspect}"
|
913
|
-
|
914
|
-
obj = nil
|
915
|
-
o = self
|
916
|
-
dbp14 "[seta]>> self: #{o.inspect}"
|
917
|
-
set_idx = index.pop
|
918
|
-
par_class = set_idx =~ /^\d+$/ ? Array : Hash
|
919
|
-
par_idx = nil
|
920
|
-
index.each do |idx|
|
921
|
-
unless o
|
922
|
-
dbp14 "[seta]>> parent idx: #{par_idx.inspect}, idx: #{idx.inspect}, parent obj: #{o.inspect}"
|
923
|
-
o = idx =~ /^\d+$/ && [] || {}
|
924
|
-
obj[par_idx] = o
|
925
|
-
end
|
926
|
-
obj = o
|
927
|
-
o = (obj.class == Hash) ? obj.geta_value(idx, options) : obj[idx]
|
928
|
-
dbp14 "[seta]>> cur idx: #{idx.inspect}, parent obj: #{obj.inspect}, obj: #{o.inspect}"
|
929
|
-
unless o
|
930
|
-
if idx == index.last
|
931
|
-
o = par_class.new
|
932
|
-
obj[idx] = o
|
933
|
-
else
|
934
|
-
par_idx = idx =~ /^\d+$/ && idx.to_i || idx
|
935
|
-
end
|
936
|
-
end
|
937
|
-
end
|
938
|
-
|
939
|
-
raise "Invalid path" unless o # TODO special exception
|
940
|
-
|
941
|
-
o[set_idx] = value
|
942
|
-
end
|
943
|
-
|
944
|
-
def |(inval)
|
945
|
-
res = self.dup
|
946
|
-
inval.each_pair do |key, val|
|
947
|
-
if val.class == res[key].class
|
948
|
-
if val.class == Hash
|
949
|
-
res[key] |= inval[key]
|
950
|
-
elsif val.class == Array
|
951
|
-
res[key].concat val
|
952
|
-
else
|
953
|
-
res[key] = val
|
954
|
-
end
|
955
|
-
else
|
956
|
-
res[key] = val
|
957
|
-
end
|
958
|
-
end
|
959
|
-
res
|
960
|
-
end
|
961
|
-
|
962
|
-
def deploy!(vars = {})
|
963
|
-
self.replace deploy(vars)
|
964
|
-
# TODO add variable copy
|
965
|
-
end
|
966
|
-
|
967
|
-
def deploy(vars = {})
|
968
|
-
res = {}
|
969
|
-
|
970
|
-
self.keys.sort do |x,y|
|
971
|
-
if x =~ /=$/
|
972
|
-
y =~ /=$/ ? x <=> y : -1
|
973
|
-
else
|
974
|
-
y !~ /=$/ ? x <=> y : 1
|
975
|
-
end
|
976
|
-
end.each do |key|
|
977
|
-
|
978
|
-
if key =~ /(.*)=$/
|
979
|
-
vars[$1] = self[key]
|
980
|
-
next
|
981
|
-
|
982
|
-
elsif key =~ /(.*)@$/
|
983
|
-
sym = $1
|
984
|
-
eval "res.class.co( :attr_accessor, :#{sym})"
|
985
|
-
eval "res.#{sym} = self[key]"
|
986
|
-
next
|
987
|
-
|
988
|
-
elsif key =~ /^%([^%].*)/
|
989
|
-
var = vars[$1].dup
|
990
|
-
if var.class == Hash
|
991
|
-
res |= var.deploy(vars)
|
992
|
-
elsif var.class == String
|
993
|
-
res[var] = nil
|
994
|
-
else
|
995
|
-
raise "Undeployable hash #{$1} value class #{var.class}"
|
996
|
-
end
|
997
|
-
next
|
998
|
-
|
999
|
-
elsif key =~ /^%%(.*)/
|
1000
|
-
key.replace $1.to_s
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
def deploy_value(value, vars)
|
1004
|
-
case value.class.to_sym
|
1005
|
-
when :String
|
1006
|
-
if value =~ /^%([^%].*)/
|
1007
|
-
begin; vars[$1].deploy(vars); rescue; nil end
|
1008
|
-
elsif value =~ /(.*)%([A-Za-z0-9_А-я]+)(.*)/
|
1009
|
-
a = [ $1.to_s, $2.to_s, $3.to_s ]
|
1010
|
-
a[1] = begin; vars[a[1]].deploy(vars).to_s; rescue; vars[a[1]] end
|
1011
|
-
a.join
|
1012
|
-
else
|
1013
|
-
value
|
1014
|
-
end
|
1015
|
-
when :Hash
|
1016
|
-
value.deploy(vars)
|
1017
|
-
when :Array
|
1018
|
-
value.map do |sub|
|
1019
|
-
deploy_value(sub, vars)
|
1020
|
-
end
|
1021
|
-
else
|
1022
|
-
value
|
1023
|
-
end
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
value = self[key]
|
1027
|
-
res[key] = deploy_value(value, vars)
|
1028
|
-
end
|
1029
|
-
res
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
def reverse!
|
1033
|
-
replace(reverse)
|
1034
|
-
end
|
1035
|
-
|
1036
|
-
def reverse
|
1037
|
-
h = {}
|
1038
|
-
self.each_pair do |key, value|
|
1039
|
-
if h.key? value
|
1040
|
-
if h[value].class == Array
|
1041
|
-
h[value] << key
|
1042
|
-
else
|
1043
|
-
h[value] = [ h[value], key ]
|
1044
|
-
end
|
1045
|
-
else
|
1046
|
-
h[value] = key
|
1047
|
-
end
|
1048
|
-
end
|
1049
|
-
h
|
1050
|
-
end
|
1051
|
-
end
|
1052
|
-
|
1053
|
-
class Numeric
|
1054
|
-
Nums = { 1 => 'I', 4 => 'IV', 5 => 'V', 9 => 'IX', 10 => 'X', 40 => 'XL', 50 => 'L',
|
1055
|
-
90 => 'XC', 100 => 'C', 400 => 'CD', 500 => 'D', 900 => 'CM', 1000 => 'M' }
|
1056
|
-
Numi = Nums.keys.sort
|
1057
|
-
|
1058
|
-
def to_rom
|
1059
|
-
res = ''
|
1060
|
-
num = self
|
1061
|
-
i = Numi.size - 1
|
1062
|
-
|
1063
|
-
while num > 0
|
1064
|
-
if num >= Numi[i]
|
1065
|
-
res << Nums[Numi[i]]
|
1066
|
-
num -= Numi[i]
|
1067
|
-
else
|
1068
|
-
i -= 1
|
1069
|
-
end
|
1070
|
-
end
|
1071
|
-
res
|
1072
|
-
end
|
1073
|
-
|
1074
|
-
def to_s(base = 10, padding_count = 1, style_formatting = false)
|
1075
|
-
raise "Base of number can't be equal or less then zero" if base <= 0
|
1076
|
-
raise "Padding count numberr can't be equal or less then zero" if padding_count <= 0
|
1077
|
-
value = self
|
1078
|
-
minus = if value < 0
|
1079
|
-
value = -value
|
1080
|
-
true
|
1081
|
-
end
|
1082
|
-
res = ''
|
1083
|
-
while value != 0
|
1084
|
-
value, rem = value.divmod(base)
|
1085
|
-
rem += 0x40 - 0x39 if rem >= 10
|
1086
|
-
res += (0x30 + rem).chr
|
1087
|
-
end
|
1088
|
-
res += "0" * (padding_count - res.size) if res.size < padding_count
|
1089
|
-
res += 'x0' if style_formatting and base == 16
|
1090
|
-
res += '-' if minus
|
1091
|
-
res.reverse
|
1092
|
-
end
|
1093
|
-
|
1094
|
-
def to_p(padding_count = 1, big_endian = true)
|
1095
|
-
value = self
|
1096
|
-
minus = if value < 0
|
1097
|
-
value = -value
|
1098
|
-
true
|
1099
|
-
end
|
1100
|
-
res = ''
|
1101
|
-
while value != 0
|
1102
|
-
value, rem = value.divmod(256)
|
1103
|
-
res += rem.chr
|
1104
|
-
end
|
1105
|
-
|
1106
|
-
pad_char = if minus
|
1107
|
-
negres += ''
|
1108
|
-
over = 1
|
1109
|
-
res.each_byte do |byte|
|
1110
|
-
negbyte = 255 - byte + over
|
1111
|
-
negres += if negbyte > 255
|
1112
|
-
over = 1
|
1113
|
-
0
|
1114
|
-
else
|
1115
|
-
over = 0
|
1116
|
-
negbyte
|
1117
|
-
end
|
1118
|
-
end
|
1119
|
-
res = negres
|
1120
|
-
"\xFF"
|
1121
|
-
else
|
1122
|
-
"\0"
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
res += pad_char * (padding_count - res.size) if res.size < padding_count
|
1126
|
-
|
1127
|
-
(big_endian ? res.reverse(String::ByteByByte) : res).to_p
|
1128
|
-
end
|
1129
|
-
end
|
1130
|
-
|
1131
|
-
class Fixnum
|
1132
|
-
alias :__chr__ :chr
|
1133
|
-
def chr
|
1134
|
-
if self >= 256
|
1135
|
-
num = self; s = "\0"; byte = 0x80; a = []
|
1136
|
-
while num >= 0x40
|
1137
|
-
s.setbyte(0, byte + (num & 0x3F))
|
1138
|
-
a << s.dup; num >>= 6; byte = 0x40
|
1139
|
-
end
|
1140
|
-
s.setbyte(0, 0xC0 + (num & 0x3F))
|
1141
|
-
a << s
|
1142
|
-
a.reverse.join
|
1143
|
-
else; __chr__ end
|
1144
|
-
end
|
1145
|
-
end
|
4
|
+
require 'rdoba/a'
|
5
|
+
require 'rdoba/io'
|
6
|
+
require 'rdoba/dup'
|
7
|
+
require 'rdoba/require'
|
8
|
+
require 'rdoba/common'
|
9
|
+
require 'rdoba/debug'
|
10
|
+
require 'rdoba/yaml'
|
11
|
+
require 'rdoba/strings'
|
12
|
+
require 'rdoba/deploy'
|
13
|
+
require 'rdoba/roman'
|
14
|
+
require 'rdoba/combinations'
|
15
|
+
require 'rdoba/hashorder'
|
16
|
+
require 'rdoba/fenc'
|
1146
17
|
|