authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-10 15:08:10-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-10 15:08:10-05:00
logc3d8b1ffebb94d180c382bd74128d17dc21c1392
tree174415dbc79d6f1de6c57d3a4eebe390c660753e
parentf30af12bea0d55971dac37d8891bd9717158d73e
signature Commit is signed but in an unrecognized format.

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.

2 files changed, 31 insertions(+), 103 deletions(-)

lib/std/array_list.zig+5-64
...@@ -84,11 +84,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -84,11 +84,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
84 self.items[i] = item;84 self.items[i] = item;
85 }85 }
8686
87 /// Return length of the list.
88 pub fn count(self: Self) usize {
89 return self.len;
90 }
91
92 /// Return the maximum number of items the list can hold87 /// Return the maximum number of items the list can hold
93 /// without allocating more memory.88 /// without allocating more memory.
94 pub fn capacity(self: Self) usize {89 pub fn capacity(self: Self) usize {
...@@ -114,7 +109,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -114,7 +109,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
114 return result;109 return result;
115 }110 }
116111
117 /// Insert `item` at index `n`. Moves `list[n .. list.count()]`112 /// Insert `item` at index `n`. Moves `list[n .. list.len]`
118 /// to make room.113 /// to make room.
119 pub fn insert(self: *Self, n: usize, item: T) !void {114 pub fn insert(self: *Self, n: usize, item: T) !void {
120 try self.ensureCapacity(self.len + 1);115 try self.ensureCapacity(self.len + 1);
...@@ -125,7 +120,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -125,7 +120,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
125 }120 }
126121
127 /// Insert slice `items` at index `n`. Moves122 /// Insert slice `items` at index `n`. Moves
128 /// `list[n .. list.count()]` to make room.123 /// `list[n .. list.len]` to make room.
129 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {124 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
130 try self.ensureCapacity(self.len + items.len);125 try self.ensureCapacity(self.len + items.len);
131 self.len += items.len;126 self.len += items.len;
...@@ -222,7 +217,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -222,7 +217,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
222 }217 }
223218
224 pub fn addOneAssumeCapacity(self: *Self) *T {219 pub fn addOneAssumeCapacity(self: *Self) *T {
225 assert(self.count() < self.capacity());220 assert(self.len < self.capacity());
226 const result = &self.items[self.len];221 const result = &self.items[self.len];
227 self.len += 1;222 self.len += 1;
228 return result;223 return result;
...@@ -240,31 +235,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -240,31 +235,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
240 if (self.len == 0) return null;235 if (self.len == 0) return null;
241 return self.pop();236 return self.pop();
242 }237 }
243
244 pub const Iterator = struct {
245 list: *const Self,
246 // how many items have we returned
247 count: usize,
248
249 pub fn next(it: *Iterator) ?T {
250 if (it.count >= it.list.len) return null;
251 const val = it.list.at(it.count);
252 it.count += 1;
253 return val;
254 }
255
256 pub fn reset(it: *Iterator) void {
257 it.count = 0;
258 }
259 };
260
261 /// Return an iterator over the list.
262 pub fn iterator(self: *const Self) Iterator {
263 return Iterator{
264 .list = self,
265 .count = 0,
266 };
267 }
268 };238 };
269}239}
270240
...@@ -275,7 +245,7 @@ test "std.ArrayList.init" {...@@ -275,7 +245,7 @@ test "std.ArrayList.init" {
275 var list = ArrayList(i32).init(allocator);245 var list = ArrayList(i32).init(allocator);
276 defer list.deinit();246 defer list.deinit();
277247
278 testing.expect(list.count() == 0);248 testing.expect(list.len == 0);
279 testing.expect(list.capacity() == 0);249 testing.expect(list.capacity() == 0);
280}250}
281251
...@@ -284,7 +254,7 @@ test "std.ArrayList.initCapacity" {...@@ -284,7 +254,7 @@ test "std.ArrayList.initCapacity" {
284 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;254 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
285 var list = try ArrayList(i8).initCapacity(allocator, 200);255 var list = try ArrayList(i8).initCapacity(allocator, 200);
286 defer list.deinit();256 defer list.deinit();
287 testing.expect(list.count() == 0);257 testing.expect(list.len == 0);
288 testing.expect(list.capacity() >= 200);258 testing.expect(list.capacity() >= 200);
289}259}
290260
...@@ -426,35 +396,6 @@ test "std.ArrayList.swapRemoveOrError" {...@@ -426,35 +396,6 @@ test "std.ArrayList.swapRemoveOrError" {
426 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));396 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
427}397}
428398
429test "std.ArrayList.iterator" {
430 var list = ArrayList(i32).init(debug.global_allocator);
431 defer list.deinit();
432
433 try list.append(1);
434 try list.append(2);
435 try list.append(3);
436
437 var count: i32 = 0;
438 var it = list.iterator();
439 while (it.next()) |next| {
440 testing.expect(next == count + 1);
441 count += 1;
442 }
443
444 testing.expect(count == 3);
445 testing.expect(it.next() == null);
446 it.reset();
447 count = 0;
448 while (it.next()) |next| {
449 testing.expect(next == count + 1);
450 count += 1;
451 if (count == 2) break;
452 }
453
454 it.reset();
455 testing.expect(it.next().? == 1);
456}
457
458test "std.ArrayList.insert" {399test "std.ArrayList.insert" {
459 var list = ArrayList(i32).init(debug.global_allocator);400 var list = ArrayList(i32).init(debug.global_allocator);
460 defer list.deinit();401 defer list.deinit();
lib/std/http/headers.zig+26-39
...@@ -133,8 +133,7 @@ pub const Headers = struct {...@@ -133,8 +133,7 @@ pub const Headers = struct {
133 self.index.deinit();133 self.index.deinit();
134 }134 }
135 {135 {
136 var it = self.data.iterator();136 for (self.data.toSliceConst()) |entry| {
137 while (it.next()) |entry| {
138 entry.deinit();137 entry.deinit();
139 }138 }
140 self.data.deinit();139 self.data.deinit();
...@@ -144,27 +143,20 @@ pub const Headers = struct {...@@ -144,27 +143,20 @@ pub const Headers = struct {
144 pub fn clone(self: Self, allocator: *Allocator) !Self {143 pub fn clone(self: Self, allocator: *Allocator) !Self {
145 var other = Headers.init(allocator);144 var other = Headers.init(allocator);
146 errdefer other.deinit();145 errdefer other.deinit();
147 try other.data.ensureCapacity(self.data.count());146 try other.data.ensureCapacity(self.data.len);
148 try other.index.initCapacity(self.index.entries.len);147 try other.index.initCapacity(self.index.entries.len);
149 var it = self.data.iterator();148 for (self.data.toSliceConst()) |entry| {
150 while (it.next()) |entry| {
151 try other.append(entry.name, entry.value, entry.never_index);149 try other.append(entry.name, entry.value, entry.never_index);
152 }150 }
153 return other;151 return other;
154 }152 }
155153
156 pub fn count(self: Self) usize {154 pub fn toSlice(self: Self) []const HeaderEntry {
157 return self.data.count();155 return self.data.toSliceConst();
158 }
159
160 pub const Iterator = HeaderList.Iterator;
161
162 pub fn iterator(self: Self) Iterator {
163 return self.data.iterator();
164 }156 }
165157
166 pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {158 pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
167 const n = self.data.count() + 1;159 const n = self.data.len + 1;
168 try self.data.ensureCapacity(n);160 try self.data.ensureCapacity(n);
169 var entry: HeaderEntry = undefined;161 var entry: HeaderEntry = undefined;
170 if (self.index.get(name)) |kv| {162 if (self.index.get(name)) |kv| {
...@@ -190,7 +182,7 @@ pub const Headers = struct {...@@ -190,7 +182,7 @@ pub const Headers = struct {
190 pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {182 pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
191 if (self.index.get(name)) |kv| {183 if (self.index.get(name)) |kv| {
192 const dex = kv.value;184 const dex = kv.value;
193 if (dex.count() != 1)185 if (dex.len != 1)
194 return error.CannotUpsertMultiValuedField;186 return error.CannotUpsertMultiValuedField;
195 var e = &self.data.at(dex.at(0));187 var e = &self.data.at(dex.at(0));
196 try e.modify(value, never_index);188 try e.modify(value, never_index);
...@@ -209,7 +201,7 @@ pub const Headers = struct {...@@ -209,7 +201,7 @@ pub const Headers = struct {
209 if (self.index.remove(name)) |kv| {201 if (self.index.remove(name)) |kv| {
210 var dex = &kv.value;202 var dex = &kv.value;
211 // iterate backwards203 // iterate backwards
212 var i = dex.count();204 var i = dex.len;
213 while (i > 0) {205 while (i > 0) {
214 i -= 1;206 i -= 1;
215 const data_index = dex.at(i);207 const data_index = dex.at(i);
...@@ -232,18 +224,18 @@ pub const Headers = struct {...@@ -232,18 +224,18 @@ pub const Headers = struct {
232 const removed = self.data.orderedRemove(i);224 const removed = self.data.orderedRemove(i);
233 const kv = self.index.get(removed.name).?;225 const kv = self.index.get(removed.name).?;
234 var dex = &kv.value;226 var dex = &kv.value;
235 if (dex.count() == 1) {227 if (dex.len == 1) {
236 // was last item; delete the index228 // was last item; delete the index
237 _ = self.index.remove(kv.key);229 _ = self.index.remove(kv.key);
238 dex.deinit();230 dex.deinit();
239 removed.deinit();231 removed.deinit();
240 self.allocator.free(kv.key);232 self.allocator.free(kv.key);
241 } else {233 } else {
242 dex.shrink(dex.count() - 1);234 dex.shrink(dex.len - 1);
243 removed.deinit();235 removed.deinit();
244 }236 }
245 // if it was the last item; no need to rebuild index237 // if it was the last item; no need to rebuild index
246 if (i != self.data.count()) {238 if (i != self.data.len) {
247 self.rebuild_index();239 self.rebuild_index();
248 }240 }
249 }241 }
...@@ -254,18 +246,18 @@ pub const Headers = struct {...@@ -254,18 +246,18 @@ pub const Headers = struct {
254 const removed = self.data.swapRemove(i);246 const removed = self.data.swapRemove(i);
255 const kv = self.index.get(removed.name).?;247 const kv = self.index.get(removed.name).?;
256 var dex = &kv.value;248 var dex = &kv.value;
257 if (dex.count() == 1) {249 if (dex.len == 1) {
258 // was last item; delete the index250 // was last item; delete the index
259 _ = self.index.remove(kv.key);251 _ = self.index.remove(kv.key);
260 dex.deinit();252 dex.deinit();
261 removed.deinit();253 removed.deinit();
262 self.allocator.free(kv.key);254 self.allocator.free(kv.key);
263 } else {255 } else {
264 dex.shrink(dex.count() - 1);256 dex.shrink(dex.len - 1);
265 removed.deinit();257 removed.deinit();
266 }258 }
267 // if it was the last item; no need to rebuild index259 // if it was the last item; no need to rebuild index
268 if (i != self.data.count()) {260 if (i != self.data.len) {
269 self.rebuild_index();261 self.rebuild_index();
270 }262 }
271 }263 }
...@@ -289,10 +281,9 @@ pub const Headers = struct {...@@ -289,10 +281,9 @@ pub const Headers = struct {
289 pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {281 pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {
290 const dex = self.getIndices(name) orelse return null;282 const dex = self.getIndices(name) orelse return null;
291283
292 const buf = try allocator.alloc(HeaderEntry, dex.count());284 const buf = try allocator.alloc(HeaderEntry, dex.len);
293 var it = dex.iterator();
294 var n: usize = 0;285 var n: usize = 0;
295 while (it.next()) |idx| {286 for (dex.toSliceConst()) |idx| {
296 buf[n] = self.data.at(idx);287 buf[n] = self.data.at(idx);
297 n += 1;288 n += 1;
298 }289 }
...@@ -314,9 +305,8 @@ pub const Headers = struct {...@@ -314,9 +305,8 @@ pub const Headers = struct {
314305
315 // adapted from mem.join306 // adapted from mem.join
316 const total_len = blk: {307 const total_len = blk: {
317 var sum: usize = dex.count() - 1; // space for separator(s)308 var sum: usize = dex.len - 1; // space for separator(s)
318 var it = dex.iterator();309 for (dex.toSliceConst()) |idx|
319 while (it.next()) |idx|
320 sum += self.data.at(idx).value.len;310 sum += self.data.at(idx).value.len;
321 break :blk sum;311 break :blk sum;
322 };312 };
...@@ -348,10 +338,9 @@ pub const Headers = struct {...@@ -348,10 +338,9 @@ pub const Headers = struct {
348 }338 }
349 }339 }
350 { // fill up indexes again; we know capacity is fine from before340 { // fill up indexes again; we know capacity is fine from before
351 var it = self.data.iterator();341 for (self.data.toSliceConst()) |entry, i| {
352 while (it.next()) |entry| {
353 var dex = &self.index.get(entry.name).?.value;342 var dex = &self.index.get(entry.name).?.value;
354 dex.appendAssumeCapacity(it.count);343 dex.appendAssumeCapacity(i);
355 }344 }
356 }345 }
357 }346 }
...@@ -369,8 +358,7 @@ pub const Headers = struct {...@@ -369,8 +358,7 @@ pub const Headers = struct {
369 comptime Errors: type,358 comptime Errors: type,
370 output: fn (@TypeOf(context), []const u8) Errors!void,359 output: fn (@TypeOf(context), []const u8) Errors!void,
371 ) Errors!void {360 ) Errors!void {
372 var it = self.iterator();361 for (self.toSlice()) |entry| {
373 while (it.next()) |entry| {
374 try output(context, entry.name);362 try output(context, entry.name);
375 try output(context, ": ");363 try output(context, ": ");
376 try output(context, entry.value);364 try output(context, entry.value);
...@@ -386,8 +374,7 @@ test "Headers.iterator" {...@@ -386,8 +374,7 @@ test "Headers.iterator" {
386 try h.append("cookie", "somevalue", null);374 try h.append("cookie", "somevalue", null);
387375
388 var count: i32 = 0;376 var count: i32 = 0;
389 var it = h.iterator();377 for (h.toSlice()) |e| {
390 while (it.next()) |e| {
391 if (count == 0) {378 if (count == 0) {
392 testing.expectEqualSlices(u8, "foo", e.name);379 testing.expectEqualSlices(u8, "foo", e.name);
393 testing.expectEqualSlices(u8, "bar", e.value);380 testing.expectEqualSlices(u8, "bar", e.value);
...@@ -420,10 +407,10 @@ test "Headers.delete" {...@@ -420,10 +407,10 @@ test "Headers.delete" {
420 try h.append("cookie", "somevalue", null);407 try h.append("cookie", "somevalue", null);
421408
422 testing.expectEqual(false, h.delete("not-present"));409 testing.expectEqual(false, h.delete("not-present"));
423 testing.expectEqual(@as(usize, 3), h.count());410 testing.expectEqual(@as(usize, 3), h.toSlice().len);
424411
425 testing.expectEqual(true, h.delete("foo"));412 testing.expectEqual(true, h.delete("foo"));
426 testing.expectEqual(@as(usize, 2), h.count());413 testing.expectEqual(@as(usize, 2), h.toSlice().len);
427 {414 {
428 const e = h.at(0);415 const e = h.at(0);
429 testing.expectEqualSlices(u8, "baz", e.name);416 testing.expectEqualSlices(u8, "baz", e.name);
...@@ -448,7 +435,7 @@ test "Headers.orderedRemove" {...@@ -448,7 +435,7 @@ test "Headers.orderedRemove" {
448 try h.append("cookie", "somevalue", null);435 try h.append("cookie", "somevalue", null);
449436
450 h.orderedRemove(0);437 h.orderedRemove(0);
451 testing.expectEqual(@as(usize, 2), h.count());438 testing.expectEqual(@as(usize, 2), h.toSlice().len);
452 {439 {
453 const e = h.at(0);440 const e = h.at(0);
454 testing.expectEqualSlices(u8, "baz", e.name);441 testing.expectEqualSlices(u8, "baz", e.name);
...@@ -471,7 +458,7 @@ test "Headers.swapRemove" {...@@ -471,7 +458,7 @@ test "Headers.swapRemove" {
471 try h.append("cookie", "somevalue", null);458 try h.append("cookie", "somevalue", null);
472459
473 h.swapRemove(0);460 h.swapRemove(0);
474 testing.expectEqual(@as(usize, 2), h.count());461 testing.expectEqual(@as(usize, 2), h.toSlice().len);
475 {462 {
476 const e = h.at(0);463 const e = h.at(0);
477 testing.expectEqualSlices(u8, "cookie", e.name);464 testing.expectEqualSlices(u8, "cookie", e.name);