1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
/* Flexible iovec -- header
* Copyright (C) 2010 Chris Hall (GMCH), Highwayman
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _ZEBRA_QIOVEC_H
#define _ZEBRA_QIOVEC_H
#include "misc.h"
#include <sys/uio.h> /* iovec stuff */
/*==============================================================================
* Alternative naming for struct iovec and its entries.
*/
struct qiov_item
{
const char* base ;
size_t len ;
} ;
typedef struct qiov_item* qiov_item ;
typedef struct qiov_item qiov_item_t[1] ;
typedef struct qiov_item* qiov_vector ;
union
{
struct qiov_item q ;
struct iovec s ;
} union_iovec ;
CONFIRM(sizeof(struct qiov_item) == sizeof(struct iovec)) ;
CONFIRM(offsetof(struct qiov_item, base) == offsetof(struct iovec, iov_base)) ;
CONFIRM(sizeof (union_iovec.q. base) == sizeof (union_iovec.s.iov_base)) ;
CONFIRM(offsetof(struct qiov_item, len) == offsetof(struct iovec, iov_len)) ;
CONFIRM(sizeof (union_iovec.q. len) == sizeof (union_iovec.s.iov_len)) ;
/*==============================================================================
* Flexible size "struct iovec"
*
* NB: a completely zero structure is a valid, empty qiovec.
*/
struct qiovec
{
qiov_vector vec ; /* the actual iovec array */
uint i_get ; /* next entry to get */
uint i_put ; /* next entry to put */
uint i_alloc ; /* number of entries allocated */
bool writing ; /* started, but not finished */
} ;
typedef struct qiovec* qiovec ;
typedef struct qiovec qiovec_t[1] ;
enum
{
QIOVEC_INIT_ALL_ZEROS = true
} ;
/*==============================================================================
* Functions
*/
extern void qiovec_start_up(void) ;
extern qiovec qiovec_init_new(qiovec qiov) ;
extern qiovec qiovec_reset(qiovec qiov, bool free_structure) ;
Inline qiovec qiovec_free(qiovec qiov) ;
Inline bool qiovec_empty(qiovec qiov) ;
extern size_t qiovec_length(qiovec qiov) ;
extern void qiovec_clear(qiovec qiov) ;
extern int qiovec_write_nb(int fd, qiovec qiov) ;
Inline uint qiovec_count(qiovec qiov) ;
Inline void qiovec_push_this(qiovec qiov, const void* base, size_t len) ;
Inline void qiovec_push(qiovec qiov, qiov_item item) ;
Inline void qiovec_pop(qiovec qiov, qiov_item item) ;
Inline void qiovec_shift(qiovec qiov, qiov_item item) ;
Inline void qiovec_unshift(qiovec qiov, qiov_item item) ;
extern int iovec_write_nb(int fd, struct iovec* p_iov, int n) ;
Inline void iovec_set(struct iovec* p_iov, const void* base, size_t len) ;
Private void qiovec_extend(qiovec qiov) ;
Private void qiovec_shuffle(qiovec qiov) ;
/*------------------------------------------------------------------------------
* Free given qiovec
*
* It is the caller's responsibility to free anything that the qiovec may
* point to.
*
* Returns: NULL
*/
Inline qiovec qiovec_free(qiovec qiov)
{
return qiovec_reset(qiov, free_it) ;
} ;
/*------------------------------------------------------------------------------
* Is given qiov empty ?
*
* NB: arranges to never add zero length entries to the iovec vector, so
* is empty when there are no active entries.
*/
Inline bool
qiovec_empty(qiovec qiov)
{
return (qiov->i_get == qiov->i_put) ;
} ;
/*------------------------------------------------------------------------------
* How many entries in the given qiov ?
*/
Inline uint
qiovec_count(qiovec qiov)
{
return (qiov->i_put - qiov->i_get) ;
} ;
/*------------------------------------------------------------------------------
* Push to qiov -- same as qiovec_push, but with item.
*
* Ignores zero length items.
*/
Inline void
qiovec_push_this(qiovec qiov, const void* base, size_t len)
{
qiov_item_t item ;
item->base = base ;
item->len = len ;
qiovec_push(qiov, item) ;
} ;
/*------------------------------------------------------------------------------
* Push (copy of) item to qiov -- ie append it to the end of the vector.
*/
Inline void
qiovec_push(qiovec qiov, qiov_item item)
{
if (item->len != 0)
{
if (qiov->i_put >= qiov->i_alloc)
qiovec_extend(qiov) ;
qiov->vec[qiov->i_put++] = *item ;
} ;
} ;
/*------------------------------------------------------------------------------
* Pop last item from qiov -- return empty item if none.
*/
Inline void
qiovec_pop(qiovec qiov, qiov_item item)
{
if (qiov->i_get < qiov->i_put)
{
*item = qiov->vec[--qiov->i_put] ;
if (qiov->i_get == qiov->i_put)
qiov->i_get = qiov->i_put = 0 ;
}
else
{
assert(qiov->i_get == qiov->i_put) ;
item->base = NULL ;
item->len = 0 ;
qiov->i_get = qiov->i_put = 0 ;
} ;
} ;
/*------------------------------------------------------------------------------
* Shift first item off qiov -- return empty item if none.
*/
Inline void
qiovec_shift(qiovec qiov, qiov_item item)
{
if (qiov->i_get < qiov->i_put)
{
*item = qiov->vec[qiov->i_get++] ;
if (qiov->i_get == qiov->i_put)
qiov->i_get = qiov->i_put = 0 ;
}
else
{
assert(qiov->i_get == qiov->i_put) ;
item->base = NULL ;
item->len = 0 ;
qiov->i_get = qiov->i_put = 0 ;
} ;
} ;
/*------------------------------------------------------------------------------
* Unshift item onto qiov -- ie prepend it to the start of the vector.
*/
Inline void
qiovec_unshift(qiovec qiov, qiov_item item)
{
if (qiov->i_get == 0)
{
if (qiov->i_put == 0)
return qiovec_push(qiov, item) ;
qiovec_shuffle(qiov) ;
} ;
if (item->len != 0)
qiov->vec[--qiov->i_get] = *item ;
} ;
/*------------------------------------------------------------------------------
* Set a given struct iovec
*
* Gets around the fact that the standard structure does not have a const
* pointer !
*/
#include "miyagi.h"
Inline void
iovec_set(struct iovec* p_iov, const void* base, size_t len)
{
p_iov->iov_base = miyagi(base) ;
p_iov->iov_len = len ;
} ;
#endif /* _ZEBRA_QIOVEC_H */
|