int guac_parser_append()

in src/libguac/parser.c [59:165]


int guac_parser_append(guac_parser* parser, void* buffer, int length) {

    char* char_buffer = (char*) buffer;
    int bytes_parsed = 0;

    /* Do not exceed maximum number of elements */
    if (parser->__elementc == GUAC_INSTRUCTION_MAX_ELEMENTS
            && parser->state != GUAC_PARSE_COMPLETE) {
        parser->state = GUAC_PARSE_ERROR;
        return 0;
    }

    /* Parse element length */
    if (parser->state == GUAC_PARSE_LENGTH) {

        int parsed_length = parser->__element_length;
        while (bytes_parsed < length) {

            /* Pull next character */
            char c = *(char_buffer++);
            bytes_parsed++;

            /* If digit, add to length */
            if (c >= '0' && c <= '9')
                parsed_length = parsed_length*10 + c - '0';

            /* If period, switch to parsing content */
            else if (c == '.') {
                parser->__elementv[parser->__elementc++] = char_buffer;
                parser->state = GUAC_PARSE_CONTENT;
                break;
            }

            /* If not digit, parse error */
            else {
                parser->state = GUAC_PARSE_ERROR;
                return 0;
            }

        }

        /* If too long, parse error */
        if (parsed_length > GUAC_INSTRUCTION_MAX_LENGTH) {
            parser->state = GUAC_PARSE_ERROR;
            return 0;
        }

        /* Save length */
        parser->__element_length = parsed_length;

    } /* end parse length */

    /* Parse element content */
    if (parser->state == GUAC_PARSE_CONTENT) {

        while (bytes_parsed < length && parser->__element_length >= 0) {

            /* Get length of current character */
            char c = *char_buffer;
            int char_length = guac_utf8_charsize((unsigned char) c);

            /* If full character not present in buffer, stop now */
            if (char_length + bytes_parsed > length)
                break;

            /* Record character as parsed */
            bytes_parsed += char_length;

            /* If end of element, handle terminator */
            if (parser->__element_length == 0) {

                *char_buffer = '\0';

                /* If semicolon, store end-of-instruction */
                if (c == ';') {
                    parser->state = GUAC_PARSE_COMPLETE;
                    parser->opcode = parser->__elementv[0];
                    parser->argv = &(parser->__elementv[1]);
                    parser->argc = parser->__elementc - 1;
                    break;
                }

                /* If comma, move on to next element */
                else if (c == ',') {
                    parser->state = GUAC_PARSE_LENGTH;
                    break;
                }

                /* Otherwise, parse error */
                else {
                    parser->state = GUAC_PARSE_ERROR;
                    return 0;
                }

            } /* end if end of element */

            /* Advance to next character */
            parser->__element_length--;
            char_buffer += char_length;

        }

    } /* end parse content */

    return bytes_parsed;

}