mirror of
https://github.com/janet-lang/janet
synced 2024-11-18 06:34:48 +00:00
Add ability to index into structs and dictionaries generically.
This commit is contained in:
parent
08dd06918e
commit
56c3b8aa94
@ -70,7 +70,8 @@ static char *decode_utf16_escape(const char *p, uint32_t *outpoint) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse a string */
|
||||
/* Parse a string. Also handles the conversion of utf-16 to
|
||||
* utf-8. */
|
||||
const char *decode_string(const char **p, Janet *out) {
|
||||
JanetBuffer *buffer = janet_buffer(0);
|
||||
const char *cp = *p;
|
||||
@ -571,7 +572,7 @@ static int json_encode(JanetArgs args) {
|
||||
JANET_ARG_BYTES(e.newline, e.newlinelen, args, 2);
|
||||
} else {
|
||||
e.newline = (const uint8_t *)"\r\n";
|
||||
e.newlinelen = 1;
|
||||
e.newlinelen = 2;
|
||||
}
|
||||
}
|
||||
const char *err = encode_one(&e, args.v[0], 0);
|
||||
|
@ -77,8 +77,7 @@ static int sql_open(JanetArgs args) {
|
||||
static int sql_close(JanetArgs args) {
|
||||
Db *db;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &sql_conn_type);
|
||||
db = (Db *)janet_unwrap_abstract(args.v[0]);
|
||||
JANET_ARG_ABSTRACT(db, args, 0, &sql_conn_type);
|
||||
closedb(db);
|
||||
JANET_RETURN_NIL(args);
|
||||
}
|
||||
|
@ -24,8 +24,6 @@
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
|
||||
#define janet_struct_maphash(cap, hash) ((uint32_t)(hash & (cap - 1)));
|
||||
|
||||
/* Begin creation of a struct */
|
||||
JanetKV *janet_struct_begin(int32_t count) {
|
||||
|
||||
@ -43,10 +41,11 @@ JanetKV *janet_struct_begin(int32_t count) {
|
||||
return st;
|
||||
}
|
||||
|
||||
/* Find an item in a struct */
|
||||
/* Find an item in a struct. Should be similar to janet_dict_find, but
|
||||
* specialized to structs (slightly more compact). */
|
||||
const JanetKV *janet_struct_find(const JanetKV *st, Janet key) {
|
||||
int32_t cap = janet_struct_capacity(st);
|
||||
int32_t index = janet_struct_maphash(cap, janet_hash(key));
|
||||
int32_t index = janet_maphash(cap, janet_hash(key));
|
||||
int32_t i;
|
||||
for (i = index; i < cap; i++)
|
||||
if (janet_checktype(st[i].key, JANET_NIL) || janet_equals(st[i].key, key))
|
||||
@ -68,7 +67,7 @@ const JanetKV *janet_struct_find(const JanetKV *st, Janet key) {
|
||||
void janet_struct_put(JanetKV *st, Janet key, Janet value) {
|
||||
int32_t cap = janet_struct_capacity(st);
|
||||
int32_t hash = janet_hash(key);
|
||||
int32_t index = janet_struct_maphash(cap, hash);
|
||||
int32_t index = janet_maphash(cap, hash);
|
||||
int32_t i, j, dist;
|
||||
int32_t bounds[4] = {index, cap, 0, index};
|
||||
if (janet_checktype(key, JANET_NIL) || janet_checktype(value, JANET_NIL)) return;
|
||||
@ -95,7 +94,7 @@ void janet_struct_put(JanetKV *st, Janet key, Janet value) {
|
||||
* will compare properly - i.e., {1 2 3 4} should equal {3 4 1 2}.
|
||||
* Collisions are resolved via an insertion sort insertion. */
|
||||
otherhash = janet_hash(kv->key);
|
||||
otherindex = janet_struct_maphash(cap, otherhash);
|
||||
otherindex = janet_maphash(cap, otherhash);
|
||||
otherdist = (i + cap - otherindex) & (cap - 1);
|
||||
if (dist < otherdist)
|
||||
status = -1;
|
||||
@ -231,4 +230,4 @@ int janet_struct_compare(const JanetKV *lhs, const JanetKV *rhs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef janet_struct_maphash
|
||||
#undef janet_maphash
|
||||
|
@ -24,8 +24,6 @@
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
|
||||
#define janet_table_maphash(cap, hash) ((uint32_t)(hash) & (cap - 1))
|
||||
|
||||
/* Initialize a table */
|
||||
JanetTable *janet_table_init(JanetTable *table, int32_t capacity) {
|
||||
JanetKV *data;
|
||||
@ -61,36 +59,7 @@ JanetTable *janet_table(int32_t capacity) {
|
||||
/* Find the bucket that contains the given key. Will also return
|
||||
* bucket where key should go if not in the table. */
|
||||
JanetKV *janet_table_find(JanetTable *t, Janet key) {
|
||||
int32_t index = janet_table_maphash(t->capacity, janet_hash(key));
|
||||
int32_t i;
|
||||
JanetKV *first_bucket = NULL;
|
||||
/* Higher half */
|
||||
for (i = index; i < t->capacity; i++) {
|
||||
JanetKV *kv = t->data + i;
|
||||
if (janet_checktype(kv->key, JANET_NIL)) {
|
||||
if (janet_checktype(kv->value, JANET_NIL)) {
|
||||
return kv;
|
||||
} else if (NULL == first_bucket) {
|
||||
first_bucket = kv;
|
||||
}
|
||||
} else if (janet_equals(kv->key, key)) {
|
||||
return t->data + i;
|
||||
}
|
||||
}
|
||||
/* Lower half */
|
||||
for (i = 0; i < index; i++) {
|
||||
JanetKV *kv = t->data + i;
|
||||
if (janet_checktype(kv->key, JANET_NIL)) {
|
||||
if (janet_checktype(kv->value, JANET_NIL)) {
|
||||
return kv;
|
||||
} else if (NULL == first_bucket) {
|
||||
first_bucket = kv;
|
||||
}
|
||||
} else if (janet_equals(kv->key, key)) {
|
||||
return t->data + i;
|
||||
}
|
||||
}
|
||||
return first_bucket;
|
||||
return (JanetKV *) janet_dict_find(t->data, t->capacity, key);
|
||||
}
|
||||
|
||||
/* Resize the dictionary table. */
|
||||
@ -298,4 +267,4 @@ int janet_lib_table(JanetArgs args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef janet_table_maphash
|
||||
#undef janet_maphash
|
||||
|
@ -95,6 +95,50 @@ int32_t janet_tablen(int32_t n) {
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
/* Helper to find a value in a Janet struct or table. Returns the bucket
|
||||
* containg the key, or the first empty bucket if there is no such key. */
|
||||
const JanetKV *janet_dict_find(const JanetKV *buckets, int32_t cap, Janet key) {
|
||||
int32_t index = janet_maphash(cap, janet_hash(key));
|
||||
int32_t i;
|
||||
const JanetKV *first_bucket = NULL;
|
||||
/* Higher half */
|
||||
for (i = index; i < cap; i++) {
|
||||
const JanetKV *kv = buckets + i;
|
||||
if (janet_checktype(kv->key, JANET_NIL)) {
|
||||
if (janet_checktype(kv->value, JANET_NIL)) {
|
||||
return kv;
|
||||
} else if (NULL == first_bucket) {
|
||||
first_bucket = kv;
|
||||
}
|
||||
} else if (janet_equals(kv->key, key)) {
|
||||
return buckets + i;
|
||||
}
|
||||
}
|
||||
/* Lower half */
|
||||
for (i = 0; i < index; i++) {
|
||||
const JanetKV *kv = buckets + i;
|
||||
if (janet_checktype(kv->key, JANET_NIL)) {
|
||||
if (janet_checktype(kv->value, JANET_NIL)) {
|
||||
return kv;
|
||||
} else if (NULL == first_bucket) {
|
||||
first_bucket = kv;
|
||||
}
|
||||
} else if (janet_equals(kv->key, key)) {
|
||||
return buckets + i;
|
||||
}
|
||||
}
|
||||
return first_bucket;
|
||||
}
|
||||
|
||||
/* Get a value from a janet struct or table. */
|
||||
Janet janet_dictionary_get(const JanetKV *data, int32_t cap, Janet key) {
|
||||
const JanetKV *kv = janet_dict_find(data, cap, key);
|
||||
if (kv && !janet_checktype(kv->key, JANET_NIL)) {
|
||||
return kv->value;
|
||||
}
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
/* Compare a janet string with a cstring. more efficient than loading
|
||||
* c string as a janet string. */
|
||||
int janet_cstrcmp(const uint8_t *str, const char *other) {
|
||||
|
@ -26,12 +26,15 @@
|
||||
#include <janet/janet.h>
|
||||
|
||||
/* Utils */
|
||||
#define janet_maphash(cap, hash) ((uint32_t)(hash) & (cap - 1))
|
||||
extern const char janet_base64[65];
|
||||
int32_t janet_array_calchash(const Janet *array, int32_t len);
|
||||
int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len);
|
||||
int32_t janet_string_calchash(const uint8_t *str, int32_t len);
|
||||
int32_t janet_tablen(int32_t n);
|
||||
void janet_buffer_push_types(JanetBuffer *buffer, int types);
|
||||
const JanetKV *janet_dict_find(const JanetKV *buckets, int32_t cap, Janet key);
|
||||
Janet janet_dict_get(const JanetKV *buckets, int32_t cap, Janet key);
|
||||
const void *janet_strbinsearch(
|
||||
const void *tab,
|
||||
size_t tabcount,
|
||||
|
@ -1001,6 +1001,7 @@ JANET_API JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity);
|
||||
JANET_API int janet_indexed_view(Janet seq, const Janet **data, int32_t *len);
|
||||
JANET_API int janet_bytes_view(Janet str, const uint8_t **data, int32_t *len);
|
||||
JANET_API int janet_dictionary_view(Janet tab, const JanetKV **data, int32_t *len, int32_t *cap);
|
||||
JANET_API Janet janet_dictionary_get(const JanetKV *data, int32_t cap, Janet key);
|
||||
|
||||
/* Abstract */
|
||||
#define janet_abstract_header(u) ((JanetAbstractHeader *)(u) - 1)
|
||||
@ -1100,7 +1101,7 @@ JANET_API int janet_typeabstract_err(JanetArgs args, int32_t n, const JanetAbstr
|
||||
Janet x = (A).v[(N)];\
|
||||
if (!janet_checktype(x, JANET_ABSTRACT) ||\
|
||||
janet_abstract_type(janet_unwrap_abstract(x)) != (AT))\
|
||||
return janet_typeabstract_err(A, N, AT);\
|
||||
return janet_typeabstract_err(A, N, AT);\
|
||||
} else {\
|
||||
return janet_typeabstract_err(A, N, AT);\
|
||||
}\
|
||||
@ -1154,7 +1155,11 @@ JANET_API int janet_typeabstract_err(JanetArgs args, int32_t n, const JanetAbstr
|
||||
#define JANET_ARG_BUFFER(DEST, A, N) _JANET_ARG(JANET_BUFFER, buffer, DEST, A, N)
|
||||
#define JANET_ARG_FUNCTION(DEST, A, N) _JANET_ARG(JANET_FUNCTION, function, DEST, A, N)
|
||||
#define JANET_ARG_CFUNCTION(DEST, A, N) _JANET_ARG(JANET_CFUNCTION, cfunction, DEST, A, N)
|
||||
#define JANET_ARG_ABSTRACT(DEST, A, N) _JANET_ARG(JANET_ABSTRACT, abstract, DEST, A, N)
|
||||
|
||||
#define JANET_ARG_ABSTRACT(DEST, A, N, AT) do { \
|
||||
JANET_CHECKABSTRACT(A, N, AT); \
|
||||
DEST = janet_unwrap_abstract((A).v[(N)]); \
|
||||
} while (0)
|
||||
|
||||
#define JANET_RETURN_NIL(A) do { return JANET_SIGNAL_OK; } while (0)
|
||||
#define JANET_RETURN_FALSE(A) JANET_RETURN(A, janet_wrap_false())
|
||||
|
Loading…
Reference in New Issue
Block a user