authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-04 01:31:29+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-05 21:11:42+00:00
log632acffcbd96a085ea92899e6f37465e40178f44
tree77b4af87060b43172eefb66943564faed365ec84
parentb3b6ccba50ef7a683ad05546cba2b71e7d10489f

update std lib to new hash map API


8 files changed, 111 insertions(+), 108 deletions(-)

lib/std/buf_map.zig+7-8
...@@ -33,10 +33,10 @@ pub const BufMap = struct {...@@ -33,10 +33,10 @@ pub const BufMap = struct {
33 pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {33 pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
34 const get_or_put = try self.hash_map.getOrPut(key);34 const get_or_put = try self.hash_map.getOrPut(key);
35 if (get_or_put.found_existing) {35 if (get_or_put.found_existing) {
36 self.free(get_or_put.kv.key);36 self.free(get_or_put.entry.key);
37 get_or_put.kv.key = key;37 get_or_put.entry.key = key;
38 }38 }
39 get_or_put.kv.value = value;39 get_or_put.entry.value = value;
40 }40 }
4141
42 /// `key` and `value` are copied into the BufMap.42 /// `key` and `value` are copied into the BufMap.
...@@ -45,19 +45,18 @@ pub const BufMap = struct {...@@ -45,19 +45,18 @@ pub const BufMap = struct {
45 errdefer self.free(value_copy);45 errdefer self.free(value_copy);
46 const get_or_put = try self.hash_map.getOrPut(key);46 const get_or_put = try self.hash_map.getOrPut(key);
47 if (get_or_put.found_existing) {47 if (get_or_put.found_existing) {
48 self.free(get_or_put.kv.value);48 self.free(get_or_put.entry.value);
49 } else {49 } else {
50 get_or_put.kv.key = self.copy(key) catch |err| {50 get_or_put.entry.key = self.copy(key) catch |err| {
51 _ = self.hash_map.remove(key);51 _ = self.hash_map.remove(key);
52 return err;52 return err;
53 };53 };
54 }54 }
55 get_or_put.kv.value = value_copy;55 get_or_put.entry.value = value_copy;
56 }56 }
5757
58 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {58 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
59 const entry = self.hash_map.get(key) orelse return null;59 return self.hash_map.get(key);
60 return entry.value;
61 }60 }
6261
63 pub fn delete(self: *BufMap, key: []const u8) void {62 pub fn delete(self: *BufMap, key: []const u8) void {
lib/std/buf_set.zig+3-5
...@@ -14,14 +14,12 @@ pub const BufSet = struct {...@@ -14,14 +14,12 @@ pub const BufSet = struct {
14 return self;14 return self;
15 }15 }
1616
17 pub fn deinit(self: *const BufSet) void {17 pub fn deinit(self: *BufSet) void {
18 var it = self.hash_map.iterator();18 for (self.hash_map.items()) |entry| {
19 while (true) {
20 const entry = it.next() orelse break;
21 self.free(entry.key);19 self.free(entry.key);
22 }20 }
23
24 self.hash_map.deinit();21 self.hash_map.deinit();
22 self.* = undefined;
25 }23 }
2624
27 pub fn put(self: *BufSet, key: []const u8) !void {25 pub fn put(self: *BufSet, key: []const u8) !void {
lib/std/build.zig+6-6
...@@ -422,12 +422,12 @@ pub const Builder = struct {...@@ -422,12 +422,12 @@ pub const Builder = struct {
422 .type_id = type_id,422 .type_id = type_id,
423 .description = description,423 .description = description,
424 };424 };
425 if ((self.available_options_map.put(name, available_option) catch unreachable) != null) {425 if ((self.available_options_map.fetchPut(name, available_option) catch unreachable) != null) {
426 panic("Option '{}' declared twice", .{name});426 panic("Option '{}' declared twice", .{name});
427 }427 }
428 self.available_options_list.append(available_option) catch unreachable;428 self.available_options_list.append(available_option) catch unreachable;
429429
430 const entry = self.user_input_options.get(name) orelse return null;430 const entry = self.user_input_options.getEntry(name) orelse return null;
431 entry.value.used = true;431 entry.value.used = true;
432 switch (type_id) {432 switch (type_id) {
433 TypeId.Bool => switch (entry.value.value) {433 TypeId.Bool => switch (entry.value.value) {
...@@ -634,7 +634,7 @@ pub const Builder = struct {...@@ -634,7 +634,7 @@ pub const Builder = struct {
634 pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool {634 pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool {
635 const gop = try self.user_input_options.getOrPut(name);635 const gop = try self.user_input_options.getOrPut(name);
636 if (!gop.found_existing) {636 if (!gop.found_existing) {
637 gop.kv.value = UserInputOption{637 gop.entry.value = UserInputOption{
638 .name = name,638 .name = name,
639 .value = UserValue{ .Scalar = value },639 .value = UserValue{ .Scalar = value },
640 .used = false,640 .used = false,
...@@ -643,7 +643,7 @@ pub const Builder = struct {...@@ -643,7 +643,7 @@ pub const Builder = struct {
643 }643 }
644644
645 // option already exists645 // option already exists
646 switch (gop.kv.value.value) {646 switch (gop.entry.value.value) {
647 UserValue.Scalar => |s| {647 UserValue.Scalar => |s| {
648 // turn it into a list648 // turn it into a list
649 var list = ArrayList([]const u8).init(self.allocator);649 var list = ArrayList([]const u8).init(self.allocator);
...@@ -675,7 +675,7 @@ pub const Builder = struct {...@@ -675,7 +675,7 @@ pub const Builder = struct {
675 pub fn addUserInputFlag(self: *Builder, name: []const u8) !bool {675 pub fn addUserInputFlag(self: *Builder, name: []const u8) !bool {
676 const gop = try self.user_input_options.getOrPut(name);676 const gop = try self.user_input_options.getOrPut(name);
677 if (!gop.found_existing) {677 if (!gop.found_existing) {
678 gop.kv.value = UserInputOption{678 gop.entry.value = UserInputOption{
679 .name = name,679 .name = name,
680 .value = UserValue{ .Flag = {} },680 .value = UserValue{ .Flag = {} },
681 .used = false,681 .used = false,
...@@ -684,7 +684,7 @@ pub const Builder = struct {...@@ -684,7 +684,7 @@ pub const Builder = struct {
684 }684 }
685685
686 // option already exists686 // option already exists
687 switch (gop.kv.value.value) {687 switch (gop.entry.value.value) {
688 UserValue.Scalar => |s| {688 UserValue.Scalar => |s| {
689 warn("Flag '-D{}' conflicts with option '-D{}={}'.\n", .{ name, name, s });689 warn("Flag '-D{}' conflicts with option '-D{}={}'.\n", .{ name, name, s });
690 return true;690 return true;
lib/std/hash_map.zig+17-8
...@@ -293,18 +293,22 @@ pub fn HashMapUnmanaged(...@@ -293,18 +293,22 @@ pub fn HashMapUnmanaged(
293293
294 pub fn clearRetainingCapacity(self: *Self) void {294 pub fn clearRetainingCapacity(self: *Self) void {
295 self.entries.items.len = 0;295 self.entries.items.len = 0;
296 if (self.header) |header| {296 if (self.index_header) |header| {
297 header.max_distance_from_start_index = 0;297 header.max_distance_from_start_index = 0;
298 const indexes = header.indexes(u8);298 switch (header.capacityIndexType()) {
299 @memset(indexes.ptr, 0xff, indexes.len);299 .u8 => mem.set(Index(u8), header.indexes(u8), Index(u8).empty),
300 .u16 => mem.set(Index(u16), header.indexes(u16), Index(u16).empty),
301 .u32 => mem.set(Index(u32), header.indexes(u32), Index(u32).empty),
302 .usize => mem.set(Index(usize), header.indexes(usize), Index(usize).empty),
303 }
300 }304 }
301 }305 }
302306
303 pub fn clearAndFree(self: *Self, allocator: *Allocator) void {307 pub fn clearAndFree(self: *Self, allocator: *Allocator) void {
304 self.entries.shrink(allocator, 0);308 self.entries.shrink(allocator, 0);
305 if (self.header) |header| {309 if (self.index_header) |header| {
306 header.free(allocator);310 header.free(allocator);
307 self.header = null;311 self.index_header = null;
308 }312 }
309 }313 }
310314
...@@ -378,13 +382,13 @@ pub fn HashMapUnmanaged(...@@ -378,13 +382,13 @@ pub fn HashMapUnmanaged(
378 try self.entries.ensureCapacity(allocator, new_capacity);382 try self.entries.ensureCapacity(allocator, new_capacity);
379 if (new_capacity <= linear_scan_max) return;383 if (new_capacity <= linear_scan_max) return;
380384
381 // Resize if indexes would be more than 75% full.385 // Resize if indexes would be more than 60% full.
382 const needed_len = new_capacity * 4 / 3;386 const needed_len = new_capacity * 5 / 3;
383 if (self.index_header) |header| {387 if (self.index_header) |header| {
384 if (needed_len > header.indexes_len) {388 if (needed_len > header.indexes_len) {
385 var new_indexes_len = header.indexes_len;389 var new_indexes_len = header.indexes_len;
386 while (true) {390 while (true) {
387 new_indexes_len += new_indexes_len / 2 + 8;391 new_indexes_len *= new_indexes_len / 2 + 8;
388 if (new_indexes_len >= needed_len) break;392 if (new_indexes_len >= needed_len) break;
389 }393 }
390 const new_header = try IndexHeader.alloc(allocator, new_indexes_len);394 const new_header = try IndexHeader.alloc(allocator, new_indexes_len);
...@@ -789,6 +793,11 @@ fn Index(comptime I: type) type {...@@ -789,6 +793,11 @@ fn Index(comptime I: type) type {
789793
790 const Self = @This();794 const Self = @This();
791795
796 const empty = Self{
797 .entry_index = math.maxInt(I),
798 .distance_from_start_index = undefined,
799 };
800
792 fn isEmpty(idx: Self) bool {801 fn isEmpty(idx: Self) bool {
793 return idx.entry_index == math.maxInt(I);802 return idx.entry_index == math.maxInt(I);
794 }803 }
lib/std/http/headers.zig+35-37
...@@ -118,13 +118,12 @@ pub const Headers = struct {...@@ -118,13 +118,12 @@ pub const Headers = struct {
118 };118 };
119 }119 }
120120
121 pub fn deinit(self: Self) void {121 pub fn deinit(self: *Self) void {
122 {122 {
123 var it = self.index.iterator();123 for (self.index.items()) |*entry| {
124 while (it.next()) |kv| {124 const dex = &entry.value;
125 var dex = &kv.value;
126 dex.deinit();125 dex.deinit();
127 self.allocator.free(kv.key);126 self.allocator.free(entry.key);
128 }127 }
129 self.index.deinit();128 self.index.deinit();
130 }129 }
...@@ -134,6 +133,7 @@ pub const Headers = struct {...@@ -134,6 +133,7 @@ pub const Headers = struct {
134 }133 }
135 self.data.deinit();134 self.data.deinit();
136 }135 }
136 self.* = undefined;
137 }137 }
138138
139 pub fn clone(self: Self, allocator: *Allocator) !Self {139 pub fn clone(self: Self, allocator: *Allocator) !Self {
...@@ -155,10 +155,10 @@ pub const Headers = struct {...@@ -155,10 +155,10 @@ pub const Headers = struct {
155 const n = self.data.items.len + 1;155 const n = self.data.items.len + 1;
156 try self.data.ensureCapacity(n);156 try self.data.ensureCapacity(n);
157 var entry: HeaderEntry = undefined;157 var entry: HeaderEntry = undefined;
158 if (self.index.get(name)) |kv| {158 if (self.index.getEntry(name)) |kv| {
159 entry = try HeaderEntry.init(self.allocator, kv.key, value, never_index);159 entry = try HeaderEntry.init(self.allocator, kv.key, value, never_index);
160 errdefer entry.deinit();160 errdefer entry.deinit();
161 var dex = &kv.value;161 const dex = &kv.value;
162 try dex.append(n - 1);162 try dex.append(n - 1);
163 } else {163 } else {
164 const name_dup = try mem.dupe(self.allocator, u8, name);164 const name_dup = try mem.dupe(self.allocator, u8, name);
...@@ -195,7 +195,7 @@ pub const Headers = struct {...@@ -195,7 +195,7 @@ pub const Headers = struct {
195 /// Returns boolean indicating if something was deleted.195 /// Returns boolean indicating if something was deleted.
196 pub fn delete(self: *Self, name: []const u8) bool {196 pub fn delete(self: *Self, name: []const u8) bool {
197 if (self.index.remove(name)) |kv| {197 if (self.index.remove(name)) |kv| {
198 var dex = &kv.value;198 const dex = &kv.value;
199 // iterate backwards199 // iterate backwards
200 var i = dex.items.len;200 var i = dex.items.len;
201 while (i > 0) {201 while (i > 0) {
...@@ -207,7 +207,7 @@ pub const Headers = struct {...@@ -207,7 +207,7 @@ pub const Headers = struct {
207 }207 }
208 dex.deinit();208 dex.deinit();
209 self.allocator.free(kv.key);209 self.allocator.free(kv.key);
210 self.rebuild_index();210 self.rebuildIndex();
211 return true;211 return true;
212 } else {212 } else {
213 return false;213 return false;
...@@ -216,45 +216,52 @@ pub const Headers = struct {...@@ -216,45 +216,52 @@ pub const Headers = struct {
216216
217 /// Removes the element at the specified index.217 /// Removes the element at the specified index.
218 /// Moves items down to fill the empty space.218 /// Moves items down to fill the empty space.
219 /// TODO this implementation can be replaced by adding
220 /// orderedRemove to the new hash table implementation as an
221 /// alternative to swapRemove.
219 pub fn orderedRemove(self: *Self, i: usize) void {222 pub fn orderedRemove(self: *Self, i: usize) void {
220 const removed = self.data.orderedRemove(i);223 const removed = self.data.orderedRemove(i);
221 const kv = self.index.get(removed.name).?;224 const kv = self.index.getEntry(removed.name).?;
222 var dex = &kv.value;225 const dex = &kv.value;
223 if (dex.items.len == 1) {226 if (dex.items.len == 1) {
224 // was last item; delete the index227 // was last item; delete the index
225 _ = self.index.remove(kv.key);
226 dex.deinit();228 dex.deinit();
227 removed.deinit();229 removed.deinit();
228 self.allocator.free(kv.key);230 const key = kv.key;
231 _ = self.index.remove(key); // invalidates `kv` and `dex`
232 self.allocator.free(key);
229 } else {233 } else {
230 dex.shrink(dex.items.len - 1);234 dex.shrink(dex.items.len - 1);
231 removed.deinit();235 removed.deinit();
232 }236 }
233 // if it was the last item; no need to rebuild index237 // if it was the last item; no need to rebuild index
234 if (i != self.data.items.len) {238 if (i != self.data.items.len) {
235 self.rebuild_index();239 self.rebuildIndex();
236 }240 }
237 }241 }
238242
239 /// Removes the element at the specified index.243 /// Removes the element at the specified index.
240 /// The empty slot is filled from the end of the list.244 /// The empty slot is filled from the end of the list.
245 /// TODO this implementation can be replaced by simply using the
246 /// new hash table which does swap removal.
241 pub fn swapRemove(self: *Self, i: usize) void {247 pub fn swapRemove(self: *Self, i: usize) void {
242 const removed = self.data.swapRemove(i);248 const removed = self.data.swapRemove(i);
243 const kv = self.index.get(removed.name).?;249 const kv = self.index.getEntry(removed.name).?;
244 var dex = &kv.value;250 const dex = &kv.value;
245 if (dex.items.len == 1) {251 if (dex.items.len == 1) {
246 // was last item; delete the index252 // was last item; delete the index
247 _ = self.index.remove(kv.key);
248 dex.deinit();253 dex.deinit();
249 removed.deinit();254 removed.deinit();
250 self.allocator.free(kv.key);255 const key = kv.key;
256 _ = self.index.remove(key); // invalidates `kv` and `dex`
257 self.allocator.free(key);
251 } else {258 } else {
252 dex.shrink(dex.items.len - 1);259 dex.shrink(dex.items.len - 1);
253 removed.deinit();260 removed.deinit();
254 }261 }
255 // if it was the last item; no need to rebuild index262 // if it was the last item; no need to rebuild index
256 if (i != self.data.items.len) {263 if (i != self.data.items.len) {
257 self.rebuild_index();264 self.rebuildIndex();
258 }265 }
259 }266 }
260267
...@@ -266,11 +273,7 @@ pub const Headers = struct {...@@ -266,11 +273,7 @@ pub const Headers = struct {
266 /// Returns a list of indices containing headers with the given name.273 /// Returns a list of indices containing headers with the given name.
267 /// The returned list should not be modified by the caller.274 /// The returned list should not be modified by the caller.
268 pub fn getIndices(self: Self, name: []const u8) ?HeaderIndexList {275 pub fn getIndices(self: Self, name: []const u8) ?HeaderIndexList {
269 if (self.index.get(name)) |kv| {276 return self.index.get(name);
270 return kv.value;
271 } else {
272 return null;
273 }
274 }277 }
275278
276 /// Returns a slice containing each header with the given name.279 /// Returns a slice containing each header with the given name.
...@@ -325,25 +328,20 @@ pub const Headers = struct {...@@ -325,25 +328,20 @@ pub const Headers = struct {
325 return buf;328 return buf;
326 }329 }
327330
328 fn rebuild_index(self: *Self) void {331 fn rebuildIndex(self: *Self) void {
329 { // clear out the indexes332 // clear out the indexes
330 var it = self.index.iterator();333 for (self.index.items()) |*entry| {
331 while (it.next()) |kv| {334 entry.value.shrinkRetainingCapacity(0);
332 var dex = &kv.value;
333 dex.items.len = 0; // keeps capacity available
334 }
335 }335 }
336 { // fill up indexes again; we know capacity is fine from before336 // fill up indexes again; we know capacity is fine from before
337 for (self.data.span()) |entry, i| {337 for (self.data.items) |entry, i| {
338 var dex = &self.index.get(entry.name).?.value;338 self.index.getEntry(entry.name).?.value.appendAssumeCapacity(i);
339 dex.appendAssumeCapacity(i);
340 }
341 }339 }
342 }340 }
343341
344 pub fn sort(self: *Self) void {342 pub fn sort(self: *Self) void {
345 std.sort.sort(HeaderEntry, self.data.items, {}, HeaderEntry.compare);343 std.sort.sort(HeaderEntry, self.data.items, {}, HeaderEntry.compare);
346 self.rebuild_index();344 self.rebuildIndex();
347 }345 }
348346
349 pub fn format(347 pub fn format(
lib/std/json.zig+28-28
...@@ -2149,27 +2149,27 @@ test "json.parser.dynamic" {...@@ -2149,27 +2149,27 @@ test "json.parser.dynamic" {
21492149
2150 var root = tree.root;2150 var root = tree.root;
21512151
2152 var image = root.Object.get("Image").?.value;2152 var image = root.Object.get("Image").?;
21532153
2154 const width = image.Object.get("Width").?.value;2154 const width = image.Object.get("Width").?;
2155 testing.expect(width.Integer == 800);2155 testing.expect(width.Integer == 800);
21562156
2157 const height = image.Object.get("Height").?.value;2157 const height = image.Object.get("Height").?;
2158 testing.expect(height.Integer == 600);2158 testing.expect(height.Integer == 600);
21592159
2160 const title = image.Object.get("Title").?.value;2160 const title = image.Object.get("Title").?;
2161 testing.expect(mem.eql(u8, title.String, "View from 15th Floor"));2161 testing.expect(mem.eql(u8, title.String, "View from 15th Floor"));
21622162
2163 const animated = image.Object.get("Animated").?.value;2163 const animated = image.Object.get("Animated").?;
2164 testing.expect(animated.Bool == false);2164 testing.expect(animated.Bool == false);
21652165
2166 const array_of_object = image.Object.get("ArrayOfObject").?.value;2166 const array_of_object = image.Object.get("ArrayOfObject").?;
2167 testing.expect(array_of_object.Array.items.len == 1);2167 testing.expect(array_of_object.Array.items.len == 1);
21682168
2169 const obj0 = array_of_object.Array.items[0].Object.get("n").?.value;2169 const obj0 = array_of_object.Array.items[0].Object.get("n").?;
2170 testing.expect(mem.eql(u8, obj0.String, "m"));2170 testing.expect(mem.eql(u8, obj0.String, "m"));
21712171
2172 const double = image.Object.get("double").?.value;2172 const double = image.Object.get("double").?;
2173 testing.expect(double.Float == 1.3412);2173 testing.expect(double.Float == 1.3412);
2174}2174}
21752175
...@@ -2217,12 +2217,12 @@ test "write json then parse it" {...@@ -2217,12 +2217,12 @@ test "write json then parse it" {
2217 var tree = try parser.parse(fixed_buffer_stream.getWritten());2217 var tree = try parser.parse(fixed_buffer_stream.getWritten());
2218 defer tree.deinit();2218 defer tree.deinit();
22192219
2220 testing.expect(tree.root.Object.get("f").?.value.Bool == false);2220 testing.expect(tree.root.Object.get("f").?.Bool == false);
2221 testing.expect(tree.root.Object.get("t").?.value.Bool == true);2221 testing.expect(tree.root.Object.get("t").?.Bool == true);
2222 testing.expect(tree.root.Object.get("int").?.value.Integer == 1234);2222 testing.expect(tree.root.Object.get("int").?.Integer == 1234);
2223 testing.expect(tree.root.Object.get("array").?.value.Array.items[0].Null == {});2223 testing.expect(tree.root.Object.get("array").?.Array.items[0].Null == {});
2224 testing.expect(tree.root.Object.get("array").?.value.Array.items[1].Float == 12.34);2224 testing.expect(tree.root.Object.get("array").?.Array.items[1].Float == 12.34);
2225 testing.expect(mem.eql(u8, tree.root.Object.get("str").?.value.String, "hello"));2225 testing.expect(mem.eql(u8, tree.root.Object.get("str").?.String, "hello"));
2226}2226}
22272227
2228fn test_parse(arena_allocator: *std.mem.Allocator, json_str: []const u8) !Value {2228fn test_parse(arena_allocator: *std.mem.Allocator, json_str: []const u8) !Value {
...@@ -2245,7 +2245,7 @@ test "integer after float has proper type" {...@@ -2245,7 +2245,7 @@ test "integer after float has proper type" {
2245 \\ "ints": [1, 2, 3]2245 \\ "ints": [1, 2, 3]
2246 \\}2246 \\}
2247 );2247 );
2248 std.testing.expect(json.Object.getValue("ints").?.Array.items[0] == .Integer);2248 std.testing.expect(json.Object.get("ints").?.Array.items[0] == .Integer);
2249}2249}
22502250
2251test "escaped characters" {2251test "escaped characters" {
...@@ -2271,16 +2271,16 @@ test "escaped characters" {...@@ -2271,16 +2271,16 @@ test "escaped characters" {
22712271
2272 const obj = (try test_parse(&arena_allocator.allocator, input)).Object;2272 const obj = (try test_parse(&arena_allocator.allocator, input)).Object;
22732273
2274 testing.expectEqualSlices(u8, obj.get("backslash").?.value.String, "\\");2274 testing.expectEqualSlices(u8, obj.get("backslash").?.String, "\\");
2275 testing.expectEqualSlices(u8, obj.get("forwardslash").?.value.String, "/");2275 testing.expectEqualSlices(u8, obj.get("forwardslash").?.String, "/");
2276 testing.expectEqualSlices(u8, obj.get("newline").?.value.String, "\n");2276 testing.expectEqualSlices(u8, obj.get("newline").?.String, "\n");
2277 testing.expectEqualSlices(u8, obj.get("carriagereturn").?.value.String, "\r");2277 testing.expectEqualSlices(u8, obj.get("carriagereturn").?.String, "\r");
2278 testing.expectEqualSlices(u8, obj.get("tab").?.value.String, "\t");2278 testing.expectEqualSlices(u8, obj.get("tab").?.String, "\t");
2279 testing.expectEqualSlices(u8, obj.get("formfeed").?.value.String, "\x0C");2279 testing.expectEqualSlices(u8, obj.get("formfeed").?.String, "\x0C");
2280 testing.expectEqualSlices(u8, obj.get("backspace").?.value.String, "\x08");2280 testing.expectEqualSlices(u8, obj.get("backspace").?.String, "\x08");
2281 testing.expectEqualSlices(u8, obj.get("doublequote").?.value.String, "\"");2281 testing.expectEqualSlices(u8, obj.get("doublequote").?.String, "\"");
2282 testing.expectEqualSlices(u8, obj.get("unicode").?.value.String, "ą");2282 testing.expectEqualSlices(u8, obj.get("unicode").?.String, "ą");
2283 testing.expectEqualSlices(u8, obj.get("surrogatepair").?.value.String, "😂");2283 testing.expectEqualSlices(u8, obj.get("surrogatepair").?.String, "😂");
2284}2284}
22852285
2286test "string copy option" {2286test "string copy option" {
...@@ -2306,11 +2306,11 @@ test "string copy option" {...@@ -2306,11 +2306,11 @@ test "string copy option" {
2306 const obj_copy = tree_copy.root.Object;2306 const obj_copy = tree_copy.root.Object;
23072307
2308 for ([_][]const u8{ "noescape", "simple", "unicode", "surrogatepair" }) |field_name| {2308 for ([_][]const u8{ "noescape", "simple", "unicode", "surrogatepair" }) |field_name| {
2309 testing.expectEqualSlices(u8, obj_nocopy.getValue(field_name).?.String, obj_copy.getValue(field_name).?.String);2309 testing.expectEqualSlices(u8, obj_nocopy.get(field_name).?.String, obj_copy.get(field_name).?.String);
2310 }2310 }
23112311
2312 const nocopy_addr = &obj_nocopy.getValue("noescape").?.String[0];2312 const nocopy_addr = &obj_nocopy.get("noescape").?.String[0];
2313 const copy_addr = &obj_copy.getValue("noescape").?.String[0];2313 const copy_addr = &obj_copy.get("noescape").?.String[0];
23142314
2315 var found_nocopy = false;2315 var found_nocopy = false;
2316 for (input) |_, index| {2316 for (input) |_, index| {
src-self-hosted/main.zig+2-2
...@@ -720,7 +720,7 @@ fn fmtPathDir(...@@ -720,7 +720,7 @@ fn fmtPathDir(
720 defer dir.close();720 defer dir.close();
721721
722 const stat = try dir.stat();722 const stat = try dir.stat();
723 if (try fmt.seen.put(stat.inode, {})) |_| return;723 if (try fmt.seen.fetchPut(stat.inode, {})) |_| return;
724724
725 var dir_it = dir.iterate();725 var dir_it = dir.iterate();
726 while (try dir_it.next()) |entry| {726 while (try dir_it.next()) |entry| {
...@@ -768,7 +768,7 @@ fn fmtPathFile(...@@ -768,7 +768,7 @@ fn fmtPathFile(
768 defer fmt.gpa.free(source_code);768 defer fmt.gpa.free(source_code);
769769
770 // Add to set after no longer possible to get error.IsDir.770 // Add to set after no longer possible to get error.IsDir.
771 if (try fmt.seen.put(stat.inode, {})) |_| return;771 if (try fmt.seen.fetchPut(stat.inode, {})) |_| return;
772772
773 const tree = try std.zig.parse(fmt.gpa, source_code);773 const tree = try std.zig.parse(fmt.gpa, source_code);
774 defer tree.deinit();774 defer tree.deinit();
src-self-hosted/translate_c.zig+13-14
...@@ -20,7 +20,7 @@ pub const Error = error{OutOfMemory};...@@ -20,7 +20,7 @@ pub const Error = error{OutOfMemory};
20const TypeError = Error || error{UnsupportedType};20const TypeError = Error || error{UnsupportedType};
21const TransError = TypeError || error{UnsupportedTranslation};21const TransError = TypeError || error{UnsupportedTranslation};
2222
23const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql);23const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql, false);
2424
25fn addrHash(x: usize) u32 {25fn addrHash(x: usize) u32 {
26 switch (@typeInfo(usize).Int.bits) {26 switch (@typeInfo(usize).Int.bits) {
...@@ -776,8 +776,8 @@ fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 {...@@ -776,8 +776,8 @@ fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 {
776}776}
777777
778fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node {778fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node {
779 if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv|779 if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |name|
780 return transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice780 return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
781 const rp = makeRestorePoint(c);781 const rp = makeRestorePoint(c);
782782
783 const typedef_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, typedef_decl)));783 const typedef_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, typedef_decl)));
...@@ -818,8 +818,8 @@ fn transCreateNodeTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedef...@@ -818,8 +818,8 @@ fn transCreateNodeTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedef
818}818}
819819
820fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node {820fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node {
821 if (c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |kv|821 if (c.decl_table.get(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)))) |name|
822 return try transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice822 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
823 const record_loc = ZigClangRecordDecl_getLocation(record_decl);823 const record_loc = ZigClangRecordDecl_getLocation(record_decl);
824824
825 var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, record_decl)));825 var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, record_decl)));
...@@ -969,7 +969,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -969,7 +969,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
969969
970fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {970fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node {
971 if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|971 if (c.decl_table.get(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)))) |name|
972 return try transCreateNodeIdentifier(c, name.value); // Avoid processing this decl twice972 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
973 const rp = makeRestorePoint(c);973 const rp = makeRestorePoint(c);
974 const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);974 const enum_loc = ZigClangEnumDecl_getLocation(enum_decl);
975975
...@@ -2130,7 +2130,7 @@ fn transInitListExprRecord(...@@ -2130,7 +2130,7 @@ fn transInitListExprRecord(
2130 var raw_name = try rp.c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));2130 var raw_name = try rp.c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
2131 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {2131 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
2132 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;2132 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;
2133 raw_name = try mem.dupe(rp.c.arena, u8, name.value);2133 raw_name = try mem.dupe(rp.c.arena, u8, name);
2134 }2134 }
2135 const field_name_tok = try appendIdentifier(rp.c, raw_name);2135 const field_name_tok = try appendIdentifier(rp.c, raw_name);
21362136
...@@ -2855,7 +2855,7 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE...@@ -2855,7 +2855,7 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE
2855 const field_decl = @ptrCast(*const struct_ZigClangFieldDecl, member_decl);2855 const field_decl = @ptrCast(*const struct_ZigClangFieldDecl, member_decl);
2856 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {2856 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
2857 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;2857 const name = rp.c.decl_table.get(@ptrToInt(ZigClangFieldDecl_getCanonicalDecl(field_decl))).?;
2858 break :blk try mem.dupe(rp.c.arena, u8, name.value);2858 break :blk try mem.dupe(rp.c.arena, u8, name);
2859 }2859 }
2860 }2860 }
2861 const decl = @ptrCast(*const ZigClangNamedDecl, member_decl);2861 const decl = @ptrCast(*const ZigClangNamedDecl, member_decl);
...@@ -6040,8 +6040,8 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {...@@ -6040,8 +6040,8 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
6040 } else if (node.id == .PrefixOp) {6040 } else if (node.id == .PrefixOp) {
6041 return node;6041 return node;
6042 } else if (node.cast(ast.Node.Identifier)) |ident| {6042 } else if (node.cast(ast.Node.Identifier)) |ident| {
6043 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |kv| {6043 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
6044 if (kv.value.cast(ast.Node.VarDecl)) |var_decl|6044 if (value.cast(ast.Node.VarDecl)) |var_decl|
6045 return getContainer(c, var_decl.init_node.?);6045 return getContainer(c, var_decl.init_node.?);
6046 }6046 }
6047 } else if (node.cast(ast.Node.InfixOp)) |infix| {6047 } else if (node.cast(ast.Node.InfixOp)) |infix| {
...@@ -6064,8 +6064,8 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {...@@ -6064,8 +6064,8 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
60646064
6065fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {6065fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
6066 if (ref.cast(ast.Node.Identifier)) |ident| {6066 if (ref.cast(ast.Node.Identifier)) |ident| {
6067 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |kv| {6067 if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| {
6068 if (kv.value.cast(ast.Node.VarDecl)) |var_decl| {6068 if (value.cast(ast.Node.VarDecl)) |var_decl| {
6069 if (var_decl.type_node) |ty|6069 if (var_decl.type_node) |ty|
6070 return getContainer(c, ty);6070 return getContainer(c, ty);
6071 }6071 }
...@@ -6104,8 +6104,7 @@ fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {...@@ -6104,8 +6104,7 @@ fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {
6104}6104}
61056105
6106fn addMacros(c: *Context) !void {6106fn addMacros(c: *Context) !void {
6107 var macro_it = c.global_scope.macro_table.iterator();6107 for (c.global_scope.macro_table.items()) |kv| {
6108 while (macro_it.next()) |kv| {
6109 if (getFnProto(c, kv.value)) |proto_node| {6108 if (getFnProto(c, kv.value)) |proto_node| {
6110 // If a macro aliases a global variable which is a function pointer, we conclude that6109 // If a macro aliases a global variable which is a function pointer, we conclude that
6111 // the macro is intended to represent a function that assumes the function pointer6110 // the macro is intended to represent a function that assumes the function pointer