/* * 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 */