You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
6.7 KiB
257 lines
6.7 KiB
5 years ago
|
/* Copyright (c) 2013 Rod Vagg, MIT License */
|
||
|
|
||
|
var xtend = require('xtend')
|
||
|
, AbstractIterator = require('./abstract-iterator')
|
||
|
, AbstractChainedBatch = require('./abstract-chained-batch')
|
||
|
|
||
|
function AbstractLevelDOWN (location) {
|
||
|
if (!arguments.length || location === undefined)
|
||
|
throw new Error('constructor requires at least a location argument')
|
||
|
|
||
|
if (typeof location != 'string')
|
||
|
throw new Error('constructor requires a location string argument')
|
||
|
|
||
|
this.location = location
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.open = function (options, callback) {
|
||
|
if (typeof options == 'function')
|
||
|
callback = options
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('open() requires a callback argument')
|
||
|
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
if (typeof this._open == 'function')
|
||
|
return this._open(options, callback)
|
||
|
|
||
|
process.nextTick(callback)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.close = function (callback) {
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('close() requires a callback argument')
|
||
|
|
||
|
if (typeof this._close == 'function')
|
||
|
return this._close(callback)
|
||
|
|
||
|
process.nextTick(callback)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.get = function (key, options, callback) {
|
||
|
var err
|
||
|
|
||
|
if (typeof options == 'function')
|
||
|
callback = options
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('get() requires a callback argument')
|
||
|
|
||
|
if (err = this._checkKeyValue(key, 'key', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (!this._isBuffer(key))
|
||
|
key = String(key)
|
||
|
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
if (typeof this._get == 'function')
|
||
|
return this._get(key, options, callback)
|
||
|
|
||
|
process.nextTick(function () { callback(new Error('NotFound')) })
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.put = function (key, value, options, callback) {
|
||
|
var err
|
||
|
|
||
|
if (typeof options == 'function')
|
||
|
callback = options
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('put() requires a callback argument')
|
||
|
|
||
|
if (err = this._checkKeyValue(key, 'key', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (err = this._checkKeyValue(value, 'value', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (!this._isBuffer(key))
|
||
|
key = String(key)
|
||
|
|
||
|
// coerce value to string in node, don't touch it in browser
|
||
|
// (indexeddb can store any JS type)
|
||
|
if (!this._isBuffer(value) && !process.browser)
|
||
|
value = String(value)
|
||
|
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
if (typeof this._put == 'function')
|
||
|
return this._put(key, value, options, callback)
|
||
|
|
||
|
process.nextTick(callback)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.del = function (key, options, callback) {
|
||
|
var err
|
||
|
|
||
|
if (typeof options == 'function')
|
||
|
callback = options
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('del() requires a callback argument')
|
||
|
|
||
|
if (err = this._checkKeyValue(key, 'key', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (!this._isBuffer(key))
|
||
|
key = String(key)
|
||
|
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
if (typeof this._del == 'function')
|
||
|
return this._del(key, options, callback)
|
||
|
|
||
|
process.nextTick(callback)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
|
||
|
if (!arguments.length)
|
||
|
return this._chainedBatch()
|
||
|
|
||
|
if (typeof options == 'function')
|
||
|
callback = options
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('batch(array) requires a callback argument')
|
||
|
|
||
|
if (!Array.isArray(array))
|
||
|
return callback(new Error('batch(array) requires an array argument'))
|
||
|
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
var i = 0
|
||
|
, l = array.length
|
||
|
, e
|
||
|
, err
|
||
|
|
||
|
for (; i < l; i++) {
|
||
|
e = array[i]
|
||
|
if (typeof e != 'object')
|
||
|
continue
|
||
|
|
||
|
if (err = this._checkKeyValue(e.type, 'type', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (err = this._checkKeyValue(e.key, 'key', this._isBuffer))
|
||
|
return callback(err)
|
||
|
|
||
|
if (e.type == 'put') {
|
||
|
if (err = this._checkKeyValue(e.value, 'value', this._isBuffer))
|
||
|
return callback(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (typeof this._batch == 'function')
|
||
|
return this._batch(array, options, callback)
|
||
|
|
||
|
process.nextTick(callback)
|
||
|
}
|
||
|
|
||
|
//TODO: remove from here, not a necessary primitive
|
||
|
AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) {
|
||
|
if ( start == null
|
||
|
|| end == null
|
||
|
|| typeof start == 'function'
|
||
|
|| typeof end == 'function') {
|
||
|
throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments')
|
||
|
}
|
||
|
|
||
|
if (typeof callback != 'function')
|
||
|
throw new Error('approximateSize() requires a callback argument')
|
||
|
|
||
|
if (!this._isBuffer(start))
|
||
|
start = String(start)
|
||
|
|
||
|
if (!this._isBuffer(end))
|
||
|
end = String(end)
|
||
|
|
||
|
if (typeof this._approximateSize == 'function')
|
||
|
return this._approximateSize(start, end, callback)
|
||
|
|
||
|
process.nextTick(function () {
|
||
|
callback(null, 0)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) {
|
||
|
var self = this
|
||
|
|
||
|
options = xtend(options)
|
||
|
|
||
|
;[ 'start', 'end', 'gt', 'gte', 'lt', 'lte' ].forEach(function (o) {
|
||
|
if (options[o] && self._isBuffer(options[o]) && options[o].length === 0)
|
||
|
delete options[o]
|
||
|
})
|
||
|
|
||
|
options.reverse = !!options.reverse
|
||
|
|
||
|
// fix `start` so it takes into account gt, gte, lt, lte as appropriate
|
||
|
if (options.reverse && options.lt)
|
||
|
options.start = options.lt
|
||
|
if (options.reverse && options.lte)
|
||
|
options.start = options.lte
|
||
|
if (!options.reverse && options.gt)
|
||
|
options.start = options.gt
|
||
|
if (!options.reverse && options.gte)
|
||
|
options.start = options.gte
|
||
|
|
||
|
if ((options.reverse && options.lt && !options.lte)
|
||
|
|| (!options.reverse && options.gt && !options.gte))
|
||
|
options.exclusiveStart = true // start should *not* include matching key
|
||
|
|
||
|
return options
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype.iterator = function (options) {
|
||
|
if (typeof options != 'object')
|
||
|
options = {}
|
||
|
|
||
|
options = this._setupIteratorOptions(options)
|
||
|
|
||
|
if (typeof this._iterator == 'function')
|
||
|
return this._iterator(options)
|
||
|
|
||
|
return new AbstractIterator(this)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype._chainedBatch = function () {
|
||
|
return new AbstractChainedBatch(this)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype._isBuffer = function (obj) {
|
||
|
return Buffer.isBuffer(obj)
|
||
|
}
|
||
|
|
||
|
AbstractLevelDOWN.prototype._checkKeyValue = function (obj, type) {
|
||
|
|
||
|
if (obj === null || obj === undefined)
|
||
|
return new Error(type + ' cannot be `null` or `undefined`')
|
||
|
|
||
|
if (this._isBuffer(obj)) {
|
||
|
if (obj.length === 0)
|
||
|
return new Error(type + ' cannot be an empty Buffer')
|
||
|
} else if (String(obj) === '')
|
||
|
return new Error(type + ' cannot be an empty String')
|
||
|
}
|
||
|
|
||
|
module.exports.AbstractLevelDOWN = AbstractLevelDOWN
|
||
|
module.exports.AbstractIterator = AbstractIterator
|
||
|
module.exports.AbstractChainedBatch = AbstractChainedBatch
|