1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
# Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org>
# Copyright © 2009, 2012-2019, 2021 Guillem Jover <guillem@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
=encoding utf8
=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
package Dpkg::Control::HashCore::Tie 0.01;
use v5.36;
use Dpkg::Control::FieldsCore;
use Carp;
use Tie::Hash;
use parent -norequire, qw(Tie::ExtraHash);
# The class is implemented as an array ref with:
# - $self->[0] is the real hash
# - $self->[1] is a reference to the hash contained by the parent object
# This reference bypasses the top-level scalar reference of a
# Dpkg::Control::Hash, hence ensuring that reference gets DESTROYed
# properly.
=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
sub new {
my ($class, @args) = @_;
my $hash = {};
tie %{$hash}, $class, @args; ## no critic (Miscellanea::ProhibitTies)
return $hash;
}
sub TIEHASH {
my ($class, $parent) = @_;
croak 'parent object must be Dpkg::Control::Hash'
if not $parent->isa('Dpkg::Control::HashCore') and
not $parent->isa('Dpkg::Control::Hash');
return bless [ {}, $$parent ], $class;
}
sub FETCH {
my ($self, $key) = @_;
$key = lc($key);
return $self->[0]->{$key} if exists $self->[0]->{$key};
return;
}
sub STORE {
my ($self, $key, $value) = @_;
$key = lc($key);
if (not exists $self->[0]->{$key}) {
push @{$self->[1]->{in_order}}, field_capitalize($key);
}
$self->[0]->{$key} = $value;
}
sub EXISTS {
my ($self, $key) = @_;
$key = lc($key);
return exists $self->[0]->{$key};
}
sub DELETE {
my ($self, $key) = @_;
my $parent = $self->[1];
my $in_order = $parent->{in_order};
$key = lc($key);
if (exists $self->[0]->{$key}) {
delete $self->[0]->{$key};
@{$in_order} = grep { lc ne $key } @{$in_order};
return 1;
} else {
return 0;
}
}
sub FIRSTKEY {
my $self = shift;
my $parent = $self->[1];
foreach my $key (@{$parent->{in_order}}) {
return $key if exists $self->[0]->{lc $key};
}
}
sub NEXTKEY {
my ($self, $prev) = @_;
my $parent = $self->[1];
my $found = 0;
foreach my $key (@{$parent->{in_order}}) {
if ($found) {
return $key if exists $self->[0]->{lc $key};
} else {
$found = 1 if $key eq $prev;
}
}
return;
}
=back
=head1 CHANGES
=head2 Version 0.xx
This is a private module.
=cut
1;
|