diff options
Diffstat (limited to '')
-rw-r--r-- | libnetdata/line_splitter/Makefile.am | 8 | ||||
-rw-r--r-- | libnetdata/line_splitter/README.md | 14 | ||||
-rw-r--r-- | libnetdata/line_splitter/line_splitter.c | 69 | ||||
-rw-r--r-- | libnetdata/line_splitter/line_splitter.h | 120 |
4 files changed, 211 insertions, 0 deletions
diff --git a/libnetdata/line_splitter/Makefile.am b/libnetdata/line_splitter/Makefile.am new file mode 100644 index 000000000..161784b8f --- /dev/null +++ b/libnetdata/line_splitter/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/libnetdata/line_splitter/README.md b/libnetdata/line_splitter/README.md new file mode 100644 index 000000000..f811bb4b3 --- /dev/null +++ b/libnetdata/line_splitter/README.md @@ -0,0 +1,14 @@ +<!-- +title: "Log" +custom_edit_url: https://github.com/netdata/netdata/edit/master/libnetdata/log/README.md +sidebar_label: "Log" +learn_status: "Published" +learn_topic_type: "Tasks" +learn_rel_path: "Developers/libnetdata" +--> + +# Log + +The netdata log library supports debug, info, error and fatal error logging. +By default we have an access log, an error log and a collectors log. + diff --git a/libnetdata/line_splitter/line_splitter.c b/libnetdata/line_splitter/line_splitter.c new file mode 100644 index 000000000..a459d3347 --- /dev/null +++ b/libnetdata/line_splitter/line_splitter.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + + +bool line_splitter_reconstruct_line(BUFFER *wb, void *ptr) { + struct line_splitter *spl = ptr; + if(!spl) return false; + + size_t added = 0; + for(size_t i = 0; i < spl->num_words ;i++) { + if(i) buffer_fast_strcat(wb, " ", 1); + + buffer_fast_strcat(wb, "'", 1); + const char *s = get_word(spl->words, spl->num_words, i); + buffer_strcat(wb, s?s:""); + buffer_fast_strcat(wb, "'", 1); + added++; + } + + return added > 0; +} + +inline int pluginsd_isspace(char c) { + switch(c) { + case ' ': + case '\t': + case '\r': + case '\n': + case '=': + return 1; + + default: + return 0; + } +} + +inline int config_isspace(char c) { + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + case ',': + return 1; + + default: + return 0; + } +} + +inline int group_by_label_isspace(char c) { + if(c == ',' || c == '|') + return 1; + + return 0; +} + +bool isspace_map_pluginsd[256] = {}; +bool isspace_map_config[256] = {}; +bool isspace_map_group_by_label[256] = {}; + +__attribute__((constructor)) void initialize_is_space_arrays(void) { + for(int c = 0; c < 256 ; c++) { + isspace_map_pluginsd[c] = pluginsd_isspace((char) c); + isspace_map_config[c] = config_isspace((char) c); + isspace_map_group_by_label[c] = group_by_label_isspace((char) c); + } +} diff --git a/libnetdata/line_splitter/line_splitter.h b/libnetdata/line_splitter/line_splitter.h new file mode 100644 index 000000000..b5a59ad3a --- /dev/null +++ b/libnetdata/line_splitter/line_splitter.h @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "../libnetdata.h" + +#ifndef NETDATA_LINE_SPLITTER_H +#define NETDATA_LINE_SPLITTER_H + +#define PLUGINSD_MAX_WORDS 30 + +struct line_splitter { + size_t count; // counts number of lines + char *words[PLUGINSD_MAX_WORDS]; // an array of pointers for the words in this line + size_t num_words; // the number of pointers used in this line +}; + +bool line_splitter_reconstruct_line(BUFFER *wb, void *ptr); + +static inline void line_splitter_reset(struct line_splitter *line) { + line->num_words = 0; +} + +int pluginsd_isspace(char c); +int config_isspace(char c); +int group_by_label_isspace(char c); + +extern bool isspace_map_pluginsd[256]; +extern bool isspace_map_config[256]; +extern bool isspace_map_group_by_label[256]; + +static inline size_t quoted_strings_splitter(char *str, char **words, size_t max_words, bool *isspace_map) { + char *s = str, quote = 0; + size_t i = 0; + + // skip all white space + while (unlikely(isspace_map[(uint8_t)*s])) + s++; + + if(unlikely(!*s)) { + words[i] = NULL; + return 0; + } + + // check for quote + if (unlikely(*s == '\'' || *s == '"')) { + quote = *s; // remember the quote + s++; // skip the quote + } + + // store the first word + words[i++] = s; + + // while we have something + while (likely(*s)) { + // if it is an escape + if (unlikely(*s == '\\' && s[1])) { + s += 2; + continue; + } + + // if it is a quote + else if (unlikely(*s == quote)) { + quote = 0; + *s = ' '; + continue; + } + + // if it is a space + else if (unlikely(quote == 0 && isspace_map[(uint8_t)*s])) { + // terminate the word + *s++ = '\0'; + + // skip all white space + while (likely(isspace_map[(uint8_t)*s])) + s++; + + // check for a quote + if (unlikely(*s == '\'' || *s == '"')) { + quote = *s; // remember the quote + s++; // skip the quote + } + + // if we reached the end, stop + if (unlikely(!*s)) + break; + + // store the next word + if (likely(i < max_words)) + words[i++] = s; + else + break; + } + + // anything else + else + s++; + } + + if (likely(i < max_words)) + words[i] = NULL; + + return i; +} + +#define quoted_strings_splitter_query_group_by_label(str, words, max_words) \ + quoted_strings_splitter(str, words, max_words, isspace_map_group_by_label) + +#define quoted_strings_splitter_config(str, words, max_words) \ + quoted_strings_splitter(str, words, max_words, isspace_map_config) + +#define quoted_strings_splitter_pluginsd(str, words, max_words) \ + quoted_strings_splitter(str, words, max_words, isspace_map_pluginsd) + +static inline char *get_word(char **words, size_t num_words, size_t index) { + if (unlikely(index >= num_words)) + return NULL; + + return words[index]; +} + +#endif //NETDATA_LINE_SPLITTER_H |