2 //metadoc List copyright Steve Dekorte 2002
3 //metadoc List license BSD revised
4 /*metadoc List description
5 A mutable array of values. The first index is 0.")
7 //metadoc List category DataStructures
12 #include "IoCFunction.h"
20 #define DATA(self) ((List *)(IoObject_dataPointer(self)))
22 IoTag
*IoList_newTag(void *state
)
24 IoTag
*tag
= IoTag_newWithName_("List");
25 IoTag_state_(tag
, state
);
26 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoList_free
);
27 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoList_rawClone
);
28 IoTag_markFunc_(tag
, (IoTagMarkFunc
*)IoList_mark
);
29 IoTag_compareFunc_(tag
, (IoTagCompareFunc
*)IoList_compare
);
30 IoTag_writeToStreamFunc_(tag
, (IoTagWriteToStreamFunc
*)IoList_writeToStream_
);
31 IoTag_readFromStreamFunc_(tag
, (IoTagReadFromStreamFunc
*)IoList_readFromStream_
);
35 void IoList_writeToStream_(IoList
*self
, BStream
*stream
)
37 List
*list
= DATA(self
);
39 BStream_writeTaggedInt32_(stream
, List_size(list
));
41 LIST_FOREACH(list
, i
, v
,
42 BStream_writeTaggedInt32_(stream
, IoObject_pid((IoObject
*)v
));
46 void IoList_readFromStream_(IoList
*self
, BStream
*stream
)
48 List
*list
= DATA(self
);
49 int i
, max
= BStream_readTaggedInt32(stream
);
51 for (i
= 0; i
< max
; i
++)
53 int pid
= BStream_readTaggedInt32(stream
);
54 IoObject
*v
= IoState_objectWithPid_(IOSTATE
, pid
);
55 List_append_(list
, v
);
59 IoList
*IoList_proto(void *state
)
61 IoMethodTable methodTable
[] = {
62 {"with", IoList_with
},
66 {"indexOf", IoList_indexOf
},
67 {"contains", IoList_contains
},
68 {"containsIdenticalTo", IoList_containsIdenticalTo
},
69 {"capacity", IoList_capacity
},
70 {"size", IoList_size
},
74 {"setSize", IoList_setSize
},
75 {"removeAll", IoList_removeAll
},
76 {"appendSeq", IoList_appendSeq
},
77 {"append", IoList_append
},
78 {"prepend", IoList_prepend
},
79 {"push", IoList_append
},
81 {"appendIfAbsent", IoList_appendIfAbsent
},
83 {"remove", IoList_remove
},
86 {"atInsert", IoList_atInsert
},
88 {"atPut", IoList_atPut
},
90 {"removeAt", IoList_removeAt
},
91 {"swapIndices", IoList_swapIndices
},
93 {"preallocateToSize", IoList_preallocateToSize
},
95 {"first", IoList_first
},
96 {"last", IoList_last
},
97 {"slice", IoList_slice
},
98 {"sliceInPlace", IoList_sliceInPlace
},
101 {"sortInPlace", IoList_sortInPlace
},
102 {"sortInPlaceBy", IoList_sortInPlaceBy
},
103 {"foreach", IoList_foreach
},
104 {"reverse", IoList_reverse
},
105 {"reverseForeach", IoList_reverseForeach
},
109 IoObject
*self
= IoObject_new(state
);
110 IoObject_tag_(self
, IoList_newTag(state
));
112 IoObject_setDataPointer_(self
, List_new());
113 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoList_proto
);
115 IoObject_addMethodTable_(self
, methodTable
);
119 IoList
*IoList_rawClone(IoList
*proto
)
121 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
122 IoObject_tag_(self
, IoObject_tag(proto
));
123 IoObject_setDataPointer_(self
, List_clone(DATA(proto
)));
127 IoList
*IoList_new(void *state
)
129 IoObject
*proto
= IoState_protoWithInitFunction_((IoState
*)state
, IoList_proto
);
130 return IOCLONE(proto
);
133 IoList
*IoList_newWithList_(void *state
, List
*list
)
135 IoList
*self
= IoList_new(state
);
136 //printf("IoList_newWithList_ %p %p\n", (void *)self, (void *)list);
137 List_free(IoObject_dataPointer(self
));
138 IoObject_setDataPointer_(self
, list
);
142 void IoList_free(IoList
*self
)
144 if (NULL
== DATA(self
))
146 printf("IoList_free(%p) already freed\n", (void *)self
);
149 //printf("IoList_free(%p) List_free(%p)\n", (void *)self, (void *)DATA(self));
151 List_free(DATA(self
));
152 IoObject_setDataPointer_(self
, NULL
);
156 void IoList_mark(IoList
*self
)
158 LIST_FOREACH(DATA(self
), i
, item
, IoObject_shouldMark(item
));
161 int IoList_compare(IoList
*self
, IoList
*otherList
)
163 if (!ISLIST(otherList
))
165 return IoObject_defaultCompare(self
, otherList
);
169 size_t s1
= List_size(DATA(self
));
170 size_t s2
= List_size(DATA(otherList
));
175 return s1
> s2
? 1 : -1;
178 for (i
= 0; i
< s1
; i
++)
180 IoObject
*v1
= LIST_AT_(DATA(self
), i
);
181 IoObject
*v2
= LIST_AT_(DATA(otherList
), i
);
182 int c
= IoObject_compare(v1
, v2
);
193 List
*IoList_rawList(IoList
*self
)
198 IoObject
*IoList_rawAt_(IoList
*self
, int i
)
200 return List_at_(DATA(self
), i
);
203 void IoList_rawAt_put_(IoList
*self
, int i
, IoObject
*v
)
205 List_at_put_(DATA(self
), i
, IOREF(v
));
208 void IoList_rawAppend_(IoList
*self
, IoObject
*v
)
210 List_append_(DATA(self
), IOREF(v
));
213 void IoList_rawRemove_(IoList
*self
, IoObject
*v
)
215 List_remove_(DATA(self
), IOREF(v
));
218 void IoList_rawAddBaseList_(IoList
*self
, List
*otherList
)
220 List
*list
= DATA(self
);
221 LIST_FOREACH(otherList
, i
, v
, List_append_(list
, IOREF((IoObject
*)v
)); );
224 void IoList_rawAddIoList_(IoList
*self
, IoList
*other
)
226 IoList_rawAddBaseList_(self
, DATA(other
));
229 size_t IoList_rawSize(IoList
*self
)
231 return List_size(DATA(self
));
234 int IoList_rawIndexOf_(IoList
*self
, IoObject
*v
)
236 List
*list
= DATA(self
);
238 LIST_FOREACH(list
, i
, item
,
239 if (IoObject_compare(v
, (IoObject
*)item
) == 0)
248 void IoList_checkIndex(IoList
*self
, IoMessage
*m
, char allowsExtending
, int index
, const char *methodName
)
250 int max
= List_size(DATA(self
));
257 if (index
< 0 || index
>= max
)
259 IoState_error_(IOSTATE
, m
, "index out of bounds\n");
263 // immutable --------------------------------------------------------
265 IoObject
*IoList_with(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
267 /*doc List with(anObject, ...)
268 Returns a new List containing the arguments.
271 int n
, argCount
= IoMessage_argCount(m
);
272 IoList
*ioList
= IOCLONE(self
);
274 for (n
= 0; n
< argCount
; n
++)
276 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, n
);
277 IoList_rawAppend_(ioList
, v
);
284 IoObject
*IoList_indexOf(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
286 /*doc List indexOf(anObject)
287 Returns the index of the first occurrence of anObject
288 in the receiver. Returns Nil if the receiver doesn't contain anObject.
291 int count
= IoMessage_argCount(m
);
293 IOASSERT(count
, "remove requires at least one argument");
296 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 0);
297 int i
= IoList_rawIndexOf_(self
, v
);
299 return i
== -1 ? IONIL(self
) :
300 (IoObject
*)IONUMBER(IoList_rawIndexOf_(self
, v
));
304 IoObject
*IoList_contains(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
306 /*doc List contains(anObject)
307 Returns true if the receiver contains anObject, otherwise returns false.
310 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 0);
311 return IOBOOL(self
, IoList_rawIndexOf_(self
, v
) != -1);
314 IoObject
*IoList_containsIdenticalTo(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
316 /*doc List containsIdenticalTo(anObject)
317 Returns true if the receiver contains a value identical to anObject, otherwise returns false.
320 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 0);
321 return IOBOOL(self
, List_contains_(DATA(self
), v
) != 0);
324 IoObject
*IoList_capacity(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
327 Returns the number of potential elements the receiver can hold before it needs to grow.
330 return IONUMBER(DATA(self
)->memSize
/ sizeof(void *));
333 IoObject
*IoList_size(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
336 Returns the number of items in the receiver.
339 return IONUMBER(List_size(DATA(self
)));
342 IoObject
*IoList_at(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
345 Returns the value at index. Returns Nil if the index is out of bounds.
348 int index
= IoMessage_locals_intArgAt_(m
, locals
, 0);
350 /*IoList_checkIndex(self, m, 0, index, "Io List at");*/
351 v
= List_at_(DATA(self
), index
);
352 return (v
) ? v
: IONIL(self
);
355 IoObject
*IoList_first(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
357 /*doc List first(optionalSize)
358 Returns the first item or Nil if the list is empty.
359 If optionalSize is provided, that number of the first items in the list are returned.
362 if (IoMessage_argCount(m
) == 0)
364 IoObject
*result
= List_at_(DATA(self
), 0);
366 return result
? result
: ((IoState
*)IOSTATE
)->ioNil
;
370 int end
= IoMessage_locals_intArgAt_(m
, locals
, 0);
374 return IoList_new(IOSTATE
);
378 List
*list
= List_cloneSlice(DATA(self
), 0, end
- 1);
379 return IoList_newWithList_(IOSTATE
, list
);
384 IoObject
*IoList_last(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
386 /*doc List last(optionalSize)
387 Returns the last item or Nil if the list is empty.
388 If optionalSize is provided, that number of the last items in the list are returned.
391 if (IoMessage_argCount(m
) == 0)
393 IoObject
*result
= List_at_(DATA(self
), List_size(DATA(self
))-1);
394 return result
? result
: ((IoState
*)IOSTATE
)->ioNil
;
398 size_t size
= IoList_rawSize(self
);
399 int start
= size
- IoMessage_locals_intArgAt_(m
, locals
, 0);
407 list
= List_cloneSlice(DATA(self
), start
, size
);
408 return IoList_newWithList_(IOSTATE
, list
);
412 void IoList_sliceArguments(IoList
*self
, IoObject
*locals
, IoMessage
*m
, int *start
, int *end
)
414 int size
= IoList_rawSize(self
);
416 *start
= IoMessage_locals_intArgAt_(m
, locals
, 0);
426 if (IoMessage_argCount(m
) == 2)
428 *end
= IoMessage_locals_intArgAt_(m
, locals
, 1);
441 IoObject
*IoList_slice(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
443 /*doc List slice(startIndex, endIndex)
444 Returns a new string containing the subset of the
445 receiver from the startIndex to the endIndex. The endIndex argument
446 is optional. If not given, it is assumed to be the end of the string.
452 IoList_sliceArguments(self
, locals
, m
, &start
, &end
);
456 return IoList_new(IOSTATE
);
460 list
= List_cloneSlice(DATA(self
), start
, end
);
461 return IoList_newWithList_(IOSTATE
, list
);
465 IoObject
*IoList_sliceInPlace(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
467 /*doc List sliceInPlace(startIndex, endIndex)
468 Returns the receiver containing the subset of the
469 receiver from the startIndex to the endIndex. The endIndex argument
470 is optional. If not given, it is assumed to be the end of the string.
475 IoList_sliceArguments(self
, locals
, m
, &start
, &end
);
479 List_removeAll(DATA(self
));
483 List_sliceInPlace(DATA(self
), start
, end
);
488 IoObject
*IoList_each(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
490 IoState
*state
= IOSTATE
;
491 IoObject
*result
= IONIL(self
);
492 IoMessage
*doMessage
= IoMessage_rawArgAt_(m
, 0);
493 List
*list
= DATA(self
);
495 IoState_pushRetainPool(state
);
497 LIST_SAFEFOREACH(list
, i
, v
,
498 IoState_clearTopPool(state
);
499 result
= IoMessage_locals_performOn_(doMessage
, locals
, (IoObject
*)v
);
500 if (IoState_handleStatus(IOSTATE
)) goto done
;
504 IoState_popRetainPoolExceptFor_(state
, result
);
509 IoObject
*IoList_foreach(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
511 /*doc List foreach(optionalIndex, value, message)
512 Loops over the list values setting the specified index and
513 value slots and executing the message. Returns the result of the last
514 execution of the message. Example:
515 <code> list(1, 2, 3) foreach(i, v, writeln(i, " = ", v))
516 list(1, 2, 3) foreach(v, writeln(v))</code>
519 IoState
*state
= IOSTATE
;
520 IoObject
*result
= IONIL(self
);
521 IoSymbol
*slotName
= NULL
;
523 IoMessage
*doMessage
;
524 List
*list
= DATA(self
);
526 if (IoMessage_argCount(m
) == 1)
528 return IoList_each(self
, locals
, m
);
531 IoMessage_foreachArgs(m
, self
, &slotName
, &valueName
, &doMessage
);
533 IoState_pushRetainPool(state
);
537 LIST_SAFEFOREACH(list
, i
, value
,
538 IoState_clearTopPool(state
);
539 IoObject_setSlot_to_(locals
, slotName
, IONUMBER(i
));
540 IoObject_setSlot_to_(locals
, valueName
, (IoObject
*)value
);
541 result
= IoMessage_locals_performOn_(doMessage
, locals
, locals
);
542 if (IoState_handleStatus(IOSTATE
)) goto done
;
547 LIST_SAFEFOREACH(list
, i
, value
,
548 IoState_clearTopPool(state
);
549 IoObject_setSlot_to_(locals
, valueName
, (IoObject
*)value
);
550 result
= IoMessage_locals_performOn_(doMessage
, locals
, locals
);
551 if (IoState_handleStatus(IOSTATE
)) goto done
;
556 IoState_popRetainPoolExceptFor_(state
, result
);
560 IoObject
*IoList_reverseForeach(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
562 /*doc List reverseForeach(index, value, message)
563 Same as foreach, but in reverse order.
566 IoState
*state
= IOSTATE
;
567 IoObject
*result
= IONIL(self
);
568 IoSymbol
*slotName
, *valueName
;
569 IoMessage
*doMessage
;
572 IoMessage_foreachArgs(m
, self
, &slotName
, &valueName
, &doMessage
);
574 IoState_pushRetainPool(state
);
576 for (i
= List_size(DATA(self
)) - 1; i
>= 0; i
--)
578 IoState_clearTopPool(state
);
580 IoObject
*value
= (IoObject
*)LIST_AT_(DATA(self
), i
);
584 IoObject_setSlot_to_(locals
, slotName
, IONUMBER(i
));
587 IoObject_setSlot_to_(locals
, valueName
, value
);
588 result
= IoMessage_locals_performOn_(doMessage
, locals
, locals
);
590 if (IoState_handleStatus(IOSTATE
))
595 if(i
> List_size(DATA(self
)) - 1) { i
= List_size(DATA(self
)) - 1; }
598 IoState_popRetainPoolExceptFor_(state
, result
);
602 // mutable --------------------------------------------------------
604 IoObject
*IoList_appendIfAbsent(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
606 /*doc List appendIfAbsent(anObject)
607 Adds each value not already contained by the receiver, returns self.
612 for (n
= 0; n
< IoMessage_argCount(m
); n
++)
614 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, n
);
616 if (IoList_rawIndexOf_(self
, v
) == -1)
618 IoState_stackRetain_(IOSTATE
, v
);
619 List_append_(DATA(self
), IOREF(v
));
626 IoObject
*IoList_appendSeq(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
628 /*doc List appendSeq(aList1, aList2, ...)
629 Add the items in the lists to the receiver. Returns self.
634 for (i
= 0; i
< IoMessage_argCount(m
); i
++)
636 IoObject
*other
= IoMessage_locals_valueArgAt_(m
, locals
, i
);
638 IOASSERT(ISLIST(other
), "requires List objects as arguments");
642 IoState_error_(IOSTATE
, m
, "can't add a list to itself\n");
646 List
*selfList
= DATA(self
);
647 List
*otherList
= DATA(other
);
648 int i
, max
= List_size(otherList
);
650 for (i
= 0; i
< max
; i
++)
652 IoObject
*v
= List_at_(otherList
, i
);
653 List_append_(selfList
, IOREF(v
));
660 IoObject
*IoList_append(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
662 /*doc List append(anObject1, anObject2, ...)
663 Appends the arguments to the end of the list. Returns self.
666 /*doc List push(anObject1, anObject2, ...)
667 Same as add(anObject1, anObject2, ...).
672 IOASSERT(IoMessage_argCount(m
), "requires at least one argument");
674 for (n
= 0; n
< IoMessage_argCount(m
); n
++)
676 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, n
);
677 List_append_(DATA(self
), IOREF(v
));
683 IoObject
*IoList_prepend(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
685 /*doc List prepend(anObject1, anObject2, ...)
686 Inserts the values at the beginning of the list. Returns self.
691 IOASSERT(IoMessage_argCount(m
), "requires at least one argument");
693 for (n
= 0; n
< IoMessage_argCount(m
); n
++)
695 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, n
);
696 List_at_insert_(DATA(self
), 0, IOREF(v
));
703 IoObject
*IoList_remove(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
705 /*doc List remove(anObject, ...)
706 Removes all occurrences of the arguments from the receiver. Returns self.
709 int count
= IoMessage_argCount(m
);
712 IOASSERT(count
, "requires at least one argument");
714 for (j
= 0; j
< count
; j
++)
716 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, j
);
718 // a quick pass to remove values with equal pointers
719 List_remove_(DATA(self
), v
);
721 // slow pass to remove values that match comparision test
724 int i
= IoList_rawIndexOf_(self
, v
);
731 List_removeIndex_(DATA(self
), i
);
738 IoObject
*IoList_pop(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
741 Returns the last item in the list and removes it
742 from the receiver. Returns nil if the receiver is empty.
745 IoObject
*v
= List_pop(DATA(self
));
746 return (v
) ? v
: IONIL(self
);
749 IoObject
*IoList_atInsert(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
751 /*doc List atInsert(index, anObject)
752 Inserts anObject at the index specified by index.
753 Adds anObject if the index equals the current count of the receiver.
754 Raises an exception if the index is out of bounds. Returns self.
757 int index
= IoMessage_locals_intArgAt_(m
, locals
, 0);
758 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 1);
760 IoList_checkIndex(self
, m
, 1, index
, "List atInsert");
761 List_at_insert_(DATA(self
), index
, IOREF(v
));
765 IoObject
*IoList_removeAt(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
767 /*doc List removeAt(index)
768 Removes the item at the specified index and returns the value removed.
769 Raises an exception if the index is out of bounds.
772 int index
= IoMessage_locals_intArgAt_(m
, locals
, 0);
773 IoObject
*v
= List_at_(DATA(self
), index
);
775 IoList_checkIndex(self
, m
, 0, index
, "Io List atInsert");
776 List_removeIndex_(DATA(self
), index
);
777 return (v
) ? v
: IONIL(self
);
780 void IoList_rawAtPut(IoList
*self
, int i
, IoObject
*v
)
782 while (List_size(DATA(self
)) < i
) /* not efficient */
784 List_append_(DATA(self
), IONIL(self
));
787 List_at_put_(DATA(self
), i
, IOREF(v
));
790 IoObject
*IoList_atPut(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
792 /*doc List atPut(index, anObject)
793 Replaces the existing value at index with anObject.
794 Raises an exception if the index is out of bounds. Returns self.
797 int index
= IoMessage_locals_intArgAt_(m
, locals
, 0);
798 IoObject
*v
= IoMessage_locals_valueArgAt_(m
, locals
, 1);
800 IoList_checkIndex(self
, m
, 0, index
, "Io List atPut");
801 IoList_rawAtPut(self
, index
, v
);
805 IoObject
*IoList_setSize(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
808 Sets the size of the receiver by either removing excess items or adding nils as needed.
811 List
*list
= DATA(self
);
812 size_t newSize
= IoMessage_locals_sizetArgAt_(m
, locals
, 0);
813 size_t oldSize
= List_size(list
);
815 if(newSize
< oldSize
)
817 List_setSize_(list
, newSize
);
821 size_t i
, max
= newSize
- oldSize
;
822 IoObject
*nilObject
= IONIL(self
);
824 for(i
= 0; i
< max
; i
++)
826 List_append_(list
, nilObject
);
833 IoObject
*IoList_removeAll(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
836 Removes all items from the receiver.
839 List_removeAll(DATA(self
));
843 IoObject
*IoList_swapIndices(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
845 /*doc List swapIndices(index1, index2)
846 Exchanges the object at index1 with the object at index2.
847 Raises an exception if either index is out of bounds. Returns self.
850 int i
= IoMessage_locals_intArgAt_(m
, locals
, 0);
851 int j
= IoMessage_locals_intArgAt_(m
, locals
, 1);
853 IoList_checkIndex(self
, m
, 0, i
, "List swapIndices");
854 IoList_checkIndex(self
, m
, 0, j
, "List swapIndices");
855 List_swap_with_(DATA(self
), i
, j
);
859 IoObject
*IoList_reverse(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
862 Reverses the ordering of all the items in the receiver. Returns self.
865 List_reverse(DATA(self
));
869 IoObject
*IoList_preallocateToSize(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
871 /*doc List preallocateToSize(aNumber)
872 Preallocates array memory to hold aNumber number of items.
875 int newSize
= IoMessage_locals_intArgAt_(m
, locals
, 0);
876 List_preallocateToSize_(DATA(self
), newSize
);
880 // sorting -----------------------------------------------
890 int MSortContext_compareForSort(MSortContext
*self
, int i
, int j
)
892 IoObject
*a
= List_at_(self
->list
, i
);
893 IoObject
*b
= List_at_(self
->list
, j
);
896 IoState_pushRetainPool(self
->state
);
898 a
= IoMessage_locals_performOn_(self
->exp
, self
->locals
, a
);
899 b
= IoMessage_locals_performOn_(self
->exp
, self
->locals
, b
);
900 r
= IoObject_compare(a
, b
);
902 IoState_popRetainPool(self
->state
);
906 void MSortContext_swapForSort(MSortContext
*self
, int i
, int j
)
908 List_swap_with_(self
->list
, i
, j
);
911 IoObject
*IoList_sortInPlace(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
913 /*doc List sortInPlace(optionalExpression)
914 Sorts the list using the compare method on the items. Returns self.
915 If an optionalExpression is provided, the sort is done on the result of the evaluation
916 of the optionalExpression on each value.
919 if (IoMessage_argCount(m
) == 0)
921 List_qsort(DATA(self
), (ListSortCallback
*)IoObject_sortCompare
);
926 MSortContext
*sortContext
= &sc
;
927 sortContext
->state
= IOSTATE
;
929 sortContext
->list
= DATA(self
);
930 sortContext
->locals
= locals
;
931 sortContext
->exp
= IoMessage_rawArgAt_(m
, 0);
933 Sorting_context_comp_swap_size_type_(sortContext
,
934 (SDSortCompareCallback
*)MSortContext_compareForSort
,
935 (SDSortSwapCallback
*)MSortContext_swapForSort
,
936 List_size(DATA(self
)), SDQuickSort
);
954 int SortContext_compareForSort(SortContext
*self
, int i
, int j
)
957 IoState_pushRetainPool(self
->state
);
959 IoMessage_cachedResult_(self
->argMsg1
, LIST_AT_(self
->list
, i
));
960 IoMessage_cachedResult_(self
->argMsg2
, LIST_AT_(self
->list
, j
));
961 cr
= IoBlock_activate(self
->block
, self
->locals
, self
->locals
, self
->blockMsg
, self
->locals
);
962 //cr = IoMessage_locals_performOn_(self->block->message, self->locals, self->locals);
964 IoState_popRetainPool(self
->state
);
965 return ISFALSE(cr
) ? 1 : -1;
968 void SortContext_swapForSort(SortContext
*self
, int i
, int j
)
970 List_swap_with_(self
->list
, i
, j
);
973 IoObject
*IoList_sortInPlaceBy(IoList
*self
, IoObject
*locals
, IoMessage
*m
)
975 /*doc List sortBy(aBlock)
976 Sort the list using aBlock as the compare function. Returns self.
980 SortContext
*sortContext
= &sc
;
981 sortContext
->state
= IOSTATE
;
983 sortContext
->list
= DATA(self
);
984 sortContext
->locals
= locals
;
985 sortContext
->block
= IoMessage_locals_blockArgAt_(m
, locals
, 0);
986 sortContext
->blockMsg
= IoMessage_new(IOSTATE
);
987 sortContext
->argMsg1
= IoMessage_new(IOSTATE
);
988 sortContext
->argMsg2
= IoMessage_new(IOSTATE
);
990 IoMessage_addArg_(sortContext
->blockMsg
, sortContext
->argMsg1
);
991 IoMessage_addArg_(sortContext
->blockMsg
, sortContext
->argMsg2
);
993 Sorting_context_comp_swap_size_type_(sortContext
,
994 (SDSortCompareCallback
*)SortContext_compareForSort
,
995 (SDSortSwapCallback
*)SortContext_swapForSort
,
996 List_size(DATA(self
)), SDQuickSort
);