a7c3939e3d
* BUG: Be sure that the welcome dialog filter has the focus. [WEBSITE MAKER] * NEW: Update for 3.3.4. [GB.DB] * BUG: A failing table or user add does not leak memory anymore. * BUG: Fix the removal method of the .SubCollection virtual class. [GB.DB.SQLITE3] * BUG: Detect serial fields correctly now. [GB.QT4] * BUG: Enusre that embedded windows emit their Open event before any Move, Resize events... git-svn-id: svn://localhost/gambas/trunk@5340 867c0c6c-44f3-4631-809d-bfa615b0a4ec
264 lines
5.5 KiB
C
264 lines
5.5 KiB
C
/***************************************************************************
|
|
|
|
c_subcollection.c
|
|
|
|
(c) 2000-2012 Benoît Minisini <gambas@users.sourceforge.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, or (at your option)
|
|
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 __C_SUBCOLLECTION_C
|
|
|
|
#include "main.h"
|
|
#include "c_subcollection.h"
|
|
|
|
|
|
static void free_string_array(char ***parray)
|
|
{
|
|
int i;
|
|
char **array = *parray;
|
|
|
|
if (!*parray)
|
|
return;
|
|
|
|
for (i = 0; i < GB.Count(array); i++)
|
|
GB.FreeString(&array[i]);
|
|
|
|
GB.FreeArray(parray);
|
|
}
|
|
|
|
static void *get_from_key(CSUBCOLLECTION *_object, const char *key, int len)
|
|
{
|
|
void *data;
|
|
char *tkey;
|
|
|
|
if (!key || !*key)
|
|
return NULL;
|
|
|
|
if (len <= 0)
|
|
len = strlen(key);
|
|
|
|
//fprintf(stderr, "get_from_key: %.*s\n", len, key);
|
|
|
|
if (GB.HashTable.Get(THIS->hash_table, key, len, &data))
|
|
{
|
|
tkey = GB.TempString(key, len);
|
|
data = (*THIS->desc->get)(THIS->container, tkey);
|
|
if (data)
|
|
{
|
|
//fprintf(stderr, "get_from_key: insert %p '%.*s'\n", data, len, key);
|
|
GB.HashTable.Add(THIS->hash_table, key, len, data);
|
|
GB.Ref(data);
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
static CSUBCOLLECTION *_current = NULL;
|
|
|
|
static void clear_one(void *data)
|
|
{
|
|
if (_current->desc->release)
|
|
(*_current->desc->release)(_current->container, data);
|
|
|
|
//fprintf(stderr, "clear: %p\n", data);
|
|
GB.Unref(&data);
|
|
}
|
|
|
|
static void clear_subcollection(CSUBCOLLECTION *_object)
|
|
{
|
|
_current = THIS;
|
|
GB.HashTable.Enum(THIS->hash_table, clear_one);
|
|
GB.HashTable.Free(&THIS->hash_table);
|
|
}
|
|
|
|
|
|
BEGIN_METHOD_VOID(CSUBCOLLECTION_free)
|
|
|
|
//*THIS->store = NULL;
|
|
free_string_array(&THIS->list);
|
|
|
|
clear_subcollection(THIS);
|
|
|
|
END_METHOD
|
|
|
|
|
|
BEGIN_PROPERTY(CSUBCOLLECTION_count)
|
|
|
|
/*free_string_array(&THIS->list);*/
|
|
if (!THIS->list)
|
|
(*THIS->desc->list)(THIS->container, &THIS->list);
|
|
|
|
if (THIS->list)
|
|
GB.ReturnInteger(GB.Count(THIS->list));
|
|
else
|
|
GB.ReturnInteger(0);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_METHOD(CSUBCOLLECTION_exist, GB_STRING key)
|
|
|
|
char *key = GB.ToZeroString(ARG(key));
|
|
|
|
if (!key || !*key)
|
|
GB.ReturnBoolean(FALSE);
|
|
else
|
|
GB.ReturnBoolean((*THIS->desc->exist)(THIS->container, key));
|
|
|
|
END_METHOD
|
|
|
|
|
|
BEGIN_METHOD_VOID(CSUBCOLLECTION_next)
|
|
|
|
int *pos = (int *)GB.GetEnum();
|
|
|
|
if (THIS->desc->list)
|
|
{
|
|
char *key = NULL;
|
|
int n;
|
|
|
|
if (*pos == 0)
|
|
{
|
|
free_string_array(&THIS->list);
|
|
(*THIS->desc->list)(THIS->container, &THIS->list);
|
|
}
|
|
|
|
if (THIS->list)
|
|
{
|
|
if (*pos < GB.Count(THIS->list))
|
|
{
|
|
n = (*pos)++;
|
|
key = THIS->list[n];
|
|
}
|
|
}
|
|
|
|
if (!key || !*key)
|
|
GB.StopEnum();
|
|
else
|
|
GB.ReturnObject(get_from_key(THIS, key, 0));
|
|
}
|
|
else
|
|
{
|
|
/*void *elt;
|
|
|
|
elt = get_from_key(THIS, NULL, *pos);
|
|
(*pos)++;
|
|
if (elt)
|
|
GB_ReturnObject(elt);
|
|
else*/
|
|
GB.StopEnum();
|
|
}
|
|
|
|
END_METHOD
|
|
|
|
|
|
BEGIN_METHOD(CSUBCOLLECTION_get, GB_STRING key)
|
|
|
|
GB.ReturnObject(get_from_key(THIS, STRING(key), LENGTH(key)));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD_VOID(CSUBCOLLECTION_refresh)
|
|
|
|
clear_subcollection(THIS);
|
|
GB.HashTable.New(&THIS->hash_table, GB_COMP_BINARY);
|
|
|
|
END_METHOD
|
|
|
|
GB_DESC SubCollectionDesc[] =
|
|
{
|
|
GB_DECLARE(".SubCollection", sizeof(CSUBCOLLECTION)),
|
|
|
|
GB_METHOD("_free", NULL, CSUBCOLLECTION_free, NULL),
|
|
|
|
GB_PROPERTY_READ("Count", "i", CSUBCOLLECTION_count),
|
|
//GB_PROPERTY_READ("Length", "i", CSUBCOLLECTION_count),
|
|
|
|
GB_METHOD("Exist", "b", CSUBCOLLECTION_exist, "(Key)s"),
|
|
GB_METHOD("_next", "o", CSUBCOLLECTION_next, NULL),
|
|
GB_METHOD("_get", "o", CSUBCOLLECTION_get, "(Key)s"),
|
|
GB_METHOD("Refresh", NULL, CSUBCOLLECTION_refresh, NULL),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|
|
|
|
void GB_SubCollectionNew(CSUBCOLLECTION **subcollection, SUBCOLLECTION_DESC *desc, void *container)
|
|
{
|
|
CSUBCOLLECTION *ob;
|
|
|
|
if (*subcollection)
|
|
return;
|
|
|
|
ob = GB.New(GB.FindClass(desc->klass), NULL, NULL);
|
|
|
|
ob->container = container;
|
|
//ob->store = subcollection;
|
|
//GB_Ref(container);
|
|
ob->desc = desc;
|
|
GB.HashTable.New(&ob->hash_table, GB_COMP_BINARY);
|
|
|
|
*subcollection = ob;
|
|
GB.Ref(ob);
|
|
}
|
|
|
|
|
|
void *GB_SubCollectionContainer(void *_object)
|
|
{
|
|
return THIS->container;
|
|
}
|
|
|
|
|
|
void GB_SubCollectionAdd(void *_object, const char *key, int len, void *value)
|
|
{
|
|
void *old_value = NULL;
|
|
|
|
if (len <= 0)
|
|
len = strlen(key);
|
|
|
|
//fprintf(stderr, "GB_SubCollectionAdd: insert %p '%.*s'\n", value, len, key);
|
|
GB.HashTable.Get(THIS->hash_table, key, len, &old_value);
|
|
GB.HashTable.Add(THIS->hash_table, key, len, value);
|
|
GB.Ref(value);
|
|
GB.Unref(&old_value);
|
|
}
|
|
|
|
void GB_SubCollectionRemove(void *_object, const char *key, int len)
|
|
{
|
|
void *old_value;
|
|
|
|
if (!THIS)
|
|
return;
|
|
|
|
if (len <= 0)
|
|
len = strlen(key);
|
|
|
|
if (!GB.HashTable.Get(THIS->hash_table, key, len, &old_value))
|
|
{
|
|
//fprintf(stderr, "GB_SubCollectionRemove: remove %p '%.*s'\n", old_value, len, key);
|
|
GB.HashTable.Remove(THIS->hash_table, key, len);
|
|
GB.Unref(&old_value);
|
|
}
|
|
}
|
|
|
|
|
|
void *GB_SubCollectionGet(void *_object, const char *key, int len)
|
|
{
|
|
return get_from_key(THIS, key, len);
|
|
}
|