Highlighting Bitmasks with React

The trend of resources (such as memory and disk space) becoming more abundant is still ongoing, and as a result, software development has become quite wasteful. While it’s quite common for an average application to guzzle several gigabytes of RAM nowadays, many people are not even aware that it’s possible to pack several pieces of information into the same byte. In fact, old games have been able to pack several pixels worth of data in a single byte, and this technique is still quite common for bit flags.

Bitmasks in Practice

Let’s consider a simple example: I have an RPG, where a character’s status can be one of the following values:

  • 1 = Paralysed
  • 2 = Poisoned
  • 4 = Diseased
  • 8 = Blind
  • 16 = Hungry
  • 32 = Fatigued

Using a power of two for each value means that I can use a single number to represent a combination of these values. For example:

  • 12 (decimal) = 001100 (binary) = Diseased and Blind
  • 2 (decimal) = 000010 (binary) = Poisoned
  • 63 (decimal) = 111111 (binary) = all six statuses apply

Each of these individual statuses is a flag with a boolean value. They are independent of each other and can be set simultaneously. By combining them into a single variable (called a bitmask) as shown above, we can store them more efficiently, both in memory and on disk.

The downside is that it becomes less readable. In order to know that a value of 21 means Hungry, Diseased and Paralysed, you need to break it down into individual bits and look up what each one means. That’s not a problem; in fact, we’ll build a little utility with React to help with this.

Listing the Bit Flags

We’re going to create a variation of the Filter List As You Type example that will list the individual flags and then highlight them based on user input. Start by creating a new React app. Once that’s done, open src/App.js and remove the logo import as well as everything inside the <header> tag so that you’re left with just this:

import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">

      </header>
    </div>
  );
}

export default App;

Next, create an object that maps the value of a flag to its description. This is just for display purposes. Inside the <header> element, use a simple map() function to display the flags (value and description) in a table:

import './App.css';

function App() {
  const flags = {
    1: 'Paralysed',
    2: 'Poisoned',
    4: 'Diseased',
    8: 'Blind',
    16: 'Hungry',
    32: 'Fatigued'
  };

  return (
    <div className="App">
      <header className="App-header">
        <table>
          <tbody>
          {
            Object.keys(flags).map(x => (
              <tr key={x}>
                <td>{x}</td>
                <td>{flags[x]}</td>
              </tr>))
          }
          </tbody>
        </table>
      </header>
    </div>
  );
}

export default App;

If you run npm start, you should be able to see the list of flags:

Listing the bit flags

Highlighting Bit Flags

Next, we’ll accept a bitmask (as a decimal number) as user input, and use it to highlight the relevant flags. This is very similar to what we did in Filter List As You Type with React, so start off by adding the relevant imports at the top of the file:

import React, { useState } from 'react';

Next, add the following to capture the state of the input field:

const [input, setInput] = useState('');

Add a text field right above the table:

        <input id="input"
          name="input"
          type="text"
          placeholder="Enter a bitmask in decimal"
          value={input}
          onChange={event => setInput(event.target.value)}
        />

Finally, we need to do the highlighting part. For this, we’ll add a getHighlightStyle() helper function, and use it on each row. The following is the full code for this article:

import React, { useState } from 'react';
import './App.css';

function App() {
  const flags = {
    1: 'Paralysed',
    2: 'Poisoned',
    4: 'Diseased',
    8: 'Blind',
    16: 'Hungry',
    32: 'Fatigued'
  };

  const [input, setInput] = useState('');

  const getHighlightStyle = flagValue =>
    (input & flagValue) > 0 ? { backgroundColor: 'red' } : null;

  return (
    <div className="App">
      <header className="App-header">
        <input id="input"
          name="input"
          type="text"
          placeholder="Enter a bitmask in decimal"
          value={input}
          onChange={event => setInput(event.target.value)}
        />
        <table>
          <tbody>
          {
            Object.keys(flags).map(value => (
              <tr key={value} style={getHighlightStyle(value)}>
                <td>{value}</td>
                <td>{flags[value]}</td>
              </tr>))
          }
          </tbody>
        </table>
      </header>
    </div>
  );
}

export default App;

We’re using the bitwise AND operator (&) to do a binary AND between the input and each flag. Let’s say the user enters 3 as the input. That’s 000011 in binary; so:

  • 000011 AND 000001 (Paralysed) results in 000001 (greater than zero);
  • similarly, 000011 AND 000010 (Poisoned) results in 000010 (also greater than zero);
  • however, 000011 AND 000100 (Diseased) results in 000000 (not greater than zero);
  • and so on.

This is a common way of determining whether individual bits are set, and it works quite nicely:

Flags are highlighted based on the bitmask in the text field

So that’s it: we’ve made a simple tool with React to help make sense of bitmasks, and hopefully learned a bit about bitmasks and bitwise operators along the way.