diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-01-24 20:36:41 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-01-24 20:36:41 +0100 |
commit | e0874f8cbcddfcf9965a85ba35199964efb1d01a (patch) | |
tree | 02cba2d1d135a96e3983f0676bb11da770ab0426 /src/channel.c | |
parent | 705ada1aff27ecd9c47c690df817d043c2ceb5e2 (diff) | |
download | vim-git-7.4.1169.tar.gz |
patch 7.4.1169v7.4.1169
Problem: The socket I/O is intertwined with the netbeans code.
Solution: Start refactoring the netbeans communication to split off the
socket I/O. Add the +channel feature.
Diffstat (limited to 'src/channel.c')
-rw-r--r-- | src/channel.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/channel.c b/src/channel.c new file mode 100644 index 000000000..a108d7e7c --- /dev/null +++ b/src/channel.c @@ -0,0 +1,187 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + */ + +/* + * Implements communication through a socket or any file handle. + */ + +#include "vim.h" + +#if defined(FEAT_CHANNEL) || defined(PROTO) + +typedef struct { + sock_T ch_fd; + int ch_idx; +} channel_T; + +static channel_T *channels = NULL; +static int channel_count = 0; + +/* + * Add a new channel slot, return the index. + * Returns -1 if out of space. + */ + static int +add_channel(void) +{ + int idx; + channel_T *new_channels; + + if (channels != NULL) + for (idx = 0; idx < channel_count; ++idx) + if (channels[idx].ch_fd < 0) + /* re-use a closed channel slot */ + return idx; + if (channel_count == MAX_OPEN_CHANNELS) + return -1; + new_channels = (channel_T *)alloc(sizeof(channel_T) * channel_count + 1); + if (new_channels == NULL) + return -1; + if (channels != NULL) + mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count); + channels = new_channels; + channels[channel_count].ch_fd = (sock_T)-1; + + return channel_count++; +} + +#if defined(FEAT_NETBEANS_INTG) || defined(PROTO) +static int netbeans_channel = -1; + +/* + * Add the netbeans socket to the channels. + * Return the channel index. + */ + int +channel_add_netbeans(sock_T fd) +{ + int idx = add_channel(); + + if (idx >= 0) + { + channels[idx].ch_fd = fd; + netbeans_channel = idx; + } + return idx; +} + + void +channel_remove_netbeans() +{ + channels[netbeans_channel].ch_fd = (sock_T)-1; + netbeans_channel = -1; +} +#endif + + static void +channel_read(int idx) +{ +# ifdef FEAT_NETBEANS_INTG + if (idx == netbeans_channel) + netbeans_read(); + else +# endif + { + ; /* TODO: read */ + } +} + +#if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) +/* + * Add open channels to the poll struct. + * Return the adjusted struct index. + * The type of "fds" is hidden to avoid problems with the function proto. + */ + int +channel_poll_setup(int nfd_in, void *fds_in) +{ + int nfd = nfd_in; + int i; + struct pollfd *fds = fds_in; + + for (i = 0; i < channel_count; ++i) + if (channels[i].ch_fd >= 0) + { + channels[i].ch_idx = nfd; + fds[nfd].fd = channels[i].ch_fd; + fds[nfd].events = POLLIN; + nfd++; + } + else + channels[i].ch_idx = -1; + + return nfd; +} + +/* + * The type of "fds" is hidden to avoid problems with the function proto. + */ + int +channel_poll_check(int ret_in, void *fds_in) +{ + int ret = ret_in; + int i; + struct pollfd *fds = fds_in; + + for (i = 0; i < channel_count; ++i) + if (ret > 0 && channels[i].ch_idx != -1 + && fds[channels[i].ch_idx].revents & POLLIN) + { + channel_read(i); + --ret; + } + + return ret; +} +#endif /* UNIX && !HAVE_SELECT */ + +#if (defined(UNIX) && defined(HAVE_SELECT)) || defined(PROTO) +/* + * The type of "rfds" is hidden to avoid problems with the function proto. + */ + int +channel_select_setup(int maxfd_in, void *rfds_in) +{ + int maxfd = maxfd_in; + int i; + fd_set *rfds = rfds_in; + + for (i = 0; i < channel_count; ++i) + if (channels[i].ch_fd >= 0) + { + FD_SET(channels[i].ch_fd, rfds); + if (maxfd < channels[i].ch_fd) + maxfd = channels[i].ch_fd; + } + + return maxfd; +} + +/* + * The type of "rfds" is hidden to avoid problems with the function proto. + */ + int +channel_select_check(int ret_in, void *rfds_in) +{ + int ret = ret_in; + int i; + fd_set *rfds = rfds_in; + + for (i = 0; i < channel_count; ++i) + if (ret > 0 && channels[i].ch_fd >= 0 + && FD_ISSET(channels[i].ch_fd, rfds)) + { + channel_read(i); + --ret; + } + + return ret; +} +#endif /* UNIX && HAVE_SELECT */ + +#endif /* FEAT_CHANNEL */ |