aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/msgpack_rpc/unpacker.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/msgpack_rpc/unpacker.c')
-rw-r--r--src/nvim/msgpack_rpc/unpacker.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c
index e60d9f220f..419349e74d 100644
--- a/src/nvim/msgpack_rpc/unpacker.c
+++ b/src/nvim/msgpack_rpc/unpacker.c
@@ -3,6 +3,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/log.h"
+#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/unpacker.h"
@@ -10,6 +11,10 @@
# include "msgpack_rpc/unpacker.c.generated.h"
#endif
+#define kv_fixsize_arena(a, v, s) \
+ ((v).capacity = (s), \
+ (v).items = (void *)arena_alloc(a, sizeof((v).items[0]) * (v).capacity, true))
+
Object unpack(const char *data, size_t size, Error *err)
{
Unpacker unpacker;
@@ -34,7 +39,7 @@ Object unpack(const char *data, size_t size, Error *err)
static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
{
- Unpacker *unpacker = parser->data.p;
+ Unpacker *p = parser->data.p;
Object *result = NULL;
String *key_location = NULL;
@@ -69,7 +74,7 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
abort();
}
} else {
- result = &unpacker->result;
+ result = &p->result;
}
switch (node->tok.type) {
@@ -88,16 +93,17 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
case MPACK_TOKEN_FLOAT:
*result = FLOAT_OBJ(mpack_unpack_float(node->tok));
break;
+
case MPACK_TOKEN_BIN:
case MPACK_TOKEN_STR: {
- String str = { .data = xmallocz(node->tok.length), .size = node->tok.length };
-
+ char *mem = arena_alloc(&p->arena, node->tok.length + 1, false);
+ mem[node->tok.length] = NUL;
+ String str = { .data = mem, .size = node->tok.length };
if (key_location) {
*key_location = str;
} else {
*result = STRING_OBJ(str);
}
-
node->data[0].p = str.data;
break;
}
@@ -105,7 +111,6 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
// handled in chunk; but save result location
node->data[0].p = result;
break;
-
case MPACK_TOKEN_CHUNK:
assert(parent);
if (parent->tok.type == MPACK_TOKEN_STR || parent->tok.type == MPACK_TOKEN_BIN) {
@@ -120,12 +125,12 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
*res = NIL;
break;
}
- memcpy(unpacker->ext_buf + parent->pos,
+ memcpy(p->ext_buf + parent->pos,
node->tok.data.chunk_ptr, node->tok.length);
if (parent->pos + node->tok.length < parent->tok.length) {
break; // EOF, let's get back to it later
}
- const char *buf = unpacker->ext_buf;
+ const char *buf = p->ext_buf;
size_t size = parent->tok.length;
mpack_token_t ext_tok;
int status = mpack_rtoken(&buf, &size, &ext_tok);
@@ -148,7 +153,7 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
case MPACK_TOKEN_ARRAY: {
Array arr = KV_INITIAL_VALUE;
- kv_resize(arr, node->tok.length);
+ kv_fixsize_arena(&p->arena, arr, node->tok.length);
kv_size(arr) = node->tok.length;
*result = ARRAY_OBJ(arr);
node->data[0].p = result;
@@ -156,12 +161,13 @@ static void api_parse_enter(mpack_parser_t *parser, mpack_node_t *node)
}
case MPACK_TOKEN_MAP: {
Dictionary dict = KV_INITIAL_VALUE;
- kv_resize(dict, node->tok.length);
+ kv_fixsize_arena(&p->arena, dict, node->tok.length);
kv_size(dict) = node->tok.length;
*result = DICTIONARY_OBJ(dict);
node->data[0].p = result;
break;
}
+
default:
abort();
}
@@ -176,6 +182,15 @@ void unpacker_init(Unpacker *p)
p->parser.data.p = p;
mpack_tokbuf_init(&p->reader);
p->unpack_error = (Error)ERROR_INIT;
+
+ p->arena = (Arena)ARENA_EMPTY;
+ p->reuse_blk = NULL;
+}
+
+void unpacker_teardown(Unpacker *p)
+{
+ arena_mem_free(p->reuse_blk, NULL);
+ arena_mem_free(arena_finish(&p->arena), NULL);
}
bool unpacker_parse_header(Unpacker *p)
@@ -282,6 +297,7 @@ bool unpacker_advance(Unpacker *p)
return false;
}
p->state = p->type == kMessageTypeResponse ? 1 : 2;
+ arena_start(&p->arena, &p->reuse_blk);
}
int result;