1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/// @file eval/typval_encode.h
///
/// Contains common definitions for eval/typval_encode.c.h. Most of time should
/// not be included directly.
#ifndef NVIM_EVAL_TYPVAL_ENCODE_H
#define NVIM_EVAL_TYPVAL_ENCODE_H
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <string.h>
#include "klib/kvec.h"
#include "nvim/eval/typval.h"
#include "nvim/func_attr.h"
/// Type of the stack entry
typedef enum {
kMPConvDict, ///< Convert dict_T *dictionary.
kMPConvList, ///< Convert list_T *list.
kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs.
kMPConvPartial, ///< Convert partial_T* partial.
kMPConvPartialList, ///< Convert argc/argv pair coming from a partial.
} MPConvStackValType;
/// Stage at which partial is being converted
typedef enum {
kMPConvPartialArgs, ///< About to convert arguments.
kMPConvPartialSelf, ///< About to convert self dictionary.
kMPConvPartialEnd, ///< Already converted everything.
} MPConvPartialStage;
/// Structure representing current VimL to messagepack conversion state
typedef struct {
MPConvStackValType type; ///< Type of the stack entry.
typval_T *tv; ///< Currently converted typval_T.
int saved_copyID; ///< copyID item used to have.
union {
struct {
dict_T *dict; ///< Currently converted dictionary.
dict_T **dictp; ///< Location where that dictionary is stored.
///< Normally it is &.tv->vval.v_dict, but not when
///< converting partials.
hashitem_T *hi; ///< Currently converted dictionary item.
size_t todo; ///< Amount of items left to process.
} d; ///< State of dictionary conversion.
struct {
list_T *list; ///< Currently converted list.
listitem_T *li; ///< Currently converted list item.
} l; ///< State of list or generic mapping conversion.
struct {
MPConvPartialStage stage; ///< Stage at which partial is being converted.
partial_T *pt; ///< Currently converted partial.
} p; ///< State of partial conversion.
struct {
typval_T *arg; ///< Currently converted argument.
typval_T *argv; ///< Start of the argument list.
size_t todo; ///< Number of items left to process.
} a; ///< State of list or generic mapping conversion.
} data; ///< Data to convert.
} MPConvStackVal;
/// Stack used to convert VimL values to messagepack.
typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack;
// Defines for MPConvStack
#define _mp_size kv_size
#define _mp_init kvi_init
#define _mp_destroy kvi_destroy
#define _mp_push kvi_push
#define _mp_pop kv_pop
#define _mp_last kv_last
static inline size_t tv_strlen(const typval_T *tv)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT
REAL_FATTR_NONNULL_ALL;
/// Length of the string stored in typval_T
///
/// @param[in] tv String for which to compute length for. Must be typval_T
/// with VAR_STRING.
///
/// @return Length of the string stored in typval_T, including 0 for NULL
/// string.
static inline size_t tv_strlen(const typval_T *const tv)
{
assert(tv->v_type == VAR_STRING);
return (tv->vval.v_string == NULL ? 0 : strlen(tv->vval.v_string));
}
/// Code for checking whether container references itself
///
/// @param[in,out] val Container to check.
/// @param copyID_attr Name of the container attribute that holds copyID.
/// After checking whether value of this attribute is
/// copyID (variable) it is set to copyID.
/// @param[in] copyID CopyID used by the caller.
/// @param conv_type Type of the conversion, @see MPConvStackValType.
#define _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val, copyID_attr, copyID, \
conv_type) \
do { \
const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(TYPVAL_ENCODE_FIRST_ARG_NAME, \
(val), &(val)->copyID_attr, mpstack, \
copyID, conv_type, objname); \
if (te_csr_ret != NOTDONE) { \
return te_csr_ret; \
} \
} while (0)
#define _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) \
pref##name##suf
#define _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, name, suf) \
_TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf)
/// Construct function name, possibly using macros
///
/// Is used to expand macros that may appear in arguments.
///
/// @note Expands all arguments, even if only one is needed.
///
/// @param[in] pref Prefix.
/// @param[in] suf Suffix.
///
/// @return Concat: pref + #TYPVAL_ENCODE_NAME + suf.
#define _TYPVAL_ENCODE_FUNC_NAME(pref, suf) \
_TYPVAL_ENCODE_FUNC_NAME_INNER(pref, TYPVAL_ENCODE_NAME, suf)
/// Self reference checker function name
#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE \
_TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _check_self_reference)
/// Entry point function name
#define _TYPVAL_ENCODE_ENCODE \
_TYPVAL_ENCODE_FUNC_NAME(encode_vim_to_, )
/// Name of the …convert_one_value function
#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE \
_TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _convert_one_value)
/// Name of the dummy const dict_T *const variable
#define TYPVAL_ENCODE_NODICT_VAR \
_TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var)
#endif // NVIM_EVAL_TYPVAL_ENCODE_H
|