Help With Bitwise Operations
Help With Bitwise Operations
am 02.12.2007 03:30:36 von Rob Wilkerson
I'm attempting to do some work around existing code that uses bitwise
operations to manage flags passed into a function and I'm quite
frankly unequipped to do so. I've never done much with bitwise
operations and all the reading I've done today doesn't appear to be
helping me much. I'm hoping someone here can provide a remedial
lesson. Given the following constants:
define('FLAG_1, 1);
define('FLAG_2', 2);
define('FLAG_3', 4);
define('FLAG_4', 8);
define('FLAG_5', 16);
define('FLAG_6', 32);
define('FLAG_7', 64);
define('FLAG_8', 128);
define('FLAG_9', 256);
define('FLAG_10', 512);
define('FLAG_11', 1024);
define('FLAG_12', 2048);
I'm making this call:
$foo = my_function ( 'arg1', 'arg2', FLAG_1|FLAG_6|FLAG_4 );
To this function signature:
function my_function ( $arg1, $arg2='blah', $flags=NULL )
Inside the function, if I just echo the value of $args I get "41".
Is that correct? From my reading, it doesn't seem correct, but it may
just be my ignorance in this area. Any assistance reading and
understanding this stuff would be much appreciated.
Thanks.
Rob
Re: Help With Bitwise Operations
am 02.12.2007 03:54:51 von zeldorblat
On Dec 1, 9:30 pm, Rob Wilkerson wrote:
> I'm attempting to do some work around existing code that uses bitwise
> operations to manage flags passed into a function and I'm quite
> frankly unequipped to do so. I've never done much with bitwise
> operations and all the reading I've done today doesn't appear to be
> helping me much. I'm hoping someone here can provide a remedial
> lesson. Given the following constants:
>
> define('FLAG_1, 1);
> define('FLAG_2', 2);
> define('FLAG_3', 4);
> define('FLAG_4', 8);
> define('FLAG_5', 16);
> define('FLAG_6', 32);
> define('FLAG_7', 64);
> define('FLAG_8', 128);
> define('FLAG_9', 256);
> define('FLAG_10', 512);
> define('FLAG_11', 1024);
> define('FLAG_12', 2048);
>
> I'm making this call:
>
> $foo = my_function ( 'arg1', 'arg2', FLAG_1|FLAG_6|FLAG_4 );
>
> To this function signature:
>
> function my_function ( $arg1, $arg2='blah', $flags=NULL )
>
> Inside the function, if I just echo the value of $args I get "41".
>
> Is that correct? From my reading, it doesn't seem correct, but it may
> just be my ignorance in this area. Any assistance reading and
> understanding this stuff would be much appreciated.
>
> Thanks.
>
> Rob
FLAG_1 = 1 = 000001
FLAG_6 = 32 = 100000
FLAG_4 = 8 = 001000
If we OR them all together we get 101001 = 41. So that's correct.
Inside your function if you want to check if any particular flag was
set you would do it like this:
if($flags & FLAG_6) {
echo 'FLAG_6 was set';
}
else {
echo 'FLAG_6 was not set';
}
So, in your example, $flags & FLAG_6 would be true because:
$flags = 41 = 101001
FLAG_6 = 32 = 100000
If we AND them together we have 100000 which, inside an if statement,
evaluates to true.
Re: Help With Bitwise Operations
am 02.12.2007 04:15:07 von Rob Wilkerson
On Dec 1, 9:54 pm, ZeldorBlat wrote:
>
> FLAG_1 = 1 = 000001
> FLAG_6 = 32 = 100000
> FLAG_4 = 8 = 001000
>
> If we OR them all together we get 101001 = 41. So that's correct.
>
> Inside your function if you want to check if any particular flag was
> set you would do it like this:
>
> if($flags & FLAG_6) {
> echo 'FLAG_6 was set';}
>
> else {
> echo 'FLAG_6 was not set';
>
> }
>
> So, in your example, $flags & FLAG_6 would be true because:
>
> $flags = 41 = 101001
> FLAG_6 = 32 = 100000
>
> If we AND them together we have 100000 which, inside an if statement,
> evaluates to true.
Interesting. Then I have more learning to do. The function is one
that I'm trying to move into an object oriented context and, given
your validation that the input is correct, what I'm finding is the my
method is doing the right thing for the wrong reasons while the
original function that has always worked is doing the wrong thing for
the right reasons. Enigmatic.
I may have to follow up on this thread, but I have to do my own due
diligence even to know what question to ask.
Thanks for your help.
Re: Help With Bitwise Operations
am 02.12.2007 04:42:37 von shimmyshack
On Dec 2, 2:54 am, ZeldorBlat wrote:
> On Dec 1, 9:30 pm, Rob Wilkerson wrote:
>
>
>
> > I'm attempting to do some work around existing code that uses bitwise
> > operations to manage flags passed into a function and I'm quite
> > frankly unequipped to do so. I've never done much with bitwise
> > operations and all the reading I've done today doesn't appear to be
> > helping me much. I'm hoping someone here can provide a remedial
> > lesson. Given the following constants:
>
> > define('FLAG_1, 1);
> > define('FLAG_2', 2);
> > define('FLAG_3', 4);
> > define('FLAG_4', 8);
> > define('FLAG_5', 16);
> > define('FLAG_6', 32);
> > define('FLAG_7', 64);
> > define('FLAG_8', 128);
> > define('FLAG_9', 256);
> > define('FLAG_10', 512);
> > define('FLAG_11', 1024);
> > define('FLAG_12', 2048);
>
> > I'm making this call:
>
> > $foo = my_function ( 'arg1', 'arg2', FLAG_1|FLAG_6|FLAG_4 );
>
> > To this function signature:
>
> > function my_function ( $arg1, $arg2='blah', $flags=NULL )
>
> > Inside the function, if I just echo the value of $args I get "41".
>
> > Is that correct? From my reading, it doesn't seem correct, but it may
> > just be my ignorance in this area. Any assistance reading and
> > understanding this stuff would be much appreciated.
>
> > Thanks.
>
> > Rob
>
> FLAG_1 = 1 = 000001
> FLAG_6 = 32 = 100000
> FLAG_4 = 8 = 001000
>
> If we OR them all together we get 101001 = 41. So that's correct.
>
> Inside your function if you want to check if any particular flag was
> set you would do it like this:
>
> if($flags & FLAG_6) {
> echo 'FLAG_6 was set';}
>
> else {
> echo 'FLAG_6 was not set';
>
> }
>
> So, in your example, $flags & FLAG_6 would be true because:
>
> $flags = 41 = 101001
> FLAG_6 = 32 = 100000
>
> If we AND them together we have 100000 which, inside an if statement,
> evaluates to true.
you can think of it like so
"if it is in a and b then put a 1"
so what does
a & b
give you
"if it is in a and b then put a 1"
convert a and b to binary bits if needed
then think of the bits in both,
and run your mental eye down the columns,
put a 1 where the bit is set for both a and b, and a 0 where it isn't
then convert the result into decimal if needed.
17 & 8
10001
01000
so the answer is
10001
01000
00000 (no 1 appears in the any once column)
0 in decimal
how about 7 & 8
0111
1000
again 0
8 & 9
01000
01001
01000
8
with | it's similar
"if it is in a OR b" then put a 1
17 | 8
10001
01000
11001
25
notice this could almost be seen as adding up but it isn't, here's 8
and 9 again:
8 | 9
01000
01001
01001
9
where the two 1 occur twice in the same column we don't end up
doubling it, we just put a 1 in the column if there is a 1 in the
other column in EITHER row.
Re: Help With Bitwise Operations
am 02.12.2007 04:47:46 von Rob Wilkerson
On Dec 1, 10:15 pm, Rob Wilkerson wrote:
> On Dec 1, 9:54 pm, ZeldorBlat wrote:
>
> I may have to follow up on this thread, but I have to do my own due
> diligence even to know what question to ask.
Okay, I figured out what I was doing wrong and have both functions
behaving exactly the same. Almost. The difference is that when the
function is called, the constants are available to it and the bitwise
expression is passed in as just that - a bitwise expression (is it
properly called an "expression"?). The method, though, is forced to
pass the expression in as a string for evaluation within the method
itself.
So the function gets FLAG_1|FLAG_6|FLAG_4 (evaluating to 41), while
the method gets 'FLAG_1|FLAG_6|FLAG_4' (no evaluation done). In the
method, I split the string, apply the constant values and get the
correct output (1|32|8), but it's still a string. How can I evaluate
that string to get 41?
Thanks again for the help.
Re: Help With Bitwise Operations
am 02.12.2007 04:57:17 von Jerry Stuckle
Rob Wilkerson wrote:
> On Dec 1, 10:15 pm, Rob Wilkerson wrote:
>> On Dec 1, 9:54 pm, ZeldorBlat wrote:
>>
>> I may have to follow up on this thread, but I have to do my own due
>> diligence even to know what question to ask.
>
> Okay, I figured out what I was doing wrong and have both functions
> behaving exactly the same. Almost. The difference is that when the
> function is called, the constants are available to it and the bitwise
> expression is passed in as just that - a bitwise expression (is it
> properly called an "expression"?). The method, though, is forced to
> pass the expression in as a string for evaluation within the method
> itself.
>
> So the function gets FLAG_1|FLAG_6|FLAG_4 (evaluating to 41), while
> the method gets 'FLAG_1|FLAG_6|FLAG_4' (no evaluation done). In the
> method, I split the string, apply the constant values and get the
> correct output (1|32|8), but it's still a string. How can I evaluate
> that string to get 41?
>
> Thanks again for the help.
Rob,
Your method should be getting the bitwise expression, also. Just
because it's a method in a class doesn't make any difference as to
what's being called.
How about some code?
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================
Re: Help With Bitwise Operations
am 02.12.2007 05:13:33 von Rob Wilkerson
On Dec 1, 10:57 pm, Jerry Stuckle wrote:
> Your method should be getting the bitwise expression, also. Just
> because it's a method in a class doesn't make any difference as to
> what's being called.
>
> How about some code?
The code is all kind of up there. I think maybe I haven't done a very
good job of describing the context so let me try to do better.
In the standalone function solution, the function exists in a file
that is included. That file also includes the constant definitions
(outside the function). When the file containing the constants and
functions is included any code calling the function can use the
constants when passing parameters to the function.
The method, on the other hand, will be part of a class that exists as
a singleton. I'll make the singleton available to other objects (in a
manner I haven't decided yet) and call the method from within that
object as MyClass::getInstance()->my_method ( ... ). At the time the
call is made, the flags will not be available as constants, but I'd
still like to be able to pass the human readable syntax. To do that,
I've moved the constants into my_method() with the intent of
translating the flag's variable name into its bit value at the top of
the method. That's done and I get the expression I'm expecting (1|32|
8), but not the evaluated value I need. Here's a snippet from the
method that _might_ help:
$result = $myobj->my_method ( 'arg1', 'arg2', 'PREG_FIND_RECURSIVE|
PREG_FIND_RETURNASSOC' );
At the top of the function, I have the following code to re-evaluate
the flags into their bits:
$tmp = preg_split ( '/([|&^~])/', $args,
-1 ,PREG_SPLIT_DELIM_CAPTURE );
$args = '';
foreach ( $tmp as $arg ) {
$args .= defined ( "self::$arg" ) ? constant ( "self::$arg" ) : $arg;
}
At this point, I have '1|32|8' rather than 41. I'm not sure how to
make that next step or, alternatively, to process the string more
effectively as a bit expression.
I hope that helps a little. Thanks again.
Re: Help With Bitwise Operations
am 02.12.2007 05:46:04 von Jerry Stuckle
Rob Wilkerson wrote:
> On Dec 1, 10:57 pm, Jerry Stuckle wrote:
>> Your method should be getting the bitwise expression, also. Just
>> because it's a method in a class doesn't make any difference as to
>> what's being called.
>>
>> How about some code?
>
> The code is all kind of up there. I think maybe I haven't done a very
> good job of describing the context so let me try to do better.
>
> In the standalone function solution, the function exists in a file
> that is included. That file also includes the constant definitions
> (outside the function). When the file containing the constants and
> functions is included any code calling the function can use the
> constants when passing parameters to the function.
>
> The method, on the other hand, will be part of a class that exists as
> a singleton. I'll make the singleton available to other objects (in a
> manner I haven't decided yet) and call the method from within that
> object as MyClass::getInstance()->my_method ( ... ). At the time the
> call is made, the flags will not be available as constants, but I'd
> still like to be able to pass the human readable syntax. To do that,
> I've moved the constants into my_method() with the intent of
> translating the flag's variable name into its bit value at the top of
> the method. That's done and I get the expression I'm expecting (1|32|
> 8), but not the evaluated value I need. Here's a snippet from the
> method that _might_ help:
>
> $result = $myobj->my_method ( 'arg1', 'arg2', 'PREG_FIND_RECURSIVE|
> PREG_FIND_RETURNASSOC' );
>
> At the top of the function, I have the following code to re-evaluate
> the flags into their bits:
>
> $tmp = preg_split ( '/([|&^~])/', $args,
> -1 ,PREG_SPLIT_DELIM_CAPTURE );
> $args = '';
>
> foreach ( $tmp as $arg ) {
> $args .= defined ( "self::$arg" ) ? constant ( "self::$arg" ) : $arg;
> }
>
> At this point, I have '1|32|8' rather than 41. I'm not sure how to
> make that next step or, alternatively, to process the string more
> effectively as a bit expression.
>
> I hope that helps a little. Thanks again.
No, let's see your entire method - and more importantly, the code that's
calling it. You shouldn't need to do any of the stuff you're doing
here. You have something else wrong, but my crystal ball is broken.
So, without the code it's impossible to see what you've got.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================
Re: Help With Bitwise Operations
am 02.12.2007 11:23:45 von Rob Wilkerson
On Dec 1, 11:46 pm, Jerry Stuckle wrote:
>
> No, let's see your entire method - and more importantly, the code that's
> calling it. You shouldn't need to do any of the stuff you're doing
> here. You have something else wrong, but my crystal ball is broken.
> So, without the code it's impossible to see what you've got.
Okay, then you need a little more background, maybe. I'm working to
adapt someone else's custom function into an object oriented
architecture. The original function (and definition of constants) can
be found at http://www.pgregg.com/projects/php/preg_find/preg_find.phps.
My object oriented translation requires just a few changes to the
function itself and they're really just syntax changes - except for
translating the bitwise expression.
CALLING THE METHOD:
require_once ( 'org/client/file/finder.php' );
$finder = new Finder();
$result = $finder->preg_find ( '/image\.php$/', '/path/to/my/includes/
org/client/content', 'PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC' );
new PHPDump ( $result );
exit();
Note that the flag definitions do not exist yet. If the single quotes
in the third argument are removed then the normal (and expected)
"constant not defined" errors are thrown. Nor, for that matter, do I
*want* them to exist here. I want to keep them with the code where
they matter rather than defining them everywhere they're used.
Similarly, I want to continue to be able to use the flags because
they're more readable than passing in the bit values themselves.
METHOD CHANGES:
class Finder {
const PREG_FIND_RECURSIVE = 1;
const PREG_FIND_DIRMATCH = 2;
const PREG_FIND_FULLPATH = 4;
const PREG_FIND_NEGATE = 8;
/**
* All of the additional flag constants defined similarly
*
* SNIP -->
*/
public function preg_find ( $pattern, $start_dir='.', $args=NULL ) {
/**
* Go through the business of evaluating the bit string.
*/
$args_in = $args; /** Save off the input string */
$tmp = preg_split ( '/([|&^~])/', $args,
-1 ,PREG_SPLIT_DELIM_CAPTURE );
$args = '';
foreach ( $tmp as $arg ) {
$args .= defined ( "self::$arg" ) ? constant ( "self::$arg" ) :
$arg;
}
/**
* Back to doing what we need to do using the bitwise expression
that is expected.
*/
static $depth = -1;
++$depth;
/**
* SNIP -->
*/
}
}
Aside from the code shown at the top of the method, only the following
changes from the original were made:
- The syntax of all references to a flag within the method was changed
to "self::FLAG_NAME".
- In the recursive call to the method, the arguments being passed are
the original arguments saved off at the top of the method.
I've found no other changes that are required thus far.
Once again, I appreciate your help.
Re: Help With Bitwise Operations
am 02.12.2007 13:59:26 von Jerry Stuckle
Rob Wilkerson wrote:
> On Dec 1, 11:46 pm, Jerry Stuckle wrote:
>> No, let's see your entire method - and more importantly, the code that's
>> calling it. You shouldn't need to do any of the stuff you're doing
>> here. You have something else wrong, but my crystal ball is broken.
>> So, without the code it's impossible to see what you've got.
>
> Okay, then you need a little more background, maybe. I'm working to
> adapt someone else's custom function into an object oriented
> architecture. The original function (and definition of constants) can
> be found at http://www.pgregg.com/projects/php/preg_find/preg_find.phps.
>
> My object oriented translation requires just a few changes to the
> function itself and they're really just syntax changes - except for
> translating the bitwise expression.
>
> CALLING THE METHOD:
>
> require_once ( 'org/client/file/finder.php' );
> $finder = new Finder();
> $result = $finder->preg_find ( '/image\.php$/', '/path/to/my/includes/
> org/client/content', 'PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC' );
> new PHPDump ( $result );
> exit();
>
> Note that the flag definitions do not exist yet. If the single quotes
> in the third argument are removed then the normal (and expected)
> "constant not defined" errors are thrown. Nor, for that matter, do I
> *want* them to exist here. I want to keep them with the code where
> they matter rather than defining them everywhere they're used.
> Similarly, I want to continue to be able to use the flags because
> they're more readable than passing in the bit values themselves.
>
> METHOD CHANGES:
>
> class Finder {
> const PREG_FIND_RECURSIVE = 1;
> const PREG_FIND_DIRMATCH = 2;
> const PREG_FIND_FULLPATH = 4;
> const PREG_FIND_NEGATE = 8;
>
> /**
> * All of the additional flag constants defined similarly
> *
> * SNIP -->
> */
>
>
> public function preg_find ( $pattern, $start_dir='.', $args=NULL ) {
> /**
> * Go through the business of evaluating the bit string.
> */
> $args_in = $args; /** Save off the input string */
> $tmp = preg_split ( '/([|&^~])/', $args,
> -1 ,PREG_SPLIT_DELIM_CAPTURE );
> $args = '';
>
> foreach ( $tmp as $arg ) {
> $args .= defined ( "self::$arg" ) ? constant ( "self::$arg" ) :
> $arg;
> }
>
> /**
> * Back to doing what we need to do using the bitwise expression
> that is expected.
> */
> static $depth = -1;
> ++$depth;
>
> /**
> * SNIP -->
> */
> }
> }
>
> Aside from the code shown at the top of the method, only the following
> changes from the original were made:
>
> - The syntax of all references to a flag within the method was changed
> to "self::FLAG_NAME".
> - In the recursive call to the method, the arguments being passed are
> the original arguments saved off at the top of the method.
>
> I've found no other changes that are required thus far.
>
> Once again, I appreciate your help.
The flags do exist in your code, because you've defined them. Your
problem is in how you're using them.
You defined the constants in the class, so you need to scope them to the
class, i.e. Finder::PREG_FIND_RECURSIVE.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex@attglobal.net
==================
Re: Help With Bitwise Operations
am 02.12.2007 15:01:47 von Rob Wilkerson
On Dec 2, 7:59 am, Jerry Stuckle wrote:
> Rob Wilkerson wrote:
> > On Dec 1, 11:46 pm, Jerry Stuckle wrote:
> >> No, let's see your entire method - and more importantly, the code that's
> >> calling it. You shouldn't need to do any of the stuff you're doing
> >> here. You have something else wrong, but my crystal ball is broken.
> >> So, without the code it's impossible to see what you've got.
>
> > Okay, then you need a little more background, maybe. I'm working to
> > adapt someone else's custom function into an object oriented
> > architecture. The original function (and definition of constants) can
> > be found athttp://www.pgregg.com/projects/php/preg_find/preg_find.php s.
>
> > My object oriented translation requires just a few changes to the
> > function itself and they're really just syntax changes - except for
> > translating the bitwise expression.
>
> > CALLING THE METHOD:
>
> > require_once ( 'org/client/file/finder.php' );
> > $finder = new Finder();
> > $result = $finder->preg_find ( '/image\.php$/', '/path/to/my/includes/
> > org/client/content', 'PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC' );
> > new PHPDump ( $result );
> > exit();
>
> > Note that the flag definitions do not exist yet. If the single quotes
> > in the third argument are removed then the normal (and expected)
> > "constant not defined" errors are thrown. Nor, for that matter, do I
> > *want* them to exist here. I want to keep them with the code where
> > they matter rather than defining them everywhere they're used.
> > Similarly, I want to continue to be able to use the flags because
> > they're more readable than passing in the bit values themselves.
>
> > METHOD CHANGES:
>
> > class Finder {
> > const PREG_FIND_RECURSIVE = 1;
> > const PREG_FIND_DIRMATCH = 2;
> > const PREG_FIND_FULLPATH = 4;
> > const PREG_FIND_NEGATE = 8;
>
> > /**
> > * All of the additional flag constants defined similarly
> > *
> > * SNIP -->
> > */
>
> > public function preg_find ( $pattern, $start_dir='.', $args=NULL ) {
> > /**
> > * Go through the business of evaluating the bit string.
> > */
> > $args_in = $args; /** Save off the input string */
> > $tmp = preg_split ( '/([|&^~])/', $args,
> > -1 ,PREG_SPLIT_DELIM_CAPTURE );
> > $args = '';
>
> > foreach ( $tmp as $arg ) {
> > $args .= defined ( "self::$arg" ) ? constant ( "self::$arg" ) :
> > $arg;
> > }
>
> > /**
> > * Back to doing what we need to do using the bitwise expression
> > that is expected.
> > */
> > static $depth = -1;
> > ++$depth;
>
> > /**
> > * SNIP -->
> > */
> > }
> > }
>
> > Aside from the code shown at the top of the method, only the following
> > changes from the original were made:
>
> > - The syntax of all references to a flag within the method was changed
> > to "self::FLAG_NAME".
> > - In the recursive call to the method, the arguments being passed are
> > the original arguments saved off at the top of the method.
>
> > I've found no other changes that are required thus far.
>
> > Once again, I appreciate your help.
>
> The flags do exist in your code, because you've defined them. Your
> problem is in how you're using them.
>
> You defined the constants in the class, so you need to scope them to the
> class, i.e. Finder::PREG_FIND_RECURSIVE.
Bingo. I didn't realize constants could be accessed that way. And,
as is usually the case, I find it clearly spelled out that way in the
docs once I kind of understand what I'm looking for.
Thanks for your help.