Mobile native Wearable native

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

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:

Table: Bundle value 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);
Go to top