1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* List object implementation */
27 #include "allobjects.h"
28 #include "modsupport.h"
42 nbytes
= size
* sizeof(object
*);
43 /* Check for overflow */
44 if (nbytes
/ sizeof(object
*) != size
) {
47 op
= (listobject
*) malloc(sizeof(listobject
));
55 op
->ob_item
= (object
**) malloc(nbytes
);
56 if (op
->ob_item
== NULL
) {
61 op
->ob_type
= &Listtype
;
63 for (i
= 0; i
< size
; i
++)
64 op
->ob_item
[i
] = NULL
;
73 if (!is_listobject(op
)) {
78 return ((listobject
*)op
) -> ob_size
;
86 if (!is_listobject(op
)) {
90 if (i
< 0 || i
>= ((listobject
*)op
) -> ob_size
) {
91 err_setstr(IndexError
, "list index out of range");
94 return ((listobject
*)op
) -> ob_item
[i
];
98 setlistitem(op
, i
, newitem
)
101 register object
*newitem
;
103 register object
*olditem
;
104 if (!is_listobject(op
)) {
109 if (i
< 0 || i
>= ((listobject
*)op
) -> ob_size
) {
111 err_setstr(IndexError
, "list assignment index out of range");
114 olditem
= ((listobject
*)op
) -> ob_item
[i
];
115 ((listobject
*)op
) -> ob_item
[i
] = newitem
;
132 items
= self
->ob_item
;
133 RESIZE(items
, object
*, self
->ob_size
+1);
140 if (where
> self
->ob_size
)
141 where
= self
->ob_size
;
142 for (i
= self
->ob_size
; --i
>= where
; )
143 items
[i
+1] = items
[i
];
146 self
->ob_item
= items
;
152 inslistitem(op
, where
, newitem
)
157 if (!is_listobject(op
)) {
161 return ins1((listobject
*)op
, where
, newitem
);
165 addlistitem(op
, newitem
)
169 if (!is_listobject(op
)) {
173 return ins1((listobject
*)op
,
174 (int) ((listobject
*)op
)->ob_size
, newitem
);
184 for (i
= 0; i
< op
->ob_size
; i
++) {
185 XDECREF(op
->ob_item
[i
]);
187 if (op
->ob_item
!= NULL
)
188 free((ANY
*)op
->ob_item
);
193 list_print(op
, fp
, flags
)
200 for (i
= 0; i
< op
->ob_size
; i
++) {
203 if (printobject(op
->ob_item
[i
], fp
, 0) != 0)
216 s
= newstringobject("[");
217 comma
= newstringobject(", ");
218 for (i
= 0; i
< v
->ob_size
&& s
!= NULL
; i
++) {
220 joinstring(&s
, comma
);
221 joinstring_decref(&s
, reprobject(v
->ob_item
[i
]));
224 joinstring_decref(&s
, newstringobject("]"));
232 int len
= (v
->ob_size
< w
->ob_size
) ? v
->ob_size
: w
->ob_size
;
234 for (i
= 0; i
< len
; i
++) {
235 int cmp
= cmpobject(v
->ob_item
[i
], w
->ob_item
[i
]);
239 return v
->ob_size
- w
->ob_size
;
254 if (i
< 0 || i
>= a
->ob_size
) {
255 err_setstr(IndexError
, "list index out of range");
258 INCREF(a
->ob_item
[i
]);
259 return a
->ob_item
[i
];
263 list_slice(a
, ilow
, ihigh
)
271 else if (ilow
> a
->ob_size
)
277 else if (ihigh
> a
->ob_size
)
279 np
= (listobject
*) newlistobject(ihigh
- ilow
);
282 for (i
= ilow
; i
< ihigh
; i
++) {
283 object
*v
= a
->ob_item
[i
];
285 np
->ob_item
[i
- ilow
] = v
;
291 getlistslice(a
, ilow
, ihigh
)
295 if (!is_listobject(a
)) {
299 return list_slice((listobject
*)a
, ilow
, ihigh
);
310 if (!is_listobject(bb
)) {
314 #define b ((listobject *)bb)
315 size
= a
->ob_size
+ b
->ob_size
;
316 np
= (listobject
*) newlistobject(size
);
320 for (i
= 0; i
< a
->ob_size
; i
++) {
321 object
*v
= a
->ob_item
[i
];
325 for (i
= 0; i
< b
->ob_size
; i
++) {
326 object
*v
= b
->ob_item
[i
];
328 np
->ob_item
[i
+ a
->ob_size
] = v
;
345 size
= a
->ob_size
* n
;
346 np
= (listobject
*) newlistobject(size
);
350 for (i
= 0; i
< n
; i
++) {
351 for (j
= 0; j
< a
->ob_size
; j
++) {
357 return (object
*) np
;
361 list_ass_slice(a
, ilow
, ihigh
, v
)
367 int n
; /* Size of replacement list */
368 int d
; /* Change in size */
369 int k
; /* Loop index */
370 #define b ((listobject *)v)
373 else if (is_listobject(v
)) {
376 /* Special case "a[i:j] = a" -- copy b first */
378 v
= list_slice(b
, 0, n
);
379 ret
= list_ass_slice(a
, ilow
, ihigh
, v
);
390 else if (ilow
> a
->ob_size
)
396 else if (ihigh
> a
->ob_size
)
399 d
= n
- (ihigh
-ilow
);
400 if (d
<= 0) { /* Delete -d items; XDECREF ihigh-ilow items */
401 for (k
= ilow
; k
< ihigh
; k
++)
404 for (/*k = ihigh*/; k
< a
->ob_size
; k
++)
407 RESIZE(item
, object
*, a
->ob_size
); /* Can't fail */
411 else { /* Insert d items; XDECREF ihigh-ilow items */
412 RESIZE(item
, object
*, a
->ob_size
+ d
);
417 for (k
= a
->ob_size
; --k
>= ihigh
; )
419 for (/*k = ihigh-1*/; k
>= ilow
; --k
)
424 for (k
= 0; k
< n
; k
++, ilow
++) {
425 object
*w
= b
->ob_item
[k
];
434 setlistslice(a
, ilow
, ihigh
, v
)
439 if (!is_listobject(a
)) {
443 return list_ass_slice((listobject
*)a
, ilow
, ihigh
, v
);
447 list_ass_item(a
, i
, v
)
452 if (i
< 0 || i
>= a
->ob_size
) {
453 err_setstr(IndexError
, "list assignment index out of range");
457 return list_ass_slice(a
, i
, i
+1, v
);
459 DECREF(a
->ob_item
[i
]);
470 if (ins1(self
, where
, v
) != 0)
477 listinsert(self
, args
)
483 if (!getargs(args
, "(iO)", &i
, &v
))
485 return ins(self
, i
, v
);
489 listappend(self
, args
)
494 if (!getargs(args
, "O", &v
))
496 return ins(self
, (int) self
->ob_size
, v
);
499 static object
*comparefunc
;
515 if (comparefunc
== NULL
)
516 return cmpobject(* (object
**) v
, * (object
**) w
);
518 /* Call the user-supplied comparison function */
519 t
= mkvalue("OO", * (object
**) v
, * (object
**) w
);
522 res
= call_object(comparefunc
, t
);
526 if (!is_intobject(res
)) {
527 err_setstr(TypeError
, "comparison function should return int");
531 i
= getintvalue(res
);
546 object
*save_comparefunc
;
547 if (self
->ob_size
<= 1) {
551 save_comparefunc
= comparefunc
;
553 if (comparefunc
!= NULL
) {
554 /* Test the comparison function for obvious errors */
555 (void) cmp(&self
->ob_item
[0], &self
->ob_item
[1]);
556 if (err_occurred()) {
557 comparefunc
= save_comparefunc
;
561 qsort((char *)self
->ob_item
,
562 (int) self
->ob_size
, sizeof(object
*), cmp
);
563 comparefunc
= save_comparefunc
;
571 listreverse(self
, args
)
575 register object
**p
, **q
;
576 register object
*tmp
;
583 if (self
->ob_size
> 1) {
584 for (p
= self
->ob_item
, q
= self
->ob_item
+ self
->ob_size
- 1;
600 if (v
== NULL
|| !is_listobject(v
)) {
604 v
= listsort((listobject
*)v
, (object
*)NULL
);
612 listindex(self
, args
)
622 for (i
= 0; i
< self
->ob_size
; i
++) {
623 if (cmpobject(self
->ob_item
[i
], args
) == 0)
624 return newintobject((long)i
);
626 err_setstr(ValueError
, "list.index(x): x not in list");
631 listcount(self
, args
)
642 for (i
= 0; i
< self
->ob_size
; i
++) {
643 if (cmpobject(self
->ob_item
[i
], args
) == 0)
646 return newintobject((long)count
);
650 listremove(self
, args
)
660 for (i
= 0; i
< self
->ob_size
; i
++) {
661 if (cmpobject(self
->ob_item
[i
], args
) == 0) {
662 if (list_ass_slice(self
, i
, i
+1, (object
*)NULL
) != 0)
669 err_setstr(ValueError
, "list.remove(x): x not in list");
673 static struct methodlist list_methods
[] = {
674 {"append", (method
)listappend
},
675 {"count", (method
)listcount
},
676 {"index", (method
)listindex
},
677 {"insert", (method
)listinsert
},
678 {"sort", (method
)listsort
},
679 {"remove", (method
)listremove
},
680 {"reverse", (method
)listreverse
},
681 {NULL
, NULL
} /* sentinel */
685 list_getattr(f
, name
)
689 return findmethod(list_methods
, (object
*)f
, name
);
692 static sequence_methods list_as_sequence
= {
693 (inquiry
)list_length
, /*sq_length*/
694 (binaryfunc
)list_concat
, /*sq_concat*/
695 (intargfunc
)list_repeat
, /*sq_repeat*/
696 (intargfunc
)list_item
, /*sq_item*/
697 (intintargfunc
)list_slice
, /*sq_slice*/
698 (intobjargproc
)list_ass_item
, /*sq_ass_item*/
699 (intintobjargproc
)list_ass_slice
, /*sq_ass_slice*/
702 typeobject Listtype
= {
703 OB_HEAD_INIT(&Typetype
)
708 (destructor
)list_dealloc
, /*tp_dealloc*/
709 (printfunc
)list_print
, /*tp_print*/
710 (getattrfunc
)list_getattr
, /*tp_getattr*/
712 (cmpfunc
)list_compare
, /*tp_compare*/
713 (reprfunc
)list_repr
, /*tp_repr*/
715 &list_as_sequence
, /*tp_as_sequence*/