2 * Copyright (C) 2005-2008, The Perl Foundation.
6 * These are the vtable functions for the GDBMHash PMC
7 * Data Structure and Algorithms:
10 * Please remove unneeded entries.
15 src/dynpmc/gdbmhash.pmc - GDBM PMC
19 This is an interface to the GNU dbm library.
23 On inserted and fetch, keys are converted to STRINGs.
27 PMC insert values are converted to STRINGs.
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.
46 #include "parrot/extend.h"
50 =item C<static STRING* make_hash_key(PARROT_INTERP, PMC *key)>
52 Returns a Parrot string for C<*key>.
58 static STRING* make_hash_key(PARROT_INTERP, NOTNULL(PMC * key))
61 real_exception(interp, NULL, OUT_OF_BOUNDS, "Hash: Cannot use NULL key");
63 return key_string(interp, key);
67 pmclass GDBMHash provides hash dynpmc lib gdbm {
71 =item C<void class_init()>
73 Class initialization. GDBMHash is a dynamic PMC, meaning that a dynamically
74 loadable module is created. On Unix-like systems this is a shared library.
75 When it is available, the shared library has linked in the library 'gdbm'.
77 On WIN32 the relevant library seems to be called 'gdbm3'.
78 So we do a bit of cheating here, and load it during class initialization.
87 /* RT#46393: What if libgdbm.so cannot be loaded */
88 /* Parrot_load_lib(interp, slib, NULL); */
89 STRING *slib = string_from_literal(interp, "gdbm3");
95 PMC_struct_val(SELF) = NULL;
99 return PMC_struct_val(SELF);
102 void set_pointer(void* p) {
103 PMC_struct_val(SELF) = p;
108 =item C<VOID set_string_native(STRING* value)>
110 Open a or create a new dbm file.
116 void set_string_native(STRING* value) {
117 char *c_db_name = string_to_cstring(interp, value);
118 GDBM_FILE dbf = gdbm_open(c_db_name, 0, GDBM_NEWDB, 0666, 0);
120 string_cstring_free(c_db_name);
122 PMC_struct_val(SELF) = dbf;
127 =item C<INTVAL get_integer()>
129 Returns the number of pairs in the hash.
130 A uninitialized GDBMHash returns 0.
134 RT#46395: This can be optimized by keeping track of number of elements
138 VTABLE INTVAL get_integer() {
139 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
146 for (key = gdbm_firstkey(dbf); key.dptr; key = nextkey) {
148 nextkey = gdbm_nextkey(dbf, key);
158 =item C<INTVAL get_bool()>
160 Returns true if the hash size is not zero.
166 VTABLE INTVAL get_bool() {
167 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
172 datum key = gdbm_firstkey(dbf);
184 =item C<void set_string_keyed(PMC *key, STRING *value)>
190 void set_string_keyed(PMC* key, STRING* value) {
192 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
193 datum key_gdbm, val_gdbm;
197 keystr = make_hash_key(interp, key);
199 key_gdbm.dsize = keystr->strlen;
200 key_gdbm.dptr = keystr->strstart;
201 val_gdbm.dsize = value->strlen;
202 val_gdbm.dptr = value->strstart;
204 gdbm_store(dbf, key_gdbm, val_gdbm, GDBM_REPLACE);
211 =item C<STRING *get_string_keyed(PMC *key)>
213 Returns the string value for the element at C<*key>.
219 STRING* get_string_keyed(PMC* key) {
220 STRING* keystr, *val;
221 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
222 datum key_gdbm, val_gdbm;
225 return CONST_STRING(INTERP, "");
227 return CONST_STRING(INTERP, "");
228 keystr = make_hash_key(interp, key);
230 key_gdbm.dsize = keystr->strlen;
231 key_gdbm.dptr = keystr->strstart;
232 val_gdbm = gdbm_fetch(dbf, key_gdbm);
234 val = string_from_cstring(interp, val_gdbm.dptr, val_gdbm.dsize);
243 =item C<void set_pmc_keyed(PMC* key, PMC *value)>
245 Convert C<value> to a string and set the string for the C<key>.
251 void set_pmc_keyed(PMC* key, PMC* value) {
254 temp = VTABLE_get_string(interp, value);
255 SELF.set_string_keyed(key, temp);
260 =item C<PMC *get_pmc_keyed(PMC *key)>
262 Returns the PMC value for the element at C<*key>.
268 PMC* get_pmc_keyed(PMC* key) {
269 STRING * ret_string = SELF.get_string_keyed(key);
270 PMC *ret_pmc = pmc_new(interp, enum_class_String);
272 VTABLE_set_string_native(interp, ret_pmc, ret_string);
279 =item C<void set_integer_keyed(PMC* key, INTVAL value)>
281 Convert C<value> to a string and set the string for the C<key>.
287 void set_integer_keyed(PMC* key, INTVAL value) {
290 temp = pmc_new(interp, enum_class_String);
291 VTABLE_set_integer_native(interp, temp, value);
292 SELF.set_pmc_keyed(key, temp);
298 =item C<void set_number_keyed(PMC* key, FLOATVAL value)>
300 Convert C<value> to a string and set the string for the C<key>.
306 void set_number_keyed(PMC* key, FLOATVAL value) {
309 temp = pmc_new(interp, enum_class_String);
310 VTABLE_set_number_native(interp, temp, value);
311 SELF.set_pmc_keyed(key, temp);
316 =item C<INTVAL exists_keyed(PMC *key)>
318 Returns whether a key C<*key> exists in the hash.
324 INTVAL exists_keyed(PMC* key) {
326 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
331 keystr = make_hash_key(interp, key);
333 key_gdbm.dsize = keystr->strlen;
334 key_gdbm.dptr = keystr->strstart;
336 return gdbm_exists(dbf, key_gdbm);
341 =item C<void delete_keyed(PMC *key)>
343 Deletes the element associated with C<*key>.
349 void delete_keyed(PMC* key) {
351 GDBM_FILE dbf = (GDBM_FILE)PMC_struct_val(SELF);
356 keystr = make_hash_key(interp, key);
358 key_gdbm.dsize = keystr->strlen;
359 key_gdbm.dptr = keystr->strstart;
361 if (gdbm_exists(dbf, key_gdbm)) {
362 gdbm_delete(dbf, key_gdbm);
375 F<docs/pdds/pdd08_keys.pod>, L<http://gdbm.gnu.org>
383 * c-file-style: "parrot"
385 * vim: expandtab shiftwidth=4: