The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
NAME
    Bitmask::Data - Handle unlimited length bitmasks in an easy and flexible
    way

SYNOPSIS
     # Create a simple bitmask class
     package MyBitmask;
     use base qw(Bitmask::Data);
     __PACKAGE__->bitmask_length(18);
     __PACKAGE__->bitmask_default('0b000000000000000011');
     __PACKAGE__->init(
        'value1' => '0b000000000000000001',
        'value2' => '0b000000000000000010',
        'value2' => '0b000000000000000100',
        'value4' => '0b000000000000001000',
        'value5' => '0b000000000000010000',
        ...
     );
 
     ## Somewhere else in your code
     use MyBitmask;
     my $bm1 = MyBitmask->new('value1','value3');
     my $bm2 = MyBitmask->new('0b000000000000010010');
     $bm1->add('value3');
     my $bm3 = $bm1 | $bm2; 
     $bm3->string;

DESCRIPTION
    This package helps you dealing with bitmasks. First you need to subclass
    Bitmask::Data and set the bitmask values and length. (If you are only
    working with a single bitmask in a simple application you might also
    initialize the bitmask directly in the Bitmask::Data module).

    After the initialization you can create an arbitrary number of bitmask
    objects which can be accessed and manipulated with convenient methods
    and overloaded arithmetic and bit operators.

    Bitmask::Data does not store bitmasks as integers internally, but as
    strings conststing of \0 and \1, hence makinging unlimited length
    bitmasks possible (32-bit perl can handle integer bitmasks only up to 40
    bits).

METHODS
  Class Methods
   bitmask_length
    Set/Get the length of the bitmask. Do not change this value after the
    initialization.

    Bitmask length is unlimited.

    Default: 16

   bitmask_default
    Set/Get the default bitmask for empty Bitmask::Data objects.

    Default: undef

   bitmask_lazyinit
    If true value that disables warnings for lazy initialization. (Lazy
    initialization = call of init without bitmask bit values).

    Default: 0

     __PACKAGE__->bitmask_lazyinit(1);
     __PACKAGE__->bitmask_length(6);
     __PACKAGE__->init(
        'value1', # will be 0b000001
        'value2', # will be 0b000010
        'value3'  # will be 0b000100
     );

    If bitmask_lazyinit is 2 then bit values will be filled from left to
    right, otherwise from right to left

     __PACKAGE__->bitmask_lazyinit(2);
     __PACKAGE__->bitmask_length(6);
     __PACKAGE__->init(
        'value1', # will be 0b100000
        'value2', # will be 0b010000
        'value3'  # will be 0b001000
     );

   bitmask_items
    HASHREF of all bitmask items, with values as keys and bitmask as values.

   init
        CLASS->init(LIST of VALUES);

    Initializes the bitmask class. You can supply a list of possible values.
    Optionally you can also specify the bits for the mask by adding bit
    values after the value.

        CLASS->init(
            'value1' => 0b000001,
            'value2' => 0b000010,
            'value3' => 0b001000,
            'value4' => 0b010000,
        );

    With "bitmask_lazyinit" enabled you can also skip the bitmask bit values

        CLASS->bitmask_lazyinit(1);
        CLASS->init(
            'value1',
            'value2',
            'value3',
            'value4',
        );

    Bits may be supplied as integers, strings or Math::BigInt objects (not
    recommended).

        CLASS->init(
            'value1' => 0b000001,               # integer
            'value2' => 2,                      # integer
            'value3' => '0b000100'              # string starting with '0b'
            'value4' => '0B001000'              # string starting with '0B'
            'value5' => '\0\1\0\0\0\0'          # string consisting of \0 and \1
            'value6' => Math::BigInt->new("32") # Math::BigInt object
        );

   int2bit
        my $bitmask_string = CLASS->int2bit(INTEGER);

    Helper method that turns an integer into the internal bitmask
    representation

   string2bit
        my $bitmask_string = CLASS->string2bit(STRING);

    Helper method that takes a string like '0B001010' or '0b010101' and
    turns it into the internal bitmask representation

   any2bitmask
        my $bitmask_string = CLASS->any2bitmask(ANYTHING);

    Helper method that tries to turn a data into the internal bitmask
    representation. This method can hanle

    *   any Bitmask::Data object

    *   Math::BigInt object

    *   a string matching on of the bitmask values

    *   a bitmask string consisting of \0 and \1 characters

    *   a bitmask string starting with '0b' or '0B' and containing only 0
        and 1

    *   an integer

   _parse_params
        my $bitmask_string = CLASS->_parse_params(LIST)

    Helper method for parsing params passed to various methods.

  Overloaded operators
    Bitmask::Data uses overload by default.

    *   Numeric context

        Returns bitmask integer value (see integer method). For large
        bitmasks (> 40 bits) this will allways be a Math::BigInt object
        (hence using this method is not recommended).

    *   Scalar context

        Returns bitmask string representation (see string method)

    *   ==, eq, <=>, cmp

        Works like 'has_any'

    *   Smartmatch

        Works like has_any.

         $bm = new Somebitmask->new('v1','v2');
         $bm ~~ ['v1','v3'] # true, because 'v1' matches even if 'v3' is not set

    *   +, -

        Adds/Removes bits to/from the bitmask without changing the current
        object. The result is returned as a new Bitmask::Data object.

    *   -=, +=

        Adds/Removes bits to/from the current bitmask object.

    *   ~, ^, &, |

        Performs the bitwise operations without changing the current object.
        The result is returned as a new Bitmask::Data object.

    *   ^=, &=, |=

        Performs the bitwise operations on the current bitmask object.

  Constructors
   new
        my $bm = MyBitmask->new();
        my $bm = MyBitmask->new('value1');
        my $bm = MyBitmask->new('0b00010000010000');
        my $bm = MyBitmask->new(124);
        my $bm = MyBitmask->new(0b00010000010000);
        my $bm = MyBitmask->new(0x2);
        my $bm = MyBitmask->new($another_bm_object);
        my $bm = MyBitmask->new("\0\1\0\0\1");
        my $bm = MyBitmask->new('value2', 'value3');
        my $bm = MyBitmask->new([32, 'value1', 0b00010000010000]);

    Create a new bitmask object. You can supply almost any combination of
    ARRAYREFS, bits, Bitmask::Data objects, Math::BigInt objects, bitmasks
    and values, even mix different types. See any2bitmask for details on
    possible formats.

   new_from_bitmask
        my $bm = MyBitmask->new_from_bitmask($bitmask_string);

    Create a new bitmask object from a bitmask string (as returned by many
    helper methods).

  Public Methods
   clone
        my $bm_new = $bm->clone();

    Clones an existing Bitmask::Data object and.

   set
        $bm->set(PARAMS);

    This methpd resets the current bitmask and sets the supplied arguments.
    Takes the same arguments as "new".

    Returns the object.

   remove
        $bm->remove(PARAMS)

    Removes the given values/bits from the bitmask. Takes the same arguments
    as "new".

    Returns the object.

   add
        $bm->add(PARAMS)

    Adds the given values/bits to the bitmask. Takes the same arguments as
    "new".

    Returns the object.

   reset
        $bm->reset()

    Resets the bitmask to the default (or empty) bitmask.

    Returns the object.

   set_all
        $bm->set_all()

    Sets all defined bits in the bitmask.

    Returns the object.

   neg
        $bm->neg()

    Negates/Inverts the bitmask

    Returns the object.

   list
        my @values = $bm->list();
        OR
        my $values = $bm->list();

    In list context, this returns a list of the set values in scalar
    context, this returns an array reference to the list of values.

   length
        my $length = $bm->length();

    Number of set bitmask values.

   first
        my $value = $bm->first()

    Returns the first set value. The order is determined by the bit value.

   integer
        my $integer = $bm->integer();

    Returns the bitmask as an integer. For bitmasks with a length > 40 this
    will always be a Math::BigInt object.

   string
        my $string = $bm->string();

    Returns the bitmask as a string of 0 and 1.

   bitmask
        my $string = $bm->bitmask();

    Returns the bitmask in the internal representation: A string of \0 and
    \1

   sqlfilter_all
    This method can be used for database searches in conjunction with
    SQL::Abstract an POSTGRESQL (SQL::Abstract is used by DBIx::Class for
    generating searches). The search will find all database rows with
    bitmask that have at least the given values set. (use the "sql" method
    for an exact match)

    Example how to use sqlfilter with SQL::Abstract:

        my($stmt, @bind) = $sql->select(
            'mytable', 
            \@fields,
            {
                $bm->sqlfilter_all('mytable.bitmaskfield'),
            }
        );

    Example how to use sqlfilter with DBIx::Class:

        my $list = $resultset->search(
            { 
                $bm->sqlfilter_all('me.bitmaskfield'), 
            },
        );

   sqlfilter_any
    Works like "sqlfilter_all" but checks for any bit matching

   sqlstring
    Returns the bitmask as a quoted string as needed by PostgreSQL:

     B'0000000000000001'::bit(16)

   has_all
        if ($bm->has_all(PARAMS)) {
            # Do something
        }

    Checks if all requestes bits/values are set and returns true or false.
    This method takes the same arguments as "new".

   has_exact
        if ($bm->has_exact(PARAMS)) {
            # Do something
        }

    Checks if the set bits/values excactly match the supplied bits/values
    and returns true or false. This method takes the same arguments as
    "new".

   has_any
        if ($bm->has_any(PARAMS)) {
            # Do something
        }

    Checks if at least one set value/bit matches the supplied bits/values
    and returns true or false. This method takes the same arguments as
    "new".

CAVEATS
    Since Bitmask::Data is very liberal with input data you cannot use
    numbers as bitmask values. (It would think that you are supplying an
    integer bitmask and not a value)

    Bitmask::Data adds a considerable processing overhead to bitmask
    manipulations. If you either don't need the extra comfort or use
    bitmasks with less that 40 bits that you should consider using just the
    perl built in bit operators on simple integer values.

SUBCLASSING
    Bitmask::Data was designed to be subclassed.

        package MyBitmask;
        use parent qw(Bitmask::Data);
        __PACKAGE__->bitmask_length(20); # Default length is 16
        __PACKAGE__->init(
            'value1' => 0b000000000000000001,
            'value2' => 0x2,
            'value2' => 4,
            'value4', # lazy initlialization
            'value5', # lazy initlialization
        );

WORKING WITH DATABASES
    This module comes with support for POSTGRESQL databases (patches for
    other database vendors are welcome).

    First you need to create the correct column types:

        CREATE TABLE bitmaskexample ( 
            id integer DEFAULT nextval('pkey_seq'::regclass) NOT NULL,
            bitmask bit(14),
            otherfields character varying
        );

    The length of the bitmask field must match "CLASS->bitmask_length".

    This module provides three convenient methods to work with databases:

    *   sqlfilter_all: Search for matching bitmasks

    *   sqlfilter_any: Search for bitmasks with matching bits

    *   string: Print the bitmask string as used by the database

    If you are working with l<DBIx::Class> you might also install de- and
    inflators for Bitmask::Data objects:

        __PACKAGE__->inflate_column('fieldname',{
            inflate => sub {
                my $value = shift;
                return MyBitmask->new($value);
            },
            deflate => sub {
                my $value = shift;
                undef $value 
                    unless ref($value) && $value->isa('MyBitmask');
                $value //= MyBitmask->new();
                return $value->string;
            },
        });

SUPPORT
    Please report any bugs or feature requests to
    "bug-bitmask-data@rt.cpan.org", or through the web interface at
    <http://rt.cpan.org/Public/Bug/Report.html?Queue=Bitmask::Data>. I will
    be notified and then you'll automatically be notified of the progress on
    your report as I make changes.

AUTHOR
        Klaus Ita
        koki [at] worstofall.com

        Maroš Kollár
        CPAN ID: MAROS
        maros [at] k-1.com
    
        L<http://www.revdev.at>

ACKNOWLEDGEMENTS
    This module was originally written by Klaus Ita (Koki) for Revdev
    <http://www.revdev.at>, a nice litte software company I (Maros) run with
    Koki and Domm (<http://search.cpan.org/~domm/>).

COPYRIGHT & LICENSE
    Bitmask::Data is Copyright (c) 2008 Klaus Ita, Maroš Kollár -
    <http://www.revdev.at>

    This program is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

    The full text of the license can be found in the LICENSE file included
    with this module.