Lindenii Project Forge
Login

hare-ds

Data structures for Hare
Commit info
ID
7ea899191fc61f03b1532b7ba65107fcc8df6792
Author
Runxi Yu <me@runxiyu.org>
Author date
Fri, 19 Sep 2025 14:37:14 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Fri, 19 Sep 2025 14:37:14 +0800
Actions
slice_sorted: Incrementally preserve sorting instead of always resorting
use sort;

// Deletes an item from a [[map]]. Returns the removed value or void.
export fn del(m: *map, key: []u8) (*opaque | void) = {
	let dummy = 0;
	let probe = (key, (&dummy: *opaque));
	match (sort::search((m.items: []const opaque),
		size(([]u8, *opaque)),
		(&probe: const *opaque), &cmp_kv)) {
	case let idx: size =>
		let v = m.items[idx].1;
		delete(m.items[idx]);
		resort(m);
		return v;
	case void =>
		return;
	};
};
use sort;

fn cmp_kv(a: const *opaque, b: const *opaque) int = {
	let ka = (*(a: *([]u8, *opaque))).0;
	let kb = (*(b: *([]u8, *opaque))).0;
	return keycmp(ka, kb);
};

fn keycmp(a: []u8, b: []u8) int = {
	let n = if (len(a) < len(b)) len(a) else len(b);
	for (let i = 0z; i < n; i += 1) {
		if (a[i] < b[i]) return -1;
		if (a[i] > b[i]) return 1;
	};
	if (len(a) < len(b)) return -1;
	if (len(a) > len(b)) return 1;
	return 0;
};

fn resort(m: *map) void = {
	sort::inplace((m.items: []opaque), size(([]u8, *opaque)), &cmp_kv);
};
use sort;

// Sets an item in a [[map]], replacing any existing item with the same key.
export fn set(m: *map, key: []u8, value: *opaque) (void | nomem) = {
	let dummy = 0;
	let probe = (key, (&dummy: *opaque));

	match (sort::search((m.items: []const opaque),
		size(([]u8, *opaque)),
		(&probe: const *opaque), &cmp_kv)) {
	case let idx: size =>
		m.items[idx].1 = value;
	case void =>
		append(m.items, (key, value))?;
		let ins = sort::lbisect((m.items: []const opaque),
			size(([]u8, *opaque)),
			(&probe: const *opaque), &cmp_kv);
		insert(m.items[ins], (key, value))?;
	};
	resort(m);
};