2015-05-07 15:58:04 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stix-prv.h"
|
|
|
|
|
2015-05-28 16:51:37 +00:00
|
|
|
static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
2015-05-28 16:51:37 +00:00
|
|
|
stix_oop_oop_t newbuc;
|
2015-05-07 15:58:04 +00:00
|
|
|
stix_oow_t oldsz, newsz, index;
|
|
|
|
stix_oop_char_t symbol;
|
|
|
|
|
|
|
|
/* TODO: derive a better growth size */
|
2015-05-28 16:51:37 +00:00
|
|
|
stix_pushtmp (stix, (stix_oop_t*)&oldbuc);
|
|
|
|
newbuc = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, STIX_OBJ_GET_SIZE(oldbuc) * 2);
|
|
|
|
stix_poptmp (stix);
|
|
|
|
if (!newbuc) return STIX_NULL;
|
2015-05-07 15:58:04 +00:00
|
|
|
|
2015-05-28 16:51:37 +00:00
|
|
|
oldsz = STIX_OBJ_GET_SIZE(oldbuc);
|
|
|
|
newsz = STIX_OBJ_GET_SIZE(newbuc);
|
2015-05-07 15:58:04 +00:00
|
|
|
|
|
|
|
while (oldsz > 0)
|
|
|
|
{
|
2015-05-28 16:51:37 +00:00
|
|
|
symbol = (stix_oop_char_t)oldbuc->slot[--oldsz];
|
2015-05-07 15:58:04 +00:00
|
|
|
if ((stix_oop_t)symbol != stix->_nil)
|
|
|
|
{
|
|
|
|
STIX_ASSERT (STIX_CLASSOF(stix,symbol) == stix->_symbol);
|
|
|
|
/*STIX_ASSERT (sym->size > 0);*/
|
|
|
|
|
2015-10-14 09:06:44 +00:00
|
|
|
index = stix_hashuchars(symbol->slot, STIX_OBJ_GET_SIZE(symbol)) % newsz;
|
2015-05-28 16:51:37 +00:00
|
|
|
while (newbuc->slot[index] != stix->_nil) index = (index + 1) % newsz;
|
|
|
|
newbuc->slot[index] = (stix_oop_t)symbol;
|
2015-05-07 15:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-28 16:51:37 +00:00
|
|
|
return newbuc;
|
2015-05-07 15:58:04 +00:00
|
|
|
}
|
|
|
|
|
2015-05-17 05:02:30 +00:00
|
|
|
static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_uch_t* ptr, stix_oow_t len, int create)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
stix_oow_t index, tally;
|
|
|
|
stix_oop_char_t symbol;
|
|
|
|
|
|
|
|
STIX_ASSERT (len > 0);
|
|
|
|
if (len <= 0)
|
|
|
|
{
|
|
|
|
/* i don't allow an empty symbol name */
|
|
|
|
stix->errnum = STIX_EINVAL;
|
|
|
|
return STIX_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
STIX_ASSERT (STIX_CLASSOF(stix,stix->symtab->bucket) == stix->_array);
|
2015-10-14 09:06:44 +00:00
|
|
|
index = stix_hashuchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
2015-05-07 15:58:04 +00:00
|
|
|
|
|
|
|
/* find a matching symbol in the open-addressed symbol table */
|
|
|
|
while (stix->symtab->bucket->slot[index] != stix->_nil)
|
|
|
|
{
|
|
|
|
symbol = (stix_oop_char_t)stix->symtab->bucket->slot[index];
|
|
|
|
STIX_ASSERT (STIX_CLASSOF(stix,symbol) == (stix_oop_t)stix->_symbol);
|
|
|
|
|
2015-05-08 14:29:35 +00:00
|
|
|
if (len == STIX_OBJ_GET_SIZE(symbol) &&
|
|
|
|
stix_equalchars (ptr, symbol->slot, len))
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return (stix_oop_t)symbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!create)
|
|
|
|
{
|
|
|
|
stix->errnum = STIX_ENOENT;
|
|
|
|
return STIX_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tally = STIX_OOP_TO_SMINT(stix->symtab->tally);
|
|
|
|
if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket))
|
|
|
|
{
|
|
|
|
stix_oop_oop_t bucket;
|
|
|
|
|
|
|
|
/* TODO: make the growth policy configurable instead of growing
|
2015-05-11 16:08:09 +00:00
|
|
|
it just before it gets full. The polcy can be grow it
|
2015-05-07 15:58:04 +00:00
|
|
|
if it's 70% full */
|
|
|
|
|
|
|
|
/* Enlarge the symbol table before it gets full to
|
|
|
|
* make sure that it has at least one free slot left
|
|
|
|
* after having added a new symbol. this is to help
|
|
|
|
* traversal end at a _nil slot if no entry is found. */
|
2015-05-26 16:31:47 +00:00
|
|
|
bucket = expand_bucket(stix, stix->symtab->bucket);
|
2015-05-07 15:58:04 +00:00
|
|
|
if (!bucket) return STIX_NULL;
|
|
|
|
|
|
|
|
stix->symtab->bucket = bucket;
|
|
|
|
|
|
|
|
/* recalculate the index for the expanded bucket */
|
2015-10-14 09:06:44 +00:00
|
|
|
index = stix_hashuchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
2015-05-07 15:58:04 +00:00
|
|
|
|
|
|
|
while (stix->symtab->bucket->slot[index] != stix->_nil)
|
|
|
|
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create a new symbol since it isn't found in the symbol table */
|
2015-05-26 16:31:47 +00:00
|
|
|
symbol = (stix_oop_char_t)stix_instantiate(stix, stix->_symbol, ptr, len);
|
2015-05-07 15:58:04 +00:00
|
|
|
if (symbol)
|
|
|
|
{
|
2015-06-04 18:34:37 +00:00
|
|
|
STIX_ASSERT (tally < STIX_SMINT_MAX);
|
2015-05-07 15:58:04 +00:00
|
|
|
stix->symtab->tally = STIX_OOP_FROM_SMINT(tally + 1);
|
|
|
|
stix->symtab->bucket->slot[index] = (stix_oop_t)symbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (stix_oop_t)symbol;
|
|
|
|
}
|
|
|
|
|
2015-05-17 05:02:30 +00:00
|
|
|
stix_oop_t stix_makesymbol (stix_t* stix, const stix_uch_t* ptr, stix_oow_t len)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return find_or_make_symbol (stix, ptr, len, 1);
|
|
|
|
}
|
|
|
|
|
2015-05-17 05:02:30 +00:00
|
|
|
stix_oop_t stix_findsymbol (stix_t* stix, const stix_uch_t* ptr, stix_oow_t len)
|
2015-05-07 15:58:04 +00:00
|
|
|
{
|
|
|
|
return find_or_make_symbol (stix, ptr, len, 0);
|
|
|
|
}
|
2015-05-26 16:31:47 +00:00
|
|
|
|
|
|
|
stix_oop_t stix_makestring (stix_t* stix, const stix_uch_t* ptr, stix_oow_t len)
|
|
|
|
{
|
|
|
|
return stix_instantiate (stix, stix->_string, ptr, len);
|
|
|
|
}
|