106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#ifndef COMMAND_LINE_FLAGS_H
1706f6ba60Sopenharmony_ci#define COMMAND_LINE_FLAGS_H
1806f6ba60Sopenharmony_ci#include <iostream>
1906f6ba60Sopenharmony_ci#include <string>
2006f6ba60Sopenharmony_ci#include <vector>
2106f6ba60Sopenharmony_ci#include <unordered_map>
2206f6ba60Sopenharmony_ci#include <cstddef>
2306f6ba60Sopenharmony_ci#include <inttypes.h>
2406f6ba60Sopenharmony_ci#include <cstdint>
2506f6ba60Sopenharmony_ci#include <type_traits>
2606f6ba60Sopenharmony_ci#include <typeinfo>
2706f6ba60Sopenharmony_ci#include <cstdlib>
2806f6ba60Sopenharmony_ci#include <climits>
2906f6ba60Sopenharmony_ci
3006f6ba60Sopenharmony_cinamespace CommandLineFlags {
3106f6ba60Sopenharmony_cienum class FlagTypes {
3206f6ba60Sopenharmony_ci    FT_void,
3306f6ba60Sopenharmony_ci    FT_bool,
3406f6ba60Sopenharmony_ci    FT_int8,
3506f6ba60Sopenharmony_ci    FT_int16,
3606f6ba60Sopenharmony_ci    FT_int32,
3706f6ba60Sopenharmony_ci    FT_int64,
3806f6ba60Sopenharmony_ci    FT_uint8,
3906f6ba60Sopenharmony_ci    FT_uint16,
4006f6ba60Sopenharmony_ci    FT_uint32,
4106f6ba60Sopenharmony_ci    FT_uint64,
4206f6ba60Sopenharmony_ci    FT_double,
4306f6ba60Sopenharmony_ci    FT_string,
4406f6ba60Sopenharmony_ci    FT_bool_array,
4506f6ba60Sopenharmony_ci    FT_int8_array,
4606f6ba60Sopenharmony_ci    FT_int16_array,
4706f6ba60Sopenharmony_ci    FT_int32_array,
4806f6ba60Sopenharmony_ci    FT_int64_array,
4906f6ba60Sopenharmony_ci    FT_uint8_array,
5006f6ba60Sopenharmony_ci    FT_uint16_array,
5106f6ba60Sopenharmony_ci    FT_uint32_array,
5206f6ba60Sopenharmony_ci    FT_uint64_array,
5306f6ba60Sopenharmony_ci    FT_double_array,
5406f6ba60Sopenharmony_ci    FT_string_array,
5506f6ba60Sopenharmony_ci};
5606f6ba60Sopenharmony_ci
5706f6ba60Sopenharmony_cistruct MetaFlag {
5806f6ba60Sopenharmony_ci    FlagTypes type_ {FlagTypes::FT_void};
5906f6ba60Sopenharmony_ci    void* addr_ {nullptr};
6006f6ba60Sopenharmony_ci    MetaFlag() = default;
6106f6ba60Sopenharmony_ci    MetaFlag(const FlagTypes& flagType, void* flagPtr): type_ {flagType}, addr_ {flagPtr} {}
6206f6ba60Sopenharmony_ci};
6306f6ba60Sopenharmony_ci
6406f6ba60Sopenharmony_cistd::unordered_map<std::string, MetaFlag> flags_ {};
6506f6ba60Sopenharmony_ci
6606f6ba60Sopenharmony_citemplate<typename T>
6706f6ba60Sopenharmony_ciclass FlagRegesterer {
6806f6ba60Sopenharmony_cipublic:
6906f6ba60Sopenharmony_ci    FlagRegesterer(const std::string& name, const T& flag)
7006f6ba60Sopenharmony_ci    {
7106f6ba60Sopenharmony_ci        if (flags_.count(name) != 0) {
7206f6ba60Sopenharmony_ci            std::cout << "CommandLineFlags WARN: flag " << name << " redefined" << std::endl;
7306f6ba60Sopenharmony_ci        } else {
7406f6ba60Sopenharmony_ci            auto& metaFlag = flags_[name];
7506f6ba60Sopenharmony_ci            metaFlag.addr_ = (void*) &flag;
7606f6ba60Sopenharmony_ci
7706f6ba60Sopenharmony_ci            if (std::is_same<T, bool>::value) {
7806f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_bool;
7906f6ba60Sopenharmony_ci            } else if (std::is_same<T, int8_t>::value) {
8006f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int8;
8106f6ba60Sopenharmony_ci            } else if (std::is_same<T, int16_t>::value) {
8206f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int16;
8306f6ba60Sopenharmony_ci            } else if (std::is_same<T, int32_t>::value) {
8406f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int32;
8506f6ba60Sopenharmony_ci            } else if (std::is_same<T, int64_t>::value) {
8606f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int64;
8706f6ba60Sopenharmony_ci            } else if (std::is_same<T, uint8_t>::value) {
8806f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint8;
8906f6ba60Sopenharmony_ci            } else if (std::is_same<T, uint16_t>::value) {
9006f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint16;
9106f6ba60Sopenharmony_ci            } else if (std::is_same<T, uint32_t>::value) {
9206f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint32;
9306f6ba60Sopenharmony_ci            } else if (std::is_same<T, uint64_t>::value) {
9406f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint64;
9506f6ba60Sopenharmony_ci            } else if (std::is_same<T, double>::value) {
9606f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_double;
9706f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::string>::value) {
9806f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_string;
9906f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<bool>>::value) {
10006f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_bool_array;
10106f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<int8_t>>::value) {
10206f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int8_array;
10306f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<int16_t>>::value) {
10406f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int16_array;
10506f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<int32_t>>::value) {
10606f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int32_array;
10706f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<int64_t>>::value) {
10806f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_int64_array;
10906f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<uint8_t>>::value) {
11006f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint8_array;
11106f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<uint16_t>>::value) {
11206f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint16_array;
11306f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<uint32_t>>::value) {
11406f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint32_array;
11506f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<uint64_t>>::value) {
11606f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_uint64_array;
11706f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<double>>::value) {
11806f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_double_array;
11906f6ba60Sopenharmony_ci            } else if (std::is_same<T, std::vector<std::string>>::value) {
12006f6ba60Sopenharmony_ci                metaFlag.type_ = FlagTypes::FT_string_array;
12106f6ba60Sopenharmony_ci            }
12206f6ba60Sopenharmony_ci        }
12306f6ba60Sopenharmony_ci    }
12406f6ba60Sopenharmony_ci};
12506f6ba60Sopenharmony_ci
12606f6ba60Sopenharmony_cistatic inline void PrintArgFormat()
12706f6ba60Sopenharmony_ci{
12806f6ba60Sopenharmony_ci    std::string format {"Arguments Format: <command> -<character> <value> --<word>[-<word>] <value>"};
12906f6ba60Sopenharmony_ci    std::cout << format << std::endl;
13006f6ba60Sopenharmony_ci    return;
13106f6ba60Sopenharmony_ci}
13206f6ba60Sopenharmony_ci
13306f6ba60Sopenharmony_cistatic inline std::string ConvertToFlagName(char* argStr, int argLen)
13406f6ba60Sopenharmony_ci{
13506f6ba60Sopenharmony_ci    for (int k = 0; k < argLen; ++k) {
13606f6ba60Sopenharmony_ci        if (argStr[k] == '-') {
13706f6ba60Sopenharmony_ci            if (argStr[k-1] == '-') {
13806f6ba60Sopenharmony_ci                // continuous '-', bad argument
13906f6ba60Sopenharmony_ci                return "";
14006f6ba60Sopenharmony_ci            }
14106f6ba60Sopenharmony_ci            argStr[k] = '_';
14206f6ba60Sopenharmony_ci        }
14306f6ba60Sopenharmony_ci    }
14406f6ba60Sopenharmony_ci    return std::string(argStr, argLen);
14506f6ba60Sopenharmony_ci}
14606f6ba60Sopenharmony_ci
14706f6ba60Sopenharmony_cistatic int GetFlagName(
14806f6ba60Sopenharmony_ci    char*** argv,
14906f6ba60Sopenharmony_ci    int& argIndex,
15006f6ba60Sopenharmony_ci    std::string& flagName)
15106f6ba60Sopenharmony_ci{
15206f6ba60Sopenharmony_ci    if ((*argv)[argIndex] == nullptr) {
15306f6ba60Sopenharmony_ci        // argument has been removed, skip it
15406f6ba60Sopenharmony_ci        flagName = "";
15506f6ba60Sopenharmony_ci        ++argIndex;
15606f6ba60Sopenharmony_ci        return 0;
15706f6ba60Sopenharmony_ci    }
15806f6ba60Sopenharmony_ci
15906f6ba60Sopenharmony_ci    // get argument prefix length and argument length
16006f6ba60Sopenharmony_ci    char* argStr = (*argv)[argIndex];
16106f6ba60Sopenharmony_ci    int prefix {0};
16206f6ba60Sopenharmony_ci    int argLen {0};
16306f6ba60Sopenharmony_ci    bool keepCounting {true};
16406f6ba60Sopenharmony_ci    for (; argStr[argLen] != '\0'; ++argLen) {
16506f6ba60Sopenharmony_ci        if (argStr[argLen] != '-') {
16606f6ba60Sopenharmony_ci            keepCounting = false;
16706f6ba60Sopenharmony_ci        }
16806f6ba60Sopenharmony_ci        if (keepCounting and argStr[argLen] == '-') {
16906f6ba60Sopenharmony_ci            ++prefix;
17006f6ba60Sopenharmony_ci        }
17106f6ba60Sopenharmony_ci    }
17206f6ba60Sopenharmony_ci    argLen -= prefix;
17306f6ba60Sopenharmony_ci
17406f6ba60Sopenharmony_ci    // short argument
17506f6ba60Sopenharmony_ci    constexpr int shortFlagLen {1};
17606f6ba60Sopenharmony_ci    if (prefix == shortFlagLen and argLen == shortFlagLen) {
17706f6ba60Sopenharmony_ci        flagName = std::string(argStr + prefix, argLen);
17806f6ba60Sopenharmony_ci        ++argIndex;
17906f6ba60Sopenharmony_ci        return 0;
18006f6ba60Sopenharmony_ci    }
18106f6ba60Sopenharmony_ci
18206f6ba60Sopenharmony_ci    // long argument
18306f6ba60Sopenharmony_ci    constexpr int longPrefix {2};
18406f6ba60Sopenharmony_ci    if (prefix == longPrefix and argLen > shortFlagLen) {
18506f6ba60Sopenharmony_ci        flagName = ConvertToFlagName(argStr + longPrefix, argLen);
18606f6ba60Sopenharmony_ci        if (flagName.empty()) {
18706f6ba60Sopenharmony_ci            // bad argument
18806f6ba60Sopenharmony_ci            std::cout << "CommandLineFlags ERROR: unrecognized argument format: "
18906f6ba60Sopenharmony_ci                    << argStr << std::endl;
19006f6ba60Sopenharmony_ci            PrintArgFormat();
19106f6ba60Sopenharmony_ci            return -1;
19206f6ba60Sopenharmony_ci        }
19306f6ba60Sopenharmony_ci        ++argIndex;
19406f6ba60Sopenharmony_ci        return 0;
19506f6ba60Sopenharmony_ci    }
19606f6ba60Sopenharmony_ci    // bad argument
19706f6ba60Sopenharmony_ci    std::cout << "CommandLineFlags ERROR: unrecognized argument format: "
19806f6ba60Sopenharmony_ci                << argStr << std::endl;
19906f6ba60Sopenharmony_ci    PrintArgFormat();
20006f6ba60Sopenharmony_ci    return -1;
20106f6ba60Sopenharmony_ci}
20206f6ba60Sopenharmony_ci
20306f6ba60Sopenharmony_cistatic int GetFlagValue(
20406f6ba60Sopenharmony_ci    char*** argv,
20506f6ba60Sopenharmony_ci    int& argIndex,
20606f6ba60Sopenharmony_ci    std::string& flagValue)
20706f6ba60Sopenharmony_ci{
20806f6ba60Sopenharmony_ci    if ((*argv)[argIndex] == nullptr) {
20906f6ba60Sopenharmony_ci        // arg removed, skip it
21006f6ba60Sopenharmony_ci        flagValue = "";
21106f6ba60Sopenharmony_ci        ++argIndex;
21206f6ba60Sopenharmony_ci        return 0;
21306f6ba60Sopenharmony_ci    }
21406f6ba60Sopenharmony_ci    char* argStr = (*argv)[argIndex];
21506f6ba60Sopenharmony_ci    int argLen {0};
21606f6ba60Sopenharmony_ci    for (; argStr[argLen] != '\0'; ++argLen);
21706f6ba60Sopenharmony_ci    flagValue = std::string(argStr, argLen);
21806f6ba60Sopenharmony_ci    ++argIndex;
21906f6ba60Sopenharmony_ci    return 0;
22006f6ba60Sopenharmony_ci}
22106f6ba60Sopenharmony_ci
22206f6ba60Sopenharmony_cistatic void ClearCString(char* str)
22306f6ba60Sopenharmony_ci{
22406f6ba60Sopenharmony_ci    if (str == nullptr) {
22506f6ba60Sopenharmony_ci        return;
22606f6ba60Sopenharmony_ci    }
22706f6ba60Sopenharmony_ci    for (int k = 0; ; ++k) {
22806f6ba60Sopenharmony_ci        if (str[k] == '\0') {
22906f6ba60Sopenharmony_ci            break;
23006f6ba60Sopenharmony_ci        }
23106f6ba60Sopenharmony_ci        str[k] = '\0';
23206f6ba60Sopenharmony_ci    }
23306f6ba60Sopenharmony_ci    return;
23406f6ba60Sopenharmony_ci}
23506f6ba60Sopenharmony_ci
23606f6ba60Sopenharmony_cistatic int GetNextFlag(
23706f6ba60Sopenharmony_ci    char*** argv,
23806f6ba60Sopenharmony_ci    int& argIndex,
23906f6ba60Sopenharmony_ci    bool rm,
24006f6ba60Sopenharmony_ci    std::string& flagName,
24106f6ba60Sopenharmony_ci    std::string& flagValue)
24206f6ba60Sopenharmony_ci{
24306f6ba60Sopenharmony_ci    if (GetFlagName(argv, argIndex, flagName) != 0) {
24406f6ba60Sopenharmony_ci        return -1;
24506f6ba60Sopenharmony_ci    }
24606f6ba60Sopenharmony_ci    GetFlagValue(argv, argIndex, flagValue);
24706f6ba60Sopenharmony_ci    // flag parsing done
24806f6ba60Sopenharmony_ci    if (rm and flags_.count(flagName) != 0) {
24906f6ba60Sopenharmony_ci        // remove parsed argument and its value
25006f6ba60Sopenharmony_ci        ClearCString((*argv)[argIndex - 1]);
25106f6ba60Sopenharmony_ci        ClearCString((*argv)[argIndex - 2]); // 2: point of args
25206f6ba60Sopenharmony_ci    }
25306f6ba60Sopenharmony_ci    return 0;
25406f6ba60Sopenharmony_ci}
25506f6ba60Sopenharmony_ci
25606f6ba60Sopenharmony_cistatic int ParseBoolFlag(const std::string& flag, const std::string& valStr)
25706f6ba60Sopenharmony_ci{
25806f6ba60Sopenharmony_ci    bool *val = (bool*) flags_[flag].addr_;
25906f6ba60Sopenharmony_ci    if (valStr.compare("false") == 0) {
26006f6ba60Sopenharmony_ci        *val = false;
26106f6ba60Sopenharmony_ci    } else if (valStr.compare("true") == 0) {
26206f6ba60Sopenharmony_ci        *val = true;
26306f6ba60Sopenharmony_ci    } else {
26406f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
26506f6ba60Sopenharmony_ci                  << " of bool type should only be assigned with 'true' or 'false' but "
26606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
26706f6ba60Sopenharmony_ci        return -1;
26806f6ba60Sopenharmony_ci    }
26906f6ba60Sopenharmony_ci    return 0;
27006f6ba60Sopenharmony_ci}
27106f6ba60Sopenharmony_ci
27206f6ba60Sopenharmony_ci// we will not handle any exceptions thrown by std::stoi() series functions, we should
27306f6ba60Sopenharmony_ci// just let exceptions abort the process.
27406f6ba60Sopenharmony_cistatic int ParseInt8Flag(const std::string& flag, const std::string& valStr)
27506f6ba60Sopenharmony_ci{
27606f6ba60Sopenharmony_ci    char* pos = nullptr;
27706f6ba60Sopenharmony_ci    long int tmpVal = strtol(valStr.c_str(), &pos, 10);
27806f6ba60Sopenharmony_ci    if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
27906f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
28006f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
28106f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
28206f6ba60Sopenharmony_ci        return -1;
28306f6ba60Sopenharmony_ci    }
28406f6ba60Sopenharmony_ci    int8_t* val = (int8_t*) flags_[flag].addr_;
28506f6ba60Sopenharmony_ci    *val = static_cast<int8_t>(tmpVal);
28606f6ba60Sopenharmony_ci    return 0;
28706f6ba60Sopenharmony_ci}
28806f6ba60Sopenharmony_ci
28906f6ba60Sopenharmony_cistatic int ParseInt16Flag(const std::string& flag, const std::string& valStr)
29006f6ba60Sopenharmony_ci{
29106f6ba60Sopenharmony_ci    char* pos = nullptr;
29206f6ba60Sopenharmony_ci    long int tmpVal = strtol(valStr.c_str(), &pos, 10);
29306f6ba60Sopenharmony_ci    if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
29406f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
29506f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
29606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
29706f6ba60Sopenharmony_ci        return -1;
29806f6ba60Sopenharmony_ci    }
29906f6ba60Sopenharmony_ci    int16_t* val = (int16_t*) flags_[flag].addr_;
30006f6ba60Sopenharmony_ci    *val = static_cast<int16_t>(tmpVal);
30106f6ba60Sopenharmony_ci    return 0;
30206f6ba60Sopenharmony_ci}
30306f6ba60Sopenharmony_ci
30406f6ba60Sopenharmony_cistatic int ParseInt32Flag(const std::string& flag, const std::string& valStr)
30506f6ba60Sopenharmony_ci{
30606f6ba60Sopenharmony_ci    char* pos = nullptr;
30706f6ba60Sopenharmony_ci    long int tmpVal = strtol(valStr.c_str(), &pos, 10);
30806f6ba60Sopenharmony_ci    if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
30906f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
31006f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
31106f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
31206f6ba60Sopenharmony_ci        return -1;
31306f6ba60Sopenharmony_ci    }
31406f6ba60Sopenharmony_ci    int32_t* val = (int32_t*) flags_[flag].addr_;
31506f6ba60Sopenharmony_ci    *val = static_cast<int32_t>(tmpVal);
31606f6ba60Sopenharmony_ci    return 0;
31706f6ba60Sopenharmony_ci}
31806f6ba60Sopenharmony_ci
31906f6ba60Sopenharmony_cistatic int ParseInt64Flag(const std::string& flag, const std::string& valStr)
32006f6ba60Sopenharmony_ci{
32106f6ba60Sopenharmony_ci    char* pos = nullptr;
32206f6ba60Sopenharmony_ci    long int tmpVal = strtol(valStr.c_str(), &pos, 10);
32306f6ba60Sopenharmony_ci    if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
32406f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
32506f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
32606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
32706f6ba60Sopenharmony_ci        return -1;
32806f6ba60Sopenharmony_ci    }
32906f6ba60Sopenharmony_ci    int64_t* val = (int64_t*) flags_[flag].addr_;
33006f6ba60Sopenharmony_ci    *val = static_cast<int64_t>(tmpVal);
33106f6ba60Sopenharmony_ci    return 0;
33206f6ba60Sopenharmony_ci}
33306f6ba60Sopenharmony_ci
33406f6ba60Sopenharmony_cistatic int ParseUint8Flag(const std::string& flag, const std::string& valStr)
33506f6ba60Sopenharmony_ci{
33606f6ba60Sopenharmony_ci    char* pos = nullptr;
33706f6ba60Sopenharmony_ci    unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
33806f6ba60Sopenharmony_ci    if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
33906f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
34006f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
34106f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
34206f6ba60Sopenharmony_ci        return -1;
34306f6ba60Sopenharmony_ci    }
34406f6ba60Sopenharmony_ci    uint8_t* val = (uint8_t*) flags_[flag].addr_;
34506f6ba60Sopenharmony_ci    *val = static_cast<uint8_t>(tmpVal);
34606f6ba60Sopenharmony_ci    return 0;
34706f6ba60Sopenharmony_ci}
34806f6ba60Sopenharmony_ci
34906f6ba60Sopenharmony_cistatic int ParseUint16Flag(const std::string& flag, const std::string& valStr)
35006f6ba60Sopenharmony_ci{
35106f6ba60Sopenharmony_ci    char* pos = nullptr;
35206f6ba60Sopenharmony_ci    unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
35306f6ba60Sopenharmony_ci    if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
35406f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
35506f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
35606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
35706f6ba60Sopenharmony_ci        return -1;
35806f6ba60Sopenharmony_ci    }
35906f6ba60Sopenharmony_ci    uint16_t* val = (uint16_t*) flags_[flag].addr_;
36006f6ba60Sopenharmony_ci    *val = static_cast<uint16_t>(tmpVal);
36106f6ba60Sopenharmony_ci    return 0;
36206f6ba60Sopenharmony_ci}
36306f6ba60Sopenharmony_ci
36406f6ba60Sopenharmony_cistatic int ParseUint32Flag(const std::string& flag, const std::string& valStr)
36506f6ba60Sopenharmony_ci{
36606f6ba60Sopenharmony_ci    char* pos = nullptr;
36706f6ba60Sopenharmony_ci    unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
36806f6ba60Sopenharmony_ci    if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
36906f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
37006f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
37106f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
37206f6ba60Sopenharmony_ci        return -1;
37306f6ba60Sopenharmony_ci    }
37406f6ba60Sopenharmony_ci    uint32_t* val = (uint32_t*) flags_[flag].addr_;
37506f6ba60Sopenharmony_ci    *val = static_cast<uint32_t>(tmpVal);
37606f6ba60Sopenharmony_ci    return 0;
37706f6ba60Sopenharmony_ci}
37806f6ba60Sopenharmony_ci
37906f6ba60Sopenharmony_cistatic int ParseUint64Flag(const std::string& flag, const std::string& valStr)
38006f6ba60Sopenharmony_ci{
38106f6ba60Sopenharmony_ci    char* pos = nullptr;
38206f6ba60Sopenharmony_ci    unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
38306f6ba60Sopenharmony_ci    if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
38406f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
38506f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
38606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
38706f6ba60Sopenharmony_ci        return -1;
38806f6ba60Sopenharmony_ci    }
38906f6ba60Sopenharmony_ci    uint64_t* val = (uint64_t*) flags_[flag].addr_;
39006f6ba60Sopenharmony_ci    *val = static_cast<uint64_t>(tmpVal);
39106f6ba60Sopenharmony_ci    return 0;
39206f6ba60Sopenharmony_ci}
39306f6ba60Sopenharmony_ci
39406f6ba60Sopenharmony_cistatic int ParseDoubleFlag(const std::string& flag, const std::string& valStr)
39506f6ba60Sopenharmony_ci{
39606f6ba60Sopenharmony_ci    char* pos = nullptr;
39706f6ba60Sopenharmony_ci    double tmpVal = strtod(valStr.c_str(), &pos);
39806f6ba60Sopenharmony_ci    if (tmpVal == 0.0 || tmpVal == HUGE_VAL) {
39906f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROR: argument " << flag
40006f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
40106f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
40206f6ba60Sopenharmony_ci        return -1;
40306f6ba60Sopenharmony_ci    }
40406f6ba60Sopenharmony_ci    double* val = (double*) flags_[flag].addr_;
40506f6ba60Sopenharmony_ci    *val = tmpVal;
40606f6ba60Sopenharmony_ci    return 0;
40706f6ba60Sopenharmony_ci}
40806f6ba60Sopenharmony_ci
40906f6ba60Sopenharmony_cistatic int ParseStringFlag(const std::string& flag, const std::string& valStr)
41006f6ba60Sopenharmony_ci{
41106f6ba60Sopenharmony_ci    std::string* val = (std::string*) flags_[flag].addr_;
41206f6ba60Sopenharmony_ci    *val = valStr;
41306f6ba60Sopenharmony_ci    return 0;
41406f6ba60Sopenharmony_ci}
41506f6ba60Sopenharmony_ci
41606f6ba60Sopenharmony_cistatic int ParseBoolArrayFlag(const std::string& flag, const std::string& valStr)
41706f6ba60Sopenharmony_ci{
41806f6ba60Sopenharmony_ci    std::vector<bool>* val = (std::vector<bool>*) flags_[flag].addr_;
41906f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
42006f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
42106f6ba60Sopenharmony_ci            if (start == end) {
42206f6ba60Sopenharmony_ci                ++start;
42306f6ba60Sopenharmony_ci                continue;
42406f6ba60Sopenharmony_ci            }
42506f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
42606f6ba60Sopenharmony_ci            if (str.compare("false") == 0) {
42706f6ba60Sopenharmony_ci                val->push_back(false);
42806f6ba60Sopenharmony_ci            } else if (str.compare("true") == 0) {
42906f6ba60Sopenharmony_ci                val->push_back(true);
43006f6ba60Sopenharmony_ci            } else {
43106f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
43206f6ba60Sopenharmony_ci                          << " of bool type should only be assigned with 'true' or 'false' but "
43306f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
43406f6ba60Sopenharmony_ci                val->clear();
43506f6ba60Sopenharmony_ci                return -1;
43606f6ba60Sopenharmony_ci            }
43706f6ba60Sopenharmony_ci            start =  end + 1;
43806f6ba60Sopenharmony_ci        }
43906f6ba60Sopenharmony_ci    }
44006f6ba60Sopenharmony_ci    return 0;
44106f6ba60Sopenharmony_ci}
44206f6ba60Sopenharmony_ci
44306f6ba60Sopenharmony_cistatic int ParseInt8ArrayFlag(const std::string& flag, const std::string& valStr)
44406f6ba60Sopenharmony_ci{
44506f6ba60Sopenharmony_ci    std::vector<int8_t>* val = (std::vector<int8_t>*) flags_[flag].addr_;
44606f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
44706f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
44806f6ba60Sopenharmony_ci            if (start == end) {
44906f6ba60Sopenharmony_ci                ++start;
45006f6ba60Sopenharmony_ci                continue;
45106f6ba60Sopenharmony_ci            }
45206f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
45306f6ba60Sopenharmony_ci            char* pos = nullptr;
45406f6ba60Sopenharmony_ci            long int tmpVal = strtol(valStr.c_str(), &pos, 10);
45506f6ba60Sopenharmony_ci            if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
45606f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
45706f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
45806f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
45906f6ba60Sopenharmony_ci                val->clear();
46006f6ba60Sopenharmony_ci                return -1;
46106f6ba60Sopenharmony_ci            }
46206f6ba60Sopenharmony_ci            val->push_back(static_cast<int8_t>(tmpVal));
46306f6ba60Sopenharmony_ci            start =  end + 1;
46406f6ba60Sopenharmony_ci        }
46506f6ba60Sopenharmony_ci    }
46606f6ba60Sopenharmony_ci    return 0;
46706f6ba60Sopenharmony_ci}
46806f6ba60Sopenharmony_ci
46906f6ba60Sopenharmony_cistatic int ParseInt16ArrayFlag(const std::string& flag, const std::string& valStr)
47006f6ba60Sopenharmony_ci{
47106f6ba60Sopenharmony_ci    std::vector<int16_t>* val = (std::vector<int16_t>*) flags_[flag].addr_;
47206f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
47306f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
47406f6ba60Sopenharmony_ci            if (start == end) {
47506f6ba60Sopenharmony_ci                ++start;
47606f6ba60Sopenharmony_ci                continue;
47706f6ba60Sopenharmony_ci            }
47806f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
47906f6ba60Sopenharmony_ci            char* pos = nullptr;
48006f6ba60Sopenharmony_ci            long int tmpVal = strtol(valStr.c_str(), &pos, 10);
48106f6ba60Sopenharmony_ci            if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
48206f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
48306f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
48406f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
48506f6ba60Sopenharmony_ci                val->clear();
48606f6ba60Sopenharmony_ci                return -1;
48706f6ba60Sopenharmony_ci            }
48806f6ba60Sopenharmony_ci            val->push_back(static_cast<int16_t>(tmpVal));
48906f6ba60Sopenharmony_ci            start =  end + 1;
49006f6ba60Sopenharmony_ci        }
49106f6ba60Sopenharmony_ci    }
49206f6ba60Sopenharmony_ci    return 0;
49306f6ba60Sopenharmony_ci}
49406f6ba60Sopenharmony_ci
49506f6ba60Sopenharmony_cistatic int ParseInt32ArrayFlag(const std::string& flag, const std::string& valStr)
49606f6ba60Sopenharmony_ci{
49706f6ba60Sopenharmony_ci    std::vector<int32_t>* val = (std::vector<int32_t>*) flags_[flag].addr_;
49806f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
49906f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
50006f6ba60Sopenharmony_ci            if (start == end) {
50106f6ba60Sopenharmony_ci                ++start;
50206f6ba60Sopenharmony_ci                continue;
50306f6ba60Sopenharmony_ci            }
50406f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
50506f6ba60Sopenharmony_ci            char* pos = nullptr;
50606f6ba60Sopenharmony_ci            long int tmpVal = strtol(valStr.c_str(), &pos, 10);
50706f6ba60Sopenharmony_ci            if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
50806f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
50906f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
51006f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
51106f6ba60Sopenharmony_ci                val->clear();
51206f6ba60Sopenharmony_ci                return -1;
51306f6ba60Sopenharmony_ci            }
51406f6ba60Sopenharmony_ci            val->push_back(static_cast<int32_t>(tmpVal));
51506f6ba60Sopenharmony_ci            start =  end + 1;
51606f6ba60Sopenharmony_ci        }
51706f6ba60Sopenharmony_ci    }
51806f6ba60Sopenharmony_ci    return 0;
51906f6ba60Sopenharmony_ci}
52006f6ba60Sopenharmony_ci
52106f6ba60Sopenharmony_cistatic int ParseInt64ArrayFlag(const std::string& flag, const std::string& valStr)
52206f6ba60Sopenharmony_ci{
52306f6ba60Sopenharmony_ci    std::vector<int64_t>* val = (std::vector<int64_t>*) flags_[flag].addr_;
52406f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
52506f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
52606f6ba60Sopenharmony_ci            if (start == end) {
52706f6ba60Sopenharmony_ci                ++start;
52806f6ba60Sopenharmony_ci                continue;
52906f6ba60Sopenharmony_ci            }
53006f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
53106f6ba60Sopenharmony_ci            char* pos = nullptr;
53206f6ba60Sopenharmony_ci            long int tmpVal = strtol(valStr.c_str(), &pos, 10);
53306f6ba60Sopenharmony_ci            if (tmpVal == 0L || tmpVal == LONG_MAX || tmpVal == LONG_MIN) {
53406f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
53506f6ba60Sopenharmony_ci                  << " of numeric type should only be assigned with number but "
53606f6ba60Sopenharmony_ci                  << valStr << " is given" << std::endl;
53706f6ba60Sopenharmony_ci                val->clear();
53806f6ba60Sopenharmony_ci                return -1;
53906f6ba60Sopenharmony_ci            }
54006f6ba60Sopenharmony_ci            val->push_back(static_cast<int64_t>(tmpVal));
54106f6ba60Sopenharmony_ci            start =  end + 1;
54206f6ba60Sopenharmony_ci        }
54306f6ba60Sopenharmony_ci    }
54406f6ba60Sopenharmony_ci    return 0;
54506f6ba60Sopenharmony_ci}
54606f6ba60Sopenharmony_ci
54706f6ba60Sopenharmony_cistatic int ParseUint8ArrayFlag(const std::string& flag, const std::string& valStr)
54806f6ba60Sopenharmony_ci{
54906f6ba60Sopenharmony_ci    std::vector<uint8_t>* val = (std::vector<uint8_t>*) flags_[flag].addr_;
55006f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
55106f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
55206f6ba60Sopenharmony_ci            if (start == end) {
55306f6ba60Sopenharmony_ci                ++start;
55406f6ba60Sopenharmony_ci                continue;
55506f6ba60Sopenharmony_ci            }
55606f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
55706f6ba60Sopenharmony_ci            char* pos = nullptr;
55806f6ba60Sopenharmony_ci            unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
55906f6ba60Sopenharmony_ci            if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
56006f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
56106f6ba60Sopenharmony_ci                          << " of numeric type should only be assigned with number but "
56206f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
56306f6ba60Sopenharmony_ci                val->clear();
56406f6ba60Sopenharmony_ci                return -1;
56506f6ba60Sopenharmony_ci            }
56606f6ba60Sopenharmony_ci            val->push_back(static_cast<uint8_t>(tmpVal));
56706f6ba60Sopenharmony_ci            start =  end + 1;
56806f6ba60Sopenharmony_ci        }
56906f6ba60Sopenharmony_ci    }
57006f6ba60Sopenharmony_ci    return 0;
57106f6ba60Sopenharmony_ci}
57206f6ba60Sopenharmony_ci
57306f6ba60Sopenharmony_cistatic int ParseUint16ArrayFlag(const std::string& flag, const std::string& valStr)
57406f6ba60Sopenharmony_ci{
57506f6ba60Sopenharmony_ci    std::vector<uint16_t>* val = (std::vector<uint16_t>*) flags_[flag].addr_;
57606f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
57706f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
57806f6ba60Sopenharmony_ci            if (start == end) {
57906f6ba60Sopenharmony_ci                ++start;
58006f6ba60Sopenharmony_ci                continue;
58106f6ba60Sopenharmony_ci            }
58206f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
58306f6ba60Sopenharmony_ci            char* pos = nullptr;
58406f6ba60Sopenharmony_ci            unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
58506f6ba60Sopenharmony_ci            if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
58606f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
58706f6ba60Sopenharmony_ci                          << " of numeric type should only be assigned with number but "
58806f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
58906f6ba60Sopenharmony_ci                val->clear();
59006f6ba60Sopenharmony_ci                return -1;
59106f6ba60Sopenharmony_ci            }
59206f6ba60Sopenharmony_ci            val->push_back(static_cast<uint16_t>(tmpVal));
59306f6ba60Sopenharmony_ci            start =  end + 1;
59406f6ba60Sopenharmony_ci        }
59506f6ba60Sopenharmony_ci    }
59606f6ba60Sopenharmony_ci    return 0;
59706f6ba60Sopenharmony_ci}
59806f6ba60Sopenharmony_ci
59906f6ba60Sopenharmony_cistatic int ParseUint32ArrayFlag(const std::string& flag, const std::string& valStr)
60006f6ba60Sopenharmony_ci{
60106f6ba60Sopenharmony_ci    std::vector<uint32_t>* val = (std::vector<uint32_t>*) flags_[flag].addr_;
60206f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
60306f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
60406f6ba60Sopenharmony_ci            if (start == end) {
60506f6ba60Sopenharmony_ci                ++start;
60606f6ba60Sopenharmony_ci                continue;
60706f6ba60Sopenharmony_ci            }
60806f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
60906f6ba60Sopenharmony_ci            char* pos = nullptr;
61006f6ba60Sopenharmony_ci            unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
61106f6ba60Sopenharmony_ci            if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
61206f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
61306f6ba60Sopenharmony_ci                          << " of numeric type should only be assigned with number but "
61406f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
61506f6ba60Sopenharmony_ci                val->clear();
61606f6ba60Sopenharmony_ci                return -1;
61706f6ba60Sopenharmony_ci            }
61806f6ba60Sopenharmony_ci            val->push_back(static_cast<uint32_t>(tmpVal));
61906f6ba60Sopenharmony_ci            start =  end + 1;
62006f6ba60Sopenharmony_ci        }
62106f6ba60Sopenharmony_ci    }
62206f6ba60Sopenharmony_ci    return 0;
62306f6ba60Sopenharmony_ci}
62406f6ba60Sopenharmony_ci
62506f6ba60Sopenharmony_cistatic int ParseUint64ArrayFlag(const std::string& flag, const std::string& valStr)
62606f6ba60Sopenharmony_ci{
62706f6ba60Sopenharmony_ci    std::vector<uint64_t>* val = (std::vector<uint64_t>*) flags_[flag].addr_;
62806f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
62906f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
63006f6ba60Sopenharmony_ci            if (start == end) {
63106f6ba60Sopenharmony_ci                ++start;
63206f6ba60Sopenharmony_ci                continue;
63306f6ba60Sopenharmony_ci            }
63406f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
63506f6ba60Sopenharmony_ci            char* pos = nullptr;
63606f6ba60Sopenharmony_ci            unsigned long long int tmpVal = strtoull(valStr.c_str(), &pos, 10);
63706f6ba60Sopenharmony_ci            if (tmpVal == 0ULL || tmpVal == ULONG_MAX) {
63806f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
63906f6ba60Sopenharmony_ci                          << " of numeric type should only be assigned with number but "
64006f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
64106f6ba60Sopenharmony_ci                val->clear();
64206f6ba60Sopenharmony_ci                return -1;
64306f6ba60Sopenharmony_ci            }
64406f6ba60Sopenharmony_ci            val->push_back(static_cast<uint64_t>(tmpVal));
64506f6ba60Sopenharmony_ci            start =  end + 1;
64606f6ba60Sopenharmony_ci        }
64706f6ba60Sopenharmony_ci    }
64806f6ba60Sopenharmony_ci    return 0;
64906f6ba60Sopenharmony_ci}
65006f6ba60Sopenharmony_ci
65106f6ba60Sopenharmony_cistatic int ParseDoubleArrayFlag(const std::string& flag, const std::string& valStr)
65206f6ba60Sopenharmony_ci{
65306f6ba60Sopenharmony_ci    std::vector<double>* val = (std::vector<double>*) flags_[flag].addr_;
65406f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
65506f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
65606f6ba60Sopenharmony_ci            if (start == end) {
65706f6ba60Sopenharmony_ci                ++start;
65806f6ba60Sopenharmony_ci                continue;
65906f6ba60Sopenharmony_ci            }
66006f6ba60Sopenharmony_ci            auto str = valStr.substr(start, end - start);
66106f6ba60Sopenharmony_ci            char* pos = nullptr;
66206f6ba60Sopenharmony_ci            double tmpVal = strtod(valStr.c_str(), &pos);
66306f6ba60Sopenharmony_ci            if (tmpVal == 0.0 || tmpVal == HUGE_VAL) {
66406f6ba60Sopenharmony_ci                std::cout << "CommandLineFlags ERROR: argument " << flag
66506f6ba60Sopenharmony_ci                          << " of numeric type should only be assigned with number but "
66606f6ba60Sopenharmony_ci                          << valStr << " is given" << std::endl;
66706f6ba60Sopenharmony_ci                val->clear();
66806f6ba60Sopenharmony_ci                return -1;
66906f6ba60Sopenharmony_ci            }
67006f6ba60Sopenharmony_ci            val->push_back(tmpVal);
67106f6ba60Sopenharmony_ci            start =  end + 1;
67206f6ba60Sopenharmony_ci        }
67306f6ba60Sopenharmony_ci    }
67406f6ba60Sopenharmony_ci    return 0;
67506f6ba60Sopenharmony_ci}
67606f6ba60Sopenharmony_ci
67706f6ba60Sopenharmony_cistatic int ParseStringArrayFlag(const std::string& flag, const std::string& valStr)
67806f6ba60Sopenharmony_ci{
67906f6ba60Sopenharmony_ci    std::vector<std::string>* val = (std::vector<std::string>*) flags_[flag].addr_;
68006f6ba60Sopenharmony_ci    for (std::size_t start = 0, end = 0; end <= valStr.length(); ++end) {
68106f6ba60Sopenharmony_ci        if (valStr[end] == ',' or end == valStr.length()) {
68206f6ba60Sopenharmony_ci            if (start == end) {
68306f6ba60Sopenharmony_ci                ++start;
68406f6ba60Sopenharmony_ci                continue;
68506f6ba60Sopenharmony_ci            }
68606f6ba60Sopenharmony_ci            val->emplace_back(valStr.c_str() + start, end - start);
68706f6ba60Sopenharmony_ci            start =  end + 1;
68806f6ba60Sopenharmony_ci        }
68906f6ba60Sopenharmony_ci    }
69006f6ba60Sopenharmony_ci    return 0;
69106f6ba60Sopenharmony_ci}
69206f6ba60Sopenharmony_ci
69306f6ba60Sopenharmony_cistatic int ParseFlag(const std::string& flagName, const std::string flagValue)
69406f6ba60Sopenharmony_ci{
69506f6ba60Sopenharmony_ci    int ret {0};
69606f6ba60Sopenharmony_ci    switch (flags_[flagName].type_) {
69706f6ba60Sopenharmony_ci        case FlagTypes::FT_bool: ret = ParseBoolFlag(flagName, flagValue); break;
69806f6ba60Sopenharmony_ci        case FlagTypes::FT_int8: ret =  ParseInt8Flag(flagName, flagValue); break;
69906f6ba60Sopenharmony_ci        case FlagTypes::FT_int16: ret = ParseInt16Flag(flagName, flagValue); break;
70006f6ba60Sopenharmony_ci        case FlagTypes::FT_int32: ret = ParseInt32Flag(flagName, flagValue); break;
70106f6ba60Sopenharmony_ci        case FlagTypes::FT_int64: ret = ParseInt64Flag(flagName, flagValue); break;
70206f6ba60Sopenharmony_ci        case FlagTypes::FT_uint8: ret = ParseUint8Flag(flagName, flagValue); break;
70306f6ba60Sopenharmony_ci        case FlagTypes::FT_uint16: ret = ParseUint16Flag(flagName, flagValue); break;
70406f6ba60Sopenharmony_ci        case FlagTypes::FT_uint32: ret = ParseUint32Flag(flagName, flagValue); break;
70506f6ba60Sopenharmony_ci        case FlagTypes::FT_uint64: ret = ParseUint64Flag(flagName, flagValue); break;
70606f6ba60Sopenharmony_ci        case FlagTypes::FT_double: ret = ParseDoubleFlag(flagName, flagValue); break;
70706f6ba60Sopenharmony_ci        case FlagTypes::FT_string: ret = ParseStringFlag(flagName, flagValue); break;
70806f6ba60Sopenharmony_ci        case FlagTypes::FT_bool_array: ret = ParseInt8ArrayFlag(flagName, flagValue); break;
70906f6ba60Sopenharmony_ci        case FlagTypes::FT_int8_array: ret = ParseInt8ArrayFlag(flagName, flagValue); break;
71006f6ba60Sopenharmony_ci        case FlagTypes::FT_int16_array: ret = ParseInt16ArrayFlag(flagName, flagValue); break;
71106f6ba60Sopenharmony_ci        case FlagTypes::FT_int32_array: ret = ParseInt32ArrayFlag(flagName, flagValue); break;
71206f6ba60Sopenharmony_ci        case FlagTypes::FT_int64_array: ret = ParseInt64ArrayFlag(flagName, flagValue); break;
71306f6ba60Sopenharmony_ci        case FlagTypes::FT_uint8_array: ret = ParseUint8ArrayFlag(flagName, flagValue); break;
71406f6ba60Sopenharmony_ci        case FlagTypes::FT_uint16_array: ret = ParseUint16ArrayFlag(flagName, flagValue); break;
71506f6ba60Sopenharmony_ci        case FlagTypes::FT_uint32_array: ret = ParseUint32ArrayFlag(flagName, flagValue); break;
71606f6ba60Sopenharmony_ci        case FlagTypes::FT_uint64_array: ret = ParseUint64ArrayFlag(flagName, flagValue); break;
71706f6ba60Sopenharmony_ci        case FlagTypes::FT_double_array: ret = ParseDoubleArrayFlag(flagName, flagValue); break;
71806f6ba60Sopenharmony_ci        case FlagTypes::FT_string_array: ret = ParseStringArrayFlag(flagName, flagValue); break;
71906f6ba60Sopenharmony_ci        default: ret = -1;
72006f6ba60Sopenharmony_ci    }
72106f6ba60Sopenharmony_ci    return ret;
72206f6ba60Sopenharmony_ci}
72306f6ba60Sopenharmony_ci
72406f6ba60Sopenharmony_ciint ParseFlags(int *argc, char ***argv, bool rm = true)
72506f6ba60Sopenharmony_ci{
72606f6ba60Sopenharmony_ci    std::string flagName {};
72706f6ba60Sopenharmony_ci    std::string flagValue {};
72806f6ba60Sopenharmony_ci    int argIndex {1};
72906f6ba60Sopenharmony_ci    if (((*argc) % 2) == 0) { // 2: double
73006f6ba60Sopenharmony_ci        std::cout << "CommandLineFlags ERROE: incorrect number of arguments" << std::endl;
73106f6ba60Sopenharmony_ci        PrintArgFormat();
73206f6ba60Sopenharmony_ci        return -1;
73306f6ba60Sopenharmony_ci    }
73406f6ba60Sopenharmony_ci    while (argIndex < (*argc) - 1) {
73506f6ba60Sopenharmony_ci        if (GetNextFlag(argv, argIndex, rm, flagName, flagValue) != 0) {
73606f6ba60Sopenharmony_ci            // argument format error
73706f6ba60Sopenharmony_ci            return -1;
73806f6ba60Sopenharmony_ci        }
73906f6ba60Sopenharmony_ci        if (flagName.empty() or flags_.count(flagName) == 0) {
74006f6ba60Sopenharmony_ci            // argument removed or undefined, skip it and continue;
74106f6ba60Sopenharmony_ci            continue;
74206f6ba60Sopenharmony_ci        }
74306f6ba60Sopenharmony_ci        if (ParseFlag(flagName, flagValue) != 0) {
74406f6ba60Sopenharmony_ci            // argument value error
74506f6ba60Sopenharmony_ci            return -1;
74606f6ba60Sopenharmony_ci        }
74706f6ba60Sopenharmony_ci    }
74806f6ba60Sopenharmony_ci
74906f6ba60Sopenharmony_ci    return 0;
75006f6ba60Sopenharmony_ci}
75106f6ba60Sopenharmony_ci} // end of namespace CommandLineFlags
75206f6ba60Sopenharmony_ci
75306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_bool(name, default_val, help)                                        \
75406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
75506f6ba60Sopenharmony_cinamespace BoolFlags {                                                               \
75606f6ba60Sopenharmony_ci    static bool FLAGS_##name {default_val};                                         \
75706f6ba60Sopenharmony_ci    static std::string FLAGS_HELP_##name {help};                                    \
75806f6ba60Sopenharmony_ci    static FlagRegesterer<bool> name##_obj {#name, FLAGS_##name};                   \
75906f6ba60Sopenharmony_ci}                                                                                   \
76006f6ba60Sopenharmony_ci}                                                                                   \
76106f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
76206f6ba60Sopenharmony_ci
76306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_int8(name, default_val, help)                                        \
76406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
76506f6ba60Sopenharmony_cinamespace Int8Flags {                                                               \
76606f6ba60Sopenharmony_ci    static int8_t FLAGS_##name {default_val};                                       \
76706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
76806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
76906f6ba60Sopenharmony_ci}                                                                                   \
77006f6ba60Sopenharmony_ci}                                                                                   \
77106f6ba60Sopenharmony_ciusing CommandLineFlags::Int8Flags::FLAGS_##name;
77206f6ba60Sopenharmony_ci
77306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_int16(name, default_val, help)                                       \
77406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
77506f6ba60Sopenharmony_cinamespace Int16Flags {                                                              \
77606f6ba60Sopenharmony_ci    static int16_t FLAGS_##name {default_val};                                      \
77706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
77806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
77906f6ba60Sopenharmony_ci}                                                                                   \
78006f6ba60Sopenharmony_ci}                                                                                   \
78106f6ba60Sopenharmony_ciusing CommandLineFlags::Int16Flags::FLAGS_##name;
78206f6ba60Sopenharmony_ci
78306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_int32(name, default_val, help)                                       \
78406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
78506f6ba60Sopenharmony_cinamespace Int32Flags {                                                              \
78606f6ba60Sopenharmony_ci    static int32_t FLAGS_##name {default_val};                                      \
78706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
78806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
78906f6ba60Sopenharmony_ci}                                                                                   \
79006f6ba60Sopenharmony_ci}                                                                                   \
79106f6ba60Sopenharmony_ciusing CommandLineFlags::Int32Flags::FLAGS_##name;
79206f6ba60Sopenharmony_ci
79306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_int64(name, default_val, help)                                       \
79406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
79506f6ba60Sopenharmony_cinamespace Int64Flags {                                                              \
79606f6ba60Sopenharmony_ci    static int64_t FLAGS_##name {default_val};                                      \
79706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
79806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
79906f6ba60Sopenharmony_ci}                                                                                   \
80006f6ba60Sopenharmony_ci}                                                                                   \
80106f6ba60Sopenharmony_ciusing CommandLineFlags::Int64Flags::FLAGS_##name;
80206f6ba60Sopenharmony_ci
80306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_uint8(name, default_val, help)                                       \
80406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
80506f6ba60Sopenharmony_cinamespace Uint8Flags {                                                              \
80606f6ba60Sopenharmony_ci    static uint8_t FLAGS_##name {default_val};                                      \
80706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
80806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
80906f6ba60Sopenharmony_ci}                                                                                   \
81006f6ba60Sopenharmony_ci}                                                                                   \
81106f6ba60Sopenharmony_ciusing CommandLineFlags::Uint8Flags::FLAGS_##name;
81206f6ba60Sopenharmony_ci
81306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_uint16(name, default_val, help)                                      \
81406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
81506f6ba60Sopenharmony_cinamespace Uint16Flags {                                                             \
81606f6ba60Sopenharmony_ci    static uint16_t FLAGS_##name {default_val};                                     \
81706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
81806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
81906f6ba60Sopenharmony_ci}                                                                                   \
82006f6ba60Sopenharmony_ci}                                                                                   \
82106f6ba60Sopenharmony_ciusing CommandLineFlags::Uint16Flags::FLAGS_##name;
82206f6ba60Sopenharmony_ci
82306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_uint32(name, default_val, help)                                      \
82406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
82506f6ba60Sopenharmony_cinamespace Uint32Flags {                                                             \
82606f6ba60Sopenharmony_ci    static uint32_t FLAGS_##name {default_val};                                     \
82706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
82806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
82906f6ba60Sopenharmony_ci}                                                                                   \
83006f6ba60Sopenharmony_ci}                                                                                   \
83106f6ba60Sopenharmony_ciusing CommandLineFlags::Uint32Flags::FLAGS_##name;
83206f6ba60Sopenharmony_ci
83306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_uint64(name, default_val, help)                                      \
83406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
83506f6ba60Sopenharmony_cinamespace Uint64Flags {                                                             \
83606f6ba60Sopenharmony_ci    static uint64_t FLAGS_##name {default_val};                                     \
83706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
83806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
83906f6ba60Sopenharmony_ci}                                                                                   \
84006f6ba60Sopenharmony_ci}                                                                                   \
84106f6ba60Sopenharmony_ciusing CommandLineFlags::Uint64Flags::FLAGS_##name;
84206f6ba60Sopenharmony_ci
84306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_double(name, default_val, help)                                      \
84406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
84506f6ba60Sopenharmony_cinamespace DoubleFlags {                                                             \
84606f6ba60Sopenharmony_ci    static double FLAGS_##name {default_val};                                       \
84706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
84806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
84906f6ba60Sopenharmony_ci}                                                                                   \
85006f6ba60Sopenharmony_ci}                                                                                   \
85106f6ba60Sopenharmony_ciusing CommandLineFlags::DoubleFlags::FLAGS_##name;
85206f6ba60Sopenharmony_ci
85306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_string(name, default_val, help)                                      \
85406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
85506f6ba60Sopenharmony_cinamespace StringFlags {                                                             \
85606f6ba60Sopenharmony_ci    static std::string FLAGS_##name {default_val};                                  \
85706f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
85806f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
85906f6ba60Sopenharmony_ci}                                                                                   \
86006f6ba60Sopenharmony_ci}                                                                                   \
86106f6ba60Sopenharmony_ciusing CommandLineFlags::StringFlags::FLAGS_##name;
86206f6ba60Sopenharmony_ci
86306f6ba60Sopenharmony_ci#define HIEBPF_DEFINE_array(name, type, help)                                              \
86406f6ba60Sopenharmony_cinamespace CommandLineFlags {                                                        \
86506f6ba60Sopenharmony_cinamespace ArrayFlags {                                                              \
86606f6ba60Sopenharmony_ci    using std::string;                                                              \
86706f6ba60Sopenharmony_ci    static std::vector<type> FLAGS_##name {};                                       \
86806f6ba60Sopenharmony_ci    static std::string FLAGS_##name##_help {help};                                  \
86906f6ba60Sopenharmony_ci    static FlagRegesterer name##_obj {#name, FLAGS_##name};                         \
87006f6ba60Sopenharmony_ci}                                                                                   \
87106f6ba60Sopenharmony_ci}                                                                                   \
87206f6ba60Sopenharmony_ciusing CommandLineFlags::ArrayFlags::FLAGS_##name;
87306f6ba60Sopenharmony_ci
87406f6ba60Sopenharmony_ci#define DECLARE_bool(name)                                                          \
87506f6ba60Sopenharmony_ciextern bool CommandLineFlags::BoolFlags::FLAGS_##name;                              \
87606f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
87706f6ba60Sopenharmony_ci
87806f6ba60Sopenharmony_ci#define DECLARE_int8(name)                                                          \
87906f6ba60Sopenharmony_ciextern int8_t CommandLineFlags::BoolFlags::FLAGS_##name;                            \
88006f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
88106f6ba60Sopenharmony_ci
88206f6ba60Sopenharmony_ci#define DECLARE_int16(name)                                                         \
88306f6ba60Sopenharmony_ciextern int16_t CommandLineFlags::BoolFlags::FLAGS_##name;                           \
88406f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
88506f6ba60Sopenharmony_ci
88606f6ba60Sopenharmony_ci#define DECLARE_int32(name)                                                         \
88706f6ba60Sopenharmony_ciextern int32_t CommandLineFlags::BoolFlags::FLAGS_##name;                           \
88806f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
88906f6ba60Sopenharmony_ci
89006f6ba60Sopenharmony_ci#define DECLARE_int64(name)                                                         \
89106f6ba60Sopenharmony_ciextern int64_t CommandLineFlags::BoolFlags::FLAGS_##name;                           \
89206f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
89306f6ba60Sopenharmony_ci
89406f6ba60Sopenharmony_ci#define DECLARE_uint8(name)                                                         \
89506f6ba60Sopenharmony_ciextern uint8_t CommandLineFlags::BoolFlags::FLAGS_##name;                           \
89606f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
89706f6ba60Sopenharmony_ci
89806f6ba60Sopenharmony_ci#define DECLARE_uint16(name)                                                        \
89906f6ba60Sopenharmony_ciextern uint16_t CommandLineFlags::BoolFlags::FLAGS_##name;                          \
90006f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
90106f6ba60Sopenharmony_ci
90206f6ba60Sopenharmony_ci#define DECLARE_uint32(name)                                                        \
90306f6ba60Sopenharmony_ciextern uint32_t CommandLineFlags::BoolFlags::FLAGS_##name;                          \
90406f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
90506f6ba60Sopenharmony_ci
90606f6ba60Sopenharmony_ci#define DECLARE_uint64(name)                                                        \
90706f6ba60Sopenharmony_ciextern uint64_t CommandLineFlags::BoolFlags::FLAGS_##name;                          \
90806f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
90906f6ba60Sopenharmony_ci
91006f6ba60Sopenharmony_ci#define DECLARE_double(name)                                                        \
91106f6ba60Sopenharmony_ciextern double CommandLineFlags::BoolFlags::FLAGS_##name;                            \
91206f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
91306f6ba60Sopenharmony_ci
91406f6ba60Sopenharmony_ci#define DECLARE_string(name)                                                        \
91506f6ba60Sopenharmony_ciextern std::string CommandLineFlags::BoolFlags::FLAGS_##name;                       \
91606f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
91706f6ba60Sopenharmony_ci
91806f6ba60Sopenharmony_ci#define DECLARE_array(name, type)                                                   \
91906f6ba60Sopenharmony_ciusing std::string;                                                                  \
92006f6ba60Sopenharmony_ciextern std::vector<type> CommandLineFlags::BoolFlags::FLAGS_##name;                 \
92106f6ba60Sopenharmony_ciusing CommandLineFlags::BoolFlags::FLAGS_##name;
92206f6ba60Sopenharmony_ci
92306f6ba60Sopenharmony_ci#endif