1 /**
2 * Copyright (c) 2021-2025 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 #include <charconv>
22
23 namespace ark::verifier::test {
24
25 // CC-OFFNXT(G.FUN.01, huge_method) solid logic
EnvOptions(const char * envVarName)26 EnvOptions::EnvOptions(const char *envVarName)
27 {
28 using ark::parser::Action;
29 using ark::parser::Charset;
30 using ark::parser::Parser;
31
32 struct Context {
33 std::string name;
34 OptionValue value;
35 };
36
37 using Par = Parser<Context, const char, const char *>::Next<EnvOptions>;
38
39 static const auto WS = Par::OfCharset(" \t\r\n"); // NOLINT(readability-static-accessed-through-instance)
40 static const auto DELIM = Par::OfString(";"); // NOLINT(readability-static-accessed-through-instance)
41 static const auto NAME_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
42 if (a == Action::PARSED) {
43 c.name = std::string {s, e};
44 }
45 return true;
46 };
47 static const auto NAME =
48 WS.OfCharset("abcdefghijklmnopqrstuvwxyz_") // NOLINT(readability-static-accessed-through-instance)
49 |= NAME_HANDLER;
50 static const auto EQ = NAME.OfString("="); // NOLINT(readability-static-accessed-through-instance)
51 static const auto BOOL_TRUE = EQ.OfString("true"); // NOLINT(readability-static-accessed-through-instance)
52 static const auto BOOL_FALSE = BOOL_TRUE.OfString("false"); // NOLINT(readability-static-accessed-through-instance)
53 static const auto BOOL_HANDLER = [](auto a, Context &c, auto s, [[maybe_unused]] auto to,
54 [[maybe_unused]] auto end) {
55 if (a == Action::PARSED) {
56 if (*s == 'f') {
57 c.value = false;
58 } else {
59 c.value = true;
60 }
61 }
62 return true;
63 };
64 static const auto BOOL = BOOL_FALSE | BOOL_TRUE |= BOOL_HANDLER;
65 static const auto DEC = BOOL.OfCharset("0123456789"); // NOLINT(readability-static-accessed-through-instance)
66 static const auto HEX = DEC.OfString("0x") >> DEC; // NOLINT(readability-static-accessed-through-instance)
67 static const auto NUM_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
68 if (a == Action::PARSED) {
69 int tempValue = 0;
70 std::string value = std::string {s, e};
71 std::from_chars(value.data(), &(*value.end()), tempValue, 0);
72 c.value = tempValue;
73 }
74 return true;
75 };
76 static const auto NUM = HEX | DEC |= NUM_HANDLER;
77 static const auto QUOTES = HEX.OfString("\""); // NOLINT(readability-static-accessed-through-instance)
78 static const auto NON_QUOTES =
79 QUOTES.OfCharset(!Charset("\"")); // NOLINT(readability-static-accessed-through-instance)
80 static const auto STRING_HANDLER = [](auto a, Context &c, auto s, auto e, [[maybe_unused]] auto end) {
81 if (a == Action::PARSED) {
82 c.value = std::string {s, e};
83 }
84 return true;
85 };
86 static const auto STRING = QUOTES >> (*NON_QUOTES |= STRING_HANDLER) >> QUOTES;
87
88 static const auto VALUE = STRING | NUM | BOOL;
89
90 static const auto KV_PAIR_HANDLER = [this](auto a, Context &c, [[maybe_unused]] auto f, [[maybe_unused]] auto t,
91 [[maybe_unused]] auto e) {
92 if (a == Action::PARSED) {
93 options_[c.name] = c.value;
94 }
95 return true;
96 };
97
98 static const auto KV_PAIR = ~WS >> NAME >> ~WS >> EQ >> ~WS >> VALUE >> ~WS >> DELIM |= KV_PAIR_HANDLER;
99 static const auto OPTIONS = *KV_PAIR;
100
101 const char *s = std::getenv(envVarName);
102 if (s == nullptr) {
103 return;
104 }
105
106 Context c;
107
108 if (!OPTIONS(c, s, s + strlen(s))) { // NOLINT
109 // NOTE(vdyadov): warning that some options were not parsed
110 }
111 }
112
operator [](const std::string & name) const113 std::optional<OptionValue> EnvOptions::operator[](const std::string &name) const
114 {
115 auto it = options_.find(name);
116 if (it != options_.end()) {
117 return it->second;
118 }
119 return {};
120 }
121
122 } // namespace ark::verifier::test
123