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