summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/stream_processor/flb_sp_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/src/stream_processor/flb_sp_key.c')
-rw-r--r--fluent-bit/src/stream_processor/flb_sp_key.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/fluent-bit/src/stream_processor/flb_sp_key.c b/fluent-bit/src/stream_processor/flb_sp_key.c
new file mode 100644
index 000000000..945621843
--- /dev/null
+++ b/fluent-bit/src/stream_processor/flb_sp_key.c
@@ -0,0 +1,231 @@
+/* -*- 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.
+ */
+
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_log.h>
+#include <fluent-bit/flb_sds.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_slist.h>
+
+#include <fluent-bit/stream_processor/flb_sp.h>
+#include <fluent-bit/stream_processor/flb_sp_parser.h>
+
+void flb_sp_key_value_print(struct flb_sp_value *v)
+{
+ if (v->type == FLB_EXP_BOOL) {
+ if (v->val.boolean) {
+ printf("true");
+ }
+ else {
+ printf("false");
+ }
+ }
+ else if (v->type == FLB_EXP_INT) {
+ printf("%" PRId64, v->val.i64);
+ }
+ else if (v->type == FLB_EXP_FLOAT) {
+ printf("%f", v->val.f64);
+ }
+ else if (v->type == FLB_EXP_STRING) {
+ printf("%s", v->val.string);
+ }
+ else if (v->type == FLB_EXP_NULL) {
+ printf("NULL");
+ }
+}
+
+/* Map msgpack object intp flb_sp_value representation */
+static int msgpack_object_to_sp_value(msgpack_object o,
+ struct flb_sp_value *result)
+{
+ result->o = o;
+
+ /* Compose result with found value */
+ if (o.type == MSGPACK_OBJECT_BOOLEAN) {
+ result->type = FLB_EXP_BOOL;
+ result->val.boolean = o.via.boolean;
+ return 0;
+ }
+ else if (o.type == MSGPACK_OBJECT_POSITIVE_INTEGER ||
+ o.type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
+ result->type = FLB_EXP_INT;
+ result->val.i64 = o.via.i64;
+ return 0;
+ }
+ else if (o.type == MSGPACK_OBJECT_FLOAT32 ||
+ o.type == MSGPACK_OBJECT_FLOAT) {
+ result->type = FLB_EXP_FLOAT;
+ result->val.f64 = o.via.f64;
+ return 0;
+ }
+ else if (o.type == MSGPACK_OBJECT_STR) {
+ result->type = FLB_EXP_STRING;
+ result->val.string = flb_sds_create_len((char *) o.via.str.ptr,
+ o.via.str.size);
+ return 0;
+ }
+ else if (o.type == MSGPACK_OBJECT_MAP) {
+ /* return boolean 'true', just denoting the existence of the key */
+ result->type = FLB_EXP_BOOL;
+ result->val.boolean = true;
+ return 0;
+ }
+ else if (o.type == MSGPACK_OBJECT_NIL) {
+ result->type = FLB_EXP_NULL;
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Lookup perfect match of sub-keys and map content */
+static int subkey_to_value(msgpack_object *map, struct mk_list *subkeys,
+ struct flb_sp_value *result)
+{
+ int i = 0;
+ int ret;
+ int levels;
+ int matched = 0;
+ msgpack_object *key_found = NULL;
+ msgpack_object key;
+ msgpack_object val;
+ msgpack_object cur_map;
+ struct mk_list *head;
+ struct flb_slist_entry *entry;
+
+ /* Expected number of map levels in the map */
+ levels = mk_list_size(subkeys);
+
+ cur_map = *map;
+
+ mk_list_foreach(head, subkeys) {
+ /* Key expected key entry */
+ entry = mk_list_entry(head, struct flb_slist_entry, _head);
+
+ if (cur_map.type != MSGPACK_OBJECT_MAP) {
+ break;
+ }
+
+ /* Get map entry that matches entry name */
+ for (i = 0; i < cur_map.via.map.size; i++) {
+ key = cur_map.via.map.ptr[i].key;
+ val = cur_map.via.map.ptr[i].val;
+
+ /* A bit obvious, but it's better to validate data type */
+ if (key.type != MSGPACK_OBJECT_STR) {
+ continue;
+ }
+
+ /* Compare strings by length and content */
+ if (flb_sds_cmp(entry->str,
+ (char *) key.via.str.ptr,
+ key.via.str.size) != 0) {
+ key_found = NULL;
+ continue;
+ }
+
+ key_found = &key;
+ cur_map = val;
+ matched++;
+ break;
+ }
+
+ if (levels == matched) {
+ break;
+ }
+ }
+
+ /* No matches */
+ if (!key_found || (matched > 0 && levels != matched)) {
+ return -1;
+ }
+
+ ret = msgpack_object_to_sp_value(val, result);
+ if (ret == -1) {
+ //flb_error("[sp key] cannot process key value");
+ return -1;
+ }
+
+ return 0;
+}
+
+struct flb_sp_value *flb_sp_key_to_value(flb_sds_t ckey,
+ msgpack_object map,
+ struct mk_list *subkeys)
+{
+ int i;
+ int ret;
+ int map_size;
+ msgpack_object key;
+ msgpack_object val;
+ struct flb_sp_value *result;
+
+ map_size = map.via.map.size;
+ for (i = 0; i < map_size; i++) {
+ key = map.via.map.ptr[i].key;
+ val = map.via.map.ptr[i].val;
+
+ /* Compare by length and by key name */
+ if (flb_sds_cmp(ckey, key.via.str.ptr, key.via.str.size) != 0) {
+ continue;
+ }
+
+ result = flb_calloc(1, sizeof(struct flb_sp_value));
+ if (!result) {
+ flb_errno();
+ return NULL;
+ }
+ result->o = val;
+
+ if (val.type == MSGPACK_OBJECT_MAP && subkeys != NULL) {
+ ret = subkey_to_value(&val, subkeys, result);
+ if (ret == 0) {
+ return result;
+ }
+ else {
+ flb_free(result);
+ return NULL;
+ }
+ }
+ else {
+ ret = msgpack_object_to_sp_value(val, result);
+ if (ret == -1) {
+ flb_error("[sp key] cannot process key value");
+ flb_free(result);
+ return NULL;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ * NULL return means: failed memory allocation, an invalid value,
+ * or non-existing key.
+ */
+ return NULL;
+}
+
+void flb_sp_key_value_destroy(struct flb_sp_value *v)
+{
+ if (v->type == FLB_EXP_STRING) {
+ flb_sds_destroy(v->val.string);
+ }
+ flb_free(v);
+}