/*-
 * Copyright (c) 2000 Qube Software, Ltd.
 * All rights reserved.
 * 
 * 	$Id: utils.h,v 1.6 2000/06/13 14:46:00 nps Exp $
 */

#ifndef __utils_h__
#define __utils_h__

#ifndef UTILS_BEGIN
#define UTILS_BEGIN	namespace Utils {
#define UTILS_END	}
#endif

#include "linkage.h"

#ifdef _MSC_VER
#pragma warning(disable : 4786) // truncated debug info
#endif

UTILS_BEGIN

struct EXPORT_QUTILS Problem
{
    // Constructors
                        Problem(const char* fmt ...);
			Problem(const Problem& p);

    // Destructor
			~Problem() { delete[] msg_; }

    // Accessors
    char*               msg() const { return msg_; }
private:

    char*		msg_;
};


/**
 * Many objects in the Q apis are derived from Object to ensure that
 * the correct version of operator delete is called if an application
 * overrides this operator.
 *
 * This class also provides infrastructure support for
 * reference-counting of objects.
 */
struct EXPORT_QUTILS Object
{
    /**
     * Initialise the object with a zero reference count.
     */
			Object();

    /**
     * Delete the object, reclaiming memory.
     */
    virtual		~Object();

    /**
     * Increment the object's reference count.
     */
    void		incRef();

    /**
     * Decrement the object's reference count, returning the new
     * value. If the count reaches zero, the object is *not*
     * deleted. Deleting objects when their count's reach zero is
     * handled by the Ref template.
     */
    unsigned int	decRef();

    /**
     * Return the current reference count.
     */
    unsigned int	refCount();

    /**
     * Allocate memory.
     */
    void*		operator new(size_t amt);

    /**
     * Free memory.
     */
    void		operator delete(void*);

private:
    unsigned int	count_;
};

/**
 * To facilitate object sharing via reference counts, applications can
 * use the Ref template to hold pointers to objects. This template
 * manages the reference count and automatically deletes the object
 * when the last reference is removed.
 */
template<class T> struct Ref
{
    // Constructors
			Ref() { init(); }
			Ref(const T* t) : p_(t)
			{ if (p_) const_cast<T*>(p_)->incRef(); }
			Ref(const Ref<T>& p) { init(); *this = p; }

    // Destructors
			~Ref() { purge(); }

			operator T*() const { return const_cast<T*>(p_); }
    T*			operator->() const { return const_cast<T*>(p_); }
    T*			operator*() const { return const_cast<T*>(p_); }
    

    Ref<T>&		operator=(const Ref<T>& p)
			{
			    if (p.p_) const_cast<T*>(p.p_)->incRef();
			    purge();
			    p_ = p.p_;
			    return *this;
			}

    bool                valid() const
                        {
                            return p_?true:false;
                        }

private:

    void		init() { p_ = 0; }
    void		purge()
			{
			    if (p_ && !const_cast<T*>(p_)->Object::decRef()) {
				delete const_cast<T*>(p_);
			    }
			    p_ = 0;
			}


    const T*		p_;
};




struct EXPORT_QUTILS UID
{
    // Constructors
                                UID();      // make a unique Id.
                                UID(const UID& ids) { *this = ids; }
                                UID(const char*);
                                UID(unsigned int m,
                                    unsigned int t,
                                    unsigned int ti)
                                {
                                    machineNum_ = m;
                                    timeBits_ = t;
                                    tickBits_ = ti;
                                }
    // Destructor
    virtual                     ~UID(){}

    // Accessors
    unsigned int                machineNum() const { return machineNum_; }
    unsigned int                timeBits() const { return timeBits_; }        
    unsigned int                tickBits() const { return tickBits_; }


    int                         operator==(const UID& ids) const
                                {
                                    return compare(ids) == 0;
                                }    
    int                         operator!=(const UID& ids) const
                                { 
				    return !(*this == ids); }
    int                         operator<=(const UID& ids) const
                                { 
                                    return compare(ids) >= 0;
                                }           
    int                         operator<(const UID& ids) const
                                { 
                                    return compare(ids) > 0;
                                }           
    int                         operator>(const UID& ids) const
                                { 
                                    return compare(ids) < 0;
                                }           
    int                         operator>=(const UID& ids) const
                                { 
                                    return compare(ids) <= 0;
                                }           

    // Features
    UID&                        operator=(const UID& ids);
    int                         compare(const UID& id) const;
    bool                        valid() const;

    // note that the caller must free the buffer from asText()
    char*                       asText() const;

    bool                        isReserved() const;
    void                        nullify();
    static unsigned int         ourMachineNum();

    static const UID&           nullUID();


  protected:

    unsigned int                machineNum_;
    unsigned int                timeBits_;
    unsigned int                tickBits_;

    static unsigned int         ourMachineNum_;
};


UTILS_END


#endif // __utils_h__

// Local Variables:
// mode: c++
// End:
