random-accessible 0.1.2

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,302 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright 2011 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+
6
+ require 'common-traits'
7
+
8
+ # RandomWritable mixin provides write-access methods of Array.
9
+ # The class must provide one or more methods from replace-accessor
10
+ # ([]=, replace_at, replace_access) and shrink-accessor (shrink) respectively.
11
+ # The class may provide insert-accessor (insert_access, insert_at, insert)
12
+ # and delete-accessor (delete_access, delete_at).
13
+ # replace_at(pos, val) has same function as []= but it does not need to accept
14
+ # Range or start/length arguments.
15
+ # The class may provide one size-provider (size, length).
16
+ # The class may provide (size, length).
17
+ # replace_access(pos) is similar to replace_at. But the mixin guarantees
18
+ # that 0 <= pos, and pos < size if the class has a size-provider.
19
+ # insert_at(pos, val) is fixed-number-argument version of insert(pos, *val)
20
+ # insert_access(pos, val) is similar to insert_at. But the mixin guarantees
21
+ # that 0 <= pos, and pos < size if the class has a size-provider.
22
+ # delete_access is similar to delete_at. But the mixin guarantees
23
+ # that 0 <= pos, and pos < size if the class has a size-provider.
24
+ # If the class does not provide size-provider, insert_accessor, or delete_accessor,
25
+ # some of the methods of the module raises NotImplementedError.
26
+ # Please see the document of each method.
27
+ module RandomWritable
28
+
29
+ include RandomAccessible::CommonTraits
30
+
31
+ # Raises NotImplemented Error.
32
+ # Override this on user classes.
33
+ def insert_access(pos, val)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ # Raises NotImplemented Error.
38
+ # Override this on user classes.
39
+ def delete_access(pos)
40
+ raise NotImplementedError
41
+ end
42
+
43
+ # replace_at is similar to Array#[]=.
44
+ # But it does not need to accept Range or start/length arguments.
45
+ def replace_at(pos, val)
46
+ if pos < 0
47
+ pos = size + pos
48
+ end
49
+ if has_size? && size <= pos
50
+ expand(pos - size + 1)
51
+ end
52
+ replace_access(pos, val)
53
+ return self
54
+ end
55
+
56
+ # Empty method.
57
+ # Override if you need something to do
58
+ # when expanding the object.
59
+ def expand(n)
60
+ # Nothing to do.
61
+ end
62
+
63
+ # Fixed-number-argument version of insert(pos, *val)
64
+ # This method raises NotImplementedError
65
+ # if the class does not provide insert_access(pos, val).
66
+ def insert_at(pos, val)
67
+ if pos < 0
68
+ pos = size + pos + 1
69
+ end
70
+ if pos < 0
71
+ raise IndexError, "index is too small"
72
+ end
73
+ insert_access(pos, val)
74
+ return self
75
+ end
76
+
77
+ # Same as Array's.
78
+ # This method raises NotImplementedError
79
+ # if the class provides no size-provider and pos is negative
80
+ # This method raises NotImplementedError
81
+ # if the class does not provide delete_access.
82
+ def delete_at(pos)
83
+ if pos < 0
84
+ pos = size + pos
85
+ end
86
+ if pos < 0 || (has_size? && size <= pos)
87
+ return nil
88
+ end
89
+ return delete_access(pos)
90
+ end
91
+
92
+ # Same as Array's.
93
+ # This method raises NotImplementedError
94
+ # if the class provides no size-provider.
95
+ def <<(obj)
96
+ index = size
97
+ expand(1)
98
+ replace_access(index, obj)
99
+ return self
100
+ end
101
+
102
+ # Same as Array's.
103
+ # This method raises NotImplementedError
104
+ # if the class provides no size-provider and the argument is (or includes) negative.
105
+ def []=(*args)
106
+ if args.size <= 1 || 4 <= args.size
107
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 2..3)"
108
+ end
109
+
110
+ val = args.pop
111
+ if args.size == 2
112
+ start = args[0].to_int
113
+ len = args[1].to_int
114
+ if has_size?
115
+ if start < -size
116
+ raise IndexError, "index #{start} too small for array; minimun: #{-size}"
117
+ end
118
+ else
119
+ if start < 0
120
+ raise IndexError, "index #{start} too small for array; minimun: 0"
121
+ end
122
+ end
123
+ if val.respond_to? :to_ary
124
+ val = val.to_ary
125
+ else
126
+ val = [val]
127
+ end
128
+ if has_size?
129
+ if start + len > size
130
+ len = size - start + 1
131
+ end
132
+ if len <= 0
133
+ len = 1
134
+ end
135
+ end
136
+ if val.size < len
137
+ (len - val.size).times do
138
+ delete_at(start + val.size)
139
+ end
140
+ val.size.times do |i|
141
+ replace_at(start + i, val[i])
142
+ end
143
+ elsif val.size >= len
144
+ len.times do |i|
145
+ replace_at(start + i, val[i])
146
+ end
147
+ (val.size - len).times do |i|
148
+ insert_at(start + len + i, val[len + i])
149
+ end
150
+ end
151
+ elsif args[0].is_a? Range
152
+ range = args[0]
153
+ if !has_size?
154
+ if range.first < 0
155
+ raise RangeError, "#{range.to_s} out of range"
156
+ end
157
+ elsif range.first < -size
158
+ raise RangeError, "#{range.to_s} out of range"
159
+ end
160
+ first = range.first
161
+ last = range.last
162
+ last += 1 unless range.exclude_end?
163
+ self[first, last - first] = val
164
+ else
165
+ replace_at(args[0].to_int, val)
166
+ end
167
+ end
168
+
169
+ # Same as Array's.
170
+ # This method raises NotImplementedError
171
+ # if the class provides no size-provider.
172
+ def clear
173
+ shrink(size)
174
+ end
175
+
176
+ # Same as Array's.
177
+ # This method raises NotImplementedError
178
+ # if the class provides no size-provider.
179
+ # Note that the argument must accept read access.
180
+ def concat(other)
181
+ i = size
182
+ expand(other.size)
183
+ other.each do |el|
184
+ replace_at(i, el)
185
+ i += 1
186
+ end
187
+ end
188
+
189
+ # Same as Array's.
190
+ # This method raises NotImplementedError
191
+ # if the class provides no size-provider and the arguments does not include
192
+ # Range nor start/length.
193
+ def fill(*args, &block)
194
+ if args.size > (block.nil? ? 3 : 2) ||
195
+ args.size < (block.nil? ? 1 : 0)
196
+ raise ArgumentError, "wrong number of arguments (#{args.size})"
197
+ end
198
+
199
+ val = nil
200
+ if block.nil?
201
+ val = args.shift
202
+ end
203
+
204
+ if args[0].is_a? Range
205
+ range = args[0]
206
+ if block.nil?
207
+ fill(val, range.first, range.last - range.first)
208
+ end
209
+ elsif args.size != 0
210
+ start = args[0].to_int
211
+ len = args.size == 2 ? args[1] : size
212
+ if block.nil?
213
+ args[1].times do |i|
214
+ replace_at(start + i, val)
215
+ end
216
+ else
217
+ args[1].times do |i|
218
+ index = start + i
219
+ replace_at(index, block.call(index))
220
+ end
221
+ end
222
+ else
223
+ size.times do |i|
224
+ if block.nil?
225
+ replace_at(i, val)
226
+ else
227
+ replace_at(i, block.call(i))
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ # Same as Array's.
234
+ # This method raises NotImplementedError
235
+ # if the class provides no insert-accessor.
236
+ def insert(nth, *val)
237
+ val.each_with_index do |el, i|
238
+ if nth > 0
239
+ insert_at(nth + i, el)
240
+ else
241
+ insert_at(nth, el)
242
+ end
243
+ end
244
+ end
245
+
246
+ # Remove specified number of elements from the last of this object.
247
+ # If the number is not specified, remove one element.
248
+ # This method ALWAYS RETURNS NULL.
249
+ def pop(*args)
250
+ if args.size > 1
251
+ raise ArgumentError, "wrong number of arguments (#{args.size})"
252
+ end
253
+
254
+ n = 1
255
+ if args.size == 1
256
+ n = args[0].to_int
257
+ end
258
+ shrink(n)
259
+ return nil
260
+ end
261
+
262
+ # Same as Array's.
263
+ # This method raises NotImplementedError
264
+ # if the class provides no size-provider.
265
+ def push(*obj)
266
+ obj.each do |el|
267
+ replace_at(size, el)
268
+ end
269
+ end
270
+
271
+ # Same as Array's.
272
+ # This method raises NotImplementedError
273
+ # if the class provides no size-provider.
274
+ def replace(another)
275
+ diff = another.size - size
276
+ shrink(-diff) if diff < 0
277
+ expand(diff) if diff > 0
278
+ another.each_with_index do |el, index|
279
+ replace_at(index, el)
280
+ end
281
+ return self
282
+ end
283
+
284
+ # Same as Array's.
285
+ # This method raises NotImplementedError
286
+ # if the class provides no delete-accessor.
287
+ def shift(*args)
288
+ if args.size > 1
289
+ raise ArgumentError, "wrong number of arguments(#{args.size})"
290
+ end
291
+
292
+ n = 1
293
+ unless args.empty?
294
+ n = args[0].to_int
295
+ end
296
+ n.times do
297
+ delete_at(0)
298
+ end
299
+ return nil
300
+ end
301
+
302
+ end
@@ -0,0 +1,3 @@
1
+ require 'test/test-random-readable'
2
+ require 'test/test-random-writable'
3
+ require 'test/test-random-accessible'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: random-accessible
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Natsuki Kawai
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-03 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'RandomAccessible mixin provides all methods of Array to your classes
15
+ (regard as high-functioning edition of Enumerable).
16
+
17
+ As Enumerable mixin requests "each" method, RandomAccessible requests methods below
18
+ (or alternative, please see README.en for detail).
19
+
20
+
21
+ - size (same as Array#size)
22
+
23
+
24
+ - read_access (similar to Array#[])
25
+
26
+
27
+ - replace_access (similar to Array#[]=)
28
+
29
+
30
+ - shrink (similar to Array#pop)
31
+
32
+ '
33
+ email:
34
+ - natsuki.kawai@gmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files:
38
+ - README.en
39
+ files:
40
+ - lib/#random-readable.rb#
41
+ - lib/random-accessible.rb
42
+ - lib/common-traits.rb
43
+ - lib/random-writable.rb
44
+ - lib/random-readable.rb
45
+ - README.en
46
+ - test/test-suite.rb
47
+ homepage: https://github.com/natsuki14/random-accessible
48
+ licenses:
49
+ - Ruby's
50
+ - 2-clause BSDL
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.12
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: RandomAccessible mixin provides all methods of Array.
73
+ test_files:
74
+ - test/test-suite.rb