2 * libdpkg - Debian packaging suite library routines
3 * varbuf.c - variable length expandable buffer handling
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2015 Guillem Jover <guillem@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 #include <dpkg/i18n.h>
30 #include <dpkg/dpkg.h>
31 #include <dpkg/dpkg-db.h>
34 varbuf_new(size_t size
)
38 v
= m_malloc(sizeof(*v
));
45 varbuf_init(struct varbuf
*v
, size_t size
)
50 v
->buf
= m_malloc(size
);
56 varbuf_grow(struct varbuf
*v
, size_t need_size
)
60 /* Make sure the varbuf is in a sane state. */
61 if (v
->size
< v
->used
)
62 internerr("varbuf used(%zu) > size(%zu)", v
->used
, v
->size
);
64 /* Check if we already have enough room. */
65 if ((v
->size
- v
->used
) >= need_size
)
68 /* Check if we overflow. */
69 new_size
= (v
->size
+ need_size
) * 2;
70 if (new_size
< v
->size
)
71 ohshit(_("cannot grow varbuf to size %zu; it would overflow"),
75 v
->buf
= m_realloc(v
->buf
, v
->size
);
79 varbuf_trunc(struct varbuf
*v
, size_t used_size
)
81 /* Make sure the caller does not claim more than available. */
82 if (v
->size
< used_size
)
83 internerr("varbuf new_used(%zu) > size(%zu)", used_size
, v
->size
);
89 varbuf_reset(struct varbuf
*v
)
95 varbuf_get_str(struct varbuf
*v
)
103 varbuf_add_varbuf(struct varbuf
*v
, const struct varbuf
*other
)
105 varbuf_grow(v
, other
->used
);
106 memcpy(v
->buf
+ v
->used
, other
->buf
, other
->used
);
107 v
->used
+= other
->used
;
111 varbuf_add_char(struct varbuf
*v
, int c
)
114 v
->buf
[v
->used
++] = c
;
118 varbuf_dup_char(struct varbuf
*v
, int c
, size_t n
)
123 memset(v
->buf
+ v
->used
, c
, n
);
128 varbuf_map_char(struct varbuf
*v
, int c_src
, int c_dst
)
132 for (i
= 0; i
< v
->used
; i
++)
133 if (v
->buf
[i
] == c_src
)
138 varbuf_add_dir(struct varbuf
*v
, const char *dirname
)
140 varbuf_add_str(v
, dirname
);
141 if (v
->used
== 0 || v
->buf
[v
->used
- 1] != '/')
142 varbuf_add_char(v
, '/');
146 varbuf_add_buf(struct varbuf
*v
, const void *s
, size_t size
)
150 varbuf_grow(v
, size
);
151 memcpy(v
->buf
+ v
->used
, s
, size
);
156 varbuf_end_str(struct varbuf
*v
)
159 v
->buf
[v
->used
] = '\0';
163 varbuf_vprintf(struct varbuf
*v
, const char *fmt
, va_list args
)
168 va_copy(args_copy
, args
);
169 needed
= vsnprintf(NULL
, 0, fmt
, args_copy
);
173 ohshite(_("error formatting string into varbuf variable"));
175 varbuf_grow(v
, needed
+ 1);
177 r
= vsnprintf(v
->buf
+ v
->used
, needed
+ 1, fmt
, args
);
179 ohshite(_("error formatting string into varbuf variable"));
187 varbuf_printf(struct varbuf
*v
, const char *fmt
, ...)
193 r
= varbuf_vprintf(v
, fmt
, args
);
200 varbuf_snapshot(struct varbuf
*v
, struct varbuf_state
*vs
)
207 varbuf_rollback(struct varbuf_state
*vs
)
209 varbuf_trunc(vs
->v
, vs
->used
);
213 varbuf_rollback_len(struct varbuf_state
*vs
)
215 if (vs
->used
> vs
->v
->used
)
216 internerr("varbuf state_used(%zu) > used(%zu)",
217 vs
->used
, vs
->v
->used
);
218 return vs
->v
->used
- vs
->used
;
222 varbuf_rollback_start(struct varbuf_state
*vs
)
224 if (vs
->v
->buf
== NULL
) {
226 internerr("varbuf buf(NULL) state_used(%zu) > 0",
228 /* XXX: Ideally this would be handled by varbuf always having
229 * a valid buf or switching all users to the getter, but for
230 * now this will do. */
233 return vs
->v
->buf
+ vs
->used
;
237 varbuf_detach(struct varbuf
*v
)
249 varbuf_destroy(struct varbuf
*v
)
258 varbuf_free(struct varbuf
*v
)