| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /*
- * Copyright 2010-2018 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
- */
- #include "bx_p.h"
- #include <bx/commandline.h>
- #include <bx/string.h>
- namespace bx
- {
- // Reference:
- // - https://web.archive.org/web/20180629044234/https://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, int32_t(0) );
- return NULL != arg;
- }
- bool CommandLine::hasArg(const char* _long) const
- {
- const char* arg = findOption('\0', _long, int32_t(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)
- {
- fromString(&_value, 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)
- {
- fromString(&_value, 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)
- {
- fromString(&_value, 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)
- {
- fromString(&_value, 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 == strCmpI(arg, "false") ) )
- {
- _value = false;
- }
- else if ('0' != *arg || (0 == strCmpI(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 && 0 != strCmp(m_argv[ii], "--"); ++ii)
- {
- const char* arg = m_argv[ii];
- if ('-' == *arg)
- {
- ++arg;
- if (_short == *arg)
- {
- if (1 == strLen(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 == strCmpI(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;
- }
- int32_t CommandLine::getNum() const
- {
- return m_argc;
- }
- char const* CommandLine::get(int32_t _idx) const
- {
- return m_argv[_idx];
- }
- } // namespace bx
|