docs: function( filename, config ) {
  
  	// Setup config
  	this.config = config || {};
  
  	// Debug
  	this.logPrefix = "";
  	this.logFlags = this.config['log'] || 0x00;
  
  	// If filename contains an extension, extract missing information
  	// in the config and trim it
  	if (filename.substr(-4) == ".jbb") {
  		filename = filename.substr(0,filename.length-4);
  		if (this.config['sparse'] === undefined)
  			this.config['sparse'] = false;
  	} else if (filename.substr(-5) == ".jbbp") {
  		filename = filename.substr(0,filename.length-5);
  		if (this.config['sparse'] === undefined)
  			this.config['sparse'] = true;
  	}
  
  	// Open parallel streams in order to avoid memory exhaustion.
  	// The final file is assembled from these chunks, or kept as-is if
  	// requested to separate into multiple bundles (sparse bundle).
  	this.filename = filename;
  	this.stream64 = new BinaryStream( filename + '_b64.jbbp', 8, ((this.logFlags & LOG.WRT) != 0) );
  	this.stream32 = new BinaryStream( filename + '_b32.jbbp', 4, ((this.logFlags & LOG.WRT) != 0) );
  	this.stream16 = new BinaryStream( filename + '_b16.jbbp', 2, ((this.logFlags & LOG.WRT) != 0) );
  	this.stream8  = new BinaryStream( filename + '.jbbp', 	  1, ((this.logFlags & LOG.WRT) != 0) );
  
  	// Counters for optimising the protocol
  	this.counters = {
  		op_ctr:  0, arr_chu: 0,
  		op_prm:  0, dat_hdr: 0,
  		ref_str: 0, op_iref: 0,
  		arr_hdr: 0, op_xref: 0,
  		arr_dat: 0,
  
  		arr_dws: 0,
  		arr_delta_float: 0,
  		arr_delta_int: 0,
  		arr_num_repeated: 0,
  		arr_num_raw : 0,
  		arr_num_short: 0,
  		arr_prim_bulk_plain: 0,
  		arr_prim_bulk_known: 0,
  		arr_prim_short: 0,
  		arr_prim_repeated: 0,
  		arr_prim_raw: 0,
  		arr_prim_chunk: 0,
  		arr_empty: 0,
  	};
  
  	// Optimisation flags
  	this.optimize = {
  		cfwa_object_byval: true,	 	// By-value de-duplication of objects in chunk forward analysis (increases encoding time)
  		repeat_break_thresshold: 0.50,	// How many consecutive same items are enough for a numeric array in order
  									 	// to break it as a chunked array.
  		repeat_thresshold: 0.50,	 	// How many items must be repeating in a chunk in order to prefer
  										// using reepated items (size optimisation) at cost of speed.
  		float_int_downscale: false,	 	// Downscale floats to integers multiplied by scale
  		enable_delta: true,				// Enable delta-encoding (costs in speed, but decreases size)
  	};
  
  	// Check if this is sparse
  	this.sparse = ( this.config['sparse'] === undefined ) ? 
  			false : this.config['sparse'];
  
  	// If we are requested to use sparse bundless, add some space for header in the stream8
  	if (this.sparse) {
  
  		this.stream8.write( pack2b( 0x4231 ) ); 	// Magic header
  		this.stream8.write( pack2b( 0 ) ); 			// Object Table ID
  		this.stream8.write( pack2b( VERSION ) );	// Protocol Version
  		this.stream8.write( pack2b( 0 ) ); 			// Reserved
  
  		this.stream8.write( pack4b( 0 ) ); // 64-bit buffer lenght
  		this.stream8.write( pack4b( 0 ) ); // 32-bit buffer lenght
  		this.stream8.write( pack4b( 0 ) ); // 16-bit buffer length
  		this.stream8.write( pack4b( 0 ) ); // 8-bit buffer length
  		this.stream8.write( pack4b( 0 ) ); // Length (in bytes) of string lookup table
  		this.stream8.write( pack4b( 0 ) ); // Length (in bytes) of plain object signature table
  
  	}
  
  	// Get base dir
  	this.baseDir = this.config['base_dir'] || false;
  	if (!this.baseDir) {
  		// Get base dir
  		var parts = this.filename.split("/");
  		parts.pop(); this.baseDir = parts.join("/");
  		// Add trailing slash
  		if (this.baseDir[this.baseDir.length-1] != "/")
  			this.baseDir += "/";
  	}
  
  	// Get bundle name
  	this.bundleName = this.config['name'] || filename.split("/").pop();;
  
  	// Create a combined profile object
  	this.profile = new EncodeProfile();
  
  	// Database properties
  	this.dbTags = [];
  	this.dbObjects = [];
  	this.database = {};
  
  	// By-Reference and By-Value lookup tables
  	this.indexRef = [];
  	this.indexVal = new Array( this.profile.size );
  
  	// String lookup table
  	this.stringLookup = [];
  	this.stringLookupQuick = {};
  
  	// Plain object signatures lookup table
  	this.plainObjectSignatureID = 0;
  	this.plainObjectSignatureLookup = {};
  	this.plainObjectSignatureTable = [];
  
  	// Flag to prohibit profile adding after first encoding
  	this.canAddProfile = true;
  
  	// Add config profile if needed
  	if ( this.config['profile'] ) {
  		var prof = this.config['profile'];
  		if ( prof instanceof Array ) {
  			for (var i=0; i<prof.length; i++) {
  				this.addProfile( prof[i] );
  			}
  		} else {
  			this.addProfile( prof );
  		}
  	}
  
  }