⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pvariant.cxx

📁 PTypes是一个扩充了多线程和网络功能的STL库
💻 CXX
字号:
/* * *  C++ Portable Types Library (PTypes) *  Version 2.0.2  Released 17-May-2004 * *  Copyright (C) 2001-2004 Hovik Melikyan * *  http://www.melikyan.com/ptypes/ * */#include <stdlib.h>#include <stdio.h>#include <limits.h>#include "ptypes.h"PTYPES_BEGINconst variant nullvar;struct _varitem{    string key;    variant var;    _varitem(const string& ikey, const variant& ivar): key(ikey), var(ivar) {}};typedef _varitem* pvaritem;class ptpublic _varray: protected tobjlist<_varitem>{protected:    int refcount;    virtual int _varray::compare(const void* key, const void* item) const;    friend class variant;public:    _varray();    _varray(const _varray& a);    virtual ~_varray();    int get_count()                                     { return tobjlist<_varitem>::get_count(); }    void clear()                                        { tobjlist<_varitem>::clear(); }    void pack()                                         { tobjlist<_varitem>::pack(); }    _varitem* doget(int index) const                    { return tobjlist<_varitem>::doget(index); }    const variant& get(int index) const                 { if (unsigned(index) < unsigned(count)) return doget(index)->var; else return nullvar; }    const string& getkey(int index) const               { if (unsigned(index) < unsigned(count)) return doget(index)->key; else return nullstring; }    const variant& get(const char* key) const;    int put(const string& key, const variant& var);    void put(int index, const variant& var)             { if (unsigned(index) < unsigned(count)) doget(index)->var = var; }    void ins(int index, const variant& var)             { if (unsigned(index) < unsigned(count)) doins(index, new _varitem(nullstring, var)); }    int addvar(const variant& var);    void del(int index)                                 { if (unsigned(index) < unsigned(count)) dodel(index); }    void del(const string& key)                         { put(key, nullstring); }};typedef _varray* pvarray;_varray::_varray()    : tobjlist<_varitem>(true), refcount(0){    config.sorted = true;    config.casesens = true;}_varray::_varray(const _varray& a)    : tobjlist<_varitem>(true), refcount(0){    config.sorted = true;    config.casesens = true;    set_capacity(a.count);    for (int i = 0; i < a.count; i++)    {        _varitem* v = a.doget(i);        doins(i, new _varitem(v->key, v->var));    }}_varray::~_varray(){}int _varray::compare(const void* key, const void* item) const{   if (config.casesens)        return strcmp(pconst(key), pvaritem(item)->key);    else        return strcasecmp(pconst(key), pvaritem(item)->key);}const variant& _varray::get(const char* key) const{    int index;    if (search(key, index))        return doget(index)->var;    else        return nullvar;}int _varray::put(const string& key, const variant& var){    int index;    if (search(pconst(key), index))    {        if (isnull(var))            dodel(index);        else            doget(index)->var = var;    }    else if (!isnull(var))        doins(index, new _varitem(key, var));    return index;}int _varray::addvar(const variant& v){    int i;    if (count > 0 && isempty(doget(count - 1)->key))        i = count;    else        i = 0;    doins(i, new _varitem(nullstring, v));    return i;}static void vconverr(large v);static void vfatal(){    fatal(CRIT_FIRST + 60, "Variant data corrupt");}evariant::~evariant(){}void variant::initialize(_varray* a){    tag = VAR_ARRAY;#ifdef PTYPES_ST    a->refcount++;#else    pincrement(&a->refcount);#endif    value.a = a;}void variant::initialize(component* o){    tag = VAR_OBJECT;    value.o = addref(o);}void variant::initialize(const variant& v){    switch (v.tag)    {    case VAR_NULL:        tag = VAR_NULL;        break;    case VAR_INT:    case VAR_BOOL:    case VAR_FLOAT:        tag = v.tag;        value = v.value;        break;    case VAR_STRING:        initialize(PTR_TO_STRING(v.value.s));        break;    case VAR_ARRAY:        initialize(v.value.a);        break;    case VAR_OBJECT:        initialize(v.value.o);        break;    default:        vfatal();    }}void variant::finalize(){    if (tag >= VAR_COMPOUND)    {        switch (tag)        {        case VAR_STRING:            PTYPES_NAMESPACE::finalize(PTR_TO_STRING(value.s));            break;        case VAR_ARRAY:#ifdef PTYPES_ST            if (--value.a->refcount == 0)#else            if (pdecrement(&value.a->refcount) == 0)#endif                delete value.a;            break;        case VAR_OBJECT:            release(value.o);            break;        default:            vfatal();        }    }    tag = VAR_NULL;}void variant::assign(large v)           { finalize(); initialize(v); }void variant::assign(bool v)            { finalize(); initialize(v); }void variant::assign(double v)          { finalize(); initialize(v); }void variant::assign(const char* v)     { finalize(); initialize(v); }void variant::assign(const string& v)   {     if (tag == VAR_STRING)        PTR_TO_STRING(value.s) = v;    else    {        finalize();        initialize(v);    }}void variant::assign(_varray* a){    if (tag == VAR_ARRAY && value.a == a)        return;    finalize();    initialize(a);}void variant::assign(component* o){    if (tag == VAR_OBJECT)    {        if (value.o == o)            return;        else            release(value.o);    }    else        finalize();    initialize(o);}void variant::assign(const variant& v){    switch (v.tag)    {    case VAR_NULL:        finalize();        tag = VAR_NULL;        break;    case VAR_INT:    case VAR_BOOL:    case VAR_FLOAT:        finalize();        tag = v.tag;        value = v.value;        break;    case VAR_STRING:        assign(PTR_TO_STRING(v.value.s));        break;    case VAR_ARRAY:        assign(v.value.a);        break;    case VAR_OBJECT:        assign(v.value.o);        break;    default:        vfatal();    }}void ptdecl clear(variant& v){    v.finalize();    v.initialize();}variant::operator int() const{    large t = operator large();    if (t < INT_MIN || t > INT_MAX)        vconverr(t);    return int(t);}variant::operator unsigned int() const{    large t = operator large();    if (t < 0 || t > UINT_MAX)        vconverr(t);    return uint(t);}variant::operator long() const{    large t = operator large();    if (t < LONG_MIN || t > LONG_MAX)        vconverr(t);    return int(t);}variant::operator unsigned long() const{    large t = operator large();    if (t < 0 || t > large(ULONG_MAX))        vconverr(t);    return uint(t);}variant::operator large() const{    switch(tag)    {    case VAR_NULL: return 0;    case VAR_INT: return value.i;    case VAR_BOOL: return int(value.b);    case VAR_FLOAT: return int(value.f);    case VAR_STRING:         {            const char* p = PTR_TO_STRING(value.s);            bool neg = *p == '-';            if (neg)                p++;            large t = stringtoi(p);            if (t < 0)                return 0;            else                return neg ? -t : t;        }    case VAR_ARRAY: return value.a->count != 0;    case VAR_OBJECT: return 0;    default: vfatal();    }    return 0;}variant::operator bool() const{    switch(tag)    {    case VAR_NULL: return false;    case VAR_INT: return value.i != 0;    case VAR_BOOL: return value.b;    case VAR_FLOAT: return value.f != 0;    case VAR_STRING: return !isempty((PTR_TO_STRING(value.s)));    case VAR_ARRAY: return value.a->count != 0;    case VAR_OBJECT: return value.o != nil;    default: vfatal();    }    return false;}variant::operator double() const{    switch(tag)    {    case VAR_NULL: return 0;    case VAR_INT: return double(value.i);    case VAR_BOOL: return int(value.b);    case VAR_FLOAT: return value.f;    case VAR_STRING:         {            char* e;            double t = strtod(PTR_TO_STRING(value.s), &e);            if (*e != 0)                return 0;            else                return t;        }    case VAR_ARRAY: return int(value.a->count != 0);    case VAR_OBJECT: return 0;    default: vfatal();    }    return 0;}void string::initialize(const variant& v){    switch(v.tag)    {    case VAR_NULL: initialize(); break;    case VAR_INT: initialize(itostring(v.value.i)); break;    case VAR_BOOL: if (v.value.b) initialize('1'); else initialize('0'); break;    case VAR_FLOAT:        {            char buf[256];            sprintf(buf, "%g", v.value.f);            initialize(buf);        }        break;    case VAR_STRING: initialize(PTR_TO_STRING(v.value.s)); break;    case VAR_ARRAY: initialize(); break;    case VAR_OBJECT: initialize(); break;    default: vfatal();    }}variant::operator string() const{    // this is a 'dirty' solution to gcc 3.3 typecast problem. most compilers    // handle variant::operator string() pretty well, while gcc 3.3 requires    // to explicitly declare a constructor string::string(const variant&).    // ironically, the presence of both the typecast operator and the constructor    // confuses the MSVC compiler. so the only thing we can do to please all     // those compilers [that "move towards the c++ standard"] is to conditionally    // exclude the constructor string(const variant&). and this is not the whole    // story. i see you are bored with it and i let you go. nobody would ever care    // about this. it just works, though i'm not happy with what i wrote here:    string t;    t.initialize(*this);    return t;}variant::operator component*() const{    if (tag == VAR_OBJECT)        return value.o;    else        return nil;}bool variant::equal(const variant& v) const{    if (tag != v.tag)        return false;    switch (tag)    {    case VAR_NULL: return true;    case VAR_INT: return value.i == v.value.i;    case VAR_BOOL: return value.b == v.value.b;    case VAR_FLOAT: return value.f == v.value.f;    case VAR_STRING: return strcmp(value.s, v.value.s) == 0;    case VAR_ARRAY: return value.a == v.value.a;    case VAR_OBJECT: return value.o == v.value.o;    default: vfatal(); return false;    }}static string numkey(large key){    return itostring(key, 16, 16, '0');}void ptdecl aclear(variant& v){    if (v.tag == VAR_ARRAY)        v.value.a->clear();    else    {        v.finalize();        v.initialize(new _varray());    }}void ptdecl apack(variant& v){    if (v.tag == VAR_ARRAY)        v.value.a->pack();}variant ptdecl aclone(const variant& v){    if (v.tag == VAR_ARRAY)        return variant(new _varray(*(v.value.a)));    else        return variant(new _varray());}int ptdecl alength(const variant& v){    if (v.tag == VAR_ARRAY)        return v.value.a->get_count();    else        return 0;}const variant& ptdecl get(const variant& v, const string& key){    if (v.tag == VAR_ARRAY)        return v.value.a->get(key);    else        return nullvar;}const variant& ptdecl get(const variant& v, large key){    return get(v, numkey(key));}void ptdecl put(variant& v, const string& key, const variant& item){    if (v.tag != VAR_ARRAY)        aclear(v);    v.value.a->put(key, item);}void ptdecl put(variant& v, large key, const variant& item){    put(v, numkey(key), item);}void ptdecl del(variant& v, const string& key){    if (v.tag == VAR_ARRAY)        v.value.a->del(key);}void ptdecl del(variant& v, large key){    del(v, numkey(key));}bool ptdecl anext(const variant& array, int& index, variant& item){    string key;    return anext(array, index, item, key);}bool ptdecl anext(const variant& array, int& index, variant& item, string& key){    if (array.tag != VAR_ARRAY)    {        clear(item);        return false;    }    if (index < 0 || index >= array.value.a->get_count())    {        clear(item);        return false;    }    item = array.value.a->doget(index)->var;    key = array.value.a->doget(index)->key;    index++;    return true;}int ptdecl aadd(variant& array, const variant& item){    if (array.tag != VAR_ARRAY)        aclear(array);    return array.value.a->addvar(item);}const variant& ptdecl aget(const variant& array, int index){    if (array.tag == VAR_ARRAY)        return array.value.a->get(index);    else        return nullvar;}void ptdecl adel(variant& array, int index){    if (array.tag == VAR_ARRAY)        array.value.a->del(index);}void ptdecl aput(variant& array, int index, const variant& item){    if (array.tag == VAR_ARRAY)        array.value.a->put(index, item);}void ptdecl ains(variant& array, int index, const variant& item){    if (array.tag == VAR_ARRAY)        array.value.a->ins(index, item);}#ifdef _MSC_VER// disable "unreachable code" warning for throw (known compiler bug)#  pragma warning (disable: 4702)#endifstatic void vconverr(large v){    throw new evariant("Value out of range: " + itostring(v));}PTYPES_END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -