aboutsummaryrefslogtreecommitdiffstats
path: root/lib/orber/src/cdr_decode.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/orber/src/cdr_decode.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/orber/src/cdr_decode.erl')
-rw-r--r--lib/orber/src/cdr_decode.erl1487
1 files changed, 1487 insertions, 0 deletions
diff --git a/lib/orber/src/cdr_decode.erl b/lib/orber/src/cdr_decode.erl
new file mode 100644
index 0000000000..9d30098940
--- /dev/null
+++ b/lib/orber/src/cdr_decode.erl
@@ -0,0 +1,1487 @@
+%%--------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%-----------------------------------------------------------------
+%% File: cdr_decode.erl
+%%
+%% Description:
+%% This file contains all decoding functions for the CDR
+%% format.
+%%
+%%-----------------------------------------------------------------
+-module(cdr_decode).
+
+-include_lib("orber/src/orber_iiop.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+-include_lib("orber/include/corba.hrl").
+
+-include_lib("orber/src/ifr_objects.hrl").
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([dec_giop_message_header/1, dec_reply_header/4,
+ dec_reply_body/6, dec_locate_reply_header/4,
+ dec_locate_reply_body/5, dec_message_header/3, dec_request_body/6,
+ dec_octet_sequence_bin/6, dec_message/2, peek_request_id/2]).
+
+%%-----------------------------------------------------------------
+%% Functions which only are exported for the testcases.
+%%-----------------------------------------------------------------
+-export([dec_type/5, dec_byte_order/1, dec_system_exception/4, dec_user_exception/4,
+ dec_byte_order_list/1]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Macros
+%%-----------------------------------------------------------------
+-define(DEBUG_LEVEL, 9).
+
+-define(ODD(N), (N rem 2) == 1).
+
+%%-----------------------------------------------------------------
+%% Func: dec_message/3
+%% Args:
+%% TypeCodes - is the type_codes of the return value and out parameters
+%% when one decodes a reply.
+%% Bytes - is the the message as a byte sequence.
+%% Returns:
+%% A tupple which contains the decoded message,
+%% {ok, Header, Parameters, TypeCodes}.
+%%-----------------------------------------------------------------
+dec_message(TypeCodes, Bytes) ->
+ Message = dec_giop_message_header(Bytes),
+ case Message#giop_message.message_type of
+ ?GIOP_MSG_REQUEST ->
+ {Version, ReqHdr, Rest, Len, ByteOrder} =
+ dec_request_header(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order, Bytes),
+ dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Bytes);
+ ?GIOP_MSG_REPLY ->
+ dec_reply(Message#giop_message.giop_version,
+ TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_CANCEL_REQUEST ->
+ dec_cancel_request(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_LOCATE_REQUEST ->
+ dec_locate_request(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_LOCATE_REPLY ->
+ dec_locate_reply(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_CLOSE_CONNECTION ->
+ 'close_connection';
+ ?GIOP_MSG_MESSAGE_ERROR ->
+ 'message_error';
+ ?GIOP_MSG_FRAGMENT ->
+ dec_fragment_header(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order, Bytes)
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: dec_giop_message_header/1
+%% Args:
+%% Bytes - is the the message as a byte sequence.
+%% Returns:
+%% A giop_message record.
+%%-----------------------------------------------------------------
+%% Magic|Version|BO| Type | Size | Body
+dec_giop_message_header(<<"GIOP",1:8,0:8,1:8,MessType:8,
+ MessSize:32/little-unsigned-integer,Message/binary>>) ->
+ #giop_message{magic = "GIOP", giop_version = {1,0},
+ byte_order = little, message_type = MessType,
+ message_size = MessSize, message = Message};
+dec_giop_message_header(<<"GIOP",1:8,0:8,0:8,MessType:8,
+ MessSize:32/big-unsigned-integer,Message/binary>>) ->
+ #giop_message{magic = "GIOP", giop_version = {1,0},
+ byte_order = big, message_type = MessType,
+ message_size = MessSize, message = Message};
+dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
+ MessSize:32/little-unsigned-integer,Message/binary>>) when
+ ((Flags band 16#01) == 16#01) ->
+ #giop_message{magic = "GIOP", giop_version = {1,Minor},
+ byte_order = little, fragments = ((Flags band 16#02) == 16#02),
+ message_type = MessType, message_size = MessSize, message = Message};
+dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
+ MessSize:32/big-unsigned-integer,Message/binary>>) ->
+ #giop_message{magic = "GIOP", giop_version = {1,Minor},
+ byte_order = big, fragments = ((Flags band 16#02) == 16#02),
+ message_type = MessType, message_size = MessSize, message = Message};
+dec_giop_message_header(<<Hdr:?GIOP_HEADER_SIZE/binary, _Body/binary>>) ->
+ orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
+ "Orber cannot decode the GIOP-header.", [?LINE, Hdr], ?DEBUG_LEVEL),
+ exit(message_error);
+dec_giop_message_header(Other) ->
+ orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
+ "Orber cannot decode the GIOP-header.", [?LINE, Other], ?DEBUG_LEVEL),
+ exit(message_error).
+
+
+peek_request_id(big, <<ReqId:32/big-unsigned-integer,_/binary>>) ->
+ ReqId;
+peek_request_id(little, <<ReqId:32/little-unsigned-integer,_/binary>>) ->
+ ReqId.
+
+%%-----------------------------------------------------------------
+%% Func: dec_message_header/2
+%% Args:
+%% Header - #giop_message{}
+%% Bytes - is the the message body as a byte sequence.
+%% Returns:
+%%-----------------------------------------------------------------
+dec_message_header(TypeCodes, Message, Bytes) ->
+ case Message#giop_message.message_type of
+ ?GIOP_MSG_REQUEST ->
+ dec_request_header(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order, Bytes);
+ ?GIOP_MSG_REPLY ->
+ dec_reply(Message#giop_message.giop_version,
+ TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_CANCEL_REQUEST ->
+ dec_cancel_request(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_LOCATE_REQUEST ->
+ dec_locate_request(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_LOCATE_REPLY ->
+ dec_locate_reply(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order);
+ ?GIOP_MSG_CLOSE_CONNECTION ->
+ 'close_connection';
+ ?GIOP_MSG_MESSAGE_ERROR ->
+ 'message_error';
+ ?GIOP_MSG_FRAGMENT ->
+ dec_fragment_header(Message#giop_message.giop_version,
+ Message#giop_message.message, ?GIOP_HEADER_SIZE,
+ Message#giop_message.byte_order, Bytes)
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_byte_order/1
+%% Args:
+%% The message as a byte sequence.
+%% Returns:
+%% A tuple {Endianess, Rest} where Endianess is big or little.
+%% Rest is the remaining message byte sequence.
+%%-----------------------------------------------------------------
+dec_byte_order(<<0:8,T/binary>>) ->
+ {big, T};
+dec_byte_order(<<1:8,T/binary>>) ->
+ {little, T}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_byte_order_list/1
+%% Args:
+%% The message as a byte sequence.
+%% Returns:
+%% A tuple {Endianess, Rest} where Endianess is big or little.
+%% Rest is the remaining message byte sequence.
+%%-----------------------------------------------------------------
+dec_byte_order_list([0|T]) ->
+ {big, T};
+dec_byte_order_list([1|T]) ->
+ {little, T}.
+
+%%-----------------------------------------------------------------
+%% Func : dec_response_flags
+%% Args :
+%% Returns : boolean
+%%-----------------------------------------------------------------
+%% FIX ME!! Not correct flag handling.
+dec_response_flags(_Version, <<0:8, Rest/binary>>, Len) ->
+ {false, Rest, Len+1};
+dec_response_flags(_Version, <<1:8, Rest/binary>>, Len) ->
+ {true_oneway, Rest, Len+1};
+dec_response_flags(_Version, <<3:8, Rest/binary>>, Len) ->
+ {true, Rest, Len+1};
+dec_response_flags(_Version, <<X:8, Rest/binary>>, Len) ->
+ %% Not only the Response flag is set, test which.
+ if
+ %% Since the 6 most significant bits are unused we'll accept this for now.
+ ((X band 16#03) == 16#03) ->
+ {true, Rest, Len+1};
+ ((X band 16#01) == 16#01) ->
+ {true_oneway, Rest, Len+1};
+ true ->
+ {false, Rest, Len+1}
+ end.
+
+%%-----------------------------------------------------------------
+%% Func : dec_target_addr
+%% Args : Octet
+%% Returns : boolean
+%%-----------------------------------------------------------------
+dec_target_addr(Version, Message, Len, ByteOrder, RequestId, Type) ->
+ case dec_type(?TARGETADDRESS, Version, Message, Len, ByteOrder, [], 0) of
+ {#'GIOP_TargetAddress'{label = ?GIOP_KeyAddr, value = KeyAddr}, Rest3, Len3, C} ->
+ {dec_target_key(KeyAddr, RequestId, Version, Type), Rest3, Len3, C};
+ {#'GIOP_TargetAddress'{label = ?GIOP_ProfileAddr,
+ value = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
+ profile_data=PA}},
+ Rest3, Len3, C} ->
+ {dec_target_key(PA, RequestId, Version, Type), Rest3, Len3, C};
+ {#'GIOP_TargetAddress'{label = ?GIOP_ReferenceAddr,
+ value = #'GIOP_IORAddressingInfo'{
+ selected_profile_index = _PI,
+ ior = IOR}}, Rest3, Len3, C} ->
+ {dec_target_key(iop_ior:get_objkey(IOR), RequestId, Version, Type),
+ Rest3, Len3, C};
+ Other ->
+ orber:dbg("[~p] cdr_decode:dec_target_addr(~p);~n"
+ "Unsupported TargetAddress.", [?LINE, Other], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 12), completion_status=?COMPLETED_MAYBE})
+ end.
+
+%%-----------------------------------------------------------------
+%% Func : dec_target_key
+%% Args : Octet
+%% Returns : boolean
+%%-----------------------------------------------------------------
+dec_target_key(Key, RequestId, Version, Type) ->
+ %% The Type argument is used as an identifier of which operation it is.
+ %% We need it to be able to tell the difference if it's, for example,
+ %% a request or locate-request.
+ case corba:string_to_objkey_local(Key) of
+ {location_forward, Object} ->
+ throw({Type, Object, RequestId, Version, Key});
+ ObjRef ->
+ ObjRef
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: dec_request_header/3
+%% Args:
+%% Message - The message
+%% Len0 - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%%-----------------------------------------------------------------
+dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
+ {Request_id, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
+ ByteOrder, [], 0),
+ {ResponseFlags, Rest2, Len2} = dec_response_flags(Version, Rest1, Len1),
+ {_, Rest2b, Len2b, _} = dec_type({'tk_array', 'tk_octet', 3}, Version, Rest2, Len2, ByteOrder, [], 0),
+ {Object_key, Rest3, Len3, _} = dec_target_addr(Version, Rest2b, Len2b, ByteOrder, Request_id,
+ 'location_forward'),
+ {Operation, Rest4, Len4, _} = dec_type({'tk_string', 0}, Version, Rest3, Len3, ByteOrder, [], 0),
+ {Context, Rest5, Len5} = dec_service_context(Version, Rest4, Len4, ByteOrder),
+ {Version, #request_header{service_context=Context,
+ request_id=Request_id,
+ response_expected=ResponseFlags,
+ object_key=Object_key,
+ operation=list_to_atom(Operation),
+ requesting_principal=""}, Rest5, Len5, ByteOrder};
+dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) ->
+ {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
+ {Request_id, Rest2, Len2, _} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder, [], 0),
+ {Response_expected, Rest3, Len3, _} = dec_type('tk_boolean', Version, Rest2, Len2,
+ ByteOrder, [], 0),
+ {ObjKey, Rest4, Len4, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest3,
+ Len3, ByteOrder, [], 0),
+ Object_key = dec_target_key(ObjKey, Request_id, Version, 'location_forward'),
+ {Operation, Rest5, Len5, _} = dec_type({'tk_string', 0}, Version, Rest4, Len4, ByteOrder, [], 0),
+ {Principal, Rest, Len, _} = dec_type({'tk_string', 0}, Version, Rest5,Len5, ByteOrder, [], 0),
+ {Version, #request_header{service_context=Context,
+ request_id=Request_id,
+ response_expected=Response_expected,
+ object_key=Object_key,
+ operation=list_to_atom(Operation),
+ requesting_principal=Principal}, Rest, Len, ByteOrder}.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_service_context/4
+%% Args: Version - e.g. 1.2
+%% Message - The message
+%% Len - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%%-----------------------------------------------------------------
+dec_service_context(Version, Message, Len, ByteOrder) ->
+ {Context, Rest, Len1} = dec_type(?IOP_SERVICECONTEXT, Version, Message,
+ Len, ByteOrder),
+ {dec_used_contexts(Version, Context, []), Rest, Len1}.
+
+dec_used_contexts(_Version, [], Ctxs) ->
+ Ctxs;
+dec_used_contexts({1,0}, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets}|T], Ctxs) ->
+ %% Not supported by 1.0, drop it.
+ dec_used_contexts({1,0}, T, Ctxs);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {CodeCtx, _, _} = dec_type(?CONV_FRAME_CODESETCONTEXT, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
+ context_data = CodeCtx}|Ctxs]);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {BiDirCtx, _, _} = dec_type(?IIOP_BIDIRIIOPSERVICECONTEXT, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
+ context_data = BiDirCtx}|Ctxs]);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {Ctx, _, _} = dec_type(?FT_FTRequestServiceContext, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
+ context_data = Ctx}|Ctxs]);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {Ctx, _, _} = dec_type(?FT_FTGroupVersionServiceContext, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
+ context_data = Ctx}|Ctxs]);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {Ctx, _, _} = dec_type(?CSI_SASContextBody, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
+ context_data = Ctx}|Ctxs]);
+dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = Bytes}|T], Ctxs) ->
+ {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
+ {Ctx, _, _} = dec_type(?ORBER_GENERIC_CTX, Version,
+ Rest, 1, ByteOrder),
+ dec_used_contexts(Version, T,
+ [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
+ context_data = binary_to_term(list_to_binary(Ctx))}|Ctxs]);
+dec_used_contexts(Version, [H|T], Ctxs) ->
+ dec_used_contexts(Version, T, [H|Ctxs]).
+
+%%-----------------------------------------------------------------
+%% Func: dec_request_body
+%% Args: Version - e.g. 1.2
+%% Returns:
+%%-----------------------------------------------------------------
+dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Buffer) ->
+ {Parameters, TypeCodes, _} =
+ dec_request_body(Version, ReqHdr#request_header.object_key,
+ ReqHdr#request_header.operation,
+ Rest, Len, ByteOrder, Buffer, Len),
+ {Version, ReqHdr, Parameters, TypeCodes}.
+
+dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter)
+ when Version == {1,2} ->
+ case orber_typedefs:get_op_def(Object_key, Operation) of
+ {RetType, [], OutParameters} ->
+ {[], {RetType, [], OutParameters}, Len};
+ {RetType, InParameters, OutParameters} ->
+ {Rest, Len1, NewC} = dec_align(Body, Len, 8, Counter),
+ {Parameters, Len2} = dec_parameters(Version, InParameters, Rest, Len1,
+ ByteOrder, Buffer, NewC),
+ {Parameters, {RetType, InParameters, OutParameters}, Len2}
+ end;
+dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter) ->
+ {RetType, InParameters, OutParameters} =
+ orber_typedefs:get_op_def(Object_key, Operation),
+ {Parameters, Len1} = dec_parameters(Version, InParameters, Body, Len, ByteOrder, Buffer, Counter),
+ {Parameters, {RetType, InParameters, OutParameters}, Len1}.
+
+dec_parameters(_, [], _, Len, _, _, _) ->
+ {[], Len};
+dec_parameters(Version, [P1 |InParList], Body, Len, ByteOrder, Buffer, Counter) ->
+ {Object, Rest, Len1, NewCounter} = dec_type(P1, Version, Body, Len, ByteOrder, Buffer, Counter),
+ {List, Len2} = dec_parameters(Version, InParList, Rest, Len1, ByteOrder, Buffer, NewCounter),
+ {[Object | List], Len2}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_reply/5
+%% Args:
+%% Message - The message
+%% Len0 - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%% A tuple {ReplyHeader, Result} where ReplyHeader is a
+%% reply_header record and Result the decode result.
+%%-----------------------------------------------------------------
+dec_reply(Version, TypeCodes, Message, Len0, ByteOrder) ->
+ {ReplyHeader, Rest, Len} = dec_reply_header(Version, Message, Len0, ByteOrder),
+ {Result, Par} =
+ case ReplyHeader#reply_header.reply_status of
+ 'no_exception' ->
+ {R, P, _} = dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Message),
+ {R, P};
+ 'system_exception' ->
+ {R, _} = dec_system_exception(Version, Rest, Len, ByteOrder),
+ {R, []};
+ 'user_exception' ->
+ {R, _} = dec_user_exception(Version, Rest, Len, ByteOrder),
+ {R, []};
+ 'location_forward' ->
+ {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
+ Rest, Len, ByteOrder, Message),
+ {R, []};
+ %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
+ %% now.
+ 'location_forward_perm' ->
+ {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
+ Rest, Len, ByteOrder, Message),
+ {R, []};
+ 'needs_addressing_mode' ->
+ {R, _, _} = dec_reply_body(Version, {'tk_short', [],[]},
+ Rest, Len, ByteOrder, Message),
+ {R, []}
+ end,
+ {ReplyHeader, Result, Par}.
+
+
+%% ## NEW IIOP 1.2 ##
+dec_reply_header(Version, Message, Len0, ByteOrder) when Version == {1,2} ->
+ {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder),
+ {ReplyStatus, Rest2, Len2} = dec_reply_status(Version, Rest1, Len1, ByteOrder),
+ {Context, Rest, Len3} = dec_service_context(Version, Rest2, Len2, ByteOrder),
+ {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
+ Rest, Len3};
+
+dec_reply_header(Version, Message, Len0, ByteOrder) ->
+ {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
+ {Request_id, Rest2, Len2} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder),
+ {ReplyStatus, Rest, Len3} = dec_reply_status(Version, Rest2, Len2, ByteOrder),
+ {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
+ Rest, Len3}.
+
+dec_reply_status(Version, Status, Len, ByteOrder) ->
+ {L, Rest, Len1}= dec_type('tk_ulong', Version, Status, Len, ByteOrder),
+ {dec_giop_reply_status_type(L), Rest, Len1}.
+
+dec_reply_body(_, {'tk_void', _, []}, <<>>, Len, _, _) ->
+ %% This case is mainly to be able to avoid removing non-existent alignment for
+ %% IIOP-1.2 messages if the body should be empty, i.e., void return value and
+ %% no out parameters.
+ {ok, [], Len};
+dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len,
+ ByteOrder, Bytes) when Version == {1,2} ->
+ {Rest, Len1, Counter} = dec_align(Body, Len, 8, Len),
+ {Result, Rest2, Len2, C} = dec_type(RetType, Version, Rest, Len1, ByteOrder, Bytes, Counter),
+ {Par, Len3} = dec_parameters(Version, OutParameters, Rest2, Len2, ByteOrder, Bytes, C),
+ {Result, Par, Len3};
+dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len, ByteOrder, Bytes) ->
+ {Result, Rest, Len1, C} = dec_type(RetType, Version, Body, Len, ByteOrder, Bytes, Len),
+ {Par, Len2} = dec_parameters(Version, OutParameters, Rest, Len1, ByteOrder, Bytes, C),
+ {Result, Par, Len2}.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_cancel_request/3
+%% Args:
+%% Message - The message
+%% Len - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%% A cancel_request_header record.
+%%-----------------------------------------------------------------
+dec_cancel_request(Version, Message, Len, ByteOrder) ->
+ {Request_id, _, _} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
+ #cancel_request_header{request_id=Request_id}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_locate_request/3
+%% Args:
+%% Message - The message
+%% Len - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%% A locate_request_header record.
+%%-----------------------------------------------------------------
+%% ## NEW IIOP 1.2 ##
+dec_locate_request(Version, Message, Len, ByteOrder) when Version == {1,2} ->
+ {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
+ {Object_key, _, _, _} = dec_target_addr(Version, Rest, Len1, ByteOrder, Request_id,
+ 'object_forward'),
+ {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}};
+dec_locate_request(Version, Message, Len, ByteOrder) ->
+ {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
+ {ObjKey, _, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest,
+ Len1, ByteOrder),
+ Object_key = dec_target_key(ObjKey, Request_id, Version, 'object_forward'),
+ {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}}.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_locate_reply/3
+%% Args:
+%% Message - The message
+%% Len - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%% A locate_reply_header record.
+%%-----------------------------------------------------------------
+dec_locate_reply(Version, Message, Len, ByteOrder) ->
+ {ReplyHeader, Rest1, Len1} = dec_locate_reply_header(Version, Message, Len, ByteOrder),
+ {ReplyHeader, dec_locate_reply_body(Version, ReplyHeader#locate_reply_header.locate_status, Rest1,
+ Len1, ByteOrder)}.
+
+dec_locate_reply_header(Version, Message, Len, ByteOrder) ->
+ {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
+ {Locate_status, Rest2, Len2} = dec_locate_status(Version, Rest1, Len1, ByteOrder),
+ {#locate_reply_header{request_id=Request_id, locate_status=Locate_status}, Rest2, Len2}.
+
+dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) when Version == {1,2} ->
+ %% In CORBA-2.3.1 the LocateReply body didn't align the body (8-octet
+ %% boundry) for IIOP-1.2. This have been changed in CORBA-2.4 and
+ %% changed back in CORBA-2.6. Hence, we should not change this.
+ case LocateStatus of
+ 'object_forward' ->
+ {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
+ ObjRef;
+ 'object_forward_perm' ->
+ %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
+ %% now.
+ {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
+ ObjRef;
+ 'loc_system_exception' ->
+ %% This should be updated but since 'dec_system_exception' removes
+ %% alignment, which the LocateReplyBody don't have, for 1.2 we
+ %% pretend it's 1.1 for now.
+ {SysExc, _} = dec_system_exception({1,1}, Rest, Len, ByteOrder),
+ corba:raise(SysExc);
+ 'loc_needs_addressing_mode' ->
+ %% Not supported.
+ [];
+ _ ->
+ []
+ end;
+dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) ->
+ case LocateStatus of
+ 'object_forward' ->
+ {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
+ ObjRef;
+ _ ->
+ []
+ end.
+
+dec_locate_status(Version, Bytes, Len, ByteOrder) ->
+ {L, Rest, Len1} = dec_type('tk_ulong', Version, Bytes, Len, ByteOrder),
+ {dec_giop_locate_status_type(L), Rest, Len1}.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_fragment_header/5
+%% Args:
+%% Message - The message
+%% Len0 - Number of bytes already read.
+%% ByteOrder - little or big
+%% Returns:
+%%-----------------------------------------------------------------
+dec_fragment_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
+ {RequestId, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
+ ByteOrder, [], 0),
+ {Version, #fragment_header{request_id=RequestId}, Rest1, Len1, ByteOrder};
+dec_fragment_header(Version, _Message, _Len0, _ByteOrder, _Buffer) ->
+ %% The FragmentHeader is IIOP-1.2 specific. Hence, do nothing here.
+ orber:dbg("[~p] cdr_decode:dec_fragment_header(~p)~n"
+ "Orber only supports fragmented messages for IIOP-1.2.",
+ [?LINE, Version], ?DEBUG_LEVEL),
+ exit(message_error).
+% {Version, #fragment_header{}, Message, Len0, ByteOrder}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_giop_reply_status_type
+%% Args:
+%% An integer status code
+%% Returns:
+%% An atom which is the reply status
+%%-----------------------------------------------------------------
+dec_giop_reply_status_type(0) ->
+ 'no_exception';
+dec_giop_reply_status_type(1) ->
+ 'user_exception';
+dec_giop_reply_status_type(2) ->
+ 'system_exception';
+dec_giop_reply_status_type(3) ->
+ 'location_forward';
+%% ## IIOP-1.2 ##
+dec_giop_reply_status_type(4) ->
+ 'location_forward_perm';
+dec_giop_reply_status_type(5) ->
+ 'needs_addressing_mode'.
+
+%%-----------------------------------------------------------------
+%% Func: dec_giop_locate_status_type
+%% Args:
+%% An integer status code
+%% Returns:
+%% An atom which is the reply status
+%%-----------------------------------------------------------------
+dec_giop_locate_status_type(0) ->
+ 'unknown_object';
+dec_giop_locate_status_type(1) ->
+ 'object_here';
+dec_giop_locate_status_type(2) ->
+ 'object_forward';
+%% ## IIOP-1.2 ##
+dec_giop_locate_status_type(3) ->
+ 'object_forward_perm';
+dec_giop_locate_status_type(4) ->
+ 'loc_system_exception';
+dec_giop_locate_status_type(5) ->
+ 'loc_needs_addressing_mode'.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_type/5
+%%-----------------------------------------------------------------
+dec_type(Type, Version, Bytes, Len, ByteOrder) ->
+ {Val, Rest, Len2, _} =
+ dec_type(Type, Version, Bytes, Len, ByteOrder, [], 0),
+ {Val, Rest, Len2}.
+
+dec_type('tk_null', _Version, Bytes, Len, _, _, C) ->
+ {'null', Bytes, Len, C};
+dec_type('tk_void', _Version, Bytes, Len, _, _, C) ->
+ {'ok', Bytes, Len, C};
+dec_type('tk_short', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
+ {Short, Rest1} = cdrlib:dec_short(ByteOrder, Rest),
+ {Short, Rest1, Len1 + 2, NewC+2};
+dec_type('tk_long', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
+ {Long, Rest1} = cdrlib:dec_long(ByteOrder, Rest),
+ {Long, Rest1, Len1 + 4, NewC+4};
+dec_type('tk_longlong', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
+ {Long, Rest1} = cdrlib:dec_longlong(ByteOrder, Rest),
+ {Long, Rest1, Len1 + 8, NewC+8};
+dec_type('tk_ushort', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
+ {Short, Rest1} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
+ {Short, Rest1, Len1 + 2, NewC+2};
+dec_type('tk_ulong', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
+ {Long, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ {Long, Rest1, Len1 + 4, NewC+4};
+dec_type('tk_ulonglong', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
+ {Long, Rest1} = cdrlib:dec_unsigned_longlong(ByteOrder, Rest),
+ {Long, Rest1, Len1 + 8, NewC+8};
+dec_type('tk_float', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
+ {Float, Rest1} = cdrlib:dec_float(ByteOrder, Rest),
+ {Float, Rest1, Len1 + 4, NewC+4};
+dec_type('tk_double', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
+ {Double, Rest1} = cdrlib:dec_double(ByteOrder, Rest),
+ {Double, Rest1, Len1 + 8, NewC+8};
+dec_type('tk_boolean', _Version, Bytes, Len, _, _, C) ->
+ {Bool, Rest} = cdrlib:dec_bool(Bytes),
+ {Bool, Rest, Len + 1, C+1};
+dec_type('tk_char', _Version, Bytes, Len, _, _, C) ->
+ {Char, Rest} = cdrlib:dec_char(Bytes),
+ {Char, Rest, Len + 1, C+1};
+dec_type('tk_wchar', {1,2}, Bytes, Len, _ByteOrder, _, C) ->
+ %% For IIOP-1.2 a wchar is almost encoded the same way as an octet-sequence.
+ %% The only difference is that the length-value is an octet as well.
+ case cdrlib:dec_octet(Bytes) of
+ {2, Rest1} ->
+ %% Currently we only allow 2-bytes wchar.
+ {WChar, Rest2} = cdrlib:dec_unsigned_short(big, Rest1),
+ {WChar, Rest2, Len+3, C+3};
+ {What, _} ->
+ orber:dbg("[~p] cdr_decode:dec_type(~p); unsupported wchar",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'DATA_CONVERSION'{completion_status=?COMPLETED_NO})
+ end;
+%% For 1.1 the wchar is limited to the use of two-octet fixed-length encoding.
+dec_type('tk_wchar', _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
+ {WChar, Rest2} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
+ {WChar, Rest2, Len1 + 2, NewC+2};
+dec_type('tk_octet', _Version, Bytes, Len, _, _, C) ->
+ {Octet, Rest} = cdrlib:dec_octet(Bytes),
+ {Octet, Rest, Len + 1, C+1};
+dec_type('tk_any', Version, Bytes, Len, ByteOrder, Buff, C) ->
+ {TypeCode, Rest1, Len1, NewC} = dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C),
+ {Value, Rest2, Len2, NewC2} = dec_type(TypeCode, Version, Rest1, Len1, ByteOrder, Buff, NewC),
+ {#any{typecode=TypeCode, value=Value}, Rest2, Len2, NewC2};
+dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_type_code(Version, Bytes, Len, ByteOrder, Buff, C);
+dec_type('tk_Principal', Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_sequence(Version, Bytes, 'tk_octet', Len, ByteOrder, Buff, C);
+dec_type({'tk_objref', _IFRId, _Name}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_objref(Version, Bytes, Len, ByteOrder, Buff, C);
+dec_type({'tk_struct', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_struct(Version, IFRId, Name, ElementList, Bytes, Len, ByteOrder, Buff, C);
+dec_type({'tk_union', IFRId, Name, DiscrTC, Default, ElementList},
+ Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C);
+dec_type({'tk_enum', _IFRId, _Name, ElementList}, _Version, Bytes, Len, ByteOrder, _, C) ->
+ {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
+ {Enum, Rest1} = cdrlib:dec_enum(ByteOrder, ElementList, Rest),
+ {Enum, Rest1, Len1 + 4, NewC+4};
+dec_type({'tk_string', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_string(Version, Bytes, Len, ByteOrder, Buff, C);
+dec_type({'tk_wstring', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_wstring(Version, Bytes, Len, ByteOrder, Buff, C);
+dec_type({'tk_sequence', ElemTC, _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_sequence(Version, Bytes, ElemTC, Len, ByteOrder, Buff, C);
+dec_type({'tk_array', ElemTC, Size}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_array(Version, Bytes, Size, ElemTC, Len, ByteOrder, Buff, C);
+dec_type({'tk_alias', _IFRId, _Name, TC}, Version, Bytes, Len, ByteOrder, Buff, C) ->
+ dec_type(TC, Version, Bytes, Len, ByteOrder, Buff, C);
+%dec_type({'tk_except', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder) ->
+dec_type({'tk_fixed', Digits, Scale}, _Version, Bytes, Len, _ByteOrder, _Buff, C) ->
+ dec_fixed(Digits, Scale, Bytes, Len, C);
+dec_type(Type, _, _, _, _, _, _) ->
+ orber:dbg("[~p] cdr_decode:dec_type(~p)~n"
+ "Incorrect TypeCode or unsupported type.",
+ [?LINE, Type], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 13), completion_status=?COMPLETED_MAYBE}).
+
+stringify_enum({tk_enum,_,_,_}, Label) ->
+ atom_to_list(Label);
+stringify_enum(_, Label) ->
+ Label.
+
+%%-----------------------------------------------------------------
+%% Func: dec_fixed
+%%-----------------------------------------------------------------
+%% Digits eq. total number of digits.
+%% Scale eq. position of the decimal point.
+%% E.g. fixed<5,2> - "123.45"
+%% E.g. fixed<4,2> - "12.34"
+%% These are encoded as:
+%% ## <5,2> ## ## <4,2> ##
+%% 1,2 0,1 eq. 1 octet
+%% 3,4 2,3
+%% 5,0xC 4,0xC
+%%
+%% Each number is encoded as a half-octet. Note, for <4,2> a zero is
+%% added first to to be able to create "even" octets.
+dec_fixed(0, 0, Bytes, Len, C) ->
+ {#fixed{digits = 0, scale = 0, value = ""}, Bytes, Len, C};
+dec_fixed(Digits, Scale, Bytes, Len, C) ->
+ case ?ODD(Digits) of
+ true ->
+ {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits, Scale, Bytes, Len, C),
+ case Sign of
+ ?FIXED_POSITIVE ->
+ {#fixed{digits = Digits, scale = Scale,
+ value = list_to_integer(Fixed)}, Bytes2, Len2, C2};
+ ?FIXED_NEGATIVE ->
+ {#fixed{digits = Digits, scale = Scale,
+ value = -list_to_integer(Fixed)}, Bytes2, Len2, C2}
+ end;
+ false ->
+ %% If the length (of fixed) is even a zero is added first.
+ %% Subtract that we've read 1 digit.
+ <<0:4,D2:4,T/binary>> = Bytes,
+ {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits-1, Scale, T, Len+1, C+1),
+ case Sign of
+ ?FIXED_POSITIVE ->
+ {#fixed{digits = Digits, scale = Scale,
+ value = list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2};
+ ?FIXED_NEGATIVE ->
+ {#fixed{digits = Digits, scale = Scale,
+ value = -list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2}
+ end
+ end.
+
+dec_fixed_2(1, _Scale, <<D1:4,?FIXED_POSITIVE:4,T/binary>>, Len, C) ->
+ {[D1+48], T, Len+1, C+1, ?FIXED_POSITIVE};
+dec_fixed_2(1, _Scale, <<D1:4,?FIXED_NEGATIVE:4,T/binary>>, Len, C) ->
+ {[D1+48], T, Len+1, C+1, ?FIXED_NEGATIVE};
+dec_fixed_2(Digits, Scale, _Bytes, _Len, _C) when Digits =< 0 ->
+ orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
+ "Malformed fixed type.", [?LINE, Digits, Scale], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
+dec_fixed_2(Digits, Scale, <<>>, _Len, _C) ->
+ orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
+ "The fixed type received was to short.",
+ [?LINE, Digits, Scale], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
+dec_fixed_2(Digits, Scale, <<D1:4,D2:4,T/binary>>, Len, C) ->
+ {Seq, Rest2, Len2, NewC2, Sign} = dec_fixed_2(Digits-2, Scale, T, Len+1, C+1),
+ {[D1+48, D2+48 | Seq], Rest2, Len2, NewC2, Sign}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_sequence/7 and dec_sequence/8
+%%-----------------------------------------------------------------
+dec_sequence(_Version, Message, 'tk_octet', Len, ByteOrder, _Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
+ {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
+dec_sequence(_Version, Message, 'tk_char', Len, ByteOrder, _Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
+ {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
+%% We test if it's a sequence of struct's or unions. By doing this we only
+%% have to look up the IFR-ID once instead of N times (N eq length of sequence).
+dec_sequence(Version, Message, {'tk_struct', IFRId, ShortName, ElementList},
+ Len, ByteOrder, Buff, C) when IFRId /= "", ShortName /= "" ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ case IFRId of
+ ?SYSTEM_TYPE ->
+ dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
+ ByteOrder, Buff, NewC+4, ShortName);
+ _ ->
+ Name = ifrid_to_name(IFRId, ?IFR_StructDef),
+ dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
+ ByteOrder, Buff, NewC+4, Name)
+ end;
+dec_sequence(Version, Message,
+ {'tk_union', ?SYSTEM_TYPE, TCName, DiscrTC, Default, ElementList},
+ Len, ByteOrder, Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
+ ByteOrder, Buff, NewC+4, TCName);
+dec_sequence(Version, Message,
+ {'tk_union', IFRId, _TCName, DiscrTC, Default, ElementList},
+ Len, ByteOrder, Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
+ dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
+ ByteOrder, Buff, NewC+4, Name);
+dec_sequence(Version, Message, TypeCode, Len, ByteOrder, Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ dec_sequence(Version, Rest1, Size, TypeCode, Len1 + 4, ByteOrder, Buff, NewC+4).
+
+
+dec_sequence(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C) ->
+ {[], Message, Len, C};
+dec_sequence(Version, Message, N, Type, Len, ByteOrder, Buff, C) ->
+ {Object, Rest1, Len1, NewC} = dec_type(Type, Version, Message, Len, ByteOrder, Buff, C),
+ {Seq, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, N - 1, Type, Len1, ByteOrder, Buff, NewC),
+ {[Object | Seq], Rest2, Len2, NewC2}.
+
+dec_sequence_struct(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C, _Name) ->
+ {[], Message, Len, C};
+dec_sequence_struct(Version, Message, N, TypeCodeList, Len, ByteOrder, Buff, C, Name) ->
+ {Struct, Rest1, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
+ {Seq, Rest2, Len2, NewC2} = dec_sequence_struct(Version, Rest1, N - 1, TypeCodeList, Len1, ByteOrder,
+ Buff, NewC, Name),
+ {[list_to_tuple([Name |Struct]) | Seq], Rest2, Len2, NewC2}.
+dec_sequence_union(_, Message, 0, _DiscrTC, _Default, _ElementList, Len, _ByteOrder, _Buff, C, _Name) ->
+ {[], Message, Len, C};
+dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList, Len, ByteOrder, Buff, C, Name) ->
+
+ {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Message, Len, ByteOrder, Buff, C),
+ Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
+ Rest1, Len1, ByteOrder, Buff, NewC),
+ {Value, Rest2, Len2, NewC3} = case Result of
+ {default, R, L, NewC2} ->
+ dec_union(Version, default, ElementList, Default,
+ R, L, ByteOrder, Buff, NewC2);
+ X ->
+ X
+ end,
+ {Seq, Rest3, Len3, NewC4} = dec_sequence_union(Version, Rest2, N - 1,
+ DiscrTC, Default, ElementList,
+ Len2, ByteOrder,
+ Buff, NewC3, Name),
+ {[{Name, Label, Value} | Seq], Rest3, Len3, NewC4}.
+
+%% A special case; when something is encapsulated (i.e. sent as octet-sequence)
+%% we sometimes don not want the result to be converted to a list.
+dec_octet_sequence_bin(_Version, Message, Len, ByteOrder, _Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
+ {OctetSeq, Rest2, Len1+4+Size, NewC+4+Size}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_array/5
+%%-----------------------------------------------------------------
+dec_array(Version, Message, Size, TypeCode, Len, ByteOrder, Buff, C) ->
+ {Seq, Rest1, Len1, NewC} = dec_sequence(Version, Message, Size, TypeCode, Len,
+ ByteOrder, Buff, C),
+ {list_to_tuple(Seq), Rest1, Len1, NewC}.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_string/4
+%%-----------------------------------------------------------------
+dec_string(_Version, Message, Len, ByteOrder, _Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ if
+ Size > 0 ->
+ DataSize = Size-1,
+ <<String:DataSize/binary, _Null:1/binary, Rest2/binary>> = Rest1,
+ {binary_to_list(String), Rest2, Len1+4+Size, NewC+4+Size};
+ true ->
+ {"", Rest1, Len1 + 4, NewC+4}
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: dec_string/4
+%%-----------------------------------------------------------------
+dec_wstring({1,2}, Message, Len, ByteOrder, Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Octets, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ if
+ Octets == 0 ->
+ {"", Rest1, Len1 + 4, NewC+4};
+ Octets > 0 ->
+ Size = round(Octets/2),
+ {String, Rest2, Len2, NewC2} =
+ dec_sequence({1,2}, Rest1, Size, 'tk_ushort',
+ Len1 + 4, big, Buff, NewC+4),
+ {String, Rest2, Len2, NewC2};
+ true ->
+ orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
+ [?LINE, Rest1], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
+ end;
+dec_wstring(Version, Message, Len, ByteOrder, Buff, C) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ if
+ Size > 0 ->
+ {String, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, Size - 1, 'tk_wchar',
+ Len1 + 4, ByteOrder, Buff, NewC+4),
+ %% Remove the NULL character.
+ {_, Rest3} = cdrlib:dec_unsigned_short(ByteOrder, Rest2),
+ {String, Rest3, Len2 + 2, NewC2+2};
+ Size == 0 ->
+ {"", Rest1, Len1 + 4, NewC+4};
+ true ->
+ orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
+ [?LINE, Rest1], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_union/9
+%%-----------------------------------------------------------------
+%% ## NEW IIOP 1.2 ##
+dec_union(Version, ?SYSTEM_TYPE, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C) ->
+ {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
+ {Value, Rest2, Len2, NewC3} = dec_union(Version, Label, ElementList, Default,
+ Rest1, Len1, ByteOrder, Buff, NewC),
+ {{Name, Label, Value}, Rest2, Len2, NewC3};
+
+
+dec_union(Version, IFRId, _, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C) ->
+ {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
+ Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
+ Rest1, Len1, ByteOrder, Buff, NewC),
+ {Value, Rest2, Len2, NewC3} = case Result of
+ {default, R, L, NewC2} ->
+ dec_union(Version, default, ElementList, Default,
+ R, L, ByteOrder, Buff, NewC2);
+ X ->
+ X
+ end,
+ Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
+ {{Name, Label, Value}, Rest2, Len2, NewC3}.
+
+dec_union(_, _, [], Default, Message, Len, _, _Buff, C) when Default < 0 ->
+ {undefined, Message, Len, C};
+dec_union(_, _, [], _Default, Message, Len, _, _Buff, C) ->
+ {default, Message, Len, C};
+dec_union(Version, Label, [{Label, _Name, Type}|_List], _Default, Message, Len, ByteOrder, Buff, C) ->
+ dec_type(Type, Version, Message, Len, ByteOrder, Buff, C);
+dec_union(Version, Label, [_H|List], Default, Message, Len, ByteOrder, Buff, C) ->
+ dec_union(Version, Label, List, Default, Message, Len, ByteOrder, Buff, C).
+
+%%-----------------------------------------------------------------
+%% Func: dec_struct/7
+%%-----------------------------------------------------------------
+dec_struct(Version, "", "", TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
+ {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
+ {list_to_tuple(Struct), Rest, Len1, NewC};
+dec_struct(Version, [], Name, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
+ %% This case is used when communicating with ORB:s which don't supply the IFRId
+ %% field in struct type codes (used in any)
+ {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
+ {list_to_tuple([list_to_atom(Name) |Struct]), Rest, Len1, NewC};
+dec_struct(Version, ?SYSTEM_TYPE, ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
+ {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
+ {list_to_tuple([ShortName |Struct]), Rest, Len1, NewC};
+dec_struct(Version, IFRId, _ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
+ Name = ifrid_to_name(IFRId, ?IFR_StructDef),
+ {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
+ {list_to_tuple([Name |Struct]), Rest, Len1, NewC}.
+
+dec_struct1(_, [], Message, Len, _ByteOrder, _, C) ->
+ {[], Message, Len, C};
+dec_struct1(Version, [{_ElemName, ElemType} | TypeCodeList], Message, Len, ByteOrder, Buff, C) ->
+ {Element, Rest, Len1, NewC} = dec_type(ElemType, Version, Message, Len, ByteOrder, Buff, C),
+ {Struct, Rest1, Len2, NewC2} = dec_struct1(Version, TypeCodeList, Rest, Len1, ByteOrder, Buff, NewC),
+ {[Element |Struct], Rest1, Len2, NewC2}.
+
+ifrid_to_name([], Type) ->
+ orber:dbg("[~p] ~p:ifrid_to_name([], ~p). No Id supplied.",
+ [?LINE, ?MODULE, Type], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?CORBA_OMGVMCID bor 11),
+ completion_status=?COMPLETED_MAYBE});
+ifrid_to_name(Id, Type) ->
+ case orber:light_ifr() of
+ true ->
+ orber_ifr:get_module(Id, Type);
+ false ->
+ case catch ifrid_to_name_helper(Id, Type) of
+ {'EXCEPTION', E} ->
+ corba:raise(E);
+ {'EXIT',{aborted,{no_exists,_}}} ->
+ case orber:get_lightweight_nodes() of
+ false ->
+ orber:dbg("[~p] cdr_decode:ifrid_to_name(~p, ~p). IFRid not found.",
+ [?LINE, Id, Type], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
+ Nodes ->
+ {A,B,C} = now(),
+ random:seed(A,B,C),
+ L = length(Nodes),
+ IFR = get_ifr_node(Nodes, random:uniform(L), L),
+ list_to_atom('OrberApp_IFR':get_absolute_name(IFR, Id))
+ end;
+ {'EXIT', Other} ->
+ orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). Unknown: ~p",
+ [?LINE, Id, Other], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
+ Name ->
+ list_to_atom(Name)
+ end
+ end.
+
+ifrid_to_name_helper(Id, ?IFR_UnionDef) ->
+ case mnesia:dirty_index_read(ir_UnionDef, Id, #ir_UnionDef.id) of
+ [#ir_UnionDef{absolute_name = [$:,$:|N]}] ->
+ change_colons_to_underscore(N, []);
+ Other ->
+ orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
+ [?LINE, Id, Other], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 9),
+ completion_status=?COMPLETED_MAYBE})
+ end;
+ifrid_to_name_helper(Id, ?IFR_StructDef) ->
+ case mnesia:dirty_index_read(ir_StructDef, Id, #ir_StructDef.id) of
+ [#ir_StructDef{absolute_name = [$:,$:|N]}] ->
+ change_colons_to_underscore(N, []);
+ Other ->
+ orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
+ [?LINE, Id, Other], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 10),
+ completion_status=?COMPLETED_MAYBE})
+ end;
+ifrid_to_name_helper(Id, ?IFR_ExceptionDef) ->
+ case mnesia:dirty_index_read(ir_ExceptionDef, Id, #ir_ExceptionDef.id) of
+ [#ir_ExceptionDef{absolute_name = [$:,$:|N]}] ->
+ change_colons_to_underscore(N, []);
+ Other ->
+ orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
+ [?LINE, Id, Other], ?DEBUG_LEVEL),
+ corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
+ completion_status=?COMPLETED_MAYBE})
+ end.
+
+change_colons_to_underscore([$:, $: | T], Acc) ->
+ change_colons_to_underscore(T, [$_ |Acc]);
+change_colons_to_underscore([H |T], Acc) ->
+ change_colons_to_underscore(T, [H |Acc]);
+change_colons_to_underscore([], Acc) ->
+ lists:reverse(Acc).
+
+get_ifr_node([], _, _) ->
+ %% Were not able to contact any of the given nodes.
+ orber:dbg("[~p] cdr_decode:get_ifr_node([]). No Node available.",
+ [?LINE], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_MAYBE});
+get_ifr_node(Nodes, N, L) ->
+ Node = lists:nth(N, Nodes),
+ case catch corba:resolve_initial_references_remote("OrberIFR", [Node]) of
+ IFR when is_record(IFR, 'IOP_IOR') ->
+ IFR;
+ _ ->
+ %% Not able to commincate with the node. Try next one.
+ NewL = L-1,
+ get_ifr_node(lists:delete(Node, Nodes), random:uniform(NewL), NewL)
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Func: dec_objref/4
+%%-----------------------------------------------------------------
+dec_objref(Version, Message, Len, ByteOrder) ->
+ dec_objref(Version, Message, Len, ByteOrder, [], 0).
+dec_objref(Version, Message, Len, ByteOrder, _Buff, C) ->
+ {IOR, Rest, Length} = iop_ior:decode(Version, Message, Len, ByteOrder),
+ {IOR, Rest, Length, C+Length-Len}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_system_exception/4 and dec_user_exception/4
+%%-----------------------------------------------------------------
+dec_system_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
+ {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
+ {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
+ Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
+ {Struct, _Rest2, Len2} =
+ dec_exception_1(Version, [{"minor",'tk_ulong'},
+ {"completed",
+ {'tk_enum', "", "completion_status",
+ ["COMPLETED_YES", "COMPLETED_NO",
+ "COMPLETED_MAYBE"]}}],
+ Rest1, Len1, ByteOrder),
+ {list_to_tuple([Name, "" |Struct]), Len2};
+dec_system_exception(Version, Message, Len, ByteOrder) ->
+ {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
+ Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
+ {Struct, _Rest2, Len2} =
+ dec_exception_1(Version, [{"minor",'tk_ulong'},
+ {"completed",
+ {'tk_enum', "", "completion_status",
+ ["COMPLETED_YES", "COMPLETED_NO",
+ "COMPLETED_MAYBE"]}}],
+ Rest1, Len1, ByteOrder),
+ {list_to_tuple([Name, "" |Struct]), Len2}.
+
+dec_user_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
+ {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
+ {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
+ Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
+ {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
+ {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
+ ByteOrder),
+ {list_to_tuple([Name, TypeId |Struct]), Len2};
+dec_user_exception(Version, Message, Len, ByteOrder) ->
+ {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
+ Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
+ {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
+ {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
+ ByteOrder),
+ {list_to_tuple([Name, TypeId |Struct]), Len2}.
+
+dec_exception_1(_, [], Message, Len, _ByteOrder) ->
+ {[], Message, Len};
+dec_exception_1(Version, [{_ElemName, ElemType} | ElementList], Message,
+ Len, ByteOrder) ->
+ {Element, Rest, Len1} = dec_type(ElemType, Version, Message, Len, ByteOrder),
+ {Struct, Rest1, Len2} = dec_exception_1(Version, ElementList, Rest, Len1,
+ ByteOrder),
+ {[Element |Struct], Rest1, Len2}.
+
+
+get_user_exception_type(TypeId) ->
+ case orber:light_ifr() of
+ true ->
+ orber_ifr:get_tc(TypeId, ?IFR_ExceptionDef);
+ false ->
+ case orber:get_lightweight_nodes() of
+ false ->
+ case mnesia:dirty_index_read(ir_ExceptionDef, TypeId,
+ #ir_ExceptionDef.id) of
+ [ExcDef] when is_record(ExcDef, ir_ExceptionDef) ->
+ ExcDef#ir_ExceptionDef.type;
+ Other ->
+ orber:dbg("[~p] cdr_decode:get_user_exception_type(~p). IFR Id not found: ~p",
+ [?LINE, TypeId, Other], ?DEBUG_LEVEL),
+ corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
+ completion_status=?COMPLETED_MAYBE})
+ end;
+ Nodes ->
+ {A,B,C} = now(),
+ random:seed(A,B,C),
+ L = length(Nodes),
+ IFR = get_ifr_node(Nodes, random:uniform(L), L),
+ 'OrberApp_IFR':get_user_exception_type(IFR, TypeId)
+ end
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: dec_type_code/4
+%%-----------------------------------------------------------------
+dec_type_code(Version, Message, Len, ByteOrder, Buff, C) ->
+ {TypeNo, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
+ dec_type_code(TypeNo, Version, Message1, Len1, ByteOrder, Buff, NewC).
+
+%%-----------------------------------------------------------------
+%% Func: dec_type_code/5
+%%-----------------------------------------------------------------
+dec_type_code(0, _, Message, Len, _, _, C) ->
+ {'tk_null', Message, Len, C};
+dec_type_code(1, _, Message, Len, _, _, C) ->
+ {'tk_void', Message, Len, C};
+dec_type_code(2, _, Message, Len, _, _, C) ->
+ {'tk_short', Message, Len, C};
+dec_type_code(3, _, Message, Len, _, _, C) ->
+ {'tk_long', Message, Len, C};
+dec_type_code(23, _, Message, Len, _, _, C) ->
+ {'tk_longlong', Message, Len, C};
+dec_type_code(25, _, Message, Len, _, _, C) ->
+ {'tk_longdouble', Message, Len, C};
+dec_type_code(4, _, Message, Len, _, _, C) ->
+ {'tk_ushort', Message, Len, C};
+dec_type_code(5, _, Message, Len, _, _, C) ->
+ {'tk_ulong', Message, Len, C};
+dec_type_code(24, _, Message, Len, _, _, C) ->
+ {'tk_ulonglong', Message, Len, C};
+dec_type_code(6, _, Message, Len, _, _, C) ->
+ {'tk_float', Message, Len, C};
+dec_type_code(7, _, Message, Len, _, _, C) ->
+ {'tk_double', Message, Len, C};
+dec_type_code(8, _, Message, Len, _, _, C) ->
+ {'tk_boolean', Message, Len, C};
+dec_type_code(9, _, Message, Len, _, _, C) ->
+ {'tk_char', Message, Len, C};
+dec_type_code(26, _, Message, Len, _, _, C) ->
+ {'tk_wchar', Message, Len, C};
+dec_type_code(10, _, Message, Len, _, _, C) ->
+ {'tk_octet', Message, Len, C};
+dec_type_code(11, _, Message, Len, _, _, C) ->
+ {'tk_any', Message, Len, C};
+dec_type_code(12, _, Message, Len, _, _, C) ->
+ {'tk_TypeCode', Message, Len, C};
+dec_type_code(13, _, Message, Len, _, _, C) ->
+ {'tk_Principal', Message, Len, C};
+dec_type_code(14, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_objref', RepId, Name}, Message1, Len1, NewC};
+dec_type_code(15, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "",
+ [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"element list",
+ {'tk_sequence', {'tk_struct', "","",
+ [{"member name", {'tk_string', 0}},
+ {"member type", 'tk_TypeCode'}]},
+ 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_struct', RepId, Name, ElementList}, Message1, Len1, NewC};
+dec_type_code(16, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, DiscrTC, Default}, Rest2, RestLen2, NewC} =
+ dec_type({'tk_struct', "", "",
+ [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"discriminant type", 'tk_TypeCode'},
+ {"default used", 'tk_long'}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {ElementList, <<>>, _RestLen3, NewC2} =
+ dec_type({'tk_sequence', {'tk_struct', "","",
+ [{"label value", DiscrTC},
+ {"member name", {'tk_string', 0}},
+ {"member type", 'tk_TypeCode'}]}, 0},
+ Version, Rest2, RestLen2, ByteOrder1, Buff, NewC),
+ NewElementList =
+ case check_enum(DiscrTC) of
+ true ->
+ lists:map(fun({L,N,T}) -> {atom_to_list(L),N,T} end, ElementList);
+ false ->
+ ElementList
+ end,
+ {{'tk_union', RepId, Name, DiscrTC, Default, NewElementList}, Message1, Len1, NewC2};
+dec_type_code(17, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "",
+ [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"element list",
+ {'tk_sequence', {'tk_string', 0}, 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_enum', RepId, Name, ElementList}, Message1, Len1, NewC};
+dec_type_code(18, Version, Message, Len, ByteOrder, Buff, C) ->
+ {MaxLength, Message1, Len1, NewC} =
+ dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
+ {{'tk_string', MaxLength}, Message1, Len1, NewC};
+dec_type_code(19, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{ElemTC, MaxLength}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
+ {"max length", 'tk_ulong'}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_sequence', ElemTC, MaxLength}, Message1, Len1, NewC};
+dec_type_code(20, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{ElemTC, Length}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
+ {"length", 'tk_ulong'}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_array', ElemTC, Length}, Message1, Len1, NewC};
+dec_type_code(21, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg ge a byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, TC}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"TypeCode", 'tk_TypeCode'}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_alias', RepId, Name, TC}, Message1, Len1, NewC};
+dec_type_code(22, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ %% Decode marshalled parameters, eg get the byteorder first
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "",
+ [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"element list",
+ {'tk_sequence', {'tk_struct', "","",
+ [{"member name", {'tk_string', 0}},
+ {"member type", 'tk_TypeCode'}]},
+ 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_except', RepId, Name, ElementList}, Message1, Len1, NewC};
+dec_type_code(27, Version, Message, Len, ByteOrder, Buff, C) ->
+ {MaxLength, Message1, Len1, NewC} =
+ dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
+ {{'tk_wstring', MaxLength}, Message1, Len1, NewC};
+dec_type_code(28, Version, Message, Len, ByteOrder, Buff, C) ->
+ {Digits, Message1, Len1, C1} =
+ dec_type('tk_ushort', Version, Message, Len, ByteOrder, Buff, C),
+ {Scale, Message2, Len2, C2} =
+ dec_type('tk_short', Version, Message1, Len1, ByteOrder, Buff, C1),
+ {{'tk_fixed', Digits, Scale}, Message2, Len2, C2};
+dec_type_code(29, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, ValueModifier, TC, ElementList}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"ValueModifier", 'tk_short'},
+ {"TypeCode", 'tk_TypeCode'},
+ {"element list",
+ {'tk_sequence',
+ {'tk_struct', "","",
+ [{"member name", {'tk_string', 0}},
+ {"member type", 'tk_TypeCode'},
+ {"Visibility", 'tk_short'}]},
+ 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_value', RepId, Name, ValueModifier, TC, ElementList}, Message1, Len1, NewC};
+dec_type_code(30, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name, TC}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}},
+ {"TypeCode", 'tk_TypeCode'}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_value_box', RepId, Name, TC}, Message1, Len1, NewC};
+dec_type_code(31, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
+ {"name", {'tk_string', 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_native', RepId, Name}, Message1, Len1, NewC};
+dec_type_code(32, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
+ {"name", {'tk_string', 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_abstract_interface', RepId, Name}, Message1, Len1, NewC};
+dec_type_code(33, Version, Message, Len, ByteOrder, Buff, C) ->
+ {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
+ {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
+ {{RepId, Name}, <<>>, _Len2, NewC} =
+ dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
+ {"name", {'tk_string', 0}}]},
+ Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
+ {{'tk_local_interface', RepId, Name}, Message1, Len1, NewC};
+dec_type_code(16#ffffffff, Version, Message, Len, ByteOrder, Buff, C) -> %% placeholder
+ {Indirection, Message1, Len1, NewC} =
+ dec_type('tk_long', Version, Message, Len, ByteOrder, Buff, C),
+ Position = C+Indirection,
+ <<_:Position/binary, SubBuff/binary>> = Buff,
+ {TC, _, _, _} = dec_type_code(Version, SubBuff, Position, ByteOrder, Buff, Position),
+ {TC, Message1, Len1, NewC};
+dec_type_code(Type, _, _, _, _, _, _) ->
+ orber:dbg("[~p] cdr_decode:dec_type_code(~p); No match.",
+ [?LINE, Type], ?DEBUG_LEVEL),
+ corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 8), completion_status=?COMPLETED_MAYBE}).
+
+check_enum({'tk_enum', _, _, _}) ->
+ true;
+check_enum(_) ->
+ false.
+
+
+decode_complex_tc_parameters(_Version, Message, Len, ByteOrder) ->
+ {Rest, Len1, NewC} = dec_align(Message, Len, 4, 0),
+ {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
+ <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
+ {OctetSeq, Rest2, Len1+4+Size, NewC+4}.
+
+%%-----------------------------------------------------------------
+%% Func: dec_align/3
+%% Args:
+%% R - The byte sequence that shall be aligned.
+%% Len - The number of bytes read so far.
+%% Alignment - The alignment as an integer (for example: 2,4,8).
+%% Returns:
+%% An aligned byte sequence.
+%%-----------------------------------------------------------------
+dec_align(R, Len, Alignment, C) ->
+ Rem = Len rem Alignment,
+ if Rem == 0 ->
+ {R, Len, C};
+ true ->
+ Diff = Alignment - Rem,
+ <<_:Diff/binary,Rest/binary>> = R,
+ {Rest, Len + Diff, C + Diff}
+ end.
+
+%%---------------- EOF MODULE ----------------------------------------