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