diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-07-08 20:46:06 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-07-08 20:46:06 -0700 |
| commit | 7bd0500589f02a6f2ba75525d803b2c1d7409ebe (patch) | |
| tree | 63c26680b4ce918a718192ac540772e3152b9fe0 /lib | |
| parent | 8e425c0c8d78acc64a4223a35010df478d5b7e16 (diff) | |
| parent | 0e1c7209e8632ebf398e60de9053e2e0fe8b5661 (diff) | |
| download | zig-7bd0500589f02a6f2ba75525d803b2c1d7409ebe.tar.gz zig-7bd0500589f02a6f2ba75525d803b2c1d7409ebe.zip | |
Merge remote-tracking branch 'origin/master' into register-allocation
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/fs.zig | 2 | ||||
| -rw-r--r-- | lib/std/fs/test.zig | 45 | ||||
| -rw-r--r-- | lib/std/hash_map.zig | 32 |
3 files changed, 72 insertions, 7 deletions
diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 3c0ae8f265..0feaf69d67 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -453,6 +453,8 @@ pub const Dir = struct { pub const Error = IteratorError; + /// Memory such as file names referenced in this returned entry becomes invalid + /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. pub fn next(self: *Self) Error!?Entry { start_over: while (true) { const w = os.windows; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 52f823a32f..a3cf2e8002 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -3,10 +3,53 @@ const testing = std.testing; const builtin = std.builtin; const fs = std.fs; const mem = std.mem; +const wasi = std.os.wasi; +const ArenaAllocator = std.heap.ArenaAllocator; +const Dir = std.fs.Dir; const File = std.fs.File; const tmpDir = testing.tmpDir; +test "Dir.Iterator" { + var tmp_dir = tmpDir(.{ .iterate = true }); + defer tmp_dir.cleanup(); + + // First, create a couple of entries to iterate over. + const file = try tmp_dir.dir.createFile("some_file", .{}); + file.close(); + + try tmp_dir.dir.makeDir("some_dir"); + + var arena = ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + + var entries = std.ArrayList(Dir.Entry).init(&arena.allocator); + + // Create iterator. + var iter = tmp_dir.dir.iterate(); + while (try iter.next()) |entry| { + // We cannot just store `entry` as on Windows, we're re-using the name buffer + // which means we'll actually share the `name` pointer between entries! + const name = try arena.allocator.dupe(u8, entry.name); + try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); + } + + testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..' + testing.expect(contains(&entries, Dir.Entry{ .name = "some_file", .kind = Dir.Entry.Kind.File })); + testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory })); +} + +fn entry_eql(lhs: Dir.Entry, rhs: Dir.Entry) bool { + return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind; +} + +fn contains(entries: *const std.ArrayList(Dir.Entry), el: Dir.Entry) bool { + for (entries.items) |entry| { + if (entry_eql(entry, el)) return true; + } + return false; +} + test "readAllAlloc" { var tmp_dir = tmpDir(.{}); defer tmp_dir.cleanup(); @@ -237,7 +280,7 @@ test "fs.copyFile" { try expectFileContents(tmp.dir, dest_file2, data); } -fn expectFileContents(dir: fs.Dir, file_path: []const u8, data: []const u8) !void { +fn expectFileContents(dir: Dir, file_path: []const u8, data: []const u8) !void { const contents = try dir.readFileAlloc(testing.allocator, file_path, 1000); defer testing.allocator.free(contents); diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index a9c30aba87..645789a04b 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -533,12 +533,13 @@ pub fn HashMapUnmanaged( } pub fn clone(self: Self, allocator: *Allocator) !Self { - // TODO this can be made more efficient by directly allocating - // the memory slices and memcpying the elements. - var other = Self.init(); - try other.initCapacity(allocator, self.entries.len); - for (self.entries.items) |entry| { - other.putAssumeCapacityNoClobber(entry.key, entry.value); + var other: Self = .{}; + try other.entries.appendSlice(allocator, self.entries.items); + + if (self.index_header) |header| { + const new_header = try IndexHeader.alloc(allocator, header.indexes_len); + other.insertAllEntriesIntoNewHeader(new_header); + other.index_header = new_header; } return other; } @@ -980,6 +981,25 @@ test "ensure capacity" { testing.expect(initial_capacity == map.capacity()); } +test "clone" { + var original = AutoHashMap(i32, i32).init(std.testing.allocator); + defer original.deinit(); + + // put more than `linear_scan_max` so we can test that the index header is properly cloned + var i: u8 = 0; + while (i < 10) : (i += 1) { + try original.putNoClobber(i, i * 10); + } + + var copy = try original.clone(); + defer copy.deinit(); + + i = 0; + while (i < 10) : (i += 1) { + testing.expect(copy.get(i).? == i * 10); + } +} + pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) { return struct { fn hash(key: K) u32 { |
