mirror of
https://github.com/labwc/labwc.git
synced 2025-11-05 13:29:58 -05:00
1. All '*.env' files in an 'environment.d' directory alongside each potential 'environment' file will be parsed and added to the environment. 2. For the purposes of configuration merging, an environment definition exists at one level if either the 'environment' file is defined or its corresponding 'environment.d' contains any valid '*.env' file. 3. Variable declarations of the form "VARIABLE=", with no following value, will be written to the environment as empty strings.
172 lines
2.5 KiB
C
172 lines
2.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "common/mem.h"
|
|
#include "common/string-helpers.h"
|
|
|
|
bool
|
|
string_null_or_empty(const char *s)
|
|
{
|
|
return !s || !*s;
|
|
}
|
|
|
|
void
|
|
trim_last_field(char *buf, char delim)
|
|
{
|
|
char *p = strrchr(buf, delim);
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
}
|
|
|
|
static void
|
|
rtrim(char **s)
|
|
{
|
|
size_t len = strlen(*s);
|
|
if (!len) {
|
|
return;
|
|
}
|
|
char *end = *s + len - 1;
|
|
while (end >= *s && isspace(*end)) {
|
|
end--;
|
|
}
|
|
*(end + 1) = '\0';
|
|
}
|
|
|
|
char *
|
|
string_strip(char *s)
|
|
{
|
|
rtrim(&s);
|
|
while (isspace(*s)) {
|
|
s++;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void
|
|
string_truncate_at_pattern(char *buf, const char *pattern)
|
|
{
|
|
char *p = strstr(buf, pattern);
|
|
if (!p) {
|
|
return;
|
|
}
|
|
*p = '\0';
|
|
}
|
|
|
|
char *
|
|
strdup_printf(const char *fmt, ...)
|
|
{
|
|
size_t size = 0;
|
|
char *p = NULL;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
int n = vsnprintf(p, size, fmt, ap);
|
|
va_end(ap);
|
|
|
|
if (n < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
size = (size_t)n + 1;
|
|
p = xzalloc(size);
|
|
|
|
va_start(ap, fmt);
|
|
n = vsnprintf(p, size, fmt, ap);
|
|
va_end(ap);
|
|
|
|
if (n < 0) {
|
|
free(p);
|
|
return NULL;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
char *
|
|
str_join(const char *const parts[],
|
|
const char *restrict fmt, const char *restrict sep)
|
|
{
|
|
assert(parts);
|
|
|
|
if (!fmt) {
|
|
fmt = "%s";
|
|
}
|
|
|
|
if (!sep) {
|
|
sep = " ";
|
|
}
|
|
|
|
size_t size = 0;
|
|
size_t n_parts = 0;
|
|
|
|
size_t sep_len = strlen(sep);
|
|
|
|
/* Count the length of each formatted string */
|
|
for (const char *const *s = parts; *s; ++s) {
|
|
int n = snprintf(NULL, 0, fmt, *s);
|
|
if (n < 0) {
|
|
return NULL;
|
|
}
|
|
size += (size_t)n;
|
|
++n_parts;
|
|
}
|
|
|
|
if (n_parts < 1) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Need (n_parts - 1) separators, plus one NULL terminator */
|
|
size += (n_parts - 1) * sep_len + 1;
|
|
|
|
/* Concatenate the strings and separators */
|
|
char *buf = xzalloc(size);
|
|
char *p = buf;
|
|
for (const char *const *s = parts; *s; ++s) {
|
|
int n = 0;
|
|
|
|
if (p != buf) {
|
|
n = snprintf(p, size, "%s", sep);
|
|
if (n < 0 || (size_t)n >= size) {
|
|
p = NULL;
|
|
break;
|
|
}
|
|
size -= (size_t)n;
|
|
p += (size_t)n;
|
|
}
|
|
|
|
n = snprintf(p, size, fmt, *s);
|
|
if (n < 0 || (size_t)n >= size) {
|
|
p = NULL;
|
|
break;
|
|
}
|
|
size -= (size_t)n;
|
|
p += (size_t)n;
|
|
}
|
|
|
|
if (!p) {
|
|
free(buf);
|
|
return NULL;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
bool
|
|
str_endswith(const char *const string, const char *const suffix)
|
|
{
|
|
size_t len_str = string ? strlen(string) : 0;
|
|
size_t len_sfx = suffix ? strlen(suffix) : 0;
|
|
|
|
if (len_str < len_sfx) {
|
|
return false;
|
|
}
|
|
|
|
if (len_sfx == 0) {
|
|
return true;
|
|
}
|
|
|
|
return strcmp(string + len_str - len_sfx, suffix) == 0;
|
|
}
|