## Principle

The idea is very simple :
• Define a mask having the same size in bytes than the value to decode ( let’s call it “v” ) and set the bits to extract to 1 and the others to 0
• Apply a logical AND operation between it and v
• Then shift the result right n times where n is the index ( starting from 0 ) of the first significant bit.

## Example

Let’s apply this method on a real example, taken from the CALIPSO 05kmCLay product. We will extract the Ice/Water Phase of a cloud layer. This information is defined in the “Feature_Classification_Flags” dataset, and the phase bit flags are set at indexes 5-6 ( starting from 0 ). For a complete description of the flags definition, please refer to the CALIPSO Data Products Catalog. Be careful, the bits numbering starts from 1 in this document. The value to decode is read in the file CAL_LID_L2_05kmCLay-Prov-V2-02.2009-01-01T00-07-47ZN.hdf. Its value for the layer number 3 of the profile 3481 is 39898, on 2 bytes ( 1001101111011010 in binary format ) Define the bits selection mask We set a 2 bytes long mask, with only the bits 5 and 6 set to 1. The mask will be, in binary format :

```ibit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
---------------------------------------------------------
mask | 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 | => 96 in decimal format
```
Logical AND between the mask and the value All bits set to 0 in the mask will be 0 in the result, and all the bits set to 1 will give the same in the result than in the value
```value | 1 0 0 1 1 0 1 1 1 1 0 1 1 0 1 0 |
AND
mask | 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 |
---------------------------------------------------------
result | 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | => 64
```
Shift right to remove unsignificant bits Now, to have only the value of the bits in red, the result is shifted right 5 times ( 5 is the number of unsignificant bits on the right )
```Shift 1 time | 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 |
Shift 2 times | 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 |
...
Shift 5 times | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | => 2
```

## Synopsis

The way to implement this is different for all languages, but the C/C++/python way is :
`flag = ( value & mask ) >> n`

## Source

Here is an implementation in PYTHON, as a command-line tool. It offers 2 ways to specify the bits to read :
• by specifying the first bit position and the flag width
• by specifying explicitly the bit selection mask
Source is printed below, but can also be downloaded as a package : Get_bitflag.v1.0.0.tar.gz
``` # -*- coding: utf-8 -*-

"""
Description :
-------------
Extracts the bits from a bitflag and prints it out in a binary format

Usage :
-------
The tool can be used in 2 ways :

1) by specifying the first bit position and the flag width

python get_bitflag <flag-word> <1st-bit-index> <width>

where :

<flag-word>  : the value that contains the bits to extract
<first_bit>  : the position of the first significant bit ( starting from 0 )
<flag_width> : the number of bits of the flag to read

2) by specifying explicitly the bit selection mask

where :

<flag-word> : the value that contains the bits to extract

All input values can be specified either in decimal ( by default ), hexadecimal or binary format.
For using hexadecimal values, preceed the values by "0x" and for binary by "0b"

Example :
---------

REM : All the following forms are exactly equivalent and leads to 3. Only the base of the input values differs,
and how the bits are selected

--- flag selection by mask ---

python get_bitflag.py 59 48
python get_bitflag.py 0x3b 0x30
python get_bitflag.py 0b111011 0b110000

All will print out 3 : it selects the values the bits number 4 and 5  ( starting from 0 )

--- flag selection by first bit and width ---

python get_bitflag.py 59 4 2
python get_bitflag.py 0x3b 4 2
python get_bitflag.py 0b111011 4 2

All will print out 3 : it constructs the mask for selecting the 2 bits starting from index 4, ie 110000

Prerequisites :
---------------
python >= 2.5 ; not tested but probably all versions

Author :
--------
CGTD-ICARE/UDEV Nicolas PASCAL ( nicolas.pascal-at-icare.univ-lille.fr  )

---------
This file must be used under the terms of the CeCILL.
This source file is licensed as described in the file COPYING, which
you should have received as part of this distribution.  The terms
are also available at
http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt

History :
---------
v1.0.0 : 2009/12/07

v0.1.0 : 2009/12/04
- creation
"""

import sys

# if set to true, print detailled intermediate results
__DEBUG__=False

def get_bitflag_by_range ( flag_word, first_bit, flag_width ) :
"""
@brief read the bit flag values by specifying the first bit position and the flag width
@warning if flag_width is null, an exception is raised
@param flag_word flag word where are stored the bits to extract
@param flag_width the number of bits of the flag
@return the bit flag value
"""
if flag_width <= 0 :
raise ValueError ( "Invalid width value %d. Must be a strictly positive integer"%flag_width )

# construct the bitflag selection mask

"""
@brief read the bit flag values by an explicit specification of the mask
@param flag_word flag word where are stored the bits to extract
@return the bit flag value
"""
# find the position of the first not null bit of the mask
first_bit_pos = get_first_bit_pos ( mask )
# apply a binary AND between value and mask, then shift result ot first significant bit
return ( ( flag_word & mask ) >> first_bit_pos )

def get_first_bit_pos ( v ):
"""
@brief return the position of the first significant ( ie not null ) bit of a value, by increasing weight
@param v an integer value
"""
if v == 0 :
return 0

bit_pos = 0
while ( ( v & 1 ) == 0 ) :
bit_pos = bit_pos + 1
v = v >> 1
return bit_pos

def get_mask ( first_bit, flag_width ) :
"""
@brief construct the mask of a bitfield specified by the position of the first significant bit
and the width, in number of bits, of the flag to read
@param first_bit position of the first significant bit
@param flag_width number of bits, of the flag to read
@return the mask value, as an integer matching the binary : "flag_width" number of 1 + " first_bit" number of 0"
"""
for exp in xrange( flag_width ):
mask += 2 ** ( first_bit + exp )

def to_bin_str ( v ):
"""
@brief return the binary representation of v as a string
@param v an integer value
@return the binary representation of v as a string
"""
if v :
return to_bin_str (  v >> 1 ) + str ( v & 1 )
else :
return ""

def usage ():
"""
@brief build the script usage string
@return the script usage as a string
"""
s  = ""
s += "Usage :\n"
s += "\tpython get_bitflag <flag-word> <1st-bit-index> <width>\n\n"
s += "where :\n"
s += "\t<flag-word>  : the value that contains the bits to extract\n"
s += "\t<first_bit>  : the position of the first significant bit ( starting from 0 )\n"
s += "\t<flag_width> : the number of bits of the flag to read\n"
s += "\nOr\n"
s += "\tpython get_bitflag <flag-word> <bitmask>\n\n"
s += "where :\n"
s += "\t<flag-word>  : the value that contains the bits to extract\n"
s += "All input values can be specified either in decimal ( by default ), hexadecimal or binary format.\n"
s += "For using hexadecimal values, preceed the values by \"0x\" and for binary by \"0b\"\n"
return s

def main () :
"""
@brief program entry point
"""
if   len ( sys.argv ) == 3 :
val  = int ( sys.argv, 0 )
mask = int ( sys.argv, 0 )
if __DEBUG__ :
# print all the details of the operation
print "val  = %16s\t => %d"%( to_bin_str ( val ), val )
print "res  = %16s\t => %d"%( to_bin_str ( flag ),  flag )
else :
# just print the result
print flag

elif len ( sys.argv ) == 4 :
# --- read bits by specifying the 1st bit position and the flag width --- #
val        = int ( sys.argv, 0 )
first_bit  = int ( sys.argv, 0 )
flag_width = int ( sys.argv, 0 )
flag = get_bitflag_by_range ( val, first_bit, flag_width )
if __DEBUG__ :
# print all the details of the operation
print "val  = %16s\t => %d"%( to_bin_str ( val ), val )
print "bit_pos = %d width = %d"%( first_bit, flag_width )