Permalink
Browse files

v1.0.0

  • Loading branch information...
1 parent e1db729 commit e82a0d4a05e83a5f2a4a75eb33e15f413df03483 Gabriel Llamas committed Oct 4, 2012
View
@@ -3,50 +3,60 @@
Node BufferedReader
===================
-#### Fully configurable buffered reader for node.js ####
+#### Binary and streamed data buffers readers for node.js ####
[Show me!](#showme) | [Availability](#availability) | [Compatibility](#compatibility) | [Documentation](#documentation)
-Version: 0.2.7
+Version: 1.0.0
When you need to read a file you typically read a chunk of bytes called "buffer" to avoid multiple calls to the underlying I/O layer, so instead of reading directly from the disk, you read from the previous filled buffer. Doing this you win performance.
-This library allows you to read files using internal buffers, so you don't have to worry about them. In addition, you can read a text file line by line.
+This library allows you to read files without worry about the buffers. There are two ways to read the files. The first can only read binary data and has a pointer to move along the file (seek, skip, read). The second performs a read from the beginning to the end of the file and produces different events (byte, character, line, buffer...).
<a name="showme"></a>
#### Show me! [](#start) ####
```javascript
-var BufferedReader = require ("buffered-reader");
-
+var reader = require ("../build/buffered-reader");
+var BinaryReader = reader.BinaryReader;
+var DataReader = reader.DataReader;
+
+var close = function (binaryReader, error){
+ if (error) console.log (error);
+
+ binaryReader.close (function (error){
+ if (error) console.log (error);
+ });
+};
+
+var file = "file";
var offset;
-new BufferedReader ("file", { encoding: "utf8" })
- .on ("error", function (error){
- console.log (error);
- })
- .on ("line", function (line, byteOffset){
- if (line === "Phasellus ultrices ligula sed odio ultricies egestas."){
- offset = byteOffset;
- this.interrupt ();
- }
- })
- .on ("end", function (){
- this.seek (offset, function (error){
- if (error) return console.log (error);
-
- this.readBytes (9, function (error, bytes, bytesRead){
- if (error) return console.log (error);
-
- console.log (bytes.toString ()); //Prints: Curabitur
-
- this.close (function (error){
- if (error) console.log (error);
- });
- });
- });
- })
- .read ();
+new DataReader (file, { encoding: "utf8" })
+ .on ("error", function (error){
+ console.log (error);
+ })
+ .on ("line", function (line, byteOffset){
+ if (line === "Phasellus ultrices ligula sed odio ultricies egestas."){
+ offset = byteOffset;
+ this.interrupt ();
+ }
+ })
+ .on ("end", function (){
+ new BinaryReader (file)
+ .seek (offset, function (error){
+ if (error) return close (this, error);
+
+ this.read (9, function (error, bytes, bytesRead){
+ if (error) return close (this, error);
+
+ console.log (bytes.toString ()); //Prints: Curabitur
+
+ close (this);
+ });
+ });
+ })
+ .read ();
```
file:
@@ -1 +1 @@
-"use strict";var EVENTS=require("events"),FS=require("fs"),Error=require("errno-codes");Error.create(Error.getNextAvailableErrno(),"INVALID_BUFFER_SIZE","The buffer size must be greater than 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_START_OFFSET","The start offset must be greater than or equals to 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_END_OFFSET","The end offset must be greater than or equals to 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_RANGE_OFFSET","The end offset must be greater than or equals to the start offset."),Error.create(Error.getNextAvailableErrno(),"INVALID_BYTES_RANGE_ERROR","The number of bytes to read must be greater than 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_SEEK_OFFSET","The offset must be greater than or equals to 0."),Error.create(Error.getNextAvailableErrno(),"NO_FILE","The source is not a file.");var BUFFER_SIZE=16384,BufferedReader=function(e,t){EVENTS.EventEmitter.call(this),t=t||{},t.bufferSize===0&&(t.bufferSize=-1),this._settings={bufferSize:t.bufferSize||BUFFER_SIZE,encoding:t.encoding||null,start:t.start||0,end:t.end};if(this._settings.bufferSize<1)throw Error.get(Error.INVALID_BUFFER_SIZE);if(this._settings.start<0)throw Error.get(Error.INVALID_START_OFFSET);if(this._settings.end<0)throw Error.get(Error.INVALID_END_OFFSET);if(this._settings.end<this._settings.start)throw Error.get(Error.INVALID_RANGE_OFFSET);this._fileName=e,this._reset()};BufferedReader.prototype=Object.create(EVENTS.EventEmitter.prototype),BufferedReader.prototype.constructor=BufferedReader,BufferedReader.prototype._init=function(e){var t=this;FS.stat(this._fileName,function(n,r){if(n)return e(n);if(r.isFile()){if(t._settings.start>=r.size)return t._isEOF=!0,e(null);!t._settings.end&&t._settings.end!==0&&(t._settings.end=r.size),t._settings.end>=r.size&&(t._settings.end=r.size-1),t._fileSize=r.size,e(null)}else e(Error.get(Error.NO_FILE))})},BufferedReader.prototype._read=function(e){var t=this,n=this._settings.bufferSize;FS.read(this._fd,this._buffer,0,n,this._fileOffset,function(r,i){if(r)return e(r);t._fileOffset+=i,t._fileOffset===t._fileSize&&(t._noMoreBuffers=!0),i<n&&(t._buffer=t._buffer.slice(0,i)),e(null)})},BufferedReader.prototype._readBytes=function(e,t){if(this._needRead){this._needRead=!1;var n=this;this._read(function(r){if(r)return t(r,null,-1);n._readBytes(e,t)});return}var r=function(){var i=e-n._dataOffset,o=n._buffer.length-n._bufferOffset,u=o<=i?o:i;n._buffer.copy(s,n._dataOffset,n._bufferOffset,n._bufferOffset+u),n._bufferOffset+=u,n._realOffset+=u,n._bufferOffset===n._buffer.length&&(n._bufferOffset=0,n._needRead=!0),n._dataOffset+=u,n._dataOffset===e?(n._dataOffset=0,n._isEOF=n._noMoreBuffers,t(null,s,e)):n._noMoreBuffers?(n._isEOF=!0,u=n._dataOffset,n._dataOffset=0,t(null,s.slice(0,u),u)):(n._needRead=!1,n._read(function(e){if(e)return t(e,null,-1);r()}))},n=this,i=n._settings.end-n._realOffset+1;e=i<e?i:e;if(e===0)return t(null,null,0);var s=new Buffer(e),o=n._buffer.length;if(e<=o){var u=n._bufferOffset+e;if(u<=o)n._buffer.copy(s,0,n._bufferOffset,u),n._bufferOffset=u,n._realOffset+=e,t(null,s,e);else{var a=o-n._bufferOffset;n._realOffset+=a,a!==0&&n._buffer.copy(s,0,n._bufferOffset,n._bufferOffset+a);if(n._noMoreBuffers)return n._isEOF=!0,t(null,s.slice(0,a),a);n._read(function(r){if(r)return t(r,null,-1);o=n._buffer.length;var i=e-a;if(o<=i){n._realOffset+=o,n._isEOF=!0,n._buffer.copy(s,a,0,o);var u=a+o;t(null,s.slice(0,u),u)}else n._realOffset+=i,n._bufferOffset=i,n._buffer.copy(s,a,0,n._bufferOffset),t(null,s,e)})}}else r()},BufferedReader.prototype._reset=function(){this._fd=null,this._buffer=null,this._fileOffset=this._settings.start,this._bufferOffset=0,this._dataOffset=0,this._realOffset=this._settings.start,this._fileSize=null,this._initialized=!1,this._interrupted=!1,this._isEOF=!1,this._noMoreBuffers=!1,this._needRead=!1,this._reading=!1,this._stream=null},BufferedReader.prototype.close=function(e){e&&(e=e.bind(this));if(!this._fd){e&&e(null);return}var t=this;FS.close(this._fd,function(n){t._reset(),e&&e(n||null)})},BufferedReader.prototype.interrupt=function(){this._reading&&(this._interrupted=!0)},BufferedReader.prototype.pause=function(){this._stream&&this._stream.pause()},BufferedReader.prototype.read=function(){var e=this;FS.stat(this._fileName,function(t,n){if(t)return e.emit("error",t);e._reading=!0,e._stream=FS.createReadStream(e._fileName,e._settings),e._writeStream&&e._stream.pipe(e._writeStream);var r=null,i=0,s=n.size,o=e.listeners("character").length!==0,u=e.listeners("line").length!==0,a=e.listeners("byte").length!==0,f=o||u||a;e._stream.on("data",function(t){var n=0,l,c,h=t.length,p=!1;if(f){for(var d=0;d<h;d++){if(e._interrupted)break;c=t[d];if(!e._stream.encoding){i++,a&&e.emit("byte",c,i===s?-1:i);continue}i+=Buffer.byteLength(c,e._settings.encoding),o&&e.emit("character",c,i===s?-1:i);if(!u)continue;if(c==="\r"){p=!0;continue}c==="\n"&&(l=t.slice(n,p?d-1:d),n=d+1,r&&(l=r.concat(l),r=null),e.emit("line",l,i===s?-1:i)),p=!1}if(u&&e._stream.encoding&&n!==h){var v=n===0?t:t.slice(n);r=r?r.concat(v):v}}else i+=h;e.emit("buffer",t,i===s?-1:i),e._interrupted&&(e._interrupted=!1,e._stream.destroy(),e.emit("end"))}).on("end",function(){e._interrupted=!1,f&&r&&e.emit("line",r,i),e._reading=!1,e._stream=null,e.emit("end")}).on("error",function(t){e._interrupted=!1,e.emit("error",t)})})},BufferedReader.prototype.readBytes=function(e,t){t=t.bind(this);if(e<1||this._isEOF)return t(null,null,0);var n=function(){if(r._isEOF)return t(null,null,0);FS.open(r._fileName,"r",function(n,i){if(n){r.close(function(e){t(e,null,-1)});return}r._fd=i,r._buffer=new Buffer(r._settings.bufferSize),r._read(function(n){if(n){r.close(function(e){t(e,null,-1)});return}r._readBytes(e,function(e,n,i){if(e){r.close(function(e){t(e,n,i)});return}t(e,n,i)})})})},r=this;if(!this._initialized)this._init(function(e){if(e)return t(e,null);r._initialized=!0,n()});else{if(!this._fd)return n();this._readBytes(e,t)}},BufferedReader.prototype.resume=function(){this._stream&&this._stream.resume()},BufferedReader.prototype.seek=function(e,t){t=t.bind(this);if(e<0)return t(Error.get(Error.INVALID_SEEK_OFFSET));var n=function(){e+=r._settings.start;if(e>=r._settings.end+1)r._isEOF=!0;else{r._isEOF=!1;var n=r._fileOffset-(r._buffer?r._buffer.length:0);e>=n&&e<r._fileOffset?(r._bufferOffset=e-n,r._realOffset=e):(r._needRead=r._fd?!0:!1,r._noMoreBuffers=!1,r._fileOffset=e,r._bufferOffset=0,r._realOffset=e)}t(null)},r=this;this._initialized?n():this._init(function(e){if(e)return t(e,null);r._initialized=!0,n()})},BufferedReader.prototype.skip=function(e,t){t=t.bind(this);if(e<1||this._isEOF)return t(null,0);var n=function(){var n=r._settings.end-r._realOffset+1;e=e<=n?e:n,r.seek(r._realOffset-r._settings.start+e,function(){t(null,e)})},r=this;this._initialized?n():this._init(function(e){if(e)return t(e,null);r._initialized=!0,n()})},module.exports=BufferedReader;
+"use strict";var EVENTS=require("events"),FS=require("fs"),Error=require("errno-codes");Error.create(Error.getNextAvailableErrno(),"INVALID_BUFFER_SIZE","The buffer size must be greater than 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_WINDOW_START_OFFSET","The start offset must be greater than or equals to 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_WINDOW_END_OFFSET","The end offset must be greater than or equals to 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_WINDOW_RANGE_OFFSET","The end offset must be greater than or equals to the start offset and both of them must be inside the file range. Window: [{ws}, {we}], File: [0, {fe}]."),Error.create(Error.getNextAvailableErrno(),"INVALID_BYTES_RANGE_ERROR","The number of bytes to read must be greater than 0."),Error.create(Error.getNextAvailableErrno(),"INVALID_SEEK_OFFSET","The relative offset must be inside the window range. Relative offset: {offset}, Relative window: [0, {we}]."),Error.create(Error.getNextAvailableErrno(),"NO_FILE","The source is not a file."),Error.create(Error.getNextAvailableErrno(),"EMPTY_FILE","The file is empty."),Error.create(Error.getNextAvailableErrno(),"INVALID_READ_BYTES","The number of bytes to read must be equal or greater than 1.");var File=function(a){this._name=a,this._fd=null,this.size=null,this.isFile=null};File.prototype.readMetadata=function(a){var b=this;FS.stat(this._name,function(c,d){if(c)return a(c);if(d.size===0)return a(Error.get(Error.EMPTY_FILE));b.size=d.size,b.isFile=d.isFile(),a(null)})},File.prototype.close=function(a){if(this._fd===null)return a(null);FS.close(this._fd,function(b){a(b||null)})},File.prototype.open=function(a){if(this._fd!==null)return a(null,this._fd);var b=this;FS.open(this._name,"r",function(c,d){if(c)return a(c,null);b._fd=d,a(null,d)})};var Frame=function(a,b){if(b<1)throw Error.get(Error.INVALID_BUFFER_SIZE);if(b===undefined||b===null)b=Frame.DEFAULT_SIZE;this._bufferedReader=a,this._buffer=null,this._size=b,this._fileStart=null,this._fileEnd=null};Frame.DEFAULT_SIZE=16384,Frame.prototype.toFrameOffset=function(a){return a-this._fileStart},Frame.prototype.isInside=function(a){return this._buffer===null?!1:a>=this._fileStart&&a<=this._fileEnd},Frame.prototype.isLastFrame=function(){return this._buffer===null?!1:this._fileEnd===this._bufferedReader._window._end},Frame.prototype.length=function(){return this._fileEnd-this._fileStart+1},Frame.prototype.read=function(a){this._buffer===null&&(this._buffer=new Buffer(this._size));var b=this;this._bufferedReader._file.open(function(c,d){if(c)return a(c);var e=b._bufferedReader._window._end-b._bufferedReader._globalOffset+1;e>b._size&&(e=b._size),FS.read(d,b._buffer,0,e,b._bufferedReader._globalOffset,function(c,d){if(c)return a(c);b._fileStart=b._bufferedReader._globalOffset,b._fileEnd=b._fileStart+d-1,a(null)})})};var Window=function(a,b,c){if(!c){if(a===undefined||a===null)a=0;if(a<0)throw Error.get(Error.INVALID_WINDOW_START_OFFSET);if(b<0)throw Error.get(Error.INVALID_WINDOW_END_OFFSET);if(a>b&&b!==undefined&&b!==null)throw Error.get(Error.INVALID_WINDOW_RANGE_OFFSET,{ws:a,we:b,fe:undefined})}else if(b>a&&b!==undefined&&b!==null&&a!==undefined&&a!==null)throw Error.get(Error.INVALID_WINDOW_RANGE_OFFSET,{ws:a,we:b,fe:undefined});this._fromEnd=c,this._start=a,this._end=b};Window.prototype.toAbsoluteOffset=function(a){return a===BinaryReader.START_OF_WINDOW?this._start:a===BinaryReader.END_OF_WINDOW?this._end:this._start+a},Window.prototype.isInside=function(a){return a===BinaryReader.START_OF_WINDOW||a===BinaryReader.END_OF_WINDOW?!0:a>=0&&a<=this._end-this._start},Window.prototype.setEnd=function(a){if(this._fromEnd){this._start=this._start!==undefined&&this._start!==null?a-this._start:a,this._end=this._end!==undefined&&this._end!==null?a-this._end:a;if(this._start>this._end)return Error.get(Error.INVALID_WINDOW_RANGE_OFFSET,{ws:this._start,we:this._end,fe:a})}else if(this._end===undefined||this._end===null){if(this._start>a)return Error.get(Error.INVALID_WINDOW_RANGE_OFFSET,{ws:this._start,we:this._end,fe:a});this._end=a}return null};var DataReader=function(a,b){EVENTS.EventEmitter.call(this),b=b||{},b.bufferSize===0&&(b.bufferSize=-1);if(b.bufferSize<1)throw Error.get(Error.INVALID_BUFFER_SIZE);if(b.bufferSize===undefined||b.bufferSize===null)b.bufferSize=Frame.DEFAULT_SIZE;this._settings={encoding:b.encoding||null,bufferSize:b.bufferSize,start:0},this._fileName=a,this._stream=null,this._reading=!1,this._interrupted=!1,this._paused=!1,this._line=null};DataReader.prototype=Object.create(EVENTS.EventEmitter.prototype),DataReader.prototype.constructor=DataReader,DataReader.prototype.interrupt=function(){this._reading&&(this._interrupted=!0)},DataReader.prototype.pause=function(){this._reading&&!this._paused&&(this._paused=!0)},DataReader.prototype.read=function(){var a=this;FS.stat(this._fileName,function(b,c){if(b)return a.emit("error",b);a._reading=!0,a._stream=FS.createReadStream(a._fileName,a._settings);var d=c.size,e=a.listeners("byte").length!==0,f=a.listeners("character").length!==0,g=a.listeners("line").length!==0,h=f||g||e,i=function(){return a._settings.start===d?-1:a._settings.start};a._stream.on("error",function(b){a.emit("error",b),a._interrupted=!1,a._paused=!1,a._line=null,a._settings.start=0}).on("end",function(){a._line&&a.emit("line",a._line,-1),a._interrupted=!1,a._paused=!1,a._line=null,a._settings.start=0,a._line=null,a.emit("end")}).on("data",function(b){var c,e=!1,f,j=0,k=b.length;if(h){for(var l=0;l<k;l++){if(a._interrupted||a._paused)break;c=b[l];if(!a._settings.encoding){a._settings.start++,a.emit("byte",c,i());continue}a._settings.start+=Buffer.byteLength(c,a._settings.encoding),a.emit("character",c,i());if(!g)continue;if(c==="\r"){e=!0;continue}c==="\n"&&(f=b.substring(j,e?l-1:l),j=l+1,a._line&&(f=a._line+f,a._line=null),a.emit("line",f,i())),e=!1}g&&a._settings.encoding&&j!==d&&!a._paused&&!a._interrupted&&(f=j!==0?b.substring(j):b,a._line=a._line?a._line+f:f)}else a._settings.start+=k;if(a._interrupt||a._pause)b=b.slice(0,a._settings.start);a.emit("buffer",b,i()),a._interrupted?(a._interrupted=!1,a._line=null,a._stream.destroy(),a.emit("end")):a._paused&&a._stream.destroy()})})},DataReader.prototype.resume=function(){this._reading&&this._paused&&(this._paused=!1,this.p=!0,this.read())};var BinaryReader=function(a,b){b=b||{},b.bufferSize===0&&(b.bufferSize=-1),this._window=new Window(b.start,b.end,b.fromEnd),this._file=new File(a),this._frame=new Frame(this,b.bufferSize),this._initialized=!1,this._globalOffset=null};BinaryReader.START_OF_WINDOW={},BinaryReader.END_OF_WINDOW={},BinaryReader.prototype._init=function(a){if(!this._initialized){var b=this;this._file.readMetadata(function(c){if(c)return a(c);if(b._file.isFile){var c=null;c=b._window.setEnd(b._file.size-1),b._globalOffset=b._window._start,c||(b._initialized=!0),a(c)}else a(Error.get(Error.NO_FILE))})}else a(null)},BinaryReader.prototype.close=function(a){a=a.bind(this),this._file.close(function(b){a(b||null)})},BinaryReader.prototype.getOffset=function(){return this._globalOffset},BinaryReader.prototype.isOffsetOutOfWindow=function(){return this._globalOffset==-1},BinaryReader.prototype.read=function(a,b){b=b.bind(this);if(a<1)return b(Error.get(Error.INVALID_READ_BYTES),null,0);if(this.isOffsetOutOfWindow())return b(null,new Buffer(0),0);var c=this._window._end-this._globalOffset+1;a>c&&(a=c);var d=new Buffer(a),e=this,f=function(){var c=0,f=a,g=e._globalOffset+a-1,h=!1;g>e._frame._fileEnd&&(h=!0,g=e._frame._fileEnd),e._frame._buffer.copy(d,c,e._frame.toFrameOffset(e._globalOffset),e._frame.toFrameOffset(g+1));var i=g-e._globalOffset+1;f-=i,c+=i,h?(e._globalOffset+=i,e._frame.read(function(g){if(g)return b(g,null,null);e._frame._buffer.copy(d,c,0,f),e._globalOffset+=f,e._globalOffset===e._window._end+1&&(e._globalOffset=-1),b(null,d,a)})):(e._globalOffset+=a,e._globalOffset===e._window._end+1&&(e._globalOffset=-1),b(null,d,a))},g=function(c,f){if(e._globalOffset>e._frame._fileEnd){e._frame.read(function(a){if(a)return b(a,null,0);g(c,f)});return}var h=e._frame._fileEnd-e._globalOffset+1;h>c&&(h=c);var i=e._frame.toFrameOffset(e._globalOffset);e._frame._buffer.copy(d,f,i,i+h),e._globalOffset+=h,f+=h,c-=h;if(c===0)return b(null,d,a);g(c,f)},h=function(){a<=e._frame.length()?f():g(a,0)};this._init(function(a){if(a)return b(a);e._frame.isInside(e._globalOffset)?h():e._frame.read(function(a){if(a)return b(a,null,0);h()})})},BinaryReader.prototype.seek=function(a,b){b=b.bind(this);var c=this;this._init(function(d){if(d)return b(d);c._window.isInside(a)?(c._globalOffset=c._window.toAbsoluteOffset(a),b(null)):c._file.close(function(){b(Error.get(Error.INVALID_SEEK_OFFSET,{offset:a,we:c._window._end-c._window._start}))})})},BinaryReader.prototype.skip=function(a,b){b=b.bind(this);var c=this;if(a===0||this.isOffsetOutOfWindow())return b(null,0);this._init(function(d){if(d)return b(d,null);var e=c._globalOffset+a;e>c._window._end?(e=c._window._end,a=c._window._end-c._globalOffset):e<c._window._start&&(e=c._window._start,a=c._window._start-c._globalOffset),c._globalOffset=e,b(null,a)})};var Deprecated=function(a,b){DataReader.call(this,a,b),BinaryReader.call(this,a,b),console.log("The BufferedReader function has been deprecated. Use DataReader or BinaryReader.\n")};Deprecated.prototype.interrupt=DataReader.prototype.interrupt,Deprecated.prototype.pause=DataReader.prototype.pause,Deprecated.prototype.read=DataReader.prototype.read,Deprecated.prototype.resume=DataReader.prototype.resume,Deprecated.prototype.close=BinaryReader.prototype.close,Deprecated.prototype.readBytes=BinaryReader.prototype.read,Deprecated.prototype.seek=BinaryReader.prototype.seek,Deprecated.prototype.skip=BinaryReader.prototype.skip,Deprecated.prototype._init=BinaryReader.prototype._init,Deprecated.prototype.isOffsetOutOfWindow=BinaryReader.prototype.isOffsetOutOfWindow,Deprecated.DataReader=DataReader,Deprecated.BinaryReader=BinaryReader,module.exports=Deprecated;
Oops, something went wrong.

0 comments on commit e82a0d4

Please sign in to comment.