UninterpretedBytes.st
branchjv
changeset 19408 8c80107973c7
parent 19354 ec77be1507a3
parent 19368 1811855e8abb
child 19412 1e842c25e51e
equal deleted inserted replaced
19407:2ef90564b9cc 19408:8c80107973c7
     1 "
     1 "
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     3 	      All Rights Reserved
     3               All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
    12 "{ Package: 'stx:libbasic' }"
    12 "{ Package: 'stx:libbasic' }"
    13 
    13 
    14 "{ NameSpace: Smalltalk }"
    14 "{ NameSpace: Smalltalk }"
    15 
    15 
    16 ArrayedCollection subclass:#UninterpretedBytes
    16 ArrayedCollection subclass:#UninterpretedBytes
    17 	instanceVariableNames:''
    17         instanceVariableNames:''
    18 	classVariableNames:'IsBigEndian'
    18         classVariableNames:'IsBigEndian'
    19 	poolDictionaries:''
    19         poolDictionaries:''
    20 	category:'Collections-Abstract'
    20         category:'Collections-Abstract'
    21 !
    21 !
    22 
    22 
    23 !UninterpretedBytes primitiveDefinitions!
    23 !UninterpretedBytes primitiveDefinitions!
    24 %{
    24 %{
    25 /*
    25 /*
    33  * (yes, C is bad ...)
    33  * (yes, C is bad ...)
    34  */
    34  */
    35 #define __fetchBytePointerAndSize__(o, pPtr, pSize) \
    35 #define __fetchBytePointerAndSize__(o, pPtr, pSize) \
    36     {\
    36     {\
    37       if (__isNonNilObject(o)) { \
    37       if (__isNonNilObject(o)) { \
    38 	if (__isByteArrayLike(o)) { \
    38         if (__isByteArrayLike(o)) { \
    39 	  *(pPtr) = (unsigned char *)__ByteArrayInstPtr(o)->ba_element; \
    39           *(pPtr) = (unsigned char *)__ByteArrayInstPtr(o)->ba_element; \
    40 	  *(pSize) = __byteArraySize(o); \
    40           *(pSize) = __byteArraySize(o); \
    41 	} else if (__qIsExternalBytesLike(o)) { \
    41         } else if (__qIsExternalBytesLike(o)) { \
    42 	  OBJ __sz__ = __externalBytesSize(o); \
    42           OBJ __sz__ = __externalBytesSize(o); \
    43 	  if (__isSmallInteger(__sz__)) { \
    43           if (__isSmallInteger(__sz__)) { \
    44 	    *(pSize) = __intVal(__sz__); \
    44             *(pSize) = __intVal(__sz__); \
    45 	    *(pPtr) = (unsigned char *)(__externalBytesAddress(o)); \
    45             *(pPtr) = (unsigned char *)(__externalBytesAddress(o)); \
    46 	  } else { \
    46           } else { \
    47 	    *(pSize) = 0; \
    47             *(pSize) = 0; \
    48 	    *(pPtr) = (unsigned char *)0; \
    48             *(pPtr) = (unsigned char *)0; \
    49 	  } \
    49           } \
    50 	} else { \
    50         } else { \
    51 	    *(pSize) /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(o))->c_ninstvars)); \
    51             *(pSize) /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(o))->c_ninstvars)); \
    52 	    *(pPtr) = (char *)(__InstPtr(self)) + *(pSize) /* nInstBytes */; \
    52             *(pPtr) = (char *)(__InstPtr(self)) + *(pSize) /* nInstBytes */; \
    53 	    *(pSize) = __qSize(self) - *(pSize) /* nInstBytes */; \
    53             *(pSize) = __qSize(self) - *(pSize) /* nInstBytes */; \
    54 	} \
    54         } \
    55       } else { \
    55       } else { \
    56 	*(pSize) = 0; \
    56         *(pSize) = 0; \
    57 	*(pPtr) = (unsigned char *)0; \
    57         *(pPtr) = (unsigned char *)0; \
    58       } \
    58       } \
    59     }
    59     }
    60 
    60 
    61 %}
    61 %}
    62 ! !
    62 ! !
    64 !UninterpretedBytes class methodsFor:'documentation'!
    64 !UninterpretedBytes class methodsFor:'documentation'!
    65 
    65 
    66 copyright
    66 copyright
    67 "
    67 "
    68  COPYRIGHT (c) 1993 by Claus Gittinger
    68  COPYRIGHT (c) 1993 by Claus Gittinger
    69 	      All Rights Reserved
    69               All Rights Reserved
    70 
    70 
    71  This software is furnished under a license and may be used
    71  This software is furnished under a license and may be used
    72  only in accordance with the terms of that license and with the
    72  only in accordance with the terms of that license and with the
    73  inclusion of the above copyright notice.   This software may not
    73  inclusion of the above copyright notice.   This software may not
    74  be provided or otherwise made available to, or used by, any
    74  be provided or otherwise made available to, or used by, any
   140     sz odd ifTrue:[ ConversionError raiseWith:aString errorString:'invalid hex string (odd size)' ].
   140     sz odd ifTrue:[ ConversionError raiseWith:aString errorString:'invalid hex string (odd size)' ].
   141 
   141 
   142     bytes := self new: sz // 2.
   142     bytes := self new: sz // 2.
   143     s := aString readStream.
   143     s := aString readStream.
   144     1 to: sz // 2 do: [ :idx |
   144     1 to: sz // 2 do: [ :idx |
   145 	hi := s next digitValue.
   145         hi := s next digitValue.
   146 	lo := s next digitValue.
   146         lo := s next digitValue.
   147 	bytes at:idx put: ((hi bitShift:4) bitOr: lo)
   147         bytes at:idx put: ((hi bitShift:4) bitOr: lo)
   148     ].
   148     ].
   149     ^ bytes
   149     ^ bytes
   150 
   150 
   151     "
   151     "
   152      ByteArray fromHexString:'1234FEFF'
   152      ByteArray fromHexString:'1234FEFF'
   157      s := String streamContents:[:s | #[1 2 3] hexPrintOn:s].
   157      s := String streamContents:[:s | #[1 2 3] hexPrintOn:s].
   158      ByteArray fromHexString:s
   158      ByteArray fromHexString:s
   159     "
   159     "
   160     "
   160     "
   161      Time millisecondsToRun:[
   161      Time millisecondsToRun:[
   162 	1000000 timesRepeat:[ ByteArray fromHexString:'1234FEFF1234FEFF1234FEFF1234FEFF' ]
   162         1000000 timesRepeat:[ ByteArray fromHexString:'1234FEFF1234FEFF1234FEFF1234FEFF' ]
   163      ].
   163      ].
   164     "
   164     "
   165 
   165 
   166     "Modified (comment): / 28-08-2013 / 20:40:04 / cg"
   166     "Modified (comment): / 28-08-2013 / 20:40:04 / cg"
   167 !
   167 !
   170     "read a bytearray from a printed string representation, where
   170     "read a bytearray from a printed string representation, where
   171      individual bytes are encoded as two hex digits, optionally separated by whiteSpace.
   171      individual bytes are encoded as two hex digits, optionally separated by whiteSpace.
   172      See also fromHexString:, which does something similar, but does not allow for spaces"
   172      See also fromHexString:, which does something similar, but does not allow for spaces"
   173 
   173 
   174     ^ self streamContents:[:outStream |
   174     ^ self streamContents:[:outStream |
   175 	|inStream h|
   175         |inStream h|
   176 
   176 
   177 	inStream := aString readStream.
   177         inStream := aString readStream.
   178 
   178 
   179 	[
   179         [
   180 	    inStream skipSeparators.
   180             inStream skipSeparators.
   181 	    inStream atEnd
   181             inStream atEnd
   182 	] whileFalse:[
   182         ] whileFalse:[
   183 	    h := inStream next:2.
   183             h := inStream next:2.
   184 	    outStream nextPut:(Integer readFrom:h base:16).
   184             outStream nextPut:(Integer readFrom:h base:16).
   185 	].
   185         ].
   186     ].
   186     ].
   187 
   187 
   188     "
   188     "
   189      ByteArray fromHexString:'1234FEFF'
   189      ByteArray fromHexString:'1234FEFF'
   190      ByteArray fromHexStringWithSeparators:'   12  34 FE FF'
   190      ByteArray fromHexStringWithSeparators:'   12  34 FE FF'
   220     "the size modulo 3 is encoded in the last character, if it is in the
   220     "the size modulo 3 is encoded in the last character, if it is in the
   221      range 97 .. otherwise, its exact."
   221      range 97 .. otherwise, its exact."
   222 
   222 
   223     last := aString last codePoint.
   223     last := aString last codePoint.
   224     last > 96 ifTrue:[
   224     last > 96 ifTrue:[
   225 	stop := stop - 3 + (last - 96)
   225         stop := stop - 3 + (last - 96)
   226     ].
   226     ].
   227     bytes := self new:stop.
   227     bytes := self new:stop.
   228 
   228 
   229     index := 1. dstIndex := 1.
   229     index := 1. dstIndex := 1.
   230     [dstIndex <= stop] whileTrue:[
   230     [dstIndex <= stop] whileTrue:[
   231 	"/ take 4 characters ...
   231         "/ take 4 characters ...
   232 	"/ allow a line break before each group of 4
   232         "/ allow a line break before each group of 4
   233 	sixBits := (aString at:index) codePoint.
   233         sixBits := (aString at:index) codePoint.
   234 	[sixBits < 32] whileTrue:[
   234         [sixBits < 32] whileTrue:[
   235 	    index := index + 1.
   235             index := index + 1.
   236 	    sixBits := (aString at:index) codePoint.
   236             sixBits := (aString at:index) codePoint.
   237 	].
   237         ].
   238 	sixBits := sixBits bitAnd:16r3F.
   238         sixBits := sixBits bitAnd:16r3F.
   239 	n := sixBits.
   239         n := sixBits.
   240 
   240 
   241 	"/ self assert:(aString at:index+1) codePoint >= 32.
   241         "/ self assert:(aString at:index+1) codePoint >= 32.
   242 	sixBits := (aString at:index+1) codePoint bitAnd:16r3F.
   242         sixBits := (aString at:index+1) codePoint bitAnd:16r3F.
   243 	n := (n bitShift:6) + sixBits.
   243         n := (n bitShift:6) + sixBits.
   244 
   244 
   245 	"/ self assert:(aString at:index+2) codePoint >= 32.
   245         "/ self assert:(aString at:index+2) codePoint >= 32.
   246 	sixBits := (aString at:index+2) codePoint bitAnd:16r3F.
   246         sixBits := (aString at:index+2) codePoint bitAnd:16r3F.
   247 	n := (n bitShift:6) + sixBits.
   247         n := (n bitShift:6) + sixBits.
   248 
   248 
   249 	"/ self assert:(aString at:index+3) codePoint >= 32.
   249         "/ self assert:(aString at:index+3) codePoint >= 32.
   250 	sixBits := (aString at:index+3) codePoint bitAnd:16r3F.
   250         sixBits := (aString at:index+3) codePoint bitAnd:16r3F.
   251 	n := (n bitShift:6) + sixBits.
   251         n := (n bitShift:6) + sixBits.
   252 
   252 
   253 	index := index + 4.
   253         index := index + 4.
   254 
   254 
   255 	"/ now have 24 bits in n
   255         "/ now have 24 bits in n
   256 
   256 
   257 	bytes at:dstIndex put:(n bitShift:-16).
   257         bytes at:dstIndex put:(n bitShift:-16).
   258 
   258 
   259 	dstIndex < stop ifTrue:[
   259         dstIndex < stop ifTrue:[
   260 	    bytes at:dstIndex+1 put:((n bitShift:-8) bitAnd:16rFF).
   260             bytes at:dstIndex+1 put:((n bitShift:-8) bitAnd:16rFF).
   261 	    dstIndex+2 <= stop ifTrue:[
   261             dstIndex+2 <= stop ifTrue:[
   262 		bytes at:dstIndex+2 put:(n bitAnd:16rFF).
   262                 bytes at:dstIndex+2 put:(n bitAnd:16rFF).
   263 	    ]
   263             ]
   264 	].
   264         ].
   265 	dstIndex := dstIndex + 3.
   265         dstIndex := dstIndex + 3.
   266     ].
   266     ].
   267     ^ bytes
   267     ^ bytes
   268 
   268 
   269     "
   269     "
   270      ByteArray fromPackedString:(#[1 1 1 1] asPackedString)
   270      ByteArray fromPackedString:(#[1 1 1 1] asPackedString)
   279      ByteArray fromPackedString:((ByteArray new:131) asPackedString)
   279      ByteArray fromPackedString:((ByteArray new:131) asPackedString)
   280      ByteArray fromPackedString:((ByteArray new:132) asPackedString)
   280      ByteArray fromPackedString:((ByteArray new:132) asPackedString)
   281      ByteArray fromPackedString:((ByteArray new:64) asPackedString)
   281      ByteArray fromPackedString:((ByteArray new:64) asPackedString)
   282 
   282 
   283      0 to:256 do:[:l |
   283      0 to:256 do:[:l |
   284 	|orig copy|
   284         |orig copy|
   285 
   285 
   286 	0 to:255 do:[:fill |
   286         0 to:255 do:[:fill |
   287 	    orig := ByteArray new:l withAll:fill.
   287             orig := ByteArray new:l withAll:fill.
   288 	    copy := ByteArray fromPackedString:(orig asPackedString).
   288             copy := ByteArray fromPackedString:(orig asPackedString).
   289 	    self assert:(orig = copy).
   289             self assert:(orig = copy).
   290 	 ]
   290          ]
   291      ]
   291      ]
   292     "
   292     "
   293 
   293 
   294     "Modified: / 6.3.1997 / 15:28:52 / cg"
   294     "Modified: / 6.3.1997 / 15:28:52 / cg"
   295     "Modified: / 18.12.1997 / 17:17:11 / stefan"
   295     "Modified: / 18.12.1997 / 17:17:11 / stefan"
   312     OBJ newobj;
   312     OBJ newobj;
   313     INT instsize, nInstVars, nindexedinstvars;
   313     INT instsize, nInstVars, nindexedinstvars;
   314     REGISTER OBJ *op;
   314     REGISTER OBJ *op;
   315 
   315 
   316     if (__isSmallInteger(anInteger)) {
   316     if (__isSmallInteger(anInteger)) {
   317 	nindexedinstvars = __intVal(anInteger);
   317         nindexedinstvars = __intVal(anInteger);
   318 	if (nindexedinstvars >= 0) {
   318         if (nindexedinstvars >= 0) {
   319 	    if (self == ByteArray) {
   319             if (self == ByteArray) {
   320 		/*
   320                 /*
   321 		 * the most common case
   321                  * the most common case
   322 		 */
   322                  */
   323 		instsize = OHDR_SIZE + nindexedinstvars;
   323                 instsize = OHDR_SIZE + nindexedinstvars;
   324 		if (__CanDoQuickNew(instsize)) {        /* OBJECT ALLOCATION */
   324                 if (__CanDoQuickNew(instsize)) {        /* OBJECT ALLOCATION */
   325 		    __qCheckedNew(newobj, instsize);
   325                     __qCheckedNew(newobj, instsize);
   326 		    __InstPtr(newobj)->o_class = self;
   326                     __InstPtr(newobj)->o_class = self;
   327 		    __qSTORE(newobj, self);
   327                     __qSTORE(newobj, self);
   328 		    RETURN (newobj );
   328                     RETURN (newobj );
   329 		}
   329                 }
   330 	    } else {
   330             } else {
   331 		/*
   331                 /*
   332 		 * Take care for subclasses like TwoByteString
   332                  * Take care for subclasses like TwoByteString
   333 		 */
   333                  */
   334 		switch (__smallIntegerVal(__ClassInstPtr(self)->c_flags) & ARRAYMASK) {
   334                 switch (__smallIntegerVal(__ClassInstPtr(self)->c_flags) & ARRAYMASK) {
   335 		case BYTEARRAY:
   335                 case BYTEARRAY:
   336 		    break;
   336                     break;
   337 
   337 
   338 		case WORDARRAY:
   338                 case WORDARRAY:
   339 		case SWORDARRAY:
   339                 case SWORDARRAY:
   340 		    nindexedinstvars *= 2;
   340                     nindexedinstvars *= 2;
   341 		    break;
   341                     break;
   342 
   342 
   343 		case LONGARRAY:
   343                 case LONGARRAY:
   344 		case SLONGARRAY:
   344                 case SLONGARRAY:
   345 		    nindexedinstvars *= 4;
   345                     nindexedinstvars *= 4;
   346 		    break;
   346                     break;
   347 
   347 
   348 		default:
   348                 default:
   349 		    /* don't know about this array type, delegate to super */
   349                     /* don't know about this array type, delegate to super */
   350 		    goto out;
   350                     goto out;
   351 		}
   351                 }
   352 	    }
   352             }
   353 	    nInstVars = __intVal(__ClassInstPtr(self)->c_ninstvars);
   353             nInstVars = __intVal(__ClassInstPtr(self)->c_ninstvars);
   354 	    instsize = OHDR_SIZE + __OBJS2BYTES__(nInstVars) + nindexedinstvars;
   354             instsize = OHDR_SIZE + __OBJS2BYTES__(nInstVars) + nindexedinstvars;
   355 	    __PROTECT_CONTEXT__
   355             __PROTECT_CONTEXT__
   356 	    __qNew(newobj, instsize);   /* OBJECT ALLOCATION */
   356             __qNew(newobj, instsize);   /* OBJECT ALLOCATION */
   357 	    __UNPROTECT_CONTEXT__
   357             __UNPROTECT_CONTEXT__
   358 	    if (newobj != nil) {
   358             if (newobj != nil) {
   359 		__InstPtr(newobj)->o_class = self;
   359                 __InstPtr(newobj)->o_class = self;
   360 		__qSTORE(newobj, self);
   360                 __qSTORE(newobj, self);
   361 		if (nInstVars) {
   361                 if (nInstVars) {
   362 		    /*
   362                     /*
   363 		     * still have to nil out named instvars ...
   363                      * still have to nil out named instvars ...
   364 		     */
   364                      */
   365 #if defined(memset4) && defined(FAST_OBJECT_MEMSET4)
   365 #if defined(memset4) && defined(FAST_OBJECT_MEMSET4)
   366 		    memset4(__InstPtr(newobj)->i_instvars, nil, nInstVars);
   366                     memset4(__InstPtr(newobj)->i_instvars, nil, nInstVars);
   367 #else
   367 #else
   368 # if defined(FAST_MEMSET) && !defined(NEGATIVE_ADDRESSES)
   368 # if defined(FAST_MEMSET) && !defined(NEGATIVE_ADDRESSES)
   369 		    /*
   369                     /*
   370 		     * knowing that nil is 0
   370                      * knowing that nil is 0
   371 		     */
   371                      */
   372 		    memset(__InstPtr(newobj)->i_instvars, 0, instsize - OHDR_SIZE);
   372                     memset(__InstPtr(newobj)->i_instvars, 0, instsize - OHDR_SIZE);
   373 # else
   373 # else
   374 		    op = __InstPtr(newobj)->i_instvars;
   374                     op = __InstPtr(newobj)->i_instvars;
   375 		    while (nInstVars--)
   375                     while (nInstVars--)
   376 			*op++ = nil;
   376                         *op++ = nil;
   377 # endif
   377 # endif
   378 #endif
   378 #endif
   379 		}
   379                 }
   380 		RETURN ( newobj );
   380                 RETURN ( newobj );
   381 	    }
   381             }
   382 	}
   382         }
   383     }
   383     }
   384 out:;
   384 out:;
   385 %}.
   385 %}.
   386     ^ self basicNew:anInteger
   386     ^ self basicNew:anInteger
   387 !
   387 !
   416     "return true, if words/shorts store the most-significant
   416     "return true, if words/shorts store the most-significant
   417      byte first (MSB), false if least-sign.-first (LSB).
   417      byte first (MSB), false if least-sign.-first (LSB).
   418      I.e. false for vax, intel; true for m68k, sun.
   418      I.e. false for vax, intel; true for m68k, sun.
   419 
   419 
   420      Notice: UninterpretedBytes isBigEndian
   420      Notice: UninterpretedBytes isBigEndian
   421 	     this is inlined both by stc and the jit compiler"
   421              this is inlined both by stc and the jit compiler"
   422 
   422 
   423 %{  /* NOCONTEXT */
   423 %{  /* NOCONTEXT */
   424 
   424 
   425 #if defined(__MSBFIRST__)
   425 #if defined(__MSBFIRST__)
   426     RETURN (true);
   426     RETURN (true);
   437      * NOTICE:
   437      * NOTICE:
   438      *    both the JIT and stc may inline this to a
   438      *    both the JIT and stc may inline this to a
   439      *    constant for systems where this is known.
   439      *    constant for systems where this is known.
   440      */
   440      */
   441     union {
   441     union {
   442 	unsigned int   u_l;
   442         unsigned int   u_l;
   443 	char           u_c[sizeof(int)];
   443         char           u_c[sizeof(int)];
   444     } u;
   444     } u;
   445 
   445 
   446     u.u_l = 0x87654321;
   446     u.u_l = 0x87654321;
   447     if (u.u_c[0] == 0x21) RETURN (false);
   447     if (u.u_c[0] == 0x21) RETURN (false);
   448     RETURN (true);
   448     RETURN (true);
   465 
   465 
   466     "Modified: / 23.4.1996 / 15:56:25 / cg"
   466     "Modified: / 23.4.1996 / 15:56:25 / cg"
   467     "Modified: / 5.3.1998 / 14:56:22 / stefan"
   467     "Modified: / 5.3.1998 / 14:56:22 / stefan"
   468 ! !
   468 ! !
   469 
   469 
       
   470 
   470 !UninterpretedBytes methodsFor:'Compatibility'!
   471 !UninterpretedBytes methodsFor:'Compatibility'!
   471 
   472 
   472 doubleWordAt:index
   473 doubleWordAt:index
   473     "return the 4-bytes starting at index as an (unsigned) Integer.
   474     "return the 4-bytes starting at index as an (unsigned) Integer.
   474      The index is a smalltalk index (i.e. 1-based).
   475      The index is a smalltalk index (i.e. 1-based).
   837      The index is a smalltalk index (i.e. 1-based).
   838      The index is a smalltalk index (i.e. 1-based).
   838      The value is retrieved in the machines natural byte order.
   839      The value is retrieved in the machines natural byte order.
   839      This may be worth a primitive.
   840      This may be worth a primitive.
   840      This is the ST80 equivalent of #signedWordAt:"
   841      This is the ST80 equivalent of #signedWordAt:"
   841 
   842 
   842     ^ (self unsignedInt16At:index MSB:IsBigEndian) signExtendedShortValue
   843     ^ self signedInt16At:index MSB:IsBigEndian
   843 
   844 
   844     "
   845     "
   845      |b|
   846      |b|
   846      b := ByteArray new:2.
   847      b := ByteArray new:2.
   847      b unsignedShortAt:1 put:16rFFFF.
   848      b unsignedShortAt:1 put:16rFFFF.
   858      The index is a smalltalk index (i.e. 1-based).
   859      The index is a smalltalk index (i.e. 1-based).
   859      The value is retrieved MSB-first, if the msb-arg is true;
   860      The value is retrieved MSB-first, if the msb-arg is true;
   860      LSB-first otherwise.
   861      LSB-first otherwise.
   861      This is the ST80 equivalent of #signedWordAt:"
   862      This is the ST80 equivalent of #signedWordAt:"
   862 
   863 
   863     ^ (self unsignedInt16At:index MSB:msb) signExtendedShortValue
   864     ^ self signedInt16At:index MSB:msb
   864 
   865 
   865     "
   866     "
   866      |b|
   867      |b|
   867      b := ByteArray new:2.
   868      b := ByteArray new:2.
   868      b unsignedShortAt:1 put:16rFFFF.
   869      b unsignedShortAt:1 put:16rFFFF.
  1722     "set the byte at index as bcd-value in the range 0..99.
  1723     "set the byte at index as bcd-value in the range 0..99.
  1723      BCD treats nibbles (4-bit) as an encoded decimal number's digits
  1724      BCD treats nibbles (4-bit) as an encoded decimal number's digits
  1724      (i.e. the value n is encoded as: ((n // 10) * 16) + (n \\ 10)"
  1725      (i.e. the value n is encoded as: ((n // 10) * 16) + (n \\ 10)"
  1725 
  1726 
  1726     (aNumber between:0 and:99) ifFalse:[
  1727     (aNumber between:0 and:99) ifFalse:[
  1727 	self error:'invalid value for BCD encoding'
  1728         self error:'invalid value for BCD encoding'
  1728     ].
  1729     ].
  1729     ^ self byteAt:index put:aNumber encodeAsBCD
  1730     ^ self byteAt:index put:aNumber encodeAsBCD
  1730 
  1731 
  1731     "
  1732     "
  1732      (((ByteArray new:1) bcdByteAt:1 put:55; yourself) at:1) hexPrintString
  1733      (((ByteArray new:1) bcdByteAt:1 put:55; yourself) at:1) hexPrintString
  2477      The index is a smalltalk index (i.e. 1-based).
  2478      The index is a smalltalk index (i.e. 1-based).
  2478      Only aligned accesses are allowed."
  2479      Only aligned accesses are allowed."
  2479 
  2480 
  2480 %{
  2481 %{
  2481     if (__isSmallInteger(index)) {
  2482     if (__isSmallInteger(index)) {
  2482 	unsigned char *cp;
  2483         unsigned char *cp;
  2483 	INT sz;
  2484         INT sz;
  2484 
  2485 
  2485 	__fetchBytePointerAndSize__(self, &cp, &sz);
  2486         __fetchBytePointerAndSize__(self, &cp, &sz);
  2486 	if (cp) {
  2487         if (cp) {
  2487 	    unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1;
  2488             unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1;
  2488 	    char *pointer;
  2489             char *pointer;
  2489 
  2490 
  2490 	    if ((idx+(sizeof(pointer)-1)) < sz) {
  2491             if ((idx+(sizeof(pointer)-1)) < sz) {
  2491 		cp += idx;
  2492                 cp += idx;
  2492 		/*
  2493                 /*
  2493 		 * aligned
  2494                  * aligned
  2494 		 */
  2495                  */
  2495 		if (((INT)cp & (sizeof(pointer)-1)) == 0) {
  2496                 if (((INT)cp & (sizeof(pointer)-1)) == 0) {
  2496 		    pointer = ((char **)cp)[0];
  2497                     pointer = ((char **)cp)[0];
  2497 		    RETURN (__MKEXTERNALADDRESS(pointer));
  2498                     RETURN (__MKEXTERNALADDRESS(pointer));
  2498 		} else {
  2499                 } else {
  2499 #if 0
  2500 #if 0
  2500 		    printf("cp UNALIGNED (%"_lx_")\n", (INT)cp);
  2501                     printf("cp UNALIGNED (%"_lx_")\n", (INT)cp);
  2501 #endif
  2502 #endif
  2502 		}
  2503                 }
  2503 	    } else {
  2504             } else {
  2504 #if 0
  2505 #if 0
  2505 		printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
  2506                 printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
  2506 			idx, (int)(sizeof(pointer)-1), sz);
  2507                         idx, (int)(sizeof(pointer)-1), sz);
  2507 #endif
  2508 #endif
  2508 	    }
  2509             }
  2509 	} else {
  2510         } else {
  2510 #if 0
  2511 #if 0
  2511 	    printf("cp is NULL\n");
  2512             printf("cp is NULL\n");
  2512 #endif
  2513 #endif
  2513 	}
  2514         }
  2514     } else {
  2515     } else {
  2515 #if 0
  2516 #if 0
  2516 	printf("bad index\n");
  2517         printf("bad index\n");
  2517 #endif
  2518 #endif
  2518     }
  2519     }
  2519 bad:;
  2520 bad:;
  2520 %}.
  2521 %}.
  2521 
  2522 
  2538 
  2539 
  2539 %{
  2540 %{
  2540     OBJ *pointer;
  2541     OBJ *pointer;
  2541 
  2542 
  2542     if (__isExternalAddressLike(value)) {
  2543     if (__isExternalAddressLike(value)) {
  2543 	pointer = __externalAddressVal(value);
  2544         pointer = __externalAddressVal(value);
  2544     } else if (__isExternalBytesLike(value)) {
  2545     } else if (__isExternalBytesLike(value)) {
  2545 	pointer = __externalBytesVal(value);
  2546         pointer = __externalBytesVal(value);
  2546 	if (pointer == (OBJ *)0)
  2547         if (pointer == (OBJ *)0)
  2547 	    pointer = 0;
  2548             pointer = 0;
  2548     } else if (value == nil) {
  2549     } else if (value == nil) {
  2549 	pointer = 0;
  2550         pointer = 0;
  2550     } else if (__isSmallInteger(value)) {
  2551     } else if (__isSmallInteger(value)) {
  2551 	pointer = (OBJ *)__intVal(value);
  2552         pointer = (OBJ *)__intVal(value);
  2552     } else {
  2553     } else {
  2553 	if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) {
  2554         if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) {
  2554 	    goto bad;
  2555             goto bad;
  2555 	}
  2556         }
  2556     }
  2557     }
  2557 
  2558 
  2558     if (__isSmallInteger(index)) {
  2559     if (__isSmallInteger(index)) {
  2559 	unsigned char *cp;
  2560         unsigned char *cp;
  2560 	INT sz;
  2561         INT sz;
  2561 
  2562 
  2562 	__fetchBytePointerAndSize__(self, &cp, &sz);
  2563         __fetchBytePointerAndSize__(self, &cp, &sz);
  2563 	if (cp) {
  2564         if (cp) {
  2564 	    unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1;
  2565             unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1;
  2565 
  2566 
  2566 	    if ((idx+(sizeof(pointer)-1)) < sz) {
  2567             if ((idx+(sizeof(pointer)-1)) < sz) {
  2567 		cp += idx;
  2568                 cp += idx;
  2568 		/*
  2569                 /*
  2569 		 * aligned
  2570                  * aligned
  2570 		 */
  2571                  */
  2571 		if (((INT)cp & (sizeof(pointer)-1)) == 0) {
  2572                 if (((INT)cp & (sizeof(pointer)-1)) == 0) {
  2572 		    ((char **)cp)[0] = (char *) pointer;
  2573                     ((char **)cp)[0] = (char *) pointer;
  2573 		    RETURN (value);
  2574                     RETURN (value);
  2574 		}
  2575                 }
  2575 	    }
  2576             }
  2576 	}
  2577         }
  2577     }
  2578     }
  2578 bad:;
  2579 bad:;
  2579 %}.
  2580 %}.
  2580 
  2581 
  2581     self primitiveFailed.
  2582     self primitiveFailed.
  3154 !
  3155 !
  3155 
  3156 
  3156 signedInt16At:byteIndex MSB:msb
  3157 signedInt16At:byteIndex MSB:msb
  3157     "return the 2-bytes starting at index as a signed Integer.
  3158     "return the 2-bytes starting at index as a signed Integer.
  3158      The index is a smalltalk index (i.e. 1-based).
  3159      The index is a smalltalk index (i.e. 1-based).
  3159      The value is retrieved in the machines natural byte order.
  3160      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
  3160      This may be worth a primitive."
  3161      LSB-first (i.e. low 8-bits at lower byte index) if it's false.
  3161 
  3162      Notice: 
  3162     ^ (self unsignedInt16At:byteIndex MSB:msb) signExtendedShortValue
  3163         the index is a byte index; thus, this allows for unaligned access to
  3163 
  3164         words on any boundary."
  3164     "
  3165 
  3165      |b|
  3166     |b1 "{ Class: SmallInteger }"
  3166      b := ByteArray new:2.
  3167      b2 "{ Class: SmallInteger }"|
  3167      b wordAt:1 put:16rFFFF.
  3168 
  3168      b signedWordAt:1
  3169 %{
  3169     "
  3170     /*
  3170 
  3171      * handle the most common cases fast ...
  3171     "Modified: 1.7.1996 / 21:14:38 / cg"
  3172      */
       
  3173     if (__isSmallInteger(byteIndex)) {
       
  3174         unsigned char *cp;
       
  3175         INT sz;
       
  3176 
       
  3177         __fetchBytePointerAndSize__(self, &cp, &sz);
       
  3178         if (cp) {
       
  3179             unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1;
       
  3180 
       
  3181             if ((idx+(2-1)) < sz) {
       
  3182                 short sVal;
       
  3183 
       
  3184                 cp += idx;
       
  3185                 if (msb == false) {
       
  3186 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
       
  3187                     /*
       
  3188                      * aligned or not, we dont care (i386 can do both)
       
  3189                      */
       
  3190                     sVal = ((short *)cp)[0];
       
  3191 #else
       
  3192                     sVal = (cp[0] & 0xFF) | ((cp[1] & 0xFF) << 8);
       
  3193 #endif
       
  3194                 } else {
       
  3195                     sVal = ((cp[0] & 0xFF) << 8) | (cp[1] & 0xFF);
       
  3196                 }
       
  3197                 RETURN (__mkSmallInteger(sVal));
       
  3198             }
       
  3199         }
       
  3200     }
       
  3201 %}.
       
  3202 
       
  3203     b1 := self byteAt:byteIndex.
       
  3204     b2 := self byteAt:(byteIndex + 1).
       
  3205     msb ifTrue:[
       
  3206         ^ ((b1 bitShift:8) + b2) signExtendedShortValue
       
  3207     ].
       
  3208     ^ ((b2 bitShift:8) + b1) signExtendedShortValue
  3172 !
  3209 !
  3173 
  3210 
  3174 signedInt16At:index put:anInteger
  3211 signedInt16At:index put:anInteger
  3175     "set the 2-bytes starting at index from the signed Integer value.
  3212     "set the 2-bytes starting at index from the signed Integer value.
  3176      The index is a smalltalk index (i.e. 1-based).
  3213      The index is a smalltalk index (i.e. 1-based).
  3188     "
  3225     "
  3189 
  3226 
  3190     "Modified: 1.7.1996 / 21:12:13 / cg"
  3227     "Modified: 1.7.1996 / 21:12:13 / cg"
  3191 !
  3228 !
  3192 
  3229 
  3193 signedInt16At:index put:anInteger MSB:msb
  3230 signedInt16At:byteIndex put:anInteger MSB:msb
  3194     "set the 2-bytes starting at index from the signed Integer value.
  3231     "set the 2-bytes starting at byteIndex from the signed integer value.
  3195      The index is a smalltalk index (i.e. 1-based).
  3232      The byteIndex is a smalltalk index (i.e. 1-based).
  3196      The stored value must be in the range -32768 .. +32676.
  3233      The stored value must be in the range -32768 .. +32676.
  3197      The value is stored MSB-first, if the msb-arg is true;
  3234      The value is stored MSB-first, if the msb-arg is true;
  3198      LSB-first otherwise.
  3235      LSB-first otherwise."
  3199      This may be worth a primitive."
  3236 
  3200 
  3237 %{  /* NOCONTEXT */
  3201     |v|
  3238     /*
  3202 
  3239      * handle the most common case fast ...
       
  3240      */
       
  3241     if (__isSmallInteger(byteIndex)) {
       
  3242         unsigned char *cp;
       
  3243         INT sz;
       
  3244 
       
  3245         __fetchBytePointerAndSize__(self, &cp, &sz);
       
  3246         if (cp) {
       
  3247             unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1;
       
  3248 
       
  3249             if ((idx+1) < sz) {
       
  3250                 cp += idx;
       
  3251 
       
  3252                 if (__isSmallInteger(anInteger)) {
       
  3253                     INT __v = __intVal(anInteger);
       
  3254 
       
  3255                     if ((__v < -0x8000L) || (__v > 0x7FFF)) {
       
  3256                         goto badArg;
       
  3257                     }
       
  3258                     if (msb == false) { 
       
  3259 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
       
  3260                         ((short *)cp)[0] = (short)__v;
       
  3261 #else
       
  3262                         cp[0] = __v & 0xFF;
       
  3263                         cp[1] = (__v >> 8) & 0xFF;
       
  3264 #endif
       
  3265                     } else {        
       
  3266                         cp[0] = (__v >> 8) & 0xFF;
       
  3267                         cp[1] = __v & 0xFF;
       
  3268                     }
       
  3269                     RETURN (anInteger);
       
  3270                 }
       
  3271             }
       
  3272         }
       
  3273     }
       
  3274   badArg: ;
       
  3275 %}.
  3203     anInteger >= 0 ifTrue:[
  3276     anInteger >= 0 ifTrue:[
  3204         v := anInteger
  3277         self unsignedInt16At:byteIndex put:anInteger MSB:msb.
  3205     ] ifFalse:[
  3278     ] ifFalse:[
  3206         v := 16r10000 + anInteger
  3279         self unsignedInt16At:byteIndex put:(16r10000 + anInteger) MSB:msb.
  3207     ].
  3280     ].
  3208     self unsignedInt16At:index put:v MSB:msb.
       
  3209     ^ anInteger
  3281     ^ anInteger
  3210 
  3282 
  3211     "
  3283     "
  3212      |b|
  3284      |b|
  3213      b := ByteArray new:4.
  3285      b := ByteArray new:4.
  3214      b signedWordAt:1 put:-1.
  3286      b signedInt16At:1 put:-1.
  3215      b signedWordAt:3 put:-2.
  3287      b signedInt16At:3 put:-2.
  3216      b inspect
  3288      b inspect
  3217     "
  3289     "
  3218 
  3290 
  3219     "Modified: 1.7.1996 / 21:12:13 / cg"
  3291     "Modified: 1.7.1996 / 21:12:13 / cg"
  3220 !
  3292 !
  3226      Subclasses may redefine this for better performance."
  3298      Subclasses may redefine this for better performance."
  3227 
  3299 
  3228     ^ self unsignedInt16At:index MSB:IsBigEndian
  3300     ^ self unsignedInt16At:index MSB:IsBigEndian
  3229 !
  3301 !
  3230 
  3302 
  3231 unsignedInt16At:index MSB:msb
  3303 unsignedInt16At:byteIndex MSB:msb
  3232     "return the 2-bytes starting at index as an (unsigned) Integer.
  3304     "return the 2-bytes starting at index as an (unsigned) Integer.
  3233      The index is a smalltalk index (i.e. 1-based).
  3305      The index is a smalltalk index (i.e. 1-based).
  3234      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
  3306      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
  3235      LSB-first (i.e. low 8-bits at lower byte index) if its false.
  3307      LSB-first (i.e. low 8-bits at lower byte index) if it's false.
  3236      Notice: 
  3308      Notice: 
  3237         the index is a byte index; thus, this allows for unaligned access to
  3309         the index is a byte index; thus, this allows for unaligned access to
  3238         words on any boundary."
  3310         words on any boundary."
  3239 
  3311 
  3240     |b1 "{ Class: SmallInteger }"
  3312     |b1 "{ Class: SmallInteger }"
  3241      b2 "{ Class: SmallInteger }"|
  3313      b2 "{ Class: SmallInteger }"|
  3242 
  3314 
  3243     b1 := self byteAt:index.
  3315 %{
  3244     b2 := self byteAt:(index + 1).
  3316     /*
       
  3317      * handle the most common cases fast ...
       
  3318      */
       
  3319     if (__isSmallInteger(byteIndex)) {
       
  3320         unsigned char *cp;
       
  3321         INT sz;
       
  3322 
       
  3323         __fetchBytePointerAndSize__(self, &cp, &sz);
       
  3324         if (cp) {
       
  3325             unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1;
       
  3326 
       
  3327             if ((idx+(2-1)) < sz) {
       
  3328                 int iVal;
       
  3329 
       
  3330                 cp += idx;
       
  3331                 if (msb == false) {
       
  3332 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
       
  3333                     /*
       
  3334                      * aligned or not, we dont care (i386 can do both)
       
  3335                      */
       
  3336                     iVal = ((unsigned short *)cp)[0];
       
  3337 #else
       
  3338                     iVal = (cp[0] & 0xFF) | ((cp[1] & 0xFF) << 8);
       
  3339 #endif
       
  3340                 } else {
       
  3341                     iVal = ((cp[0] & 0xFF) << 8) | (cp[1] & 0xFF);
       
  3342                 }
       
  3343                 RETURN (__mkSmallInteger(iVal));
       
  3344             }
       
  3345         }
       
  3346     }
       
  3347 %}.
       
  3348 
       
  3349     b1 := self byteAt:byteIndex.
       
  3350     b2 := self byteAt:(byteIndex + 1).
  3245     msb ifTrue:[
  3351     msb ifTrue:[
  3246         ^ (b1 bitShift:8) + b2
  3352         ^ (b1 bitShift:8) + b2
  3247     ].
  3353     ].
  3248     ^ (b2 bitShift:8) + b1
  3354     ^ (b2 bitShift:8) + b1
  3249 !
  3355 !
  3266 
  3372 
  3267     "Created: / 5.3.1998 / 11:54:52 / stefan"
  3373     "Created: / 5.3.1998 / 11:54:52 / stefan"
  3268     "Modified: / 5.3.1998 / 14:59:38 / stefan"
  3374     "Modified: / 5.3.1998 / 14:59:38 / stefan"
  3269 !
  3375 !
  3270 
  3376 
  3271 unsignedInt16At:index put:anInteger MSB:msb
  3377 unsignedInt16At:byteIndex put:anInteger MSB:msb
  3272     "set the 2-bytes starting at index from the (unsigned) Integer value.
  3378     "set the 2-bytes starting at index from the (unsigned) Integer value.
  3273      The index is a smalltalk index (i.e. 1-based).
  3379      The index is a smalltalk index (i.e. 1-based).
  3274      The stored value must be in the range 0 .. 16rFFFF.
  3380      The stored value must be in the range 0 .. 16rFFFF.
  3275      The value is stored LSB-first (i.e. the low 8bits are stored at the
  3381      The value is stored LSB-first (i.e. the low 8bits are stored at the
  3276      lower index) if msb is false, MSB-first otherwise"
  3382      lower index) if msb is false, MSB-first otherwise"
  3277 
  3383 
  3278     |b1 b2
  3384     |b1 b2
  3279      iVal "{ Class: SmallInteger }"|
  3385      iVal "{ Class: SmallInteger }"|
  3280 
  3386 
       
  3387 %{  /* NOCONTEXT */
       
  3388     /*
       
  3389      * handle the most common case fast ...
       
  3390      */
       
  3391     if (__isSmallInteger(byteIndex)) {
       
  3392         unsigned char *cp;
       
  3393         INT sz;
       
  3394 
       
  3395         __fetchBytePointerAndSize__(self, &cp, &sz);
       
  3396 printf("cp=%"_lx_"\n", (INT)cp);
       
  3397         if (cp) {
       
  3398             unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1;
       
  3399 
       
  3400             if ((idx+1) < sz) {
       
  3401                 cp += idx;
       
  3402 
       
  3403                 if (__isSmallInteger(anInteger)) {
       
  3404                     INT __v = __intVal(anInteger);
       
  3405 
       
  3406                     if (((unsigned INT)__v) > 0xFFFF) {
       
  3407                         goto badArg;
       
  3408                     }
       
  3409                     if (msb == false) { 
       
  3410 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
       
  3411                         ((unsigned short *)cp)[0] = (unsigned short)__v;
       
  3412 #else
       
  3413                         cp[0] = __v & 0xFF;
       
  3414                         cp[1] = (__v >> 8) & 0xFF;
       
  3415 #endif
       
  3416                     } else {        
       
  3417                         cp[0] = (__v >> 8) & 0xFF;
       
  3418                         cp[1] = __v & 0xFF;
       
  3419                     }
       
  3420                     RETURN (anInteger);
       
  3421                 }
       
  3422             }
       
  3423         }
       
  3424     }
       
  3425   badArg: ;
       
  3426 %}.
  3281     iVal := anInteger.
  3427     iVal := anInteger.
  3282     ((iVal < 0) or:[iVal > 16rFFFF]) ifTrue:[
  3428     ((iVal < 0) or:[iVal > 16rFFFF]) ifTrue:[
  3283         ^ self elementBoundsError:iVal
  3429         ^ self elementBoundsError:iVal
  3284     ].
  3430     ].
  3285     msb ifTrue:[
  3431     msb ifTrue:[
  3287         b2 := (iVal bitAnd:16rFF).
  3433         b2 := (iVal bitAnd:16rFF).
  3288     ] ifFalse:[
  3434     ] ifFalse:[
  3289         b1 := (iVal bitAnd:16rFF).
  3435         b1 := (iVal bitAnd:16rFF).
  3290         b2 := ((iVal bitShift:-8) bitAnd:16rFF).
  3436         b2 := ((iVal bitShift:-8) bitAnd:16rFF).
  3291     ].
  3437     ].
  3292     self byteAt:index   put:b1.
  3438     self byteAt:byteIndex   put:b1.
  3293     self byteAt:index+1 put:b2.
  3439     self byteAt:byteIndex+1 put:b2.
  3294     ^ anInteger
  3440     ^ anInteger
  3295 
  3441 
  3296     "
  3442     "
  3297      |b|
  3443      |b|
  3298      b := ByteArray new:8.
  3444      b := ByteArray new:8.
  3299      b unsignedShortAt:1 put:16r0102 bigEndian:false.
  3445      b unsignedInt16At:1 put:16r0102 MSB:false.
  3300      b unsignedShortAt:3 put:16r0304 bigEndian:false.
  3446      b unsignedInt16At:3 put:16r0304 MSB:false.
  3301      b unsignedShortAt:5 put:16r0102 bigEndian:true.
  3447      b unsignedInt16At:5 put:16r0102 MSB:true.
  3302      b unsignedShortAt:7 put:16r0304 bigEndian:true.
  3448      b unsignedInt16At:7 put:16r0304 MSB:true.
  3303      b inspect
  3449      b inspect
  3304     "
  3450     "
  3305 
  3451 
  3306     "Modified: / 21.1.1998 / 17:48:15 / cg"
  3452     "Modified: / 21.1.1998 / 17:48:15 / cg"
  3307     "Modified: / 5.3.1998 / 11:52:28 / stefan"
  3453     "Modified: / 5.3.1998 / 11:52:28 / stefan"
  3316     |stream i "{ Class: SmallInteger }" c|
  3462     |stream i "{ Class: SmallInteger }" c|
  3317 
  3463 
  3318     stream := WriteStream on:(String new:40).
  3464     stream := WriteStream on:(String new:40).
  3319     i := index.
  3465     i := index.
  3320     [(c := self byteAt:i) ~~ 0] whileTrue:[
  3466     [(c := self byteAt:i) ~~ 0] whileTrue:[
  3321 	stream nextPut:(Character value:c).
  3467         stream nextPut:(Character value:c).
  3322 	i := i + 1.
  3468         i := i + 1.
  3323     ].
  3469     ].
  3324     ^ stream contents
  3470     ^ stream contents
  3325 
  3471 
  3326     "
  3472     "
  3327       #[71 72 73 74 75 76 77 0] stringAt:1
  3473       #[71 72 73 74 75 76 77 0] stringAt:1
  3422     stream := WriteStream on:(String new:maxSize).
  3568     stream := WriteStream on:(String new:maxSize).
  3423     start := index.
  3569     start := index.
  3424     max := start + maxSize - 1.
  3570     max := start + maxSize - 1.
  3425 
  3571 
  3426     start to:max do:[:eachIndex|
  3572     start to:max do:[:eachIndex|
  3427 	c := self byteAt:eachIndex.
  3573         c := self byteAt:eachIndex.
  3428 	c == 0 ifTrue:[
  3574         c == 0 ifTrue:[
  3429 	    ^ stream contents
  3575             ^ stream contents
  3430 	].
  3576         ].
  3431 	stream nextPut:(Character value:c).
  3577         stream nextPut:(Character value:c).
  3432     ].
  3578     ].
  3433     ^ stream contents
  3579     ^ stream contents
  3434 
  3580 
  3435     "
  3581     "
  3436       #[71 72 73 74 75 76 77] stringAt:1 size:7
  3582       #[71 72 73 74 75 76 77] stringAt:1 size:7
  3529     |size cls|
  3675     |size cls|
  3530 
  3676 
  3531     cls := self class.
  3677     cls := self class.
  3532 
  3678 
  3533     (cls == ByteArray or:[cls == ImmutableByteArray or:[cls == ExternalBytes]]) ifTrue:[
  3679     (cls == ByteArray or:[cls == ImmutableByteArray or:[cls == ExternalBytes]]) ifTrue:[
  3534 	size := self size.
  3680         size := self size.
  3535 	^ (String uninitializedNew:size) replaceBytesFrom:1 to:size with:self startingAt:1.
  3681         ^ (String uninitializedNew:size) replaceBytesFrom:1 to:size with:self startingAt:1.
  3536     ].
  3682     ].
  3537     ^ super asString.
  3683     ^ super asString.
  3538 
  3684 
  3539     "
  3685     "
  3540       #[16r41 16r42 16r43] asString
  3686       #[16r41 16r42 16r43] asString
  3566     "test:
  3712     "test:
  3567 
  3713 
  3568       |utf8Encoding original readBack|
  3714       |utf8Encoding original readBack|
  3569 
  3715 
  3570       1 to:16rFFFF do:[:ascii |
  3716       1 to:16rFFFF do:[:ascii |
  3571 	original := (Character value:ascii) asString.
  3717         original := (Character value:ascii) asString.
  3572 	utf8Encoding := original utf8Encoded.
  3718         utf8Encoding := original utf8Encoded.
  3573 	readBack := utf8Encoding utf8Decoded.
  3719         readBack := utf8Encoding utf8Decoded.
  3574 	readBack = original ifFalse:[
  3720         readBack = original ifFalse:[
  3575 	    self halt
  3721             self halt
  3576 	]
  3722         ]
  3577       ]
  3723       ]
  3578     "
  3724     "
  3579 !
  3725 !
  3580 
  3726 
  3581 utf8DecodedWithTwoByteCharactersReplacedBy:replacementCharacter
  3727 utf8DecodedWithTwoByteCharactersReplacedBy:replacementCharacter
  3584      and replace them with replacementCharacter"
  3730      and replace them with replacementCharacter"
  3585 
  3731 
  3586     |in out c|
  3732     |in out c|
  3587 
  3733 
  3588     self containsNon7BitAscii ifFalse:[
  3734     self containsNon7BitAscii ifFalse:[
  3589 	^ self asSingleByteString
  3735         ^ self asSingleByteString
  3590     ].
  3736     ].
  3591 
  3737 
  3592     out := WriteStream on:(String uninitializedNew:self size * 3 // 2).
  3738     out := WriteStream on:(String uninitializedNew:self size * 3 // 2).
  3593     in := self readStream.
  3739     in := self readStream.
  3594     [in atEnd] whileFalse:[
  3740     [in atEnd] whileFalse:[
  3595 	c := Character utf8DecodeFrom:in.
  3741         c := Character utf8DecodeFrom:in.
  3596 	c codePoint > 16rFF ifTrue:[
  3742         c codePoint > 16rFF ifTrue:[
  3597 	    c := replacementCharacter
  3743             c := replacementCharacter
  3598 	].
  3744         ].
  3599 	out nextPut:c.
  3745         out nextPut:c.
  3600     ].
  3746     ].
  3601     ^ out contents
  3747     ^ out contents
  3602 
  3748 
  3603     "
  3749     "
  3604      (Character value:16r220) utf8Encoded
  3750      (Character value:16r220) utf8Encoded
  3605 	utf8DecodedWithTwoByteCharactersReplacedBy:(Character space)
  3751         utf8DecodedWithTwoByteCharactersReplacedBy:(Character space)
  3606 
  3752 
  3607      (Character value:16r220) utf8Encoded asExternalBytes copyButLast
  3753      (Character value:16r220) utf8Encoded asExternalBytes copyButLast
  3608 	utf8DecodedWithTwoByteCharactersReplacedBy:(Character space)
  3754         utf8DecodedWithTwoByteCharactersReplacedBy:(Character space)
  3609     "
  3755     "
  3610 ! !
  3756 ! !
  3611 
  3757 
  3612 !UninterpretedBytes methodsFor:'filling & replacing'!
  3758 !UninterpretedBytes methodsFor:'filling & replacing'!
  3613 
  3759 
  3631 #ifndef NO_PRIM_BYTEARR
  3777 #ifndef NO_PRIM_BYTEARR
  3632     if ((__isBytes(aCollection) || __isExternalBytesLike(aCollection))
  3778     if ((__isBytes(aCollection) || __isExternalBytesLike(aCollection))
  3633      && (__isBytes(self) || __isWords(self))
  3779      && (__isBytes(self) || __isWords(self))
  3634      && __bothSmallInteger(start, stop)
  3780      && __bothSmallInteger(start, stop)
  3635      && __isSmallInteger(repStart)) {
  3781      && __isSmallInteger(repStart)) {
  3636 	startIndex = __intVal(start) - 1;
  3782         startIndex = __intVal(start) - 1;
  3637 	if (startIndex >= 0) {
  3783         if (startIndex >= 0) {
  3638 	    dst = (__ByteArrayInstPtr(self)->ba_element) + startIndex;
  3784             dst = (__ByteArrayInstPtr(self)->ba_element) + startIndex;
  3639 	    nIndex = __byteArraySize(self);
  3785             nIndex = __byteArraySize(self);
  3640 
  3786 
  3641 	    if ((cls = __qClass(self)) != @global(ByteArray)) {
  3787             if ((cls = __qClass(self)) != @global(ByteArray)) {
  3642 		int nInst;
  3788                 int nInst;
  3643 
  3789 
  3644 		nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
  3790                 nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
  3645 		dst += nInst;
  3791                 dst += nInst;
  3646 		nIndex -= nInst;
  3792                 nIndex -= nInst;
  3647 	    }
  3793             }
  3648 
  3794 
  3649 	    stopIndex = __intVal(stop) - 1;
  3795             stopIndex = __intVal(stop) - 1;
  3650 	    count = stopIndex - startIndex + 1;
  3796             count = stopIndex - startIndex + 1;
  3651 	    if (count == 0) {
  3797             if (count == 0) {
  3652 		RETURN ( self );
  3798                 RETURN ( self );
  3653 	    }
  3799             }
  3654 
  3800 
  3655 	    if ((count > 0) && (stopIndex < nIndex)) {
  3801             if ((count > 0) && (stopIndex < nIndex)) {
  3656 		repStartIndex = __intVal(repStart) - 1;
  3802                 repStartIndex = __intVal(repStart) - 1;
  3657 		if (repStartIndex >= 0) {
  3803                 if (repStartIndex >= 0) {
  3658 		    if (__isExternalBytesLike(aCollection)) {
  3804                     if (__isExternalBytesLike(aCollection)) {
  3659 			OBJ sz;
  3805                         OBJ sz;
  3660 
  3806 
  3661 			src = __externalAddressVal(aCollection);
  3807                         src = __externalAddressVal(aCollection);
  3662 			if (src == 0) goto fallBack;
  3808                         if (src == 0) goto fallBack;
  3663 
  3809 
  3664 			sz = __externalBytesSize(aCollection);
  3810                         sz = __externalBytesSize(aCollection);
  3665 			if (__isSmallInteger(sz)) {
  3811                         if (__isSmallInteger(sz)) {
  3666 			    repNIndex = __smallIntegerVal(sz);
  3812                             repNIndex = __smallIntegerVal(sz);
  3667 			} else {
  3813                         } else {
  3668 			    repNIndex = repStopIndex+1; /* always enough */
  3814                             repNIndex = repStopIndex+1; /* always enough */
  3669 			}
  3815                         }
  3670 			src = src + repStartIndex;
  3816                         src = src + repStartIndex;
  3671 		    } else {
  3817                     } else {
  3672 			if (__isStringLike(aCollection)) {
  3818                         if (__isStringLike(aCollection)) {
  3673 			    repNIndex = __stringSize(aCollection);
  3819                             repNIndex = __stringSize(aCollection);
  3674 			} else {
  3820                         } else {
  3675 			    repNIndex = __qSize(aCollection) - OHDR_SIZE;
  3821                             repNIndex = __qSize(aCollection) - OHDR_SIZE;
  3676 			}
  3822                         }
  3677 			src = (__ByteArrayInstPtr(aCollection)->ba_element) + repStartIndex;
  3823                         src = (__ByteArrayInstPtr(aCollection)->ba_element) + repStartIndex;
  3678 			if ((cls = __qClass(aCollection)) != @global(ByteArray)) {
  3824                         if ((cls = __qClass(aCollection)) != @global(ByteArray)) {
  3679 			    int nInst;
  3825                             int nInst;
  3680 
  3826 
  3681 			    nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
  3827                             nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
  3682 			    src += nInst;
  3828                             src += nInst;
  3683 			    repNIndex -= nInst;
  3829                             repNIndex -= nInst;
  3684 			}
  3830                         }
  3685 		    }
  3831                     }
  3686 		    repStopIndex = repStartIndex + (stopIndex - startIndex);
  3832                     repStopIndex = repStartIndex + (stopIndex - startIndex);
  3687 		    if (repStopIndex < repNIndex) {
  3833                     if (repStopIndex < repNIndex) {
  3688 			if (aCollection == self) {
  3834                         if (aCollection == self) {
  3689 			    /* take care of overlapping copy */
  3835                             /* take care of overlapping copy */
  3690 			    if (src < dst) {
  3836                             if (src < dst) {
  3691 				/* must do a reverse copy */
  3837                                 /* must do a reverse copy */
  3692 				src += count;
  3838                                 src += count;
  3693 				dst += count;
  3839                                 dst += count;
  3694 				while (count-- > 0) {
  3840                                 while (count-- > 0) {
  3695 				    *--dst = *--src;
  3841                                     *--dst = *--src;
  3696 				}
  3842                                 }
  3697 				RETURN ( self );
  3843                                 RETURN ( self );
  3698 			    }
  3844                             }
  3699 			}
  3845                         }
  3700 
  3846 
  3701 # ifdef bcopy4
  3847 # ifdef bcopy4
  3702 			if (((unsigned INT)src & 3) == ((unsigned INT)dst & 3)) {
  3848                         if (((unsigned INT)src & 3) == ((unsigned INT)dst & 3)) {
  3703 			    int nW;
  3849                             int nW;
  3704 
  3850 
  3705 			    /* copy unaligned part */
  3851                             /* copy unaligned part */
  3706 			    while (count && ((unsigned INT)src & 3)) {
  3852                             while (count && ((unsigned INT)src & 3)) {
  3707 				*dst++ = *src++;
  3853                                 *dst++ = *src++;
  3708 				count--;
  3854                                 count--;
  3709 			    }
  3855                             }
  3710 
  3856 
  3711 			    if (count > 0) {
  3857                             if (count > 0) {
  3712 				/* copy aligned part */
  3858                                 /* copy aligned part */
  3713 				nW = count >> 2;
  3859                                 nW = count >> 2;
  3714 				bcopy4(src, dst, nW);
  3860                                 bcopy4(src, dst, nW);
  3715 				if ((count = count & 3) != 0) {
  3861                                 if ((count = count & 3) != 0) {
  3716 				    /* copy any remaining part */
  3862                                     /* copy any remaining part */
  3717 				    src += (nW<<2);
  3863                                     src += (nW<<2);
  3718 				    dst += (nW<<2);
  3864                                     dst += (nW<<2);
  3719 				    while (count--) {
  3865                                     while (count--) {
  3720 					*dst++ = *src++;
  3866                                         *dst++ = *src++;
  3721 				    }
  3867                                     }
  3722 				}
  3868                                 }
  3723 			    }
  3869                             }
  3724 			    RETURN ( self );
  3870                             RETURN ( self );
  3725 			}
  3871                         }
  3726 # else
  3872 # else
  3727 #  if __POINTER_SIZE__ == 8
  3873 #  if __POINTER_SIZE__ == 8
  3728 			if (((unsigned INT)src & 7) == ((unsigned INT)dst & 7)) {
  3874                         if (((unsigned INT)src & 7) == ((unsigned INT)dst & 7)) {
  3729 			    /* copy unaligned part */
  3875                             /* copy unaligned part */
  3730 			    while (count && ((unsigned INT)src & 7)) {
  3876                             while (count && ((unsigned INT)src & 7)) {
  3731 				*dst++ = *src++;
  3877                                 *dst++ = *src++;
  3732 				count--;
  3878                                 count--;
  3733 			    }
  3879                             }
  3734 
  3880 
  3735 			    /* copy aligned part */
  3881                             /* copy aligned part */
  3736 			    while (count >= 8) {
  3882                             while (count >= 8) {
  3737 				((unsigned INT *)dst)[0] = ((unsigned INT *)src)[0];
  3883                                 ((unsigned INT *)dst)[0] = ((unsigned INT *)src)[0];
  3738 				dst += 8;
  3884                                 dst += 8;
  3739 				src += 8;
  3885                                 src += 8;
  3740 				count -= 8;
  3886                                 count -= 8;
  3741 			    }
  3887                             }
  3742 			    while (count--) {
  3888                             while (count--) {
  3743 				*dst++ = *src++;
  3889                                 *dst++ = *src++;
  3744 			    }
  3890                             }
  3745 			    RETURN ( self );
  3891                             RETURN ( self );
  3746 			}
  3892                         }
  3747 #  endif /* 64bit */
  3893 #  endif /* 64bit */
  3748 # endif /* bcopy4 */
  3894 # endif /* bcopy4 */
  3749 
  3895 
  3750 # ifdef FAST_MEMCPY
  3896 # ifdef FAST_MEMCPY
  3751 			bcopy(src, dst, count);
  3897                         bcopy(src, dst, count);
  3752 # else
  3898 # else
  3753 #  ifdef __UNROLL_LOOPS__
  3899 #  ifdef __UNROLL_LOOPS__
  3754 			while (count >= 8) {
  3900                         while (count >= 8) {
  3755 			    dst[0] = src[0]; dst[1] = src[1];
  3901                             dst[0] = src[0]; dst[1] = src[1];
  3756 			    dst[2] = src[2]; dst[3] = src[3];
  3902                             dst[2] = src[2]; dst[3] = src[3];
  3757 			    dst[4] = src[4]; dst[5] = src[5];
  3903                             dst[4] = src[4]; dst[5] = src[5];
  3758 			    dst[6] = src[6]; dst[7] = src[7];
  3904                             dst[6] = src[6]; dst[7] = src[7];
  3759 			    dst += 8; src += 8;
  3905                             dst += 8; src += 8;
  3760 			    count -= 8;
  3906                             count -= 8;
  3761 			}
  3907                         }
  3762 #  endif /* __UNROLL_LOOPS__ */
  3908 #  endif /* __UNROLL_LOOPS__ */
  3763 			while (count-- > 0) {
  3909                         while (count-- > 0) {
  3764 			    *dst++ = *src++;
  3910                             *dst++ = *src++;
  3765 			}
  3911                         }
  3766 # endif
  3912 # endif
  3767 			RETURN ( self );
  3913                         RETURN ( self );
  3768 		    }
  3914                     }
  3769 		}
  3915                 }
  3770 	    }
  3916             }
  3771 	}
  3917         }
  3772     }
  3918     }
  3773 fallBack: ;
  3919 fallBack: ;
  3774 #endif
  3920 #endif
  3775 %}.
  3921 %}.
  3776     "
  3922     "
  3779     "
  3925     "
  3780     self slowReplaceBytesFrom:start to:stop with:aCollection startingAt:repStart
  3926     self slowReplaceBytesFrom:start to:stop with:aCollection startingAt:repStart
  3781 
  3927 
  3782     "
  3928     "
  3783      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3929      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3784 	copy
  3930         copy
  3785 	    replaceFrom:1 to:8
  3931             replaceFrom:1 to:8
  3786 	    with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3932             with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3787 	    startingAt:1
  3933             startingAt:1
  3788 
  3934 
  3789      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3935      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3790 	copy
  3936         copy
  3791 	    replaceFrom:3 to:10
  3937             replaceFrom:3 to:10
  3792 	    with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3938             with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3793 	    startingAt:1
  3939             startingAt:1
  3794 
  3940 
  3795      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3941      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3796 	copy
  3942         copy
  3797 	    replaceFrom:3 to:4
  3943             replaceFrom:3 to:4
  3798 	    with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3944             with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3799 	    startingAt:1
  3945             startingAt:1
  3800 
  3946 
  3801      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3947      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3802 	copy
  3948         copy
  3803 	    replaceFrom:0 to:9
  3949             replaceFrom:0 to:9
  3804 	    with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3950             with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3805 	    startingAt:1
  3951             startingAt:1
  3806 
  3952 
  3807      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3953      #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
  3808 	copy
  3954         copy
  3809 	    replaceFrom:1 to:10
  3955             replaceFrom:1 to:10
  3810 	    with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3956             with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160]
  3811 	    startingAt:0
  3957             startingAt:0
  3812     "
  3958     "
  3813 !
  3959 !
  3814 
  3960 
  3815 replaceBytesFrom:startIndex with:replacementCollection startingAt:repStartIndex
  3961 replaceBytesFrom:startIndex with:replacementCollection startingAt:repStartIndex
  3816     "replace elements from another collection, which must be
  3962     "replace elements from another collection, which must be
  3818 
  3964 
  3819      Notice: This operation modifies the receiver, NOT a copy;
  3965      Notice: This operation modifies the receiver, NOT a copy;
  3820      therefore the change may affect all others referencing the receiver."
  3966      therefore the change may affect all others referencing the receiver."
  3821 
  3967 
  3822     ^ self
  3968     ^ self
  3823 	replaceBytesFrom:startIndex
  3969         replaceBytesFrom:startIndex
  3824 	to:(startIndex + replacementCollection size - repStartIndex)
  3970         to:(startIndex + replacementCollection size - repStartIndex)
  3825 	with:replacementCollection
  3971         with:replacementCollection
  3826 	startingAt:repStartIndex
  3972         startingAt:repStartIndex
  3827 
  3973 
  3828     "
  3974     "
  3829      args:    startIndex            : <integer>
  3975      args:    startIndex            : <integer>
  3830 	      replacementCollection : <collection of <bytes> >
  3976               replacementCollection : <collection of <bytes> >
  3831 	      repStartIndex         : <integer>
  3977               repStartIndex         : <integer>
  3832 
  3978 
  3833      returns: self
  3979      returns: self
  3834     "
  3980     "
  3835 
  3981 
  3836     "Created: / 27.7.1998 / 16:56:46 / cg"
  3982     "Created: / 27.7.1998 / 16:56:46 / cg"
  3843 
  3989 
  3844      Notice: This operation modifies the receiver, NOT a copy;
  3990      Notice: This operation modifies the receiver, NOT a copy;
  3845      therefore the change may affect all others referencing the receiver."
  3991      therefore the change may affect all others referencing the receiver."
  3846 
  3992 
  3847     ^ self
  3993     ^ self
  3848 	replaceBytesFrom:1
  3994         replaceBytesFrom:1
  3849 	to:(replacementCollection size min:self size)
  3995         to:(replacementCollection size min:self size)
  3850 	with:replacementCollection
  3996         with:replacementCollection
  3851 	startingAt:1
  3997         startingAt:1
  3852 
  3998 
  3853     "
  3999     "
  3854      (ByteArray new:10) replaceBytesWith:'hello'
  4000      (ByteArray new:10) replaceBytesWith:'hello'
  3855      (ByteArray new:10) replaceBytesWith:'hello world bla bla bla'
  4001      (ByteArray new:10) replaceBytesWith:'hello world bla bla bla'
  3856     "
  4002     "
  3865 
  4011 
  3866      Notice: This operation modifies the receiver, NOT a copy;
  4012      Notice: This operation modifies the receiver, NOT a copy;
  3867      therefore the change may affect all others referencing the receiver."
  4013      therefore the change may affect all others referencing the receiver."
  3868 
  4014 
  3869     self class isBytes ifTrue:[
  4015     self class isBytes ifTrue:[
  3870 	((aCollection class == self class)
  4016         ((aCollection class == self class)
  3871 	 or:[aCollection isByteCollection]) ifTrue:[
  4017          or:[aCollection isByteCollection]) ifTrue:[
  3872 	    ^ self replaceBytesFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex
  4018             ^ self replaceBytesFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex
  3873 	].
  4019         ].
  3874     ].
  4020     ].
  3875     ^ super replaceFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex
  4021     ^ super replaceFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex
  3876 
  4022 
  3877     "
  4023     "
  3878      args:    startIndex            : <integer>
  4024      args:    startIndex            : <integer>
  3879 	      stopIndex             : <integer>
  4025               stopIndex             : <integer>
  3880 	      replacementCollection : <collection of <bytes> >
  4026               replacementCollection : <collection of <bytes> >
  3881 	      repStartIndex         : <integer>
  4027               repStartIndex         : <integer>
  3882 
  4028 
  3883      returns: self
  4029      returns: self
  3884     "
  4030     "
  3885 
  4031 
  3886     "Modified: / 08-05-2012 / 13:23:27 / cg"
  4032     "Modified: / 08-05-2012 / 13:23:27 / cg"
  3892     "compute and answer the SmallInteger-Hash of the bytes
  4038     "compute and answer the SmallInteger-Hash of the bytes
  3893      from startIndex to endIndex.
  4039      from startIndex to endIndex.
  3894      If endindex = 0 or endIndex > size, hash up the size.
  4040      If endindex = 0 or endIndex > size, hash up the size.
  3895 
  4041 
  3896      NOTE: startIndex and endIndex are only hints about what should be hashed.
  4042      NOTE: startIndex and endIndex are only hints about what should be hashed.
  3897 	   In fact, more bytes could be involved in hashing.
  4043            In fact, more bytes could be involved in hashing.
  3898 	   SO ARRAYS MUST BE EQUAL TO HASH TO THE SAME VALUE"
  4044            SO ARRAYS MUST BE EQUAL TO HASH TO THE SAME VALUE"
  3899 
  4045 
  3900     |w|
  4046     |w|
  3901 
  4047 
  3902 %{
  4048 %{
  3903     if (__bothSmallInteger(startIndex, endIndex)) {
  4049     if (__bothSmallInteger(startIndex, endIndex)) {
  3904 	unsigned char *cp;
  4050         unsigned char *cp;
  3905 	INT sz;
  4051         INT sz;
  3906 
  4052 
  3907 	__fetchBytePointerAndSize__(self, &cp, &sz);
  4053         __fetchBytePointerAndSize__(self, &cp, &sz);
  3908 	if (cp) {
  4054         if (cp) {
  3909 	    INT sidx = ((unsigned INT)__smallIntegerVal(startIndex)) - 1;
  4055             INT sidx = ((unsigned INT)__smallIntegerVal(startIndex)) - 1;
  3910 	    INT eidx = ((unsigned INT)__smallIntegerVal(endIndex)) - 1;
  4056             INT eidx = ((unsigned INT)__smallIntegerVal(endIndex)) - 1;
  3911 	    unsigned char *ep;
  4057             unsigned char *ep;
  3912 	    unsigned INT hash = 0, hash2 = 0, carry;
  4058             unsigned INT hash = 0, hash2 = 0, carry;
  3913 	    int i;
  4059             int i;
  3914 
  4060 
  3915 	    if (eidx < 0 || eidx >= sz) eidx = sz - 1;
  4061             if (eidx < 0 || eidx >= sz) eidx = sz - 1;
  3916 	    if (sidx > eidx) sidx = eidx;
  4062             if (sidx > eidx) sidx = eidx;
  3917 	    if (sidx < 0) {
  4063             if (sidx < 0) {
  3918 		RETURN(__mkSmallInteger(0));
  4064                 RETURN(__mkSmallInteger(0));
  3919 	    }
  4065             }
  3920 
  4066 
  3921 	    ep = cp + eidx;
  4067             ep = cp + eidx;
  3922 	    cp += sidx;
  4068             cp += sidx;
  3923 
  4069 
  3924 #if 0
  4070 #if 0
  3925 	    /*
  4071             /*
  3926 	     * On LSB-First (little endian) cpus,
  4072              * On LSB-First (little endian) cpus,
  3927 	     * this code does not produce the same result
  4073              * this code does not produce the same result
  3928 	     * if the same bytes are at different positions
  4074              * if the same bytes are at different positions
  3929 	     */
  4075              */
  3930 
  4076 
  3931 	    if ((INT)cp & (sizeof(INT)-1)) {
  4077             if ((INT)cp & (sizeof(INT)-1)) {
  3932 		/* not aligned */
  4078                 /* not aligned */
  3933 
  4079 
  3934 		for (i=0; cp <= ep; cp++) {
  4080                 for (i=0; cp <= ep; cp++) {
  3935 		    hash2 = (hash2 << 8) | *cp;
  4081                     hash2 = (hash2 << 8) | *cp;
  3936 		    if (++i == sizeof(INT)) {
  4082                     if (++i == sizeof(INT)) {
  3937 			hash ^= hash2;
  4083                         hash ^= hash2;
  3938 			i = hash2 = 0;
  4084                         i = hash2 = 0;
  3939 		    }
  4085                     }
  3940 		}
  4086                 }
  3941 	    } else {
  4087             } else {
  3942 		/* aligned */
  4088                 /* aligned */
  3943 		for (; cp+sizeof(INT) <= ep; cp += sizeof(INT)) {
  4089                 for (; cp+sizeof(INT) <= ep; cp += sizeof(INT)) {
  3944 		    hash ^= *(unsigned INT *)cp;
  4090                     hash ^= *(unsigned INT *)cp;
  3945 		}
  4091                 }
  3946 		for (; cp <= ep; cp++) {
  4092                 for (; cp <= ep; cp++) {
  3947 		    hash2 = (hash2 << 8) | *cp;
  4093                     hash2 = (hash2 << 8) | *cp;
  3948 		}
  4094                 }
  3949 	    }
  4095             }
  3950 #else
  4096 #else
  3951 	    for (i=0; cp <= ep-sizeof(INT); cp += sizeof(INT)) {
  4097             for (i=0; cp <= ep-sizeof(INT); cp += sizeof(INT)) {
  3952 		hash2 = cp[0];
  4098                 hash2 = cp[0];
  3953 		hash2 = (hash2 << 8) | cp[1];
  4099                 hash2 = (hash2 << 8) | cp[1];
  3954 		hash2 = (hash2 << 8) | cp[2];
  4100                 hash2 = (hash2 << 8) | cp[2];
  3955 		hash2 = (hash2 << 8) | cp[3];
  4101                 hash2 = (hash2 << 8) | cp[3];
  3956 #if __POINTER_SIZE__ == 8
  4102 #if __POINTER_SIZE__ == 8
  3957 		hash2 = (hash2 << 8) | cp[4];
  4103                 hash2 = (hash2 << 8) | cp[4];
  3958 		hash2 = (hash2 << 8) | cp[5];
  4104                 hash2 = (hash2 << 8) | cp[5];
  3959 		hash2 = (hash2 << 8) | cp[6];
  4105                 hash2 = (hash2 << 8) | cp[6];
  3960 		hash2 = (hash2 << 8) | cp[7];
  4106                 hash2 = (hash2 << 8) | cp[7];
  3961 #endif
  4107 #endif
  3962 		/*
  4108                 /*
  3963 		 * multiply by large prime to scramble bits and
  4109                  * multiply by large prime to scramble bits and
  3964 		 * to avoid a 0 result from
  4110                  * to avoid a 0 result from
  3965 		 * #[1 2 3 4 1 2 3 4] computeXorHashFrom:1 to:8.
  4111                  * #[1 2 3 4 1 2 3 4] computeXorHashFrom:1 to:8.
  3966 		 */
  4112                  */
  3967 		hash ^= (hash * 31415821) ^ hash2;
  4113                 hash ^= (hash * 31415821) ^ hash2;
  3968 	    }
  4114             }
  3969 	    for (hash2 = 0; cp <= ep; cp++) {
  4115             for (hash2 = 0; cp <= ep; cp++) {
  3970 		hash2 = (hash2 << 8) | *cp;
  4116                 hash2 = (hash2 << 8) | *cp;
  3971 	    }
  4117             }
  3972 #endif
  4118 #endif
  3973 	    hash ^= (hash * 31415821) ^ hash2;
  4119             hash ^= (hash * 31415821) ^ hash2;
  3974 
  4120 
  3975 	    /*
  4121             /*
  3976 	     * fold the high bits not fitting into a SmallInteger
  4122              * fold the high bits not fitting into a SmallInteger
  3977 	     */
  4123              */
  3978 	    carry = hash & ~_MAX_INT;
  4124             carry = hash & ~_MAX_INT;
  3979 	    if (carry) {
  4125             if (carry) {
  3980 		hash = (hash & _MAX_INT) ^ (carry >> 8);
  4126                 hash = (hash & _MAX_INT) ^ (carry >> 8);
  3981 	    }
  4127             }
  3982 
  4128 
  3983 	    RETURN(__mkSmallInteger(hash));
  4129             RETURN(__mkSmallInteger(hash));
  3984 	}
  4130         }
  3985     }
  4131     }
  3986 %}.
  4132 %}.
  3987 
  4133 
  3988     ^ self primitiveFailed
  4134     ^ self primitiveFailed
  3989 
  4135 
  4054 
  4200 
  4055     |first|
  4201     |first|
  4056 
  4202 
  4057     first := true.
  4203     first := true.
  4058     1 to:self size do:[:idx |
  4204     1 to:self size do:[:idx |
  4059 	aSeparatorStringOrCharacterOrNil notNil ifTrue:[
  4205         aSeparatorStringOrCharacterOrNil notNil ifTrue:[
  4060 	    first ifFalse:[
  4206             first ifFalse:[
  4061 		aSeparatorStringOrCharacterOrNil printOn:aStream
  4207                 aSeparatorStringOrCharacterOrNil printOn:aStream
  4062 	    ] ifTrue:[
  4208             ] ifTrue:[
  4063 		first := false.
  4209                 first := false.
  4064 	    ].
  4210             ].
  4065 	].
  4211         ].
  4066 	(self byteAt:idx) printOn:aStream base:16 size:2 fill:$0.
  4212         (self byteAt:idx) printOn:aStream base:16 size:2 fill:$0.
  4067     ].
  4213     ].
  4068 
  4214 
  4069     "
  4215     "
  4070       #[1 2 3 4 10 17] hexPrintOn:Transcript withSeparator:$:
  4216       #[1 2 3 4 10 17] hexPrintOn:Transcript withSeparator:$:
  4071       #[1 2 3 4 10 17] hexPrintOn:Transcript withSeparator:(Character space)
  4217       #[1 2 3 4 10 17] hexPrintOn:Transcript withSeparator:(Character space)
  4090 
  4236 
  4091 hexPrintStringWithSeparator:aSeparatorStringOrCharacterOrNil
  4237 hexPrintStringWithSeparator:aSeparatorStringOrCharacterOrNil
  4092     "print as hex string, eg: 'FF:02:43'."
  4238     "print as hex string, eg: 'FF:02:43'."
  4093 
  4239 
  4094     ^ String
  4240     ^ String
  4095 	streamContents:[:s |
  4241         streamContents:[:s |
  4096 	    self hexPrintOn:s withSeparator:aSeparatorStringOrCharacterOrNil.
  4242             self hexPrintOn:s withSeparator:aSeparatorStringOrCharacterOrNil.
  4097 	]
  4243         ]
  4098 
  4244 
  4099     "
  4245     "
  4100       #[1 2 3 4 10 17] hexPrintStringWithSeparator:$:
  4246       #[1 2 3 4 10 17] hexPrintStringWithSeparator:$:
  4101       #[1 2 3 4 10 17] hexPrintStringWithSeparator:Character space
  4247       #[1 2 3 4 10 17] hexPrintStringWithSeparator:Character space
  4102       #[1 2 3 4 10 17] hexPrintStringWithSeparator:' - '
  4248       #[1 2 3 4 10 17] hexPrintStringWithSeparator:' - '
  4161 referencesAny:aCollection
  4307 referencesAny:aCollection
  4162     "redefined to speed up searching when many of my instances are present"
  4308     "redefined to speed up searching when many of my instances are present"
  4163 
  4309 
  4164 %{ /* NOCONTEXT */
  4310 %{ /* NOCONTEXT */
  4165     if (__mkSmallInteger(0) == __ClassInstPtr(__qClass(self))->c_ninstvars) {
  4311     if (__mkSmallInteger(0) == __ClassInstPtr(__qClass(self))->c_ninstvars) {
  4166 	/* I am only bytes */
  4312         /* I am only bytes */
  4167 	RETURN(false)
  4313         RETURN(false)
  4168     }
  4314     }
  4169 %}.
  4315 %}.
  4170     ^ super referencesAny:aCollection
  4316     ^ super referencesAny:aCollection
  4171 
  4317 
  4172     "
  4318     "
  4173 	'abc' referencesAny:#()
  4319         'abc' referencesAny:#()
  4174     "
  4320     "
  4175 !
  4321 !
  4176 
  4322 
  4177 sizeInBytes
  4323 sizeInBytes
  4178     "return the number of 8-bit bytes in the receiver.
  4324     "return the number of 8-bit bytes in the receiver.