list 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +30 -0
- data/ext/list/extconf.rb +5 -0
- data/ext/list/list.c +2084 -0
- data/full_spec.sh +16 -0
- data/list.gemspec +25 -0
- data/spec/bench.rb +40 -0
- data/spec/list_spec.rb +670 -0
- data/spec/mem_spec.rb +11 -0
- data/spec/spec_helper.rb +5 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 264292b03be68afb56aa90769cddbe53f77973a9
|
4
|
+
data.tar.gz: 64157b4b9936f988264f238c7e77db0cc47bbdae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aae8d581f0359c840d9370d75cacdd31d0a10481353b303371790c94254958acb0ee136cbace00903037df94240cd69fab1c5b2d5f5ac65d93e0c73e0ac9b187
|
7
|
+
data.tar.gz: 5752f7964479242e99c30d9b474100b70e344e81552eaa3df72820047ba9bc45cc115931aead439e654b0cb2805f982af0834707797da5cee4348676109eb32f
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 ksss
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# List
|
2
|
+
|
3
|
+
List in Ruby.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/ksss/list)
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
All interface is same with Array class.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
list = List.new
|
13
|
+
list.push 1,2,3
|
14
|
+
list.pop
|
15
|
+
list[0,1]
|
16
|
+
list.each do |i|
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
+---------+ +->+---------+ +->+---------+
|
21
|
+
| value | | | value | | | value |
|
22
|
+
| next |--+ | next |--+ | next |
|
23
|
+
+---------+ +---------+ +---------+
|
24
|
+
|
25
|
+
But, List is not Array.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
list = List[1,2,3]
|
29
|
+
list.ring.each do |i|
|
30
|
+
puts i # print infinitely 1,2,3,1,2,3,1,2...
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
+->+---------+ +->+---------+ +->+---------+
|
35
|
+
| | value | | | value | | | value |
|
36
|
+
| | next |--+ | next |--+ | next |--+
|
37
|
+
| +---------+ +---------+ +---------+ |
|
38
|
+
+-----------------------------------------------+
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
gem 'list'
|
45
|
+
|
46
|
+
And then execute:
|
47
|
+
|
48
|
+
$ bundle
|
49
|
+
|
50
|
+
Or install it yourself as:
|
51
|
+
|
52
|
+
$ gem install list
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
|
56
|
+
1. Fork it ( http://github.com/ksss/list/fork )
|
57
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
58
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
59
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
60
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.rspec_opts = ["-c", "-f progress", "-Ilib"]
|
8
|
+
t.pattern = "spec/**/*_spec.rb"
|
9
|
+
t.verbose = true
|
10
|
+
end
|
11
|
+
task :spec => :compile
|
12
|
+
|
13
|
+
require 'rake/extensiontask'
|
14
|
+
spec = Bundler::GemHelper.gemspec
|
15
|
+
Rake::ExtensionTask.new('list', spec) do |ext|
|
16
|
+
ext.ext_dir = 'ext/list'
|
17
|
+
ext.lib_dir = 'lib'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "gem reinstall"
|
21
|
+
task :reinstall do |t|
|
22
|
+
system "gem uninstall list"
|
23
|
+
system "rake clean"
|
24
|
+
system "bundle exec rake"
|
25
|
+
system "rake install"
|
26
|
+
system "irb -rlist"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
task :default => [:spec,:build]
|
data/ext/list/extconf.rb
ADDED
data/ext/list/list.c
ADDED
@@ -0,0 +1,2084 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ruby/encoding.h"
|
3
|
+
|
4
|
+
#define LIST_VERSION "0.0.1"
|
5
|
+
|
6
|
+
VALUE cList;
|
7
|
+
|
8
|
+
ID id_cmp, id_each;
|
9
|
+
|
10
|
+
typedef struct item_t {
|
11
|
+
VALUE value;
|
12
|
+
struct item_t *next;
|
13
|
+
} item_t;
|
14
|
+
|
15
|
+
typedef struct {
|
16
|
+
item_t *first;
|
17
|
+
item_t *last;
|
18
|
+
long len;
|
19
|
+
} list_t;
|
20
|
+
|
21
|
+
#define DEBUG 0
|
22
|
+
|
23
|
+
#define LIST_MAX_SIZE ULONG_MAX
|
24
|
+
|
25
|
+
#ifndef FALSE
|
26
|
+
# define FALSE 0
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#ifndef TRUE
|
30
|
+
# define TRUE 1
|
31
|
+
#endif
|
32
|
+
|
33
|
+
/* compatible for ruby-v1.9.3 */
|
34
|
+
#ifndef UNLIMITED_ARGUMENTS
|
35
|
+
# define UNLIMITED_ARGUMENTS (-1)
|
36
|
+
#endif
|
37
|
+
|
38
|
+
/* compatible for ruby-v1.9.3 */
|
39
|
+
#ifndef rb_check_arity
|
40
|
+
# define rb_check_arity(argc,min,max) do { \
|
41
|
+
if (((argc) < (min) || ((max) != UNLIMITED_ARGUMENTS && (max) < (argc)))) { \
|
42
|
+
rb_raise(rb_eArgError, "wrong number of argument (%d for %d..%d)", argc, min, max); \
|
43
|
+
} \
|
44
|
+
} while (0)
|
45
|
+
#endif
|
46
|
+
|
47
|
+
/* compatible for ruby-v1.9.3 */
|
48
|
+
#ifndef RETURN_SIZED_ENUMERATOR
|
49
|
+
# define RETURN_SIZED_ENUMERATOR(a,b,c,d) RETURN_ENUMERATOR(a,b,c)
|
50
|
+
#else
|
51
|
+
static VALUE
|
52
|
+
list_enum_length(VALUE self, VALUE args, VALUE eobj)
|
53
|
+
{
|
54
|
+
list_t *ptr;
|
55
|
+
Data_Get_Struct(self, list_t, ptr);
|
56
|
+
return LONG2NUM(ptr->len);
|
57
|
+
}
|
58
|
+
#endif
|
59
|
+
|
60
|
+
#define LIST_FOR(ptr, c) for (c = ptr->first; c; c = c->next)
|
61
|
+
|
62
|
+
#define LIST_FOR_DOUBLE(ptr1, c1, ptr2, c2, code) do { \
|
63
|
+
c1 = (ptr1)->first; \
|
64
|
+
c2 = (ptr2)->first; \
|
65
|
+
while ((c1) && (c2)) { \
|
66
|
+
(code); \
|
67
|
+
c1 = (c1)->next; \
|
68
|
+
c2 = (c2)->next; \
|
69
|
+
} \
|
70
|
+
} while (0)
|
71
|
+
|
72
|
+
enum list_take_pos_flags {
|
73
|
+
LIST_TAKE_FIRST,
|
74
|
+
LIST_TAKE_LAST
|
75
|
+
};
|
76
|
+
|
77
|
+
static VALUE list_push_ary(VALUE, VALUE);
|
78
|
+
static VALUE list_push(VALUE, VALUE);
|
79
|
+
static VALUE list_unshift(VALUE, VALUE);
|
80
|
+
static VALUE list_replace(VALUE, VALUE);
|
81
|
+
|
82
|
+
#if DEBUG
|
83
|
+
static void
|
84
|
+
p(const char *str)
|
85
|
+
{
|
86
|
+
rb_p(rb_str_new2(str));
|
87
|
+
}
|
88
|
+
|
89
|
+
static void
|
90
|
+
check_print(list_t *ptr, const char *msg, long lineno)
|
91
|
+
{
|
92
|
+
printf("===ERROR(%s)", msg);
|
93
|
+
printf("lineno:%ld===\n", lineno);
|
94
|
+
printf("ptr:%p\n",ptr);
|
95
|
+
printf("ptr->len:%ld\n",ptr->len);
|
96
|
+
printf("ptr->first:%p\n",ptr->first);
|
97
|
+
printf("ptr->last:%p\n",ptr->last);
|
98
|
+
rb_raise(rb_eRuntimeError, "check is NG!");
|
99
|
+
}
|
100
|
+
|
101
|
+
static void
|
102
|
+
check(list_t *ptr, const char *msg)
|
103
|
+
{
|
104
|
+
item_t *end;
|
105
|
+
item_t *c, *b;
|
106
|
+
long len, i;
|
107
|
+
|
108
|
+
if (ptr->len == 0 && ptr->first != NULL) check_print(ptr, msg, __LINE__);
|
109
|
+
if (ptr->len != 0 && ptr->first == NULL) check_print(ptr, msg, __LINE__);
|
110
|
+
if (ptr->len == 0 && ptr->last != NULL) check_print(ptr, msg, __LINE__);
|
111
|
+
if (ptr->len != 0 && ptr->last == NULL) check_print(ptr, msg, __LINE__);
|
112
|
+
if (ptr->first == NULL && ptr->last != NULL) check_print(ptr, msg, __LINE__);
|
113
|
+
if (ptr->first != NULL && ptr->last == NULL) check_print(ptr, msg, __LINE__);
|
114
|
+
len = ptr->len;
|
115
|
+
if (len == 0) return;
|
116
|
+
i = 0;
|
117
|
+
end = ptr->last->next;
|
118
|
+
i++;
|
119
|
+
for (c = ptr->first->next; c != end; c = c->next) {
|
120
|
+
i++;
|
121
|
+
b = c;
|
122
|
+
}
|
123
|
+
if (b != ptr->last) check_print(ptr, msg, __LINE__);
|
124
|
+
if (len != i) check_print(ptr, msg, __LINE__);
|
125
|
+
}
|
126
|
+
#endif
|
127
|
+
|
128
|
+
static inline VALUE
|
129
|
+
list_new(void)
|
130
|
+
{
|
131
|
+
return rb_obj_alloc(cList);
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE
|
135
|
+
collect_all(VALUE i, VALUE list, int argc, VALUE *argv)
|
136
|
+
{
|
137
|
+
VALUE pack;
|
138
|
+
rb_thread_check_ints();
|
139
|
+
if (argc == 0) pack = Qnil;
|
140
|
+
else if (argc == 1) pack = argv[0];
|
141
|
+
else pack = rb_ary_new4(argc, argv);
|
142
|
+
|
143
|
+
list_push(list, pack);
|
144
|
+
return Qnil;
|
145
|
+
}
|
146
|
+
|
147
|
+
static VALUE
|
148
|
+
ary_to_list(int argc, VALUE *argv, VALUE obj)
|
149
|
+
{
|
150
|
+
VALUE list = list_new();
|
151
|
+
rb_block_call(obj, id_each, argc, argv, collect_all, list);
|
152
|
+
OBJ_INFECT(list, obj);
|
153
|
+
return list;
|
154
|
+
}
|
155
|
+
|
156
|
+
static VALUE
|
157
|
+
to_list(VALUE obj)
|
158
|
+
{
|
159
|
+
switch (rb_type(obj)) {
|
160
|
+
case T_DATA:
|
161
|
+
return obj;
|
162
|
+
case T_ARRAY:
|
163
|
+
return ary_to_list(0, NULL, obj);
|
164
|
+
default:
|
165
|
+
return Qnil;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
static inline void
|
170
|
+
list_modify_check(VALUE self)
|
171
|
+
{
|
172
|
+
rb_check_frozen(self);
|
173
|
+
}
|
174
|
+
|
175
|
+
static void
|
176
|
+
list_mark(list_t *ptr)
|
177
|
+
{
|
178
|
+
item_t *c;
|
179
|
+
item_t *end;
|
180
|
+
|
181
|
+
if (ptr->first == NULL) return;
|
182
|
+
end = ptr->last->next;
|
183
|
+
rb_gc_mark(ptr->first->value);
|
184
|
+
for (c = ptr->first->next; c != end; c = c->next) {
|
185
|
+
rb_gc_mark(c->value);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
static void
|
190
|
+
list_free(list_t *ptr)
|
191
|
+
{
|
192
|
+
item_t *c;
|
193
|
+
item_t *first_next;
|
194
|
+
item_t *next;
|
195
|
+
item_t *end;
|
196
|
+
|
197
|
+
if (ptr->first == NULL) return;
|
198
|
+
first_next = ptr->first->next;
|
199
|
+
end = ptr->last->next;
|
200
|
+
xfree(ptr->first);
|
201
|
+
for (c = first_next; c != end;) {
|
202
|
+
next = c->next;
|
203
|
+
xfree(c);
|
204
|
+
c = next;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
static void
|
209
|
+
list_mem_clear(list_t *ptr, long beg, long len)
|
210
|
+
{
|
211
|
+
long i;
|
212
|
+
item_t *c;
|
213
|
+
item_t *next;
|
214
|
+
item_t *mid, *last;
|
215
|
+
|
216
|
+
if (beg == 0 && len == ptr->len) {
|
217
|
+
list_free(ptr);
|
218
|
+
ptr->first = NULL;
|
219
|
+
ptr->last = NULL;
|
220
|
+
ptr->len = 0;
|
221
|
+
return;
|
222
|
+
}
|
223
|
+
|
224
|
+
i = -1;
|
225
|
+
if (beg == 0) {
|
226
|
+
for (c = ptr->first; c;) {
|
227
|
+
i++;
|
228
|
+
if (i < len) { // mid
|
229
|
+
next = c->next;
|
230
|
+
xfree(c);
|
231
|
+
c = next;
|
232
|
+
}
|
233
|
+
if (len == i) { // end
|
234
|
+
ptr->first = c;
|
235
|
+
break;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
} else if (beg + len == ptr->len) {
|
239
|
+
for (c = ptr->first; c;) {
|
240
|
+
i++;
|
241
|
+
next = c->next;
|
242
|
+
if (beg - 1 == i) { // begin
|
243
|
+
last = c;
|
244
|
+
} else if (beg <= i) { // mid
|
245
|
+
xfree(c);
|
246
|
+
}
|
247
|
+
c = next;
|
248
|
+
}
|
249
|
+
ptr->last = last;
|
250
|
+
ptr->last->next = NULL;
|
251
|
+
} else {
|
252
|
+
for (c = ptr->first; c;) {
|
253
|
+
i++;
|
254
|
+
if (beg == i) { // begin
|
255
|
+
mid = next;
|
256
|
+
}
|
257
|
+
if (beg + len == i) { // end
|
258
|
+
mid->next = c;
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
if (beg <= i) { // mid
|
262
|
+
next = c->next;
|
263
|
+
xfree(c);
|
264
|
+
c = next;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
ptr->len -= len;
|
270
|
+
}
|
271
|
+
|
272
|
+
static inline list_t *
|
273
|
+
list_new_ptr(void)
|
274
|
+
{
|
275
|
+
list_t *ptr = ALLOC(list_t);
|
276
|
+
ptr->first = NULL;
|
277
|
+
ptr->last = ptr->first;
|
278
|
+
ptr->len = 0;
|
279
|
+
return ptr;
|
280
|
+
}
|
281
|
+
|
282
|
+
static VALUE
|
283
|
+
list_alloc(VALUE self)
|
284
|
+
{
|
285
|
+
list_t *ptr = list_new_ptr();
|
286
|
+
return Data_Wrap_Struct(self, list_mark, list_free, ptr);
|
287
|
+
}
|
288
|
+
|
289
|
+
static item_t *
|
290
|
+
item_alloc(VALUE obj, item_t *next)
|
291
|
+
{
|
292
|
+
item_t *item;
|
293
|
+
item = xmalloc(sizeof(item_t));
|
294
|
+
item->value = obj;
|
295
|
+
item->next = next;
|
296
|
+
return item;
|
297
|
+
}
|
298
|
+
|
299
|
+
static VALUE
|
300
|
+
list_push(VALUE self, VALUE obj)
|
301
|
+
{
|
302
|
+
list_t *ptr;
|
303
|
+
item_t *next;
|
304
|
+
|
305
|
+
list_modify_check(self);
|
306
|
+
if (self == obj) {
|
307
|
+
rb_raise(rb_eArgError, "`List' cannot set recursive");
|
308
|
+
}
|
309
|
+
|
310
|
+
next = item_alloc(obj, NULL);
|
311
|
+
|
312
|
+
Data_Get_Struct(self, list_t, ptr);
|
313
|
+
if (ptr->first == NULL) {
|
314
|
+
ptr->first = next;
|
315
|
+
ptr->last = next;
|
316
|
+
ptr->last->next = NULL;
|
317
|
+
} else {
|
318
|
+
ptr->last->next = next;
|
319
|
+
ptr->last = next;
|
320
|
+
}
|
321
|
+
ptr->len++;
|
322
|
+
return self;
|
323
|
+
}
|
324
|
+
|
325
|
+
static VALUE
|
326
|
+
list_push_ary(VALUE self, VALUE ary)
|
327
|
+
{
|
328
|
+
long i;
|
329
|
+
|
330
|
+
list_modify_check(self);
|
331
|
+
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
332
|
+
list_push(self, rb_ary_entry(ary, i));
|
333
|
+
}
|
334
|
+
return self;
|
335
|
+
}
|
336
|
+
|
337
|
+
static VALUE
|
338
|
+
list_push_m(int argc, VALUE *argv, VALUE self)
|
339
|
+
{
|
340
|
+
long i;
|
341
|
+
|
342
|
+
list_modify_check(self);
|
343
|
+
if (argc == 0) return self;
|
344
|
+
for (i = 0; i < argc; i++) {
|
345
|
+
list_push(self, argv[i]);
|
346
|
+
}
|
347
|
+
return self;
|
348
|
+
}
|
349
|
+
|
350
|
+
static VALUE
|
351
|
+
list_s_create(int argc, VALUE *argv, VALUE klass)
|
352
|
+
{
|
353
|
+
VALUE list;
|
354
|
+
|
355
|
+
list = rb_obj_alloc(klass);
|
356
|
+
return list_push_m(argc, argv, list);
|
357
|
+
}
|
358
|
+
|
359
|
+
static VALUE
|
360
|
+
check_list_type(VALUE obj)
|
361
|
+
{
|
362
|
+
return to_list(obj);
|
363
|
+
}
|
364
|
+
|
365
|
+
static VALUE
|
366
|
+
list_s_try_convert(VALUE dummy, VALUE obj)
|
367
|
+
{
|
368
|
+
return check_list_type(obj);
|
369
|
+
}
|
370
|
+
|
371
|
+
static VALUE
|
372
|
+
list_initialize(int argc, VALUE *argv, VALUE self)
|
373
|
+
{
|
374
|
+
VALUE size, val;
|
375
|
+
long len;
|
376
|
+
long i;
|
377
|
+
|
378
|
+
list_modify_check(self);
|
379
|
+
if (argc == 0) {
|
380
|
+
return self;
|
381
|
+
}
|
382
|
+
if (argc == 1 && !FIXNUM_P(argv[0])) {
|
383
|
+
switch (rb_type(argv[0])) {
|
384
|
+
case T_ARRAY:
|
385
|
+
return list_push_ary(self, argv[0]);
|
386
|
+
case T_DATA:
|
387
|
+
return list_replace(self, argv[0]);
|
388
|
+
default:
|
389
|
+
break;
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
rb_scan_args(argc, argv, "02", &size, &val);
|
394
|
+
|
395
|
+
len = NUM2LONG(size);
|
396
|
+
if (len < 0) {
|
397
|
+
rb_raise(rb_eArgError, "negative size");
|
398
|
+
}
|
399
|
+
if (LIST_MAX_SIZE < len) {
|
400
|
+
rb_raise(rb_eArgError, "size too big");
|
401
|
+
}
|
402
|
+
|
403
|
+
if (rb_block_given_p()) {
|
404
|
+
if (argc == 2) {
|
405
|
+
rb_warn("block supersedes default value argument");
|
406
|
+
}
|
407
|
+
for (i = 0; i < len; i++) {
|
408
|
+
list_push(self, rb_yield(LONG2NUM(i)));
|
409
|
+
}
|
410
|
+
} else {
|
411
|
+
for (i = 0; i < len; i++) {
|
412
|
+
list_push(self, val);
|
413
|
+
}
|
414
|
+
}
|
415
|
+
return self;
|
416
|
+
}
|
417
|
+
|
418
|
+
static VALUE
|
419
|
+
list_each(VALUE self)
|
420
|
+
{
|
421
|
+
item_t *c;
|
422
|
+
list_t *ptr;
|
423
|
+
|
424
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
425
|
+
Data_Get_Struct(self, list_t, ptr);
|
426
|
+
if (ptr->first == NULL) return self;
|
427
|
+
|
428
|
+
LIST_FOR(ptr, c) {
|
429
|
+
rb_yield(c->value);
|
430
|
+
}
|
431
|
+
return self;
|
432
|
+
}
|
433
|
+
|
434
|
+
static VALUE
|
435
|
+
list_each_index(VALUE self)
|
436
|
+
{
|
437
|
+
item_t *c;
|
438
|
+
list_t *ptr;
|
439
|
+
long index;
|
440
|
+
|
441
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
442
|
+
Data_Get_Struct(self, list_t, ptr);
|
443
|
+
if (ptr->first == NULL) return self;
|
444
|
+
|
445
|
+
index = 0;
|
446
|
+
LIST_FOR(ptr, c) {
|
447
|
+
rb_yield(LONG2NUM(index++));
|
448
|
+
}
|
449
|
+
return self;
|
450
|
+
}
|
451
|
+
|
452
|
+
static VALUE
|
453
|
+
list_clear(VALUE self)
|
454
|
+
{
|
455
|
+
list_modify_check(self);
|
456
|
+
list_t *ptr;
|
457
|
+
Data_Get_Struct(self, list_t, ptr);
|
458
|
+
list_free(ptr);
|
459
|
+
ptr->first = NULL;
|
460
|
+
ptr->last = NULL;
|
461
|
+
ptr->len = 0;
|
462
|
+
return self;
|
463
|
+
}
|
464
|
+
|
465
|
+
static VALUE
|
466
|
+
list_replace_ary(VALUE copy, VALUE orig)
|
467
|
+
{
|
468
|
+
list_t *ptr_copy;
|
469
|
+
item_t *c_copy;
|
470
|
+
long i, olen;
|
471
|
+
|
472
|
+
list_modify_check(copy);
|
473
|
+
if (copy == orig) return copy;
|
474
|
+
|
475
|
+
Data_Get_Struct(copy, list_t, ptr_copy);
|
476
|
+
olen = RARRAY_LEN(orig);
|
477
|
+
if (olen == 0) {
|
478
|
+
return list_clear(copy);
|
479
|
+
}
|
480
|
+
if (olen == ptr_copy->len) {
|
481
|
+
i = 0;
|
482
|
+
LIST_FOR(ptr_copy, c_copy) {
|
483
|
+
c_copy->value = rb_ary_entry(orig, i);
|
484
|
+
i++;
|
485
|
+
}
|
486
|
+
} else {
|
487
|
+
list_clear(copy);
|
488
|
+
for (i = 0; i < olen; i++) {
|
489
|
+
list_push(copy, rb_ary_entry(orig, i));
|
490
|
+
}
|
491
|
+
}
|
492
|
+
return copy;
|
493
|
+
}
|
494
|
+
|
495
|
+
static VALUE
|
496
|
+
list_replace(VALUE copy, VALUE orig)
|
497
|
+
{
|
498
|
+
list_t *ptr_copy;
|
499
|
+
list_t *ptr_orig;
|
500
|
+
item_t *c_orig;
|
501
|
+
item_t *c_copy;
|
502
|
+
long olen;
|
503
|
+
|
504
|
+
list_modify_check(copy);
|
505
|
+
if (copy == orig) return copy;
|
506
|
+
|
507
|
+
switch (rb_type(orig)) {
|
508
|
+
case T_ARRAY:
|
509
|
+
return list_replace_ary(copy, orig);
|
510
|
+
case T_DATA:
|
511
|
+
break;
|
512
|
+
default:
|
513
|
+
rb_raise(rb_eTypeError, "cannot convert to list");
|
514
|
+
}
|
515
|
+
orig = to_list(orig);
|
516
|
+
Data_Get_Struct(copy, list_t, ptr_copy);
|
517
|
+
Data_Get_Struct(orig, list_t, ptr_orig);
|
518
|
+
olen = ptr_orig->len;
|
519
|
+
if (olen == 0) {
|
520
|
+
return list_clear(copy);
|
521
|
+
}
|
522
|
+
if (olen == ptr_copy->len) {
|
523
|
+
LIST_FOR_DOUBLE(ptr_orig, c_orig, ptr_copy, c_copy, {
|
524
|
+
c_copy->value = c_orig->value;
|
525
|
+
});
|
526
|
+
} else {
|
527
|
+
list_clear(copy);
|
528
|
+
LIST_FOR(ptr_orig, c_orig) {
|
529
|
+
list_push(copy, c_orig->value);
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
return copy;
|
534
|
+
}
|
535
|
+
|
536
|
+
static VALUE
|
537
|
+
inspect_list(VALUE self, VALUE dummy, int recur)
|
538
|
+
{
|
539
|
+
VALUE str, s;
|
540
|
+
list_t *ptr;
|
541
|
+
item_t *c;
|
542
|
+
|
543
|
+
Data_Get_Struct(self, list_t, ptr);
|
544
|
+
if (recur) return rb_usascii_str_new_cstr("[...]");
|
545
|
+
|
546
|
+
str = rb_str_buf_new2("#<");
|
547
|
+
rb_str_buf_cat2(str, rb_obj_classname(self));
|
548
|
+
rb_str_buf_cat2(str, ": [");
|
549
|
+
LIST_FOR(ptr, c) {
|
550
|
+
s = rb_inspect(c->value);
|
551
|
+
if (ptr->first == c) rb_enc_copy(str, s);
|
552
|
+
else rb_str_buf_cat2(str, ", ");
|
553
|
+
rb_str_buf_append(str, s);
|
554
|
+
}
|
555
|
+
rb_str_buf_cat2(str, "]>");
|
556
|
+
return str;
|
557
|
+
}
|
558
|
+
|
559
|
+
static VALUE
|
560
|
+
list_inspect(VALUE self)
|
561
|
+
{
|
562
|
+
list_t *ptr;
|
563
|
+
Data_Get_Struct(self, list_t, ptr);
|
564
|
+
if (ptr->len == 0)
|
565
|
+
return rb_sprintf("#<%s: []>", rb_obj_classname(self));
|
566
|
+
return rb_exec_recursive(inspect_list, self, 0);
|
567
|
+
}
|
568
|
+
|
569
|
+
static VALUE
|
570
|
+
list_to_a(VALUE self)
|
571
|
+
{
|
572
|
+
list_t *ptr;
|
573
|
+
item_t *c;
|
574
|
+
VALUE ary;
|
575
|
+
long i = 0;
|
576
|
+
|
577
|
+
Data_Get_Struct(self, list_t, ptr);
|
578
|
+
ary = rb_ary_new2(ptr->len);
|
579
|
+
LIST_FOR(ptr, c) {
|
580
|
+
rb_ary_store(ary, i++, c->value);
|
581
|
+
}
|
582
|
+
return ary;
|
583
|
+
}
|
584
|
+
|
585
|
+
static VALUE
|
586
|
+
list_frozen_p(VALUE self)
|
587
|
+
{
|
588
|
+
if (OBJ_FROZEN(self)) return Qtrue;
|
589
|
+
return Qfalse;
|
590
|
+
}
|
591
|
+
|
592
|
+
static VALUE
|
593
|
+
recursive_equal(VALUE list1, VALUE list2, int recur)
|
594
|
+
{
|
595
|
+
list_t *p1, *p2;
|
596
|
+
item_t *c1, *c2;
|
597
|
+
|
598
|
+
if (recur) return Qtrue;
|
599
|
+
|
600
|
+
Data_Get_Struct(list1, list_t, p1);
|
601
|
+
Data_Get_Struct(list2, list_t, p2);
|
602
|
+
if (p1->len != p2->len) return Qfalse;
|
603
|
+
|
604
|
+
LIST_FOR_DOUBLE(p1, c1, p2, c2, {
|
605
|
+
if (c1->value != c2->value) {
|
606
|
+
if (!rb_equal(c1->value, c2->value)) {
|
607
|
+
return Qfalse;
|
608
|
+
}
|
609
|
+
}
|
610
|
+
});
|
611
|
+
return Qtrue;
|
612
|
+
}
|
613
|
+
|
614
|
+
static VALUE
|
615
|
+
list_equal(VALUE self, VALUE obj)
|
616
|
+
{
|
617
|
+
if (self == obj)
|
618
|
+
return Qtrue;
|
619
|
+
|
620
|
+
if (!rb_obj_is_kind_of(obj, cList)) {
|
621
|
+
if (rb_type(obj) == T_ARRAY) {
|
622
|
+
return Qfalse;
|
623
|
+
}
|
624
|
+
if (!rb_respond_to(obj, rb_intern("to_list"))) {
|
625
|
+
return Qfalse;
|
626
|
+
}
|
627
|
+
return rb_equal(obj, self);
|
628
|
+
}
|
629
|
+
return rb_exec_recursive_paired(recursive_equal, self, obj, obj);
|
630
|
+
|
631
|
+
}
|
632
|
+
|
633
|
+
static VALUE
|
634
|
+
list_hash(VALUE self)
|
635
|
+
{
|
636
|
+
item_t *c;
|
637
|
+
st_index_t h;
|
638
|
+
list_t *ptr;
|
639
|
+
VALUE n;
|
640
|
+
|
641
|
+
Data_Get_Struct(self, list_t, ptr);
|
642
|
+
h = rb_hash_start(ptr->len);
|
643
|
+
h = rb_hash_uint(h, (st_index_t)list_hash);
|
644
|
+
LIST_FOR(ptr, c) {
|
645
|
+
n = rb_hash(c->value);
|
646
|
+
h = rb_hash_uint(h, NUM2LONG(n));
|
647
|
+
}
|
648
|
+
h = rb_hash_end(h);
|
649
|
+
return LONG2FIX(h);
|
650
|
+
}
|
651
|
+
|
652
|
+
static VALUE
|
653
|
+
list_elt_ptr(list_t* ptr, long offset)
|
654
|
+
{
|
655
|
+
long i;
|
656
|
+
item_t *c;
|
657
|
+
long len;
|
658
|
+
|
659
|
+
len = ptr->len;
|
660
|
+
if (len == 0) return Qnil;
|
661
|
+
if (offset < 0 || len <= offset) {
|
662
|
+
return Qnil;
|
663
|
+
}
|
664
|
+
|
665
|
+
i = 0;
|
666
|
+
LIST_FOR(ptr, c) {
|
667
|
+
if (i++ == offset) {
|
668
|
+
return c->value;
|
669
|
+
}
|
670
|
+
}
|
671
|
+
return Qnil;
|
672
|
+
}
|
673
|
+
|
674
|
+
static VALUE
|
675
|
+
list_elt(VALUE self, long offset)
|
676
|
+
{
|
677
|
+
list_t *ptr;
|
678
|
+
Data_Get_Struct(self, list_t, ptr);
|
679
|
+
return list_elt_ptr(ptr, offset);
|
680
|
+
}
|
681
|
+
|
682
|
+
static VALUE
|
683
|
+
list_entry(VALUE self, long offset)
|
684
|
+
{
|
685
|
+
list_t *ptr;
|
686
|
+
|
687
|
+
Data_Get_Struct(self, list_t, ptr);
|
688
|
+
if (offset < 0) {
|
689
|
+
offset += ptr->len;
|
690
|
+
}
|
691
|
+
return list_elt(self, offset);
|
692
|
+
}
|
693
|
+
|
694
|
+
static VALUE
|
695
|
+
list_make_partial(VALUE self, VALUE klass, long offset, long len)
|
696
|
+
{
|
697
|
+
VALUE instance;
|
698
|
+
item_t *c;
|
699
|
+
list_t *ptr;
|
700
|
+
long i;
|
701
|
+
|
702
|
+
Data_Get_Struct(self, list_t, ptr);
|
703
|
+
instance = rb_obj_alloc(klass);
|
704
|
+
i = -1;
|
705
|
+
LIST_FOR(ptr, c) {
|
706
|
+
i++;
|
707
|
+
if (i < offset) continue;
|
708
|
+
|
709
|
+
if (i < offset + len) {
|
710
|
+
list_push(instance, c->value);
|
711
|
+
} else {
|
712
|
+
break;
|
713
|
+
}
|
714
|
+
}
|
715
|
+
return instance;
|
716
|
+
}
|
717
|
+
|
718
|
+
static VALUE
|
719
|
+
list_subseq(VALUE self, long beg, long len)
|
720
|
+
{
|
721
|
+
long alen;
|
722
|
+
list_t *ptr;
|
723
|
+
|
724
|
+
Data_Get_Struct(self, list_t, ptr);
|
725
|
+
alen = ptr->len;
|
726
|
+
|
727
|
+
if (alen < beg) return Qnil;
|
728
|
+
if (beg < 0 || len < 0) return Qnil;
|
729
|
+
|
730
|
+
if (alen < len || alen < beg + len) {
|
731
|
+
len = alen - beg;
|
732
|
+
}
|
733
|
+
if (len == 0) {
|
734
|
+
return list_new();
|
735
|
+
}
|
736
|
+
|
737
|
+
return list_make_partial(self, cList, beg, len);
|
738
|
+
}
|
739
|
+
|
740
|
+
static VALUE
|
741
|
+
list_aref(int argc, VALUE *argv, VALUE self)
|
742
|
+
{
|
743
|
+
VALUE arg;
|
744
|
+
long beg, len;
|
745
|
+
list_t *ptr;
|
746
|
+
|
747
|
+
Data_Get_Struct(self, list_t, ptr);
|
748
|
+
if (argc == 2) {
|
749
|
+
beg = NUM2LONG(argv[0]);
|
750
|
+
len = NUM2LONG(argv[1]);
|
751
|
+
if (beg < 0) {
|
752
|
+
beg += ptr->len;
|
753
|
+
}
|
754
|
+
return list_subseq(self, beg, len);
|
755
|
+
}
|
756
|
+
if (argc != 1) {
|
757
|
+
rb_scan_args(argc, argv, "11", NULL, NULL);
|
758
|
+
}
|
759
|
+
arg = argv[0];
|
760
|
+
|
761
|
+
/* special case - speeding up */
|
762
|
+
if (FIXNUM_P(arg)) {
|
763
|
+
return list_entry(self, FIX2LONG(arg));
|
764
|
+
}
|
765
|
+
/* check if idx is Range */
|
766
|
+
switch (rb_range_beg_len(arg, &beg, &len, ptr->len, 0)) {
|
767
|
+
case Qfalse:
|
768
|
+
break;
|
769
|
+
case Qnil:
|
770
|
+
return Qnil;
|
771
|
+
default:
|
772
|
+
return list_subseq(self, beg, len);
|
773
|
+
}
|
774
|
+
return list_entry(self, NUM2LONG(arg));
|
775
|
+
}
|
776
|
+
|
777
|
+
static void
|
778
|
+
list_splice(VALUE self, long beg, long len, VALUE rpl)
|
779
|
+
{
|
780
|
+
long i;
|
781
|
+
long rlen, olen, alen;
|
782
|
+
list_t *ptr;
|
783
|
+
item_t *c = NULL;
|
784
|
+
item_t *item_first = NULL, *item_last = NULL, *first = NULL, *last = NULL;
|
785
|
+
|
786
|
+
if (len < 0)
|
787
|
+
rb_raise(rb_eIndexError, "negative length (%ld)", len);
|
788
|
+
|
789
|
+
Data_Get_Struct(self, list_t, ptr);
|
790
|
+
olen = ptr->len;
|
791
|
+
if (beg < 0) {
|
792
|
+
beg += olen;
|
793
|
+
if (beg < 0) {
|
794
|
+
rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
|
795
|
+
beg - olen, -olen);
|
796
|
+
}
|
797
|
+
}
|
798
|
+
if (olen < len || olen < beg + len) {
|
799
|
+
len = olen - beg;
|
800
|
+
}
|
801
|
+
|
802
|
+
if (rpl == Qundef) {
|
803
|
+
rlen = 0;
|
804
|
+
} else {
|
805
|
+
rpl = rb_ary_to_ary(rpl);
|
806
|
+
rlen = RARRAY_LEN(rpl);
|
807
|
+
olen = ptr->len;
|
808
|
+
}
|
809
|
+
if (olen <= beg) {
|
810
|
+
if (LIST_MAX_SIZE - rlen < beg) {
|
811
|
+
rb_raise(rb_eIndexError, "index %ld too big", beg);
|
812
|
+
}
|
813
|
+
for (i = ptr->len; i < beg; i++) {
|
814
|
+
list_push(self, Qnil);
|
815
|
+
}
|
816
|
+
list_push_ary(self, rpl);
|
817
|
+
} else {
|
818
|
+
alen = olen + rlen - len;
|
819
|
+
if (len != rlen) {
|
820
|
+
for (i = rlen; 0 < i; i--) {
|
821
|
+
c = item_alloc(rb_ary_entry(rpl, i - 1), c);
|
822
|
+
if (i == rlen) {
|
823
|
+
item_last = c;
|
824
|
+
}
|
825
|
+
}
|
826
|
+
item_first = c;
|
827
|
+
|
828
|
+
i = -1;
|
829
|
+
LIST_FOR(ptr, c) {
|
830
|
+
i++;
|
831
|
+
if (i == beg - 1) {
|
832
|
+
first = c;
|
833
|
+
}
|
834
|
+
if (i == beg + len) {
|
835
|
+
last = c;
|
836
|
+
break;
|
837
|
+
}
|
838
|
+
}
|
839
|
+
if (beg == 0) {
|
840
|
+
ptr->first = item_first;
|
841
|
+
} else {
|
842
|
+
first->next = item_first;
|
843
|
+
}
|
844
|
+
if (rlen == 0) {
|
845
|
+
ptr->last = first;
|
846
|
+
ptr->last->next = NULL;
|
847
|
+
} else {
|
848
|
+
item_last->next = last;
|
849
|
+
}
|
850
|
+
ptr->len += rlen - len;
|
851
|
+
} else {
|
852
|
+
i = -1;
|
853
|
+
LIST_FOR(ptr, c) {
|
854
|
+
i++;
|
855
|
+
if (beg <= i && i < beg + rlen) {
|
856
|
+
c->value = rb_ary_entry(rpl, i - beg);
|
857
|
+
}
|
858
|
+
}
|
859
|
+
}
|
860
|
+
|
861
|
+
}
|
862
|
+
}
|
863
|
+
|
864
|
+
static void
|
865
|
+
list_store(VALUE self, long idx, VALUE val)
|
866
|
+
{
|
867
|
+
item_t *c;
|
868
|
+
list_t *ptr;
|
869
|
+
long len, i;
|
870
|
+
|
871
|
+
Data_Get_Struct(self, list_t, ptr);
|
872
|
+
len = ptr->len;
|
873
|
+
|
874
|
+
if (idx < 0) {
|
875
|
+
idx += len;
|
876
|
+
if (idx < 0) {
|
877
|
+
rb_raise(rb_eIndexError, "index %ld too small for list; minimum: %ld",
|
878
|
+
idx - len, -len);
|
879
|
+
}
|
880
|
+
} else if (LIST_MAX_SIZE <= idx) {
|
881
|
+
rb_raise(rb_eIndexError, "index %ld too big", idx);
|
882
|
+
}
|
883
|
+
|
884
|
+
if (ptr->len <= idx) {
|
885
|
+
for (i = ptr->len; i <= idx; i++) {
|
886
|
+
list_push(self, Qnil);
|
887
|
+
}
|
888
|
+
}
|
889
|
+
|
890
|
+
i = -1;
|
891
|
+
LIST_FOR(ptr, c) {
|
892
|
+
i++;
|
893
|
+
if (i == idx) {
|
894
|
+
c->value = val;
|
895
|
+
break;
|
896
|
+
}
|
897
|
+
}
|
898
|
+
}
|
899
|
+
|
900
|
+
static VALUE
|
901
|
+
list_aset(int argc, VALUE *argv, VALUE self)
|
902
|
+
{
|
903
|
+
long offset, beg, len;
|
904
|
+
list_t *ptr;
|
905
|
+
|
906
|
+
list_modify_check(self);
|
907
|
+
Data_Get_Struct(self, list_t, ptr);
|
908
|
+
if (argc == 3) {
|
909
|
+
beg = NUM2LONG(argv[0]);
|
910
|
+
len = NUM2LONG(argv[1]);
|
911
|
+
list_splice(self, beg, len, argv[2]);
|
912
|
+
return argv[2];
|
913
|
+
}
|
914
|
+
rb_check_arity(argc, 2, 2);
|
915
|
+
if (FIXNUM_P(argv[0])) {
|
916
|
+
offset = FIX2LONG(argv[0]);
|
917
|
+
goto fixnum;
|
918
|
+
}
|
919
|
+
if (rb_range_beg_len(argv[0], &beg, &len, ptr->len, 1)) {
|
920
|
+
/* check if idx is Range */
|
921
|
+
list_splice(self, beg, len, argv[1]);
|
922
|
+
return argv[1];
|
923
|
+
}
|
924
|
+
|
925
|
+
offset = NUM2LONG(argv[0]);
|
926
|
+
fixnum:
|
927
|
+
list_store(self, offset, argv[1]);
|
928
|
+
return argv[1];
|
929
|
+
}
|
930
|
+
|
931
|
+
static VALUE
|
932
|
+
list_at(VALUE self, VALUE pos)
|
933
|
+
{
|
934
|
+
return list_entry(self, NUM2LONG(pos));
|
935
|
+
}
|
936
|
+
|
937
|
+
static VALUE
|
938
|
+
list_fetch(int argc, VALUE *argv, VALUE self)
|
939
|
+
{
|
940
|
+
VALUE pos, ifnone;
|
941
|
+
long block_given;
|
942
|
+
long idx;
|
943
|
+
list_t *ptr;
|
944
|
+
|
945
|
+
Data_Get_Struct(self, list_t, ptr);
|
946
|
+
rb_scan_args(argc, argv, "11", &pos, &ifnone);
|
947
|
+
block_given = rb_block_given_p();
|
948
|
+
if (block_given && argc == 2) {
|
949
|
+
rb_warn("block supersedes default value argument");
|
950
|
+
}
|
951
|
+
idx = NUM2LONG(pos);
|
952
|
+
|
953
|
+
if (idx < 0) {
|
954
|
+
idx += ptr->len;
|
955
|
+
}
|
956
|
+
if (idx < 0 || ptr->len <= idx) {
|
957
|
+
if (block_given) return rb_yield(pos);
|
958
|
+
if (argc == 1) {
|
959
|
+
rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
|
960
|
+
idx - (idx < 0 ? ptr->len : 0), -ptr->len, ptr->len);
|
961
|
+
}
|
962
|
+
return ifnone;
|
963
|
+
}
|
964
|
+
return list_entry(self, idx);
|
965
|
+
}
|
966
|
+
|
967
|
+
static VALUE
|
968
|
+
list_take_first_or_last(int argc, VALUE *argv, VALUE self, enum list_take_pos_flags flag)
|
969
|
+
{
|
970
|
+
VALUE nv;
|
971
|
+
long n;
|
972
|
+
long len;
|
973
|
+
long offset = 0;
|
974
|
+
list_t *ptr;
|
975
|
+
|
976
|
+
Data_Get_Struct(self, list_t, ptr);
|
977
|
+
rb_scan_args(argc, argv, "1", &nv);
|
978
|
+
n = NUM2LONG(nv);
|
979
|
+
len = ptr->len;
|
980
|
+
if (n > len) {
|
981
|
+
n = len;
|
982
|
+
} else if (n < 0) {
|
983
|
+
rb_raise(rb_eArgError, "negative array size");
|
984
|
+
}
|
985
|
+
if (flag == LIST_TAKE_LAST) {
|
986
|
+
offset = len - n;
|
987
|
+
}
|
988
|
+
return list_make_partial(self, cList, offset, n);
|
989
|
+
}
|
990
|
+
|
991
|
+
static VALUE
|
992
|
+
list_first(int argc, VALUE *argv, VALUE self)
|
993
|
+
{
|
994
|
+
list_t *ptr;
|
995
|
+
Data_Get_Struct(self, list_t, ptr);
|
996
|
+
if (argc == 0) {
|
997
|
+
if (ptr->first == NULL) return Qnil;
|
998
|
+
return ptr->first->value;
|
999
|
+
} else {
|
1000
|
+
return list_take_first_or_last(argc, argv, self, LIST_TAKE_FIRST);
|
1001
|
+
}
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
static VALUE
|
1005
|
+
list_last(int argc, VALUE *argv, VALUE self)
|
1006
|
+
{
|
1007
|
+
list_t *ptr;
|
1008
|
+
long len;
|
1009
|
+
|
1010
|
+
Data_Get_Struct(self, list_t, ptr);
|
1011
|
+
if (argc == 0) {
|
1012
|
+
len = ptr->len;
|
1013
|
+
if (len == 0) return Qnil;
|
1014
|
+
return list_elt(self, len - 1);
|
1015
|
+
} else {
|
1016
|
+
return list_take_first_or_last(argc, argv, self, LIST_TAKE_LAST);
|
1017
|
+
}
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
static VALUE
|
1021
|
+
list_concat(VALUE self, VALUE obj)
|
1022
|
+
{
|
1023
|
+
long len;
|
1024
|
+
list_t *ptr_self;
|
1025
|
+
list_t *ptr_obj;
|
1026
|
+
enum ruby_value_type type;
|
1027
|
+
|
1028
|
+
list_modify_check(self);
|
1029
|
+
type = rb_type(obj);
|
1030
|
+
if (type == T_DATA) {
|
1031
|
+
Data_Get_Struct(obj, list_t, ptr_obj);
|
1032
|
+
len = ptr_obj->len;
|
1033
|
+
} else if (type == T_ARRAY) {
|
1034
|
+
len = RARRAY_LEN(obj);
|
1035
|
+
} else {
|
1036
|
+
obj = to_list(obj);
|
1037
|
+
Data_Get_Struct(obj, list_t, ptr_obj);
|
1038
|
+
len = ptr_obj->len;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
Data_Get_Struct(self, list_t, ptr_self);
|
1042
|
+
if (0 < len) {
|
1043
|
+
list_splice(self, ptr_self->len, 0, obj);
|
1044
|
+
}
|
1045
|
+
return self;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
static VALUE
|
1049
|
+
list_pop(VALUE self)
|
1050
|
+
{
|
1051
|
+
VALUE result;
|
1052
|
+
list_t *ptr;
|
1053
|
+
|
1054
|
+
list_modify_check(self);
|
1055
|
+
Data_Get_Struct(self, list_t, ptr);
|
1056
|
+
if (ptr->len == 0) return Qnil;
|
1057
|
+
result = ptr->last->value;
|
1058
|
+
list_mem_clear(ptr, ptr->len - 1, 1);
|
1059
|
+
return result;
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
static VALUE
|
1063
|
+
list_pop_m(int argc, VALUE *argv, VALUE self)
|
1064
|
+
{
|
1065
|
+
list_t *ptr;
|
1066
|
+
VALUE result;
|
1067
|
+
long n;
|
1068
|
+
|
1069
|
+
if (argc == 0) {
|
1070
|
+
return list_pop(self);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
list_modify_check(self);
|
1074
|
+
result = list_take_first_or_last(argc, argv, self, LIST_TAKE_LAST);
|
1075
|
+
Data_Get_Struct(self, list_t, ptr);
|
1076
|
+
n = NUM2LONG(argv[0]);
|
1077
|
+
list_mem_clear(ptr, ptr->len - n, n);
|
1078
|
+
return result;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
static VALUE
|
1082
|
+
list_shift(VALUE self)
|
1083
|
+
{
|
1084
|
+
VALUE result;
|
1085
|
+
list_t *ptr;
|
1086
|
+
|
1087
|
+
Data_Get_Struct(self, list_t, ptr);
|
1088
|
+
if (ptr->len == 0) return Qnil;
|
1089
|
+
result = list_first(0, NULL, self);
|
1090
|
+
list_mem_clear(ptr, 0, 1);
|
1091
|
+
return result;
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
static VALUE
|
1095
|
+
list_shift_m(int argc, VALUE *argv, VALUE self)
|
1096
|
+
{
|
1097
|
+
VALUE result;
|
1098
|
+
long i;
|
1099
|
+
list_t *ptr_res;
|
1100
|
+
|
1101
|
+
if (argc == 0) {
|
1102
|
+
return list_shift(self);
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
list_modify_check(self);
|
1106
|
+
result = list_take_first_or_last(argc, argv, self, LIST_TAKE_FIRST);
|
1107
|
+
Data_Get_Struct(result, list_t, ptr_res);
|
1108
|
+
for (i = 0; i < ptr_res->len; i++) {
|
1109
|
+
list_shift(self);
|
1110
|
+
}
|
1111
|
+
return result;
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
static VALUE
|
1115
|
+
list_unshift(VALUE self, VALUE obj)
|
1116
|
+
{
|
1117
|
+
list_t *ptr;
|
1118
|
+
item_t *first;
|
1119
|
+
Data_Get_Struct(self, list_t, ptr);
|
1120
|
+
|
1121
|
+
first = item_alloc(obj, ptr->first);
|
1122
|
+
if (ptr->first == NULL) {
|
1123
|
+
ptr->first = first;
|
1124
|
+
ptr->last = first;
|
1125
|
+
ptr->last->next = NULL;
|
1126
|
+
} else {
|
1127
|
+
ptr->first = first;
|
1128
|
+
}
|
1129
|
+
ptr->len++;
|
1130
|
+
return self;
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
static VALUE
|
1134
|
+
list_unshift_m(int argc, VALUE *argv, VALUE self)
|
1135
|
+
{
|
1136
|
+
long i;
|
1137
|
+
|
1138
|
+
list_modify_check(self);
|
1139
|
+
if (argc == 0) return self;
|
1140
|
+
for (i = 0; i < argc; i++) {
|
1141
|
+
list_unshift(self, argv[i]);
|
1142
|
+
}
|
1143
|
+
return self;
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
static VALUE
|
1147
|
+
list_insert(int argc, VALUE *argv, VALUE self)
|
1148
|
+
{
|
1149
|
+
list_t *ptr;
|
1150
|
+
long pos;
|
1151
|
+
|
1152
|
+
Data_Get_Struct(self, list_t, ptr);
|
1153
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
1154
|
+
list_modify_check(self);
|
1155
|
+
if (argc == 1) return self;
|
1156
|
+
pos = NUM2LONG(argv[0]);
|
1157
|
+
if (pos == -1) {
|
1158
|
+
pos = ptr->len;
|
1159
|
+
}
|
1160
|
+
if (pos < 0) {
|
1161
|
+
pos++;
|
1162
|
+
}
|
1163
|
+
list_splice(self, pos, 0, rb_ary_new4(argc - 1, argv + 1));
|
1164
|
+
return self;
|
1165
|
+
}
|
1166
|
+
|
1167
|
+
static VALUE
|
1168
|
+
list_length(VALUE self)
|
1169
|
+
{
|
1170
|
+
list_t *ptr;
|
1171
|
+
Data_Get_Struct(self, list_t, ptr);
|
1172
|
+
return LONG2NUM(ptr->len);
|
1173
|
+
}
|
1174
|
+
|
1175
|
+
static VALUE
|
1176
|
+
list_empty_p(VALUE self)
|
1177
|
+
{
|
1178
|
+
list_t *ptr;
|
1179
|
+
Data_Get_Struct(self, list_t, ptr);
|
1180
|
+
if (ptr->len == 0)
|
1181
|
+
return Qtrue;
|
1182
|
+
return Qfalse;
|
1183
|
+
}
|
1184
|
+
|
1185
|
+
static VALUE
|
1186
|
+
list_rindex(int argc, VALUE *argv, VALUE self)
|
1187
|
+
{
|
1188
|
+
list_t *ptr;
|
1189
|
+
long i;
|
1190
|
+
long len;
|
1191
|
+
VALUE val;
|
1192
|
+
|
1193
|
+
Data_Get_Struct(self, list_t, ptr);
|
1194
|
+
i = ptr->len;
|
1195
|
+
if (argc == 0) {
|
1196
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
1197
|
+
while (i--) {
|
1198
|
+
Data_Get_Struct(self, list_t, ptr);
|
1199
|
+
if (RTEST(rb_yield(list_elt_ptr(ptr, i))))
|
1200
|
+
return LONG2NUM(i);
|
1201
|
+
if (ptr->len < i) {
|
1202
|
+
i = ptr->len;
|
1203
|
+
}
|
1204
|
+
}
|
1205
|
+
return Qnil;
|
1206
|
+
}
|
1207
|
+
rb_check_arity(argc, 0, 1);
|
1208
|
+
val = argv[0];
|
1209
|
+
if (rb_block_given_p())
|
1210
|
+
rb_warn("given block not used");
|
1211
|
+
Data_Get_Struct(self, list_t, ptr);
|
1212
|
+
while (i--) {
|
1213
|
+
if (rb_equal(list_elt_ptr(ptr, i), val)) {
|
1214
|
+
return LONG2NUM(i);
|
1215
|
+
}
|
1216
|
+
len = ptr->len;
|
1217
|
+
if (len < i) {
|
1218
|
+
i = len;
|
1219
|
+
}
|
1220
|
+
Data_Get_Struct(self, list_t, ptr);
|
1221
|
+
}
|
1222
|
+
return Qnil;
|
1223
|
+
}
|
1224
|
+
|
1225
|
+
extern VALUE rb_output_fs;
|
1226
|
+
|
1227
|
+
static void list_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
|
1228
|
+
|
1229
|
+
static VALUE
|
1230
|
+
recursive_join(VALUE obj, VALUE argp, int recur)
|
1231
|
+
{
|
1232
|
+
VALUE *arg = (VALUE *)argp;
|
1233
|
+
VALUE ary = arg[0];
|
1234
|
+
VALUE sep = arg[1];
|
1235
|
+
VALUE result = arg[2];
|
1236
|
+
int *first = (int *)arg[3];
|
1237
|
+
|
1238
|
+
if (recur) {
|
1239
|
+
rb_raise(rb_eArgError, "recursive list join");
|
1240
|
+
} else {
|
1241
|
+
list_join_1(obj, ary, sep, 0, result, first);
|
1242
|
+
}
|
1243
|
+
return Qnil;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
/* only string join */
|
1247
|
+
static void
|
1248
|
+
list_join_0(VALUE self, VALUE sep, long max, VALUE result)
|
1249
|
+
{
|
1250
|
+
list_t *ptr;
|
1251
|
+
item_t *c;
|
1252
|
+
long i = 1;
|
1253
|
+
|
1254
|
+
Data_Get_Struct(self, list_t, ptr);
|
1255
|
+
if (0 < max) rb_enc_copy(result, list_elt_ptr(ptr, 0));
|
1256
|
+
if (max <= i) return;
|
1257
|
+
c = ptr->first;
|
1258
|
+
rb_str_buf_append(result, c->value);
|
1259
|
+
for (c = c->next; i < max; c = c->next) {
|
1260
|
+
if (!NIL_P(sep))
|
1261
|
+
rb_str_buf_append(result, sep);
|
1262
|
+
rb_str_buf_append(result, c->value);
|
1263
|
+
i++;
|
1264
|
+
}
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
/* another object join */
|
1268
|
+
static void
|
1269
|
+
list_join_1(VALUE obj, VALUE list, VALUE sep, long i, VALUE result, int *first)
|
1270
|
+
{
|
1271
|
+
list_t *ptr;
|
1272
|
+
item_t *c;
|
1273
|
+
VALUE val, tmp;
|
1274
|
+
|
1275
|
+
Data_Get_Struct(list, list_t, ptr);
|
1276
|
+
if (ptr->len == 0) return;
|
1277
|
+
|
1278
|
+
LIST_FOR(ptr, c) {
|
1279
|
+
val = c->value;
|
1280
|
+
if (0 < i++ && !NIL_P(sep))
|
1281
|
+
rb_str_buf_append(result, sep);
|
1282
|
+
|
1283
|
+
switch (rb_type(val)) {
|
1284
|
+
case T_STRING:
|
1285
|
+
str_join:
|
1286
|
+
rb_str_buf_append(result, val);
|
1287
|
+
*first = FALSE;
|
1288
|
+
break;
|
1289
|
+
case T_ARRAY:
|
1290
|
+
case T_DATA:
|
1291
|
+
obj = val;
|
1292
|
+
ary_join:
|
1293
|
+
if (val == list) {
|
1294
|
+
rb_raise(rb_eArgError, "recursive list join");
|
1295
|
+
}
|
1296
|
+
VALUE args[4];
|
1297
|
+
args[0] = val;
|
1298
|
+
args[1] = sep;
|
1299
|
+
args[2] = result;
|
1300
|
+
args[3] = (VALUE)first;
|
1301
|
+
rb_exec_recursive(recursive_join, obj, (VALUE)args);
|
1302
|
+
break;
|
1303
|
+
default:
|
1304
|
+
tmp = rb_check_string_type(val);
|
1305
|
+
if (!NIL_P(tmp)) {
|
1306
|
+
val = tmp;
|
1307
|
+
goto str_join;
|
1308
|
+
}
|
1309
|
+
tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
|
1310
|
+
if (!NIL_P(tmp)) {
|
1311
|
+
obj = val;
|
1312
|
+
val = tmp;
|
1313
|
+
goto ary_join;
|
1314
|
+
}
|
1315
|
+
val = rb_obj_as_string(val);
|
1316
|
+
if (*first) {
|
1317
|
+
rb_enc_copy(result, val);
|
1318
|
+
*first = FALSE;
|
1319
|
+
}
|
1320
|
+
goto str_join;
|
1321
|
+
}
|
1322
|
+
}
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
static VALUE
|
1326
|
+
list_join(VALUE self, VALUE sep)
|
1327
|
+
{
|
1328
|
+
list_t *ptr;
|
1329
|
+
long len = 1;
|
1330
|
+
long i = 0;
|
1331
|
+
VALUE val, tmp;
|
1332
|
+
VALUE result;
|
1333
|
+
item_t *c;
|
1334
|
+
int first;
|
1335
|
+
|
1336
|
+
Data_Get_Struct(self, list_t, ptr);
|
1337
|
+
if (ptr->len == 0) return rb_usascii_str_new(0, 0);
|
1338
|
+
|
1339
|
+
if (!NIL_P(sep)) {
|
1340
|
+
StringValue(sep);
|
1341
|
+
len += RSTRING_LEN(sep) * (ptr->len - 1);
|
1342
|
+
}
|
1343
|
+
LIST_FOR(ptr, c) {
|
1344
|
+
val = c->value;
|
1345
|
+
tmp = rb_check_string_type(val);
|
1346
|
+
if (NIL_P(val) || c->value != tmp) {
|
1347
|
+
result = rb_str_buf_new(len + ptr->len);
|
1348
|
+
rb_enc_associate(result, rb_usascii_encoding());
|
1349
|
+
list_join_0(self, sep, i, result);
|
1350
|
+
first = i == 0;
|
1351
|
+
list_join_1(self, self, sep, i, result, &first);
|
1352
|
+
return result;
|
1353
|
+
}
|
1354
|
+
len += RSTRING_LEN(val);
|
1355
|
+
}
|
1356
|
+
result = rb_str_buf_new(len);
|
1357
|
+
list_join_0(self, sep, ptr->len, result);
|
1358
|
+
|
1359
|
+
return result;
|
1360
|
+
}
|
1361
|
+
|
1362
|
+
static VALUE
|
1363
|
+
list_join_m(int argc, VALUE *argv, VALUE self)
|
1364
|
+
{
|
1365
|
+
VALUE sep;
|
1366
|
+
|
1367
|
+
rb_scan_args(argc, argv, "01", &sep);
|
1368
|
+
if (NIL_P(sep)) sep = rb_output_fs;
|
1369
|
+
|
1370
|
+
return list_join(self, sep);
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
static VALUE
|
1374
|
+
list_reverse_bang(VALUE self)
|
1375
|
+
{
|
1376
|
+
VALUE tmp;
|
1377
|
+
item_t *c;
|
1378
|
+
list_t *ptr;
|
1379
|
+
long len;
|
1380
|
+
|
1381
|
+
Data_Get_Struct(self, list_t, ptr);
|
1382
|
+
if (ptr->len == 0) return self;
|
1383
|
+
tmp = list_to_a(self);
|
1384
|
+
len = ptr->len;
|
1385
|
+
LIST_FOR(ptr, c) {
|
1386
|
+
c->value = rb_ary_entry(tmp, --len);
|
1387
|
+
}
|
1388
|
+
return self;
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
static VALUE
|
1392
|
+
list_reverse_m(VALUE self)
|
1393
|
+
{
|
1394
|
+
VALUE result;
|
1395
|
+
item_t *c;
|
1396
|
+
list_t *ptr;
|
1397
|
+
|
1398
|
+
Data_Get_Struct(self, list_t, ptr);
|
1399
|
+
result = list_new();
|
1400
|
+
if (ptr->len == 0) return result;
|
1401
|
+
LIST_FOR(ptr, c) {
|
1402
|
+
list_unshift(result, c->value);
|
1403
|
+
}
|
1404
|
+
return result;
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
static VALUE
|
1408
|
+
list_rotate_bang(int argc, VALUE *argv, VALUE self)
|
1409
|
+
{
|
1410
|
+
list_t *ptr;
|
1411
|
+
item_t *c;
|
1412
|
+
long cnt = 1;
|
1413
|
+
long i = 0;
|
1414
|
+
|
1415
|
+
switch (argc) {
|
1416
|
+
case 1: cnt = NUM2LONG(argv[0]);
|
1417
|
+
case 0: break;
|
1418
|
+
default: rb_scan_args(argc, argv, "01", NULL);
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
Data_Get_Struct(self, list_t, ptr);
|
1422
|
+
if (ptr->len == 0) return self;
|
1423
|
+
cnt = (cnt < 0) ? (ptr->len - (~cnt % ptr->len) - 1) : (cnt & ptr->len);
|
1424
|
+
LIST_FOR(ptr, c) {
|
1425
|
+
if (cnt == ++i) break;
|
1426
|
+
}
|
1427
|
+
ptr->last->next = ptr->first;
|
1428
|
+
ptr->first = c->next;
|
1429
|
+
ptr->last = c;
|
1430
|
+
ptr->last->next = NULL;
|
1431
|
+
return self;
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
static VALUE
|
1435
|
+
list_rotate_m(int argc, VALUE *argv, VALUE self)
|
1436
|
+
{
|
1437
|
+
VALUE clone = rb_obj_clone(self);
|
1438
|
+
return list_rotate_bang(argc, argv, clone);
|
1439
|
+
}
|
1440
|
+
|
1441
|
+
static VALUE
|
1442
|
+
list_sort_bang(VALUE self)
|
1443
|
+
{
|
1444
|
+
list_t *ptr;
|
1445
|
+
item_t *c;
|
1446
|
+
long i = 0;
|
1447
|
+
|
1448
|
+
VALUE ary = list_to_a(self);
|
1449
|
+
rb_ary_sort_bang(ary);
|
1450
|
+
Data_Get_Struct(self, list_t, ptr);
|
1451
|
+
LIST_FOR(ptr, c) {
|
1452
|
+
c->value = rb_ary_entry(ary, i++);
|
1453
|
+
}
|
1454
|
+
return self;
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
static VALUE
|
1458
|
+
list_sort(VALUE self)
|
1459
|
+
{
|
1460
|
+
VALUE clone = rb_obj_clone(self);
|
1461
|
+
return list_sort_bang(clone);
|
1462
|
+
}
|
1463
|
+
|
1464
|
+
static VALUE
|
1465
|
+
sort_by_i(VALUE i, VALUE _data, int argc, VALUE *argv)
|
1466
|
+
{
|
1467
|
+
return rb_yield(i);
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
static VALUE
|
1471
|
+
list_sort_by(VALUE self)
|
1472
|
+
{
|
1473
|
+
VALUE ary;
|
1474
|
+
|
1475
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1476
|
+
ary = rb_block_call(list_to_a(self), rb_intern("sort_by"), 0, 0, sort_by_i, 0);
|
1477
|
+
return to_list(ary);
|
1478
|
+
}
|
1479
|
+
|
1480
|
+
static VALUE
|
1481
|
+
list_sort_by_bang(VALUE self)
|
1482
|
+
{
|
1483
|
+
VALUE sorted;
|
1484
|
+
|
1485
|
+
sorted = list_sort_by(self);
|
1486
|
+
return list_replace(self, sorted);
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
static VALUE
|
1490
|
+
list_collect_bang(VALUE self)
|
1491
|
+
{
|
1492
|
+
list_t *ptr;
|
1493
|
+
item_t *c;
|
1494
|
+
|
1495
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1496
|
+
Data_Get_Struct(self, list_t, ptr);
|
1497
|
+
LIST_FOR(ptr, c) {
|
1498
|
+
c->value = rb_yield(c->value);
|
1499
|
+
}
|
1500
|
+
return self;
|
1501
|
+
}
|
1502
|
+
|
1503
|
+
static VALUE
|
1504
|
+
list_collect(VALUE self)
|
1505
|
+
{
|
1506
|
+
return list_collect_bang(rb_obj_clone(self));
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
static VALUE
|
1510
|
+
list_select(VALUE self)
|
1511
|
+
{
|
1512
|
+
VALUE result;
|
1513
|
+
list_t *ptr;
|
1514
|
+
item_t *c;
|
1515
|
+
|
1516
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1517
|
+
Data_Get_Struct(self, list_t, ptr);
|
1518
|
+
result = list_new();
|
1519
|
+
LIST_FOR(ptr, c) {
|
1520
|
+
if (RTEST(rb_yield(c->value))) {
|
1521
|
+
list_push(result, c->value);
|
1522
|
+
}
|
1523
|
+
}
|
1524
|
+
return result;
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
static VALUE
|
1528
|
+
list_select_bang(VALUE self)
|
1529
|
+
{
|
1530
|
+
VALUE result;
|
1531
|
+
list_t *ptr;
|
1532
|
+
item_t *c;
|
1533
|
+
long i = 0;
|
1534
|
+
|
1535
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1536
|
+
Data_Get_Struct(self, list_t, ptr);
|
1537
|
+
result = list_new();
|
1538
|
+
LIST_FOR(ptr, c) {
|
1539
|
+
if (RTEST(rb_yield(c->value))) {
|
1540
|
+
i++;
|
1541
|
+
list_push(result, c->value);
|
1542
|
+
}
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
if (i == ptr->len) return Qnil;
|
1546
|
+
return list_replace(self, result);
|
1547
|
+
}
|
1548
|
+
|
1549
|
+
static VALUE
|
1550
|
+
list_keep_if(VALUE self)
|
1551
|
+
{
|
1552
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1553
|
+
list_select_bang(self);
|
1554
|
+
return self;
|
1555
|
+
}
|
1556
|
+
|
1557
|
+
static VALUE
|
1558
|
+
list_values_at(int argc, VALUE *argv, VALUE self)
|
1559
|
+
{
|
1560
|
+
VALUE result = list_new();
|
1561
|
+
long beg, len;
|
1562
|
+
long i, j;
|
1563
|
+
list_t *ptr;
|
1564
|
+
|
1565
|
+
Data_Get_Struct(self, list_t, ptr);
|
1566
|
+
for (i = 0; i < argc; i++) {
|
1567
|
+
if (FIXNUM_P(argv[i])) {
|
1568
|
+
list_push(result, list_entry(self, FIX2LONG(argv[i])));
|
1569
|
+
} else if (rb_range_beg_len(argv[i], &beg, &len, ptr->len, 1)) {
|
1570
|
+
for (j = beg; j < beg + len; j++) {
|
1571
|
+
if (ptr->len < j) {
|
1572
|
+
list_push(result, Qnil);
|
1573
|
+
} else {
|
1574
|
+
list_push(result, list_elt_ptr(ptr, j));
|
1575
|
+
}
|
1576
|
+
}
|
1577
|
+
} else {
|
1578
|
+
list_push(result, list_entry(self, NUM2LONG(argv[i])));
|
1579
|
+
}
|
1580
|
+
}
|
1581
|
+
return result;
|
1582
|
+
}
|
1583
|
+
|
1584
|
+
static VALUE
|
1585
|
+
list_delete(VALUE self, VALUE item)
|
1586
|
+
{
|
1587
|
+
list_t *ptr;
|
1588
|
+
item_t *c, *before = NULL, *next;
|
1589
|
+
long len;
|
1590
|
+
|
1591
|
+
list_modify_check(self);
|
1592
|
+
Data_Get_Struct(self, list_t, ptr);
|
1593
|
+
if (ptr->len == 0) return Qnil;
|
1594
|
+
|
1595
|
+
len = ptr->len;
|
1596
|
+
for (c = ptr->first; c; c = next) {
|
1597
|
+
next = c->next;
|
1598
|
+
if (rb_equal(c->value, item)) {
|
1599
|
+
if (ptr->first == ptr->last) {
|
1600
|
+
ptr->first = NULL;
|
1601
|
+
ptr->last = NULL;
|
1602
|
+
} else if (c == ptr->first) {
|
1603
|
+
ptr->first = c->next;
|
1604
|
+
} else if (c == ptr->last) {
|
1605
|
+
ptr->last = before;
|
1606
|
+
ptr->last->next = NULL;
|
1607
|
+
} else {
|
1608
|
+
before->next = c->next;
|
1609
|
+
}
|
1610
|
+
xfree(c);
|
1611
|
+
ptr->len--;
|
1612
|
+
} else {
|
1613
|
+
before = c;
|
1614
|
+
}
|
1615
|
+
}
|
1616
|
+
|
1617
|
+
if (ptr->len == len) {
|
1618
|
+
if (rb_block_given_p()) {
|
1619
|
+
return rb_yield(item);
|
1620
|
+
}
|
1621
|
+
return Qnil;
|
1622
|
+
} else {
|
1623
|
+
return item;
|
1624
|
+
}
|
1625
|
+
}
|
1626
|
+
|
1627
|
+
static VALUE
|
1628
|
+
list_delete_at(VALUE self, long pos)
|
1629
|
+
{
|
1630
|
+
VALUE del;
|
1631
|
+
list_t *ptr;
|
1632
|
+
item_t *c, *before = NULL, *next;
|
1633
|
+
long len, i = 0;
|
1634
|
+
|
1635
|
+
Data_Get_Struct(self, list_t, ptr);
|
1636
|
+
len = ptr->len;
|
1637
|
+
if (ptr->len == 0) return Qnil;
|
1638
|
+
if (pos < 0) {
|
1639
|
+
pos += len;
|
1640
|
+
if (pos < 0) return Qnil;
|
1641
|
+
}
|
1642
|
+
list_modify_check(self);
|
1643
|
+
|
1644
|
+
for (c = ptr->first; c; c = next) {
|
1645
|
+
next = c->next;
|
1646
|
+
if (pos == i++) {
|
1647
|
+
del = c->value;
|
1648
|
+
if (ptr->first == ptr->last) {
|
1649
|
+
ptr->first = NULL;
|
1650
|
+
ptr->last = NULL;
|
1651
|
+
} else if (c == ptr->first) {
|
1652
|
+
ptr->first = c->next;
|
1653
|
+
} else if (c == ptr->last) {
|
1654
|
+
ptr->last = before;
|
1655
|
+
ptr->last->next = NULL;
|
1656
|
+
} else {
|
1657
|
+
before->next = c->next;
|
1658
|
+
}
|
1659
|
+
xfree(c);
|
1660
|
+
ptr->len--;
|
1661
|
+
break;
|
1662
|
+
} else {
|
1663
|
+
before = c;
|
1664
|
+
}
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
if (ptr->len == len) {
|
1668
|
+
return Qnil;
|
1669
|
+
} else {
|
1670
|
+
return del;
|
1671
|
+
}
|
1672
|
+
}
|
1673
|
+
|
1674
|
+
static VALUE
|
1675
|
+
list_delete_at_m(VALUE self, VALUE pos)
|
1676
|
+
{
|
1677
|
+
return list_delete_at(self, NUM2LONG(pos));
|
1678
|
+
}
|
1679
|
+
|
1680
|
+
static VALUE
|
1681
|
+
reject(VALUE self, VALUE result)
|
1682
|
+
{
|
1683
|
+
list_t *ptr;
|
1684
|
+
item_t *c;
|
1685
|
+
|
1686
|
+
Data_Get_Struct(self, list_t, ptr);
|
1687
|
+
LIST_FOR(ptr, c) {
|
1688
|
+
if (!RTEST(rb_yield(c->value))) {
|
1689
|
+
list_push(result, c->value);
|
1690
|
+
}
|
1691
|
+
}
|
1692
|
+
return result;
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
static VALUE
|
1696
|
+
reject_bang(VALUE self)
|
1697
|
+
{
|
1698
|
+
list_t *ptr;
|
1699
|
+
item_t *c, *before = NULL, *next;
|
1700
|
+
long len;
|
1701
|
+
|
1702
|
+
Data_Get_Struct(self, list_t, ptr);
|
1703
|
+
len = ptr->len;
|
1704
|
+
for (c = ptr->first; c; c = next) {
|
1705
|
+
next = c->next;
|
1706
|
+
if (RTEST(rb_yield(c->value))) {
|
1707
|
+
if (ptr->first == ptr->last) {
|
1708
|
+
ptr->first = NULL;
|
1709
|
+
ptr->last = NULL;
|
1710
|
+
} else if (c == ptr->first) {
|
1711
|
+
ptr->first = c->next;
|
1712
|
+
} else if (c == ptr->last) {
|
1713
|
+
ptr->last = before;
|
1714
|
+
ptr->last->next = NULL;
|
1715
|
+
} else {
|
1716
|
+
before->next = c->next;
|
1717
|
+
}
|
1718
|
+
xfree(c);
|
1719
|
+
ptr->len--;
|
1720
|
+
} else {
|
1721
|
+
before = c;
|
1722
|
+
}
|
1723
|
+
}
|
1724
|
+
|
1725
|
+
if (ptr->len == len) {
|
1726
|
+
return Qnil;
|
1727
|
+
} else {
|
1728
|
+
return self;
|
1729
|
+
}
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
static VALUE
|
1733
|
+
list_reject_bang(VALUE self)
|
1734
|
+
{
|
1735
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1736
|
+
return reject_bang(self);
|
1737
|
+
}
|
1738
|
+
|
1739
|
+
static VALUE
|
1740
|
+
list_reject(VALUE self)
|
1741
|
+
{
|
1742
|
+
VALUE rejected_list;
|
1743
|
+
|
1744
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1745
|
+
rejected_list = list_new();
|
1746
|
+
reject(self, rejected_list);
|
1747
|
+
return rejected_list;
|
1748
|
+
}
|
1749
|
+
|
1750
|
+
static VALUE
|
1751
|
+
list_delete_if(VALUE self)
|
1752
|
+
{
|
1753
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, list_enum_length);
|
1754
|
+
list_reject_bang(self);
|
1755
|
+
return self;
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
static VALUE
|
1759
|
+
list_zip(int argc, VALUE *argv, VALUE self)
|
1760
|
+
{
|
1761
|
+
VALUE ary;
|
1762
|
+
long i;
|
1763
|
+
|
1764
|
+
ary = rb_funcall2(list_to_a(self), rb_intern("zip"), argc, argv);
|
1765
|
+
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
1766
|
+
rb_ary_store(ary, i, to_list(rb_ary_entry(ary, i)));
|
1767
|
+
}
|
1768
|
+
if (rb_block_given_p()) {
|
1769
|
+
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
1770
|
+
rb_yield(rb_ary_entry(ary, i));
|
1771
|
+
}
|
1772
|
+
return Qnil;
|
1773
|
+
} else {
|
1774
|
+
return to_list(ary);
|
1775
|
+
}
|
1776
|
+
}
|
1777
|
+
|
1778
|
+
static VALUE
|
1779
|
+
list_transpose(VALUE self)
|
1780
|
+
{
|
1781
|
+
VALUE ary;
|
1782
|
+
long i;
|
1783
|
+
|
1784
|
+
ary = rb_funcall(list_to_a(self), rb_intern("transpose"), 0);
|
1785
|
+
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
1786
|
+
rb_ary_store(ary, i, to_list(rb_ary_entry(ary, i)));
|
1787
|
+
}
|
1788
|
+
return to_list(ary);
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
static VALUE
|
1792
|
+
list_fill(int argc, VALUE *argv, VALUE self)
|
1793
|
+
{
|
1794
|
+
VALUE item, arg1, arg2;
|
1795
|
+
long beg = 0, len = 0, end = 0;
|
1796
|
+
long i;
|
1797
|
+
int block_p = FALSE;
|
1798
|
+
list_t *ptr;
|
1799
|
+
item_t *c;
|
1800
|
+
|
1801
|
+
Data_Get_Struct(self, list_t, ptr);
|
1802
|
+
|
1803
|
+
list_modify_check(self);
|
1804
|
+
if (rb_block_given_p()) {
|
1805
|
+
block_p = TRUE;
|
1806
|
+
rb_scan_args(argc, argv, "02", &arg1, &arg2);
|
1807
|
+
argc += 1; /* hackish */
|
1808
|
+
} else {
|
1809
|
+
rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
|
1810
|
+
}
|
1811
|
+
switch (argc) {
|
1812
|
+
case 1:
|
1813
|
+
beg = 0;
|
1814
|
+
len = ptr->len;
|
1815
|
+
break;
|
1816
|
+
case 2:
|
1817
|
+
if (rb_range_beg_len(arg1, &beg, &len, ptr->len, 1)) {
|
1818
|
+
break;
|
1819
|
+
}
|
1820
|
+
/* fall through */
|
1821
|
+
case 3:
|
1822
|
+
beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
|
1823
|
+
if (beg < 0) {
|
1824
|
+
beg = ptr->len + beg;
|
1825
|
+
if (beg < 0) beg = 0;
|
1826
|
+
}
|
1827
|
+
len = NIL_P(arg2) ? ptr->len - beg : NUM2LONG(arg2);
|
1828
|
+
break;
|
1829
|
+
}
|
1830
|
+
if (len < 0) {
|
1831
|
+
return self;
|
1832
|
+
}
|
1833
|
+
if (LIST_MAX_SIZE <= beg || LIST_MAX_SIZE - beg < len) {
|
1834
|
+
rb_raise(rb_eArgError, "argument too big");
|
1835
|
+
}
|
1836
|
+
end = beg + len;
|
1837
|
+
if (ptr->len < end) {
|
1838
|
+
for (i = 0; i < end - ptr->len; i++) {
|
1839
|
+
list_push(self, Qnil);
|
1840
|
+
}
|
1841
|
+
}
|
1842
|
+
|
1843
|
+
i = -1;
|
1844
|
+
LIST_FOR(ptr, c) {
|
1845
|
+
i++;
|
1846
|
+
if (i < beg) continue;
|
1847
|
+
if ((end - 1) < i) break;
|
1848
|
+
if (block_p) {
|
1849
|
+
c->value = rb_yield(LONG2NUM(i));
|
1850
|
+
} else {
|
1851
|
+
c->value = item;
|
1852
|
+
}
|
1853
|
+
}
|
1854
|
+
return self;
|
1855
|
+
}
|
1856
|
+
|
1857
|
+
static VALUE
|
1858
|
+
list_include_p(VALUE self, VALUE item)
|
1859
|
+
{
|
1860
|
+
list_t *ptr;
|
1861
|
+
item_t *c;
|
1862
|
+
|
1863
|
+
Data_Get_Struct(self, list_t, ptr);
|
1864
|
+
LIST_FOR (ptr, c) {
|
1865
|
+
if (rb_equal(c->value, item)) {
|
1866
|
+
return Qtrue;
|
1867
|
+
}
|
1868
|
+
}
|
1869
|
+
return Qfalse;
|
1870
|
+
}
|
1871
|
+
|
1872
|
+
static VALUE
|
1873
|
+
recursive_cmp(VALUE list1, VALUE list2, int recur)
|
1874
|
+
{
|
1875
|
+
list_t *p1, *p2;
|
1876
|
+
item_t *c1, *c2;
|
1877
|
+
long len;
|
1878
|
+
|
1879
|
+
if (recur) return Qundef;
|
1880
|
+
Data_Get_Struct(list1, list_t, p1);
|
1881
|
+
Data_Get_Struct(list2, list_t, p2);
|
1882
|
+
len = p1->len;
|
1883
|
+
if (p2->len < len) {
|
1884
|
+
len = p2->len;
|
1885
|
+
}
|
1886
|
+
LIST_FOR_DOUBLE(p1,c1,p2,c2,{
|
1887
|
+
VALUE v = rb_funcall2(c1->value, id_cmp, 1, &(c2->value));
|
1888
|
+
if (v != INT2FIX(0)) {
|
1889
|
+
return v;
|
1890
|
+
}
|
1891
|
+
});
|
1892
|
+
return Qundef;
|
1893
|
+
}
|
1894
|
+
|
1895
|
+
static VALUE
|
1896
|
+
list_cmp(VALUE list1, VALUE list2)
|
1897
|
+
{
|
1898
|
+
VALUE v;
|
1899
|
+
list_t *p1, *p2;
|
1900
|
+
long len;
|
1901
|
+
|
1902
|
+
if (rb_type(list2) != T_DATA) return Qnil;
|
1903
|
+
if (list1 == list2) return INT2FIX(0);
|
1904
|
+
v = rb_exec_recursive_paired(recursive_cmp, list1, list2, list2);
|
1905
|
+
if (v != Qundef) return v;
|
1906
|
+
Data_Get_Struct(list1, list_t, p1);
|
1907
|
+
Data_Get_Struct(list2, list_t, p2);
|
1908
|
+
len = p1->len - p2->len;
|
1909
|
+
if (len == 0) return INT2FIX(0);
|
1910
|
+
if (0 < len) return INT2FIX(1);
|
1911
|
+
return INT2FIX(-1);
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
static VALUE
|
1915
|
+
list_slice_bang(int argc, VALUE *argv, VALUE self)
|
1916
|
+
{
|
1917
|
+
long pos = 0, len = 0;
|
1918
|
+
list_t *ptr;
|
1919
|
+
|
1920
|
+
Data_Get_Struct(self, list_t, ptr);
|
1921
|
+
|
1922
|
+
list_modify_check(self);
|
1923
|
+
if (argc == 1) {
|
1924
|
+
if (FIXNUM_P(argv[0])) {
|
1925
|
+
return list_delete_at(self, NUM2LONG(argv[0]));
|
1926
|
+
} else {
|
1927
|
+
switch (rb_range_beg_len(argv[0], &pos, &len, ptr->len, 0)) {
|
1928
|
+
case Qtrue: /* valid range */
|
1929
|
+
break;
|
1930
|
+
case Qnil: /* invalid range */
|
1931
|
+
return Qnil;
|
1932
|
+
default: /* not a range */
|
1933
|
+
return list_delete_at(self, NUM2LONG(argv[0]));
|
1934
|
+
}
|
1935
|
+
}
|
1936
|
+
} else if (argc == 2) {
|
1937
|
+
pos = NUM2LONG(argv[0]);
|
1938
|
+
len = NUM2LONG(argv[1]);
|
1939
|
+
} else {
|
1940
|
+
rb_scan_args(argc, argv, "11", NULL, NULL);
|
1941
|
+
}
|
1942
|
+
if (len < 0) return Qnil;
|
1943
|
+
if (pos < 0) {
|
1944
|
+
pos += ptr->len;
|
1945
|
+
if (pos < 0) return Qnil;
|
1946
|
+
} else if (ptr->len < pos) {
|
1947
|
+
return Qnil;
|
1948
|
+
}
|
1949
|
+
if (ptr->len < pos + len) {
|
1950
|
+
len = ptr->len - pos;
|
1951
|
+
}
|
1952
|
+
if (len == 0) return list_new();
|
1953
|
+
VALUE list2 = list_subseq(self, pos, len);
|
1954
|
+
list_mem_clear(ptr, pos, len);
|
1955
|
+
return list2;
|
1956
|
+
}
|
1957
|
+
|
1958
|
+
static VALUE
|
1959
|
+
list_ring_bang(VALUE self)
|
1960
|
+
{
|
1961
|
+
list_t *ptr;
|
1962
|
+
|
1963
|
+
Data_Get_Struct(self, list_t, ptr);
|
1964
|
+
if (ptr->first == NULL)
|
1965
|
+
rb_raise(rb_eRuntimeError, "length is zero list cannot to change ring");
|
1966
|
+
rb_obj_freeze(self);
|
1967
|
+
ptr->last->next = ptr->first;
|
1968
|
+
return self;
|
1969
|
+
}
|
1970
|
+
|
1971
|
+
static VALUE
|
1972
|
+
list_ring(VALUE self)
|
1973
|
+
{
|
1974
|
+
VALUE clone = rb_obj_clone(self);
|
1975
|
+
return list_ring_bang(clone);
|
1976
|
+
}
|
1977
|
+
|
1978
|
+
static VALUE
|
1979
|
+
list_ring_p(VALUE self)
|
1980
|
+
{
|
1981
|
+
list_t *ptr;
|
1982
|
+
|
1983
|
+
Data_Get_Struct(self, list_t, ptr);
|
1984
|
+
if (ptr->first == NULL)
|
1985
|
+
return Qfalse;
|
1986
|
+
if (ptr->first == ptr->last->next)
|
1987
|
+
return Qtrue;
|
1988
|
+
return Qfalse;
|
1989
|
+
}
|
1990
|
+
|
1991
|
+
static VALUE
|
1992
|
+
list_to_list(VALUE self)
|
1993
|
+
{
|
1994
|
+
return self;
|
1995
|
+
}
|
1996
|
+
|
1997
|
+
void
|
1998
|
+
Init_list(void)
|
1999
|
+
{
|
2000
|
+
cList = rb_define_class("List", rb_cObject);
|
2001
|
+
rb_include_module(cList, rb_mEnumerable);
|
2002
|
+
|
2003
|
+
rb_define_alloc_func(cList, list_alloc);
|
2004
|
+
|
2005
|
+
rb_define_singleton_method(cList, "[]", list_s_create, -1);
|
2006
|
+
rb_define_singleton_method(cList, "try_convert", list_s_try_convert, 1);
|
2007
|
+
|
2008
|
+
rb_define_method(cList, "initialize", list_initialize, -1);
|
2009
|
+
rb_define_method(cList, "initialize_copy", list_replace, 1);
|
2010
|
+
|
2011
|
+
rb_define_method(cList, "inspect", list_inspect, 0);
|
2012
|
+
rb_define_alias(cList, "to_s", "inspect");
|
2013
|
+
rb_define_method(cList, "to_a", list_to_a, 0);
|
2014
|
+
rb_define_method(cList, "to_ary", list_to_a, 0);
|
2015
|
+
rb_define_method(cList, "frozen?", list_frozen_p, 0);
|
2016
|
+
|
2017
|
+
rb_define_method(cList, "==", list_equal, 1);
|
2018
|
+
rb_define_method(cList, "hash", list_hash, 0);
|
2019
|
+
|
2020
|
+
rb_define_method(cList, "[]", list_aref, -1);
|
2021
|
+
rb_define_method(cList, "[]=", list_aset, -1);
|
2022
|
+
rb_define_method(cList, "at", list_at, 1);
|
2023
|
+
rb_define_method(cList, "fetch", list_fetch, -1);
|
2024
|
+
rb_define_method(cList, "first", list_first, -1);
|
2025
|
+
rb_define_method(cList, "last", list_last, -1);
|
2026
|
+
rb_define_method(cList, "concat", list_concat, 1);
|
2027
|
+
rb_define_method(cList, "<<", list_push, 1);
|
2028
|
+
rb_define_method(cList, "push", list_push_m, -1);
|
2029
|
+
rb_define_method(cList, "pop", list_pop_m, -1);
|
2030
|
+
rb_define_method(cList, "shift", list_shift_m, -1);
|
2031
|
+
rb_define_method(cList, "unshift", list_unshift_m, -1);
|
2032
|
+
rb_define_method(cList, "insert", list_insert, -1);
|
2033
|
+
rb_define_method(cList, "each", list_each, 0);
|
2034
|
+
rb_define_method(cList, "each_index", list_each_index, 0);
|
2035
|
+
rb_define_method(cList, "length", list_length, 0);
|
2036
|
+
rb_define_alias(cList, "size", "length");
|
2037
|
+
rb_define_method(cList, "empty?", list_empty_p, 0);
|
2038
|
+
rb_define_alias(cList, "index", "find_index");
|
2039
|
+
rb_define_method(cList, "rindex", list_rindex, -1);
|
2040
|
+
rb_define_method(cList, "join", list_join_m, -1);
|
2041
|
+
rb_define_method(cList, "reverse", list_reverse_m, 0);
|
2042
|
+
rb_define_method(cList, "reverse!", list_reverse_bang, 0);
|
2043
|
+
rb_define_method(cList, "rotate", list_rotate_m, -1);
|
2044
|
+
rb_define_method(cList, "rotate!", list_rotate_bang, -1);
|
2045
|
+
rb_define_method(cList, "sort", list_sort, 0);
|
2046
|
+
rb_define_method(cList, "sort!", list_sort_bang, 0);
|
2047
|
+
rb_define_method(cList, "sort_by", list_sort_by, 0);
|
2048
|
+
rb_define_method(cList, "sort_by!", list_sort_by_bang, 0);
|
2049
|
+
rb_define_method(cList, "collect", list_collect, 0);
|
2050
|
+
rb_define_method(cList, "collect!", list_collect_bang, 0);
|
2051
|
+
rb_define_method(cList, "map", list_collect, 0);
|
2052
|
+
rb_define_method(cList, "map!", list_collect_bang, 0);
|
2053
|
+
rb_define_method(cList, "select", list_select, 0);
|
2054
|
+
rb_define_method(cList, "select!", list_select_bang, 0);
|
2055
|
+
rb_define_method(cList, "keep_if", list_keep_if, 0);
|
2056
|
+
rb_define_method(cList, "values_at", list_values_at, -1);
|
2057
|
+
rb_define_method(cList, "delete", list_delete, 1);
|
2058
|
+
rb_define_method(cList, "delete_at", list_delete_at_m, 1);
|
2059
|
+
rb_define_method(cList, "delete_if", list_delete_if, 0);
|
2060
|
+
rb_define_method(cList, "reject", list_reject, 0);
|
2061
|
+
rb_define_method(cList, "reject!", list_reject_bang, 0);
|
2062
|
+
rb_define_method(cList, "zip", list_zip, -1);
|
2063
|
+
rb_define_method(cList, "transpose", list_transpose, 0);
|
2064
|
+
rb_define_method(cList, "replace", list_replace, 1);
|
2065
|
+
rb_define_method(cList, "clear", list_clear, 0);
|
2066
|
+
rb_define_method(cList, "fill", list_fill, -1);
|
2067
|
+
rb_define_method(cList, "include?", list_include_p, 1);
|
2068
|
+
rb_define_method(cList, "<=>", list_cmp, 1);
|
2069
|
+
|
2070
|
+
rb_define_method(cList, "slice", list_aref, -1);
|
2071
|
+
rb_define_method(cList, "slice!", list_slice_bang, -1);
|
2072
|
+
|
2073
|
+
rb_define_method(cList, "ring", list_ring, 0);
|
2074
|
+
rb_define_method(cList, "ring!", list_ring_bang, 0);
|
2075
|
+
rb_define_method(cList, "ring?", list_ring_p, 0);
|
2076
|
+
|
2077
|
+
rb_define_method(cList, "to_list", list_to_list, 0);
|
2078
|
+
rb_define_method(rb_mEnumerable, "to_list", ary_to_list, -1);
|
2079
|
+
|
2080
|
+
rb_define_const(cList, "VERSION", rb_str_new2(LIST_VERSION));
|
2081
|
+
|
2082
|
+
id_cmp = rb_intern("<=>");
|
2083
|
+
id_each = rb_intern("each");
|
2084
|
+
}
|