#ifndef __PTYPES_H__ 
#define __PTYPES_H__ 
#ifndef __PPORT_H__ 
#include "pport.h" 
#endif 
#include <string.h> 
PTYPES_BEGIN
#ifdef _MSC_VER 
#pragma pack(push, 4) 
#pragma warning(disable : 4275) 
#pragma warning(push) 
#pragma warning(disable : 4127) 
#endif 
int   __PFASTCALL pincrement(int* target);
int   __PFASTCALL pdecrement(int* target);
int   __PFASTCALL pexchange(int* target, int value);
void* __PFASTCALL pexchange(void** target, void* value);
template <class T> inline T* tpexchange(T** target, T* value)
    { return (T*)pexchange((void**)target, (void*)value); }
#if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ == 4) 
#  define VARIANT_TYPECAST_HACK 
#endif 
struct _strrec 
{
    int refcount;
    int length;
};
typedef _strrec* _pstrrec;
#define STR_BASE(x)      (_pstrrec(x)-1) 
#define STR_REFCOUNT(x)  (STR_BASE(x)->refcount) 
#define STR_LENGTH(x)    (STR_BASE(x)->length) 
#define PTR_TO_PSTRING(p)   (pstring(&(p))) 
#define PTR_TO_STRING(p)    (*PTR_TO_PSTRING(p)) 
extern char* emptystr;
class variant;
class string 
{
    friend class variant;
protected:
    char* data;
    static void idxerror();
    void _alloc(int);
    void _realloc(int);
    void _free();
    void initialize()  { data = emptystr; }
    void initialize(const char*, int);
    void initialize(const char*);
    void initialize(char);
    void initialize(const string& s);
    void initialize(const char*, int, const char*, int);
    void initialize(const variant&);
    void finalize();
    void assign(const char*, int);
    void assign(const char*);
    void assign(const string&);
    void assign(char);
#ifdef CHECK_BOUNDS 
    void idx(int index) const  { if (unsigned(index) >= unsigned(STR_LENGTH(data))) idxerror(); }
#else 
    void idx(int) const        { }
#endif 
    string(const char* s1, int len1, const char* s2, int len2)  { initialize(s1, len1, s2, len2); }
public:
    friend int    length(const string& s);
    friend int    refcount(const string& s);
    friend void   assign(string& s, const char* buf, int len);
    friend void   clear(string& s);
    friend bool   isempty(const string& s);
    friend char*  setlength(string&, int);
    friend char*  unique(string&);
    friend void   concat(string& s, const char* sc, int catlen);
    friend void   concat(string& s, const char* s1);
    friend void   concat(string& s, char s1);
    friend void   concat(string& s, const string& s1);
    friend string copy(const string& s, int from, int cnt);
    friend string copy(const string& s, int from);
    friend void   ins(const char* s1, int s1len, string& s, int at);
    friend void   ins(const char* s1, string& s, int at);
    friend void   ins(char s1, string& s, int at);
    friend void   ins(const string& s1, string& s, int at);
    friend void   del(string& s, int at, int cnt);
    friend void   del(string& s, int at);
    friend int    pos(const char* s1, const string& s);
    friend int    pos(char s1, const string& s);
    friend int    pos(const string& s1, const string& s);
    friend int    rpos(char s1, const string& s);
    friend bool   contains(const char* s1, int len, const string& s, int at);
    friend bool   contains(const char* s1, const string& s, int at);
    friend bool   contains(char s1, const string& s, int at);
    friend bool   contains(const string& s1, const string& s, int at);
    friend string dup(const string& s);
    string()                                      { initialize(); }
    string(const char* sc, int initlen)           { initialize(sc, initlen); }
    string(const char* sc)                        { initialize(sc); }
    string(char c)                                { initialize(c); }
    string(const string& s)                       { initialize(s); }
    ~string()                                     { finalize(); }
#ifdef VARIANT_TYPECAST_HACK 
    string(const variant& v)                      { initialize(v); }
#endif 
    string& operator=  (const char* sc)           { assign(sc); return *this; }
    string& operator=  (char c)                   { assign(c); return *this; }
    string& operator=  (const string& s)          { assign(s); return *this; }
    string& operator+= (const char* sc)           { concat(*this, sc); return *this; }
    string& operator+= (char c)                   { concat(*this, c); return *this; }
    string& operator+= (const string& s)          { concat(*this, s); return *this; }
    string  operator+  (const char* sc) const;
    string  operator+  (char c) const;
    string  operator+  (const string& s) const;
    friend string operator+ (const char* sc, const string& s);
    friend string operator+ (char c, const string& s);
    bool operator== (const char* sc) const        { return strcmp(data, sc) == 0; }
    bool operator== (char) const;
    bool operator== (const string&) const;
    bool operator!= (const char* sc) const        { return !(*this == sc); }
    bool operator!= (char c) const                { return !(*this == c); }
    bool operator!= (const string& s) const       { return !(*this == s); }
    friend bool operator== (const char*, const string&);
    friend bool operator== (char, const string&);
    friend bool operator!= (const char*, const string&);
    friend bool operator!= (char, const string&);
    operator const char*() const                  { return data; }
    operator const uchar*() const                 { return (uchar*)data; }
    char&       operator[] (int i)                { idx(i); return unique(*this)[i]; }
    const char& operator[] (int i) const          { idx(i); return data[i]; }
    friend void initialize(string& s);
    friend void initialize(string& s, const string& s1);
    friend void initialize(string& s, const char* s1);
    friend void finalize(string& s);
};
typedef string* pstring;
inline int  length(const string& s)                     { return STR_LENGTH(s.data); }
inline int  refcount(const string& s)                   { return STR_REFCOUNT(s.data); }
inline void assign(string& s, const char* buf, int len) { s.assign(buf, len); }
inline void clear(string& s)                            { s.finalize(); }
inline bool isempty(const string& s)                    { return length(s) == 0; }
inline int  pos(const string& s1, const string& s)      { return pos(s1.data, s); }
inline bool operator== (const char* sc, const string& s){ return s == sc; }
inline bool operator== (char c, const string& s)        { return s == c; }
inline bool operator!= (const char* sc, const string& s){ return s != sc; }
inline bool operator!= (char c, const string& s)        { return s != c; }
inline void initialize(string& s)                       { s.initialize(); }
inline void initialize(string& s, const string& s1)     { s.initialize(s1); }
inline void initialize(string& s, const char* s1)       { s.initialize(s1); }
inline void finalize(string& s)                         { s.finalize(); }
extern int stralloc;
extern string nullstring;
string fill(int width, char pad);
string pad(const string& s, int width, char c, bool left = true);
string itostring(large value, int base, int width = 0, char pad = 0);
string itostring(ularge value, int base, int width = 0, char pad = 0);
string itostring(int value, int base, int width = 0, char pad = 0);
string itostring(unsigned value, int base, int width = 0, char pad = 0);
string itostring(large v);
string itostring(ularge v);
string itostring(int v);
string itostring(unsigned v);
large  stringtoi(const char*);
large  stringtoie(const char*);
ularge stringtoue(const char*, int base);
string lowercase(const char* s);
string lowercase(const string& s);
char hex4(char c);
inline char locase(char c) 
    { if (c >= 'A' && c <= 'Z') return char(c + 32); return c; }
inline char upcase(char c) 
    { if (c >= 'a' && c <= 'z') return char(c - 32); return c; }
inline int hstrlen(const char* p) 
    { return p == nil ? 0 : (int)strlen(p); }
const int  _csetbits = 256;
const int  _csetbytes = _csetbits / 8;
const int  _csetwords = _csetbytes / sizeof(int);
const char _csetesc = '~';
class cset 
{
protected:
    char data[_csetbytes];
    void assign(const cset& s)                  { memcpy(data, s.data, _csetbytes); }
    void assign(const char* setinit);
    void clear()                                { memset(data, 0, _csetbytes); }
    void fill()                                 { memset(data, -1, _csetbytes); }
    void include(char b)                        { data[uchar(b) / 8] |= uchar(1 << (uchar(b) % 8)); }
    void include(char min, char max);
    void exclude(char b)                        { data[uchar(b) / 8] &= uchar(~(1 << (uchar(b) % 8))); }
    void unite(const cset& s);
    void subtract(const cset& s);
    void intersect(const cset& s);
    void invert();
    bool contains(char b) const                 { return (data[uchar(b) / 8] & (1 << (uchar(b) % 8))) != 0; }
    bool eq(const cset& s) const                { return memcmp(data, s.data, _csetbytes) == 0; }
    bool le(const cset& s) const;
public:
    cset()                                      { clear(); }
    cset(const cset& s)                         { assign(s); }
    cset(const char* setinit)                   { assign(setinit); }
    cset& operator=  (const cset& s)            { assign(s); return *this; }
    cset& operator+= (const cset& s)            { unite(s); return *this; }
    cset& operator+= (char b)                   { include(b); return *this; }
    cset  operator+  (const cset& s) const      { cset t = *this; return t += s; }
    cset  operator+  (char b) const             { cset t = *this; return t += b; }
    cset& operator-= (const cset& s)            { subtract(s); return *this; }
    cset& operator-= (char b)                   { exclude(b); return *this; }
    cset  operator-  (const cset& s) const      { cset t = *this; return t -= s; }
    cset  operator-  (char b) const             { cset t = *this; return t -= b; }
    cset& operator*= (const cset& s)            { intersect(s); return *this; }
    cset  operator*  (const cset& s) const      { cset t = *this; return t *= s; }
    cset  operator!  () const                   { cset t = *this; t.invert(); return t; }
    bool  operator== (const cset& s) const      { return eq(s); }
    bool  operator!= (const cset& s) const      { return !eq(s); }
    bool  operator<= (const cset& s) const      { return le(s); }
    bool  operator>= (const cset& s) const      { return s.le(*this); }
    friend cset operator+ (char b, const cset& s);
    friend bool operator& (char b, const cset& s);
    friend void assign(cset& s, const char* setinit);
    friend void clear(cset& s);
    friend void fill(cset& s);
    friend void include(cset& s, char b);
    friend void include(cset& s, char min, char max);
    friend void exclude(cset& s, char b);
    friend string asstring(const cset& s);
};
inline cset operator+ (char b, const cset& s)     { return s + b; }
inline bool operator& (char b, const cset& s)     { return s.contains(b); }
inline void assign(cset& s, const char* setinit)  { s.assign(setinit); }
inline void clear(cset& s)                        { s.clear(); }
inline void fill(cset& s)                         { s.fill(); }
inline void include(cset& s, char b)              { s.include(b); }
inline void include(cset& s, char min, char max)  { s.include(min, max); }
inline void exclude(cset& s, char b)              { s.exclude(b); }
extern int objalloc;
class unknown 
{
private:
    // make all classes non-copyable by default
    unknown(const unknown&);
    const unknown& operator= (const unknown&);
public:
#ifdef COUNT_OBJALLOC 
    unknown()           { pincrement(&objalloc); }
    virtual ~unknown()  { pdecrement(&objalloc); }
#else 
    unknown()           { }
    virtual ~unknown()  { }
#endif 
};
typedef unknown* punknown;
class noncopyable 
{
private:
    noncopyable(const noncopyable&);
    const noncopyable& operator= (const noncopyable&);
public:
    noncopyable() {}
    ~noncopyable() {}
};
class exception: public unknown 
{
protected:
    string message;
public:
    exception(const char* imsg);
    exception(const string& imsg);
    virtual ~exception();
    virtual string get_message() { return message; }
};
class econv: public exception
{
public:
    econv(const char* msg): exception(msg)  {}
    econv(const string& msg): exception(msg)  {}
    virtual ~econv();
};
class _podlist: public noncopyable
{
protected:
    void* list;                   
    int   count;                  
    int   capacity;               
    int   itemsize;               
    static void idxerror();
    _podlist& operator =(const _podlist& t);
    void  grow();
    void* doins(int index);
    void  doins(int index, const _podlist&);
    void* doget(int index) const            { return (char*)list + index * itemsize; }
    void  dodel(int index);
    void  dodel(int index, int count);
    void  dopop();
#ifdef CHECK_BOUNDS 
    void idx(int index) const               { if (unsigned(index) >= unsigned(count)) idxerror(); }
    void idxa(int index) const              { if (unsigned(index) > unsigned(count)) idxerror(); }
#else 
    void idx(int) const                     { }
    void idxa(int) const                    { }
#endif 
public:
    _podlist(int itemsize);
    ~_podlist();
    int   get_count() const                 { return count; }
    void  set_count(int newcount, bool zero = false);
    int   get_capacity() const              { return capacity; }
    void  set_capacity(int newcap);
    void  clear()                           { set_count(0); }
    void  pack()                            { set_capacity(count); }
    void* ins(int index)                    { idxa(index); return doins(index); }
    void  ins(int index, const _podlist& t) { idxa(index); doins(index, t); }
    void* add();
    void  add(const _podlist& t);
    void* operator [](int index)            { idx(index); return doget(index); }
    void* top()                             { return operator [](count - 1); }
    void  del(int index)                    { idx(index); dodel(index); }
    void  del(int index, int count)         { idx(index); dodel(index, count); }
    void  pop()                             { idx(0); dopop(); }
};
template <class X, bool initzero = false> class tpodlist: public _podlist
{
protected:
    X&   dozero(X& t)                       { if (initzero) memset(&t, 0, sizeof(X)); return t; }
    X&   doget(int index) const             { return ((X*)list)[index]; }
    X&   doins(int index)                   { X& t = *(X*)_podlist::doins(index); return dozero(t); }
    void doins(int index, const X& item)    { *(X*)_podlist::doins(index) = item; }
public:
    tpodlist(): _podlist(sizeof(X))         {}
    tpodlist<X, initzero>& operator =(const tpodlist<X, initzero>& t)
                                            { _podlist::operator =(t); return *this; }
    void set_count(int newcount)            { _podlist::set_count(newcount, initzero); }
    X&   ins(int index)                     { idxa(index); return doins(index); }
    void ins(int index, const X& item)      { idxa(index); doins(index, item); }
    void ins(int index, const tpodlist<X, initzero>& t)
                                            { _podlist::ins(index, t); }
    X&   add()                              { grow(); return dozero(doget(count++)); }
    void add(const X& item)                 { grow(); doget(count++) = item; }
    void add(const tpodlist<X, initzero>& t)
					    { _podlist::add(t); }
    X&   operator [](int index)             { idx(index); return doget(index); }
    const X& operator [](int index) const   { idx(index); return doget(index); }
    X&   top()                              { idx(0); return doget(count - 1); }
};
class _objlist: public unknown, protected tpodlist<void*, true>
{
protected:
    struct
    {
        unsigned ownobjects :1;   
        unsigned ownslobjects :1; 
        unsigned sorted :1;       
        unsigned duplicates :1;   
        unsigned casesens :1;     
        unsigned _reserved :27;
    } config;
    _objlist(bool ownobjects);	  
    void* doget(int index) const            { return ((void**)list)[index]; }
    void  doput(int index, void* obj);
    void  dodel(int index);
    void  dodel(int index, int count);
    void* dopop();
    void  dofree(int index, int count);
    virtual void dofree(void* obj);        
    virtual int compare(const void* key, const void* obj) const;  
public:
    _objlist();
    virtual ~_objlist();
    int   get_count() const                 { return count; }
    void  set_count(int newcount);
    int   get_capacity() const              { return capacity; }
    void  set_capacity(int newcap)          { tpodlist<void*,true>::set_capacity(newcap); }
    void  clear()                           { set_count(0); }
    void  pack()                            { tpodlist<void*,true>::pack(); }
    void  ins(int index, void* obj)         { tpodlist<void*,true>::ins(index, obj); }
    void  add(void* obj)                    { tpodlist<void*,true>::add(obj); }
    void  put(int index, void* obj)         { idx(index); doput(index, obj); }
    void* operator [](int index) const      { idx(index); return doget(index); }
    void* top() const                       { idx(0); return doget(count - 1); }
    void* pop()                             { idx(0); return dopop(); }
    void  del(int index)                    { idx(index); dodel(index); }
    void  del(int index, int count)         { idx(index); dodel(index, count); }
    int   indexof(void* obj) const;
    bool  search(const void* key, int& index) const;
};
template <class X> class tobjlist: public _objlist
{
protected:
    X* doget(int index) const               { return (X*)_objlist::doget(index); }
    virtual void dofree(void* obj);
public:
    tobjlist(bool ownobjects = false): _objlist(ownobjects)  {}
    virtual ~tobjlist();
    bool  get_ownobjects() const            { return config.ownobjects; }
    void  set_ownobjects(bool newval)       { config.ownobjects = newval; }
    void  ins(int index, X* obj)            { _objlist::ins(index, obj); }
    void  add(X* obj)                       { _objlist::add(obj); }
    void  put(int index, X* obj)            { _objlist::put(index, obj); }
    X*    operator [](int index) const      { idx(index); return (X*)doget(index); }
    X*    top() const                       { return (X*)_objlist::top(); }
    X*    pop()                             { return (X*)_objlist::pop(); }
    int   indexof(X* obj) const             { return _objlist::indexof(obj); }
#ifdef PTYPES19_COMPAT 
    friend inline void ins(tobjlist& s, int i, X* obj)          { s.ins(i, obj); }
    friend inline int  add(tobjlist& s, X* obj)                 { s.add(obj); return s.get_count() - 1; }
    friend inline void put(tobjlist& s, int i, X* obj)          { s.put(i, obj); }
    friend inline int  indexof(const tobjlist& s, X* obj)       { return s.indexof(obj); }
    friend inline int  push(tobjlist& s, X* obj)                { s.add(obj); return s.get_count() - 1; }
    friend inline X*   pop(tobjlist& s)                         { return (X*)s.pop(); }
    friend inline X*   top(const tobjlist& s)                   { return (X*)s.top(); }
    friend inline X*   get(const tobjlist& s, int i)            { return (X*)s[i]; }
#endif 
};
template <class X> void tobjlist<X>::dofree(void* item)
{
    delete (X*)item;
}
template <class X> tobjlist<X>::~tobjlist()
{
    set_count(0);
}
typedef int slflags; 
#define SL_SORTED      1 
#define SL_DUPLICATES  2 
#define SL_CASESENS    4 
#define SL_OWNOBJECTS  8 
struct _stritem
{
    string key;
    void* obj;
    _stritem(const string& ikey, void* iobj)
        : key(ikey), obj(iobj)  {}
};
class _strlist: protected tobjlist<_stritem>
{
protected:
    static void sortederror();
    static void notsortederror();
    static void duperror();
    virtual void dofree(void* item);
    virtual int  compare(const void* key, const void* item) const;
    virtual void dofreeobj(void* obj);          
    const string& dogetkey(int index) const             { return doget(index)->key; }
    void* dogetobj(int index) const                     { return doget(index)->obj; }
    void  doins(int index, const string& key, void* obj);
    void  doput(int index, const string& key, void* obj);
    void  doput(int index, void* obj);
public:
    _strlist(int flags = 0);
    virtual ~_strlist();
    int   get_count() const                             { return count; }
    void  set_count(int newcount)                       { tobjlist<_stritem>::set_count(newcount); }
    int   get_capacity() const                          { return capacity; }
    void  set_capacity(int newcap)                      { tobjlist<_stritem>::set_capacity(newcap); }
    void  clear()                                       { tobjlist<_stritem>::clear(); }
    void  pack()                                        { tobjlist<_stritem>::pack(); }
    bool  get_sorted() const                            { return config.sorted; }
    bool  get_duplicates() const                        { return config.duplicates; }
    bool  get_casesens() const                          { return config.casesens; }
    bool  get_ownobjects() const                        { return config.ownslobjects; }
    void  set_ownobjects(bool newval)                   { config.ownslobjects = newval; }
    void  ins(int index, const string& key, void* obj)  { idxa(index); doins(index, key, obj); }
    void  put(int index, const string& key, void* obj)  { idx(index); doput(index, key, obj); }
    void  put(int index, void* obj)                     { idx(index); doput(index, obj); }
    int   put(const string& key, void* obj);
    int   add(const string& key, void* obj);
    void* operator [](int index) const                  { idx(index); return dogetobj(index); }
    void* operator [](const char* key) const;
    const string& getkey(int index) const               { idx(index); return dogetkey(index); }
    bool  search(const char* key, int& index) const     { return _objlist::search(key, index); }
    void  del(int index)                                { idx(index); dodel(index); }
    void  del(int index, int delcount)                  { idx(index); dodel(index, delcount); }
    void  del(const char* key)                          { put(key, nil); }
    int   indexof(const char* key) const;
    int   indexof(void* obj) const;
};
template <class X> class tstrlist: public _strlist
{
protected:
    virtual void dofreeobj(void* obj);
public:
    tstrlist(int flags = 0): _strlist(flags)  {}
    virtual ~tstrlist();
    void  ins(int index, const string& key, X* obj)     { _strlist::ins(index, key, obj); }
    void  put(int index, const string& key, X* obj)     { _strlist::put(index, key, obj); }
    void  put(int index, X* obj)                        { _strlist::put(index, obj); }
    int   put(const string& key, X* obj)                { return _strlist::put(key, obj); }
    int   add(const string& key, X* obj)                { return _strlist::add(key, obj); }
    X*    operator [](int index) const                  { return (X*)_strlist::operator [](index); }
    X*    operator [](const char* key) const            { return (X*)_strlist::operator [](key); }
    int   indexof(X* obj) const                         { return _strlist::indexof(obj); }
    int   indexof(const char* key) const                { return _strlist::indexof(key); }
#ifdef PTYPES19_COMPAT 
    // pre-2.0 interface for backwards compatibility
    friend inline void ins(tstrlist& s, int i, const string& str, X* obj)  { s.ins(i, str, obj); }
    friend inline int  add(tstrlist& s, const string& str, X* obj)         { return s.add(str, obj); }
    friend inline void put(tstrlist& s, int i, const string& str, X* obj)  { s.put(i, str, obj); }
    friend inline void put(tstrlist& s, int i, X* obj)                     { s.put(i, obj); }
    friend inline int indexof(const tstrlist& s, X* obj)                   { return s.indexof(obj); }
    friend inline X* get(const tstrlist& s, int i)                         { return (X*)s[i]; }
#endif 
};
template <class X> void tstrlist<X>::dofreeobj(void* obj)
{
    delete (X*)obj;
}
template <class X> tstrlist<X>::~tstrlist()
{
    set_count(0);
}
struct _textitem
{
    string key;
    string value;
    _textitem(const string& ikey, const string& ivalue)
        : key(ikey), value(ivalue)  {}
};
class textmap: protected tobjlist<_textitem>
{
protected:
    virtual int compare(const void* key, const void* item) const;
    const string& dogetvalue(int index) const           { return doget(index)->value; }
    const string& dogetkey(int index) const             { return doget(index)->key; }
public:
    textmap(bool casesens = false);
    virtual ~textmap();
    int   get_count() const                             { return tobjlist<_textitem>::get_count(); }
    void  pack()                                        { tobjlist<_textitem>::pack(); }
    void  clear()                                       { tobjlist<_textitem>::clear(); }
    int   put(const string& key, const string& value);
    void  del(int index)                                { idx(index); dodel(index); }
    void  del(const char* key)                          { put(key, nullstring); }
    const string& get(int index) const                  { idx(index); return dogetvalue(index); }
    const string& getkey(int index) const               { idx(index); return dogetkey(index); }
    const string& get(const char* key) const;
    const string& operator [](int index) const          { return get(index); }
    const string& operator [](const char* key) const    { return get(key); }
    int   indexof(const char* key) const;
};
const int CLASS_UNDEFINED = 0x00000000;
const int CLASS_INSTM     = 0x00000001;
const int CLASS_OUTSTM    = 0x00000002;
const int CLASS_UNIT      = 0x00000003;
const int CLASS2_INFILE    = 0x00000100 | CLASS_INSTM;
const int CLASS2_INMEMORY  = 0x00000200 | CLASS_INSTM;
const int CLASS2_FDX       = 0x00000300 | CLASS_INSTM;
const int CLASS2_OUTFILE   = 0x00000100 | CLASS_OUTSTM;
const int CLASS2_OUTMEMORY = 0x00000200 | CLASS_OUTSTM;
const int CLASS3_LOGFILE   = 0x00010000 | CLASS2_OUTFILE;
const int CLASS3_IPSTM     = 0x00020000 | CLASS2_FDX;
const int CLASS3_NPIPE     = 0x00030000 | CLASS2_FDX;
class component: public unknown 
{
protected:
    int                  refcount;     
    tobjlist<component>* freelist;     
    void*                typeinfo;     
    virtual void freenotify(component* sender);
public:
    component();
    virtual ~component();
    void addnotification(component* obj);
    void delnotification(component* obj);
    
    friend component* addref(component*);
    friend bool release(component*);
    friend int refcount(component* c);
    virtual int classid();
    void  set_typeinfo(void* t) { typeinfo = t; }
    void* get_typeinfo()        { return typeinfo; }
};
typedef component* pcomponent;
inline int refcount(component* c)  { return c->refcount; }
template <class T> inline T* taddref(T* c)
    { return (T*)addref((component*)c); }
template <class T> class compref
{
protected:
    T* ref;
public:
    compref()                                   { ref = 0; }
    compref(const compref<T>& r)                { ref = taddref<T>(r.ref); }
    compref(T* c)                               { ref = taddref<T>(c); }
    ~compref()                                  { release(ref); }
    compref<T>& operator =(T* c);
    compref<T>& operator =(const compref<T>& r) { return operator =(r.ref); }
    T&   operator *() const                     { return *ref; }
    T*   operator ->() const                    { return ref; }
    bool operator ==(const compref<T>& r) const { return ref == r.ref; }
    bool operator ==(T* c) const                { return ref == c; }
    bool operator !=(const compref<T>& r) const { return ref != r.ref; }
    bool operator !=(T* c) const                { return ref != c; }
         operator T*() const                    { return ref; }
};
template <class T> compref<T>& compref<T>::operator =(T* c)
{
    release(tpexchange<T>(&ref, taddref<T>(c)));
    return *this;
}
enum {
    VAR_NULL,
    VAR_INT,
    VAR_BOOL,
    VAR_FLOAT,
    VAR_STRING,
    VAR_ARRAY,
    VAR_OBJECT,
    VAR_COMPOUND = VAR_STRING
};
class _varray;
class variant
{
    friend class string;
    friend class _varray;
protected:
    int tag;            
    union {
        large      i;   
        bool       b;   
        double     f;   
        char*      s;   
        _varray*   a;   
        component* o;   
    } value;            
    void initialize()                       { tag = VAR_NULL; }
    void initialize(large v)                { tag = VAR_INT; value.i = v; }
    void initialize(bool v)                 { tag = VAR_BOOL; value.b = v; }
    void initialize(double v)               { tag = VAR_FLOAT; value.f = v; }
    void initialize(const char* v)          { tag = VAR_STRING; PTYPES_NAMESPACE::initialize(PTR_TO_STRING(value.s), v); }
    void initialize(const string& v)        { tag = VAR_STRING; PTYPES_NAMESPACE::initialize(PTR_TO_STRING(value.s), v); }
    void initialize(_varray* a);
    void initialize(component* o);
    void initialize(const variant& v);
    void finalize();
    void assign(large);
    void assign(bool);
    void assign(double);
    void assign(const char*);
    void assign(const string&);
    void assign(_varray*);
    void assign(component*);
    void assign(const variant&);
    bool equal(const variant& v) const;
    variant(_varray* a)                     { initialize(a); }
public:
    // construction
    variant()                               { initialize(); }
    variant(int v)                          { initialize(large(v)); }
    variant(unsigned int v)                 { initialize(large(v)); }
    variant(large v)                        { initialize(v); }
    variant(bool v)                         { initialize(v); }
    variant(double v)                       { initialize(v); }
    variant(const char* v)                  { initialize(v); }
    variant(const string& v)                { initialize(v); }
    variant(component* v)                   { initialize(v); }
    variant(const variant& v)               { initialize(v); }
    ~variant()                              { finalize(); }
    // assignment
    variant& operator= (int v)              { assign(large(v)); return *this; }
    variant& operator= (unsigned int v)     { assign(large(v)); return *this; }
    variant& operator= (large v)            { assign(v); return *this; }
    variant& operator= (bool v)             { assign(v); return *this; }
    variant& operator= (double v)           { assign(v); return *this; }
    variant& operator= (const char* v)      { assign(v); return *this; }
    variant& operator= (const string& v)    { assign(v); return *this; }
    variant& operator= (component* v)       { assign(v); return *this; }
    variant& operator= (const variant& v)   { assign(v); return *this; }
    // typecast
    operator int() const;
    operator unsigned int() const;
    operator long() const;
    operator unsigned long() const;
    operator large() const;
    operator bool() const;
    operator double() const;
    operator string() const;
    operator component*() const;
    // comparison
    bool operator== (const variant& v) const  { return equal(v); }
    bool operator!= (const variant& v) const  { return !equal(v); }
    // typification
    friend void clear(variant&);
    friend int  vartype(const variant& v);
    friend bool isnull(const variant& v);
    friend bool isint(const variant& v);
    friend bool isbool(const variant& v);
    friend bool isfloat(const variant& v);
    friend bool isstring(const variant& v);
    friend bool isarray(const variant& v);
    friend bool isobject(const variant& v);
    friend bool iscompound(const variant& v);
    // array manipulation
    friend void aclear(variant&);
    friend variant aclone(const variant&);
    friend const variant& get(const variant&, const string& key);
    friend const variant& get(const variant&, large key);
    friend void put(variant&, const string& key, const variant& item);
    friend void put(variant&, large key, const variant& item);
    friend void del(variant&, const string& key);
    friend void del(variant&, large key);
    // indexed access to arrays
    friend int  alength(const variant&);
    friend void apack(variant&);
    friend bool anext(const variant& a, int&, variant& item);
    friend bool anext(const variant& a, int&, variant& item, string& key);
    friend int  aadd(variant&, const variant& item);
    friend void aput(variant&, int index, const variant& item);
    friend void ains(variant&, int index, const variant& item);
    friend void adel(variant&, int index);
    friend const variant& aget(const variant&, int index);
    friend string akey(const variant&, int index);
    const variant& operator[](const char* key) const    { return get(*this, string(key)); }
    const variant& operator[](const string& key) const  { return get(*this, key); }
    const variant& operator[](large key) const          { return get(*this, key); }
    // 'manual' initialization/finalization, undocumented. use with care!
    friend void initialize(variant& v);
    friend void initialize(variant& v, large i);
    friend void initialize(variant& v, int i);
    friend void initialize(variant& v, unsigned int i);
    friend void initialize(variant& v, bool i);
    friend void initialize(variant& v, double i);
    friend void initialize(variant& v, const char* i);
    friend void initialize(variant& v, const string& i);
    friend void initialize(variant& v, component* i);
    friend void initialize(variant& v, const variant& i);
    friend void finalize(variant& v);
};
typedef variant* pvariant;
inline int  vartype(const variant& v)       { return v.tag; }
inline bool isnull(const variant& v)        { return v.tag == VAR_NULL; }
inline bool isint(const variant& v)         { return v.tag == VAR_INT; }
inline bool isbool(const variant& v)        { return v.tag == VAR_BOOL; }
inline bool isfloat(const variant& v)       { return v.tag == VAR_FLOAT; }
inline bool isstring(const variant& v)      { return v.tag == VAR_STRING; }
inline bool isarray(const variant& v)       { return v.tag == VAR_ARRAY; }
inline bool isobject(const variant& v)      { return v.tag == VAR_OBJECT; }
inline bool iscompound(const variant& v)    { return v.tag >= VAR_COMPOUND; }
inline void initialize(variant& v)                   { v.initialize(); }
inline void initialize(variant& v, large i)          { v.initialize(i); }
inline void initialize(variant& v, int i)            { v.initialize(large(i)); }
inline void initialize(variant& v, unsigned int i)   { v.initialize(large(i)); }
inline void initialize(variant& v, bool i)           { v.initialize(i); }
inline void initialize(variant& v, double i)         { v.initialize(i); }
inline void initialize(variant& v, const char* i)    { v.initialize(i); }
inline void initialize(variant& v, const string& i)  { v.initialize(i); }
inline void initialize(variant& v, component* i)     { v.initialize(i); }
inline void initialize(variant& v, const variant& i) { v.initialize(i); }
inline void finalize(variant& v)                     { if (v.tag >= VAR_COMPOUND) v.finalize(); }
extern const variant nullvar;
class evariant: public exception
{
protected:
public:
    evariant(const char* msg): exception(msg)  {}
    evariant(const string& msg): exception(msg)  {}
    virtual ~evariant();
};
#ifdef PTYPES19_COMPAT 
class objlist: public tobjlist<unknown>
{
public:
    objlist(bool ownobjects = false);
    virtual ~objlist();
};
inline int  length(const _objlist& s)                { return s.get_count(); }
inline void setlength(_objlist& s, int newcount)     { s.set_count(newcount); }
inline void pack(_objlist& s)                        { s.pack(); }
inline void clear(_objlist& s)                       { s.clear(); }
inline int  push(_objlist& s, unknown* obj)          { s.add(obj); return length(s) - 1; }
inline unknown* top(const _objlist& s)               { return (unknown*)s.top(); }
inline void ins(_objlist& s, int i, unknown* obj)    { s.ins(i, obj); }
inline int  add(_objlist& s, unknown* obj)           { s.add(obj); return length(s) - 1; }
inline void put(_objlist& s, int i, unknown* obj)    { s.put(i, obj); }
inline unknown* get(const _objlist& s, int i)        { return (unknown*)s[i]; }
inline unknown* pop(_objlist& s)                     { return (unknown*)s.pop(); }
inline void del(_objlist& s, int i)                  { s.del(i); }
inline int  indexof(const _objlist& s, unknown* obj) { return s.indexof(obj); }
class strlist: public tstrlist<unknown>
{
public:
    strlist(int flags = 0);
    virtual ~strlist();
};
inline int  length(const _strlist& s)                                { return s.get_count(); }
inline void clear(_strlist& s)                                       { s.clear(); }
inline void pack(_strlist& s)                                        { s.pack(); }
inline bool search(const _strlist& s, const char* key, int& i)       { return s.search(key, i); }
inline void ins(_strlist& s, int i, const string& key, unknown* obj) { s.ins(i, key, obj); }
inline int  add(_strlist& s, const string& key, unknown* obj)        { return s.add(key, obj); }
inline void put(_strlist& s, int i, const string& key, unknown* obj) { s.put(i, key, obj); }
inline void put(_strlist& s, int i, unknown* obj)                    { s.put(i, obj); }
inline unknown* get(const _strlist& s, int i)                        { return (unknown*)s[i]; }
inline const string& getstr(const _strlist& s, int i)                { return s.getkey(i); }
inline void del(_strlist& s, int i)                                  { s.del(i); }
inline int  find(const _strlist& s, const char* key)                 { return s.indexof(key); }
inline int  indexof(const _strlist& s, unknown* obj)                 { return s.indexof(obj); }
class strmap: public tstrlist<unknown>
{
public:
    strmap(int flags = 0);
    virtual ~strmap();
};
inline void     put(strmap& m, const string& key, unknown* obj)     { m.put(key, obj); }
inline unknown* get(const strmap& m, const char* key)               { return m[key]; }
inline void     del(strmap& m, const char* key)                     { m.del(key); }
template <class X> class tstrmap: public strmap
{
public:
    tstrmap(): strmap()  {}
    tstrmap(int iflags): strmap(iflags)  {}
    friend inline X* get(const tstrmap& m, const char* str)         { return (X*)PTYPES_NAMESPACE::get((const strmap&)m, str); }
    friend inline void put(tstrmap& m, const string& str, X* obj)   { unknown* t = obj; PTYPES_NAMESPACE::put(m, str, t); }
    X* operator[] (const char* str) const                           { return (X*)PTYPES_NAMESPACE::get(*this, str); }
};
inline int   length(const textmap& m)                           { return m.get_count(); }
inline void  clear(textmap& m)                                  { m.clear(); }
inline const string& get(const textmap& m, const string& k)     { return m.get(k); }
inline void  put(textmap& m, const string& k, const string& v)  { m.put(k, v); }
inline void  del(textmap& m, const string& k)                   { m.del(k); }
#endif 
#ifdef _MSC_VER 
#pragma warning(pop) 
#pragma pack(pop) 
#endif 
PTYPES_END
#endif