kconfig: use pkg-config for ncurses detection
[akaros.git] / user / parlib / iovec.c
1 /* Copyright (c) 2016 Google Inc
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Various utility functions. */
6
7 #include <parlib/iovec.h>
8 #include <assert.h>
9 #include <sys/param.h>
10
11 /* Strips bytes from the front of the iovec.  This modifies the base and
12  * length of the iovecs in the array. */
13 void iov_strip_bytes(struct iovec *iov, int iovcnt, size_t amt)
14 {
15         for (int i = 0; i < iovcnt; i++) {
16                 if (iov[i].iov_len <= amt) {
17                         amt -= iov[i].iov_len;
18                         iov[i].iov_len = 0;
19                         continue;
20                 }
21                 iov[i].iov_len -= amt;
22                 iov[i].iov_base += amt;
23                 amt = 0;
24         }
25 }
26
27 /* Drops bytes from the end of the iovec.  This modified the length of the
28  * iovecs in the array. */
29 void iov_drop_trailing_bytes(struct iovec *iov, int iovcnt, size_t amt)
30 {
31         for (int i = iovcnt - 1; i >= 0; i--) {
32                 if (iov[i].iov_len <= amt) {
33                         amt -= iov[i].iov_len;
34                         iov[i].iov_len = 0;
35                         continue;
36                 }
37                 iov[i].iov_len -= amt;
38                 break;
39         }
40 }
41
42 /* Trims the iov's length to new_len, modifying the iov_lens.  If the iov is
43  * shorter than new_len, it will not grow. */
44 void iov_trim_len_to(struct iovec *iov, int iovcnt, size_t new_len)
45 {
46         for (int i = 0; i < iovcnt; i++) {
47                 if (iov[i].iov_len <= new_len) {
48                         new_len -= iov[i].iov_len;
49                         continue;
50                 }
51                 iov[i].iov_len = new_len;
52                 break;
53         }
54 }
55
56 /* Checks if iov has amt bytes in it. */
57 bool iov_has_bytes(struct iovec *iov, int iovcnt, size_t amt)
58 {
59         for (int i = 0; i < iovcnt; i++) {
60                 if (iov[i].iov_len >= amt)
61                         return TRUE;
62                 amt -= iov[i].iov_len;
63         }
64         return FALSE;
65 }
66
67 size_t iov_get_len(struct iovec *iov, int iovcnt)
68 {
69         size_t ret = 0;
70
71         for (int i = 0; i < iovcnt; i++)
72                 ret += iov[i].iov_len;
73         return ret;
74 }
75
76 /* Copies up to len bytes of the contents of IOV into buf. */
77 void iov_linearize(struct iovec *iov, int iovcnt, uint8_t *buf, size_t len)
78 {
79         size_t copy_amt;
80         size_t sofar = 0;
81
82         for (int i = 0; i < iovcnt; i++) {
83                 if (!len)
84                         break;
85                 copy_amt = MIN(iov[i].iov_len, len);
86                 memcpy(buf + sofar, iov[i].iov_base, copy_amt);
87                 sofar += copy_amt;
88                 len -= copy_amt;
89         }
90 }
91
92 /* Sets a byte in an iov, essentially iov_mem[idx] = val. */
93 void iov_set_byte(struct iovec *iov, int iovcnt, size_t idx, uint8_t val)
94 {
95         uint8_t *p = NULL;
96
97         for (int i = 0; i < iovcnt; i++) {
98                 if (iov[i].iov_len <= idx) {
99                         idx -= iov[i].iov_len;
100                         continue;
101                 }
102                 p = iov[i].iov_base + idx;
103                 break;
104         }
105         assert(p);
106         *p = val;
107 }
108
109 /* Sets a byte in an iov, essentially *val = iov_mem[idx]. */
110 uint8_t iov_get_byte(struct iovec *iov, int iovcnt, size_t idx)
111 {
112         uint8_t *p = NULL;
113
114         for (int i = 0; i < iovcnt; i++) {
115                 if (iov[i].iov_len <= idx) {
116                         idx -= iov[i].iov_len;
117                         continue;
118                 }
119                 p = iov[i].iov_base + idx;
120                 break;
121         }
122         assert(p);
123         return *p;
124 }
125
126 void iov_memcpy_from(struct iovec *iov, int iovcnt, size_t from,
127                      void *to, size_t amt)
128 {
129         size_t copy_amt;
130         void *copy_start;
131         size_t sofar = 0;
132
133         for (int i = 0; i < iovcnt; i++) {
134                 if (!amt)
135                         break;
136                 if (iov[i].iov_len <= from) {
137                         from -= iov[i].iov_len;
138                         continue;
139                 }
140                 copy_start = iov[i].iov_base + from;
141                 copy_amt = iov[i].iov_len - from;
142                 from = 0;
143                 copy_amt = MIN(copy_amt, amt);
144                 memcpy(to + sofar, copy_start, copy_amt);
145                 sofar += copy_amt;
146                 amt -= copy_amt;
147         }
148         assert(!amt);
149 }
150
151 void iov_memcpy_to(struct iovec *iov, int iovcnt, size_t to,
152                    void *from, size_t amt)
153 {
154         size_t copy_amt;
155         void *copy_start;
156         size_t sofar = 0;
157
158         for (int i = 0; i < iovcnt; i++) {
159                 if (!amt)
160                         break;
161                 if (iov[i].iov_len <= to) {
162                         to -= iov[i].iov_len;
163                         continue;
164                 }
165                 copy_start = iov[i].iov_base + to;
166                 copy_amt = iov[i].iov_len - to;
167                 to = 0;
168                 copy_amt = MIN(copy_amt, amt);
169                 memcpy(copy_start, from + sofar, copy_amt);
170                 sofar += copy_amt;
171                 amt -= copy_amt;
172         }
173         assert(!amt);
174 }
175
176 uint16_t iov_get_be16(struct iovec *iov, int iovcnt, size_t idx)
177 {
178         return ((uint16_t)iov_get_byte(iov, iovcnt, idx + 0) << 8)
179              | ((uint16_t)iov_get_byte(iov, iovcnt, idx + 1) << 0);
180 }
181
182 uint16_t iov_get_be32(struct iovec *iov, int iovcnt, size_t idx)
183 {
184         return ((uint32_t)iov_get_byte(iov, iovcnt, idx + 0) << 24)
185              | ((uint32_t)iov_get_byte(iov, iovcnt, idx + 1) << 16)
186              | ((uint32_t)iov_get_byte(iov, iovcnt, idx + 2) << 8)
187              | ((uint32_t)iov_get_byte(iov, iovcnt, idx + 3) << 0);
188 }
189
190 void iov_put_be16(struct iovec *iov, int iovcnt, size_t idx, uint16_t val)
191 {
192         iov_set_byte(iov, iovcnt, idx + 0, (val >> 8) & 0xff);
193         iov_set_byte(iov, iovcnt, idx + 1, (val >> 0) & 0xff);
194 }
195
196 void iov_put_be32(struct iovec *iov, int iovcnt, size_t idx, uint32_t val)
197 {
198         iov_set_byte(iov, iovcnt, idx + 0, (val >> 24) & 0xff);
199         iov_set_byte(iov, iovcnt, idx + 1, (val >> 16) & 0xff);
200         iov_set_byte(iov, iovcnt, idx + 2, (val >>  8) & 0xff);
201         iov_set_byte(iov, iovcnt, idx + 3, (val >>  0) & 0xff);
202 }