nano

nano with my custom patches
git clone git://bsandro.tech/nano
Log | Files | Refs | README | LICENSE

commit 6fde7d8a51a18eb127a375e78b88df6c5e7a7f91
parent e4abef5768a8d1a43d7525486cb99a2f76ee9d52
Author: Benno Schulenberg <bensberg@telfort.nl>
Date:   Sun, 25 Sep 2022 15:51:02 +0200

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.

Diffstat:
Msrc/nano.c | 18+++++++++++-------
Msrc/prompt.c | 17+++++++++++------
2 files changed, 22 insertions(+), 13 deletions(-)

diff --git 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 @@ -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; } }