Skip to content

Commit

Permalink
0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Pupix committed Jun 28, 2015
1 parent 47b7d0b commit b530c35
Show file tree
Hide file tree
Showing 5 changed files with 560 additions and 323 deletions.
29 changes: 2 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# binary-file-parser (WIP)
A binary file parser with internal buffer and caching system that lets you read virtually infinitely sized files.
Badly written, working, 90% asynchronous and still under development.
Still under development.

## Simple example

Expand All @@ -16,25 +16,8 @@ var Parser = require('binary-file-parser'),
filesCount: 'uint'
});

parser.struct('Body', function (cache) {
var i,
files = [],
file = {};

parser.seek(cache.header.dataOffset);

for (i = 0; i < cache.header.structCount; i += 1) {
file.size = parser.uint();
file.bytes = parser.uint(file.size);
files.push(file);
}

return files;
});

parser.struct('myFile', {
header: 'Header',
data: 'Body'
});

parser.parse('myFile', function (err, data) {
Expand All @@ -45,14 +28,7 @@ var Parser = require('binary-file-parser'),
"id": 434,
"dataOffset": 20,
"filesCount": 3
},
"data": [
{
"size": 56
"bytes": [23, 87, 21, 46, ...]
}
...
]
}
}
});
```
Expand All @@ -71,7 +47,6 @@ var Parser = require('binary-file-parser'),
## Cache methods

### getCache
### clearCache

## Low level methods

Expand Down
227 changes: 227 additions & 0 deletions lib/buffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*jslint regexp:true, browser: true, devel: true, node: true, ass: true, nomen: true, unparam: true, indent: 4 */

(function () {
"use strict";

// Vars
var XP = require('expandjs'),
fs = require('xp-fs'),
Queue = require('smart-queue');


/*********************************************************************/

module.exports = new XP.Class('Stream', {

/**
*
* @param {Object} opt
* @param {string} opt.path
* @param {string} opt.chunkSize
*/
initialize: function (opt) {
var self = this;

XP.assertArgument(XP.isObject(opt), 1, 'Object');
XP.assertOption(XP.isString(opt.path), 'opt.path', 'string');
XP.assertOption(XP.isVoid(opt.chunkSize) || XP.isNumber(opt.chunkSize), 'opt.chunkSize', 'number or void');

self._path = opt.path;
self._chunkSize = opt.chunkSize || 64 * 1024;
self._initialize();

},

/**************************************************************/

_path: {
value: '',
configurable: false,
enumerable: false
},

_chunk: {
value: null,
configurable: false,
enumerable: false
},

_start: {
value: null,
configurable: false,
enumerable: false
},

_end: {
value: null,
configurable: false,
enumerable: false
},

_chunkSize: {
value: null,
configurable: false,
enumerable: false
},

_queue: {
value: new Queue(),
configurable: false,
enumerable: false
},

_reading: {
value: true,
configurable: false,
enumerable: false
},

/**************************************************************/

getPath: function () {
return this._path;
},

/**************************************************************/

read: {
promise: true,
value: function (length, offset, cb) {
var self = this,
chip;

self._queue.join(function () {
self._updateChunk(length, offset, function (err) {
if (!err && self._chunk) {
chip = new Buffer(self._chunk.slice(offset - self._start, (offset - self._start) + length));
}
cb(err, chip);
});
});
self._solveQueue();
},
configurable: false,
enumerable: false
},

close: {
promise: true,
value: function (cb) {
var self = this;
self._queue.join(function () {
fs.close(self._fd, cb);
});
self._solveQueue();
},
configurable: false,
enumerable: false
},

/**************************************************************/

_initialize: {
promise: true,
value: function () {

//Vars
var self = this;

//Checking
fs.stat(self._path, function (err, stats) {
if (err) { throw err; }
if (!stats.isFile()) { throw new Error('Specified path is not a file'); }

//Loading initial chunk
fs.open(self._path, 'r', function (err, fd) {
if (err) { throw err; }

self._fd = fd;
self._readChunk(0, function (err) {
if (err) { throw err; }
});
});
});
},
configurable: false,
enumerable: false
},

_updateChunk: {
promise: true,
value: function (length, offset, cb) {

//Vars
var self = this,
highMark,
lowMark;

//Defaults
offset = offset || 0;
length = length || 0;

//The new read's offset is lower than the one present in the current chunk
lowMark = XP.isNumeric(self._start) && (offset < self._start);

//The new read's length exceeds current chunk's bytes
highMark = XP.isNumeric(self._end) && (offset + length > self._end);

if (lowMark || highMark) {
return self._readChunk(offset, length, cb);
}

//CASE: Reading from the current chunk
cb();

},
configurable: false,
enumerable: false
},

_readChunk: {
promise: true,
value: function (offset, length, cb) {

//Vars
var self = this;

//Flag to interrupt new queue calls
self._reading = true;

fs.read(self._fd, new Buffer(self._chunkSize), 0, self._chunkSize, offset, function (err, bytes, buffer) {
if (err) { cb(err); }

//Setting
self._chunk = buffer.slice(0, bytes);
self._start = offset;
self._end = self._start + bytes;

//Reset queue flag
self._reading = false;

//Start resolving queue requests
self._solveQueue();
cb();
});

},
configurable: false,
enumerable: false
},

_solveQueue: {
value: function () {
var self = this,
q = self._queue,
tmp;

while (!self._reading && (undefined !== (tmp = q.next()))) {
tmp.value();
}
},
configurable: false,
enumerable: false
}

});

}());
56 changes: 39 additions & 17 deletions lib/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,66 @@
(function () {
"use strict";

var XP = require('expandjs'),
leet = require('l33teral');
var XP = require('expandjs'),
_ = require('lodash');

module.exports = new XP.Class('Cache', {

initialize: function () {
this.cache_ = leet({});
_cache: {
enumerable: false,
configurable: false,
value: {main: null}
},

cache_: {
_parent: {
value: 'main',
enumerable: false,
value: null
configurable: false
},

set: function (name, value) {
this.cache_.plant(name, value);
_getPath: function (name) {
return name ? this._parent + '.' + name : this._parent;
},

get: function (name, defaultValue) {
return this.cache_.tap(name, defaultValue);
_isValidPath: function (path) {
return !XP.includes(path, '$');
},

/**********************************************************************/
set: function (name, value) {
var self = this,
path = self._getPath(name);

if (self._isValidPath(path)) {
_.set(self._cache, path, value);
return _.get(self._cache, path);
}

purge: function () {
this.cache_ = leet({});
},

/**********************************************************************/
get: function (name) {
var self = this,
path = self._getPath(name);

return _.get(self._cache, path);
},

remove: function (name) {
if (name) {
var self = this,
path = self._getPath(name),
splices = path.split('.'),
toBeRemoved = splices.pop();

path = splices.join('.');

exists: function (name) {
return this.cache_.probe(name);
delete _.get(self._cache, path)[toBeRemoved];
}
},

/**********************************************************************/

getAll: function () {
return this.cache_.obj;
return this._cache[this._getPath()];
}
});

Expand Down
Loading

0 comments on commit b530c35

Please sign in to comment.