authorgravatar for nathan@nmichaels.orgNathan Michaels <nathan@nmichaels.org> 2019-10-28 03:57:23-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-28 03:57:23-04:00
log6fdeaac338f3a4a1f3455653ce29bf6ce4bbe335
tree97f799cf30331a81e8fe5b2a6fe9ac5bb7de8542
parent8af6c7e34ceebde898d32bb50aaee5faac538af2

Add some documentation for standard library things. (#3540)

* Add some documentation for standard library things. Added a bunch of descriptions for array_list. Added some usage notes for failing_allocator. Documented some of mem.Allocator.

3 files changed, 59 insertions(+), 0 deletions(-)

lib/std/array_list.zig+33
...@@ -5,6 +5,10 @@ const testing = std.testing;...@@ -5,6 +5,10 @@ const testing = std.testing;
5const mem = std.mem;5const mem = std.mem;
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
77
8/// List of items.
9///
10/// This is a wrapper around an array of T values. Initialize with
11/// `init`.
8pub fn ArrayList(comptime T: type) type {12pub fn ArrayList(comptime T: type) type {
9 return AlignedArrayList(T, null);13 return AlignedArrayList(T, null);
10}14}
...@@ -37,18 +41,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -37,18 +41,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
37 };41 };
38 }42 }
3943
44 /// Release all allocated memory.
40 pub fn deinit(self: Self) void {45 pub fn deinit(self: Self) void {
41 self.allocator.free(self.items);46 self.allocator.free(self.items);
42 }47 }
4348
49 /// Return contents as a slice. Only valid while the list
50 /// doesn't change size.
44 pub fn toSlice(self: Self) Slice {51 pub fn toSlice(self: Self) Slice {
45 return self.items[0..self.len];52 return self.items[0..self.len];
46 }53 }
4754
55 /// Return list as const slice. Only valid while the list
56 /// doesn't change size.
48 pub fn toSliceConst(self: Self) SliceConst {57 pub fn toSliceConst(self: Self) SliceConst {
49 return self.items[0..self.len];58 return self.items[0..self.len];
50 }59 }
5160
61 /// Safely access index i of the list.
52 pub fn at(self: Self, i: usize) T {62 pub fn at(self: Self, i: usize) T {
53 return self.toSliceConst()[i];63 return self.toSliceConst()[i];
54 }64 }
...@@ -66,10 +76,13 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -66,10 +76,13 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
66 self.items[i] = item;76 self.items[i] = item;
67 }77 }
6878
79 /// Return length of the list.
69 pub fn count(self: Self) usize {80 pub fn count(self: Self) usize {
70 return self.len;81 return self.len;
71 }82 }
7283
84 /// Return the maximum number of items the list can hold
85 /// without allocating more memory.
73 pub fn capacity(self: Self) usize {86 pub fn capacity(self: Self) usize {
74 return self.items.len;87 return self.items.len;
75 }88 }
...@@ -93,6 +106,8 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -93,6 +106,8 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
93 return result;106 return result;
94 }107 }
95108
109 /// Insert `item` at index `n`. Moves `list[n .. list.count()]`
110 /// to make room.
96 pub fn insert(self: *Self, n: usize, item: T) !void {111 pub fn insert(self: *Self, n: usize, item: T) !void {
97 try self.ensureCapacity(self.len + 1);112 try self.ensureCapacity(self.len + 1);
98 self.len += 1;113 self.len += 1;
...@@ -101,6 +116,8 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -101,6 +116,8 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
101 self.items[n] = item;116 self.items[n] = item;
102 }117 }
103118
119 /// Insert slice `items` at index `n`. Moves
120 /// `list[n .. list.count()]` to make room.
104 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {121 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
105 try self.ensureCapacity(self.len + items.len);122 try self.ensureCapacity(self.len + items.len);
106 self.len += items.len;123 self.len += items.len;
...@@ -109,16 +126,22 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -109,16 +126,22 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
109 mem.copy(T, self.items[n .. n + items.len], items);126 mem.copy(T, self.items[n .. n + items.len], items);
110 }127 }
111128
129 /// Extend the list by 1 element. Allocates more memory as
130 /// necessary.
112 pub fn append(self: *Self, item: T) !void {131 pub fn append(self: *Self, item: T) !void {
113 const new_item_ptr = try self.addOne();132 const new_item_ptr = try self.addOne();
114 new_item_ptr.* = item;133 new_item_ptr.* = item;
115 }134 }
116135
136 /// Extend the list by 1 element, but asserting `self.capacity`
137 /// is sufficient to hold an additional item.
117 pub fn appendAssumeCapacity(self: *Self, item: T) void {138 pub fn appendAssumeCapacity(self: *Self, item: T) void {
118 const new_item_ptr = self.addOneAssumeCapacity();139 const new_item_ptr = self.addOneAssumeCapacity();
119 new_item_ptr.* = item;140 new_item_ptr.* = item;
120 }141 }
121142
143 /// Remove the element at index `i` from the list and return
144 /// its value. Asserts the array has at least one item.
122 pub fn orderedRemove(self: *Self, i: usize) T {145 pub fn orderedRemove(self: *Self, i: usize) T {
123 const newlen = self.len - 1;146 const newlen = self.len - 1;
124 if (newlen == i) return self.pop();147 if (newlen == i) return self.pop();
...@@ -149,17 +172,22 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -149,17 +172,22 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
149 return self.swapRemove(i);172 return self.swapRemove(i);
150 }173 }
151174
175 /// Append the slice of items to the list. Allocates more
176 /// memory as necessary.
152 pub fn appendSlice(self: *Self, items: SliceConst) !void {177 pub fn appendSlice(self: *Self, items: SliceConst) !void {
153 try self.ensureCapacity(self.len + items.len);178 try self.ensureCapacity(self.len + items.len);
154 mem.copy(T, self.items[self.len..], items);179 mem.copy(T, self.items[self.len..], items);
155 self.len += items.len;180 self.len += items.len;
156 }181 }
157182
183 /// Adjust the list's length to `new_len`. Doesn't initialize
184 /// added items if any.
158 pub fn resize(self: *Self, new_len: usize) !void {185 pub fn resize(self: *Self, new_len: usize) !void {
159 try self.ensureCapacity(new_len);186 try self.ensureCapacity(new_len);
160 self.len = new_len;187 self.len = new_len;
161 }188 }
162189
190 /// Reduce allocated capacity to `new_len`.
163 pub fn shrink(self: *Self, new_len: usize) void {191 pub fn shrink(self: *Self, new_len: usize) void {
164 assert(new_len <= self.len);192 assert(new_len <= self.len);
165 self.len = new_len;193 self.len = new_len;
...@@ -178,6 +206,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -178,6 +206,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
178 self.items = try self.allocator.realloc(self.items, better_capacity);206 self.items = try self.allocator.realloc(self.items, better_capacity);
179 }207 }
180208
209 /// Increase length by 1, returning pointer to the new item.
181 pub fn addOne(self: *Self) !*T {210 pub fn addOne(self: *Self) !*T {
182 const new_length = self.len + 1;211 const new_length = self.len + 1;
183 try self.ensureCapacity(new_length);212 try self.ensureCapacity(new_length);
...@@ -191,11 +220,14 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -191,11 +220,14 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
191 return result;220 return result;
192 }221 }
193222
223 /// Remove and return the last element from the list. Asserts
224 /// the list has at least one item.
194 pub fn pop(self: *Self) T {225 pub fn pop(self: *Self) T {
195 self.len -= 1;226 self.len -= 1;
196 return self.items[self.len];227 return self.items[self.len];
197 }228 }
198229
230 /// Like `pop` but returns `null` if empty.
199 pub fn popOrNull(self: *Self) ?T {231 pub fn popOrNull(self: *Self) ?T {
200 if (self.len == 0) return null;232 if (self.len == 0) return null;
201 return self.pop();233 return self.pop();
...@@ -218,6 +250,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {...@@ -218,6 +250,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
218 }250 }
219 };251 };
220252
253 /// Return an iterator over the list.
221 pub fn iterator(self: *const Self) Iterator {254 pub fn iterator(self: *const Self) Iterator {
222 return Iterator{255 return Iterator{
223 .list = self,256 .list = self,
lib/std/debug/failing_allocator.zig+16
...@@ -3,6 +3,14 @@ const mem = std.mem;...@@ -3,6 +3,14 @@ const mem = std.mem;
33
4/// Allocator that fails after N allocations, useful for making sure out of4/// Allocator that fails after N allocations, useful for making sure out of
5/// memory conditions are handled correctly.5/// memory conditions are handled correctly.
6///
7/// To use this, first initialize it and get an allocator with
8///
9/// `const failing_allocator = &FailingAllocator.init(<allocator>,
10/// <fail_index>).allocator;`
11///
12/// Then use `failing_allocator` anywhere you would have used a
13/// different allocator.
6pub const FailingAllocator = struct {14pub const FailingAllocator = struct {
7 allocator: mem.Allocator,15 allocator: mem.Allocator,
8 index: usize,16 index: usize,
...@@ -13,6 +21,14 @@ pub const FailingAllocator = struct {...@@ -13,6 +21,14 @@ pub const FailingAllocator = struct {
13 allocations: usize,21 allocations: usize,
14 deallocations: usize,22 deallocations: usize,
1523
24 /// `fail_index` is the number of successful allocations you can
25 /// expect from this allocator. The next allocation will fail.
26 /// For example, if this is called with `fail_index` equal to 2,
27 /// the following test will pass:
28 ///
29 /// var a = try failing_alloc.create(i32);
30 /// var b = try failing_alloc.create(i32);
31 /// testing.expectError(error.OutOfMemory, failing_alloc.create(i32));
16 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {32 pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
17 return FailingAllocator{33 return FailingAllocator{
18 .internal_allocator = allocator,34 .internal_allocator = allocator,
lib/std/mem.zig+10
...@@ -93,6 +93,14 @@ pub const Allocator = struct {...@@ -93,6 +93,14 @@ pub const Allocator = struct {
93 assert(shrink_result.len == 0);93 assert(shrink_result.len == 0);
94 }94 }
9595
96 /// Allocates an array of `n` items of type `T` and sets all the
97 /// items to `undefined`. Depending on the Allocator
98 /// implementation, it may be required to call `free` once the
99 /// memory is no longer needed, to avoid a resource leak. If the
100 /// `Allocator` implementation is unknown, then correct code will
101 /// call `free` when done.
102 ///
103 /// For allocating a single item, see `create`.
96 pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T {104 pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T {
97 return self.alignedAlloc(T, null, n);105 return self.alignedAlloc(T, null, n);
98 }106 }
...@@ -218,6 +226,8 @@ pub const Allocator = struct {...@@ -218,6 +226,8 @@ pub const Allocator = struct {
218 return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));226 return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
219 }227 }
220228
229 /// Free an array allocated with `alloc`. To free a single item,
230 /// see `destroy`.
221 pub fn free(self: *Allocator, memory: var) void {231 pub fn free(self: *Allocator, memory: var) void {
222 const Slice = @typeInfo(@typeOf(memory)).Pointer;232 const Slice = @typeInfo(@typeOf(memory)).Pointer;
223 const bytes = @sliceToBytes(memory);233 const bytes = @sliceToBytes(memory);