leveldb
Version:
Bindings for using LevelDB through node.
337 lines (259 loc) • 8.81 kB
JavaScript
// Generated by CoffeeScript 1.3.3
var Iterator, binding,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
binding = require('../../build/Release/leveldb.node');
/*
An iterator allows sequential and random access to the database.
Usage:
var leveldb = require('leveldb');
leveldb.open('/tmp/test.db', function(err, db) {
db.iterator(function(err, it) {
// iterator is initially invalid
it.first(function(err) {
// get a key
it.get('foobar', function(err, val) {
console.log(val);
});
});
});
});
*/
exports.Iterator = Iterator = (function() {
var toBuffer, toValue;
toBuffer = function(val) {
if (Buffer.isBuffer(val)) {
return val;
} else {
return new Buffer(val);
}
};
toValue = function(val, options) {
if (!val) {
return null;
} else if (!(options != null ? options.as_buffer : void 0)) {
return val.toString('utf8');
} else {
return val;
}
};
Iterator.prototype._wrapSeek = function(callback, validate) {
var _this = this;
this._lock();
if (validate && !this._valid) {
throw new Error('Illegal state');
}
if (!callback) {
throw new Error('Missing callback');
}
return function(err, valid, key, val) {
_this._unlock();
_this._valid = valid;
_this._key = key;
_this._val = val;
if (callback) {
return callback(err);
}
};
};
Iterator.prototype._lock = function() {
if (this._busy) {
throw new Error('Concurrent operations not supported');
}
return this._busy = true;
};
Iterator.prototype._unlock = function() {
if (!this._busy) {
throw new Error('Not locked');
}
return this._busy = false;
};
Iterator.prototype._getKey = function(options) {
return toValue(this._key, options);
};
Iterator.prototype._getVal = function(options) {
return toValue(this._val, options);
};
/*
Constructor.
@param {Native} self The underlying iterator object.
*/
function Iterator(self) {
this.self = self;
this._wrapSeek = __bind(this._wrapSeek, this);
this._busy = this._valid = false;
this._key = this._val = null;
}
/*
Apply a callback over a range.
The iterator will be positioned at the given key or the first key if
not given, then the callback will be applied on each record moving
forward until the iterator is positioned at the limit key or at an
invalid key. Stops on first error.
@param {String|Buffer} [startKey] Optional start key (inclusive) from
which to begin applying the callback. If not given, defaults to the
first key.
@param {String|Buffer} [limitKey] Optional limit key (inclusive) at
which to end applying the callback.
@param {Object} [options] Optional options.
@param {Boolean} [options.as_buffer=false] If true, data will be
returned as a `Buffer`.
@param {Function} callback The callback to apply to the range.
@param {Error} error The error value on error, null otherwise.
@param {String|Buffer} key The key.
@param {String|Buffer} value The value.
@param {Function} finishedCallback An optional callback being called when the limit key has been reached
*/
Iterator.prototype.forRange = function() {
var args, callback, finishedCallback, limit, limitKey, next, options, startKey,
_this = this;
args = Array.prototype.slice.call(arguments);
if (typeof args[args.length - 1] === 'function' && typeof args[args.length - 2] === 'function') {
finishedCallback = args.pop();
}
callback = args.pop();
if (!callback) {
throw new Error('Missing callback');
}
options = args[args.length - 1];
if (typeof options === 'object' && !Buffer.isBuffer(options)) {
args.pop();
} else {
options = {};
}
startKey = args[0], limitKey = args[1];
if (limitKey) {
limit = limitKey.toString('binary');
}
next = function(err) {
if (err) {
return callback(err);
}
if (_this._valid) {
callback(null, _this._getKey(options), _this._getVal(options));
if (!limit || limit !== _this._key.toString('binary')) {
return _this.next(next);
}
} else if (finishedCallback) {
return finishedCallback();
}
};
if (startKey) {
return this.seek(startKey, next);
} else {
return this.first(next);
}
};
/*
True if the iterator is positioned at a valid key.
*/
Iterator.prototype.valid = function() {
return this._valid;
};
/*
Position the iterator at a key.
@param {String} key The key at which to position the iterator.
@param {Function} [callback] Optional callback.
@param {Error} error The error value on error, null otherwise.
*/
Iterator.prototype.seek = function(key, callback) {
return this.self.seek(toBuffer(key), this._wrapSeek(callback));
};
/*
Position the iterator at the first key.
@param {Function} [callback] Optional callback.
@param {Error} error The error value on error, null otherwise.
*/
Iterator.prototype.first = function(callback) {
return this.self.first(this._wrapSeek(callback));
};
/*
Position the iterator at the last key.
@param {Function} [callback] Optional callback.
@param {Error} error The error value on error, null otherwise.
*/
Iterator.prototype.last = function(callback) {
return this.self.last(this._wrapSeek(callback));
};
/*
Advance the iterator to the next key.
@param {Function} [callback] Optional callback.
@param {Error} error The error value on error, null otherwise.
*/
Iterator.prototype.next = function(callback) {
return this.self.next(this._wrapSeek(callback, true));
};
/*
Advance the iterator to the previous key.
@param {Function} [callback] Optional callback.
@param {Error} error The error value on error, null otherwise.
*/
Iterator.prototype.prev = function(callback) {
return this.self.prev(this._wrapSeek(callback, true));
};
/*
Get the key at the current iterator position.
@param {Object} [options] Optional options.
@param {Boolean} [options.as_buffer=false] If true, data will be
returned as a `Buffer`.
@param {Function} callback The callback function.
@param {Error} error The error value on error, null otherwise.
@param {String|Buffer} key The key if successful.
*/
Iterator.prototype.key = function(options, callback) {
var key;
if (typeof options === 'function') {
callback = options;
options = null;
}
key = this._getKey(options);
if (typeof callback === "function") {
callback(null, key);
}
return key;
};
/*
Get the value at the current iterator position.
@param {Object} [options] Optional options.
@param {Boolean} [options.as_buffer=false] If true, data will be
returned as a `Buffer`.
@param {Function} callback The callback function.
@param {Error} error The error value on error, null otherwise.
@param {String|Buffer} value The value if successful.
*/
Iterator.prototype.value = function(options, callback) {
var val;
if (typeof options === 'function') {
callback = options;
options = null;
}
val = this._getVal(options);
if (typeof callback === "function") {
callback(null, val);
}
return val;
};
/*
Get the key and value at the current iterator position.
@param {Object} [options] Optional options.
@param {Boolean} [options.as_buffer=false] If true, data will be
returned as a `Buffer`.
@param {Function} callback The callback function.
@param {Error} error The error value on error, null otherwise.
@param {String|Buffer} key The key if successful.
@param {String|Buffer} value The value if successful.
*/
Iterator.prototype.current = function(options, callback) {
var key, val;
if (typeof options === 'function') {
callback = options;
options = null;
}
key = this._getKey(options);
val = this._getVal(options);
if (typeof callback === "function") {
callback(null, key, val);
}
return [key, val];
};
return Iterator;
})();