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_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 
44 /* nxo. */
45 int32_t
nxo_compare(const cw_nxo_t * a_a,const cw_nxo_t * a_b)46 nxo_compare(const cw_nxo_t *a_a, const cw_nxo_t *a_b)
47 {
48     int32_t retval;
49 
50     switch (nxo_type_get(a_a))
51     {
52 	case NXOT_ARRAY:
53 #ifdef CW_OOP
54 	case NXOT_CLASS:
55 #endif
56 #ifdef CW_THREADS
57 	case NXOT_CONDITION:
58 #endif
59 	case NXOT_DICT:
60 	case NXOT_FILE:
61 #ifdef CW_HANDLE
62 	case NXOT_HANDLE:
63 #endif
64 #ifdef CW_OOP
65 	case NXOT_INSTANCE:
66 #endif
67 #ifdef CW_THREADS
68 	case NXOT_MUTEX:
69 #endif
70 #ifdef CW_REGEX
71 	case NXOT_REGEX:
72 	case NXOT_REGSUB:
73 #endif
74 	case NXOT_STACK:
75 	case NXOT_THREAD:
76 	{
77 	    if (nxo_type_get(a_a) == nxo_type_get(a_b)
78 		&& a_a->o.nxoe == a_b->o.nxoe)
79 	    {
80 		retval = 0;
81 	    }
82 	    else
83 	    {
84 		retval = 1;
85 	    }
86 	    break;
87 	}
88 	case NXOT_OPERATOR:
89 	{
90 	    if (nxo_type_get(a_b) == NXOT_OPERATOR
91 		&& a_a->o.oper.f == a_b->o.oper.f)
92 	    {
93 		retval = 0;
94 	    }
95 	    else
96 	    {
97 		retval = 1;
98 	    }
99 	    break;
100 	}
101 	case NXOT_NAME:
102 	case NXOT_STRING:
103 	{
104 	    const char *str_a, *str_b;
105 	    uint32_t len_a, len_b;
106 #ifdef CW_THREADS
107 	    bool lock_a, lock_b;
108 #endif
109 
110 	    if (nxo_type_get(a_a) == NXOT_NAME)
111 	    {
112 		str_a = nxo_name_str_get(a_a);
113 		len_a = nxo_name_len_get(a_a);
114 #ifdef CW_THREADS
115 		lock_a = false;
116 #endif
117 	    }
118 	    else
119 	    {
120 		str_a = nxo_string_get(a_a);
121 		len_a = nxo_string_len_get(a_a);
122 #ifdef CW_THREADS
123 		lock_a = true;
124 #endif
125 	    }
126 
127 	    if (nxo_type_get(a_b) == NXOT_NAME)
128 	    {
129 		str_b = nxo_name_str_get(a_b);
130 		len_b = nxo_name_len_get(a_b);
131 #ifdef CW_THREADS
132 		lock_b = false;
133 #endif
134 	    }
135 	    else if (nxo_type_get(a_b) == NXOT_STRING)
136 	    {
137 		str_b = nxo_string_get(a_b);
138 		len_b = nxo_string_len_get(a_b);
139 #ifdef CW_THREADS
140 		lock_b = true;
141 #endif
142 	    }
143 	    else
144 	    {
145 		retval = 2;
146 		break;
147 	    }
148 
149 #ifdef CW_THREADS
150 	    if (lock_a)
151 	    {
152 		nxo_string_lock((cw_nxo_t *) a_a);
153 	    }
154 	    if (lock_b)
155 	    {
156 		nxo_string_lock((cw_nxo_t *) a_b);
157 	    }
158 #endif
159 	    if (len_a == len_b)
160 	    {
161 		retval = strncmp(str_a, str_b, len_a);
162 	    }
163 	    else if (len_a < len_b)
164 	    {
165 		retval = strncmp(str_a, str_b, len_a);
166 		if (retval == 0)
167 		{
168 		    retval = -1;
169 		}
170 	    }
171 	    else
172 	    {
173 		retval = strncmp(str_a, str_b, len_b);
174 		if (retval == 0)
175 		{
176 		    retval = 1;
177 		}
178 	    }
179 #ifdef CW_THREADS
180 	    if (lock_b)
181 	    {
182 		nxo_string_unlock((cw_nxo_t *) a_b);
183 	    }
184 	    if (lock_a)
185 	    {
186 		nxo_string_unlock((cw_nxo_t *) a_a);
187 	    }
188 #endif
189 	    break;
190 	}
191 	case NXOT_BOOLEAN:
192 	{
193 	    if (nxo_type_get(a_b) != NXOT_BOOLEAN)
194 	    {
195 		retval = 2;
196 		break;
197 	    }
198 
199 	    if (a_a->o.boolean.val == a_b->o.boolean.val)
200 	    {
201 		retval = 0;
202 	    }
203 	    else
204 	    {
205 		retval = 1;
206 	    }
207 	    break;
208 	}
209 	case NXOT_INTEGER:
210 	{
211 	    switch (nxo_type_get(a_b))
212 	    {
213 		case NXOT_INTEGER:
214 		{
215 		    if (a_a->o.integer.i < a_b->o.integer.i)
216 		    {
217 			retval = -1;
218 		    }
219 		    else if (a_a->o.integer.i == a_b->o.integer.i)
220 		    {
221 			retval = 0;
222 		    }
223 		    else
224 		    {
225 			retval = 1;
226 		    }
227 		    break;
228 		}
229 #ifdef CW_REAL
230 		case NXOT_REAL:
231 		{
232 		    if (((cw_nxor_t) a_a->o.integer.i) < a_b->o.real.r)
233 		    {
234 			retval = -1;
235 		    }
236 		    else if (((cw_nxor_t) a_a->o.integer.i) == a_b->o.real.r)
237 		    {
238 			retval = 0;
239 		    }
240 		    else
241 		    {
242 			retval = 1;
243 		    }
244 		    break;
245 		}
246 #endif
247 		default:
248 		{
249 		    retval = 2;
250 		    break;
251 		}
252 	    }
253 	    break;
254 	}
255 #ifdef CW_REAL
256 	case NXOT_REAL:
257 	{
258 	    switch (nxo_type_get(a_b))
259 	    {
260 		case NXOT_INTEGER:
261 		{
262 		    if (a_a->o.real.r < ((cw_nxor_t) a_b->o.integer.i))
263 		    {
264 			retval = -1;
265 		    }
266 		    else if (a_a->o.real.r == ((cw_nxor_t) a_b->o.integer.i))
267 		    {
268 			retval = 0;
269 		    }
270 		    else
271 		    {
272 			retval = 1;
273 		    }
274 		    break;
275 		}
276 		case NXOT_REAL:
277 		{
278 		    if (a_a->o.real.r < a_b->o.real.r)
279 		    {
280 			retval = -1;
281 		    }
282 		    else if (a_a->o.real.r == a_b->o.real.r)
283 		    {
284 			retval = 0;
285 		    }
286 		    else
287 		    {
288 			retval = 1;
289 		    }
290 		    break;
291 		}
292 		default:
293 		{
294 		    retval = 2;
295 		    break;
296 		}
297 	    }
298 	    break;
299 	}
300 #endif
301 	case NXOT_FINO:
302 	case NXOT_MARK:
303 	case NXOT_NULL:
304 	case NXOT_PMARK:
305 	{
306 	    if (nxo_type_get(a_a) == nxo_type_get(a_b))
307 	    {
308 		retval = 0;
309 	    }
310 	    else
311 	    {
312 		retval = 2;
313 	    }
314 	    break;
315 	}
316 	default:
317 	{
318 	    cw_not_reached();
319 	}
320     }
321 
322     return retval;
323 }
324 
325 cw_nxoe_t *
nxo_nxoe_get(const cw_nxo_t * a_nxo)326 nxo_nxoe_get(const cw_nxo_t *a_nxo)
327 {
328     cw_nxoe_t *retval;
329 
330     cw_check_ptr(a_nxo);
331     cw_assert(a_nxo->magic == CW_NXO_MAGIC || nxo_type_get(a_nxo) == NXOT_NO);
332 
333     switch (nxo_type_get(a_nxo))
334     {
335 	case NXOT_ARRAY:
336 #ifdef CW_OOP
337 	case NXOT_CLASS:
338 #endif
339 #ifdef CW_THREADS
340 	case NXOT_CONDITION:
341 #endif
342 	case NXOT_DICT:
343 	case NXOT_FILE:
344 #ifdef CW_HANDLE
345 	case NXOT_HANDLE:
346 #endif
347 #ifdef CW_OOP
348 	case NXOT_INSTANCE:
349 #endif
350 #ifdef CW_THREADS
351 	case NXOT_MUTEX:
352 #endif
353 	case NXOT_NAME:
354 #ifdef CW_REGEX
355 	case NXOT_REGEX:
356 	case NXOT_REGSUB:
357 #endif
358 	case NXOT_STACK:
359 	case NXOT_STRING:
360 	case NXOT_THREAD:
361 	{
362 	    retval = a_nxo->o.nxoe;
363 	    break;
364 	}
365 	default:
366 	{
367 	    retval = NULL;
368 	}
369     }
370 
371     return retval;
372 }
373 
374 #ifdef CW_THREADS
375 bool
nxo_ilocked(cw_nxo_t * a_nxo)376 nxo_ilocked(cw_nxo_t *a_nxo)
377 {
378     bool retval;
379 
380     cw_check_ptr(a_nxo);
381     cw_dassert(a_nxo->magic == CW_NXO_MAGIC);
382 
383 #ifdef CW_DBG
384     switch (nxo_type_get(a_nxo))
385     {
386 	case NXOT_ARRAY:
387 	case NXOT_DICT:
388 	case NXOT_FILE:
389 	case NXOT_STACK:
390 	case NXOT_STRING:
391 	{
392 	    retval = a_nxo->o.nxoe->locking;
393 	    break;
394 	}
395 	default:
396 	{
397 	    cw_not_reached();
398 	}
399     }
400 #else
401     retval = a_nxo->o.nxoe->locking;
402 #endif
403 
404     return retval;
405 }
406 #endif
407 
408 /* nxoe. */
409 /* Can be called at any time during nxoe_* initialization. */
410 void
nxoe_l_new(cw_nxoe_t * a_nxoe,cw_nxot_t a_type,bool a_locking)411 nxoe_l_new(cw_nxoe_t *a_nxoe, cw_nxot_t a_type, bool a_locking)
412 {
413     /* Initialize the common section. */
414     memset(a_nxoe, 0, sizeof(cw_nxoe_t));
415 
416     qr_new(a_nxoe, link);
417     a_nxoe->type = a_type;
418 #ifdef CW_THREADS
419     a_nxoe->locking = a_locking;
420 #endif
421 #ifdef CW_DBG
422     a_nxoe->magic = CW_NXOE_MAGIC;
423 #endif
424 }
425