File Coverage

File:Dpkg/Control/HashCore/Tie.pm
Coverage:91.9%

linestmtbrancondsubpodtimecode
1# Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org>
2# Copyright © 2009, 2012-2019, 2021 Guillem Jover <guillem@debian.org>
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17=encoding utf8
18
19 - 35
=head1 NAME

Dpkg::Control::HashCore::Tie - ties a Dpkg::Control::Hash object

=head1 DESCRIPTION

This module provides a class that is used to tie a hash.
It implements hash-like functions by normalizing the name of fields received
in keys (using Dpkg::Control::Fields::field_capitalize()).
It also stores the order in which fields have been added in order to be able
to dump them in the same order.
But the order information is stored in a parent object of type
L<Dpkg::Control>.

B<Note>: This is a private module, its API can change at any time.

=cut
36
37package Dpkg::Control::HashCore::Tie 0.01;
38
39
138
138
138
495
135
2199
use strict;
40
138
138
138
454
151
3265
use warnings;
41
42
138
138
138
262
105
6302
use Dpkg::Control::FieldsCore;
43
44
138
138
138
291
94
3298
use Carp;
45
138
138
138
272
104
3100
use Tie::Hash;
46
138
138
138
313
111
486
use parent -norequire, qw(Tie::ExtraHash);
47
48# $self->[0] is the real hash
49# $self->[1] is a reference to the hash contained by the parent object.
50# This reference bypasses the top-level scalar reference of a
51# Dpkg::Control::Hash, hence ensuring that reference gets DESTROYed
52# properly.
53
54 - 63
=head1 FUNCTIONS

=over 4

=item Dpkg::Control::Hash->new($parent)

Return a reference to a tied hash implementing storage of simple
"field: value" mapping as used in many Debian-specific files.

=cut
64
65sub new {
66
2676
1
2664
    my ($class, @args) = @_;
67
2676
2013
    my $hash = {};
68
69
2676
2676
1728
4365
    tie %{$hash}, $class, @args; ## no critic (Miscellanea::ProhibitTies)
70
2676
4442
    return $hash;
71}
72
73sub TIEHASH  {
74
2676
2486
    my ($class, $parent) = @_;
75
76
2676
5613
    croak 'parent object must be Dpkg::Control::Hash'
77        if not $parent->isa('Dpkg::Control::HashCore') and
78           not $parent->isa('Dpkg::Control::Hash');
79
2676
7610
    return bless [ {}, $$parent ], $class;
80}
81
82sub FETCH {
83
14169
10838
    my ($self, $key) = @_;
84
85
14169
9193
    $key = lc($key);
86
14169
33432
    return $self->[0]->{$key} if exists $self->[0]->{$key};
87
39
78
    return;
88}
89
90sub STORE {
91
19101
19715
    my ($self, $key, $value) = @_;
92
93
19101
12238
    $key = lc($key);
94
19101
18165
    if (not exists $self->[0]->{$key}) {
95
15030
15030
8381
15595
        push @{$self->[1]->{in_order}}, field_capitalize($key);
96    }
97
19101
26572
    $self->[0]->{$key} = $value;
98}
99
100sub EXISTS {
101
7383
5801
    my ($self, $key) = @_;
102
103
7383
5074
    $key = lc($key);
104
7383
12315
    return exists $self->[0]->{$key};
105}
106
107sub DELETE {
108
3
7
    my ($self, $key) = @_;
109
3
8
    my $parent = $self->[1];
110
3
5
    my $in_order = $parent->{in_order};
111
112
3
4
    $key = lc($key);
113
3
6
    if (exists $self->[0]->{$key}) {
114
3
3
        delete $self->[0]->{$key};
115
3
3
9
3
3
3
175
4
        @{$in_order} = grep { lc ne $key } @{$in_order};
116
3
266
        return 1;
117    } else {
118
0
0
        return 0;
119    }
120}
121
122sub FIRSTKEY {
123
2292
1559
    my $self = shift;
124
2292
1699
    my $parent = $self->[1];
125
126
2292
2292
1424
2566
    foreach my $key (@{$parent->{in_order}}) {
127
2292
5190
        return $key if exists $self->[0]->{lc $key};
128    }
129}
130
131sub NEXTKEY {
132
4239
3283
    my ($self, $prev) = @_;
133
4239
2595
    my $parent = $self->[1];
134
4239
2466
    my $found = 0;
135
136
4239
4239
2451
3334
    foreach my $key (@{$parent->{in_order}}) {
137
9210
6236
        if ($found) {
138
1947
3794
            return $key if exists $self->[0]->{lc $key};
139        } else {
140
7263
6760
            $found = 1 if $key eq $prev;
141        }
142    }
143
2292
2956
    return;
144}
145
146=back
147
148 - 154
=head1 CHANGES

=head2 Version 0.xx

This is a private module.

=cut
155
1561;