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