Fields.pm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package Dpkg::Fields;
  2. use strict;
  3. use warnings;
  4. use Exporter;
  5. our @ISA = qw(Exporter);
  6. our @EXPORT_OK = qw(capit set_field_importance sort_field_by_importance);
  7. sub capit {
  8. my @pieces = map { ucfirst(lc) } split /-/, $_[0];
  9. return join '-', @pieces;
  10. }
  11. my %fieldimps;
  12. sub set_field_importance(@)
  13. {
  14. my @fields = @_;
  15. my $i = 1;
  16. grep($fieldimps{$_} = $i++, @fields);
  17. }
  18. sub sort_field_by_importance($$)
  19. {
  20. my ($a, $b) = @_;
  21. if (defined $fieldimps{$a} && defined $fieldimps{$b}) {
  22. $fieldimps{$a} <=> $fieldimps{$b};
  23. } elsif (defined($fieldimps{$a})) {
  24. -1;
  25. } elsif (defined($fieldimps{$b})) {
  26. 1;
  27. } else {
  28. $a cmp $b;
  29. }
  30. }
  31. package Dpkg::Fields::Object;
  32. =head1 OTHER OBJECTS
  33. =head2 Dpkg::Fields::Object
  34. This object is used to tie a hash. It implements hash-like functions by
  35. normalizing the name of fields received in keys (using
  36. Dpkg::Fields::capit). It also stores the order in which fields have been
  37. added in order to be able to dump them in the same order.
  38. You can also dump the content of the hash with tied(%hash)->dump($fh).
  39. =cut
  40. use Tie::Hash;
  41. our @ISA = qw(Tie::ExtraHash Tie::Hash);
  42. use Dpkg::ErrorHandling qw(internerr syserr);
  43. # Import capit
  44. Dpkg::Fields->import('capit', 'sort_field_by_importance');
  45. # $self->[0] is the real hash
  46. # $self->[1] is an array containing the ordered list of keys
  47. =head2 Dpkg::Fields::Object->new()
  48. Return a reference to a tied hash implementing storage of simple
  49. "field: value" mapping as used in many Debian-specific files.
  50. =cut
  51. sub new {
  52. my $hash = {};
  53. tie %{$hash}, 'Dpkg::Fields::Object';
  54. return $hash;
  55. }
  56. sub TIEHASH {
  57. my $class = shift;
  58. return bless [{}, []], $class;
  59. }
  60. sub FETCH {
  61. my ($self, $key) = @_;
  62. $key = capit($key);
  63. return $self->[0]->{$key} if exists $self->[0]->{$key};
  64. return undef;
  65. }
  66. sub STORE {
  67. my ($self, $key, $value) = @_;
  68. $key = capit($key);
  69. if (not exists $self->[0]->{$key}) {
  70. push @{$self->[1]}, $key;
  71. }
  72. $self->[0]->{$key} = $value;
  73. }
  74. sub EXISTS {
  75. my ($self, $key) = @_;
  76. $key = capit($key);
  77. return exists $self->[0]->{$key};
  78. }
  79. sub DELETE {
  80. my ($self, $key) = @_;
  81. $key = capit($key);
  82. if (exists $self->[0]->{$key}) {
  83. delete $self->[0]->{$key};
  84. @{$self->[1]} = grep { $_ ne $key } @{$self->[1]};
  85. return 1;
  86. } else {
  87. return 0;
  88. }
  89. }
  90. sub FIRSTKEY {
  91. my $self = shift;
  92. foreach (@{$self->[1]}) {
  93. return $_ if exists $self->[0]->{$_};
  94. }
  95. }
  96. sub NEXTKEY {
  97. my ($self, $last) = @_;
  98. my $found = 0;
  99. foreach (@{$self->[1]}) {
  100. if ($found) {
  101. return $_ if exists $self->[0]->{$_};
  102. } else {
  103. $found = 1 if $_ eq $last;
  104. }
  105. }
  106. return undef;
  107. }
  108. sub dump {
  109. my ($self, $fh) = @_;
  110. foreach (@{$self->[1]}) {
  111. if (exists $self->[0]->{$_}) {
  112. print $fh "$_: " . $self->[0]->{$_} . "\n";
  113. }
  114. }
  115. }
  116. sub output {
  117. my ($self, $fh, $substvars) = @_;
  118. # Add substvars to refer to other fields
  119. if (defined($substvars)) {
  120. foreach my $f (keys %{$self->[0]}) {
  121. $substvars->set("F:$f", $self->[0]->{$f});
  122. }
  123. }
  124. for my $f (sort sort_field_by_importance keys %{$self->[0]}) {
  125. my $v = $self->[0]->{$f};
  126. if (defined($substvars)) {
  127. $v = $substvars->substvars($v);
  128. }
  129. $v =~ m/\S/ || next; # delete whitespace-only fields
  130. $v =~ m/\n\S/ &&
  131. internerr(_g("field %s has newline then non whitespace >%s<"),
  132. $f, $v);
  133. $v =~ m/\n[ \t]*\n/ &&
  134. internerr(_g("field %s has blank lines >%s<"), $f, $v);
  135. $v =~ m/\n$/ &&
  136. internerr(_g("field %s has trailing newline >%s<"), $f, $v);
  137. if (defined($substvars)) {
  138. $v =~ s/,[\s,]*,/,/g;
  139. $v =~ s/^\s*,\s*//;
  140. $v =~ s/\s*,\s*$//;
  141. }
  142. $v =~ s/\$\{\}/\$/g;
  143. print $fh "$f: $v\n" || syserr(_g("write error on control data"));
  144. }
  145. }
  146. 1;