From cf7450713c950678fd6f0dd1406888833f8271ec Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Sun, 25 Feb 2024 16:00:46 -0800 Subject: [PATCH 1/3] lib: cfl: upgrade to v0.4.0 Signed-off-by: Eduardo Silva --- lib/cfl/CMakeLists.txt | 2 +- lib/cfl/include/cfl/cfl.h | 1 + lib/cfl/include/cfl/cfl_array.h | 4 +- lib/cfl/include/cfl/cfl_compat.h | 2 + lib/cfl/include/cfl/cfl_kvlist.h | 51 ++ lib/cfl/include/cfl/cfl_object.h | 41 + lib/cfl/include/cfl/cfl_variant.h | 24 +- lib/cfl/src/CMakeLists.txt | 1 + lib/cfl/src/cfl_array.c | 23 +- lib/cfl/src/cfl_kvlist.c | 238 ++++-- lib/cfl/src/cfl_object.c | 106 +++ lib/cfl/src/cfl_variant.c | 25 +- lib/cfl/tests/CMakeLists.txt | 2 + lib/cfl/tests/kvlist.c | 1197 +++++++++++++++++++++++++++++ lib/cfl/tests/object.c | 58 ++ lib/cfl/tests/variant.c | 92 ++- 16 files changed, 1802 insertions(+), 65 deletions(-) create mode 100644 lib/cfl/include/cfl/cfl_object.h create mode 100644 lib/cfl/src/cfl_object.c create mode 100644 lib/cfl/tests/kvlist.c create mode 100644 lib/cfl/tests/object.c 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}, From 17ab18b6131b1ef5056a20b32f8990fdc0f0d4ac Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Sun, 25 Feb 2024 16:05:11 -0800 Subject: [PATCH 2/3] processor_attributes: remove code for new CFL calls Signed-off-by: Eduardo Silva --- plugins/processor_attributes/attributes.c | 64 ++--------------------- 1 file changed, 3 insertions(+), 61 deletions(-) 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); } From 1e84c0bb81995ad4a2bbb35dbc289bbf68748f25 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Sun, 25 Feb 2024 16:06:37 -0800 Subject: [PATCH 3/3] mp: new API to convert between msgpack and CFL object Looking forward to improve how do we manipulate msgpack buffers, we aim to operate on top of the new CFL object structure and reduce the number of serializations required, plus decrease the complexity of the logic in certain plugins that requires several modifcation operations. This patch implements 2 new API calls and test case for: - Convert from MessagePack Object (unpacked) to CFL object - Convert from CFL object to MessagePack buffer (serialized) In the next patches we will extend Log processors by using this new interface. Signed-off-by: Eduardo Silva --- include/fluent-bit/flb_mp.h | 3 + src/flb_mp.c | 319 +++++++++++++++++++++++++++++++++++- tests/internal/mp.c | 99 ++++++++++- 3 files changed, 418 insertions(+), 3 deletions(-) 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/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 } };