/*

sshstrmapping.c

Author: Vesa Suontama <vsuontam@ssh.fi>

Copyright (c) 1999 Vesa Suontama <vsuontam@ssh.fi>, Espoo, Finland
                   All rights reserved

Created: Thu Sep  2 11:06:25 1999 vsuontam
Last modified: Thu Sep  2 13:35:11 1999 vsuontam

*/

#include "sshincludes.h"
#include "sshstrmapping.h"


/* Hash function. */
unsigned long ssh_str_mapping_hash_func(const void *key,
                           size_t key_length)
{
  return ssh_default_hash_function(key, strlen((char *)key) + 1);
}


/* Hash comparing function. */
int ssh_str_mapping_compare_func(const void *key1,
                                 const void *key2,
                                 size_t key_length)
{
  return strcmp((char *)key1, (char *)key2);
}


/* Destructor procedure for key */
void ssh_str_mapping_dest_func(void *key,
                               size_t key_length,
                               void *value,
                               size_t value_length)
{
  ssh_xfree(key);
}

/* Allocates the string mapping.  This function returns pointer to
   allocated SshMapping set or NULL in case of error. */
SshMapping ssh_str_mapping_allocate()
{
  return ssh_mapping_allocate_with_func(SSH_MAPPING_FL_VARIABLE_LENGTH,
                                        ssh_str_mapping_hash_func,
                                        ssh_str_mapping_compare_func,
                                        ssh_str_mapping_dest_func,
                                        sizeof(char *),
                                        sizeof(void *));

}



/* Adds a mapping for a key. Duplicate keys are stored only once.  If
   mapping for this key already exists, the old value is replaced with
   the new one. In that case this returns TRUE, otherwise FALSE.  */
Boolean ssh_str_mapping_put(SshMapping set, const char *key, void *value)
{
  void *value_tmp = value;

  return ssh_mapping_put_vl(set, (char *) key, strlen(key) + 1, &value_tmp,
                            sizeof(void *));
}

/* Removes a mapping for a key. If there was no mapping for specified
   key, FALSE is returned. If mapping existed, this returns TRUE and
   if `value_return' is not NULL, also copies the old mapped value to
   it. */
Boolean ssh_str_mapping_remove(SshMapping set, const char *key,
                               void *value_return)
{

  size_t tmp_size;
  Boolean result;
  void *pvalue;

  result =  ssh_mapping_remove_vl(set, key, strlen(key) + 1,
                               &pvalue, &tmp_size);
  if (result && value_return)
    {
      memcpy(value_return, pvalue, tmp_size);
    }

  return result;
}

/* Checks the existance of key in set and returns TRUE if it is found,
   FALSE otherwise.  If `value_return' is not NULL, copies also the
   mapped value to buffer pointer in it. */
Boolean ssh_str_mapping_get(const SshMapping set, const char *key,
                            void *value_return)
{
  size_t tmp_size;
  Boolean result;
  void *pvalue;

  result =  ssh_mapping_get_vl(set, key, strlen(key) + 1,
                               &pvalue, &tmp_size);
  if (result && value_return)
    {
      memcpy(value_return, pvalue, tmp_size);
    }

  return result;
}

/* Get next for str mapping. Gets a next item from mapping. */
Boolean ssh_str_mapping_get_next(SshMapping set, char **key_return,
                                 void *value_return)
{

  size_t tmp_size, str_size;
  Boolean result;
  void *pvalue;

  result =  ssh_mapping_get_next_vl(set, (void *)key_return, &str_size,
                                    &pvalue, &tmp_size);
  if (result && value_return)
    {
      memcpy(value_return, pvalue, tmp_size);
    }
  return result;
}

/* Removes all the elements from the mapping and calls the destructor function
   for each of them. */
void ssh_str_mapping_destroy(SshMapping set, 
                             SshStrMappingDestructorCB destructor_cb,
                             void *context)
{
  Boolean ok;
  char *key;
  void *value;

  if (destructor_cb == NULL)
    {
      ssh_str_mapping_free(set);
      return;
    }
  ssh_str_mapping_reset_index(set);

  ok = ssh_str_mapping_get_next(set, &key, &value);
  while(ok)
    {
      destructor_cb(key, value, context);
      ok = ssh_str_mapping_get_next(set, &key, &value);
    }

  ssh_str_mapping_free(set);
  return;
  
}
