aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/blocks/fs.c20
-rw-r--r--src/blocks/ram.c20
-rw-r--r--src/format.c93
-rw-r--r--src/format.h21
-rw-r--r--src/util.c9
-rw-r--r--src/util.h2
6 files changed, 104 insertions, 61 deletions
diff --git a/src/blocks/fs.c b/src/blocks/fs.c
index 9c0a50c..188f14a 100644
--- a/src/blocks/fs.c
+++ b/src/blocks/fs.c
@@ -25,13 +25,13 @@ typedef enum {
FS_USED_PERC,
} block_fs_mark_t;
-static const format_pair_t block_fs_pairs[] = {
- { "total", FS_TOTAL },
- { "free", FS_FREE },
- { "used", FS_USED },
- { "free-percentage", FS_FREE_PERC },
- { "used-percentage", FS_USED_PERC },
- { NULL },
+static const format_option_t block_fs_options[] = {
+ { { "total", FS_TOTAL } },
+ { { "free", FS_FREE } },
+ { { "used", FS_USED } },
+ { { "free-percentage", FS_FREE_PERC } },
+ { { "used-percentage", FS_USED_PERC } },
+ { { NULL } },
};
static const struct timespec block_fs_interval = {
@@ -59,9 +59,9 @@ static void block_fs_update(block_t *block)
size_t rest = start >= size ? 0 : size - start;
if (rest == 0) break;
- switch (fs->format.marks[i]) {
+ switch (fs->format.parts[i].mark) {
case FS_STRING:
- start += snprintf(buffer + start, rest, "%s", fs->format.parts[i]);
+ start += snprintf(buffer + start, rest, "%s", fs->format.parts[i].string);
break;
case FS_TOTAL:
start += snprintf(buffer + start, rest, "%ld", sbuf.f_bsize * (uint64_t)sbuf.f_blocks);
@@ -124,7 +124,7 @@ static bool block_fs_validate(block_t *block, const block_scheme_t *scheme)
return false;
}
- int marked = format_remark(&fs->format, block->label, block_fs_pairs);
+ int marked = format_remark(&fs->format, block->label, block_fs_options);
if (marked < 0)
return false;
diff --git a/src/blocks/ram.c b/src/blocks/ram.c
index 0536c26..4841860 100644
--- a/src/blocks/ram.c
+++ b/src/blocks/ram.c
@@ -21,13 +21,13 @@ typedef enum {
RAM_USED_PERC,
} block_ram_mark_t;
-static const format_pair_t block_ram_pairs[] = {
- { "total", RAM_TOTAL },
- { "free", RAM_FREE },
- { "used", RAM_USED },
- { "free-percentage", RAM_FREE_PERC },
- { "used-percentage", RAM_USED_PERC },
- { NULL },
+static const format_option_t block_ram_options[] = {
+ { { "total", RAM_TOTAL } },
+ { { "free", RAM_FREE } },
+ { { "used", RAM_USED } },
+ { { "free-percentage", RAM_FREE_PERC } },
+ { { "used-percentage", RAM_USED_PERC } },
+ { { NULL } },
};
static const struct timespec block_ram_interval = {
@@ -74,9 +74,9 @@ static void block_ram_update(block_t *block)
size_t rest = start >= size ? 0 : size - start;
if (rest == 0) break;
- switch (ram->format.marks[i]) {
+ switch (ram->format.parts[i].mark) {
case RAM_STRING:
- start += snprintf(buffer + start, rest, "%s", ram->format.parts[i]);
+ start += snprintf(buffer + start, rest, "%s", ram->format.parts[i].string);
break;
case RAM_TOTAL:
start += snprintf(buffer + start, rest, "%ld", total);
@@ -138,7 +138,7 @@ static bool block_ram_validate(block_t *block, const block_scheme_t *scheme)
return false;
}
- int marked = format_remark(&ram->format, block->label, block_ram_pairs);
+ int marked = format_remark(&ram->format, block->label, block_ram_options);
if (marked < 0)
return false;
diff --git a/src/format.c b/src/format.c
index 49d5d35..2a2ee03 100644
--- a/src/format.c
+++ b/src/format.c
@@ -11,18 +11,14 @@
do { \
if (n + 1 >= length) { \
length += (need); \
- parts = realloc(parts, length * sizeof(char *)); \
+ parts = realloc(parts, length * sizeof(format_pair_t)); \
assert(parts != NULL); \
- marks = realloc(marks, length * sizeof(uint8_t)); \
- assert(marks != NULL); \
} \
} while (0)
bool format_init(format_t *format, const char *string, char delim)
{
- char **parts = NULL;
- uint8_t *marks = NULL;
-
+ format_pair_t *parts = NULL;
size_t length = 0, n = 0;
size_t start = 0, end = 0;
@@ -34,19 +30,16 @@ bool format_init(format_t *format, const char *string, char delim)
format_grow(2);
if (start != end) {
- parts[n] = strslice(string, start, end);
- marks[n] = false;
+ parts[n].string = strslice(string, start, end);
+ parts[n].mark = 0;
n++;
}
start = end += 2;
while (string[end] != '}') {
if (string[end] == '\0' || (string[end] == '$' && string[end + 1] == '{')) {
- for (size_t k = 0; k < n; k++)
- free(parts[k]);
-
- free(parts);
- free(marks);
+ format->parts = parts, format->length = length;
+ format_free(format);
return false;
}
end++;
@@ -58,8 +51,8 @@ bool format_init(format_t *format, const char *string, char delim)
while (start <= end && isspace(string[start])) start++, l--;
while (start <= end && isspace(string[end])) end--, l--;
- parts[n] = strslice(string, start, start + l);
- marks[n] = true;
+ parts[n].string = strslice(string, start, start + l);
+ parts[n].mark = 1;
n++;
start = end = ++next;
@@ -75,35 +68,70 @@ next:
while (string[end] != '\0') end++;
format_grow(1);
- parts[n] = strslice(string, start, end);
- marks[n] = false;
+ parts[n].string = strslice(string, start, end);
+ parts[n].mark = 0;
n++;
}
format->parts = parts;
- format->marks = marks;
format->length = n;
return true;
}
-int format_remark(format_t *format, const char *label, const format_pair_t *pairs)
+static size_t format_option_cmp(const char *a, const char *b)
{
- int errors = 0, marked = 0;
+ size_t i = 0;
+ while (b[i] != '\0') {
+ if (a[i] != b[i]) return 0;
+ i++;
+ }
+ return i;
+}
+static bool format_option_match(format_pair_t *part, const format_option_t *option)
+{
+ format_mark_t mark = 0;
+ size_t off = 0;
+
+ for (format_pair_t *ps = option->prefixes; ps != NULL && ps->string != NULL; ps++) {
+ off = format_option_cmp(part->string, ps->string);
+ if (off != 0) {
+ mark |= ps->mark;
+ break;
+ }
+ }
+
+ size_t tmp = format_option_cmp(part->string + off, option->option.string);
+ if (tmp == 0) return false;
+ off += tmp;
+ mark |= option->option.mark;
+
+ for (format_pair_t *ss = option->suffixes; ss != NULL && ss->string != NULL; ss++) {
+ tmp = format_option_cmp(part->string + off, ss->string);
+ if (tmp != 0) {
+ mark |= ss->mark;
+ break;
+ }
+ }
+
+ if (part->string[tmp] != '\0')
+ return false;
+
+ part->mark = mark;
+ return true;
+}
+
+int format_remark(format_t *format, const char *label, const format_option_t *options)
+{
+ int errors = 0, marked = 0;
for (size_t i = 0; i < format->length; i++) {
- // Skip regular strings
- if (!format->marks[i]) continue;
- size_t l = strlen(format->parts[i]);
- for (size_t j = 0; pairs[j].key != NULL; j++) {
- size_t kl = strlen(pairs[j].key);
+ // Skip regular strings
+ if (!format->parts[i].mark) continue;
- if ((pairs[j].prefix && !strncmp(pairs[j].key, format->parts[i], kl)) ||
- (pairs[j].postfix && l > kl && !strncmp(pairs[j].key, format->parts[i] + (l - kl), kl)) ||
- !strcmp(pairs[j].key, format->parts[i]))
- {
- format->marks[i] = pairs[j].mark;
+ for (size_t j = 0; !iszero(&options[j], sizeof(format_option_t)); j++) {
+ if (format_option_match(&format->parts[i], &options[j])) {
marked++;
goto next;
}
@@ -111,7 +139,7 @@ int format_remark(format_t *format, const char *label, const format_pair_t *pair
errors++;
if (label != NULL)
- log_error("Unknown format option '%s' for block '%s'", format->parts[i], label);
+ log_error("Unknown format option '%s' for block '%s'", format->parts[i].string, label);
next:
}
@@ -121,8 +149,7 @@ next:
void format_free(format_t *format)
{
for (size_t i = 0; i < format->length; i++)
- free(format->parts[i]);
+ free(format->parts[i].string);
free(format->parts);
- free(format->marks);
}
diff --git a/src/format.h b/src/format.h
index 8f8eafc..e5173de 100644
--- a/src/format.h
+++ b/src/format.h
@@ -4,22 +4,27 @@
#include <stdint.h>
#include <stdbool.h>
+typedef int format_mark_t;
+
typedef struct {
- char **parts;
- uint8_t *marks;
+ char *string;
+ format_mark_t mark;
+} format_pair_t;
+
+typedef struct {
+ format_pair_t *parts;
size_t length;
} format_t;
typedef struct {
- const char *key;
- uint8_t mark;
- bool prefix;
- bool postfix;
-} format_pair_t;
+ format_pair_t option;
+ format_pair_t *prefixes;
+ format_pair_t *suffixes;
+} format_option_t;
bool format_init(format_t *format, const char *string, char delim);
-int format_remark(format_t *format, const char *label, const format_pair_t *pairs);
+int format_remark(format_t *format, const char *label, const format_option_t *options);
void format_free(format_t *format);
diff --git a/src/util.c b/src/util.c
index ac178cc..d5ca902 100644
--- a/src/util.c
+++ b/src/util.c
@@ -216,3 +216,12 @@ void strfree(char **list)
free(list);
}
+
+bool iszero(const void *ptr, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ if (((const char *)ptr)[i] != 0)
+ return false;
+ }
+ return true;
+}
diff --git a/src/util.h b/src/util.h
index a45ae4d..5f58a79 100644
--- a/src/util.h
+++ b/src/util.h
@@ -71,4 +71,6 @@ char *strformat(const char *string, char delim, const char *keys[], const char *
void strfree(char **list);
+bool iszero(const void *ptr, size_t size);
+
#endif