diff --git a/include/fluent-bit/flb_mp.h b/include/fluent-bit/flb_mp.h index 28a216d82c9..88d249ccab4 100644 --- a/include/fluent-bit/flb_mp.h +++ b/include/fluent-bit/flb_mp.h @@ -85,4 +85,7 @@ void flb_mp_accessor_set_active(struct flb_mp_accessor *mpa, int status); int flb_mp_accessor_set_active_by_pattern(struct flb_mp_accessor *mpa, const char *pattern, int status); +struct cfl_object *flb_mp_object_to_cfl(msgpack_object *o); +int flb_mp_cfl_to_msgpack(struct cfl_object *obj, char **out_buf, size_t *out_size); + #endif diff --git a/lib/cfl/CMakeLists.txt b/lib/cfl/CMakeLists.txt index 3f8424dffc7..dbdd62ed913 100644 --- a/lib/cfl/CMakeLists.txt +++ b/lib/cfl/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # C Floppy Version set(CFL_VERSION_MAJOR 0) -set(CFL_VERSION_MINOR 3) +set(CFL_VERSION_MINOR 4) set(CFL_VERSION_PATCH 0) set(CFL_VERSION_STR "${CFL_VERSION_MAJOR}.${CFL_VERSION_MINOR}.${CFL_VERSION_PATCH}") diff --git a/lib/cfl/include/cfl/cfl.h b/lib/cfl/include/cfl/cfl.h index fee8fcf4dc1..8e4efa763d4 100644 --- a/lib/cfl/include/cfl/cfl.h +++ b/lib/cfl/include/cfl/cfl.h @@ -36,6 +36,7 @@ #include #include #include +#include int cfl_init(); diff --git a/lib/cfl/include/cfl/cfl_array.h b/lib/cfl/include/cfl/cfl_array.h index bc525013174..590a8593fe9 100644 --- a/lib/cfl/include/cfl/cfl_array.h +++ b/lib/cfl/include/cfl/cfl_array.h @@ -54,10 +54,10 @@ int cfl_array_append_bool(struct cfl_array *array, int value); int cfl_array_append_int64(struct cfl_array *array, int64_t value); int cfl_array_append_uint64(struct cfl_array *array, uint64_t value); int cfl_array_append_double(struct cfl_array *array, double value); +int cfl_array_append_null(struct cfl_array *array); int cfl_array_append_array(struct cfl_array *array, struct cfl_array *value); int cfl_array_append_new_array(struct cfl_array *array, size_t size); -int cfl_array_append_kvlist(struct cfl_array *array, struct -cfl_kvlist *value); +int cfl_array_append_kvlist(struct cfl_array *array, struct cfl_kvlist *value); int cfl_array_print(FILE *fp, struct cfl_array *array); #endif diff --git a/lib/cfl/include/cfl/cfl_compat.h b/lib/cfl/include/cfl/cfl_compat.h index 36c56233be5..bc1de9a0673 100644 --- a/lib/cfl/include/cfl/cfl_compat.h +++ b/lib/cfl/include/cfl/cfl_compat.h @@ -39,8 +39,10 @@ #define timezone _timezone #define tzname _tzname #define strncasecmp _strnicmp +#define strcasecmp _stricmp #define timegm _mkgmtime #endif /* _MSC_VER */ #endif #endif + diff --git a/lib/cfl/include/cfl/cfl_kvlist.h b/lib/cfl/include/cfl/cfl_kvlist.h index d766e9656c4..6c223debfc8 100644 --- a/lib/cfl/include/cfl/cfl_kvlist.h +++ b/lib/cfl/include/cfl/cfl_kvlist.h @@ -76,4 +76,55 @@ int cfl_kvlist_count(struct cfl_kvlist *list); struct cfl_variant *cfl_kvlist_fetch(struct cfl_kvlist *list, char *key); int cfl_kvlist_print(FILE *fp, struct cfl_kvlist *list); +int cfl_kvlist_insert_string_s(struct cfl_kvlist *list, + char *key, size_t key_size, + char *value, size_t value_size); + +int cfl_kvlist_insert_bytes_s(struct cfl_kvlist *list, + char *key, size_t key_size, + char *value, + size_t value_length); + +int cfl_kvlist_insert_reference_s(struct cfl_kvlist *list, + char *key, size_t key_size, + void *value); + +int cfl_kvlist_insert_bool_s(struct cfl_kvlist *list, + char *key, size_t key_size, int value); + +int cfl_kvlist_insert_int64_s(struct cfl_kvlist *list, + char *key, size_t key_size, + int64_t value); + +int cfl_kvlist_insert_uint64_s(struct cfl_kvlist *list, + char *key, size_t key_size, + uint64_t value); + +int cfl_kvlist_insert_double_s(struct cfl_kvlist *list, + char *key, size_t key_size, + double value); + +int cfl_kvlist_insert_array_s(struct cfl_kvlist *list, + char *key, size_t key_size, + struct cfl_array *value); + +int cfl_kvlist_insert_new_array_s(struct cfl_kvlist *list, + char *key, size_t key_size, + size_t size); + +int cfl_kvlist_insert_kvlist_s(struct cfl_kvlist *list, + char *key, size_t key_size, + struct cfl_kvlist *value); + +int cfl_kvlist_insert_s(struct cfl_kvlist *list, + char *key, size_t key_size, + struct cfl_variant *value); + +struct cfl_variant *cfl_kvlist_fetch_s(struct cfl_kvlist *list, char *key, size_t key_size); + +int cfl_kvlist_contains(struct cfl_kvlist *kvlist, char *name); +int cfl_kvlist_remove(struct cfl_kvlist *kvlist, char *name); +void cfl_kvpair_destroy(struct cfl_kvpair *pair); + + #endif diff --git a/lib/cfl/include/cfl/cfl_object.h b/lib/cfl/include/cfl/cfl_object.h new file mode 100644 index 00000000000..f959ac4ef3b --- /dev/null +++ b/lib/cfl/include/cfl/cfl_object.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CFL + * === + * Copyright (C) 2022 The CFL 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. + */ + +#ifndef CFL_OBJECT_H +#define CFL_OBJECT_H + +enum { + CFL_OBJECT_NONE = 0, + CFL_OBJECT_KVLIST = 1, + CFL_OBJECT_VARIANT, + CFL_OBJECT_ARRAY +}; + +struct cfl_object { + int type; + struct cfl_variant *variant; + struct cfl_list _head; +}; + +struct cfl_object *cfl_object_create(); +void cfl_object_destroy(struct cfl_object *obj); +int cfl_object_set(struct cfl_object *o, int type, void *ptr); +int cfl_object_print(FILE *stream, struct cfl_object *o); + +#endif diff --git a/lib/cfl/include/cfl/cfl_variant.h b/lib/cfl/include/cfl/cfl_variant.h index 964dc2ebf18..e7135c99314 100644 --- a/lib/cfl/include/cfl/cfl_variant.h +++ b/lib/cfl/include/cfl/cfl_variant.h @@ -21,23 +21,26 @@ #define CFL_VARIANT_H #include +#include #include -#define CFL_VARIANT_STRING 1 -#define CFL_VARIANT_BOOL 2 -#define CFL_VARIANT_INT 3 -#define CFL_VARIANT_DOUBLE 4 -#define CFL_VARIANT_ARRAY 5 -#define CFL_VARIANT_KVLIST 6 -#define CFL_VARIANT_BYTES 7 -#define CFL_VARIANT_REFERENCE 8 -#define CFL_VARIANT_UINT 9 +#define CFL_VARIANT_STRING 1 +#define CFL_VARIANT_BOOL 2 +#define CFL_VARIANT_INT 3 +#define CFL_VARIANT_DOUBLE 4 +#define CFL_VARIANT_ARRAY 5 +#define CFL_VARIANT_KVLIST 6 +#define CFL_VARIANT_BYTES 7 +#define CFL_VARIANT_REFERENCE 8 +#define CFL_VARIANT_UINT 9 +#define CFL_VARIANT_NULL 10 struct cfl_array; struct cfl_kvlist; struct cfl_variant { int type; + size_t size; union { cfl_sds_t as_string; @@ -51,14 +54,17 @@ struct cfl_variant { struct cfl_kvlist *as_kvlist; } data; }; + int cfl_variant_print(FILE *fp, struct cfl_variant *val); struct cfl_variant *cfl_variant_create_from_string(char *value); +struct cfl_variant *cfl_variant_create_from_string_s(char *value, size_t value_length); struct cfl_variant *cfl_variant_create_from_bytes(char *value, size_t length); struct cfl_variant *cfl_variant_create_from_bool(int value); struct cfl_variant *cfl_variant_create_from_int64(int64_t value); struct cfl_variant *cfl_variant_create_from_uint64(uint64_t value); struct cfl_variant *cfl_variant_create_from_double(double value); struct cfl_variant *cfl_variant_create_from_array(struct cfl_array *value); +struct cfl_variant *cfl_variant_create_from_null(); struct cfl_variant *cfl_variant_create_from_kvlist(struct cfl_kvlist *value); struct cfl_variant *cfl_variant_create_from_reference(void *value); struct cfl_variant *cfl_variant_create(); diff --git a/lib/cfl/src/CMakeLists.txt b/lib/cfl/src/CMakeLists.txt index 53f2a620e31..05383f3fef3 100644 --- a/lib/cfl/src/CMakeLists.txt +++ b/lib/cfl/src/CMakeLists.txt @@ -5,6 +5,7 @@ set(src cfl_time.c cfl_kv.c cfl_kvlist.c + cfl_object.c cfl_array.c cfl_variant.c cfl_checksum.c diff --git a/lib/cfl/src/cfl_array.c b/lib/cfl/src/cfl_array.c index e9b87c77fc5..1bad9e86212 100644 --- a/lib/cfl/src/cfl_array.c +++ b/lib/cfl/src/cfl_array.c @@ -2,7 +2,7 @@ /* CFL * === - * Copyright (C) 2022 The CFL Authors + * Copyright (C) 2022-2024 The CFL Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -305,6 +305,24 @@ int cfl_array_append_double(struct cfl_array *array, double value) return 0; } +int cfl_array_append_null(struct cfl_array *array) +{ + struct cfl_variant *value_instance; + int result; + + value_instance = cfl_variant_create_from_null(); + if (value_instance == NULL) { + return -1; + } + + result = cfl_array_append(array, value_instance); + if (result) { + cfl_variant_destroy(value_instance); + return -2; + } + + return 0; +} int cfl_array_append_array(struct cfl_array *array, struct cfl_array *value) { @@ -347,8 +365,7 @@ int cfl_array_append_new_array(struct cfl_array *array, size_t size) return result; } -int cfl_array_append_kvlist(struct cfl_array *array, struct -cfl_kvlist *value) +int cfl_array_append_kvlist(struct cfl_array *array, struct cfl_kvlist *value) { struct cfl_variant *value_instance; int result; diff --git a/lib/cfl/src/cfl_kvlist.c b/lib/cfl/src/cfl_kvlist.c index bdfc9f0375d..ca1bf3b8090 100644 --- a/lib/cfl/src/cfl_kvlist.c +++ b/lib/cfl/src/cfl_kvlist.c @@ -21,6 +21,7 @@ #include #include #include +#include struct cfl_kvlist *cfl_kvlist_create() { @@ -98,18 +99,18 @@ int cfl_kvlist_insert(struct cfl_kvlist *list, } */ -int cfl_kvlist_insert_string(struct cfl_kvlist *list, - char *key, char *value) +int cfl_kvlist_insert_string_s(struct cfl_kvlist *list, + char *key, size_t key_size, char *value, size_t value_size) { struct cfl_variant *value_instance; int result; - value_instance = cfl_variant_create_from_string(value); + value_instance = cfl_variant_create_from_string_s(value, value_size); if (value_instance == NULL) { return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -119,9 +120,10 @@ int cfl_kvlist_insert_string(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_bytes(struct cfl_kvlist *list, - char *key, char *value, - size_t length) +int cfl_kvlist_insert_bytes_s(struct cfl_kvlist *list, + char *key, size_t key_size, + char *value, + size_t length) { struct cfl_variant *value_instance; int result; @@ -132,7 +134,7 @@ int cfl_kvlist_insert_bytes(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -143,8 +145,8 @@ int cfl_kvlist_insert_bytes(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_reference(struct cfl_kvlist *list, - char *key, void *value) +int cfl_kvlist_insert_reference_s(struct cfl_kvlist *list, + char *key, size_t key_size, void *value) { struct cfl_variant *value_instance; int result; @@ -155,7 +157,7 @@ int cfl_kvlist_insert_reference(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -166,8 +168,8 @@ int cfl_kvlist_insert_reference(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_bool(struct cfl_kvlist *list, - char *key, int value) +int cfl_kvlist_insert_bool_s(struct cfl_kvlist *list, + char *key, size_t key_size, int value) { struct cfl_variant *value_instance; int result; @@ -178,7 +180,7 @@ int cfl_kvlist_insert_bool(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -189,8 +191,8 @@ int cfl_kvlist_insert_bool(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_int64(struct cfl_kvlist *list, - char *key, int64_t value) +int cfl_kvlist_insert_int64_s(struct cfl_kvlist *list, + char *key, size_t key_size, int64_t value) { struct cfl_variant *value_instance; int result; @@ -201,7 +203,7 @@ int cfl_kvlist_insert_int64(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -212,8 +214,8 @@ int cfl_kvlist_insert_int64(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_uint64(struct cfl_kvlist *list, - char *key, uint64_t value) +int cfl_kvlist_insert_uint64_s(struct cfl_kvlist *list, + char *key, size_t key_size, uint64_t value) { struct cfl_variant *value_instance; int result; @@ -224,7 +226,7 @@ int cfl_kvlist_insert_uint64(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -235,8 +237,8 @@ int cfl_kvlist_insert_uint64(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_double(struct cfl_kvlist *list, - char *key, double value) +int cfl_kvlist_insert_double_s(struct cfl_kvlist *list, + char *key, size_t key_size, double value) { struct cfl_variant *value_instance; int result; @@ -247,7 +249,7 @@ int cfl_kvlist_insert_double(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -258,8 +260,8 @@ int cfl_kvlist_insert_double(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_array(struct cfl_kvlist *list, - char *key, struct cfl_array *value) +int cfl_kvlist_insert_array_s(struct cfl_kvlist *list, + char *key, size_t key_size, struct cfl_array *value) { struct cfl_variant *value_instance; int result; @@ -270,7 +272,7 @@ int cfl_kvlist_insert_array(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -281,8 +283,9 @@ int cfl_kvlist_insert_array(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert_new_array(struct cfl_kvlist *list, - char *key, size_t size) + +int cfl_kvlist_insert_new_array_s(struct cfl_kvlist *list, + char *key, size_t key_size, size_t size) { int result; struct cfl_array *value; @@ -293,7 +296,7 @@ int cfl_kvlist_insert_new_array(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert_array(list, key, value); + result = cfl_kvlist_insert_array_s(list, key, key_size, value); if (result) { cfl_array_destroy(value); @@ -302,8 +305,8 @@ int cfl_kvlist_insert_new_array(struct cfl_kvlist *list, return result; } -int cfl_kvlist_insert_kvlist(struct cfl_kvlist *list, - char *key, struct cfl_kvlist *value) +int cfl_kvlist_insert_kvlist_s(struct cfl_kvlist *list, + char *key, size_t key_size, struct cfl_kvlist *value) { struct cfl_variant *value_instance; int result; @@ -313,7 +316,7 @@ int cfl_kvlist_insert_kvlist(struct cfl_kvlist *list, return -1; } - result = cfl_kvlist_insert(list, key, value_instance); + result = cfl_kvlist_insert_s(list, key, key_size, value_instance); if (result) { cfl_variant_destroy(value_instance); @@ -324,19 +327,23 @@ int cfl_kvlist_insert_kvlist(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_insert(struct cfl_kvlist *list, - char *key, struct cfl_variant *value) +int cfl_kvlist_insert_s(struct cfl_kvlist *list, + char *key, size_t key_size, + struct cfl_variant *value) { struct cfl_kvpair *pair; + if (list == NULL || key == NULL || value == NULL) { + return -1; + } + pair = malloc(sizeof(struct cfl_kvpair)); if (pair == NULL) { cfl_report_runtime_error(); return -1; } - pair->key = cfl_sds_create(key); - + pair->key = cfl_sds_create_len(key, key_size); if (pair->key == NULL) { free(pair); @@ -349,27 +356,19 @@ int cfl_kvlist_insert(struct cfl_kvlist *list, return 0; } -int cfl_kvlist_count(struct cfl_kvlist *list) +struct cfl_variant *cfl_kvlist_fetch_s(struct cfl_kvlist *list, char *key, size_t key_size) { - return cfl_list_size(&list->list); -} - -struct cfl_variant *cfl_kvlist_fetch(struct cfl_kvlist *list, char *key) -{ - int len; struct cfl_list *head; struct cfl_kvpair *pair; - len = strlen(key); - cfl_list_foreach(head, &list->list) { pair = cfl_list_entry(head, struct cfl_kvpair, _head); - if (cfl_sds_len(pair->key) != len) { + if (cfl_sds_len(pair->key) != key_size) { continue; } - if (strcmp(pair->key, key) == 0) { + if (strncmp(pair->key, key, key_size) == 0) { return pair->val; } } @@ -377,6 +376,94 @@ struct cfl_variant *cfl_kvlist_fetch(struct cfl_kvlist *list, char *key) return NULL; } + +int cfl_kvlist_insert_string(struct cfl_kvlist *list, + char *key, char *value) +{ + int key_len; + int val_len; + + if (!key || !value) { + return -1; + } + + key_len = strlen(key); + val_len = strlen(value); + + return cfl_kvlist_insert_string_s(list, key, key_len, value, val_len); +} + +int cfl_kvlist_insert_bytes(struct cfl_kvlist *list, + char *key, char *value, + size_t length) +{ + return cfl_kvlist_insert_bytes_s(list, key, strlen(key), value, length); +} + +int cfl_kvlist_insert_reference(struct cfl_kvlist *list, + char *key, void *value) +{ + return cfl_kvlist_insert_reference_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_bool(struct cfl_kvlist *list, + char *key, int value) +{ + return cfl_kvlist_insert_bool_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_int64(struct cfl_kvlist *list, + char *key, int64_t value) +{ + return cfl_kvlist_insert_int64_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_uint64(struct cfl_kvlist *list, + char *key, uint64_t value) +{ + return cfl_kvlist_insert_uint64_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_double(struct cfl_kvlist *list, + char *key, double value) +{ + return cfl_kvlist_insert_double_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_array(struct cfl_kvlist *list, + char *key, struct cfl_array *value) +{ + return cfl_kvlist_insert_array_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert_new_array(struct cfl_kvlist *list, + char *key, size_t size) +{ + return cfl_kvlist_insert_new_array_s(list, key, strlen(key), size); +} + +int cfl_kvlist_insert_kvlist(struct cfl_kvlist *list, + char *key, struct cfl_kvlist *value) +{ + return cfl_kvlist_insert_kvlist_s(list, key, strlen(key), value); +} + +int cfl_kvlist_insert(struct cfl_kvlist *list, + char *key, struct cfl_variant *value) +{ + return cfl_kvlist_insert_s(list, key, strlen(key), value); +} + +struct cfl_variant *cfl_kvlist_fetch(struct cfl_kvlist *list, char *key) +{ + return cfl_kvlist_fetch_s(list, key, strlen(key)); +} + +int cfl_kvlist_count(struct cfl_kvlist *list) +{ + return cfl_list_size(&list->list); +} + int cfl_kvlist_print(FILE *fp, struct cfl_kvlist *list) { size_t size; @@ -411,3 +498,60 @@ int cfl_kvlist_print(FILE *fp, struct cfl_kvlist *list) return ret; } + +int cfl_kvlist_contains(struct cfl_kvlist *kvlist, char *name) +{ + struct cfl_list *iterator; + struct cfl_kvpair *pair; + + cfl_list_foreach(iterator, &kvlist->list) { + pair = cfl_list_entry(iterator, + struct cfl_kvpair, _head); + + if (strcasecmp(pair->key, name) == 0) { + return CFL_TRUE; + } + } + + return CFL_FALSE; +} + + +int cfl_kvlist_remove(struct cfl_kvlist *kvlist, char *name) +{ + struct cfl_list *iterator_backup; + struct cfl_list *iterator; + struct cfl_kvpair *pair; + + cfl_list_foreach_safe(iterator, iterator_backup, &kvlist->list) { + pair = cfl_list_entry(iterator, + struct cfl_kvpair, _head); + + if (strcasecmp(pair->key, name) == 0) { + cfl_kvpair_destroy(pair); + } + } + + return CFL_TRUE; +} + + +void cfl_kvpair_destroy(struct cfl_kvpair *pair) +{ + if (pair != NULL) { + if (!cfl_list_entry_is_orphan(&pair->_head)) { + cfl_list_del(&pair->_head); + } + + if (pair->key != NULL) { + cfl_sds_destroy(pair->key); + } + + if (pair->val != NULL) { + cfl_variant_destroy(pair->val); + } + + free(pair); + } +} + diff --git a/lib/cfl/src/cfl_object.c b/lib/cfl/src/cfl_object.c new file mode 100644 index 00000000000..56d13ee2ea8 --- /dev/null +++ b/lib/cfl/src/cfl_object.c @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CFL + * === + * Copyright (C) 2022-2024 The CFL 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 "cfl/cfl.h" + +/* CFL Object + * ========== + * the CFL Object interface is a generic object that can hold a cfl_kvlist, cfl_array + * or a cfl_variant. It's used as a wrapper to link different objects and/or provide + * a common interface to the user. + */ + + +/* Create CFL Object context */ +struct cfl_object *cfl_object_create() +{ + struct cfl_object *o; + + o = calloc(1, sizeof(struct cfl_object)); + if (!o) { + cfl_errno(); + return NULL; + } + + /* mark it as not initialized */ + o->type = CFL_OBJECT_NONE; + return o; +} + +/* + * Associate a CFL data type to the object. We only support kvlist, array and variant. Note + * that everything is held as a variant internally. + */ +int cfl_object_set(struct cfl_object *o, int type, void *ptr) +{ + if (!o) { + return -1; + } + + if (type == CFL_OBJECT_KVLIST) { + o->type = CFL_OBJECT_KVLIST; + o->variant = cfl_variant_create_from_kvlist(ptr); + } + else if (type == CFL_OBJECT_VARIANT) { + o->type = CFL_OBJECT_VARIANT; + o->variant = ptr; + } + else if (type == CFL_OBJECT_ARRAY) { + o->type = CFL_OBJECT_ARRAY; + o->variant = cfl_variant_create_from_array(ptr); + } + else { + return -1; + } + + return 0; +} + +int cfl_object_print(FILE *stream, struct cfl_object *o) +{ + if (!o) { + return -1; + } + + if (!o->variant) { + return -1; + } + + cfl_variant_print(stream, o->variant); + printf("\n"); + + return 0; +} + +/* + * Destroy the object, note that if a CFL data type is linked + * it will be destroyed as well + */ +void cfl_object_destroy(struct cfl_object *o) +{ + if (!o) { + return; + } + + if (o->variant) { + cfl_variant_destroy(o->variant); + } + + free(o); +} \ No newline at end of file diff --git a/lib/cfl/src/cfl_variant.c b/lib/cfl/src/cfl_variant.c index 455af099bdc..5f6748ce400 100644 --- a/lib/cfl/src/cfl_variant.c +++ b/lib/cfl/src/cfl_variant.c @@ -21,6 +21,7 @@ #include #include #include +#include #if defined(__MINGW32__) || defined(__MINGW64__) #define HEXDUMPFORMAT "%#x" @@ -59,6 +60,9 @@ int cfl_variant_print(FILE *fp, struct cfl_variant *val) case CFL_VARIANT_DOUBLE: ret = fprintf(fp, "%lf", val->data.as_double); break; + case CFL_VARIANT_NULL: + ret = fprintf(fp, "null"); + break; case CFL_VARIANT_BYTES: size = cfl_sds_len(val->data.as_bytes); for (i=0; idata.as_string = cfl_sds_create(value); + instance->data.as_string = cfl_sds_create_len(value, value_size); if (instance->data.as_string == NULL) { free(instance); instance = NULL; @@ -103,6 +107,11 @@ struct cfl_variant *cfl_variant_create_from_string(char *value) return instance; } +struct cfl_variant *cfl_variant_create_from_string(char *value) +{ + return cfl_variant_create_from_string_s(value, strlen(value)); +} + struct cfl_variant *cfl_variant_create_from_bytes(char *value, size_t length) { struct cfl_variant *instance; @@ -175,6 +184,18 @@ struct cfl_variant *cfl_variant_create_from_double(double value) return instance; } +struct cfl_variant *cfl_variant_create_from_null() +{ + struct cfl_variant *instance; + + instance = cfl_variant_create(); + if (instance != NULL) { + instance->type = CFL_VARIANT_NULL; + } + + return instance; +} + struct cfl_variant *cfl_variant_create_from_array(struct cfl_array *value) { struct cfl_variant *instance; diff --git a/lib/cfl/tests/CMakeLists.txt b/lib/cfl/tests/CMakeLists.txt index 0fac328ca72..513facc9cc3 100644 --- a/lib/cfl/tests/CMakeLists.txt +++ b/lib/cfl/tests/CMakeLists.txt @@ -2,10 +2,12 @@ include_directories(lib/acutest) set(UNIT_TESTS_FILES kv.c + kvlist.c sds.c hash.c list.c variant.c + object.c ) configure_file( diff --git a/lib/cfl/tests/kvlist.c b/lib/cfl/tests/kvlist.c new file mode 100644 index 00000000000..fce4319b898 --- /dev/null +++ b/lib/cfl/tests/kvlist.c @@ -0,0 +1,1197 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CFL + * === + * Copyright (C) 2022-2024 The CFL 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 + +#include +#include + +#include "cfl_tests_internal.h" + +static void create_destroy() +{ + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + cfl_kvlist_destroy(list); +} + +static void count() +{ + struct cfl_kvlist *list = NULL; + int i; + int count = 12; + int ret; + char buf[128] = {0}; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + for (i=0; itype == CFL_VARIANT_INT)) { + TEST_MSG("variant type is not int. ret=%d", var->type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_int64 == 128)) { + TEST_MSG("variant value error.got=%"PRId64" expect=128", var->data.as_int64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void fetch_s() +{ + int ret; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_int64(list, "key", 128); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_int64 failed"); + cfl_kvlist_destroy(list); + return; + } + + /* invalid key name 'k' */ + var = cfl_kvlist_fetch(list, "k"); + if (!TEST_CHECK(var == NULL)) { + TEST_MSG("cfl_kvlist_fetch returned invalid pointer"); + cfl_kvlist_destroy(list); + return; + } + + /* invalid key name 'key_is_invalid' */ + var = cfl_kvlist_fetch(list, "key_is_invalid"); + if (!TEST_CHECK(var == NULL)) { + TEST_MSG("cfl_kvlist_fetch returned invalid pointer"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key_is_long_name", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == CFL_VARIANT_INT)) { + TEST_MSG("variant type is not int. ret=%d", var->type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_int64 == 128)) { + TEST_MSG("variant value error.got=%"PRId64" expect=128", var->data.as_int64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_string() +{ + int ret; + int expect_type = CFL_VARIANT_STRING; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_string(list, "key", "value"); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_string failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(strncmp("value", var->data.as_string,5) == 0)) { + TEST_MSG("variant value error.got=%s expect=value", var->data.as_string); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_bytes() +{ + int ret; + int expect_type = CFL_VARIANT_BYTES; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_bytes(list, "key", "value", 5); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_bytes failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(memcmp("value", var->data.as_bytes,5) == 0)) { + TEST_MSG("variant value error.got=%s expect=value", var->data.as_bytes); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_reference() +{ + int ret; + int expect_type = CFL_VARIANT_REFERENCE; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_reference(list, "key", &expect_type); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_reference failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_reference == &expect_type)) { + TEST_MSG("variant value error.got=%p expect=%p", var->data.as_reference, &expect_type); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_bool() +{ + int ret; + int expect_type = CFL_VARIANT_BOOL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_bool(list, "key", CFL_TRUE); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_bool failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_bool == CFL_TRUE)) { + TEST_MSG("variant value error.got=%d expect=%d", var->data.as_bool, CFL_TRUE); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_int64() +{ + int ret; + int expect_type = CFL_VARIANT_INT; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_int64(list, "key", -123456); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_int64 failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_int64 == -123456)) { + TEST_MSG("variant value error.got=%"PRId64" expect=-123456", var->data.as_int64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_uint64() +{ + int ret; + int expect_type = CFL_VARIANT_UINT; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_uint64(list, "key", 123456); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_uint64 failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_uint64 == 123456)) { + TEST_MSG("variant value error.got=%"PRIu64" expect=123456", var->data.as_uint64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_double() +{ + int ret; + double input = 123456.789; + int expect_type = CFL_VARIANT_DOUBLE; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_double(list, "key", input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_double failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(fabs(var->data.as_double - input) < DBL_EPSILON)) { + TEST_MSG("variant value error.got=%lf expect=%lf", var->data.as_double, input); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_new_array() +{ + int ret; + int expect_type = CFL_VARIANT_ARRAY; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_new_array(list, "key", 123); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_new_array failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_array->slot_count == 123)) { + TEST_MSG("variant value error.got=%d expect=123", var->data.as_array->slot_count); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_empty_array() +{ + int ret; + int expect_type = CFL_VARIANT_ARRAY; + struct cfl_array *input = NULL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + input = cfl_array_create(123); + if (!TEST_CHECK(input != NULL)) { + TEST_MSG("cfl_array_create failed"); + cfl_kvlist_destroy(list); + return; + } + + ret = cfl_kvlist_insert_array(list, "key", input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_array failed"); + cfl_kvlist_destroy(list); + cfl_array_destroy(input); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_array->slot_count == 123)) { + TEST_MSG("variant value error.got=%d expect=123", var->data.as_array->slot_count); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_empty_kvlist() +{ + int ret; + int expect_type = CFL_VARIANT_KVLIST; + struct cfl_kvlist *input = NULL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + input = cfl_kvlist_create(); + if (!TEST_CHECK(input != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + cfl_kvlist_destroy(list); + return; + } + + ret = cfl_kvlist_insert_kvlist(list, "key", input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_kvlist failed"); + cfl_kvlist_destroy(list); + cfl_kvlist_destroy(input); + return; + } + + var = cfl_kvlist_fetch(list, "key"); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_string_s() +{ + int ret; + int expect_type = CFL_VARIANT_STRING; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_string_s(list, "key!!!!!", 3, "value", 5); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_string_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key?????", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(strncmp("value", var->data.as_string,5) == 0)) { + TEST_MSG("variant value error.got=%s expect=value", var->data.as_string); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_bytes_s() +{ + int ret; + int expect_type = CFL_VARIANT_BYTES; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_bytes_s(list, "key!!!!!", 3, "value", 5); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_bytes_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key??????????????", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(memcmp("value", var->data.as_bytes,5) == 0)) { + TEST_MSG("variant value error.got=%s expect=value", var->data.as_bytes); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_reference_s() +{ + int ret; + int expect_type = CFL_VARIANT_REFERENCE; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_reference_s(list, "key!!!", 3, &expect_type); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_reference_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key????", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_reference == &expect_type)) { + TEST_MSG("variant value error.got=%p expect=%p", var->data.as_reference, &expect_type); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_bool_s() +{ + int ret; + int expect_type = CFL_VARIANT_BOOL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_bool_s(list, "key!!!!", 3, CFL_TRUE); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_bool_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key???", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_bool == CFL_TRUE)) { + TEST_MSG("variant value error.got=%d expect=%d", var->data.as_bool, CFL_TRUE); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_int64_s() +{ + int ret; + int expect_type = CFL_VARIANT_INT; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_int64_s(list, "key!!!!", 3, -123456); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_int64_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key??", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_int64 == -123456)) { + TEST_MSG("variant value error.got=%"PRId64" expect=-123456", var->data.as_int64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_uint64_s() +{ + int ret; + int expect_type = CFL_VARIANT_UINT; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_uint64_s(list, "key???", 3, 123456); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_uint64_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key!!!", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_uint64 == 123456)) { + TEST_MSG("variant value error.got=%"PRIu64" expect=123456", var->data.as_uint64); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_double_s() +{ + int ret; + double input = 123456.789; + int expect_type = CFL_VARIANT_DOUBLE; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_double_s(list, "key????", 3, input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_double_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key!!!", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(fabs(var->data.as_double - input) < DBL_EPSILON)) { + TEST_MSG("variant value error.got=%lf expect=%lf", var->data.as_double, input); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_new_array_s() +{ + int ret; + int expect_type = CFL_VARIANT_ARRAY; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + ret = cfl_kvlist_insert_new_array_s(list, "key???", 3, 123); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_new_array_s failed"); + cfl_kvlist_destroy(list); + return; + } + + var = cfl_kvlist_fetch_s(list, "key!!!!!", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_array->slot_count == 123)) { + TEST_MSG("variant value error.got=%d expect=123", var->data.as_array->slot_count); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_empty_array_s() +{ + int ret; + int expect_type = CFL_VARIANT_ARRAY; + struct cfl_array *input = NULL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + input = cfl_array_create(123); + if (!TEST_CHECK(input != NULL)) { + TEST_MSG("cfl_array_create failed"); + cfl_kvlist_destroy(list); + return; + } + + ret = cfl_kvlist_insert_array_s(list, "key!!!", 3, input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_array_s failed"); + cfl_kvlist_destroy(list); + cfl_array_destroy(input); + return; + } + + var = cfl_kvlist_fetch_s(list, "key??????", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->data.as_array->slot_count == 123)) { + TEST_MSG("variant value error.got=%d expect=123", var->data.as_array->slot_count); + cfl_kvlist_destroy(list); + return; + } + + cfl_kvlist_destroy(list); +} + +static void insert_empty_kvlist_s() +{ + int ret; + int expect_type = CFL_VARIANT_KVLIST; + struct cfl_kvlist *input = NULL; + struct cfl_variant *var = NULL; + struct cfl_kvlist *list = NULL; + + list = cfl_kvlist_create(); + if (!TEST_CHECK(list != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + return; + } + + input = cfl_kvlist_create(); + if (!TEST_CHECK(input != NULL)) { + TEST_MSG("cfl_kvlist_create failed"); + cfl_kvlist_destroy(list); + return; + } + + ret = cfl_kvlist_insert_kvlist_s(list, "key????", 3, input); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("cfl_kvlist_insert_kvlist_s failed"); + cfl_kvlist_destroy(list); + cfl_kvlist_destroy(input); + return; + } + + var = cfl_kvlist_fetch_s(list, "key!", 3); + if (!TEST_CHECK(var != NULL)) { + TEST_MSG("cfl_kvlist_fetch returned NULL"); + cfl_kvlist_destroy(list); + return; + } + + if (!TEST_CHECK(var->type == expect_type)) { + TEST_MSG("variant type error. got=%d expect=%d", var->type, expect_type); + cfl_kvlist_destroy(list); + return; + } + cfl_kvlist_destroy(list); +} + +static void test_basics() +{ + int ret; + struct cfl_kvlist *list; + struct cfl_kvlist *list2; + struct cfl_array *array; + struct cfl_variant *variant; + + list = cfl_kvlist_create(); + TEST_CHECK(list != NULL); + + /* + * Inserts + */ + ret = cfl_kvlist_insert_string(list, "key1", "value1"); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_bytes(list, "key2", "value2", 6); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_reference(list, "key3", (void *) 0xdeadbeef); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_bool(list, "key4", 1); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_int64(list, "key5", 1234567890); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_uint64(list, "key6", 1234567890); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_double(list, "key7", 1234567890.1234567890); + TEST_CHECK(ret == 0); + + array = cfl_array_create(2); + TEST_CHECK(array != NULL); + + ret = cfl_kvlist_insert_array(list, "key8", array); + TEST_CHECK(ret == 0); + + ret = cfl_kvlist_insert_new_array(list, "key9", 0); + TEST_CHECK(ret == 0); + + list2 = cfl_kvlist_create(); + ret = cfl_kvlist_insert_kvlist(list, "key10", list2); + TEST_CHECK(ret == 0); + + variant = cfl_variant_create_from_string("value1"); + TEST_CHECK(variant != NULL); + + ret = cfl_kvlist_insert(list, "key11", variant); + TEST_CHECK(ret == 0); + + /* Count elements */ + ret = cfl_kvlist_count(list); + TEST_CHECK(ret == 11); + + /* Fetch */ + variant = cfl_kvlist_fetch(list, "key8"); + TEST_CHECK(variant != NULL); + TEST_CHECK(variant->type == CFL_VARIANT_ARRAY); + + /* Check if entry exists */ + ret = cfl_kvlist_contains(list, "key7"); + TEST_CHECK(ret == 1); + + ret = cfl_kvlist_contains(list, "key12"); + TEST_CHECK(ret == 0); + + /* Remove entry */ + ret = cfl_kvlist_remove(list, "key5"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_count(list); + TEST_CHECK(ret == 10); + + /* Remove all entries one by one (for memory sanitizer) */ + ret = cfl_kvlist_remove(list, "key1"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key2"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key3"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key4"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key6"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key7"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key8"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key9"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key10"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_remove(list, "key11"); + TEST_CHECK(ret == CFL_TRUE); + + ret = cfl_kvlist_count(list); + TEST_CHECK(ret == 0); + + /* failure scenarios */ + ret = cfl_kvlist_insert_string(list, NULL, "value1"); + TEST_CHECK(ret < 0); + + cfl_kvlist_destroy(list); +} + +TEST_LIST = { + {"create_destroy", create_destroy}, + {"count", count}, + {"fetch", fetch}, + {"insert_string", insert_string}, + {"insert_bytes", insert_bytes}, + {"insert_reference", insert_reference}, + {"insert_bool", insert_bool}, + {"insert_int64", insert_int64}, + {"insert_uint64", insert_uint64}, + {"insert_double", insert_double}, + {"insert_new_array", insert_new_array}, + {"insert_empty_array", insert_empty_array}, + {"insert_empty_kvlist", insert_empty_kvlist}, + + {"fetch_s", fetch_s}, + {"insert_string_s", insert_string_s}, + {"insert_bytes_s", insert_bytes_s}, + {"insert_reference_s", insert_reference_s}, + {"insert_bool_s", insert_bool_s}, + {"insert_int64_s", insert_int64_s}, + {"insert_uint64_s", insert_uint64_s}, + {"insert_double_s", insert_double_s}, + {"insert_new_array_s", insert_new_array_s}, + {"insert_empty_array_s", insert_empty_array_s}, + {"insert_empty_kvlist_s", insert_empty_kvlist_s}, + {"basics", test_basics}, + { 0 } +}; diff --git a/lib/cfl/tests/object.c b/lib/cfl/tests/object.c new file mode 100644 index 00000000000..4c372e3e1df --- /dev/null +++ b/lib/cfl/tests/object.c @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CFL + * === + * Copyright (C) 2022-2024 The CFL 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 +#include "cfl_tests_internal.h" + +static void test_basics() +{ + int ret; + struct cfl_object *object; + struct cfl_kvlist *list; + struct cfl_array *array; + + object = cfl_object_create(); + TEST_CHECK(object != NULL); + + /* + * Inserts + */ + list = cfl_kvlist_create(); + TEST_CHECK(list != NULL); + + ret = cfl_object_set(object, CFL_OBJECT_KVLIST, list); + TEST_CHECK(ret == 0); + + array = cfl_array_create(2); + TEST_CHECK(array != NULL); + + ret = cfl_kvlist_insert_array(list, "key1", array); + TEST_CHECK(ret == 0); + + /* + * Destroy + */ + cfl_object_destroy(object); +} + +TEST_LIST = { + { "test_basics", test_basics }, + { 0 } +}; diff --git a/lib/cfl/tests/variant.c b/lib/cfl/tests/variant.c index 2bb2853085f..0af28418751 100644 --- a/lib/cfl/tests/variant.c +++ b/lib/cfl/tests/variant.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "cfl_tests_internal.h" @@ -44,6 +45,7 @@ static int compare(FILE *fp, char *expect, int ignore_len) return -1; } } + if (ignore_len) { if (!TEST_CHECK(strstr(&buf[0], expect) != NULL)) { TEST_MSG("compare error. got=%s expect=%s", &buf[0], expect); @@ -105,6 +107,43 @@ static void test_variant_print_bool() } } +static void test_variant_print_null() +{ + int ret; + char expects[] = "null"; + + FILE *fp = NULL; + struct cfl_variant *val = NULL; + + fp = tmpfile(); + if (!TEST_CHECK(fp != NULL)) { + TEST_MSG("fp is NULL"); + } + + val = cfl_variant_create_from_null(); + if (!TEST_CHECK(val != NULL)) { + TEST_MSG("cfl_variant_create_from_null failed"); + fclose(fp); + } + + ret = cfl_variant_print(fp, val); + + /* Check whether EOF or not. Not checking for positive + * number here. */ + if (!TEST_CHECK(ret != EOF)) { + TEST_MSG("cfl_variant_print failed"); + cfl_variant_destroy(val); + fclose(fp); + } + + ret = compare(fp, expects, 0); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("compare failed"); + } + cfl_variant_destroy(val); + fclose(fp); +} + static void test_variant_print_int64() { int ret; @@ -254,7 +293,7 @@ static void test_variant_print_kvlist() struct cfl_variant *val = NULL; if (!TEST_CHECK(sizeof(key_inputs)/sizeof(char*) == sizeof(val_inputs)/sizeof(int64_t))) { - TEST_MSG("key val array size mismatch. key_len=%d val_len=%d", + TEST_MSG("key val array size mismatch. key_len=%d val_len=%d", sizeof(key_inputs)/sizeof(char*), sizeof(val_inputs)/sizeof(int64_t)); exit(1); @@ -384,6 +423,55 @@ static void test_variant_print_string() } } +struct str_and_len { + char *str; + size_t str_size; +}; + +static void test_variant_print_string_s() +{ + int ret; + int i; + struct str_and_len inputs[] = { + {.str = "hoge", .str_size = 4}, + {.str = "aaa", .str_size = 3}, + }; + + char *expects[] = {"\"hoge\"", "\"aaa\""}; + + FILE *fp = NULL; + struct cfl_variant *val = NULL; + + for (i=0; i 0)) { + TEST_MSG("%d:cfl_variant_print failed", i); + cfl_variant_destroy(val); + fclose(fp); + continue; + } + ret = compare(fp, expects[i], 0); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("%d:compare failed", i); + } + cfl_variant_destroy(val); + fclose(fp); + } +} + static void test_variant_print_bytes() { int ret; @@ -497,10 +585,12 @@ static void test_variant_print_unknown() TEST_LIST = { {"variant_print_bool", test_variant_print_bool}, + {"variant_print_null", test_variant_print_null}, {"variant_print_int64", test_variant_print_int64}, {"variant_print_uint64", test_variant_print_uint64}, {"variant_print_double", test_variant_print_double}, {"variant_print_string", test_variant_print_string}, + {"variant_print_string_s", test_variant_print_string_s}, {"variant_print_bytes", test_variant_print_bytes}, {"variant_print_array", test_variant_print_array}, {"variant_print_kvlist", test_variant_print_kvlist}, diff --git a/plugins/processor_attributes/attributes.c b/plugins/processor_attributes/attributes.c index f521c7423db..64576a5ed0d 100644 --- a/plugins/processor_attributes/attributes.c +++ b/plugins/processor_attributes/attributes.c @@ -317,66 +317,8 @@ static int cb_exit(struct flb_processor_instance *processor_instance) return FLB_PROCESSOR_SUCCESS; } -static int cfl_kvlist_contains(struct cfl_kvlist *kvlist, - char *name) -{ - struct cfl_list *iterator; - struct cfl_kvpair *pair; - - cfl_list_foreach(iterator, &kvlist->list) { - pair = cfl_list_entry(iterator, - struct cfl_kvpair, _head); - - if (strcasecmp(pair->key, name) == 0) { - return FLB_TRUE; - } - } - - return FLB_FALSE; -} - -static void cfl_kvpair_destroy(struct cfl_kvpair *pair) -{ - if (pair != NULL) { - if (!cfl_list_entry_is_orphan(&pair->_head)) { - cfl_list_del(&pair->_head); - } - - if (pair->key != NULL) { - cfl_sds_destroy(pair->key); - } - - if (pair->val != NULL) { - cfl_variant_destroy(pair->val); - } - - free(pair); - } -} - -static int cfl_kvlist_remove(struct cfl_kvlist *kvlist, - char *name) -{ - struct cfl_list *iterator_backup; - struct cfl_list *iterator; - struct cfl_kvpair *pair; - - cfl_list_foreach_safe(iterator, iterator_backup, &kvlist->list) { - pair = cfl_list_entry(iterator, - struct cfl_kvpair, _head); - - if (strcasecmp(pair->key, name) == 0) { - cfl_kvpair_destroy(pair); - } - } - - return FLB_TRUE; -} - /* local declarations */ - - static cfl_sds_t cfl_variant_convert_to_json(struct cfl_variant *value) { cfl_sds_t json_result; @@ -826,11 +768,11 @@ static void attribute_match_cb(const char *name, if (temporary_value != NULL) { span = (struct ctrace_span *) context; - if (span_contains_attribute(span, name) == FLB_TRUE) { - span_remove_attribute(span, name); + if (span_contains_attribute(span, (char *) name) == FLB_TRUE) { + span_remove_attribute(span, (char *) name); } - ctr_span_set_attribute_string(span, name, temporary_value); + ctr_span_set_attribute_string(span, (char *) name, temporary_value); cfl_sds_destroy(temporary_value); } diff --git a/src/flb_mp.c b/src/flb_mp.c index 77f53fefe4a..e4ce9dcb60d 100644 --- a/src/flb_mp.c +++ b/src/flb_mp.c @@ -677,7 +677,6 @@ void flb_mp_accessor_destroy(struct flb_mp_accessor *mpa) { struct mk_list *tmp; struct mk_list *head; - struct flb_record_accessor *ra; struct flb_mp_accessor_ra *mp_ra; if (!mpa) { @@ -697,3 +696,321 @@ void flb_mp_accessor_destroy(struct flb_mp_accessor *mpa) flb_free(mpa); } + + +static int mp_object_to_cfl(void **ptr, msgpack_object *o) +{ + int i; + int ret = -1; + struct cfl_array *array; + struct cfl_kvlist *kvlist; + void *var; + msgpack_object key; + msgpack_object val; + + switch(o->type) { + case MSGPACK_OBJECT_NIL: + var = cfl_variant_create_from_null(); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_BOOLEAN: + var = cfl_variant_create_from_bool(o->via.boolean); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_POSITIVE_INTEGER: + var = cfl_variant_create_from_uint64(o->via.u64); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + var = cfl_variant_create_from_int64(o->via.i64); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: + var = cfl_variant_create_from_double(o->via.f64); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_STR: + var = cfl_variant_create_from_string_s((char *) o->via.str.ptr, + o->via.str.size); + if (!var) { + return -1; + } + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_BIN: + var = cfl_variant_create_from_bytes((char *) o->via.str.ptr, + o->via.str.size); + if (!var) { + return -1; + } + + *ptr = var; + ret = CFL_OBJECT_VARIANT; + break; + case MSGPACK_OBJECT_EXT: + /* we do not pack extension type content */ + *ptr = NULL; + ret = CFL_OBJECT_NONE; + break; + case MSGPACK_OBJECT_ARRAY: + array = cfl_array_create(o->via.map.size); + if (!array) { + return -1; + } + ret = 0; + + for (i = 0; i < o->via.map.size; i++) { + ret = mp_object_to_cfl((void *) &var, &o->via.array.ptr[i]); + if (ret == CFL_OBJECT_KVLIST) { + ret = cfl_array_append_kvlist(array, var); + } + else if (ret == CFL_OBJECT_VARIANT) { + ret = cfl_array_append(array, var); + } + else if (ret == CFL_OBJECT_ARRAY) { + ret = cfl_array_append_array(array, var); + } + else { + ret = -1; + break; + } + } + + if (ret == -1) { + cfl_array_destroy(array); + return -1; + } + + *ptr = array; + ret = CFL_OBJECT_ARRAY; + break; + case MSGPACK_OBJECT_MAP: + kvlist = cfl_kvlist_create(); + if (!kvlist) { + return -1; + } + + ret = 0; + for (i = 0; i < o->via.map.size; i++) { + key = o->via.map.ptr[i].key; + val = o->via.map.ptr[i].val; + + /* force key type to be strin, otherwise just abort */ + if (key.type != MSGPACK_OBJECT_STR) { + ret = -1; + break; + } + + /* key variant is ready, now we need the value variant */ + ret = mp_object_to_cfl((void *) &var, &val); + if (ret == -1) { + break; + } + + if (ret == CFL_OBJECT_KVLIST) { + ret = cfl_kvlist_insert_kvlist_s(kvlist, + (char *) key.via.str.ptr, key.via.str.size, + var); + } + else if (ret == CFL_OBJECT_VARIANT) { + ret = cfl_kvlist_insert_s(kvlist, + (char *) key.via.str.ptr, key.via.str.size, + var); + } + else if (ret == CFL_OBJECT_ARRAY) { + ret = cfl_kvlist_insert_array_s(kvlist, + (char *) key.via.str.ptr, key.via.str.size, + var); + } + else { + ret = -1; + break; + } + } + + if (ret == -1) { + cfl_kvlist_destroy(kvlist); + return -1; + } + + *ptr = kvlist; + ret = CFL_OBJECT_KVLIST; + break; + default: + break; + } + + return ret; +} + + +/* Convert a msgpack object to a cfl_object */ +struct cfl_object *flb_mp_object_to_cfl(msgpack_object *o) +{ + int ret; + void *out = NULL; + struct cfl_object *obj; + + /* For now, only allow to convert to map (kvlist) or array */ + if (o->type != MSGPACK_OBJECT_MAP && o->type != MSGPACK_OBJECT_ARRAY) { + return NULL; + } + + obj = cfl_object_create(); + if (!obj) { + return NULL; + } + + ret = mp_object_to_cfl(&out, o); + if (ret < 0) { + cfl_object_destroy(obj); + return NULL; + } + + ret = cfl_object_set(obj, ret, out); + if (ret == -1) { + if (ret == CFL_OBJECT_KVLIST) { + cfl_kvlist_destroy(out); + } + else if (ret == CFL_OBJECT_ARRAY) { + cfl_array_destroy(out); + } + cfl_object_destroy(obj); + return NULL; + } + + return obj; +} + +static int mp_cfl_to_msgpack(struct cfl_variant *var, + msgpack_sbuffer *mp_sbuf, msgpack_packer *mp_pck) +{ + int i; + int ret; + struct cfl_list *head; + struct cfl_kvpair *kv; + struct cfl_kvlist *kvlist; + struct cfl_variant *variant; + struct flb_mp_map_header mh; + + switch (var->type) { + case CFL_VARIANT_BOOL: + if (var->data.as_bool) { + msgpack_pack_true(mp_pck); + } + else { + msgpack_pack_false(mp_pck); + } + break; + case CFL_VARIANT_INT: + msgpack_pack_int64(mp_pck, var->data.as_int64); + break; + case CFL_VARIANT_UINT: + msgpack_pack_uint64(mp_pck, var->data.as_uint64); + break; + case CFL_VARIANT_DOUBLE: + msgpack_pack_double(mp_pck, var->data.as_double); + break; + case CFL_VARIANT_NULL: + msgpack_pack_nil(mp_pck); + break; + case CFL_VARIANT_REFERENCE: + /* we don't save references */ + break; + case CFL_VARIANT_STRING: + msgpack_pack_str(mp_pck, cfl_sds_len(var->data.as_string)); + msgpack_pack_str_body(mp_pck, + var->data.as_string, cfl_sds_len(var->data.as_string)); + break; + case CFL_VARIANT_BYTES: + msgpack_pack_bin(mp_pck, cfl_sds_len(var->data.as_bytes)); + msgpack_pack_bin_body(mp_pck, + var->data.as_bytes, cfl_sds_len(var->data.as_bytes)); + break; + case CFL_VARIANT_ARRAY: + msgpack_pack_array(mp_pck, var->data.as_array->entry_count); + for (i = 0; i < var->data.as_array->entry_count; i++) { + variant = var->data.as_array->entries[i]; + ret = mp_cfl_to_msgpack(variant, mp_sbuf, mp_pck); + if (ret == -1) { + return -1; + } + } + break; + case CFL_VARIANT_KVLIST: + kvlist = var->data.as_kvlist; + flb_mp_map_header_init(&mh, mp_pck); + cfl_list_foreach(head, &kvlist->list) { + kv = cfl_list_entry(head, struct cfl_kvpair, _head); + + flb_mp_map_header_append(&mh); + + /* key */ + msgpack_pack_str(mp_pck, cfl_sds_len(kv->key)); + msgpack_pack_str_body(mp_pck, kv->key, cfl_sds_len(kv->key)); + + /* value */ + ret = mp_cfl_to_msgpack(kv->val, mp_sbuf, mp_pck); + if (ret == -1) { + return -1; + } + } + flb_mp_map_header_end(&mh); + break; + } + + return 0; +} + +/* Convert a CFL Object and serialize it content in a msgpack buffer */ +int flb_mp_cfl_to_msgpack(struct cfl_object *obj, char **out_buf, size_t *out_size) +{ + int ret; + msgpack_sbuffer mp_sbuf; + msgpack_packer mp_pck; + + if (!obj) { + return -1; + } + + /* unitialized CFL object ? */ + if (obj->type == CFL_OBJECT_NONE) { + return -1; + } + + /* initialize msgpack buffer */ + msgpack_sbuffer_init(&mp_sbuf); + msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write); + + ret = mp_cfl_to_msgpack(obj->variant, &mp_sbuf, &mp_pck); + if (ret == -1) { + return -1; + } + + *out_buf = mp_sbuf.data; + *out_size = mp_sbuf.size; + + return 0; +} diff --git a/tests/internal/mp.c b/tests/internal/mp.c index 5c1e17c224f..6651d8200e0 100644 --- a/tests/internal/mp.c +++ b/tests/internal/mp.c @@ -326,7 +326,7 @@ void remove_subkey_keys(char *list[], int list_size, int index_start) void test_keys_remove_subkey_keys() { char *list[] = {"$kubernetes[2]['annotations']['fluentbit.io/tag']", - "$kubernetes[2]['a']", + "$kubernetes[2]['a']", "$kubernetes"}; char *list2[] = {"$kubernetes[2]['annotations']['fluentbit.io/tag']", "$kubernetes", @@ -334,7 +334,7 @@ void test_keys_remove_subkey_keys() int size = sizeof(list)/sizeof(char*); int i; - + for (i=0; i> original JSON in msgpack:\n"); + flb_pack_print(buf, size); + + /* Unpack msgpack to get a msgpack object, and convert it to CFL */ + /* Unpack the content */ + msgpack_unpacked_init(&result); + msgpack_unpack_next(&result, buf, size, &off); + map = result.data; + + obj = flb_mp_object_to_cfl(&map); + TEST_CHECK(obj != NULL); + + /* Print the CFL object*/ + printf("\n>> CFL print:\n"); + cfl_object_print(stdout, obj); + + /* Convert back the CFL Object to a msgpack buffer. */ + ret = flb_mp_cfl_to_msgpack(obj, &out_buf, &out_size); + TEST_CHECK(ret == 0); + + /* Print msgpack */ + + printf("\n>> CFL to msgpack content:\n"); + flb_pack_print(out_buf, out_size); + + /* + * Convert buf (msgpack 1 buffer) to JSON, and compare the strings + * generated by out_buf (msgpack 2 buffer). They must match. + */ + buf1 = flb_msgpack_raw_to_json_sds(buf, size); + buf2 = flb_msgpack_raw_to_json_sds(out_buf, out_size); + + ret = strcmp(buf1, buf2); + printf("\n>> Compare JSON buf1 v/s JSON buf2 (ret=%i):\n", ret); + TEST_CHECK(ret == 0); + printf("[buf1]: %s\n", buf1); + printf("[buf2]: %s\n\n", buf2); + + flb_sds_destroy(buf1); + flb_sds_destroy(buf2); + + msgpack_unpacked_destroy(&result); + flb_free(buf); + flb_free(out_buf); + + cfl_object_destroy(obj); +} + TEST_LIST = { {"count" , test_count}, {"map_header" , test_map_header}, {"accessor_keys_remove" , test_accessor_keys_remove}, {"accessor_keys_remove_subkey_key" , test_keys_remove_subkey_key}, {"accessor_keys_remove_subkey_keys" , test_keys_remove_subkey_keys}, + {"object_to_cfl_to_msgpack" , test_object_to_cfl_to_msgpack}, { 0 } };