sequence 0.1.0

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