diff --git a/src/lib/binaryarray.ts b/src/lib/binaryarray.ts index a8f2522..b158e1a 100644 --- a/src/lib/binaryarray.ts +++ b/src/lib/binaryarray.ts @@ -11,6 +11,11 @@ export class BinaryArray{ this.maxnum = maxnum this.storage = createArray(getArraySize(maxnum), 0) } + /** + * resolve the internal position from the flag number. + * @param no flag number + * @returns Tuple of array index and bit flag + */ private findBitPosition(no : number) : TupleFlag { assert(this.maxnum > no, 'on:over flagmax') const idx = getArrayIndex(no) @@ -19,11 +24,21 @@ export class BinaryArray{ const flag = 1 << pos return [idx, flag] } + /** + * Set the bit of the specified flag number + * @param no flag number + * @returns this instance + */ bitOn(no : number) : BinaryArray{ const [idx, flag] = this.findBitPosition(no) this.storage[idx] |= flag return this } + /** + * Erase the bit of the specified flag number + * @param no flag number + * @returns this instance + */ bitOff(no : number) : BinaryArray{ const [idx, flag] = this.findBitPosition(no) if(this.storage[idx] & flag){ @@ -31,23 +46,20 @@ export class BinaryArray{ } return this } + /** + * Get the value of the specified flag number + * @param no flag number + * @returns this instance + */ at(no : number) : number{ const [idx, flag] = this.findBitPosition(no) return this.storage[idx] & flag ? 1 : 0 } - toArray() : Array{ - const results : Array = Array.from( Array(this.maxnum), (v, idx) => this.at(idx)) - return results - } - serialize(spec : Object) : Array{ - assert(spec instanceof Object, 'spec is must be Object') - const flaglist = this.toArray() - return Object.keys(spec) - .filter((k) => flaglist[spec[k]]) - } - toJSON() : string{ - return JSON.stringify(this.toArray()) - } + /** + * Check whether the flag number is valid + * @param no flag number + * @returns + */ isRange(no : number) : boolean{ if(!(this.maxnum > no)){ return false @@ -58,6 +70,11 @@ export class BinaryArray{ } return true } + /** + * Specify multiple flag numbers to acquire + * @param no_list flag numbers + * @returns + */ rangeOf(no_list : number | Array) : Object{ const xs = (no_list instanceof Array) ? no_list : [no_list] return xs.reduce((r : Object, no : number) => { @@ -65,6 +82,12 @@ export class BinaryArray{ return r }, {}) } + /** + * Specify multiple flag numbers and check whether condition is satisfied + * @param on_list flag on list + * @param off_list flag off list [optional] + * @returns + */ check(on_list : Array, off_list : Array = []) : boolean{ const on = this.rangeOf(on_list) const off = this.rangeOf(off_list) @@ -72,6 +95,36 @@ export class BinaryArray{ const y = Object.keys(off).reduce((r, v) => { return r & ~off[v] }, 1) return (x & y) ? true : false } + /** + * export flag list + * @returns flaglist + */ + toArray() : Array{ + const results : Array = Array.from( Array(this.maxnum), (v, idx) => this.at(idx)) + return results + } + /** + * Serialize flag data with Enum-like object. + * @param enum-like object + * @returns serialized string list + */ + serialize(spec : Object) : Array{ + assert(spec instanceof Object, 'spec is must be Object') + const flaglist = this.toArray() + return Object.keys(spec) + .filter((k) => flaglist[spec[k]]) + } + /** + * JSON wrap toArray method + * @returns JSON string + */ + toJSON() : string{ + return JSON.stringify(this.toArray()) + } + /** + * internal storage to hex string + * @returns hexstring + */ toHexString() : string{ let str = '' const n = this.storage.length @@ -80,34 +133,54 @@ export class BinaryArray{ } return str } + /** + * make clone instance + * @returns new instance + */ clone() : BinaryArray{ return BinaryArray.loadFromArray(this.toArray()) } - static loadFromHexString(maxnum : number, str : string) : BinaryArray{ + /** + * create new instance from hex string + * @param maxnum max flag number + * @param hexstr hexstring + * @returns new instance + */ + static loadFromHexString(maxnum : number, hexstr : string) : BinaryArray{ const ba = new BinaryArray(maxnum) - const s = 8 - let b = str.length - s - let e = str.length - 0 - const n = str.length / s + const s = 8 // bitsize + let b = hexstr.length - s + let e = hexstr.length - 0 + const n = hexstr.length / s for(let i = 0; i < n; ++i){ - ba.storage[i] = parseInt(str.substring(b, e), 16) + ba.storage[i] = parseInt(hexstr.substring(b, e), 16) b -= s e -= s } return ba } + /** + * create new instance from flag array + * @param flaglist + * @returns new instance + */ static loadFromArray(flaglist : Array) : BinaryArray{ - const ba = new BinaryArray(flaglist.length) - flaglist.map((v : number, i : number) : TupleFlag => [i, v]) + return flaglist.map((value : number, index : number) : TupleFlag => [index, value]) .filter((tuple) => tuple[1]) - .forEach((tuple) => { - ba.bitOn(tuple[0]) - }) - return ba - } - static deserialize(list : Array, spec : Object, max : number) : BinaryArray{ - const ba = new BinaryArray(max) - list.forEach((v) => { ba.bitOn(spec[v]) }) - return ba + .reduce((ba : BinaryArray, tuple : TupleFlag) => { + return ba.bitOn(tuple[0]) + }, new BinaryArray(flaglist.length)) + } + /** + * create new instance from serialize data + * @param keylist enum-like key + * @param spec enum-like object + * @param maxnum max flag number + * @returns new instance + */ + static deserialize(keylist : Array, spec : Object, maxnum : number) : BinaryArray{ + return keylist.map(key => spec[key]).reduce((ba : BinaryArray, no : number) => { + return ba.bitOn(no) + }, new BinaryArray(maxnum)) } }