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.
- data/README.en +31 -0
- data/lib/#random-readable.rb# +598 -0
- data/lib/common-traits.rb +71 -0
- data/lib/random-accessible.rb +340 -0
- data/lib/random-readable.rb +598 -0
- data/lib/random-writable.rb +302 -0
- data/test/test-suite.rb +3 -0
- metadata +74 -0
@@ -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
|
data/test/test-suite.rb
ADDED
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
|