1/*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15// Autogenerated file -- DO NOT EDIT!
16
17#ifndef PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H
18#define PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H
19
20#include "utils/pandargs.h"
21#include "macros.h"
22
23#include <optional>
24#include <string>
25#include <unordered_set>
26#include <vector>
27
28namespace <%= Common::module.namespace %> {
29// NOLINTBEGIN(readability-identifier-naming)
30class PANDA_PUBLIC_API Options {
31public:
32    class Error {
33    public:
34        explicit Error(std::string msg) : msg_(std::move(msg)) {}
35
36        std::string GetMessage() {
37            return msg_;
38        }
39    private:
40        std::string msg_;
41    };
42
43    explicit Options(const std::string &exe_path) : exe_dir_(GetExeDir(exe_path)) {}
44
45    // NOLINTBEGIN(readability-function-size)
46    void AddOptions(PandArgParser *parser) {
47        parser->Add(&version_);
48% Common::options.each do |op|
49%   next if op.sub_option?
50%   next if op.deprecated?
51        parser->Add(&<%= op.field_name %>);
52% end
53    }
54    // NOLINTEND(readability-function-size)
55
56    bool IsVersion() const {
57        return version_.GetValue();
58    }
59
60    void SetVersion(bool value) {
61        version_.SetValue(value);
62    }
63
64    bool WasSetVersion() {
65        return version_.WasSet();
66    }
67
68% Common::options.each do |op|
69%   if !op.lang_specific? && !op.has_lang_suboptions?
70    <%= op.type %> <%= op.getter_name %>([[maybe_unused]] std::string_view lang = "") const {
71%   if op.deprecated?
72        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
73%   end
74        return <%= op.field_name %>.GetValue();
75    }
76
77    void <%= op.setter_name %>(<%= op.type %> value) {
78%   if op.deprecated?
79        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
80%   end
81        <%= op.field_name %>.SetValue(<%= op.type == 'std::string' || op.type == 'arg_list_t' ? 'std::move(value)' : 'value' %>);
82    }
83
84    bool WasSet<%= op.camel_name %>([[maybe_unused]] std::string_view lang = "") const {
85%   if op.deprecated?
86        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
87%   end
88        return <%= op.field_name %>.WasSet();
89    }
90%   end
91%   if op.has_lang_suboptions?
92    <%= op.type %> <%= op.getter_name %>(std::string_view lang) const {
93%   if op.deprecated?
94        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
95%   end
96%     op.lang.each do |lang|
97        if (lang == "<%= "#{lang}" %>") {
98            return WasSet<%= op.lang_camel_name(lang) %>() ? <%= op.lang_field_name(lang) %>.GetValue() : <%= op.field_name %>.GetValue();
99        }
100%     end
101        return <%= op.field_name %>.GetValue();
102    }
103
104    void <%= op.setter_name %>(<%= op.type %> value) {
105%   if op.deprecated?
106        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
107%   end
108        <%= op.field_name %>.SetValue(<%= op.type == 'std::string' || op.type == 'arg_list_t' ? 'std::move(value)' : 'value' %>);
109    }
110
111    bool WasSet<%= op.camel_name %>(std::string_view lang) const {
112%   if op.deprecated?
113        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
114%   end
115%     op.lang.each do |lang|
116        if (lang == "<%= "#{lang}" %>") {
117            return <%= op.lang_field_name(lang) %>.WasSet();
118        }
119%     end
120        return <%= op.field_name %>.WasSet();
121    }
122%   end
123% end
124// NOLINTNEXTLINE(readability-function-size)
125    std::optional<Error> Validate() const {
126% Common::options.each do |op|
127%   next unless defined? op.possible_values
128%   is_string = op.type == 'std::string' || op.type == 'arg_list_t'
129%   possible_values = op.possible_values.map { |e| is_string ? Common::to_raw(e) : e }.join(', ')
130        {
131            std::unordered_set<<%= is_string ? "std::string" : op.type %>> possible_values{<%= possible_values %>};
132%   if op.type != 'arg_list_t'
133            std::vector<<%= op.type %>> values{<%= op.field_name %>.GetValue()};
134%   else
135            const auto &values = <%= op.field_name %>.GetValue();
136%   end
137            for (const auto &value : values) {
138                if (possible_values.find(value) == possible_values.cend()) {
139                    return Error("argument --<%= op.name %>: invalid value: '" + <%= is_string ? "value" : "std::to_string(value)" %> + \
140                                 R"('. Possible values: <%= op.possible_values %>)");
141                }
142            }
143        }
144% end
145        return {};
146    }
147
148private:
149% Common::options.each do |op|
150%   if op.lang_specific?
151    bool WasSet<%= op.camel_name %>() const {
152%   if op.deprecated?
153        std::cerr << "WARNING: Option '<%= op.name %>' is deprecated and should not be used\n";
154%   end
155        return <%= op.field_name %>.WasSet();
156    }
157%   end
158% end
159
160    static std::string GetExeDir(const std::string &exe_path) {
161        auto pos = exe_path.find_last_of('/');
162        return exe_path.substr(0, pos);
163    }
164
165% Common::options.each do |op|
166%   next unless op.need_default_constant
167    static constexpr <%= op.type %> <%= op.default_constant_name %> = <%= op.default %>;
168
169% end
170    std::string exe_dir_;
171    PandArg<bool> version_{"version", false, R"(Ark version, file format version and minimum supported file format version)"};
172% Common::options.each do |op|
173% if defined? op.delimiter
174    PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>, "<%= op.delimiter %>"};
175% elsif defined? op.range
176%   min, max = op.range.match('(\d+)\D*(\d+)').captures;
177%   if op.default.to_i > max.to_i || op.default.to_i < min.to_i
178%     abort "FAILED: Default value of argument " + op.name + " has out of range default parameter"
179%   end
180    PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>, <%= min.to_i %>, <%= max.to_i %>};
181% elsif op.has_sub_options
182    PandArgCompound <%= op.field_name %>{"<%= op.name %>", <%= op.full_description %>, {<%= op.sub_options.map{|o| '&' + o.field_name}.join(', ') %>}};
183% else
184    PandArg<<%= op.type %>> <%= op.field_name %>{"<%= op.name %>", <%= op.default_value %>, <%= op.full_description %>};
185% end
186% end
187};
188// NOLINTEND(readability-identifier-naming)
189}  // namespace <%= Common::module.namespace %>
190
191#endif  // PANDA_<%= Common::module.name.upcase %>_OPTIONS_GEN_H
192