object: dict: use b_strings as keys rather than plain c-strings.
now that strings can contain UTF-8 codepoints and null chars, the b_dict api has been enhanced to accept keys as b_strings as well as regular c-strings. keys are now stored as b_strings internally, to allow a wider range of keys to be used.
This commit is contained in:
@@ -105,7 +105,35 @@ b_status b_dict_put(struct b_dict *dict, const char *key, b_object *value)
|
|||||||
return B_ERR_NO_MEMORY;
|
return B_ERR_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->bi_str = b_strdup(key);
|
item->bi_str = b_string_create_from_cstr(key);
|
||||||
|
item->bi_value = b_retain(value);
|
||||||
|
|
||||||
|
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
|
||||||
|
|
||||||
|
return B_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
b_status b_dict_put_sk(
|
||||||
|
struct b_dict *dict, const struct b_string *key, b_object *value)
|
||||||
|
{
|
||||||
|
uint64_t hash = b_string_hash(key);
|
||||||
|
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||||
|
if (!bucket) {
|
||||||
|
bucket = create_bucket();
|
||||||
|
if (!bucket) {
|
||||||
|
return B_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket->bk_hash = hash;
|
||||||
|
put_bucket(&dict->d_buckets, bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct b_dict_bucket_item *item = create_bucket_item();
|
||||||
|
if (!item) {
|
||||||
|
return B_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->bi_str = b_string_duplicate(key);
|
||||||
item->bi_value = b_retain(value);
|
item->bi_value = b_retain(value);
|
||||||
|
|
||||||
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
|
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
|
||||||
@@ -126,7 +154,28 @@ b_object *b_dict_at(const struct b_dict *dict, const char *key)
|
|||||||
struct b_dict_bucket_item *item
|
struct b_dict_bucket_item *item
|
||||||
= b_unbox(struct b_dict_bucket_item, it.entry, bi_entry);
|
= b_unbox(struct b_dict_bucket_item, it.entry, bi_entry);
|
||||||
|
|
||||||
if (!strcmp(item->bi_str, key)) {
|
if (!strcmp(b_string_ptr(item->bi_str), key)) {
|
||||||
|
return item->bi_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
b_object *b_dict_at_sk(const struct b_dict *dict, const struct b_string *key)
|
||||||
|
{
|
||||||
|
uint64_t hash = b_string_hash(key);
|
||||||
|
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||||
|
if (!bucket) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
b_queue_iterator it;
|
||||||
|
b_queue_foreach (&it, &bucket->bk_items) {
|
||||||
|
struct b_dict_bucket_item *item
|
||||||
|
= b_unbox(struct b_dict_bucket_item, it.entry, bi_entry);
|
||||||
|
|
||||||
|
if (b_string_compare(item->bi_str, key)) {
|
||||||
return item->bi_value;
|
return item->bi_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,11 +193,26 @@ b_object *b_dict_get(struct b_dict *dict, const char *key)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b_object *b_dict_get_sk(struct b_dict *dict, const struct b_string *key)
|
||||||
|
{
|
||||||
|
b_object *value = b_dict_at_sk(dict, key);
|
||||||
|
if (value) {
|
||||||
|
b_retain(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
bool b_dict_has_key(const struct b_dict *dict, const char *key)
|
bool b_dict_has_key(const struct b_dict *dict, const char *key)
|
||||||
{
|
{
|
||||||
return b_dict_at(dict, key) != NULL;
|
return b_dict_at(dict, key) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool b_dict_has_skey(const struct b_dict *dict, const struct b_string *key)
|
||||||
|
{
|
||||||
|
return b_dict_at_sk(dict, key) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
size_t b_dict_get_size(const struct b_dict *dict)
|
size_t b_dict_get_size(const struct b_dict *dict)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@@ -203,7 +267,8 @@ static void dict_to_string(const struct b_object *obj, struct b_stream *out)
|
|||||||
b_dict_iterator it;
|
b_dict_iterator it;
|
||||||
b_dict_foreach(&it, dict)
|
b_dict_foreach(&it, dict)
|
||||||
{
|
{
|
||||||
b_stream_write_fmt(out, NULL, "%s: ", it.key);
|
b_to_string(B_OBJECT(it.key), out);
|
||||||
|
b_stream_write_string(out, ": ", NULL);
|
||||||
|
|
||||||
bool is_string = b_typeid(it.value) == B_OBJECT_TYPE_STRING;
|
bool is_string = b_typeid(it.value) == B_OBJECT_TYPE_STRING;
|
||||||
|
|
||||||
@@ -243,11 +308,12 @@ static bool dict_iterator_is_valid(const struct b_iterator *it)
|
|||||||
return b_dict_iterator_is_valid((struct b_dict_iterator *)it);
|
return b_dict_iterator_is_valid((struct b_dict_iterator *)it);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct b_iterator_ops it_ops
|
static struct b_iterator_ops it_ops = {
|
||||||
= {.it_next = dict_iterator_next,
|
.it_next = dict_iterator_next,
|
||||||
.it_close = NULL,
|
.it_close = NULL,
|
||||||
.it_erase = dict_iterator_erase,
|
.it_erase = dict_iterator_erase,
|
||||||
.it_is_valid = dict_iterator_is_valid};
|
.it_is_valid = dict_iterator_is_valid,
|
||||||
|
};
|
||||||
|
|
||||||
int b_dict_iterator_begin(struct b_dict *dict, b_dict_iterator *it)
|
int b_dict_iterator_begin(struct b_dict *dict, b_dict_iterator *it)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,9 +6,11 @@
|
|||||||
#include <blue/core/btree.h>
|
#include <blue/core/btree.h>
|
||||||
#include <blue/core/queue.h>
|
#include <blue/core/queue.h>
|
||||||
|
|
||||||
|
struct b_string;
|
||||||
|
|
||||||
struct b_dict_bucket_item {
|
struct b_dict_bucket_item {
|
||||||
b_queue_entry bi_entry;
|
b_queue_entry bi_entry;
|
||||||
char *bi_str;
|
struct b_string *bi_str;
|
||||||
struct b_object *bi_value;
|
struct b_object *bi_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <blue/object/object.h>
|
#include <blue/object/object.h>
|
||||||
#include <blue/object/type.h>
|
#include <blue/object/type.h>
|
||||||
|
|
||||||
|
struct b_string;
|
||||||
|
|
||||||
#define B_DICT(p) ((b_dict *)(p))
|
#define B_DICT(p) ((b_dict *)(p))
|
||||||
|
|
||||||
#define B_DICT_ITEM(k, v) \
|
#define B_DICT_ITEM(k, v) \
|
||||||
@@ -28,7 +30,7 @@ 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 char *key;
|
const struct b_string *key;
|
||||||
b_object *value;
|
b_object *value;
|
||||||
|
|
||||||
b_dict *_d;
|
b_dict *_d;
|
||||||
@@ -54,10 +56,15 @@ static inline void b_dict_release(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(b_dict *dict, const char *key, b_object *value);
|
||||||
|
BLUE_API b_status b_dict_put_sk(
|
||||||
|
b_dict *dict, const struct b_string *key, b_object *value);
|
||||||
BLUE_API b_object *b_dict_at(const b_dict *dict, const char *key);
|
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 struct b_string *key);
|
||||||
BLUE_API b_object *b_dict_get(b_dict *dict, const char *key);
|
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 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 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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user