You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1616 lines
40 KiB
1616 lines
40 KiB
//=============================================================================
|
|
//
|
|
// File : kvi_kvs_variant.cpp
|
|
// Created on Tue 07 Oct 2003 04:01:19 by Szymon Stefanek
|
|
//
|
|
// This file is part of the KVIrc IRC client distribution
|
|
// Copyright (C) 2003 Szymon Stefanek <pragma at kvirc dot net>
|
|
//
|
|
// This program is FREE software. You can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your opinion) any later version.
|
|
//
|
|
// This program is distributed in the HOPE that it will be USEFUL,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, write to the Free Software Foundation,
|
|
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
//=============================================================================
|
|
|
|
#define __KVIRC__
|
|
|
|
#include "kvi_kvs_variant.h"
|
|
#include "kvi_kvs_arraycast.h"
|
|
#include "kvi_kvs_hash.h"
|
|
#include "kvi_kvs_array.h"
|
|
|
|
#include <math.h>
|
|
|
|
KviKvsVariant::KviKvsVariant()
|
|
{
|
|
m_pData = 0;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(TQString * pString)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::String;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pString = pString;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(const TQString &szString)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::String;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pString = new TQString(szString);
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(const char * szString)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::String;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pString = new TQString(TQString::fromUtf8(szString));
|
|
}
|
|
|
|
|
|
KviKvsVariant::KviKvsVariant(KviKvsArray * pArray)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Array;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pArray = pArray;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(KviKvsHash * pHash)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Hash;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pHash = pHash;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(kvs_real_t * pReal)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Real;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pReal = pReal;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(kvs_real_t dReal)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Real;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.pReal = new kvs_real_t;
|
|
*(m_pData->m_u.pReal) = dReal;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(bool bBoolean)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Boolean;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.bBoolean = bBoolean;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(kvs_int_t iInteger)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::Integer;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.iInteger = iInteger;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(kvs_hobject_t hObject)
|
|
{
|
|
m_pData = new KviKvsVariantData;
|
|
m_pData->m_eType = KviKvsVariantData::HObject;
|
|
m_pData->m_uRefs = 1;
|
|
m_pData->m_u.hObject = hObject;
|
|
}
|
|
|
|
KviKvsVariant::KviKvsVariant(const KviKvsVariant &v)
|
|
{
|
|
m_pData = v.m_pData;
|
|
if(m_pData)m_pData->m_uRefs++;
|
|
}
|
|
|
|
#define DELETE_VARIANT_CONTENTS \
|
|
switch(m_pData->m_eType) \
|
|
{ \
|
|
case KviKvsVariantData::Array: delete m_pData->m_u.pArray; break; \
|
|
case KviKvsVariantData::Hash: delete m_pData->m_u.pHash; break; \
|
|
case KviKvsVariantData::String: delete m_pData->m_u.pString; break; \
|
|
case KviKvsVariantData::Real: delete m_pData->m_u.pReal; break; \
|
|
default: /* make gcc happy */ break; \
|
|
}
|
|
|
|
#define DETACH_CONTENTS \
|
|
if(m_pData) \
|
|
{ \
|
|
if(m_pData->m_uRefs <= 1) \
|
|
{ \
|
|
DELETE_VARIANT_CONTENTS \
|
|
delete m_pData; \
|
|
} else { \
|
|
m_pData->m_uRefs--; \
|
|
} \
|
|
}
|
|
|
|
#define RENEW_VARIANT_DATA \
|
|
if(m_pData) \
|
|
{ \
|
|
if(m_pData->m_uRefs > 1) \
|
|
{ \
|
|
m_pData->m_uRefs--; \
|
|
m_pData = new KviKvsVariantData; \
|
|
m_pData->m_uRefs = 1; \
|
|
} else { \
|
|
DELETE_VARIANT_CONTENTS \
|
|
} \
|
|
} else { \
|
|
m_pData = new KviKvsVariantData; \
|
|
m_pData->m_uRefs = 1; \
|
|
}
|
|
|
|
KviKvsVariant::~KviKvsVariant()
|
|
{
|
|
DETACH_CONTENTS
|
|
}
|
|
|
|
void KviKvsVariant::setString(TQString * pString)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::String;
|
|
m_pData->m_u.pString = pString;
|
|
}
|
|
|
|
void KviKvsVariant::setString(const TQString &szString)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::String;
|
|
m_pData->m_u.pString = new TQString(szString);
|
|
}
|
|
|
|
void KviKvsVariant::setReal(kvs_real_t dReal)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Real;
|
|
m_pData->m_u.pReal = new kvs_real_t;
|
|
*(m_pData->m_u.pReal) = dReal;
|
|
}
|
|
|
|
void KviKvsVariant::setHObject(kvs_hobject_t hObject)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::HObject;
|
|
m_pData->m_u.hObject = hObject;
|
|
}
|
|
|
|
void KviKvsVariant::setBoolean(bool bBoolean)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Boolean;
|
|
m_pData->m_u.bBoolean = bBoolean;
|
|
}
|
|
|
|
void KviKvsVariant::setReal(kvs_real_t * pReal)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Real;
|
|
m_pData->m_u.pReal = pReal;
|
|
}
|
|
|
|
void KviKvsVariant::setInteger(kvs_int_t iInteger)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Integer;
|
|
m_pData->m_u.iInteger = iInteger;
|
|
}
|
|
|
|
void KviKvsVariant::setArray(KviKvsArray * pArray)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Array;
|
|
m_pData->m_u.pArray = pArray;
|
|
}
|
|
|
|
void KviKvsVariant::setHash(KviKvsHash * pHash)
|
|
{
|
|
RENEW_VARIANT_DATA
|
|
m_pData->m_eType = KviKvsVariantData::Hash;
|
|
m_pData->m_u.pHash = pHash;
|
|
}
|
|
|
|
void KviKvsVariant::setNothing()
|
|
{
|
|
if(m_pData)
|
|
{
|
|
if(m_pData->m_uRefs <= 1)
|
|
{
|
|
DELETE_VARIANT_CONTENTS
|
|
delete m_pData;
|
|
} else {
|
|
// just detach
|
|
m_pData->m_uRefs--;
|
|
}
|
|
m_pData = 0;
|
|
}
|
|
}
|
|
|
|
bool KviKvsVariant::isEmpty() const
|
|
{
|
|
if(!m_pData)return true;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String: return m_pData->m_u.pString->isEmpty(); break;
|
|
case KviKvsVariantData::Array: return m_pData->m_u.pArray->isEmpty(); break;
|
|
case KviKvsVariantData::Hash: return m_pData->m_u.pHash->isEmpty(); break;
|
|
case KviKvsVariantData::HObject: return m_pData->m_u.hObject == 0; break;
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool KviKvsVariant::asBoolean() const
|
|
{
|
|
if(!m_pData)return false;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Boolean: return m_pData->m_u.bBoolean; break;
|
|
case KviKvsVariantData::String:
|
|
{
|
|
if(m_pData->m_u.pString->isEmpty())return false;
|
|
// check integer or real values
|
|
bool bOk;
|
|
kvs_int_t iVal = (kvs_int_t)KviTQString::toI64(*(m_pData->m_u.pString),&bOk);
|
|
if(bOk)return iVal;
|
|
kvs_real_t dVal = m_pData->m_u.pString->toDouble(&bOk);
|
|
if(bOk)return (dVal != 0.0);
|
|
// non number, non empty
|
|
return true;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Integer: return m_pData->m_u.iInteger; break;
|
|
case KviKvsVariantData::Real: return *(m_pData->m_u.pReal) != 0.0; break;
|
|
case KviKvsVariantData::Array: return !(m_pData->m_u.pArray->isEmpty()); break;
|
|
case KviKvsVariantData::Hash: return !(m_pData->m_u.pHash->isEmpty()); break;
|
|
case KviKvsVariantData::HObject: return m_pData->m_u.hObject; break;
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
tqDebug("WARNING: invalid variant type %d in KviKvsVariant::asBoolean()",m_pData->m_eType);
|
|
return false;
|
|
}
|
|
|
|
bool KviKvsVariant::asHObject(kvs_hobject_t &hObject) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
// nothing evaluates to a null object
|
|
hObject = 0;
|
|
return true;
|
|
}
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
hObject = m_pData->m_u.hObject;
|
|
return true;
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
if(m_pData->m_u.iInteger == 0)
|
|
{
|
|
hObject = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
if(*(m_pData->m_u.pString) == "0")
|
|
{
|
|
hObject = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
if(!(m_pData->m_u.bBoolean))
|
|
{
|
|
hObject = 0;
|
|
return true;
|
|
}
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool KviKvsVariant::asNumber(KviKvsNumber &n) const
|
|
{
|
|
if(!m_pData)return false;
|
|
|
|
if(isInteger())
|
|
{
|
|
n.m_u.iInteger = m_pData->m_u.iInteger;
|
|
n.m_type = KviKvsNumber::Integer;
|
|
return true;
|
|
}
|
|
if(isReal())
|
|
{
|
|
n.m_u.dReal = *(m_pData->m_u.pReal);
|
|
n.m_type = KviKvsNumber::Real;
|
|
return true;
|
|
}
|
|
if(asInteger(n.m_u.iInteger))
|
|
{
|
|
n.m_type = KviKvsNumber::Integer;
|
|
return true;
|
|
}
|
|
if(asReal(n.m_u.dReal))
|
|
{
|
|
n.m_type = KviKvsNumber::Real;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void KviKvsVariant::castToNumber(KviKvsNumber &n) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
n.m_u.iInteger = 0;
|
|
n.m_type = KviKvsNumber::Integer;
|
|
return;
|
|
}
|
|
|
|
if(isInteger())
|
|
{
|
|
n.m_u.iInteger = m_pData->m_u.iInteger;
|
|
n.m_type = KviKvsNumber::Integer;
|
|
return;
|
|
}
|
|
if(isReal())
|
|
{
|
|
n.m_u.dReal = *(m_pData->m_u.pReal);
|
|
n.m_type = KviKvsNumber::Real;
|
|
return;
|
|
}
|
|
if(asInteger(n.m_u.iInteger))
|
|
{
|
|
n.m_type = KviKvsNumber::Integer;
|
|
return;
|
|
}
|
|
if(asReal(n.m_u.dReal))
|
|
{
|
|
n.m_type = KviKvsNumber::Real;
|
|
return;
|
|
}
|
|
castToInteger(n.m_u.iInteger);
|
|
n.m_type = KviKvsNumber::Integer;
|
|
}
|
|
|
|
void KviKvsVariant::castToArray(KviKvsArrayCast *c) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
c->set(new KviKvsArray(),true);
|
|
return;
|
|
}
|
|
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Array:
|
|
c->set(m_pData->m_u.pArray,false);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
{
|
|
KviPointerHashTableIterator<TQString,KviKvsVariant> it(*(m_pData->m_u.pHash->dict()));
|
|
KviKvsArray * a = new KviKvsArray();
|
|
kvs_int_t idx = 0;
|
|
while(KviKvsVariant * v = it.current())
|
|
{
|
|
a->set(idx,new KviKvsVariant(*v));
|
|
++it;
|
|
idx++;
|
|
}
|
|
c->set(a,true);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
// other scalars
|
|
KviKvsArray * a = new KviKvsArray();
|
|
a->set(0,new KviKvsVariant(*this));
|
|
c->set(a,true);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void KviKvsVariant::convertToArray()
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
setArray(new KviKvsArray());
|
|
return;
|
|
}
|
|
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Array:
|
|
return;
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
{
|
|
KviPointerHashTableIterator<TQString,KviKvsVariant> it(*(m_pData->m_u.pHash->dict()));
|
|
KviKvsArray * a = new KviKvsArray();
|
|
kvs_int_t idx = 0;
|
|
while(KviKvsVariant * v = it.current())
|
|
{
|
|
a->set(idx,new KviKvsVariant(*v));
|
|
++it;
|
|
idx++;
|
|
}
|
|
setArray(a);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
// other scalars
|
|
KviKvsArray * a = new KviKvsArray();
|
|
a->set(0,new KviKvsVariant(*this));
|
|
setArray(a);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool KviKvsVariant::asInteger(kvs_int_t &iVal) const
|
|
{
|
|
if(!m_pData)return false;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Integer:
|
|
iVal = m_pData->m_u.iInteger;
|
|
return true;
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
{
|
|
bool bOk;
|
|
iVal = (kvs_int_t)KviTQString::toI64(*(m_pData->m_u.pString),&bOk);
|
|
return bOk;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
// FIXME: this truncates the value!
|
|
iVal = (kvs_int_t)*(m_pData->m_u.pReal);
|
|
return true;
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
iVal = m_pData->m_u.bBoolean ? 1 : 0;
|
|
return true;
|
|
break;
|
|
//case KviKvsVariantData::HObject: <-- light casts from objects to integer are not valid
|
|
// iVal = m_pData->m_u.hObject ? 1 : 0;
|
|
// return true;
|
|
//break;
|
|
default: /* make gcc happy */
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void KviKvsVariant::castToInteger(kvs_int_t &iVal) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
iVal = 0;
|
|
return;
|
|
}
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Integer:
|
|
iVal = m_pData->m_u.iInteger;
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
iVal = m_pData->m_u.bBoolean ? 1 : 0;
|
|
break;
|
|
case KviKvsVariantData::HObject:
|
|
iVal = m_pData->m_u.hObject ? 1 : 0;
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
{
|
|
bool bOk;
|
|
iVal = (kvs_int_t)KviTQString::toI64(*(m_pData->m_u.pString),&bOk);
|
|
if(bOk)return;
|
|
iVal = m_pData->m_u.pString->length();
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
// FIXME: this truncates the value!
|
|
iVal = (kvs_int_t)*(m_pData->m_u.pReal);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
iVal = m_pData->m_u.pArray->size();
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
iVal = m_pData->m_u.pHash->size();
|
|
break;
|
|
default: /* make gcc happy */
|
|
iVal = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
bool KviKvsVariant::asReal(kvs_real_t & dVal) const
|
|
{
|
|
if(!m_pData)return false;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::Integer:
|
|
dVal = m_pData->m_u.iInteger;
|
|
return true;
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
{
|
|
bool bOk;
|
|
dVal = m_pData->m_u.pString->toDouble(&bOk);
|
|
return bOk;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
dVal = *(m_pData->m_u.pReal);
|
|
return true;
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
dVal = m_pData->m_u.bBoolean ? 1.0 : 0.0;
|
|
return true;
|
|
break;
|
|
default: /* by default we make gcc happy */ break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void KviKvsVariant::asString(TQString &szBuffer) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
szBuffer = TQString();
|
|
return;
|
|
}
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String: szBuffer = *(m_pData->m_u.pString); break;
|
|
case KviKvsVariantData::Array: szBuffer = TQString(); m_pData->m_u.pArray->appendAsString(szBuffer); break;
|
|
case KviKvsVariantData::Hash: szBuffer = TQString(); m_pData->m_u.pHash->appendAsString(szBuffer); break;
|
|
case KviKvsVariantData::Integer: szBuffer.setNum(m_pData->m_u.iInteger); break;
|
|
case KviKvsVariantData::Real: szBuffer.setNum(*(m_pData->m_u.pReal)); break;
|
|
case KviKvsVariantData::Boolean: szBuffer.setNum(m_pData->m_u.bBoolean ? 1 : 0); break;
|
|
case KviKvsVariantData::HObject:
|
|
if(m_pData->m_u.hObject)
|
|
KviTQString::sprintf(szBuffer,"object[%lx]",m_pData->m_u.hObject);
|
|
else
|
|
szBuffer = "null-object";
|
|
break;
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
}
|
|
|
|
void KviKvsVariant::appendAsString(TQString &szBuffer) const
|
|
{
|
|
if(!m_pData)return;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String: szBuffer.append(*(m_pData->m_u.pString)); break;
|
|
case KviKvsVariantData::Array: m_pData->m_u.pArray->appendAsString(szBuffer); break;
|
|
case KviKvsVariantData::Hash: m_pData->m_u.pHash->appendAsString(szBuffer); break;
|
|
case KviKvsVariantData::Integer: KviTQString::appendNumber(szBuffer,m_pData->m_u.iInteger); break;
|
|
case KviKvsVariantData::Real: KviTQString::appendNumber(szBuffer,*(m_pData->m_u.pReal)); break;
|
|
case KviKvsVariantData::Boolean: KviTQString::appendNumber(szBuffer,m_pData->m_u.bBoolean ? 1 : 0); break;
|
|
case KviKvsVariantData::HObject: szBuffer.append(m_pData->m_u.hObject ? "object" : "null-object"); break;
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
}
|
|
|
|
void KviKvsVariant::dump(const char * prefix) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
tqDebug("%s Nothing [this=0x%lx]",prefix,this);
|
|
return;
|
|
}
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String: tqDebug("%s String(%s) [this=0x%lx]",prefix,m_pData->m_u.pString->utf8().data(),this); break;
|
|
case KviKvsVariantData::Array: tqDebug("%s Array(ptr=0x%lx) [this=0x%lx]",prefix,m_pData->m_u.pArray,this); break;
|
|
case KviKvsVariantData::Hash: tqDebug("%s Hash(ptr=0x%lx,dict=0x%lx) [this=0x%lx]",prefix,m_pData->m_u.pHash,m_pData->m_u.pHash->dict(),this); break;
|
|
case KviKvsVariantData::Integer: tqDebug("%s Integer(%d) [this=0x%lx]",prefix,m_pData->m_u.iInteger,this); break;
|
|
case KviKvsVariantData::Real: tqDebug("%s Real(%f) [this=0x%lx]",prefix,*(m_pData->m_u.pReal),this); break;
|
|
case KviKvsVariantData::Boolean: tqDebug("%s Boolean(%s) [this=0x%lx]",prefix,m_pData->m_u.bBoolean ? "true" : "false",this); break;
|
|
case KviKvsVariantData::HObject: tqDebug("%s HObject(%lx) [this=0x%lx]",prefix,m_pData->m_u.hObject,this); break;
|
|
default: /* make gcc happy */ break;
|
|
}
|
|
}
|
|
|
|
void KviKvsVariant::copyFrom(const KviKvsVariant * v)
|
|
{
|
|
DETACH_CONTENTS
|
|
m_pData = v->m_pData;
|
|
if(m_pData)m_pData->m_uRefs++;
|
|
}
|
|
|
|
void KviKvsVariant::copyFrom(const KviKvsVariant &v)
|
|
{
|
|
DETACH_CONTENTS
|
|
m_pData = v.m_pData;
|
|
if(m_pData)m_pData->m_uRefs++;
|
|
|
|
}
|
|
|
|
void KviKvsVariant::takeFrom(KviKvsVariant * v)
|
|
{
|
|
DETACH_CONTENTS
|
|
m_pData = v->m_pData;
|
|
v->m_pData = 0;
|
|
}
|
|
|
|
void KviKvsVariant::takeFrom(KviKvsVariant &v)
|
|
{
|
|
DETACH_CONTENTS
|
|
m_pData = v.m_pData;
|
|
v.m_pData = 0;
|
|
}
|
|
|
|
void KviKvsVariant::getTypeName(TQString &szBuffer) const
|
|
{
|
|
if(!m_pData)
|
|
{
|
|
szBuffer = "nothing";
|
|
return;
|
|
}
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String: szBuffer = "string"; break;
|
|
case KviKvsVariantData::Hash: szBuffer = "hash"; break;
|
|
case KviKvsVariantData::Array: szBuffer = "array"; break;
|
|
case KviKvsVariantData::Real: szBuffer = "real"; break;
|
|
case KviKvsVariantData::Integer: szBuffer = "integer"; break;
|
|
case KviKvsVariantData::Boolean: szBuffer = "boolean"; break;
|
|
case KviKvsVariantData::HObject: szBuffer = "hobject"; break;
|
|
default: szBuffer = "internal_error"; break;
|
|
}
|
|
}
|
|
|
|
bool KviKvsVariant::isEqualToNothing() const
|
|
{
|
|
if(!m_pData)return true;
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
return (m_pData->m_u.hObject == (kvs_hobject_t)0);
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
return (m_pData->m_u.iInteger == 0);
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
return (*(m_pData->m_u.pReal) == 0.0);
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
{
|
|
if(m_pData->m_u.pString->isEmpty())return true;
|
|
kvs_real_t dReal;
|
|
if(asReal(dReal))
|
|
return dReal == 0.0;
|
|
return false;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
return !m_pData->m_u.bBoolean;
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return m_pData->m_u.pHash->isEmpty();
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return m_pData->m_u.pArray->isEmpty();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
#define CMP_THISGREATER -1
|
|
#define CMP_EQUAL 0
|
|
#define CMP_OTHERGREATER 1
|
|
|
|
class KviKvsVariantComparison
|
|
{
|
|
public:
|
|
static inline int compare_integer_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.iInteger == 0)
|
|
{
|
|
if(v2->m_pData->m_u.pString->isEmpty())return CMP_EQUAL;
|
|
}
|
|
kvs_real_t dReal;
|
|
if(v2->asReal(dReal))
|
|
{
|
|
if(((kvs_real_t)v1->m_pData->m_u.iInteger) == dReal)return CMP_EQUAL;
|
|
if(((kvs_real_t)v1->m_pData->m_u.iInteger) > dReal)return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
// compare as strings instead
|
|
TQString szString;
|
|
v1->asString(szString);
|
|
return -1 * KviTQString::cmpCI(szString,*(v2->m_pData->m_u.pString));
|
|
}
|
|
|
|
static inline int compare_integer_real(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(((kvs_real_t)v1->m_pData->m_u.iInteger) == *(v2->m_pData->m_u.pReal))return CMP_EQUAL;
|
|
if(((kvs_real_t)v1->m_pData->m_u.iInteger) > *(v2->m_pData->m_u.pReal))return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_integer_boolean(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.iInteger == 0)
|
|
return v2->m_pData->m_u.bBoolean ? CMP_OTHERGREATER : CMP_EQUAL;
|
|
return v2->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_integer_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.iInteger == 0)
|
|
return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_integer_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.iInteger == 0)
|
|
return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_integer_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.iInteger == 0.0)
|
|
return (v2->m_pData->m_u.hObject == (kvs_hobject_t)0) ? CMP_EQUAL : CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_real_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == 0.0)
|
|
return (v2->m_pData->m_u.hObject == (kvs_hobject_t)0) ? CMP_EQUAL : CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_real_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == 0.0)
|
|
{
|
|
if(v2->m_pData->m_u.pString->isEmpty())return CMP_EQUAL;
|
|
}
|
|
kvs_real_t dReal;
|
|
if(v2->asReal(dReal))
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == dReal)return CMP_EQUAL;
|
|
if(*(v1->m_pData->m_u.pReal) > dReal)return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
// compare as strings instead
|
|
TQString szString;
|
|
v1->asString(szString);
|
|
return -1 * KviTQString::cmpCI(szString,*(v2->m_pData->m_u.pString));
|
|
}
|
|
|
|
static inline int compare_real_boolean(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == 0.0)
|
|
return v2->m_pData->m_u.bBoolean ? CMP_OTHERGREATER : CMP_EQUAL;
|
|
return v2->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_real_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == 0)
|
|
return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_real_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(*(v1->m_pData->m_u.pReal) == 0)
|
|
return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_string_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.pString->isEmpty())
|
|
{
|
|
return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
}
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_string_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.pString->isEmpty())
|
|
{
|
|
return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
}
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_string_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v2->m_pData->m_u.hObject == (kvs_hobject_t)0)
|
|
{
|
|
if(v1->m_pData->m_u.pString->isEmpty())
|
|
return CMP_EQUAL;
|
|
kvs_real_t dReal;
|
|
if(v1->asReal(dReal))
|
|
{
|
|
if(dReal == 0)return CMP_EQUAL;
|
|
}
|
|
}
|
|
|
|
return CMP_THISGREATER;
|
|
}
|
|
|
|
static inline int compare_boolean_string(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v2->isEqualToNothing())
|
|
{
|
|
return v1->m_pData->m_u.bBoolean ? CMP_THISGREATER : CMP_EQUAL;
|
|
} else {
|
|
return v1->m_pData->m_u.bBoolean ? CMP_EQUAL : CMP_THISGREATER;
|
|
}
|
|
}
|
|
|
|
static inline int compare_boolean_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.bBoolean)
|
|
return v2->m_pData->m_u.pHash->isEmpty() ? CMP_THISGREATER : CMP_EQUAL;
|
|
else
|
|
return v2->m_pData->m_u.pHash->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_boolean_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.bBoolean)
|
|
return v2->m_pData->m_u.pArray->isEmpty() ? CMP_THISGREATER : CMP_EQUAL;
|
|
else
|
|
return v2->m_pData->m_u.pArray->isEmpty() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_boolean_hobject(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.bBoolean)
|
|
return v2->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
|
|
else
|
|
return v2->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_array_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v1->m_pData->m_u.pArray->size() > v2->m_pData->m_u.pHash->size())return CMP_THISGREATER;
|
|
if(v1->m_pData->m_u.pArray->size() == v2->m_pData->m_u.pHash->size())return CMP_EQUAL;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
|
|
static inline int compare_hobject_hash(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v2->m_pData->m_u.pHash->isEmpty())
|
|
return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
|
|
}
|
|
|
|
static inline int compare_hobject_array(const KviKvsVariant * v1,const KviKvsVariant * v2)
|
|
{
|
|
if(v2->m_pData->m_u.pArray->isEmpty())
|
|
return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
return v1->m_pData->m_u.hObject == ((kvs_hobject_t)0) ? CMP_THISGREATER : CMP_EQUAL;
|
|
}
|
|
|
|
};
|
|
void KviKvsVariant::serializeString(TQString& buffer)
|
|
{
|
|
buffer.replace('\\',"\\\\");
|
|
buffer.replace('\n',"\\n");
|
|
buffer.replace('\r',"\\r");
|
|
buffer.replace('\b',"\\b");
|
|
buffer.replace('\t',"\\t");
|
|
buffer.replace('\f',"\\f");
|
|
buffer.replace('/',"\\/");
|
|
buffer.replace('"',"\\\"");
|
|
buffer.prepend('"');
|
|
buffer.append('"');
|
|
}
|
|
|
|
void KviKvsVariant::serialize(TQString& result)
|
|
{
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
//can't serialize objects yet
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
result.setNum(m_pData->m_u.iInteger);
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
result.setNum(*(m_pData->m_u.pReal));
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
result = *(m_pData->m_u.pString);
|
|
serializeString(result);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
result = m_pData->m_u.bBoolean ? "true" : "false";
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
m_pData->m_u.pHash->serialize(result);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
m_pData->m_u.pArray->serialize(result);
|
|
break;
|
|
case KviKvsVariantData::Nothing:
|
|
result="null";
|
|
break;
|
|
default: // just make gcc happy
|
|
break;
|
|
}
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeTrue(const TQChar** aux)
|
|
{
|
|
if(KviTQString::equalCIN(TQString("true"),*aux,4))
|
|
{
|
|
(*aux)+=4;
|
|
return new KviKvsVariant(true);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeFalse(const TQChar** aux)
|
|
{
|
|
if(KviTQString::equalCIN(TQString("false"),*aux,5))
|
|
{
|
|
(*aux)+=5;
|
|
return new KviKvsVariant(false);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeNull(const TQChar** aux)
|
|
{
|
|
if(KviTQString::equalCIN(TQString("null"),*aux,4))
|
|
{
|
|
(*aux)+=4;
|
|
return new KviKvsVariant();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeRealOrInteger(const TQChar** aux)
|
|
{
|
|
TQString data;
|
|
if((*aux)->unicode() == '-')
|
|
{
|
|
data.append('-');
|
|
(*aux)++;
|
|
}
|
|
if(!(*aux)->isDigit())
|
|
{
|
|
return 0;
|
|
}
|
|
while((*aux)->isDigit())
|
|
{
|
|
data.append(**aux);
|
|
(*aux)++;
|
|
}
|
|
if((*aux)->unicode()=='.')
|
|
{
|
|
return unserializeReal(aux,data);
|
|
}
|
|
return unserializeInteger(aux,data);
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeReal(const TQChar** aux,TQString& data)
|
|
{
|
|
TQString exponent;
|
|
(*aux)++; //skip .
|
|
data.append('.');
|
|
while((*aux)->isDigit())
|
|
{
|
|
data.append(**aux);
|
|
(*aux)++;
|
|
}
|
|
|
|
if((*aux)->unicode() == 'e' || (*aux)->unicode() == 'E')
|
|
{
|
|
(*aux)++;
|
|
if((*aux)->unicode() == '-')
|
|
{
|
|
exponent.append('-');
|
|
(*aux)++;
|
|
} else {
|
|
if((*aux)->unicode() == '+')
|
|
{
|
|
exponent.append('+');
|
|
(*aux)++;
|
|
}
|
|
}
|
|
|
|
while((*aux)->isDigit())
|
|
{
|
|
exponent.append(**aux);
|
|
(*aux)++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
float value = data.toFloat();
|
|
if(!exponent.isNull())
|
|
{
|
|
value*=pow(10.0,exponent.toInt());
|
|
}
|
|
return new KviKvsVariant(value);
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeInteger(const TQChar** aux,TQString& data)
|
|
{
|
|
|
|
TQString exponent;
|
|
|
|
if((*aux)->unicode() == 'e' || (*aux)->unicode() == 'E')
|
|
{
|
|
(*aux)++;
|
|
if((*aux)->unicode() == '-')
|
|
{
|
|
exponent.append('-');
|
|
(*aux)++;
|
|
} else {
|
|
if((*aux)->unicode() == '+')
|
|
{
|
|
exponent.append('+');
|
|
(*aux)++;
|
|
}
|
|
}
|
|
|
|
while((*aux)->isDigit())
|
|
{
|
|
exponent.append(**aux);
|
|
(*aux)++;
|
|
}
|
|
}
|
|
|
|
kvs_int_t value = data.toInt();
|
|
if(!exponent.isNull())
|
|
{
|
|
value*=pow(10.0,exponent.toInt());
|
|
}
|
|
return new KviKvsVariant(value);
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeString(const TQChar** aux)
|
|
{
|
|
TQString buffer;
|
|
unserializeString(aux,buffer);
|
|
return new KviKvsVariant(buffer);
|
|
}
|
|
|
|
void KviKvsVariant::unserializeString(const TQChar** aux,TQString& data)
|
|
{
|
|
data="";
|
|
TQString hex; //temp var
|
|
//skip leading "
|
|
(*aux)++;
|
|
while((*aux)->unicode())
|
|
{
|
|
switch((*aux)->unicode())
|
|
{
|
|
case '"':
|
|
//EOF
|
|
(*aux)++;
|
|
return;
|
|
break;
|
|
case '\\':
|
|
//Special
|
|
(*aux)++;
|
|
switch((*aux)->unicode())
|
|
{
|
|
case 't':
|
|
data.append('\t');
|
|
break;
|
|
case '\"':
|
|
data.append('\"');
|
|
break;
|
|
case '/':
|
|
data.append('/');
|
|
case 'b':
|
|
data.append('\b');
|
|
case 'f':
|
|
data.append('\f');
|
|
break;
|
|
case 'n':
|
|
data.append('\n');
|
|
break;
|
|
case 'r':
|
|
data.append('\r');
|
|
break;
|
|
case 'u':
|
|
//4 hexadecmical digits pending...
|
|
hex="";
|
|
(*aux)++;
|
|
for(int k=0;k<4 && (*aux)->unicode(); k++)
|
|
{
|
|
if((*aux)->isDigit() ||
|
|
((*aux)->unicode() >='A' && (*aux)->unicode() <='F')|| //ABCDEF
|
|
((*aux)->unicode() >='a' && (*aux)->unicode() <='f')) //abcdef
|
|
{
|
|
hex.append(**aux);
|
|
(*aux)++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
(*aux)--;
|
|
data.append(TQChar(hex.toUInt(0,16)));
|
|
break;
|
|
default:
|
|
//Fallback; incorrect escape
|
|
(*aux)--;
|
|
data.append('\\');
|
|
}
|
|
(*aux)++;
|
|
break;
|
|
default:
|
|
data.append(**aux);
|
|
(*aux)++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeHash(const TQChar** aux)
|
|
{
|
|
KviKvsHash* pHash = new KviKvsHash();
|
|
TQString szKey;
|
|
KviKvsVariant* pElement = 0;
|
|
//skip leading '{'
|
|
(*aux)++;
|
|
int i=0;
|
|
while(1)
|
|
{
|
|
//skip leading space
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
//waiting for starting of string
|
|
if((*aux)->unicode()!='\"')
|
|
{
|
|
//strange characters
|
|
delete pHash;
|
|
return 0;
|
|
}
|
|
unserializeString(aux,szKey);
|
|
if(szKey.isEmpty())
|
|
{
|
|
//Strange element name
|
|
delete pHash;
|
|
return 0;
|
|
}
|
|
|
|
//skip leading space before ':'
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
//waiting for name-value delimeter
|
|
if((*aux)->unicode()!=':')
|
|
{
|
|
//strange characters
|
|
delete pHash;
|
|
return 0;
|
|
}
|
|
(*aux)++;
|
|
|
|
|
|
//getting element
|
|
pElement = unserialize(aux);
|
|
if(pElement)
|
|
{
|
|
pHash->set(szKey,pElement);
|
|
i++;
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
switch((*aux)->unicode())
|
|
{
|
|
case ',':
|
|
//goto next
|
|
(*aux)++;
|
|
break;
|
|
case '}':
|
|
//EOF array
|
|
(*aux)++;
|
|
return new KviKvsVariant(pHash);
|
|
break;
|
|
default:
|
|
delete pHash;
|
|
return 0;
|
|
break;
|
|
}
|
|
} else {
|
|
//error
|
|
delete pHash;
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserializeArray(const TQChar** aux)
|
|
{
|
|
KviKvsArray* pArray = new KviKvsArray();
|
|
KviKvsVariant* pElement = 0;
|
|
(*aux)++;
|
|
int i=0;
|
|
while(1)
|
|
{
|
|
pElement = unserialize(aux);
|
|
if(pElement)
|
|
{
|
|
pArray->set(i,pElement);
|
|
i++;
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
switch((*aux)->unicode())
|
|
{
|
|
case ',':
|
|
//goto next
|
|
(*aux)++;
|
|
break;
|
|
case ']':
|
|
//EOF array
|
|
(*aux)++;
|
|
return new KviKvsVariant(pArray);
|
|
break;
|
|
default:
|
|
delete pArray;
|
|
return 0;
|
|
break;
|
|
}
|
|
} else {
|
|
//error
|
|
delete pArray;
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserialize(const TQChar** aux)
|
|
{
|
|
KviKvsVariant* pResult = 0;
|
|
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
|
|
switch((*aux)->unicode())
|
|
{
|
|
case 't':
|
|
//true
|
|
pResult = unserializeTrue(aux);
|
|
break;
|
|
case 'f':
|
|
//false
|
|
pResult = unserializeFalse(aux);
|
|
break;
|
|
case 'n':
|
|
//null
|
|
pResult = unserializeNull(aux);
|
|
break;
|
|
case '[':
|
|
//array
|
|
pResult = unserializeArray(aux);
|
|
break;
|
|
case '{':
|
|
//hash
|
|
pResult = unserializeHash(aux);
|
|
break;
|
|
case '"':
|
|
//string
|
|
pResult = unserializeString(aux);
|
|
break;
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case '0':
|
|
case '-':
|
|
//real or integer
|
|
pResult = unserializeRealOrInteger(aux);
|
|
break;
|
|
default:
|
|
//incorrect value
|
|
return 0;
|
|
}
|
|
|
|
while((*aux)->isSpace())
|
|
(*aux)++;
|
|
|
|
return pResult;
|
|
}
|
|
|
|
KviKvsVariant* KviKvsVariant::unserialize(const TQString& data)
|
|
{
|
|
KviKvsVariant* pResult = 0;
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
const TQChar * aux = (const TQChar *)data.constData();
|
|
#else
|
|
const TQChar * aux = (const TQChar *)data.ucs2();
|
|
#endif
|
|
|
|
pResult = unserialize(&aux);
|
|
|
|
if(aux->unicode())
|
|
{
|
|
//strange extra characters?
|
|
if(pResult) delete pResult;
|
|
pResult = 0;
|
|
}
|
|
|
|
return pResult;
|
|
}
|
|
|
|
int KviKvsVariant::compare(const KviKvsVariant * pOther,bool bPreferNumeric) const
|
|
{
|
|
// returns -1 if this variant is greater than pOther
|
|
// 0 if they are considered to be equal
|
|
// 1 if the other variant is greater
|
|
|
|
if(!pOther)
|
|
return isEqualToNothing() ? CMP_EQUAL : CMP_THISGREATER;
|
|
if(!pOther->m_pData)
|
|
return isEqualToNothing() ? CMP_EQUAL : CMP_THISGREATER;
|
|
if(!m_pData)
|
|
return pOther->isEqualToNothing() ? CMP_EQUAL : CMP_OTHERGREATER;
|
|
|
|
switch(m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
if(m_pData->m_u.hObject == pOther->m_pData->m_u.hObject)return CMP_EQUAL;
|
|
if(m_pData->m_u.hObject == ((kvs_hobject_t)0))return CMP_OTHERGREATER;
|
|
return CMP_THISGREATER;
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_hobject(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
return -1 * KviKvsVariantComparison::compare_real_hobject(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
return -1 * KviKvsVariantComparison::compare_string_hobject(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
return -1 * KviKvsVariantComparison::compare_boolean_hobject(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_hobject_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return KviKvsVariantComparison::compare_hobject_array(this,pOther);
|
|
break;
|
|
default: // just make gcc happy
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
return KviKvsVariantComparison::compare_integer_hobject(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
if(m_pData->m_u.iInteger == pOther->m_pData->m_u.iInteger)return CMP_EQUAL;
|
|
if(m_pData->m_u.iInteger > pOther->m_pData->m_u.iInteger)return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
return KviKvsVariantComparison::compare_integer_real(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
return KviKvsVariantComparison::compare_integer_string(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
return KviKvsVariantComparison::compare_integer_boolean(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_integer_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return KviKvsVariantComparison::compare_integer_array(this,pOther);
|
|
break;
|
|
default: // just make gcc happy
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::HObject:
|
|
return KviKvsVariantComparison::compare_real_hobject(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_real(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
if(*(m_pData->m_u.pReal) == *(pOther->m_pData->m_u.pReal))return CMP_EQUAL;
|
|
if(*(m_pData->m_u.pReal) > *(pOther->m_pData->m_u.pReal))return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
return KviKvsVariantComparison::compare_real_string(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
return KviKvsVariantComparison::compare_real_boolean(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_real_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return KviKvsVariantComparison::compare_real_array(this,pOther);
|
|
break;
|
|
default: // just make gcc happy
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::String:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String:
|
|
if(bPreferNumeric)
|
|
{
|
|
// prefer numeric comparison
|
|
double dReal1;
|
|
double dReal2;
|
|
if(asReal(dReal1))
|
|
{
|
|
if(pOther->asReal(dReal2))
|
|
{
|
|
if(dReal1 == dReal2)return CMP_EQUAL;
|
|
if(dReal1 > dReal2)return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
}
|
|
}
|
|
}
|
|
return -1 * KviTQString::cmpCI(*(m_pData->m_u.pString),*(pOther->m_pData->m_u.pString));
|
|
case KviKvsVariantData::Real:
|
|
return -1 * KviKvsVariantComparison::compare_real_string(pOther,this);
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_string(pOther,this);
|
|
case KviKvsVariantData::Boolean:
|
|
return -1 * KviKvsVariantComparison::compare_boolean_string(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_string_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return KviKvsVariantComparison::compare_string_array(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::HObject:
|
|
return KviKvsVariantComparison::compare_string_hobject(this,pOther);
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String:
|
|
return -1 * KviKvsVariantComparison::compare_string_hash(pOther,this);
|
|
case KviKvsVariantData::Real:
|
|
return -1 * KviKvsVariantComparison::compare_real_hash(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_hash(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
return -1 * KviKvsVariantComparison::compare_boolean_hash(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
if(m_pData->m_u.pHash->size() > pOther->m_pData->m_u.pHash->size())return CMP_THISGREATER;
|
|
if(m_pData->m_u.pHash->size() == pOther->m_pData->m_u.pHash->size())return CMP_EQUAL;
|
|
return CMP_OTHERGREATER;
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return -1 * KviKvsVariantComparison::compare_array_hash(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::HObject:
|
|
return -1 * KviKvsVariantComparison::compare_hobject_hash(pOther,this);
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String:
|
|
return -1 * KviKvsVariantComparison::compare_string_array(pOther,this);
|
|
case KviKvsVariantData::Real:
|
|
return -1 * KviKvsVariantComparison::compare_real_array(pOther,this);
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_array(pOther,this);
|
|
case KviKvsVariantData::Boolean:
|
|
return -1 * KviKvsVariantComparison::compare_boolean_array(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_array_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
if(m_pData->m_u.pArray->size() > pOther->m_pData->m_u.pArray->size())return CMP_THISGREATER;
|
|
if(m_pData->m_u.pArray->size() == pOther->m_pData->m_u.pArray->size())return CMP_EQUAL;
|
|
return CMP_OTHERGREATER;
|
|
break;
|
|
case KviKvsVariantData::HObject:
|
|
return -1 * KviKvsVariantComparison::compare_hobject_array(pOther,this);
|
|
break;
|
|
}
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
switch(pOther->m_pData->m_eType)
|
|
{
|
|
case KviKvsVariantData::String:
|
|
return KviKvsVariantComparison::compare_boolean_string(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Real:
|
|
return -1 * KviKvsVariantComparison::compare_real_boolean(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Integer:
|
|
return -1 * KviKvsVariantComparison::compare_integer_boolean(pOther,this);
|
|
break;
|
|
case KviKvsVariantData::Boolean:
|
|
if(m_pData->m_u.bBoolean == pOther->m_pData->m_u.bBoolean)return CMP_EQUAL;
|
|
if(m_pData->m_u.bBoolean)return CMP_THISGREATER;
|
|
return CMP_OTHERGREATER;
|
|
break;
|
|
case KviKvsVariantData::Hash:
|
|
return KviKvsVariantComparison::compare_boolean_hash(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::Array:
|
|
return KviKvsVariantComparison::compare_boolean_array(this,pOther);
|
|
break;
|
|
case KviKvsVariantData::HObject:
|
|
return KviKvsVariantComparison::compare_boolean_hobject(this,pOther);
|
|
break;
|
|
}
|
|
break;
|
|
default: // should never happen anyway
|
|
break;
|
|
}
|
|
|
|
return CMP_THISGREATER; // should never happen
|
|
}
|
|
|