--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SignedByteArray.st Thu Feb 11 16:51:08 2016 +0100
@@ -0,0 +1,426 @@
+"
+ COPYRIGHT (c) 2016 by eXept Sofware AG
+ 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.
+"
+"{ Package: 'stx:libbasic' }"
+
+"{ NameSpace: Smalltalk }"
+
+ByteArray variableByteSubclass:#SignedByteArray
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Collections-Arrayed'
+!
+
+!SignedByteArray class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2016 by eXept Sofware AG
+ 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.
+
+"
+!
+
+documentation
+"
+ Instances of this class hold signed bytes in the range -128 ... +127.
+
+ [author:]
+ Stefan Vogel
+
+ [see also:]
+ ByteArray
+"
+! !
+
+!SignedByteArray methodsFor:'accessing'!
+
+basicAt:index
+ "return the indexed instance variable with index, anInteger
+ - redefined here to return a signed interger."
+
+%{ /* NOCONTEXT */
+
+ REGISTER int indx;
+ REGISTER OBJ slf;
+ REGISTER OBJ cls;
+ REGISTER int nIndex;
+
+ if (__isSmallInteger(index)) {
+ indx = __intVal(index) - 1;
+ slf = self;
+ if ((cls = __qClass(slf)) != @global(SignedByteArray)) {
+ if (((INT)__ClassInstPtr(cls)->c_flags & __MASKSMALLINT(ARRAYMASK))
+ != __MASKSMALLINT(BYTEARRAY)) {
+ goto fail;
+ }
+ if (indx < 0) goto fail;
+ indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ }
+ nIndex = __byteArraySize(slf);
+ if ((unsigned)indx < (unsigned)nIndex) {
+ int byte = ((signed char *)__ByteArrayInstPtr(slf)->ba_element)[indx];
+ RETURN ( __mkSmallInteger(byte));
+ }
+ }
+ fail: ;
+%}.
+ ^ super basicAt:index
+
+ "
+ #[0 1 2 3 127 128 254 255] copy changeClassTo:self
+ "
+!
+
+basicAt:index put:value
+ "set the indexed instance variable with index, anInteger to value.
+ Returns value (sigh).
+ - redefined here to allow value to be a signed integer"
+
+%{ /* NOCONTEXT */
+
+ REGISTER int indx;
+ int nIndex;
+ int val;
+ REGISTER OBJ slf;
+ REGISTER OBJ cls;
+
+ if (__bothSmallInteger(index, value)) {
+ val = __intVal(value);
+ if ((val >= -128) && (val <= 127)) {
+ indx = __intVal(index) - 1;
+ slf = self;
+ if ((cls = __qClass(slf)) != @global(SignedByteArray)) {
+ if (((INT)__ClassInstPtr(cls)->c_flags & __MASKSMALLINT(ARRAYMASK))
+ != __MASKSMALLINT(BYTEARRAY)) {
+ goto fail;
+ }
+ if (indx < 0) goto fail;
+ indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ }
+ nIndex = __byteArraySize(slf);
+ if ((unsigned)indx < (unsigned)nIndex) {
+ __ByteArrayInstPtr(slf)->ba_element[indx] = val;
+ RETURN ( value );
+ }
+ }
+ }
+ fail: ;
+%}.
+ ^ super basicAt:index put:value
+
+ "
+ (self new:5) basicAt:1 put:-1; yourself
+ "
+
+ "Modified: 19.4.1996 / 11:14:40 / cg"
+! !
+
+!SignedByteArray methodsFor:'converting'!
+
+asSignedByteArray
+ ^ self.
+!
+
+asUnsignedByteArray
+ "Answer a unsigned byte array.
+ elements < 0 are converted to positive numbers."
+
+ self class == SignedByteArray ifTrue:[
+ self copy changeClassTo:ByteArray.
+ ] ifFalse:[
+ self shouldNotImplement.
+ ].
+
+ "
+ #(-1 -128 3 4) asSignedByteArray asUnsignedByteArray
+ "
+!
+
+beSigned
+ "that's what I am"
+
+ ^ self.
+!
+
+beUnsigned
+ "make mayself unsigned.
+ elements < 0 are converted to positive numbers."
+
+ self class == SignedByteArray ifTrue:[
+ self changeClassTo:ByteArray.
+ ] ifFalse:[
+ self shouldNotImplement.
+ ].
+
+ "
+ #(-1 -128 3 4) asSignedByteArray beUnsigned
+ "
+! !
+
+!SignedByteArray methodsFor:'filling & replacing'!
+
+from:start to:stop put:aNumber
+ "fill part of the receiver with aNumber.
+ - reimplemented here for speed"
+
+%{ /* NOCONTEXT */
+
+ REGISTER unsigned char *dstp;
+ REGISTER int count, value;
+ int len, index1, index2;
+ OBJ cls;
+
+ if (__isSmallInteger(aNumber)
+ && __bothSmallInteger(start, stop)
+ && __isBytes(self)) {
+ len = __byteArraySize(self);
+ index1 = __intVal(start);
+ index2 = __intVal(stop);
+
+ dstp = __ByteArrayInstPtr(self)->ba_element + index1 - 1;
+ if ((cls = __qClass(self)) != @global(SignedByteArray)) {
+ int nInst;
+
+ nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ dstp += nInst;
+ len -= nInst;
+ }
+
+ value = __intVal(aNumber);
+ if ((value >= -128) && (value <= 127)
+ && (index1 <= index2)
+ && (index1 > 0)) {
+ if (index2 <= len) {
+ count = index2 - index1 + 1;
+
+#ifdef memset4
+ if (count > 20) {
+ /* fill unaligned part */
+ while (((unsigned INT)dstp & 3) != 0) {
+ *dstp++ = (unsigned char)value;
+ count--;
+ }
+ /* fill aligned part */
+ {
+ unsigned int n4 = count & ~3;
+ unsigned int v4, nW;
+
+ v4 = ((unsigned char)value << 8) | (unsigned char)value;
+ v4 = (v4 << 16) | v4;
+ nW = n4>>2;
+ memset4(dstp, v4, nW);
+ count -= n4;
+ dstp += n4;
+ }
+ while (count--) {
+ *dstp++ = (unsigned char)value;
+ }
+ RETURN (self);
+ }
+#endif /* memset4 */
+
+#if (__POINTER_SIZE__ == 8)
+ {
+ unsigned INT v8;
+
+ v8 = ((unsigned char)value << 8) | (unsigned char)value;
+ v8 = (v8 << 16) | v8;
+ v8 = (v8 << 32) | v8;
+
+ /* fill unaligned part */
+ while ((count > 0) && (((unsigned INT)dstp & 3) != 0)) {
+ *dstp++ = (unsigned char)value;
+ count--;
+ }
+
+ if ((count >= 4) && (((unsigned INT)dstp & 7) != 0)) {
+ ((unsigned int *)dstp)[0] = v8;
+ dstp += 4;
+ count -= 4;
+ }
+
+ /* fill aligned part */
+ while (count >= 8) {
+ ((unsigned INT *)dstp)[0] = v8;
+ dstp += 8;
+ count -= 8;
+ }
+
+ /* fill rest */
+ if (count >= 4) {
+ ((unsigned int *)dstp)[0] = v8;
+ dstp += 4;
+ count -= 4;
+ }
+ if (count >= 2) {
+ ((unsigned short *)dstp)[0] = v8;
+ dstp += 2;
+ count -= 2;
+ }
+ if (count) {
+ *dstp = (unsigned char)value;
+ }
+ RETURN (self);
+ }
+#endif /* 64bit */
+
+#ifdef FAST_MEMSET
+ memset(dstp, value, count);
+#else
+# ifdef __UNROLL_LOOPS__
+ while (count >= 8) {
+ dstp[0] = dstp[1] = dstp[2] = dstp[3] =
+ dstp[4] = dstp[5] = dstp[6] = dstp[7] = (unsigned char)value;
+ dstp += 8;
+ count -= 8;
+ }
+# endif /* __UNROLL_LOOPS__ */
+ while (count--) {
+ *dstp++ = (unsigned char)value;
+ }
+#endif
+ RETURN (self);
+ }
+ }
+ }
+%}.
+ "
+ fall back in case of non-integer index or out-of-bound index/value;
+ will eventually lead to an out-of-bound signal raise
+ "
+ ^ super from:start to:stop put:aNumber
+
+ "
+ (self new:10) from:1 to:10 put:-5
+ (self new:20) from:10 to:20 put:-5
+ (self new:20) from:1 to:10 put:-5
+ "
+! !
+
+!SignedByteArray methodsFor:'queries'!
+
+max
+ "return the maximum value in the receiver -
+ redefined to speedup image processing and sound-player
+ (which need a fast method for this on byteArrays)"
+
+%{ /* NOCONTEXT */
+
+ signed char *cp;
+ int index, max, len;
+
+ if (__qClass(self) == @global(SignedByteArray)) {
+ max = -128;
+ index = 0;
+ len = __qSize(self) - OHDR_SIZE;
+
+ for (cp = __ByteArrayInstPtr(self)->ba_element; ++index <= len; cp++) {
+ int byte = *cp;
+
+ if (byte > max) {
+ max = byte;
+ if (byte == 127) break;
+ }
+ }
+ RETURN ( __mkSmallInteger(max) );
+ }
+%}.
+ ^ super max
+
+ "
+ #[1 2 3 -11 2 3 1 2 19] max
+ #(-1 -2 -3 -4) asSignedByteArray max
+ #() asSignedByteArray max
+ "
+! !
+
+!SignedByteArray methodsFor:'searching'!
+
+indexOf:aByte startingAt:start
+ "return the index of the first occurrence of the argument, aByte
+ in the receiver starting at start, anInteger; return 0 if not found.
+ - reimplemented here for speed"
+
+%{ /* NOCONTEXT */
+
+ char *cp;
+ INT index;
+ int len;
+ OBJ cls;
+
+ if (__isSmallInteger(aByte) &&__isBytes(self)) {
+ int byteValue = __intVal(aByte);
+
+ if ((byteValue < -128) || (byteValue > 127)) {
+ /*
+ * searching for something which cannot be found
+ */
+ RETURN ( __mkSmallInteger(0) );
+ }
+
+ if (__isSmallInteger(start)) {
+ index = __intVal(start);
+ len = __byteArraySize(self);
+ cp = __ByteArrayInstPtr(self)->ba_element;
+ if ((cls = __qClass(self)) != @global(SignedByteArray)) {
+ int nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ cp += nInst;
+ len -= nInst;
+ }
+ cp += index - 1;
+#ifdef __UNROLL_LOOPS__
+ while ((index+4) < len) {
+ if (cp[0] == byteValue) { RETURN ( __mkSmallInteger(index) ); }
+ if (cp[1] == byteValue) { RETURN ( __mkSmallInteger(index+1) ); }
+ if (cp[2] == byteValue) { RETURN ( __mkSmallInteger(index+2) ); }
+ if (cp[3] == byteValue) { RETURN ( __mkSmallInteger(index+3) ); }
+ index += 4;
+ cp += 4;
+ }
+#endif
+ while (index <= len) {
+ if (*cp == byteValue) {
+ RETURN ( __mkSmallInteger(index) );
+ }
+ index++;
+ cp++;
+ }
+ RETURN ( __mkSmallInteger(0) );
+ }
+ }
+%}.
+ ^ super indexOf:aByte startingAt:start
+
+ "
+ #(-1 2 3 -4 5 6 7 8 9 0 1 2 3 4 5) asSignedByteArray indexOf:0 startingAt:1
+ #(-1 2 3 -4 5 6 7 8 9 0 1 2 3 4 5) asSignedByteArray indexOf:-4 startingAt:1
+ "
+! !
+
+!SignedByteArray class methodsFor:'documentation'!
+
+version
+ ^ '$Header$'
+!
+
+version_CVS
+ ^ '$Header$'
+! !
+