#QUALITY by cg
class: SignedByteArray
comment/format in: #asSignedByteArray
changed: #beUnsigned
"{ Encoding: utf8 }"
"
COPYRIGHT (c) 2016 by eXept Software 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 Software 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 class methodsFor:'queries'!
maxVal
"the maximum value which can be stored in instances of me.
For SignedByteArrays, this is 127 (largest 8bit signed int)"
^ 127
!
minVal
"the minimum value which can be stored in instances of me.
For SignedByteArrays, this is -128 (smallest 8bit signed int)"
^ -128
! !
!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
"return the receiver as a signed byteArray.
That is the receiver already"
^ self.
"Modified (comment): / 09-06-2019 / 14:50:13 / Claus Gittinger"
!
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
"destructively make myself unsigned.
elements < 0 are converted to positive numbers.
WARNING: this changes the receiver itself - use this only for initialization of new instances"
self isImmutable ifTrue:[
self noModificationError.
].
self class == SignedByteArray ifTrue:[
self changeClassTo:ByteArray.
] ifFalse:[
self shouldNotImplement.
].
"
#(-1 -128 3 4) asSignedByteArray beUnsigned
"
"Modified: / 09-06-2019 / 14:56:41 / Claus Gittinger"
! !
!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;
if (len > 0) {
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
#[] max
#() 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
#() asSignedByteArray indexOf:-4 startingAt:1
#() indexOf:-4 startingAt:1
"
! !
!SignedByteArray class methodsFor:'documentation'!
version
^ '$Header$'
!
version_CVS
^ '$Header$'
! !