/*************************************************************************** gbx_c_subcollection.c (c) 2000-2007 Benoit Minisini 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