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
18typedef 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
27typedef 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
34typedef 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.
64typedef 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
74static 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.
85static 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