diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
commit | be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch) | |
tree | 9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/src/flb_sds.c | |
parent | Initial commit. (diff) | |
download | netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip |
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/src/flb_sds.c')
-rw-r--r-- | fluent-bit/src/flb_sds.c | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/fluent-bit/src/flb_sds.c b/fluent-bit/src/flb_sds.c new file mode 100644 index 00000000..2cb562c8 --- /dev/null +++ b/fluent-bit/src/flb_sds.c @@ -0,0 +1,500 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2022 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following SDS interface is a clone/strip-down version of the original + * SDS library created by Antirez at https://github.com/antirez/sds. + */ + +#include <fluent-bit/flb_compat.h> +#include <fluent-bit/flb_info.h> +#include <fluent-bit/flb_mem.h> +#include <fluent-bit/flb_log.h> +#include <fluent-bit/flb_sds.h> +#include <fluent-bit/flb_utf8.h> + +#include <stdarg.h> +#include <ctype.h> + +static flb_sds_t sds_alloc(size_t size) +{ + void *buf; + flb_sds_t s; + struct flb_sds *head; + + buf = flb_malloc(FLB_SDS_HEADER_SIZE + size + 1); + if (!buf) { + flb_errno(); + return NULL; + } + + head = buf; + head->len = 0; + head->alloc = size; + + s = head->buf; + *s = '\0'; + + return s; +} + +flb_sds_t flb_sds_create_len(const char *str, int len) +{ + flb_sds_t s; + struct flb_sds *head; + + s = sds_alloc(len); + if (!s) { + return NULL; + } + + if (str) { + memcpy(s, str, len); + s[len] = '\0'; + + head = FLB_SDS_HEADER(s); + head->len = len; + } + return s; +} + +flb_sds_t flb_sds_create(const char *str) +{ + size_t len; + + if (!str) { + len = 0; + } + else { + len = strlen(str); + } + + return flb_sds_create_len(str, len); +} + +flb_sds_t flb_sds_create_size(size_t size) +{ + return sds_alloc(size); +} + +/* Increase SDS buffer size 'len' bytes */ +flb_sds_t flb_sds_increase(flb_sds_t s, size_t len) +{ + size_t new_size; + struct flb_sds *head; + flb_sds_t out; + void *tmp; + + out = s; + new_size = (FLB_SDS_HEADER_SIZE + flb_sds_alloc(s) + len + 1); + head = FLB_SDS_HEADER(s); + tmp = flb_realloc(head, new_size); + if (!tmp) { + flb_errno(); + return NULL; + } + head = (struct flb_sds *) tmp; + head->alloc += len; + out = head->buf; + + return out; +} + +flb_sds_t flb_sds_cat(flb_sds_t s, const char *str, int len) +{ + size_t avail; + struct flb_sds *head; + flb_sds_t tmp = NULL; + + avail = flb_sds_avail(s); + if (avail < len) { + tmp = flb_sds_increase(s, len); + if (!tmp) { + return NULL; + } + s = tmp; + } + memcpy((char *) (s + flb_sds_len(s)), str, len); + + head = FLB_SDS_HEADER(s); + head->len += len; + s[head->len] = '\0'; + + return s; +} + + +/* + * remove empty spaces on left/right from sds buffer 's' and return the new length + * of the content. + */ +int flb_sds_trim(flb_sds_t s) +{ + unsigned int i; + unsigned int len; + char *left = 0, *right = 0; + char *buf; + + if (!s) { + return -1; + } + + len = flb_sds_len(s); + if (len == 0) { + return 0; + } + + buf = s; + left = buf; + + /* left spaces */ + while (left) { + if (isspace(*left)) { + left++; + } + else { + break; + } + } + + right = buf + (len - 1); + /* Validate right v/s left */ + if (right < left) { + buf[0] = '\0'; + return -1; + } + + /* Move back */ + while (right != buf){ + if (isspace(*right)) { + right--; + } + else { + break; + } + } + + len = (right - left) + 1; + for (i=0; i<len; i++) { + buf[i] = (char) left[i]; + } + buf[i] = '\0'; + flb_sds_len_set(buf, i); + + return i; +} + +int flb_sds_cat_safe(flb_sds_t *buf, const char *str, int len) +{ + flb_sds_t tmp; + + tmp = flb_sds_cat(*buf, str, len); + if (!tmp) { + return -1; + } + *buf = tmp; + return 0; +} + +flb_sds_t flb_sds_cat_esc(flb_sds_t s, const char *str, int len, + char *esc, size_t esc_size) +{ + size_t avail; + struct flb_sds *head; + flb_sds_t tmp = NULL; + uint32_t c; + int i; + + avail = flb_sds_avail(s); + if (avail < len) { + tmp = flb_sds_increase(s, len); + if (!tmp) { + return NULL; + } + s = tmp; + } + head = FLB_SDS_HEADER(s); + + for (i = 0; i < len; i++) { + if (flb_sds_avail(s) < 8) { + tmp = flb_sds_increase(s, 8); + if (tmp == NULL) { + return NULL; + } + s = tmp; + head = FLB_SDS_HEADER(s); + } + c = (unsigned char) str[i]; + if (esc != NULL && c < esc_size && esc[c] != 0) { + s[head->len++] = '\\'; + s[head->len++] = esc[c]; + } + else { + s[head->len++] = c; + } + } + + s[head->len] = '\0'; + + return s; +} + + +flb_sds_t flb_sds_copy(flb_sds_t s, const char *str, int len) +{ + size_t avail; + struct flb_sds *head; + flb_sds_t tmp = NULL; + + avail = flb_sds_alloc(s); + if (avail < len) { + tmp = flb_sds_increase(s, len); + if (!tmp) { + return NULL; + } + s = tmp; + } + memcpy((char *) s, str, len); + + head = FLB_SDS_HEADER(s); + head->len = len; + s[head->len] = '\0'; + + return s; +} + +flb_sds_t flb_sds_cat_utf8 (flb_sds_t *sds, const char *str, int str_len) +{ + static const char int2hex[] = "0123456789abcdef"; + int i; + int b; + int ret; + int hex_bytes; + uint32_t cp; + uint32_t state = 0; + unsigned char c; + const uint8_t *p; + struct flb_sds *head; + flb_sds_t tmp; + flb_sds_t s; + + s = *sds; + head = FLB_SDS_HEADER(s); + + if (flb_sds_avail(s) <= str_len) { + tmp = flb_sds_increase(s, str_len); + if (tmp == NULL) { + return NULL; + } + *sds = s = tmp; + head = FLB_SDS_HEADER(s); + } + + for (i = 0; i < str_len; i++) { + if (flb_sds_avail(s) < 8) { + tmp = flb_sds_increase(s, 8); + if (tmp == NULL) { + return NULL; + } + *sds = s = tmp; + head = FLB_SDS_HEADER(s); + } + + c = (unsigned char)str[i]; + if (c == '\\' || c == '"') { + s[head->len++] = '\\'; + s[head->len++] = c; + } + else if (c >= '\b' && c <= '\r') { + s[head->len++] = '\\'; + switch (c) { + case '\n': + s[head->len++] = 'n'; + break; + case '\t': + s[head->len++] = 't'; + break; + case '\b': + s[head->len++] = 'b'; + break; + case '\f': + s[head->len++] = 'f'; + break; + case '\r': + s[head->len++] = 'r'; + break; + case '\v': + s[head->len++] = 'u'; + s[head->len++] = '0'; + s[head->len++] = '0'; + s[head->len++] = '0'; + s[head->len++] = 'b'; + break; + } + } + else if (c < 32 || c == 0x7f) { + s[head->len++] = '\\'; + s[head->len++] = 'u'; + s[head->len++] = '0'; + s[head->len++] = '0'; + s[head->len++] = int2hex[ (unsigned char) ((c & 0xf0) >> 4)]; + s[head->len++] = int2hex[ (unsigned char) (c & 0x0f)]; + } + else if (c >= 0x80) { + hex_bytes = flb_utf8_len(str + i); + state = FLB_UTF8_ACCEPT; + cp = 0; + for (b = 0; b < hex_bytes; b++) { + p = (const unsigned char *) str + i + b; + if (p >= (unsigned char *) (str + str_len)) { + break; + } + ret = flb_utf8_decode(&state, &cp, *p); + if (ret == 0) { + break; + } + } + + if (state != FLB_UTF8_ACCEPT) { + /* Invalid UTF-8 hex, just skip utf-8 bytes */ + flb_warn("[pack] invalid UTF-8 bytes, skipping"); + break; + } + + s[head->len++] = '\\'; + s[head->len++] = 'u'; + if (cp > 0xFFFF) { + c = (unsigned char) ((cp & 0xf00000) >> 20); + if (c > 0) { + s[head->len++] = int2hex[c]; + } + c = (unsigned char) ((cp & 0x0f0000) >> 16); + if (c > 0) { + s[head->len++] = int2hex[c]; + } + } + s[head->len++] = int2hex[ (unsigned char) ((cp & 0xf000) >> 12)]; + s[head->len++] = int2hex[ (unsigned char) ((cp & 0x0f00) >> 8)]; + s[head->len++] = int2hex[ (unsigned char) ((cp & 0xf0) >> 4)]; + s[head->len++] = int2hex[ (unsigned char) (cp & 0x0f)]; + i += (hex_bytes - 1); + } + else { + s[head->len++] = c; + } + } + + s[head->len] = '\0'; + + return s; +} + +flb_sds_t flb_sds_printf(flb_sds_t *sds, const char *fmt, ...) +{ + va_list ap; + int len = strlen(fmt)*2; + int size; + flb_sds_t tmp = NULL; + flb_sds_t s; + struct flb_sds *head; + + if (len < 64) len = 64; + + s = *sds; + if (flb_sds_avail(s) < len) { + tmp = flb_sds_increase(s, len - flb_sds_avail(s)); + if (!tmp) { + return NULL; + } + *sds = s = tmp; + } + + va_start(ap, fmt); + size = vsnprintf((char *) (s + flb_sds_len(s)), flb_sds_avail(s), fmt, ap); + if (size < 0) { + flb_warn("[%s] buggy vsnprintf return %d", __FUNCTION__, size); + va_end(ap); + return NULL; + } + va_end(ap); + + if (size >= flb_sds_avail(s)) { + tmp = flb_sds_increase(s, size - flb_sds_avail(s) + 1); + if (!tmp) { + return NULL; + } + *sds = s = tmp; + + va_start(ap, fmt); + size = vsnprintf((char *) (s + flb_sds_len(s)), flb_sds_avail(s), fmt, ap); + if (size > flb_sds_avail(s)) { + flb_warn("[%s] vsnprintf is insatiable ", __FUNCTION__); + va_end(ap); + return NULL; + } + va_end(ap); + } + + head = FLB_SDS_HEADER(s); + head->len += size; + s[head->len] = '\0'; + + return s; +} + +void flb_sds_destroy(flb_sds_t s) +{ + struct flb_sds *head; + + if (!s) { + return; + } + + head = FLB_SDS_HEADER(s); + flb_free(head); +} + +/* + * flb_sds_snprintf is a wrapper of snprintf. + * The difference is that this function can increase the buffer of flb_sds_t. + */ +int flb_sds_snprintf(flb_sds_t *str, size_t size, const char *fmt, ...) +{ + va_list va; + flb_sds_t tmp; + int ret; + + retry_snprintf: + va_start(va, fmt); + ret = vsnprintf(*str, size, fmt, va); + if (ret > size) { + tmp = flb_sds_increase(*str, ret-size); + if (tmp == NULL) { + return -1; + } + *str = tmp; + size = ret; + va_end(va); + goto retry_snprintf; + } + va_end(va); + + flb_sds_len_set(*str, ret); + return ret; +} |