Skip to content

Instantly share code, notes, and snippets.

@gabonator
Created December 7, 2016 13:37
Show Gist options
  • Save gabonator/ad16e1ace3cdf62d12908780bd794a80 to your computer and use it in GitHub Desktop.
Save gabonator/ad16e1ace3cdf62d12908780bd794a80 to your computer and use it in GitHub Desktop.
Variant, class that holds any types - arrays, dictionaries in any hierarchy as well as simple types as numbers/strings, fast replacement for json in C++
CVariantBase::CVariantBase() : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pstrValue(NULL), m_pnValue(NULL), m_pfValue(NULL), m_pqwValue(NULL)
{
}
CVariantBase::CVariantBase(LPCTSTR strValue) : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pnValue(NULL), m_pfValue(NULL), m_pqwValue(NULL)
{
m_pstrValue = new CString();
*m_pstrValue = strValue;
}
CVariantBase::CVariantBase(INT nValue) : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pstrValue(NULL), m_pfValue(NULL), m_pqwValue(NULL)
{
m_pnValue = new INT();
*m_pnValue = nValue;
}
CVariantBase::CVariantBase(FLOAT fValue) : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pstrValue(NULL), m_pnValue(NULL), m_pqwValue(NULL)
{
m_pfValue = new FLOAT();
*m_pfValue = fValue;
}
CVariantBase::CVariantBase(QWORD qwValue) : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pstrValue(NULL), m_pnValue(NULL), m_pfValue(NULL)
{
m_pqwValue = new QWORD();
*m_pqwValue = qwValue;
}
CVariantBase::CVariantBase(CSharedPtr<CBaseObject> sValue) : m_pmapAttributes(NULL), m_parrAttributes(NULL), m_pstrValue(NULL), m_pnValue(NULL), m_pfValue(NULL), m_pqwValue(NULL)
{
m_sValue = sValue;
}
CVariantBase::~CVariantBase()
{
_ASSERT(!!m_pmapAttributes + !!m_parrAttributes + !!m_pstrValue + !!m_pnValue + !!m_pfValue + !!m_pqwValue <= 1);
SAFE_DELETE(m_pmapAttributes);
SAFE_DELETE(m_parrAttributes);
SAFE_DELETE(m_pstrValue);
SAFE_DELETE(m_pnValue);
SAFE_DELETE(m_pfValue);
SAFE_DELETE(m_pqwValue);
}
/*static*/ CVariantBase::SVariantBase& CVariantBase::Invalid()
{
static SVariantBase sVariant;
return sVariant;
}
BOOL32 CVariantBase::IsValid() const
{
return this && (IsArray() || IsMap() || IsString() || IsInteger() || IsFloat() || IsSharedPtr() || IsQword());
}
BOOL32 CVariantBase::IsArray() const
{
return !!m_parrAttributes;
}
BOOL32 CVariantBase::IsMap() const
{
return !!m_pmapAttributes;
}
BOOL32 CVariantBase::IsString() const
{
return !!m_pstrValue;
}
BOOL32 CVariantBase::IsInteger() const
{
return !!m_pnValue;
}
BOOL32 CVariantBase::IsFloat() const
{
return !!m_pfValue;
}
BOOL32 CVariantBase::IsQword() const
{
return !!m_pqwValue;
}
BOOL32 CVariantBase::IsSharedPtr() const
{
return !!m_sValue.get();
}
CString CVariantBase::GetString() const
{
if ( !IsString() )
{
_ASSERT(0);
return _T("");
}
return *m_pstrValue;
}
INT CVariantBase::GetInteger() const
{
if ( !IsInteger() )
{
_ASSERT(0);
return 0;
}
return *m_pnValue;
}
FLOAT CVariantBase::GetFloat() const
{
if ( !IsFloat() )
{
_ASSERT(0);
return 0.0f;
}
return *m_pfValue;
}
QWORD CVariantBase::GetQword() const
{
if ( !IsQword() )
{
_ASSERT(0);
return 0;
}
return *m_pqwValue;
}
INT CVariantBase::GetLength() const
{
if ( IsArray() )
return m_parrAttributes->GetSize();
if ( IsMap() )
return m_pmapAttributes->GetCount();
_ASSERT(0);
return 0;
}
CSharedPtr<CBaseObject> CVariantBase::GetSharedPtr() const
{
return m_sValue;
}
CVariantBase::SVariantBase& CVariantBase::operator[](CString strKey)
{
if ( IsValid() && !IsMap() )
{
_ASSERT(0);
return Invalid();
}
if (!IsMap())
{
m_pmapAttributes = new CMap2<CString, SVariantBase>();
}
if ( !m_pmapAttributes->LookupRef(strKey) )
{
m_pmapAttributes->SetAt(strKey, SVariantBase( new CVariantBase() ));
}
_ASSERT(m_pmapAttributes->LookupRef(strKey));
return *m_pmapAttributes->LookupRef(strKey);
}
CVariantBase::SVariantBase& CVariantBase::operator[](INT nIndex)
{
if ( IsValid() && !IsArray() )
{
_ASSERT(0);
return Invalid();
}
if ( !IsArray() )
{
m_parrAttributes = new CArray<SVariantBase>();
}
if ( nIndex >= m_parrAttributes->GetSize() )
m_parrAttributes->SetSize(nIndex+1);
_ASSERT( nIndex < m_parrAttributes->GetSize() );
if ( !m_parrAttributes->GetAt(nIndex) )
{
m_parrAttributes->SetAt(nIndex, SVariantBase( new CVariantBase() ));
}
return m_parrAttributes->GetAt(nIndex);
}
void CVariantBase::Dump(CString strPrefix)
{
if ( !this )
{
CLowSystem::SysDbg( _T("%sInvalid pointer!\n"), (LPCTSTR)strPrefix);
return;
}
if ( IsArray() )
{
CLowSystem::SysDbg( _T("%sArray [\n"), (LPCTSTR)strPrefix);
for ( INT i = 0; i < m_parrAttributes->GetSize(); i++ )
m_parrAttributes->GetAt(i)->Dump(strPrefix + _T(" "));
CLowSystem::SysDbg( _T("%s]\n"), (LPCTSTR)strPrefix);
return;
}
if ( IsMap() )
{
CLowSystem::SysDbg( _T("%sMap {\n"), (LPCTSTR)strPrefix);
POSITION pos = m_pmapAttributes->GetStartPosition();
while (pos)
{
CString strKey;
CVariantBase::SVariantBase sVariant;
m_pmapAttributes->GetNextAssoc(pos, strKey, sVariant);
CLowSystem::SysDbg( _T("%s %s:"), (LPCTSTR)strPrefix, (LPCTSTR)strKey );
sVariant->Dump(strPrefix + _T(" "));
}
CLowSystem::SysDbg( _T("%s}\n"), (LPCTSTR)strPrefix);
return;
}
if ( IsString() )
{
CLowSystem::SysDbg( _T("%sString: '%s'\n"), (LPCTSTR)strPrefix, (LPCTSTR)*m_pstrValue);
return;
}
if ( IsInteger() )
{
CLowSystem::SysDbg( _T("%sInteger: '%d'\n"), (LPCTSTR)strPrefix, *m_pnValue);
return;
}
if ( IsFloat() )
{
CLowSystem::SysDbg( _T("%sFloat: '%f'\n"), (LPCTSTR)strPrefix, *m_pfValue);
return;
}
CLowSystem::SysDbg( _T("%sNull\n"), (LPCTSTR)strPrefix);
}
CVariant::CVariant(CVariantBase::SVariantBase var) : CVariantBase::SVariantBase(var)
{
}
CVariant::CVariant()
{
Reset( new CVariantBase() );
}
/*explicit*/ CVariant::CVariant(LPCTSTR strValue)
{
Reset( new CVariantBase(strValue) );
}
/*explicit*/ CVariant::CVariant(INT nValue)
{
Reset( new CVariantBase(nValue) );
}
/*explicit*/ CVariant::CVariant(FLOAT fValue)
{
Reset( new CVariantBase(fValue) );
}
/*explicit*/ CVariant::CVariant(QWORD qwValue)
{
Reset( new CVariantBase(qwValue) );
}
/*explicit*/ CVariant::CVariant(CSharedPtr<CBaseObject> sValue)
{
Reset( new CVariantBase(sValue) );
}
CVariant& CVariant::operator[](LPCSTR strKey)
{
_ASSERT(get());
return (CVariant&)get()->operator[](CString(strKey));
}
CVariant& CVariant::operator[](CString strKey)
{
_ASSERT(get());
return (CVariant&)get()->operator[](CString(strKey));
}
CVariant& CVariant::operator[](INT nKey)
{
_ASSERT(get());
return (CVariant&)get()->operator[](nKey);
}
CVariant::operator CString() const
{
return get()->GetString();
}
CVariant::operator bool_type() const
{
return (get() && get()->IsValid()) ? &CVariant::this_type_does_not_support_comparisons : 0;
}
class CVariantBase
{
public:
typedef CSharedPtr<CVariantBase> SVariantBase;
private:
CMap2<Library::CString, SVariantBase>* m_pmapAttributes;
CArray<SVariantBase>* m_parrAttributes;
CString* m_pstrValue;
INT* m_pnValue;
FLOAT* m_pfValue;
QWORD* m_pqwValue;
CSharedPtr<CBaseObject> m_sValue;
public:
CVariantBase();
explicit CVariantBase(LPCTSTR strValue);
explicit CVariantBase(INT nValue);
explicit CVariantBase(FLOAT fValue);
explicit CVariantBase(QWORD qwValue);
CVariantBase(CSharedPtr<CBaseObject> sValue);
~CVariantBase();
public:
static SVariantBase& Invalid();
BOOL32 IsValid() const;
BOOL32 IsArray() const;
BOOL32 IsMap() const;
BOOL32 IsString() const;
BOOL32 IsInteger() const;
BOOL32 IsFloat() const;
BOOL32 IsQword() const;
BOOL32 IsSharedPtr() const;
public:
INT GetInteger() const;
FLOAT GetFloat() const;
QWORD GetQword() const;
INT GetLength() const;
CString GetString() const;
CSharedPtr<CBaseObject> GetSharedPtr() const;
SVariantBase& operator[](CString strKey);
SVariantBase& operator[](INT nIndex);
public:
void Dump(CString strPrefix = _T(""));
};
class CVariant : public CVariantBase::SVariantBase
{
public:
CVariant(CVariantBase::SVariantBase var);
CVariant();
explicit CVariant(LPCTSTR strValue);
explicit CVariant(INT nValue);
explicit CVariant(FLOAT fValue);
explicit CVariant(QWORD qwValue);
CVariant(CSharedPtr<CBaseObject> sValue);
CVariant& operator[](LPCSTR strKey);
CVariant& operator[](CString strKey);
CVariant& operator[](INT nKey);
public:
operator CString() const;
operator bool_type() const;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment