| ... | ... | @@ -270,15 +270,19 @@ fn parseTreeMode(input: string) !Tree.Object.Mode { |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | pub const Tree = struct { |
| 273 | | children: []const Object, |
| 273 | children: std.MultiArrayList(Object).Slice, |
| 274 | 274 | |
| 275 | 275 | pub fn get(self: Tree, name: string) ?Object { |
| 276 | | for (self.children) |item| { |
| 277 | | if (std.mem.eql(u8, item.name, name)) { |
| 278 | | return item; |
| 276 | if (self.children.len <= 1000) { |
| 277 | for (self.children.items(.name), 0..) |a_name, i| { |
| 278 | if (std.mem.eql(u8, a_name, name)) { |
| 279 | return self.children.get(i); |
| 280 | } |
| 279 | 281 | } |
| 282 | return null; |
| 280 | 283 | } |
| 281 | | return null; |
| 284 | const i = std.sort.binarySearch([]const u8, self.children.items(.name), name, extras.compareFnSlice(u8)) orelse return null; |
| 285 | return self.children.get(i); |
| 282 | 286 | } |
| 283 | 287 | |
| 284 | 288 | pub fn getBlob(self: Tree, name: string) ?Object { |
| ... | ... | @@ -288,9 +292,9 @@ pub const Tree = struct { |
| 288 | 292 | } |
| 289 | 293 | |
| 290 | 294 | pub fn find(self: Tree, name: string) ?Object { |
| 291 | | for (self.children) |item| { |
| 292 | | if (std.ascii.eqlIgnoreCase(item.name, name)) { |
| 293 | | return item; |
| 295 | for (self.children.items(.name), 0..) |item, i| { |
| 296 | if (std.ascii.eqlIgnoreCase(item, name)) { |
| 297 | return self.children.get(i); |
| 294 | 298 | } |
| 295 | 299 | } |
| 296 | 300 | return null; |
| ... | ... | @@ -860,7 +864,7 @@ pub const Repository = struct { |
| 860 | 864 | for (r.pack_content.values()) |v| nfs.munmap(v); |
| 861 | 865 | r.pack_content.deinit(r.gpa); |
| 862 | 866 | r.commits.deinit(r.gpa); |
| 863 | | for (r.trees.values()) |v| r.gpa.free(v.children); |
| 867 | for (r.trees.values()) |*v| v.children.deinit(r.gpa); |
| 864 | 868 | r.trees.deinit(r.gpa); |
| 865 | 869 | r.tags.deinit(r.gpa); |
| 866 | 870 | } |
| ... | ... | @@ -1192,8 +1196,9 @@ pub const Repository = struct { |
| 1192 | 1196 | } |
| 1193 | 1197 | if (try r.getObject(arena, id.id)) |obj| { |
| 1194 | 1198 | if (obj.type == .tree) { |
| 1195 | | var children = std.ArrayList(Tree.Object).init(r.gpa); |
| 1196 | | errdefer children.deinit(); |
| 1199 | var children: std.MultiArrayList(Tree.Object) = .empty; |
| 1200 | errdefer children.deinit(r.gpa); |
| 1201 | try children.ensureUnusedCapacity(r.gpa, 33); |
| 1197 | 1202 | var i: usize = 0; |
| 1198 | 1203 | while (i < obj.content.len) { |
| 1199 | 1204 | const mode_end = std.mem.indexOfScalar(u8, obj.content[i..], ' ').?; |
| ... | ... | @@ -1213,7 +1218,7 @@ pub const Repository = struct { |
| 1213 | 1218 | @memcpy(mode_buf[6 - mode.len ..], mode); |
| 1214 | 1219 | const mode_real = try parseTreeMode(&mode_buf); |
| 1215 | 1220 | |
| 1216 | | try children.append(.{ |
| 1221 | try children.append(r.gpa, .{ |
| 1217 | 1222 | .mode = mode_real, |
| 1218 | 1223 | .name = name, |
| 1219 | 1224 | .id = switch (mode_real.type) { |
| ... | ... | @@ -1225,7 +1230,26 @@ pub const Repository = struct { |
| 1225 | 1230 | }, |
| 1226 | 1231 | }); |
| 1227 | 1232 | } |
| 1228 | | const tree: Tree = .{ .children = try children.toOwnedSlice() }; |
| 1233 | |
| 1234 | const S = struct { |
| 1235 | list: *std.MultiArrayList(Tree.Object), |
| 1236 | |
| 1237 | pub fn lessThan(s: @This(), a: usize, b: usize) bool { |
| 1238 | const items = s.list.items(.name); |
| 1239 | return std.mem.order(u8, items[a], items[b]) == .lt; |
| 1240 | } |
| 1241 | pub fn swap(s: @This(), a: usize, b: usize) void { |
| 1242 | // Remove after updating to Zig 0.17. Ref: https://codeberg.org/ziglang/zig/pulls/32016 |
| 1243 | inline for (@typeInfo(Tree.Object).@"struct".fields) |field| { |
| 1244 | const its = s.list.items(@field(std.MultiArrayList(Tree.Object).Field, field.name)); |
| 1245 | std.mem.swap(@FieldType(Tree.Object, field.name), &its[a], &its[b]); |
| 1246 | } |
| 1247 | } |
| 1248 | }; |
| 1249 | if (children.len > 1000) std.mem.sortContext(0, children.len, S{ .list = &children }); |
| 1250 | |
| 1251 | var tree: Tree = .{ .children = children.toOwnedSlice() }; |
| 1252 | errdefer tree.children.deinit(r.gpa); |
| 1229 | 1253 | try r.trees.put(r.gpa, id.id, tree); |
| 1230 | 1254 | return .{ id, tree }; |
| 1231 | 1255 | } |
| ... | ... | @@ -1342,7 +1366,7 @@ pub const Repository = struct { |
| 1342 | 1366 | var found: usize = 0; |
| 1343 | 1367 | var result: std.StringArrayHashMapUnmanaged(CommitId) = .empty; |
| 1344 | 1368 | defer result.deinit(r.gpa); |
| 1345 | | for (base_tree.children) |item| try result.put(r.gpa, item.name, undefined); |
| 1369 | for (base_tree.children.items(.name)) |name| try result.put(r.gpa, name, undefined); |
| 1346 | 1370 | |
| 1347 | 1371 | var set: std.bit_set.DynamicBitSetUnmanaged = try .initEmpty(r.gpa, total); |
| 1348 | 1372 | defer set.deinit(r.gpa); |