From 6fde7d8a51a18eb127a375e78b88df6c5e7a7f91 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Sun, 25 Sep 2022 15:51:02 +0200 Subject: [PATCH] input: allocate two small character buffers too, and never free them Analogous to commit 3922b531: instead of allocating and later freeing a tiny fragment of memory for every character that the user enters (in the edit window or at a prompt), reserve a small piece in the beginning and retain it, and increase (but never decrease) its size as needed. This addresses the second part of https://savannah.gnu.org/bugs/?63086. --- src/nano.c | 18 +++++++++++------- src/prompt.c | 17 +++++++++++------ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/nano.c b/src/nano.c index 0302e971..206f54ed 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1547,6 +1547,8 @@ void process_a_keystroke(void) /* The keystroke we read in: a character or a shortcut. */ static char *puddle = NULL; /* The input buffer for actual characters. */ + static size_t capacity = 12; + /* The size of the input buffer; gets doubled whenever needed. */ static size_t depth = 0; /* The length of the input buffer. */ #ifndef NANO_TINY @@ -1593,21 +1595,23 @@ void process_a_keystroke(void) refresh_needed = TRUE; } #endif - /* Store the byte, and leave room for a terminating zero. */ - puddle = nrealloc(puddle, depth + 2); + /* When the input buffer (plus room for terminating NUL) is full, + * extend it; otherwise, if it does not exist yet, create it. */ + if (depth + 1 == capacity) { + capacity = 2 * capacity; + puddle = nrealloc(puddle, capacity); + } else if (!puddle) + puddle = nmalloc(capacity); + puddle[depth++] = (char)input; } } /* If we have a command, or if there aren't any other key codes waiting, * it's time to insert the gathered bytes into the edit buffer. */ - if ((function || waiting_keycodes() == 0) && puddle != NULL) { + if (depth > 0 && (function || waiting_keycodes() == 0)) { puddle[depth] = '\0'; - inject(puddle, depth); - - free(puddle); - puddle = NULL; depth = 0; } diff --git a/src/prompt.c b/src/prompt.c index f99bec25..df697f2b 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -256,6 +256,8 @@ void absorb_character(int input, functionptrtype function) { static char *puddle = NULL; /* The input buffer. */ + static size_t capacity = 8; + /* The size of the input buffer; gets doubled whenever needed. */ static size_t depth = 0; /* The length of the input buffer. */ @@ -267,7 +269,14 @@ void absorb_character(int input, functionptrtype function) beep(); else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || openfile->filename[0] == '\0') { - puddle = nrealloc(puddle, depth + 2); + /* When the input buffer (plus room for terminating NUL) is full, + * extend it; otherwise, if it does not exist yet, create it. */ + if (depth + 1 == capacity) { + capacity = 2 * capacity; + puddle = nrealloc(puddle, capacity); + } else if (!puddle) + puddle = nmalloc(capacity); + puddle[depth++] = (char)input; } } @@ -275,13 +284,9 @@ void absorb_character(int input, functionptrtype function) /* If we got a shortcut, or if there aren't any other keystrokes waiting, * it's time to insert all characters in the input buffer (if not empty) * into the answer, and then clear the input buffer. */ - if ((function || waiting_keycodes() == 0) && puddle != NULL) { + if (depth > 0 && (function || waiting_keycodes() == 0)) { puddle[depth] = '\0'; - inject_into_answer(puddle, depth); - - free(puddle); - puddle = NULL; depth = 0; } }