Lindenii Project Forge
Login

hare-ds

Data structures for Hare

Warning: Due to various recent migrations, viewing non-HEAD refs may be broken.

/ds/map/hashmap/iter.ha (raw)

// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2024 Drew DeVault <drew@ddevault.org>
// SPDX-FileCopyrightText: 2025 Runxi Yu <me@runxiyu.org>

use ds::map;

export type iterator = struct {
	vt: map::iterator,
	m: *map,
	bi: size,
	cur: nullable *map::iterator,
};

const _itvt: map::vtable_iterator = map::vtable_iterator {
	nexter = &vt_next,
};

fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator);

export fn iter(m: *map) (*map::iterator | nomem) = {
	let it = alloc(iterator {
		vt = &_itvt,
		m = m,
		bi = 0,
		cur = null,
	})?;
	for (it.bi < m.n) {
		let b = m.buckets[it.bi];
		it.bi += 1;
		match (map::iter(b)) {
		case let i: *map::iterator =>
			it.cur = i;
			break;
		case nomem =>
			abort("hashmap::iter: nomem");
		};
	};
	return (it: *map::iterator);
};

export fn next(it: *iterator) (([]u8, *opaque) | done) = {
	for (true) {
		match (it.cur) {
		case null =>
			if (it.bi >= it.m.n) return done;
			let b = it.m.buckets[it.bi];
			it.bi += 1;
			match (map::iter(b)) {
			case let i: *map::iterator =>
				it.cur = i;
			case nomem =>
				abort("hashmap::iter: nomem");
			};
		case let curi: *map::iterator =>
			match (map::next(curi)) {
			case let kv: ([]u8, *opaque) =>
				return kv;
			case done =>
				it.cur = null;
			};
		};
	};
};