From bccf2d9c510c94bb0b5d2ae26fdb40a29a03c25a Mon Sep 17 00:00:00 2001 From: Michal Skorupinski Date: Fri, 16 Oct 2015 12:06:35 +0200 Subject: [PATCH] [SAMPLE APP][DATA-CONTROL-PROVIDER] Map provider - function descriptions Change-Id: I068e88ee2bb619851f3c5e0ee4e2c5f4f8fde4eb Signed-off-by: Michal Skorupinski --- .../html/mobile_n/data_control_consumer_sd_mn.htm | 4 +- .../html/mobile_n/data_control_provider_sd_mn.htm | 127 +++++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/org.tizen.sampledescriptions/html/mobile_n/data_control_consumer_sd_mn.htm b/org.tizen.sampledescriptions/html/mobile_n/data_control_consumer_sd_mn.htm index 64e02f0..7dbc797 100644 --- a/org.tizen.sampledescriptions/html/mobile_n/data_control_consumer_sd_mn.htm +++ b/org.tizen.sampledescriptions/html/mobile_n/data_control_consumer_sd_mn.htm @@ -417,11 +417,11 @@ There are four request functions:
  • data_control_map_remove(s_info.provider, key, value, &req_id); - this function is used to remove the given value held by the given key. If a key is empty after this operation, it should be removed as well. If there is no value equal to value or key equal to key, an error message should be provided. The key string is taken from the key_entry widget and the value from new_value_entry widget.
  • -

    Note that there is one extra button in the map view. The Keys button sends a special get request using a "#GET_ALL_KEYS" key. In this case value received from the provider will contain all keys stored by the provider app.

    +

    Note that there is one extra button in the map view. The Keys button sends a special get request using a "#GET_ALL_KEYS" key. In this case value received from the provider will contain all keys stored by the provider app.

    The above functions are invoked by click events of the get_data_button, set_data_button, remove_data_button and add_data_button buttons placed in the map view. The above functions are used to send requests to the provider app. The provider app should send a response. Based on the response type, one of the below callbacks is invoked.

    -
    Callback definitions:
    +
    Callback definitions:
     static void __map_get_response_cb(int request_id, data_control_h provider, char **ret_value_list, int ret_value_count, bool provider_ret, const char *error, void *user_data)
    diff --git a/org.tizen.sampledescriptions/html/mobile_n/data_control_provider_sd_mn.htm b/org.tizen.sampledescriptions/html/mobile_n/data_control_provider_sd_mn.htm
    index c9e70f7..249372e 100644
    --- a/org.tizen.sampledescriptions/html/mobile_n/data_control_provider_sd_mn.htm
    +++ b/org.tizen.sampledescriptions/html/mobile_n/data_control_provider_sd_mn.htm
    @@ -147,6 +147,133 @@ static void __remove_value_request_cb(int request_id, data_control_h provider, c
        /* ... */
     }
     
    + + +

    Eina_Hash functions

    +

    The map provider part of the application uses the Eina_Hash structure to store data. Note that every key in the hash can hold multiple values, so a simple key/value pair is not enough. Every key has an Eina_List assigned as its data. There are five functions in total that allow to interact with the hash map. All of them are invoked by a proper callback.

    + +

    The function used to add new data to the hash map. As mentioned before, if a key doesn't exist, a new key should be created:

    +
    +static int __data_map_add(int request_id, const char *key, const char *value)
    +{
    +   /* ... */
    +
    +   entry = (Eina_List *)eina_hash_find(s_info.data_map, key); /* Find an Eina_List assigned to the passed key. */
    +
    +   if (entry) {
    +      /* If an Eina_List is found, a new value is added to it, and the Eina_Hash key is modified accordingly.
    +      Note that the data added to the Eina_List is sorted so the eina_hash_list_* group of functions cannot be used. */
    +      entry = eina_list_sorted_insert(entry, __data_map_item_value_comparator_cb, strdup(value));
    +      /* ... */
    +   } else {
    +      /* If an Eina_List is not found, a new list is created. A new key is created with the new list used at its value. */
    +      entry = eina_list_append(NULL, strdup(value));
    +      /* ... */
    +   }
    +
    +   return eina_list_count(entry);
    +}
    +
    + +

    The function below is a special 'get' function. When 'get' request with a special key is sent from the consumer app, an array of all keys in the hash map are sent back instead of a value array:

    +
    +static char **__get_all_keys(int *values_count)
    +{
    +   *values_count = eina_hash_population(s_info.data_map);
    +   char **ret = calloc(*values_count, sizeof(char *));
    +   eina_hash_foreach(s_info.data_map, __get_all_keys_cb, (char **)ret);
    +   return ret;
    +}
    +
    + +

    The function used to get an array of values held by the given key:

    +
    +static char **__data_map_get(int request_id, const char *key, int *values_count)
    +{
    +   /* If the requested key is equal to '#GET_ALL_KEYS', return an array of all available keys. */
    +   if(!__str_cmp_precise(key, GET_ALL_KEYS))
    +      return __get_all_keys(values_count);
    +
    +   /* Find an Eina_List assigned to the given key */
    +   entry = (Eina_List *)eina_hash_find(s_info.data_map, key);
    +   if (!entry) {
    +      *values_count = 0;
    +
    +      /* If no Eina_List is found, an error message is sent.
    +         Note that this call will automatically set the provider_ret in the consumer's app callback to false. */
    +      data_control_provider_send_error(request_id, NO_KEY_FOUND);
    +      return NULL;
    +   }
    +
    +   /* Prepare an array of strings with values assigned to the given key. */
    +   *values_count = eina_list_count(entry);
    +   char **ret = calloc(*values_count, sizeof(char *));
    +
    +   EINA_LIST_FOREACH(entry, l, item)
    +   {
    +      ret[index] = item;
    +      index++;
    +   }
    +   return ret;
    +}
    +
    + +

    The function used to update the value assigned to the given key:

    +
    +static Eina_Bool __data_map_set(int request_id, const char *key, const char *old, const char *new)
    +{
    +   /* ... */
    +
    +   /* Search for the value to modify. */
    +   Eina_List *old_data_list = __search_value(entry, key, old);
    +   /* ... */
    +
    +   /* Remove the found value. This is used to simplify the sorted insertion to the Eina_List. */
    +   entry = eina_list_remove_list(entry, old_data_list);
    +   if (!entry)
    +      dlog_print(DLOG_INFO, LOG_TAG, "entry == NULL");
    +
    +   /* Insert the new value. */
    +   entry = eina_list_sorted_insert(entry, __data_map_item_value_comparator_cb, strdup(new));
    +
    +   /* Modify the key. */
    +   if (!eina_hash_modify(s_info.data_map, key, entry)) {
    +      dlog_print(DLOG_ERROR, LOG_TAG, "Failed to modify a key value pair");
    +      return EINA_FALSE;
    +   }
    +
    +   return EINA_TRUE;
    +}
    +
    + +

    The function used to remove the value assigned to the given key:

    +
    +static void __data_map_remove(int request_id, const char* key, const char *value)
    +{
    +   /* ... */
    +
    +   if(eina_list_count(entry) > 1) {
    +      entry = eina_list_remove_list(entry, old_data_list);
    +      if (!eina_hash_modify(s_info.data_map, key, entry)) {
    +         dlog_print(DLOG_ERROR, LOG_TAG, "Failed to modify a key value pair");
    +         return;
    +      }
    +
    +   } else {
    +      /* If akey is left empty after the value removal the key should be removed as well. */
    +      if (!eina_hash_del_by_key(s_info.data_map, key)) {
    +         dlog_print(DLOG_ERROR, LOG_TAG, "Failed to remove a key: %s", key);
    +         return;
    +      } else {
    +         dlog_print(DLOG_INFO, LOG_TAG, "Key [%s] removed", key);
    +         text = eina_stringshare_printf(KEY_REMOVED, key);
    +         data_control_provider_send_error(request_id, text);
    +         eina_stringshare_del(text);
    +      }
    +   }
    +}
    +
    + -- 2.7.4