148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci#ifndef HIPERF_OPTION_H_
1648f512ceSopenharmony_ci#define HIPERF_OPTION_H_
1748f512ceSopenharmony_ci
1848f512ceSopenharmony_ci#include <functional>
1948f512ceSopenharmony_ci#include <map>
2048f512ceSopenharmony_ci#include <memory>
2148f512ceSopenharmony_ci#include <string>
2248f512ceSopenharmony_ci#include <vector>
2348f512ceSopenharmony_ci#include "debug_logger.h"
2448f512ceSopenharmony_ci#include "utilities.h"
2548f512ceSopenharmony_ci
2648f512ceSopenharmony_ciusing argsVector = std::vector<std::string>;
2748f512ceSopenharmony_cinamespace OHOS {
2848f512ceSopenharmony_cinamespace Developtools {
2948f512ceSopenharmony_cinamespace HiPerf {
3048f512ceSopenharmony_cinamespace Option {
3148f512ceSopenharmony_cistruct MainOption {
3248f512ceSopenharmony_ci    std::string help;
3348f512ceSopenharmony_ci    std::function<bool(std::vector<std::string> &)> callBackFunction;
3448f512ceSopenharmony_ci};
3548f512ceSopenharmony_ci
3648f512ceSopenharmony_ci// called from main
3748f512ceSopenharmony_cibool RegisterMainOption(const std::string &optionName, const std::string &help,
3848f512ceSopenharmony_ci                        std::function<bool(std::vector<std::string> &)> callBackFunction);
3948f512ceSopenharmony_ci
4048f512ceSopenharmony_civoid ClearMainOptions();
4148f512ceSopenharmony_ci
4248f512ceSopenharmony_cibool CheckOptionFormat(const std::string &optionName);
4348f512ceSopenharmony_ci
4448f512ceSopenharmony_ciargsVector::iterator FindOption(argsVector &args, const std::string &optionName);
4548f512ceSopenharmony_ci
4648f512ceSopenharmony_ci// some option function
4748f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName, bool &value);
4848f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName, int &value);
4948f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName, float &value);
5048f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName, std::string &value);
5148f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName, std::vector<int> &values);
5248f512ceSopenharmony_cibool GetValueFromString(const std::string &optionValue, const std::string &optionName,
5348f512ceSopenharmony_ci                        std::vector<std::string> &values);
5448f512ceSopenharmony_ci
5548f512ceSopenharmony_cibool GetOptionTrackedCommand(argsVector &args, std::vector<std::string> &trackedCommand);
5648f512ceSopenharmony_ci
5748f512ceSopenharmony_ci/*
5848f512ceSopenharmony_ciReturn false to indicate that the parameter is illegal
5948f512ceSopenharmony_ciThe program should exit with an error.
6048f512ceSopenharmony_ci
6148f512ceSopenharmony_ciReturn true, indicating that the parameter is legal (but the user does not necessarily enter the
6248f512ceSopenharmony_ciparameter)
6348f512ceSopenharmony_ci*/
6448f512ceSopenharmony_citemplate<class T>
6548f512ceSopenharmony_cibool GetOptionValue(argsVector &args, std::string optionName, T &value)
6648f512ceSopenharmony_ci{
6748f512ceSopenharmony_ci    // we need keep the ref if we got failed
6848f512ceSopenharmony_ci    // so we use a local value first.
6948f512ceSopenharmony_ci    T localValues = {};
7048f512ceSopenharmony_ci    if constexpr (std::is_same<T, std::vector<std::vector<std::string>>>::value) {
7148f512ceSopenharmony_ci        // try unitl failed.
7248f512ceSopenharmony_ci        while (true) {
7348f512ceSopenharmony_ci            if (!GetOptionValue(args, optionName, localValues.emplace_back())) {
7448f512ceSopenharmony_ci                printf("incorrect option %s\n", optionName.c_str());
7548f512ceSopenharmony_ci                return false; // format error
7648f512ceSopenharmony_ci            } else if (localValues.back().size() == 0) {
7748f512ceSopenharmony_ci                // if the last one we request is empty , we remove it
7848f512ceSopenharmony_ci                localValues.pop_back();
7948f512ceSopenharmony_ci                // nothing more needed
8048f512ceSopenharmony_ci                // we don't allow empty value
8148f512ceSopenharmony_ci                break;
8248f512ceSopenharmony_ci            }
8348f512ceSopenharmony_ci        }
8448f512ceSopenharmony_ci        if (localValues.size() > 0) {
8548f512ceSopenharmony_ci            value = localValues;
8648f512ceSopenharmony_ci        }
8748f512ceSopenharmony_ci        return true;
8848f512ceSopenharmony_ci    } else {
8948f512ceSopenharmony_ci        if (!CheckOptionFormat(optionName)) {
9048f512ceSopenharmony_ci            if (optionName.empty()) {
9148f512ceSopenharmony_ci                printf("unable to use empty option name!\n");
9248f512ceSopenharmony_ci            } else {
9348f512ceSopenharmony_ci                printf("format error. must use '-' at the begin of option '%s'!\n",
9448f512ceSopenharmony_ci                       optionName.c_str());
9548f512ceSopenharmony_ci            }
9648f512ceSopenharmony_ci            return false; // something wrong
9748f512ceSopenharmony_ci        }
9848f512ceSopenharmony_ci        auto it = FindOption(args, optionName);
9948f512ceSopenharmony_ci        if (it == args.end()) {
10048f512ceSopenharmony_ci            HLOGV("not found option, return default value");
10148f512ceSopenharmony_ci            return true; // not found but also not error
10248f512ceSopenharmony_ci        } else {
10348f512ceSopenharmony_ci            it = args.erase(it);
10448f512ceSopenharmony_ci            // some special case
10548f512ceSopenharmony_ci            if constexpr (std::is_same<T, bool>::value) {
10648f512ceSopenharmony_ci                // for bool we don't need get value.
10748f512ceSopenharmony_ci                // this always return true
10848f512ceSopenharmony_ci                GetValueFromString(optionName, optionName, value);
10948f512ceSopenharmony_ci                return true;
11048f512ceSopenharmony_ci            } else if (it == args.end()) {
11148f512ceSopenharmony_ci                // no value means failed
11248f512ceSopenharmony_ci                printf("option %s value missed\n", optionName.c_str());
11348f512ceSopenharmony_ci                return false;
11448f512ceSopenharmony_ci            } else if (GetValueFromString(*it, optionName, localValues)) {
11548f512ceSopenharmony_ci                // got some value
11648f512ceSopenharmony_ci                value = localValues;
11748f512ceSopenharmony_ci                args.erase(it);
11848f512ceSopenharmony_ci                return true;
11948f512ceSopenharmony_ci            } else {
12048f512ceSopenharmony_ci                // have value but convert failed.
12148f512ceSopenharmony_ci                printf("incorrect option value '%s' for option '%s'. View the usage with the --help option.\n",
12248f512ceSopenharmony_ci                       (*it).c_str(), optionName.c_str());
12348f512ceSopenharmony_ci                return false;
12448f512ceSopenharmony_ci            }
12548f512ceSopenharmony_ci        }
12648f512ceSopenharmony_ci    }
12748f512ceSopenharmony_ci}
12848f512ceSopenharmony_ci
12948f512ceSopenharmony_ciconst MainOption *FindMainOption(const std::string &argName);
13048f512ceSopenharmony_ci
13148f512ceSopenharmony_ciconst std::map<std::string, std::unique_ptr<MainOption>> &GetMainOptions();
13248f512ceSopenharmony_ci} // namespace Option
13348f512ceSopenharmony_ci} // namespace HiPerf
13448f512ceSopenharmony_ci} // namespace Developtools
13548f512ceSopenharmony_ci} // namespace OHOS
13648f512ceSopenharmony_ci#endif // HIPERF_OPTION_H_
137