bitwise operators - php

I would like to understand the following code from Zenphoto’s plugin:
$plugin_is_filter = 5|ADMIN_PLUGIN|THEME_PLUGIN;
The snippet was disjointed from context. It is just about the Idea behind it.
Are 5|ADMIN_PLUGIN|THEME_PLUGIN Permissions using bitwise?
When it is useful to use?
Thanks for any hint, links.

Bitfields are useful when you need to provide a set of boolean options in one variable. For example, PHP lets you set your error reporting like this:
error_reporting(E_ERROR | E_WARNING | E_PARSE);
In binary, those constants have these values:
E_ERROR 0001
E_WARNING 0010
E_PARSE 0100
If you OR a set of options like that together, you'll be able to express the settings in one field:
E_ERROR | E_WARNING | E_PARSE 0111
Then, you can check for an option being set using AND:
if ($option & E_ERROR === E_ERROR) {
// E_ERROR is set, do something
}

Yes, that is an example of bitwise OR.
You typically use bitwise operations when you're interested in packing multiple boolean flags into a single integer. Bitwise operators allow you to manipulate the individual bits of a byte, meaning an 8 bit byte can be used to store 8 distinct boolean values. It's a technique which was useful when using a whole 8 bit byte to store a single binary "yes" or "no" was considered wasteful.
Today, there is virtually no reason to ever prefer using this kind of bitpacking in PHP (especially with a magic number like that 5) over a simple configuration array. It is a technique which adds virtually nothing of value to PHP code, increasing complexity and decreasing maintainability for no real gain. I would be very skeptical of any new PHP code produced which makes use of bitwise flags in this way.

The variable $plugin_is_filter is being used to flag which plugins to load. Essentially, it is being treated like an array bits that correspond to an enumerated set plugins. For more information, see the links below.
This explains what ADMIN_PLUGIN and THEME_PLUGIN are.
Search the page for '$plugin_is_filter' to get a brief explanation of how to use this variable.
http://www.zenphoto.org/news/zenphoto-plugin-architecture
I hope this helps.

Related

Function parameters of the form foo(A | B | C)

This is a language-independent question, though I've tagged with languages just to give some tags relevant to the code samples I'm posting below. I'm somewhat new to programming. In various languages I've seen functions that have parameters separated by what I think is the bitwise OR operator. I've used these functions without understanding exactly how the parameters work.
I'll give some examples in case you're not sure what I'm talking about.
From http://www.php.net/manual/en/function.error-reporting.php:
<?php
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>
From http://www.cplusplus.com/doc/tutorial/files/:
ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);
What exactly is the deal with functions that take parameters like that? Can someone explain?
If you lookup what those constants are, you'll see they'll be like this: 1, 2, 4, 8, 16, etc.
So by adding them all together basically, (what the bitwise does AFAIK from this: "Bit shifting in PHP is arithmetic.") you get a new "number".
http://us2.php.net/manual/en/language.operators.bitwise.php
The manual page has a lot of good info on how it works.
So basically to answer the question of how that function works, it is accepting one integer, and the bitwise operator is doing the "math" and turning those three constants into one new number.
var_dump(E_ERROR);
var_dump(E_WARNING);
var_dump(E_PARSE);
var_dump(E_ERROR | E_WARNING | E_PARSE);
int(1)
int(2)
int(4)
int(7)
So it's the same as:
error_reporting(7);
The same thing as a + b + c. It's just an expression, with
the | (bitwise or) operator.
These are predefined constants, whose values are combined to produce a bit field.
You can use decbin() in PHP to give an insight into how these constants work. decbin produces a string which shows the binary representation of the number.
printf("%02s", decbin(E_ERROR)); // output 01
printf("%02s", decbin(E_WARNING)); // output 10
printf("%02s", decbin(E_ERROR | E_WARNING)); // output 11
(I padded all the values so that the OR operation is clear)
You're passing a single number to the function, whose value represents the options you want to enable. In the function, the options could be extracted using bitwise &:
function func($flag) {
if ($flag & E_ERROR) echo "E_ERROR enabled";
// etc.
}
These are flags. Sometimes a function receives multiple indications on how to operate, such as whether to open the file in binary mode, or in read-only mode, etc... This modes are not mutually exclusive - file can be opened for reading in both text and binary mode, or for writing in both text and binary mode. So you need to be able to specify both options together if you want.
One simple way to achieve this is with bit flags. You have one integer number that holds all the flags. The least significant bit says, for example, if the file is to be opened in text mode (0 - text, 1 - binary), the second bit from the right says whether to open for read or write, etc...
To implement this you use constants:
BINARY = 1
WRITE = 2
Now, if you want to open in both binary and write mode, you use BINARY | WRITE - which results in 3.
The called function then breaks the number back into bits:
isBinary = (flags & BINARY) != 0;
isWriteMode = (flags % WRITE) != 0;
I think
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
is equivalent to the following in C or C++
// Report simple running errors
int const error_filter = E_ERROR | E_WARNING | E_PARSE;
error_reporting( error_filter );
Most probably, the symbols E_ERROR, E_WARNING are numbers with a single bit set, such as for example
E_ERROR = 00000001
E_WARNING = 00000010
E_PARSE = 00000100
So, a bitwise-OR of them returns a number with the bit set in all of those positions
error_filter = E_ERROR | E_WARNING | E_PARSE = 00000111
One tricky thing is the type of error_filter, I wrote int but that may not be pedantically correct. One can say uint32_t. Another alternative is to leave the type altogether as in the original code.

Binary operation to get / set property

I would like to store user rights as integer in database, but not sure how... How does it work on PHP with for example error_reporting() ?
You got different constants, like... E_ERROR = 1, E_WARNING = 2, E_PARSE = 4, E_NOTICE = 8 etc... and you can set it like error_reporting(E_ERROR | E_NOTICE) ...
In this case E_WARNING | E_NOTICE == 10.
Ok, so I do understand that this is binary operation "OR" and as far as consecutive constants are multiplied by 2, everything should be reversable... but how?
So I got this (int)10. And how do I check that it is E_WARNING and E_NOTICE?
PS. I do understand that it is 1010 on binary notation.
If you want to check if values are set, you can use the bitwise AND & operator.
$warningEnabled = $val & E_WARNING;
This works because (assume $val is 128)...
1000 0000 & # $value
0000 0010 # E_WARNING
Since the same bit isn't set in both, you can tell that $val doesn't have warnings set.
You can execute this in PHP if you like with bindec() function (wrap the above values as strings), it may help you understand better.
If you want to know if the value contains E_WARNING, do:
if ($value & E_WARNING)

Bitwise comparison in PHP

I confess I don't really know what I'm doing! I'm pulling some data from SecondLife and parsing it in PHP. The data is an integer from llGetRegionFlags which, in my case, returns 1048592
Now I need to do a bitwise comparison in PHP to figure out which flags are true/false. For example 0x00000040 is used for the "block terraform" flag.
The notations are in hex for each flag, and I have an integer to test against, and the PHP manual suggests integers and shows examples in binary.
So my question really is, given an integer and some hex flags, how do I go about doing the bitwise comparison in PHP? Brainfried! Thanks in advance
To determine if a particular bit is turned on, use the & (AND) operator:
if ($data & 0x00000040) {
// block terraform flag is true
}
If the bit is turned on, the AND operator will return a positive number. If it is turned off, then the AND operator will result in a zero.
Use a single AND & / OR |
if ($value1 & $value2) { }
The PHP Manual explains more: http://php.net/manual/en/language.operators.bitwise.php
You could define the bits required, and check against them to make it look clean. ie
define('BLOCK_TERAFORM', 0x00000040);
....
if($data & BLOCK_TERAFORM) {
... do something ...
}
Usually the bitflags are checked with a piece of code like this:
$blockTerraformFlag = 0x00000040;
$isBlockTerraform = (($RegionFlags & $blockTerraformFlag) == $blockTerraformFlag);

PHP debug_backtrace bitmask usage

Trying to understand this entry in the php manual on debug_backtrace.
I don't understand what they mean by "this parameter is a bitmask for ...."
I have done web searches on bitmasks and my head is spinning round so I have decided I don't really want to learn the detail about it but just to know how I can supposed to add the options to that function.
Do I put in both options as in
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS)
if I want both and one of them if I only want that one?
Be aware that those 2 constants (DEBUG_BACKTRACE_PROVIDE_OBJECT, DEBUG_BACKTRACE_IGNORE_ARGS) are different in meaning. While DEBUG_BACKTRACE_PROVIDE_OBJECT provides an additional object when present, DEBUG_BACKTRACE_IGNORE_ARGS strips the args when present.
Since the most common use-case for these constants is to reduce memory usage, the way with least memory-consumption is:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
NOT
// false friend!
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It overrides the default of DEBUG_BACKTRACE_PROVIDE_OBJECT and additionally ignores DEBUG_BACKTRACE_IGNORE_ARGS.
The constants will have values of 2^n in decimal, or (10)^n in binary. For example - 1, 10, 100, 1000, etc (in binary).
Say a=001, b=010, c=100:
You can do bitwise or on, for example, a and b. This will mean each bit will be 'turned on' if the same bit in either a or b is 'on'.
a | b == 011
This is a bitmask. The bitmask is checked for the inclusion of a by
bitmask & a != 0
Which is
011 & 001 == 001 != 0
However, because c is not in the bitmask:
bitmask & c == 011 & 100 == 0
So, to include both a and b in the bitmask, you use the binary or operator.
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
It means you combine options with the bitwise OR operator: |.
For example:
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
For more details about bitmasks: http://en.wikipedia.org/wiki/Mask_(computing)

bitmask type of argument in javascript

I see that in PHP there are functions that can accept multiple options into a single argument, for example:
error_reporting(E_ERROR & E_WARNING);
I want to implement this kind of functionality into my javascript function. Do you know examples of functions that take this kind of arguments?
I'm totally confused about how does the function know what are the options that are passed...
(Assume it is instead: error_reporting(E_ERROR | E_WARNING); )
Well, it is a bitmask. So E_ERROR might be a number like this (in binary):
0010000
and E_WARNING might be:
0000010
and when they are combined with |, you get
0010010
(a single integer, with multiple bits set)
The function can then check which bits are set using the & bitwise operator. You can certainly do it in javascript, although it might be less common, and possibly less efficient and reliable as the numbers get bigger since javascript doesn't really have integers, they are really floating point numbers.
In javascript, you might prefer to use something like this:
error_reporting({warning: true, error: true});
(edited to show it in the more sensible way, with | not & to combine them)
Yes, it's possible, but it works with |.
var flag1 = 1,
flag2 = 2; // powers of 2
function get(flags) {
if((flags & flag1) === flag1) { // remove all other bits and check
alert('flag1'); // whether you get the flag itself
}
if((flags & flag2) === flag2) {
alert('flag2');
}
}
get(flag1 | flag2); // alerts both
You could of course create a helper function which does the chekcing so that you don't need those parentheses:
function contains(flags, flag) {
return (flags & flag) === flag;
}
http://jsfiddle.net/pimvdb/NpFYj/1/

Categories