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