Tuesday, November 8, 2011

Bit Field in PHP

So, a coworker ran across a piece of legacy code and wasn't sure what it was doing.



His first guess was a typo in a logical AND (&&). I completely understand his confusion, binary operators are not commonly used in PHP programs. Being an old C programmer, when I saw this I knew immediately it was a bit field. Checking the database table that $external_reports was pull from confirmed this :
+----------+------+
| Name     | Type |
+----------+------+
| Report A |    1 |  
| Report B |    2 |
        ...
| Repord H |  256 |
| Report I |  512 |
+----------+------+

So, what is a bit field? Wikipedia says Bit Field is a "common idiom used in computer programming to compactly store multiple logical values as a short series of bits where each of the single bits can be addressed separately." These are extremely important when the memory usage is vital (and probably other scenarios that I can't think of while I write this). Infact, C/C++ has the idea of bit fields built into the struct type.

Okay, so the important part, how they work. First let's look at that table again with an extra piece of information, the binary representation of the numbers :
+----------+------+
| Name     | Type |
+----------+------+------------+
| Report A |    1 | 0000000001 |
| Report B |    2 | 0000000010 |
        ...
| Repord H |  256 | 0100000000 |
| Report I |  512 | 1000000000 |
+----------+------+------------+

So, if $show_reports = 512 (binary of 1000000011). So the code loops through each of the report types AND'ing it to the value. So the results are :
Report A                     Report B
  0000000001                   0000000010
& 1000000011                 & 1000000011
============                 ============
  0000000001 (TRUE)            0000000010 (TRUE)



Repord H                     Report I
  0100000000                   1000000000
& 1000000011                 & 1000000011
============                 ============
  0000000000 (FALSE)           1000000000 (TRUE)

So, display_report() will be displayed for A,B, & I.

So, how does the value change? Well to add a new report one just OR's it:


To remove a value, it's AND'ed on the ones' complement of the value:


Okay, so reading back over this, it doesn't seem a good blog post. Oh well :P