/* copyright 2013 Sascha Kruse and contributors (see LICENSE for licensing information) */ #include "utils.h" #include #include #include #include #include #include #include #include #include #include "log.h" /* see utils.h */ void free_string_array(char **arr) { if (arr){ for (int i = 0; arr[i]; i++){ g_free(arr[i]); } } g_free(arr); } /* see utils.h */ char *string_replace_char(char needle, char replacement, char *haystack) { ASSERT_OR_RET(haystack, NULL); char *current = haystack; while ((current = strchr(current, needle))) *current++ = replacement; return haystack; } /* see utils.h */ char *string_replace_at(char *buf, int pos, int len, const char *repl) { assert(buf); assert(repl); char *tmp; int size, buf_len, repl_len; buf_len = strlen(buf); repl_len = strlen(repl); size = (buf_len - len) + repl_len + 1; if (repl_len <= len) { tmp = buf; } else { tmp = g_malloc(size); memcpy(tmp, buf, pos); } memcpy(tmp + pos, repl, repl_len); memmove(tmp + pos + repl_len, buf + pos + len, buf_len - (pos + len) + 1); if (tmp != buf) { g_free(buf); } return tmp; } /* see utils.h */ char *string_replace_all(const char *needle, const char *replacement, char *haystack) { ASSERT_OR_RET(haystack, NULL); assert(needle); assert(replacement); char *start; int needle_pos; int needle_len, repl_len; needle_len = strlen(needle); if (needle_len == 0) { return haystack; } start = strstr(haystack, needle); repl_len = strlen(replacement); while (start) { needle_pos = start - haystack; haystack = string_replace_at(haystack, needle_pos, needle_len, replacement); start = strstr(haystack + needle_pos + repl_len, needle); } return haystack; } /* see utils.h */ char *string_append(char *a, const char *b, const char *sep) { if (STR_EMPTY(a)) { g_free(a); return g_strdup(b); } if (STR_EMPTY(b)) return a; char *new; if (!sep) new = g_strconcat(a, b, NULL); else new = g_strconcat(a, sep, b, NULL); g_free(a); return new; } /* see utils.h */ char *string_strip_quotes(const char *value) { ASSERT_OR_RET(value, NULL); size_t len = strlen(value); char *s; if (value[0] == '"' && value[len-1] == '"') s = g_strndup(value + 1, len-2); else s = g_strdup(value); return s; } /* see utils.h */ void string_strip_delimited(char *str, char a, char b) { assert(str); int iread=-1, iwrite=0, copen=0; while (str[++iread] != 0) { if (str[iread] == a) { ++copen; } else if (str[iread] == b && copen > 0) { --copen; } else if (copen == 0) { str[iwrite++] = str[iread]; } } str[iwrite] = 0; } /* see utils.h */ char **string_to_array(const char *string) { char **arr = NULL; if (string) { arr = g_strsplit(string, ",", 0); for (int i = 0; arr[i]; i++){ g_strstrip(arr[i]); } } return arr; } /* see utils.h */ char *string_to_path(char *string) { if (string && STRN_EQ(string, "~/", 2)) { char *home = g_strconcat(user_get_home(), "/", NULL); string = string_replace_at(string, 0, 2, home); g_free(home); } return string; } /* see utils.h */ gint64 string_to_time(const char *string) { assert(string); errno = 0; char *endptr; gint64 val = strtoll(string, &endptr, 10); if (errno != 0) { LOG_W("Time: '%s': %s.", string, strerror(errno)); return 0; } else if (string == endptr) { LOG_W("Time: '%s': No digits found.", string); return 0; } else if (errno != 0 && val == 0) { LOG_W("Time: '%s': Unknown error.", string); return 0; } else if (errno == 0 && !*endptr) { return S2US(val); } // endptr may point to a separating space while (isspace(*endptr)) endptr++; if (STRN_EQ(endptr, "ms", 2)) return val * 1000; else if (STRN_EQ(endptr, "s", 1)) return S2US(val); else if (STRN_EQ(endptr, "m", 1)) return S2US(val) * 60; else if (STRN_EQ(endptr, "h", 1)) return S2US(val) * 60 * 60; else if (STRN_EQ(endptr, "d", 1)) return S2US(val) * 60 * 60 * 24; else return 0; } /* see utils.h */ gint64 time_monotonic_now(void) { struct timespec tv_now; /* On Linux, BOOTTIME is the correct monotonic time, * as BOOTTIME counts onwards during sleep. For all other * POSIX compliant OSes, MONOTONIC should also count onwards * during system sleep. */ #ifdef __linux__ clock_gettime(CLOCK_BOOTTIME, &tv_now); #else clock_gettime(CLOCK_MONOTONIC, &tv_now); #endif return S2US(tv_now.tv_sec) + tv_now.tv_nsec / 1000; } /* see utils.h */ const char *user_get_home(void) { static const char *home_directory = NULL; ASSERT_OR_RET(!home_directory, home_directory); // Check the HOME variable for the user's home home_directory = getenv("HOME"); ASSERT_OR_RET(!home_directory, home_directory); // Check the /etc/passwd entry for the user's home home_directory = getpwuid(getuid())->pw_dir; return home_directory; } bool safe_setenv(const char* key, const char* value){ if (!key) return false; if (!value) setenv(key, "", 1); else setenv(key, value, 1); return true; } /* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */