aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private/helpers.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-10-26 12:52:49 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-10-29 15:52:28 +0200
commitc3a3e654282e774ff400443cbfcbe78630fe4206 (patch)
treefe25a069ca7dd58fcd4210851e6576ea605fff8d /src/nvim/api/private/helpers.c
parentd1c470957b49380ec5ceba603dbd85a14f60f09b (diff)
downloadrneovim-c3a3e654282e774ff400443cbfcbe78630fe4206.tar.gz
rneovim-c3a3e654282e774ff400443cbfcbe78630fe4206.tar.bz2
rneovim-c3a3e654282e774ff400443cbfcbe78630fe4206.zip
refactor(api): break out vim_to_object/object_to_vim to own file
Diffstat (limited to 'src/nvim/api/private/helpers.c')
-rw-r--r--src/nvim/api/private/helpers.c332
1 files changed, 1 insertions, 331 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 745681c3f8..6b3f4a29d7 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -28,6 +28,7 @@
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/api/private/converter.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
@@ -37,11 +38,6 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-/// Helper structure for vim_to_object
-typedef struct {
- kvec_withinit_t(Object, 2) stack; ///< Object stack.
-} EncodedData;
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/funcs_metadata.generated.h"
# include "api/private/helpers.c.generated.h"
@@ -415,226 +411,6 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
current_sctx = save_current_sctx;
}
-#define TYPVAL_ENCODE_ALLOW_SPECIALS false
-
-#define TYPVAL_ENCODE_CONV_NIL(tv) \
- kvi_push(edata->stack, NIL)
-
-#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
- kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
-
-#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
- kvi_push(edata->stack, INTEGER_OBJ((Integer)(num)))
-
-#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER
-
-#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
- kvi_push(edata->stack, FLOAT_OBJ((Float)(flt)))
-
-#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
- do { \
- const size_t len_ = (size_t)(len); \
- const char *const str_ = (const char *)(str); \
- assert(len_ == 0 || str_ != NULL); \
- kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \
- } while (0)
-
-#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
-
-#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \
- TYPVAL_ENCODE_CONV_NIL(tv)
-
-#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
- do { \
- const size_t len_ = (size_t)(len); \
- const blob_T *const blob_ = (blob); \
- kvi_push(edata->stack, STRING_OBJ(((String) { \
- .data = len_ != 0 ? xmemdup(blob_->bv_ga.ga_data, len_) : NULL, \
- .size = len_ \
- }))); \
- } while (0)
-
-#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
- do { \
- TYPVAL_ENCODE_CONV_NIL(tv); \
- goto typval_encode_stop_converting_one_item; \
- } while (0)
-
-#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len)
-#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len)
-#define TYPVAL_ENCODE_CONV_FUNC_END(tv)
-
-#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
- kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
-
-#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
- kvi_push(edata->stack, \
- DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
-
-static inline void typval_encode_list_start(EncodedData *const edata, const size_t len)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- kvi_push(edata->stack, ARRAY_OBJ(((Array) {
- .capacity = len,
- .size = 0,
- .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)),
- })));
-}
-
-#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
- typval_encode_list_start(edata, (size_t)(len))
-
-#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
-
-static inline void typval_encode_between_list_items(EncodedData *const edata)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- Object item = kv_pop(edata->stack);
- Object *const list = &kv_last(edata->stack);
- assert(list->type == kObjectTypeArray);
- assert(list->data.array.size < list->data.array.capacity);
- list->data.array.items[list->data.array.size++] = item;
-}
-
-#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \
- typval_encode_between_list_items(edata)
-
-static inline void typval_encode_list_end(EncodedData *const edata)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- typval_encode_between_list_items(edata);
-#ifndef NDEBUG
- const Object *const list = &kv_last(edata->stack);
- assert(list->data.array.size == list->data.array.capacity);
-#endif
-}
-
-#define TYPVAL_ENCODE_CONV_LIST_END(tv) \
- typval_encode_list_end(edata)
-
-static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
- .capacity = len,
- .size = 0,
- .items = xmalloc(len * sizeof(
- *((Object)OBJECT_INIT).data.dictionary.items)),
- })));
-}
-
-#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
- typval_encode_dict_start(edata, (size_t)(len))
-
-#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv)
-
-#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair)
-
-static inline void typval_encode_after_key(EncodedData *const edata)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- Object key = kv_pop(edata->stack);
- Object *const dict = &kv_last(edata->stack);
- assert(dict->type == kObjectTypeDictionary);
- assert(dict->data.dictionary.size < dict->data.dictionary.capacity);
- if (key.type == kObjectTypeString) {
- dict->data.dictionary.items[dict->data.dictionary.size].key
- = key.data.string;
- } else {
- api_free_object(key);
- dict->data.dictionary.items[dict->data.dictionary.size].key
- = STATIC_CSTR_TO_STRING("__INVALID_KEY__");
- }
-}
-
-#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \
- typval_encode_after_key(edata)
-
-static inline void typval_encode_between_dict_items(EncodedData *const edata)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- Object val = kv_pop(edata->stack);
- Object *const dict = &kv_last(edata->stack);
- assert(dict->type == kObjectTypeDictionary);
- assert(dict->data.dictionary.size < dict->data.dictionary.capacity);
- dict->data.dictionary.items[dict->data.dictionary.size++].value = val;
-}
-
-#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \
- typval_encode_between_dict_items(edata)
-
-static inline void typval_encode_dict_end(EncodedData *const edata)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
-{
- typval_encode_between_dict_items(edata);
-#ifndef NDEBUG
- const Object *const dict = &kv_last(edata->stack);
- assert(dict->data.dictionary.size == dict->data.dictionary.capacity);
-#endif
-}
-
-#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \
- typval_encode_dict_end(edata)
-
-#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
- TYPVAL_ENCODE_CONV_NIL(val)
-
-#define TYPVAL_ENCODE_SCOPE static
-#define TYPVAL_ENCODE_NAME object
-#define TYPVAL_ENCODE_FIRST_ARG_TYPE EncodedData *const
-#define TYPVAL_ENCODE_FIRST_ARG_NAME edata
-#include "nvim/eval/typval_encode.c.h"
-#undef TYPVAL_ENCODE_SCOPE
-#undef TYPVAL_ENCODE_NAME
-#undef TYPVAL_ENCODE_FIRST_ARG_TYPE
-#undef TYPVAL_ENCODE_FIRST_ARG_NAME
-
-#undef TYPVAL_ENCODE_CONV_STRING
-#undef TYPVAL_ENCODE_CONV_STR_STRING
-#undef TYPVAL_ENCODE_CONV_EXT_STRING
-#undef TYPVAL_ENCODE_CONV_BLOB
-#undef TYPVAL_ENCODE_CONV_NUMBER
-#undef TYPVAL_ENCODE_CONV_FLOAT
-#undef TYPVAL_ENCODE_CONV_FUNC_START
-#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS
-#undef TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF
-#undef TYPVAL_ENCODE_CONV_FUNC_END
-#undef TYPVAL_ENCODE_CONV_EMPTY_LIST
-#undef TYPVAL_ENCODE_CONV_LIST_START
-#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START
-#undef TYPVAL_ENCODE_CONV_EMPTY_DICT
-#undef TYPVAL_ENCODE_CONV_NIL
-#undef TYPVAL_ENCODE_CONV_BOOL
-#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER
-#undef TYPVAL_ENCODE_CONV_DICT_START
-#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START
-#undef TYPVAL_ENCODE_CONV_DICT_END
-#undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY
-#undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS
-#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK
-#undef TYPVAL_ENCODE_CONV_LIST_END
-#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
-#undef TYPVAL_ENCODE_CONV_RECURSE
-#undef TYPVAL_ENCODE_ALLOW_SPECIALS
-
-/// Convert a vim object to an `Object` instance, recursively expanding
-/// Arrays/Dictionaries.
-///
-/// @param obj The source object
-/// @return The converted value
-Object vim_to_object(typval_T *obj)
-{
- EncodedData edata;
- kvi_init(edata.stack);
- const int evo_ret = encode_vim_to_object(&edata, obj,
- "vim_to_object argument");
- (void)evo_ret;
- assert(evo_ret == OK);
- Object ret = kv_A(edata.stack, 0);
- assert(kv_size(edata.stack) == 1);
- kvi_destroy(edata.stack);
- return ret;
-}
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
@@ -966,112 +742,6 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr
return true;
}
-/// Converts from type Object to a VimL value.
-///
-/// @param obj Object to convert from.
-/// @param tv Conversion result is placed here. On failure member v_type is
-/// set to VAR_UNKNOWN (no allocation was made for this variable).
-/// returns true if conversion is successful, otherwise false.
-bool object_to_vim(Object obj, typval_T *tv, Error *err)
-{
- tv->v_type = VAR_UNKNOWN;
- tv->v_lock = VAR_UNLOCKED;
-
- switch (obj.type) {
- case kObjectTypeNil:
- tv->v_type = VAR_SPECIAL;
- tv->vval.v_special = kSpecialVarNull;
- break;
-
- case kObjectTypeBoolean:
- tv->v_type = VAR_BOOL;
- tv->vval.v_bool = obj.data.boolean? kBoolVarTrue: kBoolVarFalse;
- break;
-
- case kObjectTypeBuffer:
- case kObjectTypeWindow:
- case kObjectTypeTabpage:
- case kObjectTypeInteger:
- STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T),
- "Integer size must be <= VimL number size");
- tv->v_type = VAR_NUMBER;
- tv->vval.v_number = (varnumber_T)obj.data.integer;
- break;
-
- case kObjectTypeFloat:
- tv->v_type = VAR_FLOAT;
- tv->vval.v_float = obj.data.floating;
- break;
-
- case kObjectTypeString:
- tv->v_type = VAR_STRING;
- if (obj.data.string.data == NULL) {
- tv->vval.v_string = NULL;
- } else {
- tv->vval.v_string = xmemdupz(obj.data.string.data,
- obj.data.string.size);
- }
- break;
-
- case kObjectTypeArray: {
- list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size);
-
- for (uint32_t i = 0; i < obj.data.array.size; i++) {
- Object item = obj.data.array.items[i];
- typval_T li_tv;
-
- if (!object_to_vim(item, &li_tv, err)) {
- tv_list_free(list);
- return false;
- }
-
- tv_list_append_owned_tv(list, li_tv);
- }
- tv_list_ref(list);
-
- tv->v_type = VAR_LIST;
- tv->vval.v_list = list;
- break;
- }
-
- case kObjectTypeDictionary: {
- dict_T *const dict = tv_dict_alloc();
-
- for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
- KeyValuePair item = obj.data.dictionary.items[i];
- String key = item.key;
-
- if (key.size == 0) {
- api_set_error(err, kErrorTypeValidation,
- "Empty dictionary keys aren't allowed");
- // cleanup
- tv_dict_free(dict);
- return false;
- }
-
- dictitem_T *const di = tv_dict_item_alloc(key.data);
-
- if (!object_to_vim(item.value, &di->di_tv, err)) {
- // cleanup
- tv_dict_item_free(di);
- tv_dict_free(dict);
- return false;
- }
-
- tv_dict_add(dict, di);
- }
- dict->dv_refcount++;
-
- tv->v_type = VAR_DICT;
- tv->vval.v_dict = dict;
- break;
- }
- default:
- abort();
- }
-
- return true;
-}
void api_free_string(String value)
{