Task: Hash from two arrays

C: #include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define KeyType const char *
#define ValType int

#define HASH_SIZE 4096


unsigned strhashkey( const char * key, int max)
{
    unsigned h=0;
    unsigned hl, hr;

    while(*key) {
        h += *key;
        hl= 0x5C5 ^ (h&0xfff00000 )>>18;
        hr =(h&0x000fffff );
        h = hl ^ hr ^ *key++;
    }
    return h % max;
}

typedef struct sHme {
    KeyType    key;
    ValType    value;
    struct sHme  *link;
} *MapEntry;

typedef struct he {
    MapEntry  first, last;
} HashElement;

HashElement hash[HASH_SIZE];
    
typedef void (*KeyCopyF)(KeyType *kdest, KeyType ksrc);
typedef void (*ValCopyF)(ValType *vdest, ValType vsrc);
typedef unsigned (*KeyHashF)( KeyType key, int upperBound );
typedef int (*KeyCmprF)(KeyType key1, KeyType key2);

void HashAddH( KeyType key, ValType value,
        KeyCopyF copyKey, ValCopyF copyVal, KeyHashF hashKey, KeyCmprF keySame )
{
    unsigned hix = (*hashKey)(key, HASH_SIZE);
    MapEntry m_ent;

    for (m_ent= hash[hix].first;
            m_ent && !(*keySame)(m_ent->key,key); m_ent=m_ent->link);
    if (m_ent) {
        (*copyVal)(&m_ent->value, value);
    }
    else {
        MapEntry last;
        MapEntry hme = malloc(sizeof(struct sHme));
        (*copyKey)(&hme->key, key);
        (*copyVal)(&hme->value, value);
        hme->link = NULL;
        last = hash[hix].last;
        if (last) {

            last->link = hme;
        }
        else
            hash[hix].first = hme;
        hash[hix].last = hme;
    }
}

int HashGetH(ValType *val, KeyType key, KeyHashF hashKey, KeyCmprF keySame )
{
    unsigned hix = (*hashKey)(key, HASH_SIZE);
    MapEntry m_ent;
    for (m_ent= hash[hix].first;
            m_ent && !(*keySame)(m_ent->key,key); m_ent=m_ent->link);
    if (m_ent) {
        *val = m_ent->value;
    }
    return (m_ent != NULL);
}

void copyStr(const char**dest, const char *src)
{
    *dest = strdup(src);
}
void copyInt( int *dest, int src)
{
    *dest = src;
}
int strCompare( const char *key1, const char *key2)
{
    return strcmp(key1, key2) == 0;
}
    
void HashAdd( KeyType key, ValType value )
{
    HashAddH( key, value, &copyStr, &copyInt, &strhashkey, &strCompare);
}

int HashGet(ValType *val, KeyType key)
{
    return HashGetH( val, key, &strhashkey, &strCompare);
}

int main() 
{
    static const char * keyList[] = {"red","orange","yellow","green", "blue", "violet" };
    static int valuList[] = {1,43,640, 747, 42, 42};
    int ix;

    for (ix=0; ix<6; ix++) {
        HashAdd(keyList[ix], valuList[ix]);
    }
    return 0;
}











Ada: with Ada.Strings.Hash;
with Ada.Containers.Hashed_Maps;
with Ada.Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Hash_Map_Test is
   function Equivalent_Key (Left, Right : Unbounded_String) return Boolean is
   begin
      return Left = Right;
   end Equivalent_Key;
  
   function Hash_Func(Key : Unbounded_String) return Ada.Containers.Hash_Type is
   begin
      return Ada.Strings.Hash(To_String(Key));
   end Hash_Func;
  
   package My_Hash is new Ada.Containers.Hashed_Maps(Key_Type => Unbounded_String,
      Element_Type => Unbounded_String,
      Hash => Hash_Func,
      Equivalent_Keys => Equivalent_Key);
     
   type String_Array is array(Positive range <>) of Unbounded_String;
     
   Hash : My_Hash.Map;
   Key_List : String_Array := (To_Unbounded_String("foo"), 
      To_Unbounded_String("bar"),
      To_Unbounded_String("val"));
     
   Element_List : String_Array := (To_Unbounded_String("little"), 
      To_Unbounded_String("miss"), 
      To_Unbounded_String("muffet"));
     
begin
   for I in Key_List'range loop
      Hash.Insert(Key => (Key_List(I)),
         New_Item => (Element_List(I)));
   end loop;
   for I in Key_List'range loop
      Ada.Text_Io.Put_Line(To_String(Key_List(I)) & " => " &
         To_String(Hash.Element(Key_List(I))));
   end loop;
  
end Hash_Map_Test;