<commit_before>"use strict";

var events = require ("events");
var util = require ("util");
var fs = require ("fs");
var dq = require ("../lib");

var Reader = function (path){
	events.EventEmitter.call (this);
	this._path = path;
	this._fd = null;
	var me = this;
	this._q = dq.create ();
	this._q.on ("error", function (error){
		//Forward the queue error event to the reader error handler
		me.close (function (){
			me.emit ("error", error);
		});
	});
};

util.inherits (Reader, events.EventEmitter);

Reader.prototype._open = function (cb){
	var me = this;
	fs.open (this._path, "r", function (error, fd){
		if (error) return cb (error);
		me._fd = fd;
		cb ();
	});
};

Reader.prototype.close = function (){
	var me = this;
	
	this._q.push (function (done){
		if (!me._fd) return done ();
		fs.close (me._fd, function (error){
			done (error);
		});
	}, function (error){
		//If an error occurs we don't want to call the default error handler
		//because it tries to close the file automatically, so if close fails
		//there will be infinite calls to close
		if (error){
			this.preventDefault ();
			me.emit ("error", error);
		}else{
			me.emit ("close");
		}
	});
};

Reader.prototype.read = function (bytes, cb){
	var me = this;
	var buffer = new Buffer (bytes);
	
	this._q.push (function (done){
		var read = function (){
			fs.read (me._fd, buffer, 0, bytes, null,
					function (error, bytesRead, buffer){
				if (error) return done (error);
				done (null, bytesRead, buffer.slice (0, bytesRead));
			});
		};
	
		if (!me._fd){
			me._open (function (error){
				if (error) return done (error);
				read ();
			});
		}else{
			read ();
		}
	}, function (error, bytesRead, buffer){
		if (!error) cb (bytesRead, buffer);
	});
	
	return this;
};

new Reader ("reader.js")
		.on ("error", function (error){
			console.error (error);
		})<commit_msg>updated reader example<commit_after>"use strict";

var events = require ("events");
var util = require ("util");
var fs = require ("fs");
var dq = require ("../lib");

/*
The basic idea for wrapping asynchronous functions is to execute the original
code from inside a task.
*/

var Reader = function (path){
	events.EventEmitter.call (this);
	this._path = path;
	this._fd = null;
	var me = this;
	this._q = dq.create ();
	this._q.on ("error", function (error){
		//Forward the queue error event to the reader error handler
		if (!me._fd) return me.emit ("error", error);
		fs.close (me._fd, function (){
			//The close error is ignored
			me.emit ("error", error);
		});
	});
};

util.inherits (Reader, events.EventEmitter);

Reader.prototype._open = function (cb){
	var me = this;
	fs.open (this._path, "r", function (error, fd){
		if (error) return cb (error);
		me._fd = fd;
		cb ();
	});
};

Reader.prototype.close = function (){
	var me = this;
	
	this._q.push (function (done){
		if (!me._fd) return done ();
		fs.close (me._fd, function (error){
			done (error);
		});
	}, function (error){
		//If an error occurs we don't want to call the default error handler
		//because it tries to close the file automatically, so if close fails
		//there will be infinite calls to close
		if (error){
			this.preventDefault ();
			me.emit ("error", error);
		}else{
			me.emit ("close");
		}
	});
};

Reader.prototype.read = function (bytes, cb){
	var me = this;
	
	this._q.push (function (done){
		var read = function (){
			fs.read (me._fd, new Buffer (bytes), 0, bytes, null,
					function (error, bytesRead, buffer){
				if (error) return done (error);
				done (null, bytesRead, buffer.slice (0, bytesRead));
			});
		};
	
		if (!me._fd){
			me._open (function (error){
				if (error) return done (error);
				read ();
			});
		}else{
			read ();
		}
	}, function (error, bytesRead, buffer){
		if (!error) cb (bytesRead, buffer);
	});
	
	return this;
};

new Reader ("reader.js")
		.on ("error", function (error){
			console.error (error);
		})
{'fraction_non_alphanumeric': 0.170550576184379, 'fraction_numerical': 0.001024327784891165, 'mean_word_length': 3.2595419847328246, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1632698', 'n_tokens_mistral': 1442, 'n_tokens_neox': 1297, 'n_words': 444}