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