1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
/* ************************************************************************ */
/* */
/* Neko Virtual Machine */
/* Copyright (c)2005 Motion-Twin */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */
/* */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* Lesser General Public License or the LICENSE file for more details. */
/* */
/* ************************************************************************ */
#include "neko.h"
typedef struct vlist {
value v;
struct vlist *next;
} vlist;
typedef struct vparam {
int *h;
vlist l;
} vparam;
#define HBIG(x) *h = *h * 65599 + (x)
#define HSMALL(x) *h = *h * 19 + (x)
static void hash_obj_rec( value v, field f, void *_p );
static void hash_rec( value v, int *h, vlist *l ) {
val_type t = val_type(v);
switch( t ) {
case VAL_INT:
HBIG(val_int(v));
break;
case VAL_NULL:
HSMALL(0);
break;
case VAL_FLOAT:
{
int k = sizeof(tfloat);
while( k )
HSMALL(val_string(v)[--k]);
}
break;
case VAL_BOOL:
HSMALL(val_bool(v));
break;
case VAL_STRING:
{
int k = val_strlen(v);
while( k )
HSMALL(val_string(v)[--k]);
}
break;
case VAL_OBJECT:
case VAL_ARRAY:
{
vlist *tmp = l;
int k = 0;
while( tmp != NULL ) {
if( tmp->v == v ) {
HSMALL(k);
return;
}
k = k + 1;
tmp = tmp->next;
}
}
if( t == VAL_OBJECT ) {
vparam p;
p.h = h;
p.l.v = v;
p.l.next = l;
val_iter_fields(v,hash_obj_rec,&p);
v = (value)((vobject*)v)->proto;
if( v != NULL )
hash_rec(v,h,&p.l);
} else {
vlist cur;
int k = val_array_size(v);
cur.v = v;
cur.next = l;
while( k )
hash_rec(val_array_ptr(v)[--k],h,&cur);
}
break;
default:
// ignore since we want hashes to be stable wrt memory
break;
}
}
static void hash_obj_rec( value v, field f, void *_p ) {
vparam *p = (vparam*)_p;
int *h = p->h;
HBIG((int)f);
hash_rec(v,h,&p->l);
}
EXTERN int val_hash( value v ) {
int h = 0;
hash_rec(v,&h,NULL);
return (((unsigned int)h) & 0x3FFFFFFF);
}
/* ************************************************************************ */
|