diff options
| author | Dennis Camera <skonfig@dtnr.ch> | 2022-08-03 17:41:14 +0200 |
|---|---|---|
| committer | Dennis Camera <skonfig@dtnr.ch> | 2022-08-03 17:58:16 +0200 |
| commit | 26f555c974cf49def75120dada596f421e15f1d4 (patch) | |
| tree | e45fdac5f17b04b3fb15dfd1079a9560ba9de259 /src/util | |
| parent | 1fc6697f4de4290575202661b664ca617df9b8e1 (diff) | |
| download | skonfig-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.c | 9 | ||||
| -rw-r--r-- | src/util/array.h | 18 | ||||
| -rw-r--r-- | src/util/fs.c | 23 | ||||
| -rw-r--r-- | src/util/fs.h | 40 | ||||
| -rw-r--r-- | src/util/string.c | 144 | ||||
| -rw-r--r-- | src/util/string.h | 107 |
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 |
