Mercurial > vim
changeset 8759:cc2ef7367643 v7.4.1668
commit https://github.com/vim/vim/commit/ee1f7b3cb71684aaa9bf457e2caf9d02187e6b7c
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Mar 28 14:42:14 2016 +0200
patch 7.4.1668
Problem: channel_get_all() does multiple allocations.
Solution: Compute the size and allocate once.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 28 Mar 2016 14:45:04 +0200 |
parents | b9b73c04e542 |
children | e43830c12eb2 |
files | src/channel.c src/version.c |
diffstat | 2 files changed, 32 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/channel.c +++ b/src/channel.c @@ -434,7 +434,6 @@ channel_read_fd(int fd) /* * Read a command from netbeans. - * TODO: instead of channel ID use the FD. */ #ifdef FEAT_GUI_X11 static void @@ -1325,11 +1324,34 @@ channel_get(channel_T *channel, int part static char_u * channel_get_all(channel_T *channel, int part) { - /* Concatenate everything into one buffer. - * TODO: avoid multiple allocations. */ - while (channel_collapse(channel, part) == OK) - ; - return channel_get(channel, part); + readq_T *head = &channel->ch_part[part].ch_head; + readq_T *node = head->rq_next; + long_u len = 1; + char_u *res; + char_u *p; + + /* If there is only one buffer just get that one. */ + if (head->rq_next == NULL || head->rq_next->rq_next == NULL) + return channel_get(channel, part); + + /* Concatenate everything into one buffer. */ + for (node = head->rq_next; node != NULL; node = node->rq_next) + len += (long_u)STRLEN(node->rq_buffer); + res = lalloc(len, TRUE); + if (res == NULL) + return NULL; + *res = NUL; + for (node = head->rq_next; node != NULL; node = node->rq_next) + STRCAT(res, node->rq_buffer); + + /* Free all buffers */ + do + { + p = channel_get(channel, part); + vim_free(p); + } while (p != NULL); + + return res; } /* @@ -2504,9 +2526,8 @@ channel_read(channel_T *channel, int par channel_save(channel, part, (char_u *)DETACH_MSG_RAW, (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT "); - /* TODO: When reading from stdout is not possible, should we try to - * keep stdin and stderr open? Probably not, assume the other side - * has died. */ + /* When reading from stdout is not possible, assume the other side has + * died. */ channel_close(channel, TRUE); if (channel->ch_nb_close_cb != NULL) (*channel->ch_nb_close_cb)();