#include "qapi/qmp/qlist.h"
#include "qapi/error.h"
-QObject *json_parser_parse(QList *tokens, va_list *ap);
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp);
+QObject *json_parser_parse(GQueue *tokens, va_list *ap);
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp);
#endif
#define QEMU_JSON_STREAMER_H
#include <stdint.h>
-#include "qapi/qmp/qlist.h"
+#include "glib-compat.h"
#include "qapi/qmp/json-lexer.h"
typedef struct JSONMessageParser
{
- void (*emit)(struct JSONMessageParser *parser, QList *tokens);
+ void (*emit)(struct JSONMessageParser *parser, GQueue *tokens);
JSONLexer lexer;
int brace_count;
int bracket_count;
- QList *tokens;
+ GQueue *tokens;
uint64_t token_size;
} JSONMessageParser;
void json_message_parser_init(JSONMessageParser *parser,
- void (*func)(JSONMessageParser *, QList *));
+ void (*func)(JSONMessageParser *, GQueue *));
int json_message_parser_feed(JSONMessageParser *parser,
const char *buffer, size_t size);
return input_dict;
}
-static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
+static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
{
Error *local_err = NULL;
QObject *obj, *data;
}
/* handle requests/control events coming in over the channel */
-static void process_event(JSONMessageParser *parser, QList *tokens)
+static void process_event(JSONMessageParser *parser, GQueue *tokens)
{
GAState *s = container_of(parser, GAState, parser);
QDict *qdict;
typedef struct JSONParserContext
{
Error *err;
- struct {
- QObject **buf;
- size_t pos;
- size_t count;
- } tokens;
+ QObject *current;
+ GQueue *buf;
} JSONParserContext;
#define BUG_ON(cond) assert(!(cond))
return NULL;
}
+/* Note: unless the token object returned by parser_context_peek_token
+ * or parser_context_pop_token is explicitly incref'd, it will be
+ * deleted as soon as parser_context_pop_token is called again.
+ */
static QObject *parser_context_pop_token(JSONParserContext *ctxt)
{
- QObject *token;
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
- token = ctxt->tokens.buf[ctxt->tokens.pos];
- ctxt->tokens.pos++;
- return token;
+ qobject_decref(ctxt->current);
+ assert(!g_queue_is_empty(ctxt->buf));
+ ctxt->current = g_queue_pop_head(ctxt->buf);
+ return ctxt->current;
}
-/* Note: parser_context_{peek|pop}_token do not increment the
- * token object's refcount. In both cases the references will continue
- * to be tracked and cleaned up in parser_context_free(), so do not
- * attempt to free the token object.
- */
static QObject *parser_context_peek_token(JSONParserContext *ctxt)
{
- QObject *token;
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
- token = ctxt->tokens.buf[ctxt->tokens.pos];
- return token;
-}
-
-static void tokens_append_from_iter(QObject *obj, void *opaque)
-{
- JSONParserContext *ctxt = opaque;
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
- ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
- qobject_incref(obj);
+ assert(!g_queue_is_empty(ctxt->buf));
+ return g_queue_peek_head(ctxt->buf);
}
-static JSONParserContext *parser_context_new(QList *tokens)
+static JSONParserContext *parser_context_new(GQueue *tokens)
{
JSONParserContext *ctxt;
- size_t count;
if (!tokens) {
return NULL;
}
- count = qlist_size(tokens);
- if (count == 0) {
- return NULL;
- }
-
ctxt = g_malloc0(sizeof(JSONParserContext));
- ctxt->tokens.pos = 0;
- ctxt->tokens.count = count;
- ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
- qlist_iter(tokens, tokens_append_from_iter, ctxt);
- ctxt->tokens.pos = 0;
+ ctxt->buf = tokens;
return ctxt;
}
/* to support error propagation, ctxt->err must be freed separately */
static void parser_context_free(JSONParserContext *ctxt)
{
- int i;
if (ctxt) {
- for (i = 0; i < ctxt->tokens.count; i++) {
- qobject_decref(ctxt->tokens.buf[i]);
+ while (!g_queue_is_empty(ctxt->buf)) {
+ parser_context_pop_token(ctxt);
}
- g_free(ctxt->tokens.buf);
+ qobject_decref(ctxt->current);
+ g_queue_free(ctxt->buf);
g_free(ctxt);
}
}
}
}
-QObject *json_parser_parse(QList *tokens, va_list *ap)
+QObject *json_parser_parse(GQueue *tokens, va_list *ap)
{
return json_parser_parse_err(tokens, ap, NULL);
}
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
{
JSONParserContext *ctxt = parser_context_new(tokens);
QObject *result;
#define MAX_TOKEN_SIZE (64ULL << 20)
#define MAX_NESTING (1ULL << 10)
+static void json_message_free_tokens(JSONMessageParser *parser)
+{
+ if (parser->tokens) {
+ g_queue_free(parser->tokens);
+ parser->tokens = NULL;
+ }
+}
+
static void json_message_process_token(JSONLexer *lexer, GString *input,
JSONTokenType type, int x, int y)
{
parser->token_size += input->len;
- qlist_append(parser->tokens, dict);
+ g_queue_push_tail(parser->tokens, dict);
if (type == JSON_ERROR) {
goto out_emit_bad;
* Clear out token list and tell the parser to emit an error
* indication by passing it a NULL list
*/
- QDECREF(parser->tokens);
- parser->tokens = NULL;
+ json_message_free_tokens(parser);
out_emit:
/* send current list of tokens to parser and reset tokenizer */
parser->brace_count = 0;
parser->bracket_count = 0;
+ /* parser->emit takes ownership of parser->tokens. */
parser->emit(parser, parser->tokens);
- if (parser->tokens) {
- QDECREF(parser->tokens);
- }
- parser->tokens = qlist_new();
+ parser->tokens = g_queue_new();
parser->token_size = 0;
}
void json_message_parser_init(JSONMessageParser *parser,
- void (*func)(JSONMessageParser *, QList *))
+ void (*func)(JSONMessageParser *, GQueue *))
{
parser->emit = func;
parser->brace_count = 0;
parser->bracket_count = 0;
- parser->tokens = qlist_new();
+ parser->tokens = g_queue_new();
parser->token_size = 0;
json_lexer_init(&parser->lexer, json_message_process_token);
void json_message_parser_destroy(JSONMessageParser *parser)
{
json_lexer_destroy(&parser->lexer);
- QDECREF(parser->tokens);
+ json_message_free_tokens(parser);
}
QObject *result;
} JSONParsingState;
-static void parse_json(JSONMessageParser *parser, QList *tokens)
+static void parse_json(JSONMessageParser *parser, GQueue *tokens)
{
JSONParsingState *s = container_of(parser, JSONParsingState, parser);
s->result = json_parser_parse(tokens, s->ap);
QDict *response;
} QMPResponseParser;
-static void qmp_response(JSONMessageParser *parser, QList *tokens)
+static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
{
QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
QObject *obj;