ultimatepp/uppsrc/TCore/template.h
mdelfede 263ff5f895 changed svn layout
git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-06-07 22:31:27 +00:00

587 lines
18 KiB
C++
Raw Blame History

NAMESPACE_UPP
/* TRC 2/12/2003: obsoleted by Fidler's callback1
template <class OBJECT_, class METHOD_, class A, class T>
struct Callback1MethodActionArg : public Callback1Action<A> {
OBJECT_ *object;
METHOD_ method;
T arg;
void Execute(A a) { (object->*method)(a, arg); }
bool IsEqual(const Callback1Action<A> *other) const {
const Callback1MethodActionArg<OBJECT_, METHOD_, A, T> *q
= dynamic_cast<const Callback1MethodActionArg<OBJECT_, METHOD_, A, T> *>(other);
return q && q->object == object && q->method == method && q->arg == arg;
}
unsigned GetHashValue() const {
return (unsigned)object ^ brutal_cast<unsigned>(method) ^ ::GetHashValue(arg);
}
Callback1MethodActionArg(OBJECT_ *object, METHOD_ method, T arg)
: object(object), method(method), arg(arg) {}
};
template <class Object, class R, class O, class A, class B, class T>
Callback1<A> callback2(Object *object, R (O::*method)(A, B), T arg) {
return Callback1<A>(new Callback1MethodActionArg<Object, R (O::*)(A, B), A, T>
(object, method, arg));
}
template <class Object, class R, class O, class A, class B, class T>
Callback1<A> callback2(const Object *object, R (O::*method)(A, B) const, T arg) {
return Callback1<A>(new Callback1MethodActionArg<Object, R (O::*)(A, B) const, A, T>
(object, method, arg));
}
*/
/*
template <class X, class A, class T>
struct Callback1ActionCallArg : public Callback1Action<A> {
X x;
T arg;
void Execute(A a) { x(a, arg); }
bool IsEqual(const Callback1Action<A> *other) const {
const Callback1ActionCallArg<X, A, T> *q = dynamic_cast<const Callback1ActionCallArg<X, A, T> *>(other);
return q && q->x == x && q->arg == arg;
}
unsigned GetHashValue() const {
return ::GetHashValue(x) ^ ::GetHashValue(arg);
}
Callback1ActionCallArg(X x, T arg) : x(x), arg(arg) {}
};
template <class R, class A, class B, class T>
Callback1<A> callback2(R (*fn)(A, B), T arg) {
return Callback1<A>(new Callback1ActionCallArg<R (*)(A, B), A, T>(fn, arg));
}
*/
//#define THISBACK2(m, a) callback2(this, &CLASSNAME::m, a)
template <class T>
void SerializeRaw(Stream& stream, T& object)
{
stream.SerializeRaw((byte *)&object, sizeof(object));
}
template <class T>
void SerializeEnum(Stream& stream, T& object)
{
int o = object;
stream / o;
object = T(o);
}
template <class T>
static bool SerializeIn(T& object, String data)
{
StringStream stream(data);
stream % object;
return !stream.IsError();
}
template <class T>
static String SerializeOut(const T& object)
{
StringStream stream;
stream % const_cast<T&>(object);
return stream;
}
template <class T>
class PtrValueRep : public RawValueRep<T *>
{
public:
PtrValueRep(T *v) : RawValueRep<T *>(v) {}
virtual bool IsNull() const { return this->v == 0; }
virtual unsigned GetHashValue() const { return (unsigned)this->v; }
virtual bool IsEqual(const Value::Void *p);
virtual String AsString() { return FormatIntHex((int)this->v); }
static const RawValueRep<T *> *Cast(const Value::Void *p)
{ ASSERT(dynamic_cast<const RawValueRep<T *> *>(p)); return (const RawValueRep<T *> *)p; }
};
template <class T>
bool PtrValueRep<T>::IsEqual(const Value::Void *p)
{
const RawValueRep<T *> *cast = dynamic_cast<const RawValueRep<T *> *>(p);
return cast && cast->Get() == this->v;
}
template <class T>
class PtrValue : public Value
{
protected:
typedef PtrValueRep<T> Rep;
public:
PtrValue(T *x) : Value(new Rep(x)) {}
T *Get(const Value& v) { return ::IsNull(v) ? 0 : Rep::Cast(v.GetVoidPtr())->Get(); }
static T *Extract(const Value& v) { return ::IsNull(v) ? 0 : Rep::Cast(v.GetVoidPtr())->Get(); }
};
template <class T>
inline Value PtrToValue(T *p) { return PtrValue<T>(p); }
#ifdef COMPILER_GCC
typedef std::type_info type_info;
#endif
template <class T, class I = int>
class TypeMap : Moveable< TypeMap<T, I> > {
public:
One<T> CreateObject(I id) const;
I QueryObject(const T *object) const;
One<T> Copy(const One<T>& object) const;
void Serialize(Stream& stream, One<T>& object) const;
void Serialize(Stream& stream, Array<T>& array) const;
// template<> friend Stream& operator % (Stream& stream, One<T>& object) { TypeMap<T, I>::Serialize(stream, object); return stream; }
One<T> SerializeIn(const String& string) const;
String SerializeOut(const One<T>& object) const;
typedef One<T> (*NewFunc)();
void Register(NewFunc fn, const type_info *ti, I id);
template <class ST>
struct NewType {
static One<T> New() { return new ST; }
};
template <class ST>
void RegisterType(I id) { Register(&NewType<ST>::New, &typeid(ST), id); }
public:
Index<I> id_index;
Vector< One<T> (*)()> factories;
Index<const type_info *, PtrHash> type_index;
// static Index<I>& GetIDIndex() { static Index<I> index; return index; }
// static Vector<One<T> (*)()>& GetFactories() { static Vector<One<T> (*)()> factories; return factories; }
// static Index<const type_info *, PtrHash>& GetTypeIndex() { static Index<const type_info *, PtrHash> index; return index; }
};
template <class T, class I>
One<T> TypeMap<T, I>::CreateObject(I id) const
{
if(IsNull(id))
return 0;
int f = id_index.Find(id);
if(f < 0)
return 0;
return factories[f]();
}
template <class T, class I>
I TypeMap<T, I>::QueryObject(const T *object) const
{
if(!object)
return Null;
int i = type_index.Find(&typeid(*object));
return i >= 0 ? id_index[i] : I(Null);
}
template <class T, class I>
One<T> TypeMap<T, I>::Copy(const One<T>& object) const
{
if(!object)
return NULL;
return this->SerializeIn(SerializeOut(object));
}
template <class T, class I>
One<T> TypeMap<T, I>::SerializeIn(const String& string) const
{
One<T> object;
StringStream strm(string);
Serialize(strm, object);
return object;
}
template <class T, class I>
String TypeMap<T, I>::SerializeOut(const One<T>& object) const
{
StringStream ss;
Serialize(ss, const_cast<One<T>&>(object));
return ss;
}
template <class T, class I>
void TypeMap<T, I>::Serialize(Stream& stream, One<T>& object) const
{
I ID;
if(stream.IsStoring())
ID = QueryObject(~object);
stream / ID;
if(stream.IsLoading()) {
object = CreateObject(ID);
if(object)
stream % *object;
else if(!IsNull(ID))
stream.SetError();
}
else if(object)
stream % *object;
}
template <class T, class I>
void TypeMap<T, I>::Serialize(Stream& stream, Array<T>& array) const
{
int c = array.GetCount();
stream % c;
if(stream.IsStoring()) {
for(int i = 0; i < c; i++) {
I ID = QueryObject(&array[i]);
stream / ID;
stream % array[i];
}
}
else {
array.SetCount(c);
for(int i = 0; i < c; i++) {
I ID;
stream / ID;
One<T> object = CreateObject(ID);
if(object) {
array.Add(-object);
stream % array.Top();
}
else {
stream.SetError();
return;
}
}
}
}
template <class T, class I>
void TypeMap<T, I>::Register(NewFunc fn, const type_info *ti, I id)
{
int tx = type_index.Find(ti);
if(tx >= 0)
ASSERT((id_index[tx] == id));
else {
ASSERT((id_index.Find(id) < 0));
type_index.Add(ti);
id_index.Add(id);
factories.Add() = fn;
}
}
template <class T>
void StreamOne(Stream& stream, One<T>& one)
{
bool full = one;
stream % full;
if(stream.IsLoading())
if(full)
one = new T;
else
one = NULL;
if(one)
stream % *one;
}
template <class T>
One<T> StreamCopyOne(const One<T>& one)
{
if(!one)
return NULL;
String aux = SerializeOut(*one);
One<T> out = new T;
SerializeIn(*out, aux);
return out;
}
template <class B>
struct NewableType {
typedef B *(*Factory)();
typedef VectorMap<const type_info *, Factory, PtrHash> FactoryMap;
static FactoryMap& Factories();
static B *New(const type_info& t); // throws on failure
static B *NewNull(const type_info& t); // may return 0
static Factory GetFactory(const type_info& t);
};
template <class B>
typename NewableType<B>::FactoryMap& NewableType<B>::Factories()
{
static FactoryMap *pmap = 0;
if(!pmap) // a nasty trick patching multiple construction compiler error
{
static FactoryMap map;
pmap = &map;
}
return *pmap;
}
template <class B>
B *NewableType<B>::New(const type_info& t)
{
B *ptr = NewNull(t);
if(ptr == NULL)
throw Exc(NFormat("Objekt '%s' nen<65> registrov<6F>n.", t.name()));
return ptr;
}
template <class B>
B *NewableType<B>::NewNull(const type_info& t)
{
Factory factory = GetFactory(t);
return factory ? factory() : 0;
}
template <class B>
typename NewableType<B>::Factory NewableType<B>::GetFactory(const type_info& t)
{
return Factories().Get(&t, 0);
}
template <class B, class C>
struct RegisterNewableType : NewableType<B>
{
RegisterNewableType() { typename NewableType<B>::Factory f = CreateObject; this->Factories().FindAdd(&typeid(C), f); }
private:
static B *CreateObject() { return new C; }
};
//////////////////////////////////////////////////////////////////////
// RefMemStat: refcounted object memory statistics.
#ifdef flagREFDEBUG
#define REF_DEBUG
#endif//flagREFDEBUG
class RefMemStat
{
public:
RefMemStat() {}
RefMemStat(const RefMemStat& rms, int deep) : alloc_map(rms.alloc_map, 0) {}
static RefMemStat& App();
void Add(const String& name, int allocindex);
void Remove(const String& name, int allocindex);
String Format(bool index = false) const;
String FormatDelta(const RefMemStat& old, bool index = false) const;
private:
VectorMap<String, Index<int> > alloc_map;
};
template class DeepCopyOption<RefMemStat>;
//////////////////////////////////////////////////////////////////////
// RefBase: base for refcounted objects.
/* TRC 2/12/2003: moved to Web/util
template <class T>
inline Value RefConToValue(RefCon<T> p) { return StrongValue< RefCon<T> >(p); }
template <class T>
inline Value RefPtrToValue(RefPtr<T> p) { return StrongValue< RefPtr<T> >(p); }
*/
class WeakBase : public Link<WeakBase>
{
public:
virtual ~WeakBase() { DbgChk(); }
virtual void Clear() = 0;
#ifdef _DEBUG
void DbgChk() const { Chk(); }
#else
void DbgChk() const {}
#endif
void Chk() const;
};
template <class T>
class UPP::RefCon;
template <class T>
class UPP::RefPtr;
class WeakRef;
template <class T>
class WeakCon : public WeakBase
{
friend class WeakRef;
friend class UPP::RefCon<T>;
public:
WeakCon() : ptr(0) {}
WeakCon(const WeakCon<T>& p) { p.Chk(); if(ptr = p.ptr) LinkAfter(ptr); Chk(); }
WeakCon(const T *p) { if(ptr = const_cast<T *>(p)) LinkAfter(ptr); Chk(); }
WeakCon(const RefCon<T>& p) { if(ptr = const_cast<T *>(~p)) LinkAfter(ptr); Chk(); }
~WeakCon() { Chk(); }
operator RefCon<T> () const { return RefCon<T>(ptr); }
WeakCon<T>& operator = (const T *p) { Chk(); Unlink(); if(ptr = const_cast<T *>(p)) LinkAfter(ptr); Chk(); return *this; }
WeakCon<T>& operator = (const WeakCon<T>& p) { Chk(); Unlink(); if(ptr = p.ptr) LinkAfter(ptr); Chk(); return *this; }
WeakCon<T>& operator = (const RefCon<T>& p) { Chk(); Unlink(); if(ptr = p.ptr) LinkAfter(ptr); Chk(); return *this; }
virtual void Clear() { Chk(); Unlink(); ptr = 0; }
bool IsEmpty() const { return ptr == NULL; }
bool operator ! () const { return IsEmpty(); }
const T *operator ~ () const { return ptr; }
const T& operator * () const { ASSERT(ptr); return *ptr; }
const T *operator -> () const { ASSERT(ptr); return ptr; }
friend bool operator == (const WeakCon<T>& a, const WeakCon<T>& b) { return a.ptr == b.ptr; }
friend bool operator != (const WeakCon<T>& a, const WeakCon<T>& b) { return a.ptr != b.ptr; }
friend unsigned GetHashValue(const WeakCon<T>& a) { return UPP::GetHashValue(a.ptr); }
protected:
T *ptr;
};
template <class T>
class WeakPtr : public WeakCon<T>
{
public:
WeakPtr() {}
WeakPtr(const WeakPtr<T>& p) : WeakCon<T>(p) {}
WeakPtr(T *p) : WeakCon<T>(p) {}
WeakPtr(const RefPtr<T>& p) : WeakCon<T>(p) {}
operator RefPtr<T> () const { return RefPtr<T>(const_cast<T *>(this->ptr)); }
WeakPtr<T>& operator = (T *p) { this->Chk(); this->Unlink(); if(this->ptr = p) LinkAfter(this->ptr); this->Chk(); return *this; }
WeakPtr<T>& operator = (const WeakPtr<T>& p) { this->Chk(); this->Unlink(); if(this->ptr = p.ptr) LinkAfter(this->ptr); this->Chk(); return *this; }
WeakPtr<T>& operator = (const RefPtr<T>& p) { this->Chk(); this->Unlink(); if(this->ptr = ~p) LinkAfter(this->ptr); this->Chk(); return *this; }
T *operator ~ () const { return const_cast<T *>(this->ptr); }
T& operator * () const { ASSERT(this->ptr); return *const_cast<T *>(this->ptr); }
T *operator -> () const { ASSERT(this->ptr); return const_cast<T *>(this->ptr); }
};
class WeakRef : public Link<WeakBase>
{
public:
WeakRef() : refcount(0) {}
virtual ~WeakRef() { ASSERT(refcount == 0); while(GetNext() != GetPtr()) GetNext()->Clear(); }
int GetRefCount() const { return AtomicXAdd(refcount, 0); }
void AddRef() const { if(this) AtomicInc(refcount); }
void Release() const { if(this && !AtomicDec(refcount)) delete this; }
private:
mutable Atomic refcount;
};
template <class T>
class VirtualArrayData : public RefBase
{
public:
virtual ~VirtualArrayData() {}
virtual void SetCount(int count) = 0;
virtual void SetCountR(int count) = 0;
virtual int GetCount() const = 0;
virtual void Set(int i, T t) = 0;
virtual T Get(int i) const = 0;
};
template <class T>
class VirtualArray : Moveable< VirtualArray<T> >
{
public:
VirtualArray() {}
VirtualArray(VirtualArrayData<T> *data) : data(data) {}
bool IsNullInstance() const { return !data; }
void SetCount(int count) { data->SetCount(count); }
void SetCountR(int count) { data->SetCountR(count); }
int GetCount() const { return data->GetCount(); }
void Set(int i, T t) { data->Set(i, t); }
T Get(int i) const { return data->Get(i); }
T operator [] (int i) const { ASSERT(i >= 0 && i < GetCount()); return Get(i); }
void Add(T t) { int c = GetCount(); SetCountR(c + 1); Set(c, t); }
void Clear() { data->SetCount(0); }
bool IsEmpty() const { return data->GetCount() == 0; }
typedef T ValueType;
class ConstIterator
{
protected:
const VirtualArray<T> *cont;
int ii;
public:
T operator*() const { return (*cont)[ii]; }
T operator[](int i) const { return (*cont)[ii + i]; }
ConstIterator& operator++() { ++ii; return *this; }
ConstIterator& operator--() { --ii; return *this; }
ConstIterator operator++(int) { ConstIterator t = *this; ++ii; return t; }
ConstIterator operator--(int) { ConstIterator t = *this; --ii; return t; }
ConstIterator& operator+=(int d) { ii += d; return *this; }
ConstIterator& operator-=(int d) { ii -= d; return *this; }
ConstIterator operator+(int d) const { return ConstIterator(cont, ii + d); }
ConstIterator operator-(int d) const { return ConstIterator(cont, ii - d); }
int operator-(const ConstIterator& b) const { return ii - b.ii; }
bool operator==(const ConstIterator& b) const { return ii == b.ii; }
bool operator!=(const ConstIterator& b) const { return ii != b.ii; }
bool operator<(const ConstIterator& b) const { return ii < b.ii; }
bool operator>(const ConstIterator& b) const { return ii > b.ii; }
bool operator<=(const ConstIterator& b) const { return ii <= b.ii; }
bool operator>=(const ConstIterator& b) const { return ii >= b.ii; }
// operator bool() const { return ii < 0; }
ConstIterator() { cont = NULL; ii = -1; }
ConstIterator(const VirtualArray<T> *_cont, int ii) : cont(_cont), ii(ii) {}
};
ConstIterator Begin() const { return ConstIterator(this, 0); }
ConstIterator End() const { return ConstIterator(this, GetCount()); }
ConstIterator GetIter(int i) const { ASSERT(i >= 0 && i <= GetCount()); return ConstIterator(this, i); }
private:
RefPtr< VirtualArrayData<T> > data;
};
template <class VT, class ST, int SN = 1024>
class VirtualSegtorArray : public VirtualArrayData<VT>
{
public:
virtual void SetCount(int count) { container.SetCount(count); }
virtual void SetCountR(int count) { container.SetCount(count); } //!! Fidler: co takhle Segtor::SetCountR?
virtual int GetCount() const { return container.GetCount(); }
protected:
Segtor<ST, SN> container;
};
template <class VT, class ST, int SN = 1024>
class VirtualStdSegtorArray : public VirtualSegtorArray<VT, ST, SN>
{
public:
virtual void Set(int i, VT t) { this->container[i] = t; }
virtual VT Get(int i) const { return this->container[i]; }
};
template <class T>
class VirtualValueArray : public VirtualStdSegtorArray<Value, T>
{
};
END_UPP_NAMESPACE