//================================================================ // bits$ //================================================================ function bits$(def) { this.test = bits$test; this.turnOff = bits$turnOff; this.turnOn = bits$turnOn; this.toJSON = bits$toJSON; this.fromJSON = bits$fromJSON; this.next = bits$next; this.testCount = bits$testCount; this.clear = bits$clear; this.more_ = bits$more_; this.fromDef_ = bits$fromDef_; this.or = bits$or; this.and = bits$and; this.ranges = bits$ranges; this.clear(); if (def) this.fromDef_(def); } //================================================================ // bits$or //================================================================ function bits$or(A) { while (A.next()) this.turnOn(A.value); } //================================================================ // bits$and //================================================================ function bits$and(A) { while (this.next()) { if (!A.test(this.value)) this.turnOff(this.value); } } //================================================================ // bits$ranges //================================================================ function bits$ranges() { var i, text, min, max, count; text = ''; max = ''; min = ''; for (i = 0; i <= this.maxBit; ++i) { if (this.test(i)) { if (min === '') min = i; max = i; continue; } if (min === '') continue; if (text != '') text += ','; count = (max - min) + 1; if (count == 1) text += max; if (count > 1) text += min + ':' + max + ':' + count; min = ''; } if (min !== '') { if (text != '') text += ','; count = (max - min) + 1; if (count == 1) text += max; if (count > 1) text += min + ':' + max + ':' + count; } return text; } //================================================================ // bits$next //================================================================ function bits$next() { while (this.pos <= this.maxBit) { if (this.test(this.pos)) { this.value = this.pos; this.pos += 1; return true; } this.pos += 1; } this.pos = 0; this.value = -1; return false; } //================================================================ // bits$clear //================================================================ function bits$clear() { this.buffer = null; this.length = 0; this.allocated = 0; this.maxBit = -1; this.count = 0; this.value = -1; this.pos = 0; } //================================================================ // bits$bitCount (confirmation of "Count") //================================================================ function bits$testCount() { var i, count; count = 0; for (i = 0; i <= this.maxBit; ++i) { if (this.test(i)) count += 1; } return count; } //================================================================ // bits$toJSON //================================================================ function bits$toJSON() { var i, value, text, len, lastPos, lastStat, status, first; text = '{"count":' + this.count + ',"bitmap":['; lastStat = -199; count = 0; first = true; for (i = 0; i <= this.maxBit; ++i) { status = this.test(i); if (i == 0) { if (status) { text += '0'; first = false; } lastStat = status; } if (status == lastStat) { count += 1; continue; } if (!first) text += ','; first = false; text += count; lastStat = status; count = 1; } if (count > 0 && lastStat) text += ',' + count; text += ']}'; return text; } //================================================================ // bits$fromJSON //================================================================ function bits$fromJSON(text) { var def; this.clear(); def = JSON.parse(text); this.fromDef_(def); } //================================================================ // bits$fromDef_ //================================================================ function bits$fromDef_(def) { var i, status, list, offset, b; this.clear(); if (def.bitmap.length == 0) return; status = false; offset = 0; for (i = 0; i < def.bitmap.length; ++i) { count = def.bitmap[i]; if (status) { for (j = 0; j < count; ++j) { k = j + offset; this.turnOn(k); } } offset += count; status = !status; } } //================================================================ // bits$test //================================================================ function bits$test(pos) { var b, n, mask; if (pos < 0) return false; if (pos > this.maxBit) return false; b = Math.floor(pos / 32); n = pos % 32; mask = 0x80000000 >>> n; if ((this.buffer[b] & mask) == 0) return false; return true; } //================================================================ // bits$turnOn //================================================================ function bits$turnOn(min, max) { var b, n, mask, pos; if (arguments.length < 2) max = min; for (pos = min; pos <= max; ++pos) { if (pos < 0) continue; if (pos > this.maxBit) this.more_(pos); b = Math.floor(pos / 32); n = pos % 32; mask = 0x80000000 >>> n; if (this.buffer[b] & mask != 0) continue; this.buffer[b] = this.buffer[b] | mask; this.count += 1; } } //================================================================ // bits$turnOff //================================================================ function bits$turnOff(min, max) { var b, n, mask, pos, recalculate_max; if (arguments.length < 2) max = min; if (min > max) return; if (max > this.max_bit) max = this.max_bit; recalculate_max = false; for (pos = min; pos <= max; ++pos) { if (pos < 0) continue; if (pos == this.maxBit) recalculate_max = true; b = Math.floor(pos / 32); n = pos % 32; mask = 0x80000000 >>> n; if (this.buffer[b] & mask == 0) continue; this.buffer[b] = this.buffer[b] ^ mask; this.count -= 1; } if (!recalculate_max) return; for (i = this.maxBit; i >= 0; --i) { if (!this.test(i)) continue; this.maxBit = i; return; } this.maxBit = -1; } //================================================================ // bits$more_ //================================================================ function bits$more_(pos) { var i, len, size, buf; if (pos > this.maxBit) this.maxBit = pos; len = Math.floor(this.maxBit / 32) + 1; this.length = len; if (len < this.allocated) return; size = len + 50; buf = new Uint32Array(size); for (i = 0; i < this.allocated; ++i) buf[i] = this.buffer[i]; this.buffer = buf; this.allocated = size; this.length = len; }