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.
@@ -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
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ *.bundle
4
+ *.so
5
+ *.o
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -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.
@@ -0,0 +1,60 @@
1
+ # List
2
+
3
+ List in Ruby.
4
+
5
+ [![Build Status](https://travis-ci.org/ksss/list.png?branch=master)](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
@@ -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]
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << " -Wall"
4
+
5
+ create_makefile('list')
@@ -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
+ }