#ifndef _ECOSTESTUTILS_H
#define _ECOSTESTUTILS_H

#include "stdafx.h"

#define ENTERCRITICAL CeCosTestUtils::EnterCriticalSection(__FILE__,__LINE__)
#define LEAVECRITICAL CeCosTestUtils::LeaveCriticalSection(__FILE__,__LINE__)

#ifndef TRACE
    #define TRACE CeCosTestUtils::Trace
#endif
#undef ERROR
#define ERROR CeCosTestUtils::Error

#ifdef VERBOSE
	#define VTRACE TRACE
#else
	#define VTRACE 1 ? (void)0 : TRACE
#endif

class CeCosTestUtils {
	friend class GarbageCollector;
public:
    #ifdef _WIN32
    static int CALLBACK FilterFunction(LPEXCEPTION_POINTERS p);
    #endif
	static void * GetThreadId();
	static bool SetTraceFile (const char *pszFile);
	class String {
    public:
		String ();
		String (const char *pszStr);
        String (const String &o);
		~String();
		operator const char *() const { return m_pszData; }
		unsigned int GetLength() const { return strlen(m_pszData); } 
		void SetLength(unsigned int nLen);
		const String& operator+=(const char *pszStr);
		const String& operator=(const char *lpsz);
        const String& operator=(const String& o);
		const String& operator+=(char ch);
		void Format (const char * const pszFormat,...);
		void vFormat(const char * pszFormat, va_list marker);
		char operator[](unsigned int nIndex) const;
		void MakeLower();
		void MakeUpper();
		void ReleaseBuffer();
		char * GetBuffer ();
		char * GetBuffer (unsigned int nLength);
	protected:
		char *m_pszData;
		unsigned int m_nSize;
        // Reallocate the buffer to accommodate pszContents (or
        // the specified size, not including terminating NULL)
		void AllocCopy(const char *pszContents);
	};
	
	// p and q routines (process-local recursive mutexes)
	static void LeaveCriticalSection(const char *pszFile,int nLine);
	static void EnterCriticalSection(const char *pszFile,int nLine);

	static int AtomicIncrement (int &n); // return old value
	static int AtomicDecrement (int &n); // return old value
	
	// Diagnostic output
	static void Trace (const char * pszFormat,...);
	static void Error (const char * pszFormat,...);
	// Find the tail of a filename
	static const char * const Tail (const char * const pszFile);

	// Split a host:port string into its constituent parts.
	// Result indicates success, including whether port is within bounds for a tcp/ip port
	// Caller must deallocate pszHost
	static bool ParseHostPort (const char * const pszHostPort, String &pszHost, int &nPort);
	static bool IsLegalHostPort (const char * const pszHostPort);
	static int m_nCriticalSectionLock;

    static void EnableTracing(bool b) { bVerbose=b; }
    static bool IsTracingEnabled () { return bVerbose; }

    static bool WaitFor (bool &b, int dTimeout);

    // Representation of an absolute time
    typedef int Duration;
    class Time {
    public:
        bool operator< (const Time &o) const { return m_nMSec< o.m_nMSec; }
        bool operator> (const Time &o) const { return m_nMSec> o.m_nMSec; }
        bool operator<=(const Time &o) const { return m_nMSec<=o.m_nMSec; }
        bool operator>=(const Time &o) const { return m_nMSec>=o.m_nMSec; }
        bool operator==(const Time &o) const { return m_nMSec==o.m_nMSec; }
        bool operator!=(const Time &o) const { return m_nMSec!=o.m_nMSec; }
        Duration operator- (const Time &o) {return m_nMSec-o.m_nMSec;}
        static Time Now();
        // Construct from milliseconds value
        Time (int nMSec ) : m_nMSec(nMSec) {}
        Time () : m_nMSec(0) {}
    protected:
        unsigned int m_nMSec;
    };

    static void Sleep (Duration nMsec);

protected:
    static FILE *fTrace;
    static bool bVerbose;
	class GarbageCollector {
	public:
		GarbageCollector();
		~GarbageCollector();
		static GarbageCollector gc;
	};
};

#endif
