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