From f7c5b23e6abcad6c4a7391c74878114028ddf85f Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Fri, 21 Oct 2011 21:01:35 +0000 Subject: [PATCH] code format and sort members (prepare for double and float additions) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1187537 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/util/LittleEndian.java | 764 ++++++++++-------- 1 file changed, 433 insertions(+), 331 deletions(-) diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java index 3d1c9cd937..912a5dddb3 100644 --- a/src/java/org/apache/poi/util/LittleEndian.java +++ b/src/java/org/apache/poi/util/LittleEndian.java @@ -22,236 +22,313 @@ import java.io.InputStream; import java.io.OutputStream; /** - * a utility class for handling little-endian numbers, which the 80x86 world is - * replete with. The methods are all static, and input/output is from/to byte - * arrays, or from InputStreams. - * - *@author Marc Johnson (mjohnson at apache dot org) - *@author Andrew Oliver (acoliver at apache dot org) + * a utility class for handling little-endian numbers, which the 80x86 world is + * replete with. The methods are all static, and input/output is from/to byte + * arrays, or from InputStreams. + * + * @author Marc Johnson (mjohnson at apache dot org) + * @author Andrew Oliver (acoliver at apache dot org) */ -public class LittleEndian implements LittleEndianConsts { - - private LittleEndian() { - // no instances of this class - } +public class LittleEndian implements LittleEndianConsts +{ /** - * get a short value from a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the short (16-bit) value + * Exception to handle buffer underruns + * + * @author Marc Johnson (mjohnson at apache dot org) */ - public static short getShort(byte[] data, int offset) { - int b0 = data[offset] & 0xFF; - int b1 = data[offset+1] & 0xFF; - return (short) ((b1 << 8) + (b0 << 0)); - } + public static final class BufferUnderrunException extends IOException + { + BufferUnderrunException() + { + super( "buffer underrun" ); + } + } /** - * get an unsigned short value from a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the unsigned short (16-bit) value in an integer + * Copy a portion of a byte array + * + * @param data + * the original byte array + * @param offset + * Where to start copying from. + * @param size + * Number of bytes to copy. + * @return The byteArray value + * @throws IndexOutOfBoundsException + * - if copying would cause access of data outside array bounds. */ - public static int getUShort(byte[] data, int offset) { - int b0 = data[offset] & 0xFF; - int b1 = data[offset+1] & 0xFF; - return (b1 << 8) + (b0 << 0); + public static byte[] getByteArray( byte[] data, int offset, int size ) + { + byte[] copy = new byte[size]; + System.arraycopy( data, offset, copy, 0, size ); + + return copy; } /** - * get a short value from the beginning of a byte array - * - *@param data the byte array - *@return the short (16-bit) value + * get a double value from a byte array, reads it in little endian format + * then converts the resulting revolting IEEE 754 (curse them) floating + * point number to a happy java double + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @return the double (64-bit) value */ - public static short getShort(byte[] data) { - return getShort(data, 0); + public static double getDouble( byte[] data, int offset ) + { + return Double.longBitsToDouble( getLong( data, offset ) ); } /** - * get an unsigned short value from the beginning of a byte array - * - *@param data the byte array - *@return the unsigned short (16-bit) value in an int + * get an int value from the beginning of a byte array + * + * @param data + * the byte array + * @return the int (32-bit) value */ - public static int getUShort(byte[] data) { - return getUShort(data, 0); + public static int getInt( byte[] data ) + { + return getInt( data, 0 ); } /** - * get an int value from a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the int (32-bit) value + * get an int value from a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @return the int (32-bit) value */ - public static int getInt(byte[] data, int offset) { - int i=offset; + public static int getInt( byte[] data, int offset ) + { + int i = offset; int b0 = data[i++] & 0xFF; int b1 = data[i++] & 0xFF; int b2 = data[i++] & 0xFF; int b3 = data[i++] & 0xFF; - return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0); + return ( b3 << 24 ) + ( b2 << 16 ) + ( b1 << 8 ) + ( b0 << 0 ); } /** - * get an int value from the beginning of a byte array - * - *@param data the byte array - *@return the int (32-bit) value + * get a long value from a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @return the long (64-bit) value */ - public static int getInt(byte[] data) { - return getInt(data, 0); + public static long getLong( byte[] data, int offset ) + { + long result = 0; + + for ( int j = offset + LONG_SIZE - 1; j >= offset; j-- ) + { + result <<= 8; + result |= 0xff & data[j]; + } + return result; } + /** + * get a short value from the beginning of a byte array + * + * @param data + * the byte array + * @return the short (16-bit) value + */ + public static short getShort( byte[] data ) + { + return getShort( data, 0 ); + } /** - * get an unsigned int value from a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the unsigned int (32-bit) value in a long + * get a short value from a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @return the short (16-bit) value */ - public static long getUInt(byte[] data, int offset) { - long retNum = getInt(data, offset); - return retNum & 0x00FFFFFFFFl; + public static short getShort( byte[] data, int offset ) + { + int b0 = data[offset] & 0xFF; + int b1 = data[offset + 1] & 0xFF; + return (short) ( ( b1 << 8 ) + ( b0 << 0 ) ); } /** - * get an unsigned int value from a byte array - * - *@param data the byte array - *@return the unsigned int (32-bit) value in a long + * Read short array + * + * @param data + * the original byte array + * @param offset + * Where to start copying from. + * @param size + * Number of bytes to copy. + * @throws IndexOutOfBoundsException + * - if read would cause access of data outside array bounds. */ - public static long getUInt(byte[] data) { - return getUInt(data,0); + public static short[] getShortArray( byte[] data, int offset, int size ) + { + short[] result = new short[size / SHORT_SIZE]; + for ( int i = 0; i < result.length; i++ ) + { + result[i] = getShort( data, offset + i * SHORT_SIZE ); + } + return result; } /** - * get a long value from a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the long (64-bit) value + * get the unsigned value of a byte. + * + * @param data + * the byte array. + * @param offset + * a starting offset into the byte array. + * @return the unsigned value of the byte as a 16 bit short */ - public static long getLong(byte[] data, int offset) { - long result = 0; + public static short getUByte( byte[] data, int offset ) + { + return (short) ( data[offset] & 0xFF ); + } - for (int j = offset + LONG_SIZE - 1; j >= offset; j--) { - result <<= 8; - result |= 0xff & data[j]; - } - return result; + /** + * get an unsigned int value from a byte array + * + * @param data + * the byte array + * @return the unsigned int (32-bit) value in a long + */ + public static long getUInt( byte[] data ) + { + return getUInt( data, 0 ); } /** - * get a double value from a byte array, reads it in little endian format - * then converts the resulting revolting IEEE 754 (curse them) floating - * point number to a happy java double - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@return the double (64-bit) value + * get an unsigned int value from a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @return the unsigned int (32-bit) value in a long */ - public static double getDouble(byte[] data, int offset) { - return Double.longBitsToDouble(getLong(data, offset)); + public static long getUInt( byte[] data, int offset ) + { + long retNum = getInt( data, offset ); + return retNum & 0x00FFFFFFFFl; } /** - * put a short value into a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@param value the short (16-bit) value + * get the unsigned value of a byte. + * + * @param data + * the byte array. + * @param offset + * a starting offset into the byte array. + * @return the unsigned value of the byte as a 32 bit integer + * @deprecated Use {@link #getUByte(byte[], int)} instead */ - public static void putShort(byte[] data, int offset, short value) { - int i = offset; - data[i++] = (byte)((value >>> 0) & 0xFF); - data[i++] = (byte)((value >>> 8) & 0xFF); + @Deprecated + public static int getUnsignedByte( byte[] data, int offset ) + { + return data[offset] & 0xFF; } /** - * executes:

- * - * data[offset] = (byte)value; - *

- * Added for consistency with other put~() methods + * get an unsigned short value from the beginning of a byte array + * + * @param data + * the byte array + * @return the unsigned short (16-bit) value in an int */ - public static void putByte(byte[] data, int offset, int value) { - data[offset] = (byte) value; + public static int getUShort( byte[] data ) + { + return getUShort( data, 0 ); } /** - * put an unsigned byte value into a byte array + * get an unsigned short value from a byte array * * @param data * the byte array * @param offset * a starting offset into the byte array - * @param value - * the short (16-bit) value - * - * @exception ArrayIndexOutOfBoundsException - * may be thrown + * @return the unsigned short (16-bit) value in an integer */ - public static void putUByte( byte[] data, int offset, short value ) + public static int getUShort( byte[] data, int offset ) { - data[offset] = (byte) ( value & 0xFF ); + int b0 = data[offset] & 0xFF; + int b1 = data[offset + 1] & 0xFF; + return ( b1 << 8 ) + ( b0 << 0 ); } /** - * put an unsigned short value into a byte array - * - * @param data the byte array - * @param offset a starting offset into the byte array - * @param value the short (16-bit) value - * - * @exception ArrayIndexOutOfBoundsException may be thrown - */ - public static void putUShort(byte[] data, int offset, int value) { - int i = offset; - data[i++] = (byte)((value >>> 0) & 0xFF); - data[i++] = (byte)((value >>> 8) & 0xFF); + * executes: + *

+ * + * data[offset] = (byte)value; + * + *

+ * Added for consistency with other put~() methods + */ + public static void putByte( byte[] data, int offset, int value ) + { + data[offset] = (byte) value; } /** - * put a short value into beginning of a byte array - * - *@param data the byte array - *@param value the short (16-bit) value + * put a double value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the double (64-bit) value */ - public static void putShort(byte[] data, short value) { - putShort(data, 0, value); + public static void putDouble( byte[] data, int offset, double value ) + { + putLong( data, offset, Double.doubleToLongBits( value ) ); } - /** - * put an int value into a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@param value the int (32-bit) value + * put an int value into beginning of a byte array + * + * @param data + * the byte array + * @param value + * the int (32-bit) value */ - public static void putInt(byte[] data, int offset, int value) { - int i = offset; - data[i++] = (byte)((value >>> 0) & 0xFF); - data[i++] = (byte)((value >>> 8) & 0xFF); - data[i++] = (byte)((value >>> 16) & 0xFF); - data[i++] = (byte)((value >>> 24) & 0xFF); + public static void putInt( byte[] data, int value ) + { + putInt( data, 0, value ); } /** - * put an int value into beginning of a byte array - * - *@param data the byte array - *@param value the int (32-bit) value + * put an int value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the int (32-bit) value */ - public static void putInt(byte[] data, int value) { - putInt(data, 0, value); + public static void putInt( byte[] data, int offset, int value ) + { + int i = offset; + data[i++] = (byte) ( ( value >>> 0 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 8 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 16 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 24 ) & 0xFF ); } /** @@ -274,149 +351,224 @@ public class LittleEndian implements LittleEndianConsts { } /** - * put an unsigned int value into a byte array - * - * @param data the byte array - * @param offset a starting offset into the byte array - * @param value the int (32-bit) value - * - * @exception ArrayIndexOutOfBoundsException may be thrown - */ - public static void putUInt(byte[] data, int offset, long value) { + * put a long value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the long (64-bit) value + */ + public static void putLong( byte[] data, int offset, long value ) + { + int limit = LONG_SIZE + offset; + long v = value; + + for ( int j = offset; j < limit; j++ ) + { + data[j] = (byte) ( v & 0xFF ); + v >>= 8; + } + } + + /** + * put a short value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the short (16-bit) value + */ + public static void putShort( byte[] data, int offset, short value ) + { int i = offset; - data[i++] = (byte)((value >>> 0) & 0xFF); - data[i++] = (byte)((value >>> 8) & 0xFF); - data[i++] = (byte)((value >>> 16) & 0xFF); - data[i++] = (byte)((value >>> 24) & 0xFF); + data[i++] = (byte) ( ( value >>> 0 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 8 ) & 0xFF ); } /** - * put an unsigned int value into beginning of a byte array - * - *@param data the byte array - *@param value the int (32-bit) value + * put a short value into beginning of a byte array + * + * @param data + * the byte array + * @param value + * the short (16-bit) value */ - public static void putUInt(byte[] data, long value) { - putUInt(data, 0, value); + public static void putShort( byte[] data, short value ) + { + putShort( data, 0, value ); } /** - * Put unsigned int into output stream + * Put signed short into output stream * * @param value - * the int (32-bit) value + * the short (16-bit) value * @param outputStream * output stream * @throws IOException * if an I/O error occurs */ - public static void putUInt( long value, OutputStream outputStream ) + public static void putShort( OutputStream outputStream, short value ) throws IOException { outputStream.write( (byte) ( ( value >>> 0 ) & 0xFF ) ); outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) ); - outputStream.write( (byte) ( ( value >>> 16 ) & 0xFF ) ); - outputStream.write( (byte) ( ( value >>> 24 ) & 0xFF ) ); } /** - * put a long value into a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@param value the long (64-bit) value + * Stores short array in buffer + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the short (16-bit) values */ - public static void putLong(byte[] data, int offset, long value) { - int limit = LONG_SIZE + offset; - long v = value; - - for (int j = offset; j < limit; j++) { - data[j] = (byte) (v & 0xFF); - v >>= 8; + public static void putShortArray( byte[] data, int offset, short[] value ) + { + for ( short s : value ) + { + putShort( data, offset, s ); + offset += SHORT_SIZE; } } - /** - * put a double value into a byte array - * - *@param data the byte array - *@param offset a starting offset into the byte array - *@param value the double (64-bit) value + * put an unsigned byte value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException + * may be thrown */ - public static void putDouble(byte[] data, int offset, double value) { - putLong(data, offset, Double.doubleToLongBits(value)); + public static void putUByte( byte[] data, int offset, short value ) + { + data[offset] = (byte) ( value & 0xFF ); } - /** - * Exception to handle buffer underruns - * - *@author Marc Johnson (mjohnson at apache dot org) + * put an unsigned int value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the int (32-bit) value + * + * @exception ArrayIndexOutOfBoundsException + * may be thrown */ - public static final class BufferUnderrunException extends IOException { - - BufferUnderrunException() { - super("buffer underrun"); - } + public static void putUInt( byte[] data, int offset, long value ) + { + int i = offset; + data[i++] = (byte) ( ( value >>> 0 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 8 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 16 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 24 ) & 0xFF ); } - /** - * get a short value from an InputStream - * - *@param stream the InputStream from which the short is to be read - *@return the short (16-bit) value - *@exception IOException will be propagated back to the caller - *@exception BufferUnderrunException if the stream cannot provide enough bytes + * put an unsigned int value into beginning of a byte array + * + * @param data + * the byte array + * @param value + * the int (32-bit) value */ - public static short readShort(InputStream stream) throws IOException, BufferUnderrunException { - - return (short) readUShort(stream); + public static void putUInt( byte[] data, long value ) + { + putUInt( data, 0, value ); } - public static int readUShort(InputStream stream) throws IOException, BufferUnderrunException { - - int ch1 = stream.read(); - int ch2 = stream.read(); - if ((ch1 | ch2) < 0) { - throw new BufferUnderrunException(); - } - return (ch2 << 8) + (ch1 << 0); + /** + * Put unsigned int into output stream + * + * @param value + * the int (32-bit) value + * @param outputStream + * output stream + * @throws IOException + * if an I/O error occurs + */ + public static void putUInt( long value, OutputStream outputStream ) + throws IOException + { + outputStream.write( (byte) ( ( value >>> 0 ) & 0xFF ) ); + outputStream.write( (byte) ( ( value >>> 8 ) & 0xFF ) ); + outputStream.write( (byte) ( ( value >>> 16 ) & 0xFF ) ); + outputStream.write( (byte) ( ( value >>> 24 ) & 0xFF ) ); } - /** - * get an int value from an InputStream - * - *@param stream the InputStream from which the int is to be read - * @return the int (32-bit) value - * @exception IOException will be propagated back to the caller - * @exception BufferUnderrunException if the stream cannot provide enough bytes + * put an unsigned short value into a byte array + * + * @param data + * the byte array + * @param offset + * a starting offset into the byte array + * @param value + * the short (16-bit) value + * + * @exception ArrayIndexOutOfBoundsException + * may be thrown */ - public static int readInt(InputStream stream) - throws IOException, BufferUnderrunException { + public static void putUShort( byte[] data, int offset, int value ) + { + int i = offset; + data[i++] = (byte) ( ( value >>> 0 ) & 0xFF ); + data[i++] = (byte) ( ( value >>> 8 ) & 0xFF ); + } + + /** + * get an int value from an InputStream + * + * @param stream + * the InputStream from which the int is to be read + * @return the int (32-bit) value + * @exception IOException + * will be propagated back to the caller + * @exception BufferUnderrunException + * if the stream cannot provide enough bytes + */ + public static int readInt( InputStream stream ) throws IOException, + BufferUnderrunException + { int ch1 = stream.read(); int ch2 = stream.read(); int ch3 = stream.read(); int ch4 = stream.read(); - if ((ch1 | ch2 | ch3 | ch4) < 0) { + if ( ( ch1 | ch2 | ch3 | ch4 ) < 0 ) + { throw new BufferUnderrunException(); } - return (ch4 << 24) + (ch3<<16) + (ch2 << 8) + (ch1 << 0); + return ( ch4 << 24 ) + ( ch3 << 16 ) + ( ch2 << 8 ) + ( ch1 << 0 ); } - /** - * get a long value from an InputStream - * - * @param stream the InputStream from which the long is to be read - * @return the long (64-bit) value - * @exception IOException will be propagated back to the caller - * @exception BufferUnderrunException if the stream cannot provide enough bytes - */ - public static long readLong(InputStream stream) - throws IOException, BufferUnderrunException { + * get a long value from an InputStream + * + * @param stream + * the InputStream from which the long is to be read + * @return the long (64-bit) value + * @exception IOException + * will be propagated back to the caller + * @exception BufferUnderrunException + * if the stream cannot provide enough bytes + */ + public static long readLong( InputStream stream ) throws IOException, + BufferUnderrunException + { int ch1 = stream.read(); int ch2 = stream.read(); int ch3 = stream.read(); @@ -425,112 +577,62 @@ public class LittleEndian implements LittleEndianConsts { int ch6 = stream.read(); int ch7 = stream.read(); int ch8 = stream.read(); - if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) { + if ( ( ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8 ) < 0 ) + { throw new BufferUnderrunException(); } - return - ((long)ch8 << 56) + - ((long)ch7 << 48) + - ((long)ch6 << 40) + - ((long)ch5 << 32) + - ((long)ch4 << 24) + // cast to long to preserve bit 31 (sign bit for ints) - (ch3 << 16) + - (ch2 << 8) + - (ch1 << 0); + return ( (long) ch8 << 56 ) + ( (long) ch7 << 48 ) + + ( (long) ch6 << 40 ) + ( (long) ch5 << 32 ) + + ( (long) ch4 << 24 ) + // cast to long to preserve bit 31 + // (sign bit for ints) + ( ch3 << 16 ) + ( ch2 << 8 ) + ( ch1 << 0 ); } /** - * Convert an 'unsigned' byte to an integer. ie, don't carry across the - * sign. - * - * @param b Description of the Parameter - * @return Description of the Return Value - */ - public static int ubyteToInt(byte b) { - return b & 0xFF; - } - - - /** - * get the unsigned value of a byte. - * - * @param data the byte array. - * @param offset a starting offset into the byte array. - * @return the unsigned value of the byte as a 32 bit integer - * @deprecated Use {@link #getUByte(byte[], int)} instead - */ - @Deprecated - public static int getUnsignedByte(byte[] data, int offset) { - return data[offset] & 0xFF; - } - - /** - * get the unsigned value of a byte. + * get a short value from an InputStream * - * @param data - * the byte array. - * @param offset - * a starting offset into the byte array. - * @return the unsigned value of the byte as a 16 bit short - */ - public static short getUByte( byte[] data, int offset ) + * @param stream + * the InputStream from which the short is to be read + * @return the short (16-bit) value + * @exception IOException + * will be propagated back to the caller + * @exception BufferUnderrunException + * if the stream cannot provide enough bytes + */ + public static short readShort( InputStream stream ) throws IOException, + BufferUnderrunException { - return (short) ( data[offset] & 0xFF ); + return (short) readUShort( stream ); } - /** - * Copy a portion of a byte array - * - * @param data the original byte array - * @param offset Where to start copying from. - * @param size Number of bytes to copy. - * @return The byteArray value - * @throws IndexOutOfBoundsException - if copying would cause access of - * data outside array bounds. - */ - public static byte[] getByteArray(byte[] data, int offset, int size) { - byte[] copy = new byte[size]; - System.arraycopy(data, offset, copy, 0, size); - - return copy; - } - - /** - * Read short array - * - * @param data the original byte array - * @param offset Where to start copying from. - * @param size Number of bytes to copy. - * @throws IndexOutOfBoundsException - * - if read would cause access of data outside array bounds. - */ - public static short[] getShortArray( byte[] data, int offset, int size ) + public static int readUShort( InputStream stream ) throws IOException, + BufferUnderrunException { - short[] result = new short[size / SHORT_SIZE]; - for ( int i = 0; i < result.length; i++ ) + int ch1 = stream.read(); + int ch2 = stream.read(); + if ( ( ch1 | ch2 ) < 0 ) { - result[i] = getShort( data, offset + i * SHORT_SIZE ); + throw new BufferUnderrunException(); } - return result; + return ( ch2 << 8 ) + ( ch1 << 0 ); } /** - * Stores short array in buffer + * Convert an 'unsigned' byte to an integer. ie, don't carry across the + * sign. * - * @param data - * the byte array - * @param offset - * a starting offset into the byte array - * @param value - * the short (16-bit) values + * @param b + * Description of the Parameter + * @return Description of the Return Value */ - public static void putShortArray( byte[] data, int offset, short[] value ) + public static int ubyteToInt( byte b ) { - for ( short s : value ) - { - putShort( data, offset, s ); - offset += SHORT_SIZE; - } + return b & 0xFF; + } + + private LittleEndian() + { + // no instances of this class } } -- 2.39.5