630c52937c
* OPT: Optimization of locale-aware string comparison routine. * OPT: Do not use sprintf() for searching event handlers in symbol tables. * OPT: String[].Find() and String.Exist() are now twice faster for ASCII binary and case insensitive comparisons. * BUG: Initialize the locale before loading any class. * OPT: Do not use sprintf() when searching a file inside Gambas archives. * OPT: Unroll a loop to speed up binary string identity comparison a little bit. * BUG: Collection keys are now hashed with their eight last characters. * BUG: Internal Collection automatic resizing was disabled. Re-enable it! git-svn-id: svn://localhost/gambas/trunk@4153 867c0c6c-44f3-4631-809d-bfa615b0a4ec
270 lines
6 KiB
C
270 lines
6 KiB
C
/***************************************************************************
|
|
|
|
gbx_event.c
|
|
|
|
(c) 2000-2011 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 __GBX_EVENT_C
|
|
|
|
#include "gb_common.h"
|
|
#include "gb_common_buffer.h"
|
|
#include "gbx_exec.h"
|
|
#include "gbx_api.h"
|
|
|
|
#include "gbx_event.h"
|
|
|
|
//#define DEBUG_ME 1
|
|
|
|
void *EVENT_Last = NULL;
|
|
|
|
char *EVENT_PreviousName = NULL;
|
|
char *EVENT_Name = NULL;
|
|
|
|
static EVENT_POST *_post_list = NULL;
|
|
|
|
|
|
static void check_event_method(CLASS *class, const char *name, CLASS_DESC_METHOD *desc, CLASS_EVENT *event)
|
|
{
|
|
if (event->n_param < desc->npmin)
|
|
{
|
|
/*printf("event->n_param = %d desc->npmin = %d desc->npmax = %d\n", event->n_param, desc->npmin, desc->npmax);*/
|
|
THROW(E_EVENT, class->name, name, "Too many arguments");
|
|
}
|
|
|
|
if (event->n_param > desc->npmax)
|
|
THROW(E_EVENT, class->name, name, "Not enough arguments");
|
|
|
|
if (TYPE_compare_signature(desc->signature, event->n_param, (TYPE *)event->param, event->n_param))
|
|
THROW(E_EVENT, class->name, name, "Type mismatch");
|
|
|
|
if (desc->type != T_VOID)
|
|
THROW(E_EVENT, class->name, name, "Not a procedure");
|
|
}
|
|
|
|
|
|
void EVENT_search(CLASS *class, ushort *event, const char *name, OBJECT *parent)
|
|
{
|
|
//ushort *event;
|
|
//ushort *self;
|
|
CLASS *class_parent;
|
|
int i, index;
|
|
const char *event_name;
|
|
CLASS_DESC *desc;
|
|
int kind;
|
|
int len_name, len_event_name;
|
|
char *func_name = COMMON_buffer;
|
|
char *pevent_name;
|
|
|
|
#if DEBUG_ME
|
|
fprintf(stderr, "EVENT_search: class = %s name = %s parent = %p\n", class->name, name, parent);
|
|
#endif
|
|
|
|
//event = OBJECT_event(object)->event;
|
|
//self = OBJECT_event(object)->self;
|
|
|
|
if (class->n_event <= 0)
|
|
return;
|
|
|
|
len_name = name ? strlen(name) : 0;
|
|
|
|
if (len_name == 0 || len_name >= (COMMON_BUF_MAX - 4))
|
|
{
|
|
memset(event, 0, class->n_event * sizeof(ushort));
|
|
return;
|
|
}
|
|
|
|
kind = parent->class == CLASS_Class ? CD_STATIC_METHOD : CD_METHOD;
|
|
|
|
if (kind == CD_STATIC_METHOD)
|
|
class_parent = (CLASS *)parent;
|
|
else
|
|
class_parent = parent->class;
|
|
|
|
strcpy(func_name, name);
|
|
pevent_name = &func_name[len_name];
|
|
*pevent_name++ = '_';
|
|
|
|
for (i = 0; i < class->n_event; i++)
|
|
{
|
|
event[i] = 0;
|
|
|
|
event_name = class->event[i].name;
|
|
if (*event_name == ':')
|
|
event_name++;
|
|
|
|
len_event_name = strlen(event_name);
|
|
if ((len_name + len_event_name + 1) >= COMMON_BUF_MAX)
|
|
continue;
|
|
|
|
strcpy(pevent_name, event_name);
|
|
index = CLASS_find_symbol(class_parent, func_name);
|
|
|
|
if (index != NO_SYMBOL)
|
|
{
|
|
desc = class_parent->table[index].desc;
|
|
if (CLASS_DESC_get_type(desc) == kind)
|
|
{
|
|
#if DEBUG_ME
|
|
fprintf(stderr, "EVENT_search: FOUND [%d] %s.%s index = %d parent = %s.%p\n", i, class_parent->name, func_name, index, parent->class->name, parent);
|
|
#endif
|
|
check_event_method(class_parent, func_name, &desc->method, &class->event[i]);
|
|
event[i] = index + 1;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
snprintf(func_name, COMMON_BUF_MAX, "ME_%s", event_name);
|
|
index = CLASS_find_symbol(class, func_name);
|
|
|
|
if (index != NO_SYMBOL)
|
|
{
|
|
desc = class->table[index].desc;
|
|
if (CLASS_DESC_get_type(desc) == CD_METHOD)
|
|
{
|
|
#if DEBUG_ME
|
|
printf("EVENT_search: FOUND [%d] %s.%s index = %d parent = %s.%p\n", i, class->name, func_name, index, parent->class->name, parent);
|
|
#endif
|
|
check_event_method(class, func_name, &desc->method, &class->event[i]);
|
|
if (!self)
|
|
{
|
|
ALLOC_ZERO(&self, sizeof(ushort) * class->n_event, "EVENT_search");
|
|
OBJECT_event(object)->self = self;
|
|
}
|
|
self[i] = index + 1;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EVENT_exit()
|
|
{
|
|
EVENT_POST *ep;
|
|
|
|
while (_post_list)
|
|
{
|
|
ep = _post_list;
|
|
_post_list = _post_list->list.next;
|
|
FREE(&ep, "EVENT_exit");
|
|
}
|
|
|
|
STRING_free(&EVENT_Name);
|
|
}
|
|
|
|
|
|
static void post(void (*func)(), int nparam, intptr_t param, intptr_t param2)
|
|
{
|
|
EVENT_POST *ep;
|
|
|
|
/*printf("EVENT_post\n");
|
|
fflush(NULL);*/
|
|
|
|
ALLOC(&ep, sizeof(EVENT_POST), "EVENT_post");
|
|
|
|
ep->func = func;
|
|
ep->nparam = nparam;
|
|
ep->param = param;
|
|
ep->param2 = param2;
|
|
|
|
LIST_insert(&_post_list, ep, &ep->list);
|
|
|
|
HOOK(post)();
|
|
}
|
|
|
|
|
|
void EVENT_post(void (*func)(), intptr_t param)
|
|
{
|
|
post(func, 1, param, 0);
|
|
}
|
|
|
|
void EVENT_post2(void (*func)(), intptr_t param, intptr_t param2)
|
|
{
|
|
post(func, 2, param, param2);
|
|
}
|
|
|
|
static void post_event(void *object, int event)
|
|
{
|
|
GB_Raise(object, event, 0);
|
|
OBJECT_UNREF(object, "post_event");
|
|
}
|
|
|
|
void EVENT_post_event(void *object, int event)
|
|
{
|
|
/*if (!GB_CanRaise(object, event))
|
|
{
|
|
fprintf(stderr, "EVENT_post_event: cannot raise event\n");
|
|
return;
|
|
}*/
|
|
|
|
OBJECT_REF(object, "EVENT_post_event");
|
|
post((void (*)())post_event, 2, (intptr_t)object, (intptr_t)event);
|
|
}
|
|
|
|
|
|
bool EVENT_check_post(void)
|
|
{
|
|
EVENT_POST *ep;
|
|
EVENT_POST save;
|
|
bool ret = FALSE;
|
|
|
|
#ifdef DEBUG_POST
|
|
fprintf(stderr, "EVENT_check_post: START\n");
|
|
#endif
|
|
|
|
while (_post_list)
|
|
{
|
|
ret = TRUE;
|
|
ep = _post_list;
|
|
save = *ep;
|
|
LIST_remove(&_post_list, _post_list, &_post_list->list);
|
|
|
|
FREE(&ep, "EVENT_check_post");
|
|
|
|
if (save.nparam == 1)
|
|
(*save.func)(save.param);
|
|
else
|
|
(*save.func)(save.param, save.param2);
|
|
}
|
|
|
|
/*norec = FALSE;*/
|
|
|
|
#ifdef DEBUG_POST
|
|
fprintf(stderr, "EVENT_check_post: END\n");
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
char *EVENT_enter_name(const char *name)
|
|
{
|
|
char *save = EVENT_PreviousName;
|
|
EVENT_PreviousName = EVENT_Name;
|
|
EVENT_Name = (char *)name;
|
|
return save;
|
|
}
|
|
|
|
void EVENT_leave_name(const char *save)
|
|
{
|
|
EVENT_Name = EVENT_PreviousName;
|
|
EVENT_PreviousName = (char *)save;
|
|
}
|