ccaf1f572e7abb704b86d60d29aafc6d72e065d5
[silc.git] / lib / silcutil / silcbuffer.c
1 /*
2
3   silcbuffer.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1998 - 2000 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.1  2000/09/13 17:45:15  priikone
24  *      Splitted SILC core library. Core library includes now only
25  *      SILC protocol specific stuff. New utility library includes the
26  *      old stuff from core library that is more generic purpose stuff.
27  *
28  * Revision 1.2  2000/07/05 06:06:35  priikone
29  *      Global cosmetic change.
30  *
31  * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
32  *      Imported from internal CVS/Added Log headers.
33  *
34  *
35  */
36
37 #include "silcincludes.h"
38 #include "silcbuffer.h"
39
40 static unsigned char *silc_buffer_pull_i(SilcBuffer sb, unsigned int len)
41 {
42   return silc_buffer_pull(sb, len);
43 }
44
45 static unsigned char *silc_buffer_push_i(SilcBuffer sb, unsigned int len)
46 {
47   return silc_buffer_push(sb, len);
48 }
49
50 static unsigned char *silc_buffer_pull_tail_i(SilcBuffer sb, unsigned int len)
51 {
52   return silc_buffer_pull_tail(sb, len);
53 }
54
55 static unsigned char *silc_buffer_push_tail_i(SilcBuffer sb, unsigned int len)
56 {
57   return silc_buffer_push_tail(sb, len);
58 }
59
60 static unsigned char *silc_buffer_put_head_i(SilcBuffer sb, 
61                                              unsigned char *data,
62                                              unsigned int len)
63 {
64   return silc_buffer_put_head(sb, data, len);
65 }
66
67 static unsigned char *silc_buffer_put_i(SilcBuffer sb, 
68                                         unsigned char *data,
69                                         unsigned int len)
70 {
71   return silc_buffer_put(sb, data, len);
72 }
73
74 static unsigned char *silc_buffer_put_tail_i(SilcBuffer sb, 
75                                              unsigned char *data,
76                                              unsigned int len)
77 {
78   return silc_buffer_put_tail(sb, data, len);
79 }
80
81 /* Allocates a new SilcBuffer and returns a pointer to it. The data
82    area of the new buffer is set to the real beginning of the buffer. 
83
84    Buffer after allocation:
85    ---------------------------------
86    |                               |
87    ---------------------------------
88    ^ head, data, tail              ^ end
89
90 */
91
92 SilcBuffer silc_buffer_alloc(unsigned int len)
93 {
94   SilcBuffer sb;
95   unsigned char *data;
96
97   /* Allocate new SilcBuffer */
98   sb = silc_calloc(1, sizeof(*sb));
99
100   /* Allocate the actual data area */
101   data = silc_calloc(len, sizeof(*data));
102   memset(data, 0, len);
103
104   /* Set pointers to the new buffer */
105   sb->truelen = len;
106   sb->len = 0;
107   sb->head = data;
108   sb->data = data;
109   sb->tail = data;
110   sb->end = data + sb->truelen;
111
112   /* Set the function pointers */
113   sb->pull = silc_buffer_pull_i;
114   sb->push = silc_buffer_push_i;
115   sb->pull_tail = silc_buffer_pull_tail_i;
116   sb->push_tail = silc_buffer_push_tail_i;
117   sb->put = silc_buffer_put_i;
118   sb->put_head = silc_buffer_put_head_i;
119   sb->put_tail = silc_buffer_put_tail_i;
120
121   return sb;
122 }
123
124 /* Free's a SilcBuffer */
125
126 void silc_buffer_free(SilcBuffer sb)
127 {
128   if (sb) {
129     memset(sb->head, 'F', sb->truelen);
130     silc_free(sb->head);
131     silc_free(sb);
132   }
133 }
134
135 #ifdef SILC_DEBUG               /* If we are doing debugging we won't
136                                    have the optimized inline buffer functions
137                                    available as optimization is not set
138                                    to compiler. These normal routines are
139                                    used in debugging mode. */
140
141 /* XXX These are currenly obsolte as SILC is compiled always with -O
142    flag thus inline functions maybe used. So, fix these. */
143
144 /* Pulls current data area towards end. The length of the currently
145    valid data area is also decremented. Returns pointer to the data
146    area before pulling. 
147
148    Example:
149    ---------------------------------
150    | head  | data       | tail     |
151    ---------------------------------
152            ^
153            Pulls the start of the data area.
154
155    ---------------------------------
156    | head     | data    | tail     |
157    ---------------------------------
158            ^
159 */
160
161 unsigned char *silc_buffer_pull(SilcBuffer sb, unsigned int len)
162 {
163   unsigned char *old_data = sb->data;
164
165   assert(len <= (sb->tail - sb->data));
166
167   sb->data += len;
168   sb->len -= len;
169
170   return old_data;
171 }
172
173 /* Pushes current data area towards beginning. Length of the currently
174    valid data area is also incremented. Returns a pointer to the 
175    data area before pushing. 
176
177    Example:
178    ---------------------------------
179    | head     | data    | tail     |
180    ---------------------------------
181               ^
182               Pushes the start of the data area.
183
184    ---------------------------------
185    | head  | data       | tail     |
186    ---------------------------------
187               ^
188 */
189
190 unsigned char *silc_buffer_push(SilcBuffer sb, unsigned int len)
191 {
192   unsigned char *old_data = sb->data;
193
194   assert((sb->data - len) >= sb->head);
195
196   sb->data -= len;
197   sb->len += len;
198
199   return old_data;
200 }
201
202 /* Pulls current tail section towards end. Length of the current valid
203    data area is also incremented. Returns a pointer to the data area 
204    before pulling.
205
206    Example:
207    ---------------------------------
208    | head  | data       | tail     |
209    ---------------------------------
210                         ^
211                         Pulls the start of the tail section.
212
213    ---------------------------------
214    | head  | data           | tail |
215    ---------------------------------
216                         ^
217 */
218
219 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, unsigned int len)
220 {
221   unsigned char *old_tail = sb->tail;
222
223   assert((sb->end - sb->tail) >= len);
224
225   sb->tail += len;
226   sb->len += len;
227
228   return old_tail;
229 }
230
231 /* Pushes current tail section towards beginning. Length of the current
232    valid data area is also decremented. Returns a pointer to the 
233    tail section before pushing. 
234
235    Example:
236    ---------------------------------
237    | head  | data           | tail |
238    ---------------------------------
239                             ^
240                             Pushes the start of the tail section.
241
242    ---------------------------------
243    | head  | data       | tail     |
244    ---------------------------------
245                             ^
246 */
247
248 unsigned char *silc_buffer_push_tail(SilcBuffer sb, unsigned int len)
249 {
250   unsigned char *old_tail = sb->tail;
251
252   assert((sb->tail - len) >= sb->data);
253
254   sb->tail -= len;
255   sb->len -= len;
256
257   return old_tail;
258 }
259
260 /* Puts data at the head of the buffer. Returns pointer to the copied
261    data area. 
262    
263    Example:
264    ---------------------------------
265    | head  | data       | tail     |
266    ---------------------------------
267    ^
268    Puts data to the head section. 
269 */
270
271 unsigned char *silc_buffer_put_head(SilcBuffer sb, 
272                                     unsigned char *data,
273                                     unsigned int len)
274 {
275   assert((sb->data - sb->head) >= len);
276   return memcpy(sb->head, data, len);
277 }
278
279 /* Puts data at the start of the valid data area. Returns a pointer 
280    to the copied data area. 
281
282    Example:
283    ---------------------------------
284    | head  | data       | tail     |
285    ---------------------------------
286            ^
287            Puts data to the data section.
288 */
289
290 unsigned char *silc_buffer_put(SilcBuffer sb, 
291                                unsigned char *data,
292                                unsigned int len)
293 {
294   assert((sb->tail - sb->data) >= len);
295   return memcpy(sb->data, data, len);
296 }
297
298 /* Puts data at the tail of the buffer. Returns pointer to the copied
299    data area. 
300
301    Example:
302    ---------------------------------
303    | head  | data           | tail |
304    ---------------------------------
305                             ^
306                             Puts data to the tail section.
307 */
308
309 unsigned char *silc_buffer_put_tail(SilcBuffer sb, 
310                                     unsigned char *data,
311                                     unsigned int len)
312 {
313   assert((sb->end - sb->tail) >= len);
314   return memcpy(sb->tail, data, len);
315 }
316
317 #endif