-1

How would you test if ANY integer value posted is part of the flags you have defined? (A valid combination of those.)

Example:

define('IS_NEW', 0);
define('IS_PAID', 2);
define('IS_EXTEND', 4);
define('IS_TRACK', 8);
define('IS_VIP', 16);
define('IS_HOT', 32);
define('IS_BLOCKED', 64);

Now the integer posted could be 48, 50, 75, ...

How to verify that the integer consists of our bitwise flag system - in their various combinations - and NOT other values.

48 is valid, because flags 16 + 32 = 48.

50 is valid, because flags 2 + 16 + 32 = 48.

75 is NOT valid, because flags 64 + 8 + 4 = 76.

We want to make sure that no other flag value is included.

Avatar
  • 14,622
  • 9
  • 119
  • 198
  • The question is tagged with "bitwise operators", are you having problems using them? F.ex `if ($myInt & IS_NEW) {` means bit 0 was set, `if ($myInt & IS_HOT) {` bit 5, etc. Note the single `&` which is bitwise AND, as opposed to `&&` for boolean AND. If you want to test for combinations that would be up to your "if() tree", and perhaps what combos you epxect. – Torbjörn Stabo Feb 21 '23 at 16:52
  • This is absolutely clear. But how can I identify that the integer given (the sum of potential flags) consists of the predefined flags. – Avatar Feb 21 '23 at 16:54
  • So you want to check if the integer consists of *nothing but* - combos of - flag values? If you define your "flag series" like that, in an ordered way, you could perhaps check if myInt is outside the range of the sum of all your flags? Or some kind of fallback else clause in your "if lines checking for flags" tree? – Torbjörn Stabo Feb 21 '23 at 16:55
  • Yes, exactly. Not any other integer that is not part of the defined flags. – Avatar Feb 21 '23 at 16:58
  • You could also OR your flags together to create a bitmask, and then something like `if ($myInt & BITMASK !== $myInt) {`. – Torbjörn Stabo Feb 21 '23 at 17:01
  • Does it make sense? – Torbjörn Stabo Feb 21 '23 at 17:11
  • If you want to handle it strictly programmatically I guess you could use [get_defined_constants()](https://www.php.net/manual/en/function.get-defined-constants.php) provided you can name your defines in some logical easy to access way. – Torbjörn Stabo Feb 21 '23 at 17:14
  • Any integer < 128 is a valid combination. FYI, `IS_NEW` must be 1 (2**0) – fusion3k Feb 21 '23 at 18:28
  • Exactly. (Provided that is the actual use case) If all bits from 0 up to some limit are used then it's trivial to construct the largest int possible with those bits and check whether the integer is within that interval. (0 - MAX_POSSIBLE) – Torbjörn Stabo Feb 21 '23 at 18:55
  • "Any integer < 128 is a valid combination" ... I doubt that you can create `3` out of the defined integers above. – Avatar Feb 21 '23 at 20:02
  • This is because `IS_NEW` is set to 0: how can you combine it with other flags? BTW, with the above constants: `if ($num < 0 || $num > 127 || $num&1) { *NOT VALID* } else { *VALID* }` – fusion3k Feb 22 '23 at 08:18
  • ⚠️ Which "smart user" closed the question as duplicate? ... The linked question is NOT a duplicate. @whoever: READ the question! – Avatar Feb 22 '23 at 12:26

1 Answers1

1

How can you identify that the integer given (the sum of potential flags) consists of the predefined flags...? Maybe that way:

<?php
define('IS_NEW', 0);
define('IS_PAID', 2);
define('IS_EXTEND', 4);
define('IS_TRACK', 8);
define('IS_VIP', 16);
define('IS_HOT', 32);
define('IS_BLOCKED', 64);

class myConsts {
    public $constants = ['IS_NEW','IS_PAID', 'IS_EXTEND', 'IS_TRACK', 'IS_VIP', 'IS_HOT', 'IS_BLOCKED'];

    function __construct() {
        foreach ($this->constants as &$cons) {
            $cons = -constant($cons) -1;  // negation, f.e. 0b...00000001 ==> 0b...11111110 (32 or 64 bits depends of platform)
            //printf("0b%08b.\n", $cons); // (test)
        }
    }
  
    function checkInt($myInt = 0) {   
        foreach ($this->constants as $cons) {
            $myInt = $myInt & $cons;
        }       
        return $myInt;
    }
}

$checkInts = new myConsts();

foreach ([48, 50, 75, 256*200+156] as $getInt) {
    $result = $checkInts->checkInt($getInt);
    if ($result) {
        echo "Int ".sprintf("%u (0b%1$08b)", $getInt)." constains more flags: ", sprintf("0b%08b.", $result), PHP_EOL;
    } else {
        echo "Int ".sprintf("%u (0b%1$08b)", $getInt)." consists only of predefined flags!", PHP_EOL;
    }
}
?>

Result:

Int 48 (0b00110000) consists only of predefined flags!
Int 50 (0b00110010) consists only of predefined flags!
Int 75 (0b01001011) constains more flags: 0b00000001.
Int 51356 (0b1100100010011100) constains more flags: 0b1100100010000000.

Is this what you need?

msegit
  • 110
  • 8