71f31b4b3272a592ab3a3ef36a3b4fca593d0774
[apps/madmutt.git] / lib-lib / buffer.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2006 Pierre Habouzit
18  */
19
20 /*
21  * Copyright notice from original mutt:
22  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
23  *
24  * This file is part of mutt-ng, see http://www.muttng.org/.
25  * It's licensed under the GNU General Public License,
26  * please see the file GPL in the top level source directory.
27  */
28
29 #include "lib-lib.h"
30
31 #define BUFSIZ_INCREMENT  1024
32
33 void buffer_resize(buffer_t *buf, ssize_t newsize)
34 {
35     if (newsize >= buf->size) {
36         /* rounds newsize to the 1024 multiple just after newsize+1 */
37         newsize = (newsize + BUFSIZ_INCREMENT) & ~(BUFSIZ_INCREMENT - 1);
38         p_realloc(&buf->data, newsize);
39     }
40 }
41
42
43
44
45 /****** LEGACY BUFFERS *******/
46
47 /*
48  * Creates and initializes a BUFFER*. If passed an existing BUFFER*,
49  * just initializes. Frees anything already in the buffer.
50  *
51  * Disregards the 'destroy' flag, which seems reserved for caller.
52  * This is bad, but there's no apparent protocol for it.
53  */
54 BUFFER *mutt_buffer_init(BUFFER *b)
55 {
56     if (!b) {
57         b = p_new(BUFFER, 1);
58     }
59     p_delete(&b->data);
60     p_clear(b, 1);
61     return b;
62 }
63
64 /*
65  * Creates and initializes a BUFFER*. If passed an existing BUFFER*,
66  * just initializes. Frees anything already in the buffer. Copies in
67  * the seed string.
68  *
69  * Disregards the 'destroy' flag, which seems reserved for caller.
70  * This is bad, but there's no apparent protocol for it.
71  */
72 BUFFER *mutt_buffer_from(BUFFER * b, const char *seed)
73 {
74     if (!seed)
75         return NULL;
76
77     b = mutt_buffer_init(b);
78     b->dsize = m_strlen(seed);
79     b->data  = m_strdup(seed);
80     b->dptr  = (char *)b->data + b->dsize;
81     return b;
82 }
83
84 void mutt_buffer_free(BUFFER **p)
85 {
86     if (p && *p) {
87         p_delete(&(*p)->data);
88         p_delete(p);
89     }
90 }
91
92 /* dynamically grows a BUFFER to accomodate s, in increments of 128 bytes.
93  * Always one byte bigger than necessary for the null terminator, and
94  * the buffer is always null-terminated */
95 void mutt_buffer_add(BUFFER *buf, const char *s, ssize_t len)
96 {
97     size_t offset;
98
99     if (buf->dptr + len + 1 > buf->data + buf->dsize) {
100         offset = buf->dptr - buf->data;
101         buf->dsize += ((len + 1 + 127) & ~127);
102         p_realloc(&buf->data, buf->dsize);
103         buf->dptr = buf->data + offset;
104     }
105     memcpy(buf->dptr, s, len);
106     buf->dptr += len;
107     *buf->dptr = '\0';
108 }
109
110 ssize_t buffer_addvf(buffer_t *buf, const char *fmt, va_list args)
111 {
112     ssize_t len;
113     va_list ap;
114
115     va_copy(ap, args);
116     buffer_ensure(buf, BUFSIZ);
117
118     len = vsnprintf(buf->data + buf->len, buf->size - buf->len, fmt, args);
119     if (len < 0) {
120         len = 0;
121     }
122     if (len >= buf->size - buf->len) {
123         buffer_ensure(buf, len);
124         vsnprintf(buf->data + buf->len, buf->size - buf->len, fmt, ap);
125     }
126     buf->len += len;
127     buf->data[buf->len] = '\0';
128
129     return len;
130 }
131
132 ssize_t buffer_addf(buffer_t *buf, const char *fmt, ...) {
133     ssize_t res;
134     va_list args;
135     va_start(args, fmt);
136     res = buffer_addvf(buf, fmt, args);
137     va_end(args);
138     return res;
139 }