ds: dict: update iterator interface
This commit is contained in:
262
ds/dict.c
262
ds/dict.c
@@ -26,6 +26,16 @@ struct b_dict_p {
|
||||
b_btree d_buckets;
|
||||
};
|
||||
|
||||
struct b_dict_iterator_p {
|
||||
size_t i;
|
||||
b_dict_item item;
|
||||
|
||||
b_dict *_d;
|
||||
struct b_dict_p *_d_p;
|
||||
b_btree_node *_cbn;
|
||||
b_queue_entry *_cqe;
|
||||
};
|
||||
|
||||
/*** MISC FUNCTIONS ***********************************************************/
|
||||
|
||||
static B_BTREE_DEFINE_SIMPLE_GET(
|
||||
@@ -132,14 +142,16 @@ static b_object *dict_at(const struct b_dict_p *dict, const char *key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b_queue_iterator it;
|
||||
b_queue_foreach (&it, &bucket->bk_items) {
|
||||
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
|
||||
while (entry) {
|
||||
struct b_dict_bucket_item *item
|
||||
= b_unbox(struct b_dict_bucket_item, it.entry, bi_entry);
|
||||
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
|
||||
|
||||
if (!strcmp(b_string_ptr(item->bi_str), key)) {
|
||||
return item->bi_value;
|
||||
}
|
||||
|
||||
entry = b_queue_next(entry);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -153,14 +165,16 @@ static b_object *dict_at_sk(const struct b_dict_p *dict, const b_string *key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b_queue_iterator it;
|
||||
b_queue_foreach (&it, &bucket->bk_items) {
|
||||
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
|
||||
while (entry) {
|
||||
struct b_dict_bucket_item *item
|
||||
= b_unbox(struct b_dict_bucket_item, it.entry, bi_entry);
|
||||
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
|
||||
|
||||
if (b_string_compare(item->bi_str, key)) {
|
||||
return item->bi_value;
|
||||
}
|
||||
|
||||
entry = b_queue_next(entry);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -199,6 +213,7 @@ static bool dict_has_skey(const struct b_dict_p *dict, const b_string *key)
|
||||
static size_t dict_get_size(const struct b_dict_p *dict)
|
||||
{
|
||||
size_t count = 0;
|
||||
#if 0
|
||||
b_btree_iterator it1;
|
||||
b_queue_iterator it2;
|
||||
|
||||
@@ -210,6 +225,7 @@ static size_t dict_get_size(const struct b_dict_p *dict)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -298,6 +314,7 @@ static b_status delete_item(
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
#if 0
|
||||
b_dict *b_dict_create_with_items(const b_dict_item *items)
|
||||
{
|
||||
b_dict *dict = b_dict_create();
|
||||
@@ -313,6 +330,8 @@ b_dict *b_dict_create_with_items(const b_dict_item *items)
|
||||
|
||||
return dict;
|
||||
}
|
||||
#endif
|
||||
|
||||
b_status b_dict_put(b_dict *dict, const char *key, b_object *value)
|
||||
{
|
||||
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put, dict, key, value);
|
||||
@@ -375,6 +394,7 @@ static void dict_fini(b_object *obj, void *priv)
|
||||
{
|
||||
struct b_dict_p *dict = priv;
|
||||
|
||||
#if 0
|
||||
b_btree_iterator tree_it;
|
||||
b_btree_iterator_begin(&dict->d_buckets, &tree_it);
|
||||
while (b_btree_iterator_is_valid(&tree_it)) {
|
||||
@@ -405,6 +425,7 @@ static void dict_fini(b_object *obj, void *priv)
|
||||
|
||||
free(bucket);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dict_to_string(const b_object *obj, b_stream *out)
|
||||
@@ -421,6 +442,7 @@ static void dict_to_string(const b_object *obj, b_stream *out)
|
||||
b_stream_push_indent(out, 1);
|
||||
size_t len = dict_get_size(dict);
|
||||
|
||||
#if 0
|
||||
b_dict_iterator it;
|
||||
b_dict_foreach(&it, (b_dict *)obj)
|
||||
{
|
||||
@@ -445,138 +467,163 @@ static void dict_to_string(const b_object *obj, b_stream *out)
|
||||
|
||||
b_stream_write_char(out, '\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
b_stream_pop_indent(out);
|
||||
b_stream_write_char(out, '}');
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict)
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
|
||||
B_INTERFACE_ENTRY(to_string) = dict_to_string;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
|
||||
B_TYPE_CLASS_DEFINITION_END(b_dict)
|
||||
|
||||
B_TYPE_DEFINITION_BEGIN(b_dict)
|
||||
B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10);
|
||||
B_TYPE_CLASS(b_dict_class);
|
||||
B_TYPE_INSTANCE_PRIVATE(struct b_dict_p);
|
||||
B_TYPE_INSTANCE_INIT(dict_init);
|
||||
B_TYPE_INSTANCE_FINI(dict_fini);
|
||||
B_TYPE_DEFINITION_END(b_dict)
|
||||
|
||||
/*** ITERATOR FUNCTIONS *******************************************************/
|
||||
|
||||
static bool dict_iterator_next(struct b_iterator *it)
|
||||
static b_iterator *iterable_begin(b_dict *dict)
|
||||
{
|
||||
return b_dict_iterator_next((struct b_dict_iterator *)it);
|
||||
}
|
||||
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
|
||||
if (!it_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static b_status dict_iterator_erase(struct b_iterator *it)
|
||||
{
|
||||
return b_dict_iterator_erase((struct b_dict_iterator *)it);
|
||||
}
|
||||
|
||||
static bool dict_iterator_is_valid(const struct b_iterator *it)
|
||||
{
|
||||
return b_dict_iterator_is_valid((struct b_dict_iterator *)it);
|
||||
}
|
||||
|
||||
static struct b_iterator_ops it_ops = {
|
||||
.it_next = dict_iterator_next,
|
||||
.it_close = NULL,
|
||||
.it_erase = dict_iterator_erase,
|
||||
.it_is_valid = dict_iterator_is_valid,
|
||||
};
|
||||
|
||||
int b_dict_iterator_begin(b_dict *dict, b_dict_iterator *it)
|
||||
{
|
||||
it->_base.it_ops = &it_ops;
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
it->i = 0;
|
||||
it->_d = dict;
|
||||
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
|
||||
|
||||
if (dict_is_empty(it->_d_p)) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return -1;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
|
||||
struct b_dict_bucket *first_bucket
|
||||
= b_unbox(struct b_dict_bucket, first_node, bk_node);
|
||||
if (!first_bucket) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return -1;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
|
||||
struct b_dict_bucket_item *first_item
|
||||
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
|
||||
if (!first_item) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return -1;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
it->key = first_item->bi_str;
|
||||
it->value = first_item->bi_value;
|
||||
it->item.key = first_item->bi_str;
|
||||
it->item.value = first_item->bi_value;
|
||||
|
||||
it->_d = dict;
|
||||
it->_cbn = first_node;
|
||||
it->_cqe = first_entry;
|
||||
|
||||
return 0;
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
bool b_dict_iterator_next(b_dict_iterator *it)
|
||||
static const b_iterator *iterable_cbegin(const b_dict *dict)
|
||||
{
|
||||
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
|
||||
if (!it_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
it->i = 0;
|
||||
it->_d = (b_dict *)dict;
|
||||
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
|
||||
|
||||
if (dict_is_empty(it->_d_p)) {
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
|
||||
struct b_dict_bucket *first_bucket
|
||||
= b_unbox(struct b_dict_bucket, first_node, bk_node);
|
||||
if (!first_bucket) {
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
|
||||
struct b_dict_bucket_item *first_item
|
||||
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
|
||||
if (!first_item) {
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
it->item.key = first_item->bi_str;
|
||||
it->item.value = first_item->bi_value;
|
||||
|
||||
it->_cbn = first_node;
|
||||
it->_cqe = first_entry;
|
||||
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
static enum b_status iterator_move_next(const b_iterator *obj)
|
||||
{
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
struct b_btree_node *next_node;
|
||||
struct b_queue_entry *next_entry;
|
||||
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return -1;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return B_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
struct b_dict_bucket_item *next_item
|
||||
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
|
||||
|
||||
if (!next_item) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return -1;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return B_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
it->i++;
|
||||
it->key = next_item->bi_str;
|
||||
it->value = next_item->bi_value;
|
||||
it->item.key = next_item->bi_str;
|
||||
it->item.value = next_item->bi_value;
|
||||
|
||||
it->_cbn = next_node;
|
||||
it->_cqe = next_entry;
|
||||
|
||||
return 0;
|
||||
return B_SUCCESS;
|
||||
}
|
||||
|
||||
b_status b_dict_iterator_erase(struct b_dict_iterator *it)
|
||||
static enum b_status iterator_erase(b_iterator *obj)
|
||||
{
|
||||
if ((it->key || it->value) && !(it->_cbn && it->_cqe)) {
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
if ((it->item.key || it->item.value) && !(it->_cbn && it->_cqe)) {
|
||||
return B_ERR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (!it->key || !it->_cqe) {
|
||||
return B_ERR_OUT_OF_BOUNDS;
|
||||
if (!it->item.key || !it->_cqe) {
|
||||
return B_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
struct b_btree_node *next_node;
|
||||
struct b_queue_entry *next_entry;
|
||||
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
return false;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
return B_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
struct b_dict_bucket *cur_bucket
|
||||
@@ -593,14 +640,14 @@ b_status b_dict_iterator_erase(struct b_dict_iterator *it)
|
||||
}
|
||||
|
||||
if (next_item) {
|
||||
it->key = next_item->bi_str;
|
||||
it->value = next_item->bi_value;
|
||||
it->item.key = next_item->bi_str;
|
||||
it->item.value = next_item->bi_value;
|
||||
|
||||
it->_cbn = next_node;
|
||||
it->_cqe = next_entry;
|
||||
} else {
|
||||
it->key = NULL;
|
||||
it->value = NULL;
|
||||
it->item.key = NULL;
|
||||
it->item.value = NULL;
|
||||
|
||||
it->_cbn = NULL;
|
||||
it->_cqe = NULL;
|
||||
@@ -609,7 +656,62 @@ b_status b_dict_iterator_erase(struct b_dict_iterator *it)
|
||||
return B_SUCCESS;
|
||||
}
|
||||
|
||||
bool b_dict_iterator_is_valid(const struct b_dict_iterator *it)
|
||||
static b_iterator_value iterator_get_value(b_iterator *obj)
|
||||
{
|
||||
return it->key != NULL;
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
return B_ITERATOR_VALUE_PTR(&it->item);
|
||||
}
|
||||
|
||||
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
|
||||
{
|
||||
struct b_dict_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
|
||||
|
||||
return B_ITERATOR_VALUE_CPTR(&it->item);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
// ---- b_dict DEFINITION
|
||||
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict)
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
|
||||
B_INTERFACE_ENTRY(to_string) = dict_to_string;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
|
||||
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
|
||||
B_INTERFACE_ENTRY(it_begin) = iterable_begin;
|
||||
B_INTERFACE_ENTRY(it_cbegin) = iterable_cbegin;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
|
||||
B_TYPE_CLASS_DEFINITION_END(b_dict)
|
||||
|
||||
B_TYPE_DEFINITION_BEGIN(b_dict)
|
||||
B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10);
|
||||
B_TYPE_CLASS(b_dict_class);
|
||||
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
|
||||
B_TYPE_INSTANCE_PRIVATE(struct b_dict_p);
|
||||
B_TYPE_INSTANCE_INIT(dict_init);
|
||||
B_TYPE_INSTANCE_FINI(dict_fini);
|
||||
B_TYPE_DEFINITION_END(b_dict)
|
||||
|
||||
// ---- b_dict_iterator DEFINITION
|
||||
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict_iterator)
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
|
||||
B_INTERFACE_ENTRY(to_string) = NULL;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
|
||||
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
|
||||
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
||||
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
||||
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
||||
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
|
||||
B_TYPE_CLASS_DEFINITION_END(b_dict_iterator)
|
||||
|
||||
B_TYPE_DEFINITION_BEGIN(b_dict_iterator)
|
||||
B_TYPE_ID(0x9ea96701, 0x1713, 0x4a3e, 0xbf63, 0xdc856b456f3b);
|
||||
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
|
||||
B_TYPE_CLASS(b_dict_iterator_class);
|
||||
B_TYPE_INSTANCE_PRIVATE(struct b_dict_iterator_p);
|
||||
B_TYPE_DEFINITION_END(b_dict_iterator)
|
||||
|
||||
@@ -11,14 +11,19 @@
|
||||
B_DECLS_BEGIN;
|
||||
|
||||
#define B_TYPE_DICT (b_dict_get_type())
|
||||
#define B_TYPE_DICT_ITERATOR (b_dict_iterator_get_type())
|
||||
|
||||
struct b_dict_p;
|
||||
|
||||
B_DECLARE_TYPE(b_dict);
|
||||
B_DECLARE_TYPE(b_dict_iterator);
|
||||
|
||||
B_TYPE_CLASS_DECLARATION_BEGIN(b_dict)
|
||||
B_TYPE_CLASS_DECLARATION_END(b_dict)
|
||||
|
||||
B_TYPE_CLASS_DECLARATION_BEGIN(b_dict_iterator)
|
||||
B_TYPE_CLASS_DECLARATION_END(b_dict_iterator)
|
||||
|
||||
#define B_DICT_ITEM(k, v) {.key = (k), .value = (v)}
|
||||
#define B_DICT_ITEM_END {.key = NULL, .value = NULL}
|
||||
|
||||
@@ -26,28 +31,19 @@ B_TYPE_CLASS_DECLARATION_END(b_dict)
|
||||
for (int z__b_unique_name() = b_dict_iterator_begin(dict, it); \
|
||||
(it)->key != NULL; b_dict_iterator_next(it))
|
||||
|
||||
typedef struct b_dict_iterator {
|
||||
b_iterator _base;
|
||||
size_t i;
|
||||
const b_string *key;
|
||||
b_object *value;
|
||||
|
||||
b_dict *_d;
|
||||
struct b_dict_p *_d_p;
|
||||
b_btree_node *_cbn;
|
||||
b_queue_entry *_cqe;
|
||||
} b_dict_iterator;
|
||||
|
||||
typedef struct b_dict_item {
|
||||
const char *key;
|
||||
const b_string *key;
|
||||
b_object *value;
|
||||
} b_dict_item;
|
||||
|
||||
BLUE_API b_type b_dict_get_type(void);
|
||||
BLUE_API b_type b_dict_iterator_get_type(void);
|
||||
|
||||
B_TYPE_DEFAULT_CONSTRUCTOR(b_dict, B_TYPE_DICT);
|
||||
|
||||
#if 0
|
||||
BLUE_API b_dict *b_dict_create_with_items(const b_dict_item *items);
|
||||
#endif
|
||||
|
||||
BLUE_API b_status b_dict_put(b_dict *dict, const char *key, b_object *value);
|
||||
BLUE_API b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value);
|
||||
@@ -61,11 +57,6 @@ BLUE_API bool b_dict_has_skey(const b_dict *dict, const b_string *key);
|
||||
BLUE_API size_t b_dict_get_size(const b_dict *dict);
|
||||
BLUE_API bool b_dict_is_empty(const b_dict *dict);
|
||||
|
||||
BLUE_API int b_dict_iterator_begin(b_dict *dict, b_dict_iterator *it);
|
||||
BLUE_API bool b_dict_iterator_next(b_dict_iterator *it);
|
||||
BLUE_API b_status b_dict_iterator_erase(b_dict_iterator *it);
|
||||
BLUE_API bool b_dict_iterator_is_valid(const b_dict_iterator *it);
|
||||
|
||||
B_DECLS_END;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user