summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gc.c11
-rw-r--r--hash.c40
-rw-r--r--lib.c12
-rw-r--r--lib.h12
4 files changed, 71 insertions, 4 deletions
diff --git a/gc.c b/gc.c
index 33afca91..e42e7552 100644
--- a/gc.c
+++ b/gc.c
@@ -244,7 +244,7 @@ val make_obj(void)
static void finalize(val obj)
{
- switch (obj->t.type) {
+ switch (convert(type_t, obj->t.type)) {
case NIL:
case CONS:
case CHR:
@@ -280,6 +280,12 @@ static void finalize(val obj)
case BGNUM:
mp_clear(mp(obj));
return;
+ case BUF:
+ if (obj->b.size) {
+ free(obj->b.data);
+ obj->b.data = 0;
+ }
+ return;
}
assert (0 && "corrupt type field");
@@ -395,6 +401,9 @@ tail_call:
case RNG:
mark_obj(obj->rn.from);
mark_obj_tail(obj->rn.to);
+ case BUF:
+ mark_obj(obj->b.len);
+ mark_obj_tail(obj->b.size);
}
assert (0 && "corrupt type field");
diff --git a/hash.c b/hash.c
index d1a60da5..8d27892f 100644
--- a/hash.c
+++ b/hash.c
@@ -107,6 +107,44 @@ static unsigned long hash_c_str(const wchar_t *str)
return h;
}
+static unsigned long hash_buf(const mem_t *ptr, cnum size)
+{
+ int count = hash_str_limit;
+ unsigned long h = 0;
+
+ for (; size >= 4 && count--; size -= 4, ptr += 4) {
+ unsigned long el = (((unsigned long) ptr[0]) << 24 |
+ ((unsigned long) ptr[1]) << 16 |
+ ((unsigned long) ptr[2]) << 8 |
+ ((unsigned long) ptr[3]));
+ unsigned long g;
+ h = (h << 4) + el;
+ g = h & 0x7C000000;
+ h = h ^ (g >> 26) ^ g;
+ ptr += 4;
+ }
+
+ if (count) {
+ unsigned long el = 0;
+ unsigned long g;
+ switch (size) {
+ case 0:
+ break;
+ case 3:
+ el = *ptr++;
+ case 2:
+ el = el << 8 | *ptr++;
+ case 1:
+ el = el << 8 | *ptr++;
+ h = (h << 4) + el;
+ g = h & 0x7C000000;
+ h = h ^ (g >> 26) ^ g;
+ ptr += 4;
+ }
+ }
+ return h;
+}
+
static cnum hash_double(double n)
{
#ifdef HAVE_UINTPTR_T
@@ -191,6 +229,8 @@ cnum equal_hash(val obj, int *count)
case RNG:
return (equal_hash(obj->rn.from, count)
+ 32 * (equal_hash(obj->rn.to, count) & (NUM_MAX / 16))) & NUM_MAX;
+ case BUF:
+ return hash_buf(obj->b.data, c_num(obj->b.len));
}
internal_error("unhandled case in equal function");
diff --git a/lib.c b/lib.c
index d20dca2c..99e59351 100644
--- a/lib.c
+++ b/lib.c
@@ -85,7 +85,7 @@ val package_s, system_package_s, keyword_package_s, user_package_s;
val null_s, t, cons_s, str_s, chr_s, fixnum_s, sym_s, pkg_s, fun_s, vec_s;
val lit_s, stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s, cptr_s;
val atom_s, integer_s, number_s, sequence_s, string_s;
-val env_s, bignum_s, float_s, range_s, rcons_s;
+val env_s, bignum_s, float_s, range_s, rcons_s, buf_s;
val var_s, expr_s, regex_s, chset_s, set_s, cset_s, wild_s, oneplus_s;
val nongreedy_s;
val quote_s, qquote_s, unquote_s, splice_s;
@@ -172,6 +172,7 @@ static val code2type(int code)
case BGNUM: return bignum_s;
case FLNUM: return float_s;
case RNG: return range_s;
+ case BUF: return buf_s;
}
return nil;
}
@@ -2495,6 +2496,14 @@ val equal(val left, val right)
return nil;
}
break;
+ case BUF:
+ if (type(right) == BUF) {
+ cnum ll = c_num(left->b.len);
+ cnum rl = c_num(right->b.len);
+ if (ll == rl && memcmp(left->b.data, right->b.data, ll) == 0)
+ return t;
+ }
+ break;
case COBJ:
if (left->co.ops->equalsub) {
val lsub = left->co.ops->equalsub(left);
@@ -9647,6 +9656,7 @@ static void obj_init(void)
float_s = intern(lit("float"), user_package);
range_s = intern(lit("range"), user_package);
rcons_s = intern(lit("rcons"), user_package);
+ buf_s = intern(lit("buf"), user_package);
var_s = intern(lit("var"), system_package);
expr_s = intern(lit("expr"), system_package);
regex_s = intern(lit("regex"), user_package);
diff --git a/lib.h b/lib.h
index c9456cca..44074453 100644
--- a/lib.h
+++ b/lib.h
@@ -59,7 +59,7 @@ typedef int_ptr_t cnum;
typedef enum type {
NIL = TAG_PTR, NUM = TAG_NUM, CHR = TAG_CHR, LIT = TAG_LIT, CONS,
STR, SYM, PKG, FUN, VEC, LCONS, LSTR, COBJ, ENV,
- BGNUM, FLNUM, RNG, MAXTYPE = RNG
+ BGNUM, FLNUM, RNG, BUF, MAXTYPE = BUF
/* If extending, check TYPE_SHIFT */
} type_t;
@@ -279,6 +279,13 @@ struct range {
val from, to;
};
+struct buf {
+ obj_common;
+ mem_t *data;
+ val len;
+ val size;
+};
+
union obj {
struct any t;
struct cons c;
@@ -295,6 +302,7 @@ union obj {
struct bignum bn;
struct flonum fl;
struct range rn;
+ struct buf b;
};
#if CONFIG_GEN_GC
@@ -426,7 +434,7 @@ extern val null_s, t, cons_s, str_s, chr_s, fixnum_sl;
extern val sym_s, pkg_s, fun_s, vec_s;
extern val stream_s, hash_s, hash_iter_s, lcons_s, lstr_s, cobj_s, cptr_s;
extern val atom_s, integer_s, number_s, sequence_s, string_s;
-extern val env_s, bignum_s, float_s, range_s, rcons_s;
+extern val env_s, bignum_s, float_s, range_s, rcons_s, buf_s;
extern val var_s, expr_s, regex_s, chset_s, set_s, cset_s, wild_s, oneplus_s;
extern val nongreedy_s;
extern val quote_s, qquote_s, unquote_s, splice_s;