00001 /* Part of the culibs project, <http://www.eideticdew.org/culibs/>. 00002 * Copyright (C) 2008--2010 Petter Urkedal <paurkedal@eideticdew.org> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef CUCON_HZMAP_H 00019 #define CUCON_HZMAP_H 00020 00021 #include <cucon/fwd.h> 00022 #include <cu/conf.h> 00023 #include <cu/clos.h> 00024 #include <stdio.h> 00025 00026 #define CUCON_HZMAP_COMPACT 00027 00028 CU_BEGIN_DECLARATIONS 00029 /** \defgroup cucon_hzmap_h cucon/hzmap.h: Hash Map with Flat Fixed-Sized Keys 00030 ** @{ \ingroup cucon_maps_and_sets_mod 00031 ** 00032 ** \see cucon_hzset_h 00033 ** \see cucon_umap_h 00034 ** \see cucon_pmap_h 00035 **/ 00036 00037 /** Node base struct for \ref cucon_hzmap. */ 00038 struct cucon_hzmap_node 00039 { 00040 cucon_hzmap_node_t next; 00041 }; 00042 00043 #define CUCON_HZMAP_NODE_INIT {NULL} 00044 00045 /** A hash map with fixed-size keys. */ 00046 struct cucon_hzmap 00047 { 00048 #ifdef CUCON_HZMAP_COMPACT 00049 # if CUCONF_SIZEOF_SIZE_T <= 4 00050 unsigned short key_size_w; 00051 unsigned short cap_expt; 00052 # else 00053 cu_shortsize_t key_size_w; 00054 cu_shortsize_t cap_expt; 00055 # endif 00056 #else 00057 cu_shortsize_t key_size_w; 00058 size_t mask; 00059 #endif 00060 size_t size; 00061 cucon_hzmap_node_t *arr; 00062 }; 00063 00064 /** Number of elements in \a map. */ 00065 CU_SINLINE size_t cucon_hzmap_size(cucon_hzmap_t map) 00066 { return map->size; } 00067 00068 /** The current size of the underlying array. */ 00069 CU_SINLINE size_t cucon_hzmap_capacity(cucon_hzmap_t map) 00070 #ifdef CUCON_HZMAP_COMPACT 00071 { return (size_t)1 << map->cap_expt; } 00072 #else 00073 { return map->mask + 1; } 00074 #endif 00075 00076 /** Initialize \a map as an empty map to be used with elements of key size \a 00077 ** key_size_w words. */ 00078 void cucon_hzmap_init(cucon_hzmap_t map, cu_shortsize_t key_size_w); 00079 00080 /** Return an empty map to be used for elements with key size \a key_size_w 00081 ** words. */ 00082 cucon_hzmap_t cucon_hzmap_new(cu_shortsize_t key_size_w); 00083 00084 /** As an optimisation, this function may be called prior to a sequence of 00085 ** inserts to inform how many keys will be inserted. This will cause the 00086 ** underlying array to be resized to it's final size right away. */ 00087 void cucon_hzmap_prepare_insert(cucon_hzmap_t, size_t count); 00088 00089 /** Given that \a node is initialised with a key of suitable size for \a map, 00090 ** if they key exists in \a map, returns false, else links \a node to \a map 00091 ** and returns true. The \ref cucon_hzmap_node base struct of \a node is 00092 ** initialised by this call if the insert takes place. */ 00093 cu_bool_t cucon_hzmap_insert_node(cucon_hzmap_t map, cucon_hzmap_node_t node); 00094 00095 /** If a node with key \a key exists in \a map, assign it to \c *\a node_out 00096 ** and return false, else insert a new node of size \a node_size, set it's key 00097 ** to \a key, assign it to \c *\a node_out, and return true. */ 00098 cu_bool_t cucon_hzmap_insert(cucon_hzmap_t map, void const *key, 00099 size_t node_size, cucon_hzmap_node_t *node_out); 00100 00101 /** If a node of key \a key exists in \a map, return false, else insert a node 00102 ** of key \a key an no othe data. */ 00103 cu_bool_t cucon_hzmap_insert_void(cucon_hzmap_t, void const *key); 00104 00105 /** If \a map contains a node with key \a key, erase it and return true, else 00106 ** return false. */ 00107 cu_bool_t cucon_hzmap_erase(cucon_hzmap_t, void const *key); 00108 00109 /** Same as \ref cucon_hzmap_erase, except the underlying capacity of \a map 00110 ** will be left unchanged. This is used for optimising code where many keys 00111 ** are erased in a row. Call \ref cucon_hzmap_finish_erase at the end to 00112 ** adjust the capacity. */ 00113 cu_bool_t cucon_hzmap_step_erase(cucon_hzmap_t map, void const *key); 00114 00115 /** Adjusts the capacity after a sequence of \ref cucon_hzmap_erase. */ 00116 void cucon_hzmap_finish_erase(cucon_hzmap_t); 00117 00118 /** Returns the node in \a map with key \a key, or \c NULL if no such node 00119 ** exists. */ 00120 cucon_hzmap_node_t cucon_hzmap_find(cucon_hzmap_t map, void const *key); 00121 00122 /** A version of \a cucon_hzmap_find_node optimised for the case when it is 00123 ** known that \a map has 1 word keys. */ 00124 cucon_hzmap_node_t cucon_hzmap_1w_find(cucon_hzmap_t map, void const *key); 00125 00126 /** A version of \a cucon_hzmap_find_node optimised for the case when it is 00127 ** known that \a map has 2 word keys. */ 00128 cucon_hzmap_node_t cucon_hzmap_2w_find(cucon_hzmap_t map, void const *key); 00129 00130 /** True if \a f maps all elements of \a map to true, otherwise exits with 00131 ** false on the first element which maps to false. */ 00132 cu_bool_t cucon_hzmap_forall(cu_clop(f, cu_bool_t, cucon_hzmap_node_t), 00133 cucon_hzmap_t map); 00134 00135 /** As \ref cucon_hzmap_forall, but pass only keys to \a f. */ 00136 cu_bool_t cucon_hzmap_forall_keys(cu_clop(f, cu_bool_t, void const *key), 00137 cucon_hzmap_t map); 00138 00139 /** Removes all elements from \a map which \a f maps to false. */ 00140 void cucon_hzmap_filter(cu_clop(f, cu_bool_t, cucon_hzmap_node_t), 00141 cucon_hzmap_t map); 00142 00143 /** As \ref cucon_hzmap_filter, but pass only keys to \a f. */ 00144 void cucon_hzmap_filter_keys(cu_clop(f, cu_bool_t, void const *key), 00145 cucon_hzmap_t map); 00146 00147 /** An iterator over all elements of a \ref cucon_hzmap. */ 00148 struct cucon_hzmap_itr 00149 { 00150 cucon_hzmap_node_t *arr_cur; 00151 cucon_hzmap_node_t *arr_end; 00152 cucon_hzmap_node_t node; 00153 }; 00154 00155 /** Initialise an iterator over elements of \a map. */ 00156 void cucon_hzmap_itr_init(cucon_hzmap_itr_t itr, cucon_hzmap_t map); 00157 00158 /** The next element of the sequence initialised with \ref 00159 ** cucon_hzmap_itr_init, or \c NULL if there are no more elements. */ 00160 cucon_hzmap_node_t cucon_hzmap_itr_get(cucon_hzmap_itr_t itr); 00161 00162 void const *cucon_hzmap_itr_get_key(cucon_hzmap_itr_t itr); 00163 00164 void cucon_hzmap_dump_stats(cucon_hzmap_t map, FILE *out); 00165 00166 /** @} */ 00167 CU_END_DECLARATIONS 00168 00169 #endif