diff options
Diffstat (limited to 'src/nvim/api/private')
-rw-r--r-- | src/nvim/api/private/converter.c | 43 | ||||
-rw-r--r-- | src/nvim/api/private/defs.h | 24 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 86 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.h | 10 | ||||
-rw-r--r-- | src/nvim/api/private/validate.c | 2 | ||||
-rw-r--r-- | src/nvim/api/private/validate.h | 8 |
6 files changed, 85 insertions, 88 deletions
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c index a78d78c057..59e7373f68 100644 --- a/src/nvim/api/private/converter.c +++ b/src/nvim/api/private/converter.c @@ -7,7 +7,9 @@ #include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" +#include "nvim/eval/decode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" @@ -28,6 +30,7 @@ typedef struct { #endif #define TYPVAL_ENCODE_ALLOW_SPECIALS false +#define TYPVAL_ENCODE_CHECK_BEFORE #define TYPVAL_ENCODE_CONV_NIL(tv) \ kvi_push(edata->stack, NIL) @@ -91,8 +94,7 @@ static Object typval_cbuf_to_obj(EncodedData *edata, const char *data, size_t le 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 }))) + kvi_push(edata->stack, DICT_OBJ(((Dict) { .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 @@ -134,7 +136,7 @@ static inline void typval_encode_list_end(EncodedData *const 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(arena_dict(edata->arena, len))); + kvi_push(edata->stack, DICT_OBJ(arena_dict(edata->arena, len))); } #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ @@ -149,13 +151,13 @@ static inline void typval_encode_after_key(EncodedData *const edata) { 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); + assert(dict->type == kObjectTypeDict); + assert(dict->data.dict.size < dict->data.dict.capacity); if (key.type == kObjectTypeString) { - dict->data.dictionary.items[dict->data.dictionary.size].key + dict->data.dict.items[dict->data.dict.size].key = key.data.string; } else { - dict->data.dictionary.items[dict->data.dictionary.size].key + dict->data.dict.items[dict->data.dict.size].key = STATIC_CSTR_AS_STRING("__INVALID_KEY__"); } } @@ -168,9 +170,9 @@ static inline void typval_encode_between_dict_items(EncodedData *const edata) { 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; + assert(dict->type == kObjectTypeDict); + assert(dict->data.dict.size < dict->data.dict.capacity); + dict->data.dict.items[dict->data.dict.size++].value = val; } #define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ @@ -182,7 +184,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) 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); + assert(dict->data.dict.size == dict->data.dict.capacity); #endif } @@ -217,6 +219,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #undef TYPVAL_ENCODE_CONV_LIST_START #undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CHECK_BEFORE #undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER @@ -300,15 +303,11 @@ void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Erro 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); - } + case kObjectTypeString: { + String s = obj->data.string; + *tv = decode_string(s.data, s.size, false, false); break; + } case kObjectTypeArray: { list_T *const list = tv_list_alloc((ptrdiff_t)obj->data.array.size); @@ -325,11 +324,11 @@ void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Erro break; } - case kObjectTypeDictionary: { + case kObjectTypeDict: { 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]; + for (uint32_t i = 0; i < obj->data.dict.size; i++) { + KeyValuePair *item = &obj->data.dict.items[i]; String key = item->key; dictitem_T *const di = tv_dict_item_alloc(key.data); object_to_vim_take_luaref(&item->value, &di->di_tv, take_luaref, err); diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index ca088d7a55..26d5ac09a8 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,7 +5,6 @@ #include <string.h> #include "klib/kvec.h" -#include "nvim/func_attr.h" #include "nvim/types_defs.h" #define ARRAY_DICT_INIT KV_INITIAL_VALUE @@ -18,8 +17,11 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # define ArrayOf(...) Array -# define DictionaryOf(...) Dictionary +# define DictOf(...) Dict # define Dict(name) KeyDict_##name +# define DictHash(name) KeyDict_##name##_get_field +# define DictKey(name) +# include "api/private/defs.h.inline.generated.h" #endif // Basic types @@ -47,15 +49,13 @@ typedef enum { /// Internal call from Lua code #define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1) -static inline bool is_internal_call(uint64_t channel_id) - REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; - /// Check whether call is internal /// /// @param[in] channel_id Channel id. /// /// @return true if channel_id refers to internal channel. static inline bool is_internal_call(const uint64_t channel_id) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST { return !!(channel_id & INTERNAL_CALL_MASK); } @@ -88,7 +88,9 @@ typedef struct object Object; typedef kvec_t(Object) Array; typedef struct key_value_pair KeyValuePair; -typedef kvec_t(KeyValuePair) Dictionary; +typedef kvec_t(KeyValuePair) Dict; + +typedef kvec_t(String) StringArray; typedef enum { kObjectTypeNil = 0, @@ -97,7 +99,7 @@ typedef enum { kObjectTypeFloat, kObjectTypeString, kObjectTypeArray, - kObjectTypeDictionary, + kObjectTypeDict, kObjectTypeLuaRef, // EXT types, cannot be split or reordered, see #EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer, @@ -105,6 +107,10 @@ typedef enum { kObjectTypeTabpage, } ObjectType; +typedef enum { + kUnpackTypeStringArray = -1, +} UnpackType; + /// Value by which objects represented as EXT type are shifted /// /// Subtracted when packing, added when unpacking. Used to allow moving @@ -121,7 +127,7 @@ struct object { Float floating; String string; Array array; - Dictionary dictionary; + Dict dict; LuaRef luaref; } data; }; @@ -142,7 +148,7 @@ typedef struct { typedef struct { char *str; size_t ptr_off; - ObjectType type; // kObjectTypeNil == untyped + int type; // ObjectType or UnpackType. kObjectTypeNil == untyped int opt_index; bool is_hlgroup; } KeySetLink; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index a17e78cc31..e1fb4ed732 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1,6 +1,5 @@ #include <assert.h> #include <limits.h> -#include <msgpack/unpack.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> @@ -199,7 +198,7 @@ dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err) api_set_error(err, kErrorTypeException, "Key is fixed: %s", key.data); } } else if (dict->dv_lock) { - api_set_error(err, kErrorTypeException, "Dictionary is locked"); + api_set_error(err, kErrorTypeException, "Dict is locked"); } else if (key.size == 0) { api_set_error(err, kErrorTypeValidation, "Key name is empty"); } else if (key.size > INT_MAX) { @@ -529,29 +528,19 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col start_col = start_col < 0 ? line_length + start_col + 1 : start_col; end_col = end_col < 0 ? line_length + end_col + 1 : end_col; - if (start_col >= MAXCOL || end_col >= MAXCOL) { - api_set_error(err, kErrorTypeValidation, "Column index is too high"); - return rv; - } + start_col = MIN(MAX(0, start_col), line_length); + end_col = MIN(MAX(0, end_col), line_length); if (start_col > end_col) { - api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col"); - return rv; - } - - if (start_col >= line_length) { + api_set_error(err, kErrorTypeValidation, "start_col must be less than or equal to end_col"); return rv; } - return cstrn_as_string(&bufstr[start_col], (size_t)(end_col - start_col)); + return cbuf_as_string(bufstr + start_col, (size_t)(end_col - start_col)); } void api_free_string(String value) { - if (!value.data) { - return; - } - xfree(value.data); } @@ -562,9 +551,9 @@ Array arena_array(Arena *arena, size_t max_size) return arr; } -Dictionary arena_dict(Arena *arena, size_t max_size) +Dict arena_dict(Arena *arena, size_t max_size) { - Dictionary dict = ARRAY_DICT_INIT; + Dict dict = ARRAY_DICT_INIT; kv_fixsize_arena(arena, dict, max_size); return dict; } @@ -607,8 +596,8 @@ void api_free_object(Object value) api_free_array(value.data.array); break; - case kObjectTypeDictionary: - api_free_dictionary(value.data.dictionary); + case kObjectTypeDict: + api_free_dict(value.data.dict); break; case kObjectTypeLuaRef: @@ -626,7 +615,7 @@ void api_free_array(Array value) xfree(value.items); } -void api_free_dictionary(Dictionary value) +void api_free_dict(Dict value) { for (size_t i = 0; i < value.size; i++) { api_free_string(value.items[i].key); @@ -659,7 +648,7 @@ Object api_metadata(void) Arena arena = ARENA_EMPTY; Error err = ERROR_INIT; metadata = unpack((char *)packed_api_metadata, sizeof(packed_api_metadata), &arena, &err); - if (ERROR_SET(&err) || metadata.type != kObjectTypeDictionary) { + if (ERROR_SET(&err) || metadata.type != kObjectTypeDict) { abort(); } mem_for_metadata = arena_finish(&arena); @@ -695,9 +684,9 @@ Array copy_array(Array array, Arena *arena) return rv; } -Dictionary copy_dictionary(Dictionary dict, Arena *arena) +Dict copy_dict(Dict dict, Arena *arena) { - Dictionary rv = arena_dict(arena, dict.size); + Dict rv = arena_dict(arena, dict.size); for (size_t i = 0; i < dict.size; i++) { KeyValuePair item = dict.items[i]; PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena)); @@ -724,8 +713,8 @@ Object copy_object(Object obj, Arena *arena) case kObjectTypeArray: return ARRAY_OBJ(copy_array(obj.data.array, arena)); - case kObjectTypeDictionary: - return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena)); + case kObjectTypeDict: + return DICT_OBJ(copy_dict(obj.data.dict, arena)); case kObjectTypeLuaRef: return LUAREF_OBJ(api_new_luaref(obj.data.luaref)); @@ -779,7 +768,8 @@ int object_to_hl_id(Object obj, const char *what, Error *err) String str = obj.data.string; return str.size ? syn_check_group(str.data, str.size) : 0; } else if (obj.type == kObjectTypeInteger) { - return MAX((int)obj.data.integer, 0); + int id = (int)obj.data.integer; + return (1 <= id && id <= highlight_num_groups()) ? id : 0; } else { api_set_error(err, kErrorTypeValidation, "Invalid highlight: %s", what); return 0; @@ -801,7 +791,7 @@ char *api_typename(ObjectType t) return "String"; case kObjectTypeArray: return "Array"; - case kObjectTypeDictionary: + case kObjectTypeDict: return "Dict"; case kObjectTypeLuaRef: return "Function"; @@ -854,7 +844,7 @@ free_exit: } // see also nlua_pop_keydict for the lua specific implementation -bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error *err) +bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dict dict, Error *err) { for (size_t i = 0; i < dict.size; i++) { String k = dict.items[i].key; @@ -918,23 +908,25 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error return false; }); *(Array *)mem = value->data.array; - } else if (field->type == kObjectTypeDictionary) { - Dictionary *val = (Dictionary *)mem; + } else if (field->type == kObjectTypeDict) { + Dict *val = (Dict *)mem; // allow empty array as empty dict for lua (directly or via lua-client RPC) if (value->type == kObjectTypeArray && value->data.array.size == 0) { - *val = (Dictionary)ARRAY_DICT_INIT; - } else if (value->type == kObjectTypeDictionary) { - *val = value->data.dictionary; + *val = (Dict)ARRAY_DICT_INIT; + } else if (value->type == kObjectTypeDict) { + *val = value->data.dict; } else { - api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type)); + api_err_exp(err, field->str, api_typename((ObjectType)field->type), + api_typename(value->type)); return false; } } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow || field->type == kObjectTypeTabpage) { - if (value->type == kObjectTypeInteger || value->type == field->type) { + if (value->type == kObjectTypeInteger || value->type == (ObjectType)field->type) { *(handle_T *)mem = (handle_T)value->data.integer; } else { - api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type)); + api_err_exp(err, field->str, api_typename((ObjectType)field->type), + api_typename(value->type)); return false; } } else if (field->type == kObjectTypeLuaRef) { @@ -949,9 +941,9 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error return true; } -Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena) +Dict api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena) { - Dictionary rv = arena_dict(arena, max_size); + Dict rv = arena_dict(arena, max_size); for (size_t i = 0; table[i].str; i++) { KeySetLink *field = &table[i]; bool is_set = true; @@ -979,12 +971,12 @@ Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, val = STRING_OBJ(*(String *)mem); } else if (field->type == kObjectTypeArray) { val = ARRAY_OBJ(*(Array *)mem); - } else if (field->type == kObjectTypeDictionary) { - val = DICTIONARY_OBJ(*(Dictionary *)mem); + } else if (field->type == kObjectTypeDict) { + val = DICT_OBJ(*(Dict *)mem); } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow || field->type == kObjectTypeTabpage) { val.data.integer = *(handle_T *)mem; - val.type = field->type; + val.type = (ObjectType)field->type; } else if (field->type == kObjectTypeLuaRef) { // do nothing } else { @@ -1010,8 +1002,8 @@ void api_luarefs_free_object(Object value) api_luarefs_free_array(value.data.array); break; - case kObjectTypeDictionary: - api_luarefs_free_dict(value.data.dictionary); + case kObjectTypeDict: + api_luarefs_free_dict(value.data.dict); break; default: @@ -1027,8 +1019,8 @@ void api_luarefs_free_keydict(void *dict, KeySetLink *table) api_luarefs_free_object(*(Object *)mem); } else if (table[i].type == kObjectTypeLuaRef) { api_free_luaref(*(LuaRef *)mem); - } else if (table[i].type == kObjectTypeDictionary) { - api_luarefs_free_dict(*(Dictionary *)mem); + } else if (table[i].type == kObjectTypeDict) { + api_luarefs_free_dict(*(Dict *)mem); } } } @@ -1040,7 +1032,7 @@ void api_luarefs_free_array(Array value) } } -void api_luarefs_free_dict(Dictionary value) +void api_luarefs_free_dict(Dict value) { for (size_t i = 0; i < value.size; i++) { api_luarefs_free_object(value.items[i].value); diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 7eda8ffaf6..57932e067e 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -53,9 +53,9 @@ .type = kObjectTypeArray, \ .data.array = a }) -#define DICTIONARY_OBJ(d) ((Object) { \ - .type = kObjectTypeDictionary, \ - .data.dictionary = d }) +#define DICT_OBJ(d) ((Object) { \ + .type = kObjectTypeDict, \ + .data.dict = d }) #define LUAREF_OBJ(r) ((Object) { \ .type = kObjectTypeLuaRef, \ @@ -90,7 +90,7 @@ name.items = name##__items; \ #define MAXSIZE_TEMP_DICT(name, maxsize) \ - Dictionary name = ARRAY_DICT_INIT; \ + Dict name = ARRAY_DICT_INIT; \ KeyValuePair name##__items[maxsize]; \ name.capacity = maxsize; \ name.items = name##__items; \ @@ -121,7 +121,7 @@ typedef kvec_withinit_t(Object, 16) ArrayBuilder; #define api_init_tabpage #define api_init_object = NIL #define api_init_array = ARRAY_DICT_INIT -#define api_init_dictionary = ARRAY_DICT_INIT +#define api_init_dict = ARRAY_DICT_INIT #define KEYDICT_INIT { 0 } diff --git a/src/nvim/api/private/validate.c b/src/nvim/api/private/validate.c index e198c671eb..9fd7d3bfa6 100644 --- a/src/nvim/api/private/validate.c +++ b/src/nvim/api/private/validate.c @@ -17,7 +17,7 @@ void api_err_invalid(Error *err, const char *name, const char *val_s, int64_t va char *has_space = strchr(name, ' '); // No value. - if (val_s && val_s[0] == '\0') { + if (val_s && val_s[0] == NUL) { api_set_error(err, errtype, has_space ? "Invalid %s" : "Invalid '%s'", name); return; } diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 2c1d1a241d..67af8adea8 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -42,7 +42,7 @@ #define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ - STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + STATIC_ASSERT(expected_t != kObjectTypeDict, "use VALIDATE_T_DICT"); \ if (expected_t != actual_t) { \ api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ @@ -52,7 +52,7 @@ /// Checks that `obj_` has type `expected_t`. #define VALIDATE_T2(obj_, expected_t, code) \ do { \ - STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + STATIC_ASSERT(expected_t != kObjectTypeDict, "use VALIDATE_T_DICT"); \ if ((obj_).type != expected_t) { \ api_err_exp(err, STR(obj_), api_typename(expected_t), api_typename((obj_).type)); \ code; \ @@ -62,11 +62,11 @@ /// Checks that `obj_` has Dict type. Also allows empty Array in a Lua context. #define VALIDATE_T_DICT(name, obj_, code) \ do { \ - if ((obj_).type != kObjectTypeDictionary \ + if ((obj_).type != kObjectTypeDict \ && !(channel_id == LUA_INTERNAL_CALL \ && (obj_).type == kObjectTypeArray \ && (obj_).data.array.size == 0)) { \ - api_err_exp(err, name, api_typename(kObjectTypeDictionary), api_typename((obj_).type)); \ + api_err_exp(err, name, api_typename(kObjectTypeDict), api_typename((obj_).type)); \ code; \ } \ } while (0) |