1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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#ifndef HIPERF_OPTION_H_
16#define HIPERF_OPTION_H_
17
18#include <functional>
19#include <map>
20#include <memory>
21#include <string>
22#include <vector>
23
24#include "debug_logger.h"
25#include "utilities.h"
26
27using argsVector = std::vector<std::string>;
28namespace OHOS {
29namespace Developtools {
30namespace NativeDaemon {
31namespace Option {
32struct MainOption {
33    std::string help;
34    std::function<bool(std::vector<std::string> &)> callBackFunction;
35};
36
37// called from main
38bool RegisterMainOption(const std::string &, const std::string &,
39                        std::function<bool(std::vector<std::string> &)>);
40
41void ClearMainOptions();
42
43bool CheckOptionFormat(const std::string &optionName);
44
45argsVector::iterator FindOption(argsVector &args, const std::string &optionName);
46
47// some option function
48bool GetValueFromString(const std::string &optionValue, const std::string &optionName, bool &value);
49bool GetValueFromString(const std::string &optionValue, const std::string &optionName, int &);
50bool GetValueFromString(const std::string &optionValue, const std::string &optionName,
51                        float &value);
52bool GetValueFromString(const std::string &optionValue, const std::string &optionName,
53                        std::string &value);
54bool GetValueFromString(const std::string &optionValue, const std::string &optionName,
55                        std::vector<int> &value);
56bool GetValueFromString(const std::string &optionValue, const std::string &optionName,
57                        std::vector<std::string> &value);
58
59bool GetOptionTrackedCommand(argsVector &args, std::vector<std::string> &trackedCommand);
60
61/*
62Return false to indicate that the parameter is illegal
63The program should exit with an error.
64
65Return true, indicating that the parameter is legal (but the user does not necessarily enter the
66parameter)
67*/
68template<class T>
69bool GetOptionValue(argsVector &args, std::string optionName, T &value)
70{
71    // we need keep the ref if we got failed
72    // so we use a local value first.
73    T localValues = {};
74    if constexpr (std::is_same<T, std::vector<std::vector<std::string>>>::value) {
75        // try unitl failed.
76        while (true) {
77            if (!GetOptionValue(args, optionName, localValues.emplace_back())) {
78                printf("incorrect option %s\n", optionName.c_str());
79                return false; // format error
80            } else if (localValues.back().size() == 0) {
81                // if the last one we request is empty , we remove it
82                localValues.pop_back();
83                // nothing more needed
84                // we dont allow empty value
85                break;
86            }
87        }
88        if (localValues.size() > 0) {
89            value = localValues;
90        }
91        return true;
92    } else {
93        if (!CheckOptionFormat(optionName)) {
94            if (optionName.empty()) {
95                printf("unable to use empty option name!\n");
96            } else {
97                printf("format error. must use '-' at the begin of option '%s'!\n",
98                       optionName.c_str());
99            }
100            return false; // something wrong
101        }
102        auto it = FindOption(args, optionName);
103        if (it == args.end()) {
104            HLOGV("not found option, return default value");
105            return true; // not found but also not error
106        } else {
107            it = args.erase(it);
108            // some specail case
109            if constexpr (std::is_same<T, bool>::value) {
110                // for bool we dont need get value.
111                // this always return true
112                GetValueFromString(optionName, optionName, value);
113                return true;
114            } else if (it == args.end()) {
115                // no value means failed
116                printf("option %s value missed\n", optionName.c_str());
117                return false;
118            } else if (GetValueFromString(*it, optionName, localValues)) {
119                // got some value
120                value = localValues;
121                args.erase(it);
122                return true;
123            } else {
124                // have value but conver failed.
125                printf("incorrect option value '%s'. View the usage with the --help option.\n",
126                       (*it).c_str());
127                return false;
128            }
129        }
130    }
131}
132
133const MainOption *FindMainOption(std::string);
134
135const std::map<std::string, std::unique_ptr<MainOption>> &GetMainOptions();
136} // namespace Option
137} // namespace NativeDaemon
138} // namespace Developtools
139} // namespace OHOS
140#endif