#ifdef PAKFIRE_PRIVATE
-#define pakfire_string_format(s, fmt, ...) snprintf(s, sizeof(s) - 1, fmt, __VA_ARGS__)
+/*
+ Formats a string and stores it in the given buffer.
+*/
+#define pakfire_string_format(s, format, ...) \
+ __pakfire_string_format(s, sizeof(s), format, __VA_ARGS__)
+int __pakfire_string_format(char* s, const size_t length, const char* format, ...)
+ __attribute__((format(printf, 3, 4)));;;
+
+/*
+ Simpler version when a string needs to be copied.
+*/
#define pakfire_string_set(s, value) pakfire_string_format(s, "%s", value)
int pakfire_string_startswith(const char* s, const char* prefix);
#############################################################################*/
#include <errno.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pakfire/string.h>
+int __pakfire_string_format(char* s, const size_t length, const char* format, ...) {
+ va_list args;
+
+ // Write string to buffer
+ va_start(args, format);
+ const ssize_t required = vsnprintf(s, length, format, args);
+ va_end(args);
+
+ // Catch any errors
+ if (required < 0)
+ return 1;
+
+ // Check if the entire string could be written
+ if ((size_t)required >= length) {
+ errno = ENOMEM;
+ return 1;
+ }
+
+ // Success
+ return 0;
+}
+
int pakfire_string_startswith(const char* s, const char* prefix) {
// Validate input
if (!s || !prefix) {
#include "../testsuite.h"
+static int test_string_set(const struct test* t) {
+ // Allocate a small buffer
+ char buffer[4];
+
+ // Write a string into a buffer which just has just enough space
+ ASSERT_SUCCESS(pakfire_string_set(buffer, "ABC"));
+ ASSERT_STRING_EQUALS(buffer, "ABC");
+
+ // Write a string which would not fit
+ ASSERT_ERRNO(pakfire_string_set(buffer, "1234"), ENOMEM);
+ ASSERT_STRING_EQUALS(buffer, "123");
+
+ return EXIT_SUCCESS;
+
+FAIL:
+ return EXIT_FAILURE;
+}
+
static int test_string_startswith(const struct test* t) {
ASSERT_TRUE(pakfire_string_startswith("ABC", "A"));
ASSERT_FALSE(pakfire_string_startswith("ABC", "B"));
}
int main(int argc, const char* argv[]) {
+ testsuite_add_test(test_string_set);
testsuite_add_test(test_string_startswith);
testsuite_add_test(test_string_endswith);
testsuite_add_test(test_string_matches);