authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-12 21:46:26+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-07-12 21:46:26+00:00
log7adbc1140373548f2985c8054b540cc5648f6857
treeff339ae921cbeae3a2225fc45306f4355daad80c
parent873e187f05400a8cb515f31896ce3ca11a377ac8
parent91235b937195910076a87cbb9ecbc6c5214ddd3b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5857 from daurnimator/use-unmanaged

Use unmanaged datastructures from std.http.headers

3 files changed, 50 insertions(+), 47 deletions(-)

lib/std/hash_map.zig+4
......@@ -24,6 +24,10 @@ pub fn StringHashMap(comptime V: type) type {
2424 return HashMap([]const u8, V, hashString, eqlString, true);
2525}
2626
27pub fn StringHashMapUnmanaged(comptime V: type) type {
28 return HashMapUnmanaged([]const u8, V, hashString, eqlString, true);
29}
30
2731pub fn eqlString(a: []const u8, b: []const u8) bool {
2832 return mem.eql(u8, a, b);
2933}
lib/std/http/headers.zig+45-47
......@@ -27,7 +27,6 @@ fn never_index_default(name: []const u8) bool {
2727}
2828
2929const HeaderEntry = struct {
30 allocator: *Allocator,
3130 name: []const u8,
3231 value: []u8,
3332 never_index: bool,
......@@ -36,23 +35,22 @@ const HeaderEntry = struct {
3635
3736 fn init(allocator: *Allocator, name: []const u8, value: []const u8, never_index: ?bool) !Self {
3837 return Self{
39 .allocator = allocator,
4038 .name = name, // takes reference
4139 .value = try allocator.dupe(u8, value),
4240 .never_index = never_index orelse never_index_default(name),
4341 };
4442 }
4543
46 fn deinit(self: Self) void {
47 self.allocator.free(self.value);
44 fn deinit(self: Self, allocator: *Allocator) void {
45 allocator.free(self.value);
4846 }
4947
50 pub fn modify(self: *Self, value: []const u8, never_index: ?bool) !void {
48 pub fn modify(self: *Self, allocator: *Allocator, value: []const u8, never_index: ?bool) !void {
5149 const old_len = self.value.len;
5250 if (value.len > old_len) {
53 self.value = try self.allocator.realloc(self.value, value.len);
51 self.value = try allocator.realloc(self.value, value.len);
5452 } else if (value.len < old_len) {
55 self.value = self.allocator.shrink(self.value, value.len);
53 self.value = allocator.shrink(self.value, value.len);
5654 }
5755 mem.copy(u8, self.value, value);
5856 self.never_index = never_index orelse never_index_default(self.name);
......@@ -85,22 +83,22 @@ const HeaderEntry = struct {
8583
8684test "HeaderEntry" {
8785 var e = try HeaderEntry.init(testing.allocator, "foo", "bar", null);
88 defer e.deinit();
86 defer e.deinit(testing.allocator);
8987 testing.expectEqualSlices(u8, "foo", e.name);
9088 testing.expectEqualSlices(u8, "bar", e.value);
9189 testing.expectEqual(false, e.never_index);
9290
93 try e.modify("longer value", null);
91 try e.modify(testing.allocator, "longer value", null);
9492 testing.expectEqualSlices(u8, "longer value", e.value);
9593
9694 // shorter value
97 try e.modify("x", null);
95 try e.modify(testing.allocator, "x", null);
9896 testing.expectEqualSlices(u8, "x", e.value);
9997}
10098
101const HeaderList = std.ArrayList(HeaderEntry);
102const HeaderIndexList = std.ArrayList(usize);
103const HeaderIndex = std.StringHashMap(HeaderIndexList);
99const HeaderList = std.ArrayListUnmanaged(HeaderEntry);
100const HeaderIndexList = std.ArrayListUnmanaged(usize);
101const HeaderIndex = std.StringHashMapUnmanaged(HeaderIndexList);
104102
105103pub const Headers = struct {
106104 // the owned header field name is stored in the index as part of the key
......@@ -113,8 +111,8 @@ pub const Headers = struct {
113111 pub fn init(allocator: *Allocator) Self {
114112 return Self{
115113 .allocator = allocator,
116 .data = HeaderList.init(allocator),
117 .index = HeaderIndex.init(allocator),
114 .data = HeaderList{},
115 .index = HeaderIndex{},
118116 };
119117 }
120118
......@@ -122,16 +120,16 @@ pub const Headers = struct {
122120 {
123121 for (self.index.items()) |*entry| {
124122 const dex = &entry.value;
125 dex.deinit();
123 dex.deinit(self.allocator);
126124 self.allocator.free(entry.key);
127125 }
128 self.index.deinit();
126 self.index.deinit(self.allocator);
129127 }
130128 {
131 for (self.data.span()) |entry| {
132 entry.deinit();
129 for (self.data.items) |entry| {
130 entry.deinit(self.allocator);
133131 }
134 self.data.deinit();
132 self.data.deinit(self.allocator);
135133 }
136134 self.* = undefined;
137135 }
......@@ -139,36 +137,36 @@ pub const Headers = struct {
139137 pub fn clone(self: Self, allocator: *Allocator) !Self {
140138 var other = Headers.init(allocator);
141139 errdefer other.deinit();
142 try other.data.ensureCapacity(self.data.items.len);
143 try other.index.initCapacity(self.index.entries.len);
144 for (self.data.span()) |entry| {
140 try other.data.ensureCapacity(allocator, self.data.items.len);
141 try other.index.initCapacity(allocator, self.index.entries.len);
142 for (self.data.items) |entry| {
145143 try other.append(entry.name, entry.value, entry.never_index);
146144 }
147145 return other;
148146 }
149147
150148 pub fn toSlice(self: Self) []const HeaderEntry {
151 return self.data.span();
149 return self.data.items;
152150 }
153151
154152 pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
155153 const n = self.data.items.len + 1;
156 try self.data.ensureCapacity(n);
154 try self.data.ensureCapacity(self.allocator, n);
157155 var entry: HeaderEntry = undefined;
158156 if (self.index.getEntry(name)) |kv| {
159157 entry = try HeaderEntry.init(self.allocator, kv.key, value, never_index);
160 errdefer entry.deinit();
158 errdefer entry.deinit(self.allocator);
161159 const dex = &kv.value;
162 try dex.append(n - 1);
160 try dex.append(self.allocator, n - 1);
163161 } else {
164162 const name_dup = try self.allocator.dupe(u8, name);
165163 errdefer self.allocator.free(name_dup);
166164 entry = try HeaderEntry.init(self.allocator, name_dup, value, never_index);
167 errdefer entry.deinit();
168 var dex = HeaderIndexList.init(self.allocator);
169 try dex.append(n - 1);
170 errdefer dex.deinit();
171 _ = try self.index.put(name_dup, dex);
165 errdefer entry.deinit(self.allocator);
166 var dex = HeaderIndexList{};
167 try dex.append(self.allocator, n - 1);
168 errdefer dex.deinit(self.allocator);
169 _ = try self.index.put(self.allocator, name_dup, dex);
172170 }
173171 self.data.appendAssumeCapacity(entry);
174172 }
......@@ -194,7 +192,7 @@ pub const Headers = struct {
194192
195193 /// Returns boolean indicating if something was deleted.
196194 pub fn delete(self: *Self, name: []const u8) bool {
197 if (self.index.remove(name)) |kv| {
195 if (self.index.remove(name)) |*kv| {
198196 const dex = &kv.value;
199197 // iterate backwards
200198 var i = dex.items.len;
......@@ -203,9 +201,9 @@ pub const Headers = struct {
203201 const data_index = dex.items[i];
204202 const removed = self.data.orderedRemove(data_index);
205203 assert(mem.eql(u8, removed.name, name));
206 removed.deinit();
204 removed.deinit(self.allocator);
207205 }
208 dex.deinit();
206 dex.deinit(self.allocator);
209207 self.allocator.free(kv.key);
210208 self.rebuildIndex();
211209 return true;
......@@ -225,14 +223,14 @@ pub const Headers = struct {
225223 const dex = &kv.value;
226224 if (dex.items.len == 1) {
227225 // was last item; delete the index
228 dex.deinit();
229 removed.deinit();
226 dex.deinit(self.allocator);
227 removed.deinit(self.allocator);
230228 const key = kv.key;
231229 _ = self.index.remove(key); // invalidates `kv` and `dex`
232230 self.allocator.free(key);
233231 } else {
234 dex.shrink(dex.items.len - 1);
235 removed.deinit();
232 dex.shrink(self.allocator, dex.items.len - 1);
233 removed.deinit(self.allocator);
236234 }
237235 // if it was the last item; no need to rebuild index
238236 if (i != self.data.items.len) {
......@@ -250,14 +248,14 @@ pub const Headers = struct {
250248 const dex = &kv.value;
251249 if (dex.items.len == 1) {
252250 // was last item; delete the index
253 dex.deinit();
254 removed.deinit();
251 dex.deinit(self.allocator);
252 removed.deinit(self.allocator);
255253 const key = kv.key;
256254 _ = self.index.remove(key); // invalidates `kv` and `dex`
257255 self.allocator.free(key);
258256 } else {
259 dex.shrink(dex.items.len - 1);
260 removed.deinit();
257 dex.shrink(self.allocator, dex.items.len - 1);
258 removed.deinit(self.allocator);
261259 }
262260 // if it was the last item; no need to rebuild index
263261 if (i != self.data.items.len) {
......@@ -282,7 +280,7 @@ pub const Headers = struct {
282280
283281 const buf = try allocator.alloc(HeaderEntry, dex.items.len);
284282 var n: usize = 0;
285 for (dex.span()) |idx| {
283 for (dex.items) |idx| {
286284 buf[n] = self.data.items[idx];
287285 n += 1;
288286 }
......@@ -305,7 +303,7 @@ pub const Headers = struct {
305303 // adapted from mem.join
306304 const total_len = blk: {
307305 var sum: usize = dex.items.len - 1; // space for separator(s)
308 for (dex.span()) |idx|
306 for (dex.items) |idx|
309307 sum += self.data.items[idx].value.len;
310308 break :blk sum;
311309 };
......@@ -493,8 +491,8 @@ test "Headers.getIndices" {
493491 try h.append("set-cookie", "y=2", null);
494492
495493 testing.expect(null == h.getIndices("not-present"));
496 testing.expectEqualSlices(usize, &[_]usize{0}, h.getIndices("foo").?.span());
497 testing.expectEqualSlices(usize, &[_]usize{ 1, 2 }, h.getIndices("set-cookie").?.span());
494 testing.expectEqualSlices(usize, &[_]usize{0}, h.getIndices("foo").?.items);
495 testing.expectEqualSlices(usize, &[_]usize{ 1, 2 }, h.getIndices("set-cookie").?.items);
498496}
499497
500498test "Headers.get" {
lib/std/std.zig+1
......@@ -25,6 +25,7 @@ pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
2525pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;
2626pub const SpinLock = @import("spinlock.zig").SpinLock;
2727pub const StringHashMap = hash_map.StringHashMap;
28pub const StringHashMapUnmanaged = hash_map.StringHashMapUnmanaged;
2829pub const TailQueue = @import("linked_list.zig").TailQueue;
2930pub const Target = @import("target.zig").Target;
3031pub const Thread = @import("thread.zig").Thread;