HashMap API

Click here for the API Reference documentation.


Creating a HashMap
Adding key-value pairs
Iterating over a map
Tracing a map

This API provides a straightforward HashMap implementation.

Creating a HashMap

Use le_hashmap_Create() to create a hashmap. It's the responsibility of the caller to maintain type integrity using this function's parameters. It's important to supply hash and equality functions that operate on the type of key that you intend to store. It's unwise to mix types in a single table because implementation of the table has no way to detect this behaviour.

Choose the initial size should carefully as the index size remains fixed. The best choice for the initial size is a prime number slightly larger than the maximum expected capacity. If a too small size is chosen, there will be an increase in collisions that degrade performance over time.

All hashmaps have names for diagnostic purposes.

Adding key-value pairs

Key-value pairs are added using le_hashmap_Put(). For example:

 static void StoreStuff(const char* keyStr, const char* valueStr)
 {
     myTable = le_hashmap_Create(
                         "My Table",
                         31,
                         le_hashmap_HashString,
                         le_hashmap_EqualsString
                       );

     le_hashmap_Put(myTable, keyStr, valueStr);
     ....
 }

The table does not take control of the keys or values. The map only stores the pointers to these values, not the values themselves. It's the responsibility of the caller to manage the actual data storage.

Tip

The code sample shows some pre-defined functions for certain key types. The key types supported are uint32_t and strings. The strings must be NULL terminated.

Tables can also have their own hash and equality functions, but ensure the functions work on the type of key you're storing. The hash function should provide a good distribution of values. It is not required that they be unique.

Iterating over a map

This API allows the user of the map to iterate over the entire map, acting on each key-value pair. You supply a callback function conforming to the prototype:

 bool (*callback)(void* key, void* value, void* context)

This can then be used to process every value in the map. The return value from the callback function determines if iteration should continue or stop. If the function returns false then iteration will cease. For example:

 bool ProcessTableData
 (
     void* keyPtr,     // Pointer to the map entry's key
     void* valuePtr,   // Pointer to the map entry's value
     void* contextPtr  // Pointer to an abritrary context for the callback function
 )
 {
     int keyCheck = *((int*)context);
     int currentKey = *((int*)key);

     if (keyCheck == currentKey) return false;

     // Do some stuff, maybe print out data or do a calculation
     return true;
 }

 {
     // ... somewhere else in the code ...
     int lastKey = 10;
     le_hashmap_ForEach (myTable, processTableData, &lastKey);
 }

This code sample shows the callback function must also be aware of the types stored in the table.

Alternatively, the calling function can control the iteration by first calling le_hashmap_GetIterator(). This returns an iterator that is ready to return each key/value pair in the map in the order in which they are stored. The iterator is controlled by calling le_hashmap_NextNode(), and must be called before accessing any elements. You can then retrieve pointers to the key and value by using le_hashmap_GetKey() and le_hashmap_GetValue().

Note:
There is only one iterator per hashtable. Calling le_hashmap_GetIterator() will simply re-initialize the current iterator

For example (assuming a table of string/string):

 void ProcessTable(le_hashmap_Ref_t myTable)
 {
     char* nextKey;
     char* nextVal;

     le_hashmap_It_Ref_t myIter = le_hashmap_GetIterator(myTable);

     while (LE_OK == le_hashmap_NextNode(myIter))
     {
         // Do something with the strings
         nextKey = le_hashmap_GetKey(myIter);
         nextVal = le_hashmap_GetValue(myIter);
     }
 }

Don't modify the contents of the table while iterating. This will lead to the iterator returning an error. If you need to control access to the hashmap, then a mutex can be used.

Tracing a map

Hashmaps can be traced using the logging system.

If le_hashmap_MakeTraceable() is called for a specified hashmap object, the name of that hashmap (the name passed into le_hashmap_Create() ) becomes a trace keyword to enable and disable tracing of that particular hashmap.

If le_hashmap_EnableTrace() is called for a hashmap object, tracing is immediately activated for that hashmap.

See Log Controls for more information on how to enable and disable tracing using configuration and/or the log control tool.


Copyright (C) Sierra Wireless, Inc. 2013. All rights reserved. Use of this work is subject to license.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines