Skip to content

Instantly share code, notes, and snippets.

@taikedz
Created February 7, 2025 12:32
Show Gist options
  • Save taikedz/b81bb3b2ab327d7421054997037037e7 to your computer and use it in GitHub Desktop.
Save taikedz/b81bb3b2ab327d7421054997037037e7 to your computer and use it in GitHub Desktop.
Zig: Alloctaion-less experiment
// Small allocation-less experiment.
// For sure, there are ways to not allocate at all: passing stack memory locations down.
// This does mean everything needs to be defined higher up where it is ultimately consumed fully
const std = @import("std");
const Person = struct {
name: []const u8 = "",
age: u8 = 0,
};
pub fn main() !void {
// because the struct has default values, we don't need to specify things here
var person = Person{};
var name_buf = [_]u8{0}**64;
var age_buf = [_]u8{0}**4;
const name = try readLine("Name", &name_buf);
// Interesting effect: if e.StreamTooLong error occurs (more chars than the buffer can handle)
// and we return/exit , the rest of stdin is left alone. The console then receives it - and thus executes the rest of the string
const age = std.fmt.parseInt(u8, readLine("Age", &age_buf) catch |e| {std.debug.print("{}\n", .{e}); return;}, 10) catch |err| {
std.debug.print("{}\n", .{err});
return;
};
// This initializes a stack buffer.
// We can pass it down to other stacks, no need for allocation.
var return_message = [_]u8{0}**128;
// Populate the struct with constants, and produce a message into the buffer
populate(&person, name, age, &return_message) catch |err| {
std.debug.print("Something really bad happened! {}\n", .{err});
};
std.debug.print("Person: {{name={s}, age={d}}}\n", person);
std.debug.print("[{s}]\n", .{return_message});
}
fn readLine(prompt:[] const u8, buf:[]u8) ![]const u8 {
// Returns a slice of the buffer containing the line data we want
var reader = std.io.getStdIn().reader();
std.debug.print("{s}: ", .{prompt});
_ = try reader.readUntilDelimiterOrEof(buf, '\n');
// Buffer now contains like "Alice\n" or "20\n", with subsequent zero-bytes
// We need to remove _both_ (ideally we want to iterate, detect "\n", and return slice there)
const trimmed = std.mem.trim(u8, buf, &[_]u8{'\n', 0});
// std.debug.print("[{s}]\n", .{trimmed});
return trimmed;
}
fn populate(p:*Person, name:[]const u8, age:u8, return_message:[]u8) !void {
p.name = name;
p.age = age;
_ = try std.fmt.bufPrint(return_message, "{s} is {d} years young!", .{name, age});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment