"Sputnik" help  
Sputnik Help
Language Reference - Datatypes - Enums (Bit Flags)

Enums (Bit Flags)

Before we begin make sure you have read everything in Enums and understand it well.

One of the most important features of Enums is being able to set and check for bit flags this will explained below.

Bit flags , or bit fields are a great way of storing several boolean values in a single byte (or set of bytes), and are internally represented as binary. In this tutorial we will work with bitwise operators, so if you need to brush up this is what we're using; the following key binary operators.

Bitflags are a powerful technique used to represent multiple boolean values compactly within an integer. Each bit within the integer represents a specific flag or option, allowing for efficient storage and manipulation of multiple boolean states.

Sputnik has dedicated functions to handle setting and testing for flags you can find them here:
HasFlag
SetFlag

These examples should be self-explanatory.

They show you how to do flags using the core language instead of using HasFlag and SetFlag.

In Sputnik, bitflags can be implemented using enums and bitwise operations. Here's an example that demonstrates the usage of bitflags:

enum Options 
{
  $Flag1 = 0x01,
  $Flag2 = 0x02,
  $Flag3 = 0x04,
  $Flag4 = 0x08,
  $Flag5 = 0x10,
  $Flag6 = 0x20
}

// Make a variable to store the flags
Global $Opt = 0; // No flags are set
$Opt |= Options->$Flag2; // Set Flag2 to TRUE
$Opt |= Options->$Flag3; // Set Flag3 to TRUE
$Opt |= Options->$Flag5; // Set Flag5 to TRUE
TestFlags("Test1");
 
$Opt &= ~Options->$Flag5; // Set Flag5 to FALSE
TestFlags("Test2");
 
$Opt &= ~Options->$Flag3; // Set Flag3 to FALSE
TestFlags("Test3");
 
$Opt |= Options->$Flag5; // Set Flag5 to TRUE
$Opt |= Options->$Flag3; // Set Flag3 to TRUE
TestFlags("Test4");
 
$Opt &= ~(Options->$Flag3 | Options->$Flag5); // Set Flag3 and Flag5 to FALSE
TestFlags("Test4");
 
$Opt |= (Options->$Flag1 | Options->$Flag6); // Set Flag1 and Flag6 to TRUE
TestFlags("Test5");
 
Function TestFlags($str)
{
    say ("### $str BELOW";
    say "\$Opt = {Hex('$Opt', 2)}";
    foreach( my $Flag => my $ID in Enumerate("Options") )
    {
        if($Opt & $ID)
            say "$Flag is TRUE";
        else
            say "$Flag is FALSE";
    }
    say "### $str ABOVE";
}
// PRINTS
// ### Test1 BELOW
// $Opt = 16
// flag1 is FALSE
// flag2 is TRUE
// flag3 is TRUE
// flag4 is FALSE
// flag5 is TRUE
// flag6 is FALSE
// ### Test1 ABOVE
// 
// ### Test2 BELOW
// $Opt = 06
// flag1 is FALSE
// flag2 is TRUE
// flag3 is TRUE
// flag4 is FALSE
// flag5 is FALSE
// flag6 is FALSE
// ### Test2 ABOVE
// 
// ### Test3 BELOW
// $Opt = 02
// flag1 is FALSE
// flag2 is TRUE
// flag3 is FALSE
// flag4 is FALSE
// flag5 is FALSE
// flag6 is FALSE
// ### Test3 ABOVE
// 
// ### Test4 BELOW
// $Opt = 16
// flag1 is FALSE
// flag2 is TRUE
// flag3 is TRUE
// flag4 is FALSE
// flag5 is TRUE
// flag6 is FALSE
// ### Test4 ABOVE
// 
// ### Test4 BELOW
// $Opt = 02
// flag1 is FALSE
// flag2 is TRUE
// flag3 is FALSE
// flag4 is FALSE
// flag5 is FALSE
// flag6 is FALSE
// ### Test4 ABOVE
// 
// ### Test5 BELOW
// $Opt = 23
// flag1 is TRUE
// flag2 is TRUE
// flag3 is FALSE
// flag4 is FALSE
// flag5 is FALSE
// flag6 is TRUE
// ### Test5 ABOVE

In this example, we define four options using enums: $OPT_A, $OPT_B, $OPT_C, and $OPT_H. Each option is assigned a unique bit value using hexadecimal notation.

We iterate over an argument array and use the switch statement to check each option provided. By performing bitwise OR operations |, we set the corresponding bits in the $opt variable to indicate the selected options.

We then use bitwise AND operations & to check if specific options are set. If a flag is set, we execute the corresponding code. We can also compare multiple flags using bitwise OR | and compare the result using bitwise AND &.

Additionally, the example demonstrates resetting the bitflag, appending multiple flags, adding or removing flags to an existing option field using bitwise AND-EQUALS &= and bitwise NOT ~, and checking the status of multiple flags using bitwise AND & and comparison operators ==, !=, <, >, <=, >=. Finally, the example shows how to check if specific flags are not set using bitwise AND & and comparing the result to zero.

Using bitflags can be beneficial when working with multiple boolean options or flags in a compact and efficient manner. It allows for easy combination, manipulation, and checking of various states within a single integer.

Please note that when working with bitflags, it's important to define unique and non-overlapping bit values for each option to ensure correct behavior. Additionally, bitwise operations can be powerful but require a good understanding of binary representation and bitwise logic.

Feel free to experiment with bitflags in Sputnik and explore the possibilities they offer for managing multiple boolean states efficiently.

You can also use the Vec operator to use bit flags since in Sputnik using the Vec operator with a bitsize of 2 can be an efficient way to handle bitflags. This approach allows you to represent multiple boolean states using individual bits within an integer.

Here's an example of how you can use Vec to handle bitflags efficiently:

// Define the bit positions for the flags
enum
{
    $FLAG_A,
    $FLAG_B,
    $FLAG_C,
    $FLAG_D
    // Add more flags as needed
}

// Initialize the bitflags variable
my $bitflags = 0;

// Set the flags
vec($bitflags, $FLAG_A, 2) = 1;
vec($bitflags, $FLAG_C, 2) = 1;

// Check if a flag is set
if (vec($bitflags, $FLAG_B, 2))
    say "Flag B is set";

// Toggle a flag
vec($bitflags, $FLAG_D, 2) ^= 1;

// Clear a flag
vec($bitflags, $FLAG_A, 2) = 0;

// Check if multiple flags are set
if (!vec($bitflags, $FLAG_A, 2) && vec($bitflags, $FLAG_C, 2))
    say "Flags A is not set, Flag C is set";
    
// PRINTS
// Flags A is not set, Flag C is set

Using Vec with a bitsize of 2 allows you to directly manipulate individual bits within the bitflags variable. The enum block defines the positions of each flag, starting from 0. You can set a flag by assigning a value of 1 to the corresponding bit position using vec(). To check if a flag is set, you can compare the value at the bit position to 1 using Vec. Toggling a flag is done by XOR-ing the bit position with 1 using Vec, and clearing a flag is achieved by assigning a value of 0 to the bit position using Vec.

By using Vec with a bitsize of 2, you can efficiently handle multiple boolean states within a single integer variable. This approach can save memory and provide faster bitwise operations compared to other data structures or approaches.

The Vec function allows you to store multiple boolean states efficiently by utilizing a bit-level representation within a 64-bit integer. Each bit within the integer can be considered as a separate boolean flag.

By using Vec with a bit size of 1, you can store up to 64 boolean states per 64-bit integer. The value of each bit can be either 0 (false) or 1 (true), representing the state of the corresponding flag.

For example, if you have a 64-bit integer variable called $bitflags, you can set and retrieve individual boolean states using Vec like this:

// Set the flag at position 3 to true
vec($bitflags, 3, 1) = 1;

// Set the flag at position 5 to true
vec($bitflags, 5, 1) = 1;

// Set the flag at position 7 to false
vec($bitflags, 7, 1) = 0;

// Retrieve the value of the flag at position 5
my $flagValue = vec($bitflags, 5, 1);

// Print results
say "Flag 3 " . (Bool)vec($bitflags, 3, 1);
say "Flag 5 " . (Bool)vec($bitflags, 5, 1);
say "Flag 7 " . (Bool)vec($bitflags, 7, 1);

// PRINTS
// Flag 3 true
// Flag 5 true
// Flag 7 false

Using this approach, you can efficiently manage multiple boolean states within a compact representation, optimizing memory usage and bitwise operations.

When using Vec to set boolean flags, you can conveniently use the literal values true and false to represent 1 and 0, respectively. This allows for a more intuitive and readable code. Here's an example:

// Set the flag at position 3 to true
vec($bitflags, 3, 1) = true;

// Set the flag at position 5 to true
vec($bitflags, 5, 1) = true;

// Set the flag at position 7 to false
vec($bitflags, 7, 1) = false;

// Retrieve the value of the flag at position 5
my $flagValue = vec($bitflags, 5, 1);

// Print results
say "Flag 3 " . (Bool)vec($bitflags, 3, 1);
say "Flag 5 " . (Bool)vec($bitflags, 5, 1);
say "Flag 7 " . (Bool)vec($bitflags, 7, 1);

// PRINTS
// Flag 3 true
// Flag 5 true
// Flag 7 false
Using true and false as the values to set the flags improves the clarity and expressiveness of the code, making it easier to understand the intention behind each operation.

Another example of enums:

enum 
{
    $OPT_A = 0x01,
    $OPT_B = 0x02,
    $OPT_C = 0x04,
    $OPT_H = 0x08
}

//to store the option flags
my $opt = 0x0;
 
//argument array.
my $argv = qw(a b);
foreach(my $c in $argv)
{
    switch($c)
    { 
        case "a":
        //assign option bits to "opt" bit array
            $opt |= $OPT_A;
            break;
        case "b":
            $opt |= $OPT_B;
            break;
        case "c":
            $opt |= $OPT_C;
            break;
        case "h":
            $opt |= $OPT_H;
            break;
        //this will happen if they enter an invalid option:
        default: 
            say "Unknown option $c";
            return 1; //break out of application
    }
}
 
//apply bitwise AND to check for assignedness a few times
if($opt & $OPT_A)
    say "Hello World!";
 
if($opt & $OPT_B) 
{
    my $foo = 2000;
    say "Foo has been initialized.";
}
 
//compare if two flags were specifically set
if (($opt & ($OPT_B | $OPT_C)) == ($OPT_B | $OPT_C)) 
    say "Flags B and C were set.";
 
if($opt & $OPT_H) 
{
    //print help, may wish to create exit point to stop program from executing
    say "\tHelp is not implemented yet\n\tAllowable options: [abch]";
    return 0;
}
 
//----------------- Some fun extras: ---------------------//
 
//Reset bitflag completely
$opt = 0;
 
//Apply bitwise OR to append multiple flags
$opt = ($OPT_A | $OPT_B | $OPT_C);
 
//Apply bitwise AND+EQUALS to add or remove flags to existing option field
//Then we apply bitwise NOT (a complement) to remove both flags
$opt &= ~($OPT_A | $OPT_B);
 
//Options A and B are now removed
 
//Check if BOTH flags are not set
if (($opt & ($OPT_A | $OPT_B)) == 0)
    say "Flags A and B are not set";
 
//check if only one is not set
if (($opt & $OPT_A) == 0)
    printf("Flag A is not set\n");

// PRINTS
// Hello World!
// Foo has been initialized.
// Flags A and B are not set
// Flag A is not set

You can ask Sputnik to automatically assign values to enums such as 0x02, 0x04, 0x08, 0x10 and so on using the flags rule example:

"f" enum Countries
{
    $None,
    $England,
    $France,
    $Germany,
    $Netherlands,
    $Portugal = 300,
    $Italy,
    $Russia
}
say "NONE: " . Countries->$None; // Prints 0
say "England: " . Countries->$England; // Prints 1
say "France: " . Countries->$France; // Prints 2
say "Germany: " . Countries->$Germany; // Prints 4
say "Netherlands: " . Countries->$Netherlands; // Prints 8
say "Portugal: " . Countries->$Portugal; // Prints 300
say "Italy: " . Countries->$Italy; // Prints 600
say "Russia: " . Countries->$Russia; // Prints 1200
Learn more about the flags rule here.

Contact
Cheryl (uberfox@hotmail.com)
Homepage
http://ubersoft.org