index.zig 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. const std = @import("std");
  2. const storage = @import("storage.zig");
  3. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  4. const allocator = arena.allocator();
  5. const MAX_CHILDREN = 256;
  6. const TrieNode = struct {
  7. children: [MAX_CHILDREN]?*TrieNode,
  8. eof: bool,
  9. char: u8,
  10. };
  11. var root: TrieNode = .{
  12. .children = [_]?*TrieNode{null} ** MAX_CHILDREN,
  13. .eof = false,
  14. .char = 0,
  15. };
  16. fn getChild(node: *TrieNode, c: u8) ?*TrieNode {
  17. return node.children[c];
  18. }
  19. fn addChild(node: *TrieNode, c: u8) *TrieNode {
  20. const newNode = allocator.create(TrieNode) catch unreachable;
  21. newNode.* = .{
  22. .children = [_]?*TrieNode{null} ** MAX_CHILDREN,
  23. .eof = false,
  24. .char = c,
  25. };
  26. node.children[c] = newNode;
  27. return newNode;
  28. }
  29. pub fn insert(key: []const u8) void {
  30. var current = &root;
  31. for (key) |c| {
  32. var child = getChild(current, c);
  33. if (child == null) {
  34. child = addChild(current, c);
  35. }
  36. current = child.?;
  37. }
  38. current.eof = true;
  39. }
  40. pub fn delete(key: []const u8) void {
  41. var current = &root;
  42. for (key) |c| {
  43. const child = getChild(current, c);
  44. if (child == null) {
  45. return;
  46. }
  47. current = child.?;
  48. }
  49. current.eof = false;
  50. }
  51. pub fn searchByPrefix(prefix: []const u8) ?*TrieNode {
  52. var current = &root;
  53. for (prefix) |c| {
  54. const child = getChild(current, c);
  55. if (child == null) {
  56. return null;
  57. }
  58. current = child.?;
  59. }
  60. return current;
  61. }
  62. fn countKeys(node: *TrieNode) usize {
  63. var count: usize = 0;
  64. if (node.eof) {
  65. count += 1;
  66. }
  67. for (0..MAX_CHILDREN) |i| {
  68. const child = node.children[i];
  69. if (child != null) {
  70. count += countKeys(child.?);
  71. }
  72. }
  73. return count;
  74. }
  75. fn collectKeys(node: *TrieNode, prefix: []const u8, keys: [][]const u8, index: *usize) void {
  76. if (node.eof) {
  77. const key = allocator.alloc(u8, prefix.len) catch unreachable;
  78. @memcpy(key, prefix);
  79. keys[index.*] = key;
  80. index.* += 1;
  81. }
  82. for (0..MAX_CHILDREN) |i| {
  83. const child = node.children[i];
  84. if (child != null) {
  85. const childChar = child.?.char;
  86. var newPrefix = allocator.alloc(u8, prefix.len + 1) catch unreachable;
  87. @memcpy(newPrefix[0..prefix.len], prefix);
  88. newPrefix[prefix.len] = childChar;
  89. collectKeys(child.?, newPrefix, keys, index);
  90. allocator.free(newPrefix);
  91. }
  92. }
  93. }
  94. pub fn getKeysFromNode(node: *TrieNode, prefix: []const u8) [][]const u8 {
  95. const keyCount = countKeys(node);
  96. if (keyCount == 0) {
  97. return &[_][]const u8{};
  98. }
  99. const keys = allocator.alloc([]const u8, keyCount) catch unreachable;
  100. var index: usize = 0;
  101. collectKeys(node, prefix, keys, &index);
  102. return keys;
  103. }
  104. pub fn getKeysByPrefix(prefix: []const u8) []const u8 {
  105. const node = searchByPrefix(prefix) orelse return "";
  106. const keys = getKeysFromNode(node, prefix);
  107. if (keys.len == 0) return "";
  108. return std.mem.join(allocator, "\r", keys) catch unreachable;
  109. }
  110. pub fn getValuesByPrefix(prefix: []const u8) []const u8 {
  111. const node = searchByPrefix(prefix) orelse return "";
  112. const keys = getKeysFromNode(node, prefix);
  113. if (keys.len == 0) return "";
  114. const values = allocator.alloc([]const u8, keys.len) catch unreachable;
  115. for (keys, 0..) |key, i| {
  116. const value = storage.read(key) orelse "";
  117. values[i] = value;
  118. }
  119. return std.mem.join(allocator, "\r", values) catch unreachable;
  120. }
  121. pub fn getAllKeys() []const u8 {
  122. const keys = getKeysFromNode(&root, &[_]u8{});
  123. if (keys.len == 0) return "";
  124. return std.mem.join(allocator, "\r", keys) catch unreachable;
  125. }