picrin/extlib/benz/dict.c

276 lines
5.9 KiB
C
Raw Normal View History

2014-08-25 00:38:09 -04:00
/**
* See Copyright Notice in picrin.h
*/
#include "picrin.h"
2016-02-20 10:58:58 -05:00
#include "picrin/extra.h"
2016-02-20 11:13:16 -05:00
#include "picrin/private/object.h"
2014-08-25 00:38:09 -04:00
2015-06-24 16:56:15 -04:00
KHASH_DEFINE(dict, pic_sym *, pic_value, kh_ptr_hash_func, kh_ptr_hash_equal)
2016-02-19 05:08:45 -05:00
pic_value
2014-09-12 06:41:20 -04:00
pic_make_dict(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
struct pic_dict *dict;
dict = (struct pic_dict *)pic_obj_alloc(pic, sizeof(struct pic_dict), PIC_TYPE_DICT);
2015-06-24 16:56:15 -04:00
kh_init(dict, &dict->hash);
2016-02-19 05:08:45 -05:00
return pic_obj_value(dict);
2014-08-25 00:38:09 -04:00
}
pic_value
2016-02-20 01:31:14 -05:00
pic_dict_ref(pic_state *pic, pic_value dict, pic_value key)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
khash_t(dict) *h = &pic_dict_ptr(pic, dict)->hash;
2016-02-20 11:52:34 -05:00
int it;
2014-08-25 00:38:09 -04:00
2016-02-20 01:31:14 -05:00
it = kh_get(dict, h, pic_sym_ptr(pic, key));
2015-06-24 16:56:15 -04:00
if (it == kh_end(h)) {
2016-02-20 01:31:14 -05:00
pic_errorf(pic, "element not found for a key: ~s", key);
2014-08-25 00:38:09 -04:00
}
2015-06-24 16:56:15 -04:00
return kh_val(h, it);
2014-08-25 00:38:09 -04:00
}
void
2016-02-20 01:31:14 -05:00
pic_dict_set(pic_state *pic, pic_value dict, pic_value key, pic_value val)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
khash_t(dict) *h = &pic_dict_ptr(pic, dict)->hash;
2015-06-24 16:56:15 -04:00
int ret;
2016-02-20 11:52:34 -05:00
int it;
2015-06-24 16:56:15 -04:00
2016-02-20 01:31:14 -05:00
it = kh_put(dict, h, pic_sym_ptr(pic, key), &ret);
2015-06-24 16:56:15 -04:00
kh_val(h, it) = val;
2014-08-25 00:38:09 -04:00
}
2015-08-26 06:04:27 -04:00
int
2016-02-21 05:19:35 -05:00
pic_dict_size(pic_state *PIC_UNUSED(pic), pic_value dict)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
return kh_size(&pic_dict_ptr(pic, dict)->hash);
2014-08-25 00:38:09 -04:00
}
bool
2016-02-20 01:31:14 -05:00
pic_dict_has(pic_state *pic, pic_value dict, pic_value key)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
khash_t(dict) *h = &pic_dict_ptr(pic, dict)->hash;
2016-02-20 01:31:14 -05:00
return kh_get(dict, h, pic_sym_ptr(pic, key)) != kh_end(h);
2014-08-25 00:38:09 -04:00
}
void
2016-02-20 01:31:14 -05:00
pic_dict_del(pic_state *pic, pic_value dict, pic_value key)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
khash_t(dict) *h = &pic_dict_ptr(pic, dict)->hash;
2016-02-20 11:52:34 -05:00
int it;
2015-06-24 16:56:15 -04:00
2016-02-20 01:31:14 -05:00
it = kh_get(dict, h, pic_sym_ptr(pic, key));
2015-06-24 16:56:15 -04:00
if (it == kh_end(h)) {
2016-02-20 01:31:14 -05:00
pic_errorf(pic, "no slot named ~s found in dictionary", key);
2014-08-25 00:38:09 -04:00
}
2015-06-24 16:56:15 -04:00
kh_del(dict, h, it);
2014-08-25 00:38:09 -04:00
}
2016-02-18 10:39:13 -05:00
bool
2016-02-21 05:19:35 -05:00
pic_dict_next(pic_state *PIC_UNUSED(pic), pic_value dict, int *iter, pic_value *key, pic_value *val)
2016-02-18 10:39:13 -05:00
{
2016-02-19 05:08:45 -05:00
khash_t(dict) *h = &pic_dict_ptr(pic, dict)->hash;
2016-02-18 10:39:13 -05:00
int it = *iter;
for (it = *iter; it != kh_end(h); ++it) {
if (kh_exist(h, it)) {
2016-02-20 01:31:14 -05:00
if (key) *key = pic_obj_value(kh_key(h, it));
2016-02-18 10:39:13 -05:00
if (val) *val = kh_val(h, it);
*iter = ++it;
return true;
}
}
return false;
}
2014-08-25 00:38:09 -04:00
static pic_value
2014-09-13 03:44:27 -04:00
pic_dict_make_dictionary(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
pic_get_args(pic, "");
2016-02-19 05:08:45 -05:00
return pic_make_dict(pic);
2014-08-25 00:38:09 -04:00
}
static pic_value
2014-09-13 03:44:27 -04:00
pic_dict_dictionary(pic_state *pic)
{
2016-02-19 05:08:45 -05:00
pic_value dict, *argv;
2015-08-26 06:04:27 -04:00
int argc, i;
2014-09-13 03:44:27 -04:00
pic_get_args(pic, "*", &argc, &argv);
dict = pic_make_dict(pic);
for (i = 0; i < argc; i += 2) {
pic_assert_type(pic, argv[i], sym);
2016-02-20 01:31:14 -05:00
pic_dict_set(pic, dict, argv[i], argv[i+1]);
2014-09-13 03:44:27 -04:00
}
2016-02-19 05:08:45 -05:00
return dict;
2014-09-13 03:44:27 -04:00
}
static pic_value
pic_dict_dictionary_p(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
pic_value obj;
pic_get_args(pic, "o", &obj);
return pic_bool_value(pic, pic_dict_p(pic, obj));
2014-08-25 00:38:09 -04:00
}
static pic_value
2014-09-13 03:44:27 -04:00
pic_dict_dictionary_ref(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
2016-02-20 01:31:14 -05:00
pic_value dict, key;
2014-08-25 00:38:09 -04:00
pic_get_args(pic, "dm", &dict, &key);
2014-08-25 00:38:09 -04:00
if (! pic_dict_has(pic, dict, key)) {
return pic_false_value(pic);
2014-08-30 13:39:09 -04:00
}
2016-02-20 01:31:14 -05:00
return pic_cons(pic, key, pic_dict_ref(pic, dict, key));
2014-08-25 00:38:09 -04:00
}
static pic_value
2014-09-13 03:44:27 -04:00
pic_dict_dictionary_set(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
2016-02-20 01:31:14 -05:00
pic_value dict, key, val;
2014-08-25 00:38:09 -04:00
pic_get_args(pic, "dmo", &dict, &key, &val);
2014-08-25 00:38:09 -04:00
if (pic_undef_p(pic, val)) {
if (pic_dict_has(pic, dict, key)) {
pic_dict_del(pic, dict, key);
}
}
else {
pic_dict_set(pic, dict, key, val);
}
return pic_undef_value(pic);
2014-08-25 00:38:09 -04:00
}
static pic_value
2014-09-13 03:44:27 -04:00
pic_dict_dictionary_size(pic_state *pic)
2014-08-25 00:38:09 -04:00
{
2016-02-19 05:08:45 -05:00
pic_value dict;
2014-08-25 00:38:09 -04:00
pic_get_args(pic, "d", &dict);
return pic_int_value(pic, pic_dict_size(pic, dict));
2014-08-25 00:38:09 -04:00
}
static pic_value
pic_dict_dictionary_map(pic_state *pic)
{
2016-02-20 01:31:14 -05:00
pic_value dict, proc, key, ret = pic_nil_value(pic);
2016-02-19 05:08:45 -05:00
int it = 0;
pic_get_args(pic, "ld", &proc, &dict);
2016-02-19 05:08:45 -05:00
while (pic_dict_next(pic, dict, &it, &key, NULL)) {
2016-02-20 01:31:14 -05:00
pic_push(pic, pic_call(pic, proc, 1, key), ret);
}
return pic_reverse(pic, ret);
}
static pic_value
pic_dict_dictionary_for_each(pic_state *pic)
{
2016-02-20 01:31:14 -05:00
pic_value dict, proc, key;
2016-02-19 05:08:45 -05:00
int it;
pic_get_args(pic, "ld", &proc, &dict);
2016-02-19 05:08:45 -05:00
while (pic_dict_next(pic, dict, &it, &key, NULL)) {
2016-02-20 01:31:14 -05:00
pic_call(pic, proc, 1, key);
}
return pic_undef_value(pic);
}
2014-09-13 03:44:27 -04:00
static pic_value
pic_dict_dictionary_to_alist(pic_state *pic)
{
2016-02-20 01:31:14 -05:00
pic_value dict, key, val, alist = pic_nil_value(pic);
2016-02-18 10:39:13 -05:00
int it = 0;
2014-09-13 03:44:27 -04:00
pic_get_args(pic, "d", &dict);
2016-02-20 01:31:14 -05:00
while (pic_dict_next(pic, dict, &it, &key, &val)) {
pic_push(pic, pic_cons(pic, key, val), alist);
2014-09-13 03:44:27 -04:00
}
2015-06-25 09:29:27 -04:00
return alist;
2014-09-13 03:44:27 -04:00
}
static pic_value
pic_dict_alist_to_dictionary(pic_state *pic)
{
2016-02-19 05:08:45 -05:00
pic_value dict, alist, e, it;
2014-09-13 03:44:27 -04:00
pic_get_args(pic, "o", &alist);
dict = pic_make_dict(pic);
2015-01-22 05:28:31 -05:00
pic_for_each (e, pic_reverse(pic, alist), it) {
pic_assert_type(pic, pic_car(pic, e), sym);
2016-02-20 01:31:14 -05:00
pic_dict_set(pic, dict, pic_car(pic, e), pic_cdr(pic, e));
2014-09-13 03:44:27 -04:00
}
2016-02-19 05:08:45 -05:00
return dict;
2014-09-13 03:44:27 -04:00
}
static pic_value
pic_dict_dictionary_to_plist(pic_state *pic)
{
2016-02-20 01:31:14 -05:00
pic_value dict, key, val, plist = pic_nil_value(pic);
2016-02-18 10:39:13 -05:00
int it = 0;
2014-09-13 03:44:27 -04:00
pic_get_args(pic, "d", &dict);
2016-02-20 01:31:14 -05:00
while (pic_dict_next(pic, dict, &it, &key, &val)) {
2016-02-18 10:39:13 -05:00
pic_push(pic, val, plist);
2016-02-20 01:31:14 -05:00
pic_push(pic, key, plist);
2014-09-13 03:44:27 -04:00
}
2015-06-25 09:29:27 -04:00
return plist;
2014-09-13 03:44:27 -04:00
}
static pic_value
pic_dict_plist_to_dictionary(pic_state *pic)
{
2016-02-19 05:08:45 -05:00
pic_value dict, plist, e;
2014-09-13 03:44:27 -04:00
pic_get_args(pic, "o", &plist);
dict = pic_make_dict(pic);
for (e = pic_reverse(pic, plist); ! pic_nil_p(pic, e); e = pic_cddr(pic, e)) {
pic_assert_type(pic, pic_cadr(pic, e), sym);
2016-02-20 01:31:14 -05:00
pic_dict_set(pic, dict, pic_cadr(pic, e), pic_car(pic, e));
2014-09-13 03:44:27 -04:00
}
2016-02-19 05:08:45 -05:00
return dict;
2014-09-13 03:44:27 -04:00
}
2014-08-25 00:38:09 -04:00
void
pic_init_dict(pic_state *pic)
{
2014-09-13 03:44:27 -04:00
pic_defun(pic, "make-dictionary", pic_dict_make_dictionary);
pic_defun(pic, "dictionary?", pic_dict_dictionary_p);
pic_defun(pic, "dictionary", pic_dict_dictionary);
pic_defun(pic, "dictionary-ref", pic_dict_dictionary_ref);
pic_defun(pic, "dictionary-set!", pic_dict_dictionary_set);
pic_defun(pic, "dictionary-size", pic_dict_dictionary_size);
pic_defun(pic, "dictionary-map", pic_dict_dictionary_map);
pic_defun(pic, "dictionary-for-each", pic_dict_dictionary_for_each);
2014-09-13 03:44:27 -04:00
pic_defun(pic, "dictionary->alist", pic_dict_dictionary_to_alist);
pic_defun(pic, "alist->dictionary", pic_dict_alist_to_dictionary);
pic_defun(pic, "dictionary->plist", pic_dict_dictionary_to_plist);
pic_defun(pic, "plist->dictionary", pic_dict_plist_to_dictionary);
2014-08-25 00:38:09 -04:00
}