1 /* -*- mode: c ; c-file-style: "canonware-c-style" -*-
2  ******************************************************************************
3  *
4  * Copyright (C) 1996-2005 Jason Evans <jasone@canonware.com>.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice(s), this list of conditions and the following disclaimer
12  *    unmodified other than the allowable addition of one or more
13  *    copyright notices.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice(s), this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  ******************************************************************************
32  *
33  * Version: Onyx 5.1.2
34  *
35  ******************************************************************************/
36 
37 #define CW_NXO_NAME_C_
38 
39 #include "../include/libonyx/libonyx.h"
40 #include "../include/libonyx/nx_l.h"
41 #include "../include/libonyx/nxa_l.h"
42 #include "../include/libonyx/nxo_l.h"
43 #include "../include/libonyx/nxo_name_l.h"
44 
45 /* Global variables. */
46 #ifdef CW_THREADS
47 cw_mtx_t cw_g_name_lock;
48 #endif
49 /* Hash of names (key: {name, len}, value: (nxoe_name *)).  This hash table
50  * keeps track of *all* name "values" in the virtual machine.  When a name
51  * object is created, it actually adds a reference to a nxoe_name in this hash
52  * and uses a pointer to that nxoe_name as a unique key. */
53 cw_dch_t cw_g_name_hash;
54 /* List of names, corresponding to the entries in cw_g_name_hash. */
55 cw_name_list_t cw_g_name_list;
56 
57 void
nxo_name_l_init(void)58 nxo_name_l_init(void)
59 {
60     /* Initialize the global name cache. */
61     dch_new(&cw_g_name_hash, cw_g_nxaa,
62 	    CW_LIBONYX_NAME_HASH, CW_LIBONYX_NAME_HASH / 4 * 3,
63 	    CW_LIBONYX_NAME_HASH / 4, nxo_l_name_hash,
64 	    nxo_l_name_key_comp);
65 #ifdef CW_THREADS
66     mtx_new(&cw_g_name_lock);
67 #endif
68     ql_new(&cw_g_name_list);
69 }
70 
71 void
nxo_name_l_shutdown(void)72 nxo_name_l_shutdown(void)
73 {
74     cw_assert(dch_count(&cw_g_name_hash) == 0);
75     dch_delete(&cw_g_name_hash);
76 #ifdef CW_THREADS
77     mtx_delete(&cw_g_name_lock);
78 #endif
79 }
80 
81 void
nxo_name_new(cw_nxo_t * a_nxo,const char * a_str,uint32_t a_len,bool a_is_static)82 nxo_name_new(cw_nxo_t *a_nxo, const char *a_str, uint32_t a_len,
83 	     bool a_is_static)
84 {
85     cw_nxoe_name_t *name, key;
86 
87     /* Fake up a key so that we can search the hash tables. */
88     key.str = a_str;
89     key.len = a_len;
90 
91     /* Look in the global hash for the name.  If the name doesn't exist, create
92      * it. */
93 #ifdef CW_THREADS
94     mtx_lock(&cw_g_name_lock);
95 #endif
96     if (dch_search(&cw_g_name_hash, (void *) &key, (void **) &name))
97     {
98 	/* Not found in the name hash.  Create, initialize, and insert a new
99 	 * entry. */
100 	name = (cw_nxoe_name_t *) nxa_malloc(sizeof(cw_nxoe_name_t));
101 
102 	nxoe_l_new(&name->nxoe, NXOT_NAME, false);
103 	name->nxoe.name_static = a_is_static;
104 	name->len = a_len;
105 
106 	if (a_is_static == false)
107 	{
108 	    name->str = nxa_malloc(a_len);
109 	    /* Cast away the const here; it's one of two places that the string
110 	     * is allowed to be modified, and this cast is better than dropping
111 	     * the const altogether. */
112 	    memcpy((char *) name->str, a_str, a_len);
113 	}
114 	else
115 	{
116 	    name->str = a_str;
117 	}
118 	ql_elm_new(name, link);
119 
120 	dch_insert(&cw_g_name_hash, (void *) name, (void **) name,
121 		   &name->chi);
122 	ql_head_insert(&cw_g_name_list, name, link);
123 
124 	nxo_no_new(a_nxo);
125 	a_nxo->o.nxoe = (cw_nxoe_t *) name;
126 	nxo_p_type_set(a_nxo, NXOT_NAME);
127 	nxa_l_gc_register((cw_nxoe_t *) name);
128     }
129     else
130     {
131 	nxo_no_new(a_nxo);
132 	a_nxo->o.nxoe = (cw_nxoe_t *) name;
133 	nxo_p_type_set(a_nxo, NXOT_NAME);
134     }
135 
136 #ifdef CW_THREADS
137     mtx_unlock(&cw_g_name_lock);
138 #endif
139 }
140 
141 /* Hash {name string, length}. */
142 uint32_t
nxo_l_name_hash(const void * a_key)143 nxo_l_name_hash(const void *a_key)
144 {
145     uint32_t retval, i;
146     cw_nxoe_name_t *key = (cw_nxoe_name_t *) a_key;
147     const unsigned char *str;
148 
149     cw_check_ptr(a_key);
150 
151     for (i = 0, retval = 5381, str = key->str; i < key->len; i++, str++)
152     {
153 	retval = ((retval << 5) + retval) + *str;
154     }
155 
156     return retval;
157 }
158 
159 /* Compare keys {name string, length}. */
160 bool
nxo_l_name_key_comp(const void * a_k1,const void * a_k2)161 nxo_l_name_key_comp(const void *a_k1, const void *a_k2)
162 {
163     bool retval;
164     cw_nxoe_name_t *k1 = (cw_nxoe_name_t *) a_k1;
165     cw_nxoe_name_t *k2 = (cw_nxoe_name_t *) a_k2;
166 
167     cw_check_ptr(a_k1);
168     cw_check_ptr(a_k2);
169 
170     if (k1->len == k2->len)
171     {
172 	if (strncmp((char *) k1->str, (char *) k2->str, k1->len) == 0)
173 	{
174 	    retval = true;
175 	}
176 	else
177 	{
178 	    retval = false;
179 	}
180     }
181     else
182     {
183 	retval = false;
184 
185     }
186 
187     return retval;
188 }
189 
190 const char *
nxo_name_str_get(const cw_nxo_t * a_nxo)191 nxo_name_str_get(const cw_nxo_t *a_nxo)
192 {
193     const char *retval;
194     cw_nxoe_name_t *name;
195 
196     cw_check_ptr(a_nxo);
197     cw_dassert(a_nxo->magic == CW_NXO_MAGIC);
198     cw_assert(nxo_type_get(a_nxo) == NXOT_NAME);
199 
200     name = (cw_nxoe_name_t *) a_nxo->o.nxoe;
201 
202     cw_check_ptr(name);
203     cw_dassert(name->nxoe.magic == CW_NXOE_MAGIC);
204     cw_assert(name->nxoe.type == NXOT_NAME);
205 
206     retval = name->str;
207 
208     return retval;
209 }
210 
211 uint32_t
nxo_name_len_get(const cw_nxo_t * a_nxo)212 nxo_name_len_get(const cw_nxo_t *a_nxo)
213 {
214     uint32_t retval;
215     cw_nxoe_name_t *name;
216 
217     cw_check_ptr(a_nxo);
218     cw_dassert(a_nxo->magic == CW_NXO_MAGIC);
219     cw_assert(nxo_type_get(a_nxo) == NXOT_NAME);
220 
221     name = (cw_nxoe_name_t *) a_nxo->o.nxoe;
222 
223     cw_check_ptr(name);
224     cw_dassert(name->nxoe.magic == CW_NXOE_MAGIC);
225     cw_assert(name->nxoe.type == NXOT_NAME);
226 
227     retval = name->len;
228 
229     return retval;
230 }
231