You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
4.1 KiB

/**
* @file args.cpp
* Parses command line arguments.
*
* @author Ben Gardner
* @license GPL v2+
*/
#include "args.h"
#include "unc_ctype.h"
#include <cstring>
Args::Args(int argc, char **argv)
{
m_count = argc;
m_values = argv;
size_t len = (argc >> 3) + 1;
m_used = new UINT8[len];
if (m_used != nullptr)
{
memset(m_used, 0, len);
}
}
Args::~Args()
{
if (m_used != nullptr)
{
delete[] m_used;
m_used = nullptr;
}
m_count = 0;
}
bool Args::Present(const char *token)
{
if (token != nullptr)
{
for (size_t idx = 0; idx < m_count; idx++)
{
if (strcmp(token, m_values[idx]) == 0)
{
SetUsed(idx);
return(true);
}
}
}
return(false);
}
const char *Args::Param(const char *token)
{
size_t idx = 0;
return(Params(token, idx));
}
const char *Args::Params(const char *token, size_t &index)
{
if (token == nullptr)
{
// coveralls will complain
// can only occur with a call such as: arg.Param(nullptr)
return(nullptr);
}
size_t token_len = strlen(token);
for (size_t idx = index; idx < m_count; idx++)
{
size_t arg_len = strlen(m_values[idx]);
if ( arg_len >= token_len
&& (memcmp(token, m_values[idx], token_len) == 0))
{
SetUsed(idx);
if (arg_len > token_len)
{
if (m_values[idx][token_len] == '=')
{
token_len++;
}
index = idx + 1;
return(&m_values[idx][token_len]);
}
idx++;
index = idx + 1;
if (idx < m_count)
{
SetUsed(idx);
return(m_values[idx]);
}
return(nullptr);
}
}
return(nullptr);
} // Args::Params
bool Args::GetUsed(size_t idx)
{
if ( m_used != nullptr
&& idx > 0
&& idx < m_count)
{
return((m_used[idx >> 3] & (1 << (idx & 0x07))) != 0);
}
return(false);
}
void Args::SetUsed(size_t idx)
{
if ( m_used != nullptr
&& idx > 0
&& idx < m_count)
{
m_used[idx >> 3] |= (1 << (idx & 0x07));
}
}
const char *Args::Unused(size_t &index)
{
if (m_used == nullptr)
{
return(nullptr);
}
for (size_t idx = index; idx < m_count; idx++)
{
if (!GetUsed(idx))
{
index = idx + 1;
return(m_values[idx]);
}
}
index = m_count;
return(nullptr);
}
size_t Args::SplitLine(char *text, char *args[], size_t num_args)
{
if ( text == nullptr
|| num_args == 0)
{
return(0);
}
char cur_quote = 0;
bool in_backslash = false;
bool in_arg = false;
size_t argc = 0;
char *dest = text;
while ( argc <= num_args // maximal number of arguments not reached yet
&& *text != 0) // end of string not reached yet
{
// Detect the start of an arg
if ( !in_arg
&& !unc_isspace(*text))
{
in_arg = true;
args[argc] = dest;
argc++;
}
if (in_arg)
{
if (in_backslash)
{
in_backslash = false;
*dest = *text;
dest++;
}
else if (*text == '\\')
{
in_backslash = true;
}
else if (*text == cur_quote)
{
cur_quote = 0;
}
else if ( (*text == '\'')
|| (*text == '"')
|| (*text == '`'))
{
cur_quote = *text;
}
else if (cur_quote != 0)
{
*dest = *text;
dest++;
}
else if (unc_isspace(*text))
{
*dest = 0;
dest++;
in_arg = false;
if (argc == num_args)
{
break; // all arguments found, we can stop
}
}
else
{
*dest = *text;
dest++;
}
}
text++; // go on with next character
}
*dest = 0;
return(argc);
} // Args::SplitLine