xref: /freebsd/contrib/pkgconf/libpkgconf/buffer.c (revision a3cefe7f2b4df0f70ff92d4570ce18e517af43ec)
1 /*
2  * buffer.c
3  * dynamically-managed buffers
4  *
5  * Copyright (c) 2024 pkgconf authors (see AUTHORS).
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * This software is provided 'as is' and without any warranty, express or
12  * implied.  In no event shall the authors be liable for any damages arising
13  * from the use of this software.
14  */
15 
16 #include <libpkgconf/stdinc.h>
17 #include <libpkgconf/libpkgconf.h>
18 
19 /*
20  * !doc
21  *
22  * libpkgconf `buffer` module
23  * ==========================
24  *
25  * The libpkgconf `buffer` module contains the functions related to managing
26  * dynamically-allocated buffers.
27  */
28 
29 static inline size_t
target_allocation_size(size_t target_size)30 target_allocation_size(size_t target_size)
31 {
32 	return 4096 + (4096 * (target_size / 4096));
33 }
34 
35 void
pkgconf_buffer_append(pkgconf_buffer_t * buffer,const char * text)36 pkgconf_buffer_append(pkgconf_buffer_t *buffer, const char *text)
37 {
38 	size_t needed = strlen(text) + 1;
39 	size_t newsize = pkgconf_buffer_len(buffer) + needed;
40 
41 	char *newbase = realloc(buffer->base, target_allocation_size(newsize));
42 
43 	/* XXX: silently failing here is antisocial */
44 	if (newbase == NULL)
45 		return;
46 
47 	char *newend = newbase + pkgconf_buffer_len(buffer);
48 	pkgconf_strlcpy(newend, text, needed);
49 
50 	buffer->base = newbase;
51 	buffer->end = newend + needed;
52 }
53 
54 void
pkgconf_buffer_push_byte(pkgconf_buffer_t * buffer,char byte)55 pkgconf_buffer_push_byte(pkgconf_buffer_t *buffer, char byte)
56 {
57 	size_t newsize = pkgconf_buffer_len(buffer) + 1;
58 	char *newbase = realloc(buffer->base, target_allocation_size(newsize));
59 
60 	/* XXX: silently failing here remains antisocial */
61 	if (newbase == NULL)
62 		return;
63 
64 	char *newend = newbase + newsize;
65 	*(newend - 1) = byte;
66 	*newend = '\0';
67 
68 	buffer->base = newbase;
69 	buffer->end = newend;
70 }
71 
72 void
pkgconf_buffer_trim_byte(pkgconf_buffer_t * buffer)73 pkgconf_buffer_trim_byte(pkgconf_buffer_t *buffer)
74 {
75 	size_t newsize = pkgconf_buffer_len(buffer) - 1;
76 	char *newbase = realloc(buffer->base, target_allocation_size(newsize));
77 
78 	buffer->base = newbase;
79 	buffer->end = newbase + newsize;
80 	*(buffer->end) = '\0';
81 }
82 
83 void
pkgconf_buffer_finalize(pkgconf_buffer_t * buffer)84 pkgconf_buffer_finalize(pkgconf_buffer_t *buffer)
85 {
86 	free(buffer->base);
87 }
88