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.
kvirc/src/kvirc/kvs/kvi_kvs_array.cpp

228 lines
5.3 KiB

//=============================================================================
//
// File : kvi_kvs_array.cpp
// Created on Tue 07 Oct 2003 01:07:31 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_array.h"
#include "kvi_malloc.h"
#include <stdlib.h>
#define KVI_KVS_ARRAY_ALLOC_CHUNK 8
KviKvsArray::KviKvsArray()
: KviHeapObject()
{
m_pData = 0;
m_uSize = 0;
m_uAllocSize = 0;
}
KviKvsArray::KviKvsArray(const KviKvsArray &a)
: KviHeapObject()
{
m_uSize = a.m_uSize;
m_uAllocSize = a.m_uAllocSize;
if(m_uAllocSize > 0)
{
m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
kvs_uint_t i;
for(i=0;i<m_uSize;i++)
if(a.m_pData[i])m_pData[i] = new KviKvsVariant(*(a.m_pData[i]));
else m_pData[i] = 0;
} else {
m_pData = 0;
}
}
KviKvsArray::~KviKvsArray()
{
if(m_pData)
{
for(kvs_uint_t i=0;i<m_uSize;i++)
if(m_pData[i])delete m_pData[i];
kvi_free(m_pData);
}
}
static int kvs_array_reverse_compare_func(const void * v1,const void * v2)
{
if(*((KviKvsVariant **)v1))return (*((KviKvsVariant **)v1))->compare(*((KviKvsVariant **)v2));
if(*((KviKvsVariant **)v2))return -(*((KviKvsVariant **)v2))->compare(*((KviKvsVariant **)v1));
return 0;
}
static int kvs_array_compare_func(const void * v1,const void * v2)
{
if(*((KviKvsVariant **)v1))return -(*((KviKvsVariant **)v1))->compare(*((KviKvsVariant **)v2));
if(*((KviKvsVariant **)v2))return (*((KviKvsVariant **)v2))->compare(*((KviKvsVariant **)v1));
return 0;
}
void KviKvsArray::sort()
{
if(m_uSize < 2)return; // already sorted
qsort(m_pData,m_uSize,sizeof(KviKvsVariant *),kvs_array_compare_func);
findNewSize();
}
void KviKvsArray::rsort()
{
if(m_uSize < 2)return; // already sorted
qsort(m_pData,m_uSize,sizeof(KviKvsVariant *),kvs_array_reverse_compare_func);
findNewSize();
}
void KviKvsArray::unset(kvs_uint_t uIdx)
{
if(uIdx >= m_uSize)return;
if(m_pData[uIdx])
{
delete m_pData[uIdx];
m_pData[uIdx] = 0;
}
if(uIdx == (m_uSize - 1))
{
findNewSize();
}
}
void KviKvsArray::findNewSize()
{
// find the new size
if(m_uSize == 0)return;
kvs_uint_t u = m_uSize - 1;
while(u > 0)
{
if(m_pData[u])break;
u--;
}
if(m_pData[u])m_uSize = u + 1;
else {
// u == 0, and there is no data in there
m_uSize = 0;
}
// need to shrink ?
if((m_uAllocSize - m_uSize) > KVI_KVS_ARRAY_ALLOC_CHUNK)
{
m_uAllocSize = m_uSize;
// m_pData is non-zero here since was m_uSize > 0 initally
if(m_uSize > 0)
{
m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
} else {
kvi_free(m_pData);
m_pData = 0;
}
}
}
void KviKvsArray::set(kvs_uint_t uIdx,KviKvsVariant * pVal)
{
if(uIdx >= m_uSize)
{
if(uIdx == m_uSize)
{
m_uAllocSize += KVI_KVS_ARRAY_ALLOC_CHUNK; // sequential set
} else {
m_uAllocSize = uIdx + 1;
}
if(m_pData)
m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
else
m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
for(kvs_uint_t u=m_uSize;u<uIdx;u++)
m_pData[u] = 0;
m_uSize = uIdx+1;
m_pData[uIdx] = pVal;
} else {
if(m_pData[uIdx])delete m_pData[uIdx];
m_pData[uIdx] = pVal;
}
}
KviKvsVariant * KviKvsArray::getAt(kvs_uint_t uIdx)
{
if(uIdx >= m_uSize)
{
if(uIdx == m_uSize)
{
m_uAllocSize += KVI_KVS_ARRAY_ALLOC_CHUNK; // sequential set
} else {
m_uAllocSize = uIdx + 1;
}
if(m_pData)
m_pData = (KviKvsVariant **)kvi_realloc(m_pData,(sizeof(KviKvsVariant *)) * m_uAllocSize);
else
m_pData = (KviKvsVariant **)kvi_malloc((sizeof(KviKvsVariant *)) * m_uAllocSize);
for(kvs_uint_t u=m_uSize;u<uIdx;u++)
m_pData[u] = 0;
m_uSize = uIdx+1;
m_pData[uIdx] = new KviKvsVariant();
} else {
if(!m_pData[uIdx])
m_pData[uIdx] = new KviKvsVariant();
}
return m_pData[uIdx];
}
void KviKvsArray::serialize(TQString& result)
{
TQString tmpBuffer;
result="[";
kvs_uint_t u = 0;
bool bNeedComma = false;
while(u < m_uSize)
{
if(bNeedComma)result.append(',');
else bNeedComma = true;
if(m_pData[u]) {
m_pData[u]->serialize(tmpBuffer);
result.append(tmpBuffer);
} else {
result.append("null");
}
u++;
}
result.append(']');
}
void KviKvsArray::appendAsString(TQString &szBuffer)
{
kvs_uint_t u = 0;
bool bNeedComma = false;
while(u < m_uSize)
{
if(bNeedComma)szBuffer.append(',');
else bNeedComma = true;
if(m_pData[u])m_pData[u]->appendAsString(szBuffer);
u++;
}
}