[t][cage] Remove PGE-dependence from t/op/inf_nan.t since it is part of 'make coretest'
[parrot.git] / src / dynpmc / gdbmhash.pmc
blob6dc6344825ac4f9e8f2345f2fbc09e0cc0b36c0c
1 /* gdbmhash.pmc
2  *  Copyright (C) 2005-2009, Parrot Foundation.
3  *  SVN Info
4  *     $Id$
5  *  Overview:
6  *     These are the vtable functions for the GDBMHash PMC
7  *  Data Structure and Algorithms:
8  *  History:
9  *  Notes:
10  *     Please remove unneeded entries.
11  *  References:
13 =head1 NAME
15 src/dynpmc/gdbmhash.pmc - GDBM PMC
17 =head1 DESCRIPTION
19 This is an interface to the GNU dbm library.
21 =head1 keys
23 On inserted and fetch, keys are converted to STRINGs.
25 =head2 store
27 PMC insert values are converted to STRINGs.
29 =head2 fetch
31 get_integer_keyed() and get_number_keyed() probably don't make any sense,
32 as integers usually can't be converted.
34 When a PMC is requested, a String PMC is returned.
37 =head2 Functions
39 =over 4
41 =cut
43  */
45 #include <gdbm.h>
46 #include "parrot/extend.h"
48 typedef struct GDBM_FH {
49     GDBM_FILE f;
50 } GDBM_FH;
52 #define PMC_dbfh(x) ((Parrot_GDBMHash_attributes *)PMC_data(x))->db_handle->f
57 =item C<static STRING* make_hash_key(PARROT_INTERP, PMC *key)>
59 Returns a Parrot string for C<*key>.
61 =cut
65 static STRING* make_hash_key(PARROT_INTERP, NOTNULL(PMC * key))
67     if (key)
68         return VTABLE_get_string(interp, key);
70     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
71         "Hash: Cannot use NULL key");
76 pmclass GDBMHash provides hash dynpmc lib gdbm {
77     ATTR struct GDBM_FH *db_handle;
81 =item C<void class_init()>
83 Class initialization. GDBMHash is a dynamic PMC, meaning that a dynamically
84 loadable module is created. On Unix-like systems this is a shared library.
85 When it is available, the shared library has linked in the library 'gdbm'.
87 On WIN32 the relevant library seems to be called 'gdbm3'.
88 So we do a bit of cheating here, and load it during class initialization.
90 =cut
94     VTABLE void class_init() {
95 #ifdef WIN32
96         /* TT #1252:  What if libgdbm.so cannot be loaded */
97         /* Parrot_load_lib(interp, slib, NULL); */
98         STRING *slib = CONST_STRING(interp, "gdbm3");
99 #endif
100     }
102     VTABLE void init() {
103         Parrot_GDBMHash_attributes *attrs =
104             mem_allocate_zeroed_typed(Parrot_GDBMHash_attributes);
106         attrs->db_handle = mem_allocate_zeroed_typed(GDBM_FH);
107         PMC_data(SELF)   = attrs;
108         PObj_custom_destroy_SET(SELF);
109     }
111     VTABLE void destroy() {
112         mem_sys_free(
113                 ((Parrot_GDBMHash_attributes *)PMC_data(SELF))->db_handle);
114         mem_sys_free(PMC_data(SELF));
115         PMC_data(SELF) = NULL;
116     }
118     VTABLE void* get_pointer() {
119         return PMC_dbfh(SELF);
120     }
122     VTABLE void set_pointer(void* p) {
123         PMC_dbfh(SELF) = (GDBM_FILE)p;
124     }
128 =item C<VOID set_string_native(STRING* value)>
130 Open a or create a new dbm file.
132 =cut
136     VTABLE void set_string_native(STRING* value) {
137         char * const c_db_name = Parrot_str_to_cstring(interp, value);
138         GDBM_FILE dbf          = gdbm_open(c_db_name, 0, GDBM_NEWDB, 0666, 0);
140         Parrot_str_free_cstring(c_db_name);
142         PMC_dbfh(SELF) = dbf;
143     }
147 =item C<INTVAL get_integer()>
149 Returns the number of pairs in the hash.
150 A uninitialized GDBMHash returns 0.
152 =cut
156     VTABLE INTVAL get_integer() {
157         GDBM_FILE dbf = PMC_dbfh(SELF);
158         if (! dbf) {
159             return 0;
160         }
161         else {
162             INTVAL cnt = 0;
163             datum key, nextkey;
164             for (key = gdbm_firstkey(dbf); key.dptr; key = nextkey) {
165                 cnt++;
166                 nextkey = gdbm_nextkey(dbf, key);
167                 free(key.dptr);
168             }
170             return cnt;
171         }
172     }
176 =item C<INTVAL get_bool()>
178 Returns true if the hash size is not zero.
180 =cut
184     VTABLE INTVAL get_bool() {
185         GDBM_FILE dbf = PMC_dbfh(SELF);
186         if (! dbf) {
187             return 0;
188         }
189         else {
190             datum key = gdbm_firstkey(dbf);
191             if (key.dptr) {
192                 return 1;
193             }
194             else {
195                 return 0;
196             }
197         }
198     }
202 =item C<void set_string_keyed(PMC *key, STRING *value)>
204 =cut
208     VTABLE void set_string_keyed(PMC* key, STRING* value) {
209         STRING* keystr;
210         GDBM_FILE dbf = PMC_dbfh(SELF);
211         datum key_gdbm, val_gdbm;
213         if (!key) return;
214         if (!dbf) return;
215         keystr = make_hash_key(interp, key);
217         key_gdbm.dptr  = Parrot_str_to_cstring(interp, keystr);
218         key_gdbm.dsize = strlen(key_gdbm.dptr);
219         val_gdbm.dptr  = Parrot_str_to_cstring(interp, value);
220         val_gdbm.dsize = strlen(val_gdbm.dptr);
222         gdbm_store(dbf, key_gdbm, val_gdbm, GDBM_REPLACE);
224         Parrot_str_free_cstring(key_gdbm.dptr);
225         Parrot_str_free_cstring(val_gdbm.dptr);
227         return;
228     }
232 =item C<STRING *get_string_keyed(PMC *key)>
234 Returns the string value for the element at C<*key>.
236 =cut
240     VTABLE STRING* get_string_keyed(PMC *key) {
241         STRING *keystr, *val;
242         GDBM_FILE dbf = PMC_dbfh(SELF);
243         datum key_gdbm, val_gdbm;
245         if (!key)
246             return string_from_literal(INTERP, "");
248         if (!dbf)
249             return string_from_literal(INTERP, "");
251         keystr         = make_hash_key(interp, key);
253         key_gdbm.dptr  = Parrot_str_to_cstring(interp, keystr);
254         key_gdbm.dsize = strlen(key_gdbm.dptr);
255         val_gdbm       = gdbm_fetch(dbf, key_gdbm);
257         val = Parrot_str_new(interp, val_gdbm.dptr, val_gdbm.dsize);
258         Parrot_str_free_cstring(key_gdbm.dptr);
259         free(val_gdbm.dptr);
261         return val;
262     }
267 =item C<void set_pmc_keyed(PMC* key, PMC *value)>
269 Convert C<value> to a string and set the string for the C<key>.
271 =cut
275     VTABLE void set_pmc_keyed(PMC* key, PMC* value) {
276         STRING *temp;
278         temp = VTABLE_get_string(interp, value);
279         SELF.set_string_keyed(key, temp);
280     }
284 =item C<PMC *get_pmc_keyed(PMC *key)>
286 Returns the PMC value for the element at C<*key>.
288 =cut
292     VTABLE PMC* get_pmc_keyed(PMC* key) {
293         STRING * ret_string = SELF.get_string_keyed(key);
294         PMC *ret_pmc = pmc_new(interp, enum_class_String);
296         VTABLE_set_string_native(interp, ret_pmc, ret_string);
298         return ret_pmc;
299     }
303 =item C<void set_integer_keyed(PMC* key, INTVAL value)>
305 Convert C<value> to a string and set the string for the C<key>.
307 =cut
311     VTABLE void set_integer_keyed(PMC* key, INTVAL value) {
312         PMC *temp;
314         temp = pmc_new(interp, enum_class_String);
315         VTABLE_set_integer_native(interp, temp, value);
316         SELF.set_pmc_keyed(key, temp);
317     }
322 =item C<void set_number_keyed(PMC* key, FLOATVAL value)>
324 Convert C<value> to a string and set the string for the C<key>.
326 =cut
330     VTABLE void set_number_keyed(PMC* key, FLOATVAL value) {
331         PMC *temp;
333         temp = pmc_new(interp, enum_class_String);
334         VTABLE_set_number_native(interp, temp, value);
335         SELF.set_pmc_keyed(key, temp);
336     }
340 =item C<INTVAL exists_keyed(PMC *key)>
342 Returns whether a key C<*key> exists in the hash.
344 =cut
348     VTABLE INTVAL exists_keyed(PMC* key) {
349         STRING* keystr;
350         GDBM_FILE dbf = PMC_dbfh(SELF);
351         datum key_gdbm;
352         INTVAL ret;
354         if (!key) return 0;
355         if (!dbf) return 0;
356         keystr = make_hash_key(interp, key);
358         key_gdbm.dptr  = Parrot_str_to_cstring(interp, keystr);
359         key_gdbm.dsize = strlen(key_gdbm.dptr);
361         ret = gdbm_exists(dbf, key_gdbm);
362         Parrot_str_free_cstring(key_gdbm.dptr);
364         return ret;
365     }
369 =item C<void delete_keyed(PMC *key)>
371 Deletes the element associated with C<*key>.
373 =cut
377     VTABLE void delete_keyed(PMC* key) {
378         STRING* keystr;
379         GDBM_FILE dbf = PMC_dbfh(SELF);
380         datum key_gdbm;
382         if (!key) return;
383         if (!dbf) return;
384         keystr = make_hash_key(interp, key);
386         key_gdbm.dptr  = Parrot_str_to_cstring(interp, keystr);
387         key_gdbm.dsize = strlen(key_gdbm.dptr);
389         if (gdbm_exists(dbf, key_gdbm)) {
390            gdbm_delete(dbf, key_gdbm);
391         }
393         Parrot_str_free_cstring(key_gdbm.dptr);
395         return;
396     }
401 =back
403 =head1 SEE ALSO
405 F<docs/pdds/pdd08_keys.pod>, L<http://gdbm.gnu.org>
407 =cut
412  * Local variables:
413  *   c-file-style: "parrot"
414  * End:
415  * vim: expandtab shiftwidth=4:
416  */