/*␊ |
*␊ |
* C++ Portable Types Library (PTypes)␊ |
* Version 2.1.1 Released 27-Jun-2007␊ |
*␊ |
* Copyright (C) 2001-2007 Hovik Melikyan␊ |
*␊ |
* http://www.melikyan.com/ptypes/␊ |
*␊ |
*/␊ |
␊ |
#ifndef __PTYPES_H__␊ |
#define __PTYPES_H__␊ |
␊ |
␊ |
#ifndef __PPORT_H__␊ |
#include "pport.h"␊ |
#endif␊ |
␊ |
#include <string.h>␊ |
#include <vector>␊ |
␊ |
␊ |
PTYPES_BEGIN␊ |
␊ |
␊ |
#ifdef _MSC_VER␊ |
#pragma pack(push, 4)␊ |
// disable "non dll-interface class '...' used as base for dll-interface class '...'" warning␊ |
#pragma warning(disable : 4275)␊ |
// disable "conditional expression constant" warning␊ |
#pragma warning(push)␊ |
#pragma warning(disable : 4127)␊ |
#endif␊ |
␊ |
␊ |
ptpublic int __PFASTCALL pincrement(int* target);␊ |
ptpublic int __PFASTCALL pdecrement(int* target);␊ |
ptpublic int __PFASTCALL pexchange(int* target, int value);␊ |
ptpublic 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) || defined(__hpux)␊ |
# define VARIANT_TYPECAST_HACK␊ |
#endif␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- string class --------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// dynamic string class with thread-safe ref-counted buffer␊ |
␊ |
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))␊ |
␊ |
␊ |
ptpublic extern char* emptystr;␊ |
␊ |
class ptpublic variant;␊ |
␊ |
␊ |
class ptpublic 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);␊ |
ptpublic friend char* ptdecl setlength(string&, int);␊ |
ptpublic friend char* ptdecl unique(string&);␊ |
ptpublic friend void ptdecl concat(string& s, const char* sc, int catlen);␊ |
ptpublic friend void ptdecl concat(string& s, const char* s1);␊ |
ptpublic friend void ptdecl concat(string& s, char s1);␊ |
ptpublic friend void ptdecl concat(string& s, const string& s1);␊ |
ptpublic friend string ptdecl copy(const string& s, int from, int cnt);␊ |
ptpublic friend string ptdecl copy(const string& s, int from);␊ |
ptpublic friend void ptdecl ins(const char* s1, int s1len, string& s, int at);␊ |
ptpublic friend void ptdecl ins(const char* s1, string& s, int at);␊ |
ptpublic friend void ptdecl ins(char s1, string& s, int at);␊ |
ptpublic friend void ptdecl ins(const string& s1, string& s, int at);␊ |
ptpublic friend void ptdecl del(string& s, int at, int cnt);␊ |
ptpublic friend void ptdecl del(string& s, int at);␊ |
ptpublic friend int ptdecl pos(const char* s1, const string& s);␊ |
ptpublic friend int ptdecl pos(char s1, const string& s);␊ |
friend int pos(const string& s1, const string& s);␊ |
ptpublic friend int ptdecl rpos(char s1, const string& s);␊ |
ptpublic friend bool ptdecl contains(const char* s1, int len, const string& s, int at);␊ |
ptpublic friend bool ptdecl contains(const char* s1, const string& s, int at);␊ |
ptpublic friend bool ptdecl contains(char s1, const string& s, int at);␊ |
ptpublic friend bool ptdecl contains(const string& s1, const string& s, int at);␊ |
ptpublic friend string ptdecl 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;␊ |
␊ |
ptpublic friend string ptdecl operator+ (const char* sc, const string& s);␊ |
ptpublic friend string ptdecl 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(); }␊ |
␊ |
␊ |
ptpublic extern int stralloc;␊ |
␊ |
ptpublic extern string nullstring;␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- string utilities ----------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
␊ |
ptpublic string ptdecl fill(int width, char pad);␊ |
ptpublic string ptdecl pad(const string& s, int width, char c, bool left = true);␊ |
␊ |
ptpublic string ptdecl itostring(large value, int base, int width = 0, char pad = 0);␊ |
ptpublic string ptdecl itostring(ularge value, int base, int width = 0, char pad = 0);␊ |
ptpublic string ptdecl itostring(int value, int base, int width = 0, char pad = 0);␊ |
ptpublic string ptdecl itostring(unsigned value, int base, int width = 0, char pad = 0);␊ |
ptpublic string ptdecl itostring(large v);␊ |
ptpublic string ptdecl itostring(ularge v);␊ |
ptpublic string ptdecl itostring(int v);␊ |
ptpublic string ptdecl itostring(unsigned v);␊ |
␊ |
ptpublic large ptdecl stringtoi(const char*);␊ |
ptpublic large ptdecl stringtoie(const char*);␊ |
ptpublic ularge ptdecl stringtoue(const char*, int base);␊ |
␊ |
ptpublic string ptdecl lowercase(const char* s);␊ |
ptpublic string ptdecl 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) // some Unix systems do not accept NULL␊ |
{ return p == nil ? 0 : (int)strlen(p); }␊ |
␊ |
␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- character set -------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
␊ |
const int _csetbits = 256;␊ |
const int _csetbytes = _csetbits / 8;␊ |
const int _csetwords = _csetbytes / sizeof(int);␊ |
const char _csetesc = '~';␊ |
␊ |
␊ |
class ptpublic 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);␊ |
␊ |
ptpublic friend string ptdecl 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); }␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- basic abstract classes ----------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// basic class with virtual destructor; historically was used as a base␊ |
// for all list items. also helps to count the number of created and␊ |
// destroyed objects in a program (objalloc global) in DEBUG mode, to␊ |
// detect memory leaks. most classes in ptypes are derived from unknown.␊ |
␊ |
ptpublic extern int objalloc;␊ |
␊ |
class ptpublic 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;␊ |
␊ |
␊ |
// provide non-copyable base for all classes that are␊ |
// not derived from 'unknown'␊ |
␊ |
class ptpublic noncopyable ␊ |
{␊ |
private:␊ |
noncopyable(const noncopyable&);␊ |
const noncopyable& operator= (const noncopyable&);␊ |
public:␊ |
noncopyable() {}␊ |
~noncopyable() {}␊ |
};␊ |
␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- exception ------------------------------------------------------ //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// the basic exception class. NOTE: the library always throws dynamically␊ |
// allocated exception objects.␊ |
␊ |
class ptpublic exception: public unknown ␊ |
{␊ |
protected:␊ |
string message;␊ |
public:␊ |
exception(const char* imsg);␊ |
exception(const string& imsg);␊ |
virtual ~exception();␊ |
virtual string get_message() { return message; }␊ |
};␊ |
␊ |
␊ |
// conversion exception class for stringtoie() and stringtoue()␊ |
␊ |
class ptpublic econv: public exception␊ |
{␊ |
public:␊ |
econv(const char* msg): exception(msg) {}␊ |
econv(const string& msg): exception(msg) {}␊ |
virtual ~econv();␊ |
};␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- tpodlist ------------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// _podlist implements dynamic array of small POD structures; it serves␊ |
// as a basis for all list types in the library. this class is undocumented.␊ |
// tpodlist template must be used instead.␊ |
␊ |
class _podlist: public noncopyable␊ |
{␊ |
protected:␊ |
void* list; // pointer to the array␊ |
int count; // number of items in the list␊ |
int capacity; // allocated for the list␊ |
int itemsize; // list item size␊ |
␊ |
/*#ifndef DEBUG␊ |
static␊ |
#endif*/␊ |
␉static void idxerror() { fatal(CRIT_FIRST + 30, "List index out of bounds"); }␊ |
␉//void idxerror() const { fatal(CRIT_FIRST + 30, "List index out of bounds"); }␊ |
␊ |
_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(); }␊ |
};␊ |
␊ |
␊ |
// tpodlist is a fully-inlined template based on _podlist␊ |
␊ |
template <class X, bool initzero = false> class ptpublic 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; }␊ |
␉~tpodlist() { }␊ |
␊ |
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); }␊ |
};␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- tobjlist ------------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// _objlist is a base for the tobjlist template, don't use it directly.␊ |
// also, _objlist is a base for _strlist and derivatives.␊ |
␊ |
class ptpublic _objlist: public unknown, protected tpodlist<void*, true>␊ |
{␊ |
protected:␊ |
struct␊ |
{␊ |
unsigned ownobjects :1; // list is responsible for destroying the items; used in _objlist␊ |
unsigned ownslobjects :1; // same but for _strlist items (in _stritem structure)␊ |
unsigned sorted :1; // sorted list (_objlist+)␊ |
unsigned duplicates :1; // sorted: allows duplicate keys (_objlist+)␊ |
unsigned casesens :1; // sorted: string comparison is case sensitive (_strlist+)␊ |
unsigned _reserved :27;␊ |
} config;␊ |
␊ |
_objlist(bool ownobjects);␉ // we hide this ctor, since _objlist actually can't free objects␊ |
␊ |
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); // pure method; defined in tobjlist instances␊ |
virtual int compare(const void* key, const void* obj) const; // pure method; defined in _strlist␊ |
␊ |
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;␊ |
};␊ |
␊ |
␊ |
// the tobjlist template implements a list of pointers to arbitrary␊ |
// structures. optionally can automatically free objects (ownobjects)␊ |
// when removed from a list. only 2 virtual functions are being␊ |
// instantiated by this template, the rest is static code in _objlist.␊ |
␊ |
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);␊ |
}␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- tstrlist ------------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// _strlist is a base for the tstrlist template␊ |
␊ |
␊ |
typedef int slflags; // left for compatibility␊ |
␊ |
#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 ptpublic _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); // pure; tstrlist overrides it␊ |
␊ |
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;␊ |
};␊ |
␊ |
␊ |
// the tstrlist template implements a list of string/object pairs,␊ |
// optionally sorted for fast searching by string key.␊ |
␊ |
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);␊ |
}␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- textmap -------------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// textmap is a list of string pairs (key/value)␊ |
␊ |
struct _textitem␊ |
{␊ |
string key;␊ |
string value;␊ |
␊ |
_textitem(const string& ikey, const string& ivalue)␊ |
: key(ikey), value(ivalue) {}␊ |
};␊ |
␊ |
␊ |
class ptpublic 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;␊ |
};␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- component ------------------------------------------------------ //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
// the component class is an abstract class that provides reference␊ |
// counting and delete notification mechanisms. all stream classes␊ |
// in ptypes are derived from component.␊ |
␊ |
// class ID's for all basic types: the first byte (least significant)␊ |
// contains the base ID, the next is for the second level of inheritance,␊ |
// etc. total of 4 levels allowed for basic types. call classid() for an␊ |
// object, mask out first N bytes of interest and compare with a CLASS_XXX␊ |
// value. f.ex. to determine whether an object is of type infile or any␊ |
// derivative: (o->classid() & 0xffff) == CLASS2_INFILE. this scheme is for␊ |
// internal use by PTypes and Objection; partly replaces the costly C++ RTTI␊ |
// system.␊ |
␊ |
// first level of inheritance␊ |
const int CLASS_UNDEFINED = 0x00000000;␊ |
const int CLASS_INSTM = 0x00000001;␊ |
const int CLASS_OUTSTM = 0x00000002;␊ |
const int CLASS_UNIT = 0x00000003;␊ |
␊ |
// second level of inheritance␊ |
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;␊ |
␊ |
// third level of inheritance␊ |
const int CLASS3_LOGFILE = 0x00010000 | CLASS2_OUTFILE;␊ |
const int CLASS3_IPSTM = 0x00020000 | CLASS2_FDX;␊ |
const int CLASS3_NPIPE = 0x00030000 | CLASS2_FDX;␊ |
␊ |
␊ |
class ptpublic component: public unknown ␊ |
{␊ |
protected:␊ |
int refcount; // reference counting, used by addref() and release()␊ |
tobjlist<component>* freelist; // list of components to notify about destruction, safer alternative to ref-counting␊ |
void* typeinfo; // reserved for future use␊ |
␊ |
virtual void freenotify(component* sender);␊ |
␊ |
public:␊ |
component();␊ |
virtual ~component();␊ |
void addnotification(component* obj);␊ |
void delnotification(component* obj);␊ |
␊ |
ptpublic friend component* ptdecl addref(component*);␊ |
ptpublic friend bool ptdecl 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;␊ |
}␊ |
␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- variant -------------------------------------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
␊ |
enum {␊ |
VAR_NULL,␊ |
VAR_INT,␊ |
VAR_BOOL,␊ |
VAR_FLOAT,␊ |
VAR_STRING,␊ |
VAR_ARRAY,␊ |
VAR_OBJECT,␊ |
␊ |
VAR_COMPOUND = VAR_STRING␊ |
};␊ |
␊ |
␊ |
class ptpublic _varray;␊ |
␊ |
␊ |
class ptpublic variant␊ |
{␊ |
friend class string;␊ |
friend class _varray;␊ |
␊ |
protected:␊ |
int tag; // VAR_XXX␊ |
union {␊ |
large i; // 64-bit int value␊ |
bool b; // bool value␊ |
double f; // double value␊ |
char* s; // string object; can't declare as string because of the union␊ |
_varray* a; // pointer to a reference-counted _strlist object␊ |
component* o; // pointer to a reference-counted component object (or derivative)␊ |
} value; // we need this name to be able to copy the entire union in some situations␊ |
␊ |
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␊ |
ptpublic friend void ptdecl 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␊ |
ptpublic friend void ptdecl aclear(variant&);␊ |
ptpublic friend variant ptdecl aclone(const variant&);␊ |
ptpublic friend const variant& ptdecl get(const variant&, const string& key);␊ |
ptpublic friend const variant& ptdecl get(const variant&, large key);␊ |
ptpublic friend void ptdecl put(variant&, const string& key, const variant& item);␊ |
ptpublic friend void ptdecl put(variant&, large key, const variant& item);␊ |
ptpublic friend void ptdecl del(variant&, const string& key);␊ |
ptpublic friend void ptdecl del(variant&, large key);␊ |
␉ptpublic friend void ptdecl add(variant & v, const variant & var);␊ |
␊ |
// indexed access to arrays␊ |
ptpublic friend int ptdecl alength(const variant&);␊ |
ptpublic friend void ptdecl apack(variant&);␊ |
ptpublic friend bool ptdecl anext(const variant& a, int&, variant& item);␊ |
ptpublic friend bool ptdecl anext(const variant& a, int&, variant& item, string& key);␊ |
ptpublic friend int ptdecl aadd(variant&, const variant& item);␊ |
ptpublic friend void ptdecl aput(variant&, int index, const variant& item);␊ |
ptpublic friend void ptdecl ains(variant&, int index, const variant& item);␊ |
ptpublic friend void ptdecl adel(variant&, int index);␊ |
ptpublic friend const variant& ptdecl aget(const variant&, int index);␊ |
ptpublic friend string ptdecl 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(); }␊ |
␊ |
␊ |
ptpublic extern const variant nullvar;␊ |
␊ |
␊ |
// variant exception class; may be thrown when a variant␊ |
// is being typecast'ed to 32-bit int and the value is␊ |
// out of range␊ |
␊ |
class ptpublic evariant: public exception␊ |
{␊ |
protected:␊ |
public:␊ |
evariant(const char* msg): exception(msg) {}␊ |
evariant(const string& msg): exception(msg) {}␊ |
virtual ~evariant();␊ |
};␊ |
␊ |
/*␊ |
Added by Nathan Adams - the following is not apart of the original ptypes␊ |
*/␊ |
␊ |
enum {␊ |
␉ARR_ASSOCIATIVE,␊ |
␉ARR_LIST,␊ |
␉ARR_NULL␊ |
};␊ |
␊ |
/*␊ |
␉The reason for a tparray is that while a variant can be an␊ |
␉associative array - it stores numeric keys as hex strings␊ |
␉this can be very problematic if you want to loop through␊ |
␉all the elements and know if a given key was a number.␊ |
␉(For example for JSON encoding)␊ |
␊ |
␉A tparray uses a variant for both the keys/values so␊ |
␉this really opens it up to a wide range of uses. Also,␊ |
␉it performs no conversions on the data so when you loop␊ |
␉through all the keys/vals they are what you stored them as.␊ |
␊ |
␉This object's complexity is O(n) and it could in theory be better␊ |
␉by sectioning off the arrays such that␊ |
␉-------------------------------------------------------␊ |
␉| string | string | string | number | number | number |␊ |
␉-------------------------------------------------------␊ |
␉This would increase the complexity of adding items, and␊ |
␉if you don't have a very diverse number of items them you␊ |
␉may not benefit much from the algorithm.␊ |
␊ |
*/␊ |
class ptpublic tparray : public component␊ |
{␊ |
protected:␊ |
␉int tag;␊ |
␉// using a tpodlist was causing variant data corrupt errors␊ |
␉// perhaps it has to do with the issue of the converting to pointers␊ |
␉// TODO: Write dynamic array class␊ |
␉//std::vector<variant> _keys;␊ |
␉//std::vector<variant> _vals;␊ |
␉variant _keys;␊ |
␉variant _vals;␊ |
␉//tpodlist<variant> _keys;␊ |
␉//tpodlist<variant> _vals;␊ |
public:␊ |
␉tparray() { tag = ARR_NULL; }␊ |
␉//anext function acts similar for variants and loops through elements␊ |
␊ |
␉// This is allowed for both types␊ |
␉ptpublic friend bool ptdecl anext(const tparray& a, int& i, variant& val);␊ |
␊ |
␉// This is only allowed for Associative arrays as a list doesn't have keys␊ |
␉ptpublic friend bool ptdecl anext(const tparray& a, int& i, variant& val, variant & key);␊ |
␊ |
␉/*␊ |
␉␉Initialy the object will be NULL - but calling one of these functions␊ |
␉␉will change the type (permanently)␊ |
␉*/␊ |
␉ptpublic friend void ptdecl add(tparray & t, const variant & val);␊ |
␉ptpublic friend void ptdecl add(tparray & t, const variant & key, const variant & val);␊ |
␊ |
␉// get will perform a O(n) search for the matching variant in the keys array␊ |
␉ptpublic friend variant ptdecl get(tparray & t, const variant & val);␊ |
␊ |
␉// This will return the value at the given index␊ |
␉ptpublic friend variant ptdecl at(tparray & t, large index);␊ |
␊ |
␉// This will return the key at the given index␊ |
␉ptpublic friend variant ptdecl keyat(tparray & t, large index);␊ |
␊ |
␉friend bool isassoc(const tparray& t);␊ |
␉friend bool islist(const tparray& t);␊ |
␉friend bool isnull(const tparray& t);␊ |
};␊ |
␊ |
inline bool isassoc(const tparray& t) { return t.tag == ARR_ASSOCIATIVE; }␊ |
inline bool islist(const tparray& t) { return t.tag == ARR_LIST; }␊ |
inline bool isnull(const tparray& t) { return t.tag == ARR_NULL; }␊ |
␊ |
␊ |
/*␍␊ |
*␍␊ |
* C++ Portable Types Library (PTypes)␍␊ |
* Version 2.1.1 Released 27-Jun-2007␍␊ |
*␍␊ |
* Copyright (C) 2001-2007 Hovik Melikyan␍␊ |
*␍␊ |
* http://www.melikyan.com/ptypes/␍␊ |
*␍␊ |
*/␍␊ |
␍␊ |
#ifndef __PTYPES_H__␍␊ |
#define __PTYPES_H__␍␊ |
␍␊ |
␍␊ |
#ifndef __PPORT_H__␍␊ |
#include "pport.h"␍␊ |
#endif␍␊ |
␍␊ |
#include <string.h>␍␊ |
#include <vector>␍␊ |
␍␊ |
␍␊ |
PTYPES_BEGIN␍␊ |
␍␊ |
␍␊ |
#ifdef _MSC_VER␍␊ |
#pragma pack(push, 4)␍␊ |
// disable "non dll-interface class '...' used as base for dll-interface class '...'" warning␍␊ |
#pragma warning(disable : 4275)␍␊ |
// disable "conditional expression constant" warning␍␊ |
#pragma warning(push)␍␊ |
#pragma warning(disable : 4127)␍␊ |
#endif␍␊ |
␍␊ |
␍␊ |
ptpublic int __PFASTCALL pincrement(int* target);␍␊ |
ptpublic int __PFASTCALL pdecrement(int* target);␍␊ |
ptpublic int __PFASTCALL pexchange(int* target, int value);␍␊ |
ptpublic 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) || defined(__hpux)␍␊ |
# define VARIANT_TYPECAST_HACK␍␊ |
#endif␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- string class --------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// dynamic string class with thread-safe ref-counted buffer␍␊ |
␍␊ |
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))␍␊ |
␍␊ |
␍␊ |
ptpublic extern char* emptystr;␍␊ |
␍␊ |
class ptpublic variant;␍␊ |
␍␊ |
␍␊ |
class ptpublic 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);␍␊ |
ptpublic friend char* ptdecl setlength(string&, int);␍␊ |
ptpublic friend char* ptdecl unique(string&);␍␊ |
ptpublic friend void ptdecl concat(string& s, const char* sc, int catlen);␍␊ |
ptpublic friend void ptdecl concat(string& s, const char* s1);␍␊ |
ptpublic friend void ptdecl concat(string& s, char s1);␍␊ |
ptpublic friend void ptdecl concat(string& s, const string& s1);␍␊ |
ptpublic friend string ptdecl copy(const string& s, int from, int cnt);␍␊ |
ptpublic friend string ptdecl copy(const string& s, int from);␍␊ |
ptpublic friend void ptdecl ins(const char* s1, int s1len, string& s, int at);␍␊ |
ptpublic friend void ptdecl ins(const char* s1, string& s, int at);␍␊ |
ptpublic friend void ptdecl ins(char s1, string& s, int at);␍␊ |
ptpublic friend void ptdecl ins(const string& s1, string& s, int at);␍␊ |
ptpublic friend void ptdecl del(string& s, int at, int cnt);␍␊ |
ptpublic friend void ptdecl del(string& s, int at);␍␊ |
ptpublic friend int ptdecl pos(const char* s1, const string& s);␍␊ |
ptpublic friend int ptdecl pos(char s1, const string& s);␍␊ |
friend int pos(const string& s1, const string& s);␍␊ |
ptpublic friend int ptdecl rpos(char s1, const string& s);␍␊ |
ptpublic friend bool ptdecl contains(const char* s1, int len, const string& s, int at);␍␊ |
ptpublic friend bool ptdecl contains(const char* s1, const string& s, int at);␍␊ |
ptpublic friend bool ptdecl contains(char s1, const string& s, int at);␍␊ |
ptpublic friend bool ptdecl contains(const string& s1, const string& s, int at);␍␊ |
ptpublic friend string ptdecl 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;␍␊ |
␍␊ |
ptpublic friend string ptdecl operator+ (const char* sc, const string& s);␍␊ |
ptpublic friend string ptdecl 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(); }␍␊ |
␍␊ |
␍␊ |
ptpublic extern int stralloc;␍␊ |
␍␊ |
ptpublic extern string nullstring;␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- string utilities ----------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
␍␊ |
ptpublic string ptdecl fill(int width, char pad);␍␊ |
ptpublic string ptdecl pad(const string& s, int width, char c, bool left = true);␍␊ |
␍␊ |
ptpublic string ptdecl itostring(large value, int base, int width = 0, char pad = 0);␍␊ |
ptpublic string ptdecl itostring(ularge value, int base, int width = 0, char pad = 0);␍␊ |
ptpublic string ptdecl itostring(int value, int base, int width = 0, char pad = 0);␍␊ |
ptpublic string ptdecl itostring(unsigned value, int base, int width = 0, char pad = 0);␍␊ |
ptpublic string ptdecl itostring(large v);␍␊ |
ptpublic string ptdecl itostring(ularge v);␍␊ |
ptpublic string ptdecl itostring(int v);␍␊ |
ptpublic string ptdecl itostring(unsigned v);␍␊ |
␍␊ |
ptpublic large ptdecl stringtoi(const char*);␍␊ |
ptpublic large ptdecl stringtoie(const char*);␍␊ |
ptpublic ularge ptdecl stringtoue(const char*, int base);␍␊ |
␍␊ |
ptpublic string ptdecl lowercase(const char* s);␍␊ |
ptpublic string ptdecl 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) // some Unix systems do not accept NULL␍␊ |
{ return p == nil ? 0 : (int)strlen(p); }␍␊ |
␍␊ |
␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- character set -------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
␍␊ |
const int _csetbits = 256;␍␊ |
const int _csetbytes = _csetbits / 8;␍␊ |
const int _csetwords = _csetbytes / sizeof(int);␍␊ |
const char _csetesc = '~';␍␊ |
␍␊ |
␍␊ |
class ptpublic 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);␍␊ |
␍␊ |
ptpublic friend string ptdecl 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); }␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- basic abstract classes ----------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// basic class with virtual destructor; historically was used as a base␍␊ |
// for all list items. also helps to count the number of created and␍␊ |
// destroyed objects in a program (objalloc global) in DEBUG mode, to␍␊ |
// detect memory leaks. most classes in ptypes are derived from unknown.␍␊ |
␍␊ |
ptpublic extern int objalloc;␍␊ |
␍␊ |
class ptpublic 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;␍␊ |
␍␊ |
␍␊ |
// provide non-copyable base for all classes that are␍␊ |
// not derived from 'unknown'␍␊ |
␍␊ |
class ptpublic noncopyable ␍␊ |
{␍␊ |
private:␍␊ |
noncopyable(const noncopyable&);␍␊ |
const noncopyable& operator= (const noncopyable&);␍␊ |
public:␍␊ |
noncopyable() {}␍␊ |
~noncopyable() {}␍␊ |
};␍␊ |
␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- exception ------------------------------------------------------ //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// the basic exception class. NOTE: the library always throws dynamically␍␊ |
// allocated exception objects.␍␊ |
␍␊ |
class ptpublic exception: public unknown ␍␊ |
{␍␊ |
protected:␍␊ |
string message;␍␊ |
public:␍␊ |
exception(const char* imsg);␍␊ |
exception(const string& imsg);␍␊ |
virtual ~exception();␍␊ |
virtual string get_message() { return message; }␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// conversion exception class for stringtoie() and stringtoue()␍␊ |
␍␊ |
class ptpublic econv: public exception␍␊ |
{␍␊ |
public:␍␊ |
econv(const char* msg): exception(msg) {}␍␊ |
econv(const string& msg): exception(msg) {}␍␊ |
virtual ~econv();␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- tpodlist ------------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// _podlist implements dynamic array of small POD structures; it serves␍␊ |
// as a basis for all list types in the library. this class is undocumented.␍␊ |
// tpodlist template must be used instead.␍␊ |
␍␊ |
class _podlist: public noncopyable␍␊ |
{␍␊ |
protected:␍␊ |
void* list; // pointer to the array␍␊ |
int count; // number of items in the list␍␊ |
int capacity; // allocated for the list␍␊ |
int itemsize; // list item size␍␊ |
␍␊ |
/*#ifndef DEBUG␍␊ |
static␍␊ |
#endif*/␍␊ |
␉static void idxerror();␍␊ |
␉//void idxerror() const { fatal(CRIT_FIRST + 30, "List index out of bounds"); }␍␊ |
␍␊ |
_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(); }␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// tpodlist is a fully-inlined template based on _podlist␍␊ |
␍␊ |
template <class X, bool initzero = false> class ptpublic 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; }␍␊ |
␉~tpodlist() { }␍␊ |
␍␊ |
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); }␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- tobjlist ------------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// _objlist is a base for the tobjlist template, don't use it directly.␍␊ |
// also, _objlist is a base for _strlist and derivatives.␍␊ |
␍␊ |
class ptpublic _objlist: public unknown, protected tpodlist<void*, true>␍␊ |
{␍␊ |
protected:␍␊ |
struct␍␊ |
{␍␊ |
unsigned ownobjects :1; // list is responsible for destroying the items; used in _objlist␍␊ |
unsigned ownslobjects :1; // same but for _strlist items (in _stritem structure)␍␊ |
unsigned sorted :1; // sorted list (_objlist+)␍␊ |
unsigned duplicates :1; // sorted: allows duplicate keys (_objlist+)␍␊ |
unsigned casesens :1; // sorted: string comparison is case sensitive (_strlist+)␍␊ |
unsigned _reserved :27;␍␊ |
} config;␍␊ |
␍␊ |
_objlist(bool ownobjects);␉ // we hide this ctor, since _objlist actually can't free objects␍␊ |
␍␊ |
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); // pure method; defined in tobjlist instances␍␊ |
virtual int compare(const void* key, const void* obj) const; // pure method; defined in _strlist␍␊ |
␍␊ |
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;␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// the tobjlist template implements a list of pointers to arbitrary␍␊ |
// structures. optionally can automatically free objects (ownobjects)␍␊ |
// when removed from a list. only 2 virtual functions are being␍␊ |
// instantiated by this template, the rest is static code in _objlist.␍␊ |
␍␊ |
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);␍␊ |
}␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- tstrlist ------------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// _strlist is a base for the tstrlist template␍␊ |
␍␊ |
␍␊ |
typedef int slflags; // left for compatibility␍␊ |
␍␊ |
#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 ptpublic _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); // pure; tstrlist overrides it␍␊ |
␍␊ |
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;␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// the tstrlist template implements a list of string/object pairs,␍␊ |
// optionally sorted for fast searching by string key.␍␊ |
␍␊ |
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);␍␊ |
}␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- textmap -------------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// textmap is a list of string pairs (key/value)␍␊ |
␍␊ |
struct _textitem␍␊ |
{␍␊ |
string key;␍␊ |
string value;␍␊ |
␍␊ |
_textitem(const string& ikey, const string& ivalue)␍␊ |
: key(ikey), value(ivalue) {}␍␊ |
};␍␊ |
␍␊ |
␍␊ |
class ptpublic 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;␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- component ------------------------------------------------------ //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
// the component class is an abstract class that provides reference␍␊ |
// counting and delete notification mechanisms. all stream classes␍␊ |
// in ptypes are derived from component.␍␊ |
␍␊ |
// class ID's for all basic types: the first byte (least significant)␍␊ |
// contains the base ID, the next is for the second level of inheritance,␍␊ |
// etc. total of 4 levels allowed for basic types. call classid() for an␍␊ |
// object, mask out first N bytes of interest and compare with a CLASS_XXX␍␊ |
// value. f.ex. to determine whether an object is of type infile or any␍␊ |
// derivative: (o->classid() & 0xffff) == CLASS2_INFILE. this scheme is for␍␊ |
// internal use by PTypes and Objection; partly replaces the costly C++ RTTI␍␊ |
// system.␍␊ |
␍␊ |
// first level of inheritance␍␊ |
const int CLASS_UNDEFINED = 0x00000000;␍␊ |
const int CLASS_INSTM = 0x00000001;␍␊ |
const int CLASS_OUTSTM = 0x00000002;␍␊ |
const int CLASS_UNIT = 0x00000003;␍␊ |
␍␊ |
// second level of inheritance␍␊ |
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;␍␊ |
␍␊ |
// third level of inheritance␍␊ |
const int CLASS3_LOGFILE = 0x00010000 | CLASS2_OUTFILE;␍␊ |
const int CLASS3_IPSTM = 0x00020000 | CLASS2_FDX;␍␊ |
const int CLASS3_NPIPE = 0x00030000 | CLASS2_FDX;␍␊ |
␍␊ |
␍␊ |
class ptpublic component: public unknown ␍␊ |
{␍␊ |
protected:␍␊ |
int refcount; // reference counting, used by addref() and release()␍␊ |
tobjlist<component>* freelist; // list of components to notify about destruction, safer alternative to ref-counting␍␊ |
void* typeinfo; // reserved for future use␍␊ |
␍␊ |
virtual void freenotify(component* sender);␍␊ |
␍␊ |
public:␍␊ |
component();␍␊ |
virtual ~component();␍␊ |
void addnotification(component* obj);␍␊ |
void delnotification(component* obj);␍␊ |
␍␊ |
ptpublic friend component* ptdecl addref(component*);␍␊ |
ptpublic friend bool ptdecl 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;␍␊ |
}␍␊ |
␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- variant -------------------------------------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
␍␊ |
enum {␍␊ |
VAR_NULL,␍␊ |
VAR_INT,␍␊ |
VAR_BOOL,␍␊ |
VAR_FLOAT,␍␊ |
VAR_STRING,␍␊ |
VAR_ARRAY,␍␊ |
VAR_OBJECT,␍␊ |
␍␊ |
VAR_COMPOUND = VAR_STRING␍␊ |
};␍␊ |
␍␊ |
␍␊ |
class ptpublic _varray;␍␊ |
␍␊ |
␍␊ |
class ptpublic variant␍␊ |
{␍␊ |
friend class string;␍␊ |
friend class _varray;␍␊ |
␍␊ |
protected:␍␊ |
int tag; // VAR_XXX␍␊ |
union {␍␊ |
large i; // 64-bit int value␍␊ |
bool b; // bool value␍␊ |
double f; // double value␍␊ |
char* s; // string object; can't declare as string because of the union␍␊ |
_varray* a; // pointer to a reference-counted _strlist object␍␊ |
component* o; // pointer to a reference-counted component object (or derivative)␍␊ |
} value; // we need this name to be able to copy the entire union in some situations␍␊ |
␍␊ |
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␍␊ |
ptpublic friend void ptdecl 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␍␊ |
ptpublic friend void ptdecl aclear(variant&);␍␊ |
ptpublic friend variant ptdecl aclone(const variant&);␍␊ |
ptpublic friend const variant& ptdecl get(const variant&, const string& key);␍␊ |
ptpublic friend const variant& ptdecl get(const variant&, large key);␍␊ |
ptpublic friend void ptdecl put(variant&, const string& key, const variant& item);␍␊ |
ptpublic friend void ptdecl put(variant&, large key, const variant& item);␍␊ |
ptpublic friend void ptdecl del(variant&, const string& key);␍␊ |
ptpublic friend void ptdecl del(variant&, large key);␍␊ |
␉ptpublic friend void ptdecl add(variant & v, const variant & var);␍␊ |
␍␊ |
// indexed access to arrays␍␊ |
ptpublic friend int ptdecl alength(const variant&);␍␊ |
ptpublic friend void ptdecl apack(variant&);␍␊ |
ptpublic friend bool ptdecl anext(const variant& a, int&, variant& item);␍␊ |
ptpublic friend bool ptdecl anext(const variant& a, int&, variant& item, string& key);␍␊ |
ptpublic friend int ptdecl aadd(variant&, const variant& item);␍␊ |
ptpublic friend void ptdecl aput(variant&, int index, const variant& item);␍␊ |
ptpublic friend void ptdecl ains(variant&, int index, const variant& item);␍␊ |
ptpublic friend void ptdecl adel(variant&, int index);␍␊ |
ptpublic friend const variant& ptdecl aget(const variant&, int index);␍␊ |
ptpublic friend string ptdecl 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(); }␍␊ |
␍␊ |
␍␊ |
ptpublic extern const variant nullvar;␍␊ |
␍␊ |
␍␊ |
// variant exception class; may be thrown when a variant␍␊ |
// is being typecast'ed to 32-bit int and the value is␍␊ |
// out of range␍␊ |
␍␊ |
class ptpublic evariant: public exception␍␊ |
{␍␊ |
protected:␍␊ |
public:␍␊ |
evariant(const char* msg): exception(msg) {}␍␊ |
evariant(const string& msg): exception(msg) {}␍␊ |
virtual ~evariant();␍␊ |
};␍␊ |
␍␊ |
/*␍␊ |
Added by Nathan Adams - the following is not apart of the original ptypes␍␊ |
*/␍␊ |
␍␊ |
enum {␍␊ |
␉ARR_ASSOCIATIVE,␍␊ |
␉ARR_LIST,␍␊ |
␉ARR_NULL␍␊ |
};␍␊ |
␍␊ |
/*␍␊ |
␉The reason for a tparray is that while a variant can be an␍␊ |
␉associative array - it stores numeric keys as hex strings␍␊ |
␉this can be very problematic if you want to loop through␍␊ |
␉all the elements and know if a given key was a number.␍␊ |
␉(For example for JSON encoding)␍␊ |
␍␊ |
␉A tparray uses a variant for both the keys/values so␍␊ |
␉this really opens it up to a wide range of uses. Also,␍␊ |
␉it performs no conversions on the data so when you loop␍␊ |
␉through all the keys/vals they are what you stored them as.␍␊ |
␍␊ |
␉This object's complexity is O(n) and it could in theory be better␍␊ |
␉by sectioning off the arrays such that␍␊ |
␉-------------------------------------------------------␍␊ |
␉| string | string | string | number | number | number |␍␊ |
␉-------------------------------------------------------␍␊ |
␉This would increase the complexity of adding items, and␍␊ |
␉if you don't have a very diverse number of items them you␍␊ |
␉may not benefit much from the algorithm.␍␊ |
␍␊ |
*/␍␊ |
class ptpublic tparray : public component␍␊ |
{␍␊ |
protected:␍␊ |
␉int tag;␍␊ |
␉// using a tpodlist was causing variant data corrupt errors␍␊ |
␉// perhaps it has to do with the issue of the converting to pointers␍␊ |
␉// TODO: Write dynamic array class␍␊ |
␉//std::vector<variant> _keys;␍␊ |
␉//std::vector<variant> _vals;␍␊ |
␉variant _keys;␍␊ |
␉variant _vals;␍␊ |
␉//tpodlist<variant> _keys;␍␊ |
␉//tpodlist<variant> _vals;␍␊ |
public:␍␊ |
␉tparray() { tag = ARR_NULL; }␍␊ |
␉//anext function acts similar for variants and loops through elements␍␊ |
␍␊ |
␉// This is allowed for both types␍␊ |
␉ptpublic friend bool ptdecl anext(const tparray& a, int& i, variant& val);␍␊ |
␍␊ |
␉// This is only allowed for Associative arrays as a list doesn't have keys␍␊ |
␉ptpublic friend bool ptdecl anext(const tparray& a, int& i, variant& val, variant & key);␍␊ |
␍␊ |
␉/*␍␊ |
␉␉Initialy the object will be NULL - but calling one of these functions␍␊ |
␉␉will change the type (permanently)␍␊ |
␉*/␍␊ |
␉ptpublic friend void ptdecl add(tparray & t, const variant & val);␍␊ |
␉ptpublic friend void ptdecl add(tparray & t, const variant & key, const variant & val);␍␊ |
␍␊ |
␉// get will perform a O(n) search for the matching variant in the keys array␍␊ |
␉ptpublic friend variant ptdecl get(tparray & t, const variant & val);␍␊ |
␍␊ |
␉// This will return the value at the given index␍␊ |
␉ptpublic friend variant ptdecl at(tparray & t, large index);␍␊ |
␍␊ |
␉// This will return the key at the given index␍␊ |
␉ptpublic friend variant ptdecl keyat(tparray & t, large index);␍␊ |
␍␊ |
␉friend bool isassoc(const tparray& t);␍␊ |
␉friend bool islist(const tparray& t);␍␊ |
␉friend bool isnull(const tparray& t);␍␊ |
};␍␊ |
␍␊ |
inline bool isassoc(const tparray& t) { return t.tag == ARR_ASSOCIATIVE; }␍␊ |
inline bool islist(const tparray& t) { return t.tag == ARR_LIST; }␍␊ |
inline bool isnull(const tparray& t) { return t.tag == ARR_NULL; }␍␊ |
␍␊ |
␍␊ |
//http://stackoverflow.com/a/7936901/195722␍␊ |
template<typename T> class ByRef {␍␊ |
public:␍␊ |
|
␍␊ |
private:␍␊ |
T mValue;␍␊ |
};␊ |
␊ |
␊ |
};␍␊ |
␍␊ |
␍␊ |
class json␍␊ |
{␍␊ |
␉␉␍␊ |
|
␉␉␉variant JsonDecode(const string & json, bool & success = ByRef<bool>(true));␍␊ |
␉␉␉string JsonEncode(const variant & v);␍␊ |
␍␊ |
};␊ |
␊ |
// -------------------------------------------------------------------- //␊ |
// --- pre-2.0 compatibility declarations ----------------------------- //␊ |
// -------------------------------------------------------------------- //␊ |
␊ |
␊ |
#ifdef PTYPES19_COMPAT␊ |
␊ |
// ptypes-1.9 objlist and strlist: accept only 'unknown' and␊ |
// derivatives as a base type␊ |
␊ |
class ptpublic 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 ptpublic 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); }␊ |
␊ |
␊ |
// ptypes-1.9 strmap: now replaced with _strlist(SL_SORTED)␊ |
␊ |
class ptpublic 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); }␊ |
};␊ |
␊ |
␊ |
// ptypes-1.9 textmap interface␊ |
␊ |
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 // PTYPES19_COMPAT␊ |
␊ |
␊ |
#ifdef _MSC_VER␊ |
#pragma warning(pop)␊ |
#pragma pack(pop)␊ |
#endif␊ |
␊ |
␊ |
PTYPES_END␊ |
␊ |
#endif // __PTYPES_H__␊ |
};␍␊ |
␍␊ |
// -------------------------------------------------------------------- //␍␊ |
// --- pre-2.0 compatibility declarations ----------------------------- //␍␊ |
// -------------------------------------------------------------------- //␍␊ |
␍␊ |
␍␊ |
#ifdef PTYPES19_COMPAT␍␊ |
␍␊ |
// ptypes-1.9 objlist and strlist: accept only 'unknown' and␍␊ |
// derivatives as a base type␍␊ |
␍␊ |
class ptpublic 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 ptpublic 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); }␍␊ |
␍␊ |
␍␊ |
// ptypes-1.9 strmap: now replaced with _strlist(SL_SORTED)␍␊ |
␍␊ |
class ptpublic 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); }␍␊ |
};␍␊ |
␍␊ |
␍␊ |
// ptypes-1.9 textmap interface␍␊ |
␍␊ |
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 // PTYPES19_COMPAT␍␊ |
␍␊ |
␍␊ |
#ifdef _MSC_VER␍␊ |
#pragma warning(pop)␍␊ |
#pragma pack(pop)␍␊ |
#endif␍␊ |
␍␊ |
␍␊ |
PTYPES_END␍␊ |
␍␊ |
#endif // __PTYPES_H__␍␊ |