Skip to content

Map

Description

Typesafe multimap definition.

This behaves like the other generic containers in the project: each use of Map(K, V) creates a distinct anonymous type, so reusable aliases should be defined with typedef. Multiple values may be stored for the same key.

Fields

Name Description
length Number of stored key/value pairs, including duplicate keys.
capacity Total number of probe slots currently allocated.
tombstones Number of deleted slots currently retained for probing.
key_copy_init Optional deep-copy callback for keys.
key_copy_deinit Optional deinit callback for keys held by the map.
value_copy_init Optional deep-copy callback for values.
value_copy_deinit Optional deinit callback for values held by the map.
key_compare Required comparator for keys. Equality is compare == 0.
value_compare Optional comparator for values. Required for pair-level APIs.
key_hash Required hash callback for keys.
entries Pointer to entry storage. Do not index directly.
states Slot-state storage used internally by the probing policy.
policy Copy of the probing policy used by this map.

Usage example (from documentation)

  typedef Map(int, Str) IntStrMap;
  typedef Map(T(Pair(i32, i32)), float) PairFloatMap;

Usage example (Cross-references)

Usage examples (Cross-references)
    
    #include <Misra/Std.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Std/Memory.h>
    /// Generic map implementation
    
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Std/Memory.h>
        limit = map->policy.max_probe_count;
        if (limit == 0) {
            LOG_FATAL("Map policy '{}' has invalid max_probe_count", map->policy.name);
        }
    static void validate_map_structural(const GenericMap *map) {
        if (!map->key_compare || !map->key_hash) {
            LOG_FATAL("Map must have valid key compare and key hash callbacks");
        }
        if (!map->allocator) {
        }
        if (!map->allocator) {
            LOG_FATAL("Map allocator pointer is NULL");
        }
        if (!map->allocator->allocate || !map->allocator->resize || !map->allocator->remap || !map->allocator->deallocate) {
        }
        if (!map->allocator->allocate || !map->allocator->resize || !map->allocator->remap || !map->allocator->deallocate) {
            LOG_FATAL("Map allocator is invalid");
        }
        validate_map_policy(&map->policy);
        validate_map_policy(&map->policy);
        if (map->length > map->capacity) {
            LOG_FATAL("Map length cannot exceed capacity");
        }
        if ((map->length + map->tombstones) > map->capacity) {
        }
        if ((map->length + map->tombstones) > map->capacity) {
            LOG_FATAL("Map occupied slots and tombstones cannot exceed capacity");
        }
        if (!map->capacity) {
        if (!map->capacity) {
            if (map->entries || map->states) {
                LOG_FATAL("Map with zero capacity must not have allocated storage");
            }
            return;
        }
        if (!map->entries || !map->states) {
            LOG_FATAL("Map storage is corrupted");
        }
    }
    void validate_map(const GenericMap *map) {
        if (!map) {
            LOG_FATAL("Expected a valid Map pointer");
        }
        if (!MAGIC_MATCHES(map->__magic, MAP_MAGIC)) {
        }
        if (!MAGIC_MATCHES(map->__magic, MAP_MAGIC)) {
            LOG_FATAL("Map is uninitialized or corrupted");
        }
        if (!(map->__magic & MAGIC_VALIDATED_BIT)) {
    
        if (new_capacity < (n > map->length ? n : (size)map->length)) {
            LOG_FATAL("Map policy '{}' returned insufficient capacity {}", policy.name, new_capacity);
        }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_insert_and_set(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_set_first(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInitWithValueCompare(i32_hash, i32_compare, i32_compare, &alloc);
    
    static bool test_map_lvalue_zeroing(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    // would re-probe the same cluster and loop forever).
    static bool test_map_churn_does_not_loop(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc  = DefaultAllocatorInit();
        IntIntMap        map    = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_ensure_ptr(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Insert tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Insert");
    }
    
        WriteFmt("[INFO] Starting Map.Insert tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Insert");
    }
    #include <Misra/Std/Container/Float.h>
    #include <Misra/Std/Container/Int.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    // the GenericHash / GenericCompare-shaped helpers wire in directly.
    bool test_float_hash_as_map_key(void) {
        WriteFmt("Testing float_hash as Map<Float, u64> key\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        Map(Float, u64) counts = MapInit(float_hash, float_compare, &alloc);
    
        Float k1 = FloatFromStr("3.14", &alloc.base);
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_foreach_ptr(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc     = DefaultAllocatorInit();
        IntIntMap        map       = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_foreach_multimap_iterators(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc          = DefaultAllocatorInit();
        IntIntMap        map            = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Foreach tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Foreach");
    }
    
        WriteFmt("[INFO] Starting Map.Foreach tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Foreach");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
        WriteFmt("Testing ValidateMap on uninitialized map\n");
    
        Map(int, int) map = {0};
        ValidateMap(&map);
        WriteFmt("Testing MapContainsPair without value comparator\n");
    
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        WriteFmt("Testing MapRemovePair without value comparator\n");
    
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        WriteFmt("Testing MapRemoveIf without predicate\n");
    
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        WriteFmt("Testing MapRetainIf without predicate\n");
    
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Deadend tests\n\n");
        return run_test_suite(
            NULL,
            deadend_tests,
            (int)(sizeof(deadend_tests) / sizeof(deadend_tests[0])),
            "Map.Deadend"
        );
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_remove_value(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_remove_pair(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInitWithValueCompare(i32_hash, i32_compare, i32_compare, &alloc);
    
    static bool test_map_remove_if(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_remove_all(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_tombstone_reuse(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Remove tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Remove");
    }
    
        WriteFmt("[INFO] Starting Map.Remove tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Remove");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Int.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include <Misra/Types.h>
    // GenericHash / GenericCompare-shaped helpers wire in directly.
    bool test_int_hash_as_map_key(void) {
        WriteFmt("Testing int_hash as Map<Int,u64> key\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        Map(Int, u64) counts = MapInit(int_hash, int_compare, &alloc);
    
        Int k1 = IntFrom(100u, &alloc.base);
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_contains_and_find(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInitWithValueCompare(i32_hash, i32_compare, i32_compare, &alloc);
    
    static bool test_map_get_ptr(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_try_get_ptr(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_get_or_default(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_value_cursor_query(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc     = DefaultAllocatorInit();
        IntIntMap        map       = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_cursor_invalidated_after_removal(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc  = DefaultAllocatorInit();
        IntIntMap        map    = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Access tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Access");
    }
    
        WriteFmt("[INFO] Starting Map.Access tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Access");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_reserve_and_clear(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_rehash_policy_switch(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_custom_policy_growth(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc         = DefaultAllocatorInit();
        MapPolicy        custom_policy = {
        };
    
        WriteFmt("[INFO] Starting Map.Init tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Init");
    }
    
        WriteFmt("[INFO] Starting Map.Init tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Init");
    }
    #include <Misra/Std/Zstr.h>
    #include <Misra/Std/Container/Graph.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Container/Str.h>
    #include <Misra/Std/Log.h>
    
    typedef Graph(Str) CityGraph;
    typedef Map(Str, GraphNodeId) CityIndex;
    
    static GraphNodeId city_add_intersection(CityGraph *graph, CityIndex *index, const Str *name, DefaultAllocator *alloc) {
    
        typedef Graph(int) IntGraph;
        typedef Map(GraphNodeId, u64) CountMap;
    
        IntGraph graph  = GraphInit(&alloc);
    #include <Misra/Std/Container/BitVec.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Log.h>
    // shaped helpers wired in directly -- no per-callsite cast needed.
    bool test_bitvec_hash_as_map_key(void) {
        WriteFmt("Testing bitvec_hash as Map<BitVec, u64> key\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Allocator       *base  = ALLOCATOR_OF(&alloc);
    
        Map(BitVec, u64) counts = MapInit(bitvec_hash, bitvec_compare, &alloc);
    
        BitVec k1 = BitVecInit(base);
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Zstr.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Container/Str.h>
    #include <Misra/Std/Memory.h>
    
    static bool test_map_deep_copy_zstrs(void) {
        typedef Map(Zstr, Zstr) ZstrMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        ZstrMap          map   = MapInitWithDeepCopy(
    
    static bool test_map_policy_switch_preserves_entries(void) {
        typedef Map(Zstr, Zstr) ZstrMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        ZstrMap          map   = MapInitWithDeepCopy(
    
    static bool test_map_compact_and_swap(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc  = DefaultAllocatorInit();
        IntIntMap        first  = MapInitWithValueCompare(i32_hash, i32_compare, i32_compare, &alloc);
    
    static bool test_map_retain_if(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc     = DefaultAllocatorInit();
        IntIntMap        map       = MapInit(i32_hash, i32_compare, &alloc);
        };
    
        WriteFmt("[INFO] Starting Map.Ops tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Ops");
    }
    
        WriteFmt("[INFO] Starting Map.Ops tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Ops");
    }
    #include <Misra/Std/Allocator/Default.h>
    #include <Misra/Std/Zstr.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Log.h>
    #include "../Util/TestRunner.h"
    
    static bool test_map_type_defaults(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInit(i32_hash, i32_compare, &alloc);
    
    static bool test_map_type_with_value_compare(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc = DefaultAllocatorInit();
        IntIntMap        map   = MapInitWithValueCompare(i32_hash, i32_compare, i32_compare, &alloc);
    
    static bool test_map_policy_copy(void) {
        typedef Map(int, int) IntIntMap;
        DefaultAllocator alloc         = DefaultAllocatorInit();
        MapPolicy        custom_policy = {
        };
    
        WriteFmt("[INFO] Starting Map.Type tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Type");
    }
    
        WriteFmt("[INFO] Starting Map.Type tests\n\n");
        return run_test_suite(tests, (int)(sizeof(tests) / sizeof(tests[0])), NULL, 0, "Map.Type");
    }
    #endif
    #if FEATURE_MAP
    #    include <Misra/Std/Container/Map.h>
    #endif
    #if FEATURE_GRAPH
    #include <Misra/Std/Allocator/Heap.h>
    #include <Misra/Std/Allocator/Page.h>
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Container/Str.h>
    #include <Misra/Std/Container/Vec.h>
        } DebugRecord;
    
        typedef Map(void *, DebugRecord) DebugRecordMap;
    
        ///
    
    // clang-format off
    #include "Map/Type.h"
    #include "Map/Init.h"
    #include "Map/Insert.h"
    // clang-format off
    #include "Map/Type.h"
    #include "Map/Init.h"
    #include "Map/Insert.h"
    #include "Map/Remove.h"
    #include "Map/Type.h"
    #include "Map/Init.h"
    #include "Map/Insert.h"
    #include "Map/Remove.h"
    #include "Map/Access.h"
    #include "Map/Init.h"
    #include "Map/Insert.h"
    #include "Map/Remove.h"
    #include "Map/Access.h"
    #include "Map/Memory.h"
    #include "Map/Insert.h"
    #include "Map/Remove.h"
    #include "Map/Access.h"
    #include "Map/Memory.h"
    #include "Map/Foreach.h"
    #include "Map/Remove.h"
    #include "Map/Access.h"
    #include "Map/Memory.h"
    #include "Map/Foreach.h"
    #include "Map/Ops.h"
    #include "Map/Access.h"
    #include "Map/Memory.h"
    #include "Map/Foreach.h"
    #include "Map/Ops.h"
    #include "Map/Private.h"
    #include "Map/Memory.h"
    #include "Map/Foreach.h"
    #include "Map/Ops.h"
    #include "Map/Private.h"
    // clang-format on
    #include "Map/Foreach.h"
    #include "Map/Ops.h"
    #include "Map/Private.h"
    // clang-format on
    #define MISRA_PARSERS_KVCONFIG_H
    
    #include <Misra/Std/Container/Map.h>
    #include <Misra/Std/Container/Str.h>
    #include <Misra/Std/Utility/StrIter.h>
    // translation-unit-visible spot so the public header and the
    // implementation agree on the layout.
    typedef Map(Str, Str) KvConfig;
    
    // Private backends. Included AFTER the KvConfig typedef so the
Last updated on