GDPR-IAB-TCFv2
view release on metacpan or search on metacpan
lib/GDPR/IAB/TCFv2/BitField.pm view on Meta::CPAN
croak "missing 'options'" unless defined $args{options};
croak "missing 'options.json'" unless defined $args{options}->{json};
my $data = $args{data};
my $data_size = $args{data_size};
my $offset = $args{offset} // 0;
my $max_id = $args{max_id};
my $options = $args{options};
croak
"a BitField for $max_id bits requires a consent string of at least @{[ $offset + $max_id ]} bits. This consent string only had @{[ $data_size << 3 ]} bits"
if $offset + $max_id > ($data_size << 3);
my $self = {data => $data, offset => $offset, max_id => $max_id, options => $options,};
bless $self, $klass;
return ($self, $offset + $max_id);
}
sub max_id {
my $self = shift;
return $self->{max_id};
}
sub contains {
my ($self, $id) = @_;
croak "invalid vendor id $id: must be positive integer bigger than 0" if $id < 1;
return if $id > $self->{max_id};
return is_set($self->{data}, $self->{offset} + $id - 1);
}
sub all {
my $self = shift;
my $bitstring = unpack("B*", substr($self->{data}, $self->{offset} >> 3));
$bitstring = substr($bitstring, $self->{offset} & 7, $self->{max_id});
my @set_bits;
while ($bitstring =~ /1/g) {
push @set_bits, pos($bitstring);
}
return \@set_bits;
}
sub TO_JSON {
my ($self, $filter_id) = @_;
if (defined $filter_id) {
my $val = $self->contains($filter_id);
if (!!$self->{options}->{json}->{compact}) {
return $val ? [$filter_id] : [];
}
my ($false, $true) = @{$self->{options}->{json}->{boolean_values}};
my $bool_val = $val ? $true : $false;
if (!!$self->{options}->{json}->{verbose}) {
return {$filter_id => $bool_val};
}
return $val ? {$filter_id => $true} : {};
}
if (!!$self->{options}->{json}->{compact}) {
return $self->all;
}
my $bitstring = unpack("B*", substr($self->{data}, $self->{offset} >> 3));
$bitstring = substr($bitstring, $self->{offset} & 7, $self->{max_id});
my ($false, $true) = @{$self->{options}->{json}->{boolean_values}};
if (!!$self->{options}->{json}->{verbose}) {
my %map = map { $_ => $false } 1 .. $self->{max_id};
while ($bitstring =~ /1/g) {
$map{pos($bitstring)} = $true;
}
return \%map;
}
my %map;
while ($bitstring =~ /1/g) {
$map{pos($bitstring)} = $true;
}
return \%map;
}
1;
__END__
=head1 NAME
GDPR::IAB::TCFv2::BitField - TCF v2.3 bitfield parser
=head1 SYNOPSIS
use GDPR::IAB::TCFv2::BitField;
my $data = '...'; # raw binary data
my $max_id_consent = 100;
my ($bit_field) = GDPR::IAB::TCFv2::BitField->Parse(
data => $data,
data_size => length($data),
max_id => $max_id_consent,
options => { json => {} },
);
if ($bit_field->contains(284)) {
# ...
}
=head1 CONSTRUCTOR
Constructor C<Parse> receives a hash of 5 parameters:
=over
=item *
Key C<data> is the binary data
=item *
Key C<data_size> is the original binary data size
=item *
Key C<offset> is the bit offset. Optional (defaults to 0).
=item *
( run in 0.611 second using v1.01-cache-2.11-cpan-acf6aa7dc9e )