// $Id: Hash.h,v 1.15 2003/07/13 19:23:40 vern Exp $
//
// Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef hash_h
#define hash_h

#include <stdlib.h>

#include "BroString.h"

typedef unsigned int hash_t;

typedef enum {
	HASH_KEY_INT, HASH_KEY_DOUBLE, HASH_KEY_STRING
#define NUM_HASH_KEYS (int(HASH_KEY_STRING) + 1)
} HashKeyTag;

class HashKey {
public:
	HashKey(int i);
	HashKey(uint32 u);
	HashKey(const uint32 u[], int n);
	HashKey(double d);
	HashKey(const char* s);
	HashKey(const BroString* s);
	~HashKey()
		{
		if ( is_our_dynamic )
			delete [] (char *) key;
		}

	// Create a HashKey given all of its components.  "key" is assumed
	// to be dynamically allocated and to now belong to this HashKey
	// (to delete upon destruct'ing).  If "copy_key" is true, it's
	// first copied.
	//
	// The calling sequence here is unusual (normally key would be
	// first) to avoid possible ambiguities with the next constructor,
	// which is the more commonly used one.
	HashKey(int copy_key, void* key, int size);

	// Same, but automatically copies the key.
	HashKey(const void* key, int size, hash_t hash);

	// Builds a key from the given chunk of bytes.
	HashKey(const void* bytes, int size);

	// Hands over the key to the caller.  This means that if the
	// key is our dynamic, we give it to the caller and mark it
	// as not our dynamic.  If initially it's not our dynamic,
	// we give them a copy of it.
	void* TakeKey();

	const void* Key() const	{ return key; }
	int Size() const	{ return size; }
	hash_t Hash() const	{ return hash; }

protected:
	void* CopyKey(const void* key, int size) const;
	hash_t HashBytes(const void* bytes, int size) const;

	union {
		int i;
		double d;
	} key_u;

	void* key;
	int is_our_dynamic;
	int size, hash;
};

#endif
