<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >Hash table</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="libEtPan! API" HREF="book1.htm"><LINK REL="UP" TITLE="Tools and datatypes" HREF="c16.htm"><LINK REL="PREVIOUS" TITLE="List" HREF="x88.htm"><LINK REL="NEXT" TITLE="Buffered I/O" HREF="x229.htm"></HEAD ><BODY CLASS="SECT1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >libEtPan! API</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="x88.htm" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" >Chapter 2. Tools and datatypes</TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="x229.htm" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="SECT1" ><H1 CLASS="SECT1" ><A NAME="AEN161" >Hash table</A ></H1 ><PRE CLASS="PROGRAMLISTING" >#include <libetpan/libetpan.h> typedef struct chash chash; typedef struct chashcell chashiter; typedef struct { char * data; int len; } chashdatum; </PRE ><P > <B CLASS="COMMAND" >chash</B > is a hash table. <B CLASS="COMMAND" >chashiter</B > is a pointer to an element of the hash table. <B CLASS="COMMAND" >chashdatum</B > is an element to be placed in the hash table as a key or a value. It consists in data and a corresponding length. </P ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-NEW" >chash_new and chash_free</A ></H2 ><PRE CLASS="PROGRAMLISTING" >#define CHASH_COPYNONE 0 #define CHASH_COPYKEY 1 #define CHASH_COPYVALUE 2 #define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) chash * chash_new(int size, int flags); void chash_free(chash * hash); </PRE ><P > <B CLASS="COMMAND" >chash_new()</B > returns a new empty hash table or <B CLASS="COMMAND" >NULL</B > if this failed. <B CLASS="COMMAND" >size</B > is the initial size of the table used for implementation. <B CLASS="COMMAND" >flags</B > can be a combinaison of <B CLASS="COMMAND" >CHASH_COPYKEY</B > and <B CLASS="COMMAND" >CHASH_COPYVALUE</B >. <B CLASS="COMMAND" >CHASH_COPYKEY</B > enables copy of key, so that the initial value used for <B CLASS="COMMAND" >chash_set()</B > </P ><P > <B CLASS="COMMAND" >chash_free()</B > releases memory used by the hash table. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-GET" >chash_set and chash_get</A ></H2 ><PRE CLASS="PROGRAMLISTING" >int chash_set(chash * hash, chashdatum * key, chashdatum * value, chashdatum * oldvalue); int chash_get(chash * hash, chashdatum * key, chashdatum * result); </PRE ><P > <B CLASS="COMMAND" >chash_set()</B > adds a new element into the hash table. If a previous element had the same key, it is returns into oldvalue if <B CLASS="COMMAND" >oldvalue</B > is different of NULL. Medium complexity is O(1). </P ><P > returns -1 if it fails, 0 on success. </P ><P > <B CLASS="COMMAND" >chash_get()</B >returns the corresponding value of the given key. If there is no corresponding value, -1 is returned. 0 on success. Medium complexity is O(1). </P ><DIV CLASS="EXAMPLE" ><A NAME="AEN191" ></A ><P ><B >Example 2-9. chash insert and lookup</B ></P ><PRE CLASS="PROGRAMLISTING" >int main(void) { chash * hash; int r; chashdatum key; chashdatum value; char * str1 = "my-data"; char * str2 = "my-data"; hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); key.data = "foo"; key.len = strlen("foo"); value.data = str1; value.data = strlen(str1) + 1; /* + 1 is needed to get the terminal zero in the returned string */ r = chash_set(hash, &key, &value, NULL); if (r < 0) goto free_hash; key.data = "bar"; key.len = strlen("bar"); value.data = str2; value.data = strlen(str2) + 1; if (r < 0) goto free_hash; key.data = "foo"; key.len = strlen("foo"); r = chash_get(hash, &key, &value); if (r < 0) { printf("element not found\n"); } else { char * str; str = value.data; printf("found : %s", str); } chash_free(hash); exit(EXIT_SUCCESS); free_hash: chash_free(hash); err: exit(EXIT_FAILURE); } </PRE ></DIV ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-DELETE" >chash_delete</A ></H2 ><PRE CLASS="PROGRAMLISTING" >int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue); </PRE ><P > deletes the key/value pair given the corresponding key. The value is returned in old_value. If there is no corresponding value, -1 is returned. 0 on success. Medium complexity is O(1). </P ><DIV CLASS="EXAMPLE" ><A NAME="AEN198" ></A ><P ><B >Example 2-10. key deletion in a chash</B ></P ><PRE CLASS="PROGRAMLISTING" >int main(void) { chash * hash; int r; chashdatum key; chashdatum value; char * str1 = "my-data"; char * str2 = "my-data"; hash = build_hash(); key.data = "foo"; key.len = strlen("foo"); chash_delete(hash, &key, &value); /* it will never be possible to lookup "foo" */ key.data = "foo"; key.len = strlen("foo"); r = chash_get(hash, &key, &value); if (r < 0) { printf("element not found\n"); } else { char * str; str = value.data; printf("found : %s", str); } chash_free(hash); exit(EXIT_SUCCESS); free_hash: chash_free(hash); err: exit(EXIT_FAILURE); } </PRE ></DIV ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-RESIZE" >chash_resize</A ></H2 ><PRE CLASS="PROGRAMLISTING" >int chash_resize(chash * hash, int size); </PRE ><P > <B CLASS="COMMAND" >chash_resize()</B > changes the size of the table used for implementation of the hash table. returns 0 on success, -1 on failure. </P ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-BEGIN" >running through the chash</A ></H2 ><PRE CLASS="PROGRAMLISTING" >chashiter * chash_begin(chash * hash); chashiter * chash_next(chash * hash, chashiter * iter); void chash_key(chashiter * iter, chashdatum * result); void chash_value(chashiter iter, chashdatum * result); </PRE ><P > <B CLASS="COMMAND" >chash_begin()</B > returns a pointer to the first element of the hash table. Returns <B CLASS="COMMAND" >NULL</B > if there is no elements in the hash table. Complexity is O(n). </P ><P > <B CLASS="COMMAND" >chash_next()</B > returns a pointer to the next element of the hash table. Returns <B CLASS="COMMAND" >NULL</B > if there is no next element. Complexity is O(n) but n calls to chash_next() also has a complexity of O(n). </P ><P > <B CLASS="COMMAND" >chash_key()</B > returns the key of the given element of the hash table. </P ><P > <B CLASS="COMMAND" >chash_value</B > returns the value of the given element of the hash table. </P ><DIV CLASS="EXAMPLE" ><A NAME="AEN219" ></A ><P ><B >Example 2-11. running through a chash</B ></P ><PRE CLASS="PROGRAMLISTING" >int main(void) { chash * hash; int r; chashiter * iter; hash = build_hash(); /* this will display all the values stored in the hash */ for(iter = chash_begin(hash) ; iter != NULL ; iter = chash_next(hash, iter)) { chashdatum key; chashdatum value; char * str; chash_value(iter, &value); str = value.data; printf("%s\n", str); } chash_free(hash); } </PRE ></DIV ></DIV ><DIV CLASS="SECT2" ><H2 CLASS="SECT2" ><A NAME="CHASH-COUNT" >chash_size and chash_count</A ></H2 ><PRE CLASS="PROGRAMLISTING" >int chash_size(chash * hash); int chash_count(chash * hash); </PRE ><P > <B CLASS="COMMAND" >chash_size()</B > returns the size of the table used for implementation of the hash table. Complexity is O(1). </P ><P > <B CLASS="COMMAND" >chash_count()</B > returns the number of elements in the hash table. Complexity is O(1). </P ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="x88.htm" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="book1.htm" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="x229.htm" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >List</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="c16.htm" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Buffered I/O</TD ></TR ></TABLE ></DIV ></BODY ></HTML >