| author | |
| committer | |
| log | 632acffcbd96a085ea92899e6f37465e40178f44 |
| tree | 77b4af87060b43172eefb66943564faed365ec84 |
| parent | b3b6ccba50ef7a683ad05546cba2b71e7d10489f |
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 | } |
| 41 | 41 | ||
| 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 | } |
| 57 | 57 | ||
| 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 | } |
| 62 | 61 | ||
| 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 | } |
| 16 | 16 | ||
| 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 | } |
| 26 | 24 | ||
| 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; |
| 429 | 429 | ||
| 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 | } |
| 644 | 644 | ||
| 645 | // option already exists | 645 | // 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 list | 648 | // 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 | } |
| 685 | 685 | ||
| 686 | // option already exists | 686 | // 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( |
| 293 | 293 | ||
| 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 | } |
| 302 | 306 | ||
| 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 | } |
| 310 | 314 | ||
| ... | @@ -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; |
| 380 | 384 | ||
| 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 { |
| 789 | 793 | ||
| 790 | const Self = @This(); | 794 | const Self = @This(); |
| 791 | 795 | ||
| 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 | } |
| 120 | 120 | ||
| 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 | } |
| 138 | 138 | ||
| 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 backwards | 199 | // 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 { |
| 216 | 216 | ||
| 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 index | 227 | // 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 index | 237 | // 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 | } |
| 238 | 242 | ||
| 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 index | 252 | // 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 index | 262 | // 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 | } |
| 260 | 267 | ||
| ... | @@ -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 | } |
| 275 | 278 | ||
| 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 | } |
| 327 | 330 | ||
| 328 | fn rebuild_index(self: *Self) void { | 331 | fn rebuildIndex(self: *Self) void { |
| 329 | { // clear out the indexes | 332 | // 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 before | 336 | // 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 | } |
| 343 | 341 | ||
| 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 | } |
| 348 | 346 | ||
| 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" { |
| 2149 | 2149 | ||
| 2150 | var root = tree.root; | 2150 | var root = tree.root; |
| 2151 | 2151 | ||
| 2152 | var image = root.Object.get("Image").?.value; | 2152 | var image = root.Object.get("Image").?; |
| 2153 | 2153 | ||
| 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); |
| 2156 | 2156 | ||
| 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); |
| 2159 | 2159 | ||
| 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")); |
| 2162 | 2162 | ||
| 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); |
| 2165 | 2165 | ||
| 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); |
| 2168 | 2168 | ||
| 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")); |
| 2171 | 2171 | ||
| 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 | } |
| 2175 | 2175 | ||
| ... | @@ -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(); |
| 2219 | 2219 | ||
| 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 | } |
| 2227 | 2227 | ||
| 2228 | fn test_parse(arena_allocator: *std.mem.Allocator, json_str: []const u8) !Value { | 2228 | fn 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 | } |
| 2250 | 2250 | ||
| 2251 | test "escaped characters" { | 2251 | test "escaped characters" { |
| ... | @@ -2271,16 +2271,16 @@ test "escaped characters" { | ... | @@ -2271,16 +2271,16 @@ test "escaped characters" { |
| 2271 | 2271 | ||
| 2272 | const obj = (try test_parse(&arena_allocator.allocator, input)).Object; | 2272 | const obj = (try test_parse(&arena_allocator.allocator, input)).Object; |
| 2273 | 2273 | ||
| 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 | } |
| 2285 | 2285 | ||
| 2286 | test "string copy option" { | 2286 | test "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; |
| 2307 | 2307 | ||
| 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 | } |
| 2311 | 2311 | ||
| 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]; |
| 2314 | 2314 | ||
| 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(); |
| 721 | 721 | ||
| 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; |
| 724 | 724 | ||
| 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); |
| 769 | 769 | ||
| 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; |
| 772 | 772 | ||
| 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}; |
| 20 | const TypeError = Error || error{UnsupportedType}; | 20 | const TypeError = Error || error{UnsupportedType}; |
| 21 | const TransError = TypeError || error{UnsupportedTranslation}; | 21 | const TransError = TypeError || error{UnsupportedTranslation}; |
| 22 | 22 | ||
| 23 | const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql); | 23 | const DeclTable = std.HashMap(usize, []const u8, addrHash, addrEql, false); |
| 24 | 24 | ||
| 25 | fn addrHash(x: usize) u32 { | 25 | fn 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 | } |
| 777 | 777 | ||
| 778 | fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node { | 778 | fn 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 twice | 780 | return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice |
| 781 | const rp = makeRestorePoint(c); | 781 | const rp = makeRestorePoint(c); |
| 782 | 782 | ||
| 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 | } |
| 819 | 819 | ||
| 820 | fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node { | 820 | fn 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 twice | 822 | 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); |
| 824 | 824 | ||
| 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!?* |
| 969 | 969 | ||
| 970 | fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.Node { | 970 | fn 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 twice | 972 | 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); |
| 975 | 975 | ||
| ... | @@ -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); |
| 2136 | 2136 | ||
| ... | @@ -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 { |
| 6064 | 6064 | ||
| 6065 | fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { | 6065 | fn 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 | } |
| 6105 | 6105 | ||
| 6106 | fn addMacros(c: *Context) !void { | 6106 | fn 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 that | 6109 | // 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 pointer | 6110 | // the macro is intended to represent a function that assumes the function pointer |