5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1998 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
27 SilcBuffer is very simple and easy to use, yet you can do to the
28 buffer almost anything you want with its method functions. The buffer
29 is constructed of four different data sections that in whole creates
30 the allocated data area. Following short description of the fields
35 True length of the buffer. This is set at the allocation of the
36 buffer and it should not be touched after that. This field should
37 be considered read-only.
41 Length of the currently valid data area. Tells the length of the
42 data at the buffer. This is set to zero at the allocation of the
43 buffer and should not be updated by hand. Method functions of the
44 buffer automatically updates this field. However, it is not
45 read-only field and can be updated manually if necessary.
49 Head of the allocated buffer. This is the start of the allocated
50 data area and remains as same throughout the lifetime of the buffer.
51 However, the end of the head area or the start of the currently valid
52 data area is variable.
54 --------------------------------
55 | head | data | tail |
56 --------------------------------
59 Current head section in the buffer is sb->data - sb->head.
63 Currently valid data area. This is the start of the currently valid
64 main data area. The data area is variable in all directions.
66 --------------------------------
67 | head | data | tail |
68 --------------------------------
71 Current valid data area in the buffer is sb->tail - sb->data.
75 Tail of the buffer. This is the end of the currently valid data area
76 or start of the tail area. The start of the tail area is variable.
78 --------------------------------
79 | head | data | tail |
80 --------------------------------
83 Current tail section in the buffer is sb->end - sb->tail.
87 End of the allocated buffer. This is the end of the allocated data
88 area and remains as same throughout the lifetime of the buffer.
89 Usually this field is not needed except when checking the size
92 --------------------------------
93 | head | data | tail |
94 --------------------------------
97 Length of the entire buffer is (ie. truelen) sb->end - sb->head.
99 Currently valid data area is considered to be the main data area in
100 the buffer. However, the entire buffer is of course valid data and can
101 be used as such. Usually head section of the buffer includes different
102 kind of headers or similiar. Data section includes the main data of
103 the buffer. Tail section can be seen as a reserve space of the data
104 section. Tail section can be pulled towards end thus the data section
107 This buffer scheme is based on Linux kernel's Socket Buffer, the
108 idea were taken directly from there and credits should go there.
112 typedef struct SilcBufferStruct {
113 unsigned int truelen;
120 /* Method functions. */
121 unsigned char *(*pull)(struct SilcBufferStruct *, unsigned int);
122 unsigned char *(*push)(struct SilcBufferStruct *, unsigned int);
123 unsigned char *(*pull_tail)(struct SilcBufferStruct *, unsigned int);
124 unsigned char *(*push_tail)(struct SilcBufferStruct *, unsigned int);
125 unsigned char *(*put)(struct SilcBufferStruct *, unsigned char *,
127 unsigned char *(*put_head)(struct SilcBufferStruct *, unsigned char *,
129 unsigned char *(*put_tail)(struct SilcBufferStruct *, unsigned char *,
133 typedef SilcBufferObject *SilcBuffer;
137 /* Returns the true length of the buffer. This is used to pull
138 the buffer area to the end of the buffer. */
139 #define SILC_BUFFER_END(x) ((x)->end - (x)->head)
141 #ifndef SILC_DEBUG /* When we are not doing debugging we use
142 optimized inline buffer functions. */
144 * Optimized buffer managing routines. These are short inline
148 /* Pulls current data area towards end. The length of the currently
149 valid data area is also decremented. Returns pointer to the data
153 ---------------------------------
154 | head | data | tail |
155 ---------------------------------
157 Pulls the start of the data area.
159 ---------------------------------
160 | head | data | tail |
161 ---------------------------------
166 unsigned char *silc_buffer_pull(SilcBuffer sb, unsigned int len)
168 unsigned char *old_data = sb->data;
170 assert(len <= (sb->tail - sb->data));
178 /* Pushes current data area towards beginning. Length of the currently
179 valid data area is also incremented. Returns a pointer to the
180 data area before pushing.
183 ---------------------------------
184 | head | data | tail |
185 ---------------------------------
187 Pushes the start of the data area.
189 ---------------------------------
190 | head | data | tail |
191 ---------------------------------
196 unsigned char *silc_buffer_push(SilcBuffer sb, unsigned int len)
198 unsigned char *old_data = sb->data;
200 assert((sb->data - len) >= sb->head);
208 /* Pulls current tail section towards end. Length of the current valid
209 data area is also incremented. Returns a pointer to the data area
213 ---------------------------------
214 | head | data | tail |
215 ---------------------------------
217 Pulls the start of the tail section.
219 ---------------------------------
220 | head | data | tail |
221 ---------------------------------
226 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, unsigned int len)
228 unsigned char *old_tail = sb->tail;
230 assert((sb->end - sb->tail) >= len);
238 /* Pushes current tail section towards beginning. Length of the current
239 valid data area is also decremented. Returns a pointer to the
240 tail section before pushing.
243 ---------------------------------
244 | head | data | tail |
245 ---------------------------------
247 Pushes the start of the tail section.
249 ---------------------------------
250 | head | data | tail |
251 ---------------------------------
256 unsigned char *silc_buffer_push_tail(SilcBuffer sb, unsigned int len)
258 unsigned char *old_tail = sb->tail;
260 assert((sb->tail - len) >= sb->data);
268 /* Puts data at the head of the buffer. Returns pointer to the copied
272 ---------------------------------
273 | head | data | tail |
274 ---------------------------------
276 Puts data to the head section.
280 unsigned char *silc_buffer_put_head(SilcBuffer sb,
284 assert((sb->data - sb->head) >= len);
285 return memcpy(sb->head, data, len);
288 /* Puts data at the start of the valid data area. Returns a pointer
289 to the copied data area.
292 ---------------------------------
293 | head | data | tail |
294 ---------------------------------
296 Puts data to the data section.
300 unsigned char *silc_buffer_put(SilcBuffer sb,
304 assert((sb->tail - sb->data) >= len);
305 return memcpy(sb->data, data, len);
308 /* Puts data at the tail of the buffer. Returns pointer to the copied
312 ---------------------------------
313 | head | data | tail |
314 ---------------------------------
316 Puts data to the tail section.
320 unsigned char *silc_buffer_put_tail(SilcBuffer sb,
324 assert((sb->end - sb->tail) >= len);
325 return memcpy(sb->tail, data, len);
328 #endif /* !SILC_DEBUG */
331 SilcBuffer silc_buffer_alloc(unsigned int len);
332 void silc_buffer_free(SilcBuffer sb);
334 unsigned char *silc_buffer_pull(SilcBuffer sb, unsigned int len);
335 unsigned char *silc_buffer_push(SilcBuffer sb, unsigned int len);
336 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, unsigned int len);
337 unsigned char *silc_buffer_push_tail(SilcBuffer sb, unsigned int len);
338 unsigned char *silc_buffer_put_head(SilcBuffer sb,
341 unsigned char *silc_buffer_put(SilcBuffer sb,
344 unsigned char *silc_buffer_put_tail(SilcBuffer sb,