|
|
34b321 |
From 88ee76fed6344de6cede3bfbb3873423e9a90333 Mon Sep 17 00:00:00 2001
|
|
|
34b321 |
From: Markus Armbruster <armbru@redhat.com>
|
|
|
34b321 |
Date: Wed, 27 Jul 2016 07:35:09 +0200
|
|
|
34b321 |
Subject: [PATCH 11/16] qjson: store tokens in a GQueue
|
|
|
34b321 |
|
|
|
34b321 |
RH-Author: Markus Armbruster <armbru@redhat.com>
|
|
|
34b321 |
Message-id: <1469604913-12442-13-git-send-email-armbru@redhat.com>
|
|
|
34b321 |
Patchwork-id: 71478
|
|
|
34b321 |
O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 11/15] qjson: store tokens in a GQueue
|
|
|
34b321 |
Bugzilla: 1276036
|
|
|
34b321 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
34b321 |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
34b321 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
34b321 |
|
|
|
34b321 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
34b321 |
|
|
|
34b321 |
Even though we still have the "streamer" concept, the tokens can now
|
|
|
34b321 |
be deleted as they are read. While doing so convert from QList to
|
|
|
34b321 |
GQueue, since the next step will make tokens not a QObject and we
|
|
|
34b321 |
will have to do the conversion anyway.
|
|
|
34b321 |
|
|
|
34b321 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
34b321 |
Message-Id: <1448300659-23559-4-git-send-email-pbonzini@redhat.com>
|
|
|
34b321 |
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
|
|
34b321 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
34b321 |
(cherry picked from commit 95385fe9ace7db156b924da6b6f5c9082b68ba68)
|
|
|
34b321 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
34b321 |
|
|
|
34b321 |
Conflicts:
|
|
|
34b321 |
monitor.c
|
|
|
34b321 |
|
|
|
34b321 |
Trivial context difference because we lack a small cleanup part of the
|
|
|
34b321 |
(fairly invasive) series b821cbe..489653b.
|
|
|
34b321 |
|
|
|
34b321 |
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
|
|
34b321 |
|
|
|
34b321 |
include/qapi/qmp/json-parser.h | 4 +
|
|
|
34b321 |
include/qapi/qmp/json-streamer.h | 8 ++
|
|
|
34b321 |
monitor.c | 2 +-
|
|
|
34b321 |
qga/main.c | 2 +-
|
|
|
34b321 |
qobject/json-parser.c | 65 +++++++++++++
|
|
|
34b321 |
qobject/json-streamer.c | 25 +++++++++
|
|
|
34b321 |
qobject/qjson.c | 2 +-
|
|
|
34b321 |
tests/libqtest.c | 2 +-
|
|
|
34b321 |
8 files changed, 45 insertions(+), 65 deletions(-)
|
|
|
34b321 |
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 44d88f3..fea89f8 100644
|
|
|
34b321 |
|
|
|
34b321 |
+++ b/include/qapi/qmp/json-parser.h
|
|
|
34b321 |
@@ -18,7 +18,7 @@
|
|
|
34b321 |
#include "qapi/qmp/qlist.h"
|
|
|
34b321 |
#include "qapi/error.h"
|
|
|
34b321 |
|
|
|
34b321 |
-QObject *json_parser_parse(QList *tokens, va_list *ap);
|
|
|
34b321 |
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp);
|
|
|
34b321 |
+QObject *json_parser_parse(GQueue *tokens, va_list *ap);
|
|
|
34b321 |
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp);
|
|
|
34b321 |
|
|
|
34b321 |
#endif
|
|
|
34b321 |
diff
|
|
|
34b321 |
index e901144..e9f2937 100644
|
|
|
34b321 |
|
|
|
34b321 |
+++ b/include/qapi/qmp/json-streamer.h
|
|
|
34b321 |
@@ -15,21 +15,21 @@
|
|
|
34b321 |
#define QEMU_JSON_STREAMER_H
|
|
|
34b321 |
|
|
|
34b321 |
#include <stdint.h>
|
|
|
34b321 |
-#include "qapi/qmp/qlist.h"
|
|
|
34b321 |
+#include "glib-compat.h"
|
|
|
34b321 |
#include "qapi/qmp/json-lexer.h"
|
|
|
34b321 |
|
|
|
34b321 |
typedef struct JSONMessageParser
|
|
|
34b321 |
{
|
|
|
34b321 |
- void (*emit)(struct JSONMessageParser *parser, QList *tokens);
|
|
|
34b321 |
+ void (*emit)(struct JSONMessageParser *parser, GQueue *tokens);
|
|
|
34b321 |
JSONLexer lexer;
|
|
|
34b321 |
int brace_count;
|
|
|
34b321 |
int bracket_count;
|
|
|
34b321 |
- QList *tokens;
|
|
|
34b321 |
+ GQueue *tokens;
|
|
|
34b321 |
uint64_t token_size;
|
|
|
34b321 |
} JSONMessageParser;
|
|
|
34b321 |
|
|
|
34b321 |
void json_message_parser_init(JSONMessageParser *parser,
|
|
|
34b321 |
- void (*func)(JSONMessageParser *, QList *));
|
|
|
34b321 |
+ void (*func)(JSONMessageParser *, GQueue *));
|
|
|
34b321 |
|
|
|
34b321 |
int json_message_parser_feed(JSONMessageParser *parser,
|
|
|
34b321 |
const char *buffer, size_t size);
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 33c5bc8..1b28ff3 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -4514,7 +4514,7 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
|
|
|
34b321 |
qobject_decref(data);
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
-static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
|
|
|
34b321 |
+static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
|
|
|
34b321 |
{
|
|
|
34b321 |
int err;
|
|
|
34b321 |
QObject *obj;
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 0e04e73..7e8f9a0 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -569,7 +569,7 @@ static void process_command(GAState *s, QDict *req)
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
-static void process_event(JSONMessageParser *parser, QList *tokens)
|
|
|
34b321 |
+static void process_event(JSONMessageParser *parser, GQueue *tokens)
|
|
|
34b321 |
{
|
|
|
34b321 |
GAState *s = container_of(parser, GAState, parser);
|
|
|
34b321 |
QObject *obj;
|
|
|
34b321 |
diff
|
|
|
34b321 |
index b242fba..6e5e257 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -27,11 +27,8 @@
|
|
|
34b321 |
typedef struct JSONParserContext
|
|
|
34b321 |
{
|
|
|
34b321 |
Error *err;
|
|
|
34b321 |
- struct {
|
|
|
34b321 |
- QObject **buf;
|
|
|
34b321 |
- size_t pos;
|
|
|
34b321 |
- size_t count;
|
|
|
34b321 |
- } tokens;
|
|
|
34b321 |
+ QObject *current;
|
|
|
34b321 |
+ GQueue *buf;
|
|
|
34b321 |
} JSONParserContext;
|
|
|
34b321 |
|
|
|
34b321 |
#define BUG_ON(cond) assert(!(cond))
|
|
|
34b321 |
@@ -244,56 +241,34 @@ out:
|
|
|
34b321 |
return NULL;
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
+
|
|
|
34b321 |
+ * or parser_context_pop_token is explicitly incref'd, it will be
|
|
|
34b321 |
+ * deleted as soon as parser_context_pop_token is called again.
|
|
|
34b321 |
+ */
|
|
|
34b321 |
static QObject *parser_context_pop_token(JSONParserContext *ctxt)
|
|
|
34b321 |
{
|
|
|
34b321 |
- QObject *token;
|
|
|
34b321 |
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
|
|
|
34b321 |
- token = ctxt->tokens.buf[ctxt->tokens.pos];
|
|
|
34b321 |
- ctxt->tokens.pos++;
|
|
|
34b321 |
- return token;
|
|
|
34b321 |
+ qobject_decref(ctxt->current);
|
|
|
34b321 |
+ assert(!g_queue_is_empty(ctxt->buf));
|
|
|
34b321 |
+ ctxt->current = g_queue_pop_head(ctxt->buf);
|
|
|
34b321 |
+ return ctxt->current;
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
-/* Note: parser_context_{peek|pop}_token do not increment the
|
|
|
34b321 |
- * token object's refcount. In both cases the references will continue
|
|
|
34b321 |
- * to be tracked and cleaned up in parser_context_free(), so do not
|
|
|
34b321 |
- * attempt to free the token object.
|
|
|
34b321 |
- */
|
|
|
34b321 |
static QObject *parser_context_peek_token(JSONParserContext *ctxt)
|
|
|
34b321 |
{
|
|
|
34b321 |
- QObject *token;
|
|
|
34b321 |
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
|
|
|
34b321 |
- token = ctxt->tokens.buf[ctxt->tokens.pos];
|
|
|
34b321 |
- return token;
|
|
|
34b321 |
-}
|
|
|
34b321 |
-
|
|
|
34b321 |
-static void tokens_append_from_iter(QObject *obj, void *opaque)
|
|
|
34b321 |
-{
|
|
|
34b321 |
- JSONParserContext *ctxt = opaque;
|
|
|
34b321 |
- g_assert(ctxt->tokens.pos < ctxt->tokens.count);
|
|
|
34b321 |
- ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
|
|
|
34b321 |
- qobject_incref(obj);
|
|
|
34b321 |
+ assert(!g_queue_is_empty(ctxt->buf));
|
|
|
34b321 |
+ return g_queue_peek_head(ctxt->buf);
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
-static JSONParserContext *parser_context_new(QList *tokens)
|
|
|
34b321 |
+static JSONParserContext *parser_context_new(GQueue *tokens)
|
|
|
34b321 |
{
|
|
|
34b321 |
JSONParserContext *ctxt;
|
|
|
34b321 |
- size_t count;
|
|
|
34b321 |
|
|
|
34b321 |
if (!tokens) {
|
|
|
34b321 |
return NULL;
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
- count = qlist_size(tokens);
|
|
|
34b321 |
- if (count == 0) {
|
|
|
34b321 |
- return NULL;
|
|
|
34b321 |
- }
|
|
|
34b321 |
-
|
|
|
34b321 |
ctxt = g_malloc0(sizeof(JSONParserContext));
|
|
|
34b321 |
- ctxt->tokens.pos = 0;
|
|
|
34b321 |
- ctxt->tokens.count = count;
|
|
|
34b321 |
- ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
|
|
|
34b321 |
- qlist_iter(tokens, tokens_append_from_iter, ctxt);
|
|
|
34b321 |
- ctxt->tokens.pos = 0;
|
|
|
34b321 |
+ ctxt->buf = tokens;
|
|
|
34b321 |
|
|
|
34b321 |
return ctxt;
|
|
|
34b321 |
}
|
|
|
34b321 |
@@ -301,12 +276,12 @@ static JSONParserContext *parser_context_new(QList *tokens)
|
|
|
34b321 |
|
|
|
34b321 |
static void parser_context_free(JSONParserContext *ctxt)
|
|
|
34b321 |
{
|
|
|
34b321 |
- int i;
|
|
|
34b321 |
if (ctxt) {
|
|
|
34b321 |
- for (i = 0; i < ctxt->tokens.count; i++) {
|
|
|
34b321 |
- qobject_decref(ctxt->tokens.buf[i]);
|
|
|
34b321 |
+ while (!g_queue_is_empty(ctxt->buf)) {
|
|
|
34b321 |
+ parser_context_pop_token(ctxt);
|
|
|
34b321 |
}
|
|
|
34b321 |
- g_free(ctxt->tokens.buf);
|
|
|
34b321 |
+ qobject_decref(ctxt->current);
|
|
|
34b321 |
+ g_queue_free(ctxt->buf);
|
|
|
34b321 |
g_free(ctxt);
|
|
|
34b321 |
}
|
|
|
34b321 |
}
|
|
|
34b321 |
@@ -597,12 +572,12 @@ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
|
|
|
34b321 |
}
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
-QObject *json_parser_parse(QList *tokens, va_list *ap)
|
|
|
34b321 |
+QObject *json_parser_parse(GQueue *tokens, va_list *ap)
|
|
|
34b321 |
{
|
|
|
34b321 |
return json_parser_parse_err(tokens, ap, NULL);
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
|
|
|
34b321 |
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
|
|
|
34b321 |
{
|
|
|
34b321 |
JSONParserContext *ctxt = parser_context_new(tokens);
|
|
|
34b321 |
QObject *result;
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 7292f3a..f7a3e78 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -22,6 +22,14 @@
|
|
|
34b321 |
#define MAX_TOKEN_SIZE (64ULL << 20)
|
|
|
34b321 |
#define MAX_NESTING (1ULL << 10)
|
|
|
34b321 |
|
|
|
34b321 |
+static void json_message_free_tokens(JSONMessageParser *parser)
|
|
|
34b321 |
+{
|
|
|
34b321 |
+ if (parser->tokens) {
|
|
|
34b321 |
+ g_queue_free(parser->tokens);
|
|
|
34b321 |
+ parser->tokens = NULL;
|
|
|
34b321 |
+ }
|
|
|
34b321 |
+}
|
|
|
34b321 |
+
|
|
|
34b321 |
static void json_message_process_token(JSONLexer *lexer, GString *input,
|
|
|
34b321 |
JSONTokenType type, int x, int y)
|
|
|
34b321 |
{
|
|
|
34b321 |
@@ -53,7 +61,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
|
|
|
34b321 |
|
|
|
34b321 |
parser->token_size += input->len;
|
|
|
34b321 |
|
|
|
34b321 |
- qlist_append(parser->tokens, dict);
|
|
|
34b321 |
+ g_queue_push_tail(parser->tokens, dict);
|
|
|
34b321 |
|
|
|
34b321 |
if (type == JSON_ERROR) {
|
|
|
34b321 |
goto out_emit_bad;
|
|
|
34b321 |
@@ -77,27 +85,24 @@ out_emit_bad:
|
|
|
34b321 |
* Clear out token list and tell the parser to emit an error
|
|
|
34b321 |
* indication by passing it a NULL list
|
|
|
34b321 |
*/
|
|
|
34b321 |
- QDECREF(parser->tokens);
|
|
|
34b321 |
- parser->tokens = NULL;
|
|
|
34b321 |
+ json_message_free_tokens(parser);
|
|
|
34b321 |
out_emit:
|
|
|
34b321 |
/* send current list of tokens to parser and reset tokenizer */
|
|
|
34b321 |
parser->brace_count = 0;
|
|
|
34b321 |
parser->bracket_count = 0;
|
|
|
34b321 |
+ /* parser->emit takes ownership of parser->tokens. */
|
|
|
34b321 |
parser->emit(parser, parser->tokens);
|
|
|
34b321 |
- if (parser->tokens) {
|
|
|
34b321 |
- QDECREF(parser->tokens);
|
|
|
34b321 |
- }
|
|
|
34b321 |
- parser->tokens = qlist_new();
|
|
|
34b321 |
+ parser->tokens = g_queue_new();
|
|
|
34b321 |
parser->token_size = 0;
|
|
|
34b321 |
}
|
|
|
34b321 |
|
|
|
34b321 |
void json_message_parser_init(JSONMessageParser *parser,
|
|
|
34b321 |
- void (*func)(JSONMessageParser *, QList *))
|
|
|
34b321 |
+ void (*func)(JSONMessageParser *, GQueue *))
|
|
|
34b321 |
{
|
|
|
34b321 |
parser->emit = func;
|
|
|
34b321 |
parser->brace_count = 0;
|
|
|
34b321 |
parser->bracket_count = 0;
|
|
|
34b321 |
- parser->tokens = qlist_new();
|
|
|
34b321 |
+ parser->tokens = g_queue_new();
|
|
|
34b321 |
parser->token_size = 0;
|
|
|
34b321 |
|
|
|
34b321 |
json_lexer_init(&parser->lexer, json_message_process_token);
|
|
|
34b321 |
@@ -117,5 +122,5 @@ int json_message_parser_flush(JSONMessageParser *parser)
|
|
|
34b321 |
void json_message_parser_destroy(JSONMessageParser *parser)
|
|
|
34b321 |
{
|
|
|
34b321 |
json_lexer_destroy(&parser->lexer);
|
|
|
34b321 |
- QDECREF(parser->tokens);
|
|
|
34b321 |
+ json_message_free_tokens(parser);
|
|
|
34b321 |
}
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 6cf2511..fdc274a 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -28,7 +28,7 @@ typedef struct JSONParsingState
|
|
|
34b321 |
QObject *result;
|
|
|
34b321 |
} JSONParsingState;
|
|
|
34b321 |
|
|
|
34b321 |
-static void parse_json(JSONMessageParser *parser, QList *tokens)
|
|
|
34b321 |
+static void parse_json(JSONMessageParser *parser, GQueue *tokens)
|
|
|
34b321 |
{
|
|
|
34b321 |
JSONParsingState *s = container_of(parser, JSONParsingState, parser);
|
|
|
34b321 |
s->result = json_parser_parse(tokens, s->ap);
|
|
|
34b321 |
diff
|
|
|
34b321 |
index 359d571..69b7cd6 100644
|
|
|
34b321 |
|
|
|
34b321 |
|
|
|
34b321 |
@@ -299,7 +299,7 @@ typedef struct {
|
|
|
34b321 |
QDict *response;
|
|
|
34b321 |
} QMPResponseParser;
|
|
|
34b321 |
|
|
|
34b321 |
-static void qmp_response(JSONMessageParser *parser, QList *tokens)
|
|
|
34b321 |
+static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
|
|
|
34b321 |
{
|
|
|
34b321 |
QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
|
|
|
34b321 |
QObject *obj;
|
|
|
34b321 |
--
|
|
|
34b321 |
1.8.3.1
|
|
|
34b321 |
|