sequence 0.1.0
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/COPYING +58 -0
- data/GPL +340 -0
- data/Manifest.txt +36 -0
- data/README.txt +320 -0
- data/Rakefile +32 -0
- data/lib/assert.rb +16 -0
- data/lib/sequence/arraylike.rb +57 -0
- data/lib/sequence/buffered.rb +188 -0
- data/lib/sequence/circular.rb +272 -0
- data/lib/sequence/enum.rb +260 -0
- data/lib/sequence/file.rb +172 -0
- data/lib/sequence/functional.rb +152 -0
- data/lib/sequence/generator.rb +290 -0
- data/lib/sequence/indexed.rb +234 -0
- data/lib/sequence/io.rb +102 -0
- data/lib/sequence/list.rb +292 -0
- data/lib/sequence/ofhash.rb +38 -0
- data/lib/sequence/ofobjectivars.rb +29 -0
- data/lib/sequence/ofobjectmethods.rb +87 -0
- data/lib/sequence/position.rb +100 -0
- data/lib/sequence/reversed.rb +180 -0
- data/lib/sequence/shifting.rb +190 -0
- data/lib/sequence/singleitem.rb +50 -0
- data/lib/sequence/stringlike.rb +482 -0
- data/lib/sequence/subseq.rb +90 -0
- data/lib/sequence/usedata.rb +35 -0
- data/lib/sequence/version.rb +5 -0
- data/lib/sequence.rb +721 -0
- data/lib/weakrefset.rb +254 -0
- data/test/test.rb +609 -0
- data/test/test_all.rb +6 -0
- data/test/test_changes.rb +44 -0
- data/test/test_circulars.rb +89 -0
- data/test/test_rexscan.rb +899 -0
- data/test/test_seqrex.rb +204 -0
- data/test/test_sequences.rb +106 -0
- metadata +90 -0
@@ -0,0 +1,180 @@
|
|
1
|
+
# $Id$
|
2
|
+
# Copyright (C) 2006 Caleb Clausen
|
3
|
+
# Distributed under the terms of Ruby's license.
|
4
|
+
|
5
|
+
require 'sequence'
|
6
|
+
|
7
|
+
class Sequence
|
8
|
+
class Circular< Sequence; end #forward decl
|
9
|
+
# This class can be used to reverse the direction of operations on a given
|
10
|
+
# sequence. It has a separate position, independant of the original sequence's.
|
11
|
+
class Reversed < Sequence
|
12
|
+
#when reversed and circular, always put the Circular outermost.
|
13
|
+
class<<self
|
14
|
+
alias new__no_circular new
|
15
|
+
def new(sequence,pos=0)
|
16
|
+
if Circular===sequence
|
17
|
+
Circular.new(new__no_circular(sequence.data,pos))
|
18
|
+
else
|
19
|
+
new__no_circular(sequence,pos)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def initialize(sequence,pos=0)
|
26
|
+
@seq = sequence
|
27
|
+
@pos=pos
|
28
|
+
@size=sequence.size
|
29
|
+
extend @seq.like
|
30
|
+
|
31
|
+
@seq.on_change_notify self
|
32
|
+
end
|
33
|
+
|
34
|
+
def translate_pos(pos)
|
35
|
+
@size-pos
|
36
|
+
end
|
37
|
+
|
38
|
+
def change_notification(cu,first,oldsize,newsize)
|
39
|
+
# Process.kill("INT",0)
|
40
|
+
assert cu==@seq
|
41
|
+
# @pos =translate_pos cu._adjust_pos_on_change(translate_pos(pos), first,oldsize,newsize)
|
42
|
+
first=translate_pos(first+oldsize)
|
43
|
+
@pos =_adjust_pos_on_change((pos), first,oldsize,newsize)
|
44
|
+
@size+=newsize-oldsize
|
45
|
+
assert @size==@seq.size
|
46
|
+
notify_change(self, first,oldsize,newsize)
|
47
|
+
end
|
48
|
+
|
49
|
+
# :stopdoc:
|
50
|
+
def new_data
|
51
|
+
@seq.new_data
|
52
|
+
end
|
53
|
+
=begin ***
|
54
|
+
def read1after
|
55
|
+
@seq.read1before
|
56
|
+
end
|
57
|
+
def read1before
|
58
|
+
@seq.read1after
|
59
|
+
end
|
60
|
+
|
61
|
+
def skip1next
|
62
|
+
@seq.skip1prev
|
63
|
+
end
|
64
|
+
def skip1prev
|
65
|
+
@seq.skip1next
|
66
|
+
end
|
67
|
+
def skip1after
|
68
|
+
@seq.skip1before
|
69
|
+
end
|
70
|
+
def skip1before
|
71
|
+
@seq.skip1after
|
72
|
+
end
|
73
|
+
def delete1after
|
74
|
+
v0 = @seq.delete1before
|
75
|
+
v0 && @positions && _adjust_delete
|
76
|
+
v0
|
77
|
+
end
|
78
|
+
def delete1before
|
79
|
+
v0 = @seq.delete1after
|
80
|
+
v0 && @positions && _adjust_delete
|
81
|
+
v0
|
82
|
+
end
|
83
|
+
def delete1after?
|
84
|
+
v0 = @seq.delete1before?
|
85
|
+
v0.nil? || @positions && _adjust_delete
|
86
|
+
v0
|
87
|
+
end
|
88
|
+
def delete1before?
|
89
|
+
v0 = @seq.delete1after?
|
90
|
+
v0.nil? || @positions && _adjust_delete
|
91
|
+
v0
|
92
|
+
end
|
93
|
+
def write1next(v)
|
94
|
+
@seq.write1prev(v)
|
95
|
+
end
|
96
|
+
def write1prev(v)
|
97
|
+
@seq.write1next(v)
|
98
|
+
end
|
99
|
+
def write1after(v)
|
100
|
+
@seq.write1before(v)
|
101
|
+
end
|
102
|
+
def write1before(v)
|
103
|
+
@seq.write1after(v)
|
104
|
+
end
|
105
|
+
def write1next?(v)
|
106
|
+
@seq.write1prev?(v)
|
107
|
+
end
|
108
|
+
def write1prev?(v)
|
109
|
+
@seq.write1next?(v)
|
110
|
+
end
|
111
|
+
def write1after?(v)
|
112
|
+
@seq.write1before?(v)
|
113
|
+
end
|
114
|
+
def write1before?(v)
|
115
|
+
@seq.write1after?(v)
|
116
|
+
end
|
117
|
+
def insert1before(v)
|
118
|
+
@positions && _adjust_insert
|
119
|
+
@seq.insert1after(v)
|
120
|
+
end
|
121
|
+
def insert1after(v)
|
122
|
+
@positions && _adjust_insert
|
123
|
+
@seq.insert1before(v)
|
124
|
+
end
|
125
|
+
def scan1next(v)
|
126
|
+
@seq.scan1prev(v)
|
127
|
+
end
|
128
|
+
def scan1prev(v)
|
129
|
+
@seq.scan1next(v)
|
130
|
+
end
|
131
|
+
def modify1next(lookup)
|
132
|
+
@seq.modify1prev(lookup)
|
133
|
+
end
|
134
|
+
def modify1prev(lookup)
|
135
|
+
@seq.modify1next(lookup)
|
136
|
+
end
|
137
|
+
=end
|
138
|
+
attr_reader :pos,:size
|
139
|
+
def _pos=(pos)
|
140
|
+
@pos=pos
|
141
|
+
end
|
142
|
+
|
143
|
+
def read(len)
|
144
|
+
assert @pos>=0
|
145
|
+
assert @size>=@pos
|
146
|
+
start =@size-@pos-len
|
147
|
+
start<0 and start=0
|
148
|
+
result=@seq[start...@size-@pos] or return ""
|
149
|
+
@pos+=result.size
|
150
|
+
result.reverse
|
151
|
+
end
|
152
|
+
|
153
|
+
def modify(*args)
|
154
|
+
first,len,only1=_parse_slice_args( *args[0..-2] )
|
155
|
+
# puts "first=#{first}, len=#{len}"
|
156
|
+
first=@size-first-len
|
157
|
+
@seq.modify first, len, args.last.reverse
|
158
|
+
#notify_change(self,first,len,args.last.size) #?? is this a good idea?
|
159
|
+
args.last
|
160
|
+
end
|
161
|
+
|
162
|
+
def eof?
|
163
|
+
@pos>=@size
|
164
|
+
end
|
165
|
+
|
166
|
+
def closed?
|
167
|
+
super or @seq.closed?
|
168
|
+
end
|
169
|
+
|
170
|
+
def reverse
|
171
|
+
@seq.position(0)
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
# :startdoc:
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# $Id$
|
2
|
+
# Copyright (C) 2006 Caleb Clausen
|
3
|
+
# Distributed under the terms of Ruby's license.
|
4
|
+
|
5
|
+
require 'sequence'
|
6
|
+
|
7
|
+
class Sequence
|
8
|
+
#a primary sequence (presumably unidirectional) with a secondary sequence
|
9
|
+
#as backup. the primary is traversed in the forward direcion only. the
|
10
|
+
#secondary holds a copy of data as it comes from the primary sequence. the
|
11
|
+
#position can be independantly changed to any location; if before the
|
12
|
+
#current position of the primary sequence, the secondary sequence is used
|
13
|
+
#instead. all writes go to the secondary sequence.
|
14
|
+
|
15
|
+
|
16
|
+
class Shifting < Sequence
|
17
|
+
def initialize(seq,data= Sequence::Indexed.new(seq.new_data))
|
18
|
+
@seq=seq #primary
|
19
|
+
@data = data #secondary
|
20
|
+
@offset=@seq.pos
|
21
|
+
|
22
|
+
extend @seq.like
|
23
|
+
|
24
|
+
@seq.on_change_notify self
|
25
|
+
end
|
26
|
+
# :stopdoc:
|
27
|
+
def new_data
|
28
|
+
@data.new_data
|
29
|
+
end
|
30
|
+
|
31
|
+
def change_notification(cu,first,oldsize,newsize)
|
32
|
+
assert @seq==cu
|
33
|
+
|
34
|
+
if first<=@offset
|
35
|
+
if first+oldsize>=@offset
|
36
|
+
offset=first
|
37
|
+
end
|
38
|
+
@offset-=oldsize-newsize
|
39
|
+
end
|
40
|
+
|
41
|
+
#modify @data (shift buffer) to suit
|
42
|
+
if first<@offset
|
43
|
+
@data.prepend @seq[first...@offset]
|
44
|
+
@offset=first
|
45
|
+
elsif first<@data.size+@offset #if change within already shifted data
|
46
|
+
@data[first-@offset,oldsize]= @seq[first,newsize]
|
47
|
+
end
|
48
|
+
|
49
|
+
notify_change(self,first,oldsize,newsize)
|
50
|
+
end
|
51
|
+
=begin ***
|
52
|
+
protected
|
53
|
+
def _delete1after?
|
54
|
+
@pos.nonzero? && (@pos0 -= 1) && @data.slice!(0)
|
55
|
+
end
|
56
|
+
def _delete1before?
|
57
|
+
@pos==@data.size ? nil : @data.slice!(-1)
|
58
|
+
end
|
59
|
+
def _insert1before(v)
|
60
|
+
@data << v
|
61
|
+
true
|
62
|
+
end
|
63
|
+
def _insert1after(v)
|
64
|
+
@data[0,0] = (@data.class.new << v)
|
65
|
+
@pos += 1
|
66
|
+
true
|
67
|
+
end
|
68
|
+
=end
|
69
|
+
protected
|
70
|
+
def history_mode?
|
71
|
+
!@data.eof?
|
72
|
+
end
|
73
|
+
|
74
|
+
public
|
75
|
+
def read(len)
|
76
|
+
assert oldpos=pos
|
77
|
+
if history_mode?
|
78
|
+
rest=@seq.pos-pos
|
79
|
+
len<=rest and return @data.read(len)
|
80
|
+
@data.append @seq.read(len-rest)
|
81
|
+
else
|
82
|
+
assert @data.pos+@offset==@seq.pos
|
83
|
+
@data.append @seq.read(len)
|
84
|
+
end
|
85
|
+
result=@data.read!
|
86
|
+
# assert pos==oldpos+len || pos==size
|
87
|
+
return result
|
88
|
+
end
|
89
|
+
|
90
|
+
def _pos= x;
|
91
|
+
assert @data.empty?|| (0..@data.size)===pos-@offset
|
92
|
+
#assert @data.size+@offset==@seq.pos
|
93
|
+
if @data.empty?
|
94
|
+
diff=x-@offset
|
95
|
+
@data<<
|
96
|
+
if diff<0
|
97
|
+
@offset=x
|
98
|
+
diff=-diff
|
99
|
+
@seq[x,diff] rescue
|
100
|
+
case data_class
|
101
|
+
when ::Array: [nil]
|
102
|
+
when ::String: "\0"
|
103
|
+
else fail
|
104
|
+
end*diff
|
105
|
+
|
106
|
+
else #diff>=0
|
107
|
+
@seq.read(diff)
|
108
|
+
end
|
109
|
+
|
110
|
+
@data.pos=x-@offset
|
111
|
+
assert @data.size+@offset==@seq.pos
|
112
|
+
assert( (0..@data.size)===x-@offset )
|
113
|
+
elsif x<@offset
|
114
|
+
offset=@offset
|
115
|
+
@offset=x
|
116
|
+
@data.prepend((
|
117
|
+
@seq[x...offset] rescue
|
118
|
+
case data_class
|
119
|
+
when ::Array: [nil]
|
120
|
+
when ::String: "\0"
|
121
|
+
else fail
|
122
|
+
end*(offset-x)
|
123
|
+
))
|
124
|
+
# assert @data.size+@offset==@seq.pos
|
125
|
+
assert( (0..@data.size)===x-@offset )
|
126
|
+
elsif x>@data.size+@offset
|
127
|
+
# assert @seq.pos==@data.size+@offset
|
128
|
+
@data<<@seq.read(x-@data.size-@offset)
|
129
|
+
@data.pos=@data.size
|
130
|
+
#assert @data.size+@offset==@seq.pos
|
131
|
+
assert( (0..@data.size)===x-@offset )
|
132
|
+
else
|
133
|
+
@data.pos=x-@offset
|
134
|
+
#assert @data.size+@offset==@seq.pos
|
135
|
+
assert( (0..@data.size)===x-@offset )
|
136
|
+
end
|
137
|
+
#assert @data.size+@offset==@seq.pos
|
138
|
+
assert( (0..@data.size)===x-@offset )
|
139
|
+
# assert(pos==x || pos==size)
|
140
|
+
x
|
141
|
+
end
|
142
|
+
|
143
|
+
def modify *args
|
144
|
+
newvals=args.pop
|
145
|
+
first,len,only1=_parse_slice_args( *args )
|
146
|
+
only1 and newvals=new_data<<newvals
|
147
|
+
|
148
|
+
assert @data.size+@offset==@seq.pos
|
149
|
+
|
150
|
+
oldpos=pos
|
151
|
+
|
152
|
+
if @data.empty?
|
153
|
+
@offset=first
|
154
|
+
@data<<newvals
|
155
|
+
@data.pos=_adjust_pos_on_change(oldpos, first, len, newvals.size)-@offset
|
156
|
+
#assert @data.size+@offset==@seq.pos
|
157
|
+
else
|
158
|
+
#if first...first+len outside of @data, read it into @data first
|
159
|
+
oldpos=pos
|
160
|
+
self._pos=first
|
161
|
+
self._pos=first+len
|
162
|
+
self._pos=oldpos #then revert to orig position
|
163
|
+
|
164
|
+
assert( (0...@data.size)===first-@offset )
|
165
|
+
assert( (0...@data.size)===first+len-@offset )
|
166
|
+
@data.modify first-@offset,len,newvals
|
167
|
+
#assert @data.size+@offset==@seq.pos
|
168
|
+
end
|
169
|
+
notify_change(self,first,len,newvals.size)
|
170
|
+
|
171
|
+
#assert @data.size+@offset==@seq.pos
|
172
|
+
|
173
|
+
newvals
|
174
|
+
end
|
175
|
+
|
176
|
+
def pos; @data.pos+@offset end
|
177
|
+
|
178
|
+
def_delegators :@seq, :size
|
179
|
+
|
180
|
+
def eof?; @data.eof? and @seq.eof? end
|
181
|
+
# :startdoc:
|
182
|
+
|
183
|
+
def closed?
|
184
|
+
super or @seq.closed?
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright (C) 2006 Caleb Clausen
|
2
|
+
# Distributed under the terms of Ruby's license.
|
3
|
+
require 'sequence'
|
4
|
+
|
5
|
+
class Sequence
|
6
|
+
#represnts a seq over a single item
|
7
|
+
class SingleItem < Sequence
|
8
|
+
include ArrayLike
|
9
|
+
def initialize(obj)
|
10
|
+
@obj=obj
|
11
|
+
@eof=false
|
12
|
+
end
|
13
|
+
|
14
|
+
def read1
|
15
|
+
result=readahead1
|
16
|
+
@eof=true
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def readahead1
|
21
|
+
@obj unless @eof
|
22
|
+
end
|
23
|
+
|
24
|
+
def size; 1 end
|
25
|
+
|
26
|
+
def eof?; @eof end
|
27
|
+
|
28
|
+
def read(len)
|
29
|
+
@eof and return []
|
30
|
+
@eof=true
|
31
|
+
return [@obj]
|
32
|
+
end
|
33
|
+
|
34
|
+
def begin!
|
35
|
+
@eof=false
|
36
|
+
end
|
37
|
+
|
38
|
+
def end!
|
39
|
+
@eof=true
|
40
|
+
end
|
41
|
+
|
42
|
+
def pos
|
43
|
+
@eof ? 1 : 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def _pos=(pos)
|
47
|
+
@eof=pos.nonzero?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|