/* ====================================================================== Binary number read/write functions Ernie Wright 15 Oct 03 Updated 12 April 04 ====================================================================== */ /* ====================================================================== readShort() 2-byte signed two's-complement integers readInt() 4-byte signed two's-complement integers readFloat() 4-byte IEEE floating-point readDouble() 8-byte IEEE floating-point Read a number from a binary file. If 'pcOrder' is TRUE, the number is read in little-endian (Windows) byte order, otherwise it's read in big-endian (Motorola, Internet) order. ====================================================================== */ readShort : inFile, pcOrder { var byte[ 2 ]; readBytes( inFile, byte, 2, pcOrder ); if ( byte[ 1 ] < 128 ) return byte[ 1 ] * 256 + byte[ 2 ]; else return -(( 255 - byte[ 1 ] ) * 256 + ( 256 - byte[ 2 ] )); } readInt : inFile, pcOrder { var byte[ 4 ]; readBytes( inFile, byte, 4, pcOrder ); if ( byte[ 1 ] < 128 ) return byte[ 1 ] * 16777216 + byte[ 2 ] * 65536 + byte[ 3 ] * 256 + byte[ 4 ]; else return -(( 255 - byte[ 1 ] ) * 16777216 + ( 255 - byte[ 2 ] ) * 65536 + ( 255 - byte[ 3 ] ) * 256 + ( 256 - byte[ 4 ] )); } readFloat : inFile, pcOrder // Effective range of representation ~ +/- 10^38.52 { var byte[ 4 ]; readBytes( inFile, byte, 4, pcOrder ); if ( byte[ 1 ] == 0 && byte[ 2 ] == 0 && byte[ 3 ] == 0 && byte[ 4 ] == 0 ) return 0; m = 1.0 + (( byte[ 2 ] % 128 ) * 65536 + byte[ 3 ] * 256 + byte[ 4 ] ) / 8388608.0; e = ( byte[ 1 ] % 128 ) * 2 + integer( byte[ 2 ] / 128 ) - 127; x = m * pow( 2.0, e ); if ( byte[ 1 ] > 127 ) x = -x; return x; } readDouble : inFile, pcOrder // Effective range of representation ~ +/- 10^308.25 { var byte[ 8 ]; readBytes( inFile, byte, 8, pcOrder ); if ( byte[ 1 ] == 0 && byte[ 2 ] == 0 && byte[ 3 ] == 0 && byte[ 4 ] == 0 && byte[ 5 ] == 0 && byte[ 6 ] == 0 && byte[ 7 ] == 0 && byte[ 8 ] == 0 ) return 0; m1 = ( byte[ 2 ] % 16 ) * 65536 + byte[ 3 ] * 256 + byte[ 4 ]; m2 = byte[ 5 ] * 256 + byte[ 6 ]; m3 = byte[ 7 ] * 256 + byte[ 8 ]; m = 1.0 + m1 / 1048576.0 // = m1 / 2^20 + m2 / 68719476736.0 // = m2 / 2^36 + m3 / 4503599627370496.0; // = m3 / 2^52 e = ( byte[ 1 ] % 128 ) * 16 + integer( byte[ 2 ] / 16 ) - 1023; x = m * pow( 2.0, e ); if ( byte[ 1 ] > 127 ) x = -x; return x; } /* ====================================================================== writeShort() 2-byte signed two's complement integers writeInt() 4-byte signed two's complement integers writeFloat() 4-byte IEEE floating-point readDouble() 8-byte IEEE floating-point Write a number to a binary file. If 'pcOrder' is TRUE, the number is written in little-endian (Windows) byte order, otherwise it's written in big-endian (Motorola, Internet) order. ====================================================================== */ writeShort : outFile, i, pcOrder { var byte[ 2 ]; if ( i >= 0 ) { byte[ 1 ] = integer( i / 256 ) % 256; byte[ 2 ] = i % 256; } else { j = -i - 1; byte[ 1 ] = 255 - ( integer( j / 256 ) % 256 ); byte[ 2 ] = 255 - ( j % 256 ); } writeBytes( outFile, byte, 2, pcOrder ); } writeInt : outFile, i, pcOrder { var byte[ 4 ]; if ( i >= 0 ) { byte[ 1 ] = integer( i / 16777216 ); byte[ 2 ] = integer( i / 65536 ) % 256; byte[ 3 ] = integer( i / 256 ) % 256; byte[ 4 ] = i % 256; } else { j = -i - 1; byte[ 1 ] = 255 - integer( j / 16777216 ); byte[ 2 ] = 255 - ( integer( j / 65536 ) % 256 ); byte[ 3 ] = 255 - ( integer( j / 256 ) % 256 ); byte[ 4 ] = 255 - ( j % 256 ); } writeBytes( outFile, byte, 4, pcOrder ); } writeFloat : outFile, x, pcOrder { var byte[ 4 ]; if(x==0) { byte[ 4 ] = 0; byte[ 3 ] = 0; byte[ 2 ] = 0; byte[ 1 ] = 0; } else { lgx = log( abs( x )) / log( 2.0 ); e = integer( floor( lgx )); m = integer( floor(( pow( 2.0, lgx - e ) - 1.0 ) * 8388608 )); e += 127; byte[ 1 ] = integer( e / 2 ) + ( x < 0 ? 128 : 0 ); byte[ 2 ] = integer( m / 65536 ) + 128 * ( e % 2 ); byte[ 3 ] = integer( m / 256 ) % 256; byte[ 4 ] = m % 256; } writeBytes( outFile, byte, 4, pcOrder ); } writeDouble : outFile, x, pcOrder { var byte[ 8 ]; if ( x == 0 ) { byte[ 8 ] = 0; byte[ 7 ] = 0; byte[ 6 ] = 0; byte[ 5 ] = 0; byte[ 4 ] = 0; byte[ 3 ] = 0; byte[ 2 ] = 0; byte[ 1 ] = 0; } else { lgx = log( abs( x )) / log( 2.0 ); e = integer( floor( lgx )); m = ( pow( 2.0, lgx - e ) - 1.0 ) * 1048576.0; m1 = integer( floor( m )); m = ( m - m1 ) * 65536.0; m2 = integer( floor( m )); m = ( m - m2 ) * 65536.0; m3 = integer( floor( m )); e += 1023; byte[ 1 ] = integer( e / 16 ) + ( x < 0 ? 128 : 0 ); byte[ 2 ] = integer( m1 / 65536 ) + 16 * ( e % 16 ); byte[ 3 ] = integer( m1 / 256 ) % 256; byte[ 4 ] = m1 % 256; byte[ 5 ] = m2 / 256; byte[ 6 ] = m2 % 256; byte[ 7 ] = m3 / 256; byte[ 8 ] = m3 % 256; } writeBytes( outFile, byte, 8, pcOrder ); } /* ====================================================================== readBytes() Read bytes from a file. Called by the number reading functions. inFile the file to read byte array where bytes are stored n the number of bytes to read from inFile pcOrder bytes are stored in reverse order if TRUE ====================================================================== */ readBytes : inFile, byte, n, pcOrder { if ( pcOrder ) { first = n; stop = 0; step = -1; } else { first = 1; stop = n + 1; step = 1; } for ( i = first; i != stop; i += step ) byte[ i ] = inFile.readByte(); } /* ====================================================================== writeBytes() Write an array of bytes to a file. Called by the number writing functions. outFile the file to write byte an array of bytes n the number of bytes to write pcOrder bytes are written in reverse order if TRUE ====================================================================== */ writeBytes : outFile, byte, n, pcOrder { if ( pcOrder ) { first = n; stop = 0; step = -1; } else { first = 1; stop = n + 1; step = 1; } for ( i = first; i != stop; i += step ) outFile.writeByte( byte[ i ] ); }