aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPolesznyák Márk <contact@pml68.dev>2026-04-08 15:12:45 +0200
committerPolesznyák Márk <contact@pml68.dev>2026-04-08 15:12:45 +0200
commit40f0c5a4559f0d837d4738ff483736f1fad2865f (patch)
treea928f9dd891a88430cd816bf64251c4bbb94f21a
parentfeat: initial commit (diff)
downloadhare-1brc-40f0c5a4559f0d837d4738ff483736f1fad2865f.tar.gz
feat: Hare updates (rt -> sys), fix sorting and parsing
-rw-r--r--hashmap.ha25
-rw-r--r--main.ha48
2 files changed, 44 insertions, 29 deletions
diff --git a/hashmap.ha b/hashmap.ha
index dd580b0..41235ea 100644
--- a/hashmap.ha
+++ b/hashmap.ha
@@ -1,15 +1,28 @@
-use hash::fnv;
-
def BUCKETS: size = 1 << 17;
-type hashmap = [BUCKETS](str, data);
+type hashmap = [BUCKETS][](size, data);
fn getitem(map: *hashmap, hash: size) data = {
let bucket = &map[hash & (BUCKETS - 1)];
- return bucket.1;
+ for (let i = 0z; i < len(bucket); i += 1) {
+ if (bucket[i].0 == hash)
+ return bucket[i].1;
+ };
+ return data { ... };
};
-fn setitem(map: *hashmap, hash: size, key: str, value: data) void = {
+fn setitem(map: *hashmap, hash: size, value: data) void = {
let bucket = &map[hash & (BUCKETS - 1)];
- *bucket = (key, value);
+ for (let i = 0z; i < len(bucket); i += 1) {
+ if (bucket[i].0 == hash) {
+ bucket[i].1 = value;
+ return;
+ };
+ };
+ append(bucket, (hash, value))!;
+};
+
+fn finish(map: *hashmap) void = {
+ for (let i = 0z; i < len(map); i += 1)
+ free(map[i]);
};
diff --git a/main.ha b/main.ha
index a95f757..05c9dab 100644
--- a/main.ha
+++ b/main.ha
@@ -5,10 +5,10 @@ use hash;
use hash::fnv;
use io;
use os;
-use rt;
+use sys;
use sort;
use sort::cmp;
-use strings::{fromutf8_unsafe, split, toutf8};
+use strings;
use types;
type data = struct {
@@ -44,23 +44,23 @@ fn i64parse(bytes: []u8) (i64, size) = {
};
@test fn parsei64() void = {
- assert(i64parse(toutf8("0.0")).0 == 0);
- assert(i64parse(toutf8("9.2")).0 == 92);
- assert(i64parse(toutf8("-9.2")).0 == -92);
- assert(i64parse(toutf8("98.2")).0 == 982);
- assert(i64parse(toutf8("-98.2")).0 == -982);
+ assert(i64parse(strings::toutf8("0.0")).0 == 0);
+ assert(i64parse(strings::toutf8("9.2")).0 == 92);
+ assert(i64parse(strings::toutf8("-9.2")).0 == -92);
+ assert(i64parse(strings::toutf8("98.2")).0 == 982);
+ assert(i64parse(strings::toutf8("-98.2")).0 == -982);
};
fn mmap(fd: io::file) []u8 = {
- let sb = rt::st { ... };
- rt::fstat(fd, &sb)!;
+ let sb = sys::st { ... };
+ sys::fstat(fd, &sb)!;
- let ptr = rt::mmap(null, sb.sz, rt::PROT_READ, rt::MAP_PRIVATE, fd, 0)!;
+ let ptr = sys::mmap(null, sb.sz, sys::PROT_READ, sys::MAP_PRIVATE, fd, 0)!;
// Hardcoded value for MADV_SEQUENTIAL, from libc-rs it seems like it's
// 2 on all currently supported platforms (Linux, FreeBSD, NetBSD,
// OpenBSD, Dragonfly).
- assert(rt::syscall(rt::SYS_madvise, ptr: uintptr: u64, sb.sz: u64, 2) == 0);
+ assert(sys::syscall(sys::SYS_madvise, ptr: uintptr: u64, sb.sz: u64, 2) == 0);
return *(&types::slice {
data = ptr,
@@ -71,7 +71,7 @@ fn mmap(fd: io::file) []u8 = {
fn free_mmap(map: []u8) void = {
let map = &map: *types::slice;
- rt::munmap(map.data: *opaque, map.length)!;
+ sys::munmap(map.data: *opaque, map.length)!;
};
fn names_cmp(a: *opaque, b: *opaque) int = {
@@ -82,7 +82,8 @@ fn names_cmp(a: *opaque, b: *opaque) int = {
};
export fn main() void = {
- let map: hashmap = [("", data { ... })...];
+ let map: hashmap = [[]...];
+ defer finish(&map);
if (len(os::args) != 2)
fmt::fatalf("usage: {} <file>", os::args[0]);
@@ -93,6 +94,7 @@ export fn main() void = {
free_mmap(fmap);
let buf: *[1024 * 1024]u8 = alloc([0...])!;
+ defer free(buf);
let read_start = 0z;
let names_buf: *[10000](u64, str) = alloc([(0, "")...])!;
@@ -111,7 +113,7 @@ export fn main() void = {
let chunk = buf[..read_start + n];
- let newline = match(bytes::index(chunk, '\n': u8)) {
+ let newline = match(bytes::rindex(chunk, '\n': u8)) {
case let idx: size =>
yield idx;
case void =>
@@ -141,7 +143,7 @@ export fn main() void = {
hash::reset(&fnv);
let after = chunk[sep_idx + 1..];
- const name = fromutf8_unsafe(chunk[..sep_idx]);
+ const name = strings::fromutf8_unsafe(chunk[..sep_idx]);
const (temp, index) = i64parse(after);
chunk = after[index..];
@@ -149,7 +151,7 @@ export fn main() void = {
let item = getitem(&map, hash);
if (item.count == 0) {
- static append(names, (hash, name))!;
+ static append(names, (hash, strings::dup(name)!))!;
item.min = temp;
item.max = temp;
} else {
@@ -162,7 +164,7 @@ export fn main() void = {
item.sum += temp;
item.count += 1;
- setitem(&map, hash, name, item);
+ setitem(&map, hash, item);
};
read_start = len(remaining);
@@ -173,12 +175,8 @@ export fn main() void = {
fmt::print("{")!;
for (let i = 0z; i < len(names); i += 1) {
- let (station, item) = map[names[i].0: size & (BUCKETS - 1)];
-
- if (station == "") {
- i -= 1;
- continue;
- };
+ let station = names[i].1;
+ let item = getitem(&map, names[i].0);
if (i > 0)
fmt::print(", ")!;
@@ -189,6 +187,10 @@ export fn main() void = {
item.max: f64 / 10.0,
item.sum: f64 / 10.0 / item.count: f64,
)!;
+
+ free(names[i].1);
};
fmt::println("}")!;
+
+ free(names);
};