| ... | @@ -309,7 +309,6 @@ pub const ExportSymbol = struct { | ... | @@ -309,7 +309,6 @@ pub const ExportSymbol = struct { |
| 309 | /// This operation may change the layout of the trie by splicing edges in | 309 | /// This operation may change the layout of the trie by splicing edges in |
| 310 | /// certain circumstances. | 310 | /// certain circumstances. |
| 311 | pub fn put(self: *Trie, allocator: Allocator, symbol: ExportSymbol) !void { | 311 | pub fn put(self: *Trie, allocator: Allocator, symbol: ExportSymbol) !void { |
| 312 | try self.createRoot(allocator); | | |
| 313 | const node = try self.root.?.put(allocator, symbol.name); | 312 | const node = try self.root.?.put(allocator, symbol.name); |
| 314 | node.terminal_info = .{ | 313 | node.terminal_info = .{ |
| 315 | .vmaddr_offset = symbol.vmaddr_offset, | 314 | .vmaddr_offset = symbol.vmaddr_offset, |
| ... | @@ -362,7 +361,6 @@ const ReadError = error{ | ... | @@ -362,7 +361,6 @@ const ReadError = error{ |
| 362 | | 361 | |
| 363 | /// Parse the trie from a byte stream. | 362 | /// Parse the trie from a byte stream. |
| 364 | pub fn read(self: *Trie, allocator: Allocator, reader: anytype) ReadError!usize { | 363 | pub fn read(self: *Trie, allocator: Allocator, reader: anytype) ReadError!usize { |
| 365 | try self.createRoot(allocator); | | |
| 366 | return self.root.?.read(allocator, reader); | 364 | return self.root.?.read(allocator, reader); |
| 367 | } | 365 | } |
| 368 | | 366 | |
| ... | @@ -377,6 +375,14 @@ pub fn write(self: Trie, writer: anytype) !u64 { | ... | @@ -377,6 +375,14 @@ pub fn write(self: Trie, writer: anytype) !u64 { |
| 377 | return counting_writer.bytes_written; | 375 | return counting_writer.bytes_written; |
| 378 | } | 376 | } |
| 379 | | 377 | |
| | 378 | pub fn init(self: *Trie, allocator: Allocator) !void { |
| | 379 | assert(self.root == null); |
| | 380 | const root = try allocator.create(Node); |
| | 381 | root.* = .{ .base = self }; |
| | 382 | self.root = root; |
| | 383 | self.node_count += 1; |
| | 384 | } |
| | 385 | |
| 380 | pub fn deinit(self: *Trie, allocator: Allocator) void { | 386 | pub fn deinit(self: *Trie, allocator: Allocator) void { |
| 381 | if (self.root) |root| { | 387 | if (self.root) |root| { |
| 382 | root.deinit(allocator); | 388 | root.deinit(allocator); |
| ... | @@ -385,19 +391,11 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { | ... | @@ -385,19 +391,11 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { |
| 385 | self.ordered_nodes.deinit(allocator); | 391 | self.ordered_nodes.deinit(allocator); |
| 386 | } | 392 | } |
| 387 | | 393 | |
| 388 | fn createRoot(self: *Trie, allocator: Allocator) !void { | | |
| 389 | if (self.root == null) { | | |
| 390 | const root = try allocator.create(Node); | | |
| 391 | root.* = .{ .base = self }; | | |
| 392 | self.root = root; | | |
| 393 | self.node_count += 1; | | |
| 394 | } | | |
| 395 | } | | |
| 396 | | | |
| 397 | test "Trie node count" { | 394 | test "Trie node count" { |
| 398 | var gpa = testing.allocator; | 395 | var gpa = testing.allocator; |
| 399 | var trie: Trie = .{}; | 396 | var trie: Trie = .{}; |
| 400 | defer trie.deinit(gpa); | 397 | defer trie.deinit(gpa); |
| | 398 | try trie.init(gpa); |
| 401 | | 399 | |
| 402 | try testing.expectEqual(trie.node_count, 0); | 400 | try testing.expectEqual(trie.node_count, 0); |
| 403 | try testing.expect(trie.root == null); | 401 | try testing.expect(trie.root == null); |
| ... | @@ -443,6 +441,7 @@ test "Trie basic" { | ... | @@ -443,6 +441,7 @@ test "Trie basic" { |
| 443 | var gpa = testing.allocator; | 441 | var gpa = testing.allocator; |
| 444 | var trie: Trie = .{}; | 442 | var trie: Trie = .{}; |
| 445 | defer trie.deinit(gpa); | 443 | defer trie.deinit(gpa); |
| | 444 | try trie.init(gpa); |
| 446 | | 445 | |
| 447 | // root --- _st ---> node | 446 | // root --- _st ---> node |
| 448 | try trie.put(gpa, .{ | 447 | try trie.put(gpa, .{ |
| ... | @@ -508,6 +507,7 @@ test "write Trie to a byte stream" { | ... | @@ -508,6 +507,7 @@ test "write Trie to a byte stream" { |
| 508 | var gpa = testing.allocator; | 507 | var gpa = testing.allocator; |
| 509 | var trie: Trie = .{}; | 508 | var trie: Trie = .{}; |
| 510 | defer trie.deinit(gpa); | 509 | defer trie.deinit(gpa); |
| | 510 | try trie.init(gpa); |
| 511 | | 511 | |
| 512 | try trie.put(gpa, .{ | 512 | try trie.put(gpa, .{ |
| 513 | .name = "__mh_execute_header", | 513 | .name = "__mh_execute_header", |
| ... | @@ -566,6 +566,7 @@ test "parse Trie from byte stream" { | ... | @@ -566,6 +566,7 @@ test "parse Trie from byte stream" { |
| 566 | var in_stream = std.io.fixedBufferStream(&in_buffer); | 566 | var in_stream = std.io.fixedBufferStream(&in_buffer); |
| 567 | var trie: Trie = .{}; | 567 | var trie: Trie = .{}; |
| 568 | defer trie.deinit(gpa); | 568 | defer trie.deinit(gpa); |
| | 569 | try trie.init(gpa); |
| 569 | const nread = try trie.read(gpa, in_stream.reader()); | 570 | const nread = try trie.read(gpa, in_stream.reader()); |
| 570 | | 571 | |
| 571 | try testing.expect(nread == in_buffer.len); | 572 | try testing.expect(nread == in_buffer.len); |
| ... | @@ -583,6 +584,7 @@ test "ordering bug" { | ... | @@ -583,6 +584,7 @@ test "ordering bug" { |
| 583 | var gpa = testing.allocator; | 584 | var gpa = testing.allocator; |
| 584 | var trie: Trie = .{}; | 585 | var trie: Trie = .{}; |
| 585 | defer trie.deinit(gpa); | 586 | defer trie.deinit(gpa); |
| | 587 | try trie.init(gpa); |
| 586 | | 588 | |
| 587 | try trie.put(gpa, .{ | 589 | try trie.put(gpa, .{ |
| 588 | .name = "_asStr", | 590 | .name = "_asStr", |