mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
remove iterator API from std.ArrayList
This is not a meaningful abstraction. Use a for loop on the result of `toSlice` or `toSliceConst`. An iterator can be implemented on top of ArrayList by applications which want additional functionality, such as removing elements while iterating. Closes #3037.
This commit is contained in:
parent
f30af12bea
commit
c3d8b1ffeb
@ -84,11 +84,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
|
||||
self.items[i] = item;
|
||||
}
|
||||
|
||||
/// Return length of the list.
|
||||
pub fn count(self: Self) usize {
|
||||
return self.len;
|
||||
}
|
||||
|
||||
/// Return the maximum number of items the list can hold
|
||||
/// without allocating more memory.
|
||||
pub fn capacity(self: Self) usize {
|
||||
@ -114,7 +109,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Insert `item` at index `n`. Moves `list[n .. list.count()]`
|
||||
/// Insert `item` at index `n`. Moves `list[n .. list.len]`
|
||||
/// to make room.
|
||||
pub fn insert(self: *Self, n: usize, item: T) !void {
|
||||
try self.ensureCapacity(self.len + 1);
|
||||
@ -125,7 +120,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
|
||||
}
|
||||
|
||||
/// Insert slice `items` at index `n`. Moves
|
||||
/// `list[n .. list.count()]` to make room.
|
||||
/// `list[n .. list.len]` to make room.
|
||||
pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
|
||||
try self.ensureCapacity(self.len + items.len);
|
||||
self.len += items.len;
|
||||
@ -222,7 +217,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
|
||||
}
|
||||
|
||||
pub fn addOneAssumeCapacity(self: *Self) *T {
|
||||
assert(self.count() < self.capacity());
|
||||
assert(self.len < self.capacity());
|
||||
const result = &self.items[self.len];
|
||||
self.len += 1;
|
||||
return result;
|
||||
@ -240,31 +235,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
|
||||
if (self.len == 0) return null;
|
||||
return self.pop();
|
||||
}
|
||||
|
||||
pub const Iterator = struct {
|
||||
list: *const Self,
|
||||
// how many items have we returned
|
||||
count: usize,
|
||||
|
||||
pub fn next(it: *Iterator) ?T {
|
||||
if (it.count >= it.list.len) return null;
|
||||
const val = it.list.at(it.count);
|
||||
it.count += 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
pub fn reset(it: *Iterator) void {
|
||||
it.count = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Return an iterator over the list.
|
||||
pub fn iterator(self: *const Self) Iterator {
|
||||
return Iterator{
|
||||
.list = self,
|
||||
.count = 0,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -275,7 +245,7 @@ test "std.ArrayList.init" {
|
||||
var list = ArrayList(i32).init(allocator);
|
||||
defer list.deinit();
|
||||
|
||||
testing.expect(list.count() == 0);
|
||||
testing.expect(list.len == 0);
|
||||
testing.expect(list.capacity() == 0);
|
||||
}
|
||||
|
||||
@ -284,7 +254,7 @@ test "std.ArrayList.initCapacity" {
|
||||
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
|
||||
var list = try ArrayList(i8).initCapacity(allocator, 200);
|
||||
defer list.deinit();
|
||||
testing.expect(list.count() == 0);
|
||||
testing.expect(list.len == 0);
|
||||
testing.expect(list.capacity() >= 200);
|
||||
}
|
||||
|
||||
@ -426,35 +396,6 @@ test "std.ArrayList.swapRemoveOrError" {
|
||||
testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
|
||||
}
|
||||
|
||||
test "std.ArrayList.iterator" {
|
||||
var list = ArrayList(i32).init(debug.global_allocator);
|
||||
defer list.deinit();
|
||||
|
||||
try list.append(1);
|
||||
try list.append(2);
|
||||
try list.append(3);
|
||||
|
||||
var count: i32 = 0;
|
||||
var it = list.iterator();
|
||||
while (it.next()) |next| {
|
||||
testing.expect(next == count + 1);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
testing.expect(count == 3);
|
||||
testing.expect(it.next() == null);
|
||||
it.reset();
|
||||
count = 0;
|
||||
while (it.next()) |next| {
|
||||
testing.expect(next == count + 1);
|
||||
count += 1;
|
||||
if (count == 2) break;
|
||||
}
|
||||
|
||||
it.reset();
|
||||
testing.expect(it.next().? == 1);
|
||||
}
|
||||
|
||||
test "std.ArrayList.insert" {
|
||||
var list = ArrayList(i32).init(debug.global_allocator);
|
||||
defer list.deinit();
|
||||
|
||||
@ -133,8 +133,7 @@ pub const Headers = struct {
|
||||
self.index.deinit();
|
||||
}
|
||||
{
|
||||
var it = self.data.iterator();
|
||||
while (it.next()) |entry| {
|
||||
for (self.data.toSliceConst()) |entry| {
|
||||
entry.deinit();
|
||||
}
|
||||
self.data.deinit();
|
||||
@ -144,27 +143,20 @@ pub const Headers = struct {
|
||||
pub fn clone(self: Self, allocator: *Allocator) !Self {
|
||||
var other = Headers.init(allocator);
|
||||
errdefer other.deinit();
|
||||
try other.data.ensureCapacity(self.data.count());
|
||||
try other.data.ensureCapacity(self.data.len);
|
||||
try other.index.initCapacity(self.index.entries.len);
|
||||
var it = self.data.iterator();
|
||||
while (it.next()) |entry| {
|
||||
for (self.data.toSliceConst()) |entry| {
|
||||
try other.append(entry.name, entry.value, entry.never_index);
|
||||
}
|
||||
return other;
|
||||
}
|
||||
|
||||
pub fn count(self: Self) usize {
|
||||
return self.data.count();
|
||||
}
|
||||
|
||||
pub const Iterator = HeaderList.Iterator;
|
||||
|
||||
pub fn iterator(self: Self) Iterator {
|
||||
return self.data.iterator();
|
||||
pub fn toSlice(self: Self) []const HeaderEntry {
|
||||
return self.data.toSliceConst();
|
||||
}
|
||||
|
||||
pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
|
||||
const n = self.data.count() + 1;
|
||||
const n = self.data.len + 1;
|
||||
try self.data.ensureCapacity(n);
|
||||
var entry: HeaderEntry = undefined;
|
||||
if (self.index.get(name)) |kv| {
|
||||
@ -190,7 +182,7 @@ pub const Headers = struct {
|
||||
pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
|
||||
if (self.index.get(name)) |kv| {
|
||||
const dex = kv.value;
|
||||
if (dex.count() != 1)
|
||||
if (dex.len != 1)
|
||||
return error.CannotUpsertMultiValuedField;
|
||||
var e = &self.data.at(dex.at(0));
|
||||
try e.modify(value, never_index);
|
||||
@ -209,7 +201,7 @@ pub const Headers = struct {
|
||||
if (self.index.remove(name)) |kv| {
|
||||
var dex = &kv.value;
|
||||
// iterate backwards
|
||||
var i = dex.count();
|
||||
var i = dex.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
const data_index = dex.at(i);
|
||||
@ -232,18 +224,18 @@ pub const Headers = struct {
|
||||
const removed = self.data.orderedRemove(i);
|
||||
const kv = self.index.get(removed.name).?;
|
||||
var dex = &kv.value;
|
||||
if (dex.count() == 1) {
|
||||
if (dex.len == 1) {
|
||||
// was last item; delete the index
|
||||
_ = self.index.remove(kv.key);
|
||||
dex.deinit();
|
||||
removed.deinit();
|
||||
self.allocator.free(kv.key);
|
||||
} else {
|
||||
dex.shrink(dex.count() - 1);
|
||||
dex.shrink(dex.len - 1);
|
||||
removed.deinit();
|
||||
}
|
||||
// if it was the last item; no need to rebuild index
|
||||
if (i != self.data.count()) {
|
||||
if (i != self.data.len) {
|
||||
self.rebuild_index();
|
||||
}
|
||||
}
|
||||
@ -254,18 +246,18 @@ pub const Headers = struct {
|
||||
const removed = self.data.swapRemove(i);
|
||||
const kv = self.index.get(removed.name).?;
|
||||
var dex = &kv.value;
|
||||
if (dex.count() == 1) {
|
||||
if (dex.len == 1) {
|
||||
// was last item; delete the index
|
||||
_ = self.index.remove(kv.key);
|
||||
dex.deinit();
|
||||
removed.deinit();
|
||||
self.allocator.free(kv.key);
|
||||
} else {
|
||||
dex.shrink(dex.count() - 1);
|
||||
dex.shrink(dex.len - 1);
|
||||
removed.deinit();
|
||||
}
|
||||
// if it was the last item; no need to rebuild index
|
||||
if (i != self.data.count()) {
|
||||
if (i != self.data.len) {
|
||||
self.rebuild_index();
|
||||
}
|
||||
}
|
||||
@ -289,10 +281,9 @@ pub const Headers = struct {
|
||||
pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {
|
||||
const dex = self.getIndices(name) orelse return null;
|
||||
|
||||
const buf = try allocator.alloc(HeaderEntry, dex.count());
|
||||
var it = dex.iterator();
|
||||
const buf = try allocator.alloc(HeaderEntry, dex.len);
|
||||
var n: usize = 0;
|
||||
while (it.next()) |idx| {
|
||||
for (dex.toSliceConst()) |idx| {
|
||||
buf[n] = self.data.at(idx);
|
||||
n += 1;
|
||||
}
|
||||
@ -314,9 +305,8 @@ pub const Headers = struct {
|
||||
|
||||
// adapted from mem.join
|
||||
const total_len = blk: {
|
||||
var sum: usize = dex.count() - 1; // space for separator(s)
|
||||
var it = dex.iterator();
|
||||
while (it.next()) |idx|
|
||||
var sum: usize = dex.len - 1; // space for separator(s)
|
||||
for (dex.toSliceConst()) |idx|
|
||||
sum += self.data.at(idx).value.len;
|
||||
break :blk sum;
|
||||
};
|
||||
@ -348,10 +338,9 @@ pub const Headers = struct {
|
||||
}
|
||||
}
|
||||
{ // fill up indexes again; we know capacity is fine from before
|
||||
var it = self.data.iterator();
|
||||
while (it.next()) |entry| {
|
||||
for (self.data.toSliceConst()) |entry, i| {
|
||||
var dex = &self.index.get(entry.name).?.value;
|
||||
dex.appendAssumeCapacity(it.count);
|
||||
dex.appendAssumeCapacity(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,8 +358,7 @@ pub const Headers = struct {
|
||||
comptime Errors: type,
|
||||
output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
var it = self.iterator();
|
||||
while (it.next()) |entry| {
|
||||
for (self.toSlice()) |entry| {
|
||||
try output(context, entry.name);
|
||||
try output(context, ": ");
|
||||
try output(context, entry.value);
|
||||
@ -386,8 +374,7 @@ test "Headers.iterator" {
|
||||
try h.append("cookie", "somevalue", null);
|
||||
|
||||
var count: i32 = 0;
|
||||
var it = h.iterator();
|
||||
while (it.next()) |e| {
|
||||
for (h.toSlice()) |e| {
|
||||
if (count == 0) {
|
||||
testing.expectEqualSlices(u8, "foo", e.name);
|
||||
testing.expectEqualSlices(u8, "bar", e.value);
|
||||
@ -420,10 +407,10 @@ test "Headers.delete" {
|
||||
try h.append("cookie", "somevalue", null);
|
||||
|
||||
testing.expectEqual(false, h.delete("not-present"));
|
||||
testing.expectEqual(@as(usize, 3), h.count());
|
||||
testing.expectEqual(@as(usize, 3), h.toSlice().len);
|
||||
|
||||
testing.expectEqual(true, h.delete("foo"));
|
||||
testing.expectEqual(@as(usize, 2), h.count());
|
||||
testing.expectEqual(@as(usize, 2), h.toSlice().len);
|
||||
{
|
||||
const e = h.at(0);
|
||||
testing.expectEqualSlices(u8, "baz", e.name);
|
||||
@ -448,7 +435,7 @@ test "Headers.orderedRemove" {
|
||||
try h.append("cookie", "somevalue", null);
|
||||
|
||||
h.orderedRemove(0);
|
||||
testing.expectEqual(@as(usize, 2), h.count());
|
||||
testing.expectEqual(@as(usize, 2), h.toSlice().len);
|
||||
{
|
||||
const e = h.at(0);
|
||||
testing.expectEqualSlices(u8, "baz", e.name);
|
||||
@ -471,7 +458,7 @@ test "Headers.swapRemove" {
|
||||
try h.append("cookie", "somevalue", null);
|
||||
|
||||
h.swapRemove(0);
|
||||
testing.expectEqual(@as(usize, 2), h.count());
|
||||
testing.expectEqual(@as(usize, 2), h.toSlice().len);
|
||||
{
|
||||
const e = h.at(0);
|
||||
testing.expectEqualSlices(u8, "cookie", e.name);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user