%% =====================================================================
%% This module was formed by merging the following modules:
%% 
%% 		`'DSS''
%% 		`asn1rt_ber_bin_v2'
%% 		`asn1rt_check'
%% 		`asn1rt_driver_handler'
%% 
%% Created by Igor 2008-11-05, 12:54:55.
%% 

-module('DSS').

-export([dec_DSAPrivateKey/2, decode/2, decode_disp/2,
	 enc_DSAPrivateKey/2, encode/2, encode_disp/2,
	 encoding_rule/0, info/0]).

%% =====================================================================
%% 
%% The following code stems from module `'DSS''.
%% 

%% Generated by the Erlang ASN.1 BER_V2-compiler version, utilizing bit-syntax:1.6.2
%% Purpose: encoder and decoder to the types in mod DSS

-record('DSAPrivateKey', {version, p, q, g, y, x}).

%%<<< -asn1_info([{vsn, '1.6.2'}, {module, 'DSS'},
%%<<<             {options,
%%<<<              [ber_bin_v2, report_errors,
%%<<<               {cwd,
%%<<<                "/ldisk/daily_build/otp_prebuild_r12b.2008-11-"
%%<<<                "05_12/otp_src_R12B-5/lib/ssh/src"},
%%<<<               {outdir,
%%<<<                "/ldisk/daily_build/otp_prebuild_r12b.2008-11-"
%%<<<                "05_12/otp_src_R12B-5/lib/ssh/src"},
%%<<<               inline, noobj, optimize, compact_bit_string, der,
%%<<<               {i, "."},
%%<<<               {i,
%%<<<                "/ldisk/daily_build/otp_prebuild_r12b.2008-11-"
%%<<<                "05_12/otp_src_R12B-5/lib/ssh/src"}]}]).

encoding_rule() -> ber_bin_v2.

encode(Type, Data) ->
    case catch encode_disp(Type, Data) of
      {'EXIT', {error, Reason}} -> {error, Reason};
      {'EXIT', Reason} -> {error, {asn1, Reason}};
      {Bytes, _Len} -> {ok, Bytes};
      Bytes -> {ok, Bytes}
    end.

decode(Type, Data) ->
    case catch decode_disp(Type, element(1, decode(Data)))
	of
      {'EXIT', {error, Reason}} -> {error, Reason};
      {'EXIT', Reason} -> {error, {asn1, Reason}};
      Result -> {ok, Result}
    end.

encode_disp('DSAPrivateKey', Data) ->
    enc_DSAPrivateKey(Data);
encode_disp(Type, _Data) ->
    exit({error, {asn1, {undefined_type, Type}}}).

decode_disp('DSAPrivateKey', Data) ->
    dec_DSAPrivateKey(Data);
decode_disp(Type, _Data) ->
    exit({error, {asn1, {undefined_type, Type}}}).

info() ->
    case module_info() of
      MI when is_list(MI) ->
	  case lists:keysearch(attributes, 1, MI) of
	    {value, {_, Attributes}} when is_list(Attributes) ->
		case lists:keysearch(asn1_info, 1, Attributes) of
		  {value, {_, Info}} when is_list(Info) -> Info;
		  _ -> []
		end;
	    _ -> []
	  end
    end.

%%================================
%%  DSAPrivateKey
%%================================
enc_DSAPrivateKey(Val) ->
    enc_DSAPrivateKey(Val, [<<48>>]).

enc_DSAPrivateKey(Val, TagIn) ->
    {_, Cindex1, Cindex2, Cindex3, Cindex4, Cindex5,
     Cindex6} =
	Val,
    %%-------------------------------------------------
    %% attribute version(1) with type INTEGER
    %%-------------------------------------------------
    {EncBytes1, EncLen1} = encode_integer([], Cindex1,
					  [<<2>>]),
    %%-------------------------------------------------
    %% attribute p(2) with type INTEGER
    %%-------------------------------------------------
    {EncBytes2, EncLen2} = encode_integer([], Cindex2,
					  [<<2>>]),
    %%-------------------------------------------------
    %% attribute q(3) with type INTEGER
    %%-------------------------------------------------
    {EncBytes3, EncLen3} = encode_integer([], Cindex3,
					  [<<2>>]),
    %%-------------------------------------------------
    %% attribute g(4) with type INTEGER
    %%-------------------------------------------------
    {EncBytes4, EncLen4} = encode_integer([], Cindex4,
					  [<<2>>]),
    %%-------------------------------------------------
    %% attribute y(5) with type INTEGER
    %%-------------------------------------------------
    {EncBytes5, EncLen5} = encode_integer([], Cindex5,
					  [<<2>>]),
    %%-------------------------------------------------
    %% attribute x(6) with type INTEGER
    %%-------------------------------------------------
    {EncBytes6, EncLen6} = encode_integer([], Cindex6,
					  [<<2>>]),
    BytesSoFar = [EncBytes1, EncBytes2, EncBytes3,
		  EncBytes4, EncBytes5, EncBytes6],
    LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 +
		 EncLen5
		 + EncLen6,
    encode_tags(TagIn, BytesSoFar, LenSoFar).

dec_DSAPrivateKey(Tlv) -> dec_DSAPrivateKey(Tlv, [16]).

dec_DSAPrivateKey(Tlv, TagIn) ->
    %%-------------------------------------------------
    %% decode tag and length
    %%-------------------------------------------------
    Tlv1 = match_tags(Tlv, TagIn),
    %%-------------------------------------------------
    %% attribute version(1) with type INTEGER
    %%-------------------------------------------------
    [V1 | Tlv2] = Tlv1,
    Term1 = decode_integer(V1, [], [2]),
    %%-------------------------------------------------
    %% attribute p(2) with type INTEGER
    %%-------------------------------------------------
    [V2 | Tlv3] = Tlv2,
    Term2 = decode_integer(V2, [], [2]),
    %%-------------------------------------------------
    %% attribute q(3) with type INTEGER
    %%-------------------------------------------------
    [V3 | Tlv4] = Tlv3,
    Term3 = decode_integer(V3, [], [2]),
    %%-------------------------------------------------
    %% attribute g(4) with type INTEGER
    %%-------------------------------------------------
    [V4 | Tlv5] = Tlv4,
    Term4 = decode_integer(V4, [], [2]),
    %%-------------------------------------------------
    %% attribute y(5) with type INTEGER
    %%-------------------------------------------------
    [V5 | Tlv6] = Tlv5,
    Term5 = decode_integer(V5, [], [2]),
    %%-------------------------------------------------
    %% attribute x(6) with type INTEGER
    %%-------------------------------------------------
    [V6 | Tlv7] = Tlv6,
    Term6 = decode_integer(V6, [], [2]),
    case Tlv7 of
      [] -> true;
      _ ->
	  exit({error,
		{asn1, {unexpected, Tlv7}}}) % extra fields not allowed
    end,
    {'DSAPrivateKey', Term1, Term2, Term3, Term4, Term5,
     Term6}.

%% =====================================================================
%% 
%% The following code stems from module `asn1rt_ber_bin_v2'.
%% 

%%<copyright>
%% <year>2002-2008</year>
%% <holder>Ericsson AB, All Rights Reserved</holder>
%%</copyright>
%%<legalnotice>
%% 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.
%%
%% The Initial Developer of the Original Code is Ericsson AB.
%%</legalnotice>
%%

%% encoding / decoding of BER

-record(module,
	{pos, name, defid, tagdefault = 'EXPLICIT',
	 exports = {exports, []}, imports = {imports, []},
	 extensiondefault = empty, typeorval}).

-record('SEQUENCE',
	{pname = false, tablecinf = false, components = []}).

-record('SET',
	{pname = false, sorted = false, tablecinf = false,
	 components = []}).

-record('ComponentType',
	{pos, name, typespec, prop, tags, textual_order}).

-record('ObjectClassFieldType',
	{classname, class, fieldname, type}).

-record(typedef,
	{checked = false, pos, name, typespec}).

-record(classdef,
	{checked = false, pos, name, typespec}).

-record(valuedef,
	{checked = false, pos, name, type, value, module}).

-record(ptypedef,
	{checked = false, pos, name, args, typespec}).

-record(pvaluedef,
	{checked = false, pos, name, args, type, value}).

-record(pvaluesetdef,
	{checked = false, pos, name, args, type, valueset}).

-record(pobjectdef,
	{checked = false, pos, name, args, class, def}).

-record(pobjectsetdef,
	{checked = false, pos, name, args, class, def}).

-record(typereference, {pos, val}).

-record(identifier, {pos, val}).

-record(constraint, {c, e}).

-record('Constraint',
	{'SingleValue' = no, 'SizeConstraint' = no,
	 'ValueRange' = no, 'PermittedAlphabet' = no,
	 'ContainedSubtype' = no, 'TypeConstraint' = no,
	 'InnerSubtyping' = no, e = no, 'Other' = no}).

-record(simpletableattributes,
	{objectsetname, c_name, c_index, usedclassfield,
	 uniqueclassfield, valueindex}).

-record(type,
	{tag = [], def, constraint = [], tablecinf = [],
	 inlined = no}).

-record(objectclass, {fields = [], syntax}).

-record('Object', {classname, gen = true, def}).

-record('ObjectSet',
	{class, gen = true, uniquefname, set}).

-record(tag, {class, number, type, form = 32}).

-record(cmap,
	{single_value = no, contained_subtype = no,
	 value_range = no, size = no, permitted_alphabet = no,
	 type_constraint = no, inner_subtyping = no}).

-record('EXTENSIONMARK', {pos, val}).

-record('SymbolsFromModule', {symbols, module, objid}).

-record('Externaltypereference', {pos, module, type}).

-record('Externalvaluereference', {pos, module, value}).

-record(state,
	{module, mname, type, tname, value, vname, erule,
	 parameters = [], inputmodules, abscomppath = [],
	 recordtopname = [], options, sourcedir}).

-record(gen_state,
	{active = false, prefix, inc_tag_pattern, tag_pattern,
	 inc_type_pattern, type_pattern, func_name, namelist,
	 tobe_refed_funcs = [], gen_refed_funcs = [],
	 generated_functions = [], suffix_index = 1,
	 current_suffix_index}).

% the encoding of class of tag bits 8 and 7

%%% primitive or constructed encoding % bit 6

%%% The tag-number for universal types

% the complete tag-word of built-in types

                                                              % can be CONSTRUCTED

                                                              % can be CONSTRUCTED

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

                                                               %can be constructed

% encode(Tlv={_Tag={?PRIMITIVE,_},_VList}) ->
%     encode_primitive(Tlv);
% encode(Tlv) ->
%     encode_constructed(Tlv).

decode(Bin) when is_binary(Bin) ->
    decode_primitive(Bin);
decode(Tlv) -> % assume it is a tlv
    {Tlv, <<>>}.

decode_primitive(Bin) ->
    {{Form, TagNo, Len, V}, Rest} = decode_tlv(Bin),
    case Form of
      1
	  when Len == indefinite -> % constructed
	  {Vlist, Rest2} = decode_constructed_indefinite(V, []),
	  {{TagNo, Vlist}, Rest2};
      1 -> % constructed
	  {{TagNo, decode_constructed(V)}, Rest};
      0 -> % primitive
	  {{TagNo, V}, Rest}
    end.

decode_constructed(<<>>) -> [];
decode_constructed(Bin) ->
    {Tlv, Rest} = decode_primitive(Bin),
    [Tlv | decode_constructed(Rest)].

decode_constructed_indefinite(<<0, 0, Rest/binary>>,
			      Acc) ->
    {lists:reverse(Acc), Rest};
decode_constructed_indefinite(Bin, Acc) ->
    {Tlv, Rest} = decode_primitive(Bin),
    decode_constructed_indefinite(Rest, [Tlv | Acc]).

decode_tlv(Bin) ->
    {Form, TagNo, Len, Bin2} = decode_tag_and_length(Bin),
    case Len of
      indefinite -> {{Form, TagNo, Len, Bin2}, []};
      _ ->
	  <<V:Len/binary, Bin3/binary>> = Bin2,
	  {{Form, TagNo, Len, V}, Bin3}
    end.

%% skip_tag and skip_length_and_value are rutines used both by
%% decode_partial_incomplete and decode_selective (decode/2).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% match_tags takes a Tlv (Tag, Length, Value) structure and matches
%% it with the tags in TagList. If the tags does not match the function
%% crashes otherwise it returns the remaining Tlv after that the tags have
%% been removed.
%%
%% match_tags(Tlv, TagList)
%%

match_tags({T, V}, [T | Tt]) -> match_tags(V, Tt);
match_tags([{T, V}], [T | Tt]) -> match_tags(V, Tt);
match_tags(Vlist = [{T, _V} | _], [T]) -> Vlist;
match_tags(Tlv, []) -> Tlv;
match_tags({Tag, _V}, [T | _Tt]) ->
    {error, {asn1, {wrong_tag, {Tag, T}}}}.

%%===============================================================================
%%===============================================================================
%%===============================================================================
%% Optionals, preset not filled optionals with asn1_NOVALUE
%%===============================================================================
%%===============================================================================
%%===============================================================================

%%===============================================================================
%% Decode a tag
%%
%% decode_tag(OctetListBuffer) -> {{Form, (Class bsl 16)+ TagNo}, RestOfBuffer, RemovedBytes}
%%===============================================================================

decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 0:1,
			Length:7, RestBuffer/binary>>)
    when TagNo < 31 ->
    {Form, Class bsl 16 + TagNo, Length, RestBuffer};
decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1,
			0:7, T/binary>>)
    when TagNo < 31 ->
    {Form, Class bsl 16 + TagNo, indefinite, T};
decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1,
			LL:7, T/binary>>)
    when TagNo < 31 ->
    <<Length:LL/unit:8, RestBuffer/binary>> = T,
    {Form, Class bsl 16 + TagNo, Length, RestBuffer};
decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1,
			TagNo:7, 0:1, Length:7, RestBuffer/binary>>) ->
    {Form, Class bsl 16 + TagNo, Length, RestBuffer};
decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1,
			TagNo:7, 1:1, 0:7, T/binary>>) ->
    {Form, Class bsl 16 + TagNo, indefinite, T};
decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1,
			TagNo:7, 1:1, LL:7, T/binary>>) ->
    <<Length:LL/unit:8, RestBuffer/binary>> = T,
    {Form, Class bsl 16 + TagNo, Length, RestBuffer};
decode_tag_and_length(<<Class:2, Form:1, 31:5,
			Buffer/binary>>) ->
    {TagNo, Buffer1} = decode_tag(Buffer, 0),
    {Length, RestBuffer} = decode_length(Buffer1),
    {Form, Class bsl 16 + TagNo, Length, RestBuffer}.

%% last partial tag
decode_tag(<<0:1, PartialTag:7, Buffer/binary>>,
	   TagAck) ->
    TagNo = TagAck bsl 7 bor PartialTag,
    %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
    {TagNo, Buffer};
% more tags
decode_tag(<<_:1, PartialTag:7, Buffer/binary>>,
	   TagAck) ->
    TagAck1 = TagAck bsl 7 bor PartialTag,
    %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
    decode_tag(Buffer, TagAck1).

%%=======================================================================
%%
%% Encode all tags in the list Tags and return a possibly deep list of
%% bytes with tag and length encoded
%% The taglist must be in reverse order (fixed by the asn1 compiler)
%% e.g [T1,T2] will result in
%% {[EncodedT2,EncodedT1|BytesSoFar],LenSoFar+LenT2+LenT1}
%%

encode_tags([Tag | Trest], BytesSoFar, LenSoFar) ->
    % remove    {Bytes1,L1} = encode_one_tag(Tag),
    {Bytes2, L2} = encode_length(LenSoFar),
    encode_tags(Trest, [Tag, Bytes2 | BytesSoFar],
		LenSoFar + size(Tag) + L2);
encode_tags([], BytesSoFar, LenSoFar) ->
    {BytesSoFar, LenSoFar}.

encode_tags(TagIn, {BytesSoFar, LenSoFar}) ->
    encode_tags(TagIn, BytesSoFar, LenSoFar).

% encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) ->			
%     NewForm = case Type of
% 	       'EXPLICIT' ->
% 		   ?CONSTRUCTED;
% 	       _ ->
% 		   Form
% 	   end,
%     Bytes = encode_tag_val({Class,NewForm,No}),
%     {Bytes,size(Bytes)}.

%%===============================================================================
%%
%% This comment is valid for all the encode/decode functions
%%
%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound}
%%     used for PER-coding but not for BER-coding.
%%
%% Val = Value.  If Val is an atom then it is a symbolic integer value
%%       (i.e the atom must be one of the names in the NamedNumberList).
%%       The NamedNumberList is used to translate the atom to an integer value
%%       before encoding.
%%
%%===============================================================================

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% encode_open_type(Value) -> io_list (i.e nested list with integers, binaries)
%% Value = list of bytes of an already encoded value (the list must be flat)
%%         | binary

%%===============================================================================
%%===============================================================================
%%===============================================================================
%% Boolean, ITU_T X.690 Chapter 8.2
%%===============================================================================
%%===============================================================================
%%===============================================================================

%%===============================================================================
%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len}
%%===============================================================================

%%===========================================================================
%% Integer, ITU_T X.690 Chapter 8.3

%% encode_integer(Constraint, Value, Tag) -> [octet list]
%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list]
%%    Value = INTEGER | {Name,INTEGER}
%%    Tag = tag | notag
%%===========================================================================

encode_integer(C, Val, Tag) when is_integer(Val) ->
    encode_tags(Tag, encode_integer(C, Val));
encode_integer(C, {Name, Val}, Tag)
    when is_atom(Name) ->
    encode_integer(C, Val, Tag);
encode_integer(_C, Val, _Tag) ->
    exit({error, {asn1, {encode_integer, Val}}}).

encode_integer(_, Val) ->
    Bytes = if Val >= 0 -> encode_integer_pos(Val, []);
	       true -> encode_integer_neg(Val, [])
	    end,
    {Bytes, length(Bytes)}.

encode_integer_pos(0, L = [B | _Acc]) when B < 128 -> L;
encode_integer_pos(N, Acc) ->
    encode_integer_pos(N bsr 8, [N band 255 | Acc]).

encode_integer_neg(-1, L = [B1 | _T]) when B1 > 127 ->
    L;
encode_integer_neg(N, Acc) ->
    encode_integer_neg(N bsr 8, [N band 255 | Acc]).

%%===============================================================================
%% decode integer
%%    (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
%%    (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
%%===============================================================================

decode_integer(Tlv, Range, TagIn) ->
    V = match_tags(Tlv, TagIn),
    Int = decode_integer(V),
    range_check_integer(Int, Range),
    Int.

%% decoding postitive integer values.
decode_integer(Bin = <<0:1, _:7, _/binary>>) ->
    Len = size(Bin),
    %    <<Int:Len/unit:8,Buffer2/binary>> = Bin,
    <<Int:Len/unit:8>> = Bin,
    Int;
%% decoding negative integer values.
decode_integer(Bin = <<1:1, B2:7, Bs/binary>>) ->
    Len = size(Bin),
    %    <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
    <<N:Len/unit:8>> = <<B2, Bs/binary>>,
    Int = N - (1 bsl (8 * Len - 1)),
    Int.

range_check_integer(Int, Range) ->
    case Range of
      [] -> % No length constraint
	  Int;
      {Lb, Ub}
	  when Int >= Lb,
	       Ub >= Int -> % variable length constraint
	  Int;
      Int -> % fixed value constraint
	  Int;
      {_, _} ->
	  exit({error, {asn1, {integer_range, Range, Int}}});
      SingleValue when is_integer(SingleValue) ->
	  exit({error, {asn1, {integer_range, Range, Int}}});
      _ -> % some strange constraint that we don't support yet
	  Int
    end.

%%============================================================================
%% Enumerated value, ITU_T X.690 Chapter 8.4

%% The encode_enumerated functions below this line can be removed when the
%% new code generation is stable. (the functions might have to be kept here
%% a while longer for compatibility reasons)

%%============================================================================
%%
%% Real value, ITU_T X.690 Chapter 8.5
%%============================================================================
%%
%% encode real value
%%============================================================================

%%============================================================================
%% decode real value
%%
%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
%%  {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
%%     RestBuff}
%%
%% only for base 2 and 10 decoding sofar!!
%%============================================================================

%%    exit({error,{asn1, {unimplemented,real}}}).
%%  decode_real2(Buffer, Form, size(Buffer)).

% decode_real2(Buffer, Form, Len) ->
%     <<First, Buffer2/binary>> = Buffer,
%     if
% 	First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
% 	First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
% 	First =:= 2#00000000 -> {0, Buffer2};
% 	true ->
% 	    %% have some check here to verify only supported bases (2)
% 	    <<B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>,
% 		Sign = B6,
% 	    Base =
% 		case B5_4 of
% 		    0 -> 2;  % base 2, only one so far
% 		    _ -> exit({error,{asn1, {non_supported_base, First}}})
% 		end,
% 	    ScalingFactor =
% 		case B3_2 of
% 		    0 -> 0;  % no scaling so far
% 		    _ -> exit({error,{asn1, {non_supported_scaling, First}}})
% 		end,

% 	    {FirstLen,Exp,Buffer3} =
% 		case B1_0 of
% 		    0 ->
% 			<<_:1/unit:8,Buffer21/binary>> = Buffer2,
% 			{2, decode_integer2(1, Buffer2),Buffer21};
% 		    1 ->
% 			<<_:2/unit:8,Buffer21/binary>> = Buffer2,
% 			{3, decode_integer2(2, Buffer2)};
% 		    2 ->
% 			<<_:3/unit:8,Buffer21/binary>> = Buffer2,
% 			{4, decode_integer2(3, Buffer2)};
% 		    3 ->
% 			<<ExpLen1,RestBuffer/binary>> = Buffer2,
% 			<<_:ExpLen1/unit:8,RestBuffer2/binary>> = RestBuffer,
% 			{ ExpLen1 + 2,
% 			  decode_integer2(ExpLen1, RestBuffer, RemBytes1),
% 			  RestBuffer2}
% 		end,
% 	    Length = Len - FirstLen,
% 	    <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
% 	    {Mantissa, Buffer4} =
% 		if Sign =:= 0 ->

% 			{LongInt, RestBuff};%  sign plus,
% 		   true ->

% 			{-LongInt, RestBuff}%  sign minus
% 		end,
% 	    case Form of
% 		tuple ->
% 		    {Val,Buf,RemB} = Exp,
% 		    {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3};
% 		_value ->
% 		    comming
% 	    end
%     end.

%%============================================================================
%% Bitstring value, ITU_T X.690 Chapter 8.6
%%
%% encode bitstring value
%%
%% bitstring NamedBitList
%% Val can be  of:
%% - [identifiers] where only named identifers are set to one,
%%   the Constraint must then have some information of the
%%   bitlength.
%% - [list of ones and zeroes] all bits
%% - integer value representing the bitlist
%% C is constrint Len, only valid when identifiers
%%============================================================================

%%=================================================================
%% Encode named bits
%%=================================================================

%%----------------------------------------
%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
%%   [sorted_list_of_bitpositions_to_set]
%%----------------------------------------

%%----------------------------------------
%% make_and_set_list(Len of list to return, [list of positions to set to 1])->
%% returns list of Len length, with all in SetPos set.
%% in positioning in list the first element is 0, the second 1 etc.., but
%% Len will make a list of length Len, not Len + 1.
%%    BitList = make_and_set_list(C, ToSetPos, 0),
%%----------------------------------------

%%=================================================================
%% Do the actual encoding
%%     ([bitlist]) -> {ListLen, UnusedBits, OctetList}
%%=================================================================

%%============================================================================
%% decode bitstring value
%%    (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
%%============================================================================

%%decode_bitstring2(1, Unused, Buffer) ->
%%    make_bits_of_int(hd(Buffer), 128, 8-Unused);
%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) ->
%%    [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8),
%%    [B7, B6, B5, B4, B3, B2, B1, B0 |
%%     decode_bitstring2(Len - 1, Unused, Buffer)].

%%make_bits_of_int(_, _, 0) ->
%%    [];
%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 ->
%%    X = case MaskVal band BitVal of
%%	    0 -> 0 ;
%%	    _ -> 1
%%	end,
%%    [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)].

%%----------------------------------------
%% Decode the bitlist to names
%%----------------------------------------

%%============================================================================
%% Null value, ITU_T X.690 Chapter 8.8
%%
%% encode NULL value
%%============================================================================

%%============================================================================
%% decode NULL value
%%    (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
%%============================================================================

%%============================================================================
%% Object identifier, ITU_T X.690 Chapter 8.19
%%
%% encode Object Identifier value
%%============================================================================

%%%%%%%%%%%
%% mk_object_val(Value) -> {OctetList, Len}
%% returns a Val as a list of octets, the 8 bit is allways set to one except
%% for the last octet, where its 0
%%

%%============================================================================
%% decode Object Identifier value
%%    (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
%%============================================================================

%%============================================================================
%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
%%    (Buffer, Range, StringType, HasTag, TotalLen) ->
%%                                  {String, Remain, RemovedBytes}
%%============================================================================

% 	case StringType of
% 	    ?N_BIT_STRING when BinOrOld == bin ->
% 		{concat_bit_binaries(AccVal, Val), AccRb+Rb};
% 	    _ when binary(Val),binary(AccVal) ->
% 		{<<AccVal/binary,Val/binary>>,AccRb+Rb};
% 	    _ when binary(Val), AccVal==[] ->
% 		{Val,AccRb+Rb};				
% 	    _ ->	
% 		{AccVal++Val, AccRb+Rb}
% 	end,

%%============================================================================
%% encode Universal string
%%============================================================================

%%===========================================================================
%% decode Universal strings
%%    (Buffer, Range, StringType, HasTag, LenIn) ->
%%                           {String, Remain, RemovedBytes}
%%===========================================================================

%%============================================================================
%% encode UTF8 string
%%============================================================================

%%============================================================================
%% decode UTF8 string
%%============================================================================

%%============================================================================
%% encode BMP string
%%============================================================================

%%============================================================================
%% Generalized time, ITU_T X.680 Chapter 39
%%
%% encode Generalized time
%%============================================================================

%%============================================================================
%% decode Generalized time
%%    (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
%%============================================================================

%%============================================================================
%% Universal time, ITU_T X.680 Chapter 40
%%
%% encode UTC time
%%============================================================================

%%============================================================================
%% decode UTC time
%%    (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
%%============================================================================

%%============================================================================
%% Length handling
%%
%% Encode length
%%
%% encode_length(Int | indefinite) ->
%%          [<127]| [128 + Int (<127),OctetList] | [16#80]
%%============================================================================

encode_length(indefinite) ->
    {[128], 1}; % 128
encode_length(L) when L =< 127 -> {[L], 1};
encode_length(L) ->
    Oct = minimum_octets(L),
    Len = length(Oct),
    if Len =< 126 -> {[128 + Len | Oct], Len + 1};
       true -> exit({error, {asn1, to_long_length_oct, Len}})
    end.

%% Val must be >= 0
minimum_octets(Val) -> minimum_octets(Val, []).

minimum_octets(0, Acc) -> Acc;
minimum_octets(Val, Acc) ->
    minimum_octets(Val bsr 8, [Val band 255 | Acc]).

%%===========================================================================
%% Decode length
%%
%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
%%                             {{Length, RestOctetsL}, NoRemovedBytes}
%%===========================================================================

decode_length(<<1:1, 0:7, T/binary>>) ->
    {indefinite, T};
decode_length(<<0:1, Length:7, T/binary>>) ->
    {Length, T};
decode_length(<<1:1, LL:7, T/binary>>) ->
    <<Length:LL/unit:8, Rest/binary>> = T, {Length, Rest}.

%%-------------------------------------------------------------------------
%% INTERNAL HELPER FUNCTIONS (not exported)
%%-------------------------------------------------------------------------

%% =====================================================================
%% 
%% The following code stems from module `asn1rt_check'.
%% 

%%<copyright>
%% <year>2001-2008</year>
%% <holder>Ericsson AB, All Rights Reserved</holder>
%%</copyright>
%%<legalnotice>
%% 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.
%%
%% The Initial Developer of the Original Code is Ericsson AB.
%%</legalnotice>
%%

%%<<< -record(module,
%%<<<         {pos, name, defid, tagdefault = 'EXPLICIT',
%%<<<          exports = {exports, []}, imports = {imports, []},
%%<<<          extensiondefault = empty, typeorval}).

%%<<< -record('SEQUENCE',
%%<<<         {pname = false, tablecinf = false, components = []}).

%%<<< -record('SET',
%%<<<         {pname = false, sorted = false, tablecinf = false,
%%<<<          components = []}).

%%<<< -record('ComponentType',
%%<<<         {pos, name, typespec, prop, tags, textual_order}).

%%<<< -record('ObjectClassFieldType',
%%<<<         {classname, class, fieldname, type}).

%%<<< -record(typedef,
%%<<<         {checked = false, pos, name, typespec}).

%%<<< -record(classdef,
%%<<<         {checked = false, pos, name, typespec}).

%%<<< -record(valuedef,
%%<<<         {checked = false, pos, name, type, value, module}).

%%<<< -record(ptypedef,
%%<<<         {checked = false, pos, name, args, typespec}).

%%<<< -record(pvaluedef,
%%<<<         {checked = false, pos, name, args, type, value}).

%%<<< -record(pvaluesetdef,
%%<<<         {checked = false, pos, name, args, type, valueset}).

%%<<< -record(pobjectdef,
%%<<<         {checked = false, pos, name, args, class, def}).

%%<<< -record(pobjectsetdef,
%%<<<         {checked = false, pos, name, args, class, def}).

%%<<< -record(typereference, {pos, val}).

%%<<< -record(identifier, {pos, val}).

%%<<< -record(constraint, {c, e}).

%%<<< -record('Constraint',
%%<<<         {'SingleValue' = no, 'SizeConstraint' = no,
%%<<<          'ValueRange' = no, 'PermittedAlphabet' = no,
%%<<<          'ContainedSubtype' = no, 'TypeConstraint' = no,
%%<<<          'InnerSubtyping' = no, e = no, 'Other' = no}).

%%<<< -record(simpletableattributes,
%%<<<         {objectsetname, c_name, c_index, usedclassfield,
%%<<<          uniqueclassfield, valueindex}).

%%<<< -record(type,
%%<<<         {tag = [], def, constraint = [], tablecinf = [],
%%<<<          inlined = no}).

%%<<< -record(objectclass, {fields = [], syntax}).

%%<<< -record('Object', {classname, gen = true, def}).

%%<<< -record('ObjectSet',
%%<<<         {class, gen = true, uniquefname, set}).

%%<<< -record(tag, {class, number, type, form = 32}).

%%<<< -record(cmap,
%%<<<         {single_value = no, contained_subtype = no,
%%<<<          value_range = no, size = no, permitted_alphabet = no,
%%<<<          type_constraint = no, inner_subtyping = no}).

%%<<< -record('EXTENSIONMARK', {pos, val}).

%%<<< -record('SymbolsFromModule', {symbols, module, objid}).

%%<<< -record('Externaltypereference', {pos, module, type}).

%%<<< -record('Externalvaluereference', {pos, module, value}).

%%<<< -record(state,
%%<<<         {module, mname, type, tname, value, vname, erule,
%%<<<          parameters = [], inputmodules, abscomppath = [],
%%<<<          recordtopname = [], options, sourcedir}).

%%<<< -record(gen_state,
%%<<<         {active = false, prefix, inc_tag_pattern, tag_pattern,
%%<<<          inc_type_pattern, type_pattern, func_name, namelist,
%%<<<          tobe_refed_funcs = [], gen_refed_funcs = [],
%%<<<          generated_functions = [], suffix_index = 1,
%%<<<          current_suffix_index}).

%% =====================================================================
%% 
%% The following code stems from module `asn1rt_driver_handler'.
%% 

%%<copyright>
%% <year>2002-2008</year>
%% <holder>Ericsson AB, All Rights Reserved</holder>
%%</copyright>
%%<legalnotice>
%% 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.
%%
%% The Initial Developer of the Original Code is Ericsson AB.
%%</legalnotice>
%%

%%<<< -record(module,
%%<<<         {pos, name, defid, tagdefault = 'EXPLICIT',
%%<<<          exports = {exports, []}, imports = {imports, []},
%%<<<          extensiondefault = empty, typeorval}).

%%<<< -record('SEQUENCE',
%%<<<         {pname = false, tablecinf = false, components = []}).

%%<<< -record('SET',
%%<<<         {pname = false, sorted = false, tablecinf = false,
%%<<<          components = []}).

%%<<< -record('ComponentType',
%%<<<         {pos, name, typespec, prop, tags, textual_order}).

%%<<< -record('ObjectClassFieldType',
%%<<<         {classname, class, fieldname, type}).

%%<<< -record(typedef,
%%<<<         {checked = false, pos, name, typespec}).

%%<<< -record(classdef,
%%<<<         {checked = false, pos, name, typespec}).

%%<<< -record(valuedef,
%%<<<         {checked = false, pos, name, type, value, module}).

%%<<< -record(ptypedef,
%%<<<         {checked = false, pos, name, args, typespec}).

%%<<< -record(pvaluedef,
%%<<<         {checked = false, pos, name, args, type, value}).

%%<<< -record(pvaluesetdef,
%%<<<         {checked = false, pos, name, args, type, valueset}).

%%<<< -record(pobjectdef,
%%<<<         {checked = false, pos, name, args, class, def}).

%%<<< -record(pobjectsetdef,
%%<<<         {checked = false, pos, name, args, class, def}).

%%<<< -record(typereference, {pos, val}).

%%<<< -record(identifier, {pos, val}).

%%<<< -record(constraint, {c, e}).

%%<<< -record('Constraint',
%%<<<         {'SingleValue' = no, 'SizeConstraint' = no,
%%<<<          'ValueRange' = no, 'PermittedAlphabet' = no,
%%<<<          'ContainedSubtype' = no, 'TypeConstraint' = no,
%%<<<          'InnerSubtyping' = no, e = no, 'Other' = no}).

%%<<< -record(simpletableattributes,
%%<<<         {objectsetname, c_name, c_index, usedclassfield,
%%<<<          uniqueclassfield, valueindex}).

%%<<< -record(type,
%%<<<         {tag = [], def, constraint = [], tablecinf = [],
%%<<<          inlined = no}).

%%<<< -record(objectclass, {fields = [], syntax}).

%%<<< -record('Object', {classname, gen = true, def}).

%%<<< -record('ObjectSet',
%%<<<         {class, gen = true, uniquefname, set}).

%%<<< -record(tag, {class, number, type, form = 32}).

%%<<< -record(cmap,
%%<<<         {single_value = no, contained_subtype = no,
%%<<<          value_range = no, size = no, permitted_alphabet = no,
%%<<<          type_constraint = no, inner_subtyping = no}).

%%<<< -record('EXTENSIONMARK', {pos, val}).

%%<<< -record('SymbolsFromModule', {symbols, module, objid}).

%%<<< -record('Externaltypereference', {pos, module, type}).

%%<<< -record('Externalvaluereference', {pos, module, value}).

%%<<< -record(state,
%%<<<         {module, mname, type, tname, value, vname, erule,
%%<<<          parameters = [], inputmodules, abscomppath = [],
%%<<<          recordtopname = [], options, sourcedir}).

%%<<< -record(gen_state,
%%<<<         {active = false, prefix, inc_tag_pattern, tag_pattern,
%%<<<          inc_type_pattern, type_pattern, func_name, namelist,
%%<<<          tobe_refed_funcs = [], gen_refed_funcs = [],
%%<<<          generated_functions = [], suffix_index = 1,
%%<<<          current_suffix_index}).

