1 #include "config.h"
2 #include <orbit/orbit.h>
3 #include <string.h>
4 #include "../util/orbit-purify.h"
5 
6 typedef struct {
7 	CORBA_TypeCode tc;
8 	guint index;
9 } TCRecursionNode;
10 
11 typedef struct {
12 	GSList *prior_tcs;   /* Could be a hash table by typecode */
13 	guint   start_idx;
14 } TCEncodeContext;
15 
16 typedef struct {
17 	GSList *prior_tcs;   /* Could be a hash table by offset */
18 	guint   current_idx; /* The offset from the start of the toplevel buffer of this buffer */
19 } TCDecodeContext;
20 
21 /* Two methods called in co-recursion */
22 static gboolean tc_dec (CORBA_TypeCode  *t,
23 			GIOPRecvBuffer  *c,
24 			TCDecodeContext *ctx);
25 static void     tc_enc (CORBA_TypeCode   tc,
26 			GIOPSendBuffer  *buf,
27 			TCEncodeContext *ctx);
28 
29 #define get_wptr(buf) (buf->msg.header.message_size - ctx->start_idx)
30 #define get_rptr(buf) (buf->cur-buf->message_body)
31 
32 #define CDR_put_string(buf,str) (giop_send_buffer_append_string ((buf), (str)))
33 #define CDR_put_ulong(buf, n) (giop_send_buffer_align(buf, sizeof(n)), \
34 			       giop_send_buffer_append(buf, &(n), sizeof(n)))
35 #define CDR_put_long(buf, n) CDR_put_ulong(buf, n)
36 #define CDR_put_ulong_long(buf, n) CDR_put_ulong(buf, n)
37 #define CDR_put_wchar(buf, n) CDR_put_ulong(buf, n)
38 #define CDR_put_octet(buf, n) CDR_put_ulong(buf, n)
39 #define CDR_put_ushort(buf, n) CDR_put_ulong(buf, n)
40 #define CDR_put_short(buf, n) CDR_put_ulong(buf, n)
41 
42 typedef void (*CORBA_TypeCodeEncoder)(CORBA_TypeCode t,
43 				      GIOPSendBuffer *c,
44 				      TCEncodeContext* ctx);
45 
46 typedef gboolean (*CORBA_TypeCodeDecoder)(CORBA_TypeCode t,
47 					  GIOPRecvBuffer *c,
48 					  TCDecodeContext* ctx);
49 
50 typedef enum {
51 	TK_EMPTY,
52 	TK_SIMPLE,
53 	TK_COMPLEX
54 } TkType;
55 
56 typedef struct {
57 	TkType                type;
58 	CORBA_TypeCodeEncoder encoder;
59 	CORBA_TypeCodeDecoder decoder;
60 	CORBA_TypeCode        basic_type;
61 } TkInfo;
62 
63 #define DEF_TC_BASIC(nom, c_align)                                      \
64 	ORBIT2_MAYBE_CONST struct CORBA_TypeCode_struct TC_CORBA_##nom##_struct = { \
65 		{&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC},           \
66 		CORBA_tk_##nom,                                         \
67 		0, 0, c_align,						\
68 		0, 0, NULL, NULL,					\
69 		#nom,                                                   \
70 		"IDL:omg.org/CORBA/" #nom ":1.0",			\
71 		NULL, CORBA_OBJECT_NIL, -1				\
72 }
73 
74 #define CORBA_tk_Object CORBA_tk_objref
75 #define CORBA_tk_unsigned_long CORBA_tk_ulong
76 #define CORBA_tk_long_long CORBA_tk_longlong
77 #define CORBA_tk_unsigned_long_long CORBA_tk_ulonglong
78 #define CORBA_tk_unsigned_short CORBA_tk_ushort
79 #define CORBA_tk_long_double CORBA_tk_longdouble
80 
81 ORBIT2_MAYBE_CONST struct CORBA_TypeCode_struct TC_null_struct = {
82 	{&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC},
83 	CORBA_tk_null, 0, 0, -1, 0, 0, NULL,
84 	CORBA_OBJECT_NIL, "null", "IDL:omg.org/CORBA/Null:1.0"
85 };
86 
87 ORBIT2_MAYBE_CONST struct CORBA_TypeCode_struct TC_void_struct = {
88 	{&ORBit_TypeCode_epv, ORBIT_REFCOUNT_STATIC},
89 	CORBA_tk_void, 0, 0, -1, 0, 0, NULL,
90 	CORBA_OBJECT_NIL, "void", "IDL:omg.org/CORBA/void:1.0"
91 };
92 
93 DEF_TC_BASIC(char, ORBIT_ALIGNOF_CORBA_CHAR);
94 DEF_TC_BASIC(wchar, ORBIT_ALIGNOF_CORBA_WCHAR);
95 DEF_TC_BASIC(string, ORBIT_ALIGNOF_CORBA_POINTER);
96 DEF_TC_BASIC(long, ORBIT_ALIGNOF_CORBA_LONG);
97 DEF_TC_BASIC(unsigned_long, ORBIT_ALIGNOF_CORBA_LONG);
98 DEF_TC_BASIC(float, ORBIT_ALIGNOF_CORBA_FLOAT);
99 DEF_TC_BASIC(double, ORBIT_ALIGNOF_CORBA_DOUBLE);
100 DEF_TC_BASIC(short, ORBIT_ALIGNOF_CORBA_SHORT);
101 DEF_TC_BASIC(unsigned_short, ORBIT_ALIGNOF_CORBA_SHORT);
102 DEF_TC_BASIC(boolean, ORBIT_ALIGNOF_CORBA_BOOLEAN);
103 DEF_TC_BASIC(octet, ORBIT_ALIGNOF_CORBA_OCTET);
104 DEF_TC_BASIC(any, ORBIT_ALIGNOF_CORBA_ANY);
105 DEF_TC_BASIC(TypeCode, ORBIT_ALIGNOF_CORBA_POINTER);
106 DEF_TC_BASIC(Principal, 1); /* Hmm */
107 DEF_TC_BASIC(Object, ORBIT_ALIGNOF_CORBA_POINTER);
108 DEF_TC_BASIC(wstring, ORBIT_ALIGNOF_CORBA_POINTER);
109 DEF_TC_BASIC(long_double, ORBIT_ALIGNOF_CORBA_LONG_DOUBLE);
110 DEF_TC_BASIC(long_long, ORBIT_ALIGNOF_CORBA_LONG_LONG);
111 DEF_TC_BASIC(unsigned_long_long, ORBIT_ALIGNOF_CORBA_LONG_LONG);
112 
113 static void
tc_enc_tk_objref(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)114 tc_enc_tk_objref(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
115 {
116 	CDR_put_string (c, t->repo_id);
117 	CDR_put_string (c, t->name);
118 }
119 
120 static void
tc_enc_tk_sequence(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)121 tc_enc_tk_sequence(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
122 {
123 	tc_enc (*t->subtypes, c, ctx);
124 	CDR_put_ulong (c, t->length);
125 }
126 
127 static void
tc_enc_tk_string(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)128 tc_enc_tk_string(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
129 {
130 	CDR_put_ulong(c, t->length);
131 }
132 
133 static void
tc_enc_tk_struct(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)134 tc_enc_tk_struct(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
135 {
136 	CORBA_unsigned_long i;
137 
138 	CDR_put_string(c, t->repo_id);
139 	CDR_put_string(c, t->name);
140 	CDR_put_ulong(c, t->sub_parts);
141 
142 	for(i = 0; i < t->sub_parts; i++) {
143 		CDR_put_string (c, t->subnames [i]);
144 		tc_enc (t->subtypes [i], c, ctx);
145 	}
146 }
147 
148 static void
tc_enc_tk_union(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)149 tc_enc_tk_union (CORBA_TypeCode   t,
150 		 GIOPSendBuffer  *c,
151 		 TCEncodeContext *ctx)
152 {
153 	CORBA_unsigned_long i;
154 
155 	CDR_put_string (c, t->repo_id);
156 	CDR_put_string (c, t->name);
157 	tc_enc (t->discriminator, c, ctx);
158 	CDR_put_long (c, t->default_index);
159 	CDR_put_ulong (c, t->sub_parts);
160 
161 	i = t->sub_parts;
162 
163 #define MEMBER_LOOPER_ENC(putname, typename, tkname)		 		\
164 	case CORBA_tk_##tkname:							\
165 		for(i = 0; i < t->sub_parts; i++) {				\
166 			CORBA_##typename tmp;					\
167 			tmp = (CORBA_##typename) t->sublabels [i];		\
168 			CDR_put_##putname (c, tmp);				\
169 			CDR_put_string (c, t->subnames [i]);			\
170 			tc_enc (t->subtypes [i], c, ctx);			\
171 		}								\
172 		break
173 
174 #define UNION_MEMBERS(dir)							\
175 	MEMBER_LOOPER_##dir(ulong, long, long);					\
176     case CORBA_tk_enum: /* fall through */					\
177 	MEMBER_LOOPER_##dir(ulong, unsigned_long, ulong);			\
178 	MEMBER_LOOPER_##dir(octet, boolean, boolean);				\
179 	MEMBER_LOOPER_##dir(octet, char, char);					\
180 	MEMBER_LOOPER_##dir(ushort, short, short);				\
181 	MEMBER_LOOPER_##dir(ushort, unsigned_short, ushort);			\
182 	MEMBER_LOOPER_##dir(ulong_long, long_long, longlong);			\
183 	MEMBER_LOOPER_##dir(ulong_long, unsigned_long_long, ulonglong);		\
184 	MEMBER_LOOPER_##dir(wchar, wchar, wchar);
185 
186 	switch (t->discriminator->kind) {
187 		UNION_MEMBERS (ENC);
188 	default:
189 		g_error ("tc_enc_tk_union: Illegal union discriminator "
190 			 "type %s\n", t->discriminator->name);
191 		break;
192     }
193 }
194 
195 static void
tc_enc_tk_enum(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)196 tc_enc_tk_enum(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
197 {
198   CORBA_unsigned_long i;
199   CDR_put_string(c, t->repo_id);
200   CDR_put_string(c, t->name);
201   CDR_put_ulong(c, t->sub_parts);
202   for(i=0;i<t->sub_parts;i++)
203     CDR_put_string(c, t->subnames[i]);
204 }
205 
206 static void
tc_enc_tk_alias(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)207 tc_enc_tk_alias(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
208 {
209   CDR_put_string(c, t->repo_id);
210   CDR_put_string(c, t->name);
211   tc_enc(*t->subtypes, c, ctx);
212 }
213 
214 static void
tc_enc_tk_except(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)215 tc_enc_tk_except(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
216 {
217   gulong i;
218   CDR_put_string(c, t->repo_id);
219   CDR_put_string(c, t->name);
220   CDR_put_ulong(c, t->sub_parts);
221   for(i=0;i<t->sub_parts;i++){
222     CDR_put_string(c, t->subnames[i]);
223     tc_enc(t->subtypes[i], c, ctx);
224   }
225 }
226 
227 static void
tc_enc_tk_array(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)228 tc_enc_tk_array(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
229 {
230   tc_enc(*t->subtypes, c, ctx);
231   CDR_put_ulong(c, t->length);
232 }
233 
234 static void
tc_enc_tk_wstring(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)235 tc_enc_tk_wstring(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
236 {
237   CDR_put_ulong(c, t->length);
238 }
239 
240 static void
tc_enc_tk_fixed(CORBA_TypeCode t,GIOPSendBuffer * c,TCEncodeContext * ctx)241 tc_enc_tk_fixed(CORBA_TypeCode t, GIOPSendBuffer *c, TCEncodeContext* ctx)
242 {
243   CDR_put_ushort(c, t->digits);
244   CDR_put_short(c, t->scale);
245 }
246 
247 static void
ORBit_TypeCode_free_fn(ORBit_RootObject obj_in)248 ORBit_TypeCode_free_fn (ORBit_RootObject obj_in)
249 {
250 	CORBA_TypeCode tc = (CORBA_TypeCode) obj_in;
251 	int i;
252 
253 	g_free ((char*)(tc->name));
254 	g_free ((char*)(tc->repo_id));
255 
256 	for (i = 0; i < tc->sub_parts; i++) {
257 		if (tc->subnames)
258 			g_free ((char*)(tc->subnames [i]));
259 
260 		if (tc->subtypes)
261 			ORBit_RootObject_release_T (tc->subtypes [i]);
262 	}
263 
264 	g_free (tc->subnames);
265 	g_free (tc->subtypes);
266 	g_free (tc->sublabels);
267 
268 	if (tc->discriminator)
269 		ORBit_RootObject_release_T (tc->discriminator);
270 
271 	p_free (tc, struct CORBA_TypeCode_struct);
272 }
273 
274 static gboolean
CDR_get(GIOPRecvBuffer * buf,guchar * ptr,guint len)275 CDR_get (GIOPRecvBuffer *buf,
276 	 guchar         *ptr,
277 	 guint           len)
278 {
279 	buf->cur = ALIGN_ADDRESS (buf->cur, len);
280 
281 	if ((buf->cur + len) > buf->end)
282 		return TRUE;
283 
284 	memcpy (ptr, buf->cur, len);
285 
286 	if (len != 1 && giop_msg_conversion_needed (buf))
287 		switch (len) {
288 		case 2:
289 			*(guint16 *)ptr = GUINT16_SWAP_LE_BE (*(guint16 *)ptr);
290 			break;
291 		case 4:
292 			*(guint32 *)ptr = GUINT32_SWAP_LE_BE (*(guint32 *)ptr);
293 			break;
294 		case 8:
295 			*(guint64 *)ptr = GUINT64_SWAP_LE_BE (*(guint64 *)ptr);
296 			break;
297 		default:
298 			g_assert_not_reached ();
299 			break;
300 		}
301 
302 	buf->cur += len;
303 
304 	return FALSE;
305 }
306 
307 #define CDR_get_ulong(x, y)       CDR_get(x, (guchar *)y, 4)
308 #define CDR_get_ushort(x, y)      CDR_get(x, (guchar *)y, 2)
309 #define CDR_get_short(x, y)       CDR_get(x, (guchar *)y, 2)
310 #define CDR_get_ulong_long(x, y)  CDR_get(x, (guchar *)y, 8)
311 #define CDR_get_octet(x, y)       CDR_get(x, (guchar *)y, 1)
312 #define CDR_get_wchar(x, y)       CDR_get(x, (guchar *)y, 2)
313 
314 static gboolean
CDR_get_const_string(GIOPRecvBuffer * buf,char ** ptr)315 CDR_get_const_string(GIOPRecvBuffer *buf, char **ptr)
316 {
317   CORBA_unsigned_long len;
318 
319   if(CDR_get_ulong(buf, &len))
320     return TRUE;
321 
322   if((buf->cur + len) > buf->end
323      || (buf->cur + len) < buf->cur)
324     return TRUE;
325   *ptr = g_memdup(buf->cur, len);
326   buf->cur += len;
327 
328   return FALSE;
329 }
330 
331 static CORBA_short
ORBit_TC_find_c_alignment(CORBA_TypeCode tc)332 ORBit_TC_find_c_alignment (CORBA_TypeCode tc)
333 {
334 	CORBA_short retval = 1;
335 	int         i;
336 
337 	while (tc->kind == CORBA_tk_alias)
338 		tc = tc->subtypes[0];
339 
340 	switch(tc->kind) {
341 	case CORBA_tk_union:
342 		retval = MAX (retval,
343 			      ORBit_TC_find_c_alignment (tc->discriminator));
344 	case CORBA_tk_except:
345 	case CORBA_tk_struct:
346 #if ORBIT_ALIGNOF_CORBA_STRUCT > 1
347 		retval = MAX (retval, ORBIT_ALIGNOF_CORBA_STRUCT);
348 #endif
349 		for(i = 0; i < tc->sub_parts; i++)
350 			retval = MAX (retval,
351 				      ORBit_TC_find_c_alignment (tc->subtypes[i]));
352 		return retval;
353 	case CORBA_tk_ulong:
354 	case CORBA_tk_long:
355 	case CORBA_tk_enum:
356 		return ORBIT_ALIGNOF_CORBA_LONG;
357 	case CORBA_tk_ushort:
358 	case CORBA_tk_short:
359 	case CORBA_tk_wchar:
360 		return ORBIT_ALIGNOF_CORBA_SHORT;
361 	case CORBA_tk_longlong:
362 	case CORBA_tk_ulonglong:
363 		return ORBIT_ALIGNOF_CORBA_LONG_LONG;
364 	case CORBA_tk_float:
365 		return ORBIT_ALIGNOF_CORBA_FLOAT;
366 	case CORBA_tk_double:
367 		return ORBIT_ALIGNOF_CORBA_DOUBLE;
368 	case CORBA_tk_longdouble:
369 		return ORBIT_ALIGNOF_CORBA_LONG_DOUBLE;
370 	case CORBA_tk_boolean:
371 	case CORBA_tk_char:
372 	case CORBA_tk_octet:
373 		return ORBIT_ALIGNOF_CORBA_CHAR;
374 	case CORBA_tk_string:
375 	case CORBA_tk_wstring:
376 	case CORBA_tk_TypeCode:
377 	case CORBA_tk_objref:
378 		return ORBIT_ALIGNOF_CORBA_POINTER;
379 	case CORBA_tk_sequence:
380 		return ORBIT_ALIGNOF_CORBA_SEQ;
381 	case CORBA_tk_any:
382 		return ORBIT_ALIGNOF_CORBA_ANY;
383 	case CORBA_tk_array:
384 		return ORBit_TC_find_c_alignment (tc->subtypes[0]);
385 	case CORBA_tk_fixed:
386 		return ORBIT_ALIGNOF_CORBA_FIXED;
387 	default:
388 		return 1;
389 	}
390 }
391 
392 static gboolean
tc_dec_tk_objref(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)393 tc_dec_tk_objref (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
394 {
395 	if (CDR_get_const_string (c, &t->repo_id))
396 		return TRUE;
397 	if (CDR_get_const_string (c, &t->name))
398 		return TRUE;
399 	return FALSE;
400 }
401 
402 static gboolean
tc_dec_tk_sequence(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)403 tc_dec_tk_sequence (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
404 {
405 	t->subtypes = g_new0 (CORBA_TypeCode, 1);
406 	if (tc_dec (&t->subtypes[0], c, ctx))
407 		return TRUE;
408 	t->sub_parts = 1;
409 	if (CDR_get_ulong (c, &t->length))
410 		return TRUE;
411 	return FALSE;
412 }
413 
414 static gboolean
tc_dec_tk_string(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)415 tc_dec_tk_string (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
416 {
417 	if (CDR_get_ulong (c, &t->length))
418 		return TRUE;
419 	return FALSE;
420 }
421 
422 static gboolean
tc_dec_tk_struct(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)423 tc_dec_tk_struct (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
424 {
425 	CORBA_unsigned_long i;
426 
427 	if (CDR_get_const_string (c, &t->repo_id))
428 		return TRUE;
429 	if (CDR_get_const_string (c, &t->name))
430 		return TRUE;
431 	if (CDR_get_ulong (c, &t->sub_parts))
432 		return TRUE;
433 
434 	t->subnames = g_new0 (char*, t->sub_parts);
435 	t->subtypes = g_new0 (CORBA_TypeCode, t->sub_parts);
436 
437 	for (i = 0; i < t->sub_parts; i++) {
438 		if (CDR_get_const_string (c, &t->subnames [i]))
439 			return TRUE;
440 		if (tc_dec (&t->subtypes [i], c, ctx))
441 			return TRUE;
442 	}
443 
444 	return FALSE;
445 }
446 
447 static gboolean
tc_dec_tk_union(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)448 tc_dec_tk_union (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
449 {
450 	CORBA_unsigned_long i;
451 
452 	if (CDR_get_const_string (c, &t->repo_id))
453 		return TRUE;
454 	if (CDR_get_const_string (c, &t->name))
455 		return TRUE;
456 	if (tc_dec (&t->discriminator, c, ctx))
457 		return TRUE;
458 	if (CDR_get_ulong (c, &t->default_index))
459 		return TRUE;
460 	if (CDR_get_ulong (c, &t->sub_parts))
461 		return TRUE;
462 
463 	t->sublabels = g_new0 (CORBA_long, t->sub_parts);
464 	t->subnames  = g_new0 (char *, t->sub_parts);
465 	t->subtypes  = g_new0 (CORBA_TypeCode, t->sub_parts);
466 
467 #define MEMBER_LOOPER_DEC(getname, typename, tkname)			\
468 	case CORBA_tk_##tkname:						\
469 		for(i = 0; i < t->sub_parts; i++){ 			\
470 			CORBA_##typename tmp;				\
471 			if (CDR_get_##getname (c, &tmp))		\
472 				return TRUE;				\
473 			t->sublabels [i] = (CORBA_long) tmp;		\
474 			if (CDR_get_const_string (c, &t->subnames[i]))	\
475 				return TRUE;				\
476 			if (tc_dec (&t->subtypes[i], c, ctx))		\
477 				return TRUE;				\
478 		}							\
479 		break
480 
481 	switch (t->discriminator->kind) {
482 		UNION_MEMBERS (DEC);
483 	default:
484 		/* XXX: what is correct error handling? */
485 		g_error("Don't know how to handle this type (%d) of discriminator.",
486 			t->discriminator->kind);
487 	}
488 
489 	return FALSE;
490 }
491 
492 static gboolean
tc_dec_tk_enum(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)493 tc_dec_tk_enum (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
494 {
495 	CORBA_unsigned_long i;
496 
497 	if (CDR_get_const_string (c, &t->repo_id))
498 		return TRUE;
499 	if (CDR_get_const_string (c, &t->name))
500 		return TRUE;
501 	if (CDR_get_ulong (c, &t->sub_parts))
502 		return TRUE;
503 
504 	t->subnames = g_new0 (char*, t->sub_parts);
505 	for(i = 0; i < t->sub_parts; i++) {
506 		if (CDR_get_const_string (c, &t->subnames[i]))
507 			return TRUE;
508 	}
509 
510 	return FALSE;
511 }
512 
513 static gboolean
tc_dec_tk_alias(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)514 tc_dec_tk_alias (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
515 {
516 	CDR_get_const_string (c, &t->repo_id);
517 	CDR_get_const_string (c, &t->name);
518 
519 	t->subtypes = g_new0 (CORBA_TypeCode, 1);
520 	if (tc_dec (t->subtypes, c, ctx))
521 		return TRUE;
522 	t->sub_parts = 1;
523 
524 	return FALSE;
525 }
526 
527 
528 static gboolean
tc_dec_tk_except(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)529 tc_dec_tk_except (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
530 {
531 	gulong i;
532 
533 	if (CDR_get_const_string (c, &t->repo_id))
534 		return TRUE;
535 	if (CDR_get_const_string (c, &t->name))
536 		return TRUE;
537 	if (CDR_get_ulong (c, &t->sub_parts))
538 		return TRUE;
539 
540 	t->subtypes = g_new0 (CORBA_TypeCode, t->sub_parts);
541 	t->subnames = g_new0 (char *, t->sub_parts);
542 
543 	for (i = 0; i < t->sub_parts; i++) {
544 		if (CDR_get_const_string (c, &t->subnames[i]))
545 			return TRUE;
546 		if (tc_dec (&t->subtypes[i], c, ctx))
547 			return TRUE;
548 	}
549 
550 	return FALSE;
551 }
552 
553 static gboolean
tc_dec_tk_array(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)554 tc_dec_tk_array (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
555 {
556 	t->subtypes = g_new (CORBA_TypeCode, 1);
557 
558 	if (tc_dec (t->subtypes, c, ctx))
559 		return TRUE;
560 
561 	t->sub_parts = 1;
562 	if (CDR_get_ulong (c, &t->length))
563 		return TRUE;
564 
565 	return FALSE;
566 }
567 
568 
569 static gboolean
tc_dec_tk_wstring(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)570 tc_dec_tk_wstring (CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
571 {
572 	if (CDR_get_ulong (c, &t->length))
573 		return TRUE;
574 	return FALSE;
575 }
576 
577 static gboolean
tc_dec_tk_fixed(CORBA_TypeCode t,GIOPRecvBuffer * c,TCDecodeContext * ctx)578 tc_dec_tk_fixed(CORBA_TypeCode t, GIOPRecvBuffer *c, TCDecodeContext* ctx)
579 {
580 	if (CDR_get_ushort (c, &t->digits))
581 		return TRUE;
582 	if (CDR_get_short (c, &t->scale))
583 		return TRUE;
584 
585 	return FALSE;
586 }
587 
588 /* FIXME: Right now this function doesn't record whether or not it has
589    already visited a given TypeCode.  I'm not sure if every recursive
590    type will have a tk_recursive node in it; if not, then this will
591    need to be reworked a bit.  */
592 static CORBA_boolean
typecode_equiv_internal(CORBA_TypeCode obj,CORBA_TypeCode tc,gboolean strict_equal,CORBA_Environment * ev)593 typecode_equiv_internal (CORBA_TypeCode obj,
594 			 CORBA_TypeCode tc,
595 			 gboolean       strict_equal,
596 			 CORBA_Environment *ev)
597 {
598 	int i;
599 
600 	g_return_val_if_fail (tc != NULL, CORBA_FALSE);
601 	g_return_val_if_fail (obj != NULL, CORBA_FALSE);
602 
603 	if (!strict_equal) {
604 		while (obj->kind == CORBA_tk_alias)
605 			obj = obj->subtypes [0];
606 
607 		while (tc->kind  == CORBA_tk_alias)
608 			tc  = tc->subtypes [0];
609 	}
610 
611 	if (obj->kind != tc->kind)
612 		return CORBA_FALSE;
613 
614 	switch (obj->kind) {
615 	case CORBA_tk_wstring:
616 	case CORBA_tk_string:
617 		return obj->length == tc->length;
618 	case CORBA_tk_objref:
619 		return ! strcmp (obj->repo_id, tc->repo_id);
620 	case CORBA_tk_except:
621 	case CORBA_tk_struct:
622 		if (strcmp (obj->repo_id, tc->repo_id)
623 		    || obj->sub_parts != tc->sub_parts)
624 			return CORBA_FALSE;
625 		for (i = 0; i < obj->sub_parts; ++i)
626 			if (! typecode_equiv_internal (obj->subtypes[i],
627 						       tc->subtypes[i],
628 						       strict_equal, ev))
629 				return CORBA_FALSE;
630 		break;
631 	case CORBA_tk_union:
632 		if (strcmp (obj->repo_id, tc->repo_id)
633 		    || obj->sub_parts != tc->sub_parts
634 		    || ! typecode_equiv_internal (obj->discriminator,
635 						   tc->discriminator,
636 						   strict_equal, ev)
637 		    || obj->default_index != tc->default_index)
638 			return CORBA_FALSE;
639 		for (i = 0; i < obj->sub_parts; ++i)
640 
641 			if (! typecode_equiv_internal (obj->subtypes[i],
642 						       tc->subtypes[i],
643 						       strict_equal, ev)
644 			    || obj->sublabels [i] != tc->sublabels [i])
645 				return CORBA_FALSE;
646 
647 		break;
648 	case CORBA_tk_enum:
649 		if (obj->sub_parts != tc->sub_parts
650 		    || strcmp (obj->repo_id, tc->repo_id))
651 			return CORBA_FALSE;
652 		for (i = 0; i < obj->sub_parts; ++i)
653 			if (strcmp (obj->subnames[i], tc->subnames[i]))
654 				return CORBA_FALSE;
655 		break;
656 	case CORBA_tk_sequence:
657 	case CORBA_tk_array:
658 		if (obj->length != tc->length)
659 			return CORBA_FALSE;
660 		g_assert (obj->sub_parts == 1);
661 		g_assert (tc->sub_parts == 1);
662 		return typecode_equiv_internal (obj->subtypes[0],
663 						tc->subtypes[0],
664 						strict_equal, ev);
665 	case CORBA_tk_alias:
666 		if (strcmp (obj->repo_id, tc->repo_id))
667 			return CORBA_FALSE;
668 
669 		g_assert (obj->sub_parts == 1);
670 		g_assert (tc->sub_parts == 1);
671 
672 		return typecode_equiv_internal (obj->subtypes[0],
673 						tc->subtypes[0],
674 						strict_equal, ev);
675 		break;
676 	case CORBA_tk_recursive:
677 		return obj->recurse_depth == tc->recurse_depth;
678 	case CORBA_tk_fixed:
679 		return obj->digits == tc->digits && obj->scale == tc->scale;
680 
681 	default:
682 		/* Everything else is primitive.  */
683 		break;
684 	}
685 
686 	return CORBA_TRUE;
687 }
688 
689 CORBA_boolean
CORBA_TypeCode_equal(CORBA_TypeCode obj,const CORBA_TypeCode tc,CORBA_Environment * ev)690 CORBA_TypeCode_equal (CORBA_TypeCode obj,
691 		      const CORBA_TypeCode tc,
692 		      CORBA_Environment *ev)
693 {
694 	return typecode_equiv_internal (obj, tc, TRUE, ev);
695 }
696 
697 CORBA_boolean
CORBA_TypeCode_equivalent(CORBA_TypeCode obj,const CORBA_TypeCode tc,CORBA_Environment * ev)698 CORBA_TypeCode_equivalent (CORBA_TypeCode obj,
699 			   const CORBA_TypeCode tc,
700 			   CORBA_Environment *ev)
701 {
702 	return typecode_equiv_internal (obj, tc, FALSE, ev);
703 }
704 
705 CORBA_TypeCode
CORBA_TypeCode_get_compact_typecode(CORBA_TypeCode typecode,CORBA_Environment * ev)706 CORBA_TypeCode_get_compact_typecode (CORBA_TypeCode     typecode,
707 				     CORBA_Environment *ev)
708 {
709 	/* FIXME: implement */
710 	CORBA_exception_set_system (
711 		ev, ex_CORBA_NO_IMPLEMENT, CORBA_COMPLETED_NO);
712 
713 	return CORBA_OBJECT_NIL;
714 }
715 
716 CORBA_TCKind
CORBA_TypeCode_kind(CORBA_TypeCode typecode,CORBA_Environment * ev)717 CORBA_TypeCode_kind (CORBA_TypeCode     typecode,
718 		     CORBA_Environment *ev)
719 {
720 	return typecode->kind;
721 }
722 
723 CORBA_RepositoryId
CORBA_TypeCode_id(CORBA_TypeCode typecode,CORBA_Environment * ev)724 CORBA_TypeCode_id (CORBA_TypeCode     typecode,
725 		   CORBA_Environment *ev)
726 {
727 	if (!(typecode->kind == CORBA_tk_objref             ||
728 	      typecode->kind == CORBA_tk_value              ||
729 	      typecode->kind == CORBA_tk_value_box          ||
730 	      typecode->kind == CORBA_tk_abstract_interface ||
731 	      typecode->kind == CORBA_tk_native             ||
732 	      typecode->kind == CORBA_tk_struct             ||
733 	      typecode->kind == CORBA_tk_union              ||
734 	      typecode->kind == CORBA_tk_enum               ||
735 	      typecode->kind == CORBA_tk_alias              ||
736 	      typecode->kind == CORBA_tk_except)) {
737 		CORBA_exception_set (
738 			ev, CORBA_USER_EXCEPTION,
739 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
740 		return NULL;
741 	}
742 
743 	return CORBA_string_dup (typecode->repo_id);
744 }
745 
746 CORBA_Identifier
CORBA_TypeCode_name(CORBA_TypeCode typecode,CORBA_Environment * ev)747 CORBA_TypeCode_name (CORBA_TypeCode     typecode,
748 		     CORBA_Environment *ev)
749 {
750 	if (!(typecode->kind == CORBA_tk_objref             ||
751 	      typecode->kind == CORBA_tk_struct             ||
752 	      typecode->kind == CORBA_tk_union              ||
753 	      typecode->kind == CORBA_tk_enum               ||
754 	      typecode->kind == CORBA_tk_alias              ||
755 	      typecode->kind == CORBA_tk_abstract_interface ||
756 	      typecode->kind == CORBA_tk_value              ||
757 	      typecode->kind == CORBA_tk_value_box          ||
758 	      typecode->kind == CORBA_tk_native             ||
759 	      typecode->kind == CORBA_tk_except)) {
760 		CORBA_exception_set (
761 			ev, CORBA_USER_EXCEPTION,
762 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
763 		return NULL;
764 	}
765 
766 	return CORBA_string_dup (typecode->name);
767 }
768 
769 CORBA_unsigned_long
CORBA_TypeCode_member_count(CORBA_TypeCode typecode,CORBA_Environment * ev)770 CORBA_TypeCode_member_count (CORBA_TypeCode     typecode,
771 			     CORBA_Environment *ev)
772 {
773 	if (!(typecode->kind == CORBA_tk_struct ||
774 	      typecode->kind == CORBA_tk_union  ||
775 	      typecode->kind == CORBA_tk_value  ||
776 	      typecode->kind == CORBA_tk_enum   ||
777 	      typecode->kind == CORBA_tk_except)) {
778 		CORBA_exception_set (
779 			ev, CORBA_USER_EXCEPTION,
780 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
781 		return 0;
782 	}
783 
784 	return typecode->sub_parts;
785 }
786 
787 CORBA_Identifier
CORBA_TypeCode_member_name(CORBA_TypeCode typecode,const CORBA_unsigned_long index,CORBA_Environment * ev)788 CORBA_TypeCode_member_name (CORBA_TypeCode       typecode,
789 			    const CORBA_unsigned_long index,
790 			    CORBA_Environment   *ev)
791 {
792 	if (!(typecode->kind == CORBA_tk_struct ||
793 	      typecode->kind == CORBA_tk_union  ||
794 	      typecode->kind == CORBA_tk_value  ||
795 	      typecode->kind == CORBA_tk_enum   ||
796 	      typecode->kind == CORBA_tk_except)) {
797 		CORBA_exception_set (
798 			ev, CORBA_USER_EXCEPTION,
799 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
800 		return NULL;
801 	}
802 
803 	if (index > typecode->sub_parts) {
804 		CORBA_exception_set (
805 			ev, CORBA_USER_EXCEPTION,
806 			"IDL:omg.org/CORBA/TypeCode/Bounds/1.0", NULL);
807 		return NULL;
808 	}
809 
810 	return CORBA_string_dup (typecode->subnames [index]);
811 }
812 
813 CORBA_TypeCode
CORBA_TypeCode_member_type(CORBA_TypeCode typecode,const CORBA_unsigned_long index,CORBA_Environment * ev)814 CORBA_TypeCode_member_type (CORBA_TypeCode       typecode,
815 			    const CORBA_unsigned_long index,
816 			    CORBA_Environment   *ev)
817 {
818 	if (!(typecode->kind == CORBA_tk_struct ||
819 	      typecode->kind == CORBA_tk_union  ||
820 	      typecode->kind == CORBA_tk_value  ||
821 	      typecode->kind == CORBA_tk_enum   ||
822 	      typecode->kind == CORBA_tk_except)) {
823 		CORBA_exception_set (
824 			ev, CORBA_USER_EXCEPTION,
825 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
826 		return NULL;
827 	}
828 
829 	if (index > typecode->sub_parts) {
830 		CORBA_exception_set (
831 			ev, CORBA_USER_EXCEPTION,
832 			"IDL:omg.org/CORBA/TypeCode/Bounds/1.0", NULL);
833 		return NULL;
834 	}
835 
836 	return ORBit_RootObject_duplicate (typecode->subtypes [index]);
837 }
838 
839 CORBA_any *
CORBA_TypeCode_member_label(CORBA_TypeCode typecode,const CORBA_unsigned_long index,CORBA_Environment * ev)840 CORBA_TypeCode_member_label (CORBA_TypeCode       typecode,
841 			     const CORBA_unsigned_long index,
842 			     CORBA_Environment   *ev)
843 {
844 	CORBA_any *retval;
845 
846 	if (typecode->kind != CORBA_tk_union) {
847 		CORBA_exception_set (
848 			ev, CORBA_USER_EXCEPTION,
849 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
850 		return NULL;
851 	}
852 
853 	if (index > typecode->sub_parts) {
854 		CORBA_exception_set (
855 			ev, CORBA_USER_EXCEPTION,
856 			"IDL:omg.org/CORBA/TypeCode/Bounds/1.0", NULL);
857 		return NULL;
858 	}
859 
860 	retval = CORBA_any__alloc ();
861 
862 	retval->_type  = ORBit_RootObject_duplicate (typecode->discriminator);
863 	retval->_value = ORBit_copy_value (&typecode->sublabels [index],
864 					   typecode->discriminator);
865 	retval->_release = CORBA_TRUE;
866 
867 	return retval;
868 }
869 
870 CORBA_TypeCode
CORBA_TypeCode_discriminator_type(CORBA_TypeCode typecode,CORBA_Environment * ev)871 CORBA_TypeCode_discriminator_type (CORBA_TypeCode     typecode,
872 				   CORBA_Environment *ev)
873 {
874 	if (typecode->kind != CORBA_tk_union) {
875 		CORBA_exception_set (
876 			ev, CORBA_USER_EXCEPTION,
877 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
878 		return NULL;
879 	}
880 
881 	return ORBit_RootObject_duplicate (typecode->discriminator);
882 }
883 
884 CORBA_long
CORBA_TypeCode_default_index(CORBA_TypeCode typecode,CORBA_Environment * ev)885 CORBA_TypeCode_default_index (CORBA_TypeCode     typecode,
886 			      CORBA_Environment *ev)
887 {
888 	if (typecode->kind != CORBA_tk_union) {
889 		CORBA_exception_set (
890 			ev, CORBA_USER_EXCEPTION,
891 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
892 		return 0;
893 	}
894 
895 	return typecode->default_index;
896 }
897 
898 CORBA_unsigned_long
CORBA_TypeCode_length(CORBA_TypeCode typecode,CORBA_Environment * ev)899 CORBA_TypeCode_length (CORBA_TypeCode     typecode,
900 		       CORBA_Environment *ev)
901 {
902 	if (!(typecode->kind == CORBA_tk_string   ||
903 	      typecode->kind == CORBA_tk_wstring  ||
904 	      typecode->kind == CORBA_tk_sequence ||
905 	      typecode->kind == CORBA_tk_array)) {
906 		CORBA_exception_set (
907 			ev, CORBA_USER_EXCEPTION,
908 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
909 		return 0;
910 	}
911 
912 	return typecode->length;
913 }
914 
915 CORBA_TypeCode
CORBA_TypeCode_content_type(CORBA_TypeCode typecode,CORBA_Environment * ev)916 CORBA_TypeCode_content_type (CORBA_TypeCode     typecode,
917 			     CORBA_Environment *ev)
918 {
919 	if (!(typecode->kind == CORBA_tk_sequence  ||
920 	      typecode->kind == CORBA_tk_array     ||
921 	      typecode->kind == CORBA_tk_value_box ||
922 	      typecode->kind == CORBA_tk_alias)) {
923 		CORBA_exception_set (
924 			ev, CORBA_USER_EXCEPTION,
925 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
926 		return NULL;
927 	}
928 
929 	g_assert (typecode->sub_parts == 1);
930 
931 	return ORBit_RootObject_duplicate (typecode->subtypes [0]);
932 }
933 
934 CORBA_unsigned_short
CORBA_TypeCode_fixed_digits(CORBA_TypeCode typecode,CORBA_Environment * ev)935 CORBA_TypeCode_fixed_digits (CORBA_TypeCode     typecode,
936 			     CORBA_Environment *ev)
937 {
938 	if (typecode->kind != CORBA_tk_fixed) {
939 		CORBA_exception_set (
940 			ev, CORBA_USER_EXCEPTION,
941 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
942 		return 0;
943 	}
944 
945 	return typecode->digits;
946 }
947 
948 CORBA_short
CORBA_TypeCode_fixed_scale(CORBA_TypeCode typecode,CORBA_Environment * ev)949 CORBA_TypeCode_fixed_scale (CORBA_TypeCode     typecode,
950 			    CORBA_Environment *ev)
951 {
952 	if (typecode->kind != CORBA_tk_fixed) {
953 		CORBA_exception_set (
954 			ev, CORBA_USER_EXCEPTION,
955 			"IDL:omg.org/CORBA/TypeCode/BadKind/1.0", NULL);
956 		return 0;
957 	}
958 
959 	return typecode->scale;
960 }
961 
962 CORBA_Visibility
CORBA_TypeCode_member_visibility(CORBA_TypeCode typecode,const CORBA_unsigned_long index,CORBA_Environment * ev)963 CORBA_TypeCode_member_visibility (CORBA_TypeCode             typecode,
964 				  const CORBA_unsigned_long  index,
965 				  CORBA_Environment         *ev)
966 {
967 	/* FIXME: implement */
968 	CORBA_exception_set_system (
969 		ev, ex_CORBA_NO_IMPLEMENT, CORBA_COMPLETED_NO);
970 
971 	return 0;
972 }
973 
974 CORBA_ValueModifier
CORBA_TypeCode_type_modifier(CORBA_TypeCode typecode,CORBA_Environment * ev)975 CORBA_TypeCode_type_modifier (CORBA_TypeCode     typecode,
976 			      CORBA_Environment *ev)
977 {
978 	/* FIXME: implement */
979 	CORBA_exception_set_system (
980 		ev, ex_CORBA_NO_IMPLEMENT, CORBA_COMPLETED_NO);
981 
982 	return 0;
983 }
984 
985 CORBA_TypeCode
CORBA_TypeCode_concrete_base_type(CORBA_TypeCode typecode,CORBA_Environment * ev)986 CORBA_TypeCode_concrete_base_type (CORBA_TypeCode     typecode,
987 				   CORBA_Environment *ev)
988 {
989 	/* FIXME: implement */
990 	CORBA_exception_set_system (
991 		ev, ex_CORBA_NO_IMPLEMENT, CORBA_COMPLETED_NO);
992 
993 	return CORBA_OBJECT_NIL;
994 }
995 
996 const char *
ORBit_tk_to_name(CORBA_unsigned_long tk)997 ORBit_tk_to_name (CORBA_unsigned_long tk)
998 {
999 #define CSE(a, b) \
1000 	case CORBA_tk_ ## a: return b;
1001 
1002 	switch (tk) {
1003 		CSE (null, "null");
1004 		CSE (void, "void");
1005 		CSE (short, "short");
1006 		CSE (long, "long");
1007 		CSE (ushort, "ushort");
1008 		CSE (ulong, "ulong");
1009 		CSE (float, "float");
1010 		CSE (double, "double");
1011 		CSE (boolean, "boolean");
1012 		CSE (char, "char");
1013 		CSE (octet, "octet");
1014 		CSE (any, "any");
1015 		CSE (TypeCode, "TypeCode");
1016 		CSE (Principal, "Principal");
1017 		CSE (objref, "objref");
1018 		CSE (struct, "struct");
1019 		CSE (union, "union");
1020 		CSE (enum, "enum");
1021 		CSE (string, "string");
1022 		CSE (sequence, "sequence");
1023 		CSE (array, "array");
1024 		CSE (alias, "alias");
1025 		CSE (except, "except");
1026 		CSE (longlong, "longlong");
1027 		CSE (ulonglong, "ulonglong");
1028 		CSE (longdouble, "longdouble");
1029 		CSE (wchar, "wchar");
1030 		CSE (wstring, "wstring");
1031 		CSE (fixed, "fixed");
1032 		CSE (value, "value");
1033 		CSE (value_box, "value_box");
1034 		CSE (native, "native");
1035 		CSE (abstract_interface, "abstract_interface");
1036 	default:
1037 		return "Invalid type";
1038 	}
1039 }
1040 
1041 static const TkInfo tk_info[CORBA_tk_last]= {
1042 	{ TK_EMPTY, NULL, NULL, TC_null }, /* tk_null */
1043 	{ TK_EMPTY, NULL, NULL, TC_void }, /* tk_void */
1044 	{ TK_EMPTY, NULL, NULL, TC_CORBA_short }, /* tk_short */
1045 	{ TK_EMPTY, NULL, NULL, TC_CORBA_long }, /* tk_long */
1046 	{ TK_EMPTY, NULL, NULL, TC_CORBA_unsigned_short }, /* tk_ushort */
1047 	{ TK_EMPTY, NULL, NULL, TC_CORBA_unsigned_long }, /* tk_ulong */
1048 	{ TK_EMPTY, NULL, NULL, TC_CORBA_float }, /* tk_float */
1049 	{ TK_EMPTY, NULL, NULL, TC_CORBA_double }, /* tk_double */
1050 	{ TK_EMPTY, NULL, NULL, TC_CORBA_boolean }, /* tk_boolean */
1051 	{ TK_EMPTY, NULL, NULL, TC_CORBA_char }, /* tk_char */
1052 	{ TK_EMPTY, NULL, NULL, TC_CORBA_octet }, /* tk_octet */
1053 	{ TK_EMPTY, NULL, NULL, TC_CORBA_any }, /* tk_any */
1054 	{ TK_EMPTY, NULL, NULL, TC_CORBA_TypeCode }, /* tk_TypeCode */
1055         { TK_EMPTY, NULL, NULL, TC_CORBA_Principal }, /* tk_Principal */
1056 	{ TK_COMPLEX, tc_enc_tk_objref, tc_dec_tk_objref }, /* tk_objref */
1057 	{ TK_COMPLEX, tc_enc_tk_struct, tc_dec_tk_struct }, /* tk_struct */
1058         { TK_COMPLEX, tc_enc_tk_union, tc_dec_tk_union }, /* tk_union */
1059         { TK_COMPLEX, tc_enc_tk_enum, tc_dec_tk_enum }, /* tk_enum */
1060         { TK_SIMPLE, tc_enc_tk_string, tc_dec_tk_string }, /* tk_string */
1061         { TK_COMPLEX, tc_enc_tk_sequence, tc_dec_tk_sequence }, /* tk_sequence */
1062         { TK_COMPLEX, tc_enc_tk_array, tc_dec_tk_array }, /* tk_array */
1063         { TK_COMPLEX, tc_enc_tk_alias, tc_dec_tk_alias }, /* tk_alias */
1064         { TK_COMPLEX, tc_enc_tk_except, tc_dec_tk_except }, /* tk_except */
1065         { TK_EMPTY, NULL, NULL, TC_CORBA_long_long}, /* tk_longlong */
1066         { TK_EMPTY, NULL, NULL, TC_CORBA_unsigned_long_long }, /* tk_ulonglong */
1067         { TK_EMPTY, NULL, NULL, TC_CORBA_long_double }, /* tk_longdouble */
1068         { TK_EMPTY, NULL, NULL, TC_CORBA_wchar }, /* tk_wchar */
1069 	{ TK_SIMPLE, tc_enc_tk_wstring, tc_dec_tk_wstring}, /* tk_wstring */
1070 	{ TK_SIMPLE, tc_enc_tk_fixed, tc_dec_tk_fixed} /* tk_fixed */
1071 };
1072 
1073 ORBIT2_MAYBE_CONST ORBit_RootObject_Interface ORBit_TypeCode_epv = {
1074 	ORBIT_ROT_TYPECODE,
1075 	ORBit_TypeCode_free_fn
1076 };
1077 
1078 static gboolean
tc_dec(CORBA_TypeCode * t,GIOPRecvBuffer * c,TCDecodeContext * ctx)1079 tc_dec (CORBA_TypeCode  *t,
1080 	GIOPRecvBuffer  *c,
1081 	TCDecodeContext *ctx)
1082 {
1083 	guint               tmp_index;
1084 	const TkInfo       *info;
1085 	CORBA_TCKind        kind;
1086 	GIOPRecvBuffer     *encaps;
1087 	TCRecursionNode    *node;
1088 	CORBA_unsigned_long lkind;
1089 
1090 	if (CDR_get_ulong (c, &lkind))
1091 		return TRUE;
1092 
1093 	kind = lkind;
1094 
1095 	if (lkind >= CORBA_tk_last) {
1096 		CORBA_long offset;
1097 		GSList    *l;
1098 
1099 		if (lkind != CORBA_tk_recursive) {
1100 			g_warning ("%s: invalid CORBA_TCKind, lkind=%lu",
1101 				   G_STRFUNC, (unsigned long int) lkind);
1102 			return TRUE;
1103 		}
1104 
1105 		if (CDR_get_ulong (c, &offset))
1106 			return TRUE;
1107 
1108 		for (l = ctx->prior_tcs; l; l = l->next) {
1109 			node = l->data;
1110 			if (offset == node->index - ctx->current_idx - get_rptr (c)) {
1111 				*t = ORBit_RootObject_duplicate (node->tc);
1112 				return FALSE;
1113 			}
1114 /*			else
1115 				g_warning ("back tc mismactch '%d' == '%d - %d - %d' = '%d' Tk %d",
1116 					   offset, node->index, ctx->current_idx, get_rptr (c),
1117 					   node->index - ctx->current_idx - get_rptr (c),
1118 					   node->tc->kind);*/
1119 		}
1120 
1121 		/* FIXME: we should handle this slightly gracefully */
1122 		g_error ("tc_dec: Invalid CORBA_TypeCode recursion "
1123 			 "offset in input buffer\n");
1124 		g_assert_not_reached ();
1125 	}
1126 
1127 	g_assert (kind < CORBA_tk_last);
1128 
1129 	node = g_new (TCRecursionNode, 1);
1130 	node->index = ctx->current_idx + get_rptr(c) - 4; /* -4 for the TCKind */
1131 	info = &tk_info [kind];
1132 
1133 	if (info->type == TK_EMPTY)
1134 		node->tc = info->basic_type;
1135 
1136 	else {
1137 		CORBA_TypeCode      tc;
1138 
1139 		tc = g_new0 (struct CORBA_TypeCode_struct, 1);
1140 
1141 		ORBit_RootObject_init (&tc->parent, &ORBit_TypeCode_epv);
1142 		ORBit_RootObject_duplicate (tc);
1143 
1144 		tc->kind = kind;
1145 
1146 		switch (info->type) {
1147 
1148 		case TK_EMPTY:
1149 			g_assert_not_reached ();
1150 			break;
1151 
1152 		case TK_COMPLEX:
1153 			tmp_index = ctx->current_idx;
1154 			ctx->current_idx += get_rptr (c) + 4;
1155 			/* NB. the encaps buffer is for data validation */
1156 			encaps = giop_recv_buffer_use_encaps_buf (c);
1157 			info->decoder (tc, encaps, ctx);
1158 			ctx->current_idx = tmp_index;
1159 			giop_recv_buffer_unuse (encaps);
1160 			break;
1161 
1162 		case TK_SIMPLE:
1163 			info->decoder (tc, c, ctx);
1164 			break;
1165 		}
1166 
1167 		tc->c_align = ORBit_TC_find_c_alignment (tc);
1168 		node->tc = tc;
1169 	}
1170 
1171 	*t = node->tc;
1172 	ctx->prior_tcs = g_slist_prepend (ctx->prior_tcs, node);
1173 
1174 	return FALSE;
1175 }
1176 
1177 gboolean
ORBit_decode_CORBA_TypeCode(CORBA_TypeCode * tc,GIOPRecvBuffer * buf)1178 ORBit_decode_CORBA_TypeCode (CORBA_TypeCode *tc,
1179 			     GIOPRecvBuffer *buf)
1180 {
1181 	GSList         *l;
1182 	gboolean        retval;
1183 	TCDecodeContext ctx;
1184 
1185 	ctx.current_idx = 0;
1186 	ctx.prior_tcs = NULL;
1187 
1188 	retval = tc_dec (tc, buf, &ctx);
1189 
1190 	for (l = ctx.prior_tcs; l; l = l->next)
1191 		g_free (l->data);
1192 
1193 	g_slist_free (ctx.prior_tcs);
1194 
1195 	return retval;
1196 }
1197 
1198 /* Encode a typecode to a codec, possibly recursively */
1199 static void
tc_enc(CORBA_TypeCode tc,GIOPSendBuffer * buf,TCEncodeContext * ctx)1200 tc_enc (CORBA_TypeCode tc, GIOPSendBuffer *buf, TCEncodeContext *ctx)
1201 {
1202 	TCRecursionNode     *node;
1203 	const TkInfo        *info;
1204 	GSList              *l;
1205 	CORBA_unsigned_long  len, tmp;
1206 	guchar              *marker;
1207 	gint8                endianness;
1208 
1209 	g_assert (CLAMP (0, tc->kind, CORBA_tk_last) == tc->kind);
1210 
1211 	giop_send_buffer_align (buf, 4);
1212 
1213 	info = &tk_info [tc->kind];
1214 
1215 	/* For base types it is better to marshal just the tc->kind */
1216 	if (info->type != TK_EMPTY) {
1217 
1218 		for (l = ctx->prior_tcs; l; l = l->next) {
1219 			node = l->data;
1220 
1221 			if (node->tc == tc) {
1222 				tmp = CORBA_tk_recursive;
1223 				giop_send_buffer_append_aligned (buf, &tmp, 4);
1224 				len = node->index - buf->msg.header.message_size - 4;
1225 				giop_send_buffer_append_aligned (buf, &len, 4);
1226 				return;
1227 			}
1228 		}
1229 
1230 		/* only keep track of larger, more complex typecodes */
1231 		node = g_new (TCRecursionNode, 1);
1232 		node->tc = tc;
1233 		node->index = buf->msg.header.message_size;
1234 		ctx->prior_tcs = g_slist_prepend (ctx->prior_tcs, node);
1235 	}
1236 
1237 	giop_send_buffer_append (buf, &tc->kind, sizeof (tc->kind));
1238 
1239 	switch (info->type) {
1240 	case TK_EMPTY:
1241 		break;
1242 	case TK_COMPLEX:
1243 		marker = giop_send_buffer_append_aligned (buf, NULL, 4);
1244 
1245 		tmp = buf->msg.header.message_size;
1246 		endianness = GIOP_FLAG_ENDIANNESS;
1247 
1248 		giop_send_buffer_append (buf, &endianness, 1);
1249 
1250 		info->encoder (tc, buf, ctx);
1251 
1252 		len = buf->msg.header.message_size - tmp;
1253 
1254 		memcpy (marker, &len, 4);
1255 		break;
1256 	case TK_SIMPLE:
1257 		info->encoder (tc, buf, ctx);
1258 		break;
1259 	}
1260 }
1261 
1262 void
ORBit_encode_CORBA_TypeCode(CORBA_TypeCode tc,GIOPSendBuffer * buf)1263 ORBit_encode_CORBA_TypeCode (CORBA_TypeCode  tc,
1264 			     GIOPSendBuffer *buf)
1265 {
1266 	GSList         *l;
1267 	TCEncodeContext ctx;
1268 
1269 	ctx.start_idx = buf->msg.header.message_size;
1270 	ctx.prior_tcs = NULL;
1271 
1272 	tc_enc (tc, buf, &ctx);
1273 
1274 	for (l = ctx.prior_tcs; l; l = l->next)
1275 		g_free (l->data);
1276 
1277 	g_slist_free (ctx.prior_tcs);
1278 }
1279