--- a/Array.st Tue Nov 14 12:18:26 1995 +0100
+++ b/Array.st Tue Nov 14 15:25:25 1995 +0100
@@ -10,33 +10,17 @@
hereby transferred.
"
+'From Smalltalk/X, Version:2.10.8 on 14-nov-1995 at 15:25:17' !
+
ArrayedCollection variableSubclass:#Array
- instanceVariableNames:''
- classVariableNames:''
- poolDictionaries:''
- category:'Collections-Arrayed'
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Collections-Arrayed'
!
!Array class methodsFor:'documentation'!
-copyright
-"
- COPYRIGHT (c) 1989 by Claus Gittinger
- All Rights Reserved
-
- This software is furnished under a license and may be used
- only in accordance with the terms of that license and with the
- inclusion of the above copyright notice. This software may not
- be provided or otherwise made available to, or used by, any
- other person. No title to or ownership of the software is
- hereby transferred.
-"
-!
-
-version
- ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.40 1995-11-11 14:26:37 cg Exp $'
-!
-
documentation
"
Instances of Array store general objects; the arrays size is fixed,
@@ -64,14 +48,24 @@
#('foo' nil true #true)
#('one' two [3 3 3] (4 4 4))
"
-! !
+!
-!Array class methodsFor:'queries'!
+copyright
+"
+ COPYRIGHT (c) 1989 by Claus Gittinger
+ All Rights Reserved
-isBuiltInClass
- "this class is known by the run-time-system"
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
- ^ self == Array
+version
+ ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.41 1995-11-14 14:25:25 cg Exp $'
! !
!Array class methodsFor:'instance creation'!
@@ -230,135 +224,16 @@
^ ObjectMemory allocationFailureSignal raise.
! !
-!Array class ignoredMethodsFor:'instance creation'!
-
-with:one
- "redefined for performance.
- I really dont know, if it is worth it.
- Detailed measurements may show that this can be removed to save some
- space."
-
-%{ /* NOCONTEXT */
- if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) {
- if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(1))) {
- OBJ newArray;
-
- _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(1));
- _InstPtr(newArray)->o_class = self;
- _ArrayInstPtr(newArray)->a_element[0] = one;
- __qSTORE(newArray, self);
- __STORE(newArray, one);
- return newArray;
- }
- }
-%}.
- ^ super with:one
-!
-
-with:one with:two
- "redefined for performance.
- I really dont know, if it is worth it.
- Detailed measurements may show that this can be removed to save some
- space."
-
-%{ /* NOCONTEXT */
- if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) {
- if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(2))) {
- OBJ newArray;
-
- _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(2));
- _InstPtr(newArray)->o_class = self;
- _ArrayInstPtr(newArray)->a_element[0] = one;
- _ArrayInstPtr(newArray)->a_element[1] = two;
- __qSTORE(newArray, self);
- __STORE(newArray, one);
- __STORE(newArray, two);
- return newArray;
- }
- }
-%}.
- ^ super with:one with:two
-!
+!Array class methodsFor:'queries'!
-with:one with:two with:three
- "redefined for performance.
- I really dont know, if it is worth it.
- Detailed measurements may show that this can be removed to save some
- space."
-
-%{ /* NOCONTEXT */
- if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) {
- if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(3))) {
- OBJ newArray;
-
- _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(3));
- _InstPtr(newArray)->o_class = self;
- _ArrayInstPtr(newArray)->a_element[0] = one;
- _ArrayInstPtr(newArray)->a_element[1] = two;
- _ArrayInstPtr(newArray)->a_element[2] = three;
- __qSTORE(newArray, self);
- __STORE(newArray, one);
- __STORE(newArray, two);
- __STORE(newArray, three);
- return newArray;
- }
- }
-%}.
- ^ super with:one with:two with:three
-!
+isBuiltInClass
+ "this class is known by the run-time-system"
-with:one with:two with:three with:four
- "redefined for performance.
- I really dont know, if it is worth it.
- Detailed measurements may show that this can be removed to save some
- space."
-
-%{ /* NOCONTEXT */
- if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) {
- if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(4))) {
- OBJ newArray;
-
- _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(4));
- _InstPtr(newArray)->o_class = self;
- _ArrayInstPtr(newArray)->a_element[0] = one;
- _ArrayInstPtr(newArray)->a_element[1] = two;
- _ArrayInstPtr(newArray)->a_element[2] = three;
- _ArrayInstPtr(newArray)->a_element[3] = four;
- __qSTORE(newArray, self);
- __STORE(newArray, one);
- __STORE(newArray, two);
- __STORE(newArray, three);
- __STORE(newArray, four);
- return newArray;
- }
- }
-%}.
- ^ super with:one with:two with:three with:four
+ ^ self == Array
! !
!Array methodsFor:'accessing'!
-basicSize
- "return the number of indexed elements in the receiver"
-
-%{ /* NOCONTEXT */
-
- RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
-%}
-!
-
-size
- "return the number of indexed elements in the receiver.
- Reimplemented here to avoid the additional size->basicSize send
- (which we can do here, since size is obviously not redefined in a subclass).
- This method is the same as basicSize."
-
-%{ /* NOCONTEXT */
-
- RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
-%}
-!
-
basicAt:index
"return the indexed instance variable with index, anInteger
- added here for speed"
@@ -385,6 +260,47 @@
^ super basicAt:index
!
+at:index put:anObject
+ "store the 2nd arg, anObject as indexed instvar with index, anInteger.
+ Reimplemented here to avoid the additional at:put:->basicAt:put: send
+ (which we can do here, since at: is obviously not redefined in a subclass).
+ This method is the same as at:."
+
+%{ /* NOCONTEXT */
+
+ REGISTER int indx;
+ REGISTER unsigned int nIndex;
+ OBJ cls;
+
+ if (__isSmallInteger(index)) {
+ indx = _intVal(index) - 1;
+ if (indx >= 0) {
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ if ((cls = __qClass(self)) != Array)
+ indx += _intVal(_ClassInstPtr(cls)->c_ninstvars);
+ if (indx < nIndex) {
+ _InstPtr(self)->i_instvars[indx] = anObject;
+ __STORE(self, anObject);
+ RETURN ( anObject );
+ }
+ }
+ }
+%}.
+ ^ super at:index put:anObject
+!
+
+size
+ "return the number of indexed elements in the receiver.
+ Reimplemented here to avoid the additional size->basicSize send
+ (which we can do here, since size is obviously not redefined in a subclass).
+ This method is the same as basicSize."
+
+%{ /* NOCONTEXT */
+
+ RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
+%}
+!
+
at:index
"return the indexed instance variable with index, anInteger.
Reimplemented here to avoid the additional at:->basicAt: send
@@ -440,33 +356,13 @@
^ super basicAt:index put:anObject
!
-at:index put:anObject
- "store the 2nd arg, anObject as indexed instvar with index, anInteger.
- Reimplemented here to avoid the additional at:put:->basicAt:put: send
- (which we can do here, since at: is obviously not redefined in a subclass).
- This method is the same as at:."
+basicSize
+ "return the number of indexed elements in the receiver"
%{ /* NOCONTEXT */
- REGISTER int indx;
- REGISTER unsigned int nIndex;
- OBJ cls;
-
- if (__isSmallInteger(index)) {
- indx = _intVal(index) - 1;
- if (indx >= 0) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- if ((cls = __qClass(self)) != Array)
- indx += _intVal(_ClassInstPtr(cls)->c_ninstvars);
- if (indx < nIndex) {
- _InstPtr(self)->i_instvars[indx] = anObject;
- __STORE(self, anObject);
- RETURN ( anObject );
- }
- }
- }
-%}.
- ^ super at:index put:anObject
+ RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
+%}
! !
!Array methodsFor:'converting'!
@@ -555,542 +451,6 @@
^ super copyWith:something
! !
-!Array ignoredMethodsFor:'filling & replacing'!
-
-atAllPut:anObject
- "reimplemented for speed if receiver is an Array"
-
-%{ /* NOCONTEXT */
-
- unsigned int nIndex;
- REGISTER OBJ *dst;
-
- if (__qClass(self) == Array) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- dst = __ArrayInstPtr(self)->a_element;
-#ifdef memset4
- memset4(dst, anObject, nIndex);
- __STORE(self, anObject);
-#else
- if ((INT)anObject == 0) {
- memset(dst, 0, __OBJS2BYTES__(nIndex));
- } else {
-#ifdef UNROLL_LOOPS
- while (nIndex >= 8) {
- dst[0] = anObject;
- dst[1] = anObject;
- dst[2] = anObject;
- dst[3] = anObject;
- dst[4] = anObject;
- dst[5] = anObject;
- dst[6] = anObject;
- dst[7] = anObject;
- dst += 8;
- nIndex -= 8;
- }
-#endif
- for (; nIndex; nIndex--) {
- *dst++ = anObject;
- }
- __STORE(self, anObject);
- }
-#endif
- RETURN ( self );
- }
-%}.
- ^ super atAllPut:anObject
-! !
-
-!Array methodsFor:'filling & replacing'!
-
-from:index1 to:index2 put:anObject
- "reimplemented for speed if receiver is an Array"
-
-%{ /* NOCONTEXT */
-
- REGISTER int index;
- unsigned int nIndex;
- unsigned int endIndex;
- REGISTER OBJ *dst;
-
- if ((__qClass(self) == Array)
- && __bothSmallInteger(index1, index2)) {
- index = _intVal(index1) - 1;
- if (index >= 0) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- endIndex = _intVal(index2) - 1;
- if (endIndex < nIndex) {
- dst = &(_InstPtr(self)->i_instvars[index]);
-#ifdef memset4
- memset4(dst, anObject, (endIndex-index+1));
- __STORE(self, anObject);
-#else
- if ((INT)anObject == 0) {
- memset(dst, 0, __OBJS2BYTES__(endIndex-index+1));
- } else {
-#if defined(UNROLL_LOOPS)
- {
- int i8;
-
- while ((i8 = index + 8) <= endIndex) {
- dst[0] = anObject;
- dst[1] = anObject;
- dst[2] = anObject;
- dst[3] = anObject;
- dst[4] = anObject;
- dst[5] = anObject;
- dst[6] = anObject;
- dst[7] = anObject;
- dst += 8;
- index = i8;
- }
- }
-#endif
- for (; index <= endIndex; index++) {
- *dst++ = anObject;
- }
- __STORE(self, anObject);
- }
-#endif
- RETURN ( self );
- }
- }
- }
-%}
-.
- ^ super from:index1 to:index2 put:anObject
-!
-
-replaceFrom:start to:stop with:aCollection startingAt:repStart
- "reimplemented for speed if both receiver and aCollection are Arrays"
-
-%{ /* NOCONTEXT */
-
- unsigned int nIndex;
- unsigned int repNIndex;
- int startIndex, stopIndex;
- REGISTER OBJ *src;
- REGISTER OBJ *dst;
- int repStopIndex;
- REGISTER int repStartIndex;
- REGISTER OBJ t;
- REGISTER int count;
-
-
- if ((_ClassInstPtr(__qClass(self))->c_ninstvars == __MKSMALLINT(0))
- && (((t = __Class(aCollection)) == Array) || (t == __qClass(self)))
- && __bothSmallInteger(start, stop)
- && __isSmallInteger(repStart)) {
- startIndex = _intVal(start) - 1;
- if (startIndex >= 0) {
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- stopIndex = _intVal(stop) - 1;
- count = stopIndex - startIndex + 1;
- if (count == 0) {
- RETURN ( self );
- }
- if ((count > 0) && (stopIndex < nIndex)) {
- repStartIndex = _intVal(repStart) - 1;
- if (repStartIndex >= 0) {
- repNIndex = __BYTES2OBJS__(__qSize(aCollection)-OHDR_SIZE);
- repStopIndex = repStartIndex + (stopIndex - startIndex);
- if (repStopIndex < repNIndex) {
- src = &(_InstPtr(aCollection)->i_instvars[repStartIndex]);
- dst = &(_InstPtr(self)->i_instvars[startIndex]);
- if (aCollection == self) {
- /*
- * no need to check stores if copying
- * from myself
- */
- /*
- * take care of overlapping copy
- * do not depend on memset being smart enough
- * (some are not ;-)
- */
- if (src < dst) {
- /* must do a reverse copy */
- src += count;
- dst += count;
-#if defined(UNROLL_LOOPS)
- while (count > 8) {
- dst[-1] = src[-1];
- dst[-2] = src[-2];
- dst[-3] = src[-3];
- dst[-4] = src[-4];
- dst[-5] = src[-5];
- dst[-6] = src[-6];
- dst[-7] = src[-7];
- dst[-8] = src[-8];
- dst -= 8; src -= 8;
- count -= 8;
- }
-#endif
- while (count-- > 0) {
- *--dst = *--src;
- }
- RETURN ( self );
- }
-#ifdef bcopy4
- bcopy4(src, dst, count);
-#else
-# ifdef FAST_MEMCPY
- bcopy(src, dst, __OBJS2BYTES__(count));
-# else
- while (count--) {
- *dst++ = *src++;
- }
-# endif
-#endif
- } else {
- REGISTER int spc;
-
- spc = __qSpace(self);
-#if defined(UNROLL_LOOPS)
- while (count >= 4) {
- t = src[0]; dst[0] = t; __STORE_SPC(self, t, spc);
- t = src[1]; dst[1] = t; __STORE_SPC(self, t, spc);
- t = src[2]; dst[2] = t; __STORE_SPC(self, t, spc);
- t = src[3]; dst[3] = t; __STORE_SPC(self, t, spc);
- count -= 4; src += 4; dst += 4;
- }
-#endif
- while (count-- > 0) {
- t = *src++;
- *dst++ = t;
- __STORE_SPC(self, t, spc);
- }
- }
- RETURN ( self );
- }
- }
- }
- }
- }
-%}.
- ^ super replaceFrom:start to:stop with:aCollection startingAt:repStart
-! !
-
-!Array methodsFor:'queries'!
-
-isArray
- "return true, if the receiver is some kind of array (or weakArray etc).
- true is returned here"
-
- ^ true
-!
-
-isLiteral
- "return true, if the receiver can be used as a literal
- (i.e. can be used in constant arrays)"
-
- "no, subclasses of array are not"
- self class == Array ifFalse:[^ false].
-
- thisContext isRecursive ifTrue:[^ false].
-
- self do:[:element |
- element isLiteral ifFalse:[^ false]
- ].
- ^ true
-!
-
-refersToLiteral: aLiteral
- self do: [ :el |
- el == aLiteral ifTrue:[^true].
- el class == Array ifTrue:[
- (el refersToLiteral: aLiteral) ifTrue: [^true]
- ]
- ].
- ^ false
-
- "
- #(1 2 3) refersToLiteral:#foo
- #(1 2 3 foo bar baz) refersToLiteral:#foo
- #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo
- "
-! !
-
-!Array methodsFor:'testing'!
-
-includes:anObject
- "return true, if the argument, anObject is contained in the array
- - reimplemented for speed"
-
- |element|
-
-%{ /* NOCONTEXT */
-
- /*
- * first, do a quick check using ==
- * this does not need a context or message send.
- * In many cases this will already find a match.
- */
- REGISTER int index;
- REGISTER OBJ o;
- unsigned int nIndex;
-
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
-
- /*
- * however, the search is limited to the first 1000
- * elements, since otherwise, we may spend too much time
- * searching for identity if an equal value is found early
- */
- if (nIndex > 1000) nIndex = 1000;
-
- o = anObject;
-#if defined(UNROLL_LOOPS)
- {
- unsigned int i8;
-
- while ((i8 = index + 8) < nIndex) {
- if (_InstPtr(self)->i_instvars[index] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+1] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+2] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+3] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+4] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+5] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+6] == o) { RETURN ( true ); }
- if (_InstPtr(self)->i_instvars[index+7] == o) { RETURN ( true ); }
- index = i8;
- }
- }
-#endif
- while (index < nIndex) {
- if (_InstPtr(self)->i_instvars[index++] == o) {
- RETURN ( true );
- }
- }
- if (o == nil) {
- RETURN ( false );
- }
-%}
-.
-%{
- /*
- * then do a slow(er) check using =
- */
- REGISTER int index;
- unsigned int nIndex;
- static struct inlineCache eq = _ILC1;
-
- /*
- * sorry: cannot access the stuff from above ...
- */
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
-
- while (index < nIndex) {
- element = _InstPtr(self)->i_instvars[index++];
- if (element != nil) {
- if ((*eq.ilc_func)(anObject,
- @symbol(=),
- CON_COMMA nil,&eq,
- element)==true) {
- RETURN ( true );
- }
- }
- }
-%}.
- ^ false
-!
-
-indexOf:anElement startingAt:start
- "search the array for anElement; return index if found, 0 otherwise
- - reimplemented for speed"
-
- |element|
-%{
- REGISTER int index;
- unsigned int nIndex, nInsts;
- static struct inlineCache eq = _ILC1;
-
- if (__isSmallInteger(start)) {
- index = _intVal(start) - 1;
- if (index >= 0) {
- nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
- index += nInsts;
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- if (anElement != nil) {
- while (index < nIndex) {
- element = _InstPtr(self)->i_instvars[index++];
- if (element != nil) {
- if ((element == anElement)
- || ((*eq.ilc_func)(anElement,
- @symbol(=),
- CON_COMMA nil,&eq,
- element) == true)) {
- RETURN ( __MKSMALLINT(index - nInsts) );
- }
- }
- }
- } else {
- /* search for nil */
-#if defined(UNROLL_LOOPS)
- {
- unsigned int i8;
-
- while ((i8 = index + 8) < nIndex) {
- if (_InstPtr(self)->i_instvars[index] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 1) ); }
- if (_InstPtr(self)->i_instvars[index+1] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 2) ); }
- if (_InstPtr(self)->i_instvars[index+2] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 3) ); }
- if (_InstPtr(self)->i_instvars[index+3] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 4) ); }
- if (_InstPtr(self)->i_instvars[index+4] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 5) ); }
- if (_InstPtr(self)->i_instvars[index+5] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 6) ); }
- if (_InstPtr(self)->i_instvars[index+6] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 7) ); }
- if (_InstPtr(self)->i_instvars[index+7] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 8) ); }
- index = i8;
- }
- }
-#endif
-
- while (index < nIndex) {
- if (_InstPtr(self)->i_instvars[index++] == nil) {
- RETURN ( __MKSMALLINT(index - nInsts) );
- }
- }
- }
- }
- }
-%}.
- ^ 0
-!
-
-identityIndexOf:anElement startingAt:start
- "search the array for anElement; return index if found, 0 otherwise
- - reimplemented for speed"
-
-%{ /* NOCONTEXT */
-
- REGISTER int index;
- REGISTER OBJ el;
- REGISTER OBJ *op;
- REGISTER unsigned int nIndex;
- int nInsts;
-
- if (__isSmallInteger(start)) {
- index = _intVal(start) - 1;
- if (index >= 0) {
- nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
- index += nInsts;
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- el = anElement;
- op = & (_InstPtr(self)->i_instvars[index]);
-#if defined(UNROLL_LOOPS)
- {
- unsigned int i8;
-
- while ((i8 = index + 8) < nIndex) {
- if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
- if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
- if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
- if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
- if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
- if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
- if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
- if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
- index = i8;
- op += 8;
- }
- }
-#endif
- while (index++ < nIndex) {
- if (*op++ == el) {
- RETURN ( __MKSMALLINT(index - nInsts) );
- }
- }
- RETURN ( __MKSMALLINT(0) );
- }
- }
-%}.
- ^ super identityIndexOf:anElement startingAt:start
-!
-
-identityIndexOf:anElement or:alternative
- "search the array for anElement or alternative;
- return the index of anElement if found, or the index of anAlternative,
- if not found. If anAlternative is also not found, return 0.
- This is a special interface for high-speed searching in an array
- and at the same time searching for an empty slot.
- Do not use this method for your application classes, since it is
- not portable (i.e. other smalltalks do not offer this)"
-
-%{ /* NOCONTEXT */
-
- REGISTER int index;
- REGISTER OBJ o, el1, el2;
- REGISTER OBJ *op;
- REGISTER unsigned int nIndex;
- int altIndex = 0;
- int nInsts;
-
- index = 0;
- nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
- index += nInsts;
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
- el1 = anElement; el2 = alternative;
- op = & (_InstPtr(self)->i_instvars[index]);
- while (index++ < nIndex) {
- if ((o = *op++) == el1) {
- RETURN ( __MKSMALLINT(index - nInsts) );
- }
- if (o == el2) {
- if (altIndex == 0) {
- altIndex = index;
- }
- }
- }
- RETURN ( __MKSMALLINT(altIndex) );
-%}
-
- "
- #(1 2 3 4 5 6 7 8 9) identityIndexOf:3 or:5
- #(1 2 0 4 5 6 7 8 9) identityIndexOf:3 or:5
- #(1 2 0 4 5 6 7 3 9) identityIndexOf:3 or:5
- #(1 2 3 4 5 nil 7 3 9) identityIndexOf:3 or:nil
- #(1 2 nil 4 5 6 7 3 9) identityIndexOf:3 or:nil
- #(1 2 nil 4 5 6 7 8 9) identityIndexOf:3 or:nil
- #() identityIndexOf:3 or:nil
- #(1 2) identityIndexOf:3 or:nil
- "
-! !
-
-!Array methodsFor:'printing & storing'!
-
-displayString
- "return a printed representation of the receiver for displaying"
-
- |s|
-
- (self isLiteral) ifTrue:[
- s := WriteStream on:String new.
- s nextPutAll:'#('.
- self do:[:element | s nextPutAll:element displayString. s space].
- s nextPutAll:')'.
- ^ s contents
- ].
- ^ super displayString
-!
-
-storeOn:aStream
- "append a printed representation of the receiver to aStream,
- which allows reconstructing it via readFrom:.
- Redefined to output a somewhat more user friendly string."
-
- self isLiteral ifTrue:[
- aStream nextPutAll:'#('.
- self do:[:element | element storeOn:aStream. aStream space].
- aStream nextPutAll:')'
- ] ifFalse:[
- super storeOn:aStream
- ]
-
- "
- #(1 2 $a 'hello') storeString
- "
-! !
-
!Array methodsFor:'enumerating'!
do:aBlock
@@ -1236,50 +596,6 @@
^ self
!
-reverseDo:aBlock
- "evaluate the argument, aBlock for each element in the collection in reverse order.
- - reimplemented for speed"
-
- |home|
-%{
- REGISTER OBJFUNC codeVal;
- REGISTER int index;
- unsigned int nIndex;
- int endIndex;
- extern OBJ Block;
- static struct inlineCache val = _ILC1;
-
- endIndex = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
- nIndex = __arraySize(self);
-
- if (__isBlockLike(aBlock)
- && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
- && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
-#ifdef NEW_BLOCK_CALL
- for (index=nIndex-1; index >= endIndex; index--) {
- if (InterruptPending != nil) __interruptL(@line COMMA_CON);
- (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]);
- }
-#else
- home = _BlockInstPtr(aBlock)->b_home;
- for (index=nIndex-1; index >= endIndex; index--) {
- if (InterruptPending != nil) __interruptL(@line COMMA_CON);
- (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]);
- }
-#endif
- } else {
- for (index=nIndex-1; index >= endIndex; index--) {
- if (InterruptPending != nil) __interruptL(@line COMMA_CON);
- (*val.ilc_func)(aBlock,
- @symbol(value:),
- CON_COMMA nil, &val,
- _InstPtr(self)->i_instvars[index]);
- }
- }
-%}.
- ^ self
-!
-
from:start to:stop do:aBlock
"evaluate the argument, aBlock for the elements starting at index start
up to (and including) stop in the collection.
@@ -1367,6 +683,73 @@
^ super from:start to:stop do:aBlock
!
+nonNilElementsDo:aBlock
+ "evaluate the argument, aBlock for each non-nil element"
+
+ |home|
+%{
+ REGISTER OBJFUNC codeVal;
+ REGISTER int index;
+ int nIndex;
+ extern OBJ Block;
+ static struct inlineCache val = _ILC1;
+ REGISTER OBJ rHome;
+ REGISTER OBJ element;
+
+ index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ if (__isBlockLike(aBlock)
+ && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
+ && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
+#ifdef NEW_BLOCK_CALL
+ for (; index < nIndex; index++) {
+ if (InterruptPending != nil) __interruptL(CONARG);
+
+ element = _InstPtr(self)->i_instvars[index];
+ if (element != nil)
+ (*codeVal)(aBlock, CON_COMMA element);
+ }
+#else
+ home = _BlockInstPtr(aBlock)->b_home;
+ rHome = home;
+ if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
+ /*
+ * home will not move - keep in in a register
+ */
+ for (; index < nIndex; index++) {
+ if (InterruptPending != nil) __interruptL(CONARG);
+
+ element = _InstPtr(self)->i_instvars[index];
+ if (element != nil)
+ (*codeVal)(rHome, CON_COMMA element);
+ }
+ } else {
+ for (; index < nIndex; index++) {
+ if (InterruptPending != nil) __interruptL(@line CONARG);
+
+ element = _InstPtr(self)->i_instvars[index];
+ if (element != nil)
+ (*codeVal)(home, CON_COMMA element);
+ }
+ }
+#endif
+ } else {
+ for (; index < nIndex; index++) {
+ if (InterruptPending != nil) __interruptL(@line CONARG);
+
+ element = _InstPtr(self)->i_instvars[index];
+ if (element != nil)
+ (*val.ilc_func)(aBlock,
+ @symbol(value:),
+ CON_COMMA nil, &val,
+ element);
+ }
+ }
+%}
+.
+ ^ self
+!
+
from:start to:stop reverseDo:aBlock
"evaluate the argument, aBlock for the elements starting at index start
up to (and including) stop in the collection. Step in reverse order.
@@ -1436,73 +819,63 @@
^ super from:start to:stop reverseDo:aBlock
!
-nonNilElementsDo:aBlock
- "evaluate the argument, aBlock for each non-nil element"
+reverseDo:aBlock
+ "evaluate the argument, aBlock for each element in the collection in reverse order.
+ - reimplemented for speed"
|home|
%{
REGISTER OBJFUNC codeVal;
REGISTER int index;
- int nIndex;
+ unsigned int nIndex;
+ int endIndex;
extern OBJ Block;
static struct inlineCache val = _ILC1;
- REGISTER OBJ rHome;
- REGISTER OBJ element;
- index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
- nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ endIndex = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+ nIndex = __arraySize(self);
+
if (__isBlockLike(aBlock)
&& ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
&& (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
#ifdef NEW_BLOCK_CALL
- for (; index < nIndex; index++) {
- if (InterruptPending != nil) __interruptL(CONARG);
-
- element = _InstPtr(self)->i_instvars[index];
- if (element != nil)
- (*codeVal)(aBlock, CON_COMMA element);
+ for (index=nIndex-1; index >= endIndex; index--) {
+ if (InterruptPending != nil) __interruptL(@line COMMA_CON);
+ (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]);
}
#else
home = _BlockInstPtr(aBlock)->b_home;
- rHome = home;
- if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
- /*
- * home will not move - keep in in a register
- */
- for (; index < nIndex; index++) {
- if (InterruptPending != nil) __interruptL(CONARG);
-
- element = _InstPtr(self)->i_instvars[index];
- if (element != nil)
- (*codeVal)(rHome, CON_COMMA element);
- }
- } else {
- for (; index < nIndex; index++) {
- if (InterruptPending != nil) __interruptL(@line CONARG);
-
- element = _InstPtr(self)->i_instvars[index];
- if (element != nil)
- (*codeVal)(home, CON_COMMA element);
- }
+ for (index=nIndex-1; index >= endIndex; index--) {
+ if (InterruptPending != nil) __interruptL(@line COMMA_CON);
+ (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]);
}
#endif
} else {
- for (; index < nIndex; index++) {
- if (InterruptPending != nil) __interruptL(@line CONARG);
-
- element = _InstPtr(self)->i_instvars[index];
- if (element != nil)
- (*val.ilc_func)(aBlock,
- @symbol(value:),
- CON_COMMA nil, &val,
- element);
+ for (index=nIndex-1; index >= endIndex; index--) {
+ if (InterruptPending != nil) __interruptL(@line COMMA_CON);
+ (*val.ilc_func)(aBlock,
+ @symbol(value:),
+ CON_COMMA nil, &val,
+ _InstPtr(self)->i_instvars[index]);
}
}
-%}
-.
+%}.
^ self
!
+addAllTo:aCollection
+ "add all elements of the receiver to aCollection.
+ return aCollection."
+
+ |stop "{ Class: SmallInteger }"|
+
+ stop := self size.
+ 1 to:stop do:[:idx |
+ aCollection add:(self at:idx)
+ ].
+ ^ aCollection
+!
+
traverse:aBlock
"Evaluate aBlock for every element that is not an Array,
and traverse Arrays.
@@ -1525,17 +898,495 @@
#(1 2 (3 (4 5 (6 7) 8) 9 10) 11 (12 (13)) 14) traverse:[:el | s nextPut:el].
s contents
"
+! !
+
+!Array methodsFor:'filling & replacing'!
+
+replaceFrom:start to:stop with:aCollection startingAt:repStart
+ "reimplemented for speed if both receiver and aCollection are Arrays"
+
+%{ /* NOCONTEXT */
+
+ unsigned int nIndex;
+ unsigned int repNIndex;
+ int startIndex, stopIndex;
+ REGISTER OBJ *src;
+ REGISTER OBJ *dst;
+ int repStopIndex;
+ REGISTER int repStartIndex;
+ REGISTER OBJ t;
+ REGISTER int count;
+
+
+ if ((_ClassInstPtr(__qClass(self))->c_ninstvars == __MKSMALLINT(0))
+ && (((t = __Class(aCollection)) == Array) || (t == __qClass(self)))
+ && __bothSmallInteger(start, stop)
+ && __isSmallInteger(repStart)) {
+ startIndex = _intVal(start) - 1;
+ if (startIndex >= 0) {
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ stopIndex = _intVal(stop) - 1;
+ count = stopIndex - startIndex + 1;
+ if (count == 0) {
+ RETURN ( self );
+ }
+ if ((count > 0) && (stopIndex < nIndex)) {
+ repStartIndex = _intVal(repStart) - 1;
+ if (repStartIndex >= 0) {
+ repNIndex = __BYTES2OBJS__(__qSize(aCollection)-OHDR_SIZE);
+ repStopIndex = repStartIndex + (stopIndex - startIndex);
+ if (repStopIndex < repNIndex) {
+ src = &(_InstPtr(aCollection)->i_instvars[repStartIndex]);
+ dst = &(_InstPtr(self)->i_instvars[startIndex]);
+ if (aCollection == self) {
+ /*
+ * no need to check stores if copying
+ * from myself
+ */
+ /*
+ * take care of overlapping copy
+ * do not depend on memset being smart enough
+ * (some are not ;-)
+ */
+ if (src < dst) {
+ /* must do a reverse copy */
+ src += count;
+ dst += count;
+#if defined(UNROLL_LOOPS)
+ while (count > 8) {
+ dst[-1] = src[-1];
+ dst[-2] = src[-2];
+ dst[-3] = src[-3];
+ dst[-4] = src[-4];
+ dst[-5] = src[-5];
+ dst[-6] = src[-6];
+ dst[-7] = src[-7];
+ dst[-8] = src[-8];
+ dst -= 8; src -= 8;
+ count -= 8;
+ }
+#endif
+ while (count-- > 0) {
+ *--dst = *--src;
+ }
+ RETURN ( self );
+ }
+#ifdef bcopy4
+ bcopy4(src, dst, count);
+#else
+# ifdef FAST_MEMCPY
+ bcopy(src, dst, __OBJS2BYTES__(count));
+# else
+ while (count--) {
+ *dst++ = *src++;
+ }
+# endif
+#endif
+ } else {
+ REGISTER int spc;
+
+ spc = __qSpace(self);
+#if defined(UNROLL_LOOPS)
+ while (count >= 4) {
+ t = src[0]; dst[0] = t; __STORE_SPC(self, t, spc);
+ t = src[1]; dst[1] = t; __STORE_SPC(self, t, spc);
+ t = src[2]; dst[2] = t; __STORE_SPC(self, t, spc);
+ t = src[3]; dst[3] = t; __STORE_SPC(self, t, spc);
+ count -= 4; src += 4; dst += 4;
+ }
+#endif
+ while (count-- > 0) {
+ t = *src++;
+ *dst++ = t;
+ __STORE_SPC(self, t, spc);
+ }
+ }
+ RETURN ( self );
+ }
+ }
+ }
+ }
+ }
+%}.
+ ^ super replaceFrom:start to:stop with:aCollection startingAt:repStart
+!
+
+from:index1 to:index2 put:anObject
+ "reimplemented for speed if receiver is an Array"
+
+%{ /* NOCONTEXT */
+
+ REGISTER int index;
+ unsigned int nIndex;
+ unsigned int endIndex;
+ REGISTER OBJ *dst;
+
+ if ((__qClass(self) == Array)
+ && __bothSmallInteger(index1, index2)) {
+ index = _intVal(index1) - 1;
+ if (index >= 0) {
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ endIndex = _intVal(index2) - 1;
+ if (endIndex < nIndex) {
+ dst = &(_InstPtr(self)->i_instvars[index]);
+#ifdef memset4
+ memset4(dst, anObject, (endIndex-index+1));
+ __STORE(self, anObject);
+#else
+ if ((INT)anObject == 0) {
+ memset(dst, 0, __OBJS2BYTES__(endIndex-index+1));
+ } else {
+#if defined(UNROLL_LOOPS)
+ {
+ int i8;
+
+ while ((i8 = index + 8) <= endIndex) {
+ dst[0] = anObject;
+ dst[1] = anObject;
+ dst[2] = anObject;
+ dst[3] = anObject;
+ dst[4] = anObject;
+ dst[5] = anObject;
+ dst[6] = anObject;
+ dst[7] = anObject;
+ dst += 8;
+ index = i8;
+ }
+ }
+#endif
+ for (; index <= endIndex; index++) {
+ *dst++ = anObject;
+ }
+ __STORE(self, anObject);
+ }
+#endif
+ RETURN ( self );
+ }
+ }
+ }
+%}
+.
+ ^ super from:index1 to:index2 put:anObject
+! !
+
+!Array methodsFor:'printing & storing'!
+
+displayString
+ "return a printed representation of the receiver for displaying"
+
+ |s|
+
+ (self isLiteral) ifTrue:[
+ s := WriteStream on:String new.
+ s nextPutAll:'#('.
+ self do:[:element | s nextPutAll:element displayString. s space].
+ s nextPutAll:')'.
+ ^ s contents
+ ].
+ ^ super displayString
+!
+
+storeOn:aStream
+ "append a printed representation of the receiver to aStream,
+ which allows reconstructing it via readFrom:.
+ Redefined to output a somewhat more user friendly string."
+
+ self isLiteral ifTrue:[
+ aStream nextPutAll:'#('.
+ self do:[:element | element storeOn:aStream. aStream space].
+ aStream nextPutAll:')'
+ ] ifFalse:[
+ super storeOn:aStream
+ ]
+
+ "
+ #(1 2 $a 'hello') storeString
+ "
+! !
+
+!Array methodsFor:'queries'!
+
+isArray
+ "return true, if the receiver is some kind of array (or weakArray etc).
+ true is returned here"
+
+ ^ true
+!
+
+isLiteral
+ "return true, if the receiver can be used as a literal
+ (i.e. can be used in constant arrays)"
+
+ "no, subclasses of array are not"
+ self class == Array ifFalse:[^ false].
+
+ thisContext isRecursive ifTrue:[^ false].
+
+ self do:[:element |
+ element isLiteral ifFalse:[^ false]
+ ].
+ ^ true
!
-addAllTo:aCollection
- "add all elements of the receiver to aCollection.
- return aCollection."
+refersToLiteral: aLiteral
+ self do: [ :el |
+ el == aLiteral ifTrue:[^true].
+ el class == Array ifTrue:[
+ (el refersToLiteral: aLiteral) ifTrue: [^true]
+ ]
+ ].
+ ^ false
+
+ "
+ #(1 2 3) refersToLiteral:#foo
+ #(1 2 3 foo bar baz) refersToLiteral:#foo
+ #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo
+ "
+! !
+
+!Array methodsFor:'testing'!
+
+identityIndexOf:anElement startingAt:start
+ "search the array for anElement; return index if found, 0 otherwise
+ - reimplemented for speed"
+
+%{ /* NOCONTEXT */
+
+ REGISTER int index;
+ REGISTER OBJ el;
+ REGISTER OBJ *op;
+ REGISTER unsigned int nIndex;
+ int nInsts;
+
+ if (__isSmallInteger(start)) {
+ index = _intVal(start) - 1;
+ if (index >= 0) {
+ nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+ index += nInsts;
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ el = anElement;
+ op = & (_InstPtr(self)->i_instvars[index]);
+#if defined(UNROLL_LOOPS)
+ {
+ unsigned int i8;
- |stop "{ Class: SmallInteger }"|
+ while ((i8 = index + 8) < nIndex) {
+ if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
+ if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
+ if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
+ if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
+ if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
+ if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
+ if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
+ if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
+ index = i8;
+ op += 8;
+ }
+ }
+#endif
+ while (index++ < nIndex) {
+ if (*op++ == el) {
+ RETURN ( __MKSMALLINT(index - nInsts) );
+ }
+ }
+ RETURN ( __MKSMALLINT(0) );
+ }
+ }
+%}.
+ ^ super identityIndexOf:anElement startingAt:start
+!
+
+includes:anObject
+ "return true, if the argument, anObject is contained in the array
+ - reimplemented for speed"
+
+ |element|
+
+%{ /* NOCONTEXT */
+
+ /*
+ * first, do a quick check using ==
+ * this does not need a context or message send.
+ * In many cases this will already find a match.
+ */
+ REGISTER int index;
+ REGISTER OBJ o;
+ unsigned int nIndex;
+
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+
+ /*
+ * however, the search is limited to the first 1000
+ * elements, since otherwise, we may spend too much time
+ * searching for identity if an equal value is found early
+ */
+ if (nIndex > 1000) nIndex = 1000;
+
+ o = anObject;
+#if defined(UNROLL_LOOPS)
+ {
+ unsigned int i8;
+
+ while ((i8 = index + 8) < nIndex) {
+ if (_InstPtr(self)->i_instvars[index] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+1] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+2] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+3] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+4] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+5] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+6] == o) { RETURN ( true ); }
+ if (_InstPtr(self)->i_instvars[index+7] == o) { RETURN ( true ); }
+ index = i8;
+ }
+ }
+#endif
+ while (index < nIndex) {
+ if (_InstPtr(self)->i_instvars[index++] == o) {
+ RETURN ( true );
+ }
+ }
+ if (o == nil) {
+ RETURN ( false );
+ }
+%}
+.
+%{
+ /*
+ * then do a slow(er) check using =
+ */
+ REGISTER int index;
+ unsigned int nIndex;
+ static struct inlineCache eq = _ILC1;
- stop := self size.
- 1 to:stop do:[:idx |
- aCollection add:(self at:idx)
- ].
- ^ aCollection
+ /*
+ * sorry: cannot access the stuff from above ...
+ */
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+
+ while (index < nIndex) {
+ element = _InstPtr(self)->i_instvars[index++];
+ if (element != nil) {
+ if ((*eq.ilc_func)(anObject,
+ @symbol(=),
+ CON_COMMA nil,&eq,
+ element)==true) {
+ RETURN ( true );
+ }
+ }
+ }
+%}.
+ ^ false
+!
+
+indexOf:anElement startingAt:start
+ "search the array for anElement; return index if found, 0 otherwise
+ - reimplemented for speed"
+
+ |element|
+%{
+ REGISTER int index;
+ unsigned int nIndex, nInsts;
+ static struct inlineCache eq = _ILC1;
+
+ if (__isSmallInteger(start)) {
+ index = _intVal(start) - 1;
+ if (index >= 0) {
+ nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+ index += nInsts;
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ if (anElement != nil) {
+ while (index < nIndex) {
+ element = _InstPtr(self)->i_instvars[index++];
+ if (element != nil) {
+ if ((element == anElement)
+ || ((*eq.ilc_func)(anElement,
+ @symbol(=),
+ CON_COMMA nil,&eq,
+ element) == true)) {
+ RETURN ( __MKSMALLINT(index - nInsts) );
+ }
+ }
+ }
+ } else {
+ /* search for nil */
+#if defined(UNROLL_LOOPS)
+ {
+ unsigned int i8;
+
+ while ((i8 = index + 8) < nIndex) {
+ if (_InstPtr(self)->i_instvars[index] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 1) ); }
+ if (_InstPtr(self)->i_instvars[index+1] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 2) ); }
+ if (_InstPtr(self)->i_instvars[index+2] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 3) ); }
+ if (_InstPtr(self)->i_instvars[index+3] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 4) ); }
+ if (_InstPtr(self)->i_instvars[index+4] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 5) ); }
+ if (_InstPtr(self)->i_instvars[index+5] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 6) ); }
+ if (_InstPtr(self)->i_instvars[index+6] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 7) ); }
+ if (_InstPtr(self)->i_instvars[index+7] == nil) { RETURN ( __MKSMALLINT(index - nInsts + 8) ); }
+ index = i8;
+ }
+ }
+#endif
+
+ while (index < nIndex) {
+ if (_InstPtr(self)->i_instvars[index++] == nil) {
+ RETURN ( __MKSMALLINT(index - nInsts) );
+ }
+ }
+ }
+ }
+ }
+%}.
+ ^ 0
+!
+
+identityIndexOf:anElement or:alternative
+ "search the array for anElement or alternative;
+ return the index of anElement if found, or the index of anAlternative,
+ if not found. If anAlternative is also not found, return 0.
+ This is a special interface for high-speed searching in an array
+ and at the same time searching for an empty slot.
+ Do not use this method for your application classes, since it is
+ not portable (i.e. other smalltalks do not offer this)"
+
+%{ /* NOCONTEXT */
+
+ REGISTER int index;
+ REGISTER OBJ o, el1, el2;
+ REGISTER OBJ *op;
+ REGISTER unsigned int nIndex;
+ int altIndex = 0;
+ int nInsts;
+
+ index = 0;
+ nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
+ index += nInsts;
+ nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+ el1 = anElement; el2 = alternative;
+ op = & (_InstPtr(self)->i_instvars[index]);
+ while (index++ < nIndex) {
+ if ((o = *op++) == el1) {
+ RETURN ( __MKSMALLINT(index - nInsts) );
+ }
+ if (o == el2) {
+ if (altIndex == 0) {
+ altIndex = index;
+ }
+ }
+ }
+ RETURN ( __MKSMALLINT(altIndex) );
+%}
+
+ "
+ #(1 2 3 4 5 6 7 8 9) identityIndexOf:3 or:5
+ #(1 2 0 4 5 6 7 8 9) identityIndexOf:3 or:5
+ #(1 2 0 4 5 6 7 3 9) identityIndexOf:3 or:5
+ #(1 2 3 4 5 nil 7 3 9) identityIndexOf:3 or:nil
+ #(1 2 nil 4 5 6 7 3 9) identityIndexOf:3 or:nil
+ #(1 2 nil 4 5 6 7 8 9) identityIndexOf:3 or:nil
+ #() identityIndexOf:3 or:nil
+ #(1 2) identityIndexOf:3 or:nil
+ "
! !
+