/*
* Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: maps.c,v 1.14 2006/05/02 17:13:41 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/heap.h"
#include "sm/maps.h"
#include "sm/mapc.h"
#include "sm/map.h"
/*
** SM_MAPS_FREE -- free map class (callback for bht_destroy)
**
** Parameters:
** value -- map system context
** key -- unused
** ctx -- unused
**
** Returns:
** none.
*/
/* ARGSUSED1 */
static void
sm_maps_free(void *value, void *key, void *ctx)
{
sm_mapc_P mapc;
SM_REQUIRE(value != NULL);
mapc = (sm_mapc_P) value;
SM_IS_MAPC(mapc);
SM_CSTR_FREE(mapc->sm_mapc_type);
sm_free_size(mapc, sizeof(*mapc));
}
/*
** SM_MAPS_TERM -- terminate map system
**
** Parameters:
** maps -- map system context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_maps_term(sm_maps_P maps)
{
if (maps == NULL)
return SM_SUCCESS;
SM_IS_MAPS(maps);
if (maps->sm_maps_ht_mapc != NULL)
{
/* XXX function to free each element? */
bht_destroy(maps->sm_maps_ht_mapc, sm_maps_free, NULL);
}
if (maps->sm_maps_ht_map != NULL)
bht_destroy(maps->sm_maps_ht_map, NULL, NULL);
sm_free_size(maps, sizeof(*maps));
return SM_SUCCESS;
}
/*
** SM_MAPS_INIT -- initialize map system
**
** Parameters:
** pmaps -- (pointer to) map system context (output)
** add parameters for hash table sizes?
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_maps_init(sm_maps_P *pmaps)
{
sm_maps_P maps;
sm_ret_T ret;
SM_REQUIRE(pmaps != NULL);
*pmaps = NULL;
maps = (sm_maps_P ) sm_zalloc(sizeof(*maps));
if (maps == NULL)
return sm_error_temp(SM_EM_MAPS, ENOMEM);
maps->sm_maps_ht_mapc = bht_new(16, 1024);
if (maps->sm_maps_ht_mapc == NULL)
{
ret = sm_error_temp(SM_EM_MAPS, ENOMEM);
goto error;
}
maps->sm_maps_ht_map = bht_new(16, 1024);
if (maps->sm_maps_ht_map == NULL)
{
ret = sm_error_temp(SM_EM_MAPS, ENOMEM);
goto error;
}
#if SM_MAPS_CHECK
maps->sm_magic = SM_MAPS_MAGIC;
#endif /* SM_MAPS_CHECK */
*pmaps = maps;
return SM_SUCCESS;
error:
if (maps->sm_maps_ht_map != NULL)
bht_destroy(maps->sm_maps_ht_map, NULL, NULL);
if (maps->sm_maps_ht_mapc != NULL)
bht_destroy(maps->sm_maps_ht_mapc, NULL, NULL);
if (maps != NULL)
sm_free_size(maps, sizeof(*maps));
return ret;
}
/*
** SM_MAPS_ADD -- add map class
**
** Parameters:
** maps -- map system context
** mapc -- map class context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_maps_add(sm_maps_P maps, sm_mapc_P mapc)
{
sm_ret_T ret;
bht_entry_P entry;
SM_IS_MAPS(maps);
SM_IS_MAPC(mapc);
ret = bht_add(maps->sm_maps_ht_mapc,
(char *)sm_cstr_data(mapc->sm_mapc_type),
sm_cstr_getlen(mapc->sm_mapc_type),
mapc, &entry);
return ret;
}
/*
** SM_MAPS_RM -- remove map class
**
** Parameters:
** maps -- map system context
** mapc -- map class context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_maps_rm(sm_maps_P maps, sm_mapc_P mapc)
{
SM_IS_MAPS(maps);
SM_IS_MAPC(mapc);
/* XXX check for existence and complain if it isn't registered? */
bht_rm(maps->sm_maps_ht_mapc,
(const char *)sm_cstr_data(mapc->sm_mapc_type),
sm_cstr_getlen(mapc->sm_mapc_type), sm_maps_free, NULL);
return SM_SUCCESS;
}
/*
** SM_MAPS_FIND -- lookup value
**
** Parameters:
** maps -- map system context
** mapc_type -- map class type
** mapc -- (pointer to) map class context (output)
**
** Returns:
** pointer to value
*/
sm_ret_T
sm_maps_find(sm_maps_P maps, const sm_cstr_P mapc_type, sm_mapc_P *pmapc)
{
void *ptr;
SM_IS_MAPS(maps);
SM_IS_CSTR(mapc_type);
ptr = bht_find(maps->sm_maps_ht_mapc,
(const char*)sm_cstr_data(mapc_type),
sm_cstr_getlen(mapc_type));
if (ptr == NULL)
return sm_error_perm(SM_EM_MAP, ENOENT);
if (pmapc != NULL)
*pmapc = (sm_mapc_P)ptr;
return SM_SUCCESS;
}
#if 0
///*
//** SM_MAPS_WALK - iterate over hash maps, apply a function to each element
//**
//** Parameters:
//** maps -- pointer to maps
//** action -- function to apply
//** ctx -- context for function.
//**
//** Returns:
//** usual sm_error code
//*/
//
//sm_ret_T
//sm_maps_walk(sm_maps_P maps, sm_bhwalk_F action, void *ctx)
//{
// uint i;
// sm_maps_entry_P *h, ht, htn;
// sm_ret_T ret;
//
// SM_IS_MAPS(maps);
// i = maps->maps_size;
// h = maps->maps_data;
// while (i-- > 0)
// {
// for (ht = *h++; ht != NULL; ht = htn)
// {
// htn = ht->bhe_next;
// ret = (*action)(ht, ctx);
// if (sm_is_err(ret))
// return ret;
// }
// }
// return SM_SUCCESS;
//}
#endif /* 0 */
syntax highlighted by Code2HTML, v. 0.9.1