0001
0002
0003
0004
0005 #include "array.h"
0006 #include <errno.h>
0007 #include <fcntl.h>
0008 #include <poll.h>
0009 #include <stdlib.h>
0010 #include <unistd.h>
0011 #include <string.h>
0012
0013 void fdarray__init(struct fdarray *fda, int nr_autogrow)
0014 {
0015 fda->entries = NULL;
0016 fda->priv = NULL;
0017 fda->nr = fda->nr_alloc = 0;
0018 fda->nr_autogrow = nr_autogrow;
0019 }
0020
0021 int fdarray__grow(struct fdarray *fda, int nr)
0022 {
0023 struct priv *priv;
0024 int nr_alloc = fda->nr_alloc + nr;
0025 size_t psize = sizeof(fda->priv[0]) * nr_alloc;
0026 size_t size = sizeof(struct pollfd) * nr_alloc;
0027 struct pollfd *entries = realloc(fda->entries, size);
0028
0029 if (entries == NULL)
0030 return -ENOMEM;
0031
0032 priv = realloc(fda->priv, psize);
0033 if (priv == NULL) {
0034 free(entries);
0035 return -ENOMEM;
0036 }
0037
0038 memset(&entries[fda->nr_alloc], 0, sizeof(struct pollfd) * nr);
0039 memset(&priv[fda->nr_alloc], 0, sizeof(fda->priv[0]) * nr);
0040
0041 fda->nr_alloc = nr_alloc;
0042 fda->entries = entries;
0043 fda->priv = priv;
0044 return 0;
0045 }
0046
0047 struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
0048 {
0049 struct fdarray *fda = calloc(1, sizeof(*fda));
0050
0051 if (fda != NULL) {
0052 if (fdarray__grow(fda, nr_alloc)) {
0053 free(fda);
0054 fda = NULL;
0055 } else {
0056 fda->nr_autogrow = nr_autogrow;
0057 }
0058 }
0059
0060 return fda;
0061 }
0062
0063 void fdarray__exit(struct fdarray *fda)
0064 {
0065 free(fda->entries);
0066 free(fda->priv);
0067 fdarray__init(fda, 0);
0068 }
0069
0070 void fdarray__delete(struct fdarray *fda)
0071 {
0072 fdarray__exit(fda);
0073 free(fda);
0074 }
0075
0076 int fdarray__add(struct fdarray *fda, int fd, short revents, enum fdarray_flags flags)
0077 {
0078 int pos = fda->nr;
0079
0080 if (fda->nr == fda->nr_alloc &&
0081 fdarray__grow(fda, fda->nr_autogrow) < 0)
0082 return -ENOMEM;
0083
0084 fda->entries[fda->nr].fd = fd;
0085 fda->entries[fda->nr].events = revents;
0086 fda->priv[fda->nr].flags = flags;
0087 fda->nr++;
0088 return pos;
0089 }
0090
0091 int fdarray__dup_entry_from(struct fdarray *fda, int pos, struct fdarray *from)
0092 {
0093 struct pollfd *entry;
0094 int npos;
0095
0096 if (pos >= from->nr)
0097 return -EINVAL;
0098
0099 entry = &from->entries[pos];
0100
0101 npos = fdarray__add(fda, entry->fd, entry->events, from->priv[pos].flags);
0102 if (npos >= 0)
0103 fda->priv[npos] = from->priv[pos];
0104
0105 return npos;
0106 }
0107
0108 int fdarray__filter(struct fdarray *fda, short revents,
0109 void (*entry_destructor)(struct fdarray *fda, int fd, void *arg),
0110 void *arg)
0111 {
0112 int fd, nr = 0;
0113
0114 if (fda->nr == 0)
0115 return 0;
0116
0117 for (fd = 0; fd < fda->nr; ++fd) {
0118 if (!fda->entries[fd].events)
0119 continue;
0120
0121 if (fda->entries[fd].revents & revents) {
0122 if (entry_destructor)
0123 entry_destructor(fda, fd, arg);
0124
0125 fda->entries[fd].revents = fda->entries[fd].events = 0;
0126 continue;
0127 }
0128
0129 if (!(fda->priv[fd].flags & fdarray_flag__nonfilterable))
0130 ++nr;
0131 }
0132
0133 return nr;
0134 }
0135
0136 int fdarray__poll(struct fdarray *fda, int timeout)
0137 {
0138 return poll(fda->entries, fda->nr, timeout);
0139 }
0140
0141 int fdarray__fprintf(struct fdarray *fda, FILE *fp)
0142 {
0143 int fd, printed = fprintf(fp, "%d [ ", fda->nr);
0144
0145 for (fd = 0; fd < fda->nr; ++fd)
0146 printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd);
0147
0148 return printed + fprintf(fp, " ]");
0149 }