Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Jonas Raoni Soares Silva http://jsfromhell.com

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

Binary Data Parser //Javascript Class



This is a prototyped class written to serialize and unserialize binary data, so you can read and write binary data files to exchange with programs written in languages like C and Pascal.

Currently the class is able to handle just the following types: signed integers (small 8 bits, short 16 bits, int 32 bits), unsigned integers (byte 8 bits, word 16 bits, dword 32 bits) and floating point (IEEE754 float 32 bits and double 64 bits).

The endianess of the binary values representation can also be configured with the class.

[UPDATED CODE AND HELP CAN BE FOUND HERE]


There's a php version right here.

Code

   1  
   2  //+ Jonas Raoni Soares Silva
   3  //@ http://jsfromhell.com/classes/binary-parser [v1.0]
   4  
   5  BinaryParser = function( bigEndian, allowExceptions ){
   6  	this.bigEndian = bigEndian;
   7  	this.allowExceptions = allowExceptions;
   8  };
   9  with( { p: BinaryParser.prototype } ){
  10  	with( {p: ( p.Buffer = function( bigEndian, buffer ){ this.bigEndian = bigEndian || 0; this.buffer = []; this.setBuffer( buffer ); } ).prototype } ){
  11  		p.setBuffer = function( data ){
  12  			if( data ){
  13  				for( var l, i = l = data.length, b = this.buffer = new Array( l ); i; b[l - i] = data.charCodeAt( --i ) );
  14  				this.bigEndian && b.reverse();
  15  			}
  16  		};
  17  		p.hasNeededBits = function( neededBits ){
  18  			return this.buffer.length >= -( -neededBits >> 3 );
  19  		};
  20  		p.checkBuffer = function( neededBits ){
  21  			if( !this.hasNeededBits( neededBits ) )
  22  				throw new Error( "checkBuffer::missing bytes" );
  23  		};
  24  		p.readBits = function( start, length ){
  25  			//shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
  26  			function shl( a, b ){
  27  				for( ; b--; a = ( ( a %= 0x7fffffff + 1 ) & 0x40000000 ) == 0x40000000 ? a * 2 : ( a - 0x40000000 ) * 2 + 0x7fffffff + 1 );
  28  				return a;
  29  			}
  30  			if( start < 0 || length <= 0 )
  31  				return 0;
  32  			this.checkBuffer( start + length );
  33  			for( var offsetLeft, offsetRight = start % 8, curByte = this.buffer.length - ( start >> 3 ) - 1, lastByte = this.buffer.length + ( -( start + length ) >> 3 ), diff = curByte - lastByte, sum = ( ( this.buffer[ curByte ] >> offsetRight ) & ( ( 1 << ( diff ? 8 - offsetRight : length ) ) - 1 ) ) + ( diff && ( offsetLeft = ( start + length ) % 8 ) ? ( this.buffer[ lastByte++ ] & ( ( 1 << offsetLeft ) - 1 ) ) << ( diff-- << 3 ) - offsetRight : 0 ); diff; sum += shl( this.buffer[ lastByte++ ], ( diff-- << 3 ) - offsetRight ) );
  34  			return sum;
  35  		};
  36  	}
  37  	p.warn = function( msg ){
  38  		if( this.allowExceptions )
  39  			throw new Error( msg );
  40  		return 1;
  41  	};
  42  	p.decodeFloat = function( data, precisionBits, exponentBits ){
  43  		var b = new this.Buffer( this.bigEndian, data );
  44  		b.checkBuffer( precisionBits + exponentBits + 1 );
  45  		var bias = Math.pow( 2, exponentBits - 1 ) - 1, signal = b.readBits( precisionBits + exponentBits, 1 ), exponent = b.readBits( precisionBits, exponentBits ), significand = 0,
  46  		divisor = 2, curByte = b.buffer.length + ( -precisionBits >> 3 ) - 1;
  47  		do
  48  			for( var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 );
  49  		while( precisionBits -= startBit );
  50  		return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 );
  51  	};
  52  	p.decodeInt = function( data, bits, signed ){
  53  		var b = new this.Buffer( this.bigEndian, data ), x = b.readBits( 0, bits ), max = Math.pow( 2, bits );
  54  		return signed && x >= max / 2 ? x - max : x;
  55  	};
  56  	p.encodeFloat = function( data, precisionBits, exponentBits ){
  57  		var bias = Math.pow( 2, exponentBits - 1 ) - 1, minExp = -bias + 1, maxExp = bias, minUnnormExp = minExp - precisionBits,
  58  		status = isNaN( n = parseFloat( data ) ) || n == -Infinity || n == +Infinity ? n : 0,
  59  		exp = 0, len = 2 * bias + 1 + precisionBits + 3, bin = new Array( len ),
  60  		signal = ( n = status !== 0 ? 0 : n ) < 0, n = Math.abs( n ), intPart = Math.floor( n ), floatPart = n - intPart,
  61  		i, lastBit, rounded, j, result;
  62  		for( i = len; i; bin[--i] = 0 );
  63  		for( i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor( intPart / 2 ) );
  64  		for( i = bias + 1; floatPart > 0 && i; ( bin[++i] = ( ( floatPart *= 2 ) >= 1 ) - 0 ) && --floatPart );
  65  		for( i = -1; ++i < len && !bin[i]; );
  66  		if( bin[( lastBit = precisionBits - 1 + ( i = ( exp = bias + 1 - i ) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - ( exp = minExp - 1 ) ) ) + 1] ){
  67  			if( !( rounded = bin[lastBit] ) )
  68  				for( j = lastBit + 2; !rounded && j < len; rounded = bin[j++] );
  69  			for( j = lastBit + 1; rounded && --j >= 0; ( bin[j] = !bin[j] - 0 ) && ( rounded = 0 ) );
  70  		}
  71  		for( i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i]; );
  72  		if( ( exp = bias + 1 - i ) >= minExp && exp <= maxExp )
  73  			++i;
  74  		else if( exp < minExp ){
  75  			exp != bias + 1 - len && exp < minUnnormExp && this.warn( "encodeFloat::float underflow" );
  76  			i = bias + 1 - ( exp = minExp - 1 );
  77  		}
  78  		if( intPart || status !== 0 ){
  79  			this.warn( intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status );
  80  			exp = maxExp + 1;
  81  			i = bias + 2;
  82  			if( status == -Infinity )
  83  				signal = 1;
  84  			else if( isNaN( status ) )
  85  				bin[i] = 1;
  86  		}
  87  		for( n = Math.abs( exp + bias ), j = exponentBits + 1, result = ""; --j; result = ( n % 2 ) + result, n = n >>= 1 );
  88  		for( n = 0, j = 0, i = ( result = ( signal ? "1" : "0" ) + result + bin.slice( i, i + precisionBits ).join( "" ) ).length, r = []; i; j = ( j + 1 ) % 8 ){
  89  			n += ( 1 << j ) * result.charAt( --i );
  90  			if( j == 7 ){
  91  				r[r.length] = String.fromCharCode( n );
  92  				n = 0;
  93  			}
  94  		}
  95  		r[r.length] = n ? String.fromCharCode( n ) : "";
  96  		return ( this.bigEndian ? r.reverse() : r ).join( "" );
  97  	};
  98  	p.encodeInt = function( data, bits, signed ){
  99  		var max = Math.pow( 2, bits );
 100  		( data >= max || data < -( max >> 1 ) ) && this.warn( "encodeInt::overflow" ) && ( data = 0 );
 101  		data < 0 && ( data += max );
 102  		for( var r = []; data; r[r.length] = String.fromCharCode( data % 256 ), data = Math.floor( data / 256 ) );
 103  		for( bits = -( -bits >> 3 ) - r.length; bits--; r[r.length] = "\0" );
 104  		return ( this.bigEndian ? r.reverse() : r ).join( "" );
 105  	};
 106  	p.toSmall    = function( data ){ return this.decodeInt( data,  8, true  ); };
 107  	p.fromSmall  = function( data ){ return this.encodeInt( data,  8, true  ); };
 108  	p.toByte     = function( data ){ return this.decodeInt( data,  8, false ); };
 109  	p.fromByte   = function( data ){ return this.encodeInt( data,  8, false ); };
 110  	p.toShort    = function( data ){ return this.decodeInt( data, 16, true  ); };
 111  	p.fromShort  = function( data ){ return this.encodeInt( data, 16, true  ); };
 112  	p.toWord     = function( data ){ return this.decodeInt( data, 16, false ); };
 113  	p.fromWord   = function( data ){ return this.encodeInt( data, 16, false ); };
 114  	p.toInt      = function( data ){ return this.decodeInt( data, 32, true  ); };
 115  	p.fromInt    = function( data ){ return this.encodeInt( data, 32, true  ); };
 116  	p.toDWord    = function( data ){ return this.decodeInt( data, 32, false ); };
 117  	p.fromDWord  = function( data ){ return this.encodeInt( data, 32, false ); };
 118  	p.toFloat    = function( data ){ return this.decodeFloat( data, 23, 8   ); };
 119  	p.fromFloat  = function( data ){ return this.encodeFloat( data, 23, 8   ); };
 120  	p.toDouble   = function( data ){ return this.decodeFloat( data, 52, 11  ); };
 121  	p.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11  ); };
 122  }
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS