mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 21:25:11 +00:00
[ADD/WIP] Create and use basic command parser
Still need to write the router.
This commit is contained in:
parent
f434f7aa87
commit
c4b7d1b92a
6 changed files with 220 additions and 12 deletions
133
src/Command/Parser.c
Normal file
133
src/Command/Parser.c
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#include <Command.h>
|
||||
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef enum CommandState {
|
||||
STATE_WHITE,
|
||||
STATE_NAME,
|
||||
STATE_VALUE
|
||||
} CommandState;
|
||||
|
||||
Command *
|
||||
CommandParse(char *cmd)
|
||||
{
|
||||
Command *ret;
|
||||
char *end_data, *cur, *namestart;
|
||||
char *key = NULL, *val = NULL;
|
||||
size_t len;
|
||||
CommandState state = STATE_WHITE;
|
||||
if (!cmd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end_data = strchr(cmd, ' ');
|
||||
if (!end_data)
|
||||
{
|
||||
ret = Malloc(sizeof(*ret));
|
||||
ret->command = StrDuplicate(cmd);
|
||||
ret->arguments = HashMapCreate();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
len = end_data - cmd;
|
||||
ret = Malloc(sizeof(*ret));
|
||||
ret->arguments = HashMapCreate();
|
||||
ret->command = Malloc(len + 1);
|
||||
memcpy(ret->command, cmd, len);
|
||||
ret->command[len] = '\0';
|
||||
|
||||
cur = end_data + 1;
|
||||
|
||||
/* Parse arguments */
|
||||
while (*cur)
|
||||
{
|
||||
char c = *cur;
|
||||
char *tmp;
|
||||
bool type;
|
||||
switch (state)
|
||||
{
|
||||
case STATE_WHITE:
|
||||
if (!isblank(c))
|
||||
{
|
||||
state = STATE_NAME;
|
||||
namestart = cur;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case STATE_NAME:
|
||||
if (c == '=')
|
||||
{
|
||||
len = cur - namestart;
|
||||
key = Malloc(len + 1);
|
||||
memcpy(key, namestart, len);
|
||||
key[len] = '\0';
|
||||
state = STATE_VALUE;
|
||||
cur++;
|
||||
val = NULL;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case STATE_VALUE:
|
||||
type = c == '"';
|
||||
if (type)
|
||||
{
|
||||
cur++;
|
||||
}
|
||||
while (*cur)
|
||||
{
|
||||
char c = *cur;
|
||||
char cb[2] = { c, '\0' };
|
||||
if ((type && c == '"') || (!type && isblank(c)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\\' && *(cur + 1) == '"')
|
||||
{
|
||||
cb[0] = '"';
|
||||
cur++;
|
||||
}
|
||||
tmp = val;
|
||||
val = StrConcat(2, val, cb);
|
||||
Free(tmp);
|
||||
|
||||
cur++;
|
||||
}
|
||||
Free(HashMapSet(ret->arguments, key, val));
|
||||
Free(key);
|
||||
key = NULL;
|
||||
val = NULL;
|
||||
state = STATE_WHITE;
|
||||
break;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
Free(key);
|
||||
Free(val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
CommandFree(Command *command)
|
||||
{
|
||||
char *key, *val;
|
||||
if (!command)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (HashMapIterate(command->arguments, &key, (void **) &val))
|
||||
{
|
||||
Free(val);
|
||||
}
|
||||
HashMapFree(command->arguments);
|
||||
|
||||
Free(command->command);
|
||||
Free(command);
|
||||
}
|
||||
49
src/Command/Router.c
Normal file
49
src/Command/Router.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <Command.h>
|
||||
|
||||
#include <Cytoplasm/Memory.h>
|
||||
|
||||
struct CommandRouter {
|
||||
HashMap *routes;
|
||||
};
|
||||
CommandRouter *
|
||||
CommandCreateRouter(void)
|
||||
{
|
||||
CommandRouter *router = Malloc(sizeof(*router));
|
||||
router->routes = HashMapCreate();
|
||||
return router;
|
||||
}
|
||||
void
|
||||
CommandAddCommand(CommandRouter *rter, char *c, CommandRoute rte)
|
||||
{
|
||||
if (!rter || !c || !rte)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HashMapSet(rter->routes, c, rte);
|
||||
}
|
||||
void
|
||||
RouteCommand(CommandRouter *rter, Command *cmd, void *d)
|
||||
{
|
||||
CommandRoute route;
|
||||
if (!rter || !cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
route = HashMapGet(rter->routes, cmd->command);
|
||||
if (route)
|
||||
{
|
||||
route(cmd, d);
|
||||
}
|
||||
}
|
||||
void
|
||||
CommandFreeRouter(CommandRouter *rter)
|
||||
{
|
||||
if (!rter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HashMapFree(rter->routes);
|
||||
Free(rter);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue