diff options
Diffstat (limited to '3rdparty/bx/src/commandline.cpp')
-rw-r--r-- | 3rdparty/bx/src/commandline.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/3rdparty/bx/src/commandline.cpp b/3rdparty/bx/src/commandline.cpp new file mode 100644 index 00000000000..400e4965a0e --- /dev/null +++ b/3rdparty/bx/src/commandline.cpp @@ -0,0 +1,322 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/commandline.h> +#include <bx/string.h> + +namespace bx +{ + // Reference: + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int32_t& _argc, char* _argv[], int32_t _maxArgvs, char _term) + { + int32_t argc = 0; + const char* curr = _commandLine; + char* currOut = _buffer; + char term = ' '; + bool sub = false; + + enum ParserState + { + SkipWhitespace, + SetTerm, + Copy, + Escape, + End, + }; + + ParserState state = SkipWhitespace; + + while ('\0' != *curr + && _term != *curr + && argc < _maxArgvs) + { + switch (state) + { + case SkipWhitespace: + for (; isSpace(*curr); ++curr) {}; // skip whitespace + state = SetTerm; + break; + + case SetTerm: + if ('"' == *curr) + { + term = '"'; + ++curr; // skip begining quote + } + else + { + term = ' '; + } + + _argv[argc] = currOut; + ++argc; + + state = Copy; + break; + + case Copy: + if ('\\' == *curr) + { + state = Escape; + } + else if ('"' == *curr + && '"' != term) + { + sub = !sub; + } + else if (isSpace(*curr) && !sub) + { + state = End; + } + else if (term != *curr || sub) + { + *currOut = *curr; + ++currOut; + } + else + { + state = End; + } + ++curr; + break; + + case Escape: + { + const char* start = --curr; + for (; '\\' == *curr; ++curr) {}; + + if ('"' != *curr) + { + int32_t count = (int32_t)(curr-start); + + curr = start; + for (int32_t ii = 0; ii < count; ++ii) + { + *currOut = *curr; + ++currOut; + ++curr; + } + } + else + { + curr = start+1; + *currOut = *curr; + ++currOut; + ++curr; + } + } + state = Copy; + break; + + case End: + *currOut = '\0'; + ++currOut; + state = SkipWhitespace; + break; + } + } + + *currOut = '\0'; + if (0 < argc + && '\0' == _argv[argc-1][0]) + { + --argc; + } + + _bufferSize = (uint32_t)(currOut - _buffer); + _argc = argc; + + if ('\0' != *curr) + { + ++curr; + } + + return curr; + } + + CommandLine::CommandLine(int32_t _argc, char const* const* _argv) + : m_argc(_argc) + , m_argv(_argv) + { + } + + const char* CommandLine::findOption(const char* _long, const char* _default) const + { + const char* result = find(0, '\0', _long, 1); + return result == NULL ? _default : result; + } + + const char* CommandLine::findOption(const char _short, const char* _long, const char* _default) const + { + const char* result = find(0, _short, _long, 1); + return result == NULL ? _default : result; + } + + const char* CommandLine::findOption(const char* _long, int32_t _numParams) const + { + const char* result = find(0, '\0', _long, _numParams); + return result; + } + + const char* CommandLine::findOption(const char _short, const char* _long, int32_t _numParams) const + { + const char* result = find(0, _short, _long, _numParams); + return result; + } + + const char* CommandLine::findOption(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const + { + const char* result = find(_skip, _short, _long, _numParams); + return result; + } + + bool CommandLine::hasArg(const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 0); + return NULL != arg; + } + + bool CommandLine::hasArg(const char* _long) const + { + const char* arg = findOption('\0', _long, 0); + return NULL != arg; + } + + bool CommandLine::hasArg(const char*& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + _value = arg; + return NULL != arg; + } + + bool CommandLine::hasArg(int32_t& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atoi(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(uint32_t& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atoi(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(float& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = float(atof(arg)); + return true; + } + + return false; + } + + bool CommandLine::hasArg(double& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atof(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(bool& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + if ('0' == *arg || (0 == strincmp(arg, "false") ) ) + { + _value = false; + } + else if ('0' != *arg || (0 == strincmp(arg, "true") ) ) + { + _value = true; + } + + return true; + } + + return false; + } + + const char* CommandLine::find(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const + { + for (int32_t ii = 0; ii < m_argc; ++ii) + { + const char* arg = m_argv[ii]; + if ('-' == *arg) + { + ++arg; + if (_short == *arg) + { + if (1 == strnlen(arg) ) + { + if (0 == _skip) + { + if (0 == _numParams) + { + return ""; + } + else if (ii+_numParams < m_argc + && '-' != *m_argv[ii+1] ) + { + return m_argv[ii+1]; + } + + return NULL; + } + + --_skip; + ii += _numParams; + } + } + else if (NULL != _long + && '-' == *arg + && 0 == strincmp(arg+1, _long) ) + { + if (0 == _skip) + { + if (0 == _numParams) + { + return ""; + } + else if (ii+_numParams < m_argc + && '-' != *m_argv[ii+1] ) + { + return m_argv[ii+1]; + } + + return NULL; + } + + --_skip; + ii += _numParams; + } + } + } + + return NULL; + } + +} // namespace bx |