database-jones/Adapter/common/BitMask.js (129 lines of code) (raw):
/*
Copyright (c) 2013, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
"use strict";
var util = require("util");
/* BitMask is implemented as an array.
Each array element holds 24 bits.
Inside V8, array elements are SMIs.
*/
var radix = 24;
function BitMask(size) {
this._mask = [];
if(typeof size === 'number') {
this._grow(size);
}
else {
this._grow(radix);
}
this.displaySize = size || this.size;
}
function greater(x, y) {
return x > y ? x : y;
}
BitMask.prototype[util.inspect.custom] = function() {
var i, str = "";
for(i = 0 ; i < this.displaySize ; i++) {
str += this.bitIsSet(i) ? "1" : "0";
}
return str;
};
BitMask.prototype._grow = function(size) {
this.size = this._mask.length * radix; // round up
size -= this.size;
while(size > 0) {
this._mask.push(0);
this.size += radix;
size -= radix;
}
};
BitMask.prototype.set = function(bit) {
if(bit >= this.size) {
this._grow(bit);
}
var offset = bit % radix;
var loc = (bit - offset) / radix;
this._mask[loc] |= Math.pow(2, offset);
};
BitMask.prototype.bitIsSet = function(bit) {
if(bit >= this.size) {
this._grow(bit);
}
var offset = bit % radix;
var loc = (bit - offset) / radix;
return this._mask[loc] & Math.pow(2, offset) ? true : false;
};
BitMask.prototype._getPart = function(n) {
var p = 0;
if(n < this._mask.length) {
p = this._mask[n];
}
return p;
};
BitMask.prototype._binaryOp = function(op, that) {
var m, i, sz;
sz = greater(this.size, that.size);
m = new BitMask(sz);
for(i = 0 ; i < m._mask.length ; i++) {
switch(op) {
case 1: // AND
m._mask[i] = this._getPart(i) & that._getPart(i);
break;
case 2: // OR
m._mask[i] = this._getPart(i) | that._getPart(i);
break;
case 3: // XOR
m._mask[i] = this._getPart(i) ^ that._getPart(i);
break;
}
}
return m;
};
BitMask.prototype.and = function(that) {
return this._binaryOp(1, that);
};
BitMask.prototype.or = function(that) {
return this._binaryOp(2, that);
};
BitMask.prototype.xor = function(that) {
return this._binaryOp(3, that);
};
BitMask.prototype.orWith = function(that) {
var mask = this.or(that);
this.size = mask.size;
this._mask = mask._mask;
return this;
};
BitMask.prototype.isNonZero = function() {
var i;
for(i = 0 ; i < this._mask.length ; i++) {
if (this._mask[i]) { return true; }
}
return false;
};
BitMask.prototype.isEqualTo = function(that) {
var i, len;
len = greater(this._mask.length, that._mask.length);
for(i = 0 ; i < len ; i++) {
if(this._getPart(i) !== that._getPart(i)) {
return false;
}
}
return true;
};
BitMask.prototype.toArray = function() {
var array, n, offset;
array = [];
offset = 0;
function maskToIntArray(mask) {
var v, i;
i = 0;
while(mask != 0) {
v = Math.pow(2,i);
if(mask & v) {
mask ^= v;
array.push(i + offset);
}
i++;
}
}
for(n = 0 ; n < this._mask.length ; n++) {
maskToIntArray(this._mask[n]);
offset += radix;
}
return array;
};
module.exports = BitMask;