diff options
| author | Bobby <[email protected]> | 2026-02-24 06:56:58 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-24 06:56:58 +0530 |
| commit | 5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8 (patch) | |
| tree | 2ae2a13678844b82b43583ca28eed4d4b6223ec0 /system.old/libraries/params/params.zig | |
| parent | 297c66b480a238dad5ce7f03405fe6f5b9123701 (diff) | |
| download | akiba-5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8.tar.xz akiba-5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8.zip | |
Bunch of stuff moved as .old for new arch change
Diffstat (limited to 'system.old/libraries/params/params.zig')
| -rw-r--r-- | system.old/libraries/params/params.zig | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/system.old/libraries/params/params.zig b/system.old/libraries/params/params.zig new file mode 100644 index 0000000..d7e5ba1 --- /dev/null +++ b/system.old/libraries/params/params.zig @@ -0,0 +1,233 @@ +//! Akiba parameter parsing + +pub const Value = union(enum) { + scalar: []const u8, + list: []const []const u8, +}; + +pub const Named = struct { + key: []const u8, + value: Value, +}; + +pub const Params = struct { + positionals: []const Value, + named: []const Named, + + pub fn positional(self: Params, index: usize) ?Value { + if (index >= self.positionals.len) return null; + return self.positionals[index]; + } + + pub fn get(self: Params, key: []const u8) ?Value { + for (self.named) |n| { + if (eql(n.key, key)) return n.value; + } + return null; + } + + pub fn getString(self: Params, key: []const u8) ?[]const u8 { + const val = self.get(key) orelse return null; + return switch (val) { + .scalar => |s| s, + .list => null, + }; + } + + pub fn getList(self: Params, key: []const u8) ?[]const []const u8 { + const val = self.get(key) orelse return null; + return switch (val) { + .scalar => null, + .list => |l| l, + }; + } + + pub fn getBool(self: Params, key: []const u8) ?bool { + const val = self.getString(key) orelse return null; + if (eql(val, "true")) return true; + if (eql(val, "false")) return false; + return null; + } + + pub fn getInt(self: Params, key: []const u8) ?i64 { + const val = self.getString(key) orelse return null; + return parseInt(val); + } +}; + +pub const Error = error{ + EmptyToken, + EmptyKey, + EmptyValue, + InvalidKey, + DuplicateKey, + PositionalAfterNamed, + LeadingComma, + TrailingComma, +}; + +const MAX_POSITIONALS = 16; +const MAX_NAMED = 32; +const MAX_LIST_ITEMS = 16; + +var positional_storage: [MAX_POSITIONALS]Value = undefined; +var named_storage: [MAX_NAMED]Named = undefined; +var list_storage: [MAX_POSITIONALS + MAX_NAMED][MAX_LIST_ITEMS][]const u8 = undefined; +var list_index: usize = 0; + +pub fn parse(pc: u32, pv: [*]const [*:0]const u8) Error!Params { + var positional_count: usize = 0; + var named_count: usize = 0; + var in_named = false; + list_index = 0; + + // Skip program name (pv[0]) + var i: u32 = 1; + while (i < pc) : (i += 1) { + const arg = sliceFromCstr(pv[i]); + + if (arg.len == 0) return Error.EmptyToken; + + const eq_pos = indexOf(arg, '='); + + if (eq_pos) |pos| { + // Named parameter + in_named = true; + + if (pos == 0) return Error.EmptyKey; + if (pos == arg.len - 1) return Error.EmptyValue; + + const key = arg[0..pos]; + const value_str = arg[pos + 1 ..]; + + if (!isValidKey(key)) return Error.InvalidKey; + if (hasDuplicateKey(named_storage[0..named_count], key)) return Error.DuplicateKey; + + const value = try parseValue(value_str); + named_storage[named_count] = .{ .key = key, .value = value }; + named_count += 1; + } else { + // Positional + if (in_named) return Error.PositionalAfterNamed; + + const value = try parseValue(arg); + positional_storage[positional_count] = value; + positional_count += 1; + } + } + + return Params{ + .positionals = positional_storage[0..positional_count], + .named = named_storage[0..named_count], + }; +} + +fn parseValue(str: []const u8) Error!Value { + if (str.len == 0) return Error.EmptyValue; + if (str[0] == ',') return Error.LeadingComma; + if (str[str.len - 1] == ',') return Error.TrailingComma; + + // Check for commas + var comma_count: usize = 0; + for (str) |c| { + if (c == ',') comma_count += 1; + } + + if (comma_count == 0) { + return Value{ .scalar = str }; + } + + // Parse list + var items: [][]const u8 = list_storage[list_index][0..]; + var item_count: usize = 0; + var start: usize = 0; + + for (str, 0..) |c, j| { + if (c == ',') { + if (j == start) return Error.LeadingComma; // Empty segment + items[item_count] = str[start..j]; + item_count += 1; + start = j + 1; + } + } + + // Last item + if (start == str.len) return Error.TrailingComma; + items[item_count] = str[start..]; + item_count += 1; + + list_index += 1; + + return Value{ .list = items[0..item_count] }; +} + +fn isValidKey(key: []const u8) bool { + if (key.len == 0) return false; + + const first = key[0]; + if (!isLetter(first)) return false; + + for (key[1..]) |c| { + if (!isLetter(c) and !isDigit(c) and c != '_') return false; + } + + return true; +} + +fn isLetter(c: u8) bool { + return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z'); +} + +fn isDigit(c: u8) bool { + return c >= '0' and c <= '9'; +} + +fn hasDuplicateKey(named: []const Named, key: []const u8) bool { + for (named) |n| { + if (eql(n.key, key)) return true; + } + return false; +} + +fn indexOf(str: []const u8, char: u8) ?usize { + for (str, 0..) |c, i| { + if (c == char) return i; + } + return null; +} + +fn eql(a: []const u8, b: []const u8) bool { + if (a.len != b.len) return false; + for (a, b) |ac, bc| { + if (ac != bc) return false; + } + return true; +} + +fn sliceFromCstr(cstr: [*:0]const u8) []const u8 { + var len: usize = 0; + while (cstr[len] != 0) : (len += 1) {} + return cstr[0..len]; +} + +fn parseInt(str: []const u8) ?i64 { + if (str.len == 0) return null; + + var negative = false; + var start: usize = 0; + + if (str[0] == '-') { + negative = true; + start = 1; + } + + if (start >= str.len) return null; + + var result: i64 = 0; + for (str[start..]) |c| { + if (!isDigit(c)) return null; + result = result * 10 + @as(i64, c - '0'); + } + + return if (negative) -result else result; +} |
