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/
Related
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.
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);
In some PHP I need to compare two strings, but only on the bits that are set as one in the bitmask. How would I implement such a behavior?
I've tried:
$string1='aaabbb';
$string2='ababbb';
$bitmask='101101';
function compare($string1, $string2, $bitmask){
$resultBitmask=(~($string1 ^ $string2)|~$bitmask);
}
For clarity's sake, I've written ff bytes as 1 in the bitmask for illustrative purposes. They would actually be ff in hex when a bitmask is generated. Same goes for 0 being null bytes.
The string and the bitmask are always different lengths each time the function is called. I've managed to get a set of bits for comparison, but am unable to check whether they are all set since the lenths differ. At this time, I've been using preg_match with a regex that matches any number of ff bytes, but is there a more elegant solution?
Edit: Since the strings are any length up to 4096 bits long, they cannot be converted to numbers.
It's not the flashest way of doing it but:
$stillTheSame = true;
for($i=0;$i<=strlen($bitmask); $i++)
{
if($bitmask[$i] == 1)
{
if($string1[$i] != $string2[$i])
{
$stillTheSame = false;
break;
}
}
}
Not sure fof your actual checking logic, but this should help hopefully.
Self-solved:
Since this will repeat with many strings of the same length during a run, but have different lengths between runs, I need to check that the resulting string after the bitwise operations is all ones and the correct length. I realized that this string full of ones can be generated when needed, which is quite rarely, once every 1000 or so string comparisons. I can generate the string before runs as follows:
$ones=str_repeat(chr(255), $byte_length);
and then defining the compare( function a bit differently:
function compare($string1, $string2, $bitmask){
global $ones;
$resultBitmask=(~($string1 ^ $string2)|~$bitmask);
if ($resultBitmask=$ones){
return 1;
} else {return 0};
}
The trick was the str_repeat which I was not aware of before.
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.
I read the following Stack Overflow questions, and I understand the differences between bitwise and logical.
Difference between & and && in PHP
Reference - What does this symbol mean in PHP?
However, none of them explains when I should use bitwise or logical.
When should I use bitwise operators rather than logical ones and vice versa?
In which situation do I need to compare bit by bit?
I am not asking about the differences, but I am asking the situation when you need to use bitwise operators.
Bitwise is useful for things in PHP just like anything else.
How about a value that can have multiple states turned on at the same time?
<?php
// since we're setting constant values in base10 we must progressively double
// them since bitwise operations work in base2. you'll see why when we output
// these as binary values below.
const STATE_FOO = 1;
const STATE_BAR = 2;
const STATE_FEZ = 4;
const STATE_BAZ = 8;
// show base2 values of the above constants
echo sprintf("STATE_FOO's base2 value is %08d\n", decbin(STATE_FOO));
echo sprintf("STATE_BAR's base2 value is %08d\n", decbin(STATE_BAR));
echo sprintf("STATE_FEZ's base2 value is %08d\n", decbin(STATE_FEZ));
echo sprintf("STATE_BAZ's base2 value is %08d\n\n", decbin(STATE_BAZ));
// set state to FOO and FEZ
$state = STATE_FOO | STATE_FEZ;
echo sprintf("base10 value of \$state is %s\n", $state);
echo sprintf("base2 value of \$state is %08d\n", decbin($state));
echo sprintf("Does \$state include FOO state? %s\n", (bool)($state & STATE_FOO));
echo sprintf("Does \$state include BAR state? %s\n", (bool)($state & STATE_BAR));
echo sprintf("Does \$state include FEZ state? %s\n", (bool)($state & STATE_FEZ));
echo sprintf("Does \$state include BAZ state? %s\n", (bool)($state & STATE_BAZ));
echo sprintf("Is state equivalent to FOO and FEZ states? %s\n", ($state == (STATE_FOO | STATE_FEZ)));
Output:
STATE_FOO's base2 value is 00000001
STATE_BAR's base2 value is 00000010
STATE_FEZ's base2 value is 00000100
STATE_BAZ's base2 value is 00001000
base10 value of $state is 5
base2 value of $state is 00000101
Does $state include FOO state? 1
Does $state include BAR state?
Does $state include FEZ state? 1
Does $state include BAZ state?
Is state equivalent to FOO and FEZ states? 1
Forget what is already in your head.
OK, now say you have some different roles: admin, user, and guest.
and some different permissions: read, write and delete
Let's create some bitmasks for permissions and roles. A bitmask is a sequence of bits that can be used to manipulate or read some kind of flags. As shown below:
// flags bitmasks
$read = 1; // 0001
$write = 2; // 0010
$delete = 4; // 0100
$admin = $read | $write | $delete; // 0001 | 0010 | 0100 => 0111
$user = $read | $write; // 0001 | 0010 => 0011
$guest = $read; // 0001 => 0001
Notice 1, 2, 4. This must be raised as double. Otherwise, it might give you some awkward results.
Forget about the things commented. Those are just sequence of bits (or bitmasks) for individual permissions and roles.
Now let's create a handy function which may be used to check a specific permission for a specific role.
function isAllowed($role, $permissison) {
return $role & $permissison ? true : false;
}
We are done. Let's check the $delete permission for all 3 roles:
var_dump(isAllowed($admin, $delete)); // bool(true)
var_dump(isAllowed($user, $delete)); // bool(false)
var_dump(isAllowed($guest, $delete)); // bool(false)
So why is bitwise operation? In a word, bitwise operation is more faster, concise and maintainable. Otherwise, using bitwise operation is always efficient for complex applications.
Bitwise | and & and logical || and && are totally different.
Bitwise operators perform operations on the bits of two numbers and return the result. That means it's not a yes or no thing. If they're being used in conditional statements, they're often used as part of logical comparisons. For example:
if ($x & 2 == 2) {
// The 2^1 bit is set in the number $x
}
Logical operators compare two (or more) conditions/expressions and return true or false. You use them most commonly in conditional statements, like if and while. For example:
if ($either_this || $or_this) {
// Either expression was true
}
Bitwise operators are specifically used in case of binary value representation.
echo '0110011010' & '0101001001';
//0100001000
Logical operators are most preferred for comparison and are a bit faster than bitwise operator in case of AND and XOR operations.
if(func1() && func2())
if func1() returns false it won't bother calling func2()
if(func1() & func2())
Will call both functions regardless of their returned values.
In most cases, you'll probably want to use logical operators. They're used for combining logical conditions, generally to control program flow, e.g. ($isAlive && $wantsToEat).
Bitwise operators are used when you want to perform operations on a bit-by-bit basis on the underlying binary representations of integers. e.g. (5 & 3) == 7. As others have suggested, there's usually not a lot of call for this in the sort of application that tends to get written in PHP (although there is in lower-level languages, like C).
Bitwise operators are useful when manipulating the bits of a number. Look here. Otherwise you should use the logical operators. Also the logical operators are short-circuited. For example, if you have a && b and a is false, b is not evaluated.
Disclaimer: I am coming from a Java background, but I guess in PHP it is the same.
They are two very different operators.
When you want two conditions to simultaneously be true, you use the logical &&. For example, I want to print out "happy birthday" only if the person's birthday is today && they have money in the account. This is used whenever we want to perform composition of two or more conditions, mostly in if statements and loop conditions (although not exclusively).
When you want to perform bitwise operations (which in day-to-day PHP programming is much more rare), you use the bitwise &. This is far more rare, and you might be performing bitwise masking (I doubt it though), so you might only want a result that both integers represent, in which case you can say newAttribute = attribute1 & attribute2;.
Well, asuming there is $x = (false && some_function());, here the value of $x will be set without calling the some_function() because the first value was FALSE.
But what if you needed to call that function anyway? Use $x = (false & some_function());.
In other words, the & uses MORE processing than the &&, just because && does not run through all the values to check them. If it found one value as false, it would return it, not looking at other values.
And in logical operations, use the && operator as it's used to return the logical operation value, where & is used to set a value and in an if statement it will always return true.