From 3568b4b3840dc6e7968c0949b16507b250a0365f Mon Sep 17 00:00:00 2001 From: MORIOKA Tomohiko Date: Mon, 1 Apr 2013 14:08:51 +0900 Subject: [PATCH] New files. --- cos-i.h | 286 ++++++++++++++++++++++++++++++++++++++++++++ cos.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cos.h | 88 ++++++++++++++ read.c | 94 +++++++++++++++ symbol.c | 264 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1130 insertions(+) create mode 100644 cos-i.h create mode 100644 cos.c create mode 100644 cos.h create mode 100644 read.c create mode 100644 symbol.c diff --git a/cos-i.h b/cos-i.h new file mode 100644 index 0000000..1468fd8 --- /dev/null +++ b/cos-i.h @@ -0,0 +1,286 @@ +/* Internal definitions of CONCORD Object System + + Copyright (C) 2013 MORIOKA Tomohiko + This file is part of the CONCORD Library. + + The CONCORD Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The CONCORD Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the CONCORD Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _COS_I_H +#define _COS_I_H + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#include "sysdep.h" +#include "concord.h" +#include "cos.h" + +#ifndef SIZEOF_COS_INT +# define SIZEOF_COS_INT SIZEOF_VOID_P +#endif + +#ifndef SIZEOF_INT +# define SIZEOF_INT (sizeof (int)) +#endif + +#ifndef SIZEOF_LONG +# define SIZEOF_LONG (sizeof (long)) +#endif + +#ifndef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG (sizeof (long long)) +#endif + +#ifndef COS_INT +# if SIZEOF_COS_INT == SIZEOF_LONG +# define COS_INT long +# elif SIZEOF_COS_INT == SIZEOF_INT +# define COS_INT int +# elif SIZEOF_COS_INT == SIZEOF_LONG_LONG +# define COS_INT long long +# else +# error Unable to determine suitable type for COS_INT +# endif +#endif + +#ifndef COS_UINT +# define COS_UINT unsigned COS_INT +#endif + +#define BITS_PER_COS_INT (SIZEOF_COS_INT * BITS_PER_CHAR) + + +enum COS_Type { + COS_Type_Entity, + COS_Type_Int_Even, + COS_Type_Char, + COS_Type_Int_Odd +}; + +#define COS_POINTER_TYPE_P(type) ((type) == COS_Type_Entity) + +#define COS_TYPE_BITS 2 +#define COS_INT_TYPE_BITS 1 + +#define COS_INT_VAL_BITS (BITS_PER_COS_INT - COS_INT_TYPE_BITS) +#define COS_VAL_BITS (BITS_PER_COS_INT - COS_TYPE_BITS) +#define COS_INT_MAX ((COS_INT) ((1UL << (COS_INT_VAL_BITS - 1)) -1UL)) +#define COS_INT_MIN (-(COS_INT_MAX) - 1) + + +typedef struct COS_Object_Header +{ + unsigned char prefix; + unsigned char type; + COS_INT reference_count; +} COS_Object_Header; + +#define COS_OBJECT_PREFIX_OBJECT 0 + +enum COS_Object_Type { + COS_Object_Type_NULL, + COS_Object_Type_C_String, + COS_Object_Type_int, + COS_Object_Type_char, + COS_Object_Type_String, + COS_Object_Type_Symbol, + COS_Object_Type_Container, + COS_Object_Type_Sexp, + COS_Object_Type_Binary, + COS_Object_Type_DS, + COS_Object_Type_Genre, + COS_Object_Type_Feature, + COS_Object_Type_Feature_INDEX, + COS_Object_Type_DB_Object +}; + +#define COS_FAT_OBJECT_TYPE_MIN COS_Object_Type_String +#define COS_OBJECT_TYPE_MAX COS_Object_Type_DB_Object + +extern int (*COS_Object_release_function_table[]) (COS_Object); + +struct COS_Object_ent +{ + COS_Object_Header header; +}; + +COS_Object cos_allocate_object_0 (enum COS_Object_Type type, + size_t size); + +#define COS_ALLOCATE_OBJECT(type) \ + ((COS_##type)cos_allocate_object_0(COS_Object_Type_##type, \ + sizeof(COS_##type##_ent))) + +#define COS_OBJECT_INT_P(obj) \ + ((COS_UINT)(obj) & 1) + +#define COS_OBJECT_CHAR_P(obj) \ + ((COS_UINT)(obj) & 2) + +#define COS_OBJECT_C_STRING_P(obj) \ + ((obj != NULL) \ + && (((unsigned char *)obj)[0] != COS_OBJECT_PREFIX_OBJECT)) + +#define COS_OBJECT_P(obj) \ + ((obj != NULL) \ + && (!COS_OBJECT_INT_P (obj)) \ + && (!COS_OBJECT_CHAR_P (obj)) \ + && (((unsigned char *)obj)[0] == COS_OBJECT_PREFIX_OBJECT)) + +#define COS_OBJECT_TYPE_P(obj, TYPE) \ + (COS_OBJECT_P (obj) \ + && (((COS_Object)obj)->header.type == COS_Object_Type_##TYPE)) + +#define COS_OBJECT_STRING_P(obj) \ + COS_OBJECT_TYPE_P (obj, String) + +#define COS_OBJECT_SYMBOL_P(obj) \ + COS_OBJECT_TYPE_P (obj, Symbol) + +#define COS_OBJECT_DS_P(obj) \ + COS_OBJECT_TYPE_P (obj, DS) + +#define COS_OBJECT_GENRE_P(obj) \ + COS_OBJECT_TYPE_P (obj, Genre) + +#define COS_OBJECT_FEATURE_P(obj) \ + COS_OBJECT_TYPE_P (obj, Feature) + +#define COS_OBJECT_FEATURE_INDEX_P(obj) \ + COS_OBJECT_TYPE_P (obj, Feature_INDEX) + + +struct COS_String_ent +{ + COS_Object_Header header; + + size_t size; + unsigned char* data; +}; + +int cos_release_string (COS_Object obj); + + +struct COS_Symbol_ent +{ + COS_Object_Header header; + + COS_String name; + COS_object value; +}; + +COS_Symbol cos_make_symbol (COS_String string); + +int cos_release_symbol (COS_Object obj); + + +typedef struct COS_Symbol_Table_ent COS_Symbol_Table_ent; +typedef COS_Symbol_Table_ent* COS_Symbol_Table; + +struct COS_Symbol_Table_ent +{ + size_t size; + COS_Symbol* data; +}; + +COS_Symbol_Table cos_make_symbol_table (void); + +int cos_symbol_table_grow (COS_Symbol_Table table); + +void cos_destroy_symbol_table (COS_Symbol_Table table); + +int cos_symbol_table_set (COS_Symbol_Table table, COS_Symbol symbol); + +COS_Symbol +cos_symbol_table_intern (COS_Symbol_Table table, COS_object name); + + +struct COS_Container_ent +{ + COS_Object_Header header; + + COS_Object type; + size_t size; + size_t len; + size_t offset; + COS_Object* data; +}; + +int cos_release_container (COS_Object obj); + + +struct COS_Sexp_ent +{ + COS_Object_Header header; + + size_t len; + char* data; +}; + +int cos_release_sexp (COS_Object obj); + + +struct COS_Binary_ent +{ + COS_Object_Header header; + + size_t len; + unsigned char* data; +}; + +int cos_release_binary (COS_Object obj); + + +int cos_release_ds (COS_Object obj); + + +int cos_release_genre (COS_Object obj); + +int concord_close_genre (COS_Genre genre); + + +int cos_release_feature (COS_Object obj); + +int concord_close_feature (COS_Feature feature); + + +int cos_release_index (COS_Object obj); + +int concord_close_index (COS_Feature_INDEX table); + + +struct COS_DB_Object_ent +{ + COS_Object_Header header; + + COS_Feature feature; + COS_Object id; +}; + +int cos_release_db_object (COS_Object obj); + +#if 0 +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif /* !_COS_I_H */ diff --git a/cos.c b/cos.c new file mode 100644 index 0000000..97f6099 --- /dev/null +++ b/cos.c @@ -0,0 +1,398 @@ +/* Copyright (C) 2013 MORIOKA Tomohiko + This file is part of the CONCORD Library. + + The CONCORD Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The CONCORD Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the CONCORD Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "sysdep.h" +#include "cos-i.h" +#include "cos-read.h" + +const char concord_db_format_version[] = CONCORD_DB_FORMAT_VERSION; +const char concord_db_dir[] = CONCORD_DB_DIR; +const char concord_system_db_dir[] = CONCORD_SI_DB_DIR; + +int (*COS_Object_release_function_table + [COS_OBJECT_TYPE_MAX - COS_Object_Type_char]) + (COS_Object) + = { cos_release_string, + cos_release_symbol, + cos_release_container, + cos_release_sexp, + cos_release_binary, + cos_release_ds, + cos_release_genre, + cos_release_feature, + cos_release_index, + cos_release_db_object +}; + + +COS_object +cos_make_int (COS_C_Int num) +{ + return (COS_object)((COS_INT)(num << 1) | 1); +} + +COS_C_Int +cos_int_value (COS_object obj) +{ + if (COS_OBJECT_INT_P (obj)) + return ((COS_INT)obj) >> 1; + return INTPTR_MIN; +} + +int +cos_int_p (COS_object obj) +{ + return COS_OBJECT_INT_P (obj); +} + + +COS_object +cos_make_char (int code) +{ + return (COS_object)((COS_INT)(code << 2) | 2); +} + +int +cos_char_id (COS_object obj) +{ + if (COS_OBJECT_CHAR_P (obj)) + return ((COS_INT)obj) >> 2; + return -1; +} + +int +cos_char_p (COS_object obj) +{ + return COS_OBJECT_CHAR_P (obj); +} + + +COS_Object +cos_allocate_object_0 (enum COS_Object_Type type, size_t size) +{ + COS_Object obj = (COS_Object)malloc (size); + + if (obj == NULL) + return NULL; + + obj->header.prefix = COS_OBJECT_PREFIX_OBJECT; + obj->header.type = type; + obj->header.reference_count = 0; + + return obj; +} + +COS_Object +cos_retain_object (COS_Object obj) +{ + obj->header.reference_count++; + + return obj; +} + +int +cos_release_object (COS_object obj) +{ + ((COS_Object)obj)->header.reference_count--; + + if ( ((COS_Object)obj)->header.reference_count <= 0 ) + return (*COS_Object_release_function_table + [((COS_Object)obj)->header.type + - COS_FAT_OBJECT_TYPE_MIN])(obj); + else + return 0; +} + + +COS_String +cos_make_string (char* str, size_t size) +{ + COS_String obj = COS_ALLOCATE_OBJECT (String); + + if (obj == NULL) + return NULL; + + obj->size = size; + obj->data = malloc (size + 1); + if (obj->data == NULL) + { + free (obj); + return NULL; + } + + strncpy ((char*)obj->data, str, size); + obj->data[size] = '\0'; + return obj; +} + +COS_String +cos_build_string (char* str) +{ +#if 0 + COS_String obj = COS_ALLOCATE_OBJECT (string); + + if (obj == NULL) + return NULL; + + obj->size = strlen (str); + obj->data = malloc (obj->size + 1); + if (obj->data == NULL) + { + free (obj); + return NULL; + } + + strncpy ((char*)obj->data, str, obj->size); + obj->data[obj->size] = '\0'; + return obj; +#else + return cos_make_string (str, strlen (str)); +#endif +} + +int +cos_release_string (COS_Object obj) +{ + if (obj == NULL) + return 0; + + if ( ((COS_String)obj)->data != NULL) + free (((COS_String)obj)->data); + free (obj); + return 0; +} + +size_t +cos_string_size (COS_String string) +{ + return string->size; +} + +char* +cos_string_data (COS_String string) +{ + return (char*)string->data; +} + + +int +cos_release_container (COS_Object obj) +{ + return 0; +} + + +int +cos_release_sexp (COS_Object obj) +{ + return 0; +} + + +int +cos_release_binary (COS_Object obj) +{ + return 0; +} + + +COS_DS +concord_open_env (COS_object ds) +{ + if (COS_OBJECT_DS_P (ds)) + return (COS_DS)ds; + else + { + char* path; + + if (COS_OBJECT_C_STRING_P (ds)) + path = (char*)ds; + else if (ds == NULL) + path = CONCORD_SI_DB_DIR; + else + return NULL; + + return concord_open_ds (CONCORD_Backend_Berkeley_DB, + path, 0, 0755); + } +} + +int +cos_release_ds (COS_Object obj) +{ + return concord_close_ds ((COS_DS)obj); +} + + +COS_Genre +concord_get_genre (COS_object ds, COS_object genre) +{ + if (COS_OBJECT_C_STRING_P (genre)) + return concord_ds_get_genre (ds, (char*)genre); + else if (COS_OBJECT_SYMBOL_P (genre)) + return concord_ds_get_genre (ds, (char*)((COS_Symbol)genre)->name->data); + else if (COS_OBJECT_GENRE_P (genre)) + return (COS_Genre)genre; + return NULL; +} + +int +cos_release_genre (COS_Object obj) +{ + return concord_close_genre ((COS_Genre)obj); +} + + +COS_Feature +concord_get_feature (COS_object ds, + COS_object genre, COS_object feature) +{ + if (COS_OBJECT_FEATURE_P (feature)) + return feature; + else + { + COS_Genre gobj = concord_get_genre (ds, genre); + char* feature_name; + + if (COS_OBJECT_C_STRING_P (feature)) + feature_name = (char*)feature; + else if (COS_OBJECT_STRING_P (feature)) + feature_name = (char*)((COS_String)feature)->data; + else if (COS_OBJECT_SYMBOL_P (feature)) + feature_name = (char*)((COS_Symbol)feature)->name->data; + else + return NULL; + + return concord_genre_get_feature (gobj, feature_name); + } +} + +int +cos_release_feature (COS_Object obj) +{ + return concord_close_feature ((COS_Feature)obj); +} + + +COS_Feature_INDEX +concord_get_feature_index (COS_object ds, + COS_object genre, COS_object feature) +{ + if (COS_OBJECT_FEATURE_INDEX_P (feature)) + return feature; + else + { + COS_Feature fobj = concord_get_feature (ds, genre, feature); + COS_Genre gobj; + char* feature_name; + + if (fobj == NULL) + return NULL; + + gobj = concord_feature_get_genre (fobj); + feature_name = concord_feature_get_name (fobj); + return concord_genre_get_index (gobj, feature_name); + } +} + +int +cos_release_index (COS_Object obj) +{ + return concord_close_index ((COS_Feature_INDEX)obj); +} + + +int +cos_release_db_object (COS_Object obj) +{ + return 0; +} + +COS_object +concord_decode_object (COS_object ds, COS_object genre, + COS_object feature, COS_object id) +{ + COS_Feature_INDEX index = concord_get_feature_index (ds, genre, feature); + char* id_str; + char buf[256]; + CONCORD_String_Tank obj_st; + COS_String obj_string; + int cid; + size_t end; + + if (index == NULL) + return NULL; + + printf ("decoding id (%lX)...", id); + if (COS_OBJECT_INT_P (id)) + { + printf ("(id is an int)..."); + snprintf(buf, 256, "%ld", cos_int_value (id)); + id_str = buf; + } + else if (COS_OBJECT_CHAR_P (id)) + { + printf ("(id is a char)..."); + snprintf(buf, 256, "%ld", cos_char_id (id)); + id_str = buf; + } + else if (COS_OBJECT_SYMBOL_P (id)) + { + printf ("(id is a symbol)...."); + id_str = cos_string_data (cos_symbol_name ((COS_Symbol)id)); + } + else if (COS_OBJECT_C_STRING_P (id)) + { + printf ("(id is a C-string)...."); + id_str = (char*)id; + } + else if (COS_OBJECT_STRING_P (id)) + { + printf ("(id is a string)...."); + id_str = cos_string_data ((COS_String)id); + } + else + return NULL; + printf ("done (%s).\n", id_str); + + if ( concord_index_strid_get_obj_string (index, id_str, &obj_st) ) + return NULL; + + obj_string = cos_make_string ((char*)CONCORD_String_data (&obj_st), + CONCORD_String_size (&obj_st)); + + cid = cos_read_char (CONCORD_String_data (&obj_st), + CONCORD_String_size (&obj_st), + 0, &end); + if ( cid >= 0 ) + { + printf ("obj = %s (%d, U+%04X), len = %d, end = %d\n", + cos_string_data (obj_string), + cid, cid, + CONCORD_String_size (&obj_st), end); + cos_release_object (obj_string); + return cos_make_char (cid); + } + else + printf ("obj = %s\n", cos_string_data (obj_string)); + + cos_release_object (obj_string); + + return NULL; +} diff --git a/cos.h b/cos.h new file mode 100644 index 0000000..dfd9679 --- /dev/null +++ b/cos.h @@ -0,0 +1,88 @@ +/* Types and functions of CONCORD Object System + + Copyright (C) 2013 MORIOKA Tomohiko + This file is part of the CONCORD Library. + + The CONCORD Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The CONCORD Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the CONCORD Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _COS_H +#define _COS_H + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +typedef void* COS_object; + +typedef struct COS_Object_ent COS_Object_ent; +typedef COS_Object_ent* COS_Object; + +COS_Object cos_retain_object (COS_Object obj); +int cos_release_object (COS_object obj); + + +typedef intptr_t COS_C_Int; + +COS_object cos_make_int (COS_C_Int num); +COS_C_Int cos_int_value (COS_object obj); +int cos_int_p (COS_object obj); + + +COS_object cos_make_char (int code); +int cos_char_id (COS_object obj); +int cos_char_p (COS_object obj); + + +typedef struct COS_String_ent COS_String_ent; +typedef struct COS_String_ent* COS_String; + +COS_String cos_make_string (char* str, size_t size); +COS_String cos_build_string (char* str); + +size_t cos_string_size (COS_String string); +char* cos_string_data (COS_String string); + + +typedef struct COS_Symbol_ent COS_Symbol_ent; +typedef struct COS_Symbol_ent* COS_Symbol; + +COS_Symbol cos_intern (COS_object name); + +COS_String cos_symbol_name (COS_Symbol symbol); + + +typedef struct COS_Container_ent COS_Container_ent; +typedef struct COS_Container_ent* COS_Container; + + +typedef struct COS_Sexp_ent COS_Sexp_ent; +typedef struct COS_Sexp_ent* COS_Sexp; + + +typedef struct COS_Binary_ent COS_Binary_ent; +typedef struct COS_Binary_ent* COS_Binary; + +#if 0 +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif /* !_COS_H */ diff --git a/read.c b/read.c new file mode 100644 index 0000000..79459ab --- /dev/null +++ b/read.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2013 MORIOKA Tomohiko + This file is part of the CONCORD Library. + + The CONCORD Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The CONCORD Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the CONCORD Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "cos-read.h" + +int +cos_read_utf8 (unsigned char *str, size_t len, size_t start, size_t* endp) +{ + size_t i = start; + + if ( len >= i + 1 ) + { + unsigned char c = str[i++]; + int counter; + int cid; + + if ( c < 0xC0 ) + { + cid = c; + counter = 0; + } + else if ( c < 0xE0 ) + { + cid = c & 0x1f; + counter = 1; + } + else if ( c < 0xF0 ) + { + cid = c & 0x0f; + counter = 2; + } + else if ( c < 0xF8 ) + { + cid = c & 0x07; + counter = 3; + } + else if ( c < 0xFC ) + { + cid = c & 0x03; + counter = 4; + } + else + { + cid = c & 0x01; + counter = 5; + } + + if (counter + i <= len) + { + int j; + + for (j = 0; j < counter; j++) + cid = (cid << 6) | (str[i++] & 0x3F); + *endp = i; + return cid; + } + } + return -1; +} + +int +cos_read_char (unsigned char *str, size_t len, size_t start, size_t* endp) +{ + size_t i = start; + + if ( (len >= start + 2) && (str[i++] == '?') ) + { + if ( (len >= start + 3) && (str[i] == '\\') ) + { + i++; + return cos_read_utf8 (str, len, i, endp); + } + else + return cos_read_utf8 (str, len, i, endp); + } + + return -1; +} diff --git a/symbol.c b/symbol.c new file mode 100644 index 0000000..bf544f7 --- /dev/null +++ b/symbol.c @@ -0,0 +1,264 @@ +/* Copyright (C) 2003,2004,2005,2006,2013 MORIOKA Tomohiko + This file is part of the CONCORD Library. + + The CONCORD Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The CONCORD Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the CONCORD Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "cos-i.h" + +unsigned long concord_hash_c_string (const unsigned char *ptr); +unsigned long cos_hash_c_string_n (const unsigned char *ptr, size_t size); +unsigned long cos_symbol_hash_string (COS_String string); + + +COS_Symbol +cos_make_symbol (COS_String string) +{ + COS_Symbol obj = COS_ALLOCATE_OBJECT (Symbol); + + if (obj == NULL) + return NULL; + + obj->name = string; + obj->value = NULL; + return obj; +} + +int +cos_release_symbol (COS_Object obj) +{ + if (obj == NULL) + return 0; + + if ( ((COS_Symbol)obj)->value != NULL) + cos_release_object (((COS_Symbol)obj)->value); + + cos_release_object (((COS_Symbol)obj)->name); + free (obj); + return 0; +} + +COS_Symbol +cos_symbol_table_intern (COS_Symbol_Table table, COS_object name) +{ + unsigned char* key; + COS_String key_string; + unsigned long i, index; + COS_Symbol entry; + + if (table == NULL) + return NULL; + + if (COS_OBJECT_C_STRING_P (name)) + { + key_string = cos_build_string ((char*)name); + } + else + { + key_string = (COS_String)name; + } + key = key_string->data; + index = cos_symbol_hash_string (key_string) % table->size; + for (i = index; i < table->size; i++) + { + entry = table->data[i]; + if (entry == NULL) + { + entry = cos_make_symbol (key_string); + cos_retain_object ((COS_object)entry); + table->data[i] = entry; + return entry; + } + else if ( (entry->name->size == key_string->size) + && (memcmp (entry->name->data, + key_string->data, key_string->size) == 0) ) + { + return entry; + } + } + if (cos_symbol_table_grow (table) == 0) + return cos_symbol_table_intern (table, key_string); + return NULL; +} + +COS_String +cos_symbol_name (COS_Symbol symbol) +{ + return symbol->name; +} + + +COS_Symbol_Table cos_default_symbol_table = NULL; + +COS_Symbol_Table cos_make_symbol_table_0 (size_t size); +void cos_destroy_symbol_table_0 (COS_Symbol_Table hash); + + +/* derived from hashpjw, Dragon Book P436. */ +unsigned long +cos_hash_c_string_n (const unsigned char *ptr, size_t size) +{ + unsigned long hash = 0; + int i; + + for ( i = 0; i < size; i++ ) + { + unsigned long g; + hash = (hash << 4) + ptr[i]; + g = hash & 0xf0000000; + if (g) + hash = (hash ^ (g >> 24)) ^ g; + } + return hash & 07777777777; +} + +unsigned long +cos_symbol_hash_string (COS_String string) +{ + return cos_hash_c_string_n (string->data, string->size); +} + + +COS_Symbol_Table +cos_make_symbol_table_0 (size_t size) +{ + COS_Symbol_Table hash + = (COS_Symbol_Table)malloc (sizeof (COS_Symbol_Table_ent)); + + if (hash == NULL) + return NULL; + + hash->data + = (COS_Symbol*) malloc (sizeof (COS_Symbol) * size); + if (hash->data == NULL) + { + free (hash); + return NULL; + } + + hash->size = size; + memset (hash->data, 0, sizeof (COS_Symbol) * size); + return hash; +} + +void +cos_destroy_symbol_table_0 (COS_Symbol_Table table) +{ + if (table == NULL) + return; + free (table->data); + free (table); +} + + +COS_Symbol_Table +cos_make_symbol_table () +{ + return cos_make_symbol_table_0 (2 /* 256 */); +} + +void +cos_destroy_symbol_table (COS_Symbol_Table table) +{ + int i; + + for (i = 0; i < table->size; i++) + { + COS_Symbol entry = table->data[i]; + + if (entry != NULL) + { + if (entry->name != NULL) + cos_release_object (entry->name); + if (entry->value != NULL) + cos_release_object (entry->value); + free (entry); + } + } + cos_destroy_symbol_table_0 (table); +} + +COS_Symbol +cos_intern (COS_object name) +{ + if (cos_default_symbol_table == NULL) + cos_default_symbol_table = cos_make_symbol_table(); + + return cos_symbol_table_intern (cos_default_symbol_table, name); +} + +int +cos_symbol_table_set (COS_Symbol_Table table, COS_Symbol symbol) +{ + int i, index; + COS_Symbol entry; + + if (table == NULL) + return -1; + + index = cos_symbol_hash_string (symbol->name) % table->size; + for (i = index; i < table->size; i++) + { + entry = table->data[i]; + if (entry == NULL) + { + entry = symbol; + cos_retain_object ((COS_object)entry); + table->data[i] = entry; + return 0; + } + else if (entry == symbol) + { + return 0; + } + } + if (cos_symbol_table_grow (table) == 0) + return cos_symbol_table_set (table, symbol); + return -1; +} + +int +cos_symbol_table_grow (COS_Symbol_Table table) +{ + COS_Symbol_Table new_table + = cos_make_symbol_table_0 ( table->size * 2 + /* - (table->size * 4 / 5) */ ); + int i; + + if (new_table == NULL) + return -1; + + for (i = 0; i < table->size; i++) + { + COS_Symbol entry = table->data[i]; + + if (entry != NULL) + { + int status = cos_symbol_table_set (new_table, entry); + + if (status != 0) + { + cos_destroy_symbol_table_0 (new_table); + return -1; + } + } + } + table->size = new_table->size; + table->data = new_table->data; + free (new_table); + return 0; +} -- 1.7.10.4