ByteArray.st
branchjv
changeset 19354 ec77be1507a3
parent 19225 9e8abf62f932
parent 19350 6eb57a6369be
child 19412 1e842c25e51e
equal deleted inserted replaced
19353:2b04ee017e72 19354:ec77be1507a3
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1989 by Claus Gittinger
     4  COPYRIGHT (c) 1989 by Claus Gittinger
     3 	      All Rights Reserved
     5 	      All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   511     ^ super basicAt:index put:value
   513     ^ super basicAt:index put:value
   512 ! !
   514 ! !
   513 
   515 
   514 !ByteArray methodsFor:'accessing-longs'!
   516 !ByteArray methodsFor:'accessing-longs'!
   515 
   517 
   516 doubleWordAt:index put:value
   518 unsignedInt32At:index put:value
   517     "set the 4-bytes starting at index from the (unsigned) Integer value.
   519     "set the 4-bytes starting at index from the (unsigned) Integer value.
   518      The value should be in the range 0 to 16rFFFFFFFF
   520      The value should be in the range 0 to 16rFFFFFFFF
   519      (for negative values, the stored value is not defined).
   521      (for negative values, the stored value is not defined).
   520      The value is stored in the machines natural byte order.
   522      The value is stored in the machine's natural byte order.
   521      Q: should it store signed values ? (see ByteArray signedDoubleWordAt:put:)"
   523      Q: should it store signed values ? (see ByteArray signedDoubleWordAt:put:)"
   522 
   524 
   523     |t|
   525     |t|
   524 
   526 
   525 %{  /* NOCONTEXT */
   527 %{  /* NOCONTEXT */
   526 
   528 
   527     REGISTER int indx;
   529     REGISTER int indx;
   528     int nIndex;
   530     int nIndex;
   529     union {
   531     union {
   530 	unsigned char u_char[4];
   532         unsigned char u_char[4];
   531 	unsigned int u_uint;
   533         unsigned int u_uint;
   532     } val;
   534     } val;
   533     OBJ cls;
   535     OBJ cls;
   534     unsigned char *byteP;
   536     unsigned char *byteP;
   535 
   537 
   536     if (__isSmallInteger(index)) {
   538     if (__isSmallInteger(index)) {
   537 	if (__isSmallInteger(value)) {
   539         if (__isSmallInteger(value)) {
   538 	    val.u_uint = __intVal(value);
   540             val.u_uint = __intVal(value);
   539 	} else {
   541         } else {
   540 	    val.u_uint = __longIntVal(value);
   542             val.u_uint = __longIntVal(value);
   541 	    if (val.u_uint == 0) goto error;
   543             if (val.u_uint == 0) goto error;
   542 	}
   544         }
   543 
   545 
   544 	indx = __intVal(index);
   546         indx = __intVal(index);
   545 	if (indx > 0) {
   547         if (indx > 0) {
   546 	    if ((cls = __qClass(self)) != @global(ByteArray))
   548             if ((cls = __qClass(self)) != @global(ByteArray))
   547 		indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
   549                 indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
   548 	    nIndex = __qSize(self) - OHDR_SIZE;
   550             nIndex = __qSize(self) - OHDR_SIZE;
   549 	    if ((indx+3) <= nIndex) {
   551             if ((indx+3) <= nIndex) {
   550 		byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   552                 byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   551 #if defined(__i386__) || defined(UNALIGNED_FETCH_OK)
   553 #if defined(__i386__) || defined(UNALIGNED_FETCH_OK)
   552 		((unsigned int *)byteP)[0] = val.u_uint;
   554                 ((unsigned int *)byteP)[0] = val.u_uint;
   553 #else
   555 #else
   554 		if (((unsigned INT)byteP & 3) == 0) {
   556                 if (((unsigned INT)byteP & 3) == 0) {
   555 		    ((unsigned int *)byteP)[0] = val.u_uint;
   557                     ((unsigned int *)byteP)[0] = val.u_uint;
   556 		} else {
   558                 } else {
   557 		    byteP[0] = val.u_char[0];
   559                     byteP[0] = val.u_char[0];
   558 		    byteP[1] = val.u_char[1];
   560                     byteP[1] = val.u_char[1];
   559 		    byteP[2] = val.u_char[2];
   561                     byteP[2] = val.u_char[2];
   560 		    byteP[3] = val.u_char[3];
   562                     byteP[3] = val.u_char[3];
   561 		}
   563                 }
   562 #endif
   564 #endif
   563 		RETURN ( value );
   565                 RETURN ( value );
   564 	    }
   566             }
   565 	}
   567         }
   566     }
   568     }
   567   error: ;
   569   error: ;
   568 %}.
   570 %}.
   569     ^ super doubleWordAt:index put:value.
   571     ^ super unsignedInt32At:index put:value.
   570 
   572 
   571     "
   573     "
   572      |b|
   574      |b|
   573      b := ByteArray new:4.
   575      b := ByteArray new:4.
   574      b doubleWordAt:1 put:16r04030201.
   576      b unsignedInt32At:1 put:16r04030201.
   575      b inspect
   577      b inspect
   576     "
   578     "
   577 !
   579 !
   578 
   580 
   579 doubleWordAt:index put:value MSB:msb
   581 unsignedInt32At:index put:value MSB:msb
   580     "set the 4-bytes starting at index from the (unsigned) Integer value.
   582     "set the 4-bytes starting at index from the (unsigned) Integer value.
   581      The value must be in the range 0 to 16rFFFFFFFF.
   583      The value must be in the range 0 to 16rFFFFFFFF.
   582      The value is stored MSB-first if msb is true; LSB-first otherwise.
   584      The value is stored MSB-first if msb is true; LSB-first otherwise.
   583      question: should it store signed values ? (see ByteArray signedDoubleWordAt:put:)"
   585      question: should it store signed values ? (see ByteArray signedDoubleWordAt:put:)"
   584 
   586 
   591     int val;
   593     int val;
   592     OBJ cls;
   594     OBJ cls;
   593     unsigned char *byteP;
   595     unsigned char *byteP;
   594 
   596 
   595     if (__isSmallInteger(index)) {
   597     if (__isSmallInteger(index)) {
   596 	if (__isSmallInteger(value)) {
   598         if (__isSmallInteger(value)) {
   597 	    val = __intVal(value);
   599             val = __intVal(value);
   598 	} else {
   600         } else {
   599 	    val = __longIntVal(value);
   601             val = __longIntVal(value);
   600 	    if (val == 0) goto error;
   602             if (val == 0) goto error;
   601 	}
   603         }
   602 	indx = __intVal(index);
   604         indx = __intVal(index);
   603 	if (indx > 0) {
   605         if (indx > 0) {
   604 	    if ((cls = __qClass(self)) != @global(ByteArray))
   606             if ((cls = __qClass(self)) != @global(ByteArray))
   605 		indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
   607                 indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
   606 	    nIndex = __qSize(self) - OHDR_SIZE;
   608             nIndex = __qSize(self) - OHDR_SIZE;
   607 	    if ((indx+3) <= nIndex) {
   609             if ((indx+3) <= nIndex) {
   608 		byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   610                 byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   609 		if (msb == true) {
   611                 if (msb == true) {
   610 		    /*
   612                     /*
   611 		     * most significant byte first (i.e sparc order)
   613                      * most significant byte first (i.e sparc order)
   612 		     */
   614                      */
   613 #if defined(__MSBFIRST__)
   615 #if defined(__MSBFIRST__)
   614 		    if (((INT)byteP & 3) == 0) {
   616                     if (((INT)byteP & 3) == 0) {
   615 			((int *)byteP)[0] = val;
   617                         ((int *)byteP)[0] = val;
   616 		    } else
   618                     } else
   617 #endif
   619 #endif
   618 		    {
   620                     {
   619 			byteP[3] = val & 0xFF;
   621                         byteP[3] = val & 0xFF;
   620 			val >>= 8;
   622                         val >>= 8;
   621 			byteP[2] = val & 0xFF;
   623                         byteP[2] = val & 0xFF;
   622 			val >>= 8;
   624                         val >>= 8;
   623 			byteP[1] = val & 0xFF;
   625                         byteP[1] = val & 0xFF;
   624 			val >>= 8;
   626                         val >>= 8;
   625 			byteP[0] = val & 0xFF;
   627                         byteP[0] = val & 0xFF;
   626 		    }
   628                     }
   627 		} else {
   629                 } else {
   628 		    /*
   630                     /*
   629 		     * least significant byte first (i.e i386/alpha order)
   631                      * least significant byte first (i.e i386/alpha order)
   630 		     */
   632                      */
   631 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
   633 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK))
   632 		    ((int *)byteP)[0] = val;
   634                     ((int *)byteP)[0] = val;
   633 #else
   635 #else
   634 # if defined(__LSBFIRST__)
   636 # if defined(__LSBFIRST__)
   635 		    if (((unsigned INT)byteP & 3) == 0) {
   637                     if (((unsigned INT)byteP & 3) == 0) {
   636 			((int *)byteP)[0] = val;
   638                         ((int *)byteP)[0] = val;
   637 		    } else
   639                     } else
   638 # endif
   640 # endif
   639 		    {
   641                     {
   640 			byteP[0] = val & 0xFF;
   642                         byteP[0] = val & 0xFF;
   641 			val >>= 8;
   643                         val >>= 8;
   642 			byteP[1] = val & 0xFF;
   644                         byteP[1] = val & 0xFF;
   643 			val >>= 8;
   645                         val >>= 8;
   644 			byteP[2] = val & 0xFF;
   646                         byteP[2] = val & 0xFF;
   645 			val >>= 8;
   647                         val >>= 8;
   646 			byteP[3] = val & 0xFF;
   648                         byteP[3] = val & 0xFF;
   647 		    }
   649                     }
   648 #endif
   650 #endif
   649 		}
   651                 }
   650 		RETURN ( value );
   652                 RETURN ( value );
   651 	    }
   653             }
   652 	}
   654         }
   653     }
   655     }
   654   error: ;
   656   error: ;
   655 %}.
   657 %}.
   656     ^ super doubleWordAt:index put:value MSB:msb
   658     ^ super unsignedInt32At:index put:value MSB:msb
   657 
   659 
   658     "
   660     "
   659      |b|
   661      |b|
   660      b := ByteArray new:8.
   662      b := ByteArray new:8.
   661      b doubleWordAt:1 put:16r04030201 MSB:true.
   663      b unsignedInt32At:1 put:16r04030201 MSB:true.
   662      b doubleWordAt:5 put:16r04030201 MSB:false.
   664      b unsignedInt32At:5 put:16r04030201 MSB:false.
   663      b inspect
   665      b inspect
   664     "
   666     "
   665 ! !
   667 ! !
   666 
   668 
   667 !ByteArray methodsFor:'accessing-shorts'!
   669 !ByteArray methodsFor:'accessing-shorts'!
   668 
   670 
   669 wordAt:index
   671 unsignedInt16At:index
   670     "return the 2-bytes starting at index as an (unsigned) Integer.
   672     "return the 2-bytes starting at index as an (unsigned) Integer.
   671      The value is retrieved in the machines natural byte order
   673      The value is retrieved in the machine's natural byte order
   672      Notice: 
   674      Notice: 
   673         the index is a byte index; thus, this allows for unaligned access to
   675         the index is a byte index; thus, this allows for unaligned access to
   674         words on any boundary.
   676         words on any boundary.
   675      Question: should it be retrieve signed values ? (see ByteArray>>signedWordAt:)"
   677      Question: should it be retrieve signed values ? (see ByteArray>>signedWordAt:)"
   676 
   678 
   693             if ((indx+1) <= nIndex) {
   695             if ((indx+1) <= nIndex) {
   694                 byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   696                 byteP = (unsigned char *)(__ByteArrayInstPtr(self)->ba_element) + indx - 1;
   695 #if defined(__i386__) || defined(UNALIGNED_FETCH_OK)
   697 #if defined(__i386__) || defined(UNALIGNED_FETCH_OK)
   696                 val.u_ushort = ((unsigned short *)byteP)[0];
   698                 val.u_ushort = ((unsigned short *)byteP)[0];
   697 #else
   699 #else
   698                 /*
   700                 val.u_char[0] = byteP[0];
   699                  * mhmh to be measured:
   701                 val.u_char[1] = byteP[1];
   700                  *   the if may hurt more than the additional
       
   701                  *   memory cycles on some machines ...
       
   702                  */
       
   703                 if (((INT)byteP & 1) == 0) {
       
   704                     /* aligned */
       
   705                     val.u_ushort = ((unsigned short *)byteP)[0];
       
   706                 } else {
       
   707                     val.u_char[0] = byteP[0];
       
   708                     val.u_char[1] = byteP[1];
       
   709                 }
       
   710 #endif
   702 #endif
   711                 RETURN ( __mkSmallInteger((val.u_ushort)) );
   703                 RETURN ( __mkSmallInteger((val.u_ushort)) );
   712             }
   704             }
   713         }
   705         }
   714     }
   706     }
   715 %}.
   707 %}.
   716     ^ super wordAt:index
   708     ^ super unsignedInt16At:index
   717 !
   709 !
   718 
   710 
   719 wordAt:index MSB:msb
   711 unsignedInt16At:index MSB:msb
   720     "return the 2-bytes starting at index as an (unsigned) Integer.
   712     "return the 2-bytes starting at index as an (unsigned) Integer.
   721      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
   713      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
   722      LSB-first (i.e. low 8-bits at lower byte index) if its false.
   714      LSB-first (i.e. low 8-bits at lower byte index) if its false.
   723      Notice: 
   715      Notice: 
   724         the index is a byte index; thus, this allows for unaligned access to
   716         the index is a byte index; thus, this allows for unaligned access to
   786                 RETURN ( __mkSmallInteger(val) );
   778                 RETURN ( __mkSmallInteger(val) );
   787             }
   779             }
   788         }
   780         }
   789     }
   781     }
   790 %}.
   782 %}.
   791     ^ super wordAt:index MSB:msb
   783     ^ super unsignedInt16At:index MSB:msb
   792 !
   784 !
   793 
   785 
   794 wordAt:index put:value
   786 unsignedInt16At:index put:value
   795     "set the 2-bytes starting at index from the (unsigned) Integer value.
   787     "set the 2-bytes starting at index from the (unsigned) Integer value.
   796      The stored value must be in the range 0 .. 16rFFFF.
   788      The stored value must be in the range 0 .. 16rFFFF.
   797      The value is stored in the machines natural byteorder,
   789      The value is stored in the machine's natural byteorder,
   798      i.e. this method should only be used to fill byteArrays which are
   790      i.e. this method should only be used to fill byteArrays which are
   799      used internally (not passed to other machines).
   791      used internally (not passed to other machines).
   800      Notice: 
   792      Notice: 
   801         the index is a byte index; thus, this allows for unaligned access to
   793         the index is a byte index; thus, this allows for unaligned access to
   802         words on any boundary.
   794         words on any boundary.
   843                 }
   835                 }
   844             }
   836             }
   845         }
   837         }
   846     }
   838     }
   847 %}.
   839 %}.
   848     ^ super wordAt:index put:value
   840     ^ super unsignedInt16At:index put:value
   849 
   841 
   850     "
   842     "
   851      |b|
   843      |b|
   852      b := ByteArray new:4.
   844      b := ByteArray new:4.
   853      b wordAt:1 put:16r0102.
   845      b unsignedInt16At:1 put:16r0102.
   854      b wordAt:3 put:16r0304.
   846      b unsignedInt16At:3 put:16r0304.
   855      b inspect
   847      b inspect
   856     "
   848     "
   857 !
   849 !
   858 
   850 
   859 wordAt:index put:value MSB:msb
   851 unsignedInt16At:index put:value MSB:msb
   860     "set the 2-bytes starting at index from the (unsigned) Integer value.
   852     "set the 2-bytes starting at index from the (unsigned) Integer value.
   861      The stored value must be in the range 0 .. 16rFFFF.
   853      The stored value must be in the range 0 .. 16rFFFF.
   862      The value is stored LSB-first (i.e. the low 8bits are stored at the
   854      The value is stored LSB-first (i.e. the low 8bits are stored at the
   863      lower index) if msb is false, MSB-first otherwise.
   855      lower index) if msb is false, MSB-first otherwise.
   864      Notice: 
   856      Notice: 
   931                 }
   923                 }
   932             }
   924             }
   933         }
   925         }
   934     }
   926     }
   935 %}.
   927 %}.
   936     ^ super wordAt:index put:value MSB:msb
   928     ^ super unsignedInt16At:index put:value MSB:msb
   937 
   929 
   938     "
   930     "
   939      |b|
   931      |b|
   940      b := ByteArray new:8.
   932      b := ByteArray new:8.
   941      b wordAt:1 put:16r0102 MSB:false.
   933      b unsignedInt16At:1 put:16r0102 MSB:false.
   942      b wordAt:3 put:16r0304 MSB:false.
   934      b unsignedInt16At:3 put:16r0304 MSB:false.
   943      b wordAt:5 put:16r0102 MSB:true.
   935      b unsignedInt16At:5 put:16r0102 MSB:true.
   944      b wordAt:7 put:16r0304 MSB:true.
   936      b unsignedInt16At:7 put:16r0304 MSB:true.
   945      b inspect
   937      b inspect
   946     "
   938     "
   947 ! !
   939 ! !
   948 
   940 
   949 
   941 
  2989     "
  2981     "
  2990      #[1 2 3 1 2 3 1 2 3 1 2 3 4 5 6 4 5 6] usedValues
  2982      #[1 2 3 1 2 3 1 2 3 1 2 3 4 5 6 4 5 6] usedValues
  2991     "
  2983     "
  2992 ! !
  2984 ! !
  2993 
  2985 
  2994 
       
  2995 !ByteArray methodsFor:'searching'!
  2986 !ByteArray methodsFor:'searching'!
  2996 
  2987 
  2997 indexOf:aByte startingAt:start
  2988 indexOf:aByte startingAt:start
  2998     "return the index of the first occurrence of the argument, aByte
  2989     "return the index of the first occurrence of the argument, aByte
  2999      in the receiver starting at start, anInteger; return 0 if not found.
  2990      in the receiver starting at start, anInteger; return 0 if not found.
  3055     "
  3046     "
  3056      #[1 2 3 4 5 6 7 8 9 0 1 2 3 4 5] indexOf:0 startingAt:1
  3047      #[1 2 3 4 5 6 7 8 9 0 1 2 3 4 5] indexOf:0 startingAt:1
  3057     "
  3048     "
  3058 ! !
  3049 ! !
  3059 
  3050 
  3060 
       
  3061 !ByteArray methodsFor:'testing'!
  3051 !ByteArray methodsFor:'testing'!
  3062 
  3052 
  3063 isByteArray
  3053 isByteArray
  3064     "return true, if the receiver is some kind of bytearray;
  3054     "return true, if the receiver is some kind of bytearray;
  3065      true is returned here - the method is redefined from Object."
  3055      true is returned here - the method is redefined from Object."