From: Anthony Liguori <anthony@codemonkey.ws>
To: Paolo Bonzini <bonzini@gnu.org>
Cc: qemu-devel@nongnu.org, Vincent Hanquez <vincent@snarc.org>,
Luiz Capitulino <lcapitulino@redhat.com>
Subject: Re: [Qemu-devel] Re: [PATCH 01/10] Introduce qmisc module
Date: Sun, 18 Oct 2009 11:26:22 -0500 [thread overview]
Message-ID: <4ADB41AE.8080103@codemonkey.ws> (raw)
In-Reply-To: <4ADB2B13.4090207@codemonkey.ws>
[-- Attachment #1: Type: text/plain, Size: 886 bytes --]
Anthony Liguori wrote:
> Paolo Bonzini wrote:
>> On 10/18/2009 04:06 PM, Luiz Capitulino wrote:
>>> Integration with QObjects is a killer feature, I think it's the
>>> stronger argument against grabbing one from the internet.
>>
>> Yeah, I'd say let's go with Anthony's stuff. I'll rebase the encoder
>> on top of it soonish (I still think it's best if JSON encoding lies
>> in QObject like a kind of toString). If we'll need the asynchronous
>> parsing later, we can easily replace it with mine or Vincent's.
>
> One thing I want to add as a feature to the 0.12 release is a nice
> client API. To have this, we'll need message boundary identification
> and a JSON encoder. I'll focus on the message boundary identification
> today.
Here's a first pass. I'll clean up this afternoon and post a proper
patch. It turned out to work pretty well.
Regards,
Anthony Liguori
[-- Attachment #2: json-streamer.c --]
[-- Type: text/x-csrc, Size: 8034 bytes --]
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define offset_of(type, member) ((unsigned long)&(((type *)0)->member))
#define container_of(obj, type, member) (type *)((void *)(obj) - offset_of(type, member))
/*
* \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\"
* '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*'
* 0|([1-9][0-9]*(.[0-9]+)?([eE]([-+])?[0-9]+))
* [{}\[\],:]
* [a-z]+
*
*/
enum json_lexer_state {
ERROR = 0,
IN_DONE,
IN_DQ_UCODE3,
IN_DQ_UCODE2,
IN_DQ_UCODE1,
IN_DQ_UCODE0,
IN_DQ_STRING_ESCAPE,
IN_DQ_STRING,
IN_SQ_UCODE3,
IN_SQ_UCODE2,
IN_SQ_UCODE1,
IN_SQ_UCODE0,
IN_SQ_STRING_ESCAPE,
IN_SQ_STRING,
IN_ZERO,
IN_DIGITS,
IN_DIGIT,
IN_EXP_E,
IN_MANTISSA,
IN_MANTISSA_DIGITS,
IN_NONZERO_NUMBER,
IN_NEG_NONZERO_NUMBER,
IN_KEYWORD,
IN_WHITESPACE,
IN_START,
DONE,
SKIP,
};
static const uint8_t json_lexer[][256] = {
[IN_DONE] = {
[1 ... 0x7F] = DONE,
},
/* double quote string */
[IN_DQ_UCODE3] = {
['0' ... '9'] = IN_DQ_STRING,
['a' ... 'f'] = IN_DQ_STRING,
['A' ... 'F'] = IN_DQ_STRING,
},
[IN_DQ_UCODE2] = {
['0' ... '9'] = IN_DQ_UCODE3,
['a' ... 'f'] = IN_DQ_UCODE3,
['A' ... 'F'] = IN_DQ_UCODE3,
},
[IN_DQ_UCODE1] = {
['0' ... '9'] = IN_DQ_UCODE2,
['a' ... 'f'] = IN_DQ_UCODE2,
['A' ... 'F'] = IN_DQ_UCODE2,
},
[IN_DQ_UCODE0] = {
['0' ... '9'] = IN_DQ_UCODE1,
['a' ... 'f'] = IN_DQ_UCODE1,
['A' ... 'F'] = IN_DQ_UCODE1,
},
[IN_DQ_STRING_ESCAPE] = {
['b'] = IN_DQ_STRING,
['f'] = IN_DQ_STRING,
['n'] = IN_DQ_STRING,
['r'] = IN_DQ_STRING,
['t'] = IN_DQ_STRING,
['\''] = IN_DQ_STRING,
['\"'] = IN_DQ_STRING,
['u'] = IN_DQ_UCODE0,
},
[IN_DQ_STRING] = {
[1 ... 0xFF] = IN_DQ_STRING,
['\\'] = IN_DQ_STRING_ESCAPE,
['"'] = IN_DONE,
},
/* single quote string */
[IN_SQ_UCODE3] = {
['0' ... '9'] = IN_SQ_STRING,
['a' ... 'f'] = IN_SQ_STRING,
['A' ... 'F'] = IN_SQ_STRING,
},
[IN_SQ_UCODE2] = {
['0' ... '9'] = IN_SQ_UCODE3,
['a' ... 'f'] = IN_SQ_UCODE3,
['A' ... 'F'] = IN_SQ_UCODE3,
},
[IN_SQ_UCODE1] = {
['0' ... '9'] = IN_SQ_UCODE2,
['a' ... 'f'] = IN_SQ_UCODE2,
['A' ... 'F'] = IN_SQ_UCODE2,
},
[IN_SQ_UCODE0] = {
['0' ... '9'] = IN_SQ_UCODE1,
['a' ... 'f'] = IN_SQ_UCODE1,
['A' ... 'F'] = IN_SQ_UCODE1,
},
[IN_SQ_STRING_ESCAPE] = {
['b'] = IN_SQ_STRING,
['f'] = IN_SQ_STRING,
['n'] = IN_SQ_STRING,
['r'] = IN_SQ_STRING,
['t'] = IN_SQ_STRING,
['\''] = IN_SQ_STRING,
['\"'] = IN_SQ_STRING,
['u'] = IN_SQ_UCODE0,
},
[IN_SQ_STRING] = {
[1 ... 0xFF] = IN_SQ_STRING,
['\\'] = IN_SQ_STRING_ESCAPE,
['\''] = IN_DONE,
},
/* Zero */
[IN_ZERO] = {
[1 ... 0x7F] = DONE,
['0' ... '9'] = ERROR,
},
/* Non-zero numbers */
[IN_DIGITS] = {
[1 ... 0x7F] = DONE,
['0' ... '9'] = IN_DIGITS,
},
[IN_DIGIT] = {
['0' ... '9'] = IN_DIGITS,
},
[IN_EXP_E] = {
['-'] = IN_DIGIT,
['+'] = IN_DIGIT,
['0' ... '9'] = IN_DIGITS,
},
[IN_MANTISSA_DIGITS] = {
[1 ... 0x7F] = DONE,
['0' ... '9'] = IN_MANTISSA_DIGITS,
['e'] = IN_EXP_E,
['E'] = IN_EXP_E,
},
[IN_MANTISSA] = {
['0' ... '9'] = IN_MANTISSA_DIGITS,
},
[IN_NONZERO_NUMBER] = {
[1 ... 0x7F] = DONE,
['0' ... '9'] = IN_NONZERO_NUMBER,
['e'] = IN_EXP_E,
['E'] = IN_EXP_E,
['.'] = IN_MANTISSA,
},
[IN_NEG_NONZERO_NUMBER] = {
['1' ... '9'] = IN_NONZERO_NUMBER,
},
/* keywords */
[IN_KEYWORD] = {
[1 ... 0x7F] = DONE,
['a' ... 'z'] = IN_KEYWORD,
},
/* whitespace */
[IN_WHITESPACE] = {
[1 ... 0x7F] = SKIP,
[' '] = IN_WHITESPACE,
['\t'] = IN_WHITESPACE,
['\r'] = IN_WHITESPACE,
['\n'] = IN_WHITESPACE,
},
/* top level rule */
[IN_START] = {
['"'] = IN_DQ_STRING,
['\''] = IN_SQ_STRING,
['0'] = IN_ZERO,
['1' ... '9'] = IN_NONZERO_NUMBER,
['-'] = IN_NEG_NONZERO_NUMBER,
['{'] = IN_DONE,
['}'] = IN_DONE,
['['] = IN_DONE,
[']'] = IN_DONE,
[','] = IN_DONE,
[':'] = IN_DONE,
['a' ... 'z'] = IN_KEYWORD,
[' '] = IN_WHITESPACE,
['\t'] = IN_WHITESPACE,
['\r'] = IN_WHITESPACE,
['\n'] = IN_WHITESPACE,
},
};
typedef struct JSONLexer
{
void (*emit)(struct JSONLexer *lexer, const char *token);
enum json_lexer_state state;
char token[1024];
size_t len;
} JSONLexer;
void json_lexer_init(JSONLexer *lexer,
void (*func)(JSONLexer *, const char *))
{
lexer->emit = func;
lexer->state = IN_START;
lexer->len = 0;
lexer->token[lexer->len] = 0;
}
int json_lexer_feed(JSONLexer *lexer, char ch)
{
lexer->state = json_lexer[lexer->state][(uint8_t)ch];
if (lexer->state == DONE || lexer->state == SKIP) {
if (lexer->state == DONE) {
lexer->emit(lexer, lexer->token);
}
lexer->state = json_lexer[IN_START][(uint8_t)ch];
lexer->len = 0;
}
if (lexer->state == ERROR) {
return -EINVAL;
}
if (lexer->len < (sizeof(lexer->token) - 1)) {
lexer->token[lexer->len++] = ch;
}
lexer->token[lexer->len] = 0;
return 0;
}
typedef struct JSONMessageParser
{
void (*emit)(struct JSONMessageParser *parser, const char *message);
JSONLexer lexer;
int brace_count;
int bracket_count;
char buffer[1024];
size_t len;
} JSONMessageParser;
static void json_message_process_token(JSONLexer *lexer, const char *token)
{
JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
if (strcmp(token, "{") == 0) {
parser->brace_count++;
} else if (strcmp(token, "}") == 0) {
parser->brace_count--;
} else if (strcmp(token, "[") == 0) {
parser->bracket_count++;
} else if (strcmp(token, "]") == 0) {
parser->bracket_count--;
}
if (parser->brace_count == 0 &&
parser->bracket_count == 0) {
parser->emit(parser, parser->buffer);
parser->len = 0;
}
}
void json_message_parser_init(JSONMessageParser *parser,
void (*func)(JSONMessageParser *, const char *))
{
parser->emit = func;
parser->brace_count = 0;
parser->bracket_count = 0;
parser->len = 0;
parser->buffer[parser->len] = 0;
json_lexer_init(&parser->lexer, json_message_process_token);
}
int json_message_parser_feed(JSONMessageParser *parser,
const char *buffer, size_t size)
{
size_t i;
for (i = 0; i < size; i++) {
int ret;
parser->buffer[parser->len++] = buffer[i];
parser->buffer[parser->len] = 0; /* FIXME overflow */
ret = json_lexer_feed(&parser->lexer, buffer[i]);
if (ret < 0) {
return ret;
}
}
return 0;
}
static void got_message(JSONMessageParser *parser, const char *message)
{
printf("got message `%s'\n", message);
}
int main(int argc, char **argv)
{
JSONMessageParser parser = {};
char buf[2];
int ch;
json_message_parser_init(&parser, got_message);
while ((ch = getchar()) != EOF) {
buf[0] = ch;
buf[1] = 0;
if (json_message_parser_feed(&parser, buf, 1) < 0) {
fprintf(stderr, "Invalid character `%c'\n", ch);
return 1;
}
}
return 0;
}
next prev parent reply other threads:[~2009-10-18 16:26 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-08 21:35 [Qemu-devel] [PATCH v0 00/10]: More QObject conversions Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 01/10] Introduce qmisc module Luiz Capitulino
2009-10-15 14:02 ` Anthony Liguori
2009-10-15 15:26 ` Luiz Capitulino
2009-10-15 15:35 ` Anthony Liguori
2009-10-15 17:17 ` Luiz Capitulino
2009-10-15 18:33 ` Anthony Liguori
2009-10-15 18:45 ` Anthony Liguori
2009-10-15 16:39 ` Daniel P. Berrange
2009-10-15 16:46 ` Daniel P. Berrange
2009-10-15 17:28 ` Luiz Capitulino
2009-10-15 18:34 ` Anthony Liguori
2009-10-16 13:24 ` [Qemu-devel] " Paolo Bonzini
2009-10-16 13:45 ` Anthony Liguori
2009-10-16 17:35 ` Paolo Bonzini
2009-10-16 17:38 ` Anthony Liguori
2009-10-16 19:36 ` Paolo Bonzini
2009-10-16 21:37 ` Anthony Liguori
2009-10-17 0:32 ` Paolo Bonzini
2009-10-17 0:38 ` malc
2009-10-17 0:46 ` Paolo Bonzini
2009-10-17 1:49 ` Anthony Liguori
2009-10-17 1:50 ` Anthony Liguori
2009-10-17 7:48 ` Paolo Bonzini
2009-10-17 10:01 ` Vincent Hanquez
2009-10-18 14:06 ` Luiz Capitulino
2009-10-18 14:08 ` Paolo Bonzini
2009-10-18 14:49 ` Anthony Liguori
2009-10-18 15:18 ` Luiz Capitulino
2009-10-18 15:25 ` Paolo Bonzini
2009-10-18 16:05 ` Luiz Capitulino
2009-10-18 16:32 ` Anthony Liguori
2009-10-18 18:04 ` Paolo Bonzini
2009-10-18 22:00 ` Luiz Capitulino
2009-10-18 16:26 ` Anthony Liguori [this message]
2009-10-18 17:32 ` Vincent Hanquez
2009-10-18 21:24 ` Anthony Liguori
2009-10-18 15:06 ` Vincent Hanquez
2009-10-18 15:35 ` Luiz Capitulino
2009-10-18 15:39 ` Paolo Bonzini
2009-10-18 16:56 ` Vincent Hanquez
2009-10-18 16:29 ` Anthony Liguori
2009-10-18 16:46 ` Vincent Hanquez
2009-10-18 17:59 ` Paolo Bonzini
2009-10-08 21:35 ` [Qemu-devel] [PATCH 02/10] monitor: Convert do_memory_save() to QObject Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 03/10] monitor: Convert do_physical_memory_save() " Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 04/10] monitor: Convert do_migrate() " Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 05/10] monitor: Convert do_migrate_set_speed() " Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 06/10] monitor: Convert do_migrate_cancel() " Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 07/10] monitor: Convert do_info_migrate() " Luiz Capitulino
2009-10-10 12:11 ` Markus Armbruster
2009-10-15 14:07 ` Anthony Liguori
2009-10-08 21:35 ` [Qemu-devel] [PATCH 08/10] monitor: Convert bdrv_info() " Luiz Capitulino
2009-10-10 12:18 ` Markus Armbruster
2009-10-14 13:23 ` Luiz Capitulino
2009-10-14 14:11 ` Markus Armbruster
2009-10-15 14:13 ` Anthony Liguori
2009-10-08 21:35 ` [Qemu-devel] [PATCH 09/10] monitor: Convert pci_device_hot_add() " Luiz Capitulino
2009-10-08 21:35 ` [Qemu-devel] [PATCH 10/10] monitor: Convert do_pci_device_hot_remove() " Luiz Capitulino
2009-10-10 12:31 ` [Qemu-devel] [PATCH v0 00/10]: More QObject conversions Markus Armbruster
2009-10-11 14:48 ` Luiz Capitulino
2009-10-12 15:36 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4ADB41AE.8080103@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=bonzini@gnu.org \
--cc=lcapitulino@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=vincent@snarc.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.