//------------------------------------------------------------------------------88
// ObjectWindows
// Copyright (c) 1998 by Yura Bidus
//
/// \file
/// Definition of container classes used and made available by OWL
//------------------------------------------------------------------------------
 
#if !defined(OWL_TEMPLATE_H)
#define OWL_TEMPLATE_H
 
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
 
#include <owl/defs.h>
#include <owl/private/wsysinc.h>
#include <new>
#include <algorithm>
 
namespace owl {
 
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
 
/// \addtogroup utility_group
/// @{
 
//-------------------------------------------------------------------------
/// \class TStandardAllocator
// ~~~~~ ~~~~~~~~~~~~~~~~~~
/// Provides class-specific operator new and operator delete that simply call
/// the global operator new and operator delete.  That is, TStandardAllocator
/// does not provide any specialized behavior. It is used in the non-managed
/// versions of the parametrized containers.
//
class TStandardAllocator {
  public:
    void  operator delete(void *ptr);
    void * operator new(size_t sz);
 
    void * Alloc(size_t sz);
    void   Free(void *ptr);
    void * ReAlloc(void *ptr, size_t sz);
 
};
 
typedef TStandardAllocator TSharedAllocator;
 
/// @}
 
//
// inlines
//
inline void  TStandardAllocator::operator delete(void *ptr){
  ::operator delete(ptr);
}
inline void * TStandardAllocator::operator new(size_t sz){
  return ::operator new(sz);
}
 
inline void * TStandardAllocator::Alloc(size_t sz){
  return ::malloc(sz);
}
inline void  TStandardAllocator::Free(void *ptr){
  ::free(ptr);
}
inline void * TStandardAllocator::ReAlloc(void *ptr, size_t sz){
  return ::realloc(ptr,sz);
}
 
 
 
 
/// \addtogroup utility_group
/// @{
 
//----------------------------------------------------------------------------
/// \class TLocalAllocator
// ~~~~~ ~~~~~~~~~~~~~~~~
/// Provides class-specific operator new and operator delete that allocate from
/// local memory.
//
class TLocalAllocator {
  public:
    void * operator new(size_t sz);
    void operator delete(void* ptr);
 
    void *   Alloc(size_t sz);
    void   Free(void *ptr);
    void *   ReAlloc(void *ptr, size_t sz);
};
 
/// @}
 
//----------------------------------------------------------------------------
// TLocalAllocator::operator new
// TLocalAllocator::operator delete
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Uses LocalAlloc.
 
inline void * TLocalAllocator::operator new(size_t sz){
  return (void*)::LocalAlloc(LPTR, sz);
}
inline void TLocalAllocator::operator delete(void * ptr){
  ::LocalFree((HLOCAL)ptr);
}
inline void * TLocalAllocator::Alloc(size_t sz){
  return (void*)::LocalAlloc(LPTR, sz);
}
inline void  TLocalAllocator::Free(void *ptr){
  ::LocalFree((HLOCAL)ptr);
}
inline void * TLocalAllocator::ReAlloc(void *ptr, size_t sz){
  return (void*)::LocalReAlloc((HLOCAL)ptr,sz,LPTR);
}
 
/// \addtogroup utility_group
/// @{
 
//----------------------------------------------------------------------------
/// \class TGlobalAllocator
// ~~~~~ ~~~~~~~~~~~~~~~~
/// Provides class-specific operator new and operator delete that allocate from
/// global memory.
//
class TGlobalAllocator {
  public:
    void * operator new(size_t sz);
    void operator delete(void* ptr);
 
    void *   Alloc(size_t sz);
    void   Free(void *ptr);
    void *   ReAlloc(void *ptr, size_t sz);
};
 
/// @}
 
//----------------------------------------------------------------------------
// TGlobalAllocator::operator new
// TGlobalAllocator::operator delete
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Uses GlobalAlloc.
 
inline void * TGlobalAllocator::operator new(size_t sz){
  return (void*)::GlobalLock(::GlobalAlloc(GPTR, sz));
}
inline void TGlobalAllocator::operator delete(void * ptr){
  HGLOBAL hMem = (HGLOBAL)GlobalHandle(ptr);
  if (GlobalUnlock(hMem) == 0)
    GlobalFree(hMem);
}
inline void * TGlobalAllocator::Alloc(size_t sz){
  return (void*)::GlobalLock(::GlobalAlloc(GPTR, sz));
}
inline void  TGlobalAllocator::Free(void *ptr){
  HGLOBAL hMem = (HGLOBAL)GlobalHandle(ptr);
  if (GlobalUnlock(hMem) == 0)
    GlobalFree(hMem);
}
inline void * TGlobalAllocator::ReAlloc(void *ptr, size_t sz){
  HGLOBAL hMem = (HGLOBAL)GlobalHandle(ptr);
  if(hMem && GlobalUnlock(hMem) == 0)
    return (void*)::GlobalLock(GlobalReAlloc(hMem, sz, GPTR));
  return 0;
}
 
//--------------------------------------------------------
// class TOleAllocator
// ~~~~~ ~~~~~~~~~~~~~
//
/*
class TOleAllocator {
  public:
    TOleAllocator();  // Gets allocator, does not initialize OLE
   ~TOleAllocator();
    void*  Alloc(unsigned long size);
    void          Free(void * pv);
    void * Realloc(void *ptr, size_t sz);
    IMalloc*  Mem;
};
*/
//
 
/// \addtogroup utility_group
/// @{
 
 
//==========================================================================
// Memory Manager
// ~~~~~~ ~~~~~~~
//--------------------------------------------------------------------------
/// \class TMBlockList
///  template \<class Alloc\> class TMBlockList
///  Used internally.
template <class A> class TMBaseMemBlocks;
 
template <class A> class TMBlockList {
  public:
    TMBlockList( TMBlockList * );
    ~TMBlockList(){}
 
  private:
    void *operator new( size_t, size_t, const A& );
    void operator delete( void * );
    void operator delete(void *p, size_t, const A& );
 
    TMBlockList*  Next;
    friend class TMBaseMemBlocks<A>;
};
 
/// @}
 
 
template <class A> inline
TMBlockList<A>::TMBlockList(TMBlockList<A>* next) : Next(next)
{
}
template <class A> inline void*
TMBlockList<A>::operator new (size_t sz, size_t extra, const A&)
{
  return A::operator new(sz + extra);
}
template <class A> inline void
TMBlockList<A>::operator delete ( void *ptr )
{
  A::operator delete (ptr);
}
template <class A> inline void
TMBlockList<A>::operator delete(void *p, size_t, const A& )
{
  A::operator delete (p);
}
 
/// \addtogroup utility_group
/// @{
 
 
//--------------------------------------------------------------------------
/// \class TBlockList
//  ~~~~~ ~~~~~~~~~~
///  Used internally.
//
class TBlockList : public TMBlockList<TStandardAllocator> {
  public:
    TBlockList( TBlockList *blk) : TMBlockList<TStandardAllocator>(blk){}
};
//--------------------------------------------------------------------------
/// \class TMBaseMemBlocks
///  template \<class A\> class TMBaseMemBlocks
///  Used internally.
template <class A> class TMBaseMemBlocks
/// \cond
 :  public A
/// \endcond
{
  public:
    TMBaseMemBlocks( size_t = 8192 );
    ~TMBaseMemBlocks();
 
    char*     Block() const { return REINTERPRET_CAST(char*, CurBlock); }
    unsigned  Count() const { return BlockCount; }
    int       AllocBlock( size_t );
    void      FreeTo( unsigned );
    size_t    GetBlockSize() const { return BlockSize; }
 
  private:
    TMBlockList<A>* CurBlock;
    const size_t    BlockSize;
    unsigned        BlockCount;
};
 
/// @}
 
 
template <class A> inline
TMBaseMemBlocks<A>::TMBaseMemBlocks( size_t sz )
: CurBlock(0), BlockSize(sz), BlockCount(0)
{
  CHECK( sz != 0 );
}
template <class A> inline
TMBaseMemBlocks<A>::~TMBaseMemBlocks()
{
#if !defined( BI_WINDOWS_WEP_BUG )
  FreeTo( 0 );
#endif
}
template <class A> int
TMBaseMemBlocks<A>::AllocBlock( size_t sz )
{
  TMBlockList<A>* temp = new( std::max(sz,BlockSize), *this ) TMBlockList<A>( CurBlock );
  CurBlock = temp+1;
  BlockCount++;
  return 1;
}
 
template <class A> void
TMBaseMemBlocks<A>::FreeTo( unsigned term )
{
  PRECONDITION( BlockCount >= term );
  while( BlockCount > term ){
    TMBlockList<A> *temp = CurBlock-1;
    CurBlock = temp->Next;
 
    delete temp;
    BlockCount--;
  }
}
 
/// \addtogroup utility_group
/// @{
 
 
//--------------------------------------------------------------------------
///  \class TBaseMemBlocks
///  Used internally.
class TBaseMemBlocks : public TMBaseMemBlocks<TStandardAllocator> {
  public:
    TBaseMemBlocks( size_t sz = 8192 ) :
        TMBaseMemBlocks<TStandardAllocator>(sz) {}
};
//--------------------------------------------------------------------------
/// \class TMMemStack
///  template \<class A\> class TMMemStack
//
///  Managed memory stack.  Implements mark and release style memory
///  management, using the allocator A.
template <class A> class TMMarker;
 
template <class A> class TMMemStack{
  public:
    friend class TMMarker<A>;
 
    TMMemStack( size_t = 8192 );
    void* Allocate( size_t );
 
  private:
    TMBaseMemBlocks<A> Data;
    size_t CurLoc;
};
 
/// @}
 
template <class A> inline TMMemStack<A>::TMMemStack( size_t sz )
: Data( sz ),CurLoc(sz)
{
  CHECK( sz != 0 );
}
 
template <class A> void* TMMemStack<A>::Allocate( size_t sz )
{
  sz = std::max( (size_t)1, sz );
  if( sz > Data.GetBlockSize() - CurLoc )
  {
    if( Data.AllocBlock( sz ) == 0 )
      return 0;
    else
      CurLoc = 0;
  }
  void* temp = Data.Block() + CurLoc;
  CurLoc += sz;
  return temp;
}
 
/// \addtogroup utility_group
/// @{
 
//--------------------------------------------------------------------------
/// \class TMMarker
///  template \<class A\> class TMMarker
///  Provides the mark for TMMemStack.
template <class A> class TMMarker{
  public:
    TMMarker(TMMemStack<A>& ms):
        Memstk(ms),Blk(ms.Data.Count()),CurLoc(ms.CurLoc)
      {}
 
    ~TMMarker()
      {
        const auto ok = Blk < Memstk.Data.Count() || (Blk == Memstk.Data.Count() && CurLoc <= Memstk.CurLoc);
        WARN(!ok, _T("TMMarker::~TMMarker: Terminating due to failed precondition."));
        if (!ok) std::terminate();
 
        Memstk.Data.FreeTo( Blk );
        Memstk.CurLoc = CurLoc;
      }
  private:
    TMMemStack<A>&  Memstk;
    const unsigned  Blk;
    const size_t    CurLoc;
};
 
//--------------------------------------------------------------------------
///  \class TMemStack
//  ~~~~~ ~~~~~~~~~
///  Implements mark and release style memory management using the
///  standard allocator.
class TMemStack : public TMMemStack<TStandardAllocator> {
  public:
    TMemStack( size_t sz = 8192 ) : TMMemStack<TStandardAllocator>(sz) {}
};
 
//--------------------------------------------------------------------------
/// \class TMarker
///  template \<class A\> class TMarker
///  Provides the mark for TMemStack.
class TMarker : public TMMarker<TStandardAllocator>{
  public:
    TMarker( TMMemStack<TStandardAllocator>& ms ):
        TMMarker<TStandardAllocator>(ms) {}
};
 
//--------------------------------------------------------------------------
///  \class TMMemBlocks
///  template \<class A\> class TMMemBlocks
//  ~~~~~~~~ ~~~~~~~~~ ~~~~~ ~~~~~~~~~~~
///  Managed single-size block allocator.  Allocates blocks
///  of the size specified in the constructor, using the memory
///  manager specified by A.
template <class A> class TMMemBlocks{
  public:
    TMMemBlocks( size_t sz, unsigned int count = 100 );
    void* Allocate( size_t sz);
    void  Free( void * block);
 
  private:
    void*         FreeList;
    TMMemStack<A> Mem;
    size_t        Size;
};
 
/// @}
 
template <class A> inline
TMMemBlocks<A>::TMMemBlocks( size_t sz, unsigned int count )
: FreeList(0), Mem( sz*count ), Size( std::max(sz,sizeof(void*)))
{
  CHECK( sz != 0 && count != 0 );
}
 
template <class A> inline void*
#if (__DEBUG > 0)
TMMemBlocks<A>::Allocate( size_t sz )
#else
TMMemBlocks<A>::Allocate( size_t )
#endif
{
  PRECONDITION( Size == std::max(sz,sizeof(void *)) );
  if( FreeList == 0 )
    return Mem.Allocate( Size );
  else{
    void *temp = FreeList;
    FreeList = *(void**)temp;
    return temp;
  }
}
 
template <class A> inline void
TMMemBlocks<A>::Free( void* block )
{
    *(void **)block = FreeList;
    FreeList = block;
}
 
/// \addtogroup utility_group
/// @{
 
//--------------------------------------------------------------------------
///  \class TMemBlocks
//
///  Single-size block allocator.  Allocates blocks of the size
///  specified in the constructor, using the global operator new
///  and operator delete.
class TMemBlocks : public TMMemBlocks<TStandardAllocator>{
  public:
    TMemBlocks( size_t sz, unsigned n = 100 ) :
        TMMemBlocks<TStandardAllocator>( sz, n ) {}
 
};
 
/// @}
 
typedef TMMemBlocks<TStandardAllocator> TStandardBlocks;
 
// support template functions
template <class T> inline T* __owl_construct(void* P)
{
  return new(P)T;
}
template <class T> inline T* __owl_construct(void* P, const T& t)
{
  return new(P)T(t);
}
template <class T> inline void __owl_destruct(T* t)
{
  static_cast<void>(t); // Suppress "not in use" warning.
  t->~T();
}
// specializations
// chars
inline char* __owl_construct(void* p, char c)                { *((char*)p) = c; return (char*)p;}
inline void __owl_destruct(char* /*t*/){}
// integers
inline int* __owl_construct(void* p, int c)                  { *((int*)p) = c; return (int*)p;}
inline unsigned int* __owl_construct(void* p, unsigned int c){  *((unsigned int*)p) = c; return (unsigned int*)p;}
inline void __owl_destruct(int* /*t*/){}
// long
inline long* __owl_construct(void* p, long c)                 { *((long*)p) = c; return (long*)p;}
inline void __owl_destruct(long* /*t*/){}
 
/// \addtogroup utility_group
/// @{
 
//--------------------------------------------------------------------------
// Container classes
//
 
/////////////
//
/// class Iterator for TObjectContainer
//
template<class T, class T1> class TObjArrayIterator{
  public:
    TObjArrayIterator(T1& array):Vect(array),Cur(0){}
    operator bool() const         { return Cur < (int)Vect.Size();  }
    const T& operator ++(int)     { Cur++; return *Vect.Data[Cur-1];}
    const T* operator ++()        { return Cur<(int)Vect.Size()?Vect.Data[++Cur]:0; }   //??????????????
    const T& operator *() const   { return *Vect.Data[Cur];         }
    T& operator *()               { return *Vect.Data[Cur];         }
    const T& Current() const      { return *Vect.Data[Cur];         }
    T& Current()                  { return *Vect.Data[Cur];         }
    void  Restart()               { Cur = 0;                        }
 
  protected:
    T1&   Vect;
    int   Cur;
};
 
//
/// Iterator for Pointer Container
//
template<class T, class T1> class TPtrArrayIterator{
  public:
    TPtrArrayIterator(T1& array):Vect(array),Cur(0){}
    operator bool() const        { return Cur < (int)Vect.Size();       }
          T  operator ++(int)    { Cur++; return Vect.Data[Cur-1];      }
    const T* operator ++()       { return Cur<(int)Vect.Size()?&Vect.Data[++Cur]:0;} //?????????????
    const T  operator *() const  { return Vect.Data[Cur];               }
          T  operator *()        { return Vect.Data[Cur];               }
    const T  Current() const     { return Vect.Data[Cur];               }
          T  Current()           { return Vect.Data[Cur];               }
    void     Restart()           { Cur = 0;                             }
 
  protected:
    T1& Vect;
    int Cur;
};
 
//
/// \class TMapNode
//
/// Usage:
///  typedef TMapNode<string,string>                         TStringMapNode;
///  typedef TSortedObjectArray< TStringMapNode >            TStringMap;
///  typedef TSortedObjectArray< TStringMapNode >::Iterator  TStringMapIterator;
//
template<class T1, class T2> class TMapNode {
  public:
    TMapNode(T1& name, T2& val):Name(name),Value(val){}
    TMapNode(T1& name):Name(name){}
    TMapNode(const TMapNode<T1,T2>& node):Name(node.Name),Value(node.Value){}
    TMapNode(){}
    ~TMapNode(){}
 
    bool operator <(const TMapNode& ms) const   { return  Name < ms.Name; }
    bool operator ==(const TMapNode& ms) const  { return  Name == ms.Name; }
    TMapNode& operator =(const TMapNode& other)
      {
        Name  = other.Name;
        Value = other.Value;
        return *this;
      }
 
    T1 Name;
    T2 Value;
};
 
//------------------------------------------------------------------------------
/// base array class -> reduce code size
class TArrayBase {
  public:
    TArrayBase():ItemCnt(0),Reserved(0){}
 
    uint    GetItemsInContainer() const { return Size();        }
    int     LowerBound() const    { return 0;                   }
    int     UpperBound() const    { return Size()-1;            }
    uint    ArraySize()  const    { return Reserved;            }
    bool    IsFull() const        { return ItemCnt>=Reserved-1; }
    bool    IsEmpty() const       { return Empty();             }
    uint    Size()  const         { return ItemCnt;             }
    uint    Count() const         { return ItemCnt;             }
    bool    Empty() const         { return ItemCnt == 0;        }
    // support STL name convention
    uint    size()  const         { return ItemCnt;             }
    bool    empty() const         { return Empty();             }
 
    static const auto NPOS = -1;
 
  protected:
    uint  ItemCnt;
    uint  Reserved;
};
 
 
//------------------------------------------------------------------------------
//TMObjectArray - holded aray pointers to strings
//------------------------------------------------------------------------------
// ISO/IEC C++ standard says:
//   11.4 par.2: elaborated-type-specifier shall be used in a friend
//     declaration for a class. elaborated-type-specifier must have class/struct
//     specifier.
//   7.1.5.3 par.2
//     The identifier in elaborated-type-specifier cannot resolve to typedef-name
//     or template type-parameter.
// This is the reason we duplicate the iterator definitions in friend declarations.
//------------------------------------------------------------------------------
/// \class TMObjectArray
/// holded array pointers to strings
template<class T, class A = TStandardAllocator> class TMObjectArray :
/// \cond
  public A,
/// \endcond
  public TArrayBase
{
  public:
    typedef void (*IterFunc)(T&, void*);
    typedef bool (*CondFunc)(const T&, void*);
 
    typedef TObjArrayIterator<T, TMObjectArray<T, A> > Iterator;
    friend class TObjArrayIterator<T, TMObjectArray<T, A> >;
    typedef Iterator                                   iterator;
 
     TMObjectArray(int upper, int lower=0, int /*delta*/ =0)
             : Mem(sizeof(T),upper-lower+1),Data(0){ Resize(upper);}
     TMObjectArray() : Mem(sizeof(T),10), Data(0){}
     ~TMObjectArray();
     TMObjectArray(const TMObjectArray<T,A>& array);
    TMObjectArray<T,A>& operator=(const TMObjectArray<T,A>& array);
    TMMemBlocks<A>& GetAllocator() { return Mem; }
 
    void  RemoveEntry( int loc )       { Remove(loc);         }
    void  SqueezeEntry( unsigned loc ) { Remove(loc);         }
    void  Grow(int index);
 
    int   Add(const T& t);
    void  AddAt(const T& t, uint index);
 
    bool  DestroyItem(const T& t);
    bool  Destroy(int loc);
    bool  HasMember(const T& t) const;
    int   Find(const T& t) const;
 
          T& operator [](int loc);
    const T& operator [](int loc) const;
 
    void  ForEach(IterFunc iter, void* args);
    T*    FirstThat(CondFunc cond, void* args) const;
    T*    LastThat(CondFunc cond, void* args) const;
 
    void Flush();
 
  protected:
    void Resize(int delta);
    void Remove(int index);
    bool  DetachItem(const T& t);
    bool  Detach(int loc);
 
  protected:
    T**                 Data;
    TMMemBlocks<A>  Mem;
};
//------------------------------------------------------------------------------
template<class T> class TObjectArray: public TMObjectArray<T,TStandardAllocator> {
  public:
    typedef void (*IterFunc)(T&, void*);
    typedef bool (*CondFunc)(const T&, void*);
 
    typedef TObjArrayIterator<T, TObjectArray<T> > Iterator;
    typedef Iterator                               iterator;
    friend Iterator;
 
     TObjectArray(int upper, int lower=0, int delta=0)
      : TMObjectArray<T,TStandardAllocator>(upper,lower,delta){}
     TObjectArray(){}
     ~TObjectArray(){}
     TObjectArray(const TObjectArray<T>& array):TMObjectArray<T,TStandardAllocator>(array){}
    TObjectArray<T>& operator=(const TObjectArray<T>& array)
      {
        TMObjectArray<T,TStandardAllocator>::operator=(array);
        return *this;
      }
};
 
//------------------------------------------------------------------------------
template<class T, class A = TStandardAllocator> class TMSortedObjectArray : public TMObjectArray<T,A> {
  public:
    typedef TObjArrayIterator<T, TMSortedObjectArray<T, A> > Iterator;
    friend class TObjArrayIterator<T, TMSortedObjectArray<T, A> >;
    typedef Iterator  iterator;
 
     TMSortedObjectArray(int upper, int lower=0, int delta=0)
                       : TMObjectArray<T,A>(upper,lower,delta){}
     TMSortedObjectArray() : TMObjectArray<T,A>(){}
     ~TMSortedObjectArray(){}
     TMSortedObjectArray(const TMSortedObjectArray<T,A>& array);
    TMSortedObjectArray<T,A>& operator=(const TMSortedObjectArray<T,A>& array);
    int   Add(const T& t);
    bool  DestroyItem(const T& t);
//    bool  Destroy(int loc);
    bool  HasMember(const T& t) const;
    int   Find(const T& t) const;
 
  protected:
    int   AddAt(const T& t, int index){ return 0;} // hide
    bool  DetachItem(const T& t);
};
 
//------------------------------------------------------------------------------
template<class T> class TSortedObjectArray: public TMSortedObjectArray<T,TStandardAllocator> {
  public:
    typedef void (*IterFunc)(T&, void*);
    typedef bool (*CondFunc)(const T&, void*);
 
    typedef TObjArrayIterator<T, TSortedObjectArray<T> > Iterator;
    typedef Iterator  iterator;
    friend Iterator;
 
     TSortedObjectArray(int upper, int lower=0, int delta=0)
      : TMSortedObjectArray<T,TStandardAllocator>(upper,lower,delta){}
     TSortedObjectArray(){}
     ~TSortedObjectArray(){}
     TSortedObjectArray(const TSortedObjectArray<T>& array):TMSortedObjectArray<T,TStandardAllocator>(array){}
    TSortedObjectArray<T>& operator=(const TSortedObjectArray<T>& array)
      {
        TMSortedObjectArray<T,TStandardAllocator>::operator=(array);
        return *this;
      }
};
 
//------------------------------------------------------------------------------
/// (store pointer to object) - Jogy: incorrect, stores simple types without assuming that they are pointer to objects
template<class T, class R, class A = TStandardAllocator> class TTypedArray :
/// \cond
  public A,
/// \endcond
  public TArrayBase
{
  public:
    typedef void (*IterFunc)(R, void*);
    typedef bool (*CondFunc)(R, void*);
 
    typedef TPtrArrayIterator<R, TTypedArray<T, R, A> > Iterator;
    friend class TPtrArrayIterator<R, TTypedArray<T, R, A> >;
    typedef Iterator  iterator;
 
     TTypedArray(int upper, int /*lower*/=0, int /*delta*/=0)
                       :Data(0) {Resize(upper);}
     TTypedArray():Data(0) {}
     ~TTypedArray() { if(Data) A::Free(Data);  }
     TTypedArray(const TTypedArray<T,R,A>& array);
    TTypedArray<T,R,A>& operator=(const TTypedArray<T,R,A>& array);
 
    void  RemoveEntry( int loc ){ Remove(loc);                }
    void  SqueezeEntry( unsigned loc ) { Remove(loc);         }
    void  Grow(int index);
 
    int   Add(R t);
    void  AddAt(R t, uint index);
    bool  DetachItem(R t);
    bool  Detach(int loc);
    bool  DestroyItem(R t);
    bool  Destroy(int loc);
    bool  HasMember(R t) const;
    int   Find(R t) const;
 
    T&    operator [](int loc);
    const T& operator [](int loc) const;
 
    void  ForEach(IterFunc iter, void* args);
    T*    FirstThat(CondFunc cond, void* args) const;
    T*    LastThat(CondFunc cond, void* args) const;
 
    void  Flush();
 
  protected:
    void  Resize(int delta);
    void  Remove(int index);
 
  protected:
    T*    Data;
};
//------------------------------------------------------------------------------
template<class T, class R, class A = TStandardAllocator> class TSTypedArray : public TTypedArray<T,R,A> {
  public:
    typedef TPtrArrayIterator<R, TSTypedArray<T,R,A> > Iterator;
    friend class TPtrArrayIterator<R, TSTypedArray<T,R,A> >;
    typedef Iterator  iterator;
 
     TSTypedArray(int upper, int lower=0, int delta=0)
                       : TTypedArray<T,R,A>(upper,lower,delta){}
     TSTypedArray() : TTypedArray<T,R,A>(){}
     ~TSTypedArray(){}
     TSTypedArray(const TSTypedArray<T,R,A>& array);
    TSTypedArray<T,R,A>& operator=(const TSTypedArray<T,R,A>& array);
 
    int   Add(R t);
    bool  DetachItem(R t);
    bool  DestroyItem(R t);
    bool  Destroy(int loc);
    bool  HasMember(R t) const;
    int   Find(R t) const;
 
  private:
    int AddAt(R t, int index); // hide
};
//------------------------------------------------------------------------------
/// \class TPtrArray
/// array of pointers of simple types
template<class T> class TPtrArray : public TTypedArray<T,T,TStandardAllocator>{
  public:
     TPtrArray(int upper, int lower=0, int delta=0)
                      :TTypedArray<T,T,TStandardAllocator>(upper,lower,delta){}
     TPtrArray():TTypedArray<T,T,TStandardAllocator>(){}
     TPtrArray(const TPtrArray<T>& array):TTypedArray<T,T,TStandardAllocator>(array){}
};
//------------------------------------------------------------------------------
/// \class TSortedPtrArray
/// sorted array of pointers of simple types
template<class T> class TSortedPtrArray : public TSTypedArray<T,T,TStandardAllocator>{
  public:
     TSortedPtrArray(int upper, int lower=0, int delta=0)
                      :TSTypedArray<T,T,TStandardAllocator>(upper,lower,delta){}
     TSortedPtrArray():TSTypedArray<T,T,TStandardAllocator>(){}
     TSortedPtrArray(const TSortedPtrArray<T>& array):TSTypedArray<T,T,TStandardAllocator>(array){}
};
//------------------------------------------------------------------------------
//
template<class T, class R, class A = TStandardAllocator> class TMIPtrArray: public TTypedArray<T,R,A> {
  public:
    typedef TPtrArrayIterator<R, TMIPtrArray<T,R,A> > Iterator;
    friend class TPtrArrayIterator<R, TMIPtrArray<T,R,A> >;
    typedef Iterator  iterator;
 
     TMIPtrArray(int upper, int lower=0, int delta=0);
     TMIPtrArray();
     ~TMIPtrArray();
     TMIPtrArray(const TMIPtrArray<T,R,A>& array);
    TMIPtrArray<T,R,A>& operator=(const TMIPtrArray<T,R,A>& array);
 
    bool  DestroyItem(R t);
    bool  Destroy(int loc);
    void  Flush(bool del = true);
};
//------------------------------------------------------------------------------
//
template<class T> class TIPtrArray: public TPtrArray<T> {
  public:
    typedef TPtrArrayIterator<T, TIPtrArray<T> > Iterator;
    friend class TPtrArrayIterator<T, TIPtrArray<T> >;
    typedef Iterator  iterator;
 
     TIPtrArray(int upper, int lower=0, int delta=0);
     TIPtrArray();
     ~TIPtrArray();
     TIPtrArray(const TIPtrArray<T>& array);
    TIPtrArray<T>& operator=(const TIPtrArray<T>& array);
 
    bool  DestroyItem(T t);
    bool  Destroy(int loc);
    void  Flush(bool del = true);
};
//
//
//
template<class T> class TISortedPtrArray: public TSortedPtrArray<T> {
  public:
    typedef TPtrArrayIterator<T, TISortedPtrArray<T> > Iterator;
    friend class TPtrArrayIterator<T, TISortedPtrArray<T> >;
    typedef Iterator  iterator;
 
     TISortedPtrArray(int upper, int lower=0, int delta=0);
     TISortedPtrArray();
     TISortedPtrArray(const TISortedPtrArray<T>& array);
     ~TISortedPtrArray();
    TISortedPtrArray<T>& operator=(const TISortedPtrArray<T>& array);
 
    bool  DestroyItem(T t);
    bool  Destroy(int loc);
    void  Flush(bool del = true);
};
//------------------------------------------------------------------------------
template<class T> class TBaseNode {
  public:
    TBaseNode(const T& data):Next(0),Prev(0),Data(data){}
 
    TBaseNode*  Next;
    TBaseNode*  Prev;
    T           Data;
};
 
// forward declaration
template<class T> class TBaseList;
 
// class Iterator
template<class T> class TBaseListIterator{
  public:
    TBaseListIterator(TBaseList<T>& list) : List(list),Cur(list.First){}
    operator bool() const         { return Cur != 0;                }
    const T& operator ++(int)     { TBaseNode<T>* tmp = Cur; Cur = Cur->Next; return tmp->Data; }
    const T* operator ++()        { Cur = Cur->Next; return Cur ? &Cur->Data : 0;  } //?????
    const T& operator --(int)     { TBaseNode<T>* tmp = Cur; Cur = Cur->Prev; return tmp->Data; }
    const T* operator --()        { Cur = Cur->Prev; return Cur ? &Cur->Data : 0;  } //?????
    const T& operator *() const   { return Cur->Data;               }
    const T& Current() const      { return Cur->Data;               }
    void  Restart()               { Cur = List.First;               }
 
 
    TBaseList<T>&   List;
    TBaseNode<T>*   Cur;
};
 
//------------------------------------------------------------------------------
// class TBaseList ->
template<class T> class TBaseList {
  public:
    typedef void (*IterFunc)(T&, void*);
    typedef bool (*CondFunc)(const T&, void*);
 
    typedef TBaseListIterator<T> Iterator;
    friend class TBaseListIterator<T>;
    typedef Iterator  iterator;
 
  public:
     TBaseList();
     TBaseList(int /*upper*/, int lower=0, int delta=0);
     ~TBaseList();
 
    int     LowerBound() const    { return 0;                   }
    uint    Size()  const         { return ItemSize;            }
    int     UpperBound() const    { return Size()-1;            }
    uint    ArraySize()  const    { return Size();              }
    bool    IsFull() const        { return true;                }
    bool    Empty() const         { return First == 0;          }
    bool    IsEmpty() const       { return Empty();             }
    uint    GetItemsInContainer() const { return Size();        }
 
 
    /// add new item at end of list
    void  Add(const T& data);
    /// add new item after iterator, if 0 add before first
    void  Add(TBaseListIterator<T> * iter, const T& data);
    // stack
    /// add new item at begin of list
    void  Push(const T& data);
    /// add new item at end of list
    void  PushBack(const T& data);
    /// remove 1 item return data item
    T     Pop();
    /// return top of list
    const T&  Top();
    /// return bottom of array
    const T&  Bottom();
 
    /// Flush all items
    void Flush();
    /// DetachItem( detach item and delete it
    bool  DetachItem(const T& t);
    /// Detach( but and delete it
    bool Detach(int loc);
    /// check item in container
    bool HasMember(const T& t) const;
    /// Find
    TBaseNode<T>* Find(const T& t) const;
    /// iterates all strings
    void ForEach(IterFunc iter, void* args);
    /// FirstThat( return first member
    T* FirstThat(CondFunc cond, void* args) const;
    /// LastThat return last member
    T* LastThat(CondFunc cond, void* args) const;
 
  protected:
    /// remove item from list not delete node
    bool  Remove(TBaseNode<T>* t);
    /// add new item after item, if 0 add before first return index
    int   Add(TBaseNode<T>* node, const T& data);
    /// add new item at end of list return index
    int   Add(TBaseNode<T>* node);
    /// add new item after item, if 0 add before first
    int   Add(TBaseNode<T>* item, TBaseNode<T>* node);
 
  protected:
    TBaseNode<T>* First;
    TBaseNode<T>* Last;
    uint          ItemSize; ///< optimization for Size()
 
    static const auto NPOS = -1;
};
 
//------------------------------------------------------------------------------
template<class T, class T1> class TTernaryNode {
  public:
    TTernaryNode(T split,const T1& data):Data(data),Split(split),LoId(0),EqId(0),HiId(0){}
 
    T             Split;
    TTernaryNode* LoId;
    TTernaryNode* EqId;
    TTernaryNode* HiId;
    T1            Data;
};
 
// class TBaseList ->
template<class T, class T1> class TTernaryTree {
  // access Public Functions
  public:
    //typedef TTernaryTreeIterator<T> Iterator;
    //friend  Iterator;
 
  public:
     TTernaryTree():Root(0){}
     ~TTernaryTree(){}
 
    T1* Find(T* s)
        {
          return RSearch(Root, s);
        }
    void Insert(T* s, const T1& data)
        {
          Root = RInsert(Root, s, data);
        }
    void Flush()
        {
          Flush(Root);
        }
  protected:
    T1* RSearch(TTernaryNode<T,T1>* p, T* s)
        {
          if(!p)
            return 0;
          if(*s < p->Split)
            return RSearch(p->LoId, s);
          else if(*s > p->Split)
            return RSearch(p->HiId, s);
          else{
            if(*s == 0)
              return &p->Data;
            return RSearch(p->EqId, ++s);
          }
        }
    TTernaryNode<T,T1>* RInsert(TTernaryNode<T,T1>* p, T* s, const T1& data)
        {
          if(!p)
            p = new TTernaryNode<T,T1>(*s, data);
          if(*s < p->Split)
            p->LoId = RInsert(p->LoId, s, data);
          else if(*s == p->Split){
            if(*s != 0)
              p->EqId = RInsert(p->EqId, ++s, data);
          }
          else
            p->HiId = RInsert(p->HiId, s, data);
          ItemCnt++;
          return p;
        }
    void Flush(TTernaryNode<T,T1>* p)
        {
          if(p){
            Flush(p->LoId);
            Flush(p->EqId);
            Flush(p->HiId);
            delete p;
          }
        }
  protected:
    TTernaryNode<T,T1>* Root;
    uint  ItemCnt;        /// item count
};
 
/// @}
 
 
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
 
//----------------------------------------------------------------------------
 
//
// inlines
//
// TMObjectArray
// ~~~~~~~~~~~~~
//
template<class T, class A>  TMObjectArray<T,A>::TMObjectArray(const TMObjectArray& array)
:Mem(sizeof(T),std::max(10,int(array.Reserved/10))),Data(0)
{
  if(array.Reserved)
    Resize(array.Reserved);
  for(int i = 0; i < static_cast<int>(array.ItemCnt); i++){
    Data[i] = __owl_construct<T>(Mem.Allocate(sizeof(T)),*array.Data[i]);
  }
  ItemCnt = array.ItemCnt;
}
 
//
template<class T, class A> inline  TMObjectArray<T,A>::~TMObjectArray()
{
  Flush();
  if(Data)
    A::Free(Data);
}
 
//
template<class T, class A> TMObjectArray<T,A>& TMObjectArray<T,A>::operator=(const TMObjectArray<T,A>& array)
{
  if(this == &array)
    return *this;
 
  Flush();
  if(array.ItemCnt >= Reserved)
    Resize(array.ItemCnt - Reserved);
  for(int i = 0; i < static_cast<int>(array.ItemCnt); i++){
    Data[i] = __owl_construct<T>(Mem.Allocate(sizeof(T)),*array.Data[i]);
  }
  ItemCnt = array.ItemCnt;
 
  return *this;
}
 
//
template<class T, class A> inline int TMObjectArray<T,A>::Add(const T& t)
{
  if(ItemCnt>=Reserved)
    Resize(ItemCnt+1);
  Data[ItemCnt] = __owl_construct<T>(Mem.Allocate(sizeof(T)),t);
  return ItemCnt++; // if fail -> throw xalloc
}
//
template<class T, class A> void TMObjectArray<T,A>::AddAt(const T& t, uint index)
{
  if(index == Size()){
    Add(t);
    return;
  }
  if(index >=Reserved)
    Resize(index+1);    // on error -> throw xalloc
  if(ItemCnt>=Reserved)
    Resize(ItemCnt+1);  // on error -> throw xalloc
  if(index < ItemCnt && ItemCnt)
    memmove(&Data[index+1], &Data[index], sizeof(T*)*(ItemCnt-index));
  Data[index] = __owl_construct<T>(Mem.Allocate(sizeof(T)),t);
  ItemCnt++;
}
 
//
template<class T, class A> inline bool TMObjectArray<T,A>::DestroyItem(const T& t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    T* tmp = Data[index];
    Remove(index);
    __owl_destruct(tmp);// call destructor
    Mem.Free(tmp);
    return true;
  }
  return false;
}
//
template<class T, class A> inline bool TMObjectArray<T,A>::Destroy(int loc)
{
  if(loc < (int)Size()){
    T* tmp = Data[loc];
    Remove(loc);
    __owl_destruct(tmp);// call destructor
    Mem.Free(tmp);
    return true;
  }
  return false;
}
 
//
template<class T, class A> inline bool TMObjectArray<T,A>::HasMember(const T& t) const
{
  return this->Find(t) != this->NPOS;
}
//
template<class T, class A> int TMObjectArray<T,A>::Find(const T& t) const
{
  for(int i = 0; i < (int)Size(); i++)
    if(*Data[i] == t)
      return i;
  return this->NPOS;
}
//
template<class T, class A> inline T& TMObjectArray<T,A>::operator [](int loc)
{
  PRECONDITION(loc < (int)Size());
  return *Data[loc];
}
 
//
template<class T, class A> inline const T& TMObjectArray<T,A>::operator [](int loc) const
{
  PRECONDITION(loc < (int)Size());
  return *Data[loc];
}
 
//
template<class T, class A> void TMObjectArray<T,A>::ForEach(IterFunc iter, void* args)
{
  for(int i = 0; i < (int)Size(); i++)
    (iter)(*Data[i],args);
}
 
//
template<class T, class A> T* TMObjectArray<T,A>::FirstThat(CondFunc cond, void* args) const
{
  for(int i = 0; i < (int)Size(); i++)
    if((cond)(*Data[i],args))
      return Data[i];
  return 0;
}
 
//
template<class T, class A> T* TMObjectArray<T,A>::LastThat(CondFunc cond, void* args) const
{
  for(int i = (int)Size()-1; i >=0; i--)
    if((cond)(*Data[i],args))
      return Data[i];
  return 0;
}
 
//
template<class T, class A> void TMObjectArray<T,A>::Flush()
{
  for(int i = 0; i < (int)Size(); i++){
    __owl_destruct(Data[i]);// call destructor
    Mem.Free(Data[i]);
  }
  ItemCnt = 0;
}
 
//
template<class T, class A> inline void TMObjectArray<T,A>::Grow(int index)
{
  if((int)Reserved > index)
    return;
  Resize(index - Reserved);
}
 
//
template<class T, class A> void TMObjectArray<T,A>::Resize(int delta)
{
  if(Data){
    T** data = (T**)A::ReAlloc((void*)Data,(Reserved+delta)*sizeof(T**));
    if(!data){
      data = (T**)A::Alloc((Reserved+delta)*sizeof(T**));
      memcpy(data,Data,Reserved*sizeof(T**));
      A::Free(Data);
    }
    Data = data;
  }
  else
    Data = (T**)A::Alloc((Reserved+delta)*sizeof(T**));
 
  memset((uint8*)Data+Reserved*sizeof(T**),0,delta*sizeof(T**));
  Reserved += delta;
}
 
//
template<class T, class A> inline void TMObjectArray<T,A>::Remove(int index)
{
  memmove(&Data[index],&Data[index+1], sizeof(T*)*(ItemCnt-index-1));
  ItemCnt--;
}
 
//
// TMSortedObjectArray/TSortedObjectArray
// ~~~~~~~~~~~~~~~~~~
 
//
template<class T, class A> inline
TMSortedObjectArray<T,A>::TMSortedObjectArray(const TMSortedObjectArray<T,A>& array)
:
  TMObjectArray<T,A>(array)
{
}
 
//
template<class T, class A> inline TMSortedObjectArray<T,A>&
TMSortedObjectArray<T,A>::operator=(const TMSortedObjectArray<T,A>& array)
{
  if(this == &array)
    return *this;
  TMObjectArray<T,A>::operator=(array);
  return *this;
}
 
//
template<class T, class A> int TMSortedObjectArray<T,A>::Add(const T& t)
{
  if(this->ItemCnt>=this->Reserved)
    TMObjectArray<T,A>::Resize(this->ItemCnt+1); // on error -> throw xalloc
  unsigned loc = this->ItemCnt++;
  while( loc > 0 && t < *(this->Data[loc-1])) {
    this->Data[loc] = this->Data[loc-1];
    loc--;
  }
  this->Data[loc] = __owl_construct<T>(this->Mem.Allocate(sizeof(T)),t);
  return loc;
}
 
//
template<class T, class A> inline bool TMSortedObjectArray<T,A>::DestroyItem(const T& t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    T* tmp = this->Data[index];
    this->Remove(index);
    __owl_destruct(tmp);// call destructor
    this->Mem.Free(tmp);
    return true;
  }
  return false;
}
 
//
template<class T, class A> inline bool TMSortedObjectArray<T,A>::HasMember(const T& t) const
{
  return this->Find(t) != this->NPOS;
}
 
//
template<class T, class A> int TMSortedObjectArray<T,A>::Find(const T& t) const
{
  auto lower = 0;
  auto upper = static_cast<int>(this->Size()) - 1;
  while (lower <= upper)
  {
    const auto middle = (lower + upper) / 2;
    if (*(this->Data[middle]) == t)
      return middle;
    if (*(this->Data[middle]) < t)
      lower = middle + 1;
    else
      upper = middle - 1;
  }
  return this->NPOS;
}
 
//
// class TTypedArray<T>
// ~~~~~ ~~~~~~~~~~~~~~
//
template<class T, class R, class A>
TTypedArray<T,R,A>::TTypedArray(const TTypedArray<T,R,A>& array)
:
  Data(0)
{
  if(array.Reserved)
    Resize(array.Reserved);
  for(int i = 0; i < static_cast<int>(array.ItemCnt); i++)
    Data[i] = array.Data[i];
  ItemCnt = array.ItemCnt;
}
//
template<class T, class R, class A> TTypedArray<T,R,A>&
TTypedArray<T,R,A>::operator=(const TTypedArray<T,R,A>& array)
{
  if(this == &array)
    return *this;
 
  Flush();
  if(array.ItemCnt >= Reserved)
    Resize(array.ItemCnt - Reserved);
  for(int i = 0; i < static_cast<int>(array.ItemCnt); i++)
    Data[i] = array.Data[i];
  ItemCnt = array.ItemCnt;
 
  return *this;
}
 
//
template<class T, class R, class A> inline int
TTypedArray<T,R,A>::Add(R t)
{
  if(ItemCnt>=Reserved)
    Resize(ItemCnt+1);
  Data[ItemCnt++] = t;
  return ItemCnt-1; // if fail -> throw xalloc
}
 
//
template<class T, class R, class A> void
TTypedArray<T,R,A>::AddAt(R t, uint index)
{
  if(index == Size()){
    Add(t);
    return;
  }
  if(index >=Reserved)
    Resize(index+1); // on error -> throw xalloc
  if(ItemCnt>=Reserved)
    Resize(ItemCnt+1); // on error -> throw xalloc
  if(index < ItemCnt && ItemCnt)
    memmove(&Data[index+1], &Data[index], sizeof(T)*(ItemCnt-index));
  Data[index] = t;
  ItemCnt++;
}
 
//
template<class T, class R, class A> bool
TTypedArray<T,R,A>::DetachItem(const R t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    Remove(index);
    return true;
  }
  return false;
}
 
//
template<class T, class R, class A> bool
TTypedArray<T,R,A>::Detach(int loc)
{
  if(loc < (int)Size()){
    Remove(loc);
    return true;
  }
  return false;
}
 
//
template<class T, class R, class A> inline bool
TTypedArray<T,R,A>::DestroyItem(R t)
{
  return DetachItem(t);
}
 
//
template<class T, class R, class A> inline bool
TTypedArray<T,R,A>::Destroy(int loc)
{
  return Detach(loc);
}
 
//
template<class T, class R, class A> inline bool
TTypedArray<T,R,A>::HasMember(R t) const
{
  return this->Find(t) != this->NPOS;
}
 
//
template<class T, class R, class A> int
TTypedArray<T,R,A>::Find(R t) const
{
  for(int i = 0; i < (int)Size(); i++)
    if(Data[i] == t)
      return i;
  return this->NPOS;
}
 
//
template<class T, class R, class A> inline T&
TTypedArray<T,R,A>::operator [](int loc)
{
  PRECONDITION(loc < (int)Size());
  return Data[loc];
}
 
//
template<class T, class R, class A> inline const T&
TTypedArray<T,R,A>::operator [](int loc) const
{
  PRECONDITION(loc < (int)Size());
  return Data[loc];
}
 
//
template<class T, class R, class A> void
TTypedArray<T,R,A>::ForEach(IterFunc iter, void* args)
{
  for(int i = 0; i < (int)Size(); i++)
    (iter)(Data[i], args);
}
 
//
template<class T, class R, class A> T*
TTypedArray<T,R,A>::FirstThat(CondFunc cond, void* args) const
{
  for(int i = 0; i < (int)Size(); i++)
    if((cond)(Data[i],args))
      return &Data[i];
  return 0;
}
 
//
template<class T, class R, class A> T*
TTypedArray<T,R,A>::LastThat(CondFunc cond, void* args) const
{
  for(int i = (int)Size()-1; i >=0; i--)
    if((cond)(Data[i],args))
      return &Data[i];
  return 0;
}
 
//
template<class T, class R, class A> inline void
TTypedArray<T,R,A>::Flush()
{
  ItemCnt = 0;
}
 
//
template<class T, class R, class A> inline void
TTypedArray<T,R,A>::Grow(int index)
{
  if(Reserved > (uint)index)
    return;
  Resize(index - Reserved);
}
 
//
template<class T, class R, class A> void
TTypedArray<T,R,A>::Resize(int delta)
{
  if (Data)
  {
    T* data = (T*)this->ReAlloc((void*)Data,(Reserved+delta)*sizeof(T));
    if (!data) //no ReAlloc, try Alloc instead
    {
      data = (T*)this->Alloc((Reserved+delta)*sizeof(T));
      if (data)
      {
        memcpy(data,Data,Reserved*sizeof(T));
        A::Free(Data);
        Data = data;
      }
      else
        return;
    }
    else
      Data = data;
  }
  else // if (Data)
    Data = (T*)this->Alloc((Reserved+delta)*sizeof(T));
 
  memset((uint8*)Data+Reserved*sizeof(T),0,delta*sizeof(T));
  Reserved += delta;
}
 
//
template<class T, class R, class A> inline void
TTypedArray<T,R,A>::Remove(int index)
{
  memmove(&Data[index],&Data[index+1], sizeof(T)*(ItemCnt-index-1));
  ItemCnt--;
}
//
// TSTypedArray
// ~~~~~~~~~~~~
//
template<class T, class R, class A> inline
TSTypedArray<T,R,A>::TSTypedArray(const TSTypedArray<T,R,A>& array)
:
  TTypedArray<T,R,A>(array)
{
}
 
//
template<class T, class R, class A> inline TSTypedArray<T,R,A>&
TSTypedArray<T,R,A>::operator=(const TSTypedArray<T,R,A>& array)
{
  if(this == &array)
    return *this;
  TTypedArray<T,R,A>::operator=(array);
  return *this;
}
 
//
template<class T, class R, class A> int
TSTypedArray<T,R,A>::Add(R t)
{
  if(this->ItemCnt>=this->Reserved)
    Resize(this->ItemCnt+1); // on error -> throw xalloc
  unsigned loc = this->ItemCnt++;
  while( loc > 0 && t < this->Data[loc-1]) {
    this->Data[loc] = this->Data[loc-1];
    loc--;
  }
  this->Data[loc] = t;
  return loc;
}
 
//
template<class T, class R, class A> bool
TSTypedArray<T,R,A>::DetachItem(R t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    this->Remove(index);
    return true;
  }
  return false;
}
 
//
template<class T, class R, class A> inline bool
TSTypedArray<T,R,A>::DestroyItem(R t)
{
  return DetachItem(t);
}
 
//
template<class T, class R, class A> inline bool
TSTypedArray<T,R,A>::HasMember(R t) const
{
  return this->Find(t) != this->NPOS;
}
 
//
template<class T, class R, class A> int
TSTypedArray<T,R,A>::Find(R t) const
{
  auto lower = 0;
  auto upper = static_cast<int>(this->Size()) - 1;
  while (lower <= upper)
  {
    const auto middle = (lower + upper) / 2;
    if (this->Data[middle] == t)
      return middle;
    if (this->Data[middle] < t)
      lower = middle + 1;
    else
      upper = middle - 1;
  }
  return this->NPOS;
}
 
//
// TMIPtrArray
// ~~~~~~~~~~~
//
template<class T, class R, class A> inline
TMIPtrArray<T,R,A>::TMIPtrArray(int upper, int lower, int delta)
:
  TTypedArray<T,R,A>(upper,lower,delta)
{
}
//
template<class T, class R, class A> inline
TMIPtrArray<T,R,A>::TMIPtrArray(const TMIPtrArray<T,R,A>& array)
:
  TTypedArray<T,R,A>(array)
{
}
//
template<class T, class R, class A> inline
TMIPtrArray<T,R,A>::TMIPtrArray()
{
}
//
template<class T, class R, class A> inline
TMIPtrArray<T,R,A>::~TMIPtrArray()
{
  Flush(true);
}
//
template<class T, class R, class A> inline TMIPtrArray<T,R,A>&
TMIPtrArray<T,R,A>::operator=(const TMIPtrArray<T,R,A>& array)
{
  if(this == &array)
    return *this;
  Flush(true);
  TTypedArray<T,R,A>::operator=(array);
  return *this;
}
//
template<class T, class R, class A> inline bool
TMIPtrArray<T,R,A>::DestroyItem(R t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    R tmp = this->Data[index];
    this->Remove(index);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
//
template<class T, class R, class A> inline bool
TMIPtrArray<T,R,A>::Destroy(int loc)
{
  if(loc < (int)this->Size()){
    R tmp = this->Data[loc];
    this->Remove(loc);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
//
template<class T, class R, class A> void
TMIPtrArray<T,R,A>::Flush(bool del)
{
  if(del){
    for(int i = 0; i < (int)this->Size(); i++)
      delete this->Data[i];// using global delete because we didn't allocate it
  }
  TTypedArray<T,R,A>::Flush();
}
/////////////////////////////////////////////////////////////////
//
// class TIPtrArray
// ~~~~~ ~~~~~~~~~~
//
template<class T> inline
TIPtrArray<T>::TIPtrArray(int upper, int lower, int delta)
:
  TPtrArray<T>(upper,lower,delta)
{
}
//
template<class T> inline
TIPtrArray<T>::TIPtrArray(const TIPtrArray<T>& array)
:
  TPtrArray<T>(array)
{
}
//
template<class T> inline TIPtrArray<T>&
TIPtrArray<T>::operator=(const TIPtrArray<T>& array)
{
  if(this == &array)
    return *this;
  Flush(true);
  TPtrArray<T>::operator=(array);
  return *this;
}
 
//
template<class T> inline
TIPtrArray<T>::TIPtrArray()
{
}
 
//
template<class T> inline
TIPtrArray<T>::~TIPtrArray()
{
  Flush(true);
}
 
//
template<class T> void
TIPtrArray<T>::Flush(bool del)
{
  if(del){
    for(int i = 0; i < (int)this->Size(); i++)
      delete this->Data[i];// using global delete because we didn't allocate it
  }
  TPtrArray<T>::Flush();
}
 
//
template<class T> inline bool
TIPtrArray<T>::DestroyItem(T t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    T tmp = this->Data[index];
    this->Remove(index);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
 
//
template<class T> inline bool
TIPtrArray<T>::Destroy(int loc)
{
  if(loc < (int)this->Size()){
    T tmp = this->Data[loc];
    this->Remove(loc);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
 
//
// TISortedPtrArray
// ~~~~~~~~~
 
//
template<class T> inline
TISortedPtrArray<T>::TISortedPtrArray(int upper, int lower, int delta)
:
  TSortedPtrArray<T>(upper,lower,delta)
{
}
 
//
template<class T> inline
TISortedPtrArray<T>::TISortedPtrArray()
{
}
 
//
template<class T> inline
TISortedPtrArray<T>::~TISortedPtrArray()
{
  Flush(true);
}
 
//
template<class T> inline
TISortedPtrArray<T>::TISortedPtrArray(const TISortedPtrArray<T>& array)
:
  TSortedPtrArray<T>(array)
{
}
 
//
template<class T> inline TISortedPtrArray<T>&
TISortedPtrArray<T>::operator=(const TISortedPtrArray<T>& array)
{
  if(this == &array)
    return *this;
 
  Flush(true);
  TSortedPtrArray<T>::operator=(array);
  return *this;
}
 
//
template<class T> void
TISortedPtrArray<T>::Flush(bool del)
{
  if(del){
    for(int i = 0; i < (int)this->Size(); i++)
      delete this->Data[i];// using global delete because we didn't allocate it
  }
  TSortedPtrArray<T>::Flush();
}
 
//
template<class T> inline bool
TISortedPtrArray<T>::DestroyItem(T t)
{
  const auto index = this->Find(t);
  if (index != this->NPOS)
  {
    T tmp = this->Data[index];
    this->Remove(index);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
 
//
template<class T> inline bool
TISortedPtrArray<T>::Destroy(int loc)
{
  if(loc < (int)this->Size()){
    T tmp = this->Data[loc];
    this->Remove(loc);
    delete tmp;// using global delete because we didn't allocate it
    return true;
  }
  return false;
}
 
 
//
// TBaseList
// ~~~~~~~~~
 
//
template<class T> inline
TBaseList<T>::TBaseList()
:
  First(0),Last(0),ItemSize(0)
{
}
 
//
template<class T> inline
TBaseList<T>::TBaseList(int /*upper*/, int /*lower*/, int /*delta*/)
:
  First(0),Last(0),ItemSize(0)
{
}
 
//
template<class T> inline
TBaseList<T>::~TBaseList()
{
  Flush();
}
 
//
template<class T> inline void
TBaseList<T>::Add(const T& data)
{
  TBaseNode<T>* node = new TBaseNode<T>(data);
  Add(node);
}
 
//
template<class T> inline void
TBaseList<T>::Add(TBaseListIterator<T>* iter, const T& data)
{
  Add( iter ? iter->Cur : 0, new TBaseNode<T>(data));
}
 
//
template<class T> inline void
TBaseList<T>::Push(const T& data)
{
  Add((TBaseNode<T>*)0, data);
}
 
//
template<class T> inline void
TBaseList<T>::PushBack(const T& data)
{
  Add(Last, data);
}
 
//
template<class T> inline T
TBaseList<T>::Pop()
{
  TBaseNode<T>* tmp = First;
  Remove(tmp);
  T data = tmp->Data; delete tmp;
  return data;
}
 
//
template<class T> inline const T&
TBaseList<T>::Top()
{
  return First->Data;
}
 
//
template<class T> inline const T&
TBaseList<T>::Bottom()
{
  return Last->Data;
}
 
//
template<class T> void
TBaseList<T>::Flush()
{
  for(TBaseNode<T>* node = First; node;){
    TBaseNode<T>* tmp = node;
    node = node->Next;
    delete tmp;
  }
  First = Last = 0;
  ItemSize = 0;
}
 
//
template<class T> bool
TBaseList<T>::DetachItem(const T& t)
{
  TBaseNode<T>* item = this->Find(t);
  if(item && Remove(item)){
    delete item;
    return true;
  }
  return false;
}
 
//
template<class T> bool
TBaseList<T>::Detach(int loc)
{
  if(loc < (int)Size()){
    int counter = 0;
    for(TBaseNode<T>* i = First; i; i = i->Next, counter++){
      if(counter == loc){
        Remove(i);
        return true;
      }
    }
  }
  return false;
}
 
//
template<class T> inline bool
TBaseList<T>::HasMember(const T& t) const
{
  return this->Find(t) != 0;
}
 
//
template<class T> TBaseNode<T>*
TBaseList<T>::Find(const T& t) const
{
  for(TBaseNode<T>* i = First; i; i = i->Next)
    if(i->Data == t)
      return i;
  return 0;
}
 
//
template<class T> void
TBaseList<T>::ForEach(IterFunc iter, void* args)
{
  for(TBaseNode<T>* i = First; i; i = i->Next)
    (iter)(i->Data, args);
}
 
//
template<class T> T*
TBaseList<T>::FirstThat(CondFunc cond, void* args) const
{
  for(TBaseNode<T>* i = First; i; i = i->Next)
    if((cond)(i->Data,args))
      return &i->Data;
  return 0;
}
 
//
template<class T> T*
TBaseList<T>::LastThat(CondFunc cond, void* args) const
{
  for(TBaseNode<T>* i = Last; i; i = i->Prev)
    if((cond)(i->Data,args))
      return &i->Data;
  return 0;
}
 
//
template<class T> bool
TBaseList<T>::Remove(TBaseNode<T>* node)
{
  if(!node)
    return false;
  if(node == First){
    First = node->Next;
    node->Next = 0;
    if(First)
      First->Prev = 0;
  }
  else if(node == Last){
    Last = node->Prev;
    node->Prev = 0;
    if(Last)
      Last->Next = 0;
  }
  else{
    node->Prev->Next = node->Next;
    node->Next->Prev = node->Prev;
    node->Prev = 0;
    node->Next = 0;
  }
 
  ItemSize--;
  return true;
}
 
//
template<class T> inline int
TBaseList<T>::Add(TBaseNode<T>* node, const T& data)
{
  return Add(node, new TBaseNode<T>(data));
}
 
//
template<class T> int
TBaseList<T>::Add(TBaseNode<T>* node)
{
  if(!node)
    return this->NPOS;
  if(!First){
    First = node;
    Last = node;
  }
  else{
    node->Prev = Last;
    Last->Next = node;
    Last = node;
  }
  return ++ItemSize;
}
 
//
template<class T> int
TBaseList<T>::Add(TBaseNode<T>* item, TBaseNode<T>* node)
{
  if(!node)
    return this->NPOS;
  if(!First){
    return Add(node);
  }
  if(!item){
    node->Next  = First;
    First->Prev = node;
    First = node;
  }
  else{
    if(item == Last)
      Last = node;
    node->Prev = item;
    node->Next = item->Next;
    item->Next = node;
    if(node->Next)
      node->Next->Prev = node;
  }
  return ++ItemSize;
}
 
} // OWL namespace
 
//
// Inlined overloads of global new
//
 
inline void * operator new(size_t sz, const owl::TStandardAllocator&)
{
  return ::operator new(sz);
}
 
inline void * operator new(size_t sz, const owl::TLocalAllocator&)
{
  return (void*)::LocalAlloc(LPTR, sz);
}
 
inline void * operator new(size_t sz, const owl::TGlobalAllocator&)
{
  return (void*)::GlobalLock(::GlobalAlloc(GPTR, sz));
}
 
template <class A>
inline void* operator new( size_t sz, owl::TMMemStack<A>& m )
{
  return m.Allocate( sz );
}
 
 
#endif  // OWL_TEMPLATE_H

V302 Member operator[] of 'TMObjectArray' class has a 32-bit type argument. Use memsize-type here.

V302 Member operator[] of 'TMObjectArray' class has a 32-bit type argument. Use memsize-type here.

V302 Member operator[] of 'TTypedArray' class has a 32-bit type argument. Use memsize-type here.

V302 Member operator[] of 'TTypedArray' class has a 32-bit type argument. Use memsize-type here.

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: ItemCnt.

V560 A part of conditional expression is always true: ItemCnt.

V560 A part of conditional expression is always true: ItemCnt.

V522 There might be dereferencing of a potential null pointer 'Data'.

V522 There might be dereferencing of a potential null pointer 'Data'.

V524 It is odd that the body of 'Alloc' function is fully equivalent to the body of 'new' function.

V524 It is odd that the body of 'Alloc' function is fully equivalent to the body of 'new' function.

V524 It is odd that the body of 'Free' function is fully equivalent to the body of 'delete' function.

V524 It is odd that the body of 'GetItemsInContainer' function is fully equivalent to the body of 'ArraySize' function.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty destructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.