aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-07-08 20:46:06 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-07-08 20:46:06 -0700
commit7bd0500589f02a6f2ba75525d803b2c1d7409ebe (patch)
tree63c26680b4ce918a718192ac540772e3152b9fe0 /lib
parent8e425c0c8d78acc64a4223a35010df478d5b7e16 (diff)
parent0e1c7209e8632ebf398e60de9053e2e0fe8b5661 (diff)
downloadzig-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.zig2
-rw-r--r--lib/std/fs/test.zig45
-rw-r--r--lib/std/hash_map.zig32
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 {