diff options
author | pommicket <pommicket@gmail.com> | 2022-12-22 16:38:32 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-12-22 16:38:32 -0500 |
commit | 23e138019964662b4e847770eeda2bb5d3130f7a (patch) | |
tree | c92d36b878d26594cab5a35110dff6ad546d6a3d | |
parent | 6bb4da5fab94d2ed3d093b996674fd1cc28eda2f (diff) |
better write_string
-rw-r--r-- | ds.c | 14 | ||||
-rw-r--r-- | json.c | 5 | ||||
-rw-r--r-- | lsp-write-request.c | 30 | ||||
-rw-r--r-- | main.c | 1 |
4 files changed, 39 insertions, 11 deletions
@@ -297,7 +297,6 @@ void str_builder_append(StrBuilder *builder, const char *s) { size_t prev_len = prev_size - 1; // null terminator // note: this zeroes the newly created elements, so we have a new null terminator arr_set_len(builder->str, prev_size + s_len); - // -1 for null terminator memcpy(builder->str + prev_len, s, s_len); } @@ -331,3 +330,16 @@ u32 str_builder_len(StrBuilder *builder) { return arr_len(builder->str) - 1; } +char *str_builder_get_ptr(StrBuilder *builder, size_t index) { + assert(index <= str_builder_len(builder)); + return &builder->str[index]; +} + +void str_builder_shrink(StrBuilder *builder, size_t new_len) { + if (new_len > str_builder_len(builder)) { + assert(0); + return; + } + arr_set_len(builder->str, new_len + 1); +} + @@ -605,7 +605,9 @@ void json_debug_print(const JSON *json) { // e.g. converts "Hello\nworld" to "Hello\\nworld" // if out_sz is at least 2 * strlen(str) + 1, the string will fit. -void json_escape_to(char *out, size_t out_sz, const char *in) { +// returns the number of bytes actually written, not including the null terminator. +size_t json_escape_to(char *out, size_t out_sz, const char *in) { + char *start = out; char *end = out + out_sz; assert(out_sz); @@ -653,6 +655,7 @@ void json_escape_to(char *out, size_t out_sz, const char *in) { } brk: *out = '\0'; + return (size_t)(out - start); } // e.g. converts "Hello\nworld" to "Hello\\nworld" diff --git a/lsp-write-request.c b/lsp-write-request.c index e5d671d..f375559 100644 --- a/lsp-write-request.c +++ b/lsp-write-request.c @@ -74,11 +74,23 @@ static void write_arr_elem(JSONWriter *o) { } } -static void write_string(JSONWriter *o, const char* string) { - // @TODO: escape in-place - char *escaped = json_escape(string); - str_builder_appendf(&o->builder, "\"%s\"", escaped); - free(escaped); +static void write_escaped(JSONWriter *o, const char *string) { + StrBuilder *b = &o->builder; + size_t output_index = str_builder_len(b); + size_t capacity = 2 * strlen(string) + 1; + // append a bunch of null bytes which will hold the escaped string + str_builder_append_null(b, capacity); + char *out = str_builder_get_ptr(b, output_index); + // do the escaping + size_t length = json_escape_to(out, capacity, string); + // shrink down to just the escaped text + str_builder_shrink(&o->builder, output_index + length); +} + +static void write_string(JSONWriter *o, const char *string) { + str_builder_append(&o->builder, "\""); + write_escaped(o, string); + str_builder_append(&o->builder, "\""); } static void write_key(JSONWriter *o, const char *key) { @@ -121,10 +133,10 @@ static void write_key_string(JSONWriter *o, const char *key, const char *s) { } static void write_file_uri(JSONWriter *o, DocumentID document) { - // @OPTIM : could store escaped document paths instead of document paths - char *escaped_path = json_escape(o->lsp->document_paths[document]); - str_builder_appendf(&o->builder, "\"file:///%s\"", escaped_path); - free(escaped_path); + const char *path = o->lsp->document_paths[document]; + str_builder_append(&o->builder, "\"file:///"); + write_escaped(o, path); + str_builder_append(&o->builder, "\""); } static void write_key_file_uri(JSONWriter *o, const char *key, DocumentID document) { @@ -1,6 +1,7 @@ /* @TODO: - send didClose +- don't select the one and only completion when user types stuff - LSP setting - scroll through completions - figure out under which circumstances backspace should close completions |