Merge pull request #29358 from bfredl/typvalpack

refactor(typval): don't use msgpack_packer for msgpackdump()
This commit is contained in:
bfredl
2024-06-24 11:30:31 +02:00
committed by GitHub
9 changed files with 146 additions and 109 deletions

View File

@@ -28,6 +28,7 @@ typedef struct {
#endif #endif
#define TYPVAL_ENCODE_ALLOW_SPECIALS false #define TYPVAL_ENCODE_ALLOW_SPECIALS false
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
kvi_push(edata->stack, NIL) kvi_push(edata->stack, NIL)
@@ -217,6 +218,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
#undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_LIST_START
#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER

View File

@@ -13,7 +13,7 @@
#include <string.h> #include <string.h>
#include "klib/kvec.h" #include "klib/kvec.h"
#include "msgpack/pack.h" #include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h" #include "nvim/ascii_defs.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/encode.h" #include "nvim/eval/encode.h"
@@ -28,6 +28,7 @@
#include "nvim/mbyte.h" #include "nvim/mbyte.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/message.h" #include "nvim/message.h"
#include "nvim/msgpack_rpc/packer.h"
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/types_defs.h" #include "nvim/types_defs.h"
#include "nvim/vim_defs.h" // For _() #include "nvim/vim_defs.h" // For _()
@@ -412,6 +413,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
ga_concat(gap, "{}") ga_concat(gap, "{}")
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
ga_concat(gap, "v:null") ga_concat(gap, "v:null")
@@ -536,6 +539,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#undef TYPVAL_ENCODE_ALLOW_SPECIALS #undef TYPVAL_ENCODE_ALLOW_SPECIALS
#define TYPVAL_ENCODE_ALLOW_SPECIALS true #define TYPVAL_ENCODE_ALLOW_SPECIALS true
#define TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
ga_concat(gap, "null") ga_concat(gap, "null")
@@ -821,6 +826,7 @@ bool encode_check_json_key(const typval_T *const tv)
#undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_LIST_START
#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
@@ -913,52 +919,22 @@ char *encode_tv2json(typval_T *tv, size_t *len)
} }
#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \
do { \ mpack_bin(buf, (len), packer); \
if ((buf) == NULL) { \
msgpack_pack_bin(packer, 0); \
} else { \
const size_t len_ = (len); \
msgpack_pack_bin(packer, len_); \
msgpack_pack_bin_body(packer, buf, len_); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \
do { \ mpack_str(cbuf_as_string(buf, (len)), packer); \
if ((buf) == NULL) { \
msgpack_pack_str(packer, 0); \
} else { \
const size_t len_ = (len); \
msgpack_pack_str(packer, len_); \
msgpack_pack_str_body(packer, buf, len_); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \
do { \ mpack_ext(buf, (len), (int8_t)(type), packer); \
if ((buf) == NULL) { \
msgpack_pack_ext(packer, 0, (int8_t)(type)); \
} else { \
const size_t len_ = (len); \
msgpack_pack_ext(packer, len_, (int8_t)(type)); \
msgpack_pack_ext_body(packer, buf, len_); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
do { \ mpack_bin((blob) ? (blob)->bv_ga.ga_data : NULL, (size_t)(len), packer); \
const size_t len_ = (size_t)(len); \
msgpack_pack_bin(packer, len_); \
if (len_ > 0) { \
msgpack_pack_bin_body(packer, (blob)->bv_ga.ga_data, len_); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
msgpack_pack_int64(packer, (int64_t)(num)) mpack_integer(&packer->ptr, (Integer)(num))
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
msgpack_pack_double(packer, (double)(flt)) mpack_float8(&packer->ptr, (double)(flt))
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
return conv_error(_("E5004: Error while dumping %s, %s: " \ return conv_error(_("E5004: Error while dumping %s, %s: " \
@@ -970,33 +946,30 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_CONV_FUNC_END(tv) #define TYPVAL_ENCODE_CONV_FUNC_END(tv)
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
msgpack_pack_array(packer, 0) mpack_array(&packer->ptr, 0)
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
msgpack_pack_array(packer, (size_t)(len)) mpack_array(&packer->ptr, (uint32_t)(len))
#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
msgpack_pack_map(packer, 0) mpack_map(&packer->ptr, 0)
#define TYPVAL_ENCODE_CHECK_BEFORE \
mpack_check_buffer(packer)
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
msgpack_pack_nil(packer) mpack_nil(&packer->ptr)
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \ mpack_bool(&packer->ptr, (bool)num); \
if (num) { \
msgpack_pack_true(packer); \
} else { \
msgpack_pack_false(packer); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \
msgpack_pack_uint64(packer, (num)) mpack_uint64(&packer->ptr, (num))
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
msgpack_pack_map(packer, (size_t)(len)) mpack_map(&packer->ptr, (uint32_t)(len))
#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
@@ -1021,7 +994,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_SCOPE #define TYPVAL_ENCODE_SCOPE
#define TYPVAL_ENCODE_NAME msgpack #define TYPVAL_ENCODE_NAME msgpack
#define TYPVAL_ENCODE_FIRST_ARG_TYPE msgpack_packer *const #define TYPVAL_ENCODE_FIRST_ARG_TYPE PackerBuffer *const
#define TYPVAL_ENCODE_FIRST_ARG_NAME packer #define TYPVAL_ENCODE_FIRST_ARG_NAME packer
#include "nvim/eval/typval_encode.c.h" #include "nvim/eval/typval_encode.c.h"
#undef TYPVAL_ENCODE_SCOPE #undef TYPVAL_ENCODE_SCOPE
@@ -1043,6 +1016,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_LIST_START
#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER

View File

@@ -5,6 +5,7 @@
#include "nvim/eval/typval_defs.h" #include "nvim/eval/typval_defs.h"
#include "nvim/garray_defs.h" #include "nvim/garray_defs.h"
#include "nvim/msgpack_rpc/packer_defs.h"
/// Convert Vimscript value to msgpack string /// Convert Vimscript value to msgpack string
/// ///
@@ -13,7 +14,7 @@
/// @param[in] objname Object name, used for error message. /// @param[in] objname Object name, used for error message.
/// ///
/// @return OK in case of success, FAIL otherwise. /// @return OK in case of success, FAIL otherwise.
int encode_vim_to_msgpack(msgpack_packer *packer, typval_T *tv, const char *objname); int encode_vim_to_msgpack(PackerBuffer *packer, typval_T *tv, const char *objname);
/// Convert Vimscript value to :echo output /// Convert Vimscript value to :echo output
/// ///

View File

@@ -94,6 +94,7 @@
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/packer.h"
#include "nvim/msgpack_rpc/server.h" #include "nvim/msgpack_rpc/server.h"
#include "nvim/normal.h" #include "nvim/normal.h"
#include "nvim/normal_defs.h" #include "nvim/normal_defs.h"
@@ -5501,15 +5502,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return; return;
} }
list_T *const list = argvars[0].vval.v_list; list_T *const list = argvars[0].vval.v_list;
msgpack_packer *packer; PackerBuffer packer = packer_string_buffer();
if (argvars[1].v_type != VAR_UNKNOWN
&& strequal(tv_get_string(&argvars[1]), "B")) {
tv_blob_alloc_ret(rettv);
packer = msgpack_packer_new(rettv->vval.v_blob, &encode_blob_write);
} else {
packer = msgpack_packer_new(tv_list_alloc_ret(rettv, kListLenMayKnow),
&encode_list_write);
}
const char *const msg = _("msgpackdump() argument, index %i"); const char *const msg = _("msgpackdump() argument, index %i");
// Assume that translation will not take more then 4 times more space // Assume that translation will not take more then 4 times more space
char msgbuf[sizeof("msgpackdump() argument, index ") * 4 + NUMBUFLEN]; char msgbuf[sizeof("msgpackdump() argument, index ") * 4 + NUMBUFLEN];
@@ -5517,11 +5510,20 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
TV_LIST_ITER(list, li, { TV_LIST_ITER(list, li, {
vim_snprintf(msgbuf, sizeof(msgbuf), msg, idx); vim_snprintf(msgbuf, sizeof(msgbuf), msg, idx);
idx++; idx++;
if (encode_vim_to_msgpack(packer, TV_LIST_ITEM_TV(li), msgbuf) == FAIL) { if (encode_vim_to_msgpack(&packer, TV_LIST_ITEM_TV(li), msgbuf) == FAIL) {
break; break;
} }
}); });
msgpack_packer_free(packer); String data = packer_take_string(&packer);
if (argvars[1].v_type != VAR_UNKNOWN && strequal(tv_get_string(&argvars[1]), "B")) {
blob_T *b = tv_blob_alloc_ret(rettv);
b->bv_ga.ga_data = data.data;
b->bv_ga.ga_len = (int)data.size;
b->bv_ga.ga_maxlen = (int)(packer.endptr - packer.startptr);
} else {
encode_list_write(tv_list_alloc_ret(rettv, kListLenMayKnow), data.data, data.size);
api_free_string(data);
}
} }
static int msgpackparse_convert_item(const msgpack_object data, const msgpack_unpack_return result, static int msgpackparse_convert_item(const msgpack_object data, const msgpack_unpack_return result,

View File

@@ -3064,8 +3064,7 @@ void f_blob2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// list2blob() function /// list2blob() function
void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {
tv_blob_alloc_ret(rettv); blob_T *blob = tv_blob_alloc_ret(rettv);
blob_T *const blob = rettv->vval.v_blob;
if (tv_check_for_list_arg(argvars, 0) == FAIL) { if (tv_check_for_list_arg(argvars, 0) == FAIL) {
return; return;
@@ -3252,11 +3251,12 @@ void tv_dict_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
/// Also sets reference count. /// Also sets reference count.
/// ///
/// @param[out] ret_tv Structure where blob is saved. /// @param[out] ret_tv Structure where blob is saved.
void tv_blob_alloc_ret(typval_T *const ret_tv) blob_T *tv_blob_alloc_ret(typval_T *const ret_tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
blob_T *const b = tv_blob_alloc(); blob_T *const b = tv_blob_alloc();
tv_blob_set_ret(ret_tv, b); tv_blob_set_ret(ret_tv, b);
return b;
} }
/// Copy a blob typval to a different typval. /// Copy a blob typval to a different typval.
@@ -3284,6 +3284,7 @@ void tv_blob_copy(blob_T *const from, typval_T *const to)
//{{{3 Clear //{{{3 Clear
#define TYPVAL_ENCODE_ALLOW_SPECIALS false #define TYPVAL_ENCODE_ALLOW_SPECIALS false
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
do { \ do { \
@@ -3500,6 +3501,7 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic
#undef TYPVAL_ENCODE_FIRST_ARG_NAME #undef TYPVAL_ENCODE_FIRST_ARG_NAME
#undef TYPVAL_ENCODE_ALLOW_SPECIALS #undef TYPVAL_ENCODE_ALLOW_SPECIALS
#undef TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_NUMBER #undef TYPVAL_ENCODE_CONV_NUMBER

View File

@@ -6,6 +6,11 @@
/// something else. For these macros to work the following macros must be /// something else. For these macros to work the following macros must be
/// defined: /// defined:
/// @def TYPVAL_ENCODE_CHECK_BEFORE
/// @brief Macro used before any specific CONV function
///
/// can be used for a common check, like flushing a buffer if necessary
/// @def TYPVAL_ENCODE_CONV_NIL /// @def TYPVAL_ENCODE_CONV_NIL
/// @brief Macros used to convert NIL value /// @brief Macros used to convert NIL value
/// ///
@@ -323,6 +328,7 @@ static int TYPVAL_ENCODE_CONVERT_ONE_VALUE(
TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, MPConvStack *const mpstack, TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, MPConvStack *const mpstack,
MPConvStackVal *const cur_mpsv, typval_T *const tv, const int copyID, const char *const objname) MPConvStackVal *const cur_mpsv, typval_T *const tv, const int copyID, const char *const objname)
{ {
TYPVAL_ENCODE_CHECK_BEFORE;
switch (tv->v_type) { switch (tv->v_type) {
case VAR_STRING: case VAR_STRING:
TYPVAL_ENCODE_CONV_STRING(tv, tv->vval.v_string, tv_strlen(tv)); TYPVAL_ENCODE_CONV_STRING(tv, tv->vval.v_string, tv_strlen(tv));
@@ -420,6 +426,7 @@ static int TYPVAL_ENCODE_CONVERT_ONE_VALUE(
break; break;
} }
} }
TYPVAL_ENCODE_CHECK_BEFORE;
if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { if (i == ARRAY_SIZE(eval_msgpack_type_lists)) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }

View File

@@ -425,6 +425,8 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_ALLOW_SPECIALS true #define TYPVAL_ENCODE_ALLOW_SPECIALS true
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \ #define TYPVAL_ENCODE_CONV_NIL(tv) \
do { \ do { \
if (typval_conv_special) { \ if (typval_conv_special) { \
@@ -574,6 +576,7 @@ static bool typval_conv_special = false;
#undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_LIST_START
#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
#undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_EMPTY_DICT
#undef TYPVAL_ENCODE_CHECK_BEFORE
#undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_NIL
#undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_BOOL
#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER

View File

@@ -8,7 +8,7 @@
# include "msgpack_rpc/packer.c.generated.h" # include "msgpack_rpc/packer.c.generated.h"
#endif #endif
static void check_buffer(PackerBuffer *packer) void mpack_check_buffer(PackerBuffer *packer)
{ {
if (mpack_remaining(packer) < MPACK_ITEM_SIZE) { if (mpack_remaining(packer) < MPACK_ITEM_SIZE) {
packer->packer_flush(packer); packer->packer_flush(packer);
@@ -87,7 +87,25 @@ void mpack_str(String str, PackerBuffer *packer)
mpack_raw(str.data, len, packer); mpack_raw(str.data, len, packer);
} }
void mpack_raw(char *data, size_t len, PackerBuffer *packer) void mpack_bin(const char *data, size_t len, PackerBuffer *packer)
{
if (len < 0xff) {
mpack_w(&packer->ptr, 0xc4);
mpack_w(&packer->ptr, len);
} else if (len < 0xffff) {
mpack_w(&packer->ptr, 0xc5);
mpack_w2(&packer->ptr, (uint32_t)len);
} else if (len < 0xffffffff) {
mpack_w(&packer->ptr, 0xc6);
mpack_w4(&packer->ptr, (uint32_t)len);
} else {
abort();
}
mpack_raw(data, len, packer);
}
void mpack_raw(const char *data, size_t len, PackerBuffer *packer)
{ {
size_t pos = 0; size_t pos = 0;
while (pos < len) { while (pos < len) {
@@ -103,6 +121,27 @@ void mpack_raw(char *data, size_t len, PackerBuffer *packer)
} }
} }
void mpack_ext(char *buf, size_t len, int8_t type, PackerBuffer *packer)
{
if (len == 1) {
mpack_w(&packer->ptr, 0xd4);
} else if (len == 2) {
mpack_w(&packer->ptr, 0xd5);
} else if (len <= 0xff) {
mpack_w(&packer->ptr, 0xc7);
} else if (len < 0xffff) {
mpack_w(&packer->ptr, 0xc8);
mpack_w2(&packer->ptr, (uint32_t)len);
} else if (len < 0xffffffff) {
mpack_w(&packer->ptr, 0xc9);
mpack_w4(&packer->ptr, (uint32_t)len);
} else {
abort();
}
mpack_w(&packer->ptr, type);
mpack_raw(buf, len, packer);
}
void mpack_handle(ObjectType type, handle_T handle, PackerBuffer *packer) void mpack_handle(ObjectType type, handle_T handle, PackerBuffer *packer)
{ {
char exttype = (char)(type - EXT_OBJECT_TYPE_SHIFT); char exttype = (char)(type - EXT_OBJECT_TYPE_SHIFT);
@@ -156,7 +195,7 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx
kvi_init(stack); kvi_init(stack);
while (true) { while (true) {
check_buffer(packer); mpack_check_buffer(packer);
switch (current->type) { switch (current->type) {
case kObjectTypeLuaRef: case kObjectTypeLuaRef:
// TODO(bfredl): could also be an error. Though kObjectTypeLuaRef // TODO(bfredl): could also be an error. Though kObjectTypeLuaRef
@@ -231,7 +270,7 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx
} else { } else {
Dictionary dict = container->data.dictionary; Dictionary dict = container->data.dictionary;
KeyValuePair *it = &dict.items[container_idx++]; KeyValuePair *it = &dict.items[container_idx++];
check_buffer(packer); mpack_check_buffer(packer);
mpack_str(it->key, packer); mpack_str(it->key, packer);
current = &it->value; current = &it->value;
if (container_idx >= dict.size) { if (container_idx >= dict.size) {
@@ -241,3 +280,32 @@ void mpack_object_inner(Object *current, Object *container, size_t container_idx
} }
kvi_destroy(stack); kvi_destroy(stack);
} }
PackerBuffer packer_string_buffer(void)
{
const size_t initial_size = 64; // must be larger than SHADA_MPACK_FREE_SPACE
char *alloc = xmalloc(initial_size);
return (PackerBuffer) {
.startptr = alloc,
.ptr = alloc,
.endptr = alloc + initial_size,
.packer_flush = flush_string_buffer,
};
}
static void flush_string_buffer(PackerBuffer *buffer)
{
size_t current_capacity = (size_t)(buffer->endptr - buffer->startptr);
size_t new_capacity = 2 * current_capacity;
size_t len = (size_t)(buffer->ptr - buffer->startptr);
buffer->startptr = xrealloc(buffer->startptr, new_capacity);
buffer->ptr = buffer->startptr + len;
buffer->endptr = buffer->startptr + new_capacity;
}
/// can only be used with a PackerBuffer from `packer_string_buffer`
String packer_take_string(PackerBuffer *buffer)
{
return (String){ .data = buffer->startptr, .size = (size_t)(buffer->ptr - buffer->startptr) };
}

View File

@@ -1354,6 +1354,12 @@ static char *shada_filename(const char *file)
#define SHADA_MPACK_FREE_SPACE (4 * MPACK_ITEM_SIZE) #define SHADA_MPACK_FREE_SPACE (4 * MPACK_ITEM_SIZE)
static int mpack_raw_wrapper(void *cookie, const char *data, size_t len)
{
mpack_raw(data, len, (PackerBuffer *)cookie);
return 0;
}
/// Write single ShaDa entry /// Write single ShaDa entry
/// ///
/// @param[in] packer Packer used to write entry. /// @param[in] packer Packer used to write entry.
@@ -1367,14 +1373,13 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
ShaDaWriteResult ret = kSDWriteFailed; ShaDaWriteResult ret = kSDWriteFailed;
msgpack_sbuffer sbuf; PackerBuffer sbuf = packer_string_buffer();
msgpack_sbuffer_init(&sbuf); msgpack_packer *spacker = msgpack_packer_new(&sbuf, &mpack_raw_wrapper);
msgpack_packer *spacker = msgpack_packer_new(&sbuf, &msgpack_sbuffer_write);
#define DUMP_ADDITIONAL_ELEMENTS(src, what) \ #define DUMP_ADDITIONAL_ELEMENTS(src, what) \
do { \ do { \
if ((src) != NULL) { \ if ((src) != NULL) { \
TV_LIST_ITER((src), li, { \ TV_LIST_ITER((src), li, { \
if (encode_vim_to_msgpack(spacker, TV_LIST_ITEM_TV(li), \ if (encode_vim_to_msgpack(&sbuf, TV_LIST_ITEM_TV(li), \
_("additional elements of ShaDa " what)) \ _("additional elements of ShaDa " what)) \
== FAIL) { \ == FAIL) { \
goto shada_pack_entry_error; \ goto shada_pack_entry_error; \
@@ -1394,7 +1399,7 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
const size_t key_len = strlen(hi->hi_key); \ const size_t key_len = strlen(hi->hi_key); \
msgpack_pack_str(spacker, key_len); \ msgpack_pack_str(spacker, key_len); \
msgpack_pack_str_body(spacker, hi->hi_key, key_len); \ msgpack_pack_str_body(spacker, hi->hi_key, key_len); \
if (encode_vim_to_msgpack(spacker, &di->di_tv, \ if (encode_vim_to_msgpack(&sbuf, &di->di_tv, \
_("additional data of ShaDa " what)) \ _("additional data of ShaDa " what)) \
== FAIL) { \ == FAIL) { \
goto shada_pack_entry_error; \ goto shada_pack_entry_error; \
@@ -1460,7 +1465,7 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
char vardesc[256] = "variable g:"; char vardesc[256] = "variable g:";
memcpy(&vardesc[sizeof("variable g:") - 1], varname.data, memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
varname.size + 1); varname.size + 1);
if (encode_vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc) if (encode_vim_to_msgpack(&sbuf, &entry.data.global_var.value, vardesc)
== FAIL) { == FAIL) {
ret = kSDWriteIgnError; ret = kSDWriteIgnError;
semsg(_(WERR "Failed to write variable %s"), semsg(_(WERR "Failed to write variable %s"),
@@ -1645,7 +1650,8 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
} }
#undef CHECK_DEFAULT #undef CHECK_DEFAULT
#undef ONE_IF_NOT_DEFAULT #undef ONE_IF_NOT_DEFAULT
if (!max_kbyte || sbuf.size <= max_kbyte * 1024) { String packed = packer_take_string(&sbuf);
if (!max_kbyte || packed.size <= max_kbyte * 1024) {
if (mpack_remaining(packer) < SHADA_MPACK_FREE_SPACE) { if (mpack_remaining(packer) < SHADA_MPACK_FREE_SPACE) {
packer->packer_flush(packer); packer->packer_flush(packer);
} }
@@ -1656,9 +1662,9 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
mpack_uint64(&packer->ptr, (uint64_t)entry.type); mpack_uint64(&packer->ptr, (uint64_t)entry.type);
} }
mpack_uint64(&packer->ptr, (uint64_t)entry.timestamp); mpack_uint64(&packer->ptr, (uint64_t)entry.timestamp);
if (sbuf.size > 0) { if (packed.size > 0) {
mpack_uint64(&packer->ptr, (uint64_t)sbuf.size); mpack_uint64(&packer->ptr, (uint64_t)packed.size);
mpack_raw(sbuf.data, sbuf.size, packer); mpack_raw(packed.data, packed.size, packer);
} }
if (packer->anyint != 0) { // error code if (packer->anyint != 0) { // error code
@@ -1668,7 +1674,7 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
ret = kSDWriteSuccessful; ret = kSDWriteSuccessful;
shada_pack_entry_error: shada_pack_entry_error:
msgpack_packer_free(spacker); msgpack_packer_free(spacker);
msgpack_sbuffer_destroy(&sbuf); xfree(sbuf.startptr);
return ret; return ret;
} }
@@ -3960,34 +3966,6 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
return jumps_size; return jumps_size;
} }
static PackerBuffer packer_string_buffer(void)
{
const size_t initial_size = 64; // must be larger than SHADA_MPACK_FREE_SPACE
char *alloc = xmalloc(initial_size);
return (PackerBuffer) {
.startptr = alloc,
.ptr = alloc,
.endptr = alloc + initial_size,
.packer_flush = flush_string_buffer,
};
}
static void flush_string_buffer(PackerBuffer *buffer)
{
size_t current_capacity = (size_t)(buffer->endptr - buffer->startptr);
size_t new_capacity = 2 * current_capacity;
size_t len = (size_t)(buffer->ptr - buffer->startptr);
buffer->startptr = xrealloc(buffer->startptr, new_capacity);
buffer->ptr = buffer->startptr + len;
buffer->endptr = buffer->startptr + new_capacity;
}
static String packer_take_string(PackerBuffer *buffer)
{
return (String){ .data = buffer->startptr, .size = (size_t)(buffer->ptr - buffer->startptr) };
}
/// Write registers ShaDa entries in given msgpack_sbuffer. /// Write registers ShaDa entries in given msgpack_sbuffer.
/// ///
/// @param[in] sbuf target msgpack_sbuffer to write to. /// @param[in] sbuf target msgpack_sbuffer to write to.