aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2020-02-28 01:03:04 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2020-02-28 01:03:04 -0500
commit58c133333ac3d1be1f7e89ce1b40a0e100ee812c (patch)
tree989106e05030d3a5e5c65087500e35066f6870eb
parentd3580f8c0b5c17150382c4b4456e0b1bfa81a50f (diff)
downloadspmc-58c133333ac3d1be1f7e89ce1b40a0e100ee812c.tar.gz
Add join_ex() [simplified join() function]
-rw-r--r--include/str.h1
-rw-r--r--src/str.c59
2 files changed, 60 insertions, 0 deletions
diff --git a/include/str.h b/include/str.h
index 06e4a77..23126ab 100644
--- a/include/str.h
+++ b/include/str.h
@@ -11,6 +11,7 @@ void strdelsuffix(char *sptr, const char *suffix);
char** split(char *sptr, const char* delim);
void split_free(char **ptr);
char *join(char **arr, const char *separator);
+char *join_ex(char *separator, ...);
char *substring_between(char *sptr, const char *delims);
void strsort(char **arr);
int find_in_file(const char *filename, const char *pattern);
diff --git a/src/str.c b/src/str.c
index 79a7326..d7b4f6d 100644
--- a/src/str.c
+++ b/src/str.c
@@ -251,6 +251,65 @@ char *join(char **arr, const char *separator) {
}
/**
+ * Join two or more strings by a `separator` string
+ * @param separator
+ * @param ...
+ * @return string
+ */
+char *join_ex(char *separator, ...) {
+ va_list ap; // Variadic argument list
+ size_t separator_len = 0; // Length of separator string
+ size_t size = 0; // Length of output string
+ size_t argc = 0; // Number of arguments ^ "..."
+ char **argv = NULL; // Arguments
+ char *current = NULL; // Current argument
+ char *result = NULL; // Output string
+
+ // Initialize array
+ argv = calloc(argc + 1, sizeof(char));
+ if (argv == NULL) {
+ perror("join_ex calloc failed");
+ return NULL;
+ }
+
+ // Get length of the separator
+ separator_len = strlen(separator);
+
+ // Process variadic arguments:
+ // 1. Iterate over argument list `ap`
+ // 2. Assign `current` with the value of argument in `ap`
+ // 3. Extend the `argv` array by the latest argument count `argc`
+ // 4. Sum the length of the argument and the `separator` passed to the function
+ // 5. Append `current` string to `argv` array
+ // 6. Update argument counter `argc`
+ va_start(ap, separator);
+ for(argc = 0; (current = va_arg(ap, char *)) != NULL; argc++) {
+ char **tmp = realloc(argv, (argc + 1) * sizeof(char *));
+ if (tmp == NULL) {
+ perror("join_ex realloc failed");
+ return NULL;
+ }
+ argv = tmp;
+ size += strlen(current) + separator_len;
+ argv[argc] = strdup(current);
+ }
+ va_end(ap);
+
+ // Generate output string
+ result = calloc(size, sizeof(char));
+ for (size_t i = 0; i < argc; i++) {
+ // Append argument to string
+ strcat(result, argv[i]);
+
+ // Do not append a trailing separator when we reach the last argument
+ if (i < (argc - 1)) {
+ strcat(result, separator);
+ }
+ }
+
+ return result;
+}
+/**
* Extract the string encapsulated by characters listed in `delims`
*
* ~~~{.c}