2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
6 Grow only buffer, add entries but never delete
21 #define GOBUFFER__BCHUNK (8 * 1024)
22 #define GOBUFFER__ZCHUNK (8 * 1024)
24 void gobuffer__init(struct gobuffer
*gb
)
27 gb
->nr_entries
= gb
->allocated_size
= 0;
32 struct gobuffer
*gobuffer__new(void)
34 struct gobuffer
*gb
= malloc(sizeof(*gb
));
42 void __gobuffer__delete(struct gobuffer
*gb
)
50 void gobuffer__delete(struct gobuffer
*gb
)
52 __gobuffer__delete(gb
);
56 void *gobuffer__ptr(const struct gobuffer
*gb
, unsigned int s
)
58 return s
? gb
->entries
+ s
: NULL
;
61 int gobuffer__allocate(struct gobuffer
*gb
, unsigned int len
)
63 const unsigned int rc
= gb
->index
;
64 const unsigned int index
= gb
->index
+ len
;
66 if (index
>= gb
->allocated_size
) {
67 unsigned int allocated_size
= (gb
->allocated_size
+
69 if (allocated_size
< index
)
70 allocated_size
= index
+ GOBUFFER__BCHUNK
;
71 char *entries
= realloc(gb
->entries
, allocated_size
);
76 gb
->allocated_size
= allocated_size
;
77 gb
->entries
= entries
;
84 int gobuffer__add(struct gobuffer
*gb
, const void *s
, unsigned int len
)
86 const int rc
= gobuffer__allocate(gb
, len
);
90 memcpy(gb
->entries
+ rc
, s
, len
);
95 void gobuffer__copy(const struct gobuffer
*gb
, void *dest
)
98 memcpy(dest
, gb
->entries
, gobuffer__size(gb
));
100 /* gobuffer__size will be 0 or 1. */
101 memcpy(dest
, "", gobuffer__size(gb
));
105 void gobuffer__sort(struct gobuffer
*gb
, unsigned int size
, int (*compar
)(const void *, const void *))
107 qsort(gb
->entries
, gb
->nr_entries
, size
, compar
);
110 const void *gobuffer__compress(struct gobuffer
*gb
, unsigned int *size
)
116 .avail_in
= gobuffer__size(gb
),
117 .next_in
= (Bytef
*)(gobuffer__entries(gb
) ? : ""),
120 unsigned int bf_size
= 0;
122 if (deflateInit(&z
, Z_BEST_COMPRESSION
) != Z_OK
)
126 const unsigned int new_bf_size
= bf_size
+ GOBUFFER__ZCHUNK
;
127 void *nbf
= realloc(bf
, new_bf_size
);
130 goto out_close_and_free
;
133 z
.avail_out
= GOBUFFER__ZCHUNK
;
134 z
.next_out
= (Bytef
*)bf
+ bf_size
;
135 bf_size
= new_bf_size
;
136 if (deflate(&z
, Z_FINISH
) == Z_STREAM_ERROR
)
137 goto out_close_and_free
;
138 } while (z
.avail_out
== 0);
141 *size
= bf_size
- z
.avail_out
;