aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/private
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/private')
-rw-r--r--src/nvim/api/private/defs.h43
-rw-r--r--src/nvim/api/private/helpers.c125
-rw-r--r--src/nvim/api/private/helpers.h44
3 files changed, 155 insertions, 57 deletions
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index b049412014..2dd229ec5f 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -5,17 +5,15 @@
#include <stdbool.h>
#include <string.h>
-#define ARRAY_DICT_INIT {.size = 0, .items = NULL}
+#define ARRAY_DICT_INIT {.size = 0, .capacity = 0, .items = NULL}
#define STRING_INIT {.data = NULL, .size = 0}
#define OBJECT_INIT { .type = kObjectTypeNil }
-#define POSITION_INIT { .row = 0, .col = 0 }
#define REMOTE_TYPE(type) typedef uint64_t type
-#define TYPED_ARRAY_OF(type) \
- typedef struct { \
- type *items; \
- size_t size; \
- } type##Array
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+ #define ArrayOf(...) Array
+ #define DictionaryOf(...) Dictionary
+#endif
// Basic types
typedef struct {
@@ -38,15 +36,6 @@ REMOTE_TYPE(Tabpage);
typedef struct object Object;
-TYPED_ARRAY_OF(Buffer);
-TYPED_ARRAY_OF(Window);
-TYPED_ARRAY_OF(Tabpage);
-TYPED_ARRAY_OF(String);
-
-typedef struct {
- Integer row, col;
-} Position;
-
typedef struct {
Object *items;
size_t size, capacity;
@@ -60,40 +49,30 @@ typedef struct {
} Dictionary;
typedef enum {
+ kObjectTypeBuffer,
+ kObjectTypeWindow,
+ kObjectTypeTabpage,
kObjectTypeNil,
kObjectTypeBoolean,
kObjectTypeInteger,
kObjectTypeFloat,
kObjectTypeString,
- kObjectTypeBuffer,
- kObjectTypeWindow,
- kObjectTypeTabpage,
kObjectTypeArray,
kObjectTypeDictionary,
- kObjectTypePosition,
- kObjectTypeStringArray,
- kObjectTypeBufferArray,
- kObjectTypeWindowArray,
- kObjectTypeTabpageArray,
} ObjectType;
struct object {
ObjectType type;
union {
+ Buffer buffer;
+ Window window;
+ Tabpage tabpage;
Boolean boolean;
Integer integer;
Float floating;
String string;
- Buffer buffer;
- Window window;
- Tabpage tabpage;
Array array;
Dictionary dictionary;
- Position position;
- StringArray stringarray;
- BufferArray bufferarray;
- WindowArray windowarray;
- TabpageArray tabpagearray;
} data;
};
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index f6fb46e1d1..14a820aa1b 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -6,6 +6,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/handle.h"
+#include "nvim/os/provider.h"
#include "nvim/ascii.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
@@ -449,6 +450,130 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
return true;
}
+void api_free_string(String value)
+{
+ if (!value.data) {
+ return;
+ }
+
+ free(value.data);
+}
+
+void api_free_object(Object value)
+{
+ switch (value.type) {
+ case kObjectTypeNil:
+ case kObjectTypeBoolean:
+ case kObjectTypeInteger:
+ case kObjectTypeFloat:
+ case kObjectTypeBuffer:
+ case kObjectTypeWindow:
+ case kObjectTypeTabpage:
+ break;
+
+ case kObjectTypeString:
+ api_free_string(value.data.string);
+ break;
+
+ case kObjectTypeArray:
+ api_free_array(value.data.array);
+ break;
+
+ case kObjectTypeDictionary:
+ api_free_dictionary(value.data.dictionary);
+ break;
+
+ default:
+ abort();
+ }
+}
+
+void api_free_array(Array value)
+{
+ for (size_t i = 0; i < value.size; i++) {
+ api_free_object(value.items[i]);
+ }
+
+ free(value.items);
+}
+
+void api_free_dictionary(Dictionary value)
+{
+ for (size_t i = 0; i < value.size; i++) {
+ api_free_string(value.items[i].key);
+ api_free_object(value.items[i].value);
+ }
+
+ free(value.items);
+}
+
+Dictionary api_metadata(void)
+{
+ static Dictionary metadata = ARRAY_DICT_INIT;
+
+ if (!metadata.size) {
+ msgpack_rpc_init_function_metadata(&metadata);
+ init_type_metadata(&metadata);
+ provider_init_feature_metadata(&metadata);
+ }
+
+ return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary;
+}
+
+static void init_type_metadata(Dictionary *metadata)
+{
+ Dictionary types = ARRAY_DICT_INIT;
+
+ Dictionary buffer_metadata = ARRAY_DICT_INIT;
+ PUT(buffer_metadata, "id", INTEGER_OBJ(kObjectTypeBuffer));
+
+ Dictionary window_metadata = ARRAY_DICT_INIT;
+ PUT(window_metadata, "id", INTEGER_OBJ(kObjectTypeWindow));
+
+ Dictionary tabpage_metadata = ARRAY_DICT_INIT;
+ PUT(tabpage_metadata, "id", INTEGER_OBJ(kObjectTypeTabpage));
+
+ PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata));
+ PUT(types, "Window", DICTIONARY_OBJ(window_metadata));
+ PUT(types, "Tabpage", DICTIONARY_OBJ(tabpage_metadata));
+
+ PUT(*metadata, "types", DICTIONARY_OBJ(types));
+}
+
+/// Creates a deep clone of an object
+static Object copy_object(Object obj)
+{
+ switch (obj.type) {
+ case kObjectTypeNil:
+ case kObjectTypeBoolean:
+ case kObjectTypeInteger:
+ case kObjectTypeFloat:
+ return obj;
+
+ case kObjectTypeString:
+ return STRING_OBJ(cstr_to_string(obj.data.string.data));
+
+ case kObjectTypeArray: {
+ Array rv = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < obj.data.array.size; i++) {
+ ADD(rv, copy_object(obj.data.array.items[i]));
+ }
+ return ARRAY_OBJ(rv);
+ }
+
+ case kObjectTypeDictionary: {
+ Dictionary rv = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < obj.data.dictionary.size; i++) {
+ KeyValuePair item = obj.data.dictionary.items[i];
+ PUT(rv, item.key.data, copy_object(item.value));
+ }
+ return DICTIONARY_OBJ(rv);
+ }
+ default:
+ abort();
+ }
+}
+
/// Recursion helper for the `vim_to_object`. This uses a pointer table
/// to avoid infinite recursion due to cyclic references
///
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index f1b9dc3bc8..f3ecdaacc4 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -51,36 +51,11 @@
.data.array = a \
})
-#define STRINGARRAY_OBJ(a) ((Object) { \
- .type = kObjectTypeStringArray, \
- .data.stringarray = a \
- })
-
-#define BUFFERARRAY_OBJ(a) ((Object) { \
- .type = kObjectTypeBufferArray, \
- .data.bufferarray = a \
- })
-
-#define WINDOWARRAY_OBJ(a) ((Object) { \
- .type = kObjectTypeWindowArray, \
- .data.windowarray = a \
- })
-
-#define TABPAGEARRAY_OBJ(a) ((Object) { \
- .type = kObjectTypeTabpageArray, \
- .data.tabpagearray = a \
- })
-
#define DICTIONARY_OBJ(d) ((Object) { \
.type = kObjectTypeDictionary, \
.data.dictionary = d \
})
-#define POSITION_OBJ(p) ((Object) { \
- .type = kObjectTypePosition, \
- .data.position = p \
- })
-
#define NIL ((Object) {.type = kObjectTypeNil})
#define PUT(dict, k, v) \
@@ -91,6 +66,25 @@
#define ADD(array, item) \
kv_push(Object, array, item)
+// Helpers used by the generated msgpack-rpc api wrappers
+#define api_init_boolean
+#define api_init_integer
+#define api_init_float
+#define api_init_string = STRING_INIT
+#define api_init_buffer
+#define api_init_window
+#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_free_boolean(value)
+#define api_free_integer(value)
+#define api_free_float(value)
+#define api_free_buffer(value)
+#define api_free_window(value)
+#define api_free_tabpage(value)
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/helpers.h.generated.h"
#endif