Moved most buffer debug messages to DBG2.
[people/xl0/gpxe.git] / src / core / ebuffer.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 /**
20  * @file
21  *
22  * Automatically expanding buffers
23  *
24  */
25
26 #include <errno.h>
27 #include <gpxe/buffer.h>
28 #include <gpxe/umalloc.h>
29 #include <gpxe/ebuffer.h>
30
31 /**
32  * Expand expandable buffer
33  *
34  * @v buffer            Buffer descriptor
35  * @v new_len           Required new size
36  * @ret rc              Return status code
37  */
38 static int ebuffer_expand ( struct buffer *buffer, size_t new_len ) {
39         size_t actual_len = 1;
40         userptr_t new_addr;
41
42         /* Round new_len up to the nearest power of two, to reduce
43          * total number of reallocations required.  Don't do this for
44          * the first expansion; this allows for protocols that do
45          * actually know the exact length in advance.
46          */
47         if ( buffer->len ) {
48                 while ( actual_len < new_len )
49                         actual_len <<= 1;
50         } else {
51                 actual_len = new_len;
52         }
53
54         /* Reallocate buffer */
55 #warning "urealloc() has issues with length zero"
56         new_addr = urealloc ( buffer->addr, // actual_len );
57                               actual_len ? actual_len : 1 );
58         if ( ! new_addr )
59                 return -ENOMEM;
60
61         buffer->addr = new_addr;
62         buffer->len = actual_len;
63         return 0;
64 }
65
66 /**
67  * Allocate expandable buffer
68  *
69  * @v buffer            Buffer descriptor
70  * @v len               Initial length (may be zero)
71  * @ret rc              Return status code
72  *
73  * Allocates space for the buffer and stores it in @c buffer->addr.
74  * The space must eventually be freed by calling ufree(buffer->addr).
75  */
76 int ebuffer_alloc ( struct buffer *buffer, size_t len ) {
77         memset ( buffer, 0, sizeof ( *buffer ) );
78         buffer->expand = ebuffer_expand;
79         return ebuffer_expand ( buffer, len );
80 }