Skip to content

Instantly share code, notes, and snippets.

@elycruz
Last active September 16, 2022 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elycruz/52055e6260298d6f10a0c3c654ee5d66 to your computer and use it in GitHub Desktop.
Save elycruz/52055e6260298d6f10a0c3c654ee5d66 to your computer and use it in GitHub Desktop.
Flags system using bitwise operators and binary numerals (in javascript).
/**
* Storing flags in one variable and checking for
* enabled/disabled states using
* bitwise operators.
* @author elycruz
* @reference:
* - https://www.youtube.com/watch?v=RRyxCmLX_ag
* - https://www.youtube.com/watch?v=6hnLMnid1M0
*/
// Calls count to print in console
let callCount = 0;
// Store flags as binary numbers to show in what bit each flag will be stored in -
// ## General Idea
// A `0`, or `1` will be stored/produced for any given flag at the position where
// a `1` exist, in the flags declaration. Using bitwise operations, later,
// we can perform sum, difference, union, etc. operations (using bitwise operators),
// to extract/update any given set of runtime flag values:
const FlagsEnum = {
A: 0b001,
B: 0b010,
C: 0b100
},
// Hexadecimal numbers matching the powers of two
// Can be used for the same purpose (to represent flags
// where a single bits represent flags, etc.).
// Powers of two (continued from `FlagsEnum`)
FlagsEnum2 = {
D: 0x08,
E: 0x10,
F: 0x20,
G: 0x40
},
// Extract enums for use
{A, B, C} = FlagsEnum,
{D, E, F, G} = FlagsEnum2,
{log} = console,
// String to print from log util
// @see the following for string format parameters:
// MDN console - Web APIs -
// https://developer.mozilla.org/en-US/docs/Web/API/console#examples
flagsFmt = "Feature %s enabled; Feature Id: %d; \"\" Id as: binary: 0b%s; hex: 0x%s;",
logFlagEnum = x => {
// log('Call no. %d', callCount++);
// Here if any bitwise `&` operation returns `0` that particular flag is
// disabled:
let chosen = 0;
if (x & A) log(flagsFmt, 'A', A, A.toString(2), A.toString(16));
if (x & B) log(flagsFmt, 'B', B, B.toString(2), B.toString(16));
if (x & C) log(flagsFmt, 'C', C, C.toString(2), C.toString(16));
if (x & D) log(flagsFmt, 'D', D, D.toString(2), D.toString(16));
if (x & E) log(flagsFmt, 'E', E, E.toString(2), E.toString(16));
if (x & F) log(flagsFmt, 'F', F, F.toString(2), F.toString(16));
if (x & G) log(flagsFmt, 'G', G, G.toString(2), G.toString(16));
if (!x) log("No features enabled.");
};
const enums = [A, B, C, D, E, F, G];
log(...enums);
console.group('Individual Flags as features');
[0].concat(enums).map(logFlagEnum);
console.groupEnd();
logFlagEnum(A | B); // Bitwise `OR` (`|`), in our case it's a `SUM` op.
logFlagEnum(A | B | C); // ""
logFlagEnum(B | C); // ""
logFlagEnum(C); // ""
console.group('Disabling a flag');
// ## Storing flags in memory location:
let bool_settings = A | B | C | D | E | F | G; // For this example we enable all flags (SUM operation (bitwise `OR`)).
log('Stored flags:');
// Log enabled/disabled states
logFlagEnum(bool_settings);
// Disable a flag
bool_settings = bool_settings & (~B); // Flip bits in `B` (`0`s flipped to `1`s, and vice-versa) and then SUM that value with settings in `bool_settings` set.
log('Stored flags after `B` flag disable');
// Log states
logFlagEnum(bool_settings);
// Close `log` group
console.groupEnd();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment