summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorDennis Camera <skonfig@dtnr.ch>2022-08-03 17:41:14 +0200
committerDennis Camera <skonfig@dtnr.ch>2022-08-03 17:58:16 +0200
commit26f555c974cf49def75120dada596f421e15f1d4 (patch)
treee45fdac5f17b04b3fb15dfd1079a9560ba9de259 /src/util
parent1fc6697f4de4290575202661b664ca617df9b8e1 (diff)
downloadskonfig-c-26f555c974cf49def75120dada596f421e15f1d4.tar.gz
skonfig-c-26f555c974cf49def75120dada596f421e15f1d4.zip
Move helper functions out to src/util/
Diffstat (limited to 'src/util')
-rw-r--r--src/util/array.c9
-rw-r--r--src/util/array.h18
-rw-r--r--src/util/fs.c23
-rw-r--r--src/util/fs.h40
-rw-r--r--src/util/string.c144
-rw-r--r--src/util/string.h107
6 files changed, 341 insertions, 0 deletions
diff --git a/src/util/array.c b/src/util/array.c
new file mode 100644
index 0000000..8436f24
--- /dev/null
+++ b/src/util/array.c
@@ -0,0 +1,9 @@
+#include "array.h"
+
+size_t anullidx(void *a[]) {
+ size_t i = 0;
+ if (NULL != a)
+ while (a[i] != NULL)
+ i++;
+ return i;
+}
diff --git a/src/util/array.h b/src/util/array.h
new file mode 100644
index 0000000..2e09952
--- /dev/null
+++ b/src/util/array.h
@@ -0,0 +1,18 @@
+#ifndef _SK_UTIL_ARRAY_H
+#define _SK_UTIL_ARRAY_H
+
+#include <stddef.h>
+
+#define arraylen(a) (sizeof(a)/sizeof(*a))
+
+/**
+ * anullidx:
+ * Returns the index of the first NULL element in an array.
+ *
+ * @param a: the array to search
+ * @returns the index of the first NULL element / the number of elements before
+ * NULL.
+ */
+size_t anullidx(void *a[]);
+
+#endif
diff --git a/src/util/fs.c b/src/util/fs.c
new file mode 100644
index 0000000..6f787c0
--- /dev/null
+++ b/src/util/fs.c
@@ -0,0 +1,23 @@
+#include "fs.h"
+
+bool is_dir(const char *restrict pathname) {
+#ifdef STAT_MACROS_BROKEN
+#error stat() macros are broken on this system. Cannot compile is_dir().
+#endif
+ struct stat s;
+ return (0 == stat(pathname, &s) && S_ISDIR(s.st_mode));
+}
+
+const char *myhome() {
+ static char home[PATH_MAX+1];
+
+ home[0] = '\0';
+ if (!getenv("HOME")) {
+ (void)strncpy(home, getenv("HOME"), PATH_MAX);
+ } else { /* HOME unset or empty */
+ (void)strncpy(home, getpwuid(getuid())->pw_dir, PATH_MAX);
+ }
+ home[PATH_MAX] = '\0';
+
+ return (const char *)&home;
+}
diff --git a/src/util/fs.h b/src/util/fs.h
new file mode 100644
index 0000000..9dc445f
--- /dev/null
+++ b/src/util/fs.h
@@ -0,0 +1,40 @@
+#ifndef _SK_UTIL_FS_H
+#define _SK_UTIL_FS_H
+
+#include "../../config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <pwd.h>
+#include <sys/stat.h>
+
+#if HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
+/**
+ * is_dir:
+ * Check if a given pathname is a directory.
+ *
+ * @returns true if the given pathname exists and is a directory, false
+ * otherwise.
+ */
+bool is_dir(const char *restrict pathname);
+
+/**
+ * myhome:
+ * Returns a pointer to a string containing the current user’s home
+ * directory.
+ * The returned pointer points to a static location (don’t free() it) and
+ * may be changed on future invocations.
+ *
+ * This function makes sure that the returned string is null-terminated and
+ * truncates the result to fit within PATH_MAX if necessary.
+ *
+ * @returns home dir
+ */
+const char *myhome();
+
+#endif
diff --git a/src/util/string.c b/src/util/string.c
new file mode 100644
index 0000000..db565c0
--- /dev/null
+++ b/src/util/string.c
@@ -0,0 +1,144 @@
+#include "string.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *strdup(const char *s) {
+ if (NULL == s) {
+ return NULL;
+ }
+
+ size_t len = strlen(s);
+ char *buf = malloc(len+1);
+
+ if (buf) {
+ memcpy(buf, s, len + 1);
+ }
+ return buf;
+}
+
+char *stranjoin(char sep, const char *a[], size_t nmemb) {
+ char *dst;
+
+ if (nmemb > 0) {
+ /* determine length of joined string */
+ size_t len = 0;
+ for (size_t i = 0; i < nmemb; i++) {
+ len += strlen(a[i]) + 1;
+ }
+
+ /* then, join strings */
+ dst = calloc(len, sizeof(char));
+ if (!dst) {
+ return NULL;
+ }
+
+ char *p = dst;
+ for (size_t i = 0; i < nmemb; i++) {
+ if (i > 0)
+ *p++ = sep;
+ size_t l = strlen(a[i]);
+ memcpy(p, a[i], l);
+ p += l;
+ }
+
+ *p = '\0';
+ } else {
+ dst = strdup("");
+ }
+
+ return dst;
+}
+
+char *_strjoin(char sep, /* const char * */...) {
+ const char *s;
+ char *dst, *p;
+ va_list ap;
+ size_t len, l;
+
+ va_start(ap, sep);
+
+ s = va_arg(ap, const char *);
+
+ if (s) {
+ /* determine length of joined string */
+ len = strlen(s) + 1;
+
+ while ((s = va_arg(ap, const char *))) {
+ len += strlen(s) + 1;
+ }
+ va_end(ap);
+
+ /* Then, join strings */
+ dst = calloc(len, sizeof(char));
+ if (!dst) {
+ return NULL;
+ }
+ p = dst;
+
+ va_start(ap, sep);
+
+ /* copy first element */
+ s = va_arg(ap, const char *);
+ l = strlen(s);
+ strcpy(dst, s);
+ p += l;
+
+ /* then the others */
+ while ((s = va_arg(ap, const char *))) {
+ l = strlen(s);
+
+ *p++ = sep;
+ strncpy(p, s, l);
+ p += l;
+ }
+
+ *p = '\0';
+ } else {
+ dst = strdup("");
+ }
+
+ va_end(ap);
+
+ return dst;
+}
+
+size_t strsplit(const char *restrict in, const char *restrict sep, void *buf) {
+ size_t i = 0;
+ char **arr = buf;
+
+ if (0 == strlen(in)) {
+ /* special case: empty string */
+ if (arr) arr[0] = NULL;
+ return sizeof(char *);
+ }
+
+ char *tok, *saveptr, *tmp = strdup(in);
+
+ tok = strtok_r(tmp, sep, &saveptr);
+ do {
+ if (arr) {
+ arr[i] = (char *)(tok - tmp); /* save char offset */
+ }
+ i++;
+ } while ((tok = strtok_r(NULL, sep, &saveptr)));
+
+ size_t strtokoffset = ((i+1)*sizeof(*arr)),
+ strtoklen = strlen(in) + 1;
+
+ if (arr) {
+ /* update array pointers */
+ for (int j = 0; j < i; j++) {
+ arr[j] = (char *)((size_t)buf + strtokoffset + (size_t)arr[j]);
+ }
+ arr[i] = NULL; /* NULL termination */
+
+ /* copy tokenized string from tmp to the back of buf */
+ (void)memcpy(buf + strtokoffset, tmp, strtoklen);
+ }
+
+ free(tmp);
+
+ return (strtoklen + strtokoffset);
+}
diff --git a/src/util/string.h b/src/util/string.h
new file mode 100644
index 0000000..6f71a11
--- /dev/null
+++ b/src/util/string.h
@@ -0,0 +1,107 @@
+#ifndef _SK_UTIL_STRING_H
+#define _SK_UTIL_STRING_H
+
+#include "array.h"
+
+#include <stddef.h>
+
+/**
+ * stringize:
+ * Convert value of preprocessor macro to C string literal.
+ *
+ * @param x: the name of the macro
+ */
+#define stringize(x) quote(x)
+
+/**
+ * quote:
+ * Quote literally whatever is passed into this macro as a C string.
+ *
+ * @param x: the value to quote
+ *
+ */
+#ifdef HAVE_STRINGIZE
+#define quote(x) #x
+#else
+#define quote(x) "x"
+#endif
+
+/**
+ * boolstr:
+ * Make string out of bool.
+ *
+ * @param b: the boolean variable
+ * @returns "true" or "false"
+ */
+#define boolstr(b) (b ? "true" : "false")
+
+/**
+ * strdup:
+ * like strdup(3p).
+ */
+char *strdup(const char *s);
+
+/**
+ * strajoin:
+ * Joins a C string array using a separator character.
+ *
+ * The returned string should be free()d.
+ *
+ * @param sep: a char to insert between each element of the array
+ * @param a: the array to join (NULL terminated)
+ * @return a newly-allocated C string containing all of the elements joined
+ */
+#define strajoin(sep, a) stranjoin(sep, a, anullidx((void *)a))
+
+/**
+ * stranjoin:
+ * Joins a C string array using a separator character.
+ *
+ * The returned string should be free()d.
+ *
+ * @param sep: a char to insert between each element of the array
+ * @param a: the array to join
+ * @param nmemb: the length of the array
+ * @return a newly-allocated C string containing all of the elements joined
+ */
+char *stranjoin(char sep, const char *a[], size_t nmemb);
+
+char *_strjoin(char sep, /* const char * */...); /* internal */
+
+/**
+ * strjoin:
+ * Joins a number of strings together to form one long string, with the
+ * @separator inserted between each of them. The returned string
+ * should be free()d.
+ *
+ * @param sep: a char to insert between each of the strings
+ * @param ...: a list of strings to join
+ * @return a newly-allocated string containing all of the strings joined
+ */
+#define strjoin(sep, ...) _strjoin(sep, __VA_ARGS__, NULL)
+
+/**
+ * pathjoin:
+ * Joins a number of path components together to form one single path.
+ * The returned string should be free()d.
+ *
+ * @param ...: a list of path components to join
+ * @return a newly-allocated string containing all of the path components joined
+ */
+#define pathjoin(...) strjoin(stringize(DIRSEP)[0], __VA_ARGS__)
+
+/**
+ * strsplit:
+ * Splits a string into a NULL-terminated array by a given separator.
+ *
+ * Call this function with a NULL buffer to determine the size of the resulting
+ * array.
+ *
+ * @param str: the input string (null-terminated)
+ * @param sep: a string containing one or more separator characters
+ * @param buf: a buffer to put the array into
+ * @returns the number of bytes written into buf
+ */
+size_t strsplit(const char *restrict in, const char *restrict sep, void *buf);
+
+#endif