baja/obj/CategoryMask.js
/**
* @copyright 2023 Tridium, Inc. All Rights Reserved.
*/
/**
* Defines {@link baja.CategoryMask}.
* @private
* @module baja/obj/CategoryMask
*/
define([
'bajaScript/baja/obj/Simple' ], function (
Simple
) {
'use strict';
/**
* @class
* @alias module:baja/obj/CategoryMask
* @private
* @extends baja.Simple
* @since Niagara 4.14
*/
class CategoryMask extends Simple {
/**
* @param {string} hex the hex encoding for this mask
*/
constructor(hex) {
super();
validateHex(hex);
this.$hex = hex;
}
/**
* @param {number} categoryIndex
* @returns {boolean} true if the bit for that category index is set
*/
get(categoryIndex) {
const hex = this.$hex;
if (hex === '*') { return true; }
const bitIndex = categoryIndex - 1; // category 1 lives in bit 0
const bitInChar = bitIndex % 4; // each char holds 4 bits
const charIndex = Math.floor(bitIndex / 4);
const hexChar = hex[hex.length - 1 - charIndex];
return !!(parseInt(hexChar, 16) & (1 << bitInChar));
}
/**
* @returns {number} the number of categories represented by this mask
*/
size() {
const hex = this.$hex;
const largestChar = parseInt(hex[0], 16);
if (!largestChar) { return 0; }
const rest = (hex.length - 1) * 4;
if (largestChar & 8) { return 4 + rest; }
if (largestChar & 4) { return 3 + rest; }
if (largestChar & 2) { return 2 + rest; }
return 1 + rest;
}
/**
* @returns {boolean} true if this is the null/default instance
*/
isNull() {
return this === CategoryMask.DEFAULT;
}
/**
* @param {string|number[]} hex the hex string, or an array of category indices (1-indexed)
* @returns {module:baja/obj/CategoryMask}
*/
static make(hex) {
if (Array.isArray(hex)) {
let bytes = [];
hex.forEach((categoryIndex) => {
categoryIndex--; // 1-based to 0-based
const byteIndex = Math.floor(categoryIndex / 4);
bytes[byteIndex] = (bytes[byteIndex] || 0) | 1 << categoryIndex % 4;
});
for (let i = 0, len = bytes.length; i < len; ++i) {
bytes[i] = bytes[i] || 0;
}
const hexString = bytes.reverse().map((b) => b.toString(16)).join('');
return CategoryMask.make(hexString);
}
return hex ? new CategoryMask(hex) : CategoryMask.DEFAULT;
}
/**
* @param {string|number[]} hex the hex string, or an array of category indices (1-indexed)
* @returns {module:baja/obj/CategoryMask}
*/
make(hex) {
return CategoryMask.make(hex);
}
/**
* @param {string} str
* @returns {module:baja/obj/CategoryMask}
*/
decodeFromString(str) {
return this.make(str);
}
/**
* @returns {string}
*/
encodeToString() {
return this.$hex;
}
}
CategoryMask.DEFAULT = new CategoryMask('');
/** @param {string} hex */
function validateHex(hex) {
if (hex === '*') { return; }
if (hex[0] === '0') { throw new Error('No leading zero allowed'); }
for (let i = 0, len = hex.length; i < len; ++i) {
const char = hex[i];
if (!char.match(/[0-9a-f]/)) { throw new Error('Invalid char ' + char); }
}
}
return CategoryMask;
});