lib: make bt_value_map_foreach_entry_{const_}func() return a status code
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 11 Nov 2019 19:36:58 +0000 (14:36 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 15 Nov 2019 15:02:17 +0000 (10:02 -0500)
This patch makes the bt_value_map_foreach_entry_func() and
bt_value_map_foreach_entry_const_func() types return status codes
instead of `bt_bool`.

The available status codes are `OK` (continue the loop, like returning
`BT_TRUE` before this patch), `ERROR`, `MEMORY_ERROR`, and `INTERRUPT`
(break the loop, like returning `BT_FALSE` before this patch).

When the user function returns
`BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR`,
bt_value_map_foreach_entry() returns
`BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR` (set to the new global
status code `__BT_FUNC_STATUS_USER_ERROR`). This makes it possible to
distinguish between an internal library error and a user function error.

The purpose of this patch is to make it possible for a user function to
append an error cause to the current thread's error the same way other
user functions do: append the cause and return an error status.

For example, consider this scenario:

1. User calls bt_value_map_foreach_entry() with a user function and user
   data which contains a status member.

2. User function calls a library function which fails. The library
   function appends a cause to the current thread's error.

3. User function appends a cause to the current thread's error.

4. User function sets the user data's status member to the failing
   library function's status and returns `BT_FALSE` to interrupt the
   loop.

5. bt_value_map_foreach_entry() returns
   `BT_VALUE_MAP_FOREACH_ENTRY_STATUS_INTERRUPTED` (not an error
   status).

6. The caller of bt_value_map_foreach_entry() interprets
   `BT_VALUE_MAP_FOREACH_ENTRY_STATUS_INTERRUPTED` as an error because
   the user data's status member has an error value.

With this patch, it becomes:

1. User calls bt_value_map_foreach_entry() with a user function.

2. User function calls a library function which fails. The library
   function appends a cause to the current thread's error.

3. User function appends a cause to the current thread's error.

4. User function returns `BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR`
   or `BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_MEMORY_ERROR`, depending
   on the failing library function's status, which breaks the loop.

5. bt_value_map_foreach_entry() appends a cause to the current thread's
   error and returns `BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR` or
   `BT_VALUE_MAP_FOREACH_ENTRY_STATUS_MEMORY_ERROR`.

The latter seems more natural to me.

In Python, nothing wraps bt_value_map_foreach_entry() directly, so I
just converted bt_value_map_get_keys_cb() to return the appropriate
status instead of `BT_TRUE` or `BT_FALSE`. In other words,
bt2.utils._handle_func_status() does not need any change because it will
never receive `native_bt.__BT_FUNC_STATUS_USER_ERROR`.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I235d7957003b51630f4a2f72c1ccdef89d6173e8
Reviewed-on: https://review.lttng.org/c/babeltrace/+/2365
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
Tested-by: jenkins <jenkins@lttng.org>
12 files changed:
include/babeltrace2/babeltrace.h
include/babeltrace2/func-status.h
include/babeltrace2/value-const.h
include/babeltrace2/value.h
src/bindings/python/bt2/bt2/native_bt_value.i.h
src/cli/babeltrace2.c
src/common/common.h
src/lib/func-status.h
src/lib/value.c
src/plugins/common/param-validation/param-validation.c
src/plugins/text/details/write.c
tests/lib/test_bt_values.c

index 5e099a593b978e0e662ecf0e21a04284c0151422..e2ea83cfbc855315d1b7e36ed1e66fcc8ffcf8d2 100644 (file)
 #undef __BT_FUNC_STATUS_NOT_FOUND
 #undef __BT_FUNC_STATUS_OK
 #undef __BT_FUNC_STATUS_OVERFLOW_ERROR
+#undef __BT_FUNC_STATUS_USER_ERROR
 #undef __BT_IN_BABELTRACE_H
 #undef __BT_UPCAST
 #undef __BT_UPCAST_CONST
index 0f1829af8e7e17fcba6d1c1755ad0665371498dd..444b219ec2228433fbc754172ea5aa70f1f0f508 100644 (file)
 # define __BT_FUNC_STATUS_MEMORY_ERROR         -12
 #endif
 
+/* User function error */
+#ifndef __BT_FUNC_STATUS_USER_ERROR
+# define __BT_FUNC_STATUS_USER_ERROR           -2
+#endif
+
 /* General error */
 #ifndef __BT_FUNC_STATUS_ERROR
 # define __BT_FUNC_STATUS_ERROR                        -1
index 0001ddd8d1e33e0a39e2621fb51f19aae489df58..f42f60d80e98e7cfe03d88e2b68a0fbe72718a5c 100644 (file)
@@ -164,11 +164,22 @@ bt_bool bt_value_map_is_empty(const bt_value *map_obj)
 extern const bt_value *bt_value_map_borrow_entry_value_const(
                const bt_value *map_obj, const char *key);
 
-typedef bt_bool (* bt_value_map_foreach_entry_const_func)(const char *key,
-               const bt_value *object, void *data);
+typedef enum bt_value_map_foreach_entry_const_func_status {
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK                 = __BT_FUNC_STATUS_OK,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_ERROR              = __BT_FUNC_STATUS_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_MEMORY_ERROR       = __BT_FUNC_STATUS_MEMORY_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_INTERRUPT          = __BT_FUNC_STATUS_INTERRUPTED,
+} bt_value_map_foreach_entry_const_func_status;
+
+typedef bt_value_map_foreach_entry_const_func_status
+               (* bt_value_map_foreach_entry_const_func)(const char *key,
+                       const bt_value *object, void *data);
 
 typedef enum bt_value_map_foreach_entry_const_status {
        BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_OK              = __BT_FUNC_STATUS_OK,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_ERROR           = __BT_FUNC_STATUS_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_MEMORY_ERROR    = __BT_FUNC_STATUS_MEMORY_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_USER_ERROR      = __BT_FUNC_STATUS_USER_ERROR,
        BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_INTERRUPTED     = __BT_FUNC_STATUS_INTERRUPTED,
 } bt_value_map_foreach_entry_const_status;
 
index e01b48fe4ff6539f6fe5e7722ef029923481fd88..42e3cf96dd22496c406b7aaf2506ca9e67ed41e0 100644 (file)
@@ -126,11 +126,22 @@ extern bt_value *bt_value_map_create(void);
 extern bt_value *bt_value_map_borrow_entry_value(
                bt_value *map_obj, const char *key);
 
-typedef bt_bool (* bt_value_map_foreach_entry_func)(const char *key,
-               bt_value *object, void *data);
+typedef enum bt_value_map_foreach_entry_func_status {
+       BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_OK               = __BT_FUNC_STATUS_OK,
+       BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR            = __BT_FUNC_STATUS_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_MEMORY_ERROR     = __BT_FUNC_STATUS_MEMORY_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_INTERRUPT        = __BT_FUNC_STATUS_INTERRUPTED,
+} bt_value_map_foreach_entry_func_status;
+
+typedef bt_value_map_foreach_entry_func_status
+               (* bt_value_map_foreach_entry_func)(const char *key,
+                       bt_value *object, void *data);
 
 typedef enum bt_value_map_foreach_entry_status {
        BT_VALUE_MAP_FOREACH_ENTRY_STATUS_OK            = __BT_FUNC_STATUS_OK,
+       BT_VALUE_MAP_FOREACH_ENTRY_STATUS_ERROR         = __BT_FUNC_STATUS_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_STATUS_MEMORY_ERROR  = __BT_FUNC_STATUS_MEMORY_ERROR,
+       BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR    = __BT_FUNC_STATUS_USER_ERROR,
        BT_VALUE_MAP_FOREACH_ENTRY_STATUS_INTERRUPTED   = __BT_FUNC_STATUS_INTERRUPTED,
 } bt_value_map_foreach_entry_status;
 
index 94645414d568d460a1f75dd48a355f4cd09108d3..5f2b0e35cd483d5e770c7d5b4a69b7a07b330204 100644 (file)
@@ -26,17 +26,16 @@ struct bt_value_map_get_keys_data {
        struct bt_value *keys;
 };
 
-static int bt_value_map_get_keys_cb(const char *key, const struct bt_value *object, void *data)
+static bt_value_map_foreach_entry_const_func_status bt_value_map_get_keys_cb(
+               const char *key, const struct bt_value *object, void *data)
 {
-       bt_value_array_append_element_status status;
+       int status;
        struct bt_value_map_get_keys_data *priv_data = data;
 
        status = bt_value_array_append_string_element(priv_data->keys, key);
-       if (status != __BT_FUNC_STATUS_OK) {
-               return BT_FALSE;
-       }
-
-       return BT_TRUE;
+       BT_ASSERT(status == __BT_FUNC_STATUS_OK ||
+               status == __BT_FUNC_STATUS_MEMORY_ERROR);
+       return status;
 }
 
 static struct bt_value *bt_value_map_get_keys(const struct bt_value *map_obj)
index cc79340650732bc1a1e9a8c88e367e6cac8e3d8b..7dfeedbdb3091252d8c447d312e3e40abe0acb1b 100644 (file)
@@ -330,13 +330,14 @@ end:
 }
 
 static
-bt_bool collect_map_keys(const char *key, const bt_value *object, void *data)
+bt_value_map_foreach_entry_const_func_status collect_map_keys(
+               const char *key, const bt_value *object, void *data)
 {
        GPtrArray *map_keys = data;
 
        g_ptr_array_add(map_keys, (gpointer *) key);
 
-       return BT_TRUE;
+       return BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK;
 }
 
 static
index 96c09b6c520413180809732c85d5ae146467ea98..e931e2d10047aa188c439853bc634849ffcd4723 100644 (file)
@@ -671,6 +671,8 @@ const char *bt_common_func_status_string(int status)
                return "UNKNOWN_OBJECT";
        case __BT_FUNC_STATUS_MEMORY_ERROR:
                return "MEMORY_ERROR";
+       case __BT_FUNC_STATUS_USER_ERROR:
+               return "USER_ERROR";
        case __BT_FUNC_STATUS_ERROR:
                return "ERROR";
        case __BT_FUNC_STATUS_OK:
index 1b9c5cdb19a564a0baffd2c651358cfd6d96dbb1..b974f84fd7686b14f7d52523b4a75a9d5fb20021 100644 (file)
@@ -32,6 +32,7 @@
  */
 #define BT_FUNC_STATUS_AGAIN           __BT_FUNC_STATUS_AGAIN
 #define BT_FUNC_STATUS_END             __BT_FUNC_STATUS_END
+#define BT_FUNC_STATUS_USER_ERROR      __BT_FUNC_STATUS_USER_ERROR
 #define BT_FUNC_STATUS_ERROR           __BT_FUNC_STATUS_ERROR
 #define BT_FUNC_STATUS_INTERRUPTED     __BT_FUNC_STATUS_INTERRUPTED
 #define BT_FUNC_STATUS_UNKNOWN_OBJECT  __BT_FUNC_STATUS_UNKNOWN_OBJECT
index 15a97a828f9656501e01993c69f458867697cc2b..2b23e80ff35a2bcfb0cd03a392ba7aedefe66d39 100644 (file)
@@ -33,6 +33,7 @@
 #include "common/common.h"
 #include "compat/glib.h"
 #include "lib/assert-pre.h"
+#include "lib/assert-post.h"
 #include "lib/value.h"
 #include "common/assert.h"
 #include "func-status.h"
@@ -1271,7 +1272,7 @@ enum bt_value_map_foreach_entry_status bt_value_map_foreach_entry(
                struct bt_value *map_obj, bt_value_map_foreach_entry_func func,
                void *data)
 {
-       enum bt_value_map_foreach_entry_status ret = BT_FUNC_STATUS_OK;
+       int status = BT_FUNC_STATUS_OK;
        gpointer key, element_obj;
        GHashTableIter iter;
        struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
@@ -1286,16 +1287,40 @@ enum bt_value_map_foreach_entry_status bt_value_map_foreach_entry(
        while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
                const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
 
-               if (!func(key_str, element_obj, data)) {
-                       BT_LOGT("User interrupted the loop: key=\"%s\", "
-                               "value-addr=%p, data=%p",
-                               key_str, element_obj, data);
-                       ret = BT_FUNC_STATUS_INTERRUPTED;
+               status = func(key_str, element_obj, data);
+               BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(status);
+               if (status != BT_FUNC_STATUS_OK) {
+                       if (status < 0) {
+                               BT_LIB_LOGE_APPEND_CAUSE(
+                                       "User function failed while iterating "
+                                       "map value entries: "
+                                       "status=%s, key=\"%s\", "
+                                       "value-addr=%p, data=%p",
+                                       bt_common_func_status_string(status),
+                                       key_str, element_obj, data);
+
+                               if (status == BT_FUNC_STATUS_ERROR) {
+                                       /*
+                                        * User function error becomes a
+                                        * user error from this
+                                        * function's caller's
+                                        * perspective.
+                                        */
+                                       status = BT_FUNC_STATUS_USER_ERROR;
+                               }
+                       } else {
+                               BT_ASSERT(status == BT_FUNC_STATUS_INTERRUPTED);
+                               BT_LOGT("User interrupted the loop: status=%s, "
+                                       "key=\"%s\", value-addr=%p, data=%p",
+                                       bt_common_func_status_string(status),
+                                       key_str, element_obj, data);
+                       }
+
                        break;
                }
        }
 
-       return ret;
+       return status;
 }
 
 enum bt_value_map_foreach_entry_const_status bt_value_map_foreach_entry_const(
@@ -1310,21 +1335,20 @@ enum bt_value_map_foreach_entry_const_status bt_value_map_foreach_entry_const(
 
 struct extend_map_element_data {
        struct bt_value *base_obj;
-       int status;
 };
 
 static
-bt_bool extend_map_element(const char *key,
-               const struct bt_value *extension_obj_elem, void *data)
+bt_value_map_foreach_entry_const_func_status extend_map_element(
+               const char *key, const struct bt_value *extension_obj_elem,
+               void *data)
 {
-       bt_bool ret = BT_TRUE;
+       int status;
        struct extend_map_element_data *extend_data = data;
        struct bt_value *extension_obj_elem_copy = NULL;
 
        /* Copy object which is to replace the current one */
-       extend_data->status = bt_value_copy(extension_obj_elem,
-               &extension_obj_elem_copy);
-       if (extend_data->status) {
+       status = bt_value_copy(extension_obj_elem, &extension_obj_elem_copy);
+       if (status) {
                BT_LIB_LOGE_APPEND_CAUSE("Cannot copy map element: %!+v",
                        extension_obj_elem);
                goto error;
@@ -1333,36 +1357,35 @@ bt_bool extend_map_element(const char *key,
        BT_ASSERT(extension_obj_elem_copy);
 
        /* Replace in base map value. */
-       extend_data->status = bt_value_map_insert_entry(
-               extend_data->base_obj, key,
+       status = bt_value_map_insert_entry(extend_data->base_obj, key,
                (void *) extension_obj_elem_copy);
-       if (extend_data->status) {
+       if (status) {
                BT_LIB_LOGE_APPEND_CAUSE(
                        "Cannot replace value in base map value: key=\"%s\", "
                        "%![base-map-value-]+v, %![element-value-]+v",
-                       key, extend_data->base_obj,
-                       extension_obj_elem_copy);
+                       key, extend_data->base_obj, extension_obj_elem_copy);
                goto error;
        }
 
        goto end;
 
 error:
-       BT_ASSERT(extend_data->status != BT_FUNC_STATUS_OK);
-       ret = BT_FALSE;
+       BT_ASSERT(status < 0);
 
 end:
        BT_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
-       return ret;
+       BT_ASSERT(status == BT_FUNC_STATUS_OK ||
+               status == BT_FUNC_STATUS_MEMORY_ERROR);
+       return status;
 }
 
 enum bt_value_map_extend_status bt_value_map_extend(
                struct bt_value *base_map_obj,
                const struct bt_value *extension_obj)
 {
+       int status = BT_FUNC_STATUS_OK;
        struct extend_map_element_data extend_data = {
                .base_obj = NULL,
-               .status = BT_FUNC_STATUS_OK,
        };
 
        BT_ASSERT_PRE_NO_ERROR();
@@ -1379,15 +1402,16 @@ enum bt_value_map_extend_status bt_value_map_extend(
         * in the base map object.
         */
        extend_data.base_obj = base_map_obj;
-
-       if (bt_value_map_foreach_entry_const(extension_obj, extend_map_element,
-                       &extend_data)) {
+       status = bt_value_map_foreach_entry_const(extension_obj,
+               extend_map_element, &extend_data);
+       if (status != BT_FUNC_STATUS_OK) {
+               BT_ASSERT(status == BT_FUNC_STATUS_MEMORY_ERROR);
                BT_LIB_LOGE_APPEND_CAUSE(
                        "Cannot iterate on the extension object's elements: "
                        "%![extension-value-]+v", extension_obj);
        }
 
-       return extend_data.status;
+       return status;
 }
 
 enum bt_value_copy_status bt_value_copy(const struct bt_value *object,
index 4b6eed739f1d2fa170fcd5b5c359daa7bf0c7120..216f274241dd9c3f62e56dbb84fa73499c190737 100644 (file)
@@ -156,8 +156,8 @@ enum bt_param_validation_status validate_value(
                struct bt_param_validation_context *ctx);
 
 static
-bt_bool validate_map_value_entry(const char *key,
-               const bt_value *value, void *v_data)
+bt_value_map_foreach_entry_const_func_status validate_map_value_entry(
+               const char *key, const bt_value *value, void *v_data)
 {
        struct validate_map_value_data *data = v_data;
        const struct bt_param_validation_map_value_entry_descr *entry = NULL;
@@ -192,7 +192,9 @@ bt_bool validate_map_value_entry(const char *key,
        }
 
        /* Continue iterating if everything is good so far. */
-       return data->status == BT_PARAM_VALIDATION_STATUS_OK;
+       return data->status == BT_PARAM_VALIDATION_STATUS_OK ?
+               BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK :
+               BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_INTERRUPT;
 }
 
 static
index f5562689035e5e975449e77d579b27e7d4261d1a..b98efb78c4d55e0afb42816ff719feecfccd7553 100644 (file)
@@ -370,14 +370,14 @@ gint compare_strings(const char **a, const char **b)
 }
 
 static
-bt_bool map_value_foreach_add_key_to_array(const char *key,
-               const bt_value *object, void *data)
+bt_value_map_foreach_entry_const_func_status map_value_foreach_add_key_to_array(
+               const char *key, const bt_value *object, void *data)
 {
        GPtrArray *keys = data;
 
        BT_ASSERT_DBG(keys);
        g_ptr_array_add(keys, (void *) key);
-       return BT_TRUE;
+       return BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK;
 }
 
 static
index c0a9f5a7c6c268c0f127100c5db43b4bbb528df6..776e5f56e97de8b910c9f376818979c395953f95 100644 (file)
@@ -25,7 +25,7 @@
 #include <string.h>
 #include "tap/tap.h"
 
-#define NR_TESTS 188
+#define NR_TESTS 190
 
 static
 void test_null(void)
@@ -368,18 +368,23 @@ void test_array(void)
 }
 
 static
-bt_bool test_map_foreach_cb_count(const char *key, bt_value *object,
+bt_value_map_foreach_entry_func_status test_map_foreach_cb_count(
+               const char *key, bt_value *object,
        void *data)
 {
        int *count = data;
 
        if (*count == 3) {
-               return BT_FALSE;
+               return BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_INTERRUPT;
+       } else if (*count == 4) {
+               return BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR;
+       } else if (*count == 5) {
+               return BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_MEMORY_ERROR;
        }
 
        (*count)++;
 
-       return BT_TRUE;
+       return BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_OK;
 }
 
 struct map_foreach_checklist {
@@ -399,8 +404,8 @@ struct map_foreach_checklist {
 };
 
 static
-bt_bool test_map_foreach_cb_check(const char *key, bt_value *object,
-       void *data)
+bt_value_map_foreach_entry_func_status test_map_foreach_cb_check(
+               const char *key, bt_value *object, void *data)
 {
        struct map_foreach_checklist *checklist = data;
 
@@ -572,7 +577,7 @@ bt_bool test_map_foreach_cb_check(const char *key, bt_value *object,
                        key);
        }
 
-       return BT_TRUE;
+       return BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_OK;
 }
 
 static
@@ -711,7 +716,21 @@ void test_map(void)
        ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_count,
                &count);
        ok(ret == BT_VALUE_MAP_FOREACH_ENTRY_STATUS_INTERRUPTED && count == 3,
-               "bt_value_map_foreach_entry() breaks the loop when the user function returns BT_FALSE");
+               "bt_value_map_foreach_entry() breaks the loop when the user function returns BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_INTERRUPT");
+
+       count = 4;
+       ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_count,
+               &count);
+       ok(ret == BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR,
+               "bt_value_map_foreach_entry() fails when the user function returns BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_ERROR");
+       bt_current_thread_clear_error();
+
+       count = 5;
+       ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_count,
+               &count);
+       ok(ret == BT_VALUE_MAP_FOREACH_ENTRY_STATUS_MEMORY_ERROR,
+               "bt_value_map_foreach_entry() fails when the user function returns BT_VALUE_MAP_FOREACH_ENTRY_FUNC_STATUS_MEMORY_ERROR");
+       bt_current_thread_clear_error();
 
        memset(&checklist, 0, sizeof(checklist));
        ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_check,
This page took 0.03385 seconds and 4 git commands to generate.