#include <bee2/core/blob.h>
#include <bee2/core/err.h>
#include <bee2/core/mem.h>
#include <bee2/core/str.h>
#include <bee2/core/util.h>
#include "bee2/cmd.h"
static size_t argWsDec(const char* args)
{
size_t c = 0;
while (args[c] == ' ' || args[c] == '\t')
++c;
return c;
}
static size_t argArgDec(char* arg, size_t* size, const char* args)
{
size_t c;
size_t s;
bool_t quotes;
ASSERT(strIsValid(args));
ASSERT(memIsNullOrValid(size, O_PER_S));
ASSERT(argWsDec(args) == 0);
for (c = s = 0, quotes = FALSE; args[c] != '\0';)
{
if (!quotes && (args[c] == ' ' || args[c] == '\t'))
break;
if (args[c] == '"')
{
if (!quotes)
++c, quotes = TRUE;
else if (args[c + 1] == '"')
{
if (arg)
arg[s] = '"';
++s, c += 2;
}
else
++c, quotes = FALSE;
continue;
}
if (args[c] == '\\')
{
size_t c1;
for (c1 = 1; args[c + c1] == '\\'; ++c1);
if (args[c + c1] == '"')
{
if (arg)
memCopy(arg + s, args + c, c1 / 2);
s += c1 / 2, c += c1;
if (c1 % 2)
{
if (arg)
arg[s] = '"';
++s, ++c;
}
}
else
{
if (arg)
memCopy(arg + s, args + c, c1);
s += c1, c += c1;
}
continue;
}
if (arg)
arg[s] = args[c];
++s, ++c;
}
ASSERT(!quotes || args[c] == '\0');
if (arg)
arg[s] = '\0';
if (size)
*size = s + 1;
return c + argWsDec(args + c);
}
err_t cmdArgCreate(int* argc, char*** argv, const char* args)
{
size_t count;
size_t size;
int pos;
void* state;
char* strs;
ASSERT(strIsValid(args));
ASSERT(memIsDisjoint2(argc, sizeof(int), argv, sizeof(char**)));
for (*argc = 0, size = 0, count = argWsDec(args); args[count] != '\0';)
{
size_t c;
size_t s;
c = argArgDec(0, &s, args + count);
*argc += 1, count += c, size += s;
}
if (!(state = blobCreate(*argc * sizeof(char*) + size)))
return ERR_OUTOFMEMORY;
*argv = (char**)state;
strs = (char*)(*argv + *argc);
for (size = 0, pos = 0, count = argWsDec(args); args[count] != '\0';)
{
size_t c;
size_t s;
(*argv)[pos] = strs + size;
c = argArgDec((*argv)[pos], &s, args + count);
count += c, size += s, ++pos;
}
ASSERT(pos == *argc);
return ERR_OK;
}
void cmdArgClose(char** argv)
{
blobClose(argv);
}