const c = @cImport({ @cInclude("tkrzw_langc.h"); }); const Self = @This(); const std = @import("std"); pub const free = c.free; dbm: *c.TkrzwDBM, const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; const encode_len = 4; pub fn numEncode(num: usize) ![encode_len]u8 { return uintEncode(num, 4, chars); } pub fn numDecode(str: []const u8) usize { return uintDecode(str, chars); } const EncodeError = error{ NumberTooBig, }; fn uintEncode(num: usize, comptime bufflen: usize, comptime charset: []const u8) ![bufflen]u8 { // Check if the number is bigger than the maximum possible number var pow = comptime std.math.pow(usize, charset.len, bufflen); if (num >= pow) return EncodeError.NumberTooBig; var buff = [_]u8{charset[0]} ** bufflen; var num_i: usize = num; for (buff) |*pos| { pow /= charset.len; pos.* = charset[@divTrunc(num_i, pow)]; num_i %= pow; } return buff; } fn uintDecode(str: []const u8, comptime charset: []const u8) usize { var ret: usize = 0; for (str) |needle, i| { for (charset) |blade, j| { if (needle == blade) { ret += std.math.pow(usize, charset.len, str.len - i - 1) * j; break; } } } return ret; } pub fn open(path: [:0]const u8, writable: bool, params: [:0]const u8) Self { return Self{ .dbm = c.tkrzw_dbm_open(path, writable, params), }; } pub fn set(self: *Self, key: []const u8, value: []const u8) void { const key_len = @intCast(i32, key.len); const value_len = @intCast(i32, value.len); _ = c.tkrzw_dbm_set(self.dbm, key.ptr, key_len, value.ptr, value_len, true); } pub fn get(self: *Self, key: []const u8) []u8 { const key_len = @intCast(i32, key.len); var len: i32 = 0; var ret = c.tkrzw_dbm_get(self.dbm, key.ptr, key_len, &len); return ret[0..@intCast(usize, len)]; }