Implemented support for new instruction format (inbound), simplified instruction parsing.

This commit is contained in:
Michael Jumper 2011-10-19 01:28:18 -07:00
parent 197029c3d8
commit 076b749225
3 changed files with 80 additions and 41 deletions

View File

@ -86,6 +86,11 @@ typedef struct GUACIO {
*/ */
char out_buf[8192]; char out_buf[8192];
/**
* The current location of parsing within the instruction buffer.
*/
int instructionbuf_parse_start;
/** /**
* The current size of the instruction buffer. * The current size of the instruction buffer.
*/ */
@ -103,6 +108,17 @@ typedef struct GUACIO {
*/ */
char* instructionbuf; char* instructionbuf;
/**
* The number of elements parsed so far.
*/
int instructionbuf_elementc;
/**
* Array of pointers into the instruction buffer, where each pointer
* points to the start of the corresponding element.
*/
char* instructionbuf_elementv[64];
} GUACIO; } GUACIO;
/** /**

View File

@ -73,6 +73,8 @@ GUACIO* guac_open(int fd) {
io->instructionbuf_size = 1024; io->instructionbuf_size = 1024;
io->instructionbuf = malloc(io->instructionbuf_size); io->instructionbuf = malloc(io->instructionbuf_size);
io->instructionbuf_used_length = 0; io->instructionbuf_used_length = 0;
io->instructionbuf_parse_start = 0;
io->instructionbuf_elementc = 0;
return io; return io;

View File

@ -359,62 +359,83 @@ int __guac_fill_instructionbuf(GUACIO* io) {
int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) {
int retval; int retval;
int i = 0; int i = io->instructionbuf_parse_start;
int argcount = 0;
int j;
int current_arg = 0;
/* Loop until a instruction is read */ /* Loop until a instruction is read */
for (;;) { for (;;) {
/* Search for end of instruction */ /* Length of element */
for (; i < io->instructionbuf_used_length; i++) { int element_length = 0;
/* Count arguments as we look for the end */ /* Parse instruction in buffe */
if (io->instructionbuf[i] == ',') while (i < io->instructionbuf_used_length) {
argcount++;
else if (io->instructionbuf[i] == ':' && argcount == 0)
argcount++;
/* End found ... */ /* Read character from buffer */
else if (io->instructionbuf[i] == ';') { char c = io->instructionbuf[i++];
/* Parse new instruction */ /* If digit, calculate element length */
char* instruction = malloc(i+1); if (c >= '0' && c <= '9')
memcpy(instruction, io->instructionbuf, i+1); element_length = element_length * 10 + c - '0';
instruction[i] = '\0'; /* Replace semicolon with null terminator. */
parsed_instruction->opcode = NULL; /* Otherwise, if end of length */
else if (c == '.') {
parsed_instruction->argc = argcount; /* Verify element is fully read */
parsed_instruction->argv = malloc(sizeof(char*) * argcount); if (i + element_length < io->instructionbuf_used_length) {
for (j=0; j<i; j++) { /* Get element value */
char* elementv = &(io->instructionbuf[i]);
/* If encountered a colon, and no opcode parsed yet, set opcode and following argument */ /* Get terminator, set null terminator of elementv */
if (instruction[j] == ':' && parsed_instruction->opcode == NULL) { char terminator = elementv[element_length];
instruction[j] = '\0'; elementv[element_length] = '\0';
parsed_instruction->argv[current_arg++] = &(instruction[j+1]);
parsed_instruction->opcode = instruction;
}
/* If encountered a comma, set following argument */ /* Move to terminator of element */
else if (instruction[j] == ',') { i += element_length;
instruction[j] = '\0';
parsed_instruction->argv[current_arg++] = &(instruction[j+1]);
}
}
/* If no arguments, set opcode to entire instruction */ /* Reset element length */
if (parsed_instruction->opcode == NULL) element_length = 0;
parsed_instruction->opcode = instruction;
/* Found. Reset buffer */ /* As element has been read successfully, update
memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1); * parse start */
io->instructionbuf_used_length -= i + 1; io->instructionbuf_parse_start = i;
/* Save element */
io->instructionbuf_elementv[io->instructionbuf_elementc++] = elementv;
/* Finish parse if terminator is a semicolon */
if (terminator == ';') {
int j;
/* Init parsed instruction */
parsed_instruction->argc = io->instructionbuf_elementc - 1;
parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc);
/* Set opcode */
parsed_instruction->opcode = strdup(io->instructionbuf_elementv[0]);
/* Copy element values to parsed instruction */
for (j=0; j<parsed_instruction->argc; j++)
parsed_instruction->argv[j] = strdup(io->instructionbuf_elementv[j+1]);
/* Reset buffer */
memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1);
io->instructionbuf_used_length -= i + 1;
io->instructionbuf_parse_start = 0;
io->instructionbuf_elementc = 0;
/* Done */
return 1;
} /* end if terminator */
} /* end if element fully read */
/* Otherwise, read more data */
else
break;
/* Done */
return 1;
} }
} }