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.
@@ -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