UninterpretedBytes.st
changeset 3433 a94725308432
parent 3410 93393f1c1022
child 3434 d04ff3256ebb
--- a/UninterpretedBytes.st	Fri May 08 15:24:35 1998 +0200
+++ b/UninterpretedBytes.st	Fri May 08 15:26:50 1998 +0200
@@ -17,6 +17,43 @@
 	category:'Collections-Abstract'
 !
 
+!UninterpretedBytes primitiveDefinitions!
+%{
+/*
+ * Notice: I am abstract, and my subclasses may be anything.
+ * Therefore, the code must always handle the fallback case
+ * where the receiver is neither an ExternalBytes nor a ByteArray.
+ * (which are, however, the most common)
+ *
+ * macro to fetch my byte address and size-in-bytes;
+ * convenient for inline-C code.
+ * (yes, C is bad ...)
+ */
+#define __fetchBytePointerAndSize__(o, pPtr, pSize) \
+    {\
+      if (__isNonNilObject(o)) { \
+        if (__qClass(o) == ByteArray) { \
+	  *(pPtr) = (char *)__ByteArrayInstPtr(o)->ba_element; \
+	  *(pSize) = __byteArraySize(o); \
+	} else if (__qClass(o) == ExternalBytes) { \
+	  OBJ __sz__ = __externalBytesSize(o); \
+	  if (__isSmallInteger(__sz__)) { \
+	    *(pSize) = __intVal(__sz__); \
+	    *(pPtr) = (char *)(__externalBytesAddress(o)); \
+	  } else { \
+	    *(pPtr) = (char *)0; \
+	  } \
+	} else { \
+	    *(pPtr) = (char *)0; \
+	} \
+      } else { \
+	*(pPtr) = (char *)0; \
+      } \
+    }
+
+%}
+! !
+
 !UninterpretedBytes class methodsFor:'documentation'!
 
 copyright
@@ -44,14 +81,21 @@
 
     UninterpretedBytes itself is abstract, so no instances of it can be created.
 
-    [author:]
-        Claus Gittinger
-
     [See also:]
         ByteArray String ExternalBytes
 
     [author:]
         Claus Gittinger
+
+    [Notice:]
+	Notice the confusion due to multiple methods with the same
+        functionality (i.e. 'xxxx:MSB:' vs. 'xxxx:bigEndian:').
+        The reason is that at the time this class was written,
+        ST80 sid not offer protocol to specify the byteOrder, and
+        ST/X provided methods ending in 'MSB:' for this.
+        In the meanwhile, VW added protocol ending in 'bigEndian:',
+	which has been added here for compatibility.
+	(certainly a point, where an ansi-standard will help)
 "
 ! !
 
@@ -108,7 +152,13 @@
 
     /*
      * I dont like ifdefs - you always forget some ...
-     * therefore we look into a structure at run-time
+     * therefore we look into a structure at run-time.
+     * (also, there are CPUs around [mips], where the byteorder
+     *  is programmable, and which come in different flavours)
+     *
+     * NOTICE: 
+     *    both the JIT and stc may inline this to a 
+     *    constant for systems where this is known.
      */
     union {
 	unsigned int   u_l;
@@ -119,7 +169,9 @@
     if (u.u_c[0] == 0x21) RETURN (false);
     RETURN (true);
 %}
-    "UninterpretedBytes isBigEndian"
+    "
+     UninterpretedBytes isBigEndian
+    "
 !
 
 isBuiltInClass
@@ -153,6 +205,7 @@
 
 doubleAt:index
     "return the 8-bytes starting at index as a Float.
+     The index is a smalltalk index (i.e. 1-based).
      Notice, that (currently) ST/X Floats are what Doubles are in ST-80.
      Notice also, that the bytes are expected to be in this machines
      float representation - if the bytearray originated from another
@@ -160,16 +213,52 @@
 
     |newFloat|
 
+%{
+    /*
+     * handle the most common cases fast ...
+     */
+    if (__isSmallInteger(index)) {
+	char *cp;
+	int sz;
+	
+	__fetchBytePointerAndSize__(self, &cp, &sz);
+        if (cp) {
+	    unsigned INT idx = ((unsigned INT)__intVal(index)) - 1;
+
+	    if ((idx+7) < sz) {
+		cp += idx;
+		/*
+		 * aligned
+		 */
+		if (((INT)cp & 7) == 0) {
+		    double dVal = ((double *)cp)[0];
+		    RETURN (__MKFLOAT(dVal));
+		}
+	    }
+	}
+    }
+%}.
+
     newFloat := Float basicNew.
     1 to:8 do:[:destIndex|
 	newFloat basicAt:destIndex put:(self at:index - 1 + destIndex)
     ].
     ^ newFloat.
+
+    "
+     |b|
+
+     b := ByteArray new:20.
+     b doubleAt:1 put:(Float pi).
+     Transcript showCR:b.
+     Transcript showCR:(b doubleAt:1)
+    "
 !
 
 doubleAt:index put:aFloat
     "store the value of the argument, aFloat into the receiver
      starting at index.
+     The index is a smalltalk index (i.e. 1-based).
      Notice, that (currently) ST/X Floats are what Doubles are in ST-80.
      Notice also, that the bytes are expected to be in this machines
      float representation - if the bytearray originated from another
@@ -178,6 +267,32 @@
     |flt|
 
     flt := aFloat asFloat.
+%{
+    /*
+     * handle the most common cases fast ...
+     */
+    if (__isSmallInteger(index) && __isFloat(flt)) {
+        char *cp;
+        int sz;
+
+        __fetchBytePointerAndSize__(self, &cp, &sz);
+        if (cp) {
+            unsigned INT idx = ((unsigned INT)__intVal(index)) - 1;
+
+            if ((idx+7) < sz) {
+                cp += idx;
+                /*
+                 * aligned
+                 */
+                if (((INT)cp & 7) == 0) {
+                    ((double *)cp)[0] = __floatVal(flt);
+                    RETURN (aFloat);
+                }
+            }
+        }
+    }
+%}.
+
     1 to:8 do:[:srcIndex|
         self at:index - 1 + srcIndex put:(flt basicAt:srcIndex)
     ].
@@ -186,6 +301,7 @@
 
 doubleWordAt:index
     "return the 4-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      Subclasses may redefine this for better performance."
 
@@ -203,12 +319,13 @@
 
 doubleWordAt:index MSB:msb
     "return the 4-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB-first, if the msb-arg is true;
      LSB-first otherwise.
      Subclasses may redefine this for better performance."
 
     |val 
-     ival "{ Class: SmallInteger }"
+     ival "{ XXClass: SmallInteger }"
      i    "{ Class: SmallInteger }"
      b1   "{ Class: SmallInteger }"
      b2   "{ Class: SmallInteger }"
@@ -225,12 +342,12 @@
         ival := b1.
         ival := (ival bitShift:8) + b2.
         ival := (ival bitShift:8) + b3.
-        val := (ival * 256) + b4.
+        val := (ival bitShift:8) + b4.
     ] ifFalse:[
         ival := b4.
         ival := (ival bitShift:8) + b3.
         ival := (ival bitShift:8) + b2.
-        val := (ival * 256) + b1.
+        val := (ival bitShift:8) + b1.
     ].
     ^ val
 
@@ -247,6 +364,7 @@
 
 doubleWordAt:index put:value
     "set the 4-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value should be in the range 0 to 16rFFFFFFFF
      (for negative values, the stored value is not defined).
      The value is stored in the machines natural byte order.
@@ -266,6 +384,7 @@
 
 doubleWordAt:index put:aNumber MSB:msb
     "set the 4-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value must be in the range 0 to 16rFFFFFFFF.
      The value is stored MSB-first if msb is true; LSB-first otherwise.
      Subclasses may redefine this for better performance."
@@ -354,6 +473,7 @@
 
 floatAt:index
     "return the 4-bytes starting at index as a Float.
+     The index is a smalltalk index (i.e. 1-based).
      Notice, that (currently) ST/X Floats are what Doubles are in ST-80;
      therefore this method reads a 4-byte float from the byteArray and returns
      a float object which keeps an 8-byte double internally.
@@ -373,6 +493,7 @@
 floatAt:index put:aFloat
     "store the 4 bytes of value of the argument, aFloat into the receiver
      starting at index.
+     The index is a smalltalk index (i.e. 1-based).
      Notice, that (currently) ST/X Floats are what Doubles are in ST-80.
      Notice also, that the bytes are expected to be in this machines
      float representation - if the bytearray originated from another
@@ -389,6 +510,7 @@
 
 ieeeDoubleAt:index
     "retrieve the 8 bytes starting at index as a float.
+     The index is a smalltalk index (i.e. 1-based).
      The 8 bytes are assumed to be in IEEE floating point single precision
      number format."
 
@@ -399,6 +521,8 @@
      To date, all supported systems use IEEE float numbers, so there should be
      no problem.
     "
+    self isIEEEFormat ifFalse:[self error:'unsupported operation'].
+
     ^ self doubleAt:index
 
     "Created: / 5.3.1998 / 10:50:03 / stefan"
@@ -406,6 +530,7 @@
 
 ieeeDoubleAt:index put:aFloat
     "store the value of the argument, aFloat into the receiver
+     The index is a smalltalk index (i.e. 1-based).
      starting at index. Storage is in IEEE floating point double precision format.
      (i.e. 8 bytes are stored)."
 
@@ -416,6 +541,8 @@
      To date, all supported systems use IEEE float numbers, so there should be
      no problem.
     "
+    self isIEEEFormat ifFalse:[self error:'unsupported operation'].
+
     ^ self doubleAt:index put:aFloat
 
     "Created: / 5.3.1998 / 10:50:26 / stefan"
@@ -423,6 +550,7 @@
 
 ieeeFloatAt:index
     "retrieve the 4 bytes starting at index as a float.
+     The index is a smalltalk index (i.e. 1-based).
      The 4 bytes are assumed to be in IEEE floating point single precision
      number format."
 
@@ -433,6 +561,8 @@
      To date, all supported systems use IEEE float numbers, so there should be
      no problem.
     "
+    self isIEEEFormat ifFalse:[self error:'unsupported operation'].
+
     ^ self floatAt:index
 
     "Created: / 5.3.1998 / 10:50:45 / stefan"
@@ -440,7 +570,8 @@
 
 ieeeFloatAt:index put:aFloat
     "store the value of the argument, aFloat into the receiver
-     starting at index. Storage is in IEEE floating point single precision format.
+     starting at index, which is a smalltalk index (i.e. 1-based). 
+     Storage is in IEEE floating point single precision format.
      (i.e. 4 bytes are stored). Since ST/X floats are really doubles, the low-
      order 4 bytes of the precision is lost."
 
@@ -451,6 +582,8 @@
      To date, all supported systems use IEEE float numbers, so there should be
      no problem.
     "
+    self isIEEEFormat ifFalse:[self error:'unsupported operation'].
+
     ^ self floatAt:index put:aFloat
 
     "Created: / 5.3.1998 / 10:51:11 / stefan"
@@ -458,6 +591,7 @@
 
 longAt:index
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive."
 
@@ -482,6 +616,7 @@
 
 longAt:index bigEndian:msb
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      Depending on msb, the value is retrieved MSB-first or LSB-first.
      This may be worth a primitive."
 
@@ -506,6 +641,7 @@
 
 longAt:index put:value
     "set the 4-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value is stored in the machines natural byte order.
      This may be worth a primitive.
 
@@ -534,6 +670,7 @@
 
 longLongAt:index
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive."
 
@@ -559,6 +696,7 @@
 
 longLongAt:index bigEndian:msb
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive."
 
@@ -584,6 +722,7 @@
 
 longLongAt:byteIndex put:anInteger
     "store a signed longLong (64bit) integer.
+     The index is a smalltalk index (i.e. 1-based).
      Same as #signedQuadWordAt:put: - for ST80 compatibility."
 
     ^ self signedQuadWordAt:byteIndex put:anInteger
@@ -594,6 +733,7 @@
 
 quadWordAt:index MSB:msb
     "return the 8-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      Depending on msb, the value is retrieved MSB or LSB-first."
 
     |l 
@@ -626,6 +766,7 @@
 
 quadWordAt:index put:anInteger MSB:msb
     "set the 8-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value must be in the range 0 to 16rFFFFFFFFFFFFFFFF.
      Depending on msb, the value is stored MSB-first or LSB-first."
 
@@ -659,6 +800,7 @@
 
 shortAt:index
     "return the 2-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive.
      This is the ST80 equivalent of #signedWordAt:"
@@ -679,6 +821,7 @@
 
 shortAt:index bigEndian:msb
     "return the 2-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB-first, if the msb-arg is true;
      LSB-first otherwise.
      This is the ST80 equivalent of #signedWordAt:"
@@ -698,6 +841,7 @@
 
 shortAt:index put:value
     "set the 2-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range -32768 .. +32676.
      The value is stored in the machines natural byteorder.
      This may be worth a primitive.
@@ -729,6 +873,7 @@
 
 signedByteAt:index
     "return the byte at index as a signed 8 bit value.
+     The index is a smalltalk index (i.e. 1-based).
      This may be worth a primitive."
 
     ^ (self at:index) signExtendedByteValue
@@ -746,6 +891,7 @@
 
 signedByteAt:index put:aSignedByteValue
     "return the byte at index as a signed 8 bit value.
+     The index is a smalltalk index (i.e. 1-based).
      Return the signedByteValue argument.
      This may be worth a primitive."
 
@@ -771,6 +917,7 @@
 
 signedDoubleWordAt:index
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive."
 
@@ -794,6 +941,7 @@
 
 signedDoubleWordAt:index MSB:msb
     "return the 4-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      Depending on msb, the value is retrieved MSB-first or LSB-first.
      This may be worth a primitive."
 
@@ -817,6 +965,7 @@
 
 signedDoubleWordAt:index put:value
     "set the 4-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value is stored in the machines natural byte order.
      This may be worth a primitive."
 
@@ -842,6 +991,7 @@
 
 signedDoubleWordAt:index put:value MSB:msb
     "set the 4-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      Depending on msb, the value is stored MSB-first or LSB-first.
      This may be worth a primitive."
 
@@ -867,6 +1017,7 @@
 
 signedWordAt:index
     "return the 2-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      This may be worth a primitive."
 
@@ -884,6 +1035,7 @@
 
 signedWordAt:index MSB:msb
     "return the 2-bytes starting at index as a signed Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB-first if the msb-arg is true,
      LSB-first otherwise.
      This may be worth a primitive."
@@ -903,6 +1055,7 @@
 
 signedWordAt:index put:value
     "set the 2-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range -32768 .. +32676.
      The value is stored in the machines natural byteorder.
      This may be worth a primitive.
@@ -934,6 +1087,7 @@
 
 signedWordAt:index put:value MSB:msb
     "set the 2-bytes starting at index from the signed Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range -32768 .. +32676.
      The value is stored MSB-first, if the msb-arg is true;
      LSB-first otherwise.
@@ -961,7 +1115,8 @@
 !
 
 stringAt:index
-    "return a string starting at index up to the 0-byte"
+    "return a string starting at index up to the 0-byte.
+     The index is a smalltalk index (i.e. 1-based)."
 
     |stream i "{ Class: SmallInteger }" c|
 
@@ -978,7 +1133,8 @@
 
 stringAt:index put:aString
     "copy aString to the externalBytes, starting at index up to
-     (and including) the 0-byte"
+     (and including) the 0-byte.
+     The index is a smalltalk index (i.e. 1-based)."
 
     |i "{ Class: SmallInteger }"|
 
@@ -1004,7 +1160,8 @@
 !
 
 stringAt:index size:maxSize
-    "return a string starting at index up to maxSize, or a 0-byte"
+    "return a string starting at index up to maxSize, or a 0-byte.
+     The index is a smalltalk index (i.e. 1-based)."
 
     |stream c i "{ Class: SmallInteger }"|
 
@@ -1022,6 +1179,7 @@
 
 unsignedLongAt:index
     "return the 4-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order.
      Subclasses may redefine this for better performance."
 
@@ -1040,6 +1198,7 @@
 
 unsignedLongAt:index bigEndian:msb
     "return the 4-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB-first, if the msb-arg is true;
      LSB-first otherwise.
      Subclasses may redefine this for better performance."
@@ -1085,6 +1244,7 @@
 
 unsignedLongAt:index put:value
     "set the 4-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value should be in the range 0 to 16rFFFFFFFF
      (for negative values, the stored value is not defined).
      The value is stored in the machines natural byte order.
@@ -1105,6 +1265,7 @@
 
 unsignedLongAt:index put:aNumber bigEndian:msb
     "set the 4-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value must be in the range 0 to 16rFFFFFFFF.
      The value is stored MSB-first if msb is true; LSB-first otherwise.
      Subclasses may redefine this for better performance."
@@ -1143,6 +1304,7 @@
 
 unsignedLongLongAt:index bigEndian:msb
     "return the 8-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      Depending on msb, the value is retrieved MSB or LSB-first."
 
     |l 
@@ -1176,6 +1338,7 @@
 
 unsignedLongLongAt:index put:anInteger
     "set the 8-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value must be in the range 0 to 16rFFFFFFFFFFFFFFFF.
      The value is stored in natural byte order."
 
@@ -1187,6 +1350,7 @@
 
 unsignedLongLongAt:index put:anInteger bigEndian:msb
     "set the 8-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The value must be in the range 0 to 16rFFFFFFFFFFFFFFFF.
      Depending on msb, the value is stored MSB-first or LSB-first."
 
@@ -1222,6 +1386,7 @@
 
 unsignedShortAt:index
     "return the 2-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order
      Subclasses may redefine this for better performance.
      This is the ST80 equivalent of #wordAt:"
@@ -1235,6 +1400,7 @@
 
 unsignedShortAt:index bigEndian:msb
     "return the 2-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB-first (high 8 bits at lower index) if msb is true;
      LSB-first (i.e. low 8-bits at lower byte index) if its false)"
 
@@ -1254,6 +1420,7 @@
 
 unsignedShortAt:index put:value
     "set the 2-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range 0 .. 16rFFFF. 
      The value is stored in the machines natural byteorder."
 
@@ -1273,6 +1440,7 @@
 
 unsignedShortAt:index put:value bigEndian:msb
     "set the 2-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range 0 .. 16rFFFF. 
      The value is stored LSB-first (i.e. the low 8bits are stored at the
      lower index) if msb is false, MSB-first otherwise"
@@ -1311,6 +1479,7 @@
 
 wordAt:index
     "return the 2-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved in the machines natural byte order
      Subclasses may redefine this for better performance."
 
@@ -1321,6 +1490,7 @@
 
 wordAt:index MSB:msb
     "return the 2-bytes starting at index as an (unsigned) Integer.
+     The index is a smalltalk index (i.e. 1-based).
      The value is retrieved MSB (high 8 bits at lower index) if msb is true;
      LSB-first (i.e. low 8-bits at lower byte index) if its false.
      Question: should it be retrieve signed values ? (see ByteArray>>signedWordAt:)"
@@ -1340,6 +1510,7 @@
 
 wordAt:index put:value
     "set the 2-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range 0 .. 16rFFFF. 
      The value is stored in the machines natural byteorder.
      Question: should it accept signed values ? (see ByteArray>>signedWordAt:put:)"
@@ -1359,6 +1530,7 @@
 
 wordAt:index put:value MSB:msb
     "set the 2-bytes starting at index from the (unsigned) Integer value.
+     The index is a smalltalk index (i.e. 1-based).
      The stored value must be in the range 0 .. 16rFFFF. 
      The value is stored LSB-first (i.e. the low 8bits are stored at the
      lower index) if msb is false, MSB-first otherwise.
@@ -1446,7 +1618,8 @@
 
 zeroByteStringAt:index maximumSize:count
     "extract a zeroByte-delimited string, given initial index and
-     maximum number of characters (bytes)"
+     maximum number of characters (bytes).
+     The index is a smalltalk index (i.e. 1-based)."
 
     |bytes idx|
 
@@ -1461,7 +1634,8 @@
 !UninterpretedBytes methodsFor:'misc'!
 
 swapLongAt:byteIndex 
-    "swap the byteOrder of a long."
+    "swap the byteOrder of a long.
+     The index is a smalltalk index (i.e. 1-based)."
 
     |t|
 
@@ -1489,6 +1663,6 @@
 !UninterpretedBytes class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/UninterpretedBytes.st,v 1.23 1998-04-25 21:33:11 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UninterpretedBytes.st,v 1.24 1998-05-08 13:26:50 cg Exp $'
 ! !
 UninterpretedBytes initialize!