rdoba 0.0.3 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rdoba.rb CHANGED
@@ -1,1146 +1,17 @@
1
1
  #!/usr/bin/ruby -KU
2
2
  #<Encoding:UTF-8>
3
3
 
4
- require 'strscan'
5
- require 'timeout'
6
-
7
- class Object
8
- attr_reader :debug
9
-
10
- eval "$debug_#{__FILE__.gsub(/[^\w\d_]/,'_')} = 0"
11
- @debug = nil
12
- @@debug = nil
13
- eval "$debug_#{self.class} = 0"
14
-
15
- public
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