Avoid unnecessary copy of document text when opening new imports
This commit is contained in:
		
							parent
							
								
									60ffc5f551
								
							
						
					
					
						commit
						76e9a079a3
					
				@ -60,6 +60,31 @@ pub fn init(self: *DocumentStore, allocator: *std.mem.Allocator, zig_lib_path: ?
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// This function assersts the document is not open yet and takes owneship
 | 
			
		||||
/// of the uri and text passed in.
 | 
			
		||||
fn newDocument(self: *DocumentStore, uri: []const u8, text: []u8) !*Handle {
 | 
			
		||||
    std.debug.warn("Opened document: {}\n", .{uri});
 | 
			
		||||
 | 
			
		||||
    errdefer {
 | 
			
		||||
        self.allocator.free(uri);
 | 
			
		||||
        self.allocator.free(text);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var handle = Handle{
 | 
			
		||||
        .count = 1,
 | 
			
		||||
        .import_uris = std.ArrayList([]const u8).init(self.allocator),
 | 
			
		||||
        .document = .{
 | 
			
		||||
            .uri = uri,
 | 
			
		||||
            .text = text,
 | 
			
		||||
            .mem = text,
 | 
			
		||||
            .sane_text = null,
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
    try self.checkSanity(&handle);
 | 
			
		||||
    try self.handles.putNoClobber(uri, handle);
 | 
			
		||||
    return &(self.handles.get(uri) orelse unreachable).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn openDocument(self: *DocumentStore, uri: []const u8, text: []const u8) !*Handle {
 | 
			
		||||
    if (self.handles.get(uri)) |entry| {
 | 
			
		||||
        std.debug.warn("Document already open: {}, incrementing count\n", .{uri});
 | 
			
		||||
@ -68,25 +93,12 @@ pub fn openDocument(self: *DocumentStore, uri: []const u8, text: []const u8) !*H
 | 
			
		||||
        return &entry.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std.debug.warn("Opened document: {}\n", .{uri});
 | 
			
		||||
    const duped_text = try std.mem.dupe(self.allocator, u8, text);
 | 
			
		||||
    errdefer self.allocator.free(duped_text);
 | 
			
		||||
    const duped_uri = try std.mem.dupe(self.allocator, u8, uri);
 | 
			
		||||
    errdefer self.allocator.free(duped_uri);
 | 
			
		||||
 | 
			
		||||
    var handle = Handle{
 | 
			
		||||
        .count = 1,
 | 
			
		||||
        .import_uris = std.ArrayList([]const u8).init(self.allocator),
 | 
			
		||||
        .document = .{
 | 
			
		||||
            .uri = duped_uri,
 | 
			
		||||
            .text = duped_text,
 | 
			
		||||
            .mem = duped_text,
 | 
			
		||||
            .sane_text = null,
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
    try self.checkSanity(&handle);
 | 
			
		||||
    try self.handles.putNoClobber(duped_uri, handle);
 | 
			
		||||
    return &(self.handles.get(duped_uri) orelse unreachable).value;
 | 
			
		||||
    return self.newDocument(duped_uri, duped_text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn decrementCount(self: *DocumentStore, uri: []const u8) void {
 | 
			
		||||
@ -243,8 +255,6 @@ pub const ImportContext = struct {
 | 
			
		||||
        var consumed_final_uri = false;
 | 
			
		||||
        defer if (!consumed_final_uri) allocator.free(final_uri);
 | 
			
		||||
 | 
			
		||||
        // @TODO Clean up code, lots of repetition
 | 
			
		||||
        {
 | 
			
		||||
        // Check if we already imported this.
 | 
			
		||||
        for (self.handle.import_uris.items) |uri| {
 | 
			
		||||
            // If we did, set our new handle and return the parsed tree root node.
 | 
			
		||||
@ -257,7 +267,6 @@ pub const ImportContext = struct {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // New import.
 | 
			
		||||
        // Check if the import is already opened by others.
 | 
			
		||||
@ -284,9 +293,9 @@ pub const ImportContext = struct {
 | 
			
		||||
        defer file.close();
 | 
			
		||||
        const size = std.math.cast(usize, try file.getEndPos()) catch std.math.maxInt(usize);
 | 
			
		||||
 | 
			
		||||
        // TODO: This is wasteful, we know we don't need to copy the text on this openDocument call
 | 
			
		||||
        {
 | 
			
		||||
            const file_contents = try allocator.alloc(u8, size);
 | 
			
		||||
        defer allocator.free(file_contents);
 | 
			
		||||
            errdefer allocator.free(file_contents);
 | 
			
		||||
 | 
			
		||||
            file.inStream().readNoEof(file_contents) catch {
 | 
			
		||||
                std.debug.warn("Could not read from file {}\n", .{file_path});
 | 
			
		||||
@ -296,8 +305,11 @@ pub const ImportContext = struct {
 | 
			
		||||
            // Add to import table of current handle.
 | 
			
		||||
            try self.handle.import_uris.append(final_uri);
 | 
			
		||||
            consumed_final_uri = true;
 | 
			
		||||
 | 
			
		||||
            // Swap handles and get new tree.
 | 
			
		||||
        self.handle = try openDocument(self.store, final_uri, file_contents);
 | 
			
		||||
            // This takes ownership of the passed uri and text.
 | 
			
		||||
            self.handle = try newDocument(self.store, try std.mem.dupe(allocator, u8, final_uri), file_contents);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (try self.handle.saneTree(allocator)) |tree| {
 | 
			
		||||
            try self.trees.append(tree);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user