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
signaturelock-open 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 {
8484 self.items[i] = item;
8585 }
8686
87 /// Return length of the list.
88 pub fn count(self: Self) usize {
89 return self.len;
90 }
91
9287 /// Return the maximum number of items the list can hold
9388 /// without allocating more memory.
9489 pub fn capacity(self: Self) usize {
......@@ -114,7 +109,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
114109 return result;
115110 }
116111
117 /// Insert `item` at index `n`. Moves `list[n .. list.count()]`
112 /// Insert `item` at index `n`. Moves `list[n .. list.len]`
118113 /// to make room.
119114 pub fn insert(self: *Self, n: usize, item: T) !void {
120115 try self.ensureCapacity(self.len + 1);
......@@ -125,7 +120,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
125120 }
126121
127122 /// Insert slice `items` at index `n`. Moves
128 /// `list[n .. list.count()]` to make room.
123 /// `list[n .. list.len]` to make room.
129124 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
130125 try self.ensureCapacity(self.len + items.len);
131126 self.len += items.len;
......@@ -222,7 +217,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
222217 }
223218
224219 pub fn addOneAssumeCapacity(self: *Self) *T {
225 assert(self.count() < self.capacity());
220 assert(self.len < self.capacity());
226221 const result = &self.items[self.len];
227222 self.len += 1;
228223 return result;
......@@ -240,31 +235,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
240235 if (self.len == 0) return null;
241236 return self.pop();
242237 }
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 }
268238 };
269239}
270240
......@@ -275,7 +245,7 @@ test "std.ArrayList.init" {
275245 var list = ArrayList(i32).init(allocator);
276246 defer list.deinit();
277247
278 testing.expect(list.count() == 0);
248 testing.expect(list.len == 0);
279249 testing.expect(list.capacity() == 0);
280250}
281251
......@@ -284,7 +254,7 @@ test "std.ArrayList.initCapacity" {
284254 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
285255 var list = try ArrayList(i8).initCapacity(allocator, 200);
286256 defer list.deinit();
287 testing.expect(list.count() == 0);
257 testing.expect(list.len == 0);
288258 testing.expect(list.capacity() >= 200);
289259}
290260
......@@ -426,35 +396,6 @@ test "std.ArrayList.swapRemoveOrError" {
426396 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
427397}
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
458399test "std.ArrayList.insert" {
459400 var list = ArrayList(i32).init(debug.global_allocator);
460401 defer list.deinit();
lib/std/http/headers.zig+26-39
......@@ -133,8 +133,7 @@ pub const Headers = struct {
133133 self.index.deinit();
134134 }
135135 {
136 var it = self.data.iterator();
137 while (it.next()) |entry| {
136 for (self.data.toSliceConst()) |entry| {
138137 entry.deinit();
139138 }
140139 self.data.deinit();
......@@ -144,27 +143,20 @@ pub const Headers = struct {
144143 pub fn clone(self: Self, allocator: *Allocator) !Self {
145144 var other = Headers.init(allocator);
146145 errdefer other.deinit();
147 try other.data.ensureCapacity(self.data.count());
146 try other.data.ensureCapacity(self.data.len);
148147 try other.index.initCapacity(self.index.entries.len);
149 var it = self.data.iterator();
150 while (it.next()) |entry| {
148 for (self.data.toSliceConst()) |entry| {
151149 try other.append(entry.name, entry.value, entry.never_index);
152150 }
153151 return other;
154152 }
155153
156 pub fn count(self: Self) usize {
157 return self.data.count();
158 }
159
160 pub const Iterator = HeaderList.Iterator;
161
162 pub fn iterator(self: Self) Iterator {
163 return self.data.iterator();
154 pub fn toSlice(self: Self) []const HeaderEntry {
155 return self.data.toSliceConst();
164156 }
165157
166158 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;
168160 try self.data.ensureCapacity(n);
169161 var entry: HeaderEntry = undefined;
170162 if (self.index.get(name)) |kv| {
......@@ -190,7 +182,7 @@ pub const Headers = struct {
190182 pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
191183 if (self.index.get(name)) |kv| {
192184 const dex = kv.value;
193 if (dex.count() != 1)
185 if (dex.len != 1)
194186 return error.CannotUpsertMultiValuedField;
195187 var e = &self.data.at(dex.at(0));
196188 try e.modify(value, never_index);
......@@ -209,7 +201,7 @@ pub const Headers = struct {
209201 if (self.index.remove(name)) |kv| {
210202 var dex = &kv.value;
211203 // iterate backwards
212 var i = dex.count();
204 var i = dex.len;
213205 while (i > 0) {
214206 i -= 1;
215207 const data_index = dex.at(i);
......@@ -232,18 +224,18 @@ pub const Headers = struct {
232224 const removed = self.data.orderedRemove(i);
233225 const kv = self.index.get(removed.name).?;
234226 var dex = &kv.value;
235 if (dex.count() == 1) {
227 if (dex.len == 1) {
236228 // was last item; delete the index
237229 _ = self.index.remove(kv.key);
238230 dex.deinit();
239231 removed.deinit();
240232 self.allocator.free(kv.key);
241233 } else {
242 dex.shrink(dex.count() - 1);
234 dex.shrink(dex.len - 1);
243235 removed.deinit();
244236 }
245237 // if it was the last item; no need to rebuild index
246 if (i != self.data.count()) {
238 if (i != self.data.len) {
247239 self.rebuild_index();
248240 }
249241 }
......@@ -254,18 +246,18 @@ pub const Headers = struct {
254246 const removed = self.data.swapRemove(i);
255247 const kv = self.index.get(removed.name).?;
256248 var dex = &kv.value;
257 if (dex.count() == 1) {
249 if (dex.len == 1) {
258250 // was last item; delete the index
259251 _ = self.index.remove(kv.key);
260252 dex.deinit();
261253 removed.deinit();
262254 self.allocator.free(kv.key);
263255 } else {
264 dex.shrink(dex.count() - 1);
256 dex.shrink(dex.len - 1);
265257 removed.deinit();
266258 }
267259 // if it was the last item; no need to rebuild index
268 if (i != self.data.count()) {
260 if (i != self.data.len) {
269261 self.rebuild_index();
270262 }
271263 }
......@@ -289,10 +281,9 @@ pub const Headers = struct {
289281 pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {
290282 const dex = self.getIndices(name) orelse return null;
291283
292 const buf = try allocator.alloc(HeaderEntry, dex.count());
293 var it = dex.iterator();
284 const buf = try allocator.alloc(HeaderEntry, dex.len);
294285 var n: usize = 0;
295 while (it.next()) |idx| {
286 for (dex.toSliceConst()) |idx| {
296287 buf[n] = self.data.at(idx);
297288 n += 1;
298289 }
......@@ -314,9 +305,8 @@ pub const Headers = struct {
314305
315306 // adapted from mem.join
316307 const total_len = blk: {
317 var sum: usize = dex.count() - 1; // space for separator(s)
318 var it = dex.iterator();
319 while (it.next()) |idx|
308 var sum: usize = dex.len - 1; // space for separator(s)
309 for (dex.toSliceConst()) |idx|
320310 sum += self.data.at(idx).value.len;
321311 break :blk sum;
322312 };
......@@ -348,10 +338,9 @@ pub const Headers = struct {
348338 }
349339 }
350340 { // fill up indexes again; we know capacity is fine from before
351 var it = self.data.iterator();
352 while (it.next()) |entry| {
341 for (self.data.toSliceConst()) |entry, i| {
353342 var dex = &self.index.get(entry.name).?.value;
354 dex.appendAssumeCapacity(it.count);
343 dex.appendAssumeCapacity(i);
355344 }
356345 }
357346 }
......@@ -369,8 +358,7 @@ pub const Headers = struct {
369358 comptime Errors: type,
370359 output: fn (@TypeOf(context), []const u8) Errors!void,
371360 ) Errors!void {
372 var it = self.iterator();
373 while (it.next()) |entry| {
361 for (self.toSlice()) |entry| {
374362 try output(context, entry.name);
375363 try output(context, ": ");
376364 try output(context, entry.value);
......@@ -386,8 +374,7 @@ test "Headers.iterator" {
386374 try h.append("cookie", "somevalue", null);
387375
388376 var count: i32 = 0;
389 var it = h.iterator();
390 while (it.next()) |e| {
377 for (h.toSlice()) |e| {
391378 if (count == 0) {
392379 testing.expectEqualSlices(u8, "foo", e.name);
393380 testing.expectEqualSlices(u8, "bar", e.value);
......@@ -420,10 +407,10 @@ test "Headers.delete" {
420407 try h.append("cookie", "somevalue", null);
421408
422409 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
425412 testing.expectEqual(true, h.delete("foo"));
426 testing.expectEqual(@as(usize, 2), h.count());
413 testing.expectEqual(@as(usize, 2), h.toSlice().len);
427414 {
428415 const e = h.at(0);
429416 testing.expectEqualSlices(u8, "baz", e.name);
......@@ -448,7 +435,7 @@ test "Headers.orderedRemove" {
448435 try h.append("cookie", "somevalue", null);
449436
450437 h.orderedRemove(0);
451 testing.expectEqual(@as(usize, 2), h.count());
438 testing.expectEqual(@as(usize, 2), h.toSlice().len);
452439 {
453440 const e = h.at(0);
454441 testing.expectEqualSlices(u8, "baz", e.name);
......@@ -471,7 +458,7 @@ test "Headers.swapRemove" {
471458 try h.append("cookie", "somevalue", null);
472459
473460 h.swapRemove(0);
474 testing.expectEqual(@as(usize, 2), h.count());
461 testing.expectEqual(@as(usize, 2), h.toSlice().len);
475462 {
476463 const e = h.at(0);
477464 testing.expectEqualSlices(u8, "cookie", e.name);