Beispiel #1
0
/*
 * Hash a term.
 */
extern hash_t hash_term(term_t t)
{
    switch (type(t))
    {
        case VAR:
            return hash_var(var(t));
        case NIL:
            return hash_nil();
        case BOOL:
            return hash_bool(boolean(t));
        case NUM:
            return hash_num(num(t));
        case ATOM:
            return hash_atom(atom(t));
        case STR:
            return hash_string(string(t));
        case FOREIGN:
            return hash_foreign(foreign(t));
        case FUNC:
            return hash_func(func(t));
        default:
        {
            hash_t dummy = HASH(0, 0);
            return dummy;
        }
    }
}
static void hash_object(object_t* object, uint32_t* hash) {
    switch (object->type) {
        case type_nil:    *hash = hash_nil(*hash); return;
        case type_bool:   *hash = hash_bool(*hash, object->b); return;
        case type_double: *hash = hash_double(*hash, object->d); return;
        case type_int:    *hash = hash_i64(*hash, object->i); return;
        case type_uint:   *hash = hash_u64(*hash, object->u); return;

        case type_str:
            *hash = hash_str(*hash, object->str, object->l);
            return;

        // unused types in this benchmark
        #if 0
        case type_float:
            write_float(hash, node_float(node));
            return;
        case type_bin:
            *hash = hash_str(*hash, node_data(node), node_data_len(node));
            return;
        case type_ext:
            *hash = hash_u8(*hash, node_exttype(node));
            *hash = hash_str(*hash, node_data(node), node_data_len(node));
            return;
        #endif

        case type_array: {
            uint32_t count = object->l;
            for (uint32_t i = 0; i < count; ++i)
                hash_object(object->children + i, hash);
            *hash = hash_u32(*hash, count);
            return;
        }

        case type_map: {
            uint32_t count = object->l;
            for (uint32_t i = 0; i < count; ++i) {

                // we expect keys to be short strings
                object_t* key = object->children + (i * 2);
                *hash = hash_str(*hash, key->str, key->l);

                hash_object(object->children + (i * 2) + 1, hash);
            }
            *hash = hash_u32(*hash, count);
            return;
        }

        default:
            break;
    }

    abort();
}
static bool hash_json(json_value* value, uint32_t* hash) {
    switch (value->type) {
        case json_null:    *hash = hash_nil(*hash); return true;
        case json_boolean: *hash = hash_bool(*hash, value->u.boolean ? true : false); return true;
        case json_double:  *hash = hash_double(*hash, value->u.dbl); return true;
        case json_string:  *hash = hash_str(*hash, value->u.string.ptr, value->u.string.length); return true;

        case json_integer:
            // json-parser does not support JSON big integers at all.
            // Judging from the code, it looks like it just overflows and
            // gives garbage with no error if an integer is outside the
            // range of int64_t.
            *hash = hash_i64(*hash, value->u.integer);
            return true;

        case json_array: {
            for (unsigned int i = 0; i < value->u.array.length; ++i)
                if (!hash_json(value->u.array.values[i], hash))
                    return false;
            *hash = hash_u32(*hash, value->u.array.length);
            return true;
        }

        case json_object: {
            for (unsigned int i = 0; i < value->u.object.length; ++i) {
                json_object_entry* entry = &value->u.object.values[i];
                *hash = hash_str(*hash, entry->name, entry->name_length);
                if (!hash_json(entry->value, hash))
                    return false;
            }
            *hash = hash_u32(*hash, value->u.object.length);
            return true;
        }

        default:
            break;
    }

    return false;
}
static bool hash_element(cmp_ctx_t* cmp, uint32_t* hash) {
    buffer_t* buffer = (buffer_t*)cmp->buf;

    cmp_object_t object;
    if (!cmp_read_object(cmp, &object))
        return false;

    // note: we fetch values out of the cmp_object_t directly rather
    // than going through the cmp_object_is/as* functions. it's much
    // faster this way.

    switch (object.type) {
        case CMP_TYPE_NIL: *hash = hash_nil(*hash); return true;
        case CMP_TYPE_BOOLEAN: *hash = hash_bool(*hash, object.as.boolean); return true;
        case CMP_TYPE_DOUBLE: *hash = hash_double(*hash, object.as.dbl); return true;

        // note: all ints are hashed as 64-bit (not all libraries read different sized types)

        case CMP_TYPE_POSITIVE_FIXNUM: *hash = hash_u64(*hash, object.as.u8); return true;
        case CMP_TYPE_UINT8: *hash = hash_u64(*hash, object.as.u8); return true;
        case CMP_TYPE_UINT16: *hash = hash_u64(*hash, object.as.u16); return true;
        case CMP_TYPE_UINT32: *hash = hash_u64(*hash, object.as.u32); return true;
        case CMP_TYPE_UINT64: *hash = hash_u64(*hash, object.as.u64); return true;

        case CMP_TYPE_NEGATIVE_FIXNUM: *hash = hash_i64(*hash, object.as.s8); return true;
        case CMP_TYPE_SINT8: *hash = hash_i64(*hash, object.as.s8); return true;
        case CMP_TYPE_SINT16: *hash = hash_i64(*hash, object.as.s16); return true;
        case CMP_TYPE_SINT32: *hash = hash_i64(*hash, object.as.s32); return true;
        case CMP_TYPE_SINT64: *hash = hash_i64(*hash, object.as.s64); return true;

        case CMP_TYPE_FIXSTR:
        case CMP_TYPE_STR8:
        case CMP_TYPE_STR16:
        case CMP_TYPE_STR32:
        {
            uint32_t len = object.as.str_size;
            if (buffer->left < len)
                return false;
            *hash = hash_str(*hash, buffer->data, len);
            buffer->data += len;
            buffer->left -= len;
            return true;
        }

        case CMP_TYPE_FIXARRAY:
        case CMP_TYPE_ARRAY16:
        case CMP_TYPE_ARRAY32:
            for (size_t i = 0; i < object.as.array_size; ++i){
                if (!hash_element(cmp, hash))
                    return false;
            }
            *hash = hash_u32(*hash, object.as.array_size);
            return true;

        case CMP_TYPE_FIXMAP:
        case CMP_TYPE_MAP16:
        case CMP_TYPE_MAP32:
        {
            for (size_t i = 0; i < object.as.map_size; ++i) {

                // we expect keys to be short strings
                char buf[16];
                uint32_t size = sizeof(buf);
                if (!cmp_read_str(cmp, buf, &size))
                    return false;
                *hash = hash_str(*hash, buf, size);

                if (!hash_element(cmp, hash))
                    return false;
            }
            *hash = hash_u32(*hash, object.as.map_size);
            return true;
        }

        default:
            break;
    }

    return false;
}
Beispiel #5
0
/*
 * hash_value - hash a value
 *
 * given:
 *	type	- hash type (see hash.h)
 *	v	- the value
 *	state	- the state to hash or NULL
 *
 * returns:
 *	the new state
 */
HASH *
hash_value(int type, void *v, HASH *state)
{
	LISTELEM *ep;		/* list element pointer */
	ASSOCELEM **assochead;	/* association chain head */
	ASSOCELEM *aep;		/* current association value */
	ASSOCELEM *nextaep;	/* next association value */
	VALUE *value = (VALUE *)v;	/* v cast to a VALUE */
	VALUE *vp;		/* pointer to next OBJ table value */
	ZVALUE fileval;		/* size, position, dev, inode of a file */
	int i;

	/*
	 * initialize if state is NULL
	 */
	if (state == NULL) {
		state = hash_init(type, NULL);
	}

	/*
	 * process the value type
	 */
	switch (value->v_type) {
	case V_NULL:
		(state->chkpt)(state);
		state->bytes = TRUE;
		break;

	case V_INT:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash as if we have a 64 bit value */
		state = hash_int(type, value->v_int, state);
		break;

	case V_NUM:
		/* hash this type */
		state = hash_number(type, value->v_num, state);
		break;

	case V_COM:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash this type */
		state = hash_complex(type, value->v_com, state);
		break;

	case V_ADDR:
		/* there is nothing to setup, simply hash what we point at */
		state = hash_value(type, value->v_addr, state);
		break;

	case V_STR:
		/* strings have no setup */

		/* hash this type */
		state = hash_STR(type, value->v_str, state);
		break;

	case V_MAT:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);
		state->bytes = TRUE;

		/* hash all the elements of the matrix */
		for (i=0; i < value->v_mat->m_size; ++i) {

			/* hash the next matrix value */
			state = hash_value(type,
					value->v_mat->m_table+i, state);
			state->bytes = FALSE;	/* as if reading words */
		}
		break;

	case V_LIST:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash all the elements of the list */
		for (i=0, ep = value->v_list->l_first;
		     ep != NULL && i < value->v_list->l_count;
		     ++i, ep = ep->e_next) {

			/* hash the next list value */
			state = hash_value(type, &ep->e_value, state);
			state->bytes = FALSE;	/* as if reading words */
		}
		break;

	case V_ASSOC:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);
		state->bytes = TRUE;

		/* hash the association */
		assochead = value->v_assoc->a_table;
		for (i = 0; i < value->v_assoc->a_size; i++) {
			nextaep = *assochead;
			while (nextaep) {
				aep = nextaep;
				nextaep = aep->e_next;

				/* hash the next association value */
				state = hash_value(type, &aep->e_value, state);
				state->bytes = FALSE; /* as if reading words */
			}
			assochead++;
		}
		break;

	case V_OBJ:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);
		state->bytes = TRUE;	/* reading bytes */

		/* hash the object name and then the element values */

		state = hash_str(type, objtypename(
			value->v_obj->o_actions->oa_index), state);
		(state->chkpt)(state);

		for (i=value->v_obj->o_actions->oa_count,
		     vp=value->v_obj->o_table;
		     i-- > 0;
		     vp++) {

			/* hash the next object value */
			state = hash_value(type, vp, state);
			state->bytes = FALSE;	/* as if reading words */
		}
		break;

	case V_FILE:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash file length if possible */
		if (getsize(value->v_file, &fileval) == 0) {
			state = hash_zvalue(type, fileval, state);
			zfree(fileval);
		} else {
			/* hash -1 for invalid length */
			state = hash_long(type, (long)-1, state);
		}
		/* hash the file position if possible */
		if (getloc(value->v_file, &fileval) == 0) {
			state = hash_zvalue(type, fileval, state);
			zfree(fileval);
		} else {
			/* hash -1 for invalid location */
			state = hash_long(type, (long)-1, state);
		}
		/* hash the file device if possible */
		if (get_device(value->v_file, &fileval) == 0) {
			state = hash_zvalue(type, fileval, state);
			zfree(fileval);
		} else {
			/* hash -1 for invalid device */
			state = hash_long(type, (long)-1, state);
		}
		/* hash the file inode if possible */
		if (get_inode(value->v_file, &fileval) == 0) {
			state = hash_zvalue(type, fileval, state);
			zfree(fileval);
		} else {
			/* hash -1 for invalid inode */
			state = hash_long(type, (long)-1, state);
		}
		break;

	case V_RAND:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash the RAND state */
		state = hash_int(type, value->v_rand->seeded, state);
		state = hash_int(type, value->v_rand->bits, state);
		(state->update)(state,
			(USB8 *)value->v_rand->buffer, SLEN*FULL_BITS/8);
		state = hash_int(type, value->v_rand->j, state);
		state = hash_int(type, value->v_rand->k, state);
		state = hash_int(type, value->v_rand->need_to_skip, state);
		(state->update)(state,
			(USB8 *)value->v_rand->slot, SCNT*FULL_BITS/8);
		(state->update)(state,
			(USB8*)value->v_rand->shuf, SHUFLEN*FULL_BITS/8);
		state->bytes = FALSE;	/* as if reading words */
		break;

	case V_RANDOM:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash the RANDOM state */
		state = hash_int(type, value->v_random->seeded, state);
		state = hash_int(type, value->v_random->bits, state);
		(state->update)(state,
			(USB8 *)&(value->v_random->buffer), BASEB/8);
		state = hash_zvalue(type, value->v_random->r, state);
		state = hash_zvalue(type, value->v_random->n, state);
		state->bytes = FALSE;	/* as if reading words */
		break;

	case V_CONFIG:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash the CONFIG state */
		state = hash_int(type, value->v_config->outmode, state);
		state = hash_int(type, value->v_config->outmode2, state);
		state = hash_long(type,(long)value->v_config->outdigits, state);
		state = hash_number(type, value->v_config->epsilon, state);
		state = hash_long(type,
			(long)value->v_config->epsilonprec, state);
		state = hash_flag(type, value->v_config->traceflags, state);
		state = hash_long(type, (long)value->v_config->maxprint, state);
		state = hash_len(type, value->v_config->mul2, state);
		state = hash_len(type, value->v_config->sq2, state);
		state = hash_len(type, value->v_config->pow2, state);
		state = hash_len(type, value->v_config->redc2, state);
		state = hash_bool(type, value->v_config->tilde_ok, state);
		state = hash_bool(type, value->v_config->tab_ok, state);
		state = hash_long(type, (long)value->v_config->quomod, state);
		state = hash_long(type, (long)value->v_config->quo, state);
		state = hash_long(type, (long)value->v_config->mod, state);
		state = hash_long(type, (long)value->v_config->sqrt, state);
		state = hash_long(type, (long)value->v_config->appr, state);
		state = hash_long(type, (long)value->v_config->cfappr, state);
		state = hash_long(type, (long)value->v_config->cfsim, state);
		state = hash_long(type, (long)value->v_config->outround, state);
		state = hash_long(type, (long)value->v_config->round, state);
		state = hash_bool(type, value->v_config->leadzero, state);
		state = hash_bool(type, value->v_config->fullzero, state);
		state = hash_long(type,
			(long)value->v_config->maxscancount, state);
		state = hash_str(type, value->v_config->prompt1, state);
		state->bytes = FALSE;	/* as if just read words */
		state = hash_str(type, value->v_config->prompt2, state);
		state->bytes = FALSE;	/* as if just read words */
		state = hash_int(type, value->v_config->blkmaxprint, state);
		state = hash_bool(type, value->v_config->blkverbose, state);
		state = hash_int(type, value->v_config->blkbase, state);
		state = hash_int(type, value->v_config->blkfmt, state);
		state = hash_long(type,
			(long)value->v_config->resource_debug, state);
		state = hash_long(type,
			(long)value->v_config->calc_debug, state);
		state = hash_long(type,
			(long)value->v_config->user_debug, state);
		state = hash_bool(type, value->v_config->verbose_quit, state);
		state = hash_int(type, value->v_config->ctrl_d, state);
		state = hash_str(type, value->v_config->program, state);
		state = hash_str(type, value->v_config->base_name, state);
		state = hash_bool(type, value->v_config->windows, state);
		state = hash_bool(type, value->v_config->cygwin, state);
		state = hash_bool(type, value->v_config->compile_custom, state);
		if (value->v_config->allow_custom != NULL &&
		    *(value->v_config->allow_custom)) {
			state = hash_bool(type, TRUE, state);
		} else {
			state = hash_bool(type, FALSE, state);
		}
		state = hash_str(type, value->v_config->version, state);
		state = hash_int(type, value->v_config->baseb, state);
		state = hash_bool(type, value->v_config->redecl_warn, state);
		state = hash_bool(type, value->v_config->dupvar_warn, state);
		break;

	case V_HASH:
		/* setup for the this value type */
		(state->chkpt)(state);
		(state->type)(value->v_type, state);

		/* hash the HASH state */
		state = hash_int(type, value->v_hash->type, state);
		state = hash_bool(type, value->v_hash->bytes,state);
		state = hash_int(type, value->v_hash->base, state);
		state = hash_int(type, value->v_hash->chunksize, state);
		state = hash_int(type, value->v_hash->unionsize, state);
		(state->update)(state,
		    value->v_hash->h_union.data, state->unionsize);
		state->bytes = FALSE;	/* as if reading words */
		break;

	case V_BLOCK:
		/* there is no setup for a BLOCK */

		/* hash the octets in the BLOCK */
		if (value->v_block->datalen > 0) {
			state = hash_usb8(type, value->v_block->data,
					   value->v_block->datalen, state);
		}
		break;

	case V_OCTET:
		/* there is no setup for an OCTET */

		/* hash the OCTET */
		state = hash_usb8(type, value->v_octet, 1, state);
		break;

	case V_NBLOCK:
		/* there is no setup for a NBLOCK */

		/* hash the octets in the NBLOCK */
		if (value->v_nblock->blk->datalen > 0) {
			state = hash_usb8(type, value->v_nblock->blk->data,
					   value->v_nblock->blk->datalen,
					   state);
		}
		break;

	default:
		math_error("hashing an unknown value");
		/*NOTREACHED*/
	}
	return state;
}
static void hash_value(void* data, UBJ_TYPE type, size_t index, uint32_t* hash) {
    switch (type) {
        case UBJ_MIXED: {
            ubjr_dynamic_t* dynamic = &((ubjr_dynamic_t*)data)[index];
            switch (dynamic->type) {
                case UBJ_INT8:
                case UBJ_UINT8:
                case UBJ_INT16:
                case UBJ_INT32:
                case UBJ_INT64:
                    // the union in a dynamic doesn't actually contain these types, so
                    // we can't just cast it and recurse like the others here. if an
                    // integer is read in a dynamic, the int64_t integer is set to the
                    // value read in priv_ubjr_pointer_to_dynamic(), but integers can
                    // be smaller sizes in fixed-type arrays and objects.
                    *hash = hash_i64(*hash, dynamic->integer);
                    return;

                case UBJ_FLOAT64: hash_value(&dynamic->real, dynamic->type, 0, hash); return;
                case UBJ_STRING:  hash_value(&dynamic->string, dynamic->type, 0, hash); return;
                case UBJ_ARRAY:   hash_value(&dynamic->container_array, dynamic->type, 0, hash); return;
                case UBJ_OBJECT:  hash_value(&dynamic->container_object, dynamic->type, 0, hash); return;

                default: break;
            }
            hash_value(NULL, dynamic->type, 0, hash);
            return;
        }

        case UBJ_NULLTYPE: *hash = hash_nil(*hash); return;
        case UBJ_BOOL_TRUE: *hash = hash_bool(*hash, true); return;
        case UBJ_BOOL_FALSE: *hash = hash_bool(*hash, false); return;
        case UBJ_FLOAT64: *hash = hash_double(*hash, ((double*)data)[index]); return;

        // we assume that the type here comes from a fixed-size array, not from
        // a dynamic (which should have been handled above.)
        case UBJ_INT8:  *hash = hash_i64(*hash, (( int8_t*)data)[index]); return;
        case UBJ_UINT8: *hash = hash_i64(*hash, ((uint8_t*)data)[index]); return;
        case UBJ_INT16: *hash = hash_i64(*hash, ((int16_t*)data)[index]); return;
        case UBJ_INT32: *hash = hash_i64(*hash, ((int32_t*)data)[index]); return;
        case UBJ_INT64: *hash = hash_i64(*hash, ((int64_t*)data)[index]); return;

        case UBJ_STRING:
        case UBJ_CHAR: {
            ubjr_string_t str = ((ubjr_string_t*)data)[index];
            *hash = hash_str(*hash, str, strlen(str));
            return;
        }

        case UBJ_ARRAY: {
            ubjr_array_t* array = &((ubjr_array_t*)data)[index];
            for (size_t i = 0; i < array->size; ++i)
                hash_value(array->values, array->type, i, hash);
            *hash = hash_u32(*hash, array->size);
            return;
        }

        case UBJ_OBJECT:
        {
            ubjr_object_t* object = &((ubjr_object_t*)data)[index];
            for (size_t i = 0; i < object->size; ++i) {
                *hash = hash_str(*hash, object->keys[i], strlen(object->keys[i]));
                hash_value(object->values, object->type, i, hash);
            }
            *hash = hash_u32(*hash, object->size);
            return;
        }

        default:
            break;
    }
}
static int parse_boolean(void* ctx, int boolean) {
    parser_t* parser = (parser_t*)ctx;
    ++parser->children[parser->depth];
    parser->hash = hash_bool(parser->hash, boolean);
    return 1;
}