Bundle: Using the String-based Dictionary ADT
This tutorial demonstrates how you can access and use bundles, which are key-value dictionaries.
Warm-up
Become familiar with the Bundle API basics by learning about:
-
Initializing a Bundle
Initialize bundle for use.
- Content management
-
Adding Content to a Bundle
Add content to a valid bundle.
-
Managing and Using the Bundle Content
Add, delete, and get values of the bundle content.
-
Iterating a Bundle
Iterate a bundle.
-
Adding Content to a Bundle
-
Encoding and Decoding a Bundle
Encode and decode a bundle.
-
Cleaning up a Bundle
Release the bundle after use.
Initializing a Bundle
To use the functions and data types of the Bundle API (in mobile and wearable applications), include the <bundle.h> header file in your application:
#include <bundle.h>
Before you can perform any operations on a bundle, create the bundle instance. Each bundle is independent from other bundles and stores its own set of records.
bundle* bund = NULL; bund = bundle_create();
Adding Content to a Bundle
Fill a valid bundle instance with content. The content is in the form of key-value pairs. The key is always a string. The value can be of the following types:
Value constant | Value type |
---|---|
BUNDLE_TYPE_STR | String (default) |
BUNDLE_TYPE_STR_ARRAY | String array |
BUNDLE_TYPE_BYTE | Byte |
Each value type is associated with a function that can operate on it:
- bundle_add_str_array(bundle *b, const char *key, const char **str_array, const int len)
- bundle_add_str(bundle *b, const char *key, const char *str)
- bundle_add_byte(bundle *b, const char *key, const void *byte, const size_t size)
When operating on bytes, control the length of the given chain:
const char* array [3] = {"Var1", "Var2", "Var3"}; int array_len = 3; bundle_add_str(bund, "Str", "String content"); bundle_add_str_array(bund, "Array", array, array_len); bundle_add_byte(bund, "Byte", "Byte content", 12);
Managing and Using the Bundle Content
You can perform the following operations on a bundle:
- Adding content: bundle_add_str(), bundle_add_str_array(), and bundle_add_byte()
- Deleting content: bundle_del()
- Getting values: bundle_get_str(), bundle_get_str_array(), bundle_get_byte(), bundle_get_count(), and bundle_get_type()
void test_bundle_add_del_get(void) { bundle *b = NULL; int count = 0; char *value; b = bundle_create(); bundle_add_str(b, "key1", "val1"); bundle_add_str(b, "key2", "val2"); bundle_get_str(b, "key2", &value); dlog_print(DLOG_DEBUG, LOG_TAG, "the value of key2 : %s", value); count = bundle_get_count(b); dlog_print(DLOG_DEBUG, LOG_TAG, "the number of bundle items : %d", count); bundle_del(b, "key2"); count = bundle_get_count(b); dlog_print(DLOG_DEBUG, LOG_TAG, "the number of bundle items : %d", count); bundle_free(b); }
Iterating a Bundle
The bundle_foreach() function requires a callback function to operate. The callback function must first determine the key-value pairs and then perform the specified operations.
After the bundle_foreach() function, the _bundle_iterator_t() function is invoked for each record in the bundle:
void iterate_bundle_foreach(const char *key, const int type, bundle_keyval_t *kv, void *user_data) { dlog_print(DLOG_DEBUG, LOG_TAG, "key : %s, type : %d ", key, type); void *ptr = NULL; char *buff = NULL; unsigned int size = 0; if (type == BUNDLE_TYPE_STR) { bundle_keyval_get_basic_val((bundle_keyval_t *) kv, &ptr, &size); buff = malloc(sizeof(char)* size + 1); snprintf(buff, size + 1, "%s", ((char*) ptr)); dlog_print(DLOG_DEBUG, LOG_TAG, "Found STR -KEY: %s, VAL: %s, SIZE: %d", key, buff, size); free(buff); } else if (type == BUNDLE_TYPE_BYTE) { bundle_keyval_get_basic_val((bundle_keyval_t *) kv, &ptr, &size); buff = malloc(sizeof(char)* size + 1); snprintf(buff, size + 1, "%s", ((char*) ptr)); dlog_print(DLOG_DEBUG, LOG_TAG, "Found STR -KEY: %s, VAL: %s, SIZE: %d", key, buff, size); free(buff); } else if (type == BUNDLE_TYPE_STR_ARRAY) { void ** array; unsigned int len = 0; size_t *element_size = NULL; dlog_print(DLOG_DEBUG, LOG_TAG, "Found STR_ARRAY -KEY: %s", key); bundle_keyval_get_array_val((bundle_keyval_t *) kv, &array, &len, &element_size); dlog_print(DLOG_DEBUG, LOG_TAG, "-Array len: %d", len); for (int i = 0; i < len; i++) { dlog_print(DLOG_DEBUG, LOG_TAG, "-%s", (char*)array[i]); } } } void test_bundle_foreach(void) { const char *s_arr[] = {"abc", "bcd", "cde"}; bundle *b; b = bundle_create(); bundle_add_str(b, "k1", "v1"); bundle_add_byte(b, "k2", "v2", 3); bundle_add_str_array(b, "k3", s_arr, 3); bundle_foreach(b, iterate_bundle_foreach, NULL); bundle_free(b); }
Encoding and Decoding a Bundle
To store or send a bundle over a serial connection, encode the bundle to bundle_raw (a typedef of unsigned char). To encode the bundle, call the bundle_encode() function.
To store the bundle, write bundle_raw to a file, for example, and then open it with the bundle_decode() function. The encoded data and created bundle must be released when no longer needed.
void test_bundle_encode_decode(void) { bundle *b1, *b2; bundle_raw *r; int size_r; char *value; b1 = bundle_create(); bundle_add_str(b1, "k1", "v1"); bundle_add_str(b1, "k2", "v2"); bundle_encode(b1, &r, &size_r); b2 = bundle_decode(r, size_r); bundle_get_str(b1, "k1", &value); dlog_print(DLOG_DEBUG, LOG_TAG, "value of k1 after decode : %s", value); bundle_free(b1); bundle_free(b2); }
Cleaning up a Bundle
When no longer needed, release the bundle by calling the bundle_free() function.
bundle_free(bund);