ds: dict: convert to new object system

This commit is contained in:
2025-10-19 11:53:08 +01:00
parent ff2ff6f136
commit 5bf3c50a7f
3 changed files with 327 additions and 289 deletions

527
ds/dict.c
View File

@@ -1,16 +1,38 @@
#include "dict.h"
#include <blue/core/status.h> #include <blue/core/status.h>
#include <blue/core/stream.h> #include <blue/core/stream.h>
#include <blue/ds/dict.h> #include <blue/ds/dict.h>
#include <blue/ds/string.h> #include <blue/ds/string.h>
#include <blue/ds/type.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#define HASH_OFFSET_BASIS 0xcbf29ce484222325 #define HASH_OFFSET_BASIS 0xcbf29ce484222325
#define HASH_PRIME 0x100000001b3 #define HASH_PRIME 0x100000001b3
/*** PRIVATE DATA *************************************************************/
struct b_dict_bucket_item {
b_queue_entry bi_entry;
b_string *bi_str;
b_object *bi_value;
};
struct b_dict_bucket {
b_btree_node bk_node;
uint64_t bk_hash;
b_queue bk_items;
};
struct b_dict_p {
b_btree d_buckets;
};
/*** MISC FUNCTIONS ***********************************************************/
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_dict_bucket, uint64_t, bk_node, bk_hash, get_bucket);
static B_BTREE_DEFINE_SIMPLE_INSERT(
struct b_dict_bucket, bk_node, bk_hash, put_bucket);
uint64_t b_cstr_hash(const char *s) uint64_t b_cstr_hash(const char *s)
{ {
uint64_t hash = HASH_OFFSET_BASIS; uint64_t hash = HASH_OFFSET_BASIS;
@@ -23,46 +45,7 @@ uint64_t b_cstr_hash(const char *s)
return hash; return hash;
} }
static void dict_release(struct b_dsref *obj); /*** PRIVATE FUNCTIONS ********************************************************/
static void dict_to_string(const struct b_dsref *obj, struct b_stream *out);
static struct b_dsref_type dict_type = {
.t_name = "corelib::dict",
.t_flags = B_DSREF_FUNDAMENTAL,
.t_id = B_DSREF_TYPE_DICT,
.t_instance_size = sizeof(struct b_dict),
.t_release = dict_release,
.t_to_string = dict_to_string,
};
struct b_dict *b_dict_create(void)
{
struct b_dict *dict
= (struct b_dict *)b_dsref_type_instantiate(&dict_type);
if (!dict) {
return NULL;
}
return dict;
}
struct b_dict *b_dict_create_with_items(const b_dict_item *items)
{
struct b_dict *dict = b_dict_create();
if (!dict) {
return NULL;
}
for (size_t i = 0; items[i].key; i++) {
b_dict_put(dict, items[i].key, items[i].value);
}
return dict;
}
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_dict_bucket, uint64_t, bk_node, bk_hash,
get_bucket) static B_BTREE_DEFINE_SIMPLE_INSERT(struct b_dict_bucket, bk_node, bk_hash, put_bucket)
static struct b_dict_bucket *create_bucket(void) static struct b_dict_bucket *create_bucket(void)
{ {
@@ -86,7 +69,7 @@ static struct b_dict_bucket_item *create_bucket_item(void)
return item; return item;
} }
b_status b_dict_put(struct b_dict *dict, const char *key, b_dsref *value) static b_status dict_put(struct b_dict_p *dict, const char *key, b_object *value)
{ {
uint64_t hash = b_cstr_hash(key); uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash); struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
@@ -106,15 +89,15 @@ b_status b_dict_put(struct b_dict *dict, const char *key, b_dsref *value)
} }
item->bi_str = b_string_create_from_cstr(key); item->bi_str = b_string_create_from_cstr(key);
item->bi_value = b_retain(value); item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry); b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS; return B_SUCCESS;
} }
b_status b_dict_put_sk( static b_status dict_put_sk(
struct b_dict *dict, const struct b_string *key, b_dsref *value) struct b_dict_p *dict, const b_string *key, b_object *value)
{ {
uint64_t hash = b_string_hash(key); uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash); struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
@@ -134,14 +117,14 @@ b_status b_dict_put_sk(
} }
item->bi_str = b_string_duplicate(key); item->bi_str = b_string_duplicate(key);
item->bi_value = b_retain(value); item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry); b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS; return B_SUCCESS;
} }
b_dsref *b_dict_at(const struct b_dict *dict, const char *key) static b_object *dict_at(const struct b_dict_p *dict, const char *key)
{ {
uint64_t hash = b_cstr_hash(key); uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash); struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
@@ -162,7 +145,7 @@ b_dsref *b_dict_at(const struct b_dict *dict, const char *key)
return NULL; return NULL;
} }
b_dsref *b_dict_at_sk(const struct b_dict *dict, const struct b_string *key) static b_object *dict_at_sk(const struct b_dict_p *dict, const b_string *key)
{ {
uint64_t hash = b_string_hash(key); uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash); struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
@@ -183,37 +166,37 @@ b_dsref *b_dict_at_sk(const struct b_dict *dict, const struct b_string *key)
return NULL; return NULL;
} }
b_dsref *b_dict_get(struct b_dict *dict, const char *key) static b_object *dict_get(struct b_dict_p *dict, const char *key)
{ {
b_dsref *value = b_dict_at(dict, key); b_object *value = dict_at(dict, key);
if (value) { if (value) {
b_retain(value); b_object_ref(value);
} }
return value; return value;
} }
b_dsref *b_dict_get_sk(struct b_dict *dict, const struct b_string *key) static b_object *dict_get_sk(struct b_dict_p *dict, const b_string *key)
{ {
b_dsref *value = b_dict_at_sk(dict, key); b_object *value = dict_at_sk(dict, key);
if (value) { if (value) {
b_retain(value); b_object_ref(value);
} }
return value; return value;
} }
bool b_dict_has_key(const struct b_dict *dict, const char *key) static bool dict_has_key(const struct b_dict_p *dict, const char *key)
{ {
return b_dict_at(dict, key) != NULL; return dict_at(dict, key) != NULL;
} }
bool b_dict_has_skey(const struct b_dict *dict, const struct b_string *key) static bool dict_has_skey(const struct b_dict_p *dict, const b_string *key)
{ {
return b_dict_at_sk(dict, key) != NULL; return dict_at_sk(dict, key) != NULL;
} }
size_t b_dict_get_size(const struct b_dict *dict) static size_t dict_get_size(const struct b_dict_p *dict)
{ {
size_t count = 0; size_t count = 0;
b_btree_iterator it1; b_btree_iterator it1;
@@ -231,7 +214,7 @@ size_t b_dict_get_size(const struct b_dict *dict)
return count; return count;
} }
bool b_dict_is_empty(const b_dict *dict) static bool dict_is_empty(const struct b_dict_p *dict)
{ {
b_btree_node *first_node = b_btree_first(&dict->d_buckets); b_btree_node *first_node = b_btree_first(&dict->d_buckets);
struct b_dict_bucket *first_bucket struct b_dict_bucket *first_bucket
@@ -250,110 +233,6 @@ bool b_dict_is_empty(const b_dict *dict)
return false; return false;
} }
static void dict_to_string(const struct b_dsref *obj, struct b_stream *out)
{
struct b_dict *dict = B_DICT(obj);
if (b_dict_is_empty(dict)) {
b_stream_write_string(out, "{}", NULL);
return;
}
b_stream_write_string(out, "{\n", NULL);
b_stream_push_indent(out, 1);
size_t len = b_dict_get_size(dict);
b_dict_iterator it;
b_dict_foreach(&it, dict)
{
b_to_string(B_DSREF(it.key), out);
b_stream_write_string(out, ": ", NULL);
bool is_string = b_typeid(it.value) == B_DSREF_TYPE_STRING;
if (is_string) {
b_stream_write_char(out, '"');
}
b_to_string(it.value, out);
if (is_string) {
b_stream_write_char(out, '"');
}
if (it.i < len - 1) {
b_stream_write_string(out, ",", NULL);
}
b_stream_write_char(out, '\n');
}
b_stream_pop_indent(out);
b_stream_write_char(out, '}');
}
static bool dict_iterator_next(struct b_iterator *it)
{
return b_dict_iterator_next((struct b_dict_iterator *)it);
}
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(struct b_dict *dict, b_dict_iterator *it)
{
it->_base.it_ops = &it_ops;
it->i = 0;
if (b_dict_is_empty(dict)) {
it->key = NULL;
it->value = NULL;
return -1;
}
b_btree_node *first_node = b_btree_first(&dict->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;
}
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->key = first_item->bi_str;
it->value = first_item->bi_value;
it->_d = dict;
it->_cbn = first_node;
it->_cqe = first_entry;
return 0;
}
static bool get_next_node( static bool get_next_node(
struct b_btree_node *cur_node, struct b_queue_entry *cur_entry, struct b_btree_node *cur_node, struct b_queue_entry *cur_entry,
struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry) struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry)
@@ -402,6 +281,256 @@ static bool get_next_node(
return true; return true;
} }
static b_status delete_item(
struct b_dict_p *dict, struct b_dict_bucket *bucket,
struct b_dict_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&dict->d_buckets, &bucket->bk_node);
free(bucket);
}
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_dict *b_dict_create_with_items(const b_dict_item *items)
{
b_dict *dict = b_dict_create();
if (!dict) {
return NULL;
}
struct b_dict_p *p = b_object_get_private(dict, B_TYPE_DICT);
for (size_t i = 0; items[i].key; i++) {
dict_put(p, items[i].key, items[i].value);
}
return dict;
}
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);
}
b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put_sk, dict, key, value);
}
b_object *b_dict_at(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at, dict, key);
}
b_object *b_dict_at_sk(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at_sk, dict, key);
}
b_object *b_dict_get(b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get, dict, key);
}
b_object *b_dict_get_sk(b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get_sk, dict, key);
}
bool b_dict_has_key(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_key, dict, key);
}
bool b_dict_has_skey(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_skey, dict, key);
}
size_t b_dict_get_size(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_get_size, dict);
}
bool b_dict_is_empty(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_is_empty, dict);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void dict_init(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
}
static void dict_fini(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
b_btree_iterator tree_it;
b_btree_iterator_begin(&dict->d_buckets, &tree_it);
while (b_btree_iterator_is_valid(&tree_it)) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, tree_it.node, bk_node);
b_btree_iterator_erase(&tree_it);
if (!bucket) {
continue;
}
b_queue_iterator bucket_it;
b_queue_iterator_begin(&bucket->bk_items, &bucket_it);
while (b_queue_iterator_is_valid(&bucket_it)) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, bucket_it.entry,
bi_entry);
b_queue_iterator_erase(&bucket_it);
if (!item) {
continue;
}
free(item->bi_str);
b_object_unref(item->bi_value);
free(item);
}
free(bucket);
}
}
static void dict_to_string(const b_object *obj, struct b_stream *out)
{
struct b_dict_p *dict = b_object_get_private(obj, B_TYPE_DICT);
if (dict_is_empty(dict)) {
b_stream_write_string(out, "{}", NULL);
return;
}
b_stream_write_string(out, "{\n", NULL);
b_stream_push_indent(out, 1);
size_t len = dict_get_size(dict);
b_dict_iterator it;
b_dict_foreach(&it, (b_dict *)obj)
{
b_object_to_string(it.key, out);
b_stream_write_string(out, ": ", NULL);
bool is_string = b_object_is_type(it.value, B_TYPE_STRING);
if (is_string) {
b_stream_write_char(out, '"');
}
b_object_to_string(it.value, out);
if (is_string) {
b_stream_write_char(out, '"');
}
if (it.i < len - 1) {
b_stream_write_string(out, ",", NULL);
}
b_stream_write_char(out, '\n');
}
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_INIT(dict_init);
B_TYPE_INSTANCE_INIT(dict_fini);
B_TYPE_DEFINITION_END(b_dict)
/*** ITERATOR FUNCTIONS *******************************************************/
static bool dict_iterator_next(struct b_iterator *it)
{
return b_dict_iterator_next((struct b_dict_iterator *)it);
}
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;
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;
}
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;
}
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->key = first_item->bi_str;
it->value = first_item->bi_value;
it->_d = dict;
it->_cbn = first_node;
it->_cqe = first_entry;
return 0;
}
bool b_dict_iterator_next(b_dict_iterator *it) bool b_dict_iterator_next(b_dict_iterator *it)
{ {
struct b_btree_node *next_node; struct b_btree_node *next_node;
@@ -431,21 +560,6 @@ bool b_dict_iterator_next(b_dict_iterator *it)
return 0; return 0;
} }
static b_status delete_item(
struct b_dict *dict, struct b_dict_bucket *bucket,
struct b_dict_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&dict->d_buckets, &bucket->bk_node);
free(bucket);
}
return B_SUCCESS;
}
b_status b_dict_iterator_erase(struct b_dict_iterator *it) b_status b_dict_iterator_erase(struct b_dict_iterator *it)
{ {
if ((it->key || it->value) && !(it->_cbn && it->_cqe)) { if ((it->key || it->value) && !(it->_cbn && it->_cqe)) {
@@ -472,7 +586,7 @@ b_status b_dict_iterator_erase(struct b_dict_iterator *it)
struct b_dict_bucket_item *next_item struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry); = b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
b_status status = delete_item(it->_d, cur_bucket, cur_item); b_status status = delete_item(it->_d_p, cur_bucket, cur_item);
if (B_ERR(status)) { if (B_ERR(status)) {
return status; return status;
} }
@@ -498,52 +612,3 @@ bool b_dict_iterator_is_valid(const struct b_dict_iterator *it)
{ {
return it->key != NULL; return it->key != NULL;
} }
static void dict_release(struct b_dsref *obj)
{
struct b_dict *dict = B_DICT(obj);
b_btree_iterator tree_it;
b_btree_iterator_begin(&dict->d_buckets, &tree_it);
while (b_btree_iterator_is_valid(&tree_it)) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, tree_it.node, bk_node);
b_btree_iterator_erase(&tree_it);
if (!bucket) {
continue;
}
b_queue_iterator bucket_it;
b_queue_iterator_begin(&bucket->bk_items, &bucket_it);
while (b_queue_iterator_is_valid(&bucket_it)) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, bucket_it.entry,
bi_entry);
b_queue_iterator_erase(&bucket_it);
if (!item) {
continue;
}
free(item->bi_str);
b_release(item->bi_value);
free(item);
}
free(bucket);
}
#if 0
b_dict_iterator it;
b_dict_iterator_begin(dict, &it);
while (b_dict_iterator_is_valid(&it)) {
b_dict_iterator_erase(&it);
}
#endif
}
b_dsref_type_id b_dict_type_id(void)
{
return (b_dsref_type_id)&dict_type;
}

View File

@@ -1,28 +0,0 @@
#ifndef _B_DICT_H_
#define _B_DICT_H_
#include "object.h"
#include <blue/core/btree.h>
#include <blue/core/queue.h>
struct b_string;
struct b_dict_bucket_item {
b_queue_entry bi_entry;
struct b_string *bi_str;
struct b_dsref *bi_value;
};
struct b_dict_bucket {
b_btree_node bk_node;
uint64_t bk_hash;
b_queue bk_items;
};
struct b_dict {
struct b_dsref d_base;
b_btree d_buckets;
};
#endif

View File

@@ -1,16 +1,23 @@
#ifndef BLUELIB_DICT_H_ #ifndef BLUE_DS_DICT_H_
#define BLUELIB_DICT_H_ #define BLUE_DS_DICT_H_
#include <blue/core/btree.h> #include <blue/core/btree.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h> #include <blue/core/misc.h>
#include <blue/core/queue.h> #include <blue/core/queue.h>
#include <blue/core/status.h> #include <blue/core/status.h>
#include <blue/ds/object.h> #include <blue/ds/string.h>
#include <blue/ds/type.h>
struct b_string; B_DECLS_BEGIN;
#define B_DICT(p) ((b_dict *)(p)) #define B_TYPE_DICT (b_dict_get_type())
struct b_dict_p;
B_DECLARE_TYPE(b_dict);
B_TYPE_CLASS_DECLARATION_BEGIN(b_dict)
B_TYPE_CLASS_DECLARATION_END(b_dict)
#define B_DICT_ITEM(k, v) {.key = (k), .value = (v)} #define B_DICT_ITEM(k, v) {.key = (k), .value = (v)}
#define B_DICT_ITEM_END {.key = NULL, .value = NULL} #define B_DICT_ITEM_END {.key = NULL, .value = NULL}
@@ -19,46 +26,38 @@ struct b_string;
for (int z__b_unique_name() = b_dict_iterator_begin(dict, it); \ for (int z__b_unique_name() = b_dict_iterator_begin(dict, it); \
(it)->key != NULL; b_dict_iterator_next(it)) (it)->key != NULL; b_dict_iterator_next(it))
typedef struct b_dict b_dict;
typedef struct b_dict_iterator { typedef struct b_dict_iterator {
b_iterator _base; b_iterator _base;
size_t i; size_t i;
const struct b_string *key; const b_string *key;
b_dsref *value; b_object *value;
b_dict *_d; b_dict *_d;
struct b_dict_p *_d_p;
b_btree_node *_cbn; b_btree_node *_cbn;
b_queue_entry *_cqe; b_queue_entry *_cqe;
} b_dict_iterator; } b_dict_iterator;
typedef struct b_dict_item { typedef struct b_dict_item {
const char *key; const char *key;
b_dsref *value; b_object *value;
} b_dict_item; } b_dict_item;
BLUE_API b_dict *b_dict_create(void); BLUE_API b_type b_dict_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_dict, B_TYPE_DICT);
BLUE_API b_dict *b_dict_create_with_items(const b_dict_item *items); BLUE_API b_dict *b_dict_create_with_items(const b_dict_item *items);
static inline b_dict *b_dict_retain(b_dict *dict) 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);
return B_DICT(b_retain(B_DSREF(dict))); BLUE_API b_object *b_dict_at(const b_dict *dict, const char *key);
} BLUE_API b_object *b_dict_at_sk(const b_dict *dict, const b_string *key);
static inline void b_dict_release(b_dict *dict) BLUE_API b_object *b_dict_get(b_dict *dict, const char *key);
{ BLUE_API b_object *b_dict_get_sk(b_dict *dict, const b_string *key);
b_release(B_DSREF(dict));
}
BLUE_API b_status b_dict_put(b_dict *dict, const char *key, b_dsref *value);
BLUE_API b_status b_dict_put_sk(
b_dict *dict, const struct b_string *key, b_dsref *value);
BLUE_API b_dsref *b_dict_at(const b_dict *dict, const char *key);
BLUE_API b_dsref *b_dict_at_sk(const b_dict *dict, const struct b_string *key);
BLUE_API b_dsref *b_dict_get(b_dict *dict, const char *key);
BLUE_API b_dsref *b_dict_get_sk(b_dict *dict, const struct b_string *key);
BLUE_API bool b_dict_has_key(const b_dict *dict, const char *key); BLUE_API bool b_dict_has_key(const b_dict *dict, const char *key);
BLUE_API bool b_dict_has_skey(const b_dict *dict, const struct b_string *key); 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 size_t b_dict_get_size(const b_dict *dict);
BLUE_API bool b_dict_is_empty(const b_dict *dict); BLUE_API bool b_dict_is_empty(const b_dict *dict);
@@ -67,4 +66,6 @@ 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 b_status b_dict_iterator_erase(b_dict_iterator *it);
BLUE_API bool b_dict_iterator_is_valid(const b_dict_iterator *it); BLUE_API bool b_dict_iterator_is_valid(const b_dict_iterator *it);
B_DECLS_END;
#endif #endif