tizen 2.4 release
[external/nghttp2.git] / lib / nghttp2_buf.h
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2014 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #ifndef NGHTTP2_BUF_H
26 #define NGHTTP2_BUF_H
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif /* HAVE_CONFIG_H */
31
32 #include <nghttp2/nghttp2.h>
33
34 #include "nghttp2_int.h"
35 #include "nghttp2_mem.h"
36
37 typedef struct {
38   /* This points to the beginning of the buffer. The effective range
39      of buffer is [begin, end). */
40   uint8_t *begin;
41   /* This points to the memory one byte beyond the end of the
42      buffer. */
43   uint8_t *end;
44   /* The position indicator for effective start of the buffer. pos <=
45      last must be hold. */
46   uint8_t *pos;
47   /* The position indicator for effective one beyond of the end of the
48      buffer. last <= end must be hold. */
49   uint8_t *last;
50   /* Mark arbitrary position in buffer [begin, end) */
51   uint8_t *mark;
52 } nghttp2_buf;
53
54 #define nghttp2_buf_len(BUF) ((ssize_t)((BUF)->last - (BUF)->pos))
55 #define nghttp2_buf_avail(BUF) ((ssize_t)((BUF)->end - (BUF)->last))
56 #define nghttp2_buf_mark_avail(BUF) ((ssize_t)((BUF)->mark - (BUF)->last))
57 #define nghttp2_buf_cap(BUF) ((ssize_t)((BUF)->end - (BUF)->begin))
58
59 #define nghttp2_buf_pos_offset(BUF) ((ssize_t)((BUF)->pos - (BUF)->begin))
60 #define nghttp2_buf_last_offset(BUF) ((ssize_t)((BUF)->last - (BUF)->begin))
61
62 #define nghttp2_buf_shift_right(BUF, AMT)                                      \
63   do {                                                                         \
64     (BUF)->pos += AMT;                                                         \
65     (BUF)->last += AMT;                                                        \
66   } while (0)
67
68 #define nghttp2_buf_shift_left(BUF, AMT)                                       \
69   do {                                                                         \
70     (BUF)->pos -= AMT;                                                         \
71     (BUF)->last -= AMT;                                                        \
72   } while (0)
73
74 /*
75  * Initializes the |buf|. No memory is allocated in this function. Use
76  * nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
77  */
78 void nghttp2_buf_init(nghttp2_buf *buf);
79
80 /*
81  * Initializes the |buf| and allocates at least |initial| bytes of
82  * memory.
83  *
84  * This function returns 0 if it succeeds, or one of the following
85  * negative error codes:
86  *
87  * NGHTTP2_ERR_NOMEM
88  *     Out of memory
89  */
90 int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem);
91
92 /*
93  * Frees buffer in |buf|.
94  */
95 void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem);
96
97 /*
98  * Extends buffer so that nghttp2_buf_cap() returns at least
99  * |new_cap|. If extensions took place, buffer pointers in |buf| will
100  * change.
101  *
102  * This function returns 0 if it succeeds, or one of the followings
103  * negative error codes:
104  *
105  * NGHTTP2_ERR_NOMEM
106  *     Out of memory
107  */
108 int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem);
109
110 /*
111  * Resets pos, last, mark member of |buf| to buf->begin.
112  */
113 void nghttp2_buf_reset(nghttp2_buf *buf);
114
115 /*
116  * Initializes |buf| using supplied buffer |begin| of length
117  * |len|. Semantically, the application should not call *_reserve() or
118  * nghttp2_free() functions for |buf|.
119  */
120 void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
121
122 struct nghttp2_buf_chain;
123
124 typedef struct nghttp2_buf_chain nghttp2_buf_chain;
125
126 /* Chains 2 buffers */
127 struct nghttp2_buf_chain {
128   /* Points to the subsequent buffer. NULL if there is no such
129      buffer. */
130   nghttp2_buf_chain *next;
131   nghttp2_buf buf;
132 };
133
134 typedef struct {
135   /* Points to the first buffer */
136   nghttp2_buf_chain *head;
137   /* Buffer pointer where write occurs. */
138   nghttp2_buf_chain *cur;
139   /* Memory allocator */
140   nghttp2_mem *mem;
141   /* The buffer capacity of each buf */
142   size_t chunk_length;
143   /* The maximum number of nghttp2_buf_chain */
144   size_t max_chunk;
145   /* The number of nghttp2_buf_chain allocated */
146   size_t chunk_used;
147   /* The number of nghttp2_buf_chain to keep on reset */
148   size_t chunk_keep;
149   /* pos offset from begin in each buffers. On initialization and
150      reset, buf->pos and buf->last are positioned at buf->begin +
151      offset. */
152   size_t offset;
153 } nghttp2_bufs;
154
155 /*
156  * This is the same as calling nghttp2_bufs_init2 with the given
157  * arguments and offset = 0.
158  */
159 int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
160                       nghttp2_mem *mem);
161
162 /*
163  * This is the same as calling nghttp2_bufs_init3 with the given
164  * arguments and chunk_keep = max_chunk.
165  */
166 int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
167                        size_t max_chunk, size_t offset, nghttp2_mem *mem);
168
169 /*
170  * Initializes |bufs|. Each buffer size is given in the
171  * |chunk_length|.  The maximum number of buffers is given in the
172  * |max_chunk|.  On reset, first |chunk_keep| buffers are kept and
173  * remaining buffers are deleted.  Each buffer will have bufs->pos and
174  * bufs->last shifted to left by |offset| bytes on creation and reset.
175  *
176  * This function allocates first buffer.  bufs->head and bufs->cur
177  * will point to the first buffer after this call.
178  *
179  * This function returns 0 if it succeeds, or one of the following
180  * negative error codes:
181  *
182  * NGHTTP2_ERR_NOMEM
183  *     Out of memory.
184  * NGHTTP2_ERR_INVALID_ARGUMENT
185  *     chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
186  *     long.
187  */
188 int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
189                        size_t max_chunk, size_t chunk_keep, size_t offset,
190                        nghttp2_mem *mem);
191
192 /*
193  * Frees any related resources to the |bufs|.
194  */
195 void nghttp2_bufs_free(nghttp2_bufs *bufs);
196
197 /*
198  * Initializes |bufs| using supplied buffer |begin| of length |len|.
199  * The first buffer bufs->head uses buffer |begin|.  The buffer size
200  * is fixed and no allocate extra chunk buffer is allocated.  In other
201  * words, max_chunk = chunk_keep = 1.  To free the resource allocated
202  * for |bufs|, use nghttp2_bufs_wrap_free().
203  *
204  * This function returns 0 if it succeeds, or one of the following
205  * negative error codes:
206  *
207  * NGHTTP2_ERR_NOMEM
208  *     Out of memory.
209  */
210 int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
211                            nghttp2_mem *mem);
212
213 /*
214  * Frees any related resource to the |bufs|.  This function does not
215  * free supplied buffer provided in nghttp2_bufs_wrap_init().
216  */
217 void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
218
219 /*
220  * Reallocates internal buffer using |chunk_length|.  The max_chunk,
221  * chunk_keep and offset do not change.  After successful allocation
222  * of new buffer, previous buffers are deallocated without copying
223  * anything into new buffers.  chunk_used is reset to 1.
224  *
225  * This function returns 0 if it succeeds, or one of the following
226  * negative error codes:
227  *
228  * NGHTTP2_ERR_NOMEM
229  *     Out of memory.
230  * NGHTTP2_ERR_INVALID_ARGUMENT
231  *     chunk_length < offset
232  */
233 int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
234
235 /*
236  * Appends the |data| of length |len| to the |bufs|. The write starts
237  * at bufs->cur->buf.last. A new buffers will be allocated to store
238  * all data.
239  *
240  * This function returns 0 if it succeeds, or one of the following
241  * negative error codes:
242  *
243  * NGHTTP2_ERR_NOMEM
244  *     Out of memory.
245  * NGHTTP2_ERR_BUFFER_ERROR
246  *     Out of buffer space.
247  */
248 int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
249
250 /*
251  * Appends a single byte |b| to the |bufs|. The write starts at
252  * bufs->cur->buf.last. A new buffers will be allocated to store all
253  * data.
254  *
255  * This function returns 0 if it succeeds, or one of the following
256  * negative error codes:
257  *
258  * NGHTTP2_ERR_NOMEM
259  *     Out of memory.
260  * NGHTTP2_ERR_BUFFER_ERROR
261  *     Out of buffer space.
262  */
263 int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
264
265 /*
266  * Behaves like nghttp2_bufs_addb(), but this does not update
267  * buf->last pointer.
268  */
269 int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
270
271 #define nghttp2_bufs_fast_addb(BUFS, B)                                        \
272   do {                                                                         \
273     *(BUFS)->cur->buf.last++ = B;                                              \
274   } while (0)
275
276 #define nghttp2_bufs_fast_addb_hold(BUFS, B)                                   \
277   do {                                                                         \
278     *(BUFS)->cur->buf.last = B;                                                \
279   } while (0)
280
281 /*
282  * Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
283  * will be allocated if necessary.
284  *
285  * This function returns 0 if it succeeds, or one of the following
286  * negative error codes:
287  *
288  * NGHTTP2_ERR_NOMEM
289  *     Out of memory.
290  * NGHTTP2_ERR_BUFFER_ERROR
291  *     Out of buffer space.
292  */
293 int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
294
295 /*
296  * Behaves like nghttp2_bufs_orb(), but does not update buf->last
297  * pointer.
298  */
299 int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
300
301 #define nghttp2_bufs_fast_orb(BUFS, B)                                         \
302   do {                                                                         \
303     *(BUFS)->cur->buf.last++ |= B;                                             \
304   } while (0)
305
306 #define nghttp2_bufs_fast_orb_hold(BUFS, B)                                    \
307   do {                                                                         \
308     *(BUFS)->cur->buf.last |= B;                                               \
309   } while (0)
310
311 /*
312  * Copies all data stored in |bufs| to the contagious buffer.  This
313  * function allocates the contagious memory to store all data in
314  * |bufs| and assigns it to |*out|.
315  *
316  * On successful return, nghttp2_bufs_len(bufs) returns 0, just like
317  * after calling nghttp2_bufs_reset().
318
319  * This function returns the length of copied data and assigns the
320  * pointer to copied data to |*out| if it succeeds, or one of the
321  * following negative error codes:
322  *
323  * NGHTTP2_ERR_NOMEM
324  *     Out of memory
325  */
326 ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
327
328 /*
329  * Resets |bufs| and makes the buffers empty.
330  */
331 void nghttp2_bufs_reset(nghttp2_bufs *bufs);
332
333 /*
334  * Moves bufs->cur to bufs->cur->next.  If resulting bufs->cur is
335  * NULL, this function allocates new buffers and bufs->cur points to
336  * it.
337  *
338  * This function returns 0 if it succeeds, or one of the following
339  * negative error codes:
340  *
341  * NGHTTP2_ERR_NOMEM
342  *     Out of memory
343  * NGHTTP2_ERR_BUFFER_ERROR
344  *     Out of buffer space.
345  */
346 int nghttp2_bufs_advance(nghttp2_bufs *bufs);
347
348 /* Sets bufs->cur to bufs->head */
349 #define nghttp2_bufs_rewind(BUFS)                                              \
350   do {                                                                         \
351     (BUFS)->cur = (BUFS)->head;                                                \
352   } while (0)
353
354 /*
355  * Move bufs->cur, from the current position, using next member, to
356  * the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
357  * which satisfies nghttp2_buf_len(buf) == 0.  If
358  * nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
359  * bufs->cur is unchanged.
360  */
361 void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
362
363 /*
364  * Returns nonzero if bufs->cur->next is not emtpy.
365  */
366 int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
367
368 #define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
369
370 /*
371  * Returns the buffer length of |bufs|.
372  */
373 ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs);
374
375 #endif /* NGHTTP2_BUF_H */