Files
neovim/src/nvim/eval/typval_encode.h
2017-03-29 10:05:06 +03:00

147 lines
5.2 KiB
C

/// @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 <stddef.h>
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include "nvim/lib/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 *const 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((char *) 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