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