#ifndef _Gen_Gen_h #define _Gen_Gen_h #include NAMESPACE_UPP //copyable interface, implementing the Copy function, used i.e. by PolyDeepCopyNew template class Copyable : public B { public: virtual ~Copyable() {} virtual T* Copy() const { return PartialCopy(); } virtual T* PartialCopy() const = 0; }; //when exporting an iterface at base lavel which is implemented/derived at top template class TypeHook : public B { public: virtual ~TypeHook() {} virtual const T& GetT() const = 0; virtual T& GetT() = 0; operator const T&() const { return GetT(); } operator T&() { return GetT(); } }; //copyable interface defining the common base class C, without implementing Copy //makes possible to clone things and accessing some defined interface template class PolyCopyableHook : public PolyDeepCopyNew, TypeHook, B> > > { }; // implements the base class accessors. //B is the derived type, i.e. EditInt, C is common base class, i.e. Ctrl //forward another baseclass CB to extend CopyableC interface template class PolyElement : public PolyDeepCopyNew, public PolyCopyableHook { public: virtual const C& GetT() const { return *this; } virtual C& GetT() { return *this; } }; //by providing additional information about the common base class //with template specialization can be defined what is copied template class PolyElementWrap : public PolyElement,B,C,CB> { public: virtual PolyElementWrap* PartialCopy() const { return new PolyElementWrap(); } }; //declares a class Serializable for Stream //maybe redundant because of global template for operator%(Stream& s, T& t) //which calls t.Serialize() //but to ensure implementation template class Serializeable : public B { public: virtual void Serialize(Stream& s) = 0; }; //maybe this should go to Stream.h template void SerializeStore(Stream& s, const T& x) { ASSERT(s.IsStoring()); s % const_cast(x); } //declares a class Xmlizeable //maybe redundant because of global template Xmlize(XmlIO& xml, T&t) //which calls t.Xmlize() //but to ensure implementations template class Xmlizeable : public B { public: virtual void Xmlize(XmlIO& xml) = 0; }; //most times it is a good idea to implement both template class Persistable : public Xmlizeable > {}; //a helper when using a class with XmlParser for DOM/SAX parsing template class XmlParseable : public B { public: virtual String ToXML() = 0; virtual void LoadXML(XmlParser& p) = 0; }; typedef void*(*GlobalInstancerType)(); typedef VectorMap GlobalInstancerMapType; GlobalInstancerMapType& GetGlobalInstancerMap(); //Instancer help class, for maps of Instancers. the static Map should //somewhere be ONCELOCK initialized with the elements //B is the common base class, T should be the derived class, to ensure //proper pointer arithmetic template class Instancer { public: typedef B*(*Type)(); typedef VectorMap MapType; template class Typed { public: static B* GetInstance() { return new T(); } static Type GetInstancer() { return &GetInstance; } static GlobalInstancerType GetGlobalInstancer() { return (GlobalInstancerType)&GetInstance; } }; static B* GetInstance() { return Typed::GetInstance(); } static MapType& Map() { static MapType _; return _; } }; template inline String TypeOfS(T* = 0) { return String(typeid(T).name()); } template inline String TypeOf(T* t = 0) { return TypeOfS(t); } //in polymorph environment, type info is needed, i.e. when xmlizing/serializing elements //to know later which one to instantiate..best used with Instancer class Typer { friend class TyperRegistrar; public: String TypeOf() const { ASSERT(tf); return (*tf)(); } //no virtual, dont permit override Typer() : tf(NULL) {} private: String (*tf)(); }; class TyperRegistrar { public: static void RegisterType(Typer& t, String (*tf)()) { t.tf = tf; } }; template class TyperT : public B, public TyperRegistrar { public: TyperT() { TyperRegistrar::RegisterType((T&)(*this), &Invoke); } protected: static inline String Invoke() { return TypeOfS((T*)NULL); } }; //to declare a class beeing partaker in Instanciating. //T is the interface / class that should be acessible at base template class Instance : public TypeHook {}; template class Shared : Moveable< Shared > { mutable T *ptr; Atomic *rfc; void Retain() const { ASSERT(rfc); AtomicInc(*rfc); } void Release() { ASSERT(rfc); if(AtomicDec(*rfc) == 0) { Free(); delete rfc; rfc = NULL; } } void Free() { if(ptr && ptr != (T*)1) delete ptr; } void Chk() const { ASSERT(ptr != (T*)1); } void ChkP() const { Chk(); ASSERT(ptr); } public: void Attach(T *data) { Free(); ptr = data; } T *Detach() pick_ { ChkP(); T *t = ptr; ptr = NULL; return t; } T *operator-() pick_ { return Detach(); } void Clear() { Free(); ptr = NULL; } void operator=(T *data) { Attach(data); } void operator=(const Shared& d){ Release(); ptr = d.ptr; rfc = d.rfc; Retain(); } void operator=(pick_ One& d) { Attach(d.Detach()); } const T *operator->() const { ChkP(); return ptr; } T *operator->() { ChkP(); return ptr; } const T *operator~() const { Chk(); return ptr; } T *operator~() { Chk(); return ptr; } const T& operator*() const { ChkP(); return *ptr; } T& operator*() { ChkP(); return *ptr; } template TT& Create() { TT *q = new TT; Attach(q); return *q; } T& Create() { T *q = new T; Attach(q); return *q; } bool IsEmpty() const { Chk(); return !ptr; } operator bool() const { return ptr; } Shared() { ptr = NULL; rfc = new Atomic(1); } Shared(T *newt) { ptr = newt; rfc = new Atomic(1); } Shared(const Shared& p) { ptr = p.ptr; rfc = p.rfc; Retain(); } ~Shared() { Release(); } Shared(pick_ One& p) { ptr = p.Detach(); rfc = new Atomic(1); } Shared(const One& p, int) { ptr = DeepCopyNew(*p); rfc = new Atomic(1); } template friend class GenerateShared; private: Shared(T* p, Atomic* r) { ptr = p; rfc = r; Retain(); } }; template class GenerateShared //can access the internals of any Shared { public: template static Shared FromShared(const Shared& p) { return Shared((T*)p.ptr, p.rfc); } }; template class Scaler { public: Scaler() : mn(0), mx(0) {} Scaler(const T& mn, const T& mx) : mn(mn), mx(mx) {} inline void Min(const T& t) { mn = t; } inline T Min() const { return mn; } inline void Max(const T& t) { mx = t; } inline T Max() const { return mx; } inline void MinMax(const T& _mn, const T& _mx) { mn = _mn; mx = _mx; } //scales local dimension value t to foreign dimensions d //returned in foreign dimension inline T To(const Scaler& d, const T& t) { return (t-mn)*(d.mx-d.mn)/(mx-mn)+d.mn; } //scales foreign dimension value t from foreign s to local dimension //return in local dimension inline T From(const Scaler& s, const T& t) { return (t-s.mn)*(mx-mn)/(s.mx-s.mn)+mn; } inline T operator() (const Scaler& s, const T& t) { return From(s, t); } protected: T mn, mx; }; //some Link helpers //returns count of linked elements //not counting the reported l element, which most times is LinkOwner anyway. template int GetLinkCount(const T& l, bool f = true) { int c = 0; const T *list = l.GetPtr(), *e = list; if(f) while((e = e->GetNext()) != list) ++c; else while((e = e->GetPrev()) != list) ++c; return c; } template inline void ChkLinkCount(const T& l) { ASSERT(GetLinkCount(l, true) == GetLinkCount(l, false)); } template inline void ChkLink(const T& l, bool f = true) { if(f) ASSERT(l.GetNext()->GetPrev() == l.GetPtr()); else ASSERT(l.GetPrev()->GetNext() == l.GetPtr()); } template int ChkLinkDeep(const T& l, bool f = true) { int c = 0; const T *list = l.GetPtr(), *e = list; do { ChkLink(*e, f); ++c; } while((e = e->GetNext()) != list); return --c; } END_UPP_NAMESPACE #endif