Merge pull request #6 from alexnask/separate_text_mem

Separate document text and memory.
This commit is contained in:
Auguste Rame 2020-05-07 13:10:18 -04:00 committed by GitHub
commit 14a2796857
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 12 deletions

View File

@ -72,11 +72,23 @@ pub fn respondGeneric(id: i64, response: []const u8) !void {
} }
pub fn openDocument(uri: []const u8, text: []const u8) !void { pub fn openDocument(uri: []const u8, text: []const u8) !void {
const du = try std.mem.dupe(allocator, u8, uri); const duped_uri = try std.mem.dupe(allocator, u8, uri);
_ = try documents.put(du, .{ const duped_text = try std.mem.dupe(allocator, u8, text);
.uri = du,
.text = try std.mem.dupe(allocator, u8, text), const res = try documents.put(duped_uri, .{
.uri = duped_uri,
.text = duped_text,
.mem = duped_text,
}); });
if (res) |existing_entry| {
try log("Opened already open file: {}", .{uri});
allocator.free(existing_entry.key);
allocator.free(existing_entry.value.mem);
if (existing_entry.value.sane_text) |str| {
allocator.free(str);
}
}
} }
pub fn cacheSane(document: *types.TextDocument) !void { pub fn cacheSane(document: *types.TextDocument) !void {
@ -320,15 +332,42 @@ pub fn processJsonRpc(json: []const u8) !void {
.character = range.Object.getValue("end").?.Object.getValue("character").?.Integer .character = range.Object.getValue("end").?.Object.getValue("character").?.Integer
}; };
const old_text = document.text; const change_text = change.Object.getValue("text").?.String;
const before = old_text[0..try document.positionToIndex(start_pos)]; const start_index = try document.positionToIndex(start_pos);
const after = old_text[try document.positionToIndex(end_pos)..document.text.len]; const end_index = try document.positionToIndex(end_pos);
document.text = try std.mem.concat(allocator, u8, &[3][]const u8{ before, change.Object.getValue("text").?.String, after });
allocator.free(old_text); const old_len = document.text.len;
const new_len = old_len + change_text.len;
if (new_len > document.mem.len) {
// We need to reallocate memory.
// We reallocate twice the current filesize or the new length, if it's more than that
// so that we can reduce the amount of realloc calls.
// We can tune this to find a better size if needed.
const realloc_len = std.math.max(2 * old_len, new_len);
document.mem = try allocator.realloc(document.mem, realloc_len);
}
// The first part of the string, [0 .. start_index] need not be changed.
// We then copy the last part of the string, [end_index ..] to its
// new position, [start_index + change_len .. ]
std.mem.copy(u8, document.mem[start_index + change_text.len..][0 .. old_len - end_index], document.mem[end_index .. old_len]);
// Finally, we copy the changes over.
std.mem.copy(u8, document.mem[start_index..][0 .. change_text.len], change_text);
// Reset the text substring.
document.text = document.mem[0 .. new_len];
} else { } else {
const old_text = document.text; const change_text = change.Object.getValue("text").?.String;
document.text = try std.mem.dupe(allocator, u8, change.Object.getValue("text").?.String); const old_len = document.text.len;
allocator.free(old_text);
if (change_text.len > document.mem.len) {
// Like above.
const realloc_len = std.math.max(2 * old_len, change_text.len);
document.mem = try allocator.realloc(document.mem, realloc_len);
}
std.mem.copy(u8, document.mem[0 .. change_text.len], change_text);
document.text = document.mem[0 .. change_text.len];
} }
} }

View File

@ -136,7 +136,10 @@ pub const PublishDiagnosticsParams = struct {
pub const TextDocument = struct { pub const TextDocument = struct {
uri: DocumentUri, uri: DocumentUri,
// This is a substring of mem starting at 0
text: String, text: String,
// This holds the memory that we have actually allocated.
mem: []u8,
sane_text: ?String = null, sane_text: ?String = null,
pub fn positionToIndex(self: *const TextDocument, position: Position) !usize { pub fn positionToIndex(self: *const TextDocument, position: Position) !usize {