File Coverage

blib/lib/Bitmask/Data.pm
Criterion Covered Total %
statement 244 244 100.0
branch 49 50 98.0
condition 18 23 78.2
subroutine 51 51 100.0
pod 25 26 96.1
total 387 394 98.2


line stmt bran cond sub pod time code
1             # ============================================================================
2             package Bitmask::Data;
3             # ============================================================================
4 9     9   191480 use strict;
  9         39  
  9         320  
5 9     9   57 use warnings;
  9         20  
  9         351  
6 9     9   3912 no if $] >= 5.017004, warnings => qw(experimental::smartmatch);
  9         107  
  9         56  
7              
8 9     9   1167 use parent qw(Class::Data::Inheritable);
  9         495  
  9         72  
9 9     9   6168 use 5.010;
  9         37  
10              
11 9     9   50 use Carp;
  9         20  
  9         516  
12 9     9   53 use Config;
  9         19  
  9         364  
13 9     9   51 use List::Util qw(reduce);
  9         19  
  9         864  
14 9     9   57 use Scalar::Util qw(blessed);
  9         31  
  9         6023  
15              
16             our $VERSION = version->new('2.05');
17             our $AUTHORITY = 'cpan:MAROS';
18              
19             our $ZERO = chr(0);
20             our $ONE = chr(1);
21              
22             =encoding utf8
23              
24             =head1 NAME
25              
26             Bitmask::Data - Handle unlimited length bitmasks in an easy and flexible way
27              
28             =head1 SYNOPSIS
29              
30             # Create a simple bitmask class
31             package MyBitmask;
32             use base qw(Bitmask::Data);
33             __PACKAGE__->bitmask_length(18);
34             __PACKAGE__->bitmask_default('0b000000000000000011');
35             __PACKAGE__->init(
36             'value1' => '0b000000000000000001',
37             'value2' => '0b000000000000000010',
38             'value2' => '0b000000000000000100',
39             'value4' => '0b000000000000001000',
40             'value5' => '0b000000000000010000',
41             ...
42             );
43            
44             ## Somewhere else in your code
45             use MyBitmask;
46             my $bm1 = MyBitmask->new('value1','value3');
47             my $bm2 = MyBitmask->new('0b000000000000010010');
48             $bm1->add('value3');
49             my $bm3 = $bm1 | $bm2;
50             $bm3->string;
51              
52             =head1 DESCRIPTION
53              
54             This package helps you dealing with bitmasks. First you need to subclass
55             Bitmask::Data and set the bitmask values and length. (If you are only working
56             with a single bitmask in a simple application you might also initialize
57             the bitmask directly in the Bitmask::Data module).
58              
59             After the initialization you can create an arbitrary number of bitmask
60             objects which can be accessed and manipulated with convenient methods and
61             overloaded arithmetic and bit operators.
62              
63             Bitmask::Data does not store bitmasks as integers internally, but as
64             strings conststing of \0 and \1, hence makinging unlimited length bitmasks
65             possible.
66              
67             =head1 METHODS
68              
69             =head2 Class Methods
70              
71             =head3 bitmask_length
72              
73             Set/Get the length of the bitmask. Do not change this value after the
74             initialization.
75              
76             Bitmask length is unlimited.
77              
78             Default: 16
79              
80             =head3 bitmask_default
81              
82             Set/Get the default bitmask for empty Bitmask::Data objects.
83              
84             Default: undef
85              
86             =head3 bitmask_lazyinit
87              
88             If true warning for lazy initialization are disabled. (Lazy
89             initialization = call of init without bitmask bit values).
90              
91             Default: 0
92              
93             __PACKAGE__->bitmask_lazyinit(1);
94             __PACKAGE__->bitmask_length(6);
95             __PACKAGE__->init(
96             'value1', # will be 0b000001
97             'value2', # will be 0b000010
98             'value3' # will be 0b000100
99             );
100            
101             If bitmask_lazyinit is 2 then bit values will be filled from left to right,
102             otherwise from right to left
103            
104             __PACKAGE__->bitmask_lazyinit(2);
105             __PACKAGE__->bitmask_length(6);
106             __PACKAGE__->init(
107             'value1', # will be 0b100000
108             'value2', # will be 0b010000
109             'value3' # will be 0b001000
110             );
111              
112             =head3 bitmask_items
113              
114             HASHREF of all bitmask items, with values as keys and bitmask as values.
115              
116             =head3 init
117              
118             CLASS->init(LIST of VALUES);
119              
120             Initializes the bitmask class. You can supply a list of possible values.
121             Optionally you can also specify the bits for the mask by adding bit values
122             after the value.
123            
124             CLASS->init(
125             'value1' => 0b000001,
126             'value2' => 0b000010,
127             'value3' => 0b001000,
128             'value4' => 0b010000,
129             );
130            
131             With C enabled you can also skip the bitmask bit values
132              
133             CLASS->bitmask_lazyinit(1);
134             CLASS->init(
135             'value1',
136             'value2',
137             'value3',
138             'value4',
139             );
140              
141             Bits may be supplied as integers, strings or Math::BigInt objects
142             (not recommended).
143              
144             CLASS->init(
145             'value1' => 0b000001, # integer
146             'value2' => 2, # integer
147             'value3' => '0b000100' # string starting with '0b'
148             'value4' => '0B001000' # string starting with '0B'
149             'value5' => '\0\1\0\0\0\0' # string consisting of \0 and \1
150             'value6' => Math::BigInt->new("32") # Math::BigInt object
151             );
152              
153             =cut
154              
155             __PACKAGE__->mk_classdata( bitmask_length => 16 );
156             __PACKAGE__->mk_classdata( bitmask_items => {} );
157             __PACKAGE__->mk_classdata( bitmask_default => undef );
158             __PACKAGE__->mk_classdata( bitmask_lazyinit => 0 );
159             __PACKAGE__->mk_classdata( bitmask_empty => undef );
160             __PACKAGE__->mk_classdata( bitmask_full => undef );
161              
162             use overload
163             '<=>' => '_compare',
164             'cmp' => '_compare',
165             '==' => '_equals',
166             'eq' => '_equals',
167             '~~' => sub {
168 9     9   22 my ($self,$value) = @_;
169 9         16 my $bitmask = $self->any2bitmask($value);
170 9 100       21 return (($bitmask & $self->{bitmask}) ne $self->bitmask_empty) ? 1:0;
171             },
172             'bool' => sub {
173 9     9   925 my ($self) = @_;
174 9 100       23 return ($self->{bitmask} ne $self->bitmask_empty) ? 1:0;
175             },
176             '0+' => 'integer',
177             '""' => 'string',
178             '+=' => 'add',
179             '-=' => 'remove',
180             '+' => sub {
181 2     2   264 my ($self,$value) = @_;
182 2         7 return $self->clone->add($value);
183             },
184             '-' => sub {
185 1     1   3 my ($self,$value) = @_;
186 1         3 return $self->clone->remove($value);
187             },
188             '&' => sub {
189 1     1   139 my ($self,$value) = @_;
190 1         3 my $bitmask = $self->any2bitmask($value);
191 1         4 return $self->new_from_bitmask($self->{bitmask} & $bitmask);
192             },
193             '^' => sub {
194 1     1   3 my ($self,$value) = @_;
195 1         3 my $bitmask = $self->any2bitmask($value);
196 1         3 return $self->new_from_bitmask($self->{bitmask} ^ $bitmask);
197             },
198             '|' => sub {
199 1     1   2 my ($self,$value) = @_;
200 1         3 my $bitmask = $self->any2bitmask($value);
201 1         5 return $self->new_from_bitmask($self->{bitmask} | $bitmask);
202             },
203             '&=' => sub {
204 1     1   3 my ($self,$value) = @_;
205 1         3 my $bitmask = $self->any2bitmask($value);
206 1         3 $self->{bitmask} &= $bitmask;
207             #$self->{cache} = undef;
208 1         2 return $self;
209             },
210             '^=' => sub {
211 1     1   3 my ($self,$value) = @_;
212 1         4 my $bitmask = $self->any2bitmask($value);
213 1         2 $self->{bitmask} ^= $bitmask;
214             #$self->{cache} = undef;
215 1         3 return $self;
216             },
217             '|=' => sub {
218 1     1   2 my ($self,$value) = @_;
219 1         4 my $bitmask = $self->any2bitmask($value);
220 1         3 $self->{bitmask} |= $bitmask;
221             #$self->{cache} = undef;
222 1         3 return $self;
223             },
224             "~" => sub {
225 1     1   2 my ($self) = @_;
226 1         4 return $self->clone->neg();
227 9     9   2865 };
  9         2223  
  9         213  
228            
229             sub _equals {
230 3     3   231 my ($self,$value) = @_;
231 3         7 my $bitmask = $self->any2bitmask($value);
232 3         23 return ($self->{bitmask} eq $bitmask);
233             }
234            
235             sub _compare {
236 6     6   16 my ($self,$value) = @_;
237              
238 6         13 my $bitmask = $self->any2bitmask($value);
239            
240 6         26 return $self->{bitmask} cmp $bitmask;
241             }
242              
243             sub init {
244 17     17 1 74685 my ($class,@params) = @_;
245              
246 17         75 my $length = $class->bitmask_length;
247              
248 17 100 100     266 croak('Bitmask length not set')
249             unless $length && $length > 0;
250            
251 15         122 $class->bitmask_empty($ZERO x $length);
252              
253 15         379 my $items = {};
254 15         37 my $count = 0;
255 15         52 my $bitmask_full = $class->bitmask_empty();
256            
257             # Take first element from @params
258 15         170 while (my $name = shift(@params)) {
259 225         437 my ($bit,$bit_readable);
260              
261 225         404 $count++;
262            
263 225 100       581 croak(sprintf('Too many values in bitmask: max <%i>',$class->bitmask_length))
264             if $count > $class->bitmask_length;
265              
266 224   100     2401 given ( $params[0] // '' ) {
267 224   66     862 when (blessed $_ && $_->isa('Math::BigInt')) {
268 2         13 $bit = $class->string2bit(shift(@params)->as_bin());
269             }
270 222         826 when (m/^\d+$/) {
271 32         136 $bit = $class->int2bit(shift(@params));
272             }
273 190         370 when (m/^0[bB][01]+$/) {
274 3         27 $bit = $class->string2bit(shift(@params));
275             }
276 187         684 when (m/^[$ZERO$ONE]+$/) {
277 2         18 $bit = $class->bit2bit(shift(@params));
278             }
279 185         306 default {
280 185 100       473 carp( "Lazy bitmask initialization detected: Please enable"
281             . " or change init parameters" )
282             unless ( $class->bitmask_lazyinit );
283 185         4528 $bit = $class->bitmask_empty;
284            
285 185 100       1523 if ($class->bitmask_lazyinit == 2) {
286 5         78 substr($bit,($count-1),1,$ONE);
287             } else {
288 180         1774 substr($bit,($length-$count),1,$ONE);
289             }
290            
291             }
292             }
293            
294 224         447 $bit_readable = $bit;
295 224         424 $bit_readable =~ tr/\0\1/01/;
296            
297 224 100       1667 croak(sprintf('Invalid bit value <%s>',$bit_readable))
298             unless $bit =~ /^[$ZERO$ONE]{$length}$/;
299              
300             croak(sprintf('Duplicate value <%s> in bitmask',$name))
301 223 100       632 if exists $items->{$name};
302              
303             croak(sprintf('Duplicate bit <%s> in bitmask',$bit_readable))
304 222 100       339 if grep { ($_ & $bit) ne $class->bitmask_empty } values %{$items};
  7095         56736  
  222         783  
305              
306 220         2084 $bitmask_full |= $bit;
307 220         963 $items->{$name} = $bit;
308             }
309              
310 10         70 $class->bitmask_full($bitmask_full);
311 10         351 $class->bitmask_items($items);
312 10 100       268 $class->bitmask_default($class->any2bitmask($class->bitmask_default))
313             if defined $class->bitmask_default;
314 9         99 return;
315             }
316              
317             =head3 int2bit
318              
319             my $bitmask_string = CLASS->int2bit(INTEGER);
320              
321             Helper method that turns an integer into the internal bitmask representation
322              
323             =cut
324              
325             sub int2bit {
326 53     53 1 130 my ($class,$integer) = @_;
327            
328 53         154 my $bit = sprintf( '%0' . $class->bitmask_length . 'b', $integer );
329 53         663 $bit =~ tr/01/\0\1/;
330 53         172 return $bit;
331             }
332              
333             =head3 string2bit
334              
335             my $bitmask_string = CLASS->string2bit(STRING);
336              
337             Helper method that takes a string like '0B001010' or '0b010101' and turns it
338             into the internal bitmask representation
339              
340             =cut
341              
342             sub string2bit {
343 13     13 1 428 my ($class,$string) = @_;
344              
345 13         65 $string =~ s/^0[bB]//;
346 13         49 $string = sprintf( '%0' . $class->bitmask_length . 's', $string );
347 13         159 $string =~ tr/01/\0\1/;
348 13         46 return $string;
349             }
350              
351             sub bit2bit {
352 21     21 0 46 my ($class,$bit) = @_;
353            
354 21         51 $bit = $ZERO x ($class->bitmask_length - length($bit)) . $bit;
355 21         201 return $bit;
356             }
357              
358             =head3 any2bitmask
359              
360             my $bitmask_string = CLASS->any2bitmask(ANYTHING);
361              
362             Helper method that tries to turn arbitrary arguments into the internal bitmask
363             representation. This method can hanle
364              
365             =over
366              
367             =item * any Bitmask::Data object
368              
369             =item * Math::BigInt object
370              
371             =item * a string matching on of the bitmask values
372              
373             =item * a bitmask string consisting of \0 and \1 characters
374              
375             =item * a bitmask string starting with '0b' or '0B' and containing only 0 and 1
376              
377             =item * an integer
378              
379             =back
380              
381             =cut
382              
383             sub any2bitmask {
384 104     104 1 230 my ($class,$param) = @_;
385              
386 104 50       199 croak "Bitmask, Item or integer expected"
387             unless defined $param;
388              
389 104         211 my $length = $class->bitmask_length;
390 104         688 my $bit;
391 104         141 given ($param) {
392 104   100     370 when (blessed $param && $param->isa('Bitmask::Data')) {
393 18         50 $bit = $class->bit2bit($param->{bitmask});
394             }
395 86   66     209 when (blessed $param && $param->isa('Math::BigInt')) {
396 2         11 $bit = $class->string2bit($param->as_bin());
397             }
398 84         158 when ($param ~~ $class->bitmask_items) {
399 54         374 $bit = $class->bitmask_items->{$param};
400             }
401 30         424 when (m/^[$ZERO$ONE]+$/) {
402 1         8 $bit = $class->bit2bit($param);
403             }
404 29         188 when (m/^[01]{$length}$/) {
405 2         12 $bit = $class->string2bit($param);
406             }
407 27         72 when (m/^0[bB][01]+$/) {
408 4         23 $bit = $class->string2bit($param);
409             }
410 23         92 when (m/^\d+$/) {
411 21         61 $bit = $class->int2bit($param);
412             }
413 2         4 default {
414 2         42 croak sprintf('Could not turn <%s> into something meaningful',$param);
415             }
416             }
417            
418 102 100       526 if (length $bit > $class->bitmask_length) {
419 4         51 croak sprintf('<%s> exceeds maximum lenth of %i',$param,$class->bitmask_length);
420             }
421            
422 98 100       707 if (($class->bitmask_full | $bit) ne $class->bitmask_full) {
423 1         34 croak sprintf('<%s> tries to set undefined bits',$param);
424             }
425              
426 97         1248 return $bit;
427             }
428              
429             =head3 _parse_params
430              
431             my $bitmask_string = CLASS->_parse_params(LIST)
432              
433             Helper method for parsing params passed to various methods.
434              
435             =cut
436              
437             sub _parse_params {
438 77     77   143 my ($class,@params) = @_;
439            
440 77         176 my $result_bitmask = $class->bitmask_empty;
441            
442 77         591 foreach my $param (@params) {
443             next
444 94 100       207 unless defined $param;
445            
446 82         110 my $bitmask;
447 82 100       186 if ( ref $param eq 'ARRAY' ) {
448 4         18 $bitmask = $class->_parse_params(@$param);
449             }
450             else {
451 78         164 $bitmask = $class->any2bitmask($param);
452             }
453              
454 75         180 $result_bitmask = $result_bitmask | $bitmask;
455             }
456              
457 70         133 return $result_bitmask;
458             }
459              
460             # TODO : method to return ordered bitmask items
461              
462             =head2 Overloaded operators
463              
464             Bitmask::Data uses overload by default.
465              
466             =over
467              
468             =item * Numeric context
469              
470             Returns bitmask integer value (see L method). For large bitmasks
471             (> 40 bits) this will always be a L object (hence using this
472             method is not recommended).
473              
474             =item * Scalar context
475              
476             Returns bitmask string representation (see L method)
477              
478             =item * ==, eq, <=>, cmp
479              
480             Works like 'has_any'
481              
482             =item * ~~
483              
484             Works like L.
485              
486             $bm = Somebitmask->new('v1','v2');
487             $bm ~~ ['v1','v3'] # true, because 'v1' matches even if 'v3' is not set
488              
489             =item * +, -
490              
491             Adds/Removes bits to/from the bitmask without changing the current object.
492             The result is returned as a new Bitmask::Data object.
493              
494             =item * -=, +=
495              
496             Adds/Removes bits to/from the current bitmask object.
497              
498             =item * ~, ^, &, |
499              
500             Performs the bitwise operations without changing the current object.
501             The result is returned as a new Bitmask::Data object.
502              
503             =item * ^=, &=, |=
504              
505             Performs the bitwise operations on the current bitmask object.
506              
507             =back
508              
509             =head2 Constructors
510              
511             =head3 new
512              
513             my $bm = MyBitmask->new();
514             my $bm = MyBitmask->new('value1');
515             my $bm = MyBitmask->new('0b00010000010000');
516             my $bm = MyBitmask->new(124);
517             my $bm = MyBitmask->new(0b00010000010000);
518             my $bm = MyBitmask->new(0x2);
519             my $bm = MyBitmask->new($another_bm_object);
520             my $bm = MyBitmask->new("\0\1\0\0\1");
521             my $bm = MyBitmask->new('value2', 'value3');
522             my $bm = MyBitmask->new([32, 'value1', 0b00010000010000]);
523              
524             Create a new bitmask object. You can supply almost any combination of
525             ARRAYREFS, bits, integers, Bitmask::Data objects, Math::BigInt objects,
526             bitmasks and values, even mix different types. See L for details
527             on possible formats.
528              
529             =cut
530              
531             sub new {
532 27     27 1 21231 my ( $class, @args ) = @_;
533              
534             croak('Bitmask not initialized')
535 27 100       47 unless scalar keys %{ $class->bitmask_items };
  27         70  
536              
537 26         252 my $self = $class->new_from_bitmask($class->bitmask_empty);
538              
539 26 100       62 if (scalar @args) {
540 17         37 $self->set( @args );
541             } else {
542 9         48 $self->set( $class->bitmask_default );
543             }
544              
545 26         60 return $self;
546             }
547              
548             =head3 new_from_bitmask
549              
550             my $bm = MyBitmask->new_from_bitmask($bitmask_string);
551              
552             Create a new bitmask object from a bitmask string (as returned by many
553             helper methods).
554              
555             =cut
556              
557             sub new_from_bitmask {
558 35     35 1 226 my ( $class, $bitmask ) = @_;
559            
560 35 100       78 $class = ref($class)
561             if ref($class);
562            
563 35         93 my $self = bless {
564             #cache => undef,
565             bitmask => $bitmask,
566             },$class;
567            
568 35         68 return $self;
569             }
570              
571             =head2 Public Methods
572              
573             =head3 clone
574              
575             my $bm_new = $bm->clone();
576              
577             Clones an existing Bitmask::Data object and returns it.
578              
579             =cut
580              
581             sub clone {
582 6     6 1 11 my ( $self ) = @_;
583            
584 6         15 my $new = $self->new_from_bitmask($self->{bitmask});
585             #$new->{cache} = $self->{cache};
586 6         21 return $new;
587             }
588              
589             =head3 set
590              
591             $bm->set(PARAMS);
592            
593             This method resets the current bitmask and sets the supplied arguments.
594             Takes the same arguments as C.
595              
596             Returns the object.
597              
598             =cut
599              
600             sub set {
601 27     27 1 124 my ( $self, @args ) = @_;
602              
603 27         60 $self->{bitmask} = $self->bitmask_empty;
604 27         581 $self->add( @args );
605              
606 27         42 return $self;
607             }
608              
609             =head3 remove
610              
611             $bm->remove(PARAMS)
612            
613             Removes the given values/bits from the bitmask. Takes the same arguments
614             as C.
615              
616             Returns the object.
617              
618             =cut
619              
620             sub remove {
621 7     7 1 20 my ( $self, @args ) = @_;
622              
623 7         19 my $bitmask = $self->_parse_params(@args);
624              
625 7         23 $self->{bitmask} = $self->{bitmask} ^ ($self->{bitmask} & $bitmask);
626             #$self->{cache} = undef;
627            
628 7         18 return $self;
629             }
630              
631              
632             =head3 add
633              
634             $bm->add(PARAMS)
635            
636             Adds the given values/bits to the bitmask. Takes the same arguments
637             as C.
638              
639             Returns the object.
640              
641             =cut
642              
643             sub add {
644 50     50 1 6388 my ( $self, @args ) = @_;
645              
646 50         121 my $bitmask = $self->_parse_params(@args);
647            
648 44         110 $self->{bitmask} = $self->{bitmask} | $bitmask;
649             #$self->{cache} = undef;
650              
651 44         79 return $self;
652             }
653              
654             =head3 reset
655              
656             $bm->reset()
657            
658             Resets the bitmask to the default (or empty) bitmask.
659              
660             Returns the object.
661              
662             =cut
663              
664             sub reset {
665 3     3 1 416 my ($self) = @_;
666            
667 3   66     12 $self->{bitmask} = $self->bitmask_default || $self->bitmask_empty;
668             #$self->{cache} = undef;
669            
670 3         48 return $self;
671             }
672              
673              
674             =head3 set_all
675              
676             $bm->set_all()
677            
678             Sets all defined bits in the bitmask.
679              
680             Returns the object.
681              
682             =cut
683              
684             sub set_all {
685 3     3 1 11 my ($self) = @_;
686            
687 3         7 $self->{bitmask} = $self->bitmask_full;
688             #$self->{cache} = undef;
689            
690 3         20 return $self;
691             }
692             *setall = \&set_all;
693              
694             =head3 neg
695              
696             $bm->neg()
697            
698             Negates/Inverts the bitmask
699              
700             Returns the object.
701              
702             =cut
703              
704             sub neg {
705 2     2 1 3 my ( $self ) = @_;
706              
707 2         5 $self->{bitmask} =~ tr/\0\1/\1\0/;
708 2         6 $self->{bitmask} = $self->{bitmask} & $self->bitmask_full;
709             #$self->{cache} = undef;
710            
711 2         21 return $self;
712             }
713              
714             =head3 list
715              
716             my @values = $bm->list();
717             OR
718             my $values = $bm->list();
719              
720             In list context, this returns a list of the set values in scalar context,
721             this returns an array reference to the list of values.
722              
723             =cut
724              
725             sub list {
726 26     26 1 53 my ($self) = @_;
727            
728             #return (wantarray ? @{$self->{cache}} : $self->{cache})
729             # if defined $self->{cache};
730            
731 26         46 my @data;
732 26         47 while (my ($value,$bit) = each %{$self->bitmask_items()}) {
  228         1850  
733             push @data,$value
734 202 100       1803 if (($bit & $self->{bitmask}) ne $self->bitmask_empty);
735             }
736            
737             #$self->{cache} = \@data;
738            
739 26 100       278 return wantarray ? @data : \@data;
740             }
741              
742             =head3 length
743              
744             my $length = $bm->length();
745              
746             Number of set bitmask values.
747              
748             =cut
749              
750             sub length {
751 21     21 1 3535 my ($self) = @_;
752            
753 21         54 my @list = $self->list;
754 21         90 return scalar @list;
755             }
756              
757             =head3 first
758              
759             my $value = $bm->first()
760            
761             Returns the first set value. The order is determined by the bit value.
762              
763             =cut
764              
765             sub first {
766 3     3 1 15 my ($self) = @_;
767            
768 3         9 my $bitmask_items = $self->bitmask_items();
769 3         26 foreach my $key (sort { $bitmask_items->{$a} cmp $bitmask_items->{$b} } keys %{$bitmask_items}) {
  63         117  
  3         19  
770             return $key
771 14 100       132 if (($bitmask_items->{$key} & $self->{bitmask}) ne $self->bitmask_empty);
772             }
773 1         16 return;
774             }
775              
776             =head3 integer
777              
778             my $integer = $bm->integer();
779              
780             Returns the bitmask as an integer. For bitmasks with a length > 40 this will
781             always be a L object.
782              
783             =cut
784              
785             *mask = \&integer;
786             sub integer {
787 15     15 1 610 my ($self) = @_;
788            
789 15         30 my $bitmask = $self->{bitmask};
790 15         29 $bitmask =~ tr/\0\1/01/;
791            
792 15 100 66     38 if ($self->bitmask_length > 64 || ($self->bitmask_length > 32 && ! $Config{use64bitint})) {
      66        
793 1         779 require Math::BigInt;
794 1         17282 return Math::BigInt->from_bin("0b".$bitmask);
795             } else {
796 9     9   21347 no warnings 'portable';
  9         27  
  9         4942  
797 14         299 return oct("0b".$bitmask);
798             }
799             }
800              
801             =head3 string
802              
803             my $string = $bm->string();
804              
805             Returns the bitmask as a string of 0 and 1.
806              
807             =cut
808              
809             sub string {
810 33     33 1 671 my ($self) = @_;
811 33         56 my $bitmask = $self->{bitmask};
812 33         56 $bitmask =~ tr/\0\1/01/;
813 33         110 return $bitmask;
814             }
815              
816             =head3 bitmask
817              
818             my $string = $bm->bitmask();
819              
820             Returns the bitmask in the internal representation: A string of \0 and \1
821              
822             =cut
823              
824             sub bitmask {
825 1     1 1 1746 my ($self) = @_;
826 1         5 return $self->{bitmask};
827             }
828              
829             =head3 sqlfilter_all
830              
831             This method can be used for database searches in conjunction with
832             L an POSTGRESQL (SQL::Abstract is used by L for
833             generating searches). The search will find all database rows
834             with bitmask that have at least the given values set. (use
835             the C method for an exact match)
836              
837             Example how to use sqlfilter with SQL::Abstract:
838              
839             my($stmt, @bind) = $sql->select(
840             'mytable',
841             \@fields,
842             {
843             $bm->sqlfilter_all('mytable.bitmaskfield'),
844             }
845             );
846              
847             Example how to use sqlfilter with DBIx::Class:
848            
849             my $list = $resultset->search(
850             {
851             $bm->sqlfilter_all('me.bitmaskfield'),
852             },
853             );
854              
855              
856             =cut
857              
858             sub sqlfilter_all {
859 1     1 1 3 my ( $self, $field ) = @_;
860              
861 1         3 my $sql_mask = $self->string();
862 1         3 my $format = "bitand( $field, B'$sql_mask' )";
863 1         4 return ( $format, \" = B'$sql_mask'" );
864             }
865             *sqlfilter = \&sqlfilter_all;
866              
867             =head3 sqlfilter_any
868              
869             Works like C but checks for any bit matching
870              
871             =cut
872              
873             sub sqlfilter_any {
874 1     1 1 830 my ( $self, $field ) = @_;
875              
876 1         2 my $sql_mask = $self->string();
877 1         3 my $format = "bitand( $field, B'$sql_mask' )";
878 1         3 my $empty_mask = $self->bitmask_empty;
879 1         7 $empty_mask =~ tr/\0\1/01/;
880 1         4 return ( $format, \" <> B'$empty_mask'" );
881             }
882              
883             =head3 sqlstring
884              
885             Returns the bitmask as a quoted string as needed by PostgreSQL:
886              
887             B'0000000000000001'::bit(16)
888              
889             =cut
890              
891             sub sqlstring {
892 1     1 1 793 my ( $self ) = @_;
893 1         3 return sprintf("B'%s'::bit(%i)",$self->string,$self->bitmask_length);
894             }
895              
896             =head3 has_all
897              
898             if ($bm->has_all(PARAMS)) {
899             # Do something
900             }
901              
902             Checks if all requestes bits/values are set and returns true or false.
903             This method takes the same arguments as C.
904              
905             =cut
906              
907             sub has_all {
908 4     4 1 17 my ( $self, @args ) = @_;
909              
910 4         9 my $bitmask = $self->_parse_params(@args);
911            
912 4 100       20 return (($bitmask & $self->{bitmask}) eq $bitmask) ? 1:0;
913             }
914             *hasall = \&has_all;
915              
916             =head3 has_exact
917              
918             if ($bm->has_exact(PARAMS)) {
919             # Do something
920             }
921              
922             Checks if the set bits/values excactly match the supplied bits/values and
923             returns true or false.
924             This method takes the same arguments as C.
925              
926             =cut
927              
928             sub has_exact {
929 6     6 1 13 my ( $self, @args ) = @_;
930              
931 6         13 my $bitmask = $self->_parse_params(@args);
932              
933 6 100       27 return ($bitmask eq $self->{bitmask}) ? 1:0;
934             }
935             *hasexact = \&has_exact;
936              
937             =head3 has_any
938              
939             if ($bm->has_any(PARAMS)) {
940             # Do something
941             }
942              
943             Checks if at least one set value/bit matches the supplied bits/values and
944             returns true or false.
945             This method takes the same arguments as C.
946              
947             =cut
948              
949             sub has_any {
950 6     6 1 20 my ( $self, @args ) = @_;
951              
952 6         16 my $bitmask = $self->_parse_params(@args);
953            
954 6 100       21 return (($bitmask & $self->{bitmask}) ne $self->bitmask_empty) ? 1:0;
955             }
956             *hasany = \&has_any;
957              
958             1;
959              
960             =head1 CAVEATS
961              
962             Since Bitmask::Data is very liberal with input data you cannot use numbers
963             as bitmask values. (It would think that you are supplying an integer
964             bitmask and not a value)
965              
966             Bitmask::Data adds a considerable processing overhead to bitmask
967             manipulations. If you either don't need the extra comfort or use
968             bitmasks with less that 32 bits that you should consider using just the perl
969             built in bit operators on simple integer values.
970              
971             =head1 SUBCLASSING
972              
973             Bitmask::Data was designed to be subclassed.
974            
975             package MyBitmask;
976             use parent qw(Bitmask::Data);
977             __PACKAGE__->bitmask_length(20); # Default length is 16
978             __PACKAGE__->init(
979             'value1' => 0b000000000000000001,
980             'value2' => 0x2,
981             'value2' => 4,
982             'value4', # lazy initlialization
983             'value5', # lazy initlialization
984             );
985              
986             =head1 WORKING WITH DATABASES
987              
988             This module comes with support for PostgreSQL databases (patches for other
989             database vendors are welcome).
990              
991             First you need to create the correct column types:
992              
993             CREATE TABLE bitmaskexample (
994             id integer DEFAULT nextval('pkey_seq'::regclass) NOT NULL,
995             bitmask bit(14),
996             otherfields character varying
997             );
998              
999             The length of the bitmask field must match Cbitmask_length>.
1000              
1001             This module provides three convenient methods to work with databases:
1002              
1003             =over
1004              
1005             =item * L: Search for matching bitmasks
1006              
1007             =item * L: Search for bitmasks with matching bits
1008              
1009             =item * L: Print the bitmask string as used by the database
1010              
1011             =back
1012              
1013             If you are working with l you might also install in- and
1014             deflators for Bitmask::Data objects:
1015              
1016             __PACKAGE__->inflate_column('fieldname',{
1017             inflate => sub {
1018             my $value = shift;
1019             return MyBitmask->new($value);
1020             },
1021             deflate => sub {
1022             my $value = shift;
1023             undef $value
1024             unless ref($value) && $value->isa('MyBitmask');
1025             $value //= MyBitmask->new();
1026             return $value->string;
1027             },
1028             });
1029              
1030             =head1 SUPPORT
1031              
1032             Please report any bugs or feature requests to
1033             C, or through the web interface at
1034             L.
1035             I will be notified and then you'll automatically be notified of the progress
1036             on your report as I make changes.
1037              
1038             =head1 AUTHOR
1039              
1040             Klaus Ita
1041             koki [at] worstofall.com
1042              
1043             Maroš Kollár
1044             CPAN ID: MAROS
1045             maros [at] k-1.com
1046            
1047             L
1048              
1049             =head1 ACKNOWLEDGEMENTS
1050              
1051             This module was originally written by Klaus Ita (Koki) for Revdev
1052             L, a nice litte software company I (Maros) run with
1053             Koki and Domm (L).
1054              
1055             =head1 COPYRIGHT & LICENSE
1056              
1057             Bitmask::Data is Copyright (c) 2008 Klaus Ita, Maroš Kollár
1058             - L
1059              
1060             This program is free software; you can redistribute it and/or modify it under
1061             the same terms as Perl itself.
1062              
1063             The full text of the license can be found in the
1064             LICENSE file included with this module.
1065              
1066             =cut