gambas-source-code/main/gbx/gbx_c_subcollection.c
Benoît Minisini 4c02c6d338 ******** Merged /branches/64bits r918:1003 into /trunk
[CONFIGURATION]
* NEW: 64 bits port.

[EXAMPLES]
* BUG: Fixed the AnalogWatch example.

[WIKI CGI SCRIPT]
* NEW: Some little cosmetic changes.

[INTERPRETER]
* NEW: The extern function implementation has been redesigned and is now
  based on libffi, so that it works on 64 bits system. Because of a flaw in
  the compiler design, projects that use the Pointer datatype must be
  recompiled to be used on a 64 bits system. This flaw will be fixed in
  Gambas 3.
* OPT: Put some tables into read-only memory. About 1000 bytes are saved
  for each running interpreter, except the first one.
* BUG: Does not crash anymore if a component cannot be loaded.
* NEW: Spanish translation updated.
* NEW: A new interpreter API for returning a pointer.

[COMPILER]
* BUG: Correctly compiles LONG constants inside code.

[GB.DEBUG]
* BUG: Compiles and links the gb.debug components with the thread
  libraries.

[GB.DB.SQLITE3]
* BUG: Getting the primary index of a table without primary index is safe
  now.

[GB.GTK]
* BUG: Modified the GLib priority of watched descriptors, as the main loop 
  could enter in a loop in which user interface events were not managed.
* BUG: Message boxes use application title without crashing now.

[GB.OPENGL]
* BUG: Disable dead code.

[GB.QT.EXT]
* BUG: TextEdit.TextWidth and TextEdit.TextHeight were not declared as
  read-only properties.

[GB.XML.XSLT]
* BUG: XSLT class is now declared as being not creatable.


git-svn-id: svn://localhost/gambas/trunk@1006 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2008-01-17 21:39:26 +00:00

296 lines
5.9 KiB
C

/***************************************************************************
gbx_c_subcollection.c
(c) 2000-2007 Benoit 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************************/
#define __GBX_C_SUBCOLLECTION_C
#include "gbx_info.h"
#ifndef GBX_INFO
#include "gb_common.h"
#include "gb_error.h"
#include "gambas.h"
#include "gb_array.h"
#include "gbx_api.h"
#include "gbx_class.h"
#include "gbx_object.h"
#include "gbx_string.h"
#include "gbx_c_subcollection.h"
static void free_string_array(char ***parray)
{
int i;
char **array = *parray;
if (!*parray)
return;
for (i = 0; i < ARRAY_count(array); i++)
GB_FreeString(&array[i]);
ARRAY_delete(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);
data = HASH_TABLE_lookup(THIS->hash_table, key, len);
if (!data)
{
STRING_new_temp(&tkey, key, len);
data = (*THIS->desc->get)(THIS->container, tkey);
if (data)
{
//fprintf(stderr, "get_from_key: insert %p '%.*s'\n", data, len, key);
*((void **)HASH_TABLE_insert(THIS->hash_table, key, len)) = data;
GB_Ref(data);
}
}
else
data = *((void **)data);
return data;
}
static void clear_subcollection(CSUBCOLLECTION *_object)
{
void *value;
HASH_ENUM iter;
CLEAR(&iter);
for(;;)
{
value = HASH_TABLE_next(THIS->hash_table, &iter);
if (value == NULL)
break;
if (THIS->desc->release)
(*THIS->desc->release)(THIS->container, *((void **)value));
GB_Unref(value);
}
HASH_TABLE_delete(&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_ReturnInt(ARRAY_count(THIS->list));
else
GB_ReturnInt(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 < ARRAY_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);
HASH_TABLE_create(&THIS->hash_table, TYPE_sizeof(T_OBJECT), 0);
END_METHOD
#endif
GB_DESC NATIVE_SubCollection[] =
{
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
};
#ifndef GBX_INFO
void GB_SubCollectionNew(GB_SUBCOLLECTION *subcollection, GB_SUBCOLLECTION_DESC *desc, void *container)
{
CSUBCOLLECTION *ob;
CLASS *class;
if (*subcollection)
return;
if (!desc->klass)
class = (void *)CLASS_SubCollection;
else
class = CLASS_find(desc->klass);
OBJECT_create_native((void **)(void *)&ob, class, NULL);
ob->container = container;
ob->store = subcollection;
//GB_Ref(container);
ob->desc = desc;
HASH_TABLE_create(&ob->hash_table, TYPE_sizeof(T_OBJECT), 0);
*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 **data;
if (len < 0)
len = strlen(key);
//fprintf(stderr, "GB_SubCollectionAdd: insert %p '%.*s'\n", value, len, key);
data = (void **)HASH_TABLE_insert(THIS->hash_table, key, len);
GB_Ref(value);
GB_Unref(data);
*data = value;
}
void GB_SubCollectionRemove(void *_object, const char *key, int len)
{
void *data;
if (!THIS)
return;
if (len < 0)
len = strlen(key);
data = HASH_TABLE_lookup(THIS->hash_table, key, len);
if (data == NULL)
return;
GB_Unref(data);
//fprintf(stderr, "GB_SubCollectionRemove: remove %p '%.*s'\n", *((void **)data), len, key);
HASH_TABLE_remove(THIS->hash_table, key, len);
}
void *GB_SubCollectionGet(void *_object, const char *key, int len)
{
return get_from_key(THIS, key, len);
}
#endif