#include "orbit.h" #include "orbit_typecode.h" #include "cdr.h" #include "corba_typecode_type.h" #include #include "../IIOP/iiop-endianP.h" #if 0 #define CORBA_Object_release(x, y) ({ g_message(__FILE__ ":%d Releasing object %#x from %d", __LINE__, \ x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_release(x, y); }) #define CORBA_Object_duplicate(x, y) ({ g_message(__FILE__ ":%d Duping object %#x from %d", __LINE__, \ x, ORBIT_ROOT_OBJECT(x)->refs); CORBA_Object_duplicate(x, y); }) #endif typedef struct{ CORBA_TypeCode tc; guint index; }TCRecursionNode; typedef struct{ GSList* prior_tcs; /* Could be a hash table by typecode */ guint current_idx; /* The "top-level" index of the start of the current codec */ }TCEncodeContext; typedef struct{ GSList* prior_tcs; /* Could be a hash table by offset */ guint current_idx; }TCDecodeContext; static void tc_enc(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec(CORBA_TypeCode* t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); static void tc_enc_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); static void tc_dec_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); typedef void (*CORBA_TypeCodeEncoder)(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx); typedef void (*CORBA_TypeCodeDecoder)(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx); typedef enum{ TK_EMPTY, TK_SIMPLE, TK_COMPLEX } TkType; typedef struct{ TkType type; CORBA_TypeCodeEncoder encoder; CORBA_TypeCodeDecoder decoder; } TkInfo; static const TkInfo tk_info[CORBA_tk_last]={ {TK_EMPTY, NULL, NULL}, /* tk_null */ {TK_EMPTY, NULL, NULL}, /* tk_void */ {TK_EMPTY, NULL, NULL}, /* tk_short */ {TK_EMPTY, NULL, NULL}, /* tk_long */ {TK_EMPTY, NULL, NULL}, /* tk_ushort */ {TK_EMPTY, NULL, NULL}, /* tk_ulong */ {TK_EMPTY, NULL, NULL}, /* tk_float */ {TK_EMPTY, NULL, NULL}, /* tk_double */ {TK_EMPTY, NULL, NULL}, /* tk_boolean */ {TK_EMPTY, NULL, NULL}, /* tk_char */ {TK_EMPTY, NULL, NULL}, /* tk_octet */ {TK_EMPTY, NULL, NULL}, /* tk_any */ {TK_EMPTY, NULL, NULL}, /* tk_TypeCode */ {TK_EMPTY, NULL, NULL}, /* tk_Principal */ {TK_COMPLEX, tc_enc_tk_objref, tc_dec_tk_objref}, /* tk_objref */ {TK_COMPLEX, tc_enc_tk_struct, tc_dec_tk_struct}, /* tk_struct */ {TK_COMPLEX, tc_enc_tk_union, tc_dec_tk_union}, /* tk_union */ {TK_COMPLEX, tc_enc_tk_enum, tc_dec_tk_enum}, /* tk_enum */ {TK_SIMPLE, tc_enc_tk_string, tc_dec_tk_string}, /* tk_string */ {TK_COMPLEX, tc_enc_tk_sequence, tc_dec_tk_sequence}, /* tk_sequence */ {TK_COMPLEX, tc_enc_tk_array, tc_dec_tk_array}, /* tk_array */ {TK_COMPLEX, tc_enc_tk_alias, tc_dec_tk_alias}, /* tk_alias */ {TK_COMPLEX, tc_enc_tk_except, tc_dec_tk_except}, /* tk_except */ {TK_EMPTY, NULL, NULL}, /* tk_longlong */ {TK_EMPTY, NULL, NULL}, /* tk_ulonglong */ {TK_EMPTY, NULL, NULL}, /* tk_longdouble */ {TK_EMPTY, NULL, NULL}, /* tk_wchar */ {TK_SIMPLE, tc_enc_tk_wstring, tc_dec_tk_wstring}, /* tk_wstring */ {TK_SIMPLE, tc_enc_tk_fixed, tc_dec_tk_fixed} /* tk_fixed */ }; void ORBit_encode_CORBA_TypeCode(CORBA_TypeCode t, GIOPSendBuffer* buf) { CDR_Codec codec_d; CDR_Codec* codec = &codec_d; TCEncodeContext ctx; GSList* l; char codecbuf[2048]; CDR_codec_init_static(codec); codec->wptr = 0; codec->buffer = codecbuf; codec->release_buffer = FALSE; codec->buf_len = 2048; codec->data_endian=FLAG_ENDIANNESS; ctx.current_idx=0; ctx.prior_tcs=NULL; tc_enc(t, codec, &ctx); for(l=ctx.prior_tcs;l;l=l->next) g_free(l->data); g_slist_free(ctx.prior_tcs); giop_send_buffer_append_mem_indirect(buf, codec->buffer, codec->wptr); } void ORBit_decode_CORBA_TypeCode(CORBA_TypeCode* t, GIOPRecvBuffer* buf) { CDR_Codec codec_d; CDR_Codec* codec = &codec_d; TCDecodeContext ctx; GSList* l; CDR_codec_init_static(codec); codec->buffer=buf->cur; codec->release_buffer=CORBA_FALSE; codec->readonly=CORBA_TRUE; codec->buf_len = /* hope this is correct */ GIOP_MESSAGE_BUFFER(buf)->message_header.message_size + (((guchar *)buf->message_body) - ((guchar *)buf->cur)); codec->data_endian=GIOP_MESSAGE_BUFFER(buf)->message_header.flags & 1; ctx.current_idx=0; ctx.prior_tcs=NULL; tc_dec(t, codec, &ctx); for(l=ctx.prior_tcs;l;l=l->next) g_free(l->data); g_slist_free(ctx.prior_tcs); ((guchar *)buf->cur) += codec->rptr; } /* Encode a typecode to a codec, possibly recursively */ static void tc_enc(CORBA_TypeCode tc, CDR_Codec* codec, TCEncodeContext* ctx) { TCRecursionNode* node; const TkInfo* info; GSList* l; char codecbuf[2048]; CDR_Codec encaps_d; CDR_Codec* encaps = &encaps_d; g_assert(tc->kind < CORBA_tk_last); for(l=ctx->prior_tcs;l;l=l->next){ TCRecursionNode* node=l->data; /* CORBA_CORBA_TypeCode_equal might save space, but is slow.. */ if(node->tc==tc){ CDR_put_ulong(codec, CORBA_tk_recursive); CDR_put_long(codec, node->index -ctx->current_idx -codec->wptr); return; } } /* All right, this isn't a previously met type. So record it. */ node=g_new(TCRecursionNode, 1); node->tc=tc; node->index=ctx->current_idx+codec->wptr; ctx->prior_tcs=g_slist_prepend(ctx->prior_tcs, node); CDR_put_ulong(codec, tc->kind); info=&tk_info[tc->kind]; switch(info->type){ guint tmp_index; case TK_EMPTY: break; case TK_COMPLEX: tmp_index=ctx->current_idx; ctx->current_idx+=codec->wptr+4; /* +4 for the length */ CDR_codec_init_static(encaps); encaps->wptr = 0; encaps->buffer = codecbuf; encaps->release_buffer = FALSE; encaps->buf_len = 2048; encaps->data_endian=FLAG_ENDIANNESS; CDR_put_octet(encaps, FLAG_ENDIANNESS); (info->encoder)(tc, encaps, ctx); CDR_put_ulong(codec, encaps->wptr); /* Now this is a time hog */ CDR_put_octets(codec, encaps->buffer, encaps->wptr); ctx->current_idx=tmp_index; break; case TK_SIMPLE: (info->encoder)(tc, codec, ctx); } } static void ORBit_TypeCode_release(gpointer obj, CORBA_Environment *ev) { /* we will initialize the TC_ constants with a negative refcount */ if(ORBIT_ROOT_OBJECT(obj)->refs >= 0) { ORBIT_ROOT_OBJECT_UNREF(obj); if(ORBIT_ROOT_OBJECT(obj)->refs <= 0) { CORBA_TypeCode tc = obj; int i; g_free(tc->name); g_free(tc->repo_id); for(i = 0; i < tc->sub_parts; i++) { if(tc->subnames) g_free(tc->subnames[i]); if(tc->subtypes) CORBA_Object_release((CORBA_Object)tc->subtypes[i], ev); if(tc->sublabels) CORBA_any__free(&tc->sublabels[i], NULL, TRUE); } g_free(tc->subnames); g_free(tc->subtypes); g_free(tc->sublabels); if(tc->discriminator) CORBA_Object_release((CORBA_Object)tc->discriminator, ev); g_free(obj); } } } const ORBit_RootObject_Interface ORBit_TypeCode_epv = { &ORBit_TypeCode_release }; static void tc_dec(CORBA_TypeCode* t, CDR_Codec* c, TCDecodeContext* ctx) { CORBA_TCKind kind; CORBA_TypeCode tc; const TkInfo* info; TCRecursionNode* node; CDR_Codec encaps_d; CDR_Codec* encaps = &encaps_d; CDR_get_ulong(c, &kind); if(kind==CORBA_tk_recursive){ CORBA_long offset; GSList* l; /* CDR_get_long(c, &offset); */ CDR_get_ulong(c, (CORBA_unsigned_long*)&offset); for(l=ctx->prior_tcs;l;l=l->next){ node=l->data; if(node->index==ctx->current_idx+offset){ *t=node->tc; return; } } ORBit_Trace(TraceMod_ORB, TraceLevel_Error, "tc_dec: Invalid CORBA_TypeCode recursion offset " "in input buffer\n"); g_assert_not_reached(); } ORBit_Trace(TraceMod_TC, TraceLevel_Debug, "codec->host_endian: %d, codec->data_endian: %d\n", c->host_endian, c->data_endian); ORBit_Trace(TraceMod_TC, TraceLevel_Debug, "kind: %d, CORBA_tk_last: %d\n", kind, CORBA_tk_last); g_assert(kindindex=ctx->current_idx+c->rptr-4; /* -4 for the TCKind */ info=&tk_info[kind]; tc=g_new0(struct CORBA_TypeCode_struct, 1); /* Passing in NULL for CORBA_Environment is patently dangerous. */ ORBit_pseudo_object_init((ORBit_PseudoObject)tc, ORBIT_PSEUDO_TYPECODE, NULL); ORBit_RootObject_set_interface((ORBit_RootObject)tc, (ORBit_RootObject_Interface *)&ORBit_TypeCode_epv, NULL); tc->kind=kind; switch(info->type){ guint tmp_index; CORBA_octet o; case TK_EMPTY: break; case TK_COMPLEX: tmp_index=ctx->current_idx; CDR_codec_init_static(encaps); CDR_get_ulong(c, &encaps->buf_len); ctx->current_idx+=c->rptr; encaps->buffer=&c->buffer[c->rptr]; encaps->release_buffer=CORBA_FALSE; CDR_get_octet(encaps, &o); encaps->data_endian=o; (info->decoder)(tc, encaps, ctx); c->rptr += encaps->buf_len; ctx->current_idx=tmp_index; break; case TK_SIMPLE: (info->decoder)(tc, c, ctx); break; } node->tc=tc; ctx->prior_tcs=g_slist_prepend(ctx->prior_tcs, node); *t=tc; } static void tc_enc_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); } static void tc_dec_tk_objref(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { CDR_get_string(c, &t->repo_id); CDR_get_string(c, &t->name); } static void tc_enc_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { tc_enc(*t->subtypes, c, ctx); CDR_put_ulong(c, t->length); } static void tc_dec_tk_sequence(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { tc_dec(t->subtypes, c, ctx); CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL); CDR_get_ulong(c, &t->length); } static void tc_enc_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CDR_put_ulong(c, t->length); } static void tc_dec_tk_string(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { CDR_get_ulong(c, &t->length); } static void tc_enc_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CORBA_unsigned_long i; CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); CDR_put_ulong(c, t->sub_parts); for(i=0;isub_parts;i++){ CDR_put_string(c, t->subnames[i]); tc_enc(t->subtypes[i], c, ctx); } } static void tc_dec_tk_struct(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { CORBA_unsigned_long i; CDR_get_string(c, &t->repo_id); CDR_get_string(c, &t->name); CDR_get_ulong(c, &t->sub_parts); t->subnames=g_new(gchar*, t->sub_parts); t->subtypes=g_new(CORBA_TypeCode, t->sub_parts); for(i=0;isub_parts;i++){ CDR_get_string(c, &t->subnames[i]); tc_dec(&t->subtypes[i], c, ctx); CORBA_Object_duplicate((CORBA_Object)t->subtypes[i], NULL); } } static void tc_enc_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CORBA_unsigned_long i; CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); tc_enc(t->discriminator, c, ctx); CDR_put_long(c, t->default_index); CDR_put_ulong(c, t->sub_parts); i=t->sub_parts; /* Thank goodness the discriminator types are rather limited, we can do the marshalling inline.. */ #define MEMBER_LOOPER(putname, typename, tkname) \ case CORBA_tk_##tkname: \ for(i=0;isub_parts;i++){ \ CDR_put_##putname(c, *(CORBA_##typename*) \ (t->sublabels[i]._value)); \ CDR_put_string(c, t->subnames[i]); \ tc_enc(t->subtypes[i], c, ctx); \ } \ break switch(t->discriminator->kind){ MEMBER_LOOPER(long, long, long); case CORBA_tk_enum: /* fall through */ MEMBER_LOOPER(ulong, unsigned_long, ulong); MEMBER_LOOPER(boolean, boolean, boolean); MEMBER_LOOPER(char, char, char); MEMBER_LOOPER(short, short, short); MEMBER_LOOPER(ushort, unsigned_short, ushort); MEMBER_LOOPER(long_long, long_long, longlong); MEMBER_LOOPER(ulong_long, unsigned_long_long, ulonglong); /* MEMBER_LOOPER(wchar, wchar, wchar); */ default: ORBit_Trace(TraceMod_ORB, TraceLevel_Error, "tc_enc_tk_union: Illegal union discriminator " "type %s\n", t->discriminator->name); } } static void tc_dec_tk_union(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { g_assert(!"Not yet implemented."); } static void tc_enc_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CORBA_unsigned_long i; CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); CDR_put_ulong(c, t->sub_parts); for(i=0;isub_parts;i++) CDR_put_string(c, t->subnames[i]); } static void tc_dec_tk_enum(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { CORBA_unsigned_long i; CDR_get_string(c, &t->repo_id); CDR_get_string(c, &t->name); CDR_get_ulong(c, &t->sub_parts); t->subnames=g_new(gchar*, t->sub_parts); for(i=0;isub_parts;i++) CDR_get_string(c, &t->subnames[i]); } static void tc_enc_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); tc_enc(*t->subtypes, c, ctx); } static void tc_dec_tk_alias(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { CDR_get_string(c, &t->repo_id); CDR_get_string(c, &t->name); tc_dec(t->subtypes, c, ctx); CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL); } static void tc_enc_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { gulong i; CDR_put_string(c, t->repo_id); CDR_put_string(c, t->name); CDR_put_ulong(c, t->sub_parts); for(i=0;ilength;i++){ CDR_put_string(c, t->subnames[i]); tc_enc(t->subtypes[i], c, ctx); } } static void tc_dec_tk_except(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { gulong i; CDR_get_string(c, &t->repo_id); CDR_get_string(c, &t->name); CDR_get_ulong(c, &t->sub_parts); t->subtypes=g_new(CORBA_TypeCode, t->sub_parts); t->subnames=g_new(gchar*, t->sub_parts); for(i=0;ilength;i++){ CDR_get_string(c, &t->subnames[i]); tc_dec(&t->subtypes[i], c, ctx); CORBA_Object_duplicate((CORBA_Object)t->subtypes[i], NULL); } } static void tc_enc_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { tc_enc(*t->subtypes, c, ctx); CDR_put_ulong(c, t->length); } static void tc_dec_tk_array(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { tc_dec(t->subtypes, c, ctx); CORBA_Object_duplicate((CORBA_Object)t->subtypes[0], NULL); CDR_get_ulong(c, &t->length); } static void tc_enc_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { g_assert(!"Not yet implemented."); } static void tc_dec_tk_wstring(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { g_assert(!"Not yet implemented."); } static void tc_enc_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCEncodeContext* ctx) { g_assert(!"Not yet implemented."); } static void tc_dec_tk_fixed(CORBA_TypeCode t, CDR_Codec* c, TCDecodeContext* ctx) { g_assert(!"Not yet implemented."); }