// $Id: util.h,v 1.44 2003/07/13 19:23:40 vern Exp $
//
// Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
//      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 util_h
#define util_h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if __STDC__
#define myattribute __attribute__
#else
#define myattribute(x)
#endif

#ifdef DEBUG_BRO

#include <assert.h>

#define ASSERT(x)	assert(x)
#define DEBUG_MSG(x...)	fprintf(stderr, x)
#define DEBUG_fputs	fputs

#else

#define ASSERT(x)
#define DEBUG_MSG(x...)
#define DEBUG_fputs(x...)

#endif

typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;

extern char* copy_string(const char* s);
extern int streq(const char* s1, const char* s2);

// Returns the character corresponding to the given escape sequence (s points
// just past the '\'), and updates s to point just beyond the last character
// of the sequence.
extern int expand_escape(const char*& s);

extern char* skip_whitespace(char* s);
extern const char* skip_whitespace(const char* s);
extern char* skip_whitespace(char* s, char* end_of_s);
extern const char* skip_whitespace(const char* s, const char* end_of_s);
extern char* skip_digits(char* s);
extern char* get_word(char*& s);
extern void get_word(int length, const char* s, int& pwlen, const char*& pw);
extern void to_upper(char* s);
extern const char* strchr_n(const char* s, const char* end_of_s, char ch);
extern const char* strrchr_n(const char* s, const char* end_of_s, char ch);
extern int decode_hex(char ch);
extern unsigned char encode_hex(int h);
extern int strcasecmp_n(int s_len, const char* s, const char* t);
extern const char* strpbrk_n(size_t len, const char* s, const char* charset);
extern int atoi_n(int len, const char* s, const char** end,
			int base, int& result);
extern int fputs(int len, const char* s, FILE* fp);

// Note: returns a pointer into a static buffer.
extern const char* fmt(const char* format, ...)
    myattribute((format (printf, 1, 2)));
extern void fmt(int& len, const char*& b, const char* format, ...)
    myattribute((format (printf, 3, 4)));

extern void hash_md5(size_t size, const unsigned char* bytes,
			unsigned char digest[16]);

extern int hmac_key_set;
extern unsigned char shared_hmac_md5_key[16];
extern void hmac_md5(size_t size, const unsigned char* bytes,
			unsigned char digest[16]);

extern const char* md5_digest_print(const unsigned char digest[16]);
extern void init_random_seed();

class BroObj;
extern void message(const char* msg);
extern void warn(const char* msg);
extern void warn(const char* msg, const char* addl);
extern void error(const char* msg);
extern void error(const char* msg, const char* addl);
extern void error(const char* msg, uint32 addl);
extern void run_time(const char* msg);
extern void run_time(const char* fmt, BroObj* obj);
extern void run_time(const char* fmt, const char* arg);
extern void run_time(const char* fmt, const char* arg1, const char* arg2);
extern void internal_error(const char* fmt, ...)
    myattribute((volatile, format (printf, 1, 2)));
extern void pinpoint();
extern int int_list_cmp(const void* v1, const void* v2);

extern const char* bro_path();
extern const char* bro_prefixes();
extern FILE* search_for_file(const char* filename, const char* ext,
	const char** full_filename);

// Current timestamp, from a networking perspective, not a wall-clock
// perspective.  In particular, if we're reading from a savefile this
// is the time of the most recent packet, not the time returned by
// gettimeofday().
extern double network_time;

// Returns the current time.
extern double current_time();

inline int min(int a, int b)
	{
	return a < b ? a : b;
	}

inline int max(int a, int b)
	{
	return a > b ? a : b;
	}


// For now, don't use hash_maps - they're not fully portable.
#if 0
// Use for hash_map's string keys.
struct eqstr {
	bool operator()(const char* s1, const char* s2) const
		{
		return strcmp(s1, s2) == 0;
		}
};
#endif

// Use for map's string keys.
struct ltstr {
	bool operator()(const char* s1, const char* s2) const
	{
	return strcmp(s1, s2) < 0;
	}
};

// Versions of realloc/malloc which abort() on out of memory

extern void out_of_memory(const char* where);

inline void* safe_realloc(void* ptr, size_t size)
	{
	if ( ! size )
		return 0;

	ptr = realloc(ptr, size);
	if ( ! ptr )
		out_of_memory("realloc");

	return ptr;
	}

inline void* safe_malloc(size_t size)
	{
	void* ptr = malloc(size);
	if ( ! ptr )
		out_of_memory("malloc");

	return ptr;
	}

#endif
