/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* dict.c: Dictionary support
*/
#include "vim.h"
#if defined(FEAT_EVAL) || defined(PROTO)
// List head for garbage collection. Although there can be a reference loop
// from partial to dict to partial, we don't need to keep track of the partial,
// since it will get freed when the dict is unused and gets freed.
static dict_T *first_dict = NULL;
/*
* Allocate an empty header for a dictionary.
* Caller should take care of the reference count.
*/
dict_T *
dict_alloc(void)
{
dict_T *d;
d = ALLOC_CLEAR_ONE(dict_T);
if (d != NULL)
{
// Add the dict to the list of dicts for garbage collection.
if (first_dict != NULL)
first_dict->dv_used_prev = d;
d->dv_used_next = first_dict;
d->dv_used_prev = NULL;
first_dict = d;
hash_init(&d->dv_hashtab);
d->dv_lock = 0;
d->dv_scope = 0;
d->dv_refcount = 0;
d->dv_copyID = 0;
}
return d;
}
/*
* dict_alloc() with an ID for alloc_fail().
*/
dict_T *
dict_alloc_id(alloc_id_T id UNUSED)
{
#ifdef FEAT_EVAL
if (alloc_fail_id == id && alloc_does_fail(sizeof(list_T)))
return NULL;
#endif
return (dict_alloc());
}
dict_T *
dict_alloc_lock(int lock)
{
dict_T *d = dict_alloc();
if (d != NULL)
d->dv_lock = lock;
return d;
}
/*
* Allocate an empty dict for a return value.
* Returns OK or FAIL.
*/
int
rettv_dict_alloc(typval_T *rettv)
{
dict_T *d = dict_alloc_lock(0);
if (d == NULL)
return FAIL;
rettv_dict_set(rettv, d);
return OK;
}
/*
* Set a dictionary as the return value
*/
void
rettv_dict_set(typval_T *rettv, dict_T *d)
{
rettv->v_type = VAR_DICT;
rettv->vval.v_dict = d;
if (d != NULL)
++d->dv_refcount;
}
/*
* Free a Dictionary, including all non-container items it contains.
* Ignores the reference count.
*/
void
dict_free_contents(dict_T *d)
{
hashtab_free_contents(&d->dv_hashtab);
}
/*