]> git.ipfire.org Git - pakfire.git/commitdiff
buffer: Create a new generic buffer implementation
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 22 Mar 2025 18:03:31 +0000 (18:03 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 22 Mar 2025 18:03:31 +0000 (18:03 +0000)
This is used to hold a dynamically growing buffer.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/pakfire/buffer.c [new file with mode: 0644]
src/pakfire/buffer.h [new file with mode: 0644]
src/pakfire/repo.c
src/pakfire/util.h

index 41455beb656eef13e45e6521fd3ff7333f4c364e..15c89c45ac63c536d3bd10c6eabe47c5645a1400 100644 (file)
@@ -194,6 +194,8 @@ libpakfire_la_SOURCES = \
        src/pakfire/archive_writer.h \
        src/pakfire/base64.c \
        src/pakfire/base64.h \
+       src/pakfire/buffer.c \
+       src/pakfire/buffer.h \
        src/pakfire/build.c \
        src/pakfire/build.h \
        src/pakfire/buildservice.c \
diff --git a/src/pakfire/buffer.c b/src/pakfire/buffer.c
new file mode 100644 (file)
index 0000000..adf3f8d
--- /dev/null
@@ -0,0 +1,148 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2025 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <pakfire/buffer.h>
+#include <pakfire/util.h>
+
+// Use chunks of 4k size
+#define CHUNK_SIZE 4096
+
+void pakfire_buffer_free(struct pakfire_buffer* buffer) {
+       if (buffer->data)
+               free(buffer->data);
+}
+
+// Rounds up length to the nearest chunk size
+static size_t pakfire_buffer_align(size_t length) {
+       return ((length + CHUNK_SIZE - 1) / CHUNK_SIZE) * CHUNK_SIZE;
+}
+
+static int pakfire_buffer_resize(struct pakfire_buffer* self, size_t length) {
+       // Check maximum length and refuse to grow
+       if (self->max_length && (length > self->max_length))
+               return -ENOBUFS;
+
+       // Round up to the nearest chunk size
+       length = pakfire_buffer_align(length);
+
+       // Re-allocate the buffer
+       self->data = pakfire_realloc(self->data, length);
+       if (!self->data)
+               return -errno;
+
+       // Adjust the size
+       self->length = length;
+
+       return 0;
+}
+
+// Grows the buffer
+static int pakfire_buffer_grow(struct pakfire_buffer* self, size_t length) {
+       // Check if we actually need to grow
+       if (self->length >= self->used + length)
+               return 0;
+
+       return pakfire_buffer_resize(self, self->length + length);
+}
+
+// Shrinks the buffer to its minimum size
+static int pakfire_buffer_shrink(struct pakfire_buffer* self) {
+       return pakfire_buffer_resize(self, self->length);
+}
+
+int pakfire_buffer_append(struct pakfire_buffer* self, const char* data, size_t length) {
+       int r;
+
+       // Check inputs
+       if (!data)
+               return -EINVAL;
+
+       // Nothing to do if there is no data
+       if (!length)
+               return 0;
+
+       // Grow the buffer
+       r = pakfire_buffer_grow(self, length);
+       if (r < 0)
+               return r;
+
+       // Copy the data
+       memcpy(self->data + self->used, data, length);
+       self->used += length;
+
+       return 0;
+}
+
+int pakfire_buffer_append_from_fd(struct pakfire_buffer* self, int fd) {
+       ssize_t bytes_read = 0;
+       int r;
+
+       // Read for as long as possible
+       for (;;) {
+               // Ensure that we have at least one chunk size available
+               r = pakfire_buffer_grow(self, CHUNK_SIZE);
+               if (r < 0)
+                       return r;
+
+               // Read into the buffer
+               bytes_read = read(fd, self->data + self->used, self->length - self->used);
+               if (bytes_read < 0)
+                       return bytes_read;
+
+               // We now use more space
+               self->used += bytes_read;
+
+               // If we have not filled the entire space, we have read everything for now
+               if (self->used < self->length)
+                       break;
+       }
+
+       return 0;
+}
+
+int pakfire_buffer_consume(struct pakfire_buffer* self, size_t length) {
+       // Check if we actually have enough data
+       if (self->used < length)
+               return -EINVAL;
+
+       memmove(self->data, self->data + length, self->used - length);
+       self->used -= length;
+
+       return 0;
+}
+
+size_t pakfire_buffer_find_line(struct pakfire_buffer* self) {
+       char* p = NULL;
+
+       // Nothing to do if there is no data
+       if (!self->used)
+               return 0;
+
+       // Find the byte
+       p = memchr(self->data, '\n', self->used);
+       if (!p)
+               return 0;
+
+       // Return the length
+       return p - self->data + 1;
+}
diff --git a/src/pakfire/buffer.h b/src/pakfire/buffer.h
new file mode 100644 (file)
index 0000000..2a3a885
--- /dev/null
@@ -0,0 +1,44 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2025 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_BUFFER_H
+#define PAKFIRE_BUFFER_H
+
+struct pakfire_buffer {
+       char* data;
+       size_t length;
+
+       // Actually used data
+       size_t used;
+
+       // Defines the maximum length this buffer can grow to
+       size_t max_length;
+};
+
+void pakfire_buffer_free(struct pakfire_buffer* buffer);
+
+int pakfire_buffer_append(struct pakfire_buffer* self, const char* data, size_t length);
+int pakfire_buffer_append_from_fd(struct pakfire_buffer* self, int fd);
+
+int pakfire_buffer_consume(struct pakfire_buffer* self, size_t length);
+
+size_t pakfire_buffer_find_line(struct pakfire_buffer* self);
+
+#endif /* PAKFIRE_BUFFER_H */
index f087f4e94316cae5d8ba86f5fc875e6496a7245f..3dee18e0c02e77e3867839af508e0cbc57df97dd 100644 (file)
@@ -35,6 +35,7 @@
 #include <json.h>
 
 #include <pakfire/archive.h>
+#include <pakfire/buffer.h>
 #include <pakfire/config.h>
 #include <pakfire/constants.h>
 #include <pakfire/ctx.h>
index 06f6dc2717b40774c9cc9c41cf644a8ec0dcb326..5adb68cabbae00623a2b9f16021174de2688235c 100644 (file)
 #define likely(x)              __builtin_expect(!!(x), 1)
 #define unlikely(x)            __builtin_expect(!!(x), 0)
 
-/*
-       A simple buffer object
-*/
-struct pakfire_buffer {
-       char* data;
-       size_t length;
-};
-
 /*
        This implementation of realloc frees the original buffer
        if it could not be resized.