Query.pm 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. # Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License 2.0 (the "License"). You may not use
  4. # this file except in compliance with the License. You can obtain a copy
  5. # in the file LICENSE in the source distribution or at
  6. # https://www.openssl.org/source/license.html
  7. package OpenSSL::Config::Query;
  8. use 5.10.0;
  9. use strict;
  10. use warnings;
  11. use Carp;
  12. =head1 NAME
  13. OpenSSL::Config::Query - Query OpenSSL configuration info
  14. =head1 SYNOPSIS
  15. use OpenSSL::Config::Info;
  16. my $query = OpenSSL::Config::Query->new(info => \%unified_info);
  17. # Query for something that's expected to give a scalar back
  18. my $variable = $query->method(... args ...);
  19. # Query for something that's expected to give a list back
  20. my @variable = $query->method(... args ...);
  21. =head1 DESCRIPTION
  22. The unified info structure, commonly known as the %unified_info table, has
  23. become quite complex, and a bit overwhelming to look through directly. This
  24. module makes querying this structure simpler, through diverse methods.
  25. =head2 Constructor
  26. =over 4
  27. =item B<new> I<%options>
  28. Creates an instance of the B<OpenSSL::Config::Query> class. It takes options
  29. in keyed pair form, i.e. a series of C<< key => value >> pairs. Available
  30. options are:
  31. =over 4
  32. =item B<info> =E<gt> I<HASHREF>
  33. A reference to a unified information hash table, most commonly known as
  34. %unified_info.
  35. =item B<config> =E<gt> I<HASHREF>
  36. A reference to a config information hash table, most commonly known as
  37. %config.
  38. =back
  39. Example:
  40. my $info = OpenSSL::Config::Info->new(info => \%unified_info);
  41. =back
  42. =cut
  43. sub new {
  44. my $class = shift;
  45. my %opts = @_;
  46. my @messages = _check_accepted_options(\%opts,
  47. info => 'HASH',
  48. config => 'HASH');
  49. croak $messages[0] if @messages;
  50. # We make a shallow copy of the input structure. We might make
  51. # a different choice in the future...
  52. my $instance = { info => $opts{info} // {},
  53. config => $opts{config} // {} };
  54. bless $instance, $class;
  55. return $instance;
  56. }
  57. =head2 Query methods
  58. =over 4
  59. =item B<get_sources> I<LIST>
  60. LIST is expected to be the collection of names of end products, such as
  61. programs, modules, libraries.
  62. The returned result is a hash table reference, with each key being one of
  63. these end product names, and its value being a reference to an array of
  64. source file names that constitutes everything that will or may become part
  65. of that end product.
  66. =cut
  67. sub get_sources {
  68. my $self = shift;
  69. my $result = {};
  70. foreach (@_) {
  71. my @sources = @{$self->{info}->{sources}->{$_} // []};
  72. my @staticlibs =
  73. grep { $_ =~ m|\.a$| } @{$self->{info}->{depends}->{$_} // []};
  74. my %parts = ( %{$self->get_sources(@sources)},
  75. %{$self->get_sources(@staticlibs)} );
  76. my @parts = map { @{$_} } values %parts;
  77. my @generator =
  78. ( ( $self->{info}->{generate}->{$_} // [] ) -> [0] // () );
  79. my %generator_parts = %{$self->get_sources(@generator)};
  80. # if there are any generator parts, we ignore it, because that means
  81. # it's a compiled program and thus NOT part of the source that's
  82. # queried.
  83. @generator = () if %generator_parts;
  84. my @partial_result =
  85. ( ( map { @{$_} } values %parts ),
  86. ( grep { !defined($parts{$_}) } @sources, @generator ) );
  87. # Push conditionally, to avoid creating $result->{$_} with an empty
  88. # value
  89. push @{$result->{$_}}, @partial_result if @partial_result;
  90. }
  91. return $result;
  92. }
  93. =item B<get_config> I<LIST>
  94. LIST is expected to be the collection of names of configuration data, such
  95. as build_infos, sourcedir, ...
  96. The returned result is a hash table reference, with each key being one of
  97. these configuration data names, and its value being a reference to the value
  98. corresponding to that name.
  99. =cut
  100. sub get_config {
  101. my $self = shift;
  102. return { map { $_ => $self->{config}->{$_} } @_ };
  103. }
  104. ########
  105. #
  106. # Helper functions
  107. #
  108. sub _check_accepted_options {
  109. my $opts = shift; # HASH reference (hopefully)
  110. my %conds = @_; # key => type
  111. my @messages;
  112. my %optnames = map { $_ => 1 } keys %$opts;
  113. foreach (keys %conds) {
  114. delete $optnames{$_};
  115. }
  116. push @messages, "Unknown options: " . join(', ', sort keys %optnames)
  117. if keys %optnames;
  118. foreach (sort keys %conds) {
  119. push @messages, "'$_' value not a $conds{$_} reference"
  120. if (defined $conds{$_} && defined $opts->{$_}
  121. && ref $opts->{$_} ne $conds{$_});
  122. }
  123. return @messages;
  124. }
  125. 1;