mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
std/ArrayList: Allow ArrayList(u0) to be created
Enable creating ArrayList with zero-sized types. This type still tracks length, but does not allocate additional memory.
This commit is contained in:
parent
551971b5c3
commit
2588451967
@ -65,16 +65,23 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
|
||||
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
|
||||
var self = Self.init(allocator);
|
||||
|
||||
const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
|
||||
self.items.ptr = new_memory.ptr;
|
||||
self.capacity = new_memory.len;
|
||||
if (@sizeOf(T) > 0) {
|
||||
const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
|
||||
self.items.ptr = new_memory.ptr;
|
||||
self.capacity = new_memory.len;
|
||||
} else {
|
||||
// If `T` is a zero-sized type, then we do not need to allocate memory.
|
||||
self.capacity = std.math.maxInt(usize);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Release all allocated memory.
|
||||
pub fn deinit(self: Self) void {
|
||||
self.allocator.free(self.allocatedSlice());
|
||||
if (@sizeOf(T) > 0) {
|
||||
self.allocator.free(self.allocatedSlice());
|
||||
}
|
||||
}
|
||||
|
||||
pub const span = @compileError("deprecated: use `items` field directly");
|
||||
@ -279,13 +286,17 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
|
||||
pub fn shrinkAndFree(self: *Self, new_len: usize) void {
|
||||
assert(new_len <= self.items.len);
|
||||
|
||||
self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) {
|
||||
error.OutOfMemory => { // no problem, capacity is still correct then.
|
||||
self.items.len = new_len;
|
||||
return;
|
||||
},
|
||||
};
|
||||
self.capacity = new_len;
|
||||
if (@sizeOf(T) > 0) {
|
||||
self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) {
|
||||
error.OutOfMemory => { // no problem, capacity is still correct then.
|
||||
self.items.len = new_len;
|
||||
return;
|
||||
},
|
||||
};
|
||||
self.capacity = new_len;
|
||||
} else {
|
||||
self.items.len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/// Reduce length to `new_len`.
|
||||
@ -313,18 +324,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
|
||||
/// Modify the array so that it can hold at least `new_capacity` items.
|
||||
/// Invalidates pointers if additional memory is needed.
|
||||
pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
|
||||
var better_capacity = self.capacity;
|
||||
if (better_capacity >= new_capacity) return;
|
||||
if (@sizeOf(T) > 0) {
|
||||
var better_capacity = self.capacity;
|
||||
if (better_capacity >= new_capacity) return;
|
||||
|
||||
while (true) {
|
||||
better_capacity += better_capacity / 2 + 8;
|
||||
if (better_capacity >= new_capacity) break;
|
||||
while (true) {
|
||||
better_capacity += better_capacity / 2 + 8;
|
||||
if (better_capacity >= new_capacity) break;
|
||||
}
|
||||
|
||||
// TODO This can be optimized to avoid needlessly copying undefined memory.
|
||||
const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
|
||||
self.items.ptr = new_memory.ptr;
|
||||
self.capacity = new_memory.len;
|
||||
} else {
|
||||
self.capacity = std.math.maxInt(usize);
|
||||
}
|
||||
|
||||
// TODO This can be optimized to avoid needlessly copying undefined memory.
|
||||
const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
|
||||
self.items.ptr = new_memory.ptr;
|
||||
self.capacity = new_memory.len;
|
||||
}
|
||||
|
||||
/// Modify the array so that it can hold at least `additional_count` **more** items.
|
||||
@ -1299,3 +1314,23 @@ test "ArrayListAligned/ArrayListAlignedUnmanaged accepts unaligned slices" {
|
||||
try testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 });
|
||||
}
|
||||
}
|
||||
|
||||
test "std.ArrayList(u0)" {
|
||||
// An ArrayList on zero-sized types should not need to allocate
|
||||
const a = &testing.FailingAllocator.init(testing.allocator, 0).allocator;
|
||||
|
||||
var list = ArrayList(u0).init(a);
|
||||
defer list.deinit();
|
||||
|
||||
try list.append(0);
|
||||
try list.append(0);
|
||||
try list.append(0);
|
||||
try testing.expectEqual(list.items.len, 3);
|
||||
|
||||
var count: usize = 0;
|
||||
for (list.items) |x| {
|
||||
try testing.expectEqual(x, 0);
|
||||
count += 1;
|
||||
}
|
||||
try testing.expectEqual(count, 3);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user