1 /**
2 * Copyright (c) 2021-2022 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
16 #include "util/tests/environment.h"
17
18 #include "util/parser/parser.h"
19
20 #include <cstring>
21
22 namespace panda::verifier::test {
23
EnvOptions(const char * env_var_name)24 EnvOptions::EnvOptions(const char *env_var_name)
25 {
26 using panda::parser::action;
27 using panda::parser::charset;
28 using panda::parser::parser;
29
30 struct Context {
31 std::string name;
32 OptionValue value;
33 };
34
35 using par = parser<Context, const char, const char *>::next<EnvOptions>;
36
37 static const auto WS = par::of_charset(" \t\r\n"); // NOLINT(readability-static-accessed-through-instance)
38 static const auto DELIM = par::of_string(";"); // NOLINT(readability-static-accessed-through-instance)
39 static const auto NAME_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
40 if (a == action::PARSED) {
41 c.name = std::string {s, e};
42 }
43 return true;
44 };
45 static const auto NAME =
46 WS.of_charset("abcdefghijklmnopqrstuvwxyz_") // NOLINT(readability-static-accessed-through-instance)
47 |= NAME_HANDLER;
48 static const auto EQ = NAME.of_string("="); // NOLINT(readability-static-accessed-through-instance)
49 static const auto BOOL_TRUE = EQ.of_string("true"); // NOLINT(readability-static-accessed-through-instance)
50 static const auto BOOL_FALSE =
51 BOOL_TRUE.of_string("false"); // NOLINT(readability-static-accessed-through-instance)
52 static const auto BOOL_HANDLER = [](auto a, Context &c, auto s, [[maybe_unused]] auto to,
53 [[maybe_unused]] auto end) {
54 if (a == action::PARSED) {
55 if (*s == 'f') {
56 c.value = false;
57 } else {
58 c.value = true;
59 }
60 }
61 return true;
62 };
63 static const auto BOOL = BOOL_FALSE | BOOL_TRUE |= BOOL_HANDLER;
64 static const auto DEC = BOOL.of_charset("0123456789"); // NOLINT(readability-static-accessed-through-instance)
65 static const auto HEX = DEC.of_string("0x") >> DEC; // NOLINT(readability-static-accessed-through-instance)
66 static const auto NUM_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
67 if (a == action::PARSED) {
68 c.value = std::stoi(std::string {s, e}, nullptr, 0);
69 }
70 return true;
71 };
72 static const auto NUM = HEX | DEC |= NUM_HANDLER;
73 static const auto QUOTES = HEX.of_string("\""); // NOLINT(readability-static-accessed-through-instance)
74 static const auto NON_QUOTES =
75 QUOTES.of_charset(!charset("\"")); // NOLINT(readability-static-accessed-through-instance)
76 static const auto STRING_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
77 if (a == action::PARSED) {
78 c.value = std::string {s, e};
79 }
80 return true;
81 };
82 static const auto STRING = QUOTES >> (*NON_QUOTES |= STRING_HANDLER) >> QUOTES;
83
84 static const auto VALUE = STRING | NUM | BOOL;
85
86 static const auto KV_PAIR_HANDLER = [this](auto a, Context &c, [[maybe_unused]] auto f, [[maybe_unused]] auto t,
87 [[maybe_unused]] auto e) {
88 if (a == action::PARSED) {
89 Options_[c.name] = c.value;
90 }
91 return true;
92 };
93
94 static const auto KV_PAIR = ~WS >> NAME >> ~WS >> EQ >> ~WS >> VALUE >> ~WS >> DELIM |= KV_PAIR_HANDLER;
95 static const auto OPTIONS = *KV_PAIR;
96
97 const char *s = std::getenv(env_var_name);
98 if (s == nullptr) {
99 return;
100 }
101
102 Context c;
103
104 if (!OPTIONS(c, s, s + strlen(s))) { // NOLINT
105 // TODO(vdyadov): warning that some options were not parsed
106 }
107 }
108
operator [](const std::string & name) const109 std::optional<OptionValue> EnvOptions::operator[](const std::string &name) const
110 {
111 auto it = Options_.find(name);
112 if (it != Options_.end()) {
113 return it->second;
114 }
115 return {};
116 }
117
118 } // namespace panda::verifier::test
119