// $Id: Desc.h,v 1.12 2002/10/11 02:20:15 leres Exp $
//
// Copyright (c) 1995, 1996, 1997, 1998, 1999, 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 descriptor_h
#define descriptor_h

#include <stdio.h>
#include "BroString.h"

typedef enum {
	DESC_READABLE,
	DESC_PORTABLE,
	DESC_BINARY,
} desc_type;

typedef enum {
	STANDARD_STYLE,
	ALTERNATIVE_STYLE,
} desc_style;

class ODesc {
public:
	ODesc(desc_type t=DESC_READABLE, FILE* f=0);

	~ODesc();

	int IsReadable() const		{ return type == DESC_READABLE; }
	int IsPortable() const		{ return type == DESC_PORTABLE; }
	int IsBinary() const		{ return type == DESC_BINARY; }

	int IsShort() const		{ return is_short; }
	void SetShort()			{ is_short = 1; }
	void SetShort(int s)		{ is_short = s; }

	desc_style Style() const	{ return style; }
	void SetStyle(desc_style s)	{ style = s; }

	void SetFlush(int arg_do_flush)	{ do_flush = arg_do_flush; }

	void PushIndent();
	void PopIndent();

	void Add(const char* s, int do_indent=1);
	void AddN(const char* s, int len)	{ AddBytes(s, len); }
	void Add(int i);
	void Add(uint32 u);
	void Add(double d);

	// Add s as a counted string.
	void AddCS(const char* s);

	void AddBytes(const BroString* s);

	void Add(const char* s1, const char* s2)
		{ Add(s1); Add(s2); }

	void AddSP(const char* s1, const char* s2)
		{ Add(s1); AddSP(s2); }

	void AddSP(const char* s )
		{ Add(s); SP(); }

	void AddCount(int n)
		{
		if ( ! IsReadable() )
			{
			Add(n);
			SP();
			}
		}

	void SP()	{
			if ( ! IsBinary() )
				Add(" ", 0);
			}
	void NL()	{
			if ( ! IsBinary() && ! is_short )
				Add("\n", 0);
			}

	// Returns the description as a string.
	const char* Description() const		{ return (const char*) base; }

	const void* Bytes() const	{ return base; }
	byte_vec TakeBytes()
		{ const void* t = base; base = 0; return (byte_vec) t; }

	int Len() const		{ return offset; }

protected:
	void Indent();

	void AddBytes(const void* bytes, unsigned int n);

	// Make buffer big enough for n bytes beyond bufp.
	void Grow(unsigned int n);

	void OutOfMemory();

	desc_type type;
	desc_style style;

	void* base;		// beginning of buffer
	unsigned int offset;	// where we are in the buffer
	unsigned int size;	// size of buffer in bytes

	FILE* f;	// or the file we're using.

	int indent_level;
	int is_short;
	int do_flush;
};

#endif
