Download third_party/ktx-src/utils/argparser.cpp from kimjunhan/vkgs-sim: direct link, hf CLI and curl.
- Browser
- Download file 4.91 kB
-
https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/third_party/ktx-src/utils/argparser.cpp
- Command line
-
hf download hf://kimjunhan/vkgs-sim/third_party/ktx-src/utils/argparser.cpp
-
curl -L -o argparser.cpp https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/third_party/ktx-src/utils/argparser.cpp
4.91 kB
| /* -*- tab-width: 4; -*- */ | |
| /* vi: set sw=2 ts=4 expandtab: */ | |
| /* | |
| * Copyright 2017-2020 Mark Callow, github.com/MarkCallow. | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| /** | |
| * @internal | |
| * @class argparser | |
| * @~English | |
| * | |
| * @brief parse a command argument list. | |
| * | |
| * Can't use getopt_long because it declares argv as char* const*. We | |
| * need const char* const* when we're parsing an embedded string. Also | |
| * Windows C library does not have getopt_long. | |
| * | |
| * @author Mark Callow, github.com/MarkCallow. | |
| */ | |
| using namespace std; | |
| /* | |
| * Construct from a string of arguments. | |
| */ | |
| argvector::argvector(const string& sArgs) | |
| { | |
| const string sep(" \t"); | |
| // std::regex does not support negative lookbehind assertions. Darn! | |
| // RE to extract argument between string start and separator. | |
| // - Match 0 is whole matching string including separator. | |
| // - Match 1 is the argument. | |
| // - Match 2 is an empty string or a backslash. | |
| // Use negative character class as it is easiest way to handle | |
| // utf-8 file names with non-Latin characters. $ must not be last | |
| // in the character class or it will be taken literally not as | |
| // end of string. | |
| // Use raw literal to avoid excess backslashes. | |
| regex re(R"--(^([^$\\ \t]+)(\\?)(?:[ \t]+|$))--"); | |
| size_t pos; | |
| pos = sArgs.find_first_not_of(sep); | |
| assert(pos != string::npos); | |
| auto first = sArgs.begin() + pos; | |
| auto last = sArgs.end(); | |
| bool continuation = false; | |
| for (smatch sm; regex_search(first, last, sm, re);) { | |
| bool needContinuation = false; | |
| std::cout << "prefix: " << sm.prefix() << '\n'; | |
| std::cout << "suffix: " << sm.suffix() << '\n'; | |
| std::cout << "match size: " << sm.size() << '\n'; | |
| for(uint32_t i = 0; i < sm.size(); i++) { | |
| std::cout << "match " << i << ": " << "\"" << sm.str(i) << "\"" << '\n'; | |
| } | |
| string arg; | |
| // All this because std::regex does not support negative | |
| // lookbehind assertions. | |
| arg = sm.str(1); | |
| if (sm.str(2)[0] == '\\') { | |
| arg += " "; | |
| needContinuation = true; | |
| } | |
| if (continuation) { | |
| this->back() += arg; | |
| } else { | |
| push_back(arg); | |
| } | |
| continuation = needContinuation; | |
| first = sm.suffix().first; | |
| } | |
| } | |
| /* | |
| * Construct from an array of C strings | |
| */ | |
| argvector::argvector(int argc, const char* const* argv) | |
| { | |
| for (int i = 0; i < argc; i++) { | |
| push_back(argv[i]); | |
| } | |
| } | |
| /* | |
| * Functions the same as getopt_long. See `man 3 getopt_long`. | |
| */ | |
| int | |
| argparser::getopt(string* shortopts, const struct option* longopts, | |
| int* /*longindex*/) | |
| { | |
| if (optind == argv.size()) | |
| return -1; | |
| string arg; | |
| arg = argv[optind]; | |
| if (arg[0] != '-' || (arg[0] == '-' && arg.size() == 1)) | |
| return -1; | |
| optind++; | |
| int retval = '?'; | |
| if (arg.compare(0, 2, "--") == 0) { | |
| if (arg.size() == 2) return -1; // " -- " separates options and files | |
| const struct option* opt = longopts; | |
| while (opt->name != nullptr) { | |
| if (arg.compare(2, string::npos, opt->name) == 0) { | |
| retval = opt->val; | |
| if (opt->has_arg != option::no_argument) { | |
| if (optind >= argv.size() || (optarg = argv[optind++])[0] == '-') { | |
| optarg.clear(); | |
| optind--; | |
| if (opt->has_arg == option::required_argument) | |
| retval = ':'; | |
| } | |
| } | |
| if (opt->flag != nullptr) { | |
| *opt->flag = opt->val; | |
| retval = 0; | |
| } | |
| break; | |
| } | |
| opt++; | |
| } | |
| } else if (shortopts != nullptr && arg.compare(0, 1, "-") == 0) { | |
| size_t pos = shortopts->find(arg.substr(1, 1)); | |
| if (pos != string::npos) { | |
| retval = (*shortopts)[pos]; | |
| if (pos < shortopts->length() | |
| && ((*shortopts)[++pos] == ':' || (*shortopts)[pos] == ';')) { | |
| if (optind >= argv.size() || (optarg = argv[optind++])[0] == '-') { | |
| optarg.clear(); | |
| optind--; | |
| if ((*shortopts)[pos] == ':') // required argument | |
| retval = ':'; | |
| } | |
| } | |
| } | |
| } | |
| return retval; | |
| } | |
| //================== Helper for apps' processArgs ======================== | |
| std::istream& operator >> (std::istream& stream, const skip& x) | |
| { | |
| std::ios_base::fmtflags f = stream.flags(); | |
| stream >> std::noskipws; | |
| char c; | |
| const char* text = x.text; | |
| while (stream && *text++) | |
| stream >> c; | |
| stream.flags(f); | |
| return stream; | |
| } | |