📄 slassoc.c
字号:
/* Copyright (c) 1998, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"/* #define SL_APP_WANTS_FOREACH */#include "slang.h"#include "_slang.h"#define USE_NEW_ANYTYPE_CODE 1typedef struct _SLAssoc_Array_Element_Type{ char *key; /* slstring */ struct _SLAssoc_Array_Element_Type *next; SLang_Object_Type value;}_SLAssoc_Array_Element_Type;typedef struct{ _SLAssoc_Array_Element_Type *elements[SLASSOC_HASH_TABLE_SIZE]; SLang_Object_Type default_value; unsigned int num_elements;#define HAS_DEFAULT_VALUE 1 unsigned int flags; unsigned char type;#if _SLANG_OPTIMIZE_FOR_SPEED int is_scalar_type;#endif}SLang_Assoc_Array_Type;#define USE_CACHED_STRING 1#if USE_CACHED_STRING static char *Cached_String;static SLang_Object_Type *Cached_Obj;static SLang_Assoc_Array_Type *Cached_Array;#endifstatic SLang_Assoc_Array_Type *alloc_assoc_array (unsigned char type, int has_default_value){ SLang_Assoc_Array_Type *a; a = (SLang_Assoc_Array_Type *)SLmalloc (sizeof (SLang_Assoc_Array_Type)); if (a == NULL) { if (has_default_value) SLdo_pop_n (1); return NULL; } memset ((char *) a, 0, sizeof (SLang_Assoc_Array_Type)); a->type = type;#if _SLANG_OPTIMIZE_FOR_SPEED a->is_scalar_type = (SLANG_CLASS_TYPE_SCALAR == _SLang_get_class_type (type));#endif if (has_default_value) { if (#if USE_NEW_ANYTYPE_CODE ((type != SLANG_ANY_TYPE) && (-1 == SLclass_typecast (type, 1, 1)))#else (-1 == SLclass_typecast (type, 1, 1))#endif || (-1 == SLang_pop (&a->default_value))) { SLfree ((char *) a); return NULL; } a->flags |= HAS_DEFAULT_VALUE; } return a;}static void free_element (_SLAssoc_Array_Element_Type *e){ if (e == NULL) return; SLang_free_object (&e->value); SLang_free_slstring (e->key);#if USE_CACHED_STRING if (e->key == Cached_String) Cached_String = NULL;#endif SLfree ((char *)e);}static void delete_assoc_array (SLang_Assoc_Array_Type *a){ unsigned int i; if (a == NULL) return; for (i = 0; i < SLASSOC_HASH_TABLE_SIZE; i++) { _SLAssoc_Array_Element_Type *e; e = a->elements[i]; while (e != NULL) { _SLAssoc_Array_Element_Type *next_e; next_e = e->next; free_element (e); e = next_e; } } if (a->flags & HAS_DEFAULT_VALUE) SLang_free_object (&a->default_value); SLfree ((char *) a);}_INLINE_static SLang_Object_Type *find_element (SLang_Assoc_Array_Type *a, char *str, unsigned long hash){ unsigned int h; _SLAssoc_Array_Element_Type *e; h = (unsigned int) (hash % SLASSOC_HASH_TABLE_SIZE); e = a->elements[h]; while (e != NULL) { if (str == e->key) /* slstrings can be compared this way */ {#if USE_CACHED_STRING Cached_String = str; Cached_Obj = &e->value; Cached_Array = a;#endif return &e->value; } e = e->next; } return NULL;}static _SLAssoc_Array_Element_Type *create_element (SLang_Assoc_Array_Type *a, char *str, unsigned long hash){ unsigned int h; _SLAssoc_Array_Element_Type *e; e = (_SLAssoc_Array_Element_Type *) SLmalloc (sizeof (_SLAssoc_Array_Element_Type)); if (e == NULL) return NULL; memset ((char *) e, 0, sizeof (_SLAssoc_Array_Element_Type)); h = (unsigned int) (hash % SLASSOC_HASH_TABLE_SIZE); if (NULL == (str = _SLstring_dup_hashed_string (str, hash))) { SLfree ((char *) e); return NULL; } e->key = str; e->next = a->elements[h]; a->elements[h] = e; a->num_elements += 1;#if USE_CACHED_STRING Cached_String = str; Cached_Obj = &e->value; Cached_Array = a;#endif return e;}static int store_object (SLang_Assoc_Array_Type *a, char *s, SLang_Object_Type *obj){ unsigned long hash; SLang_Object_Type *v;#if USE_CACHED_STRING if ((s == Cached_String) && (a == Cached_Array)) { v = Cached_Obj; SLang_free_object (v); } else {#endif hash = _SLcompute_string_hash (s); if (NULL != (v = find_element (a, s, hash))) SLang_free_object (v); else { _SLAssoc_Array_Element_Type *e; e = create_element (a, s, hash); if (e == NULL) return -1; v = &e->value; }#if USE_CACHED_STRING }#endif *v = *obj; return 0;}static void assoc_destroy (unsigned char type, VOID_STAR ptr){ (void) type; delete_assoc_array ((SLang_Assoc_Array_Type *) ptr);}static int pop_index (unsigned int num_indices, SLang_MMT_Type **mmt, SLang_Assoc_Array_Type **a, char **str){ if (NULL == (*mmt = SLang_pop_mmt (SLANG_ASSOC_TYPE))) { *a = NULL; *str = NULL; return -1; } if ((num_indices != 1) || (-1 == SLang_pop_slstring (str))) { SLang_verror (SL_NOT_IMPLEMENTED, "Assoc_Type arrays require a single string index"); SLang_free_mmt (*mmt); *mmt = NULL; *a = NULL; *str = NULL; return -1; } *a = (SLang_Assoc_Array_Type *) SLang_object_from_mmt (*mmt); return 0;}int _SLassoc_aget (SLtype type, unsigned int num_indices){ SLang_MMT_Type *mmt; char *str; SLang_Assoc_Array_Type *a; SLang_Object_Type *obj; int ret; (void) type; if (-1 == pop_index (num_indices, &mmt, &a, &str)) return -1;#if USE_CACHED_STRING if ((str == Cached_String) && (a == Cached_Array)) obj = Cached_Obj; else#endif obj = find_element (a, str, _SLcompute_string_hash (str)); if ((obj == NULL) && (a->flags & HAS_DEFAULT_VALUE)) obj = &a->default_value; if (obj == NULL) { SLang_verror (SL_INTRINSIC_ERROR, "No such element in Assoc Array: %s", str); ret = -1; } else {#if _SLANG_OPTIMIZE_FOR_SPEED if (a->is_scalar_type) ret = SLang_push (obj); else#endif ret = _SLpush_slang_obj (obj); } SLang_free_slstring (str); SLang_free_mmt (mmt); return ret;}int _SLassoc_aput (SLtype type, unsigned int num_indices){ SLang_MMT_Type *mmt; char *str; SLang_Assoc_Array_Type *a; SLang_Object_Type obj; int ret; (void) type; if (-1 == pop_index (num_indices, &mmt, &a, &str)) return -1; ret = -1; if (0 == SLang_pop (&obj)) { if ((obj.data_type != a->type)#if USE_NEW_ANYTYPE_CODE && (a->type != SLANG_ANY_TYPE)#endif ) { (void) SLang_push (&obj); if ((-1 == SLclass_typecast (a->type, 1, 1)) || (-1 == SLang_pop (&obj))) goto the_return; } if (-1 == store_object (a, str, &obj)) SLang_free_object (&obj); else ret = 0; } the_return: SLang_free_slstring (str); SLang_free_mmt (mmt); return ret;}static int assoc_anew (unsigned char type, unsigned int num_dims){ SLang_MMT_Type *mmt; SLang_Assoc_Array_Type *a; int has_default_value; has_default_value = 0; switch (num_dims) { case 0: type = SLANG_ANY_TYPE; break; case 2: (void) SLreverse_stack (2); has_default_value = 1; /* drop */ case 1: if (0 == SLang_pop_datatype (&type)) break; num_dims--; /* drop */ default: SLdo_pop_n (num_dims); SLang_verror (SL_SYNTAX_ERROR, "Usage: Assoc_Type [DataType_Type]"); return -1; } a = alloc_assoc_array (type, has_default_value); if (a == NULL) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -