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

📄 pvariant.cxx

📁 使用stl技术,(还没看,是听说的)
💻 CXX
字号:
/*
 *
 *  C++ Portable Types Library (PTypes)
 *  Version 1.8.3  Released 25-Aug-2003
 *
 *  Copyright (c) 2001, 2002, 2003 Hovik Melikyan
 *
 *  http://www.melikyan.com/ptypes/
 *  http://ptypes.sourceforge.net/
 *
 */


#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#include "ptypes.h"


PTYPES_BEGIN


const variant nullvar;


static void vfatal()
{
    fatal(CRIT_FIRST + 60, "Variant data corrupt");
}


static void vconverr(large v)
{
    throw new evariant("Value out of range: " + itostring(v));
}


evariant::~evariant()
{
}


void variant::initialize(_varray* a)
{
    tag = VAR_ARRAY;
    pincrement(&a->refcount);
    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:
            if (pdecrement(&value.a->refcount) == 0)
                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)
        if (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 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;
    }
}


varobject::~varobject()
{
}


_varray::~_varray()
{
}


PTYPES_END

⌨️ 快捷键说明

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