cvsuser 03/11/04 10:33:12
Modified: classes perlhash.pmc
include/parrot hash.h
src hash.c
t/pmc iter.t perlhash.t
Log:
Hash store is now a pointer; PerlHash is PMC only
Revision Changes Path
1.57 +115 -208 parrot/classes/perlhash.pmc
Index: perlhash.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/perlhash.pmc,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -w -r1.56 -r1.57
--- perlhash.pmc 5 Oct 2003 13:49:26 -0000 1.56
+++ perlhash.pmc 4 Nov 2003 18:33:04 -0000 1.57
@@ -1,7 +1,7 @@
/* perlhash.pmc
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: perlhash.pmc,v 1.56 2003/10/05 13:49:26 leo Exp $
+ * $Id: perlhash.pmc,v 1.57 2003/11/04 18:33:04 leo Exp $
* Overview:
* These are the vtable functions for the PerlHash base class
* Data Structure and Algorithms:
@@ -43,7 +43,7 @@
VTABLE_init(INTERP, undef);
}
PObj_custom_mark_SET(SELF);
- new_hash(INTERP, (HASH **)&PMC_ptr1v(SELF));
+ PMC_ptr1v(SELF) = new_hash(INTERP);
}
void mark () {
@@ -53,25 +53,23 @@
INTVAL type_keyed (PMC* key) {
PMC* valpmc;
+ PMC* nextkey;
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ HASHBUCKET* b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ if (b == NULL) {
return enum_hash_undef;
}
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
- valpmc = entry->val.pmc_val;
+ valpmc = b->value;
if (!nextkey)
return enum_hash_pmc;
return VTABLE_type_keyed(INTERP, valpmc, nextkey);
- }
- return entry->type;
+ return enum_hash_pmc;
}
void clone (PMC *ret) {
PObj_custom_mark_SET(ret);
- hash_clone(INTERP, (HASH *)PMC_ptr1v(SELF), (HASH **)&PMC_ptr1v(ret));
+ PMC_ptr1v(ret) = hash_clone(INTERP, (HASH *)PMC_ptr1v(SELF));
}
INTVAL get_integer () {
@@ -81,69 +79,51 @@
INTVAL get_integer_keyed (PMC* key) {
PMC* valpmc;
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ PMC* nextkey;
+ if (b == NULL) {
/* XXX Warning: use of uninitialized value */
return VTABLE_get_integer(INTERP, undef);
}
- if (entry->type == enum_hash_int) return entry->val.int_val;
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
- valpmc = entry->val.pmc_val;
+ valpmc = b->value;
if (!nextkey)
return VTABLE_get_integer(INTERP, valpmc);
return VTABLE_get_integer_keyed(INTERP, valpmc, nextkey);
}
- internal_exception(OUT_OF_BOUNDS,
- "Cannot fetch integer out of non-integer key!\n");
- return -1;
- }
FLOATVAL get_number_keyed (PMC* key) {
PMC* valpmc;
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ PMC* nextkey;
+ if (b == NULL) {
/* XXX Warning: Use of uninitialized value */
return VTABLE_get_number(INTERP, undef);
}
- if (entry->type == enum_hash_num) return entry->val.num_val;
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
- valpmc = entry->val.pmc_val;
+ valpmc = b->value;
if (!nextkey)
return VTABLE_get_number(INTERP, valpmc);
return VTABLE_get_number_keyed(INTERP, valpmc, nextkey);
}
- internal_exception(OUT_OF_BOUNDS,
- "Cannot fetch number out of non-numeric key!\n");
- return 0.0;
- }
BIGNUM* get_bignum_keyed (PMC* key) {
PMC* valpmc;
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ PMC* nextkey;
+ if (b == NULL) {
/* XXX Warning: Use of uninitialized value */
return VTABLE_get_bignum(INTERP, undef);
}
- if (entry->type == enum_hash_num) return (BIGNUM*)entry->val.struct_val;
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
- valpmc = entry->val.pmc_val;
+ valpmc = b->value;
if (!nextkey)
return VTABLE_get_bignum(INTERP, valpmc);
return VTABLE_get_bignum_keyed(INTERP, valpmc, nextkey);
}
- internal_exception(OUT_OF_BOUNDS,
- "Cannot fetch number out of non-numeric key!\n");
- return NULL;
- }
STRING* get_string () {
return Parrot_sprintf_c(INTERP, "PerlHash[0x%x]", SELF);
@@ -152,7 +132,8 @@
STRING* get_string_keyed (PMC* key) {
PMC* valpmc;
STRING* keystr;
- HASH_ENTRY* entry;
+ HASHBUCKET *b;
+ PMC* nextkey;
switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
case KEY_integer_FLAG:
@@ -161,24 +142,17 @@
default:
keystr = make_hash_key(INTERP, key);
}
- entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ if (b == NULL) {
/* XXX Warning: use of uninitialized value */
return VTABLE_get_string(INTERP, undef);
}
- if (entry->type == enum_hash_string) return entry->val.string_val;
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
- valpmc = entry->val.pmc_val;
+ valpmc = b->value;
if (!nextkey)
return VTABLE_get_string(INTERP, valpmc);
return VTABLE_get_string_keyed(INTERP, valpmc, nextkey);
}
- internal_exception(OUT_OF_BOUNDS,
- "Cannot fetch string out of non-string key!\n");
- return NULL;
- }
INTVAL get_bool () {
return hash_size(INTERP, PMC_ptr1v(SELF)) != 0;
@@ -190,23 +164,16 @@
PMC* get_pmc_keyed (PMC* key) {
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY* entry = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
- if (entry == NULL) {
+ HASHBUCKET *b = hash_get(INTERP, (HASH*) PMC_ptr1v(SELF), keystr);
+ PMC* nextkey;
+ if (b == NULL) {
PMC *new_undef = pmc_new(INTERP, enum_class_PerlUndef);
return new_undef;
}
- if (entry->type == enum_hash_pmc) {
- PMC* nextkey;
nextkey = key_next(INTERP, key);
if (!nextkey)
- return entry->val.pmc_val;
- return VTABLE_get_pmc_keyed(INTERP,
- entry->val.pmc_val, nextkey);
-
- }
- internal_exception(OUT_OF_BOUNDS,
- "Cannot fetch PMC out of non-PMC key!\n");
- return NULL;
+ return b->value;
+ return VTABLE_get_pmc_keyed(INTERP, (PMC*)b->value, nextkey);
}
INTVAL is_same (PMC* other) {
@@ -214,88 +181,34 @@
PMC_ptr1v(other) == PMC_ptr1v(SELF));
}
- void set_integer (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
- }
-
- void set_integer_native (INTVAL size) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
- }
-
- void set_integer_same (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to int\n");
- }
-
void set_integer_keyed (PMC* key, INTVAL value) {
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY entry;
- entry.type = enum_hash_int;
- entry.val.int_val = value;
- hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
- }
-
- void set_number (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
- }
-
- void set_number_native (FLOATVAL size) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
- }
-
- void set_number_same (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to number\n");
+ PMC *val = pmc_new(interpreter, enum_class_PerlInt);
+ VTABLE_set_integer_native(INTERP, val, value);
+ hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
}
void set_number_keyed (PMC* key, FLOATVAL value) {
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY entry;
- entry.type = enum_hash_num;
- entry.val.num_val = value;
- hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
- }
-
- void set_bignum (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
- }
-
- void set_bignum_native (BIGNUM* size) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
- }
-
- void set_bignum_same (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to bignum\n");
+ PMC *val = pmc_new(interpreter, enum_class_PerlNum);
+ VTABLE_set_number_native(INTERP, val, value);
+ hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
}
void set_bignum_keyed (PMC* key, BIGNUM* value) {
/* XXX */
}
- void set_string (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
- }
-
- void set_string_native (STRING* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
- }
-
- void set_string_same (PMC* value) {
- internal_exception(INTERNAL_PANIC, "Cannot set hash to string\n");
- }
-
void set_string_keyed (PMC* key, STRING* value) {
STRING* keystr = make_hash_key(INTERP, key);
- HASH_ENTRY entry;
- entry.type = enum_hash_string;
- entry.val.string_val = value;
- hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
+ PMC *val = pmc_new(interpreter, enum_class_PerlString);
+ VTABLE_set_string_native(INTERP, val, value);
+ hash_put(INTERP, PMC_ptr1v(SELF), keystr, val);
}
void set_pmc_keyed (PMC* dest_key, PMC* value) {
STRING* keystr = make_hash_key(INTERP, dest_key);
- HASH_ENTRY entry;
- entry.type = enum_hash_pmc;
- entry.val.pmc_val = value;
- hash_put(INTERP, PMC_ptr1v(SELF), keystr, &entry);
+ hash_put(INTERP, PMC_ptr1v(SELF), keystr, value);
}
@@ -307,51 +220,45 @@
INTVAL exists_keyed(PMC* key) {
STRING * sx;
HASH * h = (HASH *)PMC_ptr1v(SELF);
- HASH_ENTRY * he;
+ HASHBUCKET *b;
sx = key_string(INTERP, key);
key = key_next(INTERP, key);
- he = hash_get(INTERP, h, sx);
- if (he == NULL)
+ b = hash_get(INTERP, h, sx);
+ if (b == NULL)
return 0; /* no such key */
if (key == NULL)
return 1; /* lookup stops here */
- return VTABLE_exists_keyed(INTERP, he->val.pmc_val, key);
+ return VTABLE_exists_keyed(INTERP, (PMC*)b->value, key);
}
INTVAL defined_keyed(PMC* key) {
STRING * sx;
HASH * h = (HASH *)PMC_ptr1v(SELF);
- HASH_ENTRY * he;
+ HASHBUCKET *b;
sx = key_string(INTERP, key);
key = key_next(INTERP, key);
- he = hash_get(INTERP, h, sx);
- if (he == NULL)
+ b = hash_get(INTERP, h, sx);
+ if (b == NULL)
return 0; /* no such key */
- if (he->type == enum_hash_pmc) {
if (key == NULL)
- return VTABLE_defined(INTERP,
- he->val.pmc_val);
+ return VTABLE_defined(INTERP, (PMC*)b->value);
else
- return VTABLE_defined_keyed(
- INTERP, he->val.pmc_val, key);
- }
- /* some other contents */
- return 1;
+ return VTABLE_defined_keyed( INTERP, (PMC*)b->value, key);
}
void delete_keyed(PMC* key) {
STRING * sx;
HASH * h = (HASH *)PMC_ptr1v(SELF);
- HASH_ENTRY * he;
+ HASHBUCKET *b;
sx = key_string(INTERP, key);
key = key_next(INTERP, key);
- he = hash_get(INTERP, h, sx);
- if (he == NULL)
+ b = hash_get(INTERP, h, sx);
+ if (b == NULL)
return; /* no such key */
else if (key == NULL)
hash_delete(INTERP, h, sx);
else
- VTABLE_delete_keyed(INTERP, he->val.pmc_val, key);
+ VTABLE_delete_keyed(INTERP, (PMC*)b->value, key);
}
PMC* nextkey_keyed (PMC* key, INTVAL what) {
1.17 +14 -8 parrot/include/parrot/hash.h
Index: hash.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/hash.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -w -r1.16 -r1.17
--- hash.h 25 Oct 2003 14:45:24 -0000 1.16
+++ hash.h 4 Nov 2003 18:33:08 -0000 1.17
@@ -1,7 +1,7 @@
/* hash.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: hash.h,v 1.16 2003/10/25 14:45:24 leo Exp $
+ * $Id: hash.h,v 1.17 2003/11/04 18:33:08 leo Exp $
* Overview:
* Hashtable implementation
* Data Structure and Algorithms:
@@ -28,6 +28,9 @@
enum_hash_pmc = enum_type_PMC
} HASH_ENTRY_TYPE;
+/*
+ * hash_entry is currently unused
+ */
typedef struct _hash_entry {
HASH_ENTRY_TYPE type;
UnionVal val;
@@ -39,8 +42,8 @@
typedef UINTVAL HashIndex;
struct _hashbucket {
void *key;
- HASH_ENTRY value;
BucketIndex next;
+ void *value;
};
typedef int (*hash_comp_fn)(Parrot_Interp, void*, void*);
@@ -53,21 +56,24 @@
UINTVAL entries; /* Number of values stored in hashtable */
Buffer *bucket_pool; /* Buffer full of buckets, used and unused */
BucketIndex free_list;
+ PARROT_DATA_TYPES entry_type; /* type of value */
+ size_t value_size; /* currently unused, if set this size
+ at value is copied as a hash_entry */
hash_comp_fn compare;
hash_hash_key_fn hash_val;
hash_mark_key_fn mark_key;
};
-void new_hash(Interp * interpreter, HASH **hash_ptr);
-void new_hash_x(Interp * interpreter, HASH **hash_ptr,
+HASH * new_hash(Interp * interpreter);
+HASH * new_hash_x(Interp * interpreter,
hash_comp_fn, hash_hash_key_fn, hash_mark_key_fn);
-void new_cstring_hash(Interp *interpreter, HASH **hash_ptr);
-void hash_clone(Interp * interpreter, HASH * src, HASH **dest);
+HASH * new_cstring_hash(Interp *interpreter);
+HASH * hash_clone(Interp * interpreter, HASH * src);
INTVAL hash_size(Interp * interpreter, HASH *hash);
void hash_set_size(Interp * interpreter, HASH *hash, UINTVAL size);
void hash_destroy(Interp * interpreter, HASH *hash);
-HASH_ENTRY *hash_get(Interp * interpreter, HASH *hash, void *key);
-void hash_put(Interp * interpreter, HASH *hash, void *key, HASH_ENTRY * value);
+HASHBUCKET *hash_get(Interp * interpreter, HASH *hash, void *key);
+void hash_put(Interp * interpreter, HASH *hash, void *key, void *value);
void hash_delete(Interp * interpreter, HASH *hash, void *key);
void mark_hash(Interp * interpreter, HASH *hash);
void dump_hash(Interp * interpreter, HASH *hash);
1.50 +55 -57 parrot/src/hash.c
Index: hash.c
===================================================================
RCS file: /cvs/public/parrot/src/hash.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -w -r1.49 -r1.50
--- hash.c 26 Oct 2003 10:27:01 -0000 1.49
+++ hash.c 4 Nov 2003 18:33:10 -0000 1.50
@@ -1,7 +1,7 @@
/* hash.c
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: hash.c,v 1.49 2003/10/26 10:27:01 leo Exp $
+ * $Id: hash.c,v 1.50 2003/11/04 18:33:10 leo Exp $
* Overview:
* Data Structure and Algorithms:
* A hashtable contains an array of bucket indexes. Buckets
@@ -22,15 +22,23 @@
* hash keys are now (void *)
* add new_cstring_hash() function
*
+ * 2003.11.04 leo bucket->value is now a plain pointer, no nore
+ * an HASH_ENTRY
+ * With little changes, we can again store
+ * arbitrary items if needed, s. TODO in code
+ *
* Notes:
* Future optimizations:
* - Stop reallocating the bucket pool, and instead add chunks on.
* (Saves pointer fixups and copying during realloc.)
* - Hash contraction (dunno if it's worth it)
+ *
* References:
- * pdd08_keys.pod */
+ * pdd08_keys.pod
+ */
#include "parrot/parrot.h"
+#include <assert.h>
#define INITIAL_BUCKETS 16
#define MAXFULL_PERCENT 80
@@ -49,6 +57,7 @@
{
if (idx == NULLBucketIndex)
return NULL;
+ /* TODO honor hash->value_size */
return &((HASHBUCKET *)hash->bucket_pool->bufstart)[idx];
}
@@ -135,7 +144,7 @@
PIO_eprintf(interpreter, " Bucket %vd: ", i);
while (bucket) {
Parrot_block_GC(interpreter); /* don't allow bucket to move */
- PIO_eprintf(interpreter, "type(%d)", bucket->value.type);
+ PIO_eprintf(interpreter, "(%p)", bucket->value);
Parrot_unblock_GC(interpreter);
bucket = getBucket(hash, bucket->next);
if (bucket)
@@ -156,7 +165,7 @@
pobject_lives(interpreter, (PObj *)hash->bucket_pool);
}
- if (hash->buffer.bufstart == NULL || hash->bucket_pool->bufstart == NULL) {
+ if (!hash->buffer.bufstart|| !hash->bucket_pool->bufstart) {
return;
}
@@ -165,11 +174,10 @@
while (bucket) {
if (hash->mark_key)
(hash->mark_key)(interpreter, (PObj *)bucket->key);
- if (bucket->value.type == enum_hash_string)
- pobject_lives(interpreter,
- (PObj *)bucket->value.val.string_val);
- else if (bucket->value.type == enum_hash_pmc)
- pobject_lives(interpreter, (PObj *)bucket->value.val.pmc_val);
+ if (hash->entry_type == enum_hash_string)
+ pobject_lives(interpreter, (PObj *)bucket->value);
+ else if (hash->entry_type == enum_hash_pmc)
+ pobject_lives(interpreter, (PObj *)bucket->value);
bucket = getBucket(hash, bucket->next);
}
}
@@ -211,6 +219,7 @@
UINTVAL new_pool_size = new_size * MAXFULL_PERCENT / 100;
Parrot_reallocate(interpreter, hash, new_size * sizeof(BucketIndex));
+ /* TODO honor hash->value_size */
Parrot_reallocate(interpreter, hash->bucket_pool,
new_pool_size * sizeof(HASHBUCKET));
@@ -262,7 +271,7 @@
}
static BucketIndex
-new_bucket(Interp *interpreter, HASH *hash, STRING *key, HASH_ENTRY *value)
+new_bucket(Interp *interpreter, HASH *hash, STRING *key, void *value)
{
BucketIndex bucket_index;
@@ -285,7 +294,7 @@
hash->free_list = bucket->next;
bucket->key = key;
- bucket->value = *value;
+ bucket->value = value; /* TODO copy value_size if(value_size) */
return bucket_index;
}
@@ -314,36 +323,36 @@
return NULL;
}
-/* FIXME: This function can go back to just returning the hash struct
- * pointer once Buffers can define their own custom mark routines. */
-void
-new_hash(Interp *interpreter, HASH **hash_ptr)
+HASH *
+new_hash(Interp *interpreter)
{
- new_hash_x(interpreter, hash_ptr,
+ return new_hash_x(interpreter,
STRING_compare, /* STRING compare */
key_hash_STRING, /* hash */
pobject_lives); /* mark */
}
-void
-new_cstring_hash(Interp *interpreter, HASH **hash_ptr)
+HASH *
+new_cstring_hash(Interp *interpreter)
{
- new_hash_x(interpreter, hash_ptr,
+ return new_hash_x(interpreter,
cstring_compare, /* cstring compare */
key_hash_cstring, /* hash */
(hash_mark_key_fn)0);/* no mark */
}
-void
-new_hash_x(Interp *interpreter, HASH **hash_ptr,
+HASH *
+new_hash_x(Interp *interpreter,
hash_comp_fn compare, hash_hash_key_fn keyhash,
hash_mark_key_fn mark)
{
HASH *hash = (HASH *)new_bufferlike_header(interpreter, sizeof(*hash));
- *hash_ptr = hash;
hash->compare = compare;
hash->hash_val = keyhash;
hash->mark_key = mark;
+ /* TODO make next 2 params configurable */
+ hash->entry_type = enum_type_PMC;
+ hash->value_size = 0; /* extra size */
/* PObj_report_SET(&hash->buffer); */
@@ -362,6 +371,7 @@
/* PObj_report_SET(hash->bucket_pool); */
hash->free_list = NULLBucketIndex;
expand_hash(interpreter, hash);
+ return hash;
}
/*=for api hash hash_size
@@ -376,14 +386,11 @@
{
UNUSED(interpreter);
- if (hash != NULL) {
+ if (hash)
return hash->entries;
- }
- else {
- PIO_eprintf(interpreter, "*** hash_size asked to check a NULL hash\n");
+ internal_exception(1, "hash_size asked to check a NULL hash\n");
return 0;
}
-}
/*
* called by interator
@@ -420,8 +427,9 @@
return b->key;
}
-PARROT_INLINE static HASHBUCKET *
-hash_lookup(Interp *interpreter, HASH *hash, void *key)
+
+HASHBUCKET *
+hash_get(Interp *interpreter, HASH *hash, void *key)
{
UINTVAL hashval = (hash->hash_val)(interpreter, key);
HashIndex *table = (HashIndex *)hash->buffer.bufstart;
@@ -429,18 +437,9 @@
return find_bucket(interpreter, hash, chain, key);
}
-HASH_ENTRY *
-hash_get(Interp *interpreter, HASH *hash, void *key)
-{
- HASHBUCKET *bucket = hash_lookup(interpreter, hash, key);
- if (bucket == NULL)
- return NULL; /* Not found */
- return &bucket->value;
-}
-
/* The key is *not* copied. */
void
-hash_put(Interp *interpreter, HASH *hash, void *key, HASH_ENTRY *value)
+hash_put(Interp *interpreter, HASH *hash, void *key, void *value)
{
BucketIndex *table;
UINTVAL hashval;
@@ -452,7 +451,8 @@
hashval = (hash->hash_val)(interpreter, key);
table = (BucketIndex *)hash->buffer.bufstart;
- chain = table ? table[hashval & hash->max_chain] : NULLBucketIndex;
+ assert(table);
+ chain = table[hashval & hash->max_chain];
bucket = find_bucket(interpreter, hash, chain, key);
/* fprintf(stderr, "HASH=%p buckets=%p chain=%p bucket=%p KEY=%s\n", */
@@ -460,7 +460,7 @@
if (bucket) {
/* Replacing old value */
- memcpy(&bucket->value, value, sizeof(HASH_ENTRY));
+ bucket->value = value; /* TODO copy value_size */
}
else {
/* Create new bucket */
@@ -513,19 +513,20 @@
PANIC("hash_delete given nonexistent key");
}
-void
-hash_clone(struct Parrot_Interp *interp, HASH *hash, HASH **dest)
+HASH *
+hash_clone(struct Parrot_Interp *interp, HASH *hash)
{
HashIndex i;
+ HASH *dest;
- new_hash_x(interp, dest, hash->compare, hash->hash_val, hash->mark_key);
+ dest = new_hash_x(interp, hash->compare, hash->hash_val, hash->mark_key);
for (i = 0; i <= hash->max_chain; i++) {
BucketIndex bi = lookupBucketIndex(hash, i);
while (bi != NULLBucketIndex) {
HASHBUCKET *b = getBucket(hash, bi);
void *key = b->key;
- HASH_ENTRY valtmp;
- switch (b->value.type) {
+ void *valtmp;
+ switch (hash->entry_type) {
case enum_hash_undef:
case enum_hash_int:
case enum_hash_num:
@@ -533,24 +534,20 @@
break;
case enum_hash_string:
- valtmp.type = enum_hash_string;
- valtmp.val.string_val
- = string_copy(interp, b->value.val.string_val);
+ valtmp = string_copy(interp, b->value);
break;
case enum_hash_pmc:
- valtmp.type = enum_hash_pmc;
- valtmp.val.pmc_val = pmc_new_noinit(interp,
- b->value.val.pmc_val->vtable->base_type);
- VTABLE_clone(interp,
- b->value.val.pmc_val, valtmp.val.pmc_val );
+ valtmp = pmc_new_noinit(interp,
+ ((PMC*)b->value)->vtable->base_type);
+ VTABLE_clone(interp, (PMC*)b->value, valtmp);
break;
default:
internal_exception(-1, "hash corruption: type = %d\n",
- b->value.type);
+ hash->entry_type);
};
- hash_put(interp, *dest, key, &valtmp);
+ hash_put(interp, dest, key, valtmp);
/*
* hash_put may extend the hash, which can trigger GC
* we could also check the GC count and refetch b only when needed
@@ -559,6 +556,7 @@
bi = b->next;
}
}
+ return dest;
}
/*
1.9 +1 -47 parrot/t/pmc/iter.t
Index: iter.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/iter.t,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -w -r1.8 -r1.9
--- iter.t 19 Aug 2003 18:37:28 -0000 1.8
+++ iter.t 4 Nov 2003 18:33:12 -0000 1.9
@@ -1,6 +1,6 @@
#! perl -w
-use Parrot::Test tests => 10;
+use Parrot::Test tests => 9;
use Test::More qw(skip);
output_is(<<'CODE', <<'OUTPUT', "new iter");
new P2, .PerlArray
@@ -185,52 +185,6 @@
CODE
ok 1
ok 2
-OUTPUT
-
-output_is(<<'CODE', <<'OUTPUT', "hash iter - various types");
- .include "datatypes.pasm" # type constants
- .include "iterator.pasm"
- new P1, .PerlHash
- set P1["int"], 10
- set P1["num"], 2.5
- set P1["str"], "string"
- new P2, .PerlString
- set P2, "string"
- set P1["pmc"], P2
-
- set I10, 0 # count items
- new P0, .Iterator, P1 # setup iterator for hash P1
- set P0, .ITERATE_FROM_START
-iter_loop:
- unless P0, iter_end # while (entries) ...
- inc I10
- shift S2, P0 # get key for entry
- typeof I0, P0[S2] # get type of entry for key S2
- ne I0, .DATATYPE_INTVAL, no_int
- set I1, P0[S2]
- eq I1, 10, iter_loop
- print "not ok int\n"
- no_int:
- ne I0, .DATATYPE_FLOATVAL, no_num
- set N1, P0[S2]
- eq N1, 2.5, iter_loop
- print "not ok num\n"
- no_num:
- ne I0, .DATATYPE_STRING, no_str
- set S1, P0[S2]
- eq S1, "string", iter_loop
- print "not ok str\n"
- no_str:
- set P4, P0[S2]
- eq P4, P2, iter_loop
- print "not ok pmc\n"
- branch iter_loop
-iter_end:
- print I10
- print "\n"
- end
-CODE
-4
OUTPUT
output_is(<<'CODE', <<OUTPUT, "string iteration forward");
1.36 +2 -36 parrot/t/pmc/perlhash.t
Index: perlhash.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/perlhash.t,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -w -r1.35 -r1.36
--- perlhash.t 26 Oct 2003 12:53:44 -0000 1.35
+++ perlhash.t 4 Nov 2003 18:33:12 -0000 1.36
@@ -854,49 +854,15 @@
output_is(<<'CODE', <<OUTPUT, "entry types - type_keyed");
.include "datatypes.pasm"
- new P0, .PerlHash
- set P0["int"], 10
- set P0["num"], 2.5
- set P0["str"], "string"
new P1, .PerlHash
- set P0["pmc"], P1
- set P1["str"], "string"
- set P1["int"], 20
-
- typeof I0, P0["int"]
- eq I0, .DATATYPE_INTVAL, ok1
- print "not "
-ok1:print "ok 1\n"
- typeof I0, P0["num"]
- eq I0, .DATATYPE_FLOATVAL, ok2
- print "not "
-ok2:print "ok 2\n"
- typeof I0, P0["str"]
- eq I0, .DATATYPE_STRING, ok3
- print "not "
-ok3:print "ok 3\n"
- typeof I0, P0["pmc"]
+ set P1["pmc"], P1
+ typeof I0, P1["pmc"]
eq I0, .DATATYPE_PMC, ok4
print "not "
ok4:print "ok 4\n"
- typeof I0, P0["pmc";"str"]
- eq I0, .DATATYPE_STRING, ok5
- print I0
- print " not "
-ok5:print "ok 5\n"
- typeof I0, P0["pmc";"int"]
- eq I0, .DATATYPE_INTVAL, ok6
- print I0
- print " not "
-ok6:print "ok 6\n"
end
CODE
-ok 1
-ok 2
-ok 3
ok 4
-ok 5
-ok 6
OUTPUT
output_is(<<'CODE', <<OUTPUT, "delete and free_list");