Allocate a buffer just large enough.

I figure that's worth the overhead of iterating twice.  It's happening
during a user interaction so there's plenty of time, eh?
This commit is contained in:
Simon Forman 2023-02-20 16:23:41 -08:00
parent eeb935fa07
commit 7485383d9f
1 changed files with 41 additions and 16 deletions

View File

@ -26,28 +26,53 @@ index_of_last_symbol_char(const char *buf)
} }
void int
prefixed_completion(const char *buf, linenoiseCompletions *lc, int n) longest_completion(const char *buf, int buffer_length)
{ {
int longest = 0;
raxIterator iter; raxIterator iter;
char *prefix = malloc(1024); /* Just assume 1k is enough for now... TODO: fix! */
if (NULL == prefix)
return;
int buffer_length = strlen(buf);
memcpy(prefix, buf, n);
buf += n;
buffer_length -= n;
raxStart(&iter, rt); raxStart(&iter, rt);
raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length); raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length);
while(raxNext(&iter)) { while(raxNext(&iter)) {
if (strncmp((const char *)iter.key, buf, buffer_length)) if (strncmp((const char *)iter.key, buf, buffer_length))
break; break;
prefix[n] = 0; if (iter.key_len > longest) {
strlcat(prefix + n, (const char *)iter.key, 1024 - n); longest = iter.key_len;
linenoiseAddCompletion(lc, (const char *)prefix); };
} }
raxStop(&iter); raxStop(&iter);
free(prefix); return longest;
}
void
prefixed_completion(const char *buf, linenoiseCompletions *lc, int prefix_length)
{
raxIterator iter;
/* Get a buffer large enough to hold the largest possible completion. */
int buffer_length = strlen(buf);
int completion_buffer_size = prefix_length + longest_completion(buf, buffer_length) + 1;
char *completion_buffer = malloc(completion_buffer_size);
if (NULL == completion_buffer)
return;
/* Prepare the prefix and trim it from the front of the buf. */
memcpy(completion_buffer, buf, prefix_length);
buf += prefix_length;
buffer_length -= prefix_length;
raxStart(&iter, rt);
raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length);
while(raxNext(&iter)) {
if (strncmp((const char *)iter.key, buf, buffer_length))
break;
completion_buffer[prefix_length] = 0;
strlcat(completion_buffer + prefix_length, (const char *)iter.key, completion_buffer_size);
linenoiseAddCompletion(lc, (const char *)completion_buffer);
}
raxStop(&iter);
free(completion_buffer);
} }
@ -70,9 +95,9 @@ simple_completion(const char *buf, linenoiseCompletions *lc)
void void
completion(const char *buf, linenoiseCompletions *lc) completion(const char *buf, linenoiseCompletions *lc)
{ {
int n = index_of_last_symbol_char(buf); int prefix_length = index_of_last_symbol_char(buf);
if (n) { if (prefix_length) {
prefixed_completion(buf, lc, n); prefixed_completion(buf, lc, prefix_length);
} else { } else {
simple_completion(buf, lc); simple_completion(buf, lc);
} }