aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1')
-rw-r--r--lib/asn1/c_src/Makefile9
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c56
-rw-r--r--lib/asn1/doc/src/asn1_ug.xml519
-rw-r--r--lib/asn1/doc/src/asn1ct.xml128
-rw-r--r--lib/asn1/doc/src/asn1rt.xml41
-rw-r--r--lib/asn1/doc/src/exclusive_Win_But.ps465
-rw-r--r--lib/asn1/doc/src/notes.xml168
-rw-r--r--lib/asn1/doc/src/selective_TypeList.ps266
-rw-r--r--lib/asn1/doc/src/selective_Window2.ps515
-rw-r--r--lib/asn1/src/.gitignore2
-rw-r--r--lib/asn1/src/Makefile94
-rw-r--r--lib/asn1/src/asn1.app.src6
-rw-r--r--lib/asn1/src/asn1_db.erl69
-rw-r--r--lib/asn1/src/asn1_records.hrl10
-rw-r--r--lib/asn1/src/asn1ct.erl828
-rw-r--r--lib/asn1/src/asn1ct_check.erl1091
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber.erl1596
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl215
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl1454
-rw-r--r--lib/asn1/src/asn1ct_eval_ext.funcs1
-rw-r--r--lib/asn1/src/asn1ct_eval_per.funcs2
-rw-r--r--lib/asn1/src/asn1ct_eval_uper.funcs2
-rw-r--r--lib/asn1/src/asn1ct_func.erl100
-rw-r--r--lib/asn1/src/asn1ct_gen.erl648
-rw-r--r--lib/asn1/src/asn1ct_gen_ber.erl1749
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl928
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl1143
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl1562
-rw-r--r--lib/asn1/src/asn1ct_imm.erl800
-rw-r--r--lib/asn1/src/asn1ct_name.erl154
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl40
-rw-r--r--lib/asn1/src/asn1ct_value.erl71
-rw-r--r--lib/asn1/src/asn1rt_ber_bin.erl2471
-rw-r--r--lib/asn1/src/asn1rt_ber_bin_v2.erl2035
-rw-r--r--lib/asn1/src/asn1rt_check.erl360
-rw-r--r--lib/asn1/src/asn1rt_nif.erl27
-rw-r--r--lib/asn1/src/asn1rt_per_bin.erl2316
-rw-r--r--lib/asn1/src/asn1rt_per_bin_rt2ct.erl1781
-rw-r--r--lib/asn1/src/asn1rt_uper_bin.erl1648
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl1487
-rw-r--r--lib/asn1/src/asn1rtt_check.erl276
-rw-r--r--lib/asn1/src/asn1rtt_ext.erl72
-rw-r--r--lib/asn1/src/asn1rtt_per.erl880
-rw-r--r--lib/asn1/src/asn1rtt_per_common.erl126
-rw-r--r--lib/asn1/src/asn1rtt_real_common.erl292
-rw-r--r--lib/asn1/src/asn1rtt_uper.erl973
-rw-r--r--lib/asn1/src/prepare_templates.erl135
-rw-r--r--lib/asn1/test/Makefile9
-rw-r--r--lib/asn1/test/asn1_SUITE.erl633
-rw-r--r--lib/asn1/test/asn1_SUITE_data/BadEnumValue1.asn8
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Certificate.asn0
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ChoExtension.asn16
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn162
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Constraints.py7
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Def.py31
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EUTRA-InterNodeDefinitions.asn123
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EUTRA-UE-Variables.asn49
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumExt.asn183
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn21
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Fragmented.asn124
-rw-r--r--lib/asn1/test/asn1_SUITE_data/InfObj.asn92
-rw-r--r--lib/asn1/test/asn1_SUITE_data/InfObj2.asn156
-rw-r--r--lib/asn1/test/asn1_SUITE_data/MAP-insertSubscriberData-def.py102
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod.set.asn5
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod1.asn18
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod2.asn43
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod3.asn33
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod4.asn33
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mod5.asn37
-rw-r--r--lib/asn1/test/asn1_SUITE_data/MultipleLevels.asn19
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mvrasn.set.asn7
-rw-r--r--lib/asn1/test/asn1_SUITE_data/NullTest.asn114
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Opt.py31
-rw-r--r--lib/asn1/test/asn1_SUITE_data/P-Record.asn1dbbin3128 -> 0 bytes
-rw-r--r--lib/asn1/test/asn1_SUITE_data/P-Record.erl244
-rw-r--r--lib/asn1/test/asn1_SUITE_data/P-Record.hrl17
-rw-r--r--lib/asn1/test/asn1_SUITE_data/PDUs.py325
-rw-r--r--lib/asn1/test/asn1_SUITE_data/PartialDecSeq.asn1config10
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Pattern.asn8
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Prim.asn129
-rw-r--r--lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1108
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ROSE.asn1449
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqDefault.asn111
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqExtension.asn128
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1208
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqOf.asn19
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqOf.py45
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SetDefault.asn111
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SetOf.py42
-rw-r--r--lib/asn1/test/asn1_SUITE_data/TConstr.asn16
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Tst.py153
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Two.py34
-rw-r--r--lib/asn1/test/asn1_SUITE_data/UPERDefault.asn18
-rw-r--r--lib/asn1/test/asn1_SUITE_data/UndefType.py14
-rw-r--r--lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl89
-rw-r--r--lib/asn1/test/asn1_SUITE_data/testobj.erl57
-rw-r--r--lib/asn1/test/asn1_app_test.erl4
-rw-r--r--lib/asn1/test/asn1_test_lib.erl48
-rw-r--r--lib/asn1/test/asn1_wrapper.erl37
-rw-r--r--lib/asn1/test/ber_decode_error.erl45
-rw-r--r--lib/asn1/test/error_SUITE.erl104
-rw-r--r--lib/asn1/test/h323test.erl1
-rw-r--r--lib/asn1/test/testChoExtension.erl46
-rw-r--r--lib/asn1/test/testChoExternal.erl75
-rw-r--r--lib/asn1/test/testChoRecursive.erl51
-rw-r--r--lib/asn1/test/testChoiceIndefinite.erl5
-rw-r--r--lib/asn1/test/testCompactBitString.erl306
-rw-r--r--lib/asn1/test/testConstraints.erl277
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl54
-rw-r--r--lib/asn1/test/testDeepTConstr.erl87
-rw-r--r--lib/asn1/test/testDoubleEllipses.erl10
-rw-r--r--lib/asn1/test/testEnumExt.erl101
-rw-r--r--lib/asn1/test/testFragmented.erl42
-rw-r--r--lib/asn1/test/testINSTANCE_OF.erl17
-rw-r--r--lib/asn1/test/testInfObj.erl49
-rw-r--r--lib/asn1/test/testInfObjectClass.erl15
-rw-r--r--lib/asn1/test/testMergeCompile.erl14
-rw-r--r--lib/asn1/test/testMultipleLevels.erl27
-rw-r--r--lib/asn1/test/testNBAPsystem.erl5
-rw-r--r--lib/asn1/test/testParamBasic.erl10
-rw-r--r--lib/asn1/test/testParameterizedInfObj.erl6
-rw-r--r--lib/asn1/test/testPrim.erl577
-rw-r--r--lib/asn1/test/testPrimStrings.erl1113
-rw-r--r--lib/asn1/test/testSSLspecs.erl31
-rw-r--r--lib/asn1/test/testSeqExtension.erl164
-rw-r--r--lib/asn1/test/testSeqIndefinite.erl6
-rw-r--r--lib/asn1/test/testSeqOf.erl292
-rw-r--r--lib/asn1/test/testSeqSetDefaultVal.erl6
-rw-r--r--lib/asn1/test/testSetIndefinite.erl5
-rw-r--r--lib/asn1/test/testSetOptional.erl212
-rw-r--r--lib/asn1/test/testTCAP.erl6
-rw-r--r--lib/asn1/test/testTimer.erl53
-rw-r--r--lib/asn1/test/testTypeValueNotation.erl35
-rw-r--r--lib/asn1/test/testWSParamClass.erl17
-rw-r--r--lib/asn1/test/testX420.erl4
-rw-r--r--lib/asn1/test/test_compile_options.erl13
-rw-r--r--lib/asn1/test/test_inline.erl270
-rw-r--r--lib/asn1/test/test_modified_x420.erl2
-rw-r--r--lib/asn1/test/test_partial_incomplete_decode.erl2
-rw-r--r--lib/asn1/test/test_selective_decode.erl2
-rw-r--r--lib/asn1/test/test_special_decode_performance.erl8
-rw-r--r--lib/asn1/vsn.mk2
142 files changed, 10828 insertions, 26600 deletions
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index a73d01a83a..70238335c4 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -66,13 +66,8 @@ NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.dll
CLIB_FLAGS =
LN=cp
else
-ifeq ($(findstring vxworks,$(TARGET)),vxworks)
-NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.eld
-CLIB_FLAGS =
-else
NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.so
CLIB_FLAGS = -lc
-endif
LN= ln -s
endif
@@ -99,10 +94,10 @@ docs:
$(OBJDIR)/%.o: %.c
- $(CC) -c $(CFLAGS) -O3 -o $@ $<
+ $(V_CC) -c $(CFLAGS) -O3 -o $@ $<
$(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES)
- $(LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS)
+ $(V_LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS)
# ----------------------------------------------------
# Release Target
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index 26803a25a4..b3dd312fed 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2012. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2013. 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
@@ -27,7 +27,6 @@
#define ASN1_OK 0
#define ASN1_ERROR -1
#define ASN1_COMPL_ERROR 1
-#define ASN1_MEMORY_ERROR 0
#define ASN1_DECODE_ERROR 2
#define ASN1_TAG_ERROR -3
#define ASN1_LEN_ERROR -4
@@ -851,11 +850,8 @@ int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
};
// The remaining binary after one ASN1 segment has been decoded
- if ((rest_data = enif_make_new_binary(env, in_buf_len - ib_index, &rest))
- == NULL) {
- *term = enif_make_atom(env, "could_not_alloc_binary");
- return ASN1_ERROR;
- }
+ rest_data = enif_make_new_binary(env, in_buf_len - ib_index, &rest);
+ memcpy(rest_data, in_buf+ib_index, in_buf_len - ib_index);
*term = enif_make_tuple2(env, decoded_term, rest);
return ASN1_OK;
@@ -1222,7 +1218,33 @@ static ERL_NIF_TERM encode_per_complete(ErlNifEnv* env, int argc,
return enif_make_binary(env, &out_binary);
}
-static ERL_NIF_TERM decode_ber_tlv(ErlNifEnv* env, int argc,
+static ERL_NIF_TERM
+make_ber_error_term(ErlNifEnv* env, unsigned int return_code,
+ unsigned int err_pos)
+{
+ ERL_NIF_TERM reason;
+ ERL_NIF_TERM t;
+
+ switch (return_code) {
+ case ASN1_TAG_ERROR:
+ reason = enif_make_atom(env, "invalid_tag");
+ break;
+ case ASN1_LEN_ERROR:
+ case ASN1_INDEF_LEN_ERROR:
+ reason = enif_make_atom(env, "invalid_length");
+ break;
+ case ASN1_VALUE_ERROR:
+ reason = enif_make_atom(env, "invalid_value");
+ break;
+ default:
+ reason = enif_make_atom(env, "unknown");
+ break;
+ }
+ t = enif_make_tuple2(env, reason, enif_make_int(env, err_pos));
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), t);
+}
+
+static ERL_NIF_TERM decode_ber_tlv_raw(ErlNifEnv* env, int argc,
const ERL_NIF_TERM argv[]) {
ErlNifBinary in_binary;
ERL_NIF_TERM return_term;
@@ -1231,11 +1253,11 @@ static ERL_NIF_TERM decode_ber_tlv(ErlNifEnv* env, int argc,
if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
return enif_make_badarg(env);
- if ((return_code = ber_decode_begin(env, &return_term, in_binary.data,
- in_binary.size, &err_pos)) != ASN1_OK
- )
- return enif_make_tuple2(env, enif_make_atom(env,"error"), enif_make_tuple2(env,
- enif_make_int(env, return_code),enif_make_int(env, err_pos)));
+ return_code = ber_decode_begin(env, &return_term, in_binary.data,
+ in_binary.size, &err_pos);
+ if (return_code != ASN1_OK) {
+ return make_ber_error_term(env, return_code, err_pos);
+ }
return return_term;
}
@@ -1298,8 +1320,10 @@ static void unload(ErlNifEnv* env, void* priv_data) {
}
-static ErlNifFunc nif_funcs[] = { { "encode_per_complete", 1,
- encode_per_complete }, { "decode_ber_tlv", 1, decode_ber_tlv }, {
- "encode_ber_tlv", 1, encode_ber_tlv } };
+static ErlNifFunc nif_funcs[] = {
+ { "encode_per_complete", 1, encode_per_complete },
+ { "decode_ber_tlv_raw", 1, decode_ber_tlv_raw },
+ { "encode_ber_tlv", 1, encode_ber_tlv },
+};
ERL_NIF_INIT(asn1rt_nif, nif_funcs, load, NULL, upgrade, unload)
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml
index 1b399fb641..362ca9330f 100644
--- a/lib/asn1/doc/src/asn1_ug.xml
+++ b/lib/asn1/doc/src/asn1_ug.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -186,13 +186,21 @@ END </pre>
The following shows how the compiler
can be called from the Erlang shell:</p>
<pre>
-1><input>asn1ct:compile("People",[ber_bin]).</input>
+1><input>asn1ct:compile("People", [ber]).</input>
+ok
+2> </pre>
+
+ <p>The <c>verbose</c> option can be given to have information
+ about the generated files printed:</p>
+ <pre>
+2><input>asn1ct:compile("People", [ber,verbose]).</input>
Erlang ASN.1 compiling "People.asn"
--{generated,"People.asn1db"}--
--{generated,"People.hrl"}--
--{generated,"People.erl"}--
ok
-2> </pre>
+3> </pre>
+
<p>The ASN.1 module People is now accepted and the abstract syntax tree
is saved in the <c>People.asn1db</c> file, the
generated Erlang code is compiled using the Erlang compiler and
@@ -229,7 +237,7 @@ receive
constructed and encoded using
<c>'People':encode('Person',Answer)</c> which takes an
instance of a defined ASN.1 type and transforms it to a
- (possibly) nested list of bytes according to the BER or PER
+ binary according to the BER or PER
encoding-rules.
<br></br>
The encoder and the decoder can also be run from
@@ -239,24 +247,12 @@ The encoder and the decoder can also be run from
<pre>
2> <input>Rockstar = {'Person',"Some Name",roving,50}.</input>
{'Person',"Some Name",roving,50}
-3> <input>{ok,Bytes} = asn1rt:encode('People','Person',Rockstar).</input>
-{ok,[&lt;&lt;243&gt;&gt;,
- [17],
- [19,9,"Some Name"],
- [2,1,[2]],
- [2,1,"2"]]}
-4> <input>Bin = list_to_binary(Bytes).</input>
-&lt;&lt;243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,2,1,50&gt;&gt;
-5> <input>{ok,Person} = asn1rt:decode('People','Person',Bin).</input>
+3> <input>{ok,Bin} = asn1rt:encode('People','Person',Rockstar).</input>
+{ok,&lt;&lt;243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
+ 2,1,50&gt;&gt;}
+4> <input>{ok,Person} = asn1rt:decode('People','Person',Bin).</input>
{ok,{'Person',"Some Name",roving,50}}
-6> </pre>
- <p>Notice that the result from <c>encode</c> is a nested list which
- must be turned into a binary before the call to <c>decode</c>. A
- binary is necessary as input to decode since the module was compiled
- with the <c>ber_bin</c> option
- The reason for returning a nested list is that it is faster to produce
- and the <c>list_to_binary</c> operation is
- performed automatically when the list is sent via the Erlang port mechanism.</p>
+5> </pre>
</section>
<section>
@@ -305,17 +301,15 @@ The encoder and the decoder can also be run from
ASN.1 compiler:</p>
<pre>
erlc Person.asn
-erlc -bper_bin Person.asn
-erlc -bber_bin +optimize ../Example.asn
+erlc -bper Person.asn
+erlc -bber ../Example.asn
erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn </pre>
<p>The useful options for the ASN.1 compiler are:</p>
<taglist>
- <tag><c>-b[ber | per | ber_bin | per_bin | uper_bin]</c></tag>
+ <tag><c>-b[ber | per | uper]</c></tag>
<item>
<p>Choice of encoding rules, if omitted <c>ber</c> is the
- default. The <c>ber_bin</c> and <c>per_bin</c> options
- allows for optimizations and are therefore recommended
- instead of the <c>ber</c> and <c>per</c> options.</p>
+ default.</p>
</item>
<tag><c>-o OutDirectory</c></tag>
<item>
@@ -330,51 +324,14 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
are several places to search in. The compiler will always
search the current directory first.</p>
</item>
- <tag><c>+compact_bit_string</c></tag>
- <item>
- <p>Gives the user the option to use a compact format of the BIT
- STRING type to save memory space, typing space and
- increase encode/decode performance, for details see
- <seealso marker="#BIT STRING">BIT STRING </seealso>type section.</p>
- </item>
<tag><c>+der</c></tag>
<item>
- <p>DER encoding rule. Only when using <c>-ber</c> or
- <c>-ber_bin</c> option.</p>
- </item>
- <tag><c>+optimize</c></tag>
- <item>
- <p>This flag has effect only when used together with one of
- <c>per_bin</c> or <c>ber_bin</c> flags. It gives time optimized
- code in the generated modules and it uses another runtime module.
- In the <c>per_bin</c> case a nif is used. The
- result from an encode is a binary.</p>
- <p><em>When this flag is used you cannot use the old format</em><c>{TypeName,Value}</c> when you encode values. Since it is
- an unnecessary construct it has been removed in favor of
- performance. It
- is neither admitted to construct SEQUENCE or SET component values
- with the format <c>{ComponentName,Value}</c> since it also is
- unnecessary. The only case were it is necessary is in a CHOICE,
- were you have to pass values to the right component by specifying
- <c>{ComponentName,Value}</c>. See also about
- <seealso marker="#TypeNameValue">{Typename,Value}</seealso> below
- and in the sections for each type.</p>
- </item>
- <tag><c>+driver</c></tag>
- <item>
- <p>As of R15B this means the same as the <c>nif</c> option. Kept for
- backwards compatability reasons.</p>
- </item>
- <tag><c>+nif</c></tag>
- <item>
- <p>Together with the flags <c>ber_bin</c>
- and <c>optimize</c> you choose to use a nif for considerable
- faster encode and decode. </p>
+ <p>DER encoding rule. Only when using <c>-ber</c> option.</p>
</item>
<tag><c>+asn1config</c></tag>
<item>
<p>This functionality works together with the flags
- <c>ber_bin</c> and <c>optimize</c>. You enables the
+ <c>ber</c>. It enables the
specialized decodes, see the <seealso marker="asn1_spec">Specialized Decode</seealso> chapter.
</p>
</item>
@@ -388,22 +345,6 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
list or a binary. Earlier versions of the compiler ignored
those following bytes.</p>
</item>
- <tag><c>{inline,OutputName}</c></tag>
- <item>
- <p>Compiling with this option gives one output module
- containing all asn1 run-time functionality. The asn1 specs
- are provided in a target module <c>Module.set.asn</c> as
- described in the <seealso marker="asn1ct#asn1set">reference manual</seealso>. The name of the resulting module
- containing generated encode/decode functions and inlined
- run-time functions will be <c>OutputName.erl</c>. The
- merging/inlining of code is done by the <c>igor</c> module
- of <c>syntax_tools</c>. By default the functions generated
- from the first asn1 spec in the <c>.set.asn</c> are
- exported, unless a <c>{export,[atom()]}</c> or
- <c>{export_all,true}</c> option are provided. The list of
- atoms are names of choosen asn1 specs from the
- <c>.set.asn</c> file. See further examples of usage <seealso marker="#inlineExamples">below</seealso></p>
- </item>
<tag><c>+'Any Erlc Option'</c></tag>
<item>
<p>You may add any option to the Erlang compiler when
@@ -413,7 +354,6 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
</item>
</taglist>
<p>For a complete description of <c>erlc</c> see Erts Reference Manual.</p>
- <p>For preferred option use see <seealso marker="#preferred option use">Preferred Option Use</seealso> section.</p>
<p>The compiler and other compile-time functions can also be invoked from
the Erlang shell. Below follows a brief
description of the primary functions, for a
@@ -429,9 +369,9 @@ asn1ct:compile("H323-MESSAGES.asn1"). </pre>
<p>which equals:</p>
<pre>
asn1ct:compile("H323-MESSAGES.asn1",[ber]). </pre>
- <p>If one wants PER encoding with optimizations:</p>
+ <p>If one wants PER encoding:</p>
<pre>
-asn1ct:compile("H323-MESSAGES.asn1",[per_bin,optimize]). </pre>
+asn1ct:compile("H323-MESSAGES.asn1",[per]). </pre>
<p>The generic encode and decode functions can be invoked like this:</p>
<pre>
asn1ct:encode('H323-MESSAGES','SomeChoiceType',{call,"octetstring"}).
@@ -443,269 +383,6 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</section>
<section>
- <marker id="preferred option use"></marker>
- <title>Preferred Option Use</title>
- <p>
- It may not be obvious which compile options best fit a
- situation. This section describes the format of the result of
- encode and decode. It also gives some performance statistics
- when using certain options. Finally there is a recommendation
- which option combinations should be used.
- </p>
- <p>
- The default option is <c>ber</c>. It is the same backend as
- <c>ber_bin</c> except that the result of encode is transformed
- to a flat list. Below is a table that gives the different
- formats of input and output of encode and decode using the
- <em>allowed combinations</em> of coding and optimization
- options: (EAVF stands for how ASN1 values are represented in
- Erlang which is described in the <seealso
- marker="#ASN1Types">ASN1 Types chapter</seealso>)
- </p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Encoding Rule</em></cell>
- <cell align="left" valign="middle"><em>Compile options, allowed combinations</em></cell>
- <cell align="left" valign="middle"><em>encode input</em></cell>
- <cell align="left" valign="middle"><em>encode output</em></cell>
- <cell align="left" valign="middle"><em>decode input</em></cell>
- <cell align="left" valign="middle"><em>decode output</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle">[ber] (default)</cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">flat list</cell>
- <cell align="left" valign="middle">flat list / binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle">[ber_bin]</cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">iolist / binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PER aligned variant</cell>
- <cell align="left" valign="middle">[per]</cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">flat list</cell>
- <cell align="left" valign="middle">flat list</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PER aligned variant</cell>
- <cell align="left" valign="middle"><em>[per_bin]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist / binary</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PER aligned variant</cell>
- <cell align="left" valign="middle"><em>[per_bin, optimize]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PER unaligned variant</cell>
- <cell align="left" valign="middle"><em>[uper_bin]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
-
- <row>
- <cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle">[(ber), der]</cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">flat list</cell>
- <cell align="left" valign="middle">flat list / binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle">[ber_bin, der]</cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, der]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
- <cell align="left" valign="middle">EAVF</cell>
- <cell align="left" valign="middle">iolist</cell>
- <cell align="left" valign="middle">binary</cell>
- <cell align="left" valign="middle">EAVF</cell>
- </row>
-
-
- <tcaption>The output / input formats for different combinations of compile options.</tcaption>
- </table>
- <p>
- Encode / decode speed comparison in one user case for the above
- alternatives (except <c>DER</c>) is showed in the table below. The
- <c>DER</c> alternatives are slower than their corresponding
- <c>BER</c> alternative.
- </p>
-
- <table>
- <row>
- <cell align="left" valign="middle"><em>compile options</em></cell>
- <cell align="left" valign="middle"><em>encode time</em></cell>
- <cell align="left" valign="middle"><em>decode time</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">[ber]</cell>
- <cell align="left" valign="middle">120</cell>
- <cell align="left" valign="middle">162</cell>
- </row>
- <row>
- <cell align="left" valign="middle">[ber_bin]</cell>
- <cell align="left" valign="middle">124</cell>
- <cell align="left" valign="middle">154</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize]</em></cell>
- <cell align="left" valign="middle">50</cell>
- <cell align="left" valign="middle">78</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver]</em></cell>
- <cell align="left" valign="middle">50</cell>
- <cell align="left" valign="middle">62</cell>
- </row>
- <row>
- <cell align="left" valign="middle">[per]</cell>
- <cell align="left" valign="middle">141</cell>
- <cell align="left" valign="middle">133</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[per_bin]</em></cell>
- <cell align="left" valign="middle">125</cell>
- <cell align="left" valign="middle">123</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[per_bin, optimize]</em></cell>
- <cell align="left" valign="middle">77</cell>
- <cell align="left" valign="middle">72</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[uper_bin]</em></cell>
- <cell align="left" valign="middle">97</cell>
- <cell align="left" valign="middle">104</cell>
- </row>
- <tcaption>
- One example of difference in speed for the compile option alternatives.
- </tcaption>
- </table>
-
- <p>
- The compile options <c>ber</c>, <c>per</c> and
- <c>driver</c> are kept for backwards compatibility and should not be
- used in new code. The nif implementation which replaces the linked-in
- driver has been shown to be about 5-15% faster.
- </p>
- <p>
- You are strongly recommended to use the appropriate alternative
- of the bold typed options. The <c>optimize</c> and
- <c>nif</c> options does not affect the encode or decode
- result, just the time spent in run-time. When <c>ber_bin</c> and
- <c>nif</c> or <c>per_bin</c> and <c>optimize</c> is
- combined the C-code nif is used in chosen parts of encode /
- decode procedure.
- </p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Compile options, allowed combinations</em></cell>
- <cell align="left" valign="middle"><em>use of nif</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">[ber]</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle">[ber_bin]</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize]</em></cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
- <cell align="left" valign="middle">yes</cell>
- </row>
- <row>
- <cell align="left" valign="middle">[per]</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[per_bin]</em></cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[per_bin, optimize]</em></cell>
- <cell align="left" valign="middle">yes</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[uper_bin]</em></cell>
- <cell align="left" valign="middle">no</cell>
- </row>
-
- <row>
- <cell align="left" valign="middle">[(ber), der]</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle">[ber_bin, der]</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, der]</em></cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
- <cell align="left" valign="middle">yes</cell>
- </row>
-
-
- <tcaption>When the ASN1 nif is used.</tcaption>
- </table>
-
- </section>
- <section>
<title>Run-time Functions</title>
<p>A brief description of the major functions is given here. For a
complete description of each function see
@@ -719,9 +396,9 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}).
'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre>
<p>The asn1 nif is enabled in two occasions: encoding of
- asn1 values when the asn1 spec is compiled with <c>per_bin</c> and
- <c>optimize</c> or decode of encoded asn1 values when the asn1 spec is
- compiled with <c>ber_bin</c>, <c>optimize</c> and <c>nif</c>. In
+ asn1 values when the asn1 spec is compiled with <c>per</c> and
+ or decode of encoded asn1 values when the asn1 spec is
+ compiled with <c>ber</c>. In
those cases the nif will be loaded automatically at the first call
to <c>encode</c>/<c>decode</c>. If one doesn't want the performance
overhead of the nif being loaded at the first call it is possible
@@ -754,21 +431,8 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
any reason. Maybe you need to compile the same specs for
different encoding/decoding standards.</item>
<item>You want only one resulting module.</item>
- <item>If it is crucial to have a minimal system. Using
- <c>{inline,OutputModule}</c> includes all necessary run-time
- functions of the asn1 application, but skips those modules not
- used.</item>
- <item>Upgrading issues: Even if you upgrade your Erlang system
- you may want to continue running the old asn1 run-time
- functionality.</item>
- <item>Performance issues: If you have an asn1 system with a lot
- of cross references you may gain in performance. Measurements
- must be done for each case.</item>
</list>
- <p>You may choose either the plain multi file compilation that just
- merges the chosen asn1 specs or the <c>{inline,OutputModule}</c>
- that also includes the used asn1 run-time functionality.</p>
- <p>For both cases you need to specify which asn1 specs you will
+ <p>You need to specify which asn1 specs you will
compile in a module that must have the extension
<c>.set.asn</c>. You chose name of the module and provide the
names of the asn1 specs. For instance, if you have the specs
@@ -782,17 +446,7 @@ File3.asn </pre>
<code type="none">
~> erlc MyModule.set.asn </code>
<p>the result will be one merged module <c>MyModule.erl</c> with
- the generated code from the three asn1 specs. But if you compile
- with:</p>
- <code type="none">
-~> erlc +"{inline,'OutputModule'}" MyModule.set.asn </code>
- <p>the result will be a module <c>OutputModule.erl</c> that
- contains all encode/decode functions for the three asn1 specs and
- all used functions from the asn1 run-time modules, in this case
- <c>asn1rt_ber_bin</c>. In the former case all encode/decode
- functions are exported but in the latter only the encode/decode
- functions of the first spec in the <c>.set.asn</c>, i.e. those
- from <c>File1.asn</c>.
+ the generated code from the three asn1 specs.
</p>
</section>
@@ -868,26 +522,6 @@ Operational ::= BOOLEAN --ASN.1 definition </pre>
<pre>
Val = true,
{ok,Bytes}=asn1rt:encode(MyModule,'Operational',Val), </pre>
- <p>For historical reasons it is also possible to assign ASN.1 values
- in Erlang using a tuple notation
- with type and value as this</p>
- <pre>
-Val = {'Operational',true} </pre>
- <warning>
- <marker id="warning"></marker>
- <p>The tuple notation, <c>{Typename, Value}</c> is only kept
- because of backward compatibility and may be withdrawn in a
- future release. If the notation is used the <c>Typename</c>
- element must be spelled correctly, otherwise a run-time error
- will occur.
- </p>
- <p>If the ASN.1 module is compiled with the flags
- <c>per_bin</c> or <c>ber_bin</c> and <c>optimize</c> it is not
- allowed to use the tuple notation. That possibility has been
- removed due to performance reasons. Neither is it allowed to
- use the <c>{ComponentName,Value}</c> notation in case of a
- SEQUENCE or SET type.</p>
- </warning>
<p>Below follows a description of how
values of each type can be represented in Erlang.
</p>
@@ -1008,7 +642,7 @@ Day1 = saturday,
<section>
<marker id="BIT STRING"></marker>
- <title>BIT STRING </title>
+ <title>BIT STRING</title>
<p>The BIT STRING type can be used to model information which
is made up of arbitrary length series of bits. It is intended
to be used for a selection of flags, not for binary files. <br></br>
@@ -1019,56 +653,66 @@ Day1 = saturday,
Bits1 ::= BIT STRING
Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}
</pre>
- <p>There are four different notations available for representation of
+ <p>There are five different notations available for representation of
BIT STRING values in Erlang and as input to the encode functions.</p>
<list type="ordered">
- <item>A list of binary digits (0 or 1).</item>
- <item>A hexadecimal number (or an integer). This format should be
- avoided, since it is easy to misinterpret a <c>BIT STRING</c>
- value in this format. This format may be withdrawn in a future
- release.</item>
+ <item>A bitstring. By default, a BIT STRING with no
+ symbolic names will be decoded to an Erlang bitstring.</item>
<item>A list of atoms corresponding to atoms in the <c>NamedBitList</c>
- in the BIT STRING definition.</item>
+ in the BIT STRING definition. A BIT STRING with symbolic
+ names will always be decoded to this format.</item>
+ <item>A list of binary digits (0 or 1). This format is always
+ accepted as input to the encode functions. A BIT STRING will
+ be decoded to this format if <em>legacy_bit_string</em> option
+ has been given. <em>This format may be withdrawn in a future
+ release.</em>
+ </item>
<item>As <c>{Unused,Binary}</c> where <c>Unused</c> denotes how
- many trailing zero-bits 0 to 7 that are unused in the least
- significant byte in <c>Binary</c>. This notation is only
- available when the ASN.1 files have been compiled with the
- <em>+compact_bit_string</em> flag in the option list. In
- this case it is possible to use all kinds of notation when
- encoding. But the result when decoding is always in the
- compact form. The benefit from this notation is a more
- compact notation when one has large BIT STRINGs. The
- encode/decode performance is also much better in the case of
- large BIT STRINGs. </item>
+ many trailing zero-bits 0 to 7 that are unused in the least
+ significant byte in <c>Binary</c>. This format is always
+ accepted as input to the encode functions. A BIT STRING will
+ be decoded to this format if <em>compact_bit_string</em> has
+ been given. <em>This format may be withdrawn in a future
+ release.</em>
+ </item>
+ <item>A hexadecimal number (or an integer). This format should be
+ avoided, since it is easy to misinterpret a <c>BIT STRING</c>
+ value in this format. <em>This format may be withdrawn in a future
+ release.</em>
+ </item>
</list>
<note>
- <p>Note that it is advised not to use the integer format of a
- BIT STRING, see the second point above.</p>
+ <p>It is recommended to either use the bitstring format (for
+ BIT STRINGs with no symbolic names) or a list of symbolic
+ names (for BIT STRINGs with symbolic names). The other formats
+ should be avoided since they may be withdrawn in a future
+ release.
+ </p>
</note>
<pre>
-Bits1Val1 = [0,1,0,1,1],
+Bits1Val1 = &lt;&lt;0:1,1:1,0:1,1:1,1:1&gt;&gt;,
Bits1Val2 = 16#1A,
-Bits1Val3 = {3,&lt;&lt;0:1,1:1,0:1,1:1,1:1,0:3&gt;&gt;}
+Bits1Val3 = {3,&lt;&lt;0:1,1:1,0:1,1:1,1:1,0:3&gt;&gt;},
+Bits1Val4 = [0,1,0,1,1]
</pre>
- <p>Note that <c>Bits1Val1</c>, <c>Bits1Val2</c> and <c>Bits1Val3</c>
- denote the same value.</p>
+ <p>Note that <c>Bits1Val1</c>, <c>Bits1Val2</c>, <c>Bits1Val3</c>,
+ and <c>Bits1Val1</c> denote the same value.</p>
<pre>
Bits2Val1 = [gnu,punk],
-Bits2Val2 = 2#1110,
+Bits2Val2 = &lt;&lt;2#1110:4&gt;&gt;,
Bits2Val3 = [bar,gnu,gnome],
-Bits2Val4 = [0,1,1,1]
</pre>
- <p>The above <c>Bits2Val2</c>, <c>Bits2Val3</c> and <c>Bits2Val4</c>
- also all denote the same value.</p>
+ <p><c>Bits2Val2</c> and <c>Bits2Val3</c> above denote the same value.</p>
<p><c>Bits2Val1</c> is assigned symbolic values. The assignment means
that the bits corresponding to <c>gnu</c> and <c>punk</c> i.e. bits
2 and 14 are set to 1 and the rest set to 0. The symbolic values
appear as a list of values. If a named value appears, which is not
specified in the type definition, a run-time error will occur.</p>
<p>The compact notation equivalent to the empty BIT STRING is
- <c><![CDATA[{0,<<>>}]]></c>, which in the other notations is <c>[]</c> or
+ <c><![CDATA[{0,<<>>}]]></c>, which in the other notations is
+ <c><![CDATA[<<>>]]></c>, <c>[]</c>, or
<c>0</c>.</p>
- <p>BIT STRINGS may also be sub-typed with for example a SIZE
+ <p>BIT STRINGS may also be sub-typed with, for example, a SIZE
specification:</p>
<pre>
Bits3 ::= BIT STRING (SIZE(0..31)) </pre>
@@ -1149,7 +793,7 @@ TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]
The following example shows how it works:</p>
<p>In a file <c>PrimStrings.asn1</c> the type <c>BMP</c> is defined as
<br></br>
-<c>BMP ::= BMPString</c> then using BER encoding (<c>ber_bin</c>
+<c>BMP ::= BMPString</c> then using BER encoding (<c>ber</c>
option)the input/output format will be:</p>
<pre>
1> <input>{ok,Bytes1} = asn1rt:encode('PrimStrings','BMP',[{0,0,53,53},{0,0,45,56}]).</input>
@@ -1174,9 +818,9 @@ TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]
<c>utf8_list_to_binary</c>, are in the <c>asn1rt</c> module. In
the example below we assume an asn1 definition <c>UTF ::= UTF8String</c> in a module <c>UTF.asn</c>:</p>
<pre>
-1> <input>asn1ct:compile('UTF',[ber_bin]).</input>
+1> <input>asn1ct:compile('UTF',[ber]).</input>
Erlang ASN.1 version "1.4.3.3" compiling "UTF.asn"
-Compiler Options: [ber_bin]
+Compiler Options: [ber]
--{generated,"UTF.asn1db"}--
--{generated,"UTF.erl"}--
ok
@@ -1287,14 +931,6 @@ Pdu ::= SEQUENCE {
<p>Values can be assigned in Erlang as shown below:</p>
<pre>
MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}. </pre>
-<note>
- <p>
- In very early versions of the asn1 compiler it was also possible to
- specify the values of the components in
- a SEQUENCE or a SET as a list of tuples <c>{ComponentName,Value}</c>.
- This is no longer supported.
- </p>
-</note>
<p>The decode functions will return a record as result when decoding
a <c>SEQUENCE</c> or a <c>SET</c>.
<marker id="DEFAULT"></marker>
@@ -1739,12 +1375,9 @@ SS ::= SET {
1> <input>Val = 'Values':tt().</input>
{'TT',77,["kalle","kula"]}
2> <input>{ok,Bytes} = 'Values':encode('TT',Val).</input>
-{ok,["0",
- [18],
- [[[128],[1],"M"],["\\241","\\r",[[[4],[5],"kalle"],[[4],[4],"kula"]]]]]}
-3> <input>FlatBytes = lists:flatten(Bytes).</input>
-[48,18,128,1,77,161,13,4,5,107,97,108,108,101,4,4,107,117,108,97]
-4> <input>'Values':decode('TT',FlatBytes).</input>
+{ok,&lt;&lt;48,18,128,1,77,161,13,4,5,107,97,108,108,101,4,4,
+ 107,117,108,97&gt;&gt;}
+4> <input>'Values':decode('TT',Bytes).</input>
{ok,{'TT',77,["kalle","kula"]}}
5>
</pre>
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index 3be58cbc8e..f04bac9fec 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2012</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -41,6 +41,19 @@
encode/decode functions. There are also some generic functions which
can be used in during development of applications which handles ASN.1
data (encoded as BER or PER).</p>
+ <note>
+ <p>In R16, the options have been simplified. The back-end is chosen
+ using one of the options <c>ber</c>, <c>per</c>, or <c>uper</c>.
+ The options <c>optimize</c>, <c>nif</c>, and <c>driver</c> options
+ are no longer necessary (and the ASN.1 compiler will print a
+ warning if they are used). The options <c>ber_bin</c>, <c>per_bin</c>,
+ and <c>uper_bin</c> options will still work, but will print a warning.
+ </p>
+ <p>Another change in R16 is that the generated <c>encode/2</c>
+ function (and <c>asn1rt:encode/3</c>) always returns a binary.
+ The <c>encode/2</c> function for the BER back-end used to return
+ an iolist.</p>
+ </note>
</description>
<funcs>
<func>
@@ -50,9 +63,10 @@
<type>
<v>Asn1module = atom() | string()</v>
<v>Options = [Option| OldOption]</v>
- <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string |
- noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} | optimize |
- nif | asn1config | undec_rest | {inline, OutputName} | inline |
+ <v>Option = ber | per | uper | der | compact_bit_string |
+ legacy_bit_string |
+ noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} |
+ asn1config | undec_rest |
{macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
@@ -107,12 +121,10 @@ File3.asn </pre>
<c>Options</c> is a list with options specific for the asn1
compiler and options that are applied to the Erlang compiler.
The latter are those that not is recognized as asn1 specific.
- For <em>preferred option use</em> see <seealso
- marker="asn1_ug#preferred option use">Preferred Option Use
- section in users guide</seealso>. Available options are:
+ Available options are:
</p>
<taglist>
- <tag><c>ber | ber_bin | per | per_bin | uper_bin</c></tag>
+ <tag><c>ber | per | uper</c></tag>
<item>
<p>
The encoding rule to be used. The supported encoding rules
@@ -120,23 +132,12 @@ File3.asn </pre>
PER aligned (Packed Encoding Rules) and PER unaligned.
If the encoding rule option is omitted <c>ber</c>
is the default.
- The <c>per_bin</c> option means the aligned
- variant. To use the unaligned variant the <c>uper_bin</c>
- option has to be used.
</p>
<p>
The generated Erlang module always gets the same name
as the ASN.1 module and as a consequence of this only one
encoding rule per ASN.1 module can be used at runtime.
</p>
- <p>
- The <c>ber_bin</c> and <c>per_bin</c> options are
- equivalent with the <c>OldOptions</c> <c>ber</c> and <c>per</c>
- with the difference that the generated encoding/decoding
- functions take advantage of the bit syntax, which in most
- cases increases the performance considerably. The result
- from encoding is a binary or an iolist.
- </p>
</item>
<tag><c>der</c></tag>
<item>
@@ -144,7 +145,7 @@ File3.asn </pre>
By this option the Distinguished Encoding Rules (DER) is chosen.
DER is regarded as a specialized variant of the BER encoding
rule, therefore the <c>der</c> option only makes sense together
- with the <c>ber</c> or <c>ber_bin</c> option.
+ with the <c>ber</c> option.
This option
sometimes adds sorting and value checks when encoding, which
implies a slower encoding. The decoding routines are the same
@@ -154,22 +155,26 @@ File3.asn </pre>
<tag><c>compact_bit_string</c></tag>
<item>
<p>
- Makes it possible to use a compact notation for values
- of the BIT STRING type in Erlang. The notation:
+ The BIT STRING type will be decoded to the "compact notation".
+ <em>This option is not recommended for new code.</em>
+ </p>
+ <p>For details see
+ <seealso marker="asn1_ug#BIT STRING">
+ BIT STRING type section in the Users Guide
+ </seealso>.
</p>
- <pre>
-BitString = {Unused, Binary},
-Unused = integer(),
-Binary = binary()
- </pre>
+ </item>
+ <tag><c>legacy_bit_string</c></tag>
+ <item>
<p>
- <c>Unused</c> must be a number in the range 0 to 7. It
- tells how many bits in the least significant byte in
- <c>Binary</c> that is unused.
- For details see
+ The BIT STRING type will be decoded to the legacy
+ format, i.e. a list of zeroes and ones.
+ <em>This option is not recommended for new code.</em>
+ </p>
+ <p>For details see
<seealso marker="asn1_ug#BIT STRING">
- BIT STRING type section in users guide
- </seealso>.
+ BIT STRING type section in the Users Guide
+ </seealso>.
</p>
</item>
<tag><c>{n2n, EnumTypeName}</c></tag>
@@ -206,28 +211,6 @@ Binary = binary()
shall be placed. If omitted the files are placed in the
current directory.</p>
</item>
- <tag><c>optimize</c></tag>
- <item>
- <p>This option is only valid together with one of the
- <c>per_bin</c>
- or <c>ber_bin</c> option. It gives time optimized code
- generated and it uses another runtime module and
- in the <c>per_bin</c> case a nif. The result
- in the <c>per_bin</c> case from an encode when compiled
- with this option will be a binary.</p>
- </item>
- <tag><c>driver</c></tag>
- <item>
- <p>As of R15B this means the same as the <c>nif</c> option. Kept for
- backwards compatability reasons.</p>
- </item>
- <tag><c>nif</c></tag>
- <item>
- <p>Option valid together with <c>ber_bin</c> and <c>optimize</c>
- options. It enables the use of several nifs that gives faster
- encode and decode. Nifs are only enabled by the explicit use of
- the option <c>nif</c></p>
- </item>
<tag><c>asn1config</c></tag>
<item>
<p>When one of the specialized decodes, exclusive or
@@ -255,32 +238,6 @@ Binary = binary()
list or a binary. Earlier versions of the compiler ignored
those following bytes.</p>
</item>
- <tag><c>{inline, OutputName}</c></tag>
- <item>
- <p>Compiling with this option gives one output module
- containing all asn1 run-time functionality. The asn1 specs
- are provided in a target module Module.set.asn as described
- <seealso marker="#asn1set">above</seealso>. The name of the
- resulting module containing generated encode/decode functions
- and in-lined run-time functions will be
- <c>OutputName.erl</c>. The merging/in-lining of code is done
- by the <c>igor</c> module of <c>syntax_tools</c>. By default
- the functions generated from the first asn1 spec in the
- <c>.set.asn</c> are exported, unless a
- <c>{export, [atom()]}</c> or <c>{export_all, true}</c> option
- are provided. The list of atoms are names of chosen asn1
- specs from the <c>.set.asn</c> file. </p>
- <p>When used together with <c>nif</c> for <c>ber_bin</c>, the
- asn1 nifs will be used if the <c>asn1rt_nif</c> module is
- available. If it is not available, a slower erlang fallback
- will be used.</p>
- </item>
- <tag><c>inline</c></tag>
- <item>
- <p>It is also possible to use the sole argument <c>inline</c>.
- It is as <c>{inline, OutputName}</c>, but the output file gets the
- default name of the source <c>.set.asn</c> file.</p>
- </item>
<tag><c>{macro_name_prefix, Prefix}</c></tag>
<item>
<p>All macro names generated by the compiler are prefixed with
@@ -327,13 +284,12 @@ Binary = binary()
<type>
<v>Module = Type = atom()</v>
<v>Value = term()</v>
- <v>Bytes = [Int] when integer(Int), Int >= 0, Int =&lt; 255</v>
+ <v>Bytes = binary()</v>
<v>Reason = term()</v>
</type>
<desc>
<p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 module
- <c>Module</c>. Returns a list of bytes if successful. To get as fast execution as
- possible the
+ <c>Module</c>. To get as fast execution as possible the
encode function only performs rudimentary tests that the input
<c>Value</c>
is a correct instance of <c>Type</c>. The length of strings is for example
@@ -348,10 +304,10 @@ Binary = binary()
<type>
<v>Module = Type = atom()</v>
<v>Value = Reason = term()</v>
- <v>Bytes = [Int] when integer(Int), Int >= 0, Int =&lt; 255</v>
+ <v>Bytes = binary()</v>
</type>
<desc>
- <p>Decodes <c>Type</c> from <c>Module</c> from the list of bytes
+ <p>Decodes <c>Type</c> from <c>Module</c> from the binary
<c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p>
</desc>
</func>
diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml
index 0c3c257189..2b1b108ab1 100644
--- a/lib/asn1/doc/src/asn1rt.xml
+++ b/lib/asn1/doc/src/asn1rt.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -47,35 +47,34 @@
<type>
<v>Module = Type = atom()</v>
<v>Value = Reason = term()</v>
- <v>Bytes = binary | [Int] when integer(Int), Int >= 0, Int =&lt; 255 | binary</v>
+ <v>Bytes = binary</v>
</type>
<desc>
- <p>Decodes <c>Type</c> from <c>Module</c> from the list of bytes or
- binary <c>Bytes</c>. If the module is compiled with <c>ber_bin</c>
- or <c>per_bin</c> option <c>Bytes</c> must be a binary.
+ <p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>.
Returns <c>{ok,Value}</c> if successful.</p>
</desc>
</func>
<func>
- <name>encode(Module,Type,Value)-> {ok,BinOrList} | {error,Reason}</name>
+ <name>encode(Module,Type,Value)-> {ok,Bytes} | {error,Reason}</name>
<fsummary>Encode an ASN.1 value.</fsummary>
<type>
<v>Module = Type = atom()</v>
<v>Value = term()</v>
- <v>BinOrList = Bytes | binary()</v>
- <v>Bytes = [Int|binary|Bytes] when integer(Int), Int >= 0, Int =&lt; 255</v>
+ <v>Bytes = binary</v>
<v>Reason = term()</v>
</type>
<desc>
<p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 module
<c>Module</c>. Returns a possibly nested list of bytes and or binaries
- if successful. If <c>Module</c> was compiled with the options <c>per_bin</c> and <c>optimize</c> the result is a binary. To get as
- fast execution as possible the
+ if successful. To get as fast execution as possible the
encode function only performs rudimentary tests that the input
<c>Value</c>
is a correct instance of <c>Type</c>. The length of strings is for example
not always checked. </p>
+ <note>
+ <p>Starting in R16, <c>Bytes</c> is always a binary.</p>
+ </note>
</desc>
</func>
@@ -95,28 +94,6 @@
</func>
<func>
- <name>load_driver() -> ok | {error,Reason}</name>
- <fsummary>Loads the linked-in driver. (deprecated)</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>This function is obsolete and will be removed in R16A</p>
- </desc>
- </func>
-
- <func>
- <name>unload_driver() -> ok | {error,Reason}</name>
- <fsummary>Unloads the linked-in driver. (deprecated)</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>This function is obsolete and will be removed in R16A</p>
- </desc>
- </func>
-
- <func>
<name>utf8_binary_to_list(UTF8Binary) -> {ok,UnicodeList} | {error,Reason}</name>
<fsummary>Transforms an utf8 encoded binary to a unicode list.</fsummary>
<type>
diff --git a/lib/asn1/doc/src/exclusive_Win_But.ps b/lib/asn1/doc/src/exclusive_Win_But.ps
deleted file mode 100644
index 387b978c7f..0000000000
--- a/lib/asn1/doc/src/exclusive_Win_But.ps
+++ /dev/null
@@ -1,465 +0,0 @@
-%!PS-Adobe-2.0
-%%Title: exclusive_Win_But.ps
-%%Creator: fig2dev Version 3.2 Patchlevel 1
-%%CreationDate: Tue Oct 28 13:39:26 2003
-%%For: bertil@super (Bertil Karlsson,UAB/F/P)
-%%Orientation: Portrait
-%%BoundingBox: 40 368 572 423
-%%Pages: 1
-%%BeginSetup
-%%IncludeFeature: *PageSize Letter
-%%EndSetup
-%%Magnification: 1.0000
-%%EndComments
-/MyAppDict 100 dict dup begin def
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-
-end
-save
-22.0 480.5 translate
-1 -1 scale
-.9 .9 scale % to make patterns same scale as in xfig
-
-% This junk string is used by the show operators
-/PATsstr 1 string def
-/PATawidthshow { % cx cy cchar rx ry string
- % Loop over each character in the string
- { % cx cy cchar rx ry char
- % Show the character
- dup % cx cy cchar rx ry char char
- PATsstr dup 0 4 -1 roll put % cx cy cchar rx ry char (char)
- false charpath % cx cy cchar rx ry char
- /clip load PATdraw
- % Move past the character (charpath modified the
- % current point)
- currentpoint % cx cy cchar rx ry char x y
- newpath
- moveto % cx cy cchar rx ry char
- % Reposition by cx,cy if the character in the string is cchar
- 3 index eq { % cx cy cchar rx ry
- 4 index 4 index rmoveto
- } if
- % Reposition all characters by rx ry
- 2 copy rmoveto % cx cy cchar rx ry
- } forall
- pop pop pop pop pop % -
- currentpoint
- newpath
- moveto
-} bind def
-/PATcg {
- 7 dict dup begin
- /lw currentlinewidth def
- /lc currentlinecap def
- /lj currentlinejoin def
- /ml currentmiterlimit def
- /ds [ currentdash ] def
- /cc [ currentrgbcolor ] def
- /cm matrix currentmatrix def
- end
-} bind def
-% PATdraw - calculates the boundaries of the object and
-% fills it with the current pattern
-/PATdraw { % proc
- save exch
- PATpcalc % proc nw nh px py
- 5 -1 roll exec % nw nh px py
- newpath
- PATfill % -
- restore
-} bind def
-% PATfill - performs the tiling for the shape
-/PATfill { % nw nh px py PATfill -
- PATDict /CurrentPattern get dup begin
- setfont
- % Set the coordinate system to Pattern Space
- PatternGState PATsg
- % Set the color for uncolored pattezns
- PaintType 2 eq { PATDict /PColor get PATsc } if
- % Create the string for showing
- 3 index string % nw nh px py str
- % Loop for each of the pattern sources
- 0 1 Multi 1 sub { % nw nh px py str source
- % Move to the starting location
- 3 index 3 index % nw nh px py str source px py
- moveto % nw nh px py str source
- % For multiple sources, set the appropriate color
- Multi 1 ne { dup PC exch get PATsc } if
- % Set the appropriate string for the source
- 0 1 7 index 1 sub { 2 index exch 2 index put } for pop
- % Loop over the number of vertical cells
- 3 index % nw nh px py str nh
- { % nw nh px py str
- currentpoint % nw nh px py str cx cy
- 2 index show % nw nh px py str cx cy
- YStep add moveto % nw nh px py str
- } repeat % nw nh px py str
- } for
- 5 { pop } repeat
- end
-} bind def
-
-% PATkshow - kshow with the current pattezn
-/PATkshow { % proc string
- exch bind % string proc
- 1 index 0 get % string proc char
- % Loop over all but the last character in the string
- 0 1 4 index length 2 sub {
- % string proc char idx
- % Find the n+1th character in the string
- 3 index exch 1 add get % string proe char char+1
- exch 2 copy % strinq proc char+1 char char+1 char
- % Now show the nth character
- PATsstr dup 0 4 -1 roll put % string proc chr+1 chr chr+1 (chr)
- false charpath % string proc char+1 char char+1
- /clip load PATdraw
- % Move past the character (charpath modified the current point)
- currentpoint newpath moveto
- % Execute the user proc (should consume char and char+1)
- mark 3 1 roll % string proc char+1 mark char char+1
- 4 index exec % string proc char+1 mark...
- cleartomark % string proc char+1
- } for
- % Now display the last character
- PATsstr dup 0 4 -1 roll put % string proc (char+1)
- false charpath % string proc
- /clip load PATdraw
- neewath
- pop pop % -
-} bind def
-% PATmp - the makepattern equivalent
-/PATmp { % patdict patmtx PATmp patinstance
- exch dup length 7 add % We will add 6 new entries plus 1 FID
- dict copy % Create a new dictionary
- begin
- % Matrix to install when painting the pattern
- TilingType PATtcalc
- /PatternGState PATcg def
- PatternGState /cm 3 -1 roll put
- % Check for multi pattern sources (Level 1 fast color patterns)
- currentdict /Multi known not { /Multi 1 def } if
- % Font dictionary definitions
- /FontType 3 def
- % Create a dummy encoding vector
- /Encoding 256 array def
- 3 string 0 1 255 {
- Encoding exch dup 3 index cvs cvn put } for pop
- /FontMatrix matrix def
- /FontBBox BBox def
- /BuildChar {
- mark 3 1 roll % mark dict char
- exch begin
- Multi 1 ne {PaintData exch get}{pop} ifelse % mark [paintdata]
- PaintType 2 eq Multi 1 ne or
- { XStep 0 FontBBox aload pop setcachedevice }
- { XStep 0 setcharwidth } ifelse
- currentdict % mark [paintdata] dict
- /PaintProc load % mark [paintdata] dict paintproc
- end
- gsave
- false PATredef exec true PATredef
- grestore
- cleartomark % -
- } bind def
- currentdict
- end % newdict
- /foo exch % /foo newlict
- definefont % newfont
-} bind def
-% PATpcalc - calculates the starting point and width/height
-% of the tile fill for the shape
-/PATpcalc { % - PATpcalc nw nh px py
- PATDict /CurrentPattern get begin
- gsave
- % Set up the coordinate system to Pattern Space
- % and lock down pattern
- PatternGState /cm get setmatrix
- BBox aload pop pop pop translate
- % Determine the bounding box of the shape
- pathbbox % llx lly urx ury
- grestore
- % Determine (nw, nh) the # of cells to paint width and height
- PatHeight div ceiling % llx lly urx qh
- 4 1 roll % qh llx lly urx
- PatWidth div ceiling % qh llx lly qw
- 4 1 roll % qw qh llx lly
- PatHeight div floor % qw qh llx ph
- 4 1 roll % ph qw qh llx
- PatWidth div floor % ph qw qh pw
- 4 1 roll % pw ph qw qh
- 2 index sub cvi abs % pw ph qs qh-ph
- exch 3 index sub cvi abs exch % pw ph nw=qw-pw nh=qh-ph
- % Determine the starting point of the pattern fill
- %(px, py)
- 4 2 roll % nw nh pw ph
- PatHeight mul % nw nh pw py
- exch % nw nh py pw
- PatWidth mul exch % nw nh px py
- end
-} bind def
-
-% Save the original routines so that we can use them later on
-/oldfill /fill load def
-/oldeofill /eofill load def
-/oldstroke /stroke load def
-/oldshow /show load def
-/oldashow /ashow load def
-/oldwidthshow /widthshow load def
-/oldawidthshow /awidthshow load def
-/oldkshow /kshow load def
-
-% These defs are necessary so that subsequent procs don't bind in
-% the originals
-/fill { oldfill } bind def
-/eofill { oldeofill } bind def
-/stroke { oldstroke } bind def
-/show { oldshow } bind def
-/ashow { oldashow } bind def
-/widthshow { oldwidthshow } bind def
-/awidthshow { oldawidthshow } bind def
-/kshow { oldkshow } bind def
-/PATredef {
- MyAppDict begin
- {
- /fill { /clip load PATdraw newpath } bind def
- /eofill { /eoclip load PATdraw newpath } bind def
- /stroke { PATstroke } bind def
- /show { 0 0 null 0 0 6 -1 roll PATawidthshow } bind def
- /ashow { 0 0 null 6 3 roll PATawidthshow }
- bind def
- /widthshow { 0 0 3 -1 roll PATawidthshow }
- bind def
- /awidthshow { PATawidthshow } bind def
- /kshow { PATkshow } bind def
- } {
- /fill { oldfill } bind def
- /eofill { oldeofill } bind def
- /stroke { oldstroke } bind def
- /show { oldshow } bind def
- /ashow { oldashow } bind def
- /widthshow { oldwidthshow } bind def
- /awidthshow { oldawidthshow } bind def
- /kshow { oldkshow } bind def
- } ifelse
- end
-} bind def
-false PATredef
-% Conditionally define setcmykcolor if not available
-/setcmykcolor where { pop } {
- /setcmykcolor {
- 1 sub 4 1 roll
- 3 {
- 3 index add neg dup 0 lt { pop 0 } if 3 1 roll
- } repeat
- setrgbcolor - pop
- } bind def
-} ifelse
-/PATsc { % colorarray
- aload length % c1 ... cn length
- dup 1 eq { pop setgray } { 3 eq { setrgbcolor } { setcmykcolor
- } ifelse } ifelse
-} bind def
-/PATsg { % dict
- begin
- lw setlinewidth
- lc setlinecap
- lj setlinejoin
- ml setmiterlimit
- ds aload pop setdash
- cc aload pop setrgbcolor
- cm setmatrix
- end
-} bind def
-
-/PATDict 3 dict def
-/PATsp {
- true PATredef
- PATDict begin
- /CurrentPattern exch def
- % If it's an uncolored pattern, save the color
- CurrentPattern /PaintType get 2 eq {
- /PColor exch def
- } if
- /CColor [ currentrgbcolor ] def
- end
-} bind def
-% PATstroke - stroke with the current pattern
-/PATstroke {
- countdictstack
- save
- mark
- {
- currentpoint strokepath moveto
- PATpcalc % proc nw nh px py
- clip newpath PATfill
- } stopped {
- (*** PATstroke Warning: Path is too complex, stroking
- with gray) =
- cleartomark
- restore
- countdictstack exch sub dup 0 gt
- { { end } repeat } { pop } ifelse
- gsave 0.5 setgray oldstroke grestore
- } { pop restore pop } ifelse
- newpath
-} bind def
-/PATtcalc { % modmtx tilingtype PATtcalc tilematrix
- % Note: tiling types 2 and 3 are not supported
- gsave
- exch concat % tilingtype
- matrix currentmatrix exch % cmtx tilingtype
- % Tiling type 1 and 3: constant spacing
- 2 ne {
- % Distort the pattern so that it occupies
- % an integral number of device pixels
- dup 4 get exch dup 5 get exch % tx ty cmtx
- XStep 0 dtransform
- round exch round exch % tx ty cmtx dx.x dx.y
- XStep div exch XStep div exch % tx ty cmtx a b
- 0 YStep dtransform
- round exch round exch % tx ty cmtx a b dy.x dy.y
- YStep div exch YStep div exch % tx ty cmtx a b c d
- 7 -3 roll astore % { a b c d tx ty }
- } if
- grestore
-} bind def
-/PATusp {
- false PATredef
- PATDict begin
- CColor PATsc
- end
-} bind def
-
-% left45
-11 dict begin
-/PaintType 1 def
-/PatternType 1 def
-/TilingType 1 def
-/BBox [0 0 1 1] def
-/XStep 1 def
-/YStep 1 def
-/PatWidth 1 def
-/PatHeight 1 def
-/Multi 2 def
-/PaintData [
- { clippath } bind
- { 32 32 true [ 32 0 0 -32 0 32 ]
- {<808080804040404020202020101010100808080804040404
- 020202020101010180808080404040402020202010101010
- 080808080404040402020202010101018080808040404040
- 202020201010101008080808040404040202020201010101
- 808080804040404020202020101010100808080804040404
- 0202020201010101>}
- imagemask } bind
-] def
-/PaintProc {
- pop
- exec fill
-} def
-currentdict
-end
-/P4 exch def
-1.1111 1.1111 scale %restore scale
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
- bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
- 4 -2 roll mul srgb} bind def
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-%%EndProlog
-
-$F2psBegin
-10 setmiterlimit
-n -1000 2854 m -1000 -1000 l 10152 -1000 l 10152 2854 l cp clip
- 0.06000 0.06000 sc
-%%Page: 1 1
-% Polyline
-7.500 slw
-n 325 975 m 1125 975 l 1125 1575 l 325 1575 l cp gs col-1 s gr
-% Polyline
-n 1125 975 m 4650 975 l 4650 1575 l 1125 1575 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def
-15.00 15.00 sc P4 [16 0 0 -16 75.00 65.00] PATmp PATsp ef gr PATusp gs col-1 s gr
-% Polyline
-n 4650 975 m 5325 975 l 5325 1575 l 4650 1575 l cp gs col-1 s gr
-% Polyline
-n 5325 975 m 9140 975 l 9140 1575 l 5325 1575 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def
-15.00 15.00 sc P4 [16 0 0 -16 355.00 65.00] PATmp PATsp ef gr PATusp gs col-1 s gr
-/Times-Roman ff 180.00 scf sf
-4725 1800 m
-gs 1 -1 sc (enabled) col-1 sh gr
-/Times-Roman ff 180.00 scf sf
-6450 1800 m
-gs 1 -1 sc (actions:possibleActions) col-1 sh gr
-/Times-Roman ff 180.00 scf sf
-2550 1800 m
-gs 1 -1 sc (buttonList) col-1 sh gr
-/Times-Roman ff 180.00 scf sf
-600 1800 m
-gs 1 -1 sc (state) col-1 sh gr
-$F2psEnd
-rs
-end
-showpage
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 5cd7a1c4b8..4b5bba742c 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2012</year>
+ <year>2004</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,23 +31,73 @@
<p>This document describes the changes made to the asn1 application.</p>
-<section><title>Asn1 1.8.1.2</title>
+<section><title>Asn1 2.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
- Open types greater than 16383 bytes will now be correctly
- encoded and decoded.</p>
+ Fix some Makefile rules that didn't support silent rules.
+ Thanks to Anthony Ramine.</p>
<p>
- Own Id: OTP-11223 Aux Id: seq12386 </p>
+ Own Id: OTP-11111</p>
+ </item>
+ <item>
+ <p>PER/UPER: A semi-constrained INTEGER with a non-zero
+ lower bound would be incorrectly decoded. This bug was
+ introduced in R16.</p>
+ <p>PER/UPER: Given <c>INTEGER (10..MAX, ...)</c>,
+ attempting to decode any integer below 10 would cause the
+ encoder to enter an infinite loop.</p>
+ <p>PER/UPER: For a type with an extensible SIZE
+ constraint, sizes outside of the root range were
+ incorrectly encoded.</p>
+ <p>Given a constraint such as <c>(SIZE (5, ...))</c>,
+ encoding a size less than 5 would fail (PER/UPER).
+ Similarly, for BER decoding would fail.</p>
+ <p>PER: The encoder did not align a known multiplier
+ string (such as IA5String) of length 16 bits (exactly) to
+ an octet boundary.</p>
+ <p>In rare circumstances, DEFAULT values for the UPER
+ backend could be wrongly encoded.</p>
+ <p>
+ Own Id: OTP-11134</p>
+ </item>
+ <item>
+ <p>UPER: The compiler would crash when compiling an
+ ENUMERATED having more than 63 extended values.</p>
+ <p>PER/UPER: A SEQUENCE with more 64 extended values
+ could not be decoded.</p>
+ <p>
+ Own Id: OTP-11153</p>
+ </item>
+ <item>
+ <p>
+ When decoding a SEQUENCE defined inline inside a an
+ extension addition group, the record named generated by
+ the decoding code would not match the name in the
+ generated .hrl file.</p>
+ <p>
+ Own Id: OTP-11154 Aux Id: seq12339 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
</item>
</list>
</section>
</section>
-<section><title>Asn1 1.8.1.1</title>
+<section><title>Asn1 2.0.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -64,6 +114,110 @@
</section>
+<section><title>Asn1 2.0.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The generated decoder for the 'per' and 'uper'
+ backends did not correctly decode ENUMERATEDs with a
+ single value.</p>
+ <p>The generated encoder for the 'per' and 'uper'
+ backends generated an empty binary for a top-level type
+ that did not need to be encoded (such as an ENUMERATED
+ with a single value). The correct result should be a
+ binary containing a 0 byte.</p>
+ <p>
+ Own Id: OTP-10916 Aux Id: seq12270 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 2.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed broken table constraints within a SET OF or
+ SEQUENCE OF for the BER backend.</p>
+ <p>
+ Own Id: OTP-10853 Aux Id: seq12245 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 2.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Encoding SEQUENCEs with multiple extension addition
+ groups with optional values could fail (depending both on
+ the specification and whether all values were provided).</p>
+ <p>
+ Own Id: OTP-10664</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The options for the ASN.1 compiler has been
+ drastically simplified. The backend is chosen by using
+ <c>ber</c>, <c>per</c>, or <c>uper</c>. The options
+ <c>optimize</c>, <c>nif</c>, and <c>driver</c> are no
+ longer needed. The old options will still work, but will
+ issue a warning.</p>
+ <p>Another change is that generated <c>encode/2</c>
+ function will always return a binary (some backends used
+ to return an iolist).</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-10410 Aux Id: kunagi-254 [165] </p>
+ </item>
+ <item>
+ <p>
+ The ASN.1 compiler generates faster decode functions for
+ PER and UPER. Some minor improvements have also been made
+ for PER/UPER encoding, and to the BER backend.</p>
+ <p>
+ Own Id: OTP-10519 Aux Id: kunagi-322 [233] </p>
+ </item>
+ <item>
+ <p>The ASN.1 compiler will now always include necessary
+ run-time functions in the generated Erlang modules
+ (except for <c>asn1rt_nif</c> which is still neeeded). If
+ the option '<c>inline</c>' is used the ASN.1 compiler
+ will generate a warning. But if
+ '<c>{inline,OutputFile}</c>' is use, the ASN.1 compiler
+ will refuse to compile the file. (Use a <c>.set.asn</c>
+ file if you need to remove the output file.)</p>
+ <p>The '<c>BIT STRING</c>' type will now be decoded as
+ Erlang bitstrings by default. Use the new
+ <c>legacy_bit_string</c> option to encode as lists of
+ ones and zeroes. (The <c>compact_bit_string</c> option
+ still works as before.)</p>
+ <p>Open types are now always returned as binaries (when
+ there is no information allowing them to be decoded).</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-10588 Aux Id: kunagi-341 [252] </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -545,7 +699,7 @@
ENUMERATION type, the compilation will be terminated with an
error code.<br/>
Below follows an example on how to use the option from the command line with <c>erlc</c>:<br/>
- <c>erlc -bper_bin +optimize +driver +"{n2n,'CauseMisc'}" +"{n2n,'CausePcl'}" MyModyle.asn</c>
+ <c>erlc -bper+"{n2n,'CauseMisc'}" +"{n2n,'CausePcl'}" MyModyle.asn</c>
</p>
<p>
Own Id: OTP-8136 Aux Id: seq11347 </p>
diff --git a/lib/asn1/doc/src/selective_TypeList.ps b/lib/asn1/doc/src/selective_TypeList.ps
deleted file mode 100644
index 0d1f301240..0000000000
--- a/lib/asn1/doc/src/selective_TypeList.ps
+++ /dev/null
@@ -1,266 +0,0 @@
-%!PS-Adobe-2.0
-%%Title: selective_TypeList.ps
-%%Creator: fig2dev Version 3.2 Patchlevel 1
-%%CreationDate: Tue Oct 28 15:52:00 2003
-%%For: bertil@super (Bertil Karlsson,UAB/F/P)
-%%Orientation: Portrait
-%%BoundingBox: 158 178 453 614
-%%Pages: 1
-%%BeginSetup
-%%IncludeFeature: *PageSize Letter
-%%EndSetup
-%%Magnification: 1.0000
-%%EndComments
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-
-end
-save
-55.5 677.0 translate
-1 -1 scale
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
- bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
- 4 -2 roll mul srgb} bind def
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-%%EndProlog
-
-$F2psBegin
-10 setmiterlimit
-n -1000 9310 m -1000 -1000 l 7626 -1000 l 7626 9310 l cp clip
- 0.06000 0.06000 sc
-%%Page: 1 1
-% Arc
-7.500 slw
-gs clippath
-2363 5348 m 2475 5400 l 2352 5407 l 2484 5432 l 2495 5373 l cp
-clip
-n 2470.1 5021.7 378.3 -100.7 89.3 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-n 2363 5348 m 2475 5400 l 2352 5407 l 2357 5378 l 2363 5348 l cp gs 0.00 setgray ef gr col0 s
-% Arc
-gs clippath
-2384 7192 m 2475 7275 l 2355 7245 l 2474 7309 l 2502 7256 l cp
-clip
-n 2896.9 6337.5 1028.0 -114.2 114.2 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-n 2384 7192 m 2475 7275 l 2355 7245 l 2369 7218 l 2384 7192 l cp gs 0.00 setgray ef gr col0 s
-% Arc
-gs clippath
-2448 7504 m 2550 7575 l 2427 7561 l 2553 7608 l 2575 7552 l cp
-clip
-n 2512.5 7462.5 118.6 -108.4 71.6 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-n 2448 7504 m 2550 7575 l 2427 7561 l 2438 7533 l 2448 7504 l cp gs 0.00 setgray ef gr col0 s
-% Arc
-gs clippath
-2869 2255 m 2775 2175 l 2896 2202 l 2775 2141 l 2748 2195 l cp
-clip
-n 1347.8 5222.4 3365.1 42.6 -64.9 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-n 2869 2255 m 2775 2175 l 2896 2202 l 2882 2229 l 2869 2255 l cp gs 0.00 setgray ef gr col0 s
-% Arc
-gs clippath
-5199 1837 m 5250 1950 l 5152 1874 l 5236 1980 l 5283 1943 l cp
-clip
-n 4021.7 2817.4 1503.7 -141.2 -35.2 arc
-gs col0 s gr
- gr
-
-% arrowhead
-n 5199 1837 m 5250 1950 l 5152 1874 l 5176 1856 l 5199 1837 l cp gs 0.00 setgray ef gr col0 s
-/Times-Roman ff 180.00 scf sf
-2400 1350 m
-gs 1 -1 sc (Action ::= SEQUENCE ) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 1590 m
-gs 1 -1 sc ( { ) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 1830 m
-gs 1 -1 sc ( number INTEGER DEFAULT 15,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 2310 m
-gs 1 -1 sc ( }) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 2790 m
-gs 1 -1 sc (Key ::= [11] EXPLICIT Button) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 3030 m
-gs 1 -1 sc (Handle ::= [12] Key) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 3270 m
-gs 1 -1 sc (Button ::= SEQUENCE ) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 3510 m
-gs 1 -1 sc ( {) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 3750 m
-gs 1 -1 sc ( number INTEGER,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 3990 m
-gs 1 -1 sc ( on BOOLEAN) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 4230 m
-gs 1 -1 sc ( }) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 4950 m
-gs 1 -1 sc ( {) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 5190 m
-gs 1 -1 sc ( vsn INTEGER,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 5670 m
-gs 1 -1 sc ( }) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 6150 m
-gs 1 -1 sc (Status ::= SEQUENCE ) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 6390 m
-gs 1 -1 sc ( {) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 6630 m
-gs 1 -1 sc ( state INTEGER,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 6870 m
-gs 1 -1 sc ( buttonList SEQUENCE OF Button,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 7110 m
-gs 1 -1 sc ( enabled BOOLEAN OPTIONAL,) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 7830 m
-gs 1 -1 sc ( noOfActions INTEGER) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 8070 m
-gs 1 -1 sc ( }) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2400 8310 m
-gs 1 -1 sc ( }) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-3150 4725 m
-gs 1 -1 sc (::= CHOICE) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-2400 4710 m
-gs 1 -1 sc (Window) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-2400 5430 m
-gs 1 -1 sc ( status) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-3225 5475 m
-gs 1 -1 sc (E) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-3150 7350 m
-gs 1 -1 sc (CHOICE {) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-2400 7350 m
-gs 1 -1 sc ( actions) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-3975 7575 m
-gs 1 -1 sc (SEQUENCE OF Action) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-2400 7590 m
-gs 1 -1 sc ( possibleActions) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-5550 2100 m
-gs 1 -1 sc (12, on TRUE}) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-2400 2070 m
-gs 1 -1 sc ( handle) col0 sh gr
-/Times-Bold ff 195.00 scf sf
-4950 2100 m
-gs 1 -1 sc (number ) col0 sh gr
-/Times-Roman ff 225.00 scf sf
-1950 5100 m
-gs 1 -1 sc (1) col0 sh gr
-/Times-Roman ff 225.00 scf sf
-1725 6450 m
-gs 1 -1 sc (2) col0 sh gr
-/Times-Roman ff 225.00 scf sf
-2250 7575 m
-gs 1 -1 sc (3) col0 sh gr
-/Times-Roman ff 225.00 scf sf
-4800 4950 m
-gs 1 -1 sc (4) col0 sh gr
-/Times-Roman ff 225.00 scf sf
-4200 1200 m
-gs 1 -1 sc (5) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-3150 2100 m
-gs 1 -1 sc ([0] Handle DEFAULT {) col0 sh gr
-$F2psEnd
-rs
-showpage
diff --git a/lib/asn1/doc/src/selective_Window2.ps b/lib/asn1/doc/src/selective_Window2.ps
deleted file mode 100644
index d5a95ca591..0000000000
--- a/lib/asn1/doc/src/selective_Window2.ps
+++ /dev/null
@@ -1,515 +0,0 @@
-%!PS-Adobe-2.0
-%%Title: selective_Window2.ps
-%%Creator: fig2dev Version 3.2 Patchlevel 1
-%%CreationDate: Tue Oct 28 16:55:06 2003
-%%For: bertil@super (Bertil Karlsson,UAB/F/P)
-%%Orientation: Landscape
-%%BoundingBox: 134 128 460 713
-%%Pages: 1
-%%BeginSetup
-%%IncludeFeature: *PageSize A4
-%%EndSetup
-%%Magnification: 1.0000
-%%EndComments
-/MyAppDict 100 dict dup begin def
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-
-end
-save
-77.5 92.5 translate
- 90 rotate
-1 -1 scale
-.9 .9 scale % to make patterns same scale as in xfig
-
-% This junk string is used by the show operators
-/PATsstr 1 string def
-/PATawidthshow { % cx cy cchar rx ry string
- % Loop over each character in the string
- { % cx cy cchar rx ry char
- % Show the character
- dup % cx cy cchar rx ry char char
- PATsstr dup 0 4 -1 roll put % cx cy cchar rx ry char (char)
- false charpath % cx cy cchar rx ry char
- /clip load PATdraw
- % Move past the character (charpath modified the
- % current point)
- currentpoint % cx cy cchar rx ry char x y
- newpath
- moveto % cx cy cchar rx ry char
- % Reposition by cx,cy if the character in the string is cchar
- 3 index eq { % cx cy cchar rx ry
- 4 index 4 index rmoveto
- } if
- % Reposition all characters by rx ry
- 2 copy rmoveto % cx cy cchar rx ry
- } forall
- pop pop pop pop pop % -
- currentpoint
- newpath
- moveto
-} bind def
-/PATcg {
- 7 dict dup begin
- /lw currentlinewidth def
- /lc currentlinecap def
- /lj currentlinejoin def
- /ml currentmiterlimit def
- /ds [ currentdash ] def
- /cc [ currentrgbcolor ] def
- /cm matrix currentmatrix def
- end
-} bind def
-% PATdraw - calculates the boundaries of the object and
-% fills it with the current pattern
-/PATdraw { % proc
- save exch
- PATpcalc % proc nw nh px py
- 5 -1 roll exec % nw nh px py
- newpath
- PATfill % -
- restore
-} bind def
-% PATfill - performs the tiling for the shape
-/PATfill { % nw nh px py PATfill -
- PATDict /CurrentPattern get dup begin
- setfont
- % Set the coordinate system to Pattern Space
- PatternGState PATsg
- % Set the color for uncolored pattezns
- PaintType 2 eq { PATDict /PColor get PATsc } if
- % Create the string for showing
- 3 index string % nw nh px py str
- % Loop for each of the pattern sources
- 0 1 Multi 1 sub { % nw nh px py str source
- % Move to the starting location
- 3 index 3 index % nw nh px py str source px py
- moveto % nw nh px py str source
- % For multiple sources, set the appropriate color
- Multi 1 ne { dup PC exch get PATsc } if
- % Set the appropriate string for the source
- 0 1 7 index 1 sub { 2 index exch 2 index put } for pop
- % Loop over the number of vertical cells
- 3 index % nw nh px py str nh
- { % nw nh px py str
- currentpoint % nw nh px py str cx cy
- 2 index show % nw nh px py str cx cy
- YStep add moveto % nw nh px py str
- } repeat % nw nh px py str
- } for
- 5 { pop } repeat
- end
-} bind def
-
-% PATkshow - kshow with the current pattezn
-/PATkshow { % proc string
- exch bind % string proc
- 1 index 0 get % string proc char
- % Loop over all but the last character in the string
- 0 1 4 index length 2 sub {
- % string proc char idx
- % Find the n+1th character in the string
- 3 index exch 1 add get % string proe char char+1
- exch 2 copy % strinq proc char+1 char char+1 char
- % Now show the nth character
- PATsstr dup 0 4 -1 roll put % string proc chr+1 chr chr+1 (chr)
- false charpath % string proc char+1 char char+1
- /clip load PATdraw
- % Move past the character (charpath modified the current point)
- currentpoint newpath moveto
- % Execute the user proc (should consume char and char+1)
- mark 3 1 roll % string proc char+1 mark char char+1
- 4 index exec % string proc char+1 mark...
- cleartomark % string proc char+1
- } for
- % Now display the last character
- PATsstr dup 0 4 -1 roll put % string proc (char+1)
- false charpath % string proc
- /clip load PATdraw
- neewath
- pop pop % -
-} bind def
-% PATmp - the makepattern equivalent
-/PATmp { % patdict patmtx PATmp patinstance
- exch dup length 7 add % We will add 6 new entries plus 1 FID
- dict copy % Create a new dictionary
- begin
- % Matrix to install when painting the pattern
- TilingType PATtcalc
- /PatternGState PATcg def
- PatternGState /cm 3 -1 roll put
- % Check for multi pattern sources (Level 1 fast color patterns)
- currentdict /Multi known not { /Multi 1 def } if
- % Font dictionary definitions
- /FontType 3 def
- % Create a dummy encoding vector
- /Encoding 256 array def
- 3 string 0 1 255 {
- Encoding exch dup 3 index cvs cvn put } for pop
- /FontMatrix matrix def
- /FontBBox BBox def
- /BuildChar {
- mark 3 1 roll % mark dict char
- exch begin
- Multi 1 ne {PaintData exch get}{pop} ifelse % mark [paintdata]
- PaintType 2 eq Multi 1 ne or
- { XStep 0 FontBBox aload pop setcachedevice }
- { XStep 0 setcharwidth } ifelse
- currentdict % mark [paintdata] dict
- /PaintProc load % mark [paintdata] dict paintproc
- end
- gsave
- false PATredef exec true PATredef
- grestore
- cleartomark % -
- } bind def
- currentdict
- end % newdict
- /foo exch % /foo newlict
- definefont % newfont
-} bind def
-% PATpcalc - calculates the starting point and width/height
-% of the tile fill for the shape
-/PATpcalc { % - PATpcalc nw nh px py
- PATDict /CurrentPattern get begin
- gsave
- % Set up the coordinate system to Pattern Space
- % and lock down pattern
- PatternGState /cm get setmatrix
- BBox aload pop pop pop translate
- % Determine the bounding box of the shape
- pathbbox % llx lly urx ury
- grestore
- % Determine (nw, nh) the # of cells to paint width and height
- PatHeight div ceiling % llx lly urx qh
- 4 1 roll % qh llx lly urx
- PatWidth div ceiling % qh llx lly qw
- 4 1 roll % qw qh llx lly
- PatHeight div floor % qw qh llx ph
- 4 1 roll % ph qw qh llx
- PatWidth div floor % ph qw qh pw
- 4 1 roll % pw ph qw qh
- 2 index sub cvi abs % pw ph qs qh-ph
- exch 3 index sub cvi abs exch % pw ph nw=qw-pw nh=qh-ph
- % Determine the starting point of the pattern fill
- %(px, py)
- 4 2 roll % nw nh pw ph
- PatHeight mul % nw nh pw py
- exch % nw nh py pw
- PatWidth mul exch % nw nh px py
- end
-} bind def
-
-% Save the original routines so that we can use them later on
-/oldfill /fill load def
-/oldeofill /eofill load def
-/oldstroke /stroke load def
-/oldshow /show load def
-/oldashow /ashow load def
-/oldwidthshow /widthshow load def
-/oldawidthshow /awidthshow load def
-/oldkshow /kshow load def
-
-% These defs are necessary so that subsequent procs don't bind in
-% the originals
-/fill { oldfill } bind def
-/eofill { oldeofill } bind def
-/stroke { oldstroke } bind def
-/show { oldshow } bind def
-/ashow { oldashow } bind def
-/widthshow { oldwidthshow } bind def
-/awidthshow { oldawidthshow } bind def
-/kshow { oldkshow } bind def
-/PATredef {
- MyAppDict begin
- {
- /fill { /clip load PATdraw newpath } bind def
- /eofill { /eoclip load PATdraw newpath } bind def
- /stroke { PATstroke } bind def
- /show { 0 0 null 0 0 6 -1 roll PATawidthshow } bind def
- /ashow { 0 0 null 6 3 roll PATawidthshow }
- bind def
- /widthshow { 0 0 3 -1 roll PATawidthshow }
- bind def
- /awidthshow { PATawidthshow } bind def
- /kshow { PATkshow } bind def
- } {
- /fill { oldfill } bind def
- /eofill { oldeofill } bind def
- /stroke { oldstroke } bind def
- /show { oldshow } bind def
- /ashow { oldashow } bind def
- /widthshow { oldwidthshow } bind def
- /awidthshow { oldawidthshow } bind def
- /kshow { oldkshow } bind def
- } ifelse
- end
-} bind def
-false PATredef
-% Conditionally define setcmykcolor if not available
-/setcmykcolor where { pop } {
- /setcmykcolor {
- 1 sub 4 1 roll
- 3 {
- 3 index add neg dup 0 lt { pop 0 } if 3 1 roll
- } repeat
- setrgbcolor - pop
- } bind def
-} ifelse
-/PATsc { % colorarray
- aload length % c1 ... cn length
- dup 1 eq { pop setgray } { 3 eq { setrgbcolor } { setcmykcolor
- } ifelse } ifelse
-} bind def
-/PATsg { % dict
- begin
- lw setlinewidth
- lc setlinecap
- lj setlinejoin
- ml setmiterlimit
- ds aload pop setdash
- cc aload pop setrgbcolor
- cm setmatrix
- end
-} bind def
-
-/PATDict 3 dict def
-/PATsp {
- true PATredef
- PATDict begin
- /CurrentPattern exch def
- % If it's an uncolored pattern, save the color
- CurrentPattern /PaintType get 2 eq {
- /PColor exch def
- } if
- /CColor [ currentrgbcolor ] def
- end
-} bind def
-% PATstroke - stroke with the current pattern
-/PATstroke {
- countdictstack
- save
- mark
- {
- currentpoint strokepath moveto
- PATpcalc % proc nw nh px py
- clip newpath PATfill
- } stopped {
- (*** PATstroke Warning: Path is too complex, stroking
- with gray) =
- cleartomark
- restore
- countdictstack exch sub dup 0 gt
- { { end } repeat } { pop } ifelse
- gsave 0.5 setgray oldstroke grestore
- } { pop restore pop } ifelse
- newpath
-} bind def
-/PATtcalc { % modmtx tilingtype PATtcalc tilematrix
- % Note: tiling types 2 and 3 are not supported
- gsave
- exch concat % tilingtype
- matrix currentmatrix exch % cmtx tilingtype
- % Tiling type 1 and 3: constant spacing
- 2 ne {
- % Distort the pattern so that it occupies
- % an integral number of device pixels
- dup 4 get exch dup 5 get exch % tx ty cmtx
- XStep 0 dtransform
- round exch round exch % tx ty cmtx dx.x dx.y
- XStep div exch XStep div exch % tx ty cmtx a b
- 0 YStep dtransform
- round exch round exch % tx ty cmtx a b dy.x dy.y
- YStep div exch YStep div exch % tx ty cmtx a b c d
- 7 -3 roll astore % { a b c d tx ty }
- } if
- grestore
-} bind def
-/PATusp {
- false PATredef
- PATDict begin
- CColor PATsc
- end
-} bind def
-
-% crosshatch45
-11 dict begin
-/PaintType 1 def
-/PatternType 1 def
-/TilingType 1 def
-/BBox [0 0 1 1] def
-/XStep 1 def
-/YStep 1 def
-/PatWidth 1 def
-/PatHeight 1 def
-/Multi 2 def
-/PaintData [
- { clippath } bind
- { 32 32 true [ 32 0 0 -32 0 32 ]
- {<828282824444444428282828101010102828282844444444
- 828282820101010182828282444444442828282810101010
- 282828284444444482828282010101018282828244444444
- 282828281010101028282828444444448282828201010101
- 828282824444444428282828101010102828282844444444
- 8282828201010101>}
- imagemask } bind
-] def
-/PaintProc {
- pop
- exec fill
-} def
-currentdict
-end
-/P6 exch def
-1.1111 1.1111 scale %restore scale
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
- bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
- 4 -2 roll mul srgb} bind def
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-%%EndProlog
-
-$F2psBegin
-10 setmiterlimit
-n -1000 7375 m -1000 -1000 l 11348 -1000 l 11348 7375 l cp clip
- 0.06000 0.06000 sc
-%%Page: 1 1
-% Polyline
-7.500 slw
-n 3150 975 m 3150 1500 l gs col0 s gr
-% Polyline
-n 4800 3600 m 9975 3600 l 9975 4125 l 4800 4125 l cp gs col0 s gr
-% Polyline
-n 5925 3600 m 5925 4125 l gs col0 s gr
-% Polyline
-n 7800 4200 m 7500 5325 l gs col0 s gr
-% Polyline
-n 5400 5550 m 7200 5550 l 7200 6075 l 5400 6075 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def
-15.00 15.00 sc P6 [16 0 0 -16 360.00 370.00] PATmp PATsp ef gr PATusp gs col0 s gr
-% Polyline
-n 7200 5550 m 9300 5550 l 9300 6075 l 7200 6075 l cp gs col0 s gr
-% Polyline
-n 2400 975 m 9700 975 l 9700 1500 l 2400 1500 l cp gs col0 s gr
-% Polyline
-n 6150 975 m 6150 1500 l gs col0 s gr
-% Polyline
-n 6825 975 m 6825 1500 l gs col0 s gr
-% Polyline
- [60] 0 sd
-n 7800 975 m 7800 1500 l gs col0 s gr [] 0 sd
-% Polyline
- [60] 0 sd
-n 8775 975 m 8775 1500 l gs col0 s gr [] 0 sd
-% Polyline
-gs clippath
-6667 1636 m 6775 1575 l 6709 1679 l 6807 1586 l 6765 1543 l cp
-clip
-n 6775 1575 m 4800 3450 l gs col0 s gr gr
-
-% arrowhead
-n 6667 1636 m 6775 1575 l 6709 1679 l col0 s
-% Polyline
-n 7850 1575 m 9975 3450 l gs col0 s gr
-/Times-Roman ff 180.00 scf sf
-600 1275 m
-gs 1 -1 sc (Window:status message) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-2550 1800 m
-gs 1 -1 sc (state) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-4275 1800 m
-gs 1 -1 sc (buttonList) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-8625 1875 m
-gs 1 -1 sc (actions:possibleActions) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-5025 4350 m
-gs 1 -1 sc (number) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-7275 4425 m
-gs 1 -1 sc (handle) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-5850 6375 m
-gs 1 -1 sc (number) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-8100 6375 m
-gs 1 -1 sc (on) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-6225 1800 m
-gs 1 -1 sc (enabled) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-7275 1350 m
-gs 1 -1 sc ([1]) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-8175 1350 m
-gs 1 -1 sc ([2]) col0 sh gr
-/Times-Roman ff 180.00 scf sf
-9150 1350 m
-gs 1 -1 sc ([3]) col0 sh gr
-$F2psEnd
-rs
-end
-showpage
diff --git a/lib/asn1/src/.gitignore b/lib/asn1/src/.gitignore
new file mode 100644
index 0000000000..621f8f3623
--- /dev/null
+++ b/lib/asn1/src/.gitignore
@@ -0,0 +1,2 @@
+/asn1ct_rtt.erl
+/asn1ct_eval_*.erl
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 4bd49aa93b..33cd3cc4c3 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2013. 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
@@ -42,42 +42,35 @@ RELSYSDIR = $(RELEASE_PATH)/lib/asn1-$(VSN)
#
EBIN = ../ebin
+
+EVAL_CT_MODULES = asn1ct_eval_ext \
+ asn1ct_eval_per \
+ asn1ct_eval_uper
+
CT_MODULES= \
asn1ct \
asn1ct_check \
asn1_db \
asn1ct_pretty_format \
+ asn1ct_func \
asn1ct_gen \
asn1ct_gen_per \
asn1ct_gen_per_rt2ct \
asn1ct_name \
asn1ct_constructed_per \
- asn1ct_constructed_ber \
- asn1ct_gen_ber \
asn1ct_constructed_ber_bin_v2 \
asn1ct_gen_ber_bin_v2 \
+ asn1ct_imm \
+ asn1ct_rtt \
asn1ct_value \
asn1ct_tok \
asn1ct_parser2 \
- asn1ct_table
+ asn1ct_table \
+ $(EVAL_CT_MODULES)
RT_MODULES= \
asn1rt \
- asn1rt_per_bin \
- asn1rt_ber_bin \
- asn1rt_ber_bin_v2 \
- asn1rt_per_bin_rt2ct \
- asn1rt_uper_bin \
- asn1rt_check \
asn1rt_nif
-# asn1_sup \
-# asn1_app \
-# asn1_server
-
-
-# the rt module to use is defined in asn1_records.hrl
-# and must be updated when an incompatible change is done in the rt modules
-
MODULES= $(CT_MODULES) $(RT_MODULES)
@@ -112,7 +105,7 @@ endif
ERL_COMPILE_FLAGS += \
-I$(ERL_TOP)/lib/stdlib \
- +warn_unused_vars
+ -Werror
YRL_FLAGS =
@@ -138,13 +131,20 @@ info:
# ----------------------------------------------------
$(EBIN)/asn1ct.$(EMULATOR):asn1ct.erl
- $(ERLC) -b$(EMULATOR) -o$(EBIN) $(ERL_COMPILE_FLAGS) -Dvsn=\"$(VSN)\" $<
+ $(V_ERLC) -b$(EMULATOR) -o$(EBIN) $(ERL_COMPILE_FLAGS) -Dvsn=\"$(VSN)\" $<
+
+$(EBIN)/asn1ct_func.$(EMULATOR): asn1ct_func.erl
+ $(V_ERLC) -o$(EBIN) $(ERL_COMPILE_FLAGS) -I../rt_templates $<
+
+asn1ct_eval_%.erl: asn1ct_eval_%.funcs
+ $(gen_verbose)erl -pa $(EBIN) -noshell -noinput \
+ -run prepare_templates gen_asn1ct_eval $< >$@
$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
# ----------------------------------------------------
@@ -166,11 +166,61 @@ release_spec: opt
release_docs_spec:
+#
+# Run-time library template files.
+#
+RT_TEMPLATES = asn1rtt_check \
+ asn1rtt_ext \
+ asn1rtt_per_common \
+ asn1rtt_real_common \
+ asn1rtt_ber \
+ asn1rtt_per \
+ asn1rtt_uper
+RT_TEMPLATES_ERL = $(RT_TEMPLATES:%=%.erl)
+RT_TEMPLATES_TARGET = $(RT_TEMPLATES:%=%.$(EMULATOR))
+asn1ct_rtt.erl: prepare_templates.$(EMULATOR) $(RT_TEMPLATES_TARGET)
+ $(gen_verbose)erl -noshell -noinput -run prepare_templates gen_asn1ct_rtt \
+ $(RT_TEMPLATES_TARGET) >asn1ct_rtt.erl
+prepare_templates.$(EMULATOR): prepare_templates.erl
+ $(V_ERLC) prepare_templates.erl
+asn1rtt_%.$(EMULATOR): asn1rtt_%.erl
+ $(V_ERLC) +debug_info $<
+$(EVAL_CT_MODULES:%=%.erl): prepare_templates.$(EMULATOR) \
+ $(EBIN)/asn1ct_rtt.$(EMULATOR)
+#
+# Dependencies
+#
+$(EBIN)/asn1_app.beam: asn1_app.erl
+$(EBIN)/asn1_db.beam: asn1_db.erl
+$(EBIN)/asn1ct.beam: asn1ct.erl asn1_records.hrl
+$(EBIN)/asn1ct_check.beam: asn1ct_check.erl asn1_records.hrl
+$(EBIN)/asn1ct_constructed_ber_bin_v2.beam: asn1ct_constructed_ber_bin_v2.erl \
+ asn1_records.hrl
+$(EBIN)/asn1ct_constructed_per.beam: asn1ct_constructed_per.erl asn1_records.hrl
+$(EBIN)/asn1ct_func.beam: asn1ct_func.erl
+$(EBIN)/asn1ct_gen.beam: asn1ct_gen.erl asn1_records.hrl
+$(EBIN)/asn1ct_gen_ber_bin_v2.beam: asn1ct_gen_ber_bin_v2.erl asn1_records.hrl
+$(EBIN)/asn1ct_gen_per.beam: asn1ct_gen_per.erl asn1_records.hrl
+$(EBIN)/asn1ct_gen_per_rt2ct.beam: asn1ct_gen_per_rt2ct.erl asn1_records.hrl
+$(EBIN)/asn1ct_imm.beam: asn1ct_imm.erl
+$(EBIN)/asn1ct_name.beam: asn1ct_name.erl
+$(EBIN)/asn1ct_parser2.beam: asn1ct_parser2.erl asn1_records.hrl
+$(EBIN)/asn1ct_pretty_format.beam: asn1ct_pretty_format.erl
+$(EBIN)/asn1ct_table.beam: asn1ct_table.erl
+$(EBIN)/asn1ct_tok.beam: asn1ct_tok.erl
+$(EBIN)/asn1ct_value.beam: asn1ct_value.erl asn1_records.hrl
+$(EBIN)/asn1rt.beam: asn1rt.erl
+$(EBIN)/asn1rt_ber_bin.beam: asn1rt_ber_bin.erl asn1_records.hrl
+$(EBIN)/asn1rt_ber_bin_v2.beam: asn1rt_ber_bin_v2.erl
+$(EBIN)/asn1rt_check.beam: asn1rt_check.erl
+$(EBIN)/asn1rt_nif.beam: asn1rt_nif.erl
+$(EBIN)/asn1rt_per_bin_rt2ct.beam: asn1rt_per_bin_rt2ct.erl asn1_records.hrl
+$(EBIN)/asn1rt_uper_bin.beam: asn1rt_uper_bin.erl asn1_records.hrl
diff --git a/lib/asn1/src/asn1.app.src b/lib/asn1/src/asn1.app.src
index 09144ba2f7..f2ee8deb75 100644
--- a/lib/asn1/src/asn1.app.src
+++ b/lib/asn1/src/asn1.app.src
@@ -3,12 +3,6 @@
{vsn, "%VSN%"},
{modules, [
asn1rt,
- asn1rt_per_bin,
- asn1rt_per_bin_rt2ct,
- asn1rt_uper_bin,
- asn1rt_ber_bin,
- asn1rt_ber_bin_v2,
- asn1rt_check,
asn1rt_nif
]},
{registered, [
diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl
index 843fc66c9c..869b36ddbd 100644
--- a/lib/asn1/src/asn1_db.erl
+++ b/lib/asn1/src/asn1_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -19,31 +19,22 @@
%%
-module(asn1_db).
--export([dbstart/1,dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]).
--export([dbget_all_mod/1,dbclear/0,dberase_module/1,dbstop/0]).
+-export([dbstart/1,dbnew/1,dbsave/2,dbput/3,dbget/2]).
+-export([dbstop/0]).
-record(state, {parent, monitor, includes, table}).
%% Interface
dbstart(Includes) ->
Parent = self(),
- case get(?MODULE) of
- undefined ->
- put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)),
- true;
- _Pid ->
- req({new_includes, Includes})
- end.
+ undefined = get(?MODULE), %Assertion.
+ put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)),
+ ok.
dbnew(Module) -> req({new, Module}).
-dbsave(OutFile, Module) -> req({save, OutFile, Module}).
-dbload(Module) -> req({load, Module}).
-dbput(Module, K, V) -> req({set, Module, K, V}).
+dbsave(OutFile, Module) -> cast({save, OutFile, Module}).
+dbput(Module, K, V) -> cast({set, Module, K, V}).
dbget(Module, K) -> req({get, Module, K}).
-dbget_all(K) -> req({get_all, K}).
-dbget_all_mod(Mod) -> req({all_mod, Mod}).
-dbclear() -> req(clear).
-dberase_module({module,M}) -> req({delete_mod, M}).
dbstop() -> Resp = req(stop), erase(?MODULE), Resp.
%% Internal functions
@@ -59,8 +50,13 @@ req(Request) ->
exit({db_error,Info})
end.
+cast(Request) ->
+ get(?MODULE) ! Request,
+ ok.
+
reply({Ref,From}, Response) ->
- From ! {{Ref,?MODULE}, Response}.
+ From ! {{Ref,?MODULE}, Response},
+ ok.
init(Parent, Includes) ->
MRef = erlang:monitor(process, Parent),
@@ -70,10 +66,9 @@ init(Parent, Includes) ->
loop(#state{parent = Parent, monitor = MRef, table = Table,
includes = Includes} = State) ->
receive
- {From, {set, Mod, K2, V}} ->
+ {set, Mod, K2, V} ->
[{_, Modtab}] = ets:lookup(Table, Mod),
ets:insert(Modtab, {K2, V}),
- reply(From, ok),
loop(State);
{From, {get, Mod, K2}} ->
Result = case ets:lookup(Table, Mod) of
@@ -85,44 +80,16 @@ loop(#state{parent = Parent, monitor = MRef, table = Table,
_Error -> reply(From, undefined)
end,
loop(State);
- {From, {all_mod, Mod}} ->
- [{_, Modtab}] = ets:lookup(Table, Mod),
- reply(From, ets:tab2list(Modtab)),
- loop(State);
- {From, {delete_mod, Mod}} ->
- [{_, Modtab}] = ets:lookup(Table, Mod),
- ets:delete(Modtab),
- ets:delete(Table, Mod),
- reply(From, ok),
- loop(State);
- {From, {save, OutFile, Mod}} ->
+ {save, OutFile, Mod} ->
[{_,Mtab}] = ets:lookup(Table, Mod),
- reply(From, ets:tab2file(Mtab, OutFile)),
- loop(State);
- {From, {load, Mod}} ->
- Result = case ets:lookup(Table, Mod) of
- [] -> opentab(Table, Mod, Includes);
- [{_, Modtab}] -> {ok, Modtab}
- end,
- reply(From, Result),
+ ok = ets:tab2file(Mtab, OutFile),
loop(State);
{From, {new, Mod}} ->
- case ets:lookup(Table, Mod) of
- [{_, Modtab}] -> ets:delete(Modtab);
- _ -> true
- end,
+ [] = ets:lookup(Table, Mod), %Assertion.
ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []),
ets:insert(Table, {Mod, ModTableId}),
reply(From, ok),
loop(State);
- {From, clear} ->
- [ets:delete(Mt) || {_, Mt} <- ets:tab2list(Table)],
- ets:delete(Table),
- reply(From, cleared),
- loop(State#state{table = ets:new(asn1, [set])});
- {From, {new_includes, NewIncludes}} ->
- reply(From, true),
- loop(State#state{includes = NewIncludes});
{From, stop} ->
reply(From, stopped); %% Nothing to store
{'DOWN', MRef, process, Parent, Reason} ->
diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl
index 59a9acb7e7..396ba0fcfa 100644
--- a/lib/asn1/src/asn1_records.hrl
+++ b/lib/asn1/src/asn1_records.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -24,12 +24,6 @@
-define(dbg(Fmt, Args), no_debug).
-endif.
--define('RT_BER_BIN',"asn1rt_ber_bin").
--define('RT_PER_BIN',"asn1rt_per_bin").
-
-%% Some encoding are common for BER and PER. Shared code are in RT_COMMON
--define('RT_COMMON',asn1rt_ber_bin).
-
-define('COMPLETE_ENCODE',1).
-define('TLV_DECODE',2).
@@ -51,9 +45,7 @@
-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,
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index 8e971a1c76..8e71a5697c 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -25,22 +25,22 @@
%%-compile(export_all).
%% Public exports
-export([compile/1, compile/2]).
--export([start/0, start/1]).
-export([encode/2, encode/3, decode/3]).
-export([test/1, test/2, test/3, value/2, value/3]).
%% Application internal exports
-export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3,
vsn/0,
get_name_of_def/1,get_pos_of_def/1]).
--export([read_config_data/1,get_gen_state_field/1,get_gen_state/0,
- partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2,
+-export([read_config_data/1,get_gen_state_field/1,
+ partial_inc_dec_toptype/1,update_gen_state/2,
get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1,
- generated_refed_func/1,next_refed_func/0,pop_namelist/0,
- next_namelist_el/0,update_namelist/1,step_in_constructed/0,
+ generated_refed_func/1,next_refed_func/0,
+ update_namelist/1,step_in_constructed/0,
add_tobe_refed_func/1,add_generated_refed_func/1,
- maybe_rename_function/3,latest_sindex/0,current_sindex/0,
- set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2,
+ maybe_rename_function/3,current_sindex/0,
+ set_current_sindex/1,maybe_saved_sindex/2,
parse_and_save/2,verbose/3,warning/3,warning/4,error/3]).
+-export([get_bit_string_format/0]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -81,30 +81,43 @@
%%
%%
-
compile(File) ->
compile(File,[]).
-compile(File,Options) when is_list(Options) ->
- case lists:member(driver, Options) of %% remove me in R16A!
- true ->
- io:format("Warning: driver option is obsolete and will be removed in R16A, use nif instead!");
- false ->
- ok
- end,
- Options1 = optimize_ber_bin(Options),
- Options2 = includes(File,Options1),
- Includes = strip_includes(Options2),
- in_process(fun() -> compile_proc(File, Includes, Options2) end).
+compile(File, Options0) when is_list(Options0) ->
+ try translate_options(Options0) of
+ Options1 ->
+ Options2 = includes(File,Options1),
+ Includes = strip_includes(Options2),
+ in_process(fun() -> compile_proc(File, Includes, Options2) end)
+ catch throw:Error ->
+ Error
+ end.
+
+-record(st,
+ {file=[],
+ files=[],
+ inputmodules=[],
+ code,
+ opts=[],
+ outfile,
+ dbfile,
+ includes=[],
+ erule,
+ error=none,
+ run
+ }).
compile_proc(File, Includes, Options) ->
+ Erule = get_rule(Options),
+ St = #st{opts=Options,includes=Includes,erule=Erule},
case input_file_type(File, Includes) of
{single_file, SuffixedFile} -> %% "e.g. "/tmp/File.asn"
- compile1(SuffixedFile, Options);
+ compile1(SuffixedFile, St);
{multiple_files_file, SetBase, FileName} ->
case get_file_list(FileName, Includes) of
FileList when is_list(FileList) ->
- compile_set(SetBase, FileList, Options);
+ compile_set(SetBase, FileList, St);
Err ->
Err
end;
@@ -112,140 +125,251 @@ compile_proc(File, Includes, Options) ->
{error, Err}
end.
-compile1(File,Options) when is_list(Options) ->
- verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options),
- verbose("Compiler Options: ~p~n",[Options],Options),
- Ext = filename:extension(File),
- Base = filename:basename(File,Ext),
- OutFile = outfile(Base,"",Options),
- DbFile = outfile(Base,"asn1db",Options),
- Includes = [I || {i,I} <- Options],
- EncodingRule = get_rule(Options),
- asn1ct_table:new(asn1_functab),
- Continue1 = scan(File,Options),
- Continue2 = parse(Continue1,File,Options),
- Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule,
- DbFile,Options,[]),
- Continue4 = generate(Continue3,OutFile,EncodingRule,Options),
- asn1ct_table:delete(asn1_functab),
- Ret = compile_erl(Continue4,OutFile,Options),
- case inline(is_inline(Options),
- inline_output(Options,filename:rootname(File)),
- lists:concat([OutFile,".erl"]),Options) of
- false ->
- Ret;
- InlineRet ->
- InlineRet
+set_passes() ->
+ [{pass,scan_parse,fun set_scan_parse_pass/1},
+ {pass,merge,fun merge_pass/1}|common_passes()].
+
+single_passes() ->
+ [{pass,scan,fun scan_pass/1},
+ {pass,parse,fun parse_pass/1}|common_passes()].
+
+parse_and_save_passes() ->
+ [{pass,scan,fun scan_pass/1},
+ {pass,parse,fun parse_pass/1},
+ {pass,save,fun save_pass/1}].
+
+common_passes() ->
+ [{pass,check,fun check_pass/1},
+ {iff,abs,{pass,abs_listing,fun abs_listing/1}},
+ {pass,generate,fun generate_pass/1},
+ {unless,noobj,{pass,compile,fun compile_pass/1}}].
+
+scan_pass(#st{file=File}=St) ->
+ case asn1ct_tok:file(File) of
+ {error,Reason} ->
+ {error,St#st{error=Reason}};
+ Tokens when is_list(Tokens) ->
+ {ok,St#st{code=Tokens}}
end.
-
-%%****************************************************************************%%
-%% functions dealing with compiling of several input files to one output file %%
-%%****************************************************************************%%
+set_scan_parse_pass(#st{files=Files}=St) ->
+ try
+ L = set_scan_parse_pass_1(Files, St),
+ {ok,St#st{code=L}}
+ catch
+ throw:Error ->
+ {error,St#st{error=Error}}
+ end.
-%%%
-%% inline/4
-%% merges the resulting erlang modules with
-%% the appropriate run-time modules so the resulting module contains all
-%% run-time asn1 functionality. Then compiles the resulting file to beam code.
-%% The merging is done by the igor module. If this function is used in older
-%% versions than R10B the igor module, part of user contribution syntax_tools,
-%% must be provided. It is possible to pass options for the ASN1 compiler
-%% Types:
-%% Name -> atom()
-%% Modules -> [filename()]
-%% Options -> [term()]
-%% filename() -> file:filename()
-inline(true,Name,Module,Options) ->
- RTmodule = get_runtime_mod(Options),
- IgorOptions = igorify_options(remove_asn_flags(Options)),
- IgorName = list_to_atom(filename:rootname(filename:basename(Name))),
-% io:format("*****~nName: ~p~nModules: ~p~nIgorOptions: ~p~n*****~n",
-% [IgorName,Modules++RTmodule,IgorOptions]),
- verbose("Inlining modules: ~p in ~p~n",[[Module]++RTmodule,IgorName],Options),
- case catch igor:merge(IgorName,[Module]++RTmodule,[{preprocess,true},{stubs,false},{backups,false}]++IgorOptions) of
- {'EXIT',{undef,Reason}} -> %% module igor first in R10B
- error("Module igor in syntax_tools must be available:~n~p~n",
- [Reason],Options),
- {error,'no_compilation'};
- {'EXIT',Reason} ->
- error("Merge by igor module failed due to ~p~n",[Reason],Options),
- {error,'no_compilation'};
- _ ->
-%% io:format("compiling output module: ~p~n",[generated_file(Name,IgorOptions)]),
- erl_compile(generated_file(Name,IgorOptions),Options)
+set_scan_parse_pass_1([F|Fs], St) ->
+ case asn1ct_tok:file(F) of
+ {error,Error} ->
+ throw(Error);
+ Tokens when is_list(Tokens) ->
+ case catch asn1ct_parser2:parse(Tokens) of
+ {ok,M} ->
+ [M|set_scan_parse_pass_1(Fs, St)];
+ {error,ErrorTerm} ->
+ throw(handle_parse_error(ErrorTerm, St))
+ end
end;
-inline(_,_,_,_) ->
- false.
+set_scan_parse_pass_1([], _) -> [].
-%% compile_set/3 merges and compiles a number of asn1 modules
-%% specified in a .set.asn file to one .erl file.
-compile_set(SetBase,Files,Options)
- when is_list(hd(Files)),is_list(Options) ->
- %% case when there are several input files in a list
- verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files],Options),
- verbose("Compiler Options: ~p~n",[Options],Options),
- OutFile = outfile(SetBase,"",Options),
- DbFile = outfile(SetBase,"asn1db",Options),
- Includes = [I || {i,I} <- Options],
- EncodingRule = get_rule(Options),
- asn1ct_table:new(asn1_functab),
- ScanRes = scan_set(Files,Options),
- ParseRes = parse_set(ScanRes,Options),
- Result =
- case [X||X <- ParseRes,element(1,X)==true] of
- [] -> %% all were false, time to quit
- lists:map(fun(X)->element(2,X) end,ParseRes);
- ParseRes -> %% all were true, continue with check
- InputModules =
- lists:map(
- fun(F)->
- E = filename:extension(F),
- B = filename:basename(F,E),
- if
- is_list(B) -> list_to_atom(B);
- true -> B
- end
- end,
- Files),
- check_set(ParseRes,SetBase,OutFile,Includes,
- EncodingRule,DbFile,Options,InputModules);
- Other ->
- {error,{'unexpected error in scan/parse phase',
- lists:map(fun(X)->element(3,X) end,Other)}}
- end,
- asn1ct_table:delete(asn1_functab),
- Result.
+parse_pass(#st{code=Tokens}=St) ->
+ case catch asn1ct_parser2:parse(Tokens) of
+ {ok,M} ->
+ {ok,St#st{code=M}};
+ {error,ErrorTerm} ->
+ {error,St#st{error=handle_parse_error(ErrorTerm, St)}}
+ end.
+
+handle_parse_error(ErrorTerm, #st{file=File,opts=Opts}) ->
+ case ErrorTerm of
+ {{Line,_Mod,Message},_TokTup} ->
+ if
+ is_integer(Line) ->
+ BaseName = filename:basename(File),
+ error("syntax error at line ~p in module ~s:~n",
+ [Line,BaseName], Opts);
+ true ->
+ error("syntax error in module ~p:~n",
+ [File], Opts)
+ end,
+ print_error_message(Message),
+ Message;
+ {Line,_Mod,[Message,Token]} ->
+ error("syntax error: ~p ~p at line ~p~n",
+ [Message,Token,Line], Opts),
+ {Line,[Message,Token]}
+ end.
-check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
- Options,InputModules) ->
+merge_pass(#st{file=Base,code=Code}=St) ->
+ M = merge_modules(Code, Base),
+ {ok,St#st{code=M}}.
- MergedModule = merge_modules(ParseRes,SetBase),
- SetM = MergedModule#module{name=SetBase},
- Continue1 = check({true,SetM},SetBase,OutFile,Includes,EncRule,DbFile,
- Options,InputModules),
- Continue2 = generate(Continue1,OutFile,EncRule,Options),
+check_pass(#st{code=M,file=File,includes=Includes,
+ erule=Erule,dbfile=DbFile,opts=Opts,
+ inputmodules=InputModules}=St) ->
+ start(Includes),
+ case asn1ct_check:storeindb(#state{erule=Erule}, M) of
+ ok ->
+ Module = asn1_db:dbget(M#module.name, 'MODULE'),
+ State = #state{mname=Module#module.name,
+ module=Module#module{typeorval=[]},
+ erule=Erule,
+ inputmodules=InputModules,
+ options=Opts,
+ sourcedir=filename:dirname(File)},
+ case asn1ct_check:check(State, Module#module.typeorval) of
+ {error,Reason} ->
+ {error,St#st{error=Reason}};
+ {ok,NewTypeOrVal,GenTypeOrVal} ->
+ NewM = Module#module{typeorval=NewTypeOrVal},
+ asn1_db:dbput(NewM#module.name, 'MODULE', NewM),
+ asn1_db:dbsave(DbFile, M#module.name),
+ verbose("--~p--~n", [{generated,DbFile}], Opts),
+ {ok,St#st{code={M,GenTypeOrVal}}}
+ end;
+ {error,Reason} ->
+ {error,St#st{error=Reason}}
+ end.
- asn1ct_table:delete([renamed_defs, original_imports, automatic_tags]),
+save_pass(#st{code=M,erule=Erule,dbfile=DbFile}=St) ->
+ ok = asn1ct_check:storeindb(#state{erule=Erule}, M),
+ asn1_db:dbsave(DbFile,M#module.name),
+ {ok,St}.
- Ret = compile_erl(Continue2,OutFile,Options),
- case inline(is_inline(Options),
- inline_output(Options,filename:rootname(OutFile)),
- lists:concat([OutFile,".erl"]),Options) of
- false ->
- Ret;
- InlineRet ->
- InlineRet
+abs_listing(#st{code={M,_},outfile=OutFile}) ->
+ pretty2(M#module.name, OutFile++".abs"),
+ done.
+
+generate_pass(#st{code=Code,outfile=OutFile,erule=Erule,opts=Opts}=St0) ->
+ St = St0#st{code=undefined}, %Reclaim heap space
+ case generate(Code, OutFile, Erule, Opts) of
+ {error,Reason} ->
+ {error,St#st{error=Reason}};
+ ok ->
+ {ok,St}
end.
+compile_pass(#st{outfile=OutFile,opts=Opts0}=St) ->
+ asn1_db:dbstop(), %Reclaim memory.
+ asn1ct_table:delete([renamed_defs,original_imports,automatic_tags]),
+ Opts = remove_asn_flags(Opts0),
+ case c:c(OutFile, Opts) of
+ {ok,_Module} ->
+ {ok,St};
+ _ ->
+ {error,St}
+ end.
+
+run_passes(Passes, #st{opts=Opts}=St) ->
+ Run = case lists:member(time, Opts) of
+ false ->
+ fun(_, Pass, S) -> Pass(S) end;
+ true ->
+ fun run_tc/3
+ end,
+ run_passes_1(Passes, St#st{run=Run}).
+
+run_tc(Name, Fun, St) ->
+ Before0 = statistics(runtime),
+ Val = (catch Fun(St)),
+ After0 = statistics(runtime),
+ {Before_c, _} = Before0,
+ {After_c, _} = After0,
+ io:format("~-31s: ~10.2f s\n",
+ [Name,(After_c-Before_c) / 1000]),
+ Val.
+
+run_passes_1([{unless,Opt,Pass}|Passes], #st{opts=Opts}=St) ->
+ case proplists:get_bool(Opt, Opts) of
+ false ->
+ run_passes_1([Pass|Passes], St);
+ true ->
+ run_passes_1(Passes, St)
+ end;
+run_passes_1([{iff,Opt,Pass}|Passes], #st{opts=Opts}=St) ->
+ case proplists:get_bool(Opt, Opts) of
+ true ->
+ run_passes_1([Pass|Passes], St);
+ false ->
+ run_passes_1(Passes, St)
+ end;
+run_passes_1([{pass,Name,Pass}|Passes], #st{run=Run}=St0)
+ when is_function(Pass, 1) ->
+ try Run(Name, Pass, St0) of
+ {ok,St} ->
+ run_passes_1(Passes, St);
+ {error,#st{error=Errors}} ->
+ {Structured,AllErrors} = clean_errors(Errors),
+ print_structured_errors(Structured),
+ {error,AllErrors};
+ done ->
+ ok
+ catch
+ Class:Error ->
+ Stk = erlang:get_stacktrace(),
+ io:format("Internal error: ~p:~p\n~p\n",
+ [Class,Error,Stk]),
+ {error,{internal_error,{Class,Error}}}
+ end;
+run_passes_1([], _St) ->
+ ok.
+
+clean_errors(Errors) when is_list(Errors) ->
+ F = fun({structured_error,_,_,_}) -> true;
+ (_) -> false
+ end,
+ {Structured0,AdHoc} = lists:partition(F, Errors),
+ Structured = lists:sort(Structured0),
+ {Structured,Structured ++ AdHoc};
+clean_errors(AdHoc) -> {[],AdHoc}.
+
+print_structured_errors([_|_]=Errors) ->
+ _ = [io:format("~ts:~w: ~ts\n", [F,L,M:format_error(E)]) ||
+ {structured_error,{F,L},M,E} <- Errors],
+ ok;
+print_structured_errors(_) -> ok.
+
+compile1(File, #st{opts=Opts}=St0) ->
+ verbose("Erlang ASN.1 version ~p, compiling ~p~n", [?vsn,File], Opts),
+ verbose("Compiler Options: ~p~n", [Opts], Opts),
+ Passes = single_passes(),
+ Base = filename:rootname(filename:basename(File)),
+ OutFile = outfile(Base, "", Opts),
+ DbFile = outfile(Base, "asn1db", Opts),
+ St1 = St0#st{file=File,outfile=OutFile,dbfile=DbFile},
+ run_passes(Passes, St1).
+
+%%****************************************************************************%%
+%% functions dealing with compiling of several input files to one output file %%
+%%****************************************************************************%%
+
+%% compile_set/3 merges and compiles a number of asn1 modules
+%% specified in a .set.asn file to one .erl file.
+compile_set(SetBase, Files, #st{opts=Opts}=St0) ->
+ verbose("Erlang ASN.1 version ~p compiling ~p ~n", [?vsn,Files], Opts),
+ verbose("Compiler Options: ~p~n",[Opts], Opts),
+ OutFile = outfile(SetBase, "", Opts),
+ DbFile = outfile(SetBase, "asn1db", Opts),
+ InputModules = [begin
+ F1 = filename:basename(F0),
+ F = filename:rootname(F1),
+ list_to_atom(F)
+ end || F0 <- Files],
+ St = St0#st{file=SetBase,files=Files,outfile=OutFile,
+ dbfile=DbFile,inputmodules=InputModules},
+ Passes = set_passes(),
+ run_passes(Passes, St).
+
%% merge_modules/2 -> returns a module record where the typeorval lists are merged,
%% the exports lists are merged, the imports lists are merged when the
%% elements come from other modules than the merge set, the tagdefault
%% field gets the shared value if all modules have same tagging scheme,
%% otherwise a tagging_error exception is thrown,
%% the extensiondefault ...(not handled yet).
-merge_modules(ParseRes,CommonName) ->
- ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes),
+merge_modules(ModuleList, CommonName) ->
NewModuleList = remove_name_collisions(ModuleList),
case asn1ct_table:size(renamed_defs) of
0 -> asn1ct_table:delete(renamed_defs);
@@ -435,6 +559,8 @@ get_pos_of_def(#pobjectdef{pos=Pos}) ->
Pos;
get_pos_of_def(#pobjectsetdef{pos=Pos}) ->
Pos;
+get_pos_of_def(#'Externalvaluereference'{pos=Pos}) ->
+ Pos;
get_pos_of_def(_) ->
undefined.
@@ -707,128 +833,11 @@ delete_double_of_symbol1([],Acc) ->
Acc.
-scan_set(Files,Options) ->
- %% The files in Files already have their relative path and extension
- lists:map(
- fun(F)->
- case scan(F,Options) of
- {false,{error,Reason}} ->
- throw({error,{'scan error in file:',F,Reason}});
- {TrueOrFalse,Res} ->
- {TrueOrFalse,Res,F}
- end
- end,
- Files).
-
-parse_set(ScanRes,Options) ->
- lists:map(
- fun({TorF,Toks,F})->
- case parse({TorF,Toks},F,Options) of
- {false,{error,Reason}} ->
- throw({error,{'parse error in file:',F,Reason}});
- {TrueOrFalse,Res} ->
- {TrueOrFalse,Res,F}
- end
- end,
- ScanRes).
-
-
%%***********************************
-
-scan(File,Options) ->
- case asn1ct_tok:file(File) of
- {error,Reason} ->
- error("~p~n",[Reason],Options),
- {false,{error,Reason}};
- Tokens ->
- case lists:member(ss,Options) of
- true -> % we terminate after scan
- {false,Tokens};
- false -> % continue with next pass
- {true,Tokens}
- end
- end.
-
-
-parse({true,Tokens},File,Options) ->
- %Presult = asn1ct_parser2:parse(Tokens),
- %%case lists:member(p1,Options) of
- %% true ->
- %% asn1ct_parser:parse(Tokens);
- %% _ ->
- %% asn1ct_parser2:parse(Tokens)
- %% end,
- case catch asn1ct_parser2:parse(Tokens) of
- {error,{{Line,_Mod,Message},_TokTup}} ->
- if
- is_integer(Line) ->
- BaseName = filename:basename(File),
- error("syntax error at line ~p in module ~s:~n",
- [Line,BaseName],Options);
- true ->
- error("syntax error in module ~p:~n",
- [File],Options)
- end,
- print_error_message(Message),
- {false,{error,Message}};
- {error,{Line,_Mod,[Message,Token]}} ->
- error("syntax error: ~p ~p at line ~p~n",
- [Message,Token,Line],Options),
- {false,{error,{Line,[Message,Token]}}};
- {ok,M} ->
- case lists:member(sp,Options) of
- true -> % terminate after parse
- {false,M};
- false -> % continue with next pass
- {true,M}
- end;
- OtherError ->
- error("~p~n",[OtherError],Options)
- end;
-parse({false,Tokens},_,_) ->
- {false,Tokens}.
-
-check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
-
- start(Includes),
- case asn1ct_check:storeindb(#state{erule=EncodingRule},M) of
- ok ->
- Module = asn1_db:dbget(M#module.name,'MODULE'),
- State = #state{mname=Module#module.name,
- module=Module#module{typeorval=[]},
- erule=EncodingRule,
- inputmodules=InputMods,
- options=Options,
- sourcedir=filename:dirname(File)},
- Check = asn1ct_check:check(State,Module#module.typeorval),
- case {Check,lists:member(abs,Options)} of
- {{error,Reason},_} ->
- {false,{error,Reason}};
- {{ok,NewTypeOrVal,_},true} ->
- NewM = Module#module{typeorval=NewTypeOrVal},
- asn1_db:dbput(NewM#module.name,'MODULE',NewM),
- pretty2(M#module.name,lists:concat([OutFile,".abs"])),
- {false,ok};
- {{ok,NewTypeOrVal,GenTypeOrVal},_} ->
- NewM = Module#module{typeorval=NewTypeOrVal},
- asn1_db:dbput(NewM#module.name,'MODULE',NewM),
- asn1_db:dbsave(DbFile,M#module.name),
- verbose("--~p--~n",[{generated,DbFile}],Options),
- {true,{M,NewM,GenTypeOrVal}}
- end;
- ErrorList = {error,_} ->
- {false,ErrorList}
- end;
-check({false,M},_,_,_,_,_,_,_) ->
- {false,M}.
-
-generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
+generate({M,GenTOrV}, OutFile, EncodingRule, Options) ->
debug_on(Options),
- case lists:member(compact_bit_string,Options) of
- true -> put(compact_bit_string,true);
- _ -> ok
- end,
+ setup_bit_string_format(Options),
put(encoding_options,Options),
asn1ct_table:new(check_functions),
@@ -850,24 +859,32 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
ok
end,
debug_off(Options),
- put(compact_bit_string,false),
erase(encoding_options),
- erase(tlv_format), % used in ber_bin, optimize
- erase(class_default_type),% used in ber_bin, optimize
+ cleanup_bit_string_format(),
+ erase(tlv_format), % used in ber
+ erase(class_default_type),% used in ber
asn1ct_table:delete(check_functions),
- case Result of
- {error,_} ->
- {false,Result};
- ok ->
- case lists:member(sg,Options) of
- true -> % terminate here , with .erl file generated
- {false,true};
- false ->
- {true,true}
- end
- end;
-generate({false,M},_,_,_) ->
- {false,M}.
+ Result.
+
+setup_bit_string_format(Opts) ->
+ Format = case {lists:member(compact_bit_string, Opts),
+ lists:member(legacy_bit_string, Opts)} of
+ {false,false} -> bitstring;
+ {true,false} -> compact;
+ {false,true} -> legacy;
+ {true,true} ->
+ Message = "Contradicting options given: "
+ "compact_bit_string and legacy_bit_string",
+ exit({error,{asn1,Message}})
+ end,
+ put(bit_string_format, Format).
+
+cleanup_bit_string_format() ->
+ erase(bit_string_format).
+
+get_bit_string_format() ->
+ get(bit_string_format).
+
%% parse_and_save parses an asn1 spec and saves the unchecked parse
%% tree in a data base file.
@@ -875,15 +892,13 @@ generate({false,M},_,_,_) ->
parse_and_save(Module,S) ->
Options = S#state.options,
SourceDir = S#state.sourcedir,
- Includes = [I || {i,I} <-Options],
- Options1 = optimize_ber_bin(Options),
-
- case get_input_file(Module,[SourceDir|Includes]) of
+ Includes = [I || {i,I} <- Options],
+ case get_input_file(Module, [SourceDir|Includes]) of
%% search for asn1 source
{file,SuffixedASN1source} ->
- case dbfile_uptodate(SuffixedASN1source,Options1) of
+ case dbfile_uptodate(SuffixedASN1source,Options) of
false ->
- parse_and_save1(S,SuffixedASN1source,Options1,Includes);
+ parse_and_save1(S, SuffixedASN1source, Options);
_ -> ok
end;
Err ->
@@ -891,24 +906,14 @@ parse_and_save(Module,S) ->
[lists:concat([Module,".asn1db"])],Options),
{error,{asn1,input_file_error,Err}}
end.
-parse_and_save1(S,File,Options,Includes) ->
+
+parse_and_save1(#state{erule=Erule}, File, Options) ->
Ext = filename:extension(File),
- Base = filename:basename(File,Ext),
- DbFile = outfile(Base,"asn1db",Options),
- Continue1 = scan(File,Options),
- M =
- case parse(Continue1,File,Options) of
- {true,Mod} -> Mod;
- _ ->
-%% io:format("~p~nnow I die!!!!!!!!!!!~n",[File]),
- exit({error,{asn1,File,"no such file"}})
- end,
-% start(["."|Includes]),
- start(Includes),
- case asn1ct_check:storeindb(S,M) of
- ok ->
- asn1_db:dbsave(DbFile,M#module.name)
- end.
+ Base = filename:basename(File, Ext),
+ DbFile = outfile(Base, "asn1db", Options),
+ St = #st{file=File,dbfile=DbFile,erule=Erule},
+ Passes = parse_and_save_passes(),
+ run_passes(Passes, St).
get_input_file(Module,[]) ->
Module;
@@ -966,13 +971,6 @@ dbfile_uptodate(File,Options) ->
end.
-compile_erl({true,_},OutFile,Options) ->
- erl_compile(OutFile,Options);
-compile_erl({false,true},_,_) ->
- ok;
-compile_erl({false,Result},_,_) ->
- Result.
-
input_file_type(Name,I) ->
case input_file_type(Name) of
{error,_} -> input_file_type2(filename:basename(Name),I);
@@ -1065,9 +1063,9 @@ get_file_list1(Stream,Dir,Includes,Acc) ->
end.
get_rule(Options) ->
- case [Rule ||Rule <-[per,ber,ber_bin,ber_bin_v2,per_bin,uper_bin],
- Opt <- Options,
- Rule==Opt] of
+ case [Rule || Rule <- [ber,per,uper],
+ Opt <- Options,
+ Rule =:= Opt] of
[Rule] ->
Rule;
[Rule|_] ->
@@ -1076,46 +1074,41 @@ get_rule(Options) ->
ber
end.
-get_runtime_mod(Options) ->
- RtMod1=
- case get_rule(Options) of
- per -> ["asn1rt_per_bin.erl"];
- ber -> ["asn1rt_ber_bin.erl"];
- per_bin ->
- case lists:member(optimize,Options) of
- true -> ["asn1rt_per_bin_rt2ct.erl"];
- _ -> ["asn1rt_per_bin.erl"]
- end;
- ber_bin -> ["asn1rt_ber_bin.erl"];
- ber_bin_v2 -> ["asn1rt_ber_bin_v2.erl"];
- uper_bin -> ["asn1rt_uper_bin.erl"]
- end,
- RtMod1++["asn1rt_check.erl","asn1rt.erl"].
-
-
-erl_compile(OutFile,Options) ->
-% io:format("Options:~n~p~n",[Options]),
- case lists:member(noobj,Options) of
- true ->
- ok;
- _ ->
- ErlOptions = remove_asn_flags(Options),
- %% io:format("~n~nc:c(~p,~p)~n~n",[OutFile,ErlOptions]),
- case c:c(OutFile,ErlOptions) of
- {ok,_Module} ->
- ok;
- _ ->
- {error,'no_compilation'}
- end
- end.
+%% translate_options(NewOptions) -> OldOptions
+%% Translate the new option names to the old option name.
+
+translate_options([ber_bin|T]) ->
+ io:format("Warning: The option 'ber_bin' is now called 'ber'.\n"),
+ [ber|translate_options(T)];
+translate_options([per_bin|T]) ->
+ io:format("Warning: The option 'per_bin' is now called 'per'.\n"),
+ [per|translate_options(T)];
+translate_options([uper_bin|T]) ->
+ io:format("Warning: The option 'uper_bin' is now called 'uper'.\n"),
+ translate_options([uper|T]);
+translate_options([nif|T]) ->
+ io:format("Warning: The option 'nif' is no longer needed.\n"),
+ translate_options(T);
+translate_options([optimize|T]) ->
+ io:format("Warning: The option 'optimize' is no longer needed.\n"),
+ translate_options(T);
+translate_options([inline|T]) ->
+ io:format("Warning: The option 'inline' is no longer needed.\n"),
+ translate_options(T);
+translate_options([{inline,_}|_]) ->
+ io:format("ERROR: The option {inline,OutputFilename} is no longer supported.\n"),
+ throw({error,{unsupported_option,inline}});
+translate_options([H|T]) ->
+ [H|translate_options(T)];
+translate_options([]) -> [].
remove_asn_flags(Options) ->
[X || X <- Options,
X /= get_rule(Options),
X /= optimize,
X /= compact_bit_string,
+ X /= legacy_bit_string,
X /= debug,
- X /= keyed_list,
X /= asn1config,
X /= record_name_prefix].
@@ -1125,34 +1118,10 @@ debug_on(Options) ->
put(asndebug,true);
_ ->
true
- end,
- case lists:member(keyed_list,Options) of
- true ->
- put(asn_keyed_list,true);
- _ ->
- true
- end.
-
-igorify_options(Options) ->
- case lists:keysearch(outdir,1,Options) of
- {value,{_,Dir}} ->
- Options1 = lists:keydelete(outdir,1,Options),
- [{dir,Dir}|Options1];
- _ ->
- Options
- end.
-
-generated_file(Name,Options) ->
- case lists:keysearch(dir,1,Options) of
- {value,{_,Dir}} ->
- filename:join([Dir,filename:basename(Name)]);
- _ ->
- Name
end.
debug_off(_Options) ->
- erase(asndebug),
- erase(asn_keyed_list).
+ erase(asndebug).
outfile(Base, Ext, Opts) ->
@@ -1168,13 +1137,6 @@ outfile(Base, Ext, Opts) ->
lists:concat([Obase,".",Ext])
end.
-optimize_ber_bin(Options) ->
- case {lists:member(optimize,Options),lists:member(ber_bin,Options)} of
- {true,true} ->
- [ber_bin_v2|Options--[ber_bin]];
- _ -> Options
- end.
-
includes(File,Options) ->
Options2 = include_append(".", Options),
Options3 = include_append(filename:dirname(File), Options2),
@@ -1198,21 +1160,6 @@ option_add(Option, Options, Fun) ->
strip_includes(Includes) ->
[I || {i, I} <- Includes].
-is_inline(Options) ->
- case lists:member(inline,Options) of
- true -> true;
- _ ->
- lists:keymember(inline,1,Options)
- end.
-
-inline_output(Options,Default) ->
- case [X||{inline,X}<-Options] of
- [OutputName] ->
- OutputName;
- _ ->
- Default
- end.
-
%% compile(AbsFileName, Options)
%% Compile entry point for erl_compile.
@@ -1284,57 +1231,47 @@ make_erl_options(Opts) ->
Defines) ++
case OutputType of
undefined -> [ber]; % temporary default (ber when it's ready)
- ber -> [ber];
- ber_bin -> [ber_bin];
- ber_bin_v2 -> [ber_bin_v2];
- per -> [per];
- per_bin -> [per_bin];
- uper_bin -> [uper_bin]
+ _ -> [OutputType] % pass through
end,
Options++[errors, {cwd, Cwd}, {outdir, Outdir}|
lists:map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.
pretty2(Module,AbsFile) ->
- start(),
{ok,F} = file:open(AbsFile,[write]),
M = asn1_db:dbget(Module,'MODULE'),
io:format(F,"%%%%%%%%%%%%%%%%%%% ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.defid)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.tagdefault)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.exports)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.imports)]),
- io:format(F,"~s\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]),
+ io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.defid)]),
+ io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.tagdefault)]),
+ io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.exports)]),
+ io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.imports)]),
+ io:format(F,"~s.\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]),
{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets} = M#module.typeorval,
io:format(F,"%%%%%%%%%%%%%%%%%%% TYPES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,Types),
io:format(F,"%%%%%%%%%%%%%%%%%%% VALUES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,Values),
io:format(F,"%%%%%%%%%%%%%%%%%%% Parameterized Types in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,ParameterizedTypes),
io:format(F,"%%%%%%%%%%%%%%%%%%% Classes in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,Classes),
io:format(F,"%%%%%%%%%%%%%%%%%%% Objects in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,Objects),
io:format(F,"%%%%%%%%%%%%%%%%%%% Object Sets in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
+ lists:foreach(fun(T)-> io:format(F,"~s.\n",
[asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
end,ObjectSets).
-start() ->
- Includes = ["."],
- start(Includes).
-
start(Includes) when is_list(Includes) ->
asn1_db:dbstart(Includes).
@@ -1400,8 +1337,7 @@ test_value(Module, Type, Value) ->
in_process(fun() ->
case catch encode(Module, Type, Value) of
{ok, Bytes} ->
- M = to_atom(Module),
- NewBytes = prepare_bytes(M:encoding_rule(), Bytes),
+ NewBytes = prepare_bytes(Bytes),
case decode(Module, Type, NewBytes) of
{ok, Value} ->
{ok, {Module, Type, Value}};
@@ -1452,18 +1388,8 @@ check(Module, Includes) ->
end
end.
-to_atom(Term) when is_list(Term) -> list_to_atom(Term);
-to_atom(Term) when is_atom(Term) -> Term.
-
-prepare_bytes(ber, Bytes) -> lists:flatten(Bytes);
-prepare_bytes(ber_bin, Bytes) when is_binary(Bytes) -> Bytes;
-prepare_bytes(ber_bin, Bytes) -> list_to_binary(Bytes);
-prepare_bytes(ber_bin_v2, Bytes) when is_binary(Bytes) -> Bytes;
-prepare_bytes(ber_bin_v2, Bytes) -> list_to_binary(Bytes);
-prepare_bytes(per, Bytes) -> lists:flatten(Bytes);
-prepare_bytes(per_bin, Bytes) when is_binary(Bytes) -> Bytes;
-prepare_bytes(per_bin, Bytes) -> list_to_binary(Bytes);
-prepare_bytes(uper_bin, Bytes) -> Bytes.
+prepare_bytes(Bytes) when is_binary(Bytes) -> Bytes;
+prepare_bytes(Bytes) -> list_to_binary(Bytes).
vsn() ->
?vsn.
@@ -1504,7 +1430,7 @@ specialized_decode_prepare(Erule,M,TsAndVs,Options) ->
end.
%% Reads the configuration file if it exists and stores information
%% about partial decode and incomplete decode
-partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when is_tuple(TsAndVs) ->
+partial_decode_prepare(ber,M,TsAndVs,Options) when is_tuple(TsAndVs) ->
%% read configure file
ModName =
@@ -2188,52 +2114,6 @@ update_namelist(Name) ->
Other -> Other
end.
-pop_namelist() ->
- DeepTail = %% removes next element in order
- fun([[{_,A}]|T],_Fun) when is_atom(A) -> T;
- ([{_N,L}|T],_Fun) when is_list(L) -> [L|T];
- ([[]|T],Fun) -> Fun(T,Fun);
- ([L1|L2],Fun) when is_list(L1) ->
- case lists:flatten(L1) of
- [] -> Fun([L2],Fun);
- _ -> [Fun(L1,Fun)|L2]
- end;
- ([_H|T],_Fun) -> T
- end,
- {Pop,NewNL} =
- case get_gen_state_field(namelist) of
- [] -> {[],[]};
- L ->
- {next_namelist_el(L),
- DeepTail(L,DeepTail)}
- end,
- update_gen_state(namelist,NewNL),
- Pop.
-
-%% next_namelist_el fetches the next type/component name in turn in
-%% the namelist, without changing the namelist.
-next_namelist_el() ->
- case get_gen_state_field(namelist) of
- undefined -> undefined;
- L when is_list(L) -> next_namelist_el(L)
- end.
-
-next_namelist_el([]) ->
- [];
-next_namelist_el([L]) when is_list(L) ->
- next_namelist_el(L);
-next_namelist_el([H|_]) when is_atom(H) ->
- H;
-next_namelist_el([L|T]) when is_list(L) ->
- case next_namelist_el(L) of
- [] ->
- next_namelist_el([T]);
- R ->
- R
- end;
-next_namelist_el([H={_,A}|_]) when is_atom(A) ->
- H.
-
%% removes a bracket from the namelist
step_in_constructed() ->
case get_gen_state_field(namelist) of
@@ -2473,14 +2353,6 @@ maybe_saved_sindex(Name,Pattern) ->
end
end.
-next_sindex() ->
- SI = get_gen_state_field(suffix_index),
- update_gen_state(suffix_index,SI+1),
- SI+1.
-
-latest_sindex() ->
- get_gen_state_field(suffix_index).
-
current_sindex() ->
get_gen_state_field(current_suffix_index).
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index 99b09c4e90..f94550b0a4 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -25,7 +25,7 @@
%-compile(export_all).
%% Avoid warning for local function error/1 clashing with autoimported BIF.
-compile({no_auto_import,[error/1]}).
--export([check/2,storeindb/2]).
+-export([check/2,storeindb/2,format_error/1]).
%-define(debug,1).
-include("asn1_records.hrl").
%%% The tag-number for universal types
@@ -61,19 +61,18 @@
-define(TAG_PRIMITIVE(Num),
case S#state.erule of
- ber_bin_v2 ->
+ ber ->
#tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=0};
_ -> []
end).
-define(TAG_CONSTRUCTED(Num),
case S#state.erule of
- ber_bin_v2 ->
+ ber ->
#tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=32};
_ -> []
end).
-record(newt,{type=unchanged,tag=unchanged,constraint=unchanged,inlined=no}). % used in check_type to update type and tag
--record(newv,{type=unchanged,value=unchanged}). % used in check_value to update type and value
check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
%%Predicates used to filter errors
@@ -92,14 +91,14 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
save_asn1db_uptodate(S,S#state.erule,S#state.mname),
put(top_module,S#state.mname),
- _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used
+ _ = checkp(S, ParameterizedTypes), %must do this before the templates are used
%% table to save instances of parameterized objects,object sets
asn1ct_table:new(parameterized_objects),
asn1ct_table:new(inlined_objects),
- Terror = checkt(S,Types,[]),
+ Terror = checkt(S, Types),
?dbg("checkt finished with errors:~n~p~n~n",[Terror]),
%% get parameterized object sets sent to checkt/3
@@ -107,7 +106,7 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
{PObjSetNames1,Terror2} = filter_errors(IsPObjSet,Terror),
- Verror = checkv(S,Values ++ ObjectSets,[]), %value sets may be parsed as object sets
+ Verror = checkv(S, Values ++ ObjectSets), %value sets may be parsed as object sets
?dbg("checkv finished with errors:~n~p~n~n",[Verror]),
%% get information object classes wrongly sent to checkt/3
%% and update Terror2
@@ -116,7 +115,7 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
NewClasses = Classes++AddClasses,
- Cerror = checkc(S,NewClasses,[]),
+ Cerror = checkc(S, NewClasses),
?dbg("checkc finished with errors:~n~p~n~n",[Cerror]),
%% get object sets incorrectly sent to checkv/3
%% and update Verror
@@ -175,8 +174,9 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
{NewTypes,NewValues,ParameterizedTypes,NewClasses,
lists:subtract(NewObjects,ExclO)++InlinedObjects,
lists:subtract(NewObjectSets,ExclOS)++ParObjectSetNames}};
- _ ->{error,{asn1,lists:flatten([Terror3,Verror5,Cerror,
- Oerror,Exporterror,ImportError])}}
+ _ ->
+ {error,lists:flatten([Terror3,Verror5,Cerror,
+ Oerror,Exporterror,ImportError])}
end.
context_switch_in_spec() ->
@@ -338,51 +338,40 @@ chained_import(S,ImpMod,DefMod,Name) ->
chained_import(S,OtherMod,DefMod,Name)
end
end.
-
-checkt(S,[Name|T],Acc) ->
- ?dbg("Checking type ~p~n",[Name]),
- Result =
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({type,{internal_error,'???'},S});
- Type when is_record(Type,typedef) ->
- NewS = S#state{type=Type,tname=Name},
- case catch(check_type(NewS,Type,Type#typedef.typespec)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1_class,_ClassDef} ->
- {asn1_class,Name};
- pobjectsetdef ->
- {pobjectsetdef,Name};
- pvalueset ->
- {pvalueset,Name};
- Ts ->
- case Type#typedef.checked of
- true -> % already checked and updated
- ok;
- _ ->
- NewTypeDef = Type#typedef{checked=true,typespec = Ts},
-
- asn1_db:dbput(NewS#state.mname,Name,NewTypeDef), % update the type
- ok
- end
- end
- end,
- case Result of
- ok ->
- checkt(S,T,Acc);
- _ ->
- checkt(S,T,[Result|Acc])
- end;
-checkt(S,[],Acc) ->
- case check_contextswitchingtypes(S,[]) of
- [] ->
- lists:reverse(Acc);
- L ->
- checkt(S,L,Acc)
+checkt(S0, Names) ->
+ Check = fun do_checkt/3,
+
+ %% NOTE: check_type/3 will store information in the process
+ %% dictionary if context switching types are encountered;
+ %% therefore we must force the evaluation order.
+ Types = check_fold(S0, Names, Check),
+ CtxtSwitch = check_contextswitchingtypes(S0, []),
+ check_fold(S0, lists:reverse(CtxtSwitch), Check) ++ Types.
+
+do_checkt(S, Name, #typedef{typespec=TypeSpec}=Type0) ->
+ NewS = S#state{type=Type0,tname=Name},
+ try check_type(NewS, Type0, TypeSpec) of
+ #type{}=Ts ->
+ case Type0#typedef.checked of
+ true -> %already checked and updated
+ ok;
+ _ ->
+ Type = Type0#typedef{checked=true,
+ typespec=Ts},
+ asn1_db:dbput(NewS#state.mname,
+ Name, Type),
+ ok
+ end
+ catch
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {asn1_class,_ClassDef} ->
+ {asn1_class,Name};
+ pobjectsetdef ->
+ {pobjectsetdef,Name};
+ pvalueset ->
+ {pvalueset,Name}
end.
check_contextswitchingtypes(S,Acc) ->
@@ -402,131 +391,86 @@ check_contextswitchingtypes(S,[{T,TName}|Ts],Acc) ->
check_contextswitchingtypes(_,[],Acc) ->
Acc.
-checkv(S,[Name|T],Acc) ->
- ?dbg("Checking valuedef ~p~n",[Name]),
- Result = case asn1_db:dbget(S#state.mname,Name) of
- undefined -> error({value,{internal_error,'???'},S});
- Value when is_record(Value,valuedef);
- is_record(Value,typedef); %Value set may be parsed as object set.
- is_record(Value,pvaluedef);
- is_record(Value,pvaluesetdef) ->
- NewS = S#state{value=Value},
- case catch(check_value(NewS,Value)) of
- {error,Reason} ->
- error({value,Reason,NewS});
- {'EXIT',Reason} ->
- error({value,{internal_error,Reason},NewS});
- {pobjectsetdef} ->
- {pobjectsetdef,Name};
- {objectsetdef} ->
- {objectsetdef,Name};
- {objectdef} ->
- %% this is an object, save as typedef
- #valuedef{checked=C,pos=Pos,name=N,type=Type,
- value=Def}=Value,
- ClassName = Type#type.def,
- NewSpec = #'Object'{classname=ClassName,
- def=Def},
- NewDef = #typedef{checked=C,pos=Pos,name=N,
- typespec=NewSpec},
- asn1_db:dbput(NewS#state.mname,Name,NewDef),
- {objectdef,Name};
- {valueset,VSet} ->
- Pos = asn1ct:get_pos_of_def(Value),
- CheckedVSDef = #typedef{checked=true,pos=Pos,
- name=Name,typespec=VSet},
- asn1_db:dbput(NewS#state.mname,Name,CheckedVSDef),
- {valueset,Name};
- V ->
- %% update the valuedef
- asn1_db:dbput(NewS#state.mname,Name,V),
- ok
- end
- end,
- case Result of
- ok ->
- checkv(S,T,Acc);
- _ ->
- checkv(S,T,[Result|Acc])
- end;
-checkv(_S,[],Acc) ->
- lists:reverse(Acc).
-
-
-checkp(S,[Name|T],Acc) ->
- %io:format("check_ptypedef:~p~n",[Name]),
- Result = case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({type,{internal_error,'???'},S});
- Type when is_record(Type,ptypedef) ->
- NewS = S#state{type=Type,tname=Name},
- case catch(check_ptype(NewS,Type,Type#ptypedef.typespec)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1_class,_ClassDef} ->
- {asn1_class,Name};
- {asn1_param_class,_} -> ok;
- Ts ->
- NewType = Type#ptypedef{checked=true,typespec = Ts},
- asn1_db:dbput(NewS#state.mname,Name,NewType), % update the type
- ok
- end
- end,
- case Result of
- ok ->
- checkp(S,T,Acc);
- _ ->
- checkp(S,T,[Result|Acc])
- end;
-checkp(_S,[],Acc) ->
- lists:reverse(Acc).
-
+checkv(S, Names) ->
+ check_fold(S, Names, fun do_checkv/3).
+
+do_checkv(S, Name, Value)
+ when is_record(Value, valuedef);
+ is_record(Value, typedef); %Value set may be parsed as object set.
+ is_record(Value, pvaluedef);
+ is_record(Value, pvaluesetdef) ->
+ NewS = S#state{value=Value},
+ try check_value(NewS, Value) of
+ {valueset,VSet} ->
+ Pos = asn1ct:get_pos_of_def(Value),
+ CheckedVSDef = #typedef{checked=true,pos=Pos,
+ name=Name,typespec=VSet},
+ asn1_db:dbput(NewS#state.mname, Name, CheckedVSDef),
+ {valueset,Name};
+ V ->
+ %% update the valuedef
+ asn1_db:dbput(NewS#state.mname, Name, V),
+ ok
+ catch
+ {error,Reason} ->
+ error({value,Reason,NewS});
+ {pobjectsetdef} ->
+ {pobjectsetdef,Name};
+ {objectsetdef} ->
+ {objectsetdef,Name};
+ {objectdef} ->
+ %% this is an object, save as typedef
+ #valuedef{checked=C,pos=Pos,name=N,type=Type,
+ value=Def} = Value,
+ ClassName = Type#type.def,
+ NewSpec = #'Object'{classname=ClassName,def=Def},
+ NewDef = #typedef{checked=C,pos=Pos,name=N,typespec=NewSpec},
+ asn1_db:dbput(NewS#state.mname, Name, NewDef),
+ {objectdef,Name}
+ end.
+%% Check parameterized types.
+checkp(S, Names) ->
+ check_fold(S, Names, fun do_checkp/3).
+do_checkp(S0, Name, #ptypedef{typespec=TypeSpec}=Type0) ->
+ S = S0#state{type=Type0,tname=Name},
+ try check_ptype(S, Type0, TypeSpec) of
+ #type{}=Ts ->
+ Type = Type0#ptypedef{checked=true,typespec=Ts},
+ asn1_db:dbput(S#state.mname, Name, Type),
+ ok
+ catch
+ {error,Reason} ->
+ error({type,Reason,S});
+ {asn1_class,_ClassDef} ->
+ {asn1_class,Name};
+ {asn1_param_class,_} ->
+ ok
+ end.
-checkc(S,[Name|Cs],Acc) ->
- Result =
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({class,{internal_error,'???'},S});
- Class ->
- ClassSpec = if
- is_record(Class,classdef) ->
-% Class#classdef.typespec;
- Class;
- is_record(Class,typedef) ->
- Class#typedef.typespec
- end,
- NewS = S#state{type=Class,tname=Name},
- case catch(check_class(NewS,ClassSpec)) of
- {error,Reason} ->
- error({class,Reason,NewS});
- {'EXIT',Reason} ->
- error({class,{internal_error,Reason},NewS});
- C ->
- %% update the classdef
- NewClass =
- if
- is_record(Class,classdef) ->
- Class#classdef{checked=true,typespec=C};
- is_record(Class,typedef) ->
- #classdef{checked=true,name=Name,typespec=C}
- end,
- asn1_db:dbput(NewS#state.mname,Name,NewClass),
- ok
- end
+%% Check class definitions.
+checkc(S, Names) ->
+ check_fold(S, Names, fun do_checkc/3).
+
+do_checkc(S0, Name, Class0) ->
+ {Class1,ClassSpec} =
+ case Class0 of
+ #classdef{} ->
+ {Class0,Class0};
+ #typedef{} ->
+ {#classdef{name=Name},Class0#typedef.typespec}
end,
- case Result of
- ok ->
- checkc(S,Cs,Acc);
- _ ->
- checkc(S,Cs,[Result|Acc])
- end;
-checkc(_S,[],Acc) ->
-%% include_default_class(S#state.mname),
- lists:reverse(Acc).
+ S = S0#state{type=Class0,tname=Name},
+ try check_class(S, ClassSpec) of
+ C ->
+ Class = Class1#classdef{checked=true,typespec=C},
+ asn1_db:dbput(S#state.mname, Name, Class),
+ ok
+ catch
+ {error,Reason} ->
+ error({class,Reason,S})
+ end.
checko(S,[Name|Os],Acc,ExclO,ExclOS) ->
?dbg("Checking object ~p~n",[Name]),
@@ -695,8 +639,7 @@ check_class_fields(S,[F|Fields],Acc) ->
Type2 = maybe_unchecked_OCFT(S,Type),
Cat =
case asn1ct_gen:type(asn1ct_gen:get_inner(Type2#type.def)) of
- Def when is_record(Def,typereference);
- is_record(Def,'Externaltypereference') ->
+ Def when is_record(Def,'Externaltypereference') ->
{_,D} = get_referenced_type(S,Def),
D;
{undefined,user} ->
@@ -876,14 +819,6 @@ check_object(S,
?dbg("check_object set: ~p~n",[ObjSet#'ObjectSet'.set]),
{_,ClassDef} = get_referenced_type(S,ClassRef),
NewClassRef = check_externaltypereference(S,ClassRef),
- %% XXXXXXXXXX
- case ObjSet of
- #'ObjectSet'{set={'Externaltypereference',undefined,'MSAccessProtocol',
- 'AllOperations'}} ->
- ok;
- _ ->
- ok
- end,
{UniqueFieldName,UniqueInfo} =
case (catch get_unique_fieldname(S,ClassDef)) of
{error,'__undefined_',_} ->
@@ -1233,8 +1168,7 @@ check_object_list(S,ClassRef,[ObjOrSet|Objs],Acc) ->
ObjSet when is_record(ObjSet,type) ->
ObjSetDef =
case ObjSet#type.def of
- Ref when is_record(Ref,typereference);
- is_record(Ref,'Externaltypereference') ->
+ Ref when is_record(Ref,'Externaltypereference') ->
{_,D} = get_referenced_type(S,ObjSet#type.def),
D;
Other ->
@@ -1263,13 +1197,13 @@ check_object_list(S,ClassRef,[ObjOrSet|Objs],Acc) ->
check_object_list(S,ClassRef,Objs,[{{no_mod,no_name},Def}|Acc]);
{'ObjectSetFromObjects',Os,FieldName} when is_tuple(Os) ->
NewSet =
- check_ObjectSetFromObjects(S,element(size(Os),Os),
+ check_ObjectSetFromObjects(S, element(tuple_size(Os), Os),
FieldName,[]),
check_object_list(S,ClassRef,Objs,NewSet++Acc);
{{'ObjectSetFromObjects',Os,FieldName},InterSection}
when is_tuple(Os) ->
NewSet =
- check_ObjectSetFromObjects(S, element(size(Os),Os),
+ check_ObjectSetFromObjects(S, element(tuple_size(Os), Os),
FieldName,InterSection),
check_object_list(S,ClassRef,Objs,NewSet++Acc);
Other ->
@@ -1570,7 +1504,7 @@ gen_incl_set(S,Fields,#typedef{typespec=#type{def=Eref}})
gen_incl_set(S,Fields,CDef);
gen_incl_set(S,Fields,ClassDef) ->
case catch get_unique_fieldname(S,ClassDef) of
- Tuple when is_tuple(Tuple), size(Tuple) =:= 3 ->
+ Tuple when tuple_size(Tuple) =:= 3 ->
false;
_ ->
gen_incl_set1(S,Fields,
@@ -1589,7 +1523,7 @@ gen_incl_set1(_,['EXTENSIONMARK'],_) ->
gen_incl_set1(_,['EXTENSIONMARK'|_],_) ->
true;
gen_incl_set1(S,[Object|Rest],CFields)->
- Fields = element(size(Object),Object),
+ Fields = element(tuple_size(Object), Object),
case gen_incl1(S,Fields,CFields) of
true ->
true;
@@ -1826,10 +1760,6 @@ convert_to_defaultfield(S,ObjFieldName,[OFS|RestOFS],CField)->
T = check_type(S,#typedef{typespec=ObjFieldSetting},
ObjFieldSetting),
{#typedef{checked=true,name=Bif,typespec=T},RestSettings};
- _OCFT = #'ObjectClassFieldType'{} ->
- T=check_type(S,#typedef{typespec=ObjFieldSetting},ObjFieldSetting),
- %%io:format("OCFT=~p~n,T=~p~n",[OCFT,T]),
- {#typedef{checked=true,typespec=T},RestSettings};
_ ->
%this case should not happen any more
{Mod,T} =
@@ -2140,172 +2070,72 @@ check_value(S,#valuedef{pos=Pos,name=Name,type=Type,
NewType = Type#type{constraint=[Constr]},
{valueset,
check_type(S,#typedef{pos=Pos,name=Name,typespec=NewType},NewType)};
-check_value(OldS=#state{recordtopname=TopName},V) when is_record(V,valuedef) ->
- #valuedef{name=Name,checked=Checked,type=Vtype,
- value=Value,module=ModName} = V,
- ?dbg("check_value, V: ~p~n",[V]),
- case Checked of
- true ->
- V;
- {error,_} ->
+check_value(S, #valuedef{}=V) ->
+ ?dbg("check_value, V: ~p~n",[V0]),
+ case V of
+ #valuedef{checked=true} ->
V;
- false ->
- Def = Vtype#type.def,
- Constr = Vtype#type.constraint,
- S = OldS#state{type=Vtype,tname=Def,value=V,vname=Name},
- SVal = update_state(S,ModName),
- NewDef =
- case Def of
- Ext when is_record(Ext,'Externaltypereference') ->
- RecName = Ext#'Externaltypereference'.type,
- {RefM,Type} = get_referenced_type(S,Ext),
- %% If V isn't a value but an object Type is a #classdef{}
- %%NewS = S#state{mname=RefM},
- NewS = update_state(S,RefM),
- case Type of
- #classdef{} ->
- throw({objectdef});
- #typedef{} ->
- case is_contextswitchtype(Type) of
- true ->
- #valuedef{value=CheckedVal}=
- check_value(NewS,V#valuedef{type=Type#typedef.typespec}),
- #newv{value=CheckedVal};
- _ ->
- #valuedef{value=CheckedVal}=
- check_value(NewS#state{recordtopname=[RecName|TopName]},
- V#valuedef{type=Type#typedef.typespec}),
- #newv{value=CheckedVal}
- end;
- #type{} ->
- %% A parameter that couldn't be categorized.
- #valuedef{value=CheckedVal}=
- check_value(NewS#state{recordtopname=[RecName|TopName]},
- V#valuedef{type=Type}),
- #newv{value=CheckedVal}
- end;
- 'ANY' ->
- case Value of
- {opentypefieldvalue,ANYType,ANYValue} ->
- CheckedV=
- check_value(SVal,#valuedef{name=Name,
- type=ANYType,
- value=ANYValue,
- module=ModName}),
- #newv{value=CheckedV#valuedef.value};
- _ ->
- throw({error,{asn1,{'cant check value of type',Def}}})
- end;
- 'INTEGER' ->
- ok=validate_integer(SVal,Value,[],Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- {'INTEGER',NamedNumberList} ->
- ok=validate_integer(SVal,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- {'BIT STRING',NamedNumberList} ->
- ok=validate_bitstring(SVal,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'NULL' ->
- ok=validate_null(SVal,Value,Constr),
- #newv{};
- 'OBJECT IDENTIFIER' ->
- {ok,_}=validate_objectidentifier(SVal,Value,Constr),
- #newv{value = normalize_value(SVal,Vtype,Value,[])};
- 'RELATIVE-OID' ->
- {ok,_}=validate_relative_oid(SVal,Value,Constr),
- #newv{value = Value};
- 'ObjectDescriptor' ->
- ok=validate_objectdescriptor(SVal,Value,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'REAL' ->
- ok = validate_real(SVal,Value,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- {'ENUMERATED',NamedNumberList} ->
- ok=validate_enumerated(SVal,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'BOOLEAN'->
- ok=validate_boolean(SVal,Value,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'OCTET STRING' ->
- ok=validate_octetstring(SVal,Value,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'NumericString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- TString when TString =:= 'TeletexString';
- TString =:= 'T61String' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'VideotexString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'UTCTime' ->
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
-% exit({'cant check value of type' ,Def});
- 'GeneralizedTime' ->
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
-% exit({'cant check value of type' ,Def});
- 'GraphicString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'VisibleString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'GeneralString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'PrintableString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'IA5String' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'BMPString' ->
- ok=validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'UTF8String' ->
- ok = validate_restrictedstring(SVal,Vtype,Value,Constr),
- %%io:format("Vtype: ~p~nValue: ~p~n",[Vtype,Value]);
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- 'UniversalString' -> %added 6/12 -00
- ok = validate_restrictedstring(SVal,Value,Def,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,[])};
- Seq when is_record(Seq,'SEQUENCE') ->
- {ok,SeqVal} = validate_sequence(SVal,Value,
- Seq#'SEQUENCE'.components,
- Constr),
- #newv{value=normalize_value(SVal,Vtype,SeqVal,TopName)};
- {'SEQUENCE OF',Components} ->
- ok=validate_sequenceof(SVal,Value,Components,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,TopName)};
- {'CHOICE',Components} ->
- ok=validate_choice(SVal,Value,Components,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,TopName)};
- Set when is_record(Set,'SET') ->
- ok=validate_set(SVal,Value,Set#'SET'.components,
- Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,TopName)};
- {'SET OF',Components} ->
- ok=validate_setof(SVal,Value,Components,Constr),
- #newv{value=normalize_value(SVal,Vtype,Value,TopName)};
- {'SelectionType',SelName,SelT} ->
- CheckedT = check_selectiontype(SVal,SelName,SelT),
- NewV = V#valuedef{type=CheckedT},
- SelVDef=check_value(S#state{value=NewV},NewV),
- #newv{value=SelVDef#valuedef.value};
- Other ->
- exit({'cannot check value of type' ,Other})
- end,
- case NewDef#newv.value of
- unchanged ->
- V#valuedef{checked=true,value=Value};
- ok ->
- V#valuedef{checked=true,value=Value};
- {error,Reason} ->
- V#valuedef{checked={error,Reason},value=Value};
- _V ->
- V#valuedef{checked=true,value=_V}
- end
+ #valuedef{checked=false} ->
+ check_valuedef(S, V)
+ end.
+
+check_valuedef(#state{recordtopname=TopName}=S0, V0) ->
+ #valuedef{name=Name,type=Vtype,value=Value,module=ModName} = V0,
+ V = V0#valuedef{checked=true},
+ Def = Vtype#type.def,
+ Constr = Vtype#type.constraint,
+ S1 = S0#state{type=Vtype,tname=Def,value=V0,vname=Name},
+ SVal = update_state(S1, ModName),
+ case Def of
+ #'Externaltypereference'{type=RecName}=Ext ->
+ {RefM,Type} = get_referenced_type(S1, Ext),
+ %% If V isn't a value but an object Type is a #classdef{}
+ S2 = update_state(S1, RefM),
+ case Type of
+ #classdef{} ->
+ throw({objectdef});
+ #typedef{typespec=TypeSpec} ->
+ S3 = case is_contextswitchtype(Type) of
+ true ->
+ S2;
+ false ->
+ S2#state{recordtopname=[RecName|TopName]}
+ end,
+ #valuedef{value=CheckedVal} =
+ check_value(S3, V0#valuedef{type=TypeSpec}),
+ V#valuedef{value=CheckedVal};
+ #type{} ->
+ %% A parameter that couldn't be categorized.
+ #valuedef{value=CheckedVal} =
+ check_value(S2#state{recordtopname=[RecName|TopName]},
+ V#valuedef{type=Type}),
+ V#valuedef{value=CheckedVal}
+ end;
+ 'ANY' ->
+ {opentypefieldvalue,ANYType,ANYValue} = Value,
+ CheckedV = check_value(SVal,#valuedef{name=Name,
+ type=ANYType,
+ value=ANYValue,
+ module=ModName}),
+ V#valuedef{value=CheckedV#valuedef.value};
+ 'INTEGER' ->
+ ok = validate_integer(SVal, Value, [], Constr),
+ V#valuedef{value=normalize_value(SVal, Vtype, Value, [])};
+ {'INTEGER',NamedNumberList} ->
+ ok = validate_integer(SVal, Value, NamedNumberList, Constr),
+ V#valuedef{value=normalize_value(SVal, Vtype, Value, [])};
+ #'SEQUENCE'{components=Components} ->
+ {ok,SeqVal} = validate_sequence(SVal, Value,
+ Components, Constr),
+ V#valuedef{value=normalize_value(SVal, Vtype,
+ SeqVal, TopName)};
+ {'SelectionType',SelName,SelT} ->
+ CheckedT = check_selectiontype(SVal, SelName, SelT),
+ NewV = V#valuedef{type=CheckedT},
+ SelVDef = check_value(S1#state{value=NewV}, NewV),
+ V#valuedef{value=SelVDef#valuedef.value};
+ _ ->
+ V#valuedef{value=normalize_value(SVal, Vtype, Value, TopName)}
end.
is_contextswitchtype(#typedef{name='EXTERNAL'})->
@@ -2358,23 +2188,7 @@ validate_integer_ref(S,Ref,NamedNumberList,Constr) ->
-check_integer_range(Int,Constr) when is_list(Constr) ->
- NewConstr = [X || #constraint{c=X} <- Constr],
- check_constr(Int,NewConstr);
-
-check_integer_range(_Int,_Constr) ->
- %%io:format("~p~n",[Constr]),
- ok.
-
-check_constr(Int,[{'ValueRange',Lb,Ub}|T]) when Int >= Lb, Int =< Ub ->
- check_constr(Int,T);
-check_constr(_Int,[]) ->
- ok.
-
-validate_bitstring(_S,_Value,_NamedNumberList,_Constr) ->
- ok.
-
-validate_null(_S,'NULL',_Constr) ->
+check_integer_range(_Int, Constr) when is_list(Constr) ->
ok.
%%------------
@@ -2390,9 +2204,6 @@ is_space_list([],Acc) ->
is_space_list([H|T],Acc) ->
is_space_list(T,[H|Acc]).
-validate_objectidentifier(S,ERef,C) ->
- validate_objectidentifier(S,o_id,ERef,C).
-
validate_objectidentifier(S,OID,ERef,C)
when is_record(ERef,'Externalvaluereference') ->
validate_objectidentifier(S,OID,[ERef],C);
@@ -2490,9 +2301,6 @@ validate_oid(_, S, OID, [Atom|Rest],Acc) when is_atom(Atom) ->
validate_oid(_, S, OID, V, Acc) ->
error({value, {"illegal "++to_string(OID),V,Acc},S}).
-validate_relative_oid(S,Value,Constr) ->
- validate_objectidentifier(S,rel_oid,Value,Constr).
-
is_object_id(OID,S,ERef=#'Externaltypereference'{}) ->
{_,OI} = get_referenced_type(S,ERef),
is_object_id(OID,S,OI#typedef.typespec);
@@ -2579,43 +2387,6 @@ valid_objectid(o_id,_I,[1]) -> false;
valid_objectid(o_id,_I,[2]) -> true;
valid_objectid(_,_,_) -> true.
-
-
-
-
-
-validate_objectdescriptor(_S,_Value,_Constr) ->
- ok.
-
-validate_real(_S,_Value,_Constr) ->
- ok.
-
-validate_enumerated(S,Id,NamedNumberList,_Constr) when is_atom(Id) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end;
-validate_enumerated(S,{identifier,_Pos,Id},NamedNumberList,_Constr) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end;
-validate_enumerated(S,#'Externalvaluereference'{value=Id},
- NamedNumberList,_Constr) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end.
-
-validate_boolean(_S,_Value,_Constr) ->
- ok.
-
-validate_octetstring(_S,_Value,_Constr) ->
- ok.
-
-validate_restrictedstring(_S,_Value,_Def,_Constr) ->
- ok.
-
validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
case Vtype of
#type{tag=[{tag,'UNIVERSAL',8,'IMPLICIT',32}]} ->
@@ -2630,18 +2401,6 @@ validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
{ok,Value}
end.
-validate_sequenceof(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_choice(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_set(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_setof(_S,_Value,_Components,_Constr) ->
- ok.
-
to_EXTERNAL1990(S,[{identification,{'CHOICE',{syntax,Stx}}}|Rest]) ->
to_EXTERNAL1990(S,Rest,[{'direct-reference',Stx}]);
to_EXTERNAL1990(S,[{identification,{'CHOICE',{'presentation-context-id',I}}}|Rest]) ->
@@ -2667,7 +2426,8 @@ normalize_value(_,_,mandatory,_) ->
mandatory;
normalize_value(_,_,'OPTIONAL',_) ->
'OPTIONAL';
-normalize_value(S,Type,{'DEFAULT',Value},NameList) ->
+normalize_value(S0, Type, {'DEFAULT',Value}, NameList) ->
+ S = S0#state{value=Value},
case catch get_canonic_type(S,Type,NameList) of
{'BOOLEAN',CType,_} ->
normalize_boolean(S,Value,CType);
@@ -2892,12 +2652,12 @@ hstring_to_octetlist([H|T],BSL,Acc) when H >= $0; H =< $9 ->
hstring_to_octetlist([],_,Acc) ->
lists:reverse(Acc).
-normalize_objectidentifier(S,Value) ->
- {ok,Val}=validate_objectidentifier(S,Value,[]),
+normalize_objectidentifier(S, Value) ->
+ {ok,Val} = validate_objectidentifier(S, o_id, Value, []),
Val.
normalize_relative_oid(S,Value) ->
- {ok,Val} = validate_relative_oid(S,Value,[]),
+ {ok,Val} = validate_objectidentifier(S, rel_oid, Value, []),
Val.
normalize_objectdescriptor(Value) ->
@@ -2906,29 +2666,20 @@ normalize_objectdescriptor(Value) ->
normalize_real(Value) ->
Value.
-normalize_enumerated(S,#'Externalvaluereference'{value=V},CType)
- when is_list(CType) ->
- normalize_enumerated2(S,V,CType);
-normalize_enumerated(S,Value,CType) when is_atom(Value),is_list(CType) ->
- normalize_enumerated2(S,Value,CType);
-normalize_enumerated(S,{Name,EnumV},CType) when is_atom(Name) ->
- normalize_enumerated(S,EnumV,CType);
-normalize_enumerated(S,Value,{CType1,CType2}) when is_list(CType1), is_list(CType2)->
- normalize_enumerated(S,Value,CType1++CType2);
-normalize_enumerated(S,V,CType) ->
- asn1ct:warning("Enumerated unknown type ~p~n",[CType],S,
- "Enumerated unknown type"),
- V.
-normalize_enumerated2(S,V,Enum) ->
- case lists:keysearch(V,1,Enum) of
- {value,{Val,_}} -> Val;
- _ ->
- asn1ct:warning("enumerated value is not correct ~p~n",[V],S,
- "enumerated value is not correct"),
- V
+normalize_enumerated(S, Id, {Base,Ext}) ->
+ %% Extensible ENUMERATED.
+ normalize_enumerated(S, Id, Base++Ext);
+normalize_enumerated(S, #'Externalvaluereference'{value=Id},
+ NamedNumberList) ->
+ normalize_enumerated(S, Id, NamedNumberList);
+normalize_enumerated(S, Id, NamedNumberList) when is_atom(Id) ->
+ case lists:keymember(Id, 1, NamedNumberList) of
+ true ->
+ Id;
+ false ->
+ throw(asn1_error(S, S#state.value, {undefined,Id}))
end.
-
normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when is_atom(C) ->
case catch lists:keysearch(C,#'ComponentType'.name,CType) of
{value,#'ComponentType'{typespec=CT,name=Name}} ->
@@ -3028,7 +2779,7 @@ is_record_normalized(S,Name,V = #'Externalvaluereference'{},NumComps) ->
_ -> false
end;
is_record_normalized(_S,Name,Value,NumComps) when is_tuple(Value) ->
- (size(Value) =:= (NumComps + 1)) andalso (element(1,Value)=:=Name);
+ (tuple_size(Value) =:= (NumComps + 1)) andalso (element(1, Value) =:= Name);
is_record_normalized(_,_,_,_) ->
false.
@@ -3262,7 +3013,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
inlined=IsInlined},
TestFun =
fun(Tref) ->
- {_,MaybeChoice} = get_referenced_type(S,Tref),
+ MaybeChoice = get_non_typedef(S, Tref),
case catch((MaybeChoice#typedef.typespec)#type.def) of
{'CHOICE',_} ->
maybe_illicit_implicit_tag(choice,Tag);
@@ -3347,7 +3098,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
TempNewDef#newt{
type = check_externaltypereference(S,NewExt),
tag = case S#state.erule of
- ber_bin_v2 ->
+ ber ->
merge_tags(Ct,RefType#type.tag);
_ ->
Ct
@@ -3535,10 +3286,6 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
merge_tags(Tag,?TAG_CONSTRUCTED(?N_SET))};
%% This is a temporary hack until the full Information Obj Spec
%% in X.681 is supported
- {{typereference,_,'TYPE-IDENTIFIER'},[{typefieldreference,_,'Type'}]} ->
- Ct=maybe_illicit_implicit_tag(open_type,Tag),
- TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
-
{#'Externaltypereference'{type='TYPE-IDENTIFIER'},
[{typefieldreference,_,'Type'}]} ->
Ct=maybe_illicit_implicit_tag(open_type,Tag),
@@ -3575,7 +3322,15 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
_ ->
MergedTag
end,
- TempNewDef#newt{type=NewTypeDef,tag=Ct};
+ case TopName of
+ [] when Type#typedef.name =/= undefined ->
+ %% This is a top-level type.
+ #type{def=Simplified} =
+ simplify_type(#type{def=NewTypeDef}),
+ TempNewDef#newt{type=Simplified,tag=Ct};
+ _ ->
+ TempNewDef#newt{type=NewTypeDef,tag=Ct}
+ end;
{'TypeFromObject',{object,Object},TypeField} ->
CheckedT = get_type_from_object(S,Object,TypeField),
@@ -3591,32 +3346,47 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
Other ->
exit({'cant check' ,Other})
end,
- Ts2 = case NewDef of
- #newt{type=unchanged} ->
- Ts#type{def=Def};
- #newt{type=TDef}->
- Ts#type{def=TDef}
- end,
- NewTag = case NewDef of
- #newt{tag=unchanged} ->
- Tag;
- #newt{tag=TT} ->
- TT
- end,
- T3 = Ts2#type{tag = lists:map(fun(TempTag = #tag{type={default,TTx}}) ->
- TempTag#tag{type=TTx};
- (Else) -> Else end, NewTag)},
- T4 = case NewDef of
- #newt{constraint=unchanged} ->
- T3#type{constraint=Constr};
- #newt{constraint=NewConstr} ->
- T3#type{constraint=NewConstr}
- end,
- T5 = T4#type{inlined=NewDef#newt.inlined},
- T5#type{constraint=check_constraints(S,T5#type.constraint)};
+ #newt{type=TDef,tag=NewTags,constraint=NewConstr,inlined=Inlined} = NewDef,
+ Ts#type{def=TDef,
+ inlined=Inlined,
+ constraint=check_constraints(S, NewConstr),
+ tag=lists:map(fun(#tag{type={default,TTx}}=TempTag) ->
+ TempTag#tag{type=TTx};
+ (Other) -> Other
+ end, NewTags)};
check_type(_S,Type,Ts) ->
exit({error,{asn1,internal_error,Type,Ts}}).
+get_non_typedef(S, Tref0) ->
+ case get_referenced_type(S, Tref0) of
+ {_,#typedef{typespec=#type{def=#'Externaltypereference'{}=Tref}}} ->
+ get_non_typedef(S, Tref);
+ {_,Type} ->
+ Type
+ end.
+
+
+%%
+%% Simplify the backends by getting rid of an #'ObjectClassFieldType'{}
+%% with a type known at compile time.
+%%
+
+simplify_comps(Comps) ->
+ [simplify_comp(Comp) || Comp <- Comps].
+
+simplify_comp(#'ComponentType'{typespec=Type0}=C) ->
+ Type = simplify_type(Type0),
+ C#'ComponentType'{typespec=Type};
+simplify_comp(Other) -> Other.
+
+simplify_type(#type{tag=Tag,def=Inner}=T) ->
+ case Inner of
+ #'ObjectClassFieldType'{type={fixedtypevaluefield,_,Type}} ->
+ Type#type{tag=Tag};
+ _ ->
+ T
+ end.
+
%% tablecinf_choose. A SEQUENCE or SET may be inserted in another
%% SEQUENCE or SET by the COMPONENTS OF directive. If this inserted
%% type is a referenced type that already has been checked it already
@@ -3712,7 +3482,7 @@ maybe_open_type(S,ClassSpec=#objectclass{fields=Fs},
{typefieldreference,_} ->
case {catch get_unique_fieldname(S,#classdef{typespec=ClassSpec}),
asn1ct_gen:get_constraint(Constr,componentrelation)}of
- {Tuple,_} when is_tuple(Tuple), size(Tuple) =:= 3 ->
+ {Tuple,_} when tuple_size(Tuple) =:= 3 ->
OCFT#'ObjectClassFieldType'{fieldname=FieldNames,
type='ASN1_OPEN_TYPE'};
{_,no} ->
@@ -3995,26 +3765,10 @@ categorize(_S,type,Def) when is_record(Def,type) ->
categorize(_,_,Def) ->
[Def].
categorize(S,object_set,Def,ClassRef) ->
- %% XXXXXXXXXX
- case Def of
- {'Externaltypereference',undefined,'MSAccessProtocol','AllOperations'} ->
- ok;
- _ ->
- ok
- end,
NewObjSetSpec =
check_object(S,Def,#'ObjectSet'{class = ClassRef,
set = parse_objectset(Def)}),
Name = new_reference_name("object_set_argument"),
- %% XXXXXXXXXX
- case Name of
- internal_object_set_argument_78 ->
- ok;
- internal_object_set_argument_77 ->
- ok;
- _ ->
- ok
- end,
[save_object_set_instance(S,Name,NewObjSetSpec)];
categorize(_S,object,Def,_ClassRef) ->
%% should be handled
@@ -4040,9 +3794,7 @@ parse_objectset(Set) ->
%% check_constraints/2
%%
check_constraints(S,C) when is_list(C) ->
- check_constraints(S, C, []);
-check_constraints(S,C) when is_record(C,constraint) ->
- check_constraints(S, C#constraint.c, []).
+ check_constraints(S, C, []).
resolv_tuple_or_list(S,List) when is_list(List) ->
lists:map(fun(X)->resolv_value(S,X) end, List);
@@ -4069,23 +3821,19 @@ resolv_value1(S, ERef = #'Externalvaluereference'{value=Name}) ->
resolv_value1(S,VDef)
end
end;
-resolv_value1(S,{gt,V}) ->
- case V of
+resolv_value1(S, {gt,V}) ->
+ case resolv_value1(S, V) of
Int when is_integer(Int) ->
- V + 1;
- #valuedef{value=Int} ->
- 1 + resolv_value(S,Int);
+ Int + 1;
Other ->
- throw({error,{asn1,{undefined_type_or_value,Other}}})
+ throw({error,{asn1,{not_integer_value,Other}}})
end;
-resolv_value1(S,{lt,V}) ->
- case V of
+resolv_value1(S, {lt,V}) ->
+ case resolv_value1(S, V) of
Int when is_integer(Int) ->
- V - 1;
- #valuedef{value=Int} ->
- resolv_value(S,Int) - 1;
+ Int - 1;
Other ->
- throw({error,{asn1,{undefined_type_or_value,Other}}})
+ throw({error,{asn1,{not_integer_value,Other}}})
end;
resolv_value1(S,{'ValueFromObject',{object,Object},[{valuefieldreference,
FieldName}]}) ->
@@ -4159,7 +3907,7 @@ check_constraint(S,Ext) when is_record(Ext,'Externaltypereference') ->
check_constraint(S,{'SizeConstraint',{Lb,Ub}})
- when is_list(Lb);is_tuple(Lb),size(Lb)==2 ->
+ when is_list(Lb); tuple_size(Lb) =:= 2 ->
NewLb = range_check(resolv_tuple_or_list(S,Lb)),
NewUb = range_check(resolv_tuple_or_list(S,Ub)),
{'SizeConstraint',{NewLb,NewUb}};
@@ -4332,11 +4080,68 @@ permitted_alphabet_merge([C1|Rest],UorI,Acc) ->
%% there will be no extension if the last constraint is without extension.
%% The rootset of all constraints are considered in the "outermoust
%% intersection". See section 13.1.2 in Dubuisson.
-constraint_merge(_S,C=[H])when is_tuple(H) ->
+constraint_merge(St, Cs0) ->
+ Cs = constraint_merge_1(St, Cs0),
+ normalize_cs(Cs).
+
+normalize_cs([{'SingleValue',[V]}|Cs]) ->
+ [{'SingleValue',V}|normalize_cs(Cs)];
+normalize_cs([{'SingleValue',[_|_]=L0}|Cs]) ->
+ [H|T] = L = lists:usort(L0),
+ [case is_range(H, T) of
+ false -> {'SingleValue',L};
+ true -> {'ValueRange',{H,lists:last(T)}}
+ end|normalize_cs(Cs)];
+normalize_cs([{'ValueRange',{Sv,Sv}}|Cs]) ->
+ [{'SingleValue',Sv}|normalize_cs(Cs)];
+normalize_cs([{'ValueRange',{'MIN','MAX'}}|Cs]) ->
+ normalize_cs(Cs);
+normalize_cs([{'SizeConstraint',C0}|Cs]) ->
+ case normalize_size_constraint(C0) of
+ none ->
+ normalize_cs(Cs);
+ C ->
+ [{'SizeConstraint',C}|normalize_cs(Cs)]
+ end;
+normalize_cs([H|T]) ->
+ [H|normalize_cs(T)];
+normalize_cs([]) -> [].
+
+%% Normalize a size constraint to make it non-ambiguous and
+%% easy to interpret for the backends.
+%%
+%% Returns one of the following terms:
+%% {LowerBound,UpperBound}
+%% {{LowerBound,UpperBound},[]} % Extensible
+%% none % Remove size constraint from list
+%%
+%% where:
+%% LowerBound = integer()
+%% UpperBound = integer() | 'MAX'
+
+normalize_size_constraint(Sv) when is_integer(Sv) ->
+ {Sv,Sv};
+normalize_size_constraint({Root,Ext}) when is_list(Ext) ->
+ {normalize_size_constraint(Root),[]};
+normalize_size_constraint({{_,_},Ext}) when is_integer(Ext) ->
+ normalize_size_constraint(Ext);
+normalize_size_constraint([H|T]) ->
+ {H,lists:last(T)};
+normalize_size_constraint({0,'MAX'}) ->
+ none;
+normalize_size_constraint({Lb,Ub}=Range)
+ when is_integer(Lb), is_integer(Ub) orelse Ub =:= 'MAX' ->
+ Range.
+
+is_range(Prev, [H|T]) when Prev =:= H - 1 -> is_range(H, T);
+is_range(_, [_|_]) -> false;
+is_range(_, []) -> true.
+
+constraint_merge_1(_S, [H]=C) when is_tuple(H) ->
C;
-constraint_merge(_S,[]) ->
+constraint_merge_1(_S, []) ->
[];
-constraint_merge(S,C) ->
+constraint_merge_1(S, C) ->
%% skip all extension but the last extension
C1 = filter_extensions(C),
%% perform all internal level intersections, intersections first
@@ -4359,17 +4164,16 @@ constraint_merge(S,C) ->
%% get the least common size constraint
SZs = get_constraints(C3,'SizeConstraint'),
CombSZ = intersection_of_size(S,SZs),
- CminusSVs=ordsets:subtract(ordsets:from_list(C3),ordsets:from_list(SVs)),
- % CminusSVsVRs = ordsets:subtract(ordsets:from_list(CminusSVs),
-% ordsets:from_list(VRs)),
- RestC = ordsets:subtract(ordsets:from_list(CminusSVs),
- ordsets:from_list(SZs)),
+ RestC = ordsets:subtract(ordsets:from_list(C3),
+ ordsets:from_list(SZs ++ VRs ++ SVs)),
%% get the least common combined constraint. That is the union of each
- %% deep costraint and merge of single value and value range constraints
- NewCs = combine_constraints(S,CombSV,CombVR,CombSZ++RestC),
- [X||X <- lists:flatten(NewCs),
- X /= intersection,
- X /= union].
+ %% deep constraint and merge of single value and value range constraints.
+ %% FIXME: Removing 'intersection' from the flattened list essentially
+ %% means that intersections are converted to unions!
+ Cs = combine_constraints(S, CombSV, CombVR, CombSZ++RestC),
+ [X || X <- lists:flatten(Cs),
+ X =/= intersection,
+ X =/= union].
%% constraint_union(S,C) takes a list of constraints as input and
%% merge them to a union. Unions are performed when two
@@ -4399,16 +4203,16 @@ constraint_union(_S,C) ->
constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) ->
AunionB = constraint_union_vr([A,B]),
- constraint_union1(S,Rest,Acc ++ AunionB);
+ constraint_union1(S, AunionB++Rest, Acc);
constraint_union1(S,[A={'SingleValue',_},union,B={'SingleValue',_}|Rest],Acc) ->
AunionB = constraint_union_sv(S,[A,B]),
constraint_union1(S,Rest,Acc ++ AunionB);
constraint_union1(S,[A={'SingleValue',_},union,B={'ValueRange',_}|Rest],Acc) ->
AunionB = union_sv_vr(S,A,B),
- constraint_union1(S,Rest,Acc ++ AunionB);
+ constraint_union1(S, AunionB++Rest, Acc);
constraint_union1(S,[A={'ValueRange',_},union,B={'SingleValue',_}|Rest],Acc) ->
AunionB = union_sv_vr(S,B,A),
- constraint_union1(S,Rest,Acc ++ AunionB);
+ constraint_union1(S, AunionB++Rest, Acc);
constraint_union1(S,[union|Rest],Acc) -> %skip when unsupported constraints
constraint_union1(S,Rest,Acc);
constraint_union1(S,[A|Rest],Acc) ->
@@ -4441,15 +4245,8 @@ constraint_union_vr(VR) ->
({_,{A1,_B1}},{_,{A2,_B2}}) when is_integer(A1),is_integer(A2),A1<A2 -> true;
({_,{A,B1}},{_,{A,B2}}) when B1=<B2->true;
(_,_)->false end,
- % sort and remove duplicates
- SortedVR = lists:sort(Fun,VR),
- RemoveDup = fun([],_) ->[];
- ([H],_) -> [H];
- ([H,H|T],F) -> F([H|T],F);
- ([H|T],F) -> [H|F(T,F)]
- end,
-
- constraint_union_vr(RemoveDup(SortedVR,RemoveDup),[]).
+ SortedVR = lists:usort(Fun,VR),
+ constraint_union_vr(SortedVR, []).
constraint_union_vr([],Acc) ->
lists:reverse(Acc);
@@ -4459,8 +4256,8 @@ constraint_union_vr([{_,{Lb,Ub2}}|Rest],[{_,{Lb,_Ub1}}|Acc]) -> %Ub2 > Ub1
constraint_union_vr(Rest,[{'ValueRange',{Lb,Ub2}}|Acc]);
constraint_union_vr([{_,{_,Ub}}|Rest],A=[{_,{_,Ub}}|_Acc]) ->
constraint_union_vr(Rest,A);
-constraint_union_vr([{_,{Lb2,Ub2}}|Rest],[{_,{Lb1,Ub1}}|Acc]) when Lb2=<Ub1,
- Ub2>Ub1->
+constraint_union_vr([{_,{Lb2,Ub2}}|Rest], [{_,{Lb1,Ub1}}|Acc])
+ when Ub1 =< Lb2, Ub1 < Ub2 ->
constraint_union_vr(Rest,[{'ValueRange',{Lb1,Ub2}}|Acc]);
constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1->
constraint_union_vr(Rest,A);
@@ -4581,9 +4378,11 @@ constraint_intersection(_S,C) ->
constraint_intersection1(S,[A,intersection,B|Rest],Acc) ->
AisecB = c_intersect(S,A,B),
- constraint_intersection1(S,Rest,AisecB++Acc);
+ constraint_intersection1(S, AisecB++Rest, Acc);
constraint_intersection1(S,[A|Rest],Acc) ->
constraint_intersection1(S,Rest,[A|Acc]);
+constraint_intersection1(_, [], [C]) ->
+ C;
constraint_intersection1(_,[],Acc) ->
lists:reverse(Acc).
@@ -4901,19 +4700,7 @@ get_referenced(S,Emod,Ename,Pos) ->
end;
T when is_record(T,typedef) ->
?dbg("get_referenced T: ~p~n",[T]),
- Spec = T#typedef.typespec, %% XXXX Spec may be something else than #type
- case Spec of
- #type{def=#typereference{}} ->
- Tref = Spec#type.def,
- Def = #'Externaltypereference'{module=Emod,
- type=Tref#typereference.val,
- pos=Tref#typereference.pos},
-
-
- {Emod,T#typedef{typespec=Spec#type{def=Def}}};
- _ ->
- {Emod,T} % should add check that T is exported here
- end;
+ {Emod,T}; % should add check that T is exported here
V ->
?dbg("get_referenced V: ~p~n",[V]),
{Emod,V}
@@ -5193,7 +4980,7 @@ imported1(_Name,[]) ->
check_integer(_S,[],_C) ->
[];
check_integer(S,NamedNumberList,_C) ->
- case [X||X<-NamedNumberList,is_tuple(X),size(X)=:=2] of
+ case [X || X <- NamedNumberList, tuple_size(X) =:= 2] of
NamedNumberList ->
%% An already checked integer with NamedNumberList
NamedNumberList;
@@ -5289,7 +5076,7 @@ iof_associated_type(S,[]) ->
AssociateSeq = iof_associated_type1(S,[]),
Tag =
case S#state.erule of
- ber_bin_v2 ->
+ ber ->
[?TAG_CONSTRUCTED(?N_INSTANCE_OF)];
_ -> []
end,
@@ -5320,7 +5107,7 @@ iof_associated_type1(S,C) ->
end,
{ObjIdTag,C1TypeTag}=
case S#state.erule of
- ber_bin_v2 ->
+ ber ->
{[{'UNIVERSAL',8}],
[#tag{class='UNIVERSAL',
number=6,
@@ -5361,14 +5148,14 @@ iof_associated_type1(S,C) ->
prop=mandatory,
tags=[{'CONTEXT',0}]}],
#'SEQUENCE'{tablecinf=TableCInf,
- components=IOFComponents}.
+ components=simplify_comps(IOFComponents)}.
%% returns the leading attribute, the constraint of the components and
%% the tablecinf value for the second component.
instance_of_constraints(_,[]) ->
{false,[],[],[]};
-instance_of_constraints(S,#constraint{c={simpletable,Type}}) ->
+instance_of_constraints(S, [{simpletable,Type}]) ->
#type{def=#'Externaltypereference'{type=Name}} = Type,
ModuleName = S#state.mname,
ObjectSetRef=#'Externaltypereference'{module=ModuleName,
@@ -5379,7 +5166,8 @@ instance_of_constraints(S,#constraint{c={simpletable,Type}}) ->
[{innermost,
[#'Externalvaluereference'{module=ModuleName,
value=type}]}]}],
- TableCInf=#simpletableattributes{objectsetname=Name,
+ Mod = S#state.mname,
+ TableCInf=#simpletableattributes{objectsetname={Mod,Name},
c_name='type-id',
c_index=1,
usedclassfield=id,
@@ -5515,45 +5303,37 @@ check_sequence(S,Type,Comps) ->
%% the involved class removed, as the class of the object
%% set.
CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2),
- %% If encoding rule is in the PER family the Root Components
- %% after the second extension mark should be encoded before
- %% all extensions i.e together with the first Root components
NewComps3 = textual_order(CompListWithTblInf),
- CompListTuple =
- complist_as_tuple(is_erule_per(S#state.erule),NewComps3),
+ NewComps4 = simplify_comps(NewComps3),
+ CompListTuple = complist_as_tuple(NewComps4),
{CRelInf,CompListTuple};
Dupl ->
throw({error,{asn1,{duplicate_components,Dupl}}})
end.
-complist_as_tuple(Per,CompList) ->
- complist_as_tuple(Per,CompList,[],[],[],root).
+complist_as_tuple(CompList) ->
+ complist_as_tuple(CompList, [], [], [], root).
-complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,root) ->
- complist_as_tuple(Per,T,Acc,Ext,Acc2,ext);
-complist_as_tuple(Per,[#'EXTENSIONMARK'{}|T],Acc,Ext,Acc2,ext) ->
- complist_as_tuple(Per,T,Acc,Ext,Acc2,root2);
-complist_as_tuple(_Per,[#'EXTENSIONMARK'{}|_T],_Acc,_Ext,_Acc2,root2) ->
+complist_as_tuple([#'EXTENSIONMARK'{}|T], Acc, Ext, Acc2, root) ->
+ complist_as_tuple(T, Acc, Ext, Acc2, ext);
+complist_as_tuple([#'EXTENSIONMARK'{}|T], Acc, Ext, Acc2, ext) ->
+ complist_as_tuple(T, Acc, Ext, Acc2, root2);
+complist_as_tuple([#'EXTENSIONMARK'{}|_T], _Acc, _Ext, _Acc2, root2) ->
throw({error,{asn1,{too_many_extension_marks}}});
-complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root) ->
- complist_as_tuple(Per,T,[C|Acc],Ext,Acc2,root);
-complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,ext) ->
- complist_as_tuple(Per,T,Acc,[C|Ext],Acc2,ext);
-complist_as_tuple(Per,[C|T],Acc,Ext,Acc2,root2) ->
- complist_as_tuple(Per,T,Acc,Ext,[C|Acc2],root2);
-complist_as_tuple(_Per,[],Acc,_Ext,_Acc2,root) ->
+complist_as_tuple([C|T], Acc, Ext, Acc2, root) ->
+ complist_as_tuple(T, [C|Acc], Ext, Acc2, root);
+complist_as_tuple([C|T], Acc, Ext, Acc2, ext) ->
+ complist_as_tuple(T, Acc, [C|Ext], Acc2, ext);
+complist_as_tuple([C|T], Acc, Ext, Acc2, root2) ->
+ complist_as_tuple(T, Acc, Ext, [C|Acc2], root2);
+complist_as_tuple([], Acc, _Ext, _Acc2, root) ->
lists:reverse(Acc);
-complist_as_tuple(_Per,[],Acc,Ext,_Acc2,ext) ->
+complist_as_tuple([], Acc, Ext, _Acc2, ext) ->
{lists:reverse(Acc),lists:reverse(Ext)};
-%%complist_as_tuple(_Per = true,[],Acc,Ext,Acc2,root2) ->
-%% {lists:reverse(Acc)++lists:reverse(Acc2),lists:reverse(Ext)};
-complist_as_tuple(_Per,[],Acc,Ext,Acc2,root2) ->
+complist_as_tuple([], Acc, Ext, Acc2, root2) ->
{lists:reverse(Acc),lists:reverse(Ext),lists:reverse(Acc2)}.
-is_erule_per(Erule) ->
- lists:member(Erule,[per,per_bin,uper_bin]).
-
expand_components(S, [{'COMPONENTS OF',Type}|T]) ->
CompList = expand_components2(S,get_referenced_type(S,Type#type.def)),
expand_components(S,CompList) ++ expand_components(S,T);
@@ -5597,7 +5377,7 @@ take_only_rootset([H|T]) ->
[H|take_only_rootset(T)].
check_unique_sequence_tags(S,CompList) ->
- TagComps = case complist_as_tuple(false,CompList) of
+ TagComps = case complist_as_tuple(CompList) of
{R1,Ext,R2} ->
R1 ++ [C#'ComponentType'{prop='OPTIONAL'}||
C = #'ComponentType'{} <- Ext]++R2;
@@ -5632,7 +5412,7 @@ check_unique_sequence_tags1(S,[],Acc) ->
check_unique_tags(S,lists:reverse(Acc)).
check_sequenceof(S,Type,Component) when is_record(Component,type) ->
- check_type(S,Type,Component).
+ simplify_type(check_type(S, Type, Component)).
check_set(S,Type,Components) ->
{TableCInf,NewComponents} = check_sequence(S,Type,Components),
@@ -5641,7 +5421,7 @@ check_set(S,Type,Components) ->
{true,_} ->
{Sorted,SortedComponents} = sort_components(der,S,NewComponents),
{Sorted,TableCInf,SortedComponents};
- {_,PER} when PER =:= per; PER =:= per_bin; PER =:= uper_bin ->
+ {_,PER} when PER =:= per; PER =:= uper ->
{Sorted,SortedComponents} = sort_components(per,S,NewComponents),
{Sorted,TableCInf,SortedComponents};
_ ->
@@ -5765,7 +5545,7 @@ sort_universal_type(Components) ->
decode_type(I) when is_integer(I) ->
I;
decode_type(T) ->
- asn1ct_gen_ber:decode_type(T).
+ asn1ct_gen_ber_bin_v2:decode_type(T).
untagged_choice(_S,[#'ComponentType'{typespec=#type{tag=[],def={'CHOICE',_}}}|_Rest]) ->
true;
@@ -5854,7 +5634,7 @@ extension({Root1,ExtList,Root2}) ->
X = #'ComponentType'{prop=Y}<-ExtList], Root2}.
check_setof(S,Type,Component) when is_record(Component,type) ->
- check_type(S,Type,Component).
+ simplify_type(check_type(S, Type, Component)).
check_selectiontype(S,Name,#type{def=Eref})
when is_record(Eref,'Externaltypereference') ->
@@ -5918,8 +5698,9 @@ check_choice(S,Type,Components) when is_list(Components) ->
('ExtensionAdditionGroupEnd') -> false;
(_) -> true
end,NewComps),
- check_unique_tags(S,NewComps2),
- complist_as_tuple(is_erule_per(S#state.erule),NewComps2);
+ NewComps3 = simplify_comps(NewComps2),
+ check_unique_tags(S, NewComps3),
+ complist_as_tuple(NewComps3);
Dupl ->
throw({error,{asn1,{duplicate_choice_alternatives,Dupl}}})
end;
@@ -6297,7 +6078,7 @@ get_simple_table_info1(S,#'ComponentType'{typespec=TS},Cnames,Path) ->
simple_table_info(S,#'ObjectClassFieldType'{classname=ClRef,
class=ObjectClass,
fieldname=FieldName},Path) ->
-
+
ObjectClassFieldName =
case FieldName of
{LastFieldName,[]} -> LastFieldName;
@@ -6850,9 +6631,6 @@ get_OCFType(S,Fields,[PrimFieldName|Rest]) ->
get_taglist(S,Ext) when is_record(Ext,'Externaltypereference') ->
{_,T} = get_referenced_type(S,Ext),
get_taglist(S,T#typedef.typespec);
-get_taglist(S,Tref) when is_record(Tref,typereference) ->
- {_,T} = get_referenced_type(S,Tref),
- get_taglist(S,T#typedef.typespec);
get_taglist(S,Type) when is_record(Type,type) ->
case Type#type.tag of
[] ->
@@ -6884,16 +6662,16 @@ get_taglist(S,{ObjCl,FieldNameList}) when is_record(ObjCl,objectclass),
{TypeFieldName,_} when is_atom(TypeFieldName) -> []%should check if allowed
end;
get_taglist(S,Def) ->
- case lists:member(S#state.erule,[ber_bin_v2]) of
- false ->
+ case S#state.erule of
+ ber ->
+ [];
+ _ ->
case Def of
'ASN1_OPEN_TYPE' -> % open_type has no UNIVERSAL tag as such
[];
_ ->
[asn1ct_gen:def_to_tag(Def)]
- end;
- _ ->
- []
+ end
end.
get_taglist1(S,[#'ComponentType'{name=_Cname,tags=TagL}|Rest]) when is_list(TagL) ->
@@ -7022,60 +6800,27 @@ storeindb(S,M) when is_record(M,module) ->
NewM = M#module{typeorval=findtypes_and_values(TVlist)},
asn1_db:dbnew(NewM#module.name),
asn1_db:dbput(NewM#module.name,'MODULE', NewM),
- Res = storeindb(NewM#module.name,TVlist,[]),
+ Res = storeindb(#state{mname=NewM#module.name}, TVlist, []),
include_default_class(S,NewM#module.name),
include_default_type(NewM#module.name),
Res.
-storeindb(Module,[H|T],ErrAcc) when is_record(H,typedef) ->
- storeindb(Module,H#typedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,valuedef) ->
- storeindb(Module,H#valuedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,ptypedef) ->
- storeindb(Module,H#ptypedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,classdef) ->
- storeindb(Module,H#classdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,pvaluesetdef) ->
- storeindb(Module,H#pvaluesetdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,pobjectdef) ->
- storeindb(Module,H#pobjectdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when is_record(H,pvaluedef) ->
- storeindb(Module,H#pvaluedef.name,H,T,ErrAcc);
-storeindb(_,[],[]) -> ok;
-storeindb(_,[],ErrAcc) ->
- {error,ErrAcc}.
-
-storeindb(Module,Name,H,T,ErrAcc) ->
- case asn1_db:dbget(Module,Name) of
+storeindb(#state{mname=Module}=S, [H|T], Errors) ->
+ Name = asn1ct:get_name_of_def(H),
+ case asn1_db:dbget(Module, Name) of
undefined ->
- asn1_db:dbput(Module,Name,H),
- storeindb(Module,T,ErrAcc);
- _ ->
- case H of
- _Type when is_record(H,typedef) ->
- error({type,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when is_record(H,valuedef) ->
- error({value,"already defined",
- #state{mname=Module,value=H,vname=Name}});
- _Type when is_record(H,ptypedef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when is_record(H,pobjectdef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when is_record(H,pvaluesetdef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when is_record(H,pvaluedef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when is_record(H,classdef) ->
- error({class,"already defined",
- #state{mname=Module,value=H,vname=Name}})
- end,
- storeindb(Module,T,[H|ErrAcc])
- end.
+ asn1_db:dbput(Module, Name, H),
+ storeindb(S, T, Errors);
+ Prev ->
+ PrevLine = asn1ct:get_pos_of_def(Prev),
+ {error,Error} = asn1_error(S, H, {already_defined,Name,PrevLine}),
+ storeindb(S, T, [Error|Errors])
+ end;
+storeindb(_, [], []) ->
+ ok;
+storeindb(_, [], [_|_]=Errors) ->
+ {error,Errors}.
+
findtypes_and_values(TVList) ->
findtypes_and_values(TVList,[],[],[],[],[],[]).%% Types,Values,
@@ -7115,8 +6860,20 @@ findtypes_and_values([],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc) ->
{lists:reverse(Tacc),lists:reverse(Vacc),lists:reverse(Pacc),
lists:reverse(Cacc),lists:reverse(Oacc),lists:reverse(OSacc)}.
-
-
+asn1_error(#state{mname=Where}, Item, Error) ->
+ Pos = asn1ct:get_pos_of_def(Item),
+ {error,{structured_error,{Where,Pos},?MODULE,Error}}.
+
+format_error({already_defined,Name,PrevLine}) ->
+ io_lib:format("the name ~p has already been defined at line ~p",
+ [Name,PrevLine]);
+format_error({undefined,Name}) ->
+ io_lib:format("'~s' is referenced, but is not defined", [Name]);
+format_error(Other) ->
+ io_lib:format("~p", [Other]).
+
+error({_,{structured_error,_,_,_}=SE,_}) ->
+ SE;
error({export,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) ->
Pos = Ref#'Externaltypereference'.pos,
io:format("asn1error:~p:~p:~p~n~p~n",[Pos,Mname,Typename,Msg]),
@@ -7419,3 +7176,13 @@ insert_once(S,Tab,Key) ->
_ ->
skipped
end.
+
+check_fold(S, [H|T], Check) ->
+ Type = asn1_db:dbget(S#state.mname, H),
+ case Check(S, H, Type) of
+ ok ->
+ check_fold(S, T, Check);
+ Error ->
+ [Error|check_fold(S, T, Check)]
+ end;
+check_fold(_, [], Check) when is_function(Check, 3) -> [].
diff --git a/lib/asn1/src/asn1ct_constructed_ber.erl b/lib/asn1/src/asn1ct_constructed_ber.erl
deleted file mode 100644
index 360de77663..0000000000
--- a/lib/asn1/src/asn1ct_constructed_ber.erl
+++ /dev/null
@@ -1,1596 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2011. 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%
-%%
-%%
--module(asn1ct_constructed_ber).
-
--export([gen_encode_sequence/3]).
--export([gen_decode_sequence/3]).
--export([gen_encode_set/3]).
--export([gen_decode_set/3]).
--export([gen_encode_sof/4]).
--export([gen_decode_sof/4]).
--export([gen_encode_choice/3]).
--export([gen_decode_choice/3]).
-
-%%%% Application internal exports
--export([match_tag/2]).
-
--include("asn1_records.hrl").
-
--import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/0]).
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
-
- %% if EXTERNAL type the input value must be transformed to
- %% ASN1 1990 format
- case Typename of
- ['EXTERNAL'] ->
- emit([" NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
- nl]);
- _ ->
- ok
- end,
-
- {SeqOrSet,TableConsInfo,CompList0} =
- case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {'SEQUENCE',TCI,CL};
- #'SET'{tablecinf=TCI,components=CL} ->
- {'SET',TCI,CL}
- end,
- %% filter away extensionAdditiongroup markers
- CompList = filter_complist(CompList0),
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl1,El,Rl2} -> Rl1 ++ El ++ Rl2;
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- EncObj =
- case TableConsInfo of
- #simpletableattributes{usedclassfield=Used,
- uniqueclassfield=Unique} when Used /= Unique ->
- false;
- %% ObjectSetRef, name of the object set in constraints
- %%
- %%{ObjectSetRef,AttrN,N,UniqueFieldName}
- #simpletableattributes{objectsetname=ObjectSetRef,
- c_name=AttrN,
- c_index=N,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex
- } ->
- OSDef =
- case ObjectSetRef of
- {Module,OSName} ->
- asn1_db:dbget(Module,OSName);
- OSName ->
- asn1_db:dbget(get(currmod),OSName)
- end,
-% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
-% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
- case (OSDef#typedef.typespec)#'ObjectSet'.gen of
- true ->
-% Val = lists:concat(["?RT_BER:cindex(",
-% N+1,",Val,"]),
- ObjectEncode =
- asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
- AttrN])),
- emit({ObjectEncode," = ",nl}),
- {ObjSetMod,ObjSetName} =
- case ObjectSetRef of
- {M,O} ->
- {{asis,M},O};
- O ->
- {"?MODULE",O}
- end,
- emit({" ",ObjSetMod,":'getenc_",ObjSetName,"'(",{asis,UniqueFieldName},
- ", ",nl}),
-% emit({indent(35),"?RT_BER:cindex(",N+1,", Val,",
-% {asis,AttrN},")),",nl}),
- Length = fun(X,_LFun) when is_atom(X) ->
- length(atom_to_list(X));
- (X,_LFun) when is_list(X) ->
- length(X);
- ({X1,X2},LFun) ->
- LFun(X1,LFun) + LFun(X2,LFun)
- end,
- emit([indent(10+Length(ObjectSetRef,Length)),
- "value_match(",{asis,ValueIndex},",",
- "?RT_BER:cindex(",N+1,",Val,",
- {asis,AttrN},"))),",nl]),
- notice_value_match(),
- {AttrN,ObjectEncode};
- _ ->
- false
- end;
- _ ->
- case D#type.tablecinf of
- [{objfun,_}|_] ->
- %% when the simpletableattributes was at an
- %% outer level and the objfun has been passed
- %% through the function call
- {"got objfun through args","ObjFun"};
- _ ->
- false
- end
- end,
-
- gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
-
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(SeqOrSet),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([nl," BytesSoFar = "]),
- case SeqOrSet of
- 'SET' when (D#type.def)#'SET'.sorted == dynamic ->
- emit("asn1rt_check:dynamicsort_SET_components(["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["]),",nl]);
- _ ->
- emit("["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["],",nl])
- end,
- emit(" LenSoFar = "),
- case asn1ct_name:all(encLen) of
- [] -> emit("0");
- AllLengths ->
- mkvplus(AllLengths)
- end,
- emit([",",nl]),
-% emit(["{TagBytes,Len} = ?RT_BER:encode_tags(TagIn ++ ",
- emit([" ?RT_BER:encode_tags(TagIn ++ ",
- {asis,MyTag},", BytesSoFar, LenSoFar).",nl]).
-
-
-gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(tag),
- #'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def,
-
- %% filter away extensionAdditiongroup markers
- CList = filter_complist(CList0),
-
- Ext = extensible(CList),
- {CompList,CompList2} = case CList of
- {Rl1,El,Rl2} -> {Rl1 ++ El ++ Rl2,CList};
- {Rl,El} -> {Rl ++ El, Rl ++ El};
- _ -> {CList,CList}
- end,
-
- emit([" %%-------------------------------------------------",nl]),
- emit([" %% decode tag and length ",nl]),
- emit([" %%-------------------------------------------------",nl]),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type('SEQUENCE'),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,",asn1ct_gen_ber:unused_var("Len",D#type.def),"},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
-
- case CompList of
- [] -> true;
- _ ->
- emit({"{",{next,bytes},
- ",RemBytes} = ?RT_BER:split_list(",
- {curr,bytes},
- ",", {prev,len},"),",nl}),
- asn1ct_name:new(bytes)
- end,
-
- {DecObjInf,UniqueFName,ValueIndex} =
- case TableConsInfo of
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValIndex
- } ->
- F = fun(#'ComponentType'{typespec=CT})->
- case {asn1ct_gen:get_constraint(CT#type.constraint,componentrelation),CT#type.tablecinf} of
-% case {CT#type.constraint,CT#type.tablecinf} of
- {no,[{objfun,_}|_R]} -> true;
- _ -> false
- end
- end,
- case lists:any(F,CompList) of
- %%AttributeName = asn1ct_gen:un_hyphen_var(AttrN),
- true -> % when component relation constraint establish
- %% relation from a component to another components
- %% subtype component
- {{AttrN,{deep,ObjectSet,UniqueFieldName,
- ValIndex}},
- UniqueFieldName,ValIndex};
- false ->
- {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
- end;
- _ ->
- {false,false,false}
- end,
- RecordName = lists:concat([get_record_name_prefix(),asn1ct_gen:list2rname(Typename)]),
- case gen_dec_sequence_call(Erules,Typename,CompList2,Ext,DecObjInf) of
- no_terms -> % an empty sequence
- emit([nl,nl]),
- demit({"Result = "}), %dbg
- %% return value as record
- asn1ct_name:new(rb),
- emit([" {{'",RecordName,"'}, ",{curr,bytes},",",nl," "]),
- asn1ct_gen_ber:add_removed_bytes(),
- emit(["}.",nl]);
- {LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
- case {LeadingAttrTerm,PostponedDecArgs} of
- {[],[]} ->
- ok;
- {_,[]} ->
- ok;
- {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} =
- case ObjSet of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",ObjSet}
- end,
- emit([DecObj," =",nl," ",ObjSetMod,":'getdec_",ObjSetName,"'(",
-% {asis,UniqueFName},", ",Term,"),",nl}),
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
- gen_dec_postponed_decs(DecObj,PostponedDecArgs)
- end,
- demit({"Result = "}), %dbg
- %% return value as record
- asn1ct_name:new(rb),
- asn1ct_name:new(bytes),
- ExtStatus = case Ext of
- {ext,_,_} -> ext;
- _ -> noext % noext | extensible
- end,
- emit([" {",{next,bytes},",",{curr,rb},"} = ?RT_BER:restbytes2(RemBytes, ",
- {curr,bytes},",",ExtStatus,"),",nl]),
- asn1ct_name:new(rb),
- case Typename of
- ['EXTERNAL'] ->
- emit([" OldFormat={'",RecordName,
- "', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["},",nl]),
- emit([" ASN11994Format =",nl,
- " asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat),",nl]),
- emit([" {ASN11994Format,",{next,bytes},", "]);
- _ ->
- emit([" {{'",RecordName,"', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["}, ",{next,bytes},", "])
- end,
- asn1ct_gen_ber:add_removed_bytes(),
- emit(["}.",nl])
- end.
-
-gen_dec_postponed_decs(_,[]) ->
- emit(nl);
-gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->
-% asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
-
- emit({"{",Term,", _, _} = ",nl}),
- N = case OptOrMand of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
- emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
-% ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),
- ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),
- emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),
- emit({indent(N+9),"exit({'Type not compatible with table constraint',",
- {curr,reason},"});",nl}),
- emit({indent(N+6),{curr,tmpterm}," ->",nl}),
- emit({indent(N+9),{curr,tmpterm},nl}),
-
- case OptOrMand of
- mandatory -> emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
-% emit({indent(3),"end,",nl}),
- gen_dec_postponed_decs(DecObj,Rest).
-
-
-emit_opt_or_mand_check(Value,TmpTerm) ->
- emit([indent(3),"case ",TmpTerm," of",nl,
- indent(6),{asis,Value}," -> {",{asis,Value},",[],[]};",nl,
- indent(6),"_ ->",nl]).
-
-%%============================================================================
-%% Encode/decode SET
-%%
-%%============================================================================
-
-gen_encode_set(Erules,Typename,D) when is_record(D,type) ->
- gen_encode_sequence(Erules,Typename,D).
-
-gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:clear(),
- asn1ct_name:new(term),
- asn1ct_name:new(tag),
- #'SET'{components=TCompList0} = D#type.def,
-
- %% filter away extensionAdditiongroup markers
- TCompList = filter_complist(TCompList0),
- Ext = extensible(TCompList),
- ToOptional = fun(mandatory) ->
- 'OPTIONAL';
- (X) -> X
- end,
- CompList = case TCompList of
- {Rl1,El,Rl2} ->
- Rl1 ++ [X#'ComponentType'{prop=ToOptional(Y)}||X = #'ComponentType'{prop=Y}<-El] ++ Rl2;
- {Rl,El} -> Rl ++ El;
- _ -> TCompList
- end,
-
- emit([" %%-------------------------------------------------",nl]),
- emit([" %% decode tag and length ",nl]),
- emit([" %%-------------------------------------------------",nl]),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type('SET'),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,Len},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
- asn1ct_name:new(rb),
-
- emit([" {SetTerm, SetBytes, ",{curr,rb},"} = ?RT_BER:decode_set(0, Len, ",
- {curr,bytes},", OptOrMand, ",
- "fun 'dec_",asn1ct_gen:list2name(Typename),"_fun'/2, []),",nl]),
-
- asn1ct_name:new(rb),
- {ExtFlatten1,ExtFlatten2} =
- case Ext of
- noext -> {"",""};
- _ -> {"lists:flatten(",")"}
- end,
- emit([" 'dec_",asn1ct_gen:list2name(Typename),
- "__result__'(lists:sort(",ExtFlatten1,"SetTerm",ExtFlatten2,"), SetBytes, "]),
- asn1ct_gen_ber:add_removed_bytes(),
- emit([").",nl,nl,nl]),
-
- emit({"%%-------------------------------------------------",nl}),
- emit({"%% Set loop fun for ",asn1ct_gen:list2name(Typename),nl}),
- emit({"%%-------------------------------------------------",nl}),
-
- asn1ct_name:clear(),
- asn1ct_name:new(term),
- emit(["'dec_",asn1ct_gen:list2name(Typename),"_fun'(",{curr,bytes},
- ", OptOrMand) ->",nl]),
-
- asn1ct_name:new(bytes),
- gen_dec_set(Erules,Typename,CompList,1,Ext),
-
- emit([" %% tag not found, if extensionmark we should skip bytes here",nl]),
- emit([indent(6),"_ -> ",nl]),
- case Ext of
- noext ->
- emit([indent(9),"{[], Bytes,0}",nl]);
- _ ->
- asn1ct_name:new(rbCho),
- emit([indent(9),"{RestBytes, ",{curr,rbCho},
- "} = ?RT_BER:skipvalue(Bytes),",nl,
- indent(9),"{[], RestBytes, ",{curr,rbCho},"}",nl])
- end,
- emit([indent(3),"end.",nl,nl,nl]),
-
-
- emit({"%%-------------------------------------------------",nl}),
- emit({"%% Result ",asn1ct_gen:list2name(Typename),nl}),
- emit({"%%-------------------------------------------------",nl}),
-
- asn1ct_name:clear(),
- emit({"'dec_",asn1ct_gen:list2name(Typename),"__result__'(",
- asn1ct_gen_ber:unused_var("TermList",D#type.def),", Bytes, Rb) ->",nl}),
- RecordName = lists:concat([get_record_name_prefix(),
- asn1ct_gen:list2rname(Typename)]),
- case gen_dec_set_result(Erules,Typename,CompList) of
- no_terms ->
- %% return value as record
- asn1ct_name:new(rb),
- emit({" {{'",RecordName,"'}, Bytes, Rb}.",nl});
- _ ->
- emit({nl," case ",{curr,termList}," of",nl}),
- emit({" [] -> {{'",RecordName,"', "}),
- mkvlist(asn1ct_name:all(term)),
- emit({"}, Bytes, Rb};",nl}),
- emit({" ExtraAtt -> exit({error,{asn1,{too_many_attributes, ExtraAtt}}})",nl}),
- emit({" end.",nl}),
- emit({nl,nl,nl})
- end.
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE OF and SET OF
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sof(Erules,Typename,_InnerTypename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- {SeqOrSetOf, Cont} = D#type.def,
-
- Objfun = case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
-
- emit({" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",Objfun,",[],0),",nl}),
-
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(SeqOrSetOf),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
-% gen_encode_tags(Erules,MyTag,"EncLen","EncBytes"),
- emit([" ?RT_BER:encode_tags(TagIn ++ ",
- {asis,MyTag},", EncBytes, EncLen).",nl,nl]),
-
- gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
-% gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",0,
-% mandatory,"{EncBytes,EncLen} = "),
-
-
-gen_decode_sof(Erules,Typename,_InnerTypename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:clear(),
- {SeqOrSetOf, TypeTag, Cont} =
- case D#type.def of
- {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
- {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
- end,
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
-
- emit({" %%-------------------------------------------------",nl}),
- emit({" %% decode tag and length ",nl}),
- emit({" %%-------------------------------------------------",nl}),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(TypeTag),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,Len},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
-
- emit([" ?RT_BER:decode_components(",{curr,rb}]),
- InnerType = asn1ct_gen:get_inner(Cont#type.def),
- ContName = case asn1ct_gen:type(InnerType) of
- Atom when is_atom(Atom) -> Atom;
- _ -> TypeNameSuffix
- end,
- emit([", Len, ",{next,bytes},", "]),
-% NewCont =
-% case Cont#type.def of
-% {'ENUMERATED',_,Components}->
-% Cont#type{def={'ENUMERATED',Components}};
-% _ -> Cont
-% end,
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- []
- end,
- gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
- emit([", []).",nl,nl,nl]).
-
-
-gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
- when is_record(Cont,type)->
-
- {Objfun,ObjFun_novar,EncObj} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _",{no_attr,"ObjFun"}};
- _ ->
- {"","",false}
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([]",ObjFun_novar,", AccBytes, AccLen) -> ",nl]),
-
- case catch lists:member(der,get(encoding_options)) of
- true when SeqOrSetOf=='SET OF' ->
- emit([indent(3),
- "{asn1rt_check:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
- _ ->
- emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
- gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
-% mandatory,"{EncBytes,EncLen} = ",EncObj),
- mandatory,EncObj),
- emit([",",nl]),
- emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(T",Objfun,","]),
- emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
-
-%%============================================================================
-%% Encode/decode CHOICE
-%%
-%%============================================================================
-
-gen_encode_choice(Erules,Typename,D) when is_record(D,type) ->
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl1,El,Rl2} -> Rl1 ++ El ++ Rl2;
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit({nl,nl}).
-
-gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(bytes),
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl1,El,Rl2} -> Rl1 ++ El ++Rl2;
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit({".",nl}).
-
-
-%%============================================================================
-%% Encode SEQUENCE
-%%
-%%============================================================================
-
-gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,textual_order=Order}|Rest],Pos,Ext,EncObj) ->
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- CindexPos =
- case Order of
- undefined ->
- Pos;
- _ -> Order % der
- end,
- Element =
- case TopType of
- ['EXTERNAL'] ->
- io_lib:format("?RT_BER:cindex(~w,NewVal,~w)",[CindexPos+1,Cname]);
- _ ->
- io_lib:format("?RT_BER:cindex(~w,Val,~w)",[CindexPos+1,Cname])
- end,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- print_attribute_comment(InnerType,Pos,Prop),
- gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
- case Rest of
- [] ->
- emit({com,nl});
- _ ->
- emit({com,nl}),
- gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj)
- end;
-
-gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
- true.
-
-%%============================================================================
-%% Decode SEQUENCE
-%%
-%%============================================================================
-
-gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf)
- when is_list(CompList) ->
- gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]);
-gen_dec_sequence_call(Erules,TopType,CList,Ext,DecObjInf) ->
- gen_dec_sequence_call2(Erules,TopType,CList,Ext,DecObjInf).
-
-gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
- {LA,PostponedDec} =
- gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
- Ext,DecObjInf),
- case Rest of
- [] ->
- {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
- _ ->
- emit({com,nl}),
-% asn1ct_name:new(term),
- asn1ct_name:new(bytes),
- gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
- LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
- end;
-
-gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
- no_terms.
-
-gen_dec_sequence_call2(_Erules,_TopType,{[],[],[]},_Ext,_DecObjInf) ->
- no_terms;
-gen_dec_sequence_call2(Erules,TopType,{Root1,EList,Root2},_Ext,DecObjInf) ->
- {LA,ArgsAcc} =
- case gen_dec_sequence_call1(Erules,TopType,Root1++EList,1,
- extensible({Root1,EList}),DecObjInf,[],[]) of
- no_terms ->
- {[],[]};
- Res -> Res
- end,
- %% TagList is the tags of Root2 elements from the first up to and
- %% including the first mandatory element.
- TagList = get_root2_taglist(Root2,[]),
- emit({com,nl}),
- asn1ct_name:new(bytes),
- emit([" {",{next,bytes},", ",{next,rb},
- "} = ?RT_BER:skip_ExtensionAdditions(",
- {curr,bytes},", ",{asis,TagList},"),",nl]),
- asn1ct_name:new(rb),
- asn1ct_name:new(bytes),
- gen_dec_sequence_call1(Erules,TopType,Root2,
- length(Root1)+length(EList),noext,
- DecObjInf,LA,ArgsAcc).
-
-%% returns a list of tags of the elements in the component (second
-%% root) list up to and including the first mandatory tag. See 24.6 in
-%% X.680 (7/2002)
-get_root2_taglist([],Acc) ->
- lists:reverse(Acc);
-get_root2_taglist([#'ComponentType'{prop=Prop,typespec=Type}|Rest],Acc) ->
- FirstTag = fun([])->[];
- ([H|_T])->H#tag{class=asn1ct_gen_ber:decode_class(H#tag.class)}
- end(Type#type.tag),
- case Prop of
- mandatory ->
- %% match_tags/ may be used
- %% this is the last tag of interest -> return
- lists:reverse([FirstTag|Acc]);
- _ ->
- get_root2_taglist(Rest,[FirstTag|Acc])
- end.
-
-
-%%----------------------------
-%%SEQUENCE mandatory
-%%----------------------------
-
-gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
- _ -> asn1ct_gen:get_inner(Type#type.def)
- end,
-
- Prop1 = case {Prop,Ext} of
- {_,{ext,Epos,_Root2pos}} when Pos < Epos ->
- Prop;
- {mandatory,{ext,Epos,_}} when Pos >= Epos ->
- 'OPTIONAL';
- _ ->
- Prop
- end,
- print_attribute_comment(InnerType,Pos,Prop1),
- emit(" "),
-
- case {InnerType,DecObjInf} of
- {{typefield,_},NotFalse} when NotFalse /= false ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
- {{objectfield,_,_},_} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
- _ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term},",",{next,bytes},",",{next,rb},"} = "})
- end,
- asn1ct_name:new(rb),
- PostponedDec =
- gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
- asn1ct_name:new(form),
- PostponedDec.
-
-
-%%-------------------------------------
-%% Decode SET
-%%-------------------------------------
-
-gen_dec_set(Erules,TopType,CompList,Pos,Ext) ->
- ExtCatch = case Ext of
- noext ->"";
- _ -> " catch"
- end,
- TagList = get_all_choice_tags(CompList),
- emit({indent(3),
- {curr,tagList}," = ",{asis,TagList},",",nl}),
- emit({indent(3),
- "case",ExtCatch," ?RT_BER:check_if_valid_tag(Bytes, ",
- {curr,tagList},", OptOrMand) of",nl}),
- asn1ct_name:new(tagList),
- asn1ct_name:new(rbCho),
- asn1ct_name:new(choTags),
- gen_dec_set_cases(Erules,TopType,CompList,TagList,Pos),
- asn1ct_name:new(tag),
- asn1ct_name:new(bytes).
-
-
-
-gen_dec_set_cases(_,_,[],_,_) ->
- ok;
-gen_dec_set_cases(Erules,TopType,[H|T],List,Pos) ->
- Name = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
-
- emit({indent(6),"'",Name,"' ->",nl}),
- case Type#type.def of
- {'CHOICE',_NewCompList} ->
- gen_dec_set_cases_choice(Erules,TopType,H,Pos);
- _ ->
- gen_dec_set_cases_type(Erules,TopType,H,Pos)
- end,
- gen_dec_set_cases(Erules,TopType,T,List,Pos+1).
-
-
-
-gen_dec_set_cases_choice(_Erules,TopType,H,Pos) ->
- Cname = H#'ComponentType'.name,
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- (H#'ComponentType'.typespec)#type.tag],
- asn1ct_name:new(rbCho),
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- emit({"'dec_",asn1ct_gen:list2name([Cname|TopType]),
- "'(Bytes,OptOrMand,",{asis,Tag},"),",nl}),
- emit([" {{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
- emit([";",nl,nl]).
-
-
-gen_dec_set_cases_type(Erules,TopType,H,Pos) ->
- Cname = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
- %% always use Prop = mandatory here Prop = H#'ComponentType'.prop,
-
- asn1ct_name:new(rbCho),
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- asn1ct_name:delete(bytes),
- %% we have already seen the tag so now we must find the value
- %% that why we always use 'mandatory' here
- gen_dec_line(Erules,TopType,Cname,[],Type,mandatory,decObjInf),
- asn1ct_name:new(bytes),
-
- emit([",",nl]),
- emit(["{{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
- emit([";",nl,nl]).
-
-
-%%---------------------------------
-%% Decode SET result
-%%---------------------------------
-
-gen_dec_set_result(Erules,TopType,CompList) ->
- gen_dec_set_result1(Erules,TopType, CompList, 1).
-
-gen_dec_set_result1(Erules,TopType,
- [#'ComponentType'{name=Cname,
- typespec=Type,
- prop=Prop}|Rest],Num) ->
- gen_dec_set_component(Erules,TopType,Cname,Type,Num,Prop),
- case Rest of
- [] ->
- true;
- _ ->
- gen_dec_set_result1(Erules,TopType,Rest,Num+1)
- end;
-
-gen_dec_set_result1(_Erules,_TopType,[],1) ->
- no_terms;
-gen_dec_set_result1(_Erules,_TopType,[],_Num) ->
- true.
-
-
-gen_dec_set_component(_Erules,_TopType,_Cname,Type,Pos,Prop) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- print_attribute_comment(InnerType,Pos,Prop),
- emit({" {",{next,term},com,{next,termList},"} =",nl}),
- emit({" case ",{curr,termList}," of",nl}),
- emit({" [{",Pos,com,{curr,termTmp},"}|",
- {curr,rest},"] -> "}),
- emit({"{",{curr,termTmp},com,
- {curr,rest},"};",nl}),
- case Prop of
- 'OPTIONAL' ->
- emit([indent(10),"_ -> {asn1_NOVALUE, ",{curr,termList},"}",nl]);
- {'DEFAULT', DefVal} ->
- emit([indent(10),
- "_ -> {",{asis,DefVal},", ",{curr,termList},"}",nl]);
- mandatory ->
- emit([indent(10),
- "_ -> exit({error,{asn1,{mandatory_attribute_no, ",
- Pos,", missing}}})",nl])
- end,
- emit([indent(6),"end,",nl]),
- asn1ct_name:new(rest),
- asn1ct_name:new(term),
- asn1ct_name:new(termList),
- asn1ct_name:new(termTmp).
-
-
-%%---------------------------------------------
-%% Encode CHOICE
-%%---------------------------------------------
-%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
-
-
-gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
- gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
-
-gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext) ->
- asn1ct_name:clear(),
- emit({" {EncBytes,EncLen} = case element(1,Val) of",nl}),
- gen_enc_choice2(Erules,TopType,CompList),
- emit([nl," end,",nl,nl]),
- NewTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- Tag],
-% gen_encode_tags(Erules,NewTag,"EncLen","EncBytes").
- emit(["?RT_BER:encode_tags(TagIn ++",{asis,NewTag},", EncBytes, EncLen).",nl]).
-
-
-
-gen_enc_choice2(Erules,TopType,[H1|T]) when is_record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- emit({" ",{asis,Cname}," ->",nl}),
- {Encobj,Assign} =
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
- case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
- {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
- asn1ct_name:new(tmpBytes),
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- Emit = ["{",{curr,tmpBytes},", _} = "],
- {{no_attr,"ObjFun"},Emit};
- _ ->
- case Type#type.tablecinf of
- [{objfun,_}] -> {{no_attr,"ObjFun"},[]};
- _-> {false,[]}
- end
- end,
- gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
- mandatory,Assign,Encobj),
- case {Type#type.def,Encobj} of
- {#'ObjectClassFieldType'{},{no_attr,"ObjFun"}} ->
- emit({",",nl,indent(9),"{",{curr,encBytes},", ",
- {curr,encLen},"}"});
- _ -> ok
- end,
- emit({";",nl}),
- case T of
- [] ->
- emit([indent(6), "Else -> ",nl,
- indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
- _ ->
- true
- end,
- gen_enc_choice2(Erules,TopType,T);
-
-gen_enc_choice2(_,_,[]) ->
- true.
-
-
-
-
-%%--------------------------------------------
-%% Decode CHOICE
-%%--------------------------------------------
-
-gen_dec_choice(Erules,TopType, ChTag, CompList, Ext) ->
- asn1ct_name:delete(bytes),
- Tags = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- ChTag],
-
- emit([" {{_,Len},",{next,bytes},
- ", RbExp} = ?RT_BER:check_tags(TagIn++",
- {asis,Tags},", ",
- {curr,bytes},", OptOrMand),",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
- gen_dec_choice_indef_funs(Erules),
- case Erules of
- ber_bin ->
- emit([indent(3),"case ",{curr,bytes}," of",nl]);
- ber ->
- emit([indent(3),
- "case (catch ?RT_BER:peek_tag(",{curr,bytes},")) of",nl])
- end,
- asn1ct_name:new(tagList),
- asn1ct_name:new(choTags),
- gen_dec_choice_cases(Erules,TopType,CompList),
- case Ext of
- noext ->
- emit([indent(6), {curr,else}," -> ",nl]),
- emit([indent(9),"case OptOrMand of",nl,
- indent(12),"mandatory ->","exit({error,{asn1,",
- "{invalid_choice_tag,",{curr,else},"}}});",nl,
- indent(12),"_ ->","exit({error,{asn1,{no_optional_tag,",
- {curr,else},"}}})",nl,
- indent(9),"end",nl]);
- _ ->
- emit([indent(6),"_ -> ",nl]),
- emit([indent(9),"{{asn1_ExtAlt,",{curr,bytes},"},",
- empty_lb(Erules),", RbExp}",nl])
- end,
- emit([indent(3),"end"]),
- asn1ct_name:new(tag),
- asn1ct_name:new(else).
-
-gen_dec_choice_indef_funs(Erules) ->
- emit({indent(3),"IndefEndBytes = fun(indefinite,",indefend_match(Erules,used_var),
- ")-> R; (_,B)-> B end,",nl}),
- emit({indent(3),"IndefEndRb = fun(indefinite,",indefend_match(Erules,unused_var),
- ")-> 2; (_,_)-> 0 end,",nl}).
-
-
-gen_dec_choice_cases(_,_, []) ->
- ok;
-gen_dec_choice_cases(Erules,TopType, [H|T]) ->
- asn1ct_name:push(rbCho),
- Name = H#'ComponentType'.name,
- emit([nl,"%% '",Name,"'",nl]),
- Fcases = fun([T1,T2|Tail],Fun) ->
- emit([indent(6),match_tag(Erules,T1)," ->",nl]),
- gen_dec_choice_cases_type(Erules,TopType, H),
- Fun([T2|Tail],Fun);
- ([T1],_) ->
- emit([indent(6),match_tag(Erules,T1)," ->",nl]),
- gen_dec_choice_cases_type(Erules,TopType, H)
- end,
- Fcases(H#'ComponentType'.tags,Fcases),
- asn1ct_name:pop(rbCho),
- gen_dec_choice_cases(Erules,TopType, T).
-
-
-
-gen_dec_choice_cases_type(Erules,TopType,H) ->
- Cname = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
- Prop = H#'ComponentType'.prop,
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
- emit([",",nl,indent(9),"{{",{asis,Cname},
- ", Dec}, IndefEndBytes(Len,Rest), RbExp + ",
- {curr,rbCho}," + IndefEndRb(Len,Rest)};",nl,nl]).
-
-encode_tag_val(Erules,{Class,TagNo}) when is_integer(TagNo) ->
- Rtmod = rtmod(Erules),
- Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
- 0,TagNo});
-encode_tag_val(Erules,{Class,TypeName}) ->
- Rtmod = rtmod(Erules),
- Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
- 0,asn1ct_gen_ber:decode_type(TypeName)}).
-
-
-match_tag(ber_bin,Arg) ->
- match_tag_with_bitsyntax(Arg);
-match_tag(Erules,Arg) ->
- io_lib:format("~p",[encode_tag_val(Erules,Arg)]).
-
-match_tag_with_bitsyntax({Class,TagNo}) when is_integer(TagNo) ->
- match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
- 0,TagNo});
-match_tag_with_bitsyntax({Class,TypeName}) ->
- match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
- 0,asn1ct_gen_ber:decode_type(TypeName)}).
-
-match_tag_with_bitsyntax1({Class, _Form, TagNo}) when (TagNo =< 30) ->
- io_lib:format("<<~p:2,_:1,~p:5,_/binary>>",[Class bsr 6,TagNo]);
-
-match_tag_with_bitsyntax1({Class, _Form, TagNo}) ->
- {Octets,Len} = mk_object_val(TagNo),
- OctForm = case Len of
- 1 -> "~p";
- 2 -> "~p,~p";
- 3 -> "~p,~p,~p";
- 4 -> "~p,~p,~p,~p"
- end,
- io_lib:format("<<~p:2,_:1,31:5," ++ OctForm ++ ",_/binary>>",
- [Class bsr 6] ++ Octets).
-
-%%%%%%%%%%%
-%% 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
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-get_all_choice_tags(ComponentTypeList) ->
- get_all_choice_tags(ComponentTypeList,[]).
-
-get_all_choice_tags([],TagList) ->
- TagList;
-get_all_choice_tags([H|T],TagList) ->
- Tags = H#'ComponentType'.tags,
- get_all_choice_tags(T, TagList ++ [{H#'ComponentType'.name, Tags}]).
-
-
-
-%%---------------------------------------
-%% Generate the encode/decode code
-%%---------------------------------------
-
-gen_enc_line(Erules,TopType,Cname,
- Type=#type{constraint=C,
- def=#'ObjectClassFieldType'{type={typefield,_}}},
- Element,Indent,OptOrMand=mandatory,EncObj)
- when is_list(Element) ->
- case asn1ct_gen:get_constraint(C,componentrelation) of
- {componentrelation,_,_} ->
- asn1ct_name:new(tmpBytes),
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,tmpBytes},",_} = "],EncObj);
- _ ->
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,encBytes},",",{curr,encLen},"} = "],
- EncObj)
- end;
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
- when is_list(Element) ->
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
-
-gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
- when is_list(Element) ->
- IndDeep = indent(Indent),
-
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- WhatKind = asn1ct_gen:type(InnerType),
- emit(IndDeep),
- emit(Assign),
- gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
- Element),
- case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
- {#type{def=#'ObjectClassFieldType'{type={typefield,_},
- fieldname=RefedFieldName}},
- {componentrelation,_,_}} ->
- {_LeadingAttrName,Fun} = EncObj,
- case RefedFieldName of
- {Name,RestFieldNames} when is_atom(Name),Name =/= notype ->
- case OptOrMand of
- mandatory -> ok;
- _ ->
- emit(["{",{curr,tmpBytes},", _} = "])
- end,
- emit({Fun,"(",{asis,Name},", ",Element,", [], ",
- {asis,RestFieldNames},"),",nl}),
- emit(IndDeep),
- case OptOrMand of
- mandatory ->
- emit({"{",{curr,encBytes},", ",{curr,encLen},"} = "}),
- emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},")"});
- _ ->
- emit({"{",{next,tmpBytes},", ",{curr,tmpLen},
- "} = "}),
- emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},"),",nl}),
- emit(IndDeep),
- emit({"{",{next,tmpBytes},", ",{curr,tmpLen},"}"})
- end;
- Err ->
- throw({asn1,{'internal error',Err}})
- end;
- _ ->
- case WhatKind of
- {primitive,bif} ->
- EncType =
- case Type#type.def of
- #'ObjectClassFieldType'{
- type={fixedtypevaluefield,
- _,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- asn1ct_gen_ber:gen_encode_prim(ber,EncType,{asis,Tag},
- Element);
- 'ASN1_OPEN_TYPE' ->
- asn1ct_gen_ber:gen_encode_prim(ber,Type#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
- _ ->
- {EncFunName, _, _} =
- mkfuncname(TopType,Cname,WhatKind,enc),
- case {WhatKind,Type#type.tablecinf,EncObj} of
- {{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},
- ", ",Fun,")"]);
- _ ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
- end
- end
- end,
- case OptOrMand of
- mandatory -> true;
- _ ->
- emit({nl,indent(7),"end"})
- end.
-
-
-
-gen_optormand_case(mandatory,_,_,_,_,_,_, _) ->
- ok;
-gen_optormand_case('OPTIONAL',Erules,_,_,_,_,_,Element) ->
- emit({" case ",Element," of",nl}),
- emit({indent(9),"asn1_NOVALUE -> {",
- empty_lb(Erules),",0};",nl}),
- emit({indent(9),"_ ->",nl,indent(12)});
-gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
- InnerType,WhatKind,Element) ->
- CurrMod = get(currmod),
- case catch lists:member(der,get(encoding_options)) of
- true ->
- emit(" case catch "),
- asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
- WhatKind,{asis,DefaultValue},
- Element),
- emit({" of",nl}),
- emit({indent(12),"true -> {[],0};",nl});
- _ ->
- emit({" case ",Element," of",nl}),
- emit({indent(9),"asn1_DEFAULT -> {",
- empty_lb(Erules),
- ",0};",nl}),
- case DefaultValue of
- #'Externalvaluereference'{module=CurrMod,
- value=V} ->
- emit({indent(9),"?",{asis,V}," -> {",
- empty_lb(Erules),",0};",nl});
- _ ->
- emit({indent(9),{asis,
- DefaultValue}," -> {",
- empty_lb(Erules),",0};",nl})
- end
- end,
- emit({indent(9),"_ ->",nl,indent(12)}).
-
-
-
-
-gen_dec_line_sof(Erules,TopType,Cname,Type,ObjFun) ->
-
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- WhatKind = asn1ct_gen:type(InnerType),
- case WhatKind of
- {primitive,bif} ->
- asn1ct_name:delete(len),
-
- asn1ct_name:new(len),
- emit(["fun(FBytes,_,_)->",nl]),
- EncType = case Type#type.def of
- #'ObjectClassFieldType'{
- type={fixedtypevaluefield,
- _,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- asn1ct_gen_ber:gen_dec_prim(ber,EncType,"FBytes",Tag,
- [],no_length,?PRIMITIVE,
- mandatory),
- emit([nl,"end, []"]);
- _ ->
- case ObjFun of
- [] ->
- {DecFunName, _, _} =
- mkfunname(Erules,TopType,Cname,WhatKind,dec,3),
- emit([DecFunName,", ",{asis,Tag}]);
- _ ->
- {DecFunName, _, _} =
- mkfunname(Erules,TopType,Cname,WhatKind,dec,4),
- emit([DecFunName,", ",{asis,Tag},", ObjFun"])
- end
- end.
-
-
-gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} ->
- OCFTType;
- _ ->
- asn1ct_gen:get_inner(Type#type.def)
- end,
- PostpDec =
- case OptOrMand of
- mandatory ->
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,mandatory,", mandatory, ",
- DecObjInf,OptOrMand);
- _ -> %optional or default
- case {CTags,Erules} of
- {[CTag],ber_bin} when CTag =/= [] -> % R9C-0.patch-34
- emit(["case ",{curr,bytes}," of",nl]),
- emit([match_tag(Erules,CTag)," ->",nl]),
- PostponedDec =
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,mandatory,
- ", opt_or_default, ",DecObjInf,
- OptOrMand),
- emit([";",nl]),
- emit(["_ ->",nl]),
- case OptOrMand of
- {'DEFAULT', Def} ->
- emit(["{",{asis,Def},",",
- BytesVar,", 0 }",nl]);
- 'OPTIONAL' ->
- emit(["{ asn1_NOVALUE, ",
- BytesVar,", 0 }",nl])
- end,
- emit("end"),
- PostponedDec;
- _ ->
- emit("case (catch "),
- PostponedDec =
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,OptOrMand,
- ", opt_or_default, ",DecObjInf,
- OptOrMand),
- emit([") of",nl]),
- case OptOrMand of
- {'DEFAULT', Def} ->
- emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
- " -> {",{asis,Def},",",
- BytesVar,", 0 };",nl]);
- 'OPTIONAL' ->
- emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
- " -> { asn1_NOVALUE, ",
- BytesVar,", 0 };",nl])
- end,
- asn1ct_name:new(casetmp),
- emit([{curr,casetmp},"-> ",{curr,casetmp},nl,"end"]),
- PostponedDec
- end
- end,
- case DecObjInf of
- {Cname,ObjSet} -> % this must be the component were an object is
- %% choosen from the object set according to the table
- %% constraint.
- ObjSetName = case ObjSet of
- {deep,OSName,_,_} ->
- OSName;
- _ -> ObjSet
- end,
- {[{ObjSetName,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- PostpDec};
- _ -> {[],PostpDec}
- end.
-
-
-gen_dec_call({typefield,_},Erules,_,_,Type,_,Tag,_,_,false,_) ->
- %% this in case of a choice with typefield components
- asn1ct_name:new(reason),
- {FirstPFName,RestPFName} =
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit([nl,indent(6),"begin",nl]),
- emit([indent(9),"{OpenDec,TmpRest,TmpRbCho} =",nl,indent(12),
- "?RT_BER:decode_open_type(",Erules,",",{curr,bytes},",",
- {asis,Tag},"),",nl]),
- emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
- ", OpenDec, [], ",{asis,RestPFName},
- ")) of", nl]),%% ??? What about Tag
- emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
-%% emit({indent(15),"throw({runtime_error,{'Type not ",
-%% "compatible with tableconstraint', OpenDec}});",nl}),
- emit([indent(15),"exit({'Type not ",
- "compatible with table constraint', ",{curr,reason},"});",nl]),
- emit([indent(12),"{TmpDec,_ ,_} ->",nl]),
- emit([indent(15),"{TmpDec, TmpRest, TmpRbCho}",nl]),
- emit([indent(9),"end",nl,indent(6),"end",nl]),
- [];
-gen_dec_call({typefield,_},_Erules,_,Cname,Type,_BytesVar,Tag,_,_,
- _DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
- RefedFieldName =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- [{Cname,RefedFieldName,
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
-% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call({objectfield,PrimFieldName,PFNList},_Erules,_,Cname,_,_,Tag,_,_,_,
- OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
- [{Cname,{PrimFieldName,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
-% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
- OptOrMand,DecObjInf,_) ->
- WhatKind = asn1ct_gen:type(InnerType),
- gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
- PrimOptOrMand,OptOrMand),
- case DecObjInf of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} =
- case OSet of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",OSet}
- end,
- emit({",",nl,"ObjFun = ",ObjSetMod,":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"});
- _ ->
- ok
- end,
- [].
-gen_dec_call1({primitive,bif},InnerType,Erules,_,_,Type,BytesVar,
- Tag,OptOrMand,_) ->
- case InnerType of
- {fixedtypevaluefield,_,Btype} ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand);
- _ ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Type,BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand)
- end;
-gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,_,_,Type,BytesVar,
- Tag,OptOrMand,_) ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Type#type{def='ASN1_OPEN_TYPE'},
- BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand);
-gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,_,Tag,_,OptOrMand) ->
- {DecFunName,_,_} =
- mkfuncname(TopType,Cname,WhatKind,dec),
- case {WhatKind,Type#type.tablecinf} of
- {{constructed,bif},[{objfun,_}|_R]} ->
- emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},", ObjFun)"});
- _ ->
- emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},")"})
- end.
-
-
-%%------------------------------------------------------
-%% General and special help functions (not exported)
-%%------------------------------------------------------
-
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
- emit([{var,H},Sep]),
- mkvlist([T1|T], Sep);
-mkvlist([H|T], Sep) ->
- emit([{var,H}]),
- mkvlist(T, Sep);
-mkvlist([], _) ->
- true.
-
-mkvlist(L) ->
- mkvlist(L,", ").
-
-mkvplus(L) ->
- mkvlist(L," + ").
-
-extensible(CompList) when is_list(CompList) ->
- noext;
-extensible({RootList,ExtList}) ->
- {ext,length(RootList)+1,length(ExtList)};
-extensible({_Rl1,_ExtL,_Rl2}) ->
- extensible.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% filter away ExtensionAdditionGroup start and end marks since these
-%% have no significance for the BER encoding
-%%
-filter_complist(CompList) when is_list(CompList) ->
- lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
- false;
- ('ExtensionAdditionGroupEnd') ->
- false;
- (_) ->
- true
- end, CompList);
-filter_complist({Root,Ext}) ->
- {Root,filter_complist(Ext)};
-filter_complist({Root1,Ext,Root2}) ->
- {Root1,filter_complist(Ext),Root2}.
-
-print_attribute_comment(InnerType,Pos,Prop) ->
- CommentLine = "%%-------------------------------------------------",
- emit([nl,CommentLine]),
- case InnerType of
- {typereference,_,Name} ->
- emit([nl,"%% attribute number ",Pos," with type ",Name]);
- {'Externaltypereference',_,XModule,Name} ->
- emit([nl,"%% attribute number ",Pos," External ",XModule,":",Name]);
- _ ->
- emit([nl,"%% attribute number ",Pos," with type ",InnerType])
- end,
- case Prop of
- mandatory ->
- continue;
- {'DEFAULT', Def} ->
- emit([" DEFAULT = ",{asis,Def}]);
- 'OPTIONAL' ->
- emit([" OPTIONAL"])
- end,
- emit([nl,CommentLine,nl]).
-
-
-mkfuncname(TopType,Cname,WhatKind,DecOrEnc) ->
- CurrMod = get(currmod),
- case WhatKind of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- F = lists:concat(["'",DecOrEnc,"_",EType,"'"]),
- {F, "?MODULE", F};
- #'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"]),Mod,
- lists:concat(["'",DecOrEnc,"_",EType,"'"])};
- {constructed,bif} ->
- F = lists:concat(["'",DecOrEnc,"_",asn1ct_gen:list2name([Cname|TopType]),"'"]),
- {F, "?MODULE", F}
- end.
-
-mkfunname(Erule,TopType,Cname,WhatKind,DecOrEnc,Arity) ->
- CurrMod = get(currmod),
- case WhatKind of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]),
- {F, "?MODULE", F};
- #'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["fun '",Mod,"':'",DecOrEnc,"_",EType,"'/",Arity]),Mod,
- lists:concat(["'",DecOrEnc,"_",EType,"'"])};
- {constructed,bif} ->
- F =
- lists:concat(["fun '",DecOrEnc,"_",
- asn1ct_gen:list2name([Cname|TopType]),"'/",
- Arity]),
- {F, "?MODULE", F};
- 'ASN1_OPEN_TYPE' ->
- case Arity of
- 3 ->
- F = lists:concat(["fun(A,_,C) -> ?RT_BER:decode_open_type(",Erule,",A,C) end"]),
- {F, "?MODULE", F};
- 4 ->
- F = lists:concat(["fun(A,_,C,_) -> ?RT_BER:decode_open_type(",Erule,",A,C) end"]),
- {F, "?MODULE", F}
- end
- end.
-
-empty_lb(ber) ->
- "[]";
-empty_lb(ber_bin) ->
- "<<>>".
-
-rtmod(ber) ->
- list_to_atom(?RT_BER_BIN);
-rtmod(ber_bin) ->
- list_to_atom(?RT_BER_BIN).
-
-indefend_match(ber,used_var) ->
- "[0,0|R]";
-indefend_match(ber,unused_var) ->
- "[0,0|_R]";
-indefend_match(ber_bin,used_var) ->
- "<<0,0,R/binary>>";
-indefend_match(ber_bin,unused_var) ->
- "<<0,0,_R/binary>>".
-
-notice_value_match() ->
- Module = get(currmod),
- put(value_match,{true,Module}).
-
-value_match(Index,Value) when is_atom(Value) ->
- value_match(Index,atom_to_list(Value));
-value_match([],Value) ->
- Value;
-value_match([{VI,_Cname}|VIs],Value) ->
- value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
-value_match1(Value,[],Acc,Depth) ->
- Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
-value_match1(Value,[{VI,_Cname}|VIs],Acc,Depth) ->
- value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index 2c4b44996d..761faa53c5 100644
--- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -32,7 +32,6 @@
-include("asn1_records.hrl").
-import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/0]).
--import(asn1ct_constructed_ber,[match_tag/2]).
-define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2).
@@ -67,9 +66,9 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
ValName =
case Typename of
['EXTERNAL'] ->
- emit([indent(4),
- "NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
- nl]),
+ emit([indent(4),"NewVal = ",
+ {call,ext,transform_to_EXTERNAL1990,["Val"]},
+ com,nl]),
"NewVal";
_ ->
"Val"
@@ -115,30 +114,16 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
usedclassfield=UniqueFieldName,
uniqueclassfield=UniqueFieldName,
valueindex=ValueIndex} -> %% N is index of attribute that determines constraint
- OSDef =
- case ObjectSetRef of
- {Module,OSName} ->
- asn1_db:dbget(Module,OSName);
- OSName ->
- asn1_db:dbget(get(currmod),OSName)
- end,
-% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
-% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
+ {ObjSetMod,ObjSetName} = ObjectSetRef,
+ OSDef = asn1_db:dbget(ObjSetMod, ObjSetName),
case (OSDef#typedef.typespec)#'ObjectSet'.gen of
true ->
ObjectEncode =
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
AttrN])),
- {ObjSetMod,ObjSetName} =
- case ObjectSetRef of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",ObjectSetRef}
- end,
- emit([ObjectEncode," = ",nl]),
- emit([" ",ObjSetMod,":'getenc_",ObjSetName,"'(",{asis,UniqueFieldName},
- ", ",nl]),
+ emit([ObjectEncode," = ",nl,
+ " ",{asis,ObjSetMod},":'getenc_",ObjSetName,
+ "'(",{asis,UniqueFieldName},", ",nl]),
ValueMatch = value_match(ValueIndex,
lists:concat(["Cindex",N])),
emit([indent(35),ValueMatch,"),",nl]),
@@ -163,7 +148,8 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
emit([nl," BytesSoFar = "]),
case SeqOrSet of
'SET' when (D#type.def)#'SET'.sorted == dynamic ->
- emit("asn1rt_check:dynamicsort_SET_components(["),
+ asn1ct_func:need({ber,dynamicsort_SET_components,1}),
+ emit("dynamicsort_SET_components(["),
mkvlist(asn1ct_name:all(encBytes)),
emit(["]),",nl]);
_ ->
@@ -178,12 +164,11 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
mkvplus(AllLengths)
end,
emit([",",nl]),
- emit(["?RT_BER:encode_tags(TagIn, BytesSoFar, LenSoFar)."
- ,nl]).
+ call(encode_tags, ["TagIn","BytesSoFar","LenSoFar"]),
+ emit([".",nl]).
gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
- asn1ct_name:clear(),
asn1ct_name:new(tag),
#'SEQUENCE'{tablecinf=TableConsInfo,components=CList0} = D#type.def,
@@ -208,7 +193,8 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
_ ->
emit([{curr,tlv}," = "])
end,
- emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ call(match_tags, [{prev,tlv},"TagIn"]),
+ emit([com,nl]),
asn1ct_name:new(tlv),
asn1ct_name:new(v),
@@ -257,15 +243,9 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
{[{ObjSetRef,LeadingAttr,Term}],PostponedDecArgs} ->
DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} =
- case ObjSetRef of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",ObjSetRef}
- end,
+ {ObjSetMod,ObjSetName} = ObjSetRef,
emit([DecObj," =",nl,
- " ",ObjSetMod,":'getdec_",ObjSetName,"'(",
+ " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
{asis,UniqueFName},", ",ValueMatch,"),",nl]),
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
end,
@@ -288,8 +268,9 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
"', "]),
mkvlist(asn1ct_name:all(term)),
emit(["},",nl]),
- emit([" asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat).",nl]);
+ emit([" ",
+ {call,ext,transform_to_EXTERNAL1994,
+ ["OldFormat"]},".",nl]);
_ ->
emit([" {'",RecordName,"', "]),
mkvlist(asn1ct_name:all(term)),
@@ -347,7 +328,6 @@ gen_encode_set(Erules,Typename,D) when is_record(D,type) ->
gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
- asn1ct_name:clear(),
%% asn1ct_name:new(term),
asn1ct_name:new(tag),
#'SET'{tablecinf=TableConsInfo,components=TCompList0} = D#type.def,
@@ -372,7 +352,8 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
_ ->
emit([{curr,tlv}," = "])
end,
- emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ call(match_tags, [{prev,tlv},"TagIn"]),
+ emit([com,nl]),
asn1ct_name:new(v),
@@ -441,15 +422,9 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
{[{ObjSetRef,LeadingAttr,Term}],PostponedDecArgs} ->
DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} =
- case ObjSetRef of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",ObjSetRef}
- end,
+ {ObjSetMod,ObjSetName} = ObjSetRef,
emit([DecObj," =",nl,
- " ",ObjSetMod,":'getdec_",ObjSetName,"'(",
+ " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
{asis,UniqueFName},", ",ValueMatch,"),",nl]),
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
end,
@@ -493,14 +468,14 @@ gen_encode_sof(Erules,Typename,_InnerTypename,D) when is_record(D,type) ->
emit([" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
"_components'(Val",Objfun,",[],0),",nl]),
- emit([" ?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl,nl]),
+ emit([" ",{call,ber,encode_tags,["TagIn","EncBytes","EncLen"]},
+ ".",nl,nl]),
gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when is_record(D,type) ->
asn1ct_name:start(),
- asn1ct_name:clear(),
{SeqOrSetOf, _TypeTag, Cont} =
case D#type.def of
{'SET OF',_Cont} -> {'SET OF','SET',_Cont};
@@ -513,8 +488,8 @@ gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when is_record(D,type) ->
emit([" %%-------------------------------------------------",nl]),
asn1ct_name:new(tlv),
- emit([{curr,tlv},
- " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ emit([{curr,tlv}," = ",
+ {call,ber,match_tags,[{prev,tlv},"TagIn"]},com,nl]),
asn1ct_name:new(v),
emit(["["]),
@@ -524,14 +499,7 @@ gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when is_record(D,type) ->
Atom when is_atom(Atom) -> Atom;
_ -> TypeNameSuffix
end,
-%% fix me
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- []
- end,
+ ObjFun = false,
gen_dec_line(Erules,TypeName,ContName,[],Cont,mandatory,ObjFun),
%% gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
emit([" || ",{curr,v}," <- ",{curr,tlv},"].",nl,nl,nl]).
@@ -552,8 +520,9 @@ gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
case catch lists:member(der,get(encoding_options)) of
true when SeqOrSetOf=='SET OF'->
+ asn1ct_func:need({ber,dynamicsort_SETOF,1}),
emit([indent(3),
- "{asn1rt_check:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
+ "{dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
_ ->
emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
end,
@@ -673,8 +642,9 @@ gen_dec_sequence_call2(Erules,TopType,{Root1,EList,Root2},_Ext,DecObjInf) ->
%% including the first mandatory element.
TagList = get_root2_taglist(Root2,[]),
emit({com,nl}),
- emit([{curr,tlv}," = ?RT_BER:skip_ExtensionAdditions(",
- {prev,tlv},", ",{asis,TagList},"),",nl]),
+ emit([{curr,tlv}," = ",
+ {call,ber,skip_ExtensionAdditions,
+ [{prev,tlv},{asis,TagList}]},com,nl]),
asn1ct_name:new(tlv),
gen_dec_sequence_call1(Erules,TopType,Root2,
length(Root1)+length(EList),noext,
@@ -806,8 +776,8 @@ gen_enc_choice1(Erules,TopType,_Tag,CompList,_Ext) ->
emit([" {EncBytes,EncLen} = case element(1,Val) of",nl]),
gen_enc_choice2(Erules,TopType,CompList),
emit([nl," end,",nl,nl]),
-
- emit(["?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl]).
+ call(encode_tags, ["TagIn","EncBytes","EncLen"]),
+ emit([".",nl]).
gen_enc_choice2(Erules,TopType,[H1|T]) when is_record(H1,'ComponentType') ->
@@ -860,8 +830,8 @@ gen_enc_choice2(_Erules,_TopType,[]) ->
gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
asn1ct_name:clear(),
asn1ct_name:new(tlv),
- emit([{curr,tlv},
- " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ emit([{curr,tlv}," = ",
+ {call,ber,match_tags,[{prev,tlv},"TagIn"]},com,nl]),
asn1ct_name:new(tlv),
asn1ct_name:new(v),
emit(["case (case ",{prev,tlv},
@@ -877,8 +847,8 @@ gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
{curr,else},"}}})",nl]);
_ ->
- emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},
- asn1ct_gen:nif_parameter(),")}",nl])
+ emit([indent(9),"{asn1_ExtAlt,",
+ {call,ber,ber_encode,[{curr,else}]},"}",nl])
end,
emit([indent(3),"end",nl]),
asn1ct_name:new(tag),
@@ -913,7 +883,7 @@ gen_dec_choice_cases(Erules,TopType, [H|T]) ->
[DecTag],Type}),
asn1ct:update_gen_state(namelist,Names),
emit([indent(4),{curr,res}," = ",
- match_tag(ber_bin,{FirstT#tag.class,FirstT#tag.number}),
+ match_tag(FirstT#tag.class, FirstT#tag.number),
" -> ",nl]),
emit([indent(8),"{",{asis,Cname},", {'",
asn1ct_gen:list2name([Cname|TopType]),"',",
@@ -928,7 +898,25 @@ gen_dec_choice_cases(Erules,TopType, [H|T]) ->
end,
gen_dec_choice_cases(Erules,TopType, T).
+match_tag(Class, TagNo) when is_integer(TagNo) ->
+ match_tag1(asn1ct_gen_ber_bin_v2:decode_class(Class), TagNo).
+match_tag1(Class, TagNo) when TagNo =< 30 ->
+ io_lib:format("<<~p:2,_:1,~p:5,_/binary>>", [Class bsr 6,TagNo]);
+match_tag1(Class, TagNo) ->
+ Octets = mk_object_val(TagNo),
+ io_lib:format("<<~p:2,_:1,31:5,~s,_/binary>>", [Class bsr 6,Octets]).
+
+mk_object_val(Val) when Val < 16#80 ->
+ integer_to_list(Val);
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [integer_to_list(Val band 16#7F)]).
+
+mk_object_val(0, Acc) ->
+ Acc;
+mk_object_val(Val, Acc) ->
+ I = integer_to_list((Val band 16#7F) bor 16#80),
+ mk_object_val(Val bsr 7, [I,","|Acc]).
%%---------------------------------------
%% Generate the encode/decode code
@@ -985,9 +973,7 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
{componentrelation,_,_}} ->
{_LeadingAttrName,Fun} = EncObj,
case RefedFieldName of
-%% {notype,T} ->
-%% throw({error,{notype,type_from_object,T}});
- {Name,RestFieldNames} when is_atom(Name), Name =/= notype ->
+ {Name,RestFieldNames} when is_atom(Name) ->
case OptOrMand of
mandatory -> ok;
_ ->
@@ -1001,43 +987,25 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
case OptOrMand of
mandatory ->
emit(["{",{curr,encBytes},",",{curr,encLen},
- "} = "]),
- emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},")"]);
+ "} = ",
+ {call,ber,encode_open_type,
+ [{curr,tmpBytes},{asis,Tag}]},nl]);
_ ->
-% emit(["{",{next,tmpBytes},", _} = "]),
emit(["{",{next,tmpBytes},",",{curr,tmpLen},
- "} = "]),
- emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},"),",nl]),
+ "} = ",
+ {call,ber,encode_open_type,
+ [{curr,tmpBytes},{asis,Tag}]},com,nl]),
emit(IndDeep),
emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
end;
Err ->
throw({asn1,{'internal error',Err}})
end;
-%% {{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
-%% PFNList}},_},
-%% {componentrelation,_,_}} ->
-%% %% this is when the dotted list in the FieldName has more
-%% %% than one element
-%% {_LeadingAttrName,Fun} = EncObj,
-%% emit(["?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
-%% ", ",Element,", ",{asis,PFNList},"))"]);
_ ->
case WhatKind of
{primitive,bif} ->
- EncType =
- case Type#type.def of
- #'ObjectClassFieldType'{type={fixedtypevaluefield,_,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- ?ASN1CT_GEN_BER:gen_encode_prim(ber,EncType,{asis,Tag},
- Element);
-%% {notype,_} ->
-%% emit(["'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"]);
+ ?ASN1CT_GEN_BER:gen_encode_prim(ber, Type, {asis,Tag},
+ Element);
'ASN1_OPEN_TYPE' ->
case Type#type.def of
#'ObjectClassFieldType'{} -> %Open Type
@@ -1221,15 +1189,11 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
asn1ct_name:new(tmptlv),
{FirstPFName,RestPFName} =
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
(Type#type.def)#'ObjectClassFieldType'.fieldname,
emit([nl,indent(6),"begin",nl]),
-% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
- emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
- BytesVar,",",{asis,Tag},asn1ct_gen:nif_parameter(),"),",nl]),
-% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
-% {curr,opendec},"),",nl]),
+ emit([indent(9),{curr,tmptlv}," = ",
+ {call,ber,decode_open_type,
+ [BytesVar,{asis,Tag}]},com,nl]),
emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
", ",{curr,tmptlv},", ",{asis,RestPFName},
@@ -1242,8 +1206,7 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
emit([indent(9),"end",nl,indent(6),"end",nl]),
[];
gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
- asn1ct_gen:nif_parameter(),")"]),
+ call(decode_open_type, [BytesVar,{asis,Tag}]),
RefedFieldName =
% asn1ct_gen:get_constraint(Type#type.constraint,
% tableconstraint_info),
@@ -1251,8 +1214,7 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC
[{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
- asn1ct_gen:nif_parameter(),")"]),
+ call(decode_open_type, [BytesVar,{asis,Tag}]),
[{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
@@ -1264,15 +1226,9 @@ gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
{Cname,{_,OSet,UniqueFName,ValIndex}} ->
Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} =
- case OSet of
- {M,O} ->
- {{asis,M},O};
- _ ->
- {"?MODULE",OSet}
- end,
- emit([",",nl,"ObjFun = ",ObjSetMod,":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"]);
+ {ObjSetMod,ObjSetName} = OSet,
+ emit([",",nl,"ObjFun = ",{asis,ObjSetMod},":'getdec_",ObjSetName,
+ "'(",{asis,UniqueFName},", ",ValueMatch,")"]);
_ ->
ok
end,
@@ -1284,12 +1240,8 @@ gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
Tag,Type}),
asn1ct:update_gen_state(namelist,Rest),
-% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
BytesVar,"}"]);
- {_,{fixedtypevaluefield,_,Btype}} ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand);
_ ->
?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
?PRIMITIVE,OptOrMand)
@@ -1303,7 +1255,6 @@ gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
asn1ct:update_gen_state(namelist,Rest),
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
BytesVar,"}"]);
-% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
{_,#'ObjectClassFieldType'{type=OpenType}} ->
?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
BytesVar,Tag,[],
@@ -1376,7 +1327,8 @@ gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar,
parts,
[],Type}),
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',"]),
- EmitDecFunCall("?RT_BER:match_tags"),
+ asn1ct_func:need({ber,match_tags,2}),
+ EmitDecFunCall("match_tags"),
emit("}");
_ ->
{DecFunName,_,_}=
@@ -1457,9 +1409,7 @@ print_attribute_comment(InnerType,Pos,Cname,Prop) ->
CommentLine = "%%-------------------------------------------------",
emit([nl,CommentLine]),
case InnerType of
- {typereference,_,Name} ->
- emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",Name]);
- {'Externaltypereference',_,XModule,Name} ->
+ #'Externaltypereference'{module=XModule,type=Name} ->
emit([nl,"%% attribute ",Cname,"(",Pos,") External ",XModule,":",Name]);
_ ->
emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",InnerType])
@@ -1493,10 +1443,6 @@ mkfuncname(TopType,Cname,WhatKind,Prefix,Suffix) ->
end.
empty_lb(ber) ->
- "[]";
-empty_lb(ber_bin) ->
- "<<>>";
-empty_lb(ber_bin_v2) ->
"<<>>".
value_match(Index,Value) when is_atom(Value) ->
@@ -1509,3 +1455,6 @@ value_match1(Value,[],Acc,Depth) ->
Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
+
+call(F, Args) ->
+ asn1ct_func:call(ber, F, Args).
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index 5de29a9c77..d279e9697f 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -32,6 +32,7 @@
%-compile(export_all).
-import(asn1ct_gen, [emit/1,demit/1,get_record_name_prefix/0]).
+-import(asn1ct_func, [call/3]).
%% ENCODE GENERATOR FOR SEQUENCE TYPE ** **********
@@ -66,9 +67,9 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
end,
case Typename of
['EXTERNAL'] ->
- emit({{next,val},
- " = asn1rt_check:transform_to_EXTERNAL1990(",
- {curr,val},"),",nl}),
+ emit([{next,val}," = ",
+ {call,ext,transform_to_EXTERNAL1990,
+ [{curr,val}]},com,nl]),
asn1ct_name:new(val);
_ ->
ok
@@ -76,13 +77,9 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
case {Optionals = optionals(to_textual_order(CompList)),CompList,
is_optimized(Erule)} of
{[],EmptyCL,_} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
- emit(["%%Variable setting just to eliminate ",
- "compiler warning for unused vars!",nl,
- "_Val = ",{curr,val},",",nl]);
+ ok;
{[],_,_} ->
- emit([{next,val}," = ?RT_PER:list_to_record("]),
- emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
- emit([", ",{curr,val},"),",nl]);
+ emit([{next,val}," = ",{curr,val},",",nl]);
{_,_,true} ->
gen_fixoptionals(Optionals),
FixOpts = param_map(fun(Var) ->
@@ -90,7 +87,8 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
end,asn1ct_name:all(fixopt)),
emit({"{",{next,val},",Opt} = {",{curr,val},",[",FixOpts,"]},",nl});
{_,_,false} ->
- Fixoptcall = ",Opt} = ?RT_PER:fixoptionals(",
+ asn1ct_func:need({Erule,fixoptionals,3}),
+ Fixoptcall = ",Opt} = fixoptionals(",
emit({"{",{next,val},Fixoptcall,
{asis,Optionals},",",length(Optionals),
",",{curr,val},"),",nl})
@@ -125,8 +123,9 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
lists:foreach(ExtGroupFun,ExtGroupPosLenList)
end,
asn1ct_name:new(tmpval),
- emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},",",
- {curr,val},"),",nl]);
+ emit(["Extensions = ",
+ {call,Erule,fixextensions,[{asis,Ext},{curr,val}]},
+ com,nl]);
_ -> true
end,
EncObj =
@@ -144,40 +143,21 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
uniqueclassfield=UniqueFieldName,
valueindex=ValueIndex
} -> %% N is index of attribute that determines constraint
- {{ObjSetMod,ObjSetName},OSDef} =
- case ObjectSet of
- {Module,OSName} ->
- {{{asis,Module},OSName},asn1_db:dbget(Module,OSName)};
- OSName ->
- {{"?MODULE",OSName},asn1_db:dbget(get(currmod),OSName)}
- end,
- case (OSDef#typedef.typespec)#'ObjectSet'.gen of
+ {Module,ObjSetName} = ObjectSet,
+ #typedef{typespec=#'ObjectSet'{gen=Gen}} =
+ asn1_db:dbget(Module, ObjSetName),
+ case Gen of
true ->
ObjectEncode =
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
- emit([ObjectEncode," = ",nl]),
- emit([" ",ObjSetMod,":'getenc_",ObjSetName,"'(",
- {asis,UniqueFieldName},", ",nl]),
- El = make_element(N+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),AttrN),
-
- Length = fun(X,_LFun) when is_atom(X) ->
- length(atom_to_list(X));
- (X,_LFun) when is_list(X) ->
- length(X);
- ({X1,X2},LFun) ->
- LFun(X1,LFun) + LFun(X2,LFun)
- end,
- Indent = 12 + Length(ObjectSet,Length),
- case ValueIndex of
- [] ->
- emit([indent(Indent),El,"),",nl]);
- _ ->
- emit([indent(Indent),"value_match(",
- {asis,ValueIndex},",",El,")),",nl]),
- notice_value_match()
- end,
+ El = make_element(N+1, asn1ct_gen:mk_var(asn1ct_name:curr(val))),
+ ValueMatch = value_match(ValueIndex, El),
+ emit([ObjectEncode," =",nl,
+ " ",{asis,Module},":'getenc_",ObjSetName,"'(",
+ {asis,UniqueFieldName},", ",nl,
+ " ",ValueMatch,"),",nl]),
{AttrN,ObjectEncode};
- _ ->
+ false ->
false
end;
_ ->
@@ -195,10 +175,10 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
MaybeComma1 =
case Ext of
{ext,_Pos,NumExt2} when NumExt2 > 0 ->
- emit({"?RT_PER:setext(Extensions =/= [])"}),
+ call(Erule, setext, ["Extensions =/= []"]),
", ";
{ext,_Pos,_} ->
- emit({"?RT_PER:setext(false)"}),
+ call(Erule, setext, ["false"]),
", ";
_ ->
""
@@ -224,9 +204,73 @@ gen_decode_set(Erules,Typename,D) ->
gen_decode_sequence(Erules,Typename,D) ->
gen_decode_constructed(Erules,Typename,D).
-gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
+gen_decode_constructed(Erule, Typename, #type{}=D) ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, #type{}=D),
+ Imm = opt_imm(Imm0),
asn1ct_name:start(),
- asn1ct_name:clear(),
+ emit_gen_dec_imm(Imm),
+ emit([".",nl,nl]).
+
+opt_imm(Imm0) ->
+ {Imm,_} = opt_imm_1(Imm0, unknown, []),
+ Imm.
+
+opt_imm_1([{imm,Imm0,F}|T], Al0, Acc) ->
+ {Imm,Al} = asn1ct_imm:optimize_alignment(Imm0, Al0),
+ opt_imm_1(T, Al, [{imm,Imm,F}|Acc]);
+opt_imm_1([ignore|T], Al, Acc) ->
+ opt_imm_1(T, Al, Acc);
+opt_imm_1([{ignore,_}=H|T], Al, Acc) ->
+ opt_imm_1(T, Al, [H|Acc]);
+opt_imm_1([{safe,ignore}|T], Al, Acc) ->
+ opt_imm_1(T, Al, Acc);
+opt_imm_1([{safe,_}=H|T], Al, Acc) ->
+ opt_imm_1(T, Al, [H|Acc]);
+opt_imm_1([{group,G0}|T], Al0, Acc) ->
+ {G,Al} = opt_imm_1(G0, Al0, []),
+ opt_imm_1(T, Al, [{group,G}|Acc]);
+opt_imm_1([Emit|T], _, Acc) when is_function(Emit, 1) ->
+ opt_imm_1(T, unknown, [Emit|Acc]);
+opt_imm_1([], Al, Acc) ->
+ {lists:reverse(Acc),Al}.
+
+emit_gen_dec_imm(L) ->
+ emit_gen_dec_imm(L, "", []).
+
+emit_gen_dec_imm([{ignore,Fun}|T], Sep, St0) ->
+ St = Fun(St0),
+ emit_gen_dec_imm(T, Sep, St);
+emit_gen_dec_imm([{group,L}|T], Sep, St0) ->
+ emit(Sep),
+ St = emit_gen_dec_imm_group(L, St0),
+ emit_gen_dec_imm(T, [com,nl], St);
+emit_gen_dec_imm([{imm,Imm,Emit}|T], Sep, St0) ->
+ emit(Sep),
+ St = Emit(Imm, St0),
+ emit_gen_dec_imm(T, [com,nl], St);
+emit_gen_dec_imm([{safe,Item}|T], Sep, St) ->
+ emit_gen_dec_imm([Item|T], Sep, St);
+emit_gen_dec_imm([Emit|T], Sep, St0) ->
+ emit(Sep),
+ St = Emit(St0),
+ emit_gen_dec_imm(T, [com,nl], St);
+emit_gen_dec_imm([], _, _) -> ok.
+
+emit_gen_dec_imm_group([H|T], St0) ->
+ St = emit_gen_dec_group_item(H, St0),
+ emit_gen_dec_imm_group(T, St);
+emit_gen_dec_imm_group([], St) -> St.
+
+emit_gen_dec_group_item({ignore,Fun}, St) ->
+ Fun(St);
+emit_gen_dec_group_item({imm,Imm,Fun}, St) ->
+ Fun(Imm, St);
+emit_gen_dec_group_item({safe,Item}, St) ->
+ emit_gen_dec_group_item(Item, St);
+emit_gen_dec_group_item(Emit, St) ->
+ Emit(St).
+
+gen_dec_constructed_imm(Erule, Typename, #type{}=D) ->
{CompList,TableConsInfo} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL} ->
@@ -236,27 +280,19 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{CL,TCI} % the textual order is already taken care of
end,
Ext = extensible_dec(CompList),
- MaybeComma1 = case Ext of
- {ext,_Pos,_NumExt} ->
- gen_dec_extension_value("Bytes"),
- {",",nl};
- _ ->
- ""
- end,
+ EmitExt = case Ext of
+ {ext,_Pos,_NumExt} ->
+ gen_dec_extension_value();
+ _ -> ignore
+ end,
Optionals = optionals(CompList),
- MaybeComma2 = case Optionals of
- [] -> MaybeComma1;
- _ ->
- Bcurr = asn1ct_name:curr(bytes),
- Bnext = asn1ct_name:next(bytes),
- emit(MaybeComma1),
- GetoptCall = "} = ?RT_PER:getoptionals2(",
- emit({"{Opt,",{var,Bnext},GetoptCall,
- {var,Bcurr},",",{asis,length(Optionals)},")"}),
- asn1ct_name:new(bytes),
- ", "
- end,
- {DecObjInf,UniqueFName,ValueIndex} =
+ EmitOpt = case Optionals of
+ [] ->
+ ignore;
+ [_|_] ->
+ gen_dec_optionals(Optionals)
+ end,
+ ObjSetInfo =
case TableConsInfo of
%% {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
#simpletableattributes{objectsetname=ObjectSet,
@@ -288,13 +324,19 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{false,false,false}
end
end,
-%% NewCompList = wrap_compList(CompList),
- {AccTerm,AccBytes} =
- gen_dec_components_call(Erules,Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
- case asn1ct_name:all(term) of
- [] -> emit(MaybeComma2); % no components at all
- _ -> emit({com,nl})
- end,
+ {DecObjInf,_,_} = ObjSetInfo,
+ EmitComp = gen_dec_components_call(Erule, Typename, CompList,
+ DecObjInf, Ext, length(Optionals)),
+ EmitRest = fun({AccTerm,AccBytes}) ->
+ gen_dec_constructed_imm_2(Typename, CompList,
+ ObjSetInfo,
+ AccTerm, AccBytes)
+ end,
+ [EmitExt,EmitOpt|EmitComp++[{safe,EmitRest}]].
+
+gen_dec_constructed_imm_2(Typename, CompList,
+ ObjSetInfo, AccTerm, AccBytes) ->
+ {_,UniqueFName,ValueIndex} = ObjSetInfo,
case {AccTerm,AccBytes} of
{[],[]} ->
ok;
@@ -303,30 +345,26 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} =
- case ObjSet of
- {M,O} -> {{asis,M},O};
- _ -> {"?MODULE",ObjSet}
- end,
- emit({DecObj," =",nl," ",ObjSetMod,":'getdec_",ObjSetName,"'(",
-% {asis,UniqueFName},", ",Term,"),",nl}),
- {asis,UniqueFName},", ",ValueMatch,"),",nl}),
+ {ObjSetMod,ObjSetName} = ObjSet,
+ emit([DecObj," =",nl,
+ " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
+ {asis,UniqueFName},", ",ValueMatch,"),",nl]),
gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
end,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
%% return value as record
- RecordName = lists:concat([get_record_name_prefix(),
- asn1ct_gen:list2rname(Typename)]),
+ RecordName = record_name(Typename),
case Typename of
['EXTERNAL'] ->
emit({" OldFormat={'",RecordName,
"'"}),
mkvlist(asn1ct_name:all(term)),
emit({"},",nl}),
- emit({" ASN11994Format =",nl,
- " asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat),",nl}),
+ emit([" ASN11994Format =",nl,
+ " ",
+ {call,ext,transform_to_EXTERNAL1994,
+ ["OldFormat"]},com,nl]),
emit(" {ASN11994Format,");
_ ->
emit(["{{'",RecordName,"'"]),
@@ -336,8 +374,30 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
mkvlist(textual_order(to_encoding_order(CompList),asn1ct_name:all(term))),
emit("},")
end,
- emit({{curr,bytes},"}"}),
- emit({".",nl,nl}).
+ emit({{curr,bytes},"}"}).
+
+%% record_name([TypeName]) -> RecordNameString
+%% Construct a record name for the constructed type, ignoring any
+%% fake sequences that are used to represent an extension addition
+%% group. Such fake sequences never appear as a top type, and their
+%% name always start with "ExtAddGroup".
+
+record_name(Typename0) ->
+ [TopType|Typename1] = lists:reverse(Typename0),
+ Typename = filter_ext_add_groups(Typename1, [TopType]),
+ lists:concat([get_record_name_prefix(),
+ asn1ct_gen:list2rname(Typename)]).
+
+filter_ext_add_groups([H|T], Acc) when is_atom(H) ->
+ case atom_to_list(H) of
+ "ExtAddGroup"++_ ->
+ filter_ext_add_groups(T, Acc);
+ _ ->
+ filter_ext_add_groups(T, [H|Acc])
+ end;
+filter_ext_add_groups([H|T], Acc) ->
+ filter_ext_add_groups(T, [H|Acc]);
+filter_ext_add_groups([], Acc) -> Acc.
textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) ->
TermList;
@@ -427,7 +487,6 @@ gen_encode_choice(Erule,Typename,D) when is_record(D,type) ->
gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
- asn1ct_name:clear(),
asn1ct_name:new(bytes),
{'CHOICE',CompList} = D#type.def,
Ext = extensible_enc(CompList),
@@ -442,12 +501,8 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
asn1ct_name:start(),
{_SeqOrSetOf,ComponentType} = D#type.def,
emit({"[",nl}),
- SizeConstraint =
- case asn1ct_gen:get_constraint(D#type.constraint,
- 'SizeConstraint') of
- no -> undefined;
- Range -> Range
- end,
+ SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
+ D#type.constraint),
ObjFun =
case D#type.tablecinf of
[{objfun,_}|_R] ->
@@ -455,21 +510,15 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_->
""
end,
- gen_encode_length(SizeConstraint, is_optimized(Erule)),
+ gen_encode_length(Erule, SizeConstraint),
emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
"_components'(Val",ObjFun,", [])"}),
emit({nl,"].",nl}),
- NewComponentType =
- case ComponentType#type.def of
- {'ENUMERATED',_,Component}->
- ComponentType#type{def={'ENUMERATED',Component}};
- _ -> ComponentType
- end,
- gen_encode_sof_components(Erule,Typename,SeqOrSetOf,NewComponentType).
+ gen_encode_sof_components(Erule, Typename, SeqOrSetOf, ComponentType).
%% Logic copied from asn1_per_bin_rt2ct:encode_constrained_number
-gen_encode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
+gen_encode_length(per, {Lb,Ub}) when Ub =< 65535, Lb >= 0 ->
Range = Ub - Lb + 1,
V2 = ["(length(Val) - ",Lb,")"],
Encode = if
@@ -496,22 +545,26 @@ gen_encode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
Range =< 65536 ->
{"[20,2,<<",V2,":16>>]"};
true ->
- {"?RT_PER:encode_length(",{asis,{Lb,Ub}},",length(Val))"}
+ {call,per,encode_length,
+ [{asis,{Lb,Ub}},"length(Val)"]}
end,
emit({nl,Encode,",",nl});
-gen_encode_length(SizeConstraint,_) ->
- emit({nl,indent(3),"?RT_PER:encode_length(",
- {asis,SizeConstraint},",length(Val)),",nl}).
+gen_encode_length(Erules, SizeConstraint) ->
+ emit([nl,indent(3),
+ case SizeConstraint of
+ no ->
+ {call,Erules,encode_length,["length(Val)"]};
+ _ ->
+ {call,Erules,encode_length,
+ [{asis,SizeConstraint},"length(Val)"]}
+ end,
+ com,nl]).
gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
asn1ct_name:start(),
{_SeqOrSetOf,ComponentType} = D#type.def,
- SizeConstraint =
- case asn1ct_gen:get_constraint(D#type.constraint,
- 'SizeConstraint') of
- no -> undefined;
- Range -> Range
- end,
+ SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
+ D#type.constraint),
ObjFun =
case D#type.tablecinf of
[{objfun,_}|_R] ->
@@ -519,52 +572,19 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_ ->
""
end,
- gen_decode_length(SizeConstraint,
- is_optimized(Erules)),
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
- NewComponentType =
- case ComponentType#type.def of
- {'ENUMERATED',_,Component}->
- ComponentType#type{def={'ENUMERATED',Component}};
- _ -> ComponentType
- end,
- gen_decode_sof_components(Erules,Typename,SeqOrSetOf,NewComponentType).
+ {Num,Buf} = gen_decode_length(SizeConstraint, Erules),
+ emit([",",nl,
+ "'dec_",asn1ct_gen:list2name(Typename),
+ "_components'(",Num,", ",Buf,ObjFun,", []).",nl,nl]),
+ gen_decode_sof_components(Erules, Typename, SeqOrSetOf, ComponentType).
-%% Logic copied from asn1_per_bin_rt2ct:decode_constrained_number
-gen_decode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
- Range = Ub - Lb + 1,
- Call = if
- Range == 1 ->
- "{0,Bytes}";
- Range == 2 ->
- "?RT_PER:getbits(Bytes,1)";
- Range =< 4 ->
- "?RT_PER:getbits(Bytes,2)";
- Range =< 8 ->
- "?RT_PER:getbits(Bytes,3)";
- Range =< 16 ->
- "?RT_PER:getbits(Bytes,4)";
- Range =< 32 ->
- "?RT_PER:getbits(Bytes,5)";
- Range =< 64 ->
- "?RT_PER:getbits(Bytes,6)";
- Range =< 128 ->
- "?RT_PER:getbits(Bytes,7)";
- Range =< 255 ->
- "?RT_PER:getbits(Bytes,8)";
- Range =< 256 ->
- "?RT_PER:getoctets(Bytes,1)";
- Range =< 65536 ->
- "?RT_PER:getoctets(Bytes,2)";
- true ->
- ["exit({not_supported,{integer_range,",Range,"}}"]
- end,
- emit({nl,"{Val,Remain} = ",Call,",",nl}),
- emit({nl,"{Num,Bytes1} = {Val+",Lb,",Remain},",nl});
-gen_decode_length(SizeConstraint,_) ->
- emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",
- {asis,SizeConstraint},"),",nl}).
+is_aligned(per) -> true;
+is_aligned(uper) -> false.
+
+gen_decode_length(Constraint, Erule) ->
+ emit(["%% Length with constraint ",{asis,Constraint},nl]),
+ Imm = asn1ct_imm:per_dec_length(Constraint, true, is_aligned(Erule)),
+ asn1ct_imm:dec_slim_cg(Imm, "Bytes").
gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
{ObjFun,ObjFun_Var} =
@@ -586,11 +606,9 @@ gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
Conttype = asn1ct_gen:get_inner(Cont#type.def),
Currmod = get(currmod),
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
case asn1ct_gen:type(Conttype) of
{primitive,bif} ->
- gen_encode_prim_wrapper(Ctgenmod,Erule,Cont,false,"H");
+ asn1ct_gen_per:gen_encode_prim(Erule, Cont, "H");
{constructed,bif} ->
NewTypename = [Constructed_Suffix|Typename],
emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
@@ -600,9 +618,9 @@ gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
#'Externaltypereference'{module=EMod,type=EType} ->
emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
'ASN1_OPEN_TYPE' ->
- gen_encode_prim_wrapper(Ctgenmod,Erule,
- #type{def='ASN1_OPEN_TYPE'},
- false,"H");
+ asn1ct_gen_per:gen_encode_prim(Erule,
+ #type{def='ASN1_OPEN_TYPE'},
+ "H");
_ ->
emit({"'enc_",Conttype,"'(H)",nl,nl})
end,
@@ -617,17 +635,15 @@ gen_decode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
{"",""}
end,
emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(0, Bytes, _",ObjFun_Var,", Acc) ->",nl,
+ "_components'(0, Bytes",ObjFun_Var,", Acc) ->",nl,
indent(3),"{lists:reverse(Acc), Bytes};",nl}),
emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num, Bytes, _",ObjFun,", Acc) ->",nl}),
+ "_components'(Num, Bytes",ObjFun,", Acc) ->",nl}),
emit({indent(3),"{Term,Remain} = "}),
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
Cont#type.def),
Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
- CurrMod = get(currmod),
+ Ctgenmod = asn1ct_gen:ct_gen_module(Erule),
case asn1ct_gen:type(Conttype) of
{primitive,bif} ->
Ctgenmod:gen_dec_prim(Erule,Cont,"Bytes"),
@@ -636,12 +652,9 @@ gen_decode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
NewTypename = [Constructed_Suffix|Typename],
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
"'(Bytes, telltype",ObjFun,"),",nl});
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype),",nl});
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- emit({"'dec_",EType,"'(Bytes,telltype),",nl});
- #'Externaltypereference'{module=EMod,type=EType} ->
- emit({"'",EMod,"':'dec_",EType,"'(Bytes,telltype),",nl});
+ #'Externaltypereference'{}=Etype ->
+ asn1ct_gen_per:gen_dec_external(Etype, "Bytes"),
+ emit([com,nl]);
'ASN1_OPEN_TYPE' ->
Ctgenmod:gen_dec_prim(Erule,#type{def='ASN1_OPEN_TYPE'},
"Bytes"),
@@ -650,7 +663,7 @@ gen_decode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
end,
emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num-1, Remain, telltype",ObjFun,", [Term|Acc]).",nl}).
+ "_components'(Num-1, Remain",ObjFun,", [Term|Acc]).",nl}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -721,10 +734,25 @@ extgrouppos([_|T],ActualPos,VirtualPos,Len,Acc) ->
extgrouppos(T,ActualPos,VirtualPos,Len+1,Acc).
-
-gen_dec_extension_value(_) ->
- emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
- asn1ct_name:new(bytes).
+gen_dec_extension_value() ->
+ Imm0 = {get_bits,1,[1]},
+ E = fun(Imm, _) ->
+ emit(["{Ext,",{next,bytes},"} = "]),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ asn1ct_name:new(bytes)
+ end,
+ {imm,Imm0,E}.
+
+gen_dec_optionals(Optionals) ->
+ Imm0 = {get_bits,length(Optionals),[1]},
+ E = fun(Imm, _) ->
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ emit(["{Opt,",{next,bytes},"} = "]),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ asn1ct_name:new(bytes)
+ end,
+ {imm,Imm0,E}.
gen_fixoptionals([{Pos,Def}|R]) ->
asn1ct_name:new(fixopt),
@@ -892,7 +920,7 @@ gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_,_) ->
Pos.
gen_enc_component_default(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext,DefaultVal) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
emit({"case ",Element," of",nl}),
% emit({"asn1_DEFAULT -> [];",nl}),
emit({"DFLT when DFLT == asn1_DEFAULT; DFLT == ",{asis,DefaultVal}," -> [];",nl}),
@@ -912,7 +940,7 @@ gen_enc_component_optional(Erule,TopType,Cname,
components=_ExtGroupCompList}},
Pos,DynamicEnc,Ext) when is_integer(Number) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
emit({"case ",Element," of",nl}),
emit({"asn1_NOVALUE -> [];",nl}),
@@ -925,7 +953,7 @@ gen_enc_component_optional(Erule,TopType,Cname,
gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
emit({nl,"end"});
gen_enc_component_optional(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
emit({"case ",Element," of",nl}),
emit({"asn1_NOVALUE -> [];",nl}),
@@ -945,11 +973,9 @@ gen_enc_component_mandatory(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
gen_enc_line(Erule,TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
gen_enc_line(Erule,TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
gen_enc_line(Erule,TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
@@ -960,7 +986,9 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
case Ext of
{ext,_Ep1,_} ->
- emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
+ asn1ct_func:need({Erule,encode_open_type,1}),
+ asn1ct_func:need({Erule,complete,1}),
+ emit(["encode_open_type(complete("]);
_ -> true
end,
@@ -969,10 +997,10 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
case DynamicEnc of
{_LeadingAttrName,Fun} ->
case (Type#type.def)#'ObjectClassFieldType'.fieldname of
- {notype,T} ->
- throw({error,{notype,type_from_object,T}});
{Name,RestFieldNames} when is_atom(Name) ->
- emit({"?RT_PER:encode_open_type([],?RT_PER:complete(",nl}),
+ asn1ct_func:need({Erule,complete,1}),
+ asn1ct_func:need({Erule,encode_open_type,1}),
+ emit({"encode_open_type(complete(",nl}),
emit({" ",Fun,"(",{asis,Name},", ",
Element,", ",{asis,RestFieldNames},")))"});
Other ->
@@ -982,8 +1010,10 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
{objectfield,PrimFieldName1,PFNList} ->
case DynamicEnc of
{_LeadingAttrName,Fun} ->
- emit({"?RT_PER:encode_open_type([],"
- "?RT_PER:complete(",nl}),
+ asn1ct_func:need({Erule,complete,1}),
+ asn1ct_func:need({Erule,encode_open_type,1}),
+ emit({"encode_open_type("
+ "complete(",nl}),
emit({" ",Fun,"(",{asis,PrimFieldName1},
", ",Element,", ",{asis,PFNList},")))"})
end;
@@ -996,29 +1026,17 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
#'Externaltypereference'{module=Mod,type=EType} ->
emit({"'",Mod,"':'enc_",
EType,"'(",Element,")"});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(",Element,")"});
- {notype,_} ->
- emit({"'enc_",Atype,"'(",Element,")"});
{primitive,bif} ->
- EncType =
- case Atype of
- {fixedtypevaluefield,_,Btype} ->
- Btype;
- _ ->
- Type
- end,
- gen_encode_prim_wrapper(Ctgenmod,Erule,EncType,
- false,Element);
+ asn1ct_gen_per:gen_encode_prim(Erule, Type, Element);
'ASN1_OPEN_TYPE' ->
case Type#type.def of
#'ObjectClassFieldType'{type=OpenType} ->
- gen_encode_prim_wrapper(Ctgenmod,Erule,
- #type{def=OpenType},
- false,Element);
+ asn1ct_gen_per:gen_encode_prim(Erule,
+ #type{def=OpenType},
+ Element);
_ ->
- gen_encode_prim_wrapper(Ctgenmod,Erule,Type,
- false,Element)
+ asn1ct_gen_per:gen_encode_prim(Erule, Type,
+ Element)
end;
{constructed,bif} ->
NewTypename = [Cname|TopType],
@@ -1039,53 +1057,81 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
emit("))");
_ -> true
end.
-gen_dec_components_call(Erule,TopType,{Root,ExtList},MaybeComma,
+
+gen_dec_components_call(Erule, TopType, {Root,ExtList},
+ DecInfObj, Ext, NumberOfOptionals) ->
+ gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},
+ DecInfObj,Ext,NumberOfOptionals);
+gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2},
DecInfObj,Ext,NumberOfOptionals) ->
- gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DecInfObj,Ext,NumberOfOptionals);
-gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
%% The type has extensionmarker
-
OptTable = create_optionality_table(Root1++Root2),
- {Rpos,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, Root1++Root2, 1, OptTable,
- MaybeComma,DecInfObj,noext,[],[],
- NumberOfOptionals),
- emit([",",nl,"{Extensions,",{next,bytes},"} = "]),
- emit(["?RT_PER:getextension(Ext,",{curr,bytes},"),",nl]),
- asn1ct_name:new(bytes),
+ Init = {ignore,fun(_) -> {[],[]} end},
+ {EmitRoot,Tpos} =
+ gen_dec_comp_calls(Root1++Root2, Erule, TopType, OptTable,
+ DecInfObj, noext, NumberOfOptionals,
+ 1, []),
+ EmitGetExt = gen_dec_get_extension(Erule),
{extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
- NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
- {_Epos,AccTermE,AccBytesE} =
- gen_dec_components_call1(Erule,TopType,NewExtList,Rpos, OptTable,
- "",DecInfObj,Ext,[],[],NumberOfOptionals),
- case ExtList of
- [] -> true;
- _ -> emit([",",nl])
- end,
- emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",",
- length(ExtList)+1,",Extensions)",nl]),
- asn1ct_name:new(bytes),
- {AccTerm++AccTermE,AccBytes++AccBytesE};
-
-gen_dec_components_call(Erule,TopType,CompList,MaybeComma,DecInfObj,
- Ext,NumberOfOptionals) ->
+ NewExtList = wrap_extensionAdditionGroups(ExtList, ExtGroupPosLen),
+ {EmitExts,_} = gen_dec_comp_calls(NewExtList, Erule, TopType, OptTable,
+ DecInfObj, Ext, NumberOfOptionals,
+ Tpos, []),
+ NumExtsToSkip = ext_length(ExtList),
+ Finish =
+ fun(St) ->
+ emit([{next,bytes},"= "]),
+ call(Erule, skipextensions,
+ [{curr,bytes},NumExtsToSkip+1,"Extensions"]),
+ asn1ct_name:new(bytes),
+ St
+ end,
+ [Init] ++ EmitRoot ++ [EmitGetExt|EmitExts] ++ [Finish];
+gen_dec_components_call(Erule, TopType, CompList, DecInfObj,
+ Ext, NumberOfOptionals) ->
%% The type has no extensionmarker
OptTable = create_optionality_table(CompList),
- {_,AccTerm,AccBytes} =
- gen_dec_components_call1(Erule,TopType, CompList, 1, OptTable,
- MaybeComma,DecInfObj,Ext,[],[],
- NumberOfOptionals),
- {AccTerm,AccBytes}.
-
-
-gen_dec_components_call1(Erule,TopType,
- [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop,textual_order=TextPos}|Rest],
- Tpos,OptTable,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
+ Init = {ignore,fun(_) -> {[],[]} end},
+ {Cs,_} = gen_dec_comp_calls(CompList, Erule, TopType, OptTable,
+ DecInfObj, Ext, NumberOfOptionals,
+ 1, []),
+ [Init|Cs].
+
+gen_dec_get_extension(Erule) ->
+ Imm0 = asn1ct_imm:per_dec_extension_map(is_aligned(Erule)),
+ E = fun(Imm, St) ->
+ emit([nl,"%% Extensions",
+ nl,
+ "{Extensions,",{next,bytes},"} = ",
+ "case Ext of",nl,
+ "0 -> {<<>>,",{curr,bytes},"};",nl,
+ "1 ->",nl]),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([com,nl,
+ "{",Dst,",",DstBuf,"}",nl,
+ "end"]),
+ asn1ct_name:new(bytes),
+ St
+ end,
+ {imm,Imm0,E}.
+
+gen_dec_comp_calls([C|Cs], Erule, TopType, OptTable, DecInfObj,
+ Ext, NumberOfOptionals, Tpos, Acc) ->
+ L = gen_dec_comp_call(C, Erule, TopType, Tpos, OptTable, DecInfObj,
+ Ext, NumberOfOptionals),
+ gen_dec_comp_calls(Cs, Erule, TopType, OptTable, DecInfObj,
+ Ext, NumberOfOptionals, Tpos+1, [L|Acc]);
+gen_dec_comp_calls([], _, _, _, _, _, _, Tpos, Acc) ->
+ {lists:append(lists:reverse(Acc)),Tpos}.
+
+gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj,
+ Ext, NumberOfOptionals) ->
+ #'ComponentType'{typespec=Type,prop=Prop,textual_order=TextPos} = Comp,
Pos = case Ext of
noext -> Tpos;
{ext,Epos,_Enum} -> Tpos - Epos + 1
end,
- emit(MaybeComma),
InnerType =
case Type#type.def of
#'ObjectClassFieldType'{type=InType} ->
@@ -1094,109 +1140,127 @@ gen_dec_components_call1(Erule,TopType,
asn1ct_gen:get_inner(Def)
end,
- case InnerType of
- #'Externaltypereference'{type=T} ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- T,nl});
- IT when is_tuple(IT) ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- element(2,IT),nl});
- _ ->
- emit({nl,"%% attribute number ",TextPos," with type ",
- InnerType,nl})
- end,
-
- IsMandatoryAndPredefinedTableC =
- fun(noext,mandatory,{"got objfun through args","ObjFun"}) ->
- true;
- (_,_,{"got objfun through args","ObjFun"}) ->
- false;
- (_,_,_) ->
- true
- end,
- case {InnerType,IsMandatoryAndPredefinedTableC(Ext,Prop,DecInfObj)} of
-%% {typefield,_} when Ext == noext, Prop == mandatory ->
- {{typefield,_},true} ->
- %% DecInfObj /= {"got objfun through args","ObjFun"} |
- %% (DecInfObj == {"got objfun through args","ObjFun"} &
- %% Ext == noext & Prop == mandatory)
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ DispType = case InnerType of
+ #'Externaltypereference'{type=T} -> T;
+ IT when is_tuple(IT) -> element(2,IT);
+ _ -> InnerType
+ end,
+ Comment = fun(St) ->
+ emit([nl,"%% attribute number ",TextPos,
+ " with type ",DispType,nl]),
+ St
+ end,
+
+ Preamble =
+ case {InnerType,is_mandatory_predef_tab_c(Ext, Prop, DecInfObj)} of
+ {{typefield,_},true} ->
+ %% DecInfObj /= {"got objfun through args","ObjFun"} |
+ %% (DecInfObj == {"got objfun through args","ObjFun"} &
+ %% Ext == noext & Prop == mandatory)
+ fun(St) ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
+ St
+ end;
%%{objectfield,_,_} when Ext == noext, Prop == mandatory ->
- {{objectfield,_,_},true} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ {{objectfield,_,_},true} ->
+ fun(St) ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
+ St
+ end;
_ ->
case Type of
#type{def=#'SEQUENCE'{
extaddgroup=Number1,
components=ExtGroupCompList1}} when is_integer(Number1)->
- emit({"{{_,"}),
- emit_extaddgroupTerms(term,ExtGroupCompList1),
- emit({"}"});
- _ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term}})
- end,
- emit({",",{next,bytes},"} = "})
- end,
-
- case {Ext,Prop,is_optimized(Erule)} of
- {noext,mandatory,_} -> ok; % generate nothing
- {noext,_,_} -> %% OPTIONAL or DEFAULT
- OptPos = get_optionality_pos(TextPos,OptTable),
- Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
- emit(["case ",Element," of",nl]),
- emit([" _Opt",TextPos," when _Opt",TextPos," > 0 ->"]);
- {_,_,false} -> %% extension element, not bitstring
- emit(["case Extensions of",nl]),
- emit([" _ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl]);
- _ ->
- emit(["case Extensions of",nl]),
- emit([" <<_:",Pos-1,",1:1,_/bitstring>> when bit_size(Extensions) >= ",Pos," ->",nl])
- end,
- put(component_type,{true,C}),
- {TermVar,BytesVar} = gen_dec_line(Erule,TopType,Cname,Type,Tpos,DecInfObj,Ext,Prop),
- erase(component_type),
- case {Ext,Prop} of
- {noext,mandatory} -> true; % generate nothing
- {noext,_} ->
- emit([";",nl,"0 ->"]),
- emit(["{"]),
- gen_dec_component_no_val(Ext,Prop),
- emit({",",{curr,bytes},"}",nl}),
- emit([nl,"end"]);
- _ ->
- emit([";",nl,"_ ->",nl]),
- emit(["{"]),
- case Type of
- #type{def=#'SEQUENCE'{
- extaddgroup=Number2,
- components=ExtGroupCompList2}} when is_integer(Number2)->
- emit({"{extAddGroup,"}),
- gen_dec_extaddGroup_no_val(Ext,ExtGroupCompList2),
- emit({"}"});
+ fun(St) ->
+ emit(["{{_,"]),
+ emit_extaddgroupTerms(term,ExtGroupCompList1),
+ emit(["}"]),
+ emit([",",{next,bytes},"} = "]),
+ St
+ end;
_ ->
- gen_dec_component_no_val(Ext,Prop)
- end,
- emit({",",{curr,bytes},"}",nl}),
- emit([nl,"end"])
- end,
- asn1ct_name:new(bytes),
- case Rest of
- [] ->
- {Tpos+1,AccTerm++TermVar,AccBytes++BytesVar};
- _ ->
- emit({com,nl}),
- gen_dec_components_call1(Erule,TopType,Rest,Tpos+1,OptTable,
- "",DecInfObj,Ext, AccTerm++TermVar,
- AccBytes++BytesVar,NumberOfOptionals)
- end;
-
-gen_dec_components_call1(_,_TopType,[],Pos,_OptTable,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
- {Pos,AccTerm,AccBytes}.
+ fun(St) ->
+ asn1ct_name:new(term),
+ emit(["{",{curr,term}]),
+ emit([",",{next,bytes},"} = "]),
+ St
+ end
+ end
+ end,
+ {Pre,Post} = comp_call_pre_post(Ext, Prop, Pos, Type, TextPos,
+ OptTable, NumberOfOptionals, Ext),
+ Lines = gen_dec_seq_line_imm(Erule, TopType, Comp, Tpos, DecInfObj, Ext),
+ AdvBuffer = {ignore,fun(St) ->
+ asn1ct_name:new(bytes),
+ St
+ end},
+ [{group,[{safe,Comment},{safe,Preamble}] ++ Pre ++
+ Lines ++ Post ++ [{safe,AdvBuffer}]}].
+
+comp_call_pre_post(noext, mandatory, _, _, _, _, _, _) ->
+ {[],[]};
+comp_call_pre_post(noext, Prop, _, _, TextPos, OptTable, NumOptionals, Ext) ->
+ %% OPTIONAL or DEFAULT
+ OptPos = get_optionality_pos(TextPos, OptTable),
+ Element = case NumOptionals - OptPos of
+ 0 ->
+ "Opt band 1";
+ Shift ->
+ lists:concat(["(Opt bsr ",Shift,") band 1"])
+ end,
+ {[fun(St) ->
+ emit(["case ",Element," of",nl,
+ "1 ->",nl]),
+ St
+ end],
+ [fun(St) ->
+ emit([";",nl,
+ "0 ->",nl,
+ "{"]),
+ gen_dec_component_no_val(Ext, Prop),
+ emit([",",{curr,bytes},"}",nl,
+ "end"]),
+ St
+ end]};
+comp_call_pre_post({ext,_,_}, Prop, Pos, Type, _, _, _, Ext) ->
+ %% Extension
+ {[fun(St) ->
+ emit(["case Extensions of",nl,
+ " <<_:",Pos-1,",1:1,_/bitstring>> ->",nl]),
+ St
+ end],
+ [fun(St) ->
+ emit([";",nl,
+ "_ ->",nl,
+ "{"]),
+ case Type of
+ #type{def=#'SEQUENCE'{
+ extaddgroup=Number2,
+ components=ExtGroupCompList2}}
+ when is_integer(Number2)->
+ emit("{extAddGroup,"),
+ gen_dec_extaddGroup_no_val(Ext, ExtGroupCompList2),
+ emit("}");
+ _ ->
+ gen_dec_component_no_val(Ext, Prop)
+ end,
+ emit([",",{curr,bytes},"}",nl,
+ "end"]),
+ St
+ end]}.
+
+is_mandatory_predef_tab_c(noext, mandatory,
+ {"got objfun through args","ObjFun"}) ->
+ true;
+is_mandatory_predef_tab_c(_, _, {"got objfun through args","ObjFun"}) ->
+ false;
+is_mandatory_predef_tab_c(_,_,_) ->
+ true.
gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}])->
gen_dec_component_no_val(Ext,Prop),
@@ -1216,9 +1280,18 @@ gen_dec_component_no_val({ext,_,_},mandatory) ->
emit({"asn1_NOVALUE"}).
-gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
+gen_dec_choice_line(Erule, TopType, Comp, Pre) ->
+ Imm0 = gen_dec_line_imm(Erule, TopType, Comp, false, Pre),
+ Init = {ignore,fun(_) -> {[],[]} end},
+ Imm = [{group,[Init|Imm0]}],
+ emit_gen_dec_imm(Imm).
+
+gen_dec_seq_line_imm(Erule, TopType, Comp, Pos, DecInfObj, Ext) ->
+ Pre = gen_dec_line_open_type(Erule, Ext, Pos),
+ gen_dec_line_imm(Erule, TopType, Comp, DecInfObj, Pre).
+
+gen_dec_line_imm(Erule, TopType, Comp, DecInfObj, Pre) ->
+ #'ComponentType'{name=Cname,typespec=Type} = Comp,
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
@@ -1226,202 +1299,237 @@ gen_dec_line(Erule,TopType,Cname,Type,Pos,DecInfObj,Ext,Prop) ->
_ ->
asn1ct_gen:get_inner(Type#type.def)
end,
-
- BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- BytesVar = case Ext of
- {ext,Ep,_} when Pos >= Ep ->
- emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
- "}=?RT_PER:decode_open_type(",
- {curr,bytes},",[]),",nl,
- "{TmpValx",Pos,",_}="]),
- io_lib:format("TmpVal~p",[Pos]);
- _ -> BytesVar0
- end,
- SaveBytes =
- case Atype of
- {typefield,_} ->
- case DecInfObj of
- false -> % This is in a choice with typefield components
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
- emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
- "} = ?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- emit([indent(2),"case (catch ObjFun(",
- {asis,Name},",",{curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),"{",{asis,Cname},", {",{curr,tmpterm},", ",
- {next,bytes},"}}",nl]),
- emit([indent(2),"end"]),
- [];
- {"got objfun through args","ObjFun"} ->
- %% this is when the generated code gots the
- %% objfun though arguments on function
- %% invocation.
- if
- Ext == noext andalso Prop == mandatory ->
- ok;
- true ->
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(tmpbytes),
- emit([nl," {",{curr,tmpterm},", ",{curr,tmpbytes},"} ="])
- end,
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit(["?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- if
- Ext == noext andalso Prop == mandatory ->
- emit([{curr,term}," =",nl," "]);
- true ->
- emit([" {"])
- end,
- emit(["case (catch ObjFun(",{asis,Name},",",
- {curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([" {'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),{curr,tmpterm},nl]),
- emit([indent(2),"end"]),
- if
- Ext == noext andalso Prop == mandatory ->
- ok;
- true ->
- emit([",",nl,{curr,tmpbytes},"}"])
- end,
- [];
- _ ->
- emit(["?RT_PER:decode_open_type(",{curr,bytes},
- ", [])"]),
- RefedFieldName =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-
- [{Cname,RefedFieldName,
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}]
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- emit(["?RT_PER:decode_open_type(",{curr,bytes},", [])"]),
- [{Cname,{PrimFieldName1,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}];
- _ ->
- CurrMod = get(currmod),
- case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
- #'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
- ",telltype)"});
- {primitive,bif} ->
- case Atype of
- {fixedtypevaluefield,_,Btype} ->
- Ctgenmod:gen_dec_prim(Erule,Btype,
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(Erule,Type,
- BytesVar)
- end;
- 'ASN1_OPEN_TYPE' ->
- case Type#type.def of
- #'ObjectClassFieldType'{type=OpenType} ->
- Ctgenmod:gen_dec_prim(Erule,#type{def=OpenType},
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(Erule,Type,
- BytesVar)
- end;
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
- {notype,_} ->
- emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
- {constructed,bif} ->
- NewTypename = [Cname|TopType],
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype, ObjFun)"});
- _ ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype)"})
- end
- end,
+ Decode = gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj),
+ Post =
+ fun({SaveBytes,Finish}) ->
+ {AccTerm,AccBytes} = Finish(),
+ #'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- {ObjSetMod,ObjSetName} =
- case OSet of
- {M,O} -> {{asis,M},O};
- _ -> {"?MODULE",OSet}
+ {Cname,ObjSet} ->
+ ObjSetRef =
+ case ObjSet of
+ {deep,OSName,_,_} ->
+ OSName;
+ _ -> ObjSet
end,
- emit({",",nl,"ObjFun = ",ObjSetMod,
- ":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"});
+ {AccTerm++[{ObjSetRef,Cname,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
+ AccBytes++SaveBytes};
_ ->
- ok
- end,
- []
+ {AccTerm,AccBytes++SaveBytes}
+ end
end,
- case Ext of
- {ext,Ep2,_} when Pos >= Ep2 ->
- emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
- _ -> true
- end,
- %% Prepare return value
+ [Pre,Decode,{safe,Post}].
+
+gen_dec_line_open_type(Erule, {ext,Ep,_}, Pos) when Pos >= Ep ->
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ {safe,fun(St) ->
+ emit(["begin",nl]),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([",",nl,"{TmpValx",Pos,",_} = "]),
+ {Dst,
+ fun() ->
+ emit([",",nl,
+ "{TmpValx",Pos,",",DstBuf,"}",nl,
+ "end"]),
+ St
+ end}
+ end};
+gen_dec_line_open_type(_, _, _) ->
+ {safe,fun(St) ->
+ {asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ fun() -> St end}
+ end}.
+
+gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
+ DecInfObj) ->
+ #'ComponentType'{name=Cname,typespec=Type,prop=Prop} = Comp,
+ fun({_BytesVar,PrevSt}) ->
+ case DecInfObj of
+ false -> % This is in a choice with typefield components
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+
+ asn1ct_name:new(reason),
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ {TmpTerm,TempBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([com,nl,
+ {next,bytes}," = ",TempBuf,com,nl,
+ indent(2),"case (catch ObjFun(",
+ {asis,Name},",",TmpTerm,",telltype,",
+ {asis,RestFieldNames},")) of", nl]),
+ emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
+ emit([indent(6),"exit({'Type not ",
+ "compatible with table constraint', ",
+ {curr,reason},"});",nl]),
+ asn1ct_name:new(tmpterm),
+ emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
+ emit([indent(6),"{",{asis,Cname},", {",{curr,tmpterm},", ",
+ {next,bytes},"}}",nl]),
+ emit([indent(2),"end"]),
+ {[],PrevSt};
+ {"got objfun through args","ObjFun"} ->
+ %% this is when the generated code gots the
+ %% objfun though arguments on function
+ %% invocation.
+ if
+ Prop =:= mandatory ->
+ ok;
+ true ->
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(tmpbytes),
+ emit([nl," {",{curr,tmpterm},", ",{curr,tmpbytes},"} ="])
+ end,
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ emit([com,nl]),
+ if
+ Prop =:= mandatory ->
+ emit([{curr,term}," =",nl," "]);
+ true ->
+ emit([" {"])
+ end,
+ emit(["case (catch ObjFun(",{asis,Name},",",
+ {curr,tmpterm},",telltype,",
+ {asis,RestFieldNames},")) of", nl]),
+ emit([" {'EXIT',",{curr,reason},"} ->",nl]),
+ emit([indent(6),"exit({'Type not ",
+ "compatible with table constraint', ",
+ {curr,reason},"});",nl]),
+ asn1ct_name:new(tmpterm),
+ emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
+ emit([indent(6),{curr,tmpterm},nl]),
+ emit([indent(2),"end"]),
+ if
+ Prop =:= mandatory ->
+ ok;
+ true ->
+ emit([",",nl,{curr,tmpbytes},"}"])
+ end,
+ {[],PrevSt};
+ _ ->
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ RefedFieldName =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+
+ {[{Cname,RefedFieldName,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ Prop}],PrevSt}
+ end
+ end;
+gen_dec_line_special(Erule, {objectfield,PrimFieldName1,PFNList}, _TopType,
+ Comp, _DecInfObj) ->
+ fun({_BytesVar,PrevSt}) ->
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ #'ComponentType'{name=Cname,prop=Prop} = Comp,
+ SaveBytes = [{Cname,{PrimFieldName1,PFNList},
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ Prop}],
+ {SaveBytes,PrevSt}
+ end;
+gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) ->
+ case gen_dec_line_other(Erule, Atype, TopType, Comp) of
+ Fun when is_function(Fun, 1) ->
+ fun({BytesVar,PrevSt}) ->
+ Fun(BytesVar),
+ gen_dec_line_dec_inf(Comp, DecInfObj),
+ {[],PrevSt}
+ end;
+ Imm0 ->
+ {imm,Imm0,
+ fun(Imm, {BytesVar,PrevSt}) ->
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ gen_dec_line_dec_inf(Comp, DecInfObj),
+ {[],PrevSt}
+ end}
+ end.
+
+gen_dec_line_dec_inf(Comp, DecInfObj) ->
+ #'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,ObjSet} ->
- ObjSetRef =
- case ObjSet of
- {deep,OSName,_,_} ->
- OSName;
- _ -> ObjSet
- end,
- {[{ObjSetRef,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- SaveBytes};
+ {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ ValueMatch = value_match(ValIndex,Term),
+ {ObjSetMod,ObjSetName} = OSet,
+ emit([",",nl,
+ "ObjFun = ",{asis,ObjSetMod},
+ ":'getdec_",ObjSetName,"'(",
+ {asis,UniqueFName},", ",ValueMatch,")"]);
_ ->
- {[],SaveBytes}
+ ok
+ end.
+
+gen_dec_line_other(Erule, Atype, TopType, Comp) ->
+ #'ComponentType'{name=Cname,typespec=Type} = Comp,
+ case asn1ct_gen:type(Atype) of
+ #'Externaltypereference'{}=Etype ->
+ fun(BytesVar) ->
+ asn1ct_gen_per:gen_dec_external(Etype, BytesVar)
+ end;
+ {primitive,bif} ->
+ asn1ct_gen_per:gen_dec_imm(Erule, Type);
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OpenType} ->
+ asn1ct_gen_per:gen_dec_imm(Erule, #type{def=OpenType});
+ _ ->
+ asn1ct_gen_per:gen_dec_imm(Erule, Type)
+ end;
+ {constructed,bif} ->
+ NewTypename = [Cname|TopType],
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ fun(BytesVar) ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype, ObjFun)"})
+ end;
+ _ ->
+ fun(BytesVar) ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype)"})
+ end
+ end
end.
gen_enc_choice(Erule,TopType,CompList,Ext) ->
- gen_enc_choice_tag(CompList, [], Ext),
+ gen_enc_choice_tag(Erule, CompList, [], Ext),
emit({com,nl}),
emit({"case element(1,Val) of",nl}),
gen_enc_choice2(Erule,TopType, CompList, Ext),
emit({nl,"end"}).
-gen_enc_choice_tag({C1,C2},_,_) ->
+gen_enc_choice_tag(Erule, {C1,C2}, _, _) ->
N1 = get_name_list(C1),
N2 = get_name_list(C2),
- emit(["?RT_PER:set_choice(element(1,Val),",
- {asis,{N1,N2}},", ",{asis,{length(N1),length(N2)}},")"]);
-
-gen_enc_choice_tag({C1,C2,C3},_,_) ->
+ call(Erule,set_choice,
+ ["element(1, Val)",
+ {asis,{N1,N2}},
+ {asis,{length(N1),length(N2)}}]);
+gen_enc_choice_tag(Erule, {C1,C2,C3}, _, _) ->
N1 = get_name_list(C1),
N2 = get_name_list(C2),
N3 = get_name_list(C3),
Root = N1 ++ N3,
- emit(["?RT_PER:set_choice(element(1,Val),",
- {asis,{Root,N2}},", ",{asis,{length(Root),length(N2)}},")"]);
-gen_enc_choice_tag(C,_,_) ->
+ call(Erule,set_choice,
+ ["element(1, Val)",
+ {asis,{Root,N2}},
+ {asis,{length(Root),length(N2)}}]);
+gen_enc_choice_tag(Erule, C, _, _) ->
N = get_name_list(C),
- emit(["?RT_PER:set_choice(element(1,Val),",
- {asis,N},", ",{asis,length(N)},")"]).
+ call(Erule,set_choice,
+ ["element(1, Val)",
+ {asis,N},{asis,length(N)}]).
get_name_list(L) ->
get_name_list(L,[]).
@@ -1433,40 +1541,14 @@ get_name_list([], Acc) ->
gen_enc_choice2(Erule,TopType, {L1,L2}, Ext) ->
- gen_enc_choice2(Erule,TopType, L1 ++ L2, 0, Ext);
-gen_enc_choice2(Erule,TopType, {L1,L2,L3}, Ext) ->
- gen_enc_choice2(Erule,TopType, L1 ++ L3 ++ L2, 0, Ext);
+ gen_enc_choice2(Erule, TopType, L1 ++ L2, 0, [], Ext);
+gen_enc_choice2(Erule, TopType, {L1,L2,L3}, Ext) ->
+ gen_enc_choice2(Erule, TopType, L1 ++ L3 ++ L2, 0, [], Ext);
gen_enc_choice2(Erule,TopType, L, Ext) ->
- gen_enc_choice2(Erule,TopType, L, 0, Ext).
+ gen_enc_choice2(Erule,TopType, L, 0, [], Ext).
-gen_enc_choice2(Erule,TopType,[H1,H2|T], Pos, Ext)
-when is_record(H1,'ComponentType'), is_record(H2,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- EncObj =
- case asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation) of
- no ->
- case Type#type.tablecinf of
- [{objfun,_}|_] ->
- {"got objfun through args","ObjFun"};
- _ ->false
- end;
- _ -> {no_attr,"ObjFun"}
- end,
- emit({{asis,Cname}," ->",nl}),
- DoExt = case Ext of
- {ext,ExtPos,_} when (Pos + 1) < ExtPos -> noext;
- _ -> Ext
- end,
- gen_enc_line(Erule,TopType,Cname,Type,"element(2,Val)",
- Pos+1,EncObj,DoExt),
- emit({";",nl}),
- gen_enc_choice2(Erule,TopType,[H2|T], Pos+1, Ext);
-gen_enc_choice2(Erule,TopType,[H1|T], Pos, Ext)
- when is_record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
+gen_enc_choice2(Erule, TopType, [H|T], Pos, Sep0, Ext) ->
+ #'ComponentType'{name=Cname,typespec=Type} = H,
EncObj =
case asn1ct_gen:get_constraint(Type#type.constraint,
componentrelation) of
@@ -1474,129 +1556,171 @@ gen_enc_choice2(Erule,TopType,[H1|T], Pos, Ext)
case Type#type.tablecinf of
[{objfun,_}|_] ->
{"got objfun through args","ObjFun"};
- _ ->false
+ _ ->
+ false
end;
- _ -> {no_attr,"ObjFun"}
+ _ ->
+ {no_attr,"ObjFun"}
end,
- emit({{asis,H1#'ComponentType'.name}," ->",nl}),
+ emit([Sep0,{asis,Cname}," ->",nl]),
DoExt = case Ext of
- {ext,ExtPos,_} when (Pos + 1) < ExtPos -> noext;
+ {ext,ExtPos,_} when Pos + 1 < ExtPos -> noext;
_ -> Ext
end,
- gen_enc_line(Erule,TopType,Cname,Type,"element(2,Val)",
- Pos+1,EncObj,DoExt),
- gen_enc_choice2(Erule,TopType,T, Pos+1, Ext);
-gen_enc_choice2(_Erule,_,[], _, _) ->
- true.
+ gen_enc_line(Erule, TopType, Cname, Type, "element(2, Val)",
+ Pos+1, EncObj, DoExt),
+ Sep = [";",nl],
+ gen_enc_choice2(Erule, TopType, T, Pos+1, Sep, Ext);
+gen_enc_choice2(_, _, [], _, _, _) -> ok.
+
+%% Generate the code for CHOICE. If the CHOICE is extensible,
+%% the structure of the generated code is as follows:
+%%
+%% case Bytes of
+%% <<0:1,Bytes1/bitstring>> ->
+%% Choice = <Decode INTEGER (0..LastRootChoice) from Bytes1>
+%% case Choice of
+%% 0 -> <Decode>;
+%% :
+%% LastRootChoice -> <Decode>
+%% end;
+%% <<1:1,Bytes1/bitstring>> ->
+%% Choice = <Decode normally small number from Bytes1>
+%% TmpVal = <Decode open type>
+%% case Choice of
+%% 0 -> <Decode TmpVal>;
+%% :
+%% LastExtension -> <Decode TmpVal>;
+%% _ -> <Return TmpVal since the type is unknown>
+%% end
+%% end
+%%
+%% The return value from the generated function always looks like:
+%% {{ChoiceTag,Value},RemainingBuffer}
+%% where ChoiceTag will be 'asn1_ExtAlt' for an unknown extension.
+%%
+%% If the CHOICE is not extensible, the top-level case is omitted
+%% and only the code in the first case arm is generated.
-gen_dec_choice(Erule,TopType,CompList,{ext,Pos,NumExt}) ->
- emit({"{Ext,",{curr,bytes},"} = ?RT_PER:getbit(Bytes),",nl}),
+gen_dec_choice(Erule, TopType, CompList, {ext,_,_}=Ext) ->
+ {RootList,ExtList} = split_complist(CompList),
+ emit(["case Bytes of",nl]),
+ case RootList of
+ [] ->
+ ok;
+ [_|_] ->
+ emit(["<<0:1,Bytes1/bitstring>> ->",nl]),
+ asn1ct_name:new(bytes),
+ gen_dec_choice1(Erule, TopType, RootList, noext),
+ emit([";",nl,nl])
+ end,
+ emit(["<<1:1,Bytes1/bitstring>> ->",nl]),
+ asn1ct_name:clear(),
asn1ct_name:new(bytes),
- gen_dec_choice1(Erule,TopType,CompList,{ext,Pos,NumExt});
-gen_dec_choice(Erule,TopType,CompList,noext) ->
- gen_dec_choice1(Erule,TopType,CompList,noext).
-
-gen_dec_choice1(Erule,TopType,CompList,noext) ->
- emit({"{Choice,",{curr,bytes},
- "} = ?RT_PER:getchoice(",{prev,bytes},",",
- length(CompList),", 0),",nl}),
- emit({"{Cname,{Val,NewBytes}} = case Choice of",nl}),
- gen_dec_choice2(Erule,TopType,CompList,noext),
- emit({nl,"end,",nl}),
- emit({nl,"{{Cname,Val},NewBytes}"});
-gen_dec_choice1(Erule,TopType,{RootList,ExtList},Ext) ->
- NewList = RootList ++ ExtList,
- gen_dec_choice1(Erule,TopType, NewList, Ext);
-gen_dec_choice1(Erule,TopType,{RootList,ExtList,RootList2},Ext) ->
- NewList = RootList ++ RootList2 ++ ExtList,
- gen_dec_choice1(Erule,TopType, NewList, Ext);
-gen_dec_choice1(Erule,TopType,CompList,{ext,ExtPos,ExtNum}) ->
- emit({"{Choice,",{curr,bytes},
- "} = ?RT_PER:getchoice(",{prev,bytes},",",
- length(CompList)-ExtNum,",Ext ),",nl}),
- emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}),
- gen_dec_choice2(Erule,TopType,CompList,{ext,ExtPos,ExtNum}),
- case Erule of
- per ->
- emit([";",nl,"_ -> {asn1_ExtAlt,",nl,
- " fun() -> ",nl,
- " {XTerm,XBytes} = ?RT_PER:decode_open_type(",
- {curr,bytes},",[]),",nl,
- " {binary_to_list(XTerm),XBytes}",nl,
- " end()}"]);
- _ ->
- emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(",
- {curr,bytes},",[])}"])
+ asn1ct_name:new(bytes),
+ gen_dec_choice1(Erule, TopType, ExtList, Ext),
+ emit([nl,"end"]);
+gen_dec_choice(Erule, TopType, CompList, noext) ->
+ gen_dec_choice1(Erule, TopType, CompList, noext).
+
+split_complist({Root1,Ext,Root2}) ->
+ {Root1++Root2,Ext};
+split_complist({_,_}=CompList) ->
+ CompList.
+
+gen_dec_choice1(Erule, TopType, CompList, noext=Ext) ->
+ emit_getchoice(Erule, CompList, Ext),
+ emit(["case Choice of",nl]),
+ Pre = {safe,fun(St) ->
+ {asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ fun() -> St end}
+ end},
+ gen_dec_choice2(Erule, TopType, CompList, Pre),
+ emit([nl,"end"]);
+gen_dec_choice1(Erule, TopType, CompList, {ext,_,_}=Ext) ->
+ emit_getchoice(Erule, CompList, Ext),
+ Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)),
+ emit(["begin",nl]),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ {Dst,DstBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar),
+ emit([nl,
+ "end,",nl,
+ "case Choice of",nl]),
+ Pre = {safe,fun(St) ->
+ emit(["{TmpVal,_} = "]),
+ {Dst,
+ fun() ->
+ emit([",",nl,
+ "{TmpVal,",DstBuf,"}"]),
+ St
+ end}
+ end},
+ gen_dec_choice2(Erule, TopType, CompList, Pre),
+ case CompList of
+ [] -> ok;
+ [_|_] -> emit([";",nl])
end,
- emit({nl,"end,",nl}),
- emit({nl,"{{Cname,Val},NewBytes}"}).
-
+ emit(["_ ->",nl,
+ "{{asn1_ExtAlt,",Dst,"},",DstBuf,"}",nl,
+ "end"]).
+
+emit_getchoice(Erule, CompList, Ext) ->
+ Al = is_aligned(Erule),
+ Imm = case {Ext,CompList} of
+ {noext,[_]} ->
+ {value,0};
+ {noext,_} ->
+ asn1ct_imm:per_dec_constrained(0, length(CompList)-1, Al);
+ {{ext,_,_},_} ->
+ asn1ct_imm:per_dec_normally_small_number(Al)
+ end,
+ emit(["{Choice,",{curr,bytes},"} = ",nl]),
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:prev(bytes)),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar),
+ emit([com,nl]).
gen_dec_choice2(Erule,TopType,L,Ext) ->
- gen_dec_choice2(Erule,TopType,L,0,Ext).
+ gen_dec_choice2(Erule, TopType, L, 0, [], Ext).
-gen_dec_choice2(Erule,TopType,[H1,H2|T],Pos,Ext)
-when is_record(H1,'ComponentType'), is_record(H2,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
+gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) ->
+ #'ComponentType'{name=Cname,typespec=Type} = H0,
+ H = H0#'ComponentType'{prop=mandatory},
+ emit([Sep0,Pos," ->",nl]),
case Type#type.def of
#'ObjectClassFieldType'{type={typefield,_}} ->
- emit({Pos," -> ",nl}),
- wrap_gen_dec_line(Erule,H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit({";",nl});
- _ ->
- emit({Pos," -> {",{asis,Cname},",",nl}),
- wrap_gen_dec_line(Erule,H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit({"};",nl})
- end,
- gen_dec_choice2(Erule,TopType,[H2|T],Pos+1,Ext);
-gen_dec_choice2(Erule,TopType,[H1,_H2|T],Pos,Ext) when is_record(H1,'ComponentType') ->
- gen_dec_choice2(Erule,TopType,[H1|T],Pos,Ext); % skip extensionmark
-gen_dec_choice2(Erule,TopType,[H1|T],Pos,Ext) when is_record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- case Type#type.def of
- #'ObjectClassFieldType'{type={typefield,_}} ->
- emit({Pos," -> ",nl}),
- wrap_gen_dec_line(Erule,H1,TopType,Cname,Type,Pos+1,false,Ext);
+ emit("{Cname,{Val,NewBytes}} = begin\n"),
+ gen_dec_choice_line(Erule, TopType, H, Pre),
+ emit([nl,
+ "end,",nl,
+ "{{Cname,Val},NewBytes}"]);
_ ->
- emit({Pos," -> {",{asis,Cname},",",nl}),
- wrap_gen_dec_line(Erule,H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit("}")
+ emit("{Val,NewBytes} = begin\n"),
+ gen_dec_choice_line(Erule, TopType, H, Pre),
+ emit([nl,
+ "end,",nl,
+ "{{",{asis,Cname},",Val},NewBytes}"])
end,
- gen_dec_choice2(Erule,TopType,[T],Pos+1);
-gen_dec_choice2(Erule,TopType,[_|T],Pos,Ext) ->
- gen_dec_choice2(Erule,TopType,T,Pos,Ext);% skip extensionmark
-gen_dec_choice2(_,_,[],Pos,_) ->
- Pos.
+ Sep = [";",nl],
+ gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre);
+gen_dec_choice2(_, _, [], _, _, _) -> ok.
indent(N) ->
lists:duplicate(N,32). % 32 = space
-gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
-% put(component_type,true), % add more info in component_type
- CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
-% erase(component_type).
-
make_elements(I,Val,ExtCnames) ->
make_elements(I,Val,ExtCnames,[]).
-make_elements(I,Val,[ExtCname],Acc)-> % the last one, no comma needed
- Element = make_element(I,Val,ExtCname),
+make_elements(I,Val,[_ExtCname],Acc)-> % the last one, no comma needed
+ Element = make_element(I, Val),
make_elements(I+1,Val,[],[Element|Acc]);
-make_elements(I,Val,[ExtCname|Rest],Acc)->
- Element = make_element(I,Val,ExtCname),
+make_elements(I,Val,[_ExtCname|Rest],Acc)->
+ Element = make_element(I, Val),
make_elements(I+1,Val,Rest,[", ",Element|Acc]);
make_elements(_I,_,[],Acc) ->
lists:reverse(Acc).
-make_element(I,Val,Cname) ->
- case tuple_notation_allowed() of
- true ->
- io_lib:format("?RT_PER:cindex(~w,~s,~w)",[I,Val,Cname]);
- _ ->
- io_lib:format("element(~w,~s)",[I,Val])
- end.
+make_element(I, Val) ->
+ io_lib:format("element(~w,~s)", [I,Val]).
emit_extaddgroupTerms(VarSeries,[_]) ->
asn1ct_name:new(VarSeries),
@@ -1653,24 +1777,6 @@ wrap_extensionAdditionGroups([H|T],ExtAddGrpLenPos,Acc,ExtAddGroupDiff,ExtGroupN
wrap_extensionAdditionGroups([],_,Acc,_,_) ->
lists:reverse(Acc).
-
-tuple_notation_allowed() ->
- Options = get(encoding_options),
- not (lists:member(optimize,Options) orelse lists:member(uper_bin,Options)).
-
-wrap_gen_dec_line(Erule,C,TopType,Cname,Type,Pos,DIO,Ext) ->
- put(component_type,{true,C}),
- gen_dec_line(Erule,TopType,Cname,Type,Pos,DIO,Ext,mandatory),
- erase(component_type).
-
-get_components_prop() ->
- case get(component_type) of
- undefined ->
- mandatory;
- {true,#'ComponentType'{prop=Prop}} -> Prop
- end.
-
-
value_match(Index,Value) when is_atom(Value) ->
value_match(Index,atom_to_list(Value));
value_match([],Value) ->
@@ -1682,11 +1788,5 @@ value_match1(Value,[],Acc,Depth) ->
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
-notice_value_match() ->
- Module = get(currmod),
- put(value_match,{true,Module}).
-
-is_optimized(per_bin) ->
- lists:member(optimize,get(encoding_options));
-is_optimized(_Erule) ->
- false.
+is_optimized(per) -> true;
+is_optimized(uper) -> false.
diff --git a/lib/asn1/src/asn1ct_eval_ext.funcs b/lib/asn1/src/asn1ct_eval_ext.funcs
new file mode 100644
index 0000000000..5761901f89
--- /dev/null
+++ b/lib/asn1/src/asn1ct_eval_ext.funcs
@@ -0,0 +1 @@
+{ext,transform_to_EXTERNAL1994,1}.
diff --git a/lib/asn1/src/asn1ct_eval_per.funcs b/lib/asn1/src/asn1ct_eval_per.funcs
new file mode 100644
index 0000000000..a1ea5cd043
--- /dev/null
+++ b/lib/asn1/src/asn1ct_eval_per.funcs
@@ -0,0 +1,2 @@
+{per,encode_constrained_number,2}.
+{per,encode_small_number,1}.
diff --git a/lib/asn1/src/asn1ct_eval_uper.funcs b/lib/asn1/src/asn1ct_eval_uper.funcs
new file mode 100644
index 0000000000..884a486f40
--- /dev/null
+++ b/lib/asn1/src/asn1ct_eval_uper.funcs
@@ -0,0 +1,2 @@
+{uper,encode_constrained_number,2}.
+{uper,encode_small_number,1}.
diff --git a/lib/asn1/src/asn1ct_func.erl b/lib/asn1/src/asn1ct_func.erl
new file mode 100644
index 0000000000..ab0dbcce8f
--- /dev/null
+++ b/lib/asn1/src/asn1ct_func.erl
@@ -0,0 +1,100 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+%%
+
+-module(asn1ct_func).
+-export([start_link/0,need/1,call/3,generate/1]).
+-export([init/1,handle_call/3,handle_cast/2,terminate/2]).
+
+start_link() ->
+ {ok,Pid} = gen_server:start_link(?MODULE, [], []),
+ put(?MODULE, Pid),
+ ok.
+
+call(M, F, Args) ->
+ MFA = {M,F,length(Args)},
+ need(MFA),
+ asn1ct_gen:emit([F,"(",call_args(Args, ""),")"]).
+
+need(MFA) ->
+ asn1ct_rtt:assert_defined(MFA),
+ cast({need,MFA}).
+
+generate(Fd) ->
+ Used0 = req(get_used),
+ erase(?MODULE),
+ Used = sofs:set(Used0, [mfa]),
+ Code = sofs:relation(asn1ct_rtt:code(), [{mfa,code}]),
+ Funcs0 = sofs:image(Code, Used),
+ Funcs = sofs:to_external(Funcs0),
+ ok = file:write(Fd, Funcs).
+
+req(Req) ->
+ gen_server:call(get(?MODULE), Req, infinity).
+
+cast(Req) ->
+ gen_server:cast(get(?MODULE), Req).
+
+%%% Internal functions.
+
+-record(st, {used}).
+
+init([]) ->
+ St = #st{used=gb_sets:empty()},
+ {ok,St}.
+
+handle_cast({need,MFA}, #st{used=Used0}=St) ->
+ case gb_sets:is_member(MFA, Used0) of
+ false ->
+ Used = pull_in_deps(gb_sets:singleton(MFA), Used0),
+ {noreply,St#st{used=Used}};
+ true ->
+ {noreply,St}
+ end.
+
+handle_call(get_used, _From, #st{used=Used}=St) ->
+ {stop,normal,gb_sets:to_list(Used),St}.
+
+terminate(_, _) ->
+ ok.
+
+call_args([A|As], Sep) ->
+ [Sep,A|call_args(As, ", ")];
+call_args([], _) -> [].
+
+pull_in_deps(Ws0, Used0) ->
+ case gb_sets:is_empty(Ws0) of
+ true ->
+ Used0;
+ false ->
+ {MFA,Ws1} = gb_sets:take_smallest(Ws0),
+ Used = gb_sets:add(MFA, Used0),
+ Needs = asn1ct_rtt:dependencies(MFA),
+ Ws = update_worklist(Needs, Used, Ws1),
+ pull_in_deps(Ws, Used)
+ end.
+
+update_worklist([H|T], Used, Ws) ->
+ case gb_sets:is_member(H, Used) of
+ false ->
+ update_worklist(T, Used, gb_sets:add(H, Ws));
+ true ->
+ update_worklist(T, Used, Ws)
+ end;
+update_worklist([], _, Ws) -> Ws.
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 64a3555f62..9095e145a3 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -21,15 +21,9 @@
-include("asn1_records.hrl").
--export([pgen_exports/3,
- pgen_hrl/5,
- gen_head/3,
- demit/1,
+-export([demit/1,
emit/1,
get_inner/1,type/1,def_to_tag/1,prim_bif/1,
- type_from_object/1,
- get_typefromobject/1,get_fieldcategory/2,
- get_classfieldcategory/2,
list2name/1,
list2rname/1,
constructed_suffix/2,
@@ -37,22 +31,19 @@
gen_check_call/7,
get_constraint/2,
insert_once/2,
- rt2ct_suffix/1,
- rt2ct_suffix/0,
+ ct_gen_module/1,
index2suffix/1,
get_record_name_prefix/0]).
-export([pgen/5,
- pgen_module/6,
mk_var/1,
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
gen_decode_constructed/4]).
--export([nif_parameter/0]).
%% pgen(Outfile, Erules, Module, TypeOrVal, Options)
%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
%% .hrl file is only generated if necessary
-%% Erules = per | ber | ber_bin | per_bin
+%% Erules = per | ber
%% Module = atom()
%% TypeOrVal = {TypeList,ValueList}
%% TypeList = ValueList = [atom()]
@@ -77,23 +68,28 @@ pgen_module(OutFile,Erules,Module,
HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent),
asn1ct_name:start(),
ErlFile = lists:concat([OutFile,".erl"]),
- Fid = fopen(ErlFile,[write]),
+ Fid = fopen(ErlFile),
put(gen_file_out,Fid),
+ asn1ct_func:start_link(),
gen_head(Erules,Module,HrlGenerated),
pgen_exports(Erules,Module,TypeOrVal),
pgen_dispatcher(Erules,Module,TypeOrVal),
pgen_info(),
- pgen_typeorval(wrap_ber(Erules),Module,N2nConvEnums,TypeOrVal),
+ pgen_typeorval(Erules,Module,N2nConvEnums,TypeOrVal),
pgen_partial_incomplete_decode(Erules),
% gen_vars(asn1_db:mod_to_vars(Module)),
% gen_tag_table(AllTypes),
+ emit([nl,
+ "%%%",nl,
+ "%%% Run-time functions.",nl,
+ "%%%",nl]),
+ asn1ct_func:generate(Fid),
file:close(Fid),
asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options).
pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Rtmod = ct_gen_module(Erules),
pgen_types(Rtmod,Erules,N2nConvEnums,Module,Types),
pgen_values(Erules,Module,Values),
pgen_objects(Rtmod,Erules,Module,Objects),
@@ -112,8 +108,7 @@ pgen_values(Erules,Module,[H|T]) ->
gen_value(Valuedef),
pgen_values(Erules,Module,T).
-pgen_types(_,_,_,Module,[]) ->
- gen_value_match(Module),
+pgen_types(_, _, _, _, []) ->
true;
pgen_types(Rtmod,Erules,N2nConvEnums,Module,[H|T]) ->
asn1ct_name:clear(),
@@ -196,7 +191,7 @@ pgen_check_defaultval(Erules,Module) ->
end,
gen_check_defaultval(Erules,Module,CheckObjects).
-pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber_bin_v2 ->
+pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber ->
pgen_partial_inc_dec(Rtmod,Erule,Module),
pgen_partial_dec(Rtmod,Erule,Module);
pgen_partial_decode(_,_,_) ->
@@ -240,7 +235,7 @@ pgen_partial_inc_dec1(Rtmod,Erules,Module,[P|Ps]) ->
pgen_partial_inc_dec1(_,_,_,[]) ->
ok.
-gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber_bin_v2 ->
+gen_partial_inc_dec_refed_funcs(Rtmod,Erule) when Erule == ber ->
case asn1ct:next_refed_func() of
[] ->
ok;
@@ -296,8 +291,7 @@ pgen_partial_types1(_,undefined) ->
%% TypeList a decode function will be generated.
traverse_type_structure(Erules,Type,[],FuncName,TopTypeName) ->
%% this is the selected type
- Ctmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Ctmod = ct_gen_module(Erules),
TypeDef =
case Type of
#type{} ->
@@ -457,7 +451,7 @@ pgen_partial_incomplete_decode(Erule) ->
_ ->
ok
end.
-pgen_partial_incomplete_decode1(ber_bin_v2) ->
+pgen_partial_incomplete_decode1(ber) ->
case asn1ct:read_config_data(partial_incomplete_decode) of
undefined ->
ok;
@@ -531,7 +525,8 @@ gen_part_decode_funcs({constructed,bif},TypeName,
{_Name,parts,Tag,_Type}) ->
emit([" case Data of",nl,
" L when is_list(L) ->",nl,
- " 'dec_",TypeName,"'(lists:map(fun(X)->element(1,?RT_BER:decode(X)) end,L),",{asis,Tag},");",nl,
+ " 'dec_",TypeName,"'(lists:map(fun(X) -> element(1, ",
+ {call,ber,ber_decode_erlang,["X"]},") end, L),",{asis,Tag},");",nl,
" _ ->",nl,
" [Res] = 'dec_",TypeName,"'([Data],",{asis,Tag},"),",nl,
" Res",nl,
@@ -552,20 +547,17 @@ gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) ->
gen_types(Erules,Tname,{RootL1,ExtList,RootL2})
when is_list(RootL1), is_list(RootL2) ->
gen_types(Erules,Tname,RootL1),
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Rtmod = ct_gen_module(Erules),
gen_types(Erules,Tname,Rtmod:extaddgroup2sequence(ExtList)),
gen_types(Erules,Tname,RootL2);
gen_types(Erules,Tname,{RootList,ExtList}) when is_list(RootList) ->
gen_types(Erules,Tname,RootList),
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Rtmod = ct_gen_module(Erules),
gen_types(Erules,Tname,Rtmod:extaddgroup2sequence(ExtList));
gen_types(Erules,Tname,[{'EXTENSIONMARK',_,_}|Rest]) ->
gen_types(Erules,Tname,Rest);
gen_types(Erules,Tname,[ComponentType|Rest]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Rtmod = ct_gen_module(Erules),
asn1ct_name:clear(),
Rtmod:gen_encode(Erules,Tname,ComponentType),
asn1ct_name:clear(),
@@ -574,29 +566,12 @@ gen_types(Erules,Tname,[ComponentType|Rest]) ->
gen_types(_,_,[]) ->
true;
gen_types(Erules,Tname,Type) when is_record(Type,type) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
+ Rtmod = ct_gen_module(Erules),
asn1ct_name:clear(),
Rtmod:gen_encode(Erules,Tname,Type),
asn1ct_name:clear(),
Rtmod:gen_decode(Erules,Tname,Type).
-gen_value_match(Module) ->
- case get(value_match) of
- {true,Module} ->
- emit(["value_match([{Index,Cname}|Rest],Value) ->",nl,
- " Value2 =",nl,
- " case element(Index,Value) of",nl,
- " {Cname,Val2} -> Val2;",nl,
- " X -> X",nl,
- " end,",nl,
- " value_match(Rest,Value2);",nl,
- "value_match([],Value) ->",nl,
- " Value.",nl]);
- _ -> ok
- end,
- put(value_match,undefined).
-
gen_check_defaultval(Erules,Module,[{Name,Type}|Rest]) ->
gen_check_func(Name,Type),
gen_check_defaultval(Erules,Module,Rest);
@@ -658,9 +633,13 @@ gen_check_sof(Name,SOF,Type) ->
end,
emit({" ",{asis,NewName},"(DVs,Vs).",nl,nl}).
+gen_check_sequence(Name, []) ->
+ emit([{asis,ensure_atom(Name)},"(_,_) ->",nl,
+ " throw(badval).",nl,nl]);
gen_check_sequence(Name,Components) ->
emit([{asis,ensure_atom(Name)},"(DefaultValue,Value) ->",nl]),
gen_check_sequence(Name,Components,1).
+
gen_check_sequence(Name,[#'ComponentType'{name=N,typespec=Type}|Cs],Num) ->
InnerType = get_inner(Type#type.def),
NthDefV = ["element(",Num+1,",DefaultValue)"],
@@ -672,9 +651,7 @@ gen_check_sequence(Name,[#'ComponentType'{name=N,typespec=Type}|Cs],Num) ->
_ ->
emit({",",nl}),
gen_check_sequence(Name,Cs,Num+1)
- end;
-gen_check_sequence(_,[],_) ->
- ok.
+ end.
gen_check_choice(Name,CList=[#'ComponentType'{}|_Cs]) ->
emit([{asis,ensure_atom(Name)},"({Id,DefaultValue},{Id,Value}) ->",nl]),
@@ -754,8 +731,7 @@ gen_value(Value) when is_record(Value,valuedef) ->
emit([{asis,V},".",nl,nl]).
gen_encode_constructed(Erules,Typename,InnerType,D) when is_record(D,type) ->
-
- Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
+ Rtmod = ct_constructed_module(Erules),
case InnerType of
'SET' ->
Rtmod:gen_encode_set(Erules,Typename,D),
@@ -787,7 +763,7 @@ gen_encode_constructed(Erules,Typename,InnerType,D)
gen_encode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,type) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
+ Rtmod = ct_constructed_module(Erules),
asn1ct:step_in_constructed(), %% updates namelist for exclusive decode
case InnerType of
'SET' ->
@@ -810,7 +786,7 @@ gen_decode_constructed(Erules,Typename,InnerType,D) when is_record(D,typedef) ->
pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
- emit({"-export([encoding_rule/0]).",nl}),
+ emit(["-export([encoding_rule/0,bit_string_format/0]).",nl]),
case Types of
[] -> ok;
_ ->
@@ -818,27 +794,11 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
case Erules of
ber ->
gen_exports1(Types,"enc_",2);
- ber_bin ->
- gen_exports1(Types,"enc_",2);
- ber_bin_v2 ->
- gen_exports1(Types,"enc_",2);
_ ->
gen_exports1(Types,"enc_",1)
end,
emit({"-export([",nl}),
- gen_exports1(Types,"dec_",2),
- case Erules of
- ber ->
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",3);
- ber_bin ->
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",3);
-% ber_bin_v2 ->
-% emit({"-export([",nl}),
-% gen_exports1(Types,"dec_",2);
- _ -> ok
- end
+ gen_exports1(Types,"dec_",2)
end,
case [X || {n2n,X} <- get(encoding_options)] of
[] -> ok;
@@ -863,16 +823,11 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
gen_exports1(Objects,"enc_",3),
emit({"-export([",nl}),
gen_exports1(Objects,"dec_",4);
- ber_bin_v2 ->
+ ber ->
emit({"-export([",nl}),
gen_exports1(Objects,"enc_",3),
emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",3);
- _ ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",4),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",4)
+ gen_exports1(Objects,"dec_",3)
end
end,
case ObjectSets of
@@ -941,27 +896,25 @@ gen_selected_decode_exports1([{FuncName,_}|Rest]) ->
gen_selected_decode_exports1(Rest).
pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
- emit(["encoding_rule() ->",nl]),
- emit([{asis,Erules},".",nl,nl]);
+ gen_info_functions(Erules);
pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
- emit(["-export([encode/2,decode/2,encode_disp/2,decode_disp/2]).",nl,nl]),
- emit(["encoding_rule() ->",nl]),
- emit([" ",{asis,Erules},".",nl,nl]),
+ emit(["-export([encode/2,decode/2]).",nl,nl]),
+ gen_info_functions(Erules),
NoFinalPadding = lists:member(no_final_padding,get(encoding_options)),
- Call = case Erules of
- per -> "?RT_PER:complete(encode_disp(Type,Data))";
- per_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"];
- ber -> "encode_disp(Type,Data)";
- ber_bin -> "encode_disp(Type,Data)";
- ber_bin_v2 -> "encode_disp(Type,Data)";
- uper_bin when NoFinalPadding == true ->
- "?RT_PER:complete_NFP(encode_disp(Type,Data))";
- uper_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"]
- end,
- EncWrap = case Erules of
- ber -> "wrap_encode(Bytes)";
- _ -> "Bytes"
- end,
+ {Call,BytesAsBinary} =
+ case Erules of
+ per ->
+ asn1ct_func:need({Erules,complete,1}),
+ {["complete(encode_disp(Type, Data))"],"Bytes"};
+ ber ->
+ {"encode_disp(Type,Data)","iolist_to_binary(Bytes)"};
+ uper when NoFinalPadding == true ->
+ asn1ct_func:need({Erules,complete_NFP,1}),
+ {"complete_NFP(encode_disp(Type, Data))","Bytes"};
+ uper ->
+ asn1ct_func:need({Erules,complete,1}),
+ {["complete(encode_disp(Type, Data))"],"Bytes"}
+ end,
emit(["encode(Type,Data) ->",nl,
"case catch ",Call," of",nl,
" {'EXIT',{error,Reason}} ->",nl,
@@ -969,53 +922,33 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
" {'EXIT',Reason} ->",nl,
" {error,{asn1,Reason}};",nl,
" {Bytes,_Len} ->",nl,
- " {ok,",EncWrap,"};",nl]),
- case Erules of
- per ->
- emit([" Bytes when is_binary(Bytes) ->",nl,
- " {ok,binary_to_list(Bytes)};",nl,
- " Bytes ->",nl,
- " {ok,binary_to_list(list_to_binary(Bytes))}",nl,
- " end.",nl,nl]);
- _ ->
- emit([" Bytes ->",nl,
- " {ok,",EncWrap,"}",nl,
- "end.",nl,nl])
- end,
-
-% case Erules of
-% ber_bin_v2 ->
-% emit(["decode(Type,Data0) ->",nl]),
-% emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",nif_parameter(),"),",nl]);
-% _ ->
-% emit(["decode(Type,Data) ->",nl])
-% end,
+ " {ok,",BytesAsBinary,"};",nl,
+ " Bytes ->",nl,
+ " {ok,",BytesAsBinary,"}",nl,
+ "end.",nl,nl]),
Return_rest = lists:member(undec_rest,get(encoding_options)),
Data = case {Erules,Return_rest} of
- {ber_bin_v2,true} -> "Data0";
+ {ber,true} -> "Data0";
_ -> "Data"
end,
emit(["decode(Type,",Data,") ->",nl]),
DecAnonymous =
case {Erules,Return_rest} of
- {ber_bin_v2,false} ->
- io_lib:format("~s~s~s~n",
- ["element(1,?RT_BER:decode(Data",
- nif_parameter(),"))"]);
- {ber_bin_v2,true} ->
- emit(["{Data,Rest} = ?RT_BER:decode(Data0",
- nif_parameter(),"),",nl]),
+ {ber,false} ->
+ asn1ct_func:need({ber,ber_decode_nif,1}),
+ "element(1, ber_decode_nif(Data))";
+ {ber,true} ->
+ asn1ct_func:need({ber,ber_decode_nif,1}),
+ emit(["{Data,Rest} = ber_decode_nif(Data0),",nl]),
"Data";
_ ->
"Data"
end,
DecWrap = case Erules of
- ber -> "wrap_decode(Data)";
- ber_bin_v2 ->
+ ber ->
DecAnonymous;
- per -> "list_to_binary(Data)";
_ -> "Data"
end,
@@ -1025,32 +958,18 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
" {'EXIT',Reason} ->",nl,
" {error,{asn1,Reason}};",nl]),
case {Erules,Return_rest} of
- {ber_bin_v2,false} ->
+ {ber,false} ->
emit([" Result ->",nl,
" {ok,Result}",nl]);
- {ber_bin_v2,true} ->
+ {ber,true} ->
emit([" Result ->",nl,
" {ok,Result,Rest}",nl]);
- {per,false} ->
- emit([" {X,_Rest} ->",nl,
- " {ok,if_binary2list(X)};",nl,
- " {X,_Rest,_Len} ->",nl,
- " {ok,if_binary2list(X)}",nl]);
{_,false} ->
emit([" {X,_Rest} ->",nl,
" {ok,X};",nl,
" {X,_Rest,_Len} ->",nl,
" {ok,X}",nl]);
- {per,true} ->
- emit([" {X,{_,Rest}} ->",nl,
- " {ok,if_binary2list(X),Rest};",nl,
- " {X,{_,Rest},_Len} ->",nl,
- " {ok,if_binary2list(X),Rest};",nl,
- " {X,Rest} ->",nl,
- " {ok,if_binary2list(X),Rest};",nl,
- " {X,Rest,_Len} ->",nl,
- " {ok,if_binary2list(X),Rest}",nl]);
- {per_bin,true} ->
+ {per,true} ->
emit([" {X,{_,Rest}} ->",nl,
" {ok,X,Rest};",nl,
" {X,{_,Rest},_Len} ->",nl,
@@ -1059,7 +978,7 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
" {ok,X,Rest};",nl,
" {X,Rest,_Len} ->",nl,
" {ok,X,Rest}",nl]);
- {uper_bin,true} ->
+ {uper,true} ->
emit([" {X,{_,Rest}} ->",nl,
" {ok,X,Rest};",nl,
" {X,{_,Rest},_Len} ->",nl,
@@ -1067,34 +986,14 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
" {X,Rest} ->",nl,
" {ok,X,Rest};",nl,
" {X,Rest,_Len} ->",nl,
- " {ok,X,Rest}",nl]);
- _ ->
- emit([" {X,Rest} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,Rest,_Len} ->",nl,
" {ok,X,Rest}",nl])
end,
emit(["end.",nl,nl]),
- case Erules of
- per ->
- emit(["if_binary2list(B) when is_binary(B) ->",nl,
- " binary_to_list(B);",nl,
- "if_binary2list(L) -> L.",nl,nl]);
- _ ->
- ok
- end,
-
gen_decode_partial_incomplete(Erules),
case Erules of
ber ->
- gen_dispatcher(Types,"encode_disp","enc_",",[]"),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
- ber_bin ->
- gen_dispatcher(Types,"encode_disp","enc_",",[]"),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
- ber_bin_v2 ->
gen_dispatcher(Types,"encode_disp","enc_",""),
gen_dispatcher(Types,"decode_disp","dec_",""),
gen_partial_inc_dispatcher();
@@ -1103,17 +1002,15 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
gen_dispatcher(Types,"decode_disp","dec_",",mandatory")
end,
emit([nl]),
-
- case Erules of
- ber ->
- gen_wrapper();
- _ -> ok
- end,
emit({nl,nl}).
+gen_info_functions(Erules) ->
+ emit(["encoding_rule() -> ",
+ {asis,Erules},".",nl,nl,
+ "bit_string_format() -> ",
+ {asis,asn1ct:get_bit_string_format()},".",nl,nl]).
-gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
- Erule==ber_bin_v2 ->
+gen_decode_partial_incomplete(ber) ->
case {asn1ct:read_config_data(partial_incomplete_decode),
asn1ct:get_gen_state_field(inc_type_pattern)} of
{undefined,_} ->
@@ -1121,34 +1018,35 @@ gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
{_,undefined} ->
ok;
_ ->
- case Erule of
- ber_bin_v2 ->
- EmitCaseClauses =
- fun() ->
- emit([" {'EXIT',{error,Reason}} ->",nl,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl,
- " Result ->",nl,
- " {ok,Result}",nl,
- " end.",nl,nl])
- end,
- emit(["decode_partial_incomplete(Type,Data0,",
- "Pattern) ->",nl]),
- emit([" {Data,_RestBin} =",nl,
- " ?RT_BER:decode_primitive_",
- "incomplete(Pattern,Data0),",nl,
- " case catch decode_partial_inc_disp(Type,",
- "Data) of",nl]),
- EmitCaseClauses(),
- emit(["decode_part(Type,Data0) ->",nl]),
- emit([" case catch decode_inc_disp(Type,element(1,"
- "?RT_BER:decode(Data0",nif_parameter(),"))) of",nl]),
-% " {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,
-% " case catch decode_inc_disp(Type,Data) of",nl]),
- EmitCaseClauses();
- _ -> ok % add later
- end
+ EmitCaseClauses =
+ fun() ->
+ emit([" {'EXIT',{error,Reason}} ->",nl,
+ " {error,Reason};",nl,
+ " {'EXIT',Reason} ->",nl,
+ " {error,{asn1,Reason}};",nl,
+ " Result ->",nl,
+ " {ok,Result}",nl,
+ " end"])
+ end,
+ emit(["decode_partial_incomplete(Type,Data0,",
+ "Pattern) ->",nl]),
+ emit([" {Data,_RestBin} =",nl,
+ " ",{call,ber,decode_primitive_incomplete,
+ ["Pattern","Data0"]},com,nl,
+ " case catch decode_partial_inc_disp(Type,",
+ "Data) of",nl]),
+ EmitCaseClauses(),
+ emit([".",nl,nl]),
+ emit(["decode_part(Type, Data0) "
+ "when is_binary(Data0) ->",nl]),
+ emit([" case catch decode_inc_disp(Type,element(1, ",
+ {call,ber,ber_decode_nif,["Data0"]},")) of",nl]),
+ EmitCaseClauses(),
+ emit([";",nl]),
+ emit(["decode_part(Type, Data0) ->",nl]),
+ emit([" case catch decode_inc_disp(Type, Data0) of",nl]),
+ EmitCaseClauses(),
+ emit([".",nl,nl])
end;
gen_decode_partial_incomplete(_Erule) ->
ok.
@@ -1186,24 +1084,6 @@ gen_partial_inc_dispatcher([],_) ->
emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
" exit({error,{asn1,{undefined_type,Type}}}).",nl]).
-nif_parameter() ->
- Options = get(encoding_options),
- case {lists:member(driver,Options),lists:member(nif,Options)} of
- {true,_} -> ",nif";
- {_,true} -> ",nif";
- _ -> ""
- end.
-
-gen_wrapper() ->
- emit(["wrap_encode(Bytes) when is_list(Bytes) ->",nl,
- " binary_to_list(list_to_binary(Bytes));",nl,
- "wrap_encode(Bytes) when is_binary(Bytes) ->",nl,
- " binary_to_list(Bytes);",nl,
- "wrap_encode(Bytes) -> Bytes.",nl,nl]),
- emit(["wrap_decode(Bytes) when is_list(Bytes) ->",nl,
- " list_to_binary(Bytes);",nl,
- "wrap_decode(Bytes) -> Bytes.",nl]).
-
gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) ->
emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]),
gen_dispatcher([F2|T],FuncName,Prefix,ExtraArg);
@@ -1213,24 +1093,21 @@ gen_dispatcher([Flast|_T],FuncName,Prefix,ExtraArg) ->
pgen_info() ->
emit(["info() ->",nl,
- " case ?MODULE:module_info() of",nl,
- " MI when is_list(MI) ->",nl,
- " case lists:keysearch(attributes,1,MI) of",nl,
- " {value,{_,Attributes}} when is_list(Attributes) ->",nl,
- " case lists:keysearch(asn1_info,1,Attributes) of",nl,
- " {value,{_,Info}} when is_list(Info) ->",nl,
- " Info;",nl,
- " _ ->",nl,
- " []",nl,
- " end;",nl,
- " _ ->",nl,
- " []",nl,
- " end",nl,
+ " case ?MODULE:module_info(attributes) of",nl,
+ " Attributes when is_list(Attributes) ->",nl,
+ " case lists:keyfind(asn1_info, 1, Attributes) of",nl,
+ " {_,Info} when is_list(Info) ->",nl,
+ " Info;",nl,
+ " _ ->",nl,
+ " []",nl,
+ " end;",nl,
+ " _ ->",nl,
+ " []",nl,
" end.",nl]).
open_hrl(OutFile,Module) ->
File = lists:concat([OutFile,".hrl"]),
- Fid = fopen(File,[write]),
+ Fid = fopen(File),
put(gen_file_out,Fid),
gen_hrlhead(Module).
@@ -1245,77 +1122,67 @@ demit(Term) ->
end.
% always generation
+emit(Term) ->
+ ok = file:write(get(gen_file_out), do_emit(Term)).
-emit({external,_M,T}) ->
- emit(T);
+do_emit({external,_M,T}) ->
+ do_emit(T);
-emit({prev,Variable}) when is_atom(Variable) ->
- emit({var,asn1ct_name:prev(Variable)});
+do_emit({prev,Variable}) when is_atom(Variable) ->
+ do_emit({var,asn1ct_name:prev(Variable)});
-emit({next,Variable}) when is_atom(Variable) ->
- emit({var,asn1ct_name:next(Variable)});
+do_emit({next,Variable}) when is_atom(Variable) ->
+ do_emit({var,asn1ct_name:next(Variable)});
-emit({curr,Variable}) when is_atom(Variable) ->
- emit({var,asn1ct_name:curr(Variable)});
+do_emit({curr,Variable}) when is_atom(Variable) ->
+ do_emit({var,asn1ct_name:curr(Variable)});
-emit({var,Variable}) when is_atom(Variable) ->
+do_emit({var,Variable}) when is_atom(Variable) ->
[Head|V] = atom_to_list(Variable),
- emit([Head-32|V]);
+ [Head-32|V];
-emit({var,Variable}) ->
+do_emit({var,Variable}) ->
[Head|V] = Variable,
- emit([Head-32|V]);
-
-emit({asis,What}) ->
- format(get(gen_file_out),"~w",[What]);
-
-emit(nl) ->
- nl(get(gen_file_out));
+ [Head-32|V];
-emit(com) ->
- emit(",");
+do_emit({asis,What}) ->
+ io_lib:format("~w", [What]);
-emit(tab) ->
- put_chars(get(gen_file_out)," ");
+do_emit({call,M,F,A}) ->
+ MFA = {M,F,length(A)},
+ asn1ct_func:need(MFA),
+ [atom_to_list(F),"(",call_args(A, "")|")"];
-emit(What) when is_integer(What) ->
- put_chars(get(gen_file_out),integer_to_list(What));
+do_emit(nl) ->
+ "\n";
-emit(What) when is_list(What), is_integer(hd(What)) ->
- put_chars(get(gen_file_out),What);
+do_emit(com) ->
+ ",";
-emit(What) when is_atom(What) ->
- put_chars(get(gen_file_out),atom_to_list(What));
+do_emit(tab) ->
+ " ";
-emit(What) when is_tuple(What) ->
- emit_parts(tuple_to_list(What));
+do_emit(What) when is_integer(What) ->
+ integer_to_list(What);
-emit(What) when is_list(What) ->
- emit_parts(What);
+do_emit(What) when is_list(What), is_integer(hd(What)) ->
+ What;
-emit(X) ->
- exit({'cant emit ',X}).
+do_emit(What) when is_atom(What) ->
+ atom_to_list(What);
-emit_parts([]) -> true;
-emit_parts([H|T]) ->
- emit(H),
- emit_parts(T).
+do_emit(What) when is_tuple(What) ->
+ [do_emit(E) || E <- tuple_to_list(What)];
-format(undefined,X,Y) ->
- io:format(X,Y);
-format(X,Y,Z) ->
- io:format(X,Y,Z).
+do_emit(What) when is_list(What) ->
+ [do_emit(E) || E <- What].
-nl(undefined) -> io:nl();
-nl(X) -> io:nl(X).
+call_args([A|As], Sep) ->
+ [Sep,do_emit(A)|call_args(As, ", ")];
+call_args([], _) -> [].
-put_chars(undefined,X) ->
- io:put_chars(X);
-put_chars(Y,X) ->
- io:put_chars(Y,X).
-
-fopen(F, ModeList) ->
- case file:open(F, ModeList) of
+fopen(F) ->
+ case file:open(F, [write,raw,delayed_write]) of
{ok, Fd} ->
Fd;
{error, Reason} ->
@@ -1493,55 +1360,31 @@ gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now.
gen_head(Erules,Mod,Hrl) ->
Options = get(encoding_options),
- {Rtmac,Rtmod} = case Erules of
- per ->
- emit({"%% Generated by the Erlang ASN.1 PER-"
- "compiler version:",asn1ct:vsn(),nl}),
- {"RT_PER",?RT_PER_BIN};
- ber ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version:",asn1ct:vsn(),nl}),
- {"RT_BER",?RT_BER_BIN};
- per_bin ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- %% temporary code to enable rt2ct optimization
- case lists:member(optimize,Options) of
- true -> {"RT_PER","asn1rt_per_bin_rt2ct"};
- _ -> {"RT_PER",?RT_PER_BIN}
- end;
- ber_bin ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- {"RT_BER",?RT_BER_BIN};
- ber_bin_v2 ->
- emit({"%% Generated by the Erlang ASN.1 BER_V2-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- {"RT_BER","asn1rt_ber_bin_v2"};
- uper_bin ->
- emit(["%% Generated by the Erlang ASN.1 UNALIGNED"
- " PER-compiler version, utilizing"
- " bit-syntax:",
- asn1ct:vsn(),nl]),
- {"RT_PER","asn1rt_uper_bin"}
+ case Erules of
+ per ->
+ emit(["%% Generated by the Erlang ASN.1 PER-"
+ "compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl]);
+ ber ->
+ emit(["%% Generated by the Erlang ASN.1 BER_V2-"
+ "compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl]);
+ uper ->
+ emit(["%% Generated by the Erlang ASN.1 UNALIGNED"
+ " PER-compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl])
end,
emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}),
emit({"-module('",Mod,"').",nl}),
put(currmod,Mod),
- %emit({"-compile(export_all).",nl}),
- case {Hrl,lists:member(inline,get(encoding_options))} of
- {0,_} -> true;
- {_,true} -> true;
- _ ->
- emit({"-include(\"",Mod,".hrl\").",nl})
+ emit({"-compile(nowarn_unused_vars).",nl}),
+ case Hrl of
+ 0 -> ok;
+ _ -> emit({"-include(\"",Mod,".hrl\").",nl})
end,
- emit(["-define('",Rtmac,"',",Rtmod,").",nl]),
emit(["-asn1_info([{vsn,'",asn1ct:vsn(),"'},",nl,
" {module,'",Mod,"'},",nl,
- " {options,",io_lib:format("~w",[Options]),"}]).",nl,nl]).
+ " {options,",io_lib:format("~p",[Options]),"}]).",nl,nl]).
gen_hrlhead(Mod) ->
@@ -1619,50 +1462,41 @@ gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
emit(["fun() -> true end ()"])
end.
-gen_prim_check_call(PrimType,DefaultValue,Element,Type) ->
+gen_prim_check_call(PrimType, Default, Element, Type) ->
case unify_if_string(PrimType) of
'BOOLEAN' ->
- emit({"asn1rt_check:check_bool(",DefaultValue,", ",
- Element,")"});
+ check_call(check_bool, [Default,Element]);
'INTEGER' ->
- NNL =
- case Type#type.def of
- {_,NamedNumberList} -> NamedNumberList;
- _ -> []
- end,
- emit({"asn1rt_check:check_int(",DefaultValue,", ",
- Element,", ",{asis,NNL},")"});
+ NNL = case Type#type.def of
+ {_,NamedNumberList} -> NamedNumberList;
+ _ -> []
+ end,
+ check_call(check_int, [Default,Element,{asis,NNL}]);
'BIT STRING' ->
{_,NBL} = Type#type.def,
- emit({"asn1rt_check:check_bitstring(",DefaultValue,", ",
- Element,", ",{asis,NBL},")"});
+ check_call(check_bitstring, [Default,Element,{asis,NBL}]);
'OCTET STRING' ->
- emit({"asn1rt_check:check_octetstring(",DefaultValue,", ",
- Element,")"});
+ check_call(check_octetstring, [Default,Element]);
'NULL' ->
- emit({"asn1rt_check:check_null(",DefaultValue,", ",
- Element,")"});
+ check_call(check_null, [Default,Element]);
'OBJECT IDENTIFIER' ->
- emit({"asn1rt_check:check_objectidentifier(",DefaultValue,
- ", ",Element,")"});
+ check_call(check_objectidentifier, [Default,Element]);
'RELATIVE-OID' ->
- emit({"asn1rt_check:check_objectidentifier(",DefaultValue,
- ", ",Element,")"});
+ check_call(check_objectidentifier, [Default,Element]);
'ObjectDescriptor' ->
- emit({"asn1rt_check:check_objectdescriptor(",DefaultValue,
- ", ",Element,")"});
+ check_call(check_objectdescriptor, [Default,Element]);
'REAL' ->
- emit({"asn1rt_check:check_real(",DefaultValue,
- ", ",Element,")"});
+ check_call(check_real, [Default,Element]);
'ENUMERATED' ->
{_,Enumerations} = Type#type.def,
- emit({"asn1rt_check:check_enum(",DefaultValue,
- ", ",Element,", ",{asis,Enumerations},")"});
+ check_call(check_enum, [Default,Element,{asis,Enumerations}]);
restrictedstring ->
- emit({"asn1rt_check:check_restrictedstring(",DefaultValue,
- ", ",Element,")"})
+ check_call(check_restrictedstring, [Default,Element])
end.
+check_call(F, Args) ->
+ asn1ct_func:call(check, F, Args).
+
%% lokahead_innertype/3 traverses Type and checks if check functions
%% have to be generated, i.e. for all constructed or referenced types.
lookahead_innertype(Name,'SEQUENCE',Type) ->
@@ -1800,7 +1634,6 @@ unify_if_string(PrimType) ->
get_inner(A) when is_atom(A) -> A;
get_inner(Ext) when is_record(Ext,'Externaltypereference') -> Ext;
-get_inner(Tref) when is_record(Tref,typereference) -> Tref;
get_inner({fixedtypevaluefield,_,Type}) ->
if
is_record(Type,type) ->
@@ -1833,8 +1666,6 @@ get_inner(T) when is_tuple(T) ->
type(X) when is_record(X,'Externaltypereference') ->
X;
-type(X) when is_record(X,typereference) ->
- X;
type('ASN1_OPEN_TYPE') ->
'ASN1_OPEN_TYPE';
type({fixedtypevaluefield,_Name,Type}) when is_record(Type,type) ->
@@ -1842,15 +1673,6 @@ type({fixedtypevaluefield,_Name,Type}) when is_record(Type,type) ->
type({typefield,_}) ->
'ASN1_OPEN_TYPE';
type(X) ->
- %% io:format("asn1_types:type(~p)~n",[X]),
- case catch type2(X) of
- {'EXIT',_} ->
- {notype,X};
- Normal ->
- Normal
- end.
-
-type2(X) ->
case prim_bif(X) of
true ->
{primitive,bif};
@@ -1869,7 +1691,6 @@ prim_bif(X) ->
'REAL',
'OBJECT IDENTIFIER',
'RELATIVE-OID',
- 'ANY',
'NULL',
'BIT STRING' ,
'OCTET STRING' ,
@@ -1913,15 +1734,6 @@ def_to_tag(Def) ->
%% Information Object Class
-type_from_object(X) ->
- case (catch lists:last(element(2,X))) of
- {'EXIT',_} ->
- {notype,X};
- Normal ->
- Normal
- end.
-
-
get_fieldtype([],_FieldName)->
{no_type,no_name};
get_fieldtype([Field|Rest],FieldName) ->
@@ -1937,34 +1749,6 @@ get_fieldtype([Field|Rest],FieldName) ->
get_fieldtype(Rest,FieldName)
end.
-get_fieldcategory([],_FieldName) ->
- no_cat;
-get_fieldcategory([Field|Rest],FieldName) ->
- case element(2,Field) of
- FieldName ->
- element(1,Field);
- _ ->
- get_fieldcategory(Rest,FieldName)
- end.
-
-get_typefromobject(Type) when is_record(Type,type) ->
- case Type#type.def of
- {{objectclass,_,_},TypeFrObj} when is_list(TypeFrObj) ->
- {_,FieldName} = lists:last(TypeFrObj),
- FieldName;
- _ ->
- {no_field}
- end.
-
-get_classfieldcategory(Type,FieldName) ->
- case (catch Type#type.def) of
- {{obejctclass,Fields,_},_} ->
- get_fieldcategory(Fields,FieldName);
- {'EXIT',_} ->
- no_cat;
- _ ->
- no_cat
- end.
%% Information Object Class
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2019,43 +1803,29 @@ constructed_suffix('SEQUENCE OF',_) ->
constructed_suffix('SET OF',_) ->
'SETOF'.
-erule(ber) ->
- ber;
-erule(ber_bin) ->
- ber;
-erule(ber_bin_v2) ->
- ber_bin_v2;
-erule(per) ->
- per;
-erule(per_bin) ->
- per;
-erule(uper_bin) ->
- per.
-
-wrap_ber(ber) ->
- ber_bin;
-wrap_ber(Erule) ->
- Erule.
-
-rt2ct_suffix() ->
- Options = get(encoding_options),
- case {lists:member(optimize,Options),lists:member(per_bin,Options)} of
- {true,true} -> "_rt2ct";
- _ -> ""
- end.
-rt2ct_suffix(per_bin) ->
- Options = get(encoding_options),
- case lists:member(optimize,Options) of
- true -> "_rt2ct";
- _ -> ""
- end;
-rt2ct_suffix(_) -> "".
+erule(ber) -> ber;
+erule(per) -> per;
+erule(uper) -> per.
index2suffix(0) ->
"";
index2suffix(N) ->
lists:concat(["_",N]).
+ct_gen_module(ber) ->
+ asn1ct_gen_ber_bin_v2;
+ct_gen_module(per) ->
+ asn1ct_gen_per;
+ct_gen_module(uper) ->
+ asn1ct_gen_per.
+
+ct_constructed_module(ber) ->
+ asn1ct_constructed_ber_bin_v2;
+ct_constructed_module(per) ->
+ asn1ct_constructed_per;
+ct_constructed_module(uper) ->
+ asn1ct_constructed_per.
+
get_constraint(C,Key) ->
case lists:keysearch(Key,1,C) of
false ->
diff --git a/lib/asn1/src/asn1ct_gen_ber.erl b/lib/asn1/src/asn1ct_gen_ber.erl
deleted file mode 100644
index 491ebcb8fd..0000000000
--- a/lib/asn1/src/asn1ct_gen_ber.erl
+++ /dev/null
@@ -1,1749 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2010. 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%
-%%
-%%
--module(asn1ct_gen_ber).
-
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
-
--include("asn1_records.hrl").
-
--export([pgen/4]).
--export([decode_class/1, decode_type/1]).
--export([add_removed_bytes/0]).
--export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
--export([gen_encode_prim/4]).
--export([gen_dec_prim/8]).
--export([gen_objectset_code/2, gen_obj_code/3]).
--export([re_wrap_erule/1]).
--export([unused_var/2]).
--export([extaddgroup2sequence/1]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
- % the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
- % primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
--define(T_ObjectDescriptor, ?UNIVERSAL bor ?PRIMITIVE bor 7).
- % restricted character string types
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList,PTypeList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate ENCODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_encode(Erules,Type) when is_record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-
-%%===============================================================================
-%% encode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-gen_encode(Erules,Typename,Type) when is_record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
- ", ObjFun";
- false ->
- ""
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([nl,nl,nl,"%%================================"]),
- emit([nl,"%% ",asn1ct_gen:list2name(Typename)]),
- emit([nl,"%%================================",nl]),
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,
- ") when is_list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn",ObjFun,");",nl,nl]);
- _ -> true
- end;
- _ ->
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}, TagIn",ObjFun,") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,");",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,") ->",nl," "]),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end;
-
-%%===============================================================================
-%% encode ComponentType
-%%===============================================================================
-
-gen_encode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- gen_encode(Erules,NewTname,NewType).
-
-gen_encode_user(Erules,D) when is_record(D,typedef) ->
- Typename = [D#typedef.name],
- Type = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit([nl,nl,"%%================================"]),
- emit([nl,"%% ",Typename]),
- emit([nl,"%%================================",nl]),
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
-
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn) when is_list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn);",nl,nl]);
- _ -> true
- end;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
- emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(",
- unused_var("Val",Type#type.def),", TagIn) ->",nl}),
- CurrentMod = get(currmod),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- {primitive,bif} ->
- asn1ct_gen_ber:gen_encode_prim(ber,Type,["TagIn ++ ",
- {asis,Tag}],"Val"),
- emit([".",nl]);
- #typereference{val=Ename} ->
- emit([" 'enc_",Ename,"'(Val, TagIn ++ ",{asis,Tag},").",nl]);
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, TagIn ++ ",
- {asis,Tag},").",nl]);
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",
- {asis,Tag},").",nl]);
- 'ASN1_OPEN_TYPE' ->
- emit(["%% OPEN TYPE",nl]),
- asn1ct_gen_ber:gen_encode_prim(ber,
- Type#type{def='ASN1_OPEN_TYPE'},
- ["TagIn ++ ",
- {asis,Tag}],"Val"),
- emit([".",nl])
- end.
-
-unused_var(Var,#'SEQUENCE'{components=Cl}) ->
- unused_var1(Var,Cl);
-unused_var(Var,#'SET'{components=Cl}) ->
- unused_var1(Var,Cl);
-unused_var(Var,_) ->
- Var.
-unused_var1(Var,Cs) when Cs == []; Cs == {[],[]} ->
- lists:concat(["_",Var]);
-unused_var1(Var,_) ->
- Var.
-
-unused_optormand_var(Var,Def) ->
- case asn1ct_gen:type(asn1ct_gen:get_inner(Def)) of
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["_",Var]);
- _ ->
- Var
- end.
-
-
-gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
-
-%%% Currently not used for BER (except for BitString) and therefore replaced
-%%% with [] as a placeholder
- BitStringConstraint = D#type.constraint,
- Constraint = [],
- asn1ct_name:new(enumval),
- case D#type.def of
- 'BOOLEAN' ->
- emit_encode_func('boolean',Value,DoTag);
- 'INTEGER' ->
- emit_encode_func('integer',Constraint,Value,DoTag);
- {'INTEGER',NamedNumberList} ->
- emit_encode_func('integer',Constraint,Value,
- NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList={_,_}} ->
-
- emit(["case (case ",Value," of {_,",{curr,enumval},"}->",
- {curr,enumval},";_->", Value," end) of",nl]),
- asn1ct_name:new(enumval),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList} ->
-
- emit(["case (case ",Value," of {_,",{curr,enumval},"}->",
- {curr,enumval},";_->", Value," end) of",nl]),
- asn1ct_name:new(enumval),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
-
- 'REAL' ->
- emit_encode_func('real',Constraint,Value,DoTag);
-
- {'BIT STRING',NamedNumberList} ->
- emit_encode_func('bit_string',BitStringConstraint,Value,
- NamedNumberList,DoTag);
- 'ANY' ->
- emit_encode_func('open_type', Value,DoTag);
- 'NULL' ->
- emit_encode_func('null',Value,DoTag);
- 'OBJECT IDENTIFIER' ->
- emit_encode_func("object_identifier",Value,DoTag);
- 'RELATIVE-OID' ->
- emit_encode_func("relative_oid",Value,DoTag);
- 'ObjectDescriptor' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_ObjectDescriptor,DoTag);
- 'OCTET STRING' ->
- emit_encode_func('octet_string',Constraint,Value,DoTag);
- 'NumericString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_NumericString,DoTag);
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_TeletexString,DoTag);
- 'VideotexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VideotexString,DoTag);
- 'GraphicString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GraphicString,DoTag);
- 'VisibleString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VisibleString,DoTag);
- 'GeneralString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GeneralString,DoTag);
- 'PrintableString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_PrintableString,DoTag);
- 'IA5String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_IA5String,DoTag);
- 'UniversalString' ->
- emit_encode_func('universal_string',Constraint,Value,DoTag);
- 'UTF8String' ->
- emit_encode_func('UTF8_string',Constraint,Value,DoTag);
- 'BMPString' ->
- emit_encode_func('BMP_string',Constraint,Value,DoTag);
- 'UTCTime' ->
- emit_encode_func('utc_time',Constraint,Value,DoTag);
- 'GeneralizedTime' ->
- emit_encode_func('generalized_time',Constraint,Value,DoTag);
- 'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(D#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_encode_prim(Erules,InnerType,DoTag,Value);
- 'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- XX ->
- exit({'can not encode' ,XX})
- end;
- XX ->
- exit({'can not encode' ,XX})
- end.
-
-
-emit_encode_func(Name,Value,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Value,Tags);
-emit_encode_func(Name,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
-emit_encode_func(Name,Constraint,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Asis,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
-emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,
- ", ",{asis,Asis},
- ", ",Tags,")"]).
-
-emit_enc_enumerated_cases({L1,L2}, Tags) ->
- emit_enc_enumerated_cases(L1++L2, Tags, ext);
-emit_enc_enumerated_cases(L, Tags) ->
- emit_enc_enumerated_cases(L, Tags, noext).
-
-emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
- emit_enc_enumerated_cases([H2|T], Tags, Ext);
-emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
- case Ext of
- noext -> emit([";",nl]);
- ext ->
-%% emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
-%% "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
-%% asn1ct_name:new(enumval)
- emit([";",nl])
- end,
- emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
- emit([nl,"end"]).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate DECODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% decode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_decode(Erules,Type) when is_record(Type,typedef) ->
- D = Type,
- emit({nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes, OptOrMand) ->",nl}),
- emit({" 'dec_",Type#typedef.name,"'(Bytes, OptOrMand, []).",nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes, ",
- unused_optormand_var("OptOrMand",(Type#typedef.typespec)#type.def),", TagIn) ->",nl}),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
-
-
-%%===============================================================================
-%% decode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-gen_decode(Erules,Tname,Type) when is_record(Type,type) ->
- Typename = Tname,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({"'dec_",asn1ct_gen:list2name(Typename),"'(Bytes, OptOrMand, TagIn",ObjFun,") ->",nl}),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end;
-
-
-%%===============================================================================
-%% decode ComponentType
-%%===============================================================================
-
-gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- gen_decode(Erules,NewTname,NewType).
-
-
-gen_decode_user(Erules,D) when is_record(D,typedef) ->
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- InnerTag = Def#type.tag ,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- InnerTag],
- case asn1ct_gen:type(InnerType) of
- 'ASN1_OPEN_TYPE' ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- asn1ct_name:new(len),
- gen_dec_prim(Erules, Def#type{def='ASN1_OPEN_TYPE'},
- BytesVar, Tag, "TagIn",no_length,
- ?PRIMITIVE,"OptOrMand"),
- emit({".",nl,nl});
- {primitive,bif} ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- asn1ct_name:new(len),
- gen_dec_prim(Erules, Def, BytesVar, Tag, "TagIn",no_length,
- ?PRIMITIVE,"OptOrMand"),
- emit({".",nl,nl});
- {constructed,bif} ->
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- TheType ->
- DecFunName = mkfuncname(TheType,dec),
- emit({DecFunName,"(",{curr,bytes},
- ", OptOrMand, TagIn++",{asis,Tag},")"}),
- emit({".",nl,nl})
- end.
-
-
-gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Length,Form,OptOrMand) ->
- Typename = Att#type.def,
-%% Currently not used for BER replaced with [] as place holder
-%% Constraint = Att#type.constraint,
-%% Constraint = [],
- Constraint =
- case get_constraint(Att#type.constraint,'SizeConstraint') of
- no -> [];
- Tc -> Tc
- end,
- ValueRange =
- case get_constraint(Att#type.constraint,'ValueRange') of
- no -> [];
- Tv -> Tv
- end,
- SingleValue =
- case get_constraint(Att#type.constraint,'SingleValue') of
- no -> [];
- Sv -> Sv
- end,
- AsBin = case get(binary_strings) of
- true -> "_as_bin";
- _ -> ""
- end,
- NewTypeName = case Typename of
- 'ANY' -> 'ASN1_OPEN_TYPE';
- _ -> Typename
- end,
- DoLength =
- case NewTypeName of
- 'BOOLEAN'->
- emit({"?RT_BER:decode_boolean(",BytesVar,","}),
- false;
- 'INTEGER' ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},","}),
- false;
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},",",
- {asis,NamedNumberList},","}),
- false;
- {'ENUMERATED',NamedNumberList} ->
- emit({"?RT_BER:decode_enumerated(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- false;
- 'REAL' ->
- emit({"?RT_BER:decode_real(",BytesVar,",",
- {asis,Constraint},","}),
- false;
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_BER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},","});
- _ ->
- emit({"?RT_BER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","})
- end,
- true;
- 'NULL' ->
- emit({"?RT_BER:decode_null(",BytesVar,","}),
- false;
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
- false;
- 'RELATIVE-OID' ->
- emit({"?RT_BER:decode_relative_oid(",BytesVar,","}),
- false;
- 'ObjectDescriptor' ->
- emit({"?RT_BER:decode_restricted_string(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
- true;
- 'OCTET STRING' ->
- emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
- true;
- 'NumericString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),true;
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
- true;
- 'VideotexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
- true;
- 'GraphicString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","})
- ,true;
- 'VisibleString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
- true;
- 'GeneralString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
- true;
- 'PrintableString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
- true;
- 'IA5String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
- true;
- 'UniversalString' ->
- emit({"?RT_BER:decode_universal_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'UTF8String' ->
- emit({"?RT_BER:decode_UTF8_string",AsBin,"(",
- BytesVar,","}),
- false;
- 'BMPString' ->
- emit({"?RT_BER:decode_BMP_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'UTCTime' ->
- emit({"?RT_BER:decode_utc_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'GeneralizedTime' ->
- emit({"?RT_BER:decode_generalized_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type(",re_wrap_erule(Erules),",",
- BytesVar,","]),
- false;
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_dec_prim(Erules,InnerType,BytesVar,DoTag,TagIn,Length,Form,OptOrMand),
- false;
- 'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type(",
- re_wrap_erule(Erules),",",
- BytesVar,","]),
- false;
- XX ->
- exit({'can not decode' ,XX})
- end;
- Other ->
- exit({'can not decode' ,Other})
- end,
-
- NewLength = case DoLength of
- true -> [", ", Length];
- false -> ""
- end,
- NewOptOrMand = case OptOrMand of
- _ when is_list(OptOrMand) -> OptOrMand;
- mandatory -> {asis,mandatory};
- _ -> {asis,opt_or_default}
- end,
- case {TagIn,NewTypeName} of
- {_,#'ObjectClassFieldType'{}} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- 'ASN1_OPEN_TYPE' ->
- emit([{asis,DoTag},")"]);
- _ -> ok
- end;
- {[],'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},")"]);
- {_,'ASN1_OPEN_TYPE'} ->
- emit([TagIn,"++",{asis,DoTag},")"]);
- {[],_} ->
- emit([{asis,DoTag},NewLength,", ",NewOptOrMand,")"]);
- _ when is_list(TagIn) ->
- emit([TagIn,"++",{asis,DoTag},NewLength,", ",NewOptOrMand,")"])
- end.
-
-
-int_constr([],[]) ->
- [];
-int_constr([],ValueRange) ->
- ValueRange;
-int_constr(SingleValue,[]) ->
- SingleValue;
-int_constr(SV,VR) ->
- [SV,VR].
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=M,type=ClName} = Def#'Object'.classname,
- Class = asn1_db:dbget(M,ClName),
-
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed);
-gen_obj_code(_Erules,_Module,Obj) when is_record(Obj,pobjectdef) ->
- ok.
-
-
-gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Args,", _RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, TagIn, _RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} -> %% OPTIONAL field in class
- EmitFuncClause("Val, _"), %% Value must be anything
- %% already encoded
- emit([" {Val,0}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val, TagIn"),
- gen_encode_default_call(ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val, TagIn"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Args) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, TagIn, [H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause(" Val, TagIn, [H|T]"),
- emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause(" Val, TagIn, [H|T]"),
- emit({indent(3),"'",M,"':'enc_",TypeName,"'(H, Val, TagIn, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause(" Val, TagIn, [H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, TagIn, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(ClassName,[_|Cs],O,OF,Acc) ->
- gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_,[],_,_,Acc) ->
- Acc.
-
-
-% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-% MaybeConstr=
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% OTag = Def#type.tag,
-% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, TagIn, RestPrimFieldName) ->",nl}),
-% CAcc=
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
-% "Val"),
-% [];
-% {constructed,bif} ->
-% %%InnerType = asn1ct_gen:get_inner(Def#type.def),
-% %%asn1ct_gen:gen_encode_constructed(ber,[ObjName],
-% %% InnerType,Def);
-% emit({" 'enc_",ObjName,'_',FieldName,
-% "'(Val, TagIn ++ ",{asis,Tag},")"}),
-% [{['enc_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'enc_",TypeName,
-% "'(Val, TagIn ++ ",{asis,Tag},")"}),
-% [];
-% TypeName ->
-% emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",
-% {asis,Tag},")"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, TagIn, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
-% "'(H, Val, TagIn, T)"});
-% TypeName ->
-% emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} -> []
-% end,
-% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_encode_objectfields(C,O,[H|T],Acc) ->
-% gen_encode_objectfields(C,O,T,Acc);
-% gen_encode_objectfields(_,_,[],Acc) ->
-% Acc.
-
-% gen_encode_constr_type([{Name,Def}|Rest]) ->
-% emit({Name,"(Val,TagIn) ->",nl}),
-% InnerType = asn1ct_gen:get_inner(Def#type.def),
-% asn1ct_gen:gen_encode_constructed(ber,Name,InnerType,Def),
-% gen_encode_constr_type(Rest);
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ -> gen_encode_user(Erules,TypeDef)
- end,
- gen_encode_constr_type(Erules,Rest);
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(_ObjName,_FieldName,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- TDef = asn1_db:dbget(M,T),
- Def = TDef#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- if
- M == CurrentMod ->
- emit({" 'enc_",T,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- [];
- true ->
- emit({" '",M,"':'enc_",T,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- []
- end;
-gen_encode_field_call(ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val, TagIn ++",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val, TagIn ++ ",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- []
- end.
-
-gen_encode_default_call(ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes, TagIn ++ ",
- {asis,Tag},")"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
- []
- end.
-
-
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Args,"_) ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes, TagIn, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("Bytes, _,"),
-% emit([" asn1_NOVALUE"]),
- emit([" {Bytes,[],0}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes, TagIn,"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes, TagIn,"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Args) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,TagIn,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause("Bytes,TagIn,[H|T]"),
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, TagIn, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause("Bytes,TagIn,[H|T]"),
- emit({indent(3),"'",M,"':'dec_",TypeName,
- "'(H, Bytes, TagIn, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,TagIn,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, TagIn, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, TagIn, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-gen_decode_field_call(_ObjName,_FieldName,Bytes,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- TDef = asn1_db:dbget(M,T),
- Def = TDef#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- if
- M == CurrentMod ->
- emit({" 'dec_",T,"'(",Bytes,
- ", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- [];
- true ->
- emit({" '",M,"':'dec_",T,
- "'(",Bytes,", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- []
- end;
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",no_length,
- ?PRIMITIVE,opt_or_default),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",opt_or_default, TagIn ++ ",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,
- ", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,
- ",opt_or_default, TagIn ++ ",{asis,Tag},")"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",no_length,
- ?PRIMITIVE,opt_or_default),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,
- " ,opt_or_default, TagIn ++ ",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,
- ", opt_or_defualt, TagIn ++ ",{asis,Tag},")",nl]),
- []
- end.
-
-
-more_genfields([]) ->
- false;
-more_genfields([Field|Fields]) ->
- case element(1,Field) of
- typefield ->
- true;
- objectfield ->
- true;
- _ ->
- more_genfields(Fields)
- end.
-
-
-
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
- gen_objset_dec(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-
-%% gen_objset_enc iterates over the objects of the object set
-gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(ObjSName,UniqueName,[{_,no_unique_value,_},T|Rest],
- ClName,ClFields,NthObj,Acc) ->
- %% No need to check that this class has property OPTIONAL for the
- %% unique field, it was detected in the previous phase
- gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NthObj,Acc);
-gen_objset_enc(ObjSetName,UniqueName,[{_,no_unique_value,_}],
- _ClName,_ClFields,_NthObj,Acc) ->
- %% No need to check that this class has property OPTIONAL for the
- %% unique field, it was detected in the previous phase
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- Acc;
-gen_objset_enc(ObjSName,UniqueName,
- [{ObjName,Val,Fields},T|Rest],ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,NewNthObj}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/4"}),
- {[],NthObj};
- {ModuleName,Name} ->
- emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _Other ->
- emit({" fun 'enc_",ObjName,"'/4"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,_}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/4"}),
- {[],NthObj};
- {ModuleName,Name} ->
- emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _Other ->
- emit({" fun 'enc_",ObjName,"'/4"}),
- {[],NthObj}
- end,
- emit([";",nl]),
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- InternalFunc ++ Acc;
-%% See X.681 Annex E for the following case
-gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],
- _ClName,_ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_Attr, Val, _TagIn, _RestPrimFieldName) ->",nl}),
- emit({indent(6),"Len = case Val of",nl,indent(9),
- "Bin when is_binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Val)",nl,indent(6),"end,"}),
- emit({indent(6),"{Val,Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(ObjSetName,UniqueName,['EXTENSIONMARK','EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj,Acc) ->
- gen_objset_enc(ObjSetName,UniqueName,['EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj,Acc);
-gen_objset_enc(ObjSetName,UniqueName,['EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj,Acc) ->
- gen_objset_enc(ObjSetName,UniqueName,Rest++['EXTENSIONMARK'],
- ClName,ClFields,NthObj,Acc);
-gen_objset_enc(_,_,[],_,_,_,Acc) ->
- Acc.
-
-emit_ext_fun(EncDec,ModuleName,Name) ->
- emit([indent(3),"fun(T,V,_O1,_O2) -> '",ModuleName,"':'",EncDec,"_",
- Name,"'(T,V,_O1,_O2) end"]).
-
-emit_default_getenc(ObjSetName,UniqueName) ->
- emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
- emit([indent(3),"fun(C,V,_,_) -> exit({'Type not compatible with table constraint',{component,C},{value,V}, {unique_name_and_value,",{asis,UniqueName},", ErrV}}) end"]).
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit([indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- if
- M == CurrMod ->
- emit([indent(12),"'enc_",T,"'(Val, TagIn ++ ",
- {asis,Tag},")"]);
- true ->
- emit([indent(12),"'",M,"':'enc_",T,"'(Val,TagIn ++",
- {asis,Tag},")"])
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[]);
- false ->
- %% This field was not present in the object thus there were no
- %% type in the table and we therefore generate code that returns
- %% the input for application treatment.
- emit([indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"Len = case Val of",nl,
- indent(15),"Bin when is_binary(Bin) -> size(Bin);",nl,
- indent(15),"_ -> length(Val)",nl,indent(12),"end,",nl,
- indent(12),"{Val,Len}"]),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[])
- end;
-gen_inlined_enc_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- CurrMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- if
- M == CurrMod ->
- emit([indent(12),"'enc_",T,"'(Val, TagIn ++ ",
- {asis,Tag},")"]);
- true ->
- emit([indent(12),"'",M,"':'enc_",T,"'(Val,TagIn ++",
- {asis,Tag},")"])
- end,
- {Acc,0};
- false ->
- %% This field was not present in the object thus there were no
- %% type in the table and we therefore generate code that returns
- %% the input for application treatment.
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"Len = case Val of",nl,
- indent(15),"Bin when is_binary(Bin) -> size(Bin);",nl,
- indent(15),"_ -> length(Val)",nl,indent(12),"end,",nl,
- indent(12),"{Val,Len}"]),
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-
-emit_inner_of_fun(TDef = #typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val,TagIn ++ ",
- {asis,Tag},")"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val, TagIn ++ ",
- {asis,Tag},")"}),
- {[],0}
- end;
-emit_inner_of_fun(#typedef{name=Name,typespec=Type},_) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({indent(12),"'enc_",Name,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- {[],0};
-emit_inner_of_fun(Type,_) when is_record(Type,type) ->
- CurrMod = get(currmod),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#type.def of
- Def when is_atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val, TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val, TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val, TagIn ++ ",{asis,Tag},")"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(Erules,ObjSName,UniqueName,[{_,no_unique_value,_},T|Rest],
- ClName,ClFields,NthObj)->
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NthObj);
-gen_objset_dec(_Erules,ObjSetName,UniqueName,[{_,no_unique_value,_}],
- _ClName,_ClFields,_NthObj)->
- emit_default_getdec(ObjSetName,UniqueName),
- emit({".",nl,nl});
-gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj)->
- emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- CurrMod = get(currmod),
- NewNthObj=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSName,
- NthObj);
- {CurrMod,Name} ->
- emit({" fun 'dec_",Name,"'/4"}),
- NthObj;
- {ModName,Name} ->
- emit_ext_fun(dec,ModName,Name),
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]),
- NthObj;
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj);
-gen_objset_dec(Erules,ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSetName,
- NthObj);
- {CurrMod,Name} ->
- emit({" fun 'dec_",Name,"'/4"});
- {ModName,Name} ->
- emit_ext_fun(dec,ModName,Name);
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit({";",nl}),
- emit_default_getdec(ObjSetName,UniqueName),
- emit({".",nl,nl});
-gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
- emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Bytes, _, _) ->",nl}),
- emit({indent(6),"Len = case Bytes of",nl,indent(9),
- "Bin when is_binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Bytes)",nl,indent(6),"end,"}),
- emit({indent(6),"{Bytes,[],Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(Erule,ObjSetName,UniqueName,
- ['EXTENSIONMARK','EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj) ->
- gen_objset_dec(Erule,ObjSetName,UniqueName,['EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj);
-gen_objset_dec(Erule,ObjSetName,UniqueName,['EXTENSIONMARK'|Rest],
- ClName,ClFields,NthObj) ->
- gen_objset_dec(Erule,ObjSetName,UniqueName,Rest++['EXTENSIONMARK'],
- ClName,ClFields,NthObj);
-gen_objset_dec(_,_,_,[],_,_,_) ->
- ok.
-
-emit_default_getdec(ObjSetName,UniqueName) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
- emit([indent(3),"fun(C,V,_,_) -> exit({{component,C},{value,V}, {unique_name_and_value,",{asis,UniqueName},", ErrV}}) end"]).
-
-gen_inlined_dec_funs(Erules,Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- if
- M == CurrMod ->
- emit([indent(12),"'dec_",T,"'(Bytes, ",DecProp,
- ", TagIn ++ ",{asis,Tag},")"]);
- true ->
- emit([indent(12),"'",M,"':'dec_",T,"'(Bytes, ",
- DecProp,", TagIn ++ ",{asis,Tag},")"])
- end,
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj);
- false ->
- emit([indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Bytes)",nl,
- indent(12),"end,",nl,
- indent(12),"{Bytes,[],Len}"]),
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Erules,Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Erules,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Erules,Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- if
- M == CurrMod ->
- emit([indent(12),"'dec_",T,"'(Bytes, ",DecProp,
- ", TagIn ++ ",{asis,Tag},")"]);
- true ->
- emit([indent(12),"'",M,"':'dec_",T,"'(Bytes, ",
- DecProp,", TagIn ++ ",{asis,Tag},")"])
- end,
- 0;
- false ->
- emit([";",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Bytes)",nl,
- indent(12),"end,",nl,
- indent(12),"{Bytes,[],Len}"]),
- 0
- end,
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Erules,Fields,[_H|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
-
-emit_inner_of_decfun(Erules,#typedef{name={ExtName,Name},typespec=Type},
- Prop,InternalDefFunName) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
- ?PRIMITIVE,Prop),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",Prop,
- ", TagIn ++ ",{asis,Tag},")"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Bytes, ",Prop,
- ", TagIn ++ ",{asis,Tag},")"}),
- 0
- end;
-emit_inner_of_decfun(_,#typedef{name=Name,typespec=Type},Prop,_) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({indent(12),"'dec_",Name,"'(Bytes, ",Prop,", TagIn ++ ",
- {asis,Tag},")"}),
- 0;
-emit_inner_of_decfun(Erules,Type,Prop,_) when is_record(Type,type) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- CurrMod = get(currmod),
- Def = Type#type.def,
- InnerType = asn1ct_gen:get_inner(Def),
- WhatKind = asn1ct_gen:type(InnerType),
- case WhatKind of
- {primitive,bif} ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
- ?PRIMITIVE,Prop);
-% TRef when is_record(TRef,typereference) ->
-% T = TRef#typereference.val,
-% emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,
- "'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"})
- end,
- 0.
-
-
-gen_internal_funcs(_,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit({"'dec_",TypeDef#typedef.name,"'(Bytes, ",
- unused_optormand_var("OptOrMand",(TypeDef#typedef.typespec)#type.def),", TagIn) ->",nl}),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-
-decode_class('UNIVERSAL') ->
- ?UNIVERSAL;
-decode_class('APPLICATION') ->
- ?APPLICATION;
-decode_class('CONTEXT') ->
- ?CONTEXT;
-decode_class('PRIVATE') ->
- ?PRIVATE.
-
-decode_type('BOOLEAN') -> 1;
-decode_type('INTEGER') -> 2;
-decode_type('BIT STRING') -> 3;
-decode_type('OCTET STRING') -> 4;
-decode_type('NULL') -> 5;
-decode_type('OBJECT IDENTIFIER') -> 6;
-decode_type('ObjectDescriptor') -> 7;
-decode_type('EXTERNAL') -> 8;
-decode_type('REAL') -> 9;
-decode_type('ENUMERATED') -> 10;
-decode_type('EMBEDDED_PDV') -> 11;
-decode_type('UTF8String') -> 12;
-decode_type('RELATIVE-OID') -> 13;
-decode_type('SEQUENCE') -> 16;
-decode_type('SEQUENCE OF') -> 16;
-decode_type('SET') -> 17;
-decode_type('SET OF') -> 17;
-decode_type('NumericString') -> 18;
-decode_type('PrintableString') -> 19;
-decode_type('TeletexString') -> 20;
-decode_type('T61String') -> 20;
-decode_type('VideotexString') -> 21;
-decode_type('IA5String') -> 22;
-decode_type('UTCTime') -> 23;
-decode_type('GeneralizedTime') -> 24;
-decode_type('GraphicString') -> 25;
-decode_type('VisibleString') -> 26;
-decode_type('GeneralString') -> 27;
-decode_type('UniversalString') -> 28;
-decode_type('BMPString') -> 30;
-decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
-decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-
-add_removed_bytes() ->
- asn1ct_name:delete(rb),
- add_removed_bytes(asn1ct_name:all(rb)).
-
-add_removed_bytes([H,T1|T]) ->
- emit({{var,H},"+"}),
- add_removed_bytes([T1|T]);
-add_removed_bytes([H|T]) ->
- emit({{var,H}}),
- add_removed_bytes(T);
-add_removed_bytes([]) ->
- true.
-
-mkfuncname(WhatKind,DecOrEnc) ->
- case WhatKind of
- #'Externaltypereference'{module=Mod,type=EType} ->
- CurrMod = get(currmod),
- case CurrMod of
- Mod ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- _ ->
-% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
- lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
- end;
- #'typereference'{val=EType} ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
-
- end.
-
-optionals(L) -> optionals(L,[],1).
-
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
- lists:reverse(Acc).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%% if the original option was ber and it has been wrapped to ber_bin
-%% turn it back to ber
-re_wrap_erule(ber_bin) ->
- case get(encoding_options) of
- Options when is_list(Options) ->
- case lists:member(ber,Options) of
- true -> ber;
- _ -> ber_bin
- end;
- _ -> ber_bin
- end;
-re_wrap_erule(Erule) ->
- Erule.
-
-is_already_generated(Operation,Name) ->
- case get(class_default_type) of
- undefined ->
- put(class_default_type,[{Operation,Name}]),
- false;
- GeneratedList ->
- case lists:member({Operation,Name},GeneratedList) of
- true ->
- true;
- false ->
- put(class_default_type,[{Operation,Name}|GeneratedList]),
- false
- end
- end.
-
-get_class_fields(#classdef{typespec=ObjClass}) ->
- ObjClass#objectclass.fields;
-get_class_fields(#objectclass{fields=Fields}) ->
- Fields;
-get_class_fields(_) ->
- [].
-
-get_object_field(Name,ObjectFields) ->
- case lists:keysearch(Name,1,ObjectFields) of
- {value,Field} -> Field;
- false -> false
- end.
-
-%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
-%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
-%%
-extaddgroup2sequence(ExtList) when is_list(ExtList) ->
- lists:filter(fun(#'ExtensionAdditionGroup'{}) ->
- false;
- ('ExtensionAdditionGroupEnd') ->
- false;
- (_) ->
- true
- end, ExtList).
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 3ccfca3784..8ab49aec2c 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -24,9 +24,7 @@
-include("asn1_records.hrl").
--export([pgen/4]).
-export([decode_class/1, decode_type/1]).
--export([add_removed_bytes/0]).
-export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
-export([gen_encode_prim/4]).
-export([gen_dec_prim/7]).
@@ -59,18 +57,6 @@
-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList,PTypeList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
-
-
%%===============================================================================
%%===============================================================================
%%===============================================================================
@@ -83,8 +69,8 @@ pgen(OutFile,Erules,Module,TypeOrVal) ->
%% encode #{typedef, {pos, name, typespec}}
%%===============================================================================
-gen_encode(Erules,Type) when is_record(Type,typedef) ->
- gen_encode_user(Erules,Type).
+gen_encode(Erules, #typedef{}=D) ->
+ gen_encode_user(Erules, #typedef{}=D, true).
%%===============================================================================
%% encode #{type, {tag, def, constraint}}
@@ -114,31 +100,6 @@ gen_encode(Erules,Typename,Type) when is_record(Type,type) ->
_ -> % embedded type with constructed name
true
end,
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,
- ") when is_list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn",ObjFun,");",nl,nl]);
- _ -> true
- end;
- _ ->
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}, TagIn",ObjFun,") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,");",nl,nl])
- end,
emit(["'enc_",asn1ct_gen:list2name(Typename),
"'(Val, TagIn",ObjFun,") ->",nl," "]),
asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
@@ -159,44 +120,28 @@ gen_encode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
NewType = Type#type{tag=[]},
gen_encode(Erules,NewTname,NewType).
-gen_encode_user(Erules,D) when is_record(D,typedef) ->
+gen_encode_user(Erules, #typedef{}=D, Wrapper) ->
Typename = [D#typedef.name],
Type = D#typedef.typespec,
InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
emit([nl,nl,"%%================================"]),
emit([nl,"%% ",Typename]),
emit([nl,"%%================================",nl]),
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, ", {asis,lists:reverse(Tag)},").",nl,nl]),
-
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
-
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn) when is_list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn);",nl,nl]);
- _ -> true
- end;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
- emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
+ FuncName = "'enc_" ++ asn1ct_gen:list2name(Typename) ++ "'",
+ case Wrapper of
+ true ->
+ %% This is a top-level type. Generate an 'enc_Type'/1
+ %% wrapper.
+ OTag = Type#type.tag,
+ Tag0 = [encode_tag_val(decode_class(Class), Form, Number) ||
+ #tag{class=Class,form=Form,number=Number} <- OTag],
+ Tag = lists:reverse(Tag0),
+ emit([FuncName,"(Val) ->",nl,
+ " ",FuncName,"(Val, ",{asis,Tag},").",nl,nl]);
+ false ->
+ ok
end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn) ->",nl}),
+ emit([FuncName,"(Val, TagIn) ->",nl]),
CurrentMod = get(currmod),
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
@@ -204,8 +149,6 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
{primitive,bif} ->
gen_encode_prim(ber,Type,"TagIn","Val"),
emit([".",nl]);
- #typereference{val=Ename} ->
- emit([" 'enc_",Ename,"'(Val, TagIn).",nl]);
#'Externaltypereference'{module=CurrentMod,type=Etype} ->
emit([" 'enc_",Etype,"'(Val, TagIn).",nl]);
#'Externaltypereference'{module=Emod,type=Etype} ->
@@ -218,140 +161,74 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
emit([".",nl])
end.
-gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
-
-%%% Constraint is currently not used for BER (except for BitString) and therefore replaced
-%%% with [] as a placeholder
- BitStringConstraint = D#type.constraint,
- Constraint = [],
+gen_encode_prim(_Erules, #type{}=D, DoTag, Value) ->
+ BitStringConstraint = get_size_constraint(D#type.constraint),
asn1ct_name:new(enumval),
- case D#type.def of
+ Type = case D#type.def of
+ 'OCTET STRING' -> restricted_string;
+ 'ObjectDescriptor'-> restricted_string;
+ 'NumericString' -> restricted_string;
+ 'TeletexString' -> restricted_string;
+ 'T61String' -> restricted_string;
+ 'VideotexString' -> restricted_string;
+ 'GraphicString' -> restricted_string;
+ 'VisibleString' -> restricted_string;
+ 'GeneralString' -> restricted_string;
+ 'PrintableString' -> restricted_string;
+ 'IA5String' -> restricted_string;
+ 'UTCTime' -> restricted_string;
+ 'GeneralizedTime' -> restricted_string;
+ Other -> Other
+ end,
+ case Type of
+ restricted_string ->
+ call(encode_restricted_string, [Value,DoTag]);
'BOOLEAN' ->
- emit_encode_func('boolean',Value,DoTag);
+ call(encode_boolean, [Value,DoTag]);
'INTEGER' ->
- emit_encode_func('integer',Constraint,Value,DoTag);
+ call(encode_integer, [Value,DoTag]);
{'INTEGER',NamedNumberList} ->
- emit_encode_func('integer',Constraint,Value,
- NamedNumberList,DoTag);
+ call(encode_integer, [Value,{asis,NamedNumberList}, DoTag]);
{'ENUMERATED',NamedNumberList={_,_}} ->
-
emit(["case ",Value," of",nl]),
emit_enc_enumerated_cases(NamedNumberList,DoTag);
{'ENUMERATED',NamedNumberList} ->
-
emit(["case ",Value," of",nl]),
emit_enc_enumerated_cases(NamedNumberList,DoTag);
-
'REAL' ->
- emit_encode_func('real',Constraint,Value,DoTag);
-
+ emit([{call,ber,encode_tags,
+ [DoTag,{call,real_common,ber_encode_real,[Value]}]}]);
{'BIT STRING',NamedNumberList} ->
- emit_encode_func('bit_string',BitStringConstraint,Value,
- NamedNumberList,DoTag);
- 'ANY' ->
- emit_encode_func('open_type', Value,DoTag);
+ call(encode_bit_string,
+ [{asis,BitStringConstraint},Value,
+ {asis,NamedNumberList},DoTag]);
'NULL' ->
- emit_encode_func('null',Value,DoTag);
+ call(encode_null, [Value,DoTag]);
'OBJECT IDENTIFIER' ->
- emit_encode_func("object_identifier",Value,DoTag);
+ call(encode_object_identifier, [Value,DoTag]);
'RELATIVE-OID' ->
- emit_encode_func("relative_oid",Value,DoTag);
- 'ObjectDescriptor' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_ObjectDescriptor,DoTag);
- 'OCTET STRING' ->
- emit_encode_func('octet_string',Constraint,Value,DoTag);
- 'NumericString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_NumericString,DoTag);
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_TeletexString,DoTag);
- 'VideotexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VideotexString,DoTag);
- 'GraphicString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GraphicString,DoTag);
- 'VisibleString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VisibleString,DoTag);
- 'GeneralString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GeneralString,DoTag);
- 'PrintableString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_PrintableString,DoTag);
- 'IA5String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_IA5String,DoTag);
+ call(encode_relative_oid, [Value,DoTag]);
'UniversalString' ->
- emit_encode_func('universal_string',Constraint,Value,DoTag);
+ call(encode_universal_string, [Value,DoTag]);
'UTF8String' ->
- emit_encode_func('UTF8_string',Constraint,Value,DoTag);
+ call(encode_UTF8_string, [Value,DoTag]);
'BMPString' ->
- emit_encode_func('BMP_string',Constraint,Value,DoTag);
- 'UTCTime' ->
- emit_encode_func('utc_time',Constraint,Value,DoTag);
- 'GeneralizedTime' ->
- emit_encode_func('generalized_time',Constraint,Value,DoTag);
+ call(encode_BMP_string, [Value,DoTag]);
'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(D#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_encode_prim(Erules,InnerType,DoTag,Value);
- 'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- XX ->
- exit({'can not encode' ,XX})
- end;
- XX ->
- exit({'can not encode' ,XX})
+ call(encode_open_type, [Value,DoTag])
end.
-
-emit_encode_func(Name,Value,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Value,Tags);
-emit_encode_func(Name,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
-emit_encode_func(Name,Constraint,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Asis,Tags) when is_atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
-emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,
- ", ",{asis,Asis},
- ", ",Tags,")"]).
-
emit_enc_enumerated_cases({L1,L2}, Tags) ->
emit_enc_enumerated_cases(L1++L2, Tags, ext);
emit_enc_enumerated_cases(L, Tags) ->
emit_enc_enumerated_cases(L, Tags, noext).
-emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
- emit_enc_enumerated_cases([H2|T], Tags, Ext);
-emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
- case Ext of
- noext -> emit([";",nl]);
- ext ->
- emit([";",nl])
-%% emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
-%% "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
-%% asn1ct_name:new(enumval)
- end,
+emit_enc_enumerated_cases([{EnumName,EnumVal}|T], Tags, Ext) ->
+ emit([{asis,EnumName}," -> ",
+ {call,ber,encode_enumerated,[EnumVal,Tags]},";",nl]),
+ emit_enc_enumerated_cases(T, Tags, Ext);
+emit_enc_enumerated_cases([], _Tags, _Ext) ->
+ %% FIXME: Should extension be handled?
emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
emit([nl,"end"]).
@@ -414,9 +291,10 @@ gen_decode_selected(Erules,Type,FuncName) ->
{value,{_,P}} -> P;
false -> exit({error,{internal,no_pattern_saved}})
end,
- emit([" case ?RT_BER:decode_selective(",{asis,Pattern},",Bin) of",nl,
+ emit([" case ",{call,ber,decode_selective,
+ [{asis,Pattern},"Bin"]}," of",nl,
" {ok,Bin2} when is_binary(Bin2) ->",nl,
- " {Tlv,_} = ?RT_BER:decode(Bin2",asn1ct_gen:nif_parameter(),"),",nl]),
+ " {Tlv,_} = ", {call,ber,ber_decode_nif,["Bin2"]},com,nl]),
emit("{ok,"),
gen_decode_selected_type(Erules,Type),
emit(["};",nl," Err -> exit({error,{selective_decode,Err}})",nl,
@@ -573,183 +451,155 @@ gen_decode_user(Erules,D) when is_record(D,typedef) ->
end.
-gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
+gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) ->
Typename = Att#type.def,
%% Currently not used for BER replaced with [] as place holder
%% Constraint = Att#type.constraint,
%% Constraint = [],
- Constraint =
- case get_constraint(Att#type.constraint,'SizeConstraint') of
- no -> [];
- Tc -> Tc
- end,
- ValueRange =
- case get_constraint(Att#type.constraint,'ValueRange') of
- no -> [];
- Tv -> Tv
- end,
- SingleValue =
- case get_constraint(Att#type.constraint,'SingleValue') of
- no -> [];
- Sv -> Sv
- end,
+ Constraint = get_size_constraint(Att#type.constraint),
+ IntConstr = int_constr(Att#type.constraint),
AsBin = case get(binary_strings) of
true -> "_as_bin";
_ -> ""
end,
NewTypeName = case Typename of
- 'ANY' -> 'ASN1_OPEN_TYPE';
- _ -> Typename
+ 'OCTET STRING' -> restricted_string;
+ 'NumericString' -> restricted_string;
+ 'TeletexString' -> restricted_string;
+ 'T61String' -> restricted_string;
+ 'VideotexString' -> restricted_string;
+ 'GraphicString' -> restricted_string;
+ 'VisibleString' -> restricted_string;
+ 'GeneralString' -> restricted_string;
+ 'PrintableString' -> restricted_string;
+ 'IA5String' -> restricted_string;
+ 'ObjectDescriptor'-> restricted_string;
+ 'UTCTime' -> restricted_string;
+ 'GeneralizedTime' -> restricted_string;
+ _ -> Typename
end,
-% DoLength =
case NewTypeName of
'BOOLEAN'->
- emit({"?RT_BER:decode_boolean(",BytesVar,","}),
- add_func({decode_boolean,2});
+ emit(["decode_boolean(",BytesVar,","]),
+ need(decode_boolean, 2);
'INTEGER' ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},","}),
- add_func({decode_integer,3});
+ case IntConstr of
+ [] ->
+ emit(["decode_integer(",BytesVar,","]),
+ need(decode_integer, 2);
+ {_,_} ->
+ emit(["decode_integer(",BytesVar,",",
+ {asis,IntConstr},","]),
+ need(decode_integer, 3)
+ end;
{'INTEGER',NamedNumberList} ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},",",
- {asis,NamedNumberList},","}),
- add_func({decode_integer,4});
+ case IntConstr of
+ [] ->
+ emit(["decode_named_integer(",BytesVar,",",
+ {asis,NamedNumberList},","]),
+ need(decode_named_integer, 3);
+ {_,_} ->
+ emit(["decode_named_integer(",BytesVar,",",
+ {asis,IntConstr},",",
+ {asis,NamedNumberList},","]),
+ need(decode_named_integer, 4)
+ end;
{'ENUMERATED',NamedNumberList} ->
- emit({"?RT_BER:decode_enumerated(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_enumerated,4});
+ emit(["decode_enumerated(",BytesVar,",",
+ {asis,NamedNumberList},","]),
+ need(decode_enumerated, 3);
'REAL' ->
- emit({"?RT_BER:decode_real(",BytesVar,","}),
- add_func({decode_real,3});
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_BER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_compact_bit_string,4});
- _ ->
- emit({"?RT_BER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_bit_string,4})
- end;
+ ok;
+ {'BIT STRING',_NamedNumberList} ->
+ ok;
'NULL' ->
- emit({"?RT_BER:decode_null(",BytesVar,","}),
- add_func({decode_null,2});
+ emit(["decode_null(",BytesVar,","]),
+ need(decode_null, 2);
'OBJECT IDENTIFIER' ->
- emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
- add_func({decode_object_identifier,2});
+ emit(["decode_object_identifier(",BytesVar,","]),
+ need(decode_object_identifier, 2);
'RELATIVE-OID' ->
- emit({"?RT_BER:decode_relative_oid(",BytesVar,","}),
- add_func({decode_relative_oid,2});
- 'ObjectDescriptor' ->
- emit({"?RT_BER:decode_restricted_string(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
- add_func({decode_restricted_string,4});
- 'OCTET STRING' ->
- emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
- add_func({decode_octet_string,3});
- 'NumericString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),
- add_func({decode_restricted_string,4});
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
- add_func({decode_restricted_string,4});
- 'VideotexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
- add_func({decode_restricted_string,4});
- 'GraphicString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","}),
- add_func({decode_restricted_string,4});
- 'VisibleString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
- add_func({decode_restricted_string,4});
- 'GeneralString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
- add_func({decode_restricted_string,4});
- 'PrintableString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
- add_func({decode_restricted_string,4});
- 'IA5String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
- add_func({decode_restricted_string,4}) ;
+ emit(["decode_relative_oid(",BytesVar,","]),
+ need(decode_relative_oid, 2);
+ restricted_string ->
+ emit(["decode_restricted_string",AsBin,"(",BytesVar,","]),
+ case Constraint of
+ [] ->
+ need(decode_restricted_string, 2);
+ _ ->
+ emit([{asis,Constraint},","]),
+ need(decode_restricted_string, 3)
+ end;
'UniversalString' ->
- emit({"?RT_BER:decode_universal_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_universal_string,3});
+ emit(["decode_universal_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","]),
+ need(decode_universal_string, 3);
'UTF8String' ->
- emit({"?RT_BER:decode_UTF8_string",AsBin,"(",
- BytesVar,","}),
- add_func({decode_UTF8_string,2});
+ emit(["decode_UTF8_string",AsBin,"(",
+ BytesVar,","]),
+ need(decode_UTF8_string, 2);
'BMPString' ->
- emit({"?RT_BER:decode_BMP_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_BMP_string,3});
- 'UTCTime' ->
- emit({"?RT_BER:decode_utc_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_utc_time,3});
- 'GeneralizedTime' ->
- emit({"?RT_BER:decode_generalized_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_generalized_time,3});
+ emit(["decode_BMP_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","]),
+ need(decode_BMP_string, 3);
'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type_as_binary(",
+ emit(["decode_open_type_as_binary(",
BytesVar,","]),
- add_func({decode_open_type_as_binary,3});
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_dec_prim(Erules,InnerType,BytesVar,DoTag,TagIn,Form,OptOrMand);
- 'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type_as_binary(",
- BytesVar,","]),
- add_func({decode_open_type_as_binary,3});
- Other ->
- exit({'can not decode' ,Other})
- end;
- Other ->
- exit({'can not decode' ,Other})
+ need(decode_open_type_as_binary, 2)
end,
- case {DoTag,NewTypeName} of
- {_,#'ObjectClassFieldType'{}} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- 'ASN1_OPEN_TYPE' ->
- emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
- _ -> ok
- end;
- {{string,TagStr},'ASN1_OPEN_TYPE'} ->
- emit([TagStr,asn1ct_gen:nif_parameter(),")"]);
- {_,'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
- {{string,TagStr},_} ->
- emit([TagStr,")"]);
- _ when is_list(DoTag) ->
- emit([{asis,DoTag},")"])
+ TagStr = case DoTag of
+ {string,Tag1} -> Tag1;
+ _ when is_list(DoTag) -> {asis,DoTag}
+ end,
+ case NewTypeName of
+ {'BIT STRING',NNL} ->
+ gen_dec_bit_string(BytesVar, Constraint, NNL, TagStr);
+ 'REAL' ->
+ asn1ct_name:new(tmpbuf),
+ emit(["begin",nl,
+ {curr,tmpbuf}," = ",
+ {call,ber,match_tags,[BytesVar,TagStr]},com,nl,
+ {call,real_common,decode_real,[{curr,tmpbuf}]},nl,
+ "end",nl]);
+ _ ->
+ emit([TagStr,")"])
+ end.
+
+%% Simplify an integer constraint so that we can efficiently test it.
+-spec int_constr(term()) -> [] | {integer(),integer()|'MAX'}.
+int_constr(C) ->
+ case asn1ct_imm:effective_constraint(integer, C) of
+ [{_,[]}] ->
+ %% Extension - ignore constraint.
+ [];
+ [{'ValueRange',{'MIN',_}}] ->
+ %% Tricky to implement efficiently - ignore it.
+ [];
+ [{'ValueRange',{_,_}=Range}] ->
+ Range;
+ [{'SingleValue',Sv}] ->
+ {Sv,Sv};
+ [] ->
+ []
end.
+gen_dec_bit_string(BytesVar, _Constraint, [_|_]=NNL, TagStr) ->
+ call(decode_named_bit_string,
+ [BytesVar,{asis,NNL},TagStr]);
+gen_dec_bit_string(BytesVar, Constraint, [], TagStr) ->
+ case asn1ct:get_bit_string_format() of
+ compact ->
+ call(decode_compact_bit_string,
+ [BytesVar,{asis,Constraint},TagStr]);
+ legacy ->
+ call(decode_legacy_bit_string,
+ [BytesVar,{asis,Constraint},TagStr]);
+ bitstring ->
+ call(decode_native_bit_string,
+ [BytesVar,{asis,Constraint},TagStr])
+ end.
-int_constr([],[]) ->
- [];
-int_constr([],ValueRange) ->
- ValueRange;
-int_constr(SingleValue,[]) ->
- SingleValue;
-int_constr(SV,VR) ->
- [SV,VR].
%% Object code generating for encoding and decoding
%% ------------------------------------------------
@@ -774,9 +624,7 @@ gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
ObjName,Fields,[]),
emit(nl),
gen_decode_constr_type(Erules,DecConstructed),
- emit_tlv_format_function();
-gen_obj_code(_Erules,_Module,Obj) when is_record(Obj,pobjectdef) ->
- ok.
+ emit_tlv_format_function().
gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
ObjName,ObjectFields,ConstrAcc) ->
@@ -867,7 +715,7 @@ gen_encode_objectfields(_,[],_,_,Acc) ->
gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
case is_already_generated(enc,TypeDef#typedef.name) of
true -> ok;
- _ -> gen_encode_user(Erules,TypeDef)
+ false -> gen_encode_user(Erules, TypeDef, false)
end,
gen_encode_constr_type(Erules,Rest);
gen_encode_constr_type(_,[]) ->
@@ -925,8 +773,8 @@ gen_encode_default_call(ClassName,FieldName,Type) ->
Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes)"]),
+ emit([" 'enc_",ClassName,'_',FieldName,"'",
+ "(Val, ",{asis,Tag},")"]),
[#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
typespec=Type}];
{primitive,bif} ->
@@ -1064,7 +912,7 @@ emit_tlv_format_function() ->
end.
emit_tlv_format_function1() ->
emit(["tlv_format(Bytes) when is_binary(Bytes) ->",nl,
- " {Tlv,_}=?RT_BER:decode(Bytes",asn1ct_gen:nif_parameter(),"),",nl,
+ " {Tlv,_} = ",{call,ber,ber_decode_nif,["Bytes"]},com,nl,
" Tlv;",nl,
"tlv_format(Bytes) ->",nl,
" Bytes.",nl]).
@@ -1074,7 +922,10 @@ gen_decode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
case is_already_generated(dec,TypeDef#typedef.name) of
true -> ok;
_ ->
- gen_decode(Erules,TypeDef)
+ emit([nl,nl,
+ "'dec_",TypeDef#typedef.name,
+ "'(Tlv, TagIn) ->",nl]),
+ gen_decode_user(Erules, TypeDef)
end,
gen_decode_constr_type(Erules,Rest);
gen_decode_constr_type(_,[]) ->
@@ -1218,66 +1069,43 @@ gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
%% There is no unique field in the class of this object set
%% don't bother about the constraint
[];
-gen_objset_enc(Erules,ObjSName,UniqueName,
- [{ObjName,Val,Fields},T|Rest],ClName,ClFields,
+gen_objset_enc(Erules, ObjSetName, UniqueName,
+ [{ObjName,Val,Fields}|T], ClName, ClFields,
NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
+ emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl]),
CurrMod = get(currmod),
{InternalFunc,NewNthObj}=
case ObjName of
{no_mod,no_name} ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModuleName,Name} ->
- emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(_,ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,_} =
- case ObjName of
- {no_mod,no_name} ->
gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
{CurrMod,Name} ->
emit({" fun 'enc_",Name,"'/3"}),
{[],NthObj};
{ModuleName,Name} ->
emit_ext_fun(enc,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'enc_",Name,"'}"]),
{[],NthObj};
_ ->
emit({" fun 'enc_",ObjName,"'/3"}),
{[],NthObj}
end,
- emit([";",nl]),
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- InternalFunc ++ Acc;
+ emit({";",nl}),
+ gen_objset_enc(Erules, ObjSetName, UniqueName, T, ClName, ClFields,
+ NewNthObj, InternalFunc ++ Acc);
%% See X.681 Annex E for the following case
gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj,Acc) ->
emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
emit({indent(3),"fun(_, Val, _RestPrimFieldName) ->",nl}),
emit({indent(6),"Len = case Val of",nl,indent(9),
- "Bin when is_binary(Bin) -> size(Bin);",nl,indent(9),
+ "Bin when is_binary(Bin) -> byte_size(Bin);",nl,indent(9),
"_ -> length(Val)",nl,indent(6),"end,"}),
emit({indent(6),"{Val,Len}",nl}),
emit({indent(3),"end.",nl,nl}),
Acc;
-gen_objset_enc(_,_,_,[],_,_,_,Acc) ->
+gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) ->
+ emit_default_getenc(ObjSetName, UniqueName),
+ emit({".",nl,nl}),
Acc.
emit_ext_fun(EncDec,ModuleName,Name) ->
@@ -1291,78 +1119,34 @@ emit_default_getenc(ObjSetName,UniqueName) ->
%% gen_inlined_enc_funs for each object iterates over all fields of a
%% class, and for each typefield it checks if the object has that
%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- if
- M == CurrMod ->
- emit([indent(12),"'enc_",T,"'(Val)"]);
- true ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
-%% Tag = [encode_tag_val((decode_class(X#tag.class) bsl 10) +
-%% X#tag.number) ||
-%% X <- OTag],
- Tag = [encode_tag_val(decode_class(X#tag.class),
- X#tag.form,X#tag.number) ||
- X <- OTag],
- emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",{asis,Tag},")"])
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[]);
- false ->
- %% This field was not present in the object thus there
- %% were no type in the table and we therefore generate
- %% code that returns the input for application treatment.
- emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Val of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Val)",nl,
- indent(12),"end,",nl,
- indent(12),"{Val,Len}"]),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,[])
- end;
+gen_inlined_enc_funs(Fields, [{typefield,_,_}|_]=T, ObjSetName, NthObj) ->
+ emit([indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl]),
+ gen_inlined_enc_funs1(Fields, T, ObjSetName, [], NthObj, []);
gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
gen_inlined_enc_funs(_,[],_,NthObj) ->
{[],NthObj}.
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
+gen_inlined_enc_funs1(Fields, [{typefield,Name,_}|Rest], ObjSetName,
+ Sep0, NthObj, Acc0) ->
+ emit(Sep0),
+ Sep = [";",nl],
CurrMod = get(currmod),
InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Acc,NAdd} =
+ case lists:keyfind(Name,1,Fields) of
+ {_,#type{}=Type} ->
+ {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ {Ret,N} = emit_inner_of_fun(Type, InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#'Externaltypereference'{module=M,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
if
- M == CurrMod ->
+ M =:= CurrMod ->
emit([indent(12),"'enc_",T,"'(Val)"]);
true ->
#typedef{typespec=Type} = asn1_db:dbget(M,T),
@@ -1370,27 +1154,30 @@ gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
Tag = [encode_tag_val(decode_class(X#tag.class),
X#tag.form,X#tag.number) ||
X <- OTag],
- emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",{asis,Tag},")"])
+ emit([indent(12),"'",M,"':'enc_",T,"'(Val, ",
+ {asis,Tag},")"])
end,
- {Acc,0};
+ {Acc0,0};
false ->
%% This field was not present in the object thus there
%% were no type in the table and we therefore generate
%% code that returns the input for application
%% treatment.
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"Len = case Val of",nl,
- indent(15),"Bin when is_binary(Bin) -> size(Bin);",nl,
- indent(15),"_ -> length(Val)",nl,indent(12),"end,",nl,
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"Len = case Val of",nl,
+ indent(15),"Bin when is_binary(Bin) -> "
+ "byte_size(Bin);",nl,
+ indent(15),"_ -> length(Val)",nl,
+ indent(12),"end,",nl,
indent(12),"{Val,Len}"]),
- {Acc,0}
+ {Acc0,0}
end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
+ gen_inlined_enc_funs1(Fields, Rest, ObjSetName, Sep, NthObj+NAdd, Acc);
+gen_inlined_enc_funs1(Fields,[_|Rest], ObjSetName, Sep, NthObj, Acc)->
+ gen_inlined_enc_funs1(Fields, Rest, ObjSetName, Sep, NthObj, Acc);
+gen_inlined_enc_funs1(_, [], _, _, NthObj, Acc) ->
+ emit([nl,indent(6),"end",nl,
+ indent(3),"end"]),
{Acc,NthObj}.
emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
@@ -1429,10 +1216,6 @@ emit_inner_of_fun(Type,_) when is_record(Type,type) ->
X#tag.form,X#tag.number)||X <- OTag],
emit([indent(9),Def," ->",nl,indent(12)]),
gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val)"]);
#'Externaltypereference'{module=CurrMod,type=T} ->
emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
"'(Val)"]);
@@ -1455,8 +1238,8 @@ gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
%% There is no unique field in the class of this object set
%% don't bother about the constraint
ok;
-gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj)->
+gen_objset_dec(Erules, ObjSName, UniqueName, [{ObjName,Val,Fields}|T],
+ ClName, ClFields, NthObj)->
emit(["'getdec_",ObjSName,"'(",{asis,UniqueName},",",
{asis,Val},") ->",nl]),
CurrMod = get(currmod),
@@ -1469,144 +1252,62 @@ gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
NthObj;
{ModuleName,Name} ->
emit_ext_fun(dec,ModuleName,Name),
-% emit([" {'",ModuleName,"', 'dec_",Name,"'}"]),
NthObj;
_ ->
emit([" fun 'dec_",ObjName,"'/3"]),
NthObj
end,
emit([";",nl]),
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,
- ClFields,NewNthObj);
-gen_objset_dec(_,ObjSetName,UniqueName,[{ObjName,Val,Fields}],
- _ClName,ClFields,NthObj) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl]),
- CurrMod = get(currmod),
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/3"]);
- {ModuleName,Name} ->
- emit_ext_fun(dec,ModuleName,Name);
-% emit([" {'",ModuleName,"', 'dec_",Name,"'}"]);
- _ ->
- emit([" fun 'dec_",ObjName,"'/3"])
- end,
- emit([";",nl]),
- emit_default_getdec(ObjSetName,UniqueName),
- emit([".",nl,nl]),
- ok;
-gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
+ gen_objset_dec(Erules, ObjSName, UniqueName, T, ClName,
+ ClFields, NewNthObj);
+gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj) ->
emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
- case Erules of
- ber_bin_v2 ->
- emit([indent(4),"case Bytes of",nl,
- indent(6),"Bin when is_binary(Bin) -> ",nl,
- indent(8),"Bin;",nl,
- indent(6),"_ ->",nl,
- indent(8),"?RT_BER:encode(Bytes",driver_parameter(),")",nl,
- indent(4),"end",nl]);
- _ ->
- emit([indent(6),"Len = case Bytes of",nl,indent(9),
- "Bin when is_binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Bytes)",nl,indent(6),"end,"]),
- emit([indent(4),"{Bytes,[],Len}",nl])
- end,
+ emit([indent(4),"case Bytes of",nl,
+ indent(6),"Bin when is_binary(Bin) -> ",nl,
+ indent(8),"Bin;",nl,
+ indent(6),"_ ->",nl,
+ indent(8),{call,ber,ber_encode,["Bytes"]},nl,
+ indent(4),"end",nl]),
emit([indent(2),"end.",nl,nl]),
ok;
-gen_objset_dec(_,_,_,[],_,_,_) ->
+gen_objset_dec(_, ObjSetName, UniqueName, [], _, _, _) ->
+ emit_default_getdec(ObjSetName, UniqueName),
+ emit([".",nl,nl]),
ok.
-driver_parameter() ->
- Options = get(encoding_options),
- case {lists:member(driver,Options),lists:member(nif,Options)} of
- {true,_} -> ",nif";
- {_,true} -> ",nif";
- _ -> ",erlang"
- end.
-
emit_default_getdec(ObjSetName,UniqueName) ->
emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
emit([indent(2), "fun(C,V,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},", ErrV}}) end"]).
-gen_inlined_dec_funs(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- if
- M == CurrMod ->
- emit([indent(12),"'dec_",T,"'(Bytes)"]);
- true ->
- #typedef{typespec=Type} = asn1_db:dbget(M,T),
- OTag = Type#type.tag,
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number ||
- X <- OTag],
- emit([indent(12),"'",M,"':'dec_",T,"'(Bytes, ",{asis,Tag},")"])
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- false ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Bytes)",nl,
- indent(12),"end,",nl,
- indent(12),"{Bytes,[],Len}"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
+gen_inlined_dec_funs(Fields, ClFields, ObjSetName, NthObj) ->
+ emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl]),
+ gen_inlined_dec_funs1(Fields, ClFields, ObjSetName, "", NthObj).
-gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
+gen_inlined_dec_funs1(Fields, [{typefield,Name,Prop}|Rest],
+ ObjSetName, Sep0, NthObj) ->
+ emit(Sep0),
+ Sep = [";",nl],
DecProp = case Prop of
'OPTIONAL' -> opt_or_default;
{'DEFAULT',_} -> opt_or_default;
_ -> mandatory
end,
- CurrMod = get(currmod),
InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit([";",nl]),
+ N = case lists:keyfind(Name, 1, Fields) of
+ {_,#type{}=Type} ->
emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
+ {_,#'Externaltypereference'{module=M,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ CurrMod = get(currmod),
if
- M == CurrMod ->
+ M =:= CurrMod ->
emit([indent(12),"'dec_",T,"'(Bytes)"]);
true ->
#typedef{typespec=Type} = asn1_db:dbget(M,T),
@@ -1617,21 +1318,20 @@ gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
end,
0;
false ->
- emit([";",nl,
- indent(9),{asis,Name}," ->",nl,
+ emit([indent(9),{asis,Name}," ->",nl,
indent(12),"Len = case Bytes of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
+ indent(15),"B when is_binary(B) -> byte_size(B);",nl,
indent(15),"_ -> length(Bytes)",nl,
indent(12),"end,",nl,
indent(12),"{Bytes,[],Len}"]),
0
end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit([nl,indent(6),"end",nl]),
- emit([indent(3),"end"]),
+ gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N);
+gen_inlined_dec_funs1(Fields, [_|Rest], ObjSetName, Sep, NthObj)->
+ gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj);
+gen_inlined_dec_funs1(_, [], _, _, NthObj) ->
+ emit([nl,indent(6),"end",nl,
+ indent(3),"end"]),
NthObj.
emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
@@ -1687,10 +1387,9 @@ emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) ->
gen_internal_funcs(_,[]) ->
ok;
gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,
-% "'(Tlv, OptOrMand, TagIn) ->",nl]),
- "'(Tlv, TagIn) ->",nl]),
+ gen_encode_user(Erules, TypeDef, false),
+ emit([nl,nl,
+ "'dec_",TypeDef#typedef.name,"'(Tlv, TagIn) ->",nl]),
gen_decode_user(Erules,TypeDef),
gen_internal_funcs(Erules,Rest).
@@ -1741,59 +1440,23 @@ decode_type('BMPString') -> 30;
decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-add_removed_bytes() ->
- asn1ct_name:delete(rb),
- add_removed_bytes(asn1ct_name:all(rb)).
-
-add_removed_bytes([H,T1|T]) ->
- emit({{var,H},"+"}),
- add_removed_bytes([T1|T]);
-add_removed_bytes([H|T]) ->
- emit({{var,H}}),
- add_removed_bytes(T);
-add_removed_bytes([]) ->
- true.
-
-mkfuncname(WhatKind,DecOrEnc) ->
- case WhatKind of
- #'Externaltypereference'{module=Mod,type=EType} ->
- CurrMod = get(currmod),
- case CurrMod of
- Mod ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- _ ->
-% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
- lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
- end;
- #'typereference'{val=EType} ->
+mkfuncname(#'Externaltypereference'{module=Mod,type=EType}, DecOrEnc) ->
+ CurrMod = get(currmod),
+ case CurrMod of
+ Mod ->
lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
-
+ _ ->
+ lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
end.
-optionals(L) -> optionals(L,[],1).
-
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
- lists:reverse(Acc).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
+get_size_constraint(C) ->
+ case lists:keyfind('SizeConstraint', 1, C) of
+ false -> [];
+ {_,{_,[]}} -> []; %Extensible.
+ {_,{Sv,Sv}} -> Sv;
+ {_,{_,_}=Tc} -> Tc
end.
-
get_class_fields(#classdef{typespec=ObjClass}) ->
ObjClass#objectclass.fields;
get_class_fields(#objectclass{fields=Fields}) ->
@@ -1833,9 +1496,6 @@ mk_object_val(0, Ack, Len) ->
mk_object_val(Val, Ack, Len) ->
mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-add_func(F={_Func,_Arity}) ->
- asn1ct_table:insert(asn1_functab, {F}).
-
%% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding
%% and therefore we only filter away the ExtensionAdditionGroup start and end markers
extaddgroup2sequence(ExtList) when is_list(ExtList) ->
@@ -1847,4 +1507,8 @@ extaddgroup2sequence(ExtList) when is_list(ExtList) ->
true
end, ExtList).
+call(F, Args) ->
+ asn1ct_func:call(ber, F, Args).
+need(F, Arity) ->
+ asn1ct_func:need({ber,F,Arity}).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index bd5b81991d..69d9d51bf1 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -25,26 +25,16 @@
-include("asn1_records.hrl").
%-compile(export_all).
--export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
+-export([gen_dec_imm/2]).
+-export([gen_dec_prim/3,gen_encode_prim/3]).
-export([gen_obj_code/3,gen_objectset_code/2]).
-export([gen_decode/2, gen_decode/3]).
-export([gen_encode/2, gen_encode/3]).
--export([is_already_generated/2,more_genfields/1,get_class_fields/1,
- get_object_field/2]).
+-export([gen_dec_external/2]).
-export([extaddgroup2sequence/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
+-import(asn1ct_func, [call/3]).
%% Generate ENCODING ******************************
@@ -78,18 +68,6 @@ gen_encode(Erules,Typename,Type) when is_record(Type,type) ->
end,
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
- case InnerType of
- 'SET' ->
- true;
- 'SEQUENCE' ->
- true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}",ObjFun,") ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",ObjFun,");",nl,nl})
- end,
emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
") ->",nl}),
asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
@@ -103,297 +81,177 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
Typename = [D#typedef.name],
Def = D#typedef.typespec,
InnerType = asn1ct_gen:get_inner(Def#type.def),
- case InnerType of
- 'SET' -> true;
- 'SEQUENCE' -> true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
- end,
emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
case asn1ct_gen:type(InnerType) of
{primitive,bif} ->
- gen_encode_prim(Erules,Def,"false"),
+ gen_encode_prim(Erules, Def),
emit({".",nl});
'ASN1_OPEN_TYPE' ->
- gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
+ gen_encode_prim(Erules, Def#type{def='ASN1_OPEN_TYPE'}),
emit({".",nl});
{constructed,bif} ->
asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
#'Externaltypereference'{module=CurrMod,type=Etype} ->
emit({"'enc_",Etype,"'(Val).",nl,nl});
#'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(Val).",nl,nl});
- {notype,_} ->
- emit({"'enc_",InnerType,"'(Val).",nl,nl})
+ emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl})
end.
-gen_encode_prim(Erules,D,DoTag) ->
- Value = case asn1ct_name:active(val) of
- true ->
- asn1ct_gen:mk_var(asn1ct_name:curr(val));
- false ->
- "Val"
- end,
- gen_encode_prim(Erules,D,DoTag,Value).
-
-gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
+gen_encode_prim(Erules, D) ->
+ Value = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ gen_encode_prim(Erules, D, Value).
+
+gen_encode_prim(Erules, #type{def={'ENUMERATED',{N1,N2}}}, Value) ->
+ NewList = [{0,X} || {X,_} <- N1] ++ ['EXT_MARK'] ++
+ [{1,X} || {X,_} <- N2],
+ NewC = {0,length(N1)-1},
+ emit(["case ",Value," of",nl]),
+ emit_enc_enumerated_cases(Erules, NewC, NewList, 0);
+gen_encode_prim(Erules, #type{def={'ENUMERATED',NNL}}, Value) ->
+ NewList = [X || {X,_} <- NNL],
+ NewC = {0,length(NewList)-1},
+ emit(["case ",Value," of",nl]),
+ emit_enc_enumerated_cases(Erules, NewC, NewList, 0);
+gen_encode_prim(per=Erules, D, Value) ->
+ asn1ct_gen_per_rt2ct:gen_encode_prim(Erules, D, Value);
+gen_encode_prim(Erules, #type{}=D, Value) ->
Constraint = D#type.constraint,
- asn1ct_name:new(enumval),
+ SizeConstr = asn1ct_imm:effective_constraint(bitstring, Constraint),
+ Pa = case lists:keyfind('PermittedAlphabet', 1, Constraint) of
+ false -> no;
+ {_,Pa0} -> Pa0
+ end,
case D#type.def of
'INTEGER' ->
- emit({"?RT_PER:encode_integer(", %fel
- {asis,effective_constraint(integer,Constraint)},",",Value,")"});
+ Args = [{asis,asn1ct_imm:effective_constraint(integer,Constraint)},
+ Value],
+ call(Erules, encode_integer, Args);
{'INTEGER',NamedNumberList} ->
- emit({"?RT_PER:encode_integer(",
- {asis,effective_constraint(integer,Constraint)},",",Value,",",
- {asis,NamedNumberList},")"});
- {'ENUMERATED',{Nlist1,Nlist2}} ->
- NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
- NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
- case Erules of
- uper_bin ->
- emit(["case ",Value," of",nl]);
- _ ->
- emit(["case (case ",Value," of {_,",{curr,enumval},"}-> ",
- {curr,enumval},";_->", Value," end) of",nl]),
- asn1ct_name:new(enumval)
- end,
-%% emit_enc_enumerated_cases(Erules,NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
- emit_enc_enumerated_cases(Erules,NewC, NewList, 0);
- {'ENUMERATED',NamedNumberList} ->
- NewList = [X||{X,_} <- NamedNumberList],
- NewC = [{'ValueRange',{0,length(NewList)-1}}],
- case Erules of
- uper_bin ->
- emit(["case ",Value," of",nl]);
- _ ->
- emit(["case (case ",Value," of {_,",{curr,enumval},
- "}->",{curr,enumval},";_->",Value," end) of",nl])
- end,
- emit_enc_enumerated_cases(Erules,NewC, NewList, 0);
-
+ Args = [{asis,asn1ct_imm:effective_constraint(integer,Constraint)},
+ Value,{asis,NamedNumberList}],
+ call(Erules, encode_integer, Args);
'REAL' ->
- emit({"?RT_PER:encode_real(",Value,")"});
+ emit_enc_real(Erules, Value);
{'BIT STRING',NamedNumberList} ->
- emit({"?RT_PER:encode_bit_string(",
- {asis,Constraint},",",Value,",",
- {asis,NamedNumberList},")"});
+ call(Erules, encode_bit_string,
+ [{asis,SizeConstr},Value,
+ {asis,NamedNumberList}]);
'NULL' ->
- emit({"?RT_PER:encode_null(",Value,")"});
+ emit("[]");
'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:encode_object_identifier(",Value,")"});
+ call(Erules, encode_object_identifier, [Value]);
'RELATIVE-OID' ->
- emit({"?RT_PER:encode_relative_oid(",Value,")"});
+ call(Erules, encode_relative_oid, [Value]);
'ObjectDescriptor' ->
- emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_ObjectDescriptor,
+ [{asis,Constraint},Value]);
'BOOLEAN' ->
- emit({"?RT_PER:encode_boolean(",Value,")"});
+ call(Erules, encode_boolean, [Value]);
'OCTET STRING' ->
- emit({"?RT_PER:encode_octet_string(",{asis,Constraint},",",Value,")"});
+ case SizeConstr of
+ 0 ->
+ emit("[]");
+ no ->
+ call(Erules, encode_octet_string, [Value]);
+ C ->
+ call(Erules, encode_octet_string, [{asis,C},Value])
+ end;
'NumericString' ->
- emit({"?RT_PER:encode_NumericString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_NumericString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
TString when TString == 'TeletexString';
TString == 'T61String' ->
- emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_TeletexString, [{asis,Constraint},Value]);
'VideotexString' ->
- emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_VideotexString, [{asis,Constraint},Value]);
'UTCTime' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_VisibleString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'GeneralizedTime' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_VisibleString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'GraphicString' ->
- emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_GraphicString, [{asis,Constraint},Value]);
'VisibleString' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_VisibleString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'GeneralString' ->
- emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_GeneralString, [{asis,Constraint},Value]);
'PrintableString' ->
- emit({"?RT_PER:encode_PrintableString(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_PrintableString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'IA5String' ->
- emit({"?RT_PER:encode_IA5String(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_IA5String, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'BMPString' ->
- emit({"?RT_PER:encode_BMPString(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_BMPString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'UniversalString' ->
- emit({"?RT_PER:encode_UniversalString(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_UniversalString, [{asis,SizeConstr},
+ {asis,Pa},Value]);
'UTF8String' ->
- emit({"?RT_PER:encode_UTF8String(",Value,")"});
- 'ANY' ->
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- Value, ")"]);
+ call(Erules, encode_UTF8String, [Value]);
'ASN1_OPEN_TYPE' ->
NewValue = case Constraint of
[#'Externaltypereference'{type=Tname}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ asn1ct_func:need({Erules,complete,1}),
+ io_lib:format(
+ "complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
+ asn1ct_func:need({Erules,complete,1}),
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",
+ "complete(enc_~s(~s))",
[Tname,Value]);
- _ -> Value
+ _ ->
+ io_lib:format("iolist_to_binary(~s)",
+ [Value])
end,
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- NewValue, ")"]);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(D#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_encode_prim(Erules,InnerType,DoTag,Value);
- T -> %% 'ASN1_OPEN_TYPE'
- gen_encode_prim(Erules,D#type{def=T},DoTag,Value)
- end;
- XX ->
- exit({asn1_error,nyi,XX})
+ call(Erules, encode_open_type, [NewValue])
end.
-
-emit_enc_enumerated_cases(Erule,C, [H], Count) ->
- emit_enc_enumerated_case(Erule,C, H, Count),
- case H of
- 'EXT_MARK' -> ok;
- _ ->
- emit([";",nl])
- end,
- emit([nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
- emit([nl,"end"]);
-emit_enc_enumerated_cases(Erule, C, ['EXT_MARK'|T], _Count) ->
- emit_enc_enumerated_cases(Erule, C, T, 0);
-emit_enc_enumerated_cases(Erule, C, [H1,H2|T], Count) ->
- emit_enc_enumerated_case(Erule, C, H1, Count),
+emit_enc_real(Erules, Real) ->
+ asn1ct_name:new(tmpval),
+ asn1ct_name:new(tmplen),
+ emit(["begin",nl,
+ "{",{curr,tmpval},com,{curr,tmplen},"} = ",
+ {call,real_common,encode_real,[Real]},com,nl,
+ "[",{call,Erules,encode_length,[{curr,tmplen}]},",",
+ {curr,tmpval},"]",nl,
+ "end"]).
+
+emit_enc_enumerated_cases(Erules, C, ['EXT_MARK'|T], _Count) ->
+ %% Reset enumeration counter.
+ emit_enc_enumerated_cases(Erules, C, T, 0);
+emit_enc_enumerated_cases(Erules, C, [H|T], Count) ->
+ emit_enc_enumerated_case(Erules, C, H, Count),
emit([";",nl]),
- emit_enc_enumerated_cases(Erule, C, [H2|T], Count+1).
+ emit_enc_enumerated_cases(Erules, C, T, Count+1);
+emit_enc_enumerated_cases(_Erules, _, [], _Count) ->
+ emit(["EnumVal -> "
+ "exit({error,{asn1,{enumerated_not_in_range, EnumVal}}})",nl,
+ "end"]).
-
-
-emit_enc_enumerated_case(uper_bin,_C, {asn1_enum,High}, _) ->
- emit([
- "{asn1_enum,EnumV} when is_integer(EnumV), EnumV > ",High," -> ",
- "[<<1:1>>,?RT_PER:encode_small_number(EnumV)]"]);
-emit_enc_enumerated_case(_Per,_C, {asn1_enum,High}, _) ->
- emit([
- "{asn1_enum,EnumV} when is_integer(EnumV), EnumV > ",High," -> ",
- "[{bit,1},?RT_PER:encode_small_number(EnumV)]"]);
-emit_enc_enumerated_case(_Erule, _C, 'EXT_MARK', _Count) ->
- true;
-emit_enc_enumerated_case(uper_bin,_C, {1,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [<<1:1>>,?RT_PER:encode_small_number(",Count,")]"]);
-emit_enc_enumerated_case(_Per,_C, {1,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [{bit,1},?RT_PER:encode_small_number(",Count,")]"]);
-emit_enc_enumerated_case(uper_bin,C, {0,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [<<0:1>>,?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
-emit_enc_enumerated_case(_Per,C, {0,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [{bit,0},?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
-emit_enc_enumerated_case(_Erule, C, EnumName, Count) ->
- emit(["'",EnumName,"' -> ?RT_PER:encode_integer(",{asis,C},", ",Count,")"]).
-
-%% effective_constraint(Type,C)
-%% Type = atom()
-%% C = [C1,...]
-%% C1 = {'SingleValue',SV} | {'ValueRange',VR} | {atom(),term()}
-%% SV = integer() | [integer(),...]
-%% VR = {Lb,Ub}
-%% Lb = 'MIN' | integer()
-%% Ub = 'MAX' | integer()
-%% Returns a single value if C only has a single value constraint, and no
-%% value range constraints, that constrains to a single value, otherwise
-%% returns a value range that has the lower bound set to the lowest value
-%% of all single values and lower bound values in C and the upper bound to
-%% the greatest value.
-effective_constraint(integer,[C={{_,_},_}|_Rest]) -> % extension
- [C]; %% [C|effective_constraint(integer,Rest)]; XXX what is possible ???
-effective_constraint(integer,C) ->
- SVs = get_constraints(C,'SingleValue'),
- SV = effective_constr('SingleValue',SVs),
- VRs = get_constraints(C,'ValueRange'),
- VR = effective_constr('ValueRange',VRs),
- greatest_common_range(SV,VR).
-
-effective_constr(_,[]) ->
- [];
-effective_constr('SingleValue',List) ->
- SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
- %% Sort and remove duplicates before generating SingleValue or ValueRange
- %% In case of ValueRange, also check for 'MIN and 'MAX'
- case lists:usort(SVList) of
- [N] ->
- [{'SingleValue',N}];
- L when is_list(L) ->
- [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}]
- end;
-effective_constr('ValueRange',List) ->
- LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
- UBs = lists:map(fun({_,{_,Ub}})-> Ub end,List),
- Lb = least_Lb(LBs),
- [{'ValueRange',{Lb,lists:max(UBs)}}].
-
-greatest_common_range([],VR) ->
- VR;
-greatest_common_range(SV,[]) ->
- SV;
-greatest_common_range(SV,VR) ->
- greatest_common_range2(mk_vr(SV),mk_vr(VR)).
-greatest_common_range2({_,Int},{'MIN',Ub}) when is_integer(Int),
- Int > Ub ->
- [{'ValueRange',{'MIN',Int}}];
-greatest_common_range2({_,Int},{Lb,Ub}) when is_integer(Int),
- Int < Lb ->
- [{'ValueRange',{Int,Ub}}];
-greatest_common_range2({_,Int},VR={_Lb,_Ub}) when is_integer(Int) ->
- [{'ValueRange',VR}];
-greatest_common_range2({_,L},{Lb,Ub}) when is_list(L) ->
- Min = least_Lb([Lb|L]),
- Max = greatest_Ub([Ub|L]),
- [{'ValueRange',{Min,Max}}];
-greatest_common_range2({Lb1,Ub1},{Lb2,Ub2}) ->
- Min = least_Lb([Lb1,Lb2]),
- Max = greatest_Ub([Ub1,Ub2]),
- [{'ValueRange',{Min,Max}}].
-
-mk_vr([{Type,I}]) when is_atom(Type), is_integer(I) ->
- {I,I};
-mk_vr([{Type,{Lb,Ub}}]) when is_atom(Type) ->
- {Lb,Ub};
-mk_vr(Other) ->
- Other.
-
-least_Lb(L) ->
- case lists:member('MIN',L) of
- true -> 'MIN';
- _ -> lists:min(L)
- end.
-
-greatest_Ub(L) ->
- case lists:member('MAX',L) of
- true -> 'MAX';
- _ -> lists:max(L)
- end.
-
-
-get_constraints(L=[{Key,_}],Key) ->
- L;
-get_constraints([],_) ->
- [];
-get_constraints(C,Key) ->
- {value,L} = keysearch_allwithkey(Key,1,C,[]),
- L.
-
-keysearch_allwithkey(Key,Ix,C,Acc) ->
- case lists:keysearch(Key,Ix,C) of
- false ->
- {value,Acc};
- {value,T} ->
- RestC = lists:delete(T,C),
- keysearch_allwithkey(Key,Ix,RestC,[T|Acc])
- end.
+emit_enc_enumerated_case(Erules, C, {0,EnumName}, Count) ->
+ %% ENUMERATED with extensionmark; the value lies within then extension root
+ Enc = enc_ext_and_val(Erules, 0, encode_constrained_number, [C,Count]),
+ emit(["'",EnumName,"' -> ",{asis,Enc}]);
+emit_enc_enumerated_case(Erules, _C, {1,EnumName}, Count) ->
+ %% ENUMERATED with extensionmark; the value is higher than extension root
+ Enc = enc_ext_and_val(Erules, 1, encode_small_number, [Count]),
+ emit(["'",EnumName,"' -> ",{asis,Enc}]);
+emit_enc_enumerated_case(Erules, C, EnumName, Count) ->
+ %% ENUMERATED without extension
+ EvalMod = eval_module(Erules),
+ emit(["'",EnumName,"' -> ",
+ {asis,EvalMod:encode_constrained_number(C, Count)}]).
+
+enc_ext_and_val(per, E, F, Args) ->
+ [E|apply(asn1ct_eval_per, F, Args)];
+enc_ext_and_val(uper, E, F, Args) ->
+ Bs = list_to_bitstring([apply(asn1ct_eval_uper, F, Args)]),
+ <<E:1,Bs/bitstring>>.
%% Object code generating for encoding and decoding
@@ -416,17 +274,16 @@ gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
gen_encode_constr_type(Erules,EncConstructed),
emit(nl),
DecConstructed =
- gen_decode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
+ gen_decode_objectfields(Erules, ClassName, get_class_fields(Class),
+ ObjName, Fields, []),
emit(nl),
gen_decode_constr_type(Erules,DecConstructed),
- emit(nl);
-gen_obj_code(_,_,Obj) when is_record(Obj,pobjectdef) ->
- ok.
+ emit(nl).
-gen_encode_objectfields(Erule,ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
+gen_encode_objectfields(Erule, ClassName,
+ [{typefield,Name,OptOrMand}|Rest],
+ ObjName, ObjectFields, ConstrAcc) ->
EmitFuncClause =
fun(V) ->
emit(["'enc_",ObjName,"'(",{asis,Name},
@@ -442,20 +299,26 @@ gen_encode_objectfields(Erule,ClassName,[{typefield,Name,OptOrMand}|Rest],
{false,'OPTIONAL'} ->
EmitFuncClause("Val"),
case Erule of
- uper_bin ->
+ uper ->
emit(" Val");
- _ ->
- emit(" [{octets,Val}]")
+ per ->
+ emit([" if",nl,
+ " is_list(Val) ->",nl,
+ " NewVal = list_to_binary(Val),",nl,
+ " [20,byte_size(NewVal),NewVal];",nl,
+ " is_binary(Val) ->",nl,
+ " [20,byte_size(Val),Val]",nl,
+ " end"])
end,
[];
{false,{'DEFAULT',DefaultType}} ->
EmitFuncClause("Val"),
- gen_encode_default_call(ClassName,Name,DefaultType);
+ gen_encode_default_call(Erule, ClassName, Name, DefaultType);
{{Name,TypeSpec},_} ->
%% A specified field owerwrites any 'DEFAULT' or
%% 'OPTIONAL' field in the class
EmitFuncClause("Val"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
+ gen_encode_field_call(Erule, ObjName, Name, TypeSpec)
end,
case more_genfields(Rest) of
true ->
@@ -531,7 +394,7 @@ gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
gen_encode_constr_type(_,[]) ->
ok.
-gen_encode_field_call(_ObjName,_FieldName,
+gen_encode_field_call(_Erules, _ObjName, _FieldName,
#'Externaltypereference'{module=M,type=T}) ->
CurrentMod = get(currmod),
if
@@ -542,12 +405,11 @@ gen_encode_field_call(_ObjName,_FieldName,
emit({" '",M,"':'enc_",T,"'(Val)"}),
[]
end;
-gen_encode_field_call(ObjName,FieldName,Type) ->
+gen_encode_field_call(Erules, ObjName, FieldName, Type) ->
Def = Type#typedef.typespec,
case Type#typedef.name of
{primitive,bif} ->
- gen_encode_prim(per,Def,"false",
- "Val"),
+ gen_encode_prim(Erules, Def, "Val"),
[];
{constructed,bif} ->
emit({" 'enc_",ObjName,'_',FieldName,
@@ -563,7 +425,7 @@ gen_encode_field_call(ObjName,FieldName,Type) ->
[]
end.
-gen_encode_default_call(ClassName,FieldName,Type) ->
+gen_encode_default_call(Erules, ClassName, FieldName, Type) ->
CurrentMod = get(currmod),
InnerType = asn1ct_gen:get_inner(Type#type.def),
case asn1ct_gen:type(InnerType) of
@@ -574,7 +436,7 @@ gen_encode_default_call(ClassName,FieldName,Type) ->
[#typedef{name=[FieldName,ClassName],
typespec=Type}];
{primitive,bif} ->
- gen_encode_prim(per,Type,"false","Val"),
+ gen_encode_prim(Erules, Type, "Val"),
[];
#'Externaltypereference'{module=CurrentMod,type=Etype} ->
emit([" 'enc_",Etype,"'(Val)",nl]),
@@ -585,8 +447,9 @@ gen_encode_default_call(ClassName,FieldName,Type) ->
end.
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
+gen_decode_objectfields(Erules, ClassName,
+ [{typefield,Name,OptOrMand}|Rest],
+ ObjName, ObjectFields, ConstrAcc) ->
EmitFuncClause =
fun(Bytes) ->
emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
@@ -603,12 +466,13 @@ gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
[];
{false,{'DEFAULT',DefaultType}} ->
EmitFuncClause("Bytes"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
+ gen_decode_default_call(Erules, ClassName, Name, "Bytes",
+ DefaultType);
{{Name,TypeSpec},_} ->
%% A specified field owerwrites any 'DEFAULT' or
%% 'OPTIONAL' field in the class
EmitFuncClause("Bytes"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
+ gen_decode_field_call(Erules, ObjName, Name, "Bytes", TypeSpec)
end,
case more_genfields(Rest) of
true ->
@@ -616,9 +480,11 @@ gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
false ->
emit([".",nl])
end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
+ gen_decode_objectfields(Erules, ClassName, Rest, ObjName,
+ ObjectFields, MaybeConstr++ConstrAcc);
+gen_decode_objectfields(Erules, ClassName,
+ [{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName, ObjectFields, ConstrAcc) ->
CurrentMod = get(currmod),
EmitFuncClause =
fun(Attrs) ->
@@ -661,30 +527,25 @@ gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
false ->
emit([".",nl])
end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
+ gen_decode_objectfields(Erules, ClassName, Rest, ObjName,
+ ObjectFields, ConstrAcc);
+gen_decode_objectfields(Erules, CN, [_C|Cs], O, OF, CAcc) ->
+ gen_decode_objectfields(Erules, CN, Cs, O, OF, CAcc);
+gen_decode_objectfields(_, _, [], _, _, CAcc) ->
CAcc.
-gen_decode_field_call(_ObjName,_FieldName,Bytes,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- if
- M == CurrentMod ->
- emit([" 'dec_",T,"'(",Bytes,", telltype)"]),
- [];
- true ->
- emit([" '",M,"':'dec_",T,"'(",Bytes,", telltype)"]),
- []
- end;
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
+gen_decode_field_call(_Erules, _ObjName, _FieldName, Bytes,
+ #'Externaltypereference'{}=Etype) ->
+ emit(" "),
+ gen_dec_external(Etype, Bytes),
+ [];
+gen_decode_field_call(Erules, ObjName, FieldName, Bytes, Type) ->
Def = Type#typedef.typespec,
case Type#typedef.name of
{primitive,bif} ->
- gen_dec_prim(per,Def,Bytes),
+ gen_dec_prim(Erules, Def, Bytes),
[];
{constructed,bif} ->
emit({" 'dec_",ObjName,'_',FieldName,
@@ -700,8 +561,7 @@ gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
[]
end.
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
+gen_decode_default_call(Erules, ClassName, FieldName, Bytes, Type) ->
InnerType = asn1ct_gen:get_inner(Type#type.def),
case asn1ct_gen:type(InnerType) of
{constructed,bif} ->
@@ -710,13 +570,10 @@ gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
[#typedef{name=[FieldName,ClassName],
typespec=Type}];
{primitive,bif} ->
- gen_dec_prim(per,Type,Bytes),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ gen_dec_prim(Erules, Type, Bytes),
[];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ #'Externaltypereference'{}=Etype ->
+ asn1ct_gen_per:gen_dec_external(Etype, Bytes),
[]
end.
@@ -772,7 +629,7 @@ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
InternalFuncs=
gen_objset_enc(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
- gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
+ gen_objset_dec(Erules, ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
gen_internal_funcs(Erules,InternalFuncs).
%% gen_objset_enc iterates over the objects of the object set
@@ -780,67 +637,56 @@ gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
%% There is no unique field in the class of this object set
%% don't bother about the constraint
[];
-gen_objset_enc(Erule,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
+gen_objset_enc(Erule, ObjSetName, UniqueName, [{ObjName,Val,Fields}|T],
+ ClName, ClFields, NthObj, Acc)->
+ emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl]),
CurrMod = get(currmod),
{InternalFunc,NewNthObj}=
case ObjName of
{no_mod,no_name} ->
- gen_inlined_enc_funs(Erule,Fields,ClFields,ObjSName,NthObj);
+ gen_inlined_enc_funs(Erule, Fields, ClFields,
+ ObjSetName, NthObj);
{CurrMod,Name} ->
emit({" fun 'enc_",Name,"'/3"}),
{[],0};
{ModName,Name} ->
emit_ext_encfun(ModName,Name),
-% emit([" {'",ModName,"', 'enc_",Name,"'}"]),
{[],0};
_Other ->
emit({" fun 'enc_",ObjName,"'/3"}),
{[],0}
end,
emit({";",nl}),
- gen_objset_enc(Erule,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(Erule,ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
-
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,_}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Erule,Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModName,Name} ->
- emit_ext_encfun(ModName,Name),
-% emit([" {'",ModName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _Other ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit([";",nl]),
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- InternalFunc++Acc;
-gen_objset_enc(Erule,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj,Acc) ->
+ gen_objset_enc(Erule, ObjSetName, UniqueName, T, ClName, ClFields,
+ NewNthObj, InternalFunc ++ Acc);
+gen_objset_enc(uper, ObjSetName, _UniqueName, ['EXTENSIONMARK'],
+ _ClName, _ClFields, _NthObj, Acc) ->
emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
emit({indent(3),"fun(_, Val, _) ->",nl}),
- case Erule of
- uper_bin ->
- emit([indent(6),"Val",nl]);
- _ ->
- emit([indent(6),"[{octets,Val}]",nl])
- end,
- emit({indent(3),"end.",nl,nl}),
+ emit([indent(6),"Val",nl,
+ indent(3),"end.",nl,nl]),
Acc;
-gen_objset_enc(_,_,_,[],_,_,_,Acc) ->
+gen_objset_enc(per, ObjSetName, _UniqueName, ['EXTENSIONMARK'],
+ _ClName, _ClFields, _NthObj, Acc) ->
+ emit(["'getenc_",ObjSetName,"'(_, _) ->",nl,
+ indent(3),"fun(_, Val, _) ->",nl,
+ indent(6),"BinVal = if",nl,
+ indent(9),"is_list(Val) -> list_to_binary(Val);",nl,
+ indent(9),"true -> Val",nl,
+ indent(6),"end,",nl,
+ indent(6),"Size = byte_size(BinVal),",nl,
+ indent(6),"if",nl,
+ indent(9),"Size < 256 ->",nl,
+ indent(12),"[20,Size,BinVal];",nl,
+ indent(9),"true ->",nl,
+ indent(12),"[21,<<Size:16>>,Val]",nl,
+ indent(6),"end",nl,
+ indent(3),"end.",nl,nl]),
+ Acc;
+gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) ->
+ emit_default_getenc(ObjSetName, UniqueName),
+ emit([".",nl,nl]),
Acc.
emit_ext_encfun(ModuleName,Name) ->
@@ -855,97 +701,70 @@ emit_default_getenc(ObjSetName,UniqueName) ->
%% gen_inlined_enc_funs for each object iterates over all fields of a
%% class, and for each typefield it checks if the object has that
%% field and emits the proper code.
-gen_inlined_enc_funs(Erule,Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'enc_",T,"'(Val)"]),
-% {Ret,N} = emit_inner_of_fun(TDef,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[]);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[]);
- false when Erule == uper_bin ->
- emit([indent(3),"fun(Type,Val,_) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," -> Val",nl]),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[]);
- false ->
- emit([indent(3),"fun(Type,Val,_) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," -> [{octets,Val}]",nl]),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[])
- end;
+gen_inlined_enc_funs(Erule, Fields, [{typefield,_,_}|_]=T,
+ ObjSetName, NthObj) ->
+ emit([indent(3),"fun(Type, Val, _) ->",nl,
+ indent(6),"case Type of",nl]),
+ gen_inlined_enc_funs1(Erule, Fields, T, ObjSetName, [], NthObj, []);
gen_inlined_enc_funs(Erule,Fields,[_H|Rest],ObjSetName,NthObj) ->
gen_inlined_enc_funs(Erule,Fields,Rest,ObjSetName,NthObj);
gen_inlined_enc_funs(_,_,[],_,NthObj) ->
{[],NthObj}.
-gen_inlined_enc_funs1(Erule,Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
+gen_inlined_enc_funs1(Erule, Fields, [{typefield,Name,_}|Rest], ObjSetName,
+ Sep0, NthObj, Acc0) ->
+ emit(Sep0),
+ Sep = [";",nl],
CurrentMod = get(currmod),
InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'enc_",T,"'(Val)"]),
- {Acc,0};
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
- {Acc,0};
- false when Erule == uper_bin ->
- emit([";",nl,
- indent(9),{asis,Name}," -> ",nl,
- "Val",nl]),
- {Acc,0};
- false ->
- emit([";",nl,
- indent(9),{asis,Name}," -> ",nl,
- "[{octets,Val}]",nl]),
- {Acc,0}
+ {Acc,NAdd} =
+ case lists:keyfind(Name, 1, Fields) of
+ {_,#type{}=Type} ->
+ {Ret,N} = emit_inner_of_fun(Erule, Type, InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ {Ret,N} = emit_inner_of_fun(Erule, Type, InternalDefFunName),
+ {Ret++Acc0,N};
+ {_,#'Externaltypereference'{module=CurrentMod,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"'enc_",T,"'(Val)"]),
+ {Acc0,0};
+ {_,#'Externaltypereference'{module=M,type=T}} ->
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
+ {Acc0,0};
+ false when Erule =:= uper ->
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"Val",nl]),
+ {Acc0,0};
+ false when Erule =:= per ->
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12),"Size = case Val of",nl,
+ indent(15),"B when is_binary(B) -> size(B);",nl,
+ indent(15),"_ -> length(Val)",nl,
+ indent(12),"end,",nl,
+ indent(12),"if",nl,
+ indent(15),"Size < 256 -> [20,Size,Val];",nl,
+ indent(15),"true -> [21,<<Size:16>>,Val]",nl,
+ indent(12),"end"]),
+ {Acc0,0}
end,
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Erule,Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
+ gen_inlined_enc_funs1(Erule, Fields, Rest, ObjSetName, Sep,
+ NthObj+NAdd, Acc);
+gen_inlined_enc_funs1(Erule, Fields, [_|T], ObjSetName, Sep, NthObj, Acc)->
+ gen_inlined_enc_funs1(Erule, Fields, T, ObjSetName, Sep, NthObj, Acc);
+gen_inlined_enc_funs1(_, _, [], _, _, NthObj, Acc) ->
+ emit([nl,indent(6),"end",nl,
+ indent(3),"end"]),
{Acc,NthObj}.
-emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
+emit_inner_of_fun(Erule, #typedef{name={ExtMod,Name},typespec=Type}=TDef,
InternalDefFunName) ->
case {ExtMod,Name} of
{primitive,bif} ->
emit(indent(12)),
- gen_encode_prim(per,Type,dotag,"Val"),
+ gen_encode_prim(Erule, Type, "Val"),
{[],0};
{constructed,bif} ->
emit([indent(12),"'enc_",
@@ -955,18 +774,15 @@ emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
{[],0}
end;
-emit_inner_of_fun(#typedef{name=Name},_) ->
+emit_inner_of_fun(_Erule, #typedef{name=Name}, _) ->
emit({indent(12),"'enc_",Name,"'(Val)"}),
{[],0};
-emit_inner_of_fun(Type,_) when is_record(Type,type) ->
+emit_inner_of_fun(Erule, #type{}=Type, _) ->
CurrMod = get(currmod),
case Type#type.def of
Def when is_atom(Def) ->
emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(erules,Type,dotag,"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
+ gen_encode_prim(Erule, Type, "Val");
#'Externaltypereference'{module=CurrMod,type=T} ->
emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
#'Externaltypereference'{module=ExtMod,type=T} ->
@@ -979,63 +795,42 @@ indent(N) ->
lists:duplicate(N,32). % 32 = space
-gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
+gen_objset_dec(_, _, {unique,undefined}, _, _, _, _) ->
%% There is no unique field in the class of this object set
%% don't bother about the constraint
ok;
-gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
- ClFields,NthObj)->
-
+gen_objset_dec(Erule, ObjSName, UniqueName, [{ObjName,Val,Fields}|T], ClName,
+ ClFields, NthObj)->
emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
") ->",nl}),
CurrMod = get(currmod),
NewNthObj=
case ObjName of
{no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
+ gen_inlined_dec_funs(Erule, Fields, ClFields,
+ ObjSName, NthObj);
{CurrMod,Name} ->
emit([" fun 'dec_",Name,"'/4"]),
NthObj;
{ModName,Name} ->
emit_ext_decfun(ModName,Name),
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]),
NthObj;
_Other ->
emit({" fun 'dec_",ObjName,"'/4"}),
NthObj
end,
emit({";",nl}),
- gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
-gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
-
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- CurrMod=get(currmod),
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/4"]);
- {ModName,Name} ->
- emit_ext_decfun(ModName,Name);
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit([";",nl]),
- emit_default_getdec(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- ok;
-gen_objset_dec(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
+ gen_objset_dec(Erule, ObjSName, UniqueName, T, ClName, ClFields, NewNthObj);
+gen_objset_dec(_Erule, ObjSetName, _UniqueName, ['EXTENSIONMARK'],
+ _ClName, _ClFields, _NthObj) ->
emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
emit({indent(3),"fun(Attr1, Bytes, _,_) ->",nl}),
-%% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
emit({indent(6),"{Bytes,Attr1}",nl}),
emit({indent(3),"end.",nl,nl}),
ok;
-gen_objset_dec(_,_,[],_,_,_) ->
+gen_objset_dec(_Erule, ObjSetName, UniqueName, [], _, _, _) ->
+ emit_default_getdec(ObjSetName, UniqueName),
+ emit([".",nl,nl]),
ok.
emit_ext_decfun(ModuleName,Name) ->
@@ -1047,83 +842,46 @@ emit_default_getdec(ObjSetName,UniqueName) ->
emit([indent(2), "fun(C,V,_,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]).
-gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'dec_",T,"'(Val, telltype)"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"':'dec_",T,"'(Val, telltype)"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- false ->
- emit([indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->{Val,Type}"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
+gen_inlined_dec_funs(Erule, Fields, List, ObjSetName, NthObj0) ->
+ emit([indent(3),"fun(Type, Val, _, _) ->",nl,
+ indent(6),"case Type of",nl]),
+ NthObj = gen_inlined_dec_funs1(Erule, Fields, List,
+ ObjSetName, "", NthObj0),
+ emit([nl,indent(6),"end",nl,
+ indent(3),"end"]),
NthObj.
-gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrentMod = get(currmod),
+gen_inlined_dec_funs1(Erule, Fields, [{typefield,Name,_}|Rest],
+ ObjSetName, Sep0, NthObj) ->
InternalDefFunName = [NthObj,Name,ObjSetName],
- N=case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"'dec_",T,"'(Val,telltype)"]),
- 0;
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"'",M,"'",":'dec_",T,"'(Val,telltype)"]),
- 0;
- false ->
- emit([";",nl,
- indent(9),{asis,Name}," ->{Val,Type}"]),
- 0
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
+ emit(Sep0),
+ Sep = [";",nl],
+ N = case lists:keyfind(Name, 1, Fields) of
+ {_,#type{}=Type} ->
+ emit_inner_of_decfun(Erule, Type, InternalDefFunName);
+ {_,#typedef{}=Type} ->
+ emit([indent(9),{asis,Name}," ->",nl]),
+ emit_inner_of_decfun(Erule, Type, InternalDefFunName);
+ {_,#'Externaltypereference'{}=Etype} ->
+ emit([indent(9),{asis,Name}," ->",nl,
+ indent(12)]),
+ gen_dec_external(Etype, "Val"),
+ 0;
+ false ->
+ emit([indent(9),{asis,Name}," -> {Val,Type}"]),
+ 0
+ end,
+ gen_inlined_dec_funs1(Erule, Fields, Rest, ObjSetName, Sep, NthObj+N);
+gen_inlined_dec_funs1(Erule, Fields, [_|Rest], ObjSetName, Sep, NthObj) ->
+ gen_inlined_dec_funs1(Erule, Fields, Rest, ObjSetName, Sep, NthObj);
+gen_inlined_dec_funs1(_, _, [], _, _, NthObj) -> NthObj.
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
+emit_inner_of_decfun(Erule, #typedef{name={ExtName,Name},typespec=Type},
InternalDefFunName) ->
case {ExtName,Name} of
{primitive,bif} ->
emit(indent(12)),
- gen_dec_prim(per,Type,"Val"),
+ gen_dec_prim(Erule, Type, "Val"),
0;
{constructed,bif} ->
emit({indent(12),"'dec_",
@@ -1133,18 +891,15 @@ emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Val, telltype)"}),
0
end;
-emit_inner_of_decfun(#typedef{name=Name},_) ->
+emit_inner_of_decfun(_Erule, #typedef{name=Name}, _) ->
emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
0;
-emit_inner_of_decfun(Type,_) when is_record(Type,type) ->
+emit_inner_of_decfun(Erule, #type{}=Type, _) ->
CurrMod = get(currmod),
case Type#type.def of
Def when is_atom(Def) ->
emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(erules,Type,"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ gen_dec_prim(Erule, Type, "Val");
#'Externaltypereference'{module=CurrMod,type=T} ->
emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
#'Externaltypereference'{module=ExtMod,type=T} ->
@@ -1167,7 +922,6 @@ gen_internal_funcs(Erules,[TypeDef|Rest]) ->
%% DECODING *****************************
%%***************************************
-
gen_decode(Erules,Type) when is_record(Type,typedef) ->
D = Type,
emit({nl,nl}),
@@ -1204,7 +958,6 @@ dbdec(Type) ->
demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
gen_decode_user(Erules,D) when is_record(D,typedef) ->
- CurrMod = get(currmod),
Typename = [D#typedef.name],
Def = D#typedef.typespec,
InnerType = asn1ct_gen:get_inner(Def#type.def),
@@ -1217,152 +970,138 @@ gen_decode_user(Erules,D) when is_record(D,typedef) ->
emit({".",nl,nl});
{constructed,bif} ->
asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype)"}),
- emit({".",nl,nl});
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
+ #'Externaltypereference'{}=Etype ->
+ gen_dec_external(Etype, "Bytes"),
+ emit([".",nl,nl]);
Other ->
exit({error,{asn1,{unknown,Other}}})
end.
+gen_dec_external(Ext, BytesVar) ->
+ CurrMod = get(currmod),
+ #'Externaltypereference'{module=Mod,type=Type} = Ext,
+ emit([case CurrMod of
+ Mod -> [];
+ _ -> ["'",Mod,"':"]
+ end,"'dec_",Type,"'(",BytesVar,",telltype)"]).
+
+gen_dec_imm(Erule, #type{def=Name,constraint=C}) ->
+ Aligned = case Erule of
+ uper -> false;
+ per -> true
+ end,
+ gen_dec_imm_1(Name, C, Aligned).
+
+gen_dec_imm_1('ASN1_OPEN_TYPE', Constraint, Aligned) ->
+ imm_decode_open_type(Constraint, Aligned);
+gen_dec_imm_1({'BIT STRING',NNL}, Constr0, Aligned) ->
+ Constr = asn1ct_imm:effective_constraint(bitstring, Constr0),
+ Imm = asn1ct_imm:per_dec_raw_bitstring(Constr, Aligned),
+ case NNL of
+ [] ->
+ case asn1ct:get_bit_string_format() of
+ compact ->
+ gen_dec_bit_string(decode_compact_bit_string,
+ Imm);
+ legacy ->
+ gen_dec_bit_string(decode_legacy_bit_string,
+ Imm);
+ bitstring ->
+ gen_dec_copy_bitstring(Imm)
+ end;
+ [_|_] ->
+ D = fun(V, Buf) ->
+ As = [V,{asis,NNL}],
+ Call = {call,per_common,decode_named_bit_string,As},
+ emit(["{",Call,com,Buf,"}"])
+ end,
+ {call,D,Imm}
+ end;
+gen_dec_imm_1('NULL', _Constr, _Aligned) ->
+ {value,'NULL'};
+gen_dec_imm_1('BOOLEAN', _Constr, _Aligned) ->
+ asn1ct_imm:per_dec_boolean();
+gen_dec_imm_1({'ENUMERATED',{Base,Ext}}, _Constr, Aligned) ->
+ asn1ct_imm:per_dec_enumerated(Base, Ext, Aligned);
+gen_dec_imm_1({'ENUMERATED',NamedNumberList}, _Constr, Aligned) ->
+ asn1ct_imm:per_dec_enumerated(NamedNumberList, Aligned);
+gen_dec_imm_1('INTEGER', Constr, Aligned) ->
+ asn1ct_imm:per_dec_integer(Constr, Aligned);
+gen_dec_imm_1({'INTEGER',NamedNumberList}, Constraint, Aligned) ->
+ asn1ct_imm:per_dec_named_integer(Constraint,
+ NamedNumberList,
+ Aligned);
+gen_dec_imm_1('BMPString'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('NumericString'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('PrintableString'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('VisibleString'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('IA5String'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('UniversalString'=Type, Constraint, Aligned) ->
+ gen_dec_k_m_string(Type, Constraint, Aligned);
+gen_dec_imm_1('UTCTime', Constraint, Aligned) ->
+ gen_dec_k_m_string('VisibleString', Constraint, Aligned);
+gen_dec_imm_1('GeneralizedTime', Constraint, Aligned) ->
+ gen_dec_k_m_string('VisibleString', Constraint, Aligned);
+gen_dec_imm_1('OCTET STRING', Constraint, Aligned) ->
+ SzConstr = asn1ct_imm:effective_constraint(bitstring, Constraint),
+ Imm = asn1ct_imm:per_dec_octet_string(SzConstr, Aligned),
+ {convert,binary_to_list,Imm};
+gen_dec_imm_1('TeletexString', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('T61String', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('VideotexString', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('GraphicString', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('GeneralString', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('ObjectDescriptor', _Constraint, Aligned) ->
+ gen_dec_restricted_string(Aligned);
+gen_dec_imm_1('OBJECT IDENTIFIER', _Constraint, Aligned) ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_oid,[V]},com,
+ Buf,"}"])
+ end,
+ {call,Dec,gen_dec_restricted_string(Aligned)};
+gen_dec_imm_1('RELATIVE-OID', _Constraint, Aligned) ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_relative_oid,[V]},com,
+ Buf,"}"])
+ end,
+ {call,Dec,gen_dec_restricted_string(Aligned)};
+gen_dec_imm_1('UTF8String', _Constraint, Aligned) ->
+ asn1ct_imm:per_dec_restricted_string(Aligned);
+gen_dec_imm_1('REAL', _Constraint, Aligned) ->
+ asn1ct_imm:per_dec_real(Aligned).
+
+gen_dec_bit_string(F, Imm) ->
+ D = fun(V, Buf) ->
+ emit(["{",{call,per_common,F,[V]},com,Buf,"}"])
+ end,
+ {call,D,Imm}.
-gen_dec_prim(Erules,Att,BytesVar) ->
- Typename = Att#type.def,
- Constraint = Att#type.constraint,
- case Typename of
- 'INTEGER' ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",
- {asis,effective_constraint(integer,Constraint)},")"});
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",
- {asis,effective_constraint(integer,Constraint)},",",
- {asis,NamedNumberList},")"});
+gen_dec_copy_bitstring(Imm) ->
+ D = fun(V, Buf) ->
+ emit(["{list_to_bitstring([",V,"]),",Buf,"}"])
+ end,
+ {call,D,Imm}.
- 'REAL' ->
- emit({"?RT_PER:decode_real(",BytesVar,")"});
-
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_PER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},")"});
- _ ->
- emit({"?RT_PER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},")"})
- end;
- 'NULL' ->
- emit({"?RT_PER:decode_null(",
- BytesVar,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:decode_object_identifier(",
- BytesVar,")"});
- 'RELATIVE-OID' ->
- emit({"?RT_PER:decode_relative_oid(",
- BytesVar,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:decode_ObjectDescriptor(",
- BytesVar,")"});
- {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
- NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
- list_to_tuple([X||{X,_} <- NamedNumberList2])},
- NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- {'ENUMERATED',NamedNumberList} ->
- NewTup = list_to_tuple([X||{X,_} <- NamedNumberList]),
- NewC = [{'ValueRange',{0,size(NewTup)-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- 'BOOLEAN'->
- emit({"?RT_PER:decode_boolean(",BytesVar,")"});
- 'OCTET STRING' ->
- emit({"?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,Constraint},")"});
- 'NumericString' ->
- emit({"?RT_PER:decode_NumericString(",BytesVar,",",
- {asis,Constraint},")"});
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VideotexString' ->
- emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'UTCTime' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GeneralizedTime' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GraphicString' ->
- emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VisibleString' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GeneralString' ->
- emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
- {asis,Constraint},")"});
- 'PrintableString' ->
- emit({"?RT_PER:decode_PrintableString(",BytesVar,",",{asis,Constraint},")"});
- 'IA5String' ->
- emit({"?RT_PER:decode_IA5String(",BytesVar,",",{asis,Constraint},")"});
- 'BMPString' ->
- emit({"?RT_PER:decode_BMPString(",BytesVar,",",
- {asis,Constraint},")"});
- 'UniversalString' ->
- emit({"?RT_PER:decode_UniversalString(",BytesVar,
- ",",{asis,Constraint},")"});
- 'UTF8String' ->
- emit({"?RT_PER:decode_UTF8String(",BytesVar,")"});
- 'ANY' ->
- case Erules of
- per ->
- emit(["fun() -> {XTerm,YTermXBytes} = ?RT_PER:decode_open_type(",BytesVar,",",{asis,Constraint}, "), {binary_to_list(XTerm),XBytes} end ()"]);
- _ ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",",
- {asis,Constraint}, ")"])
- end;
- 'ASN1_OPEN_TYPE' ->
- case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- _ ->
- case Erules of
- per ->
- emit(["fun() -> {XTerm,XBytes} = ?RT_PER:decode_open_type(",BytesVar,", []), {binary_to_list(XTerm),XBytes} end()"]);
- _ ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
- end
- end;
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_dec_prim(Erules,InnerType,BytesVar);
- T ->
- gen_dec_prim(Erules,Att#type{def=T},BytesVar)
- end;
- Other ->
- exit({'cant decode' ,Other})
- end.
+gen_dec_k_m_string(Type, Constraint, Aligned) ->
+ asn1ct_imm:per_dec_k_m_string(Type, Constraint, Aligned).
+gen_dec_restricted_string(Aligned) ->
+ Imm = asn1ct_imm:per_dec_restricted_string(Aligned),
+ {convert,binary_to_list,Imm}.
+
+gen_dec_prim(Erule, Type, BytesVar) ->
+ Imm = gen_dec_imm(Erule, Type),
+ asn1ct_imm:dec_code_gen(Imm, BytesVar).
is_already_generated(Operation,Name) ->
case get(class_default_type) of
@@ -1417,3 +1156,25 @@ extaddgroup2sequence([C|T],ExtNum,Acc) ->
extaddgroup2sequence(T,ExtNum,[C|Acc]);
extaddgroup2sequence([],_,Acc) ->
lists:reverse(Acc).
+
+imm_decode_open_type([#'Externaltypereference'{type=Tname}], Aligned) ->
+ imm_dec_open_type_1(Tname, Aligned);
+imm_decode_open_type([#type{def=#'Externaltypereference'{type=Tname}}],
+ Aligned) ->
+ imm_dec_open_type_1(Tname, Aligned);
+imm_decode_open_type(_, Aligned) ->
+ asn1ct_imm:per_dec_open_type(Aligned).
+
+imm_dec_open_type_1(Type, Aligned) ->
+ D = fun(OpenType, Buf) ->
+ asn1ct_name:new(tmpval),
+ emit(["begin",nl,
+ "{",{curr,tmpval},",_} = ",
+ "dec_",Type,"(",OpenType,", mandatory),",nl,
+ "{",{curr,tmpval},com,Buf,"}",nl,
+ "end"])
+ end,
+ {call,D,asn1ct_imm:per_dec_open_type(Aligned)}.
+
+eval_module(per) -> asn1ct_eval_per;
+eval_module(uper) -> asn1ct_eval_uper.
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 16eec92847..012d54e7a1 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -19,123 +19,16 @@
%%
-module(asn1ct_gen_per_rt2ct).
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
+%% Handle encoding of primitives for aligned PER.
-include("asn1_records.hrl").
-%-compile(export_all).
--export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
--export([gen_obj_code/3,gen_objectset_code/2]).
--export([gen_decode/2, gen_decode/3]).
--export([gen_encode/2, gen_encode/3]).
--export([extaddgroup2sequence/1]).
+-export([gen_encode_prim/3]).
-import(asn1ct_gen, [emit/1,demit/1]).
--import(asn1ct_gen_per, [is_already_generated/2,more_genfields/1,
- get_class_fields/1,get_object_field/2]).
+-import(asn1ct_func, [call/3]).
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
-
-
-%% Generate ENCODING ******************************
-%%****************************************x
-
-
-gen_encode(Erules,Type) when is_record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-
-gen_encode(Erules,Typename,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTypename = [Cname|Typename],
- gen_encode(Erules,NewTypename,Type);
-
-gen_encode(Erules,Typename,Type) when is_record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
- ", ObjFun";
- false ->
- ""
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- case InnerType of
- 'SET' ->
- true;
- 'SEQUENCE' ->
- true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}",ObjFun,") ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",ObjFun,");",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
- ") ->",nl}),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-
-gen_encode_user(Erules,D) when is_record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case InnerType of
- 'SET' -> true;
- 'SEQUENCE' -> true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_encode_prim(Erules,Def,"false"),
- emit({".",nl});
- 'ASN1_OPEN_TYPE' ->
- gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
- emit({".",nl});
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'enc_",Etype,"'(Val).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(Val).",nl,nl});
- {notype,_} ->
- emit({"'enc_",InnerType,"'(Val).",nl,nl})
- end.
-
-
-gen_encode_prim(Erules,D,DoTag) ->
- Value = case asn1ct_name:active(val) of
- true ->
- asn1ct_gen:mk_var(asn1ct_name:curr(val));
- false ->
- "Val"
- end,
- gen_encode_prim(Erules,D,DoTag,Value).
-
-
-
-
-
-gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
+gen_encode_prim(Erules, #type{}=D, Value) ->
Constraint = D#type.constraint,
case D#type.def of
'INTEGER' ->
@@ -149,41 +42,28 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
emit([" %%INTEGER with effective constraint: ",
{asis,EffectiveConstr},nl]),
emit_enc_integer_NNL(Erules,EffectiveConstr,Value,NamedNumberList);
- {'ENUMERATED',{Nlist1,Nlist2}} ->
- NewList = lists:append([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
- NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
- emit(["case ",Value," of",nl]),
-%% emit_enc_enumerated_cases(Erules,NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
- emit_enc_enumerated_cases(Erules,NewC, NewList, 0);
- {'ENUMERATED',NamedNumberList} ->
- NewList = [X||{X,_} <- NamedNumberList],
- NewC = effective_constraint(integer,
- [{'ValueRange',
- {0,length(NewList)-1}}]),
- NewVal = enc_enum_cases(Value,NewList),
- emit_enc_integer(Erules,NewC,NewVal);
-
'REAL' ->
- emit({"?RT_PER:encode_real(",Value,")"});
+ emit_enc_real(Erules, Value);
{'BIT STRING',NamedNumberList} ->
EffectiveC = effective_constraint(bitstring,Constraint),
case EffectiveC of
- 0 -> emit({"[]"});
+ 0 ->
+ emit({"[]"});
_ ->
- emit({"?RT_PER:encode_bit_string(",
- {asis,EffectiveC},",",Value,",",
- {asis,NamedNumberList},")"})
+ call(Erules, encode_bit_string,
+ [{asis,EffectiveC},Value,
+ {asis,NamedNumberList}])
end;
'NULL' ->
- emit({"?RT_PER:encode_null(",Value,")"});
+ emit("[]");
'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:encode_object_identifier(",Value,")"});
+ call(Erules, encode_object_identifier, [Value]);
'RELATIVE-OID' ->
- emit({"?RT_PER:encode_relative_oid(",Value,")"});
+ call(Erules, encode_relative_oid, [Value]);
'ObjectDescriptor' ->
- emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
- ",",Value,")"});
+ call(Erules, encode_ObjectDescriptor,
+ [{asis,Constraint},Value]);
'BOOLEAN' ->
emit({"case ",Value," of",nl,
" true -> [1];",nl,
@@ -197,19 +77,19 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
emit_enc_known_multiplier_string('NumericString',Constraint,Value);
TString when TString == 'TeletexString';
TString == 'T61String' ->
- emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_TeletexString, [{asis,Constraint},Value]);
'VideotexString' ->
- emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_VideotexString, [{asis,Constraint},Value]);
'UTCTime' ->
emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
'GeneralizedTime' ->
emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
'GraphicString' ->
- emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_GraphicString, [{asis,Constraint},Value]);
'VisibleString' ->
emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
'GeneralString' ->
- emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},",",Value,")"});
+ call(Erules, encode_GeneralString, [{asis,Constraint},Value]);
'PrintableString' ->
emit_enc_known_multiplier_string('PrintableString',Constraint,Value);
'IA5String' ->
@@ -219,40 +99,38 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
'UniversalString' ->
emit_enc_known_multiplier_string('UniversalString',Constraint,Value);
'UTF8String' ->
- emit({"?RT_PER:encode_UTF8String(",Value,")"});
- 'ANY' ->
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- Value, ")"]);
+ call(Erules, encode_UTF8String, [Value]);
'ASN1_OPEN_TYPE' ->
NewValue = case Constraint of
[#'Externaltypereference'{type=Tname}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ asn1ct_func:need({Erules,complete,1}),
+ io_lib:format(
+ "complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
+ asn1ct_func:need({Erules,complete,1}),
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",
+ "complete(enc_~s(~s))",
[Tname,Value]);
- _ -> Value
+ _ ->
+ io_lib:format("iolist_to_binary(~s)",
+ [Value])
end,
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- NewValue, ")"]);
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(D#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_encode_prim(Erules,InnerType,DoTag,Value);
- T -> %% 'ASN1_OPEN_TYPE'
- gen_encode_prim(Erules,D#type{def=T},DoTag,Value)
- end;
- XX ->
- exit({asn1_error,nyi,XX})
+ call(Erules, encode_open_type, [NewValue])
end.
+emit_enc_real(Erules, Real) ->
+ asn1ct_name:new(tmpval),
+ asn1ct_name:new(tmplen),
+ emit(["begin",nl,
+ "{",{curr,tmpval},com,{curr,tmplen},"} = ",
+ {call,real_common,encode_real,[Real]},com,nl,
+ "[",{call,Erules,encode_length,[{curr,tmplen}]},",",nl,
+ {call,Erules,octets_to_complete,
+ [{curr,tmplen},{curr,tmpval}]},"]",nl,
+ "end"]).
+
emit_enc_known_multiplier_string(StringType,C,Value) ->
- SizeC =
- case get_constraint(C,'SizeConstraint') of
- L when is_list(L) -> {lists:min(L),lists:max(L)};
- L -> L
- end,
+ SizeC = effective_constraint(bitstring, C),
PAlphabC = get_constraint(C,'PermittedAlphabet'),
case {StringType,PAlphabC} of
{'UniversalString',{_,_}} ->
@@ -266,62 +144,34 @@ emit_enc_known_multiplier_string(StringType,C,Value) ->
NumBits = get_NumBits(C,StringType),
CharOutTab = get_CharOutTab(C,StringType),
%% NunBits and CharOutTab for chars_encode
- emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value).
+ emit_enc_k_m_string(SizeC, NumBits, CharOutTab, Value).
-emit_enc_k_m_string(_StringType,0,_NumBits,_CharOutTab,_Value) ->
+emit_enc_k_m_string(0, _NumBits, _CharOutTab, _Value) ->
emit({"[]"});
-emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value) ->
- emit({"?RT_PER:encode_known_multiplier_string(",{asis,StringType},",",
- {asis,SizeC},",",NumBits,",",{asis,CharOutTab},",",Value,")"}).
-
-emit_dec_known_multiplier_string(StringType,C,BytesVar) ->
- SizeC = get_constraint(C,'SizeConstraint'),
- PAlphabC = get_constraint(C,'PermittedAlphabet'),
- case {StringType,PAlphabC} of
- {'BMPString',{_,_}} ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet "
- "constraint"}}});
- _ ->
- ok
- end,
- NumBits = get_NumBits(C,StringType),
- CharInTab = get_CharInTab(C,StringType),
- case SizeC of
- 0 ->
- emit({"{[],",BytesVar,"}"});
- _ ->
- emit({"?RT_PER:decode_known_multiplier_string(",
- {asis,StringType},",",{asis,SizeC},",",NumBits,
- ",",{asis,CharInTab},",",BytesVar,")"})
- end.
+emit_enc_k_m_string(SizeC, NumBits, CharOutTab, Value) ->
+ call(per, encode_known_multiplier_string,
+ [{asis,SizeC},NumBits,{asis,CharOutTab},Value]).
%% copied from run time module
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
+get_CharOutTab(C, StringType) ->
case get_constraint(C,'PermittedAlphabet') of
{'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+ get_CharTab2(C, StringType, hd(Sv), lists:max(Sv), Sv);
no ->
case StringType of
'IA5String' ->
{0,16#7F,notab};
'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+ get_CharTab2(C, StringType, 16#20, 16#7F, notab);
'PrintableString' ->
Chars = lists:sort(
" '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+ get_CharTab2(C, StringType, hd(Chars),
+ lists:max(Chars), Chars);
'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+ get_CharTab2(C, StringType, 16#20, $9, " 0123456789");
'UniversalString' ->
{0,16#FFFFFFFF,notab};
'BMPString' ->
@@ -329,18 +179,13 @@ get_CharTab(C,StringType,InOut) ->
end
end.
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+get_CharTab2(C, StringType, Min, Max, Chars) ->
BitValMax = (1 bsl get_NumBits(C,StringType))-1,
if
Max =< BitValMax ->
{0,Max,notab};
true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
+ {Min,Max,create_char_tab(Min,Chars)}
end.
create_char_tab(Min,L) ->
@@ -409,56 +254,57 @@ charbits1(NumOfChars) ->
%% copied from run time module
-emit_enc_octet_string(_Erules,Constraint,Value) ->
- case get_constraint(Constraint,'SizeConstraint') of
+emit_enc_octet_string(Erules, Constraint, Value) ->
+ case effective_constraint(bitstring, Constraint) of
0 ->
emit({" []"});
1 ->
asn1ct_name:new(tmpval),
emit({" begin",nl}),
emit({" [",{curr,tmpval},"] = ",Value,",",nl}),
- emit({" [10,8,",{curr,tmpval},"]",nl}),
+ emit([" [[10,8],",{curr,tmpval},"]",nl]),
emit(" end");
2 ->
asn1ct_name:new(tmpval),
- emit({" begin",nl}),
- emit({" [",{curr,tmpval},",",{next,tmpval},"] = ",
- Value,",",nl}),
- emit({" [[10,8,",{curr,tmpval},"],[10,8,",
- {next,tmpval},"]]",nl}),
- emit(" end"),
- asn1ct_name:new(tmpval);
- Sv when is_integer(Sv),Sv =< 256 ->
+ emit([" begin",nl,
+ " ",{curr,tmpval}," = ",Value,",",nl,
+ " case length(",{curr,tmpval},") of",nl,
+ " 2 ->",nl,
+ " [[45,16,2]|",{curr,tmpval},"];",nl,
+ " _ ->",nl,
+ " exit({error,{value_out_of_bounds,",
+ {curr,tmpval},"}})",nl,
+ " end",nl,
+ " end"]);
+ Sv when is_integer(Sv), Sv < 256 ->
asn1ct_name:new(tmpval),
- emit({" begin",nl}),
- emit({" case length(",Value,") of",nl}),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," ->"]),
- emit([" [2,20,",{curr,tmpval},",",Value,"];",nl]),
- emit({" _ -> exit({error,{value_out_of_bounds,",
- Value,"}})", nl," end",nl}),
- emit(" end");
+ asn1ct_name:new(tmplen),
+ emit([" begin",nl,
+ " ",{curr,tmpval}," = ",Value,",",nl,
+ " case length(",{curr,tmpval},") of",nl,
+ " ",Sv,"=",{curr,tmplen}," ->",nl,
+ " [20,",{curr,tmplen},"|",{curr,tmpval},"];",nl,
+ " _ ->",nl,
+ " exit({error,{value_out_of_bounds,",
+ {curr,tmpval},"}})",nl,
+ " end",nl,
+ " end"]);
Sv when is_integer(Sv),Sv =< 65535 ->
asn1ct_name:new(tmpval),
- emit({" begin",nl}),
- emit({" case length(",Value,") of",nl}),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," ->"]),
- emit([" [2,21,",{curr,tmpval},",",Value,"];",nl]),
- emit({" _ -> exit({error,{value_out_of_bounds,",
- Value,"}})",nl," end",nl}),
- emit(" end");
+ asn1ct_name:new(tmplen),
+ emit([" begin",nl,
+ " ",{curr,tmpval}," = ",Value,",",nl,
+ " case length(",{curr,tmpval},") of",nl,
+ " ",Sv,"=",{curr,tmplen}," ->",nl,
+ " [<<21,",{curr,tmplen},":16>>|",Value,"];",nl,
+ " _ ->",nl,
+ " exit({error,{value_out_of_bounds,",
+ {curr,tmpval},"}})",nl,
+ " end",nl,
+ " end"]);
C ->
- emit({" ?RT_PER:encode_octet_string(",{asis,C},",false,",Value,")",nl})
- end.
-
-emit_dec_octet_string(Constraint,BytesVar) ->
- case get_constraint(Constraint,'SizeConstraint') of
- 0 ->
- emit({" {[],",BytesVar,"}",nl});
- {_,0} ->
- emit({" {[],",BytesVar,"}",nl});
- C ->
- emit({" ?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,C},",false)",nl})
+ call(Erules, encode_octet_string,
+ [{asis,C},Value])
end.
emit_enc_integer_case(Value) ->
@@ -545,71 +391,12 @@ emit_enc_integer(_Erule,[{_,{Lb,Ub},Range,_}],Value) when Range =< 65536 ->
nl," end",nl]),
emit_enc_integer_end_case();
+emit_enc_integer(Erule, [{'ValueRange',{Lb,Ub}=VR}], Value)
+ when is_integer(Lb), is_integer(Ub) ->
+ call(Erule, encode_constrained_number, [{asis,VR},Value]);
-emit_enc_integer(_Erule,C,Value) ->
- emit({" ?RT_PER:encode_integer(",{asis,C},",",Value,")"}).
-
-
-
-
-enc_enum_cases(Value,NewList) ->
- asn1ct_name:new(tmpval),
- TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- Cases=enc_enum_cases1(NewList),
- lists:flatten(io_lib:format("(case ~s of "++Cases++
- "~s ->exit({error,"
- "{asn1,{enumerated,~s}}})"
- " end)",
- [Value,TmpVal,TmpVal])).
-enc_enum_cases1(NNL) ->
- enc_enum_cases1(NNL,0).
-enc_enum_cases1([H|T],Index) ->
- io_lib:format("~w->~w;",[H,Index])++enc_enum_cases1(T,Index+1);
-enc_enum_cases1([],_) ->
- "".
-
-
-emit_enc_enumerated_cases(Erule, C, [H], Count) ->
- emit_enc_enumerated_case(Erule, C, H, Count),
- case H of
- 'EXT_MARK' ->
- ok;
- _ ->
- emit([";",nl])
- end,
- emit([nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
- emit([nl,"end"]);
-emit_enc_enumerated_cases(Erule, C, ['EXT_MARK'|T], _Count) ->
- emit_enc_enumerated_cases(Erule, C, T, 0);
-emit_enc_enumerated_cases(Erule, C, [H1,H2|T], Count) ->
- emit_enc_enumerated_case(Erule, C, H1, Count),
- emit([";",nl]),
- emit_enc_enumerated_cases(Erule, C, [H2|T], Count+1).
-
-
-%% The function clauses matching on tuples with first element
-%% asn1_enum, 1 or 0 and the atom 'EXT_MARK' are for ENUMERATED
-%% with extension mark.
-%% emit_enc_enumerated_case(_Erule,_C, {asn1_enum,High}, _) ->
-%% %% ENUMERATED with extensionmark
-%% %% value higher than the extension base and not
-%% %% present in the extension range.
-%% emit(["{asn1_enum,EnumV} when is_integer(EnumV), EnumV > ",High," -> ",
-%% "[1,?RT_PER:encode_small_number(EnumV)]"]);
-emit_enc_enumerated_case(_Erule,_C, {1,EnumName}, Count) ->
- %% ENUMERATED with extensionmark
- %% values higher than extension root
- emit(["'",EnumName,"' -> [1,?RT_PER:encode_small_number(",Count,")]"]);
-emit_enc_enumerated_case(_Erule,C, {0,EnumName}, Count) ->
- %% ENUMERATED with extensionmark
- %% values within extension root
-%% emit(["'",EnumName,"' -> [0,?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
- emit(["'",EnumName,"' -> ",{asis,[0|asn1rt_per_bin_rt2ct:encode_integer(C,Count)]}]);
-emit_enc_enumerated_case(_Erule, _C, 'EXT_MARK', _Count) ->
- true.
-%% %% This clause is invoked in case of an ENUMERATED without extension mark
-%% emit_enc_enumerated_case(_Erule,_C, EnumName, Count) ->
-%% emit(["'",EnumName,"' -> ",Count]).
+emit_enc_integer(Erule, C, Value) ->
+ call(Erule, encode_integer, [{asis,C},Value]).
get_constraint([{Key,V}],Key) ->
@@ -624,23 +411,6 @@ get_constraint(C,Key) ->
V
end.
-get_constraints(L=[{Key,_}],Key) ->
- L;
-get_constraints([],_) ->
- [];
-get_constraints(C,Key) ->
- {value,L} = keysearch_allwithkey(Key,1,C,[]),
- L.
-
-keysearch_allwithkey(Key,Ix,C,Acc) ->
- case lists:keysearch(Key,Ix,C) of
- false ->
- {value,Acc};
- {value,T} ->
- RestC = lists:delete(T,C),
- keysearch_allwithkey(Key,Ix,RestC,[T|Acc])
- end.
-
%% effective_constraint(Type,C)
%% Type = atom()
%% C = [C1,...]
@@ -657,69 +427,9 @@ keysearch_allwithkey(Key,Ix,C,Acc) ->
effective_constraint(integer,[C={{_,_},_}|_Rest]) -> % extension
[C]; %% [C|effective_constraint(integer,Rest)]; XXX what is possible ???
effective_constraint(integer,C) ->
- SVs = get_constraints(C,'SingleValue'),
- SV = effective_constr('SingleValue',SVs),
- VRs = get_constraints(C,'ValueRange'),
- VR = effective_constr('ValueRange',VRs),
- CRange = greatest_common_range(SV,VR),
- pre_encode(integer,CRange);
+ pre_encode(integer, asn1ct_imm:effective_constraint(integer, C));
effective_constraint(bitstring,C) ->
- get_constraint(C,'SizeConstraint').
-
-effective_constr(_,[]) ->
- [];
-effective_constr('SingleValue',List) ->
- SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
- %% Sort and remove duplicates before generating SingleValue or ValueRange
- %% In case of ValueRange, also check for 'MIN and 'MAX'
- case lists:usort(SVList) of
- [N] ->
- [{'SingleValue',N}];
- L when is_list(L) ->
- [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}]
- end;
-effective_constr('ValueRange',List) ->
- LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
- UBs = lists:map(fun({_,{_,Ub}})-> Ub end,List),
- Lb = least_Lb(LBs),
- [{'ValueRange',{Lb,lists:max(UBs)}}].
-
-greatest_common_range([],VR) ->
- VR;
-greatest_common_range(SV,[]) ->
- SV;
-greatest_common_range([{_,Int}],[{_,{'MIN',Ub}}]) when is_integer(Int),
- Int > Ub ->
- [{'ValueRange',{'MIN',Int}}];
-greatest_common_range([{_,Int}],[{_,{Lb,Ub}}]) when is_integer(Int),
- Int < Lb ->
- [{'ValueRange',{Int,Ub}}];
-greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when is_integer(Int) ->
- VR;
-greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when is_list(L) ->
- Min = least_Lb([Lb|L]),
- Max = greatest_Ub([Ub|L]),
- [{'ValueRange',{Min,Max}}];
-greatest_common_range([{_,{Lb1,Ub1}}],[{_,{Lb2,Ub2}}]) ->
- Min = least_Lb([Lb1,Lb2]),
- Max = greatest_Ub([Ub1,Ub2]),
- [{'ValueRange',{Min,Max}}].
-
-
-least_Lb(L) ->
- case lists:member('MIN',L) of
- true -> 'MIN';
- _ -> lists:min(L)
- end.
-
-greatest_Ub(L) ->
- case lists:member('MAX',L) of
- true -> 'MAX';
- _ -> lists:max(L)
- end.
-
-
-
+ asn1ct_imm:effective_constraint(bitstring, C).
pre_encode(integer,[]) ->
[];
@@ -749,1075 +459,3 @@ no_bits(N) when N=<32 -> 5;
no_bits(N) when N=<64 -> 6;
no_bits(N) when N=<128 -> 7;
no_bits(N) when N=<255 -> 8.
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when is_record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=Mod,type=ClassName} =
- Def#'Object'.classname,
- Class = asn1_db:dbget(Mod,ClassName),
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(Erules,ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit(nl);
-gen_obj_code(_Erules,_Module,Obj) when is_record(Obj,pobjectdef) ->
- ok.
-
-gen_encode_objectfields(Erules,ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(V) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",V,",_RestPrimFieldName) ->",nl])
- end,
-
- MaybeConstr =
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("Val"),
- emit([" if",nl,
- " is_list(Val) ->",nl,
- " NewVal = list_to_binary(Val),",nl,
- " [20,size(NewVal),NewVal];",nl,
- " is_binary(Val) ->",nl,
- " [20,size(Val),Val]",nl,
- " end"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val"),
- gen_encode_default_call(Erules,ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(Erules,ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(Erules,ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(Erules,ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause(" Val, [H|T]"),
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause(" Val, [H|T]"),
- emit({indent(3),"'",M,"':'enc_",TypeName,"'(H, Val, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Val,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(Erules,ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(Erules,ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(Erules,ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_Erules,_,[],_,_,Acc) ->
- Acc.
-
-
-
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- Name = lists:concat(["enc_",TypeDef#typedef.name]),
- emit({Name,"(Val) ->",nl}),
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
- gen_encode_constr_type(Erules,Rest)
- end;
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(_Erule,_ObjName,_FieldName,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- if
- M == CurrentMod ->
- emit({" 'enc_",T,"'(Val)"}),
- [];
- true ->
- emit({" '",M,"':'enc_",T,"'(Val)"}),
- []
- end;
-gen_encode_field_call(Erule,ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_encode_prim(Erule,Def,"false",
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val)"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val)"}),
- []
- end.
-
-gen_encode_default_call(Erules,ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(Erules,Type,"false","Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
- []
- end.
-
-
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Bytes) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
- ",_,_RestPrimFieldName) ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes, _, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("Bytes"),
- emit([" {Bytes,[]}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- CurrentMod = get(currmod),
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,_,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",{asis,Name},
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,#'Externalvaluereference'{module=CurrentMod,
- value=TypeName}},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"});
- {{Name,#'Externalvaluereference'{module=M,value=TypeName}},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- emit({indent(3),"'",M,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-
-gen_decode_field_call(_ObjName,_FieldName,Bytes,
- #'Externaltypereference'{module=M,type=T}) ->
- CurrentMod = get(currmod),
- if
- M == CurrentMod ->
- emit([" 'dec_",T,"'(",Bytes,", telltype)"]),
- [];
- true ->
- emit([" '",M,"':'dec_",T,"'(",Bytes,", telltype)"]),
- []
- end;
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_dec_prim(per,Def,Bytes),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",telltype)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", telltype)"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(per,Type,Bytes),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- []
- end.
-
-%%%%%%%%%%%%%%%
-
-
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when is_record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erule,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=
- gen_objset_enc(Erule,ObjSetName,UniqueFName,Set,ClassName,
- ClassFields,1,[]),
- gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erule,InternalFuncs).
-
-gen_objset_enc(_Erule,_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(Erule,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,NewNthObj}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Erule,Fields,ClFields,ObjSName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModName,Name} ->
- emit_ext_encfun(ModName,Name),
-% emit([" {'",ModName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(Erule,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc++Acc);
-gen_objset_enc(Erule,ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
-
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- {InternalFunc,_}=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_enc_funs(Erule,Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],NthObj};
- {ModName,Name} ->
- emit_ext_encfun(ModName,Name),
-% emit([" {'",ModName,"', 'enc_",Name,"'}"]),
- {[],NthObj};
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit([";",nl]),
- emit_default_getenc(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- InternalFunc++Acc;
-gen_objset_enc(_Erule,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Val, _) ->",nl}),
- emit({indent(6),"BinVal = if",nl}),
- emit({indent(9),"is_list(Val) -> list_to_binary(Val);",nl}),
- emit({indent(9),"true -> Val",nl}),
- emit({indent(6),"end,",nl}),
- emit({indent(6),"Size = size(BinVal),",nl}),
- emit({indent(6),"if",nl}),
- emit({indent(9),"Size < 256 ->",nl}),
- emit({indent(12),"[20,Size,BinVal];",nl}),
- emit({indent(9),"true ->",nl}),
- emit({indent(12),"[21,<<Size:16>>,Val]",nl}),
- emit({indent(6),"end",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(_Erule,_,_,[],_,_,_,Acc) ->
- Acc.
-
-emit_ext_encfun(ModuleName,Name) ->
- emit([indent(4),"fun(T,V,O) -> '",ModuleName,"':'enc_",
- Name,"'(T,V,O) end"]).
-
-emit_default_getenc(ObjSetName,UniqueName) ->
- emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
- emit([indent(4),"fun(C,V,_) -> exit({'Type not compatible with table constraint',{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]).
-
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Erule,Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName=asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Erule,Type,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Erule,Type,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'enc_",T,"'(Val)"]),
-% {Ret,N} = emit_inner_of_fun(Erule,TDef,InternalDefFunName),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[]);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[]);
- false ->
- emit([indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Size = case Val of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Val)",nl,
- indent(12),"end,",nl,
- indent(12),"if",nl,
- indent(15),"Size < 256 -> [20,Size,Val];",nl,
- indent(15),"true -> [21,<<Size:16>>,Val]",nl,
- indent(12),"end"]),
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,[])
- end;
-gen_inlined_enc_funs(Erule,Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Erule,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_Erule,_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Erule,Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- CurrentMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Erule,Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Erule,Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'enc_",T,"'(Val)"]),
- {Acc,0};
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"'",":'enc_",T,"'(Val)"]),
- {Acc,0};
- false ->
- emit([";",nl,
- indent(9),{asis,Name}," ->",nl,
- indent(12),"Size = case Val of",nl,
- indent(15),"B when is_binary(B) -> size(B);",nl,
- indent(15),"_ -> length(Val)",nl,
- indent(12),"end,",nl,
- indent(12),"if",nl,
- indent(15),"Size < 256 -> [20,Size,Val];",nl,
- indent(15),"true -> [21,<<Size:16>>,Val]",nl,
- indent(12),"end"]),
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Erule,Fields,[_|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Erule,Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_Erule,_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-emit_inner_of_fun(Erule,TDef=#typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(Erule,Type,dotag,"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val)"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
- {[],0}
- end;
-emit_inner_of_fun(_Erule,#typedef{name=Name},_) ->
- emit({indent(12),"'enc_",Name,"'(Val)"}),
- {[],0};
-emit_inner_of_fun(Erule,Type,_) when is_record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when is_atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(Erule,Type,dotag,"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val)"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
- ClFields,NthObj)->
-
- emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod = get(currmod),
- NewNthObj=
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/4"]),
- NthObj;
- {ModName,Name} ->
- emit_ext_decfun(ModName,Name),
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]),
- NthObj;
- _ ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
-gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
-
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- CurrMod=get(currmod),
- case ObjName of
- {no_mod,no_name} ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/4"]);
- {ModName,Name} ->
- emit_ext_decfun(ModName,Name);
-% emit([" {'",ModName,"', 'dec_",Name,"'}"]);
- _ ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit([";",nl]),
- emit_default_getdec(ObjSetName,UniqueName),
- emit({".",nl,nl}),
- ok;
-gen_objset_dec(ObjSetName,_,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
- emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(Attr1, Bytes, _, _) ->",nl}),
- %% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
- emit({indent(6),"{Bytes,Attr1}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_,_,[],_,_,_) ->
- ok.
-
-emit_ext_decfun(ModuleName,Name) ->
- emit([indent(3),"fun(T,V,O1,O2) -> '",ModuleName,"':'dec_",
- Name,"'(T,V,O1,O2) end"]).
-
-emit_default_getdec(ObjSetName,UniqueName) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
- emit([indent(2), "fun(C,V,_,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]).
-
-
-gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'dec_",T,"'(Val, telltype)"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- emit([indent(12),"'",M,"':'dec_",T,"'(Val, telltype)"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
- false ->
- emit([indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl,
- indent(9),{asis,Name}," -> {Val,Type}"]),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- CurrentMod = get(currmod),
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when is_record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,Type}} when is_record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"'dec_",T,"'(Val,telltype)"]),
- 0;
- {value,{_,#'Externaltypereference'{module=M,type=T}}} ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit([indent(12),"'",M,"':'dec_",T,"'(Val,telltype)"]),
- 0;
- false ->
- emit([";",nl,
- indent(9),{asis,Name}," -> {Val,Type}"]),
- 0
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
-
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(per,Type,"Val"),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,
- "'(Val, telltype)"}),
- 0
- end;
-emit_inner_of_decfun(#typedef{name=Name},_) ->
- emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
- 0;
-emit_inner_of_decfun(Type,_) when is_record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when is_atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(erules,Type,"Val");
- TRef when is_record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Val)"})
- end,
- 0.
-
-
-gen_internal_funcs(_Erules,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-
-%% DECODING *****************************
-%%***************************************
-
-
-gen_decode(Erules,Type) when is_record(Type,typedef) ->
- D = Type,
- emit({nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes,_) ->",nl}),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
-
-gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTname = [Cname|Tname],
- gen_decode(Erules,NewTname,Type);
-
-gen_decode(Erules,Typename,Type) when is_record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
- "'(Bytes,_",ObjFun,") ->",nl}),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-dbdec(Type) when is_list(Type)->
- demit({"io:format(\"decoding: ",asn1ct_gen:list2name(Type),"~w~n\",[Bytes]),",nl});
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-gen_decode_user(Erules,D) when is_record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_dec_prim(Erules,Def,"Bytes"),
- emit({".",nl,nl});
- 'ASN1_OPEN_TYPE' ->
- gen_dec_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"Bytes"),
- emit({".",nl,nl});
- {constructed,bif} ->
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype)"}),
- emit({".",nl,nl});
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- Other ->
- exit({error,{asn1,{unknown,Other}}})
- end.
-
-
-
-gen_dec_prim(Erules,Att,BytesVar) ->
- Typename = Att#type.def,
- Constraint = Att#type.constraint,
- case Typename of
- 'INTEGER' ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit_dec_integer(EffectiveConstr,BytesVar);
-% emit({"?RT_PER:decode_integer(",BytesVar,",",
-% {asis,EffectiveConstr},")"});
- {'INTEGER',NamedNumberList} ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit_dec_integer(EffectiveConstr,BytesVar,NamedNumberList);
-% emit({"?RT_PER:decode_integer(",BytesVar,",",
-% {asis,EffectiveConstr},",",
-% {asis,NamedNumberList},")"});
-
- 'REAL' ->
- emit(["?RT_PER:decode_real(",BytesVar,")"]);
-
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_PER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},")"});
- _ ->
- emit({"?RT_PER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},")"})
- end;
- 'NULL' ->
- emit({"?RT_PER:decode_null(",
- BytesVar,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:decode_object_identifier(",
- BytesVar,")"});
- 'RELATIVE-OID' ->
- emit({"?RT_PER:decode_relative_oid(",
- BytesVar,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:decode_ObjectDescriptor(",
- BytesVar,")"});
- {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
- NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
- list_to_tuple([X||{X,_} <- NamedNumberList2])},
- NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- {'ENUMERATED',NamedNumberList} ->
- NewNNL = [X||{X,_} <- NamedNumberList],
- NewC = effective_constraint(integer,
- [{'ValueRange',{0,length(NewNNL)-1}}]),
- emit_dec_enumerated(BytesVar,NewC,NewNNL);
- 'BOOLEAN'->
- emit({"?RT_PER:decode_boolean(",BytesVar,")"});
-
- 'OCTET STRING' ->
- emit_dec_octet_string(Constraint,BytesVar);
-
- 'NumericString' ->
- emit_dec_known_multiplier_string('NumericString',
- Constraint,BytesVar);
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
- {asis,Constraint},")"});
-
- 'VideotexString' ->
- emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
- {asis,Constraint},")"});
-
- 'UTCTime' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
- 'GeneralizedTime' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
- 'GraphicString' ->
- emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
- {asis,Constraint},")"});
-
- 'VisibleString' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
- 'GeneralString' ->
- emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
- {asis,Constraint},")"});
-
- 'PrintableString' ->
- emit_dec_known_multiplier_string('PrintableString',
- Constraint,BytesVar);
- 'IA5String' ->
- emit_dec_known_multiplier_string('IA5String',Constraint,BytesVar);
-
- 'BMPString' ->
- emit_dec_known_multiplier_string('BMPString',Constraint,BytesVar);
-
- 'UniversalString' ->
- emit_dec_known_multiplier_string('UniversalString',
- Constraint,BytesVar);
-
- 'UTF8String' ->
- emit({"?RT_PER:decode_UTF8String(",BytesVar,")"});
- 'ANY' ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",",
- {asis,Constraint}, ")"]);
- 'ASN1_OPEN_TYPE' ->
- case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- _ ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
- end;
- #'ObjectClassFieldType'{} ->
- case asn1ct_gen:get_inner(Att#type.def) of
- {fixedtypevaluefield,_,InnerType} ->
- gen_dec_prim(Erules,InnerType,BytesVar);
- T ->
- gen_dec_prim(Erules,Att#type{def=T},BytesVar)
- end;
- Other ->
- exit({'cant decode' ,Other})
- end.
-
-
-emit_dec_integer(C,BytesVar,NNL) ->
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(buffer),
- Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- Buffer = asn1ct_gen:mk_var(asn1ct_name:curr(buffer)),
- emit({" begin {",{curr,tmpterm},",",{curr,buffer},"} = ",nl}),
- emit_dec_integer(C,BytesVar),
- emit({",",nl," case ",Tmpterm," of",nl}),
- lists:map(fun({Name,Int})->emit({" ",Int," -> {",{asis,Name},",",
- Buffer,"};",nl});
- (_)-> exit({error,{asn1,{"error in named number list",NNL}}})
- end,
- NNL),
- emit({" _ -> {",Tmpterm,",",Buffer,"}",nl}),
- emit({" end",nl}), % end of case
- emit(" end"). % end of begin
-
-emit_dec_integer([{'SingleValue',Int}],BytesVar) when is_integer(Int) ->
- emit(["{",Int,",",BytesVar,"}"]);
-emit_dec_integer([{_,{Lb,_Ub},_Range,{BitsOrOctets,N}}],BytesVar) ->
- GetBorO =
- case BitsOrOctets of
- bits -> "getbits";
- _ -> "getoctets"
- end,
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(tmpremain),
- emit({" begin",nl," {",{curr,tmpterm},",",{curr,tmpremain},"}=",
- "?RT_PER:",GetBorO,"(",BytesVar,",",N,"),",nl}),
- emit({" {",{curr,tmpterm},"+",Lb,",",{curr,tmpremain},"}",nl,
- " end"});
-emit_dec_integer([{_,{'MIN',_}}],BytesVar) ->
- emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"});
-emit_dec_integer([{_,{Lb,'MAX'}}],BytesVar) ->
- emit({"?RT_PER:decode_semi_constrained_number(",BytesVar,",",Lb,")"});
-emit_dec_integer([{'ValueRange',VR={Lb,Ub}}],BytesVar) ->
- Range = Ub-Lb+1,
- emit({"?RT_PER:decode_constrained_number(",BytesVar,",",
- {asis,VR},",",Range,")"});
-emit_dec_integer(C=[{Rc,_}],BytesVar) when is_tuple(Rc) ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",{asis,C},")"});
-emit_dec_integer(_,BytesVar) ->
- emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"}).
-
-
-emit_dec_enumerated(BytesVar,C,NamedNumberList) ->
- emit_dec_enumerated_begin(),% emits a begin if component
- asn1ct_name:new(tmpterm),
- Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- asn1ct_name:new(tmpremain),
- Tmpremain = asn1ct_gen:mk_var(asn1ct_name:curr(tmpremain)),
- emit({" {",{curr,tmpterm},",",{curr,tmpremain},"} =",nl}),
- emit_dec_integer(C,BytesVar),
- emit({",",nl," case ",Tmpterm," of "}),
-
- Cases=lists:flatten(dec_enumerated_cases(NamedNumberList,Tmpremain,0)),
- emit({Cases++"_->exit({error,{asn1,{decode_enumerated,{",Tmpterm,
- ",",{asis,NamedNumberList},"}}}}) end",nl}),
- emit_dec_enumerated_end().
-
-emit_dec_enumerated_begin() ->
- case get(component_type) of
- {true,_} ->
- emit({" begin",nl});
- _ -> ok
- end.
-
-emit_dec_enumerated_end() ->
- case get(component_type) of
- {true,_} ->
- emit(" end");
- _ -> ok
- end.
-
-
-dec_enumerated_cases([Name|Rest],Tmpremain,No) ->
- io_lib:format("~w->{~w,~s};",[No,Name,Tmpremain])++
- dec_enumerated_cases(Rest,Tmpremain,No+1);
-dec_enumerated_cases([],_,_) ->
- "".
-
-%% For PER the ExtensionAdditionGroup notation has significance for the encoding and decoding
-%% the components within the ExtensionAdditionGroup is treated in a similar way as if they
-%% have been specified within a SEQUENCE, therefore we construct a fake sequence type here
-%% so that we can generate code for it
-extaddgroup2sequence(ExtList) ->
- extaddgroup2sequence(ExtList,0,[]).
-
-extaddgroup2sequence([{'ExtensionAdditionGroup',Number0}|T],ExtNum,Acc) ->
- Number = case Number0 of undefined -> 1; _ -> Number0 end,
- {ExtGroupComps,['ExtensionAdditionGroupEnd'|T2]} =
- lists:splitwith(fun(Elem) -> is_record(Elem,'ComponentType') end,T),
- extaddgroup2sequence(T2,ExtNum+1,
- [#'ComponentType'{
- name=list_to_atom("ExtAddGroup"++
- integer_to_list(ExtNum+1)),
- typespec=#type{def=#'SEQUENCE'{
- extaddgroup=Number,
- components=ExtGroupComps}},
- prop='OPTIONAL'}|Acc]);
-extaddgroup2sequence([C|T],ExtNum,Acc) ->
- extaddgroup2sequence(T,ExtNum,[C|Acc]);
-extaddgroup2sequence([],_,Acc) ->
- lists:reverse(Acc).
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
new file mode 100644
index 0000000000..bf362db843
--- /dev/null
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -0,0 +1,800 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+%%
+-module(asn1ct_imm).
+-export([per_dec_raw_bitstring/2,
+ per_dec_boolean/0,per_dec_enumerated/2,per_dec_enumerated/3,
+ per_dec_extension_map/1,
+ per_dec_integer/2,per_dec_k_m_string/3,
+ per_dec_length/3,per_dec_named_integer/3,
+ per_dec_octet_string/2,per_dec_open_type/1,per_dec_real/1,
+ per_dec_restricted_string/1]).
+-export([per_dec_constrained/3,per_dec_normally_small_number/1]).
+-export([optimize_alignment/1,optimize_alignment/2,
+ dec_slim_cg/2,dec_code_gen/2]).
+-export([effective_constraint/2]).
+-import(asn1ct_gen, [emit/1]).
+
+-record(st, {var,
+ base}).
+
+dec_slim_cg(Imm0, BytesVar) ->
+ {Imm,_} = optimize_alignment(Imm0),
+ asn1ct_name:new(v),
+ [H|T] = atom_to_list(asn1ct_name:curr(v)) ++ "@",
+ VarBase = [H-($a-$A)|T],
+ St0 = #st{var=0,base=VarBase},
+ {Res,Pre,_} = flatten(Imm, BytesVar, St0),
+ dcg_list_outside(Pre),
+ Res.
+
+dec_code_gen(Imm, BytesVar) ->
+ emit(["begin",nl]),
+ {Dst,DstBuf} = dec_slim_cg(Imm, BytesVar),
+ emit([",",nl,
+ "{",Dst,",",DstBuf,"}",nl,
+ "end"]),
+ ok.
+
+optimize_alignment(Imm) ->
+ opt_al(Imm, unknown).
+
+optimize_alignment(Imm, Al) ->
+ opt_al(Imm, Al).
+
+
+per_dec_boolean() ->
+ {map,{get_bits,1,[1]},[{0,false},{1,true}]}.
+
+per_dec_enumerated([{V,_}], _Aligned) ->
+ {value,V};
+per_dec_enumerated(NamedList0, Aligned) ->
+ Ub = length(NamedList0) - 1,
+ Constraint = [{'ValueRange',{0,Ub}}],
+ Int = per_dec_integer(Constraint, Aligned),
+ EnumTail = case matched_range(Int) of
+ {0,Ub} ->
+ %% The error case can never happen.
+ [];
+ _ ->
+ [enum_error]
+ end,
+ NamedList = per_dec_enumerated_fix_list(NamedList0, EnumTail, 0),
+ {map,Int,NamedList}.
+
+per_dec_enumerated(BaseNamedList, NamedListExt0, Aligned) ->
+ Base = per_dec_enumerated(BaseNamedList, Aligned),
+ NamedListExt = per_dec_enumerated_fix_list(NamedListExt0,
+ [enum_default], 0),
+ Ext = {map,per_dec_normally_small_number(Aligned),NamedListExt},
+ bit_case(Base, Ext).
+
+per_dec_extension_map(Aligned) ->
+ Len = per_dec_normally_small_length(Aligned),
+ {get_bits,Len,[1,bitstring]}.
+
+per_dec_integer(Constraint0, Aligned) ->
+ Constraint = effective_constraint(integer, Constraint0),
+ per_dec_integer_1(Constraint, Aligned).
+
+per_dec_length(SingleValue, _, _Aligned) when is_integer(SingleValue) ->
+ {value,SingleValue};
+per_dec_length({{Fixed,Fixed},[]}, AllowZero, Aligned) ->
+ bit_case(per_dec_length(Fixed, AllowZero, Aligned),
+ per_dec_length(no, AllowZero, Aligned));
+per_dec_length({{_,_}=Constr,[]}, AllowZero, Aligned) ->
+ bit_case(per_dec_length(Constr, AllowZero, Aligned),
+ per_dec_length(no, AllowZero, Aligned));
+per_dec_length({Lb,Ub}, _AllowZero, Aligned) when is_integer(Lb),
+ is_integer(Lb) ->
+ per_dec_constrained(Lb, Ub, Aligned);
+per_dec_length(no, AllowZero, Aligned) ->
+ decode_unconstrained_length(AllowZero, Aligned).
+
+per_dec_named_integer(Constraint, NamedList0, Aligned) ->
+ Int = per_dec_integer(Constraint, Aligned),
+ NamedList = [{K,V} || {V,K} <- NamedList0] ++ [integer_default],
+ {map,Int,NamedList}.
+
+per_dec_k_m_string(StringType, Constraint, Aligned) ->
+ SzConstr = effective_constraint(bitstring, Constraint),
+ N = string_num_bits(StringType, Constraint, Aligned),
+ %% X.691 (07/2002) 27.5.7 says if the upper bound times the number
+ %% of bits is greater than or equal to 16, then the bit field should
+ %% be aligned.
+ Imm = dec_string(SzConstr, N, Aligned, fun(_, Ub) -> Ub >= 16 end),
+ Chars = char_tab(Constraint, StringType, N),
+ convert_string(N, Chars, Imm).
+
+per_dec_octet_string(Constraint, Aligned) ->
+ dec_string(Constraint, 8, Aligned,
+ %% Aligned unless the size is fixed and =< 16.
+ fun(Sv, Sv) -> Sv > 16;
+ (_, _) -> true
+ end).
+
+per_dec_raw_bitstring(Constraint, Aligned) ->
+ dec_string(Constraint, 1, Aligned,
+ fun(Sv, Sv) -> Sv > 16;
+ (_, _) -> true
+ end).
+
+per_dec_open_type(Aligned) ->
+ {get_bits,decode_unconstrained_length(true, Aligned),
+ [8,binary,{align,Aligned}]}.
+
+per_dec_real(Aligned) ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,real_common,decode_real,[V]},
+ com,Buf,"}"])
+ end,
+ {call,Dec,
+ {get_bits,decode_unconstrained_length(true, Aligned),
+ [8,binary,{align,Aligned}]}}.
+
+per_dec_restricted_string(Aligned) ->
+ DecLen = decode_unconstrained_length(true, Aligned),
+ {get_bits,DecLen,[8,binary]}.
+
+
+%%%
+%%% Local functions.
+%%%
+
+dec_string(Sv, U, Aligned0, AF) when is_integer(Sv) ->
+ Bits = U*Sv,
+ Aligned = Aligned0 andalso AF(Bits, Bits),
+ {get_bits,Sv,[U,binary,{align,Aligned}]};
+dec_string({{Sv,Sv},[]}, U, Aligned, AF) ->
+ bit_case(dec_string(Sv, U, Aligned, AF),
+ dec_string(no, U, Aligned, AF));
+dec_string({{_,_}=C,[]}, U, Aligned, AF) ->
+ bit_case(dec_string(C, U, Aligned, AF),
+ dec_string(no, U, Aligned, AF));
+dec_string({Lb,Ub}, U, Aligned0, AF) ->
+ Len = per_dec_constrained(Lb, Ub, Aligned0),
+ Aligned = Aligned0 andalso AF(Lb*U, Ub*U),
+ {get_bits,Len,[U,binary,{align,Aligned}]};
+dec_string(_, U, Aligned, _AF) ->
+ Al = [{align,Aligned}],
+ DecRest = fun(V, Buf) ->
+ asn1ct_func:call(per_common,
+ decode_fragmented,
+ [V,Buf,U])
+ end,
+ {'case',[{test,{get_bits,1,[1|Al]},0,
+ {value,{get_bits,
+ {get_bits,7,[1]},
+ [U,binary]}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},0,
+ {value,{get_bits,
+ {get_bits,14,[1]},
+ [U,binary]}}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},1,
+ {value,{call,DecRest,{get_bits,6,[1]}}}}}]}.
+
+per_dec_enumerated_fix_list([{V,_}|T], Tail, N) ->
+ [{N,V}|per_dec_enumerated_fix_list(T, Tail, N+1)];
+per_dec_enumerated_fix_list([], Tail, _) -> Tail.
+
+per_dec_integer_1([{'SingleValue',Value}], _Aligned) ->
+ {value,Value};
+per_dec_integer_1([{'ValueRange',{Lb,'MAX'}}], Aligned) when is_integer(Lb) ->
+ per_decode_semi_constrained(Lb, Aligned);
+per_dec_integer_1([{'ValueRange',{Lb,Ub}}], Aligned) when is_integer(Lb),
+ is_integer(Ub) ->
+ per_dec_constrained(Lb, Ub, Aligned);
+per_dec_integer_1([{{_,_}=Constr0,_}], Aligned) ->
+ Constr = effective_constraint(integer, [Constr0]),
+ bit_case(per_dec_integer(Constr, Aligned),
+ per_dec_unconstrained(Aligned));
+per_dec_integer_1([], Aligned) ->
+ per_dec_unconstrained(Aligned).
+
+per_dec_unconstrained(Aligned) ->
+ {get_bits,decode_unconstrained_length(false, Aligned),[8,signed]}.
+
+per_dec_constrained(Lb, Ub, false) ->
+ Range = Ub - Lb + 1,
+ Get = {get_bits,uper_num_bits(Range),[1]},
+ add_lb(Lb, Get);
+per_dec_constrained(Lb, Ub, true) ->
+ Range = Ub - Lb + 1,
+ Get = if
+ Range =< 255 ->
+ {get_bits,per_num_bits(Range),[1,unsigned]};
+ Range == 256 ->
+ {get_bits,1,[8,unsigned,{align,true}]};
+ Range =< 65536 ->
+ {get_bits,2,[8,unsigned,{align,true}]};
+ true ->
+ RangeOctLen = byte_size(binary:encode_unsigned(Range - 1)),
+ {get_bits,per_dec_length({1,RangeOctLen}, false, true),
+ [8,unsigned,{align,true}]}
+ end,
+ add_lb(Lb, Get).
+
+add_lb(0, Get) -> Get;
+add_lb(Lb, Get) -> {add,Get,Lb}.
+
+per_dec_normally_small_number(Aligned) ->
+ Small = {get_bits,6,[1]},
+ Unlimited = per_decode_semi_constrained(0, Aligned),
+ bit_case(Small, Unlimited).
+
+per_dec_normally_small_length(Aligned) ->
+ Small = {add,{get_bits,6,[1]},1},
+ Unlimited = decode_unconstrained_length(false, Aligned),
+ bit_case(Small, Unlimited).
+
+per_decode_semi_constrained(Lb, Aligned) ->
+ add_lb(Lb, {get_bits,decode_unconstrained_length(false, Aligned),[8]}).
+
+bit_case(Base, Ext) ->
+ {'case',[{test,{get_bits,1,[1]},0,Base},
+ {test,{get_bits,1,[1]},1,Ext}]}.
+
+decode_unconstrained_length(AllowZero, Aligned) ->
+ Al = [{align,Aligned}],
+ Zero = case AllowZero of
+ false -> [non_zero];
+ true -> []
+ end,
+ {'case',[{test,{get_bits,1,[1|Al]},0,
+ {value,{get_bits,7,[1|Zero]}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},0,
+ {value,{get_bits,14,[1|Zero]}}}}]}.
+
+uper_num_bits(N) ->
+ uper_num_bits(N, 1, 0).
+
+uper_num_bits(N, T, B) when N =< T -> B;
+uper_num_bits(N, T, B) -> uper_num_bits(N, T bsl 1, B+1).
+
+per_num_bits(2) -> 1;
+per_num_bits(N) when N =< 4 -> 2;
+per_num_bits(N) when N =< 8 -> 3;
+per_num_bits(N) when N =< 16 -> 4;
+per_num_bits(N) when N =< 32 -> 5;
+per_num_bits(N) when N =< 64 -> 6;
+per_num_bits(N) when N =< 128 -> 7;
+per_num_bits(N) when N =< 255 -> 8.
+
+matched_range({get_bits,Bits0,[U|Flags]}) when is_integer(U) ->
+ case lists:member(signed, Flags) of
+ false ->
+ Bits = U*Bits0,
+ {0,(1 bsl Bits) - 1};
+ true ->
+ unknown
+ end;
+matched_range(_Op) -> unknown.
+
+string_num_bits(StringType, Constraint, Aligned) ->
+ case get_constraint(Constraint, 'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv), Aligned);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ charbits(128, Aligned);
+ 'VisibleString' ->
+ charbits(95, Aligned);
+ 'PrintableString' ->
+ charbits(74, Aligned);
+ 'NumericString' ->
+ charbits(11, Aligned);
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+charbits(NumChars, false) ->
+ uper_num_bits(NumChars);
+charbits(NumChars, true) ->
+ 1 bsl uper_num_bits(uper_num_bits(NumChars)).
+
+convert_string(8, notab, Imm) ->
+ {convert,binary_to_list,Imm};
+convert_string(NumBits, notab, Imm) when NumBits < 8 ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_chars,
+ [V,NumBits]},com,Buf,"}"])
+ end,
+ {call,Dec,Imm};
+convert_string(NumBits, notab, Imm) when NumBits =:= 16 ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_chars_16bit,
+ [V]},com,Buf,"}"])
+ end,
+ {call,Dec,Imm};
+convert_string(NumBits, notab, Imm) ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_big_chars,
+ [V,NumBits]},com,Buf,"}"])
+ end,
+ {call,Dec,Imm};
+convert_string(NumBits, Chars, Imm) ->
+ Dec = fun(V, Buf) ->
+ emit(["{",{call,per_common,decode_chars,
+ [V,NumBits,{asis,Chars}]},com,Buf,"}"])
+ end,
+ {call,Dec,Imm}.
+
+char_tab(C, StringType, NumBits) ->
+ case get_constraint(C, 'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ char_tab_1(Sv, NumBits);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ notab;
+ 'VisibleString' ->
+ notab;
+ 'PrintableString' ->
+ Chars = " '()+,-./0123456789:=?"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz",
+ char_tab_1(Chars, NumBits);
+ 'NumericString' ->
+ char_tab_1(" 0123456789", NumBits);
+ 'UniversalString' ->
+ notab;
+ 'BMPString' ->
+ notab
+ end
+ end.
+
+char_tab_1(Chars, NumBits) ->
+ Max = lists:max(Chars),
+ BitValMax = (1 bsl NumBits) - 1,
+ if
+ Max =< BitValMax ->
+ notab;
+ true ->
+ list_to_tuple(lists:sort(Chars))
+ end.
+
+%%%
+%%% Remove unnecessary aligning to octet boundaries.
+%%%
+
+opt_al({get_bits,E0,Opts0}, A0) ->
+ {E,A1} = opt_al(E0, A0),
+ Opts = opt_al_1(A1, Opts0),
+ A = update_al(A1, E, Opts),
+ {{get_bits,E,Opts},A};
+opt_al({call,Fun,E0}, A0) ->
+ {E,A} = opt_al(E0, A0),
+ {{call,Fun,E},A};
+opt_al({convert,Op,E0}, A0) ->
+ {E,A} = opt_al(E0, A0),
+ {{convert,Op,E},A};
+opt_al({value,V}=Term, A) when is_integer(V); is_atom(V) ->
+ {Term,A};
+opt_al({value,E0}, A0) ->
+ {E,A} = opt_al(E0, A0),
+ {{value,E},A};
+opt_al({add,E0,I}, A0) when is_integer(I) ->
+ {E,A} = opt_al(E0, A0),
+ {{add,E,I},A};
+opt_al({test,E0,V,B0}, A0) ->
+ {E,A1} = opt_al(E0, A0),
+ {B,A2} = opt_al(B0, A1),
+ {{test,E,V,B},A2};
+opt_al({'case',Cs0}, A0) ->
+ {Cs,A} = opt_al_cs(Cs0, A0),
+ {{'case',Cs},A};
+opt_al({map,E0,Cs}, A0) ->
+ {E,A} = opt_al(E0, A0),
+ {{map,E,Cs},A};
+opt_al(I, A) when is_integer(I) ->
+ {I,A}.
+
+opt_al_cs([C0|Cs0], A0) ->
+ {C,A1} = opt_al(C0, A0),
+ {Cs,A2} = opt_al_cs(Cs0, A0),
+ {[C|Cs],merge_al(A1, A2)};
+opt_al_cs([], _) -> {[],none}.
+
+merge_al(unknown, _) -> unknown;
+merge_al(Other, none) -> Other;
+merge_al(_, unknown) -> unknown;
+merge_al(I0, I1) ->
+ case {I0 rem 8,I1 rem 8} of
+ {I,I} -> I;
+ {_,_} -> unknown
+ end.
+
+opt_al_1(unknown, Opts) ->
+ Opts;
+opt_al_1(A, Opts0) ->
+ case alignment(Opts0) of
+ none ->
+ Opts0;
+ full ->
+ case A rem 8 of
+ 0 ->
+ %% Already in alignment.
+ proplists:delete(align, Opts0);
+ Bits ->
+ %% Cheaper alignment with a constant padding.
+ Opts1 = proplists:delete(align, Opts0),
+ [{align,8-Bits }|Opts1]
+ end;
+ A -> %Assertion.
+ Opts0
+ end.
+
+update_al(A0, E, Opts) ->
+ A = case alignment(Opts) of
+ none -> A0;
+ full -> 0;
+ Bits when is_integer(A0) ->
+ 0 = (A0 + Bits) rem 8; %Assertion.
+ _ ->
+ 0
+ end,
+ [U] = [U || U <- Opts, is_integer(U)],
+ if
+ U rem 8 =:= 0 -> A;
+ is_integer(A), is_integer(E) -> A + U*E;
+ true -> unknown
+ end.
+
+%%%
+%%% Flatten the intermediate format and assign temporaries.
+%%%
+
+flatten({get_bits,I,U}, Buf0, St0) when is_integer(I) ->
+ {Dst,St} = new_var_pair(St0),
+ Gb = {get_bits,{I,Buf0},U,Dst},
+ flatten_align(Gb, [], St);
+flatten({get_bits,E0,U}, Buf0, St0) ->
+ {E,Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var_pair(St1),
+ Gb = {get_bits,E,U,Dst},
+ flatten_align(Gb, Pre, St2);
+flatten({test,{get_bits,I,U},V,E0}, Buf0, St0) when is_integer(I) ->
+ {DstBuf0,St1} = new_var("Buf", St0),
+ Gb = {get_bits,{I,Buf0},U,{V,DstBuf0}},
+ {{_Dst,DstBuf},Pre0,St2} = flatten_align(Gb, [], St1),
+ {E,Pre1,St3} = flatten(E0, DstBuf, St2),
+ {E,Pre0++Pre1,St3};
+flatten({add,E0,I}, Buf0, St0) ->
+ {{Src,Buf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St} = new_var("Add", St1),
+ {{Dst,Buf},Pre++[{add,Src,I,Dst}],St};
+flatten({'case',Cs0}, Buf0, St0) ->
+ {Dst,St1} = new_var_pair(St0),
+ {Cs1,St} = flatten_cs(Cs0, Buf0, St1),
+ {Al,Cs2} = flatten_hoist_align(Cs1),
+ {Dst,Al++[{'case',Buf0,Cs2,Dst}],St};
+flatten({map,E0,Cs0}, Buf0, St0) ->
+ {{E,DstBuf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var("Int", St1),
+ Cs = flatten_map_cs(Cs0, E),
+ {{Dst,DstBuf},Pre++[{'map',E,Cs,{Dst,DstBuf}}],St2};
+flatten({value,V}, Buf0, St0) when is_atom(V) ->
+ {{"'"++atom_to_list(V)++"'",Buf0},[],St0};
+flatten({value,V0}, Buf0, St0) when is_integer(V0) ->
+ {{V0,Buf0},[],St0};
+flatten({value,V0}, Buf0, St0) ->
+ flatten(V0, Buf0, St0);
+flatten({convert,Op,E0}, Buf0, St0) ->
+ {{E,Buf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var("Conv", St1),
+ {{Dst,Buf},Pre++[{convert,Op,E,Dst}],St2};
+flatten({call,Fun,E0}, Buf0, St0) ->
+ {Src,Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St2} = new_var_pair(St1),
+ {Dst,Pre++[{call,Fun,Src,Dst}],St2}.
+
+flatten_cs([C0|Cs0], Buf, St0) ->
+ {C,Pre,St1} = flatten(C0, Buf, St0),
+ {Cs,St2} = flatten_cs(Cs0, Buf, St0),
+ St3 = St2#st{var=max(St1#st.var, St2#st.var)},
+ {[Pre++[{return,C}]|Cs],St3};
+flatten_cs([], _, St) -> {[],St}.
+
+flatten_map_cs(Cs, Var) ->
+ flatten_map_cs_1(Cs, {Var,Cs}).
+
+flatten_map_cs_1([{K,V}|Cs], DefData) ->
+ [{{asis,K},{asis,V}}|flatten_map_cs_1(Cs, DefData)];
+flatten_map_cs_1([integer_default], {Int,_}) ->
+ [{'_',Int}];
+flatten_map_cs_1([enum_default], {Int,_}) ->
+ [{'_',["{asn1_enum,",Int,"}"]}];
+flatten_map_cs_1([enum_error], {Var,Cs}) ->
+ Vs = [V || {_,V} <- Cs],
+ [{'_',["exit({error,{asn1,{decode_enumerated,{",Var,",",
+ {asis,Vs},"}}}})"]}];
+flatten_map_cs_1([], _) -> [].
+
+flatten_hoist_align([[{align_bits,_,_}=Ab|T]|Cs]) ->
+ flatten_hoist_align_1(Cs, Ab, [T]);
+flatten_hoist_align(Cs) -> {[],Cs}.
+
+flatten_hoist_align_1([[Ab|T]|Cs], Ab, Acc) ->
+ flatten_hoist_align_1(Cs, Ab, [T|Acc]);
+flatten_hoist_align_1([], Ab, Acc) ->
+ {[Ab],lists:reverse(Acc)}.
+
+flatten_align({get_bits,{SrcBits,SrcBuf},U,Dst}=Gb0, Pre, St0) ->
+ case alignment(U) of
+ none ->
+ flatten_align_1(U, Dst, Pre++[Gb0], St0);
+ full ->
+ {PadBits,St1} = new_var("Pad", St0),
+ {DstBuf,St2} = new_var("Buf", St1),
+ Ab = {align_bits,SrcBuf,PadBits},
+ Agb = {get_bits,{PadBits,SrcBuf},[1],{'_',DstBuf}},
+ Gb = {get_bits,{SrcBits,DstBuf},U,Dst},
+ flatten_align_1(U, Dst, Pre++[Ab,Agb,Gb], St2);
+ PadBits when is_integer(PadBits), PadBits > 0 ->
+ {DstBuf,St1} = new_var("Buf", St0),
+ Agb = {get_bits,{PadBits,SrcBuf},[1],{'_',DstBuf}},
+ Gb = {get_bits,{SrcBits,DstBuf},U,Dst},
+ flatten_align_1(U, Dst, Pre++[Agb,Gb], St1)
+ end.
+
+flatten_align_1(U, {D,_}=Dst, Pre, St) ->
+ case is_non_zero(U) of
+ false ->
+ {Dst,Pre,St};
+ true ->
+ {Dst,Pre++[{non_zero,D}],St}
+ end.
+
+new_var_pair(St0) ->
+ {Var,St1} = new_var("V", St0),
+ {Buf,St2} = new_var("Buf", St1),
+ {{Var,Buf},St2}.
+
+new_var(Tag, #st{base=VarBase,var=N}=St) ->
+ {VarBase++Tag++integer_to_list(N),St#st{var=N+1}}.
+
+alignment([{align,false}|_]) -> none;
+alignment([{align,true}|_]) -> full;
+alignment([{align,Bits}|_]) -> Bits;
+alignment([_|T]) -> alignment(T);
+alignment([]) -> none.
+
+is_non_zero(Fl) ->
+ lists:member(non_zero, Fl).
+
+%%%
+%%% Generate Erlang code from the flattened intermediate format.
+%%%
+
+dcg_list_outside([{align_bits,Buf,SzVar}|T]) ->
+ emit([SzVar," = bit_size(",Buf,") band 7"]),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{'case',Buf,Cs,Dst}|T]) ->
+ dcg_case(Buf, Cs, Dst),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{'map',Val,Cs,Dst}|T]) ->
+ dcg_map(Val, Cs, Dst),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{add,S1,S2,Dst}|T]) ->
+ emit([Dst," = ",S1," + ",S2]),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{return,{V,Buf}}|T]) ->
+ emit(["{",V,",",Buf,"}"]),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{call,Fun,{V,Buf},{Dst,DstBuf}}|T]) ->
+ emit(["{",Dst,",",DstBuf,"} = "]),
+ Fun(V, Buf),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{convert,Op,V,Dst}|T]) ->
+ emit([Dst," = ",Op,"(",V,")"]),
+ iter_dcg_list_outside(T);
+dcg_list_outside([{get_bits,{_,Buf0},_,_}|_]=L0) ->
+ emit("<<"),
+ {L,Buf} = dcg_list_inside(L0, buf),
+ emit([Buf,"/bitstring>> = ",Buf0]),
+ iter_dcg_list_outside(L);
+dcg_list_outside([]) ->
+ emit("ignore"),
+ ok.
+
+iter_dcg_list_outside([_|_]=T) ->
+ emit([",",nl]),
+ dcg_list_outside(T);
+iter_dcg_list_outside([]) -> ok.
+
+dcg_case(Buf, Cs, {Dst,DstBuf}) ->
+ emit(["{",Dst,",",DstBuf,"} = case ",Buf," of",nl]),
+ dcg_case_cs(Cs),
+ emit("end").
+
+dcg_case_cs([C|Cs]) ->
+ emit("<<"),
+ {T0,DstBuf} = dcg_list_inside(C, buf),
+ emit([DstBuf,"/bitstring>>"]),
+ T1 = dcg_guard(T0),
+ dcg_list_outside(T1),
+ case Cs of
+ [] -> emit([nl]);
+ [_|_] -> emit([";",nl])
+ end,
+ dcg_case_cs(Cs);
+dcg_case_cs([]) -> ok.
+
+dcg_guard([{non_zero,Src}|T]) ->
+ emit([" when ",Src," =/= 0 ->",nl]),
+ T;
+dcg_guard(T) ->
+ emit([" ->",nl]),
+ T.
+
+dcg_map(Val, Cs, {Dst,_}) ->
+ emit([Dst," = case ",Val," of",nl]),
+ dcg_map_cs(Cs),
+ emit("end").
+
+dcg_map_cs([{K,V}]) ->
+ emit([K," -> ",V,nl]);
+dcg_map_cs([{K,V}|Cs]) ->
+ emit([K," -> ",V,";",nl]),
+ dcg_map_cs(Cs).
+
+dcg_list_inside([{get_bits,{Sz,_},Fl0,{Dst,DstBuf}}|T], _) ->
+ Fl = bit_flags(Fl0, []),
+ emit([mk_dest(Dst),":",Sz,Fl,","]),
+ dcg_list_inside(T, DstBuf);
+dcg_list_inside(L, Dst) -> {L,Dst}.
+
+bit_flags([{align,_}|T], Acc) ->
+ bit_flags(T, Acc);
+bit_flags([non_zero|T], Acc) ->
+ bit_flags(T, Acc);
+bit_flags([U|T], Acc) when is_integer(U) ->
+ bit_flags(T, ["unit:"++integer_to_list(U)|Acc]);
+bit_flags([H|T], Acc) ->
+ bit_flags(T, [atom_to_list(H)|Acc]);
+bit_flags([], []) ->
+ "";
+bit_flags([], Acc) ->
+ case "/" ++ bit_flags_1(Acc, "") of
+ "/unit:1" -> [];
+ Opts -> Opts
+ end.
+
+
+bit_flags_1([H|T], Sep) ->
+ Sep ++ H ++ bit_flags_1(T, "-");
+bit_flags_1([], _) -> [].
+
+mk_dest(I) when is_integer(I) ->
+ integer_to_list(I);
+mk_dest(S) -> S.
+
+%% effective_constraint(Type,C)
+%% Type = atom()
+%% C = [C1,...]
+%% C1 = {'SingleValue',SV} | {'ValueRange',VR} | {atom(),term()}
+%% SV = integer() | [integer(),...]
+%% VR = {Lb,Ub}
+%% Lb = 'MIN' | integer()
+%% Ub = 'MAX' | integer()
+%% Returns a single value if C only has a single value constraint, and no
+%% value range constraints, that constrains to a single value, otherwise
+%% returns a value range that has the lower bound set to the lowest value
+%% of all single values and lower bound values in C and the upper bound to
+%% the greatest value.
+effective_constraint(integer,[C={{_,_},_}|_Rest]) -> % extension
+ [C];
+effective_constraint(integer, C) ->
+ SVs = get_constraints(C, 'SingleValue'),
+ SV = effective_constr('SingleValue', SVs),
+ VRs = get_constraints(C, 'ValueRange'),
+ VR = effective_constr('ValueRange', VRs),
+ greatest_common_range(SV, VR);
+effective_constraint(bitstring, C) ->
+ case get_constraint(C, 'SizeConstraint') of
+ {{Lb,Ub},[]}=Range when is_integer(Lb) ->
+ if
+ is_integer(Ub), Ub < 16#10000 ->
+ Range;
+ true ->
+ no
+ end;
+ {Lb,Ub}=Range when is_integer(Lb) ->
+ if
+ is_integer(Ub), Ub < 16#10000 ->
+ if
+ Lb =:= Ub -> Lb;
+ true -> Range
+ end;
+ true ->
+ no
+ end;
+ no ->
+ no
+ end.
+
+effective_constr(_, []) -> [];
+effective_constr('SingleValue', List) ->
+ SVList = lists:flatten(lists:map(fun(X) -> element(2, X) end, List)),
+ %% Sort and remove duplicates before generating SingleValue or ValueRange
+ %% In case of ValueRange, also check for 'MIN and 'MAX'
+ case lists:usort(SVList) of
+ [N] ->
+ [{'SingleValue',N}];
+ [_|_]=L ->
+ [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}]
+ end;
+effective_constr('ValueRange', List) ->
+ LBs = lists:map(fun({_,{Lb,_}}) -> Lb end, List),
+ UBs = lists:map(fun({_,{_,Ub}}) -> Ub end, List),
+ Lb = least_Lb(LBs),
+ [{'ValueRange',{Lb,lists:max(UBs)}}].
+
+greatest_common_range([], VR) ->
+ VR;
+greatest_common_range(SV, []) ->
+ SV;
+greatest_common_range([{_,Int}], [{_,{'MIN',Ub}}])
+ when is_integer(Int), Int > Ub ->
+ [{'ValueRange',{'MIN',Int}}];
+greatest_common_range([{_,Int}],[{_,{Lb,Ub}}])
+ when is_integer(Int), Int < Lb ->
+ [{'ValueRange',{Int,Ub}}];
+greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when is_integer(Int) ->
+ VR;
+greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when is_list(L) ->
+ Min = least_Lb([Lb|L]),
+ Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range([{_,{Lb1,Ub1}}], [{_,{Lb2,Ub2}}]) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
+ [{'ValueRange',{Min,Max}}].
+
+
+least_Lb(L) ->
+ case lists:member('MIN', L) of
+ true -> 'MIN';
+ false -> lists:min(L)
+ end.
+
+greatest_Ub(L) ->
+ case lists:member('MAX', L) of
+ true -> 'MAX';
+ false -> lists:max(L)
+ end.
+
+get_constraint(C, Key) ->
+ case lists:keyfind(Key, 1, C) of
+ false -> no;
+ {_,V} -> V
+ end.
+
+get_constraints([{Key,_}=Pair|T], Key) ->
+ [Pair|get_constraints(T, Key)];
+get_constraints([_|T], Key) ->
+ get_constraints(T, Key);
+get_constraints([], _) -> [].
diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl
index 3ab6f7b0ed..ba52e66ce3 100644
--- a/lib/asn1/src/asn1ct_name.erl
+++ b/lib/asn1/src/asn1ct_name.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -21,13 +21,8 @@
%%-compile(export_all).
-export([start/0,
- stop/0,
- push/1,
- pop/1,
curr/1,
clear/0,
- delete/1,
- active/1,
prev/1,
next/1,
all/1,
@@ -43,30 +38,19 @@ start() ->
end)),
ok;
_Pid ->
- already_started
+ %% Already started. Clear the variables.
+ clear()
end.
-stop() ->
- req(stop),
- erase(?MODULE).
-
name_server_loop({Ref, Parent} = Monitor,Vars) ->
%% io:format("name -- ~w~n",[Vars]),
receive
+ {_From,clear} ->
+ name_server_loop(Monitor, []);
{From,{current,Variable}} ->
From ! {?MODULE,get_curr(Vars,Variable)},
name_server_loop(Monitor,Vars);
- {From,{pop,Variable}} ->
- From ! {?MODULE,done},
- name_server_loop(Monitor,pop_var(Vars,Variable));
- {From,{push,Variable}} ->
- From ! {?MODULE,done},
- name_server_loop(Monitor,push_var(Vars,Variable));
- {From,{delete,Variable}} ->
- From ! {?MODULE,done},
- name_server_loop(Monitor,delete_var(Vars,Variable));
- {From,{new,Variable}} ->
- From ! {?MODULE,done},
+ {_From,{new,Variable}} ->
name_server_loop(Monitor,new_var(Vars,Variable));
{From,{prev,Variable}} ->
From ! {?MODULE,get_prev(Vars,Variable)},
@@ -74,32 +58,29 @@ name_server_loop({Ref, Parent} = Monitor,Vars) ->
{From,{next,Variable}} ->
From ! {?MODULE,get_next(Vars,Variable)},
name_server_loop(Monitor,Vars);
- {'DOWN', Ref, process, Parent, Reason} ->
- exit(Reason);
- {From,stop} ->
- From ! {?MODULE,stopped}
- end.
-
-active(V) ->
- case curr(V) of
- nil -> false;
- _ -> true
+ {'DOWN', Ref, process, Parent, Reason} ->
+ exit(Reason)
end.
req(Req) ->
- get(?MODULE) ! {self(), Req},
+ Pid = get(?MODULE),
+ Ref = monitor(process, Pid),
+ Pid ! {self(), Req},
receive
- {?MODULE, Reply} -> Reply
- after 5000 ->
- exit(name_server_timeout)
+ {?MODULE, Reply} ->
+ Reply;
+ {'DOWN', Ref, process, Pid, Reason} ->
+ error({name_server_died,Reason})
end.
-pop(V) -> req({pop,V}).
-push(V) -> req({push,V}).
-clear() -> stop(), start().
+cast(Req) ->
+ get(?MODULE) ! {self(), Req},
+ ok.
+
+clear() -> cast(clear).
curr(V) -> req({current,V}).
-new(V) -> req({new,V}).
-delete(V) -> req({delete,V}).
+new(V) -> cast({new,V}).
+
prev(V) ->
case req({prev,V}) of
none ->
@@ -108,11 +89,7 @@ prev(V) ->
end.
next(V) ->
- case req({next,V}) of
- none ->
- exit('cant get next of none');
- Rep -> Rep
- end.
+ req({next,V}).
all(V) ->
Curr = curr(V),
@@ -146,81 +123,36 @@ get_digs([H|T]) ->
[]
end.
-push_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- [{Variable,[0]}|Vars];
- {value,{Variable,[Digit|Drest]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit,Digit|Drest]}|NewVars]
- end.
-
-pop_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- ok;
- {value,{Variable,[_Dig]}} ->
- lists:keydelete(Variable,1,Vars);
- {value,{Variable,[_Dig|Digits]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,Digits}|NewVars]
- end.
-
-get_curr([],Variable) ->
+get_curr([], Variable) ->
Variable;
-get_curr([{Variable,[0|_Drest]}|_Tail],Variable) ->
- Variable;
-get_curr([{Variable,[Digit|_Drest]}|_Tail],Variable) ->
- list_to_atom(lists:concat([Variable,integer_to_list(Digit)]));
-
-get_curr([_|Tail],Variable) ->
- get_curr(Tail,Variable).
-
-new_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- [{Variable,[1]}|Vars];
- {value,{Variable,[Digit|Drest]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit+1|Drest]}|NewVars]
- end.
+get_curr([{Variable,Digit}|_Tail], Variable) ->
+ list_to_atom(lists:concat([Variable,Digit]));
+get_curr([_|Tail], Variable) ->
+ get_curr(Tail, Variable).
-delete_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
+new_var(Vars, Variable) ->
+ case lists:keyfind(Variable, 1, Vars) of
false ->
- Vars;
- {value,{Variable,[N]}} when N =< 1 ->
- lists:keydelete(Variable,1,Vars);
- {value,{Variable,[Digit|Drest]}} ->
- case Digit of
- 0 ->
- Vars;
- _ ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit-1|Drest]}|NewVars]
- end
+ [{Variable,1}|Vars];
+ {Variable,Digit} ->
+ NewVars = lists:keydelete(Variable, 1, Vars),
+ [{Variable,Digit+1}|NewVars]
end.
-get_prev(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
+get_prev(Vars, Variable) ->
+ case lists:keyfind(Variable, 1, Vars) of
false ->
none;
- {value,{Variable,[Digit|_]}} when Digit =< 1 ->
+ {Variable,Digit} when Digit =< 1 ->
Variable;
- {value,{Variable,[Digit|_]}} when Digit > 1 ->
- list_to_atom(lists:concat([Variable,
- integer_to_list(Digit-1)]));
- _ ->
- none
+ {Variable,Digit} when Digit > 1 ->
+ list_to_atom(lists:concat([Variable,Digit-1]))
end.
-get_next(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
+get_next(Vars, Variable) ->
+ case lists:keyfind(Variable, 1, Vars) of
false ->
list_to_atom(lists:concat([Variable,"1"]));
- {value,{Variable,[Digit|_]}} when Digit >= 0 ->
- list_to_atom(lists:concat([Variable,
- integer_to_list(Digit+1)]));
- _ ->
- none
+ {Variable,Digit} when Digit >= 0 ->
+ list_to_atom(lists:concat([Variable,Digit+1]))
end.
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 7301f49085..1abccc8626 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2013. 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
@@ -23,6 +23,10 @@
-export([parse/1]).
-include("asn1_records.hrl").
+%% Only used internally within this module.
+-record(typereference, {pos,val}).
+-record(constraint,{c,e}).
+
%% parse all types in module
parse(Tokens) ->
case catch parse_ModuleDefinition(Tokens) of
@@ -458,7 +462,8 @@ parse_BuiltinType([{'INSTANCE',_},{'OF',_}|Rest]) ->
{DefinedObjectClass,Rest2} = parse_DefinedObjectClass(Rest),
case Rest2 of
[{'(',_}|_] ->
- {Constraint,Rest3} = parse_Constraint(Rest2),
+ {Constraint0,Rest3} = parse_Constraint(Rest2),
+ Constraint = merge_constraints([Constraint0]),
{#type{def={'INSTANCE OF',DefinedObjectClass,Constraint}},Rest3};
_ ->
{#type{def={'INSTANCE OF',DefinedObjectClass,[]}},Rest2}
@@ -924,19 +929,8 @@ parse_UnionsRec([{'|',_}|Rest]) ->
{V1,V2} ->
{[V1,union,V2],Rest3}
end;
-parse_UnionsRec([{'UNION',_}|Rest]) ->
- {InterSec,Rest2} = parse_Intersections(Rest),
- {URec,Rest3} = parse_UnionsRec(Rest2),
- case {InterSec,URec} of
- {V1,[]} ->
- {V1,Rest3};
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3};
- {V1,V2} when is_list(V2) ->
- {[V1] ++ [union|V2],Rest3};
- {V1,V2} ->
- {[V1,union,V2],Rest3}
- end;
+parse_UnionsRec([{'UNION',Info}|Rest]) ->
+ parse_UnionsRec([{'|',Info}|Rest]);
parse_UnionsRec(Tokens) ->
{[],Tokens}.
@@ -971,20 +965,8 @@ parse_IElemsRec([{'^',_}|Rest]) ->
{V1,V2} ->
{[V1,intersection,V2],Rest3}
end;
-parse_IElemsRec([{'INTERSECTION',_}|Rest]) ->
- {InterSec,Rest2} = parse_IntersectionElements(Rest),
- {IRec,Rest3} = parse_IElemsRec(Rest2),
- case {InterSec,IRec} of
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',
- ordsets:intersection(to_set(V1),to_set(V2))},Rest3};
- {V1,[]} ->
- {V1,Rest3};
- {V1,V2} when is_list(V2) ->
- {[V1] ++ [intersection|V2],Rest3};
- {V1,V2} ->
- {[V1,intersection,V2],Rest3}
- end;
+parse_IElemsRec([{'INTERSECTION',Info}|Rest]) ->
+ parse_IElemsRec([{'^',Info}|Rest]);
parse_IElemsRec(Tokens) ->
{[],Tokens}.
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index 9013baef92..ecdfa3f645 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -51,10 +51,8 @@ from_type(M,Typename,Type) when is_record(Type,type) ->
from_type(Emod,Etype);
{_,user} ->
from_type(M,InnerType);
- {notype,_} ->
- true;
{primitive,bif} ->
- from_type_prim(Type,get_encoding_rule(M));
+ from_type_prim(M, Type);
'ASN1_OPEN_TYPE' ->
case Type#type.constraint of
[#'Externaltypereference'{type=TrefConstraint}] ->
@@ -65,7 +63,7 @@ from_type(M,Typename,Type) when is_record(Type,type) ->
end;
{constructed,bif} when Typename == ['EXTERNAL'] ->
Val=from_type_constructed(M,Typename,InnerType,Type),
- asn1rt_check:transform_to_EXTERNAL1994(Val);
+ asn1ct_eval_ext:transform_to_EXTERNAL1994(Val);
{constructed,bif} ->
from_type_constructed(M,Typename,InnerType,Type)
end;
@@ -164,7 +162,7 @@ gen_list(_,_,_,0) ->
gen_list(M,Typename,Oftype,N) ->
[from_type(M,Typename,Oftype)|gen_list(M,Typename,Oftype,N-1)].
-from_type_prim(D,Erule) ->
+from_type_prim(M, D) ->
C = D#type.constraint,
case D#type.def of
'INTEGER' ->
@@ -212,23 +210,10 @@ from_type_prim(D,Erule) ->
NN = [X||{X,_} <- NamedNumberList],
case NN of
[] ->
- Bl1 =lists:reverse(adjust_list(size_random(C),[1,0,1,1])),
- Bl2 = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,Bl1)),
- case {length(Bl2),get_constraint(C,'SizeConstraint')} of
- {Len,Len} ->
- Bl2;
- {_Len,Int} when is_integer(Int) ->
- Bl1;
- {Len,{Min,_}} when Min > Len ->
- Bl1;
- _ ->
- Bl2
- end;
+ random_unnamed_bit_string(M, C);
_ ->
[lists:nth(random(length(NN)),NN)]
end;
- 'ANY' ->
- exit({asn1_error,nyi,'ANY'});
'NULL' ->
'NULL';
'OBJECT IDENTIFIER' ->
@@ -303,12 +288,7 @@ from_type_prim(D,Erule) ->
adjust_list(size_random(C),c_string(C,"BMPString"));
'UTF8String' ->
{ok,Res}=asn1rt:utf8_list_to_binary(adjust_list(random(50),[$U,$T,$F,$8,$S,$t,$r,$i,$n,$g,16#ffff,16#fffffff,16#ffffff,16#fffff,16#fff])),
- case Erule of
- per ->
- binary_to_list(Res);
- _ ->
- Res
- end;
+ Res;
'UniversalString' ->
adjust_list(size_random(C),c_string(C,"UniversalString"));
XX ->
@@ -325,6 +305,32 @@ c_string(C,Default) ->
Default
end.
+random_unnamed_bit_string(M, C) ->
+ Bl1 = lists:reverse(adjust_list(size_random(C), [1,0,1,1])),
+ Bl2 = lists:reverse(lists:dropwhile(fun(0)-> true;
+ (1) -> false
+ end,Bl1)),
+ Val = case {length(Bl2),get_constraint(C, 'SizeConstraint')} of
+ {Len,Len} ->
+ Bl2;
+ {_Len,Int} when is_integer(Int) ->
+ Bl1;
+ {Len,{Min,_}} when Min > Len ->
+ Bl1;
+ _ ->
+ Bl2
+ end,
+ case M:bit_string_format() of
+ legacy ->
+ Val;
+ bitstring ->
+ << <<B:1>> || B <- Val >>;
+ compact ->
+ BitString = << <<B:1>> || B <- Val >>,
+ PadLen = (8 - (bit_size(BitString) band 7)) band 7,
+ {PadLen,<<BitString/bitstring,0:PadLen>>}
+ end.
+
%% FIXME:
%% random_sign(integer) ->
%% case random(2) of
@@ -440,20 +446,9 @@ get_encoding_rule(M) ->
end.
open_type_value(ber) ->
- [4,9,111,112,101,110,95,116,121,112,101];
-open_type_value(ber_bin) ->
-% [4,9,111,112,101,110,95,116,121,112,101];
- <<4,9,111,112,101,110,95,116,121,112,101>>;
-open_type_value(ber_bin_v2) ->
-% [4,9,111,112,101,110,95,116,121,112,101];
<<4,9,111,112,101,110,95,116,121,112,101>>;
-open_type_value(per) ->
- "\n\topen_type"; %octet string value "open_type"
-open_type_value(per_bin) ->
- <<"\n\topen_type">>;
-% <<10,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(_) ->
- [4,9,111,112,101,110,95,116,121,112,101].
+ <<"\n\topen_type">>. %octet string value "open_type"
to_textual_order({Root,Ext}) ->
{to_textual_order(Root),Ext};
diff --git a/lib/asn1/src/asn1rt_ber_bin.erl b/lib/asn1/src/asn1rt_ber_bin.erl
deleted file mode 100644
index 22f9f2ecfd..0000000000
--- a/lib/asn1/src/asn1rt_ber_bin.erl
+++ /dev/null
@@ -1,2471 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2010. 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%
-%%
-%%
--module(asn1rt_ber_bin).
-
-%% encoding / decoding of BER
-
--export([decode/1]).
--export([fixoptionals/2,split_list/2,cindex/3,restbytes2/3,
- list_to_record/2,
- encode_tag_val/1,decode_tag/1,peek_tag/1,
- check_tags/3, encode_tags/3]).
--export([encode_boolean/2,decode_boolean/3,
- encode_integer/3,encode_integer/4,
- decode_integer/4,decode_integer/5,encode_enumerated/2,
- encode_enumerated/4,decode_enumerated/5,
- encode_real/2, encode_real/3,
- decode_real/2, decode_real/4,
- encode_bit_string/4,decode_bit_string/6,
- decode_compact_bit_string/6,
- encode_octet_string/3,decode_octet_string/5,
- encode_null/2,decode_null/3,
- encode_object_identifier/2,decode_object_identifier/3,
- encode_relative_oid/2,decode_relative_oid/3,
- encode_restricted_string/4,decode_restricted_string/6,
- encode_universal_string/3,decode_universal_string/5,
- encode_UTF8_string/3, decode_UTF8_string/3,
- encode_BMP_string/3,decode_BMP_string/5,
- encode_generalized_time/3,decode_generalized_time/5,
- encode_utc_time/3,decode_utc_time/5,
- encode_length/1,decode_length/1,
- check_if_valid_tag/3,
- decode_tag_and_length/1, decode_components/6,
- decode_components/7, decode_set/6]).
-
--export([encode_open_type/1,encode_open_type/2,decode_open_type/1,decode_open_type/2,decode_open_type/3]).
--export([skipvalue/1, skipvalue/2,skip_ExtensionAdditions/2]).
-
--include("asn1_records.hrl").
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-%%% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-%%% The tag-number for universal types
--define(N_BOOLEAN, 1).
--define(N_INTEGER, 2).
--define(N_BIT_STRING, 3).
--define(N_OCTET_STRING, 4).
--define(N_NULL, 5).
--define(N_OBJECT_IDENTIFIER, 6).
--define(N_OBJECT_DESCRIPTOR, 7).
--define(N_EXTERNAL, 8).
--define(N_REAL, 9).
--define(N_ENUMERATED, 10).
--define(N_EMBEDDED_PDV, 11).
--define(N_UTF8String, 12).
--define('N_RELATIVE-OID',13).
--define(N_SEQUENCE, 16).
--define(N_SET, 17).
--define(N_NumericString, 18).
--define(N_PrintableString, 19).
--define(N_TeletexString, 20).
--define(N_VideotexString, 21).
--define(N_IA5String, 22).
--define(N_UTCTime, 23).
--define(N_GeneralizedTime, 24).
--define(N_GraphicString, 25).
--define(N_VisibleString, 26).
--define(N_GeneralString, 27).
--define(N_UniversalString, 28).
--define(N_BMPString, 30).
-
-
-% the complete tag-word of built-in types
--define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
--define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
--define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
--define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
--define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
--define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
--define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
--define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
--define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
--define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
--define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
--define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
--define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
--define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
--define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
--define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
-
-
-decode(Bin) ->
- decode_primitive(Bin).
-
-decode_primitive(Bin) ->
- {Tlv = {Tag,Len,V},<<>>} = decode_tlv(Bin),
- case element(2,Tag) of
- ?CONSTRUCTED ->
- {Tag,Len,decode_constructed(V)};
- _ ->
- Tlv
- end.
-
-decode_constructed(<<>>) ->
- [];
-decode_constructed(Bin) ->
- {Tlv = {Tag,Len,V},Rest} = decode_tlv(Bin),
- NewTlv =
- case element(2,Tag) of
- ?CONSTRUCTED ->
- {Tag,Len,decode_constructed(V)};
- _ ->
- Tlv
- end,
- [NewTlv|decode_constructed(Rest)].
-
-decode_tlv(Bin) ->
- {Tag,Bin1,_Rb1} = decode_tag(Bin),
- {{Len,Bin2},_Rb2} = decode_length(Bin1),
- <<V:Len/binary,Bin3/binary>> = Bin2,
- {{Tag,Len,V},Bin3}.
-
-
-
-%%%%%%%%%%%%%
-% split_list(List,HeadLen) -> {HeadList,TailList}
-%
-% splits List into HeadList (Length=HeadLen) and TailList
-% if HeadLen == indefinite -> return {List,indefinite}
-split_list(List,indefinite) ->
- {List, indefinite};
-split_list(Bin, Len) when is_binary(Bin) ->
- split_binary(Bin,Len);
-split_list(List,Len) ->
- {lists:sublist(List,Len),lists:nthtail(Len,List)}.
-
-
-%%% new function which fixes a bug regarding indefinite length decoding
-restbytes2(indefinite,<<0,0,RemBytes/binary>>,_) ->
- {RemBytes,2};
-restbytes2(indefinite,RemBytes,ext) ->
- skipvalue(indefinite,RemBytes);
-restbytes2(RemBytes,<<>>,_) ->
- {RemBytes,0};
-restbytes2(_RemBytes,Bytes,noext) ->
- exit({error,{asn1, {unexpected,Bytes}}});
-restbytes2(RemBytes,Bytes,ext) ->
-%% {RemBytes,0}.
- {RemBytes,byte_size(Bytes)}.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% skipvalue(Length, Bytes) -> {RemainingBytes, RemovedNumberOfBytes}
-%%
-%% skips the one complete (could be nested) TLV from Bytes
-%% handles both definite and indefinite length encodings
-%%
-
-skipvalue(L, Bytes) ->
- skipvalue(L, Bytes, 0).
-
-skipvalue(L, Bytes, Rb) ->
- skipvalue(L, Bytes, Rb, 0).
-
-skipvalue(indefinite, Bytes, Rb, IndefLevel) ->
- {T,Bytes2,R2} = decode_tag(Bytes),
- {{L,Bytes3},R3} = decode_length(Bytes2),
- case {T,L} of
- {_,indefinite} ->
- skipvalue(indefinite,Bytes3,Rb+R2+R3,IndefLevel+1);
- {{0,0,0},0} when IndefLevel =:= 0 ->
- %% See X690 8.1.5 NOTE, end of indefinite content
- {Bytes3,Rb+2};
- {{0,0,0},0} ->
- skipvalue(indefinite,Bytes3,Rb+2,IndefLevel - 1);
- _ ->
- <<_:L/binary, RestBytes/binary>> = Bytes3,
- skipvalue(indefinite,RestBytes,Rb+R2+R3+L, IndefLevel)
- %%{RestBytes, R2+R3+L}
- end;
-%% case Bytes4 of
-%% <<0,0,Bytes5/binary>> ->
-%% {Bytes5,Rb+Rb4+2};
-%% _ -> skipvalue(indefinite,Bytes4,Rb+Rb4)
-%% end;
-skipvalue(L, Bytes, Rb, _) ->
-% <<Skip:L/binary, RestBytes/binary>> = Bytes,
- <<_:L/binary, RestBytes/binary>> = Bytes,
- {RestBytes,Rb+L}.
-
-
-skipvalue(Bytes) ->
- {_T,Bytes2,R2} = decode_tag(Bytes),
- {{L,Bytes3},R3} = decode_length(Bytes2),
- skipvalue(L,Bytes3,R2+R3).
-
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%%%
-%% skips byte sequence of Bytes that do not match a tag in Tags
-skip_ExtensionAdditions(Bytes,Tags) ->
- skip_ExtensionAdditions(Bytes,Tags,0).
-skip_ExtensionAdditions(<<>>,_Tags,RmB) ->
- {<<>>,RmB};
-skip_ExtensionAdditions(Bytes,Tags,RmB) ->
- case catch decode_tag(Bytes) of
- {'EXIT',_Reason} ->
- tag_error(no_data,Tags,Bytes,'OPTIONAL');
- {_T={Class,_Form,TagNo},_Bytes2,_R2} ->
- case [X||X=#tag{class=Cl,number=TN} <- Tags,Cl==Class,TN==TagNo] of
- [] ->
- %% skip this TLV and continue with next
- {Bytes3,R3} = skipvalue(Bytes),
- skip_ExtensionAdditions(Bytes3,Tags,RmB+R3);
- _ ->
- {Bytes,RmB}
- end
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Optionals, preset not filled optionals with asn1_NOVALUE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when is_list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when is_tuple(Tuple) ->
- Tuple.
-
-
-fixoptionals(OptList,Val) when is_list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,_Acc1,Acc2) ->
- % return Val as a record
- list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
-
-
-%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%% 8bit Int | binary
-encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
- <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
-
-encode_tag_val({Class, Form, TagNo}) ->
- {Octets,_Len} = mk_object_val(TagNo),
- BinOct = list_to_binary(Octets),
- <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
-
-%% asumes whole correct tag bitpattern, multiple of 8
-encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
-%% asumes correct bitpattern of 0-5
-encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
-
-encode_tag_val2(Tag, OctAck) when (Tag =< 255) ->
- [Tag | OctAck];
-encode_tag_val2(Tag, OctAck) ->
- encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]).
-
-
-%%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%%% 8bit Int | [list of octets]
-%encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
-%%% <<Class:2,Form:1,TagNo:5>>;
-% [Class bor Form bor TagNo];
-%encode_tag_val({Class, Form, TagNo}) ->
-% {Octets,L} = mk_object_val(TagNo),
-% [Class bor Form bor 31 | Octets];
-
-
-%%============================================================================\%% Peek on the initial tag
-%% peek_tag(Bytes) -> TagBytes
-%% interprets the first byte and possible second, third and fourth byte as
-%% a tag and returns all the bytes comprising the tag, the constructed/primitive bit (6:th bit of first byte) is normalised to 0
-%%
-
-peek_tag(<<B7_6:2,_:1,31:5,Buffer/binary>>) ->
- Bin = peek_tag(Buffer, <<>>),
- <<B7_6:2,31:6,Bin/binary>>;
-%% single tag (tagno < 31)
-peek_tag(<<B7_6:2,_:1,B4_0:5,_Buffer/binary>>) ->
- <<B7_6:2,B4_0:6>>.
-
-peek_tag(<<0:1,PartialTag:7,_Buffer/binary>>, TagAck) ->
- <<TagAck/binary,PartialTag>>;
-peek_tag(<<PartialTag,Buffer/binary>>, TagAck) ->
- peek_tag(Buffer,<<TagAck/binary,PartialTag>>);
-peek_tag(_,TagAck) ->
- exit({error,{asn1, {invalid_tag,TagAck}}}).
-%%peek_tag([Tag|Buffer]) when (Tag band 31) =:= 31 ->
-%% [Tag band 2#11011111 | peek_tag(Buffer,[])];
-%%%% single tag (tagno < 31)
-%%peek_tag([Tag|Buffer]) ->
-%% [Tag band 2#11011111].
-
-%%peek_tag([PartialTag|Buffer], TagAck) when (PartialTag < 128 ) ->
-%% lists:reverse([PartialTag|TagAck]);
-%%peek_tag([PartialTag|Buffer], TagAck) ->
-%% peek_tag(Buffer,[PartialTag|TagAck]);
-%%peek_tag(Buffer,TagAck) ->
-%% exit({error,{asn1, {invalid_tag,lists:reverse(TagAck)}}}).
-
-
-%%===============================================================================
-%% Decode a tag
-%%
-%% decode_tag(OctetListBuffer) -> {{Class, Form, TagNo}, RestOfBuffer, RemovedBytes}
-%%===============================================================================
-
-%% multiple octet tag
-decode_tag(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
- {TagNo, Buffer1, RemovedBytes} = decode_tag(Buffer, 0, 1),
- {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer1, RemovedBytes};
-
-%% single tag (< 31 tags)
-decode_tag(<<Class:2,Form:1,TagNo:5, Buffer/binary>>) ->
- {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1}.
-
-%% last partial tag
-decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
- TagNo = (TagAck bsl 7) bor PartialTag,
- %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
- {TagNo, Buffer, RemovedBytes+1};
-% more tags
-decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
- TagAck1 = (TagAck bsl 7) bor PartialTag,
- %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
- decode_tag(Buffer, TagAck1, RemovedBytes+1).
-
-%%------------------------------------------------------------------
-%% check_tags_i is the same as check_tags except that it stops and
-%% returns the remaining tags not checked when it encounters an
-%% indefinite length field
-%% only called internally within this module
-
-check_tags_i([Tag], Buffer, OptOrMand) -> % optimized very usual case
- {[],check_one_tag(Tag, Buffer, OptOrMand)};
-check_tags_i(Tags, Buffer, OptOrMand) ->
- check_tags_i(Tags, Buffer, 0, OptOrMand).
-
-check_tags_i([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
- when Tag1#tag.type == 'IMPLICIT' ->
- check_tags_i([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
-
-check_tags_i([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
- {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
- case TagRest of
- [] -> {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
- _ ->
- case Form_Length of
- {?CONSTRUCTED,_} ->
- {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
- _ ->
- check_tags_i(TagRest, Buffer2, Rb + Rb1, mandatory)
- end
- end;
-
-check_tags_i([], Buffer, Rb, _) ->
- {[],{{0,0},Buffer,Rb}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This function is called from generated code
-
-check_tags([Tag], Buffer, OptOrMand) -> % optimized very usual case
- check_one_tag(Tag, Buffer, OptOrMand);
-check_tags(Tags, Buffer, OptOrMand) ->
- check_tags(Tags, Buffer, 0, OptOrMand).
-
-check_tags([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
- when Tag1#tag.type == 'IMPLICIT' ->
- check_tags([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
-
-check_tags([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
- {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
- case TagRest of
- [] -> {Form_Length, Buffer2, Rb + Rb1};
- _ -> check_tags(TagRest, Buffer2, Rb + Rb1, mandatory)
- end;
-
-check_tags([], Buffer, Rb, _) ->
- {{0,0},Buffer,Rb}.
-
-check_one_tag(Tag=#tag{class=ExpectedClass,number=ExpectedNumber}, Buffer, OptOrMand) ->
- case catch decode_tag(Buffer) of
- {'EXIT',_Reason} ->
- tag_error(no_data,Tag,Buffer,OptOrMand);
- {{ExpectedClass,Form,ExpectedNumber},Buffer2,Rb} ->
- {{L,Buffer3},RemBytes2} = decode_length(Buffer2),
- {{Form,L}, Buffer3, RemBytes2+Rb};
- {ErrorTag,_,_} ->
- tag_error(ErrorTag, Tag, Buffer, OptOrMand)
- end.
-
-tag_error(ErrorTag, Tag, Buffer, OptOrMand) ->
- case OptOrMand of
- mandatory ->
- exit({error,{asn1, {invalid_tag,
- {ErrorTag, Tag, Buffer}}}});
- _ ->
- exit({error,{asn1, {no_optional_tag,
- {ErrorTag, Tag, Buffer}}}})
- end.
-%%=======================================================================
-%%
-%% Encode all tags in the list Tags and return a possibly deep list of
-%% bytes with tag and length encoded
-%%
-%% prepend_tags(Tags, BytesSoFar, LenSoFar) -> {Bytes, Len}
-encode_tags(Tags, BytesSoFar, LenSoFar) ->
- NewTags = encode_tags1(Tags, []),
- %% NewTags contains the resulting tags in reverse order
- encode_tags2(NewTags, BytesSoFar, LenSoFar).
-
-%encode_tags2([#tag{class=?UNIVERSAL,number=No}|Trest], BytesSoFar, LenSoFar) ->
-% {Bytes2,L2} = encode_length(LenSoFar),
-% encode_tags2(Trest,[[No|Bytes2],BytesSoFar], LenSoFar + 1 + L2);
-encode_tags2([Tag|Trest], BytesSoFar, LenSoFar) ->
- {Bytes1,L1} = encode_one_tag(Tag),
- {Bytes2,L2} = encode_length(LenSoFar),
- encode_tags2(Trest, [Bytes1,Bytes2|BytesSoFar],
- LenSoFar + L1 + L2);
-encode_tags2([], BytesSoFar, LenSoFar) ->
- {BytesSoFar,LenSoFar}.
-
-encode_tags1([Tag1, Tag2| Trest], Acc) when Tag1#tag.type =:= 'IMPLICIT' ->
- encode_tags1([Tag1#tag{type=Tag2#tag.type,form=Tag2#tag.form}|Trest],Acc);
-encode_tags1([Tag1 | Trest], Acc) ->
- encode_tags1(Trest, [Tag1|Acc]);
-encode_tags1([], Acc) ->
- Acc. % the resulting tags are returned in reverse order
-
-encode_one_tag(Bin) when is_binary(Bin) ->
- {Bin,byte_size(Bin)};
-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)}.
-
-%%===============================================================================
-%% Change the tag (used when an implicit tagged type has a reference to something else)
-%% The constructed bit in the tag is taken from the tag to be replaced.
-%%
-%% change_tag(NewTag,[Tag,Buffer]) -> [NewTag,Buffer]
-%%===============================================================================
-
-%change_tag({NewClass,NewTagNr}, Buffer) ->
-% {{OldClass, OldForm, OldTagNo}, Buffer1, RemovedBytes} = decode_tag(lists:flatten(Buffer)),
-% [encode_tag_val({NewClass, OldForm, NewTagNr}) | Buffer1].
-
-
-%%===============================================================================
-%%
-%% 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) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-
-%% This version does not consider Explicit tagging of the open type. It
-%% is only left because of backward compatibility.
-encode_open_type(Val) when is_list(Val) ->
- {Val, byte_size(list_to_binary(Val))};
-encode_open_type(Val) ->
- {Val, byte_size(Val)}.
-
-%%
-encode_open_type(Val, []) when is_list(Val) ->
- {Val, byte_size(list_to_binary(Val))};
-encode_open_type(Val, []) ->
- {Val, byte_size(Val)};
-encode_open_type(Val, Tag) when is_list(Val) ->
- encode_tags(Tag, Val, byte_size(list_to_binary(Val)));
-encode_open_type(Val, Tag) ->
- encode_tags(Tag, Val, byte_size(Val)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer) -> Value
-%% Bytes = [byte] with BER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes) ->
-% {_Tag, Len, _RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
-% N = Len + RemovedBytes,
- {_Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
- {_RemainingBuffer2, RemovedBytes2} = skipvalue(Len, RemainingBuffer, RemovedBytes),
- N = RemovedBytes2,
- <<Val:N/binary, RemainingBytes/binary>> = Bytes,
-% {Val, RemainingBytes, Len + RemovedBytes}.
- {Val,RemainingBytes,N}.
-
-decode_open_type(<<>>,[]=ExplTag) -> % R9C-0.patch-40
- exit({error, {asn1,{no_optional_tag, ExplTag}}});
-decode_open_type(Bytes,ExplTag) ->
- {Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
- case {Tag,ExplTag} of
-% {{Class,Form,32},[#tag{class=Class,number=No,form=32}]} ->
-% {_Tag2, Len2, RemainingBuffer2, RemovedBytes2} = decode_tag_and_length(RemainingBuffer),
-% {_RemainingBuffer3, RemovedBytes3} = skipvalue(Len2, RemainingBuffer2, RemovedBytes2),
-% N = RemovedBytes3,
-% <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes,
-% {Val, RemainingBytes, N + RemovedBytes};
- {{Class,Form,No},[#tag{class=Class,number=No,form=Form}]} ->
- {_RemainingBuffer2, RemovedBytes2} =
- skipvalue(Len, RemainingBuffer),
- N = RemovedBytes2,
- <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes,
- {Val, RemainingBytes, N + RemovedBytes};
- _ ->
- {_RemainingBuffer2, RemovedBytes2} =
- skipvalue(Len, RemainingBuffer, RemovedBytes),
- N = RemovedBytes2,
- <<Val:N/binary, RemainingBytes/binary>> = Bytes,
- {Val, RemainingBytes, N}
- end.
-
-decode_open_type(ber_bin,Bytes,ExplTag) ->
- decode_open_type(Bytes,ExplTag);
-decode_open_type(ber,Bytes,ExplTag) ->
- {Val,RemBytes,Len}=decode_open_type(Bytes,ExplTag),
- {binary_to_list(Val),RemBytes,Len}.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Boolean, ITU_T X.690 Chapter 8.2
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode_boolean(Integer, tag | notag) -> [octet list]
-%%===============================================================================
-
-encode_boolean({Name, Val}, DoTag) when is_atom(Name) ->
- dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val));
-encode_boolean(true,[]) ->
- {[1,1,16#FF],3};
-encode_boolean(false,[]) ->
- {[1,1,0],3};
-encode_boolean(Val, DoTag) ->
- dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val)).
-
-%% encode_boolean(Boolean) -> [Len, Boolean] = [1, $FF | 0]
-encode_boolean(true) -> {[16#FF],1};
-encode_boolean(false) -> {[0],1};
-encode_boolean(X) -> exit({error,{asn1, {encode_boolean, X}}}).
-
-
-%%===============================================================================
-%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
-%% {false, Remain, RemovedBytes}
-%%===============================================================================
-
-decode_boolean(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_BOOLEAN}),
- decode_boolean_notag(Buffer, NewTags, OptOrMand).
-
-decode_boolean_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen,Buffer0,Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val,Buffer1,Rb1} = decode_boolean_notag(Buffer00, RestTags, OptOrMand),
- {Buffer2, Rb2} = restbytes2(RestBytes,Buffer1,noext),
- {Val, Buffer2, Rb0+Rb1+Rb2};
- {_,_} ->
- decode_boolean2(Buffer0, Rb0)
- end.
-
-decode_boolean2(<<0:8, Buffer/binary>>, RemovedBytes) ->
- {false, Buffer, RemovedBytes + 1};
-decode_boolean2(<<_:8, Buffer/binary>>, RemovedBytes) ->
- {true, Buffer, RemovedBytes + 1};
-decode_boolean2(Buffer, _) ->
- exit({error,{asn1, {decode_boolean, Buffer}}}).
-
-
-%%===========================================================================
-%% 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, []) when is_integer(Val) ->
- {EncVal,Len} = encode_integer(C, Val),
- dotag_universal(?N_INTEGER,EncVal,Len);
-encode_integer(C, Val, Tag) when is_integer(Val) ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, Val));
-encode_integer(C,{Name,Val},Tag) when is_atom(Name) ->
- encode_integer(C,Val,Tag);
-encode_integer(_, Val, _) ->
- exit({error,{asn1, {encode_integer, Val}}}).
-
-
-encode_integer(C, Val, NamedNumberList, Tag) when is_atom(Val) ->
- case lists:keyfind(Val, 1, NamedNumberList) of
- {_, NewVal} ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {encode_integer_namednumber, Val}}})
- end;
-encode_integer(C,{_,Val},NamedNumberList,Tag) ->
- encode_integer(C,Val,NamedNumberList,Tag);
-encode_integer(C, Val, _NamedNumberList, Tag) ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, Val)).
-
-
-encode_integer(_C, 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 16#ff| 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 16#ff|Acc]).
-
-%%===============================================================================
-%% decode integer
-%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%===============================================================================
-
-decode_integer(Buffer, Range, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
- decode_integer_notag(Buffer, Range, [], NewTags, OptOrMand).
-
-decode_integer(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
- decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand).
-
-decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(NewTags, Buffer, OptOrMand),
-% Result = {Val, Buffer2, RemovedBytes} =
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00, RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_integer_notag(Buffer00, Range, NamedNumberList,
- RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_, Len} ->
- Result =
- decode_integer2(Len,Buffer0,Rb0+Len),
- Result2 = check_integer_constraint(Result,Range),
- resolve_named_value(Result2,NamedNumberList)
- end.
-
-resolve_named_value(Result={Val,Buffer,RemBytes},NamedNumberList) ->
- case NamedNumberList of
- [] -> Result;
- _ ->
- NewVal = case lists:keyfind(Val, 2, NamedNumberList) of
- {NamedVal, _} ->
- NamedVal;
- _ ->
- Val
- end,
- {NewVal, Buffer, RemBytes}
- end.
-
-check_integer_constraint(Result={Val, _Buffer,_},Range) ->
- case Range of
- [] -> % No length constraint
- Result;
- {Lb,Ub} when Val >= Lb, Ub >= Val -> % variable length constraint
- Result;
- Val -> % fixed value constraint
- Result;
- {_,_} ->
- exit({error,{asn1,{integer_range,Range,Val}}});
- SingleValue when is_integer(SingleValue) ->
- exit({error,{asn1,{integer_range,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- Result
- end.
-
-%%============================================================================
-%% Enumerated value, ITU_T X.690 Chapter 8.4
-
-%% encode enumerated value
-%%============================================================================
-encode_enumerated(Val, []) when is_integer(Val) ->
- {EncVal,Len} = encode_integer(false,Val),
- dotag_universal(?N_ENUMERATED,EncVal,Len);
-encode_enumerated(Val, DoTag) when is_integer(Val) ->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(false,Val));
-encode_enumerated({Name,Val}, DoTag) when is_atom(Name) ->
- encode_enumerated(Val, DoTag).
-
-%% 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)
-
-encode_enumerated(C, Val, {NamedNumberList,ExtList}, DoTag) when is_atom(Val) ->
- case catch encode_enumerated(C, Val, NamedNumberList, DoTag) of
- {'EXIT',_} -> encode_enumerated(C, Val, ExtList, DoTag);
- Result -> Result
- end;
-
-encode_enumerated(C, Val, NamedNumberList, DoTag) when is_atom(Val) ->
- case lists:keyfind(Val, 1, NamedNumberList) of
- {_, NewVal} when DoTag =:= [] ->
- {EncVal,Len} = encode_integer(C,NewVal),
- dotag_universal(?N_ENUMERATED,EncVal,Len);
- {_, NewVal} ->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {enumerated_not_in_range, Val}}})
- end;
-
-encode_enumerated(C, {asn1_enum, Val}, {_,_}, DoTag) when is_integer(Val) ->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(C,Val));
-
-encode_enumerated(C, {Name,Val}, NamedNumberList, DoTag) when is_atom(Name) ->
- encode_enumerated(C, Val, NamedNumberList, DoTag);
-
-encode_enumerated(_, Val, _, _) ->
- exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
-
-
-
-%%============================================================================
-%% decode enumerated value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) ->
-%% {Value, RemainingBuffer, RemovedBytes}
-%%===========================================================================
-decode_enumerated(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_ENUMERATED}),
- decode_enumerated_notag(Buffer, Range, NamedNumberList,
- NewTags, OptOrMand).
-
-decode_enumerated_notag(Buffer, Range, NNList = {NamedNumberList,ExtList}, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {Val01, Buffer01, Rb01} =
- decode_integer2(Len, Buffer0, Rb0+Len),
- case decode_enumerated1(Val01, NamedNumberList) of
- {asn1_enum,Val01} ->
- {decode_enumerated1(Val01,ExtList), Buffer01, Rb01};
- Result01 ->
- {Result01, Buffer01, Rb01}
- end
- end;
-
-decode_enumerated_notag(Buffer, Range, NNList, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {Val01, Buffer02, Rb02} =
- decode_integer2(Len, Buffer0, Rb0+Len),
- case decode_enumerated1(Val01, NNList) of
- {asn1_enum,_} ->
- exit({error,{asn1, {illegal_enumerated, Val01}}});
- Result01 ->
- {Result01, Buffer02, Rb02}
- end
- end.
-
-decode_enumerated1(Val, NamedNumberList) ->
- %% it must be a named integer
- case lists:keyfind(Val, 2, NamedNumberList) of
- {NamedVal, _} ->
- NamedVal;
- _ ->
- {asn1_enum,Val}
- end.
-
-
-%%============================================================================
-%%
-%% Real value, ITU_T X.690 Chapter 8.5
-%%============================================================================
-%%
-%% encode real value
-%%============================================================================
-
-%% only base 2 internally so far!!
-encode_real(_C,0, DoTag) ->
- dotag(DoTag, ?N_REAL, {[],0});
-encode_real(_C,'PLUS-INFINITY', DoTag) ->
- dotag(DoTag, ?N_REAL, {[64],1});
-encode_real(_C,'MINUS-INFINITY', DoTag) ->
- dotag(DoTag, ?N_REAL, {[65],1});
-encode_real(C,Val, DoTag) when is_tuple(Val); is_list(Val) ->
- dotag(DoTag, ?N_REAL, encode_real(C,Val)).
-
-%%%%%%%%%%%%%%
-%% only base 2 encoding!
-%% binary encoding:
-%% +------------+ +------------+ +-+-+-+-+---+---+
-%% | (tag)9 | | n + p + 1 | |1|S|BB |FF |EE |
-%% +------------+ +------------+ +-+-+-+-+---+---+
-%%
-%% +------------+ +------------+
-%% | | | |
-%% +------------+ ...+------------+
-%% n octets for exponent
-%%
-%% +------------+ +------------+
-%% | | | |
-%% +------------+ ...+------------+
-%% p octets for pos mantissa
-%%
-%% S is 0 for positive sign
-%% 1 for negative sign
-%% BB: encoding base, 00 = 2, (01 = 8, 10 = 16)
-%% 01 and 10 not used
-%% FF: scale factor 00 = 0 (used in base 2 encoding)
-%% EE: encoding of the exponent:
-%% 00 - on the following octet
-%% 01 - on the 2 following octets
-%% 10 - on the 3 following octets
-%% 11 - encoding of the length of the two's-complement encoding of
-%% exponent on the following octet, and two's-complement
-%% encoding of exponent on the other octets.
-%%
-%% In DER and base 2 encoding the mantissa is encoded as value 0 or
-%% bit shifted until it is an odd number. Thus, do this for BER as
-%% well.
-%% This interface also used by RT_COMMON
-encode_real(_C,{Mantissa, Base, Exponent}) when Base =:= 2 ->
-%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
- {Man,ExpAdd} = truncate_zeros(Mantissa), %% DER adjustment
- Exp = Exponent + ExpAdd,
- OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, []));
- true -> list_to_binary(encode_integer_neg(Exp, []))
- end,
-%% ok = io:format("OctExp: ~w~n",[OctExp]),
- SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
- true -> 1
- end,
-%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
- SFactor = 0,
- OctExpLen = size(OctExp),
- if OctExpLen > 255 ->
- exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
- true -> true %% make real assert later..
- end,
- {LenCode, EOctets} = case OctExpLen of % bit 2,1
- 1 -> {0, OctExp};
- 2 -> {1, OctExp};
- 3 -> {2, OctExp};
- _ -> {3, <<OctExpLen, OctExp/binary>>}
- end,
- BB = 0, %% 00 for base 2
- FirstOctet = <<1:1,SignBit:1,BB:2,SFactor:2,LenCode:2>>,
- OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man));
- true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign
- end,
- %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
- Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
- {Bin, size(Bin)};
-encode_real(C,{Mantissa,Base,Exponent})
- when Base =:= 10, is_integer(Mantissa), is_integer(Exponent) ->
- %% always encode as NR3 due to DER on the format
- %% mmmm.Eseeee where
- %% m := digit
- %% s := '-' | '+' | []
- %% '+' only allowed in +0
- %% e := digit
- %% ex: 1234.E-5679
-%% {Man,AddExp} = truncate_zeros(Mantissa,0),
-%% ManNum = trunc(Mantissa),
-%% {TruncatedMan,NumZeros} = truncate_zeros10(Mantissa),
- ManStr = integer_to_list(Mantissa),
-
- encode_real_as_string(C,ManStr,Exponent);
-encode_real(_C,{_,Base,_}) ->
- exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}});
-%% base 10
-encode_real(C,Real) when is_list(Real) ->
- %% The Real string may come in as a NR1, NR2 or NR3 string.
- {Mantissa, Exponent} =
- case string:tokens(Real,"Ee") of
- [NR2] ->
- {NR2,0};
- [NR3MB,NR3E] ->
- %% remove beginning zeros
- {NR3MB,list_to_integer(NR3E)}
- end,
-
- %% .Decimal | Number | Number.Decimal
- ZeroDecimal =
- fun("0") -> "";
- (L) -> L
- end,
- {NewMantissa,LenDecimal} =
- case Mantissa of
- [$.|Dec] ->
- NewMan = remove_trailing_zeros(Dec),
- {NewMan,length(ZeroDecimal(NewMan))};
- _ ->
- case string:tokens(Mantissa,",.") of
- [Num] -> %% No decimal-mark
- {integer_to_list(list_to_integer(Num)),0};
- [Num,Dec] ->
- NewDec = ZeroDecimal(remove_trailing_zeros(Dec)),
- NewMan = integer_to_list(list_to_integer(Num)) ++ NewDec,
- {integer_to_list(list_to_integer(NewMan)),
- length(NewDec)}
- end
- end,
-
-% DER_Exponent = integer_to_list(Exponent - ExpReduce),
- encode_real_as_string(C,NewMantissa,Exponent - LenDecimal).
-
-encode_real_as_string(_C,Mantissa,Exponent)
- when is_list(Mantissa), is_integer(Exponent) ->
- %% Remove trailing zeros in Mantissa and add this to Exponent
- TruncMant = remove_trailing_zeros(Mantissa),
-
- ExpIncr = length(Mantissa) - length(TruncMant),
-
- ExpStr = integer_to_list(Exponent + ExpIncr),
-
- ExpBin =
- case ExpStr of
- "0" ->
- <<"E+0">>;
- _ ->
- ExpB = list_to_binary(ExpStr),
- <<$E,ExpB/binary>>
- end,
- ManBin = list_to_binary(TruncMant),
- NR3 = 3,
- {<<NR3,ManBin/binary,$.,ExpBin/binary>>,2 + size(ManBin) + size(ExpBin)}.
-
-remove_trailing_zeros(IntStr) ->
- case lists:dropwhile(fun($0)-> true;
- (_) -> false
- end, lists:reverse(IntStr)) of
- [] ->
- "0";
- ReversedIntStr ->
- lists:reverse(ReversedIntStr)
- end.
-
-truncate_zeros(Num) ->
- truncate_zeros(Num,0).
-truncate_zeros(0,Sum) ->
- {0,Sum};
-truncate_zeros(M,Sum) ->
- case M band 16#f =:= M band 16#e of
- true -> truncate_zeros(M bsr 1,Sum+1);
- _ -> {M,Sum}
- end.
-
-
-%%============================================================================
-%% decode real value
-%%
-%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
-%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
-%% RestBuff}
-%%
-%% only for base 2 decoding sofar!!
-%%============================================================================
-
-decode_real(Buffer, C, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_REAL}),
- decode_real_notag(Buffer, C, NewTags, OptOrMand).
-
-%% This interface used by RT_COMMON
-decode_real(Buffer,Len) ->
- decode_real2(Buffer,[],Len,0).
-
-decode_real_notag(Buffer, C, Tags, OptOrMand) ->
- {_RestTags, {{_,Len}, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
- decode_real2(Buffer0, C, Len, Rb0).
-
-decode_real2(Buffer, _C, 0, _RemBytes) ->
- {0,Buffer};
-decode_real2(Buffer0, _C, Len, RemBytes1) ->
- <<First, Buffer2/binary>> = Buffer0,
- if
- First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
- First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
-%% First =:= 2#00000000 -> {0, Buffer2};
- First =:= 1 orelse First =:= 2 orelse First =:= 3 ->
- %% charcter string encoding of base 10
- {NRx,Rest} = split_binary(Buffer2,Len-1),
- {binary_to_list(NRx),Rest,Len};
- true ->
- %% have some check here to verify only supported bases (2)
- %% not base 8 or 16
- <<_B7:1,Sign:1,BB:2,_FF:2,EE:2>> = <<First>>,
- Base =
- case BB of
- 0 -> 2; % base 2, only one so far
- _ -> exit({error,{asn1, {non_supported_base, BB}}})
- end,
- {FirstLen, {Exp, Buffer3,_Rb2}, RemBytes2} =
- case EE of
- 0 -> {2, decode_integer2(1, Buffer2, RemBytes1), RemBytes1+1};
- 1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2};
- 2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3};
- 3 ->
- <<ExpLen1,RestBuffer/binary>> = Buffer2,
- { ExpLen1 + 2,
- decode_integer2(ExpLen1, RestBuffer, RemBytes1),
- RemBytes1+ExpLen1}
- end,
- %% io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n",
-
- Length = Len - FirstLen,
- <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
- {{Mantissa, Buffer4}, RemBytes3} =
- if Sign =:= 0 ->
- %% io:format("sign plus~n"),
- {{LongInt, RestBuff}, 1 + Length};
- true ->
- %% io:format("sign minus~n"),
- {{-LongInt, RestBuff}, 1 + Length}
- end,
- {{Mantissa, Base, Exp}, Buffer4, RemBytes2+RemBytes3}
- 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_bit_string(C,Bin={Unused,BinBits},NamedBitList,DoTag) when is_integer(Unused), is_binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList,DoTag);
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList, DoTag) when is_atom(FirstVal) ->
- encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, DoTag) ->
- encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(C, [FirstVal| RestVal], NamedBitList, DoTag) when is_integer(FirstVal) ->
- encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(_, 0, _, []) ->
- {[?N_BIT_STRING,1,0],3};
-
-encode_bit_string(_, 0, _, DoTag) ->
- dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
-
-encode_bit_string(_, [], _, []) ->
- {[?N_BIT_STRING,1,0],3};
-
-encode_bit_string(_, [], _, DoTag) ->
- dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
-
-encode_bit_string(C, IntegerVal, NamedBitList, DoTag) when is_integer(IntegerVal) ->
- BitListVal = int_to_bitlist(IntegerVal),
- encode_bit_string_bits(C, BitListVal, NamedBitList, DoTag);
-
-encode_bit_string(C, {Name,BitList}, NamedBitList, DoTag) when is_atom(Name) ->
- encode_bit_string(C, BitList, NamedBitList, DoTag).
-
-
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when is_integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-
-%%=================================================================
-%% Encode BIT STRING of the form {Unused,BinBits}.
-%% Unused is the number of unused bits in the last byte in BinBits
-%% and BinBits is a binary representing the BIT STRING.
-%%=================================================================
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,DoTag)->
- case get_constraint(C,'SizeConstraint') of
- no ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,Unused,BinBits);
- {_Min,Max} ->
- BBLen = (size(BinBits)*8)-Unused,
- if
- BBLen > Max ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBLen},{maximum,Max}}}}});
- true ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,
- Unused,BinBits)
- end;
- Size ->
- case ((size(BinBits)*8)-Unused) of
- BBSize when BBSize =< Size ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,
- Unused,BinBits);
- BBSize ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBSize},{should_be,Size}}}}})
- end
- end.
-
-remove_unused_then_dotag(DoTag,StringType,Unused,BinBits) ->
- case Unused of
- 0 when (byte_size(BinBits) =:= 0), DoTag =:= [] ->
- %% time optimization of next case
- {[StringType,1,0],3};
- 0 when (byte_size(BinBits) =:= 0) ->
- dotag(DoTag,StringType,{<<0>>,1});
- 0 when DoTag =:= [] -> % time optimization of next case
- dotag_universal(StringType,[Unused|[BinBits]],size(BinBits)+1);
-% {LenEnc,Len} = encode_legth(size(BinBits)+1),
-% {[StringType,LenEnc,[Unused|BinBits]],size(BinBits)+1+Len+1};
- 0 ->
- dotag(DoTag,StringType,<<Unused,BinBits/binary>>);
- Num when DoTag =:= [] -> % time optimization of next case
- N = byte_size(BinBits) - 1,
- <<BBits:N/binary,LastByte>> = BinBits,
- dotag_universal(StringType,
- [Unused,BBits,(LastByte bsr Num) bsl Num],
- byte_size(BinBits) + 1);
-% {LenEnc,Len} = encode_legth(size(BinBits)+1),
-% {[StringType,LenEnc,[Unused,BBits,(LastByte bsr Num) bsl Num],
-% 1+Len+size(BinBits)+1};
- Num ->
- N = byte_size(BinBits) - 1,
- <<BBits:N/binary,LastByte>> = BinBits,
- dotag(DoTag,StringType,{[Unused,binary_to_list(BBits) ++
- [(LastByte bsr Num) bsl Num]],
- byte_size(BinBits) + 1})
- end.
-
-
-%%=================================================================
-%% Encode named bits
-%%=================================================================
-
-encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag) ->
- {Len,Unused,OctetList} =
- case get_constraint(C,'SizeConstraint') of
- no ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(lists:max(ToSetPos)+1,
- ToSetPos, 0),
- encode_bitstring(BitList);
- {_Min,Max} ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(Max, ToSetPos, 0),
- encode_bitstring(BitList);
- Size ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(Size, ToSetPos, 0),
- encode_bitstring(BitList)
- end,
- case DoTag of
- [] ->
- dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
-% {EncLen,LenLen} = encode_length(Len+1),
-% {[?N_BIT_STRING,EncLen,Unused,OctetList],1+LenLen+Len+1};
- _ ->
- dotag(DoTag, ?N_BIT_STRING, {[Unused|OctetList],Len+1})
- end.
-
-
-%%----------------------------------------
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-%%----------------------------------------
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-get_all_bitposes([Val | Rest], NamedBitList, Ack) when is_atom(Val) ->
- case lists:keyfind(Val, 1, NamedBitList) of
- {_ValName, ValPos} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-
-%%----------------------------------------
-%% 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),
-%%----------------------------------------
-
-make_and_set_list(0, [], _) -> [];
-make_and_set_list(0, _, _) ->
- exit({error,{asn1,bitstring_sizeconstraint}});
-make_and_set_list(Len, [XPos|SetPos], XPos) ->
- [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
-make_and_set_list(Len, [Pos|SetPos], XPos) ->
- [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
-make_and_set_list(Len, [], XPos) ->
- [0 | make_and_set_list(Len - 1, [], XPos + 1)].
-
-
-%%=================================================================
-%% Encode bit string for lists of ones and zeroes
-%%=================================================================
-encode_bit_string_bits(C, BitListVal, _NamedBitList, DoTag) when is_list(BitListVal) ->
- {Len,Unused,OctetList} =
- case get_constraint(C,'SizeConstraint') of
- no ->
- encode_bitstring(BitListVal);
- Constr={Min,_Max} when is_integer(Min) ->
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- {Constr={_,_},[]} ->
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- Size ->
- case length(BitListVal) of
- BitSize when BitSize =:= Size ->
- encode_bitstring(BitListVal);
- BitSize when BitSize < Size ->
- PaddedList =
- pad_bit_list(Size-BitSize,BitListVal),
- encode_bitstring(PaddedList);
- BitSize ->
- exit({error,
- {asn1,
- {bitstring_length,
- {{was,BitSize},
- {should_be,Size}}}}})
- end
- end,
- %%add unused byte to the Len
- case DoTag of
- [] ->
- dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
-% {EncLen,LenLen}=encode_length(Len+1),
-% {[?N_BIT_STRING,EncLen,Unused|OctetList],1+LenLen+Len+1};
- _ ->
- dotag(DoTag, ?N_BIT_STRING,
- {[Unused | OctetList],Len+1})
- end.
-
-
-encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,_DoTag) ->
- BitLen = length(BitListVal),
- case BitLen of
- Len when Len > Max2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max2}}}}});
- Len when Len > Max1, Len < Min2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {not_allowed_interval,
- Max1,Min2}}}}});
- _ ->
- encode_bitstring(BitListVal)
- end;
-encode_constr_bit_str_bits({Min,Max},BitListVal,_DoTag) ->
- BitLen = length(BitListVal),
- if
- BitLen > Max ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max}}}}});
- BitLen < Min ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {minimum,Min}}}}});
- true ->
- encode_bitstring(BitListVal)
- end.
-
-
-%% returns a list of length Size + length(BitListVal), with BitListVal
-%% as the most significant elements followed by padded zero elements
-pad_bit_list(Size,BitListVal) ->
- Tail = lists:duplicate(Size,0),
- BitListVal ++ Tail.
-
-%%=================================================================
-%% Do the actual encoding
-%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
-%%=================================================================
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Val], 1);
-encode_bitstring(Val) ->
- {Unused, Octet} = unused_bitlist(Val, 7, 0),
- {1, Unused, [Octet]}.
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Ack | [Val]], Len + 1);
-%%even multiple of 8 bits..
-encode_bitstring([], Ack, Len) ->
- {Len, 0, Ack};
-%% unused bits in last octet
-encode_bitstring(Rest, Ack, Len) ->
-% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
- {Unused, Val} = unused_bitlist(Rest, 7, 0),
- {Len + 1, Unused, [Ack | [Val]]}.
-
-%%%%%%%%%%%%%%%%%%
-%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
-%% {Unused bits, Last octet with bits moved to right}
-unused_bitlist([], Trail, Ack) ->
- {Trail + 1, Ack};
-unused_bitlist([Bit | Rest], Trail, Ack) ->
-%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
- unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
-
-
-%%============================================================================
-%% decode bitstring value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%============================================================================
-
-decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
- NamedNumberList, OptOrMand,bin).
-
-decode_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
- NamedNumberList, OptOrMand,old).
-
-
-decode_bit_string2(1,<<0 ,Buffer/binary>>,_NamedNumberList,RemovedBytes,BinOrOld) ->
- case BinOrOld of
- bin ->
- {{0,<<>>},Buffer,RemovedBytes};
- _ ->
- {[], Buffer, RemovedBytes}
- end;
-decode_bit_string2(Len,<<Unused,Buffer/binary>>,NamedNumberList,
- RemovedBytes,BinOrOld) ->
- L = Len - 1,
- <<Bits:L/binary,BufferTail/binary>> = Buffer,
- case NamedNumberList of
- [] ->
- case BinOrOld of
- bin ->
- {{Unused,Bits},BufferTail,RemovedBytes};
- _ ->
- BitString = decode_bitstring2(L, Unused, Buffer),
- {BitString,BufferTail, RemovedBytes}
- end;
- _ ->
- BitString = decode_bitstring2(L, Unused, Buffer),
- {decode_bitstring_NNL(BitString,NamedNumberList),
- BufferTail,
- RemovedBytes}
- end.
-
-%%----------------------------------------
-%% Decode the in buffer to bits
-%%----------------------------------------
-decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
-decode_bitstring2(Len, Unused,
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
- [B7, B6, B5, B4, B3, B2, B1, B0 |
- decode_bitstring2(Len - 1, Unused, Buffer)].
-
-%%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
-%%----------------------------------------
-
-decode_bitstring_NNL(BitList,NamedNumberList) ->
- decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
-
-
-decode_bitstring_NNL([],_,_No,Result) ->
- lists:reverse(Result);
-
-decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
- if
- B =:= 0 ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
- true ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
- end;
-decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
-decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
-
-
-%%============================================================================
-%% Octet string, ITU_T X.690 Chapter 8.7
-%%
-%% encode octet string
-%% The OctetList must be a flat list of integers in the range 0..255
-%% the function does not check this because it takes to much time
-%%============================================================================
-encode_octet_string(_C, OctetList, []) when is_binary(OctetList) ->
- dotag_universal(?N_OCTET_STRING,OctetList,byte_size(OctetList));
-encode_octet_string(_C, OctetList, DoTag) when is_binary(OctetList) ->
- dotag(DoTag, ?N_OCTET_STRING, {OctetList,byte_size(OctetList)});
-encode_octet_string(_C, OctetList, DoTag) when is_list(OctetList) ->
- case length(OctetList) of
- Len when DoTag =:= [] ->
- dotag_universal(?N_OCTET_STRING,OctetList,Len);
- Len ->
- dotag(DoTag, ?N_OCTET_STRING, {OctetList,Len})
- end;
-%% encode_octet_string(C, OctetList, DoTag) when is_list(OctetList) ->
-%% dotag(DoTag, ?N_OCTET_STRING, {OctetList,length(OctetList)});
-encode_octet_string(C, {Name,OctetList}, DoTag) when is_atom(Name) ->
- encode_octet_string(C, OctetList, DoTag).
-
-
-%%============================================================================
-%% decode octet string
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%
-%% Octet string is decoded as a restricted string
-%%============================================================================
-decode_octet_string(Buffer, Range, Tags, TotalLen, OptOrMand) ->
-%% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
- decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
- Tags, TotalLen, [], OptOrMand,old).
-
-%%============================================================================
-%% Null value, ITU_T X.690 Chapter 8.8
-%%
-%% encode NULL value
-%%============================================================================
-
-encode_null(_, []) ->
- {[?N_NULL,0],2};
-encode_null(_, DoTag) ->
- dotag(DoTag, ?N_NULL, {[],0}).
-
-%%============================================================================
-%% decode NULL value
-%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
-%%============================================================================
-decode_null(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_NULL}),
- decode_null_notag(Buffer, NewTags, OptOrMand).
-
-decode_null_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {_Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} = decode_null_notag(Buffer0, RestTags,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,0} ->
- {'NULL', Buffer0, Rb0};
- {_,Len} ->
- exit({error,{asn1,{invalid_length,'NULL',Len}}})
- end.
-
-
-%%============================================================================
-%% Object identifier, ITU_T X.690 Chapter 8.19
-%%
-%% encode Object Identifier value
-%%============================================================================
-
-encode_object_identifier({Name,Val}, DoTag) when is_atom(Name) ->
- encode_object_identifier(Val, DoTag);
-encode_object_identifier(Val, []) ->
- {EncVal,Len} = e_object_identifier(Val),
- dotag_universal(?N_OBJECT_IDENTIFIER,EncVal,Len);
-encode_object_identifier(Val, DoTag) ->
- dotag(DoTag, ?N_OBJECT_IDENTIFIER, e_object_identifier(Val)).
-
-e_object_identifier({'OBJECT IDENTIFIER', V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname, V}) when is_atom(Cname), is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname, V}) when is_atom(Cname), is_list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%%%%%%%%%%%%%%%
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-e_object_identifier([E1, E2 | Tail]) ->
- Head = 40*E1 + E2, % wow!
- {H,Lh} = mk_object_val(Head),
- {R,Lr} = enc_obj_id_tail(Tail, [], 0),
- {[H|R], Lh+Lr}.
-
-enc_obj_id_tail([], Ack, Len) ->
- {lists:reverse(Ack), Len};
-enc_obj_id_tail([H|T], Ack, Len) ->
- {B, L} = mk_object_val(H),
- enc_obj_id_tail(T, [B|Ack], Len+L).
-
-
-%%%%%%%%%%%
-%% 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
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-
-%%============================================================================
-%% decode Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-
-decode_object_identifier(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
- number=?N_OBJECT_IDENTIFIER}),
- decode_object_identifier_notag(Buffer, NewTags, OptOrMand).
-
-decode_object_identifier_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_object_identifier_notag(Buffer00,
- RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {[AddedObjVal|ObjVals],Buffer01} =
- dec_subidentifiers(Buffer0,0,[],Len),
- {Val1, Val2} = if
- AddedObjVal < 40 ->
- {0, AddedObjVal};
- AddedObjVal < 80 ->
- {1, AddedObjVal - 40};
- true ->
- {2, AddedObjVal - 80}
- end,
- {list_to_tuple([Val1, Val2 | ObjVals]), Buffer01,
- Rb0+Len}
- end.
-
-dec_subidentifiers(Buffer,_Av,Al,0) ->
- {lists:reverse(Al),Buffer};
-dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al,Len) ->
- dec_subidentifiers(T,(Av bsl 7) + H,Al,Len-1);
-dec_subidentifiers(<<H,T/binary>>,Av,Al,Len) ->
- dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1).
-
-%%============================================================================
-%% RELATIVE-OID, ITU_T X.690 Chapter 8.20
-%%
-%% encode Relative Object Identifier
-%%============================================================================
-encode_relative_oid({Name,Val},TagIn) when is_atom(Name) ->
- encode_relative_oid(Val,TagIn);
-encode_relative_oid(Val,TagIn) when is_tuple(Val) ->
- encode_relative_oid(tuple_to_list(Val),TagIn);
-encode_relative_oid(Val,[]) ->
- {EncVal,Len} = enc_relative_oid(Val),
- dotag_universal(?'N_RELATIVE-OID',EncVal,Len);
-encode_relative_oid(Val, DoTag) ->
- dotag(DoTag, ?'N_RELATIVE-OID', enc_relative_oid(Val)).
-
-enc_relative_oid(Val) ->
- lists:mapfoldl(fun(X,AccIn) ->
- {SO,L}=mk_object_val(X),
- {SO,L+AccIn}
- end
- ,0,Val).
-
-%%============================================================================
-%% decode Relative Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-decode_relative_oid(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
- number=?'N_RELATIVE-OID'}),
- decode_relative_oid_notag(Buffer, NewTags, OptOrMand).
-
-decode_relative_oid_notag(Buffer, Tags, OptOrMand) ->
- {_RestTags, {_FormLen={_,Len}, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
- {ObjVals,Buffer01} =
- dec_subidentifiers(Buffer0,0,[],Len),
- {list_to_tuple(ObjVals), Buffer01, Rb0+Len}.
-
-%%============================================================================
-%% Restricted character string types, ITU_T X.690 Chapter 8.21
-%%
-%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%%============================================================================
-encode_restricted_string(_C, OctetList, StringType, [])
- when is_binary(OctetList) ->
- dotag_universal(StringType, OctetList, byte_size(OctetList));
-encode_restricted_string(_C, OctetList, StringType, DoTag)
- when is_binary(OctetList) ->
- dotag(DoTag, StringType, {OctetList, byte_size(OctetList)});
-encode_restricted_string(_C, OctetList, StringType, [])
- when is_list(OctetList) ->
- dotag_universal(StringType, OctetList, length(OctetList));
-encode_restricted_string(_C, OctetList, StringType, DoTag)
- when is_list(OctetList) ->
- dotag(DoTag, StringType, {OctetList, length(OctetList)});
-encode_restricted_string(C,{Name,OctetL},StringType,DoTag) when is_atom(Name) ->
- encode_restricted_string(C, OctetL, StringType, DoTag).
-
-%%============================================================================
-%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, OptOrMand) ->
- {Val,Buffer2,Rb} =
- decode_restricted_string_tag(Buffer, Range, StringType, Tags,
- LenIn, [], OptOrMand,old),
- {check_and_convert_restricted_string(Val,StringType,Range,[],old),
- Buffer2,Rb}.
-
-
-decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, NNList, OptOrMand, BinOrOld ) ->
- {Val,Buffer2,Rb} =
- decode_restricted_string_tag(Buffer, Range, StringType, Tags,
- LenIn, NNList, OptOrMand, BinOrOld),
- {check_and_convert_restricted_string(Val,StringType,Range,NNList,BinOrOld),
- Buffer2,Rb}.
-
-decode_restricted_string_tag(Buffer, Range, StringType, TagsIn, LenIn, NNList, OptOrMand, BinOrOld ) ->
- NewTags = new_tags(TagsIn, #tag{class=?UNIVERSAL,number=StringType}),
- decode_restricted_string_notag(Buffer, Range, StringType, NewTags,
- LenIn, NNList, OptOrMand, BinOrOld).
-
-
-check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
- {StrLen,NewVal} = case StringType of
- ?N_BIT_STRING when NamedNumberList =/= [] ->
- {no_check,Val};
- ?N_BIT_STRING when is_list(Val) ->
- {length(Val),Val};
- ?N_BIT_STRING when is_tuple(Val) ->
- {(size(element(2,Val))*8) - element(1,Val),Val};
- _ when is_binary(Val) ->
- {byte_size(Val),binary_to_list(Val)};
- _ when is_list(Val) ->
- {length(Val), Val}
- end,
- case Range of
- _ when StrLen =:= no_check ->
- NewVal;
- [] -> % No length constraint
- NewVal;
- {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
- NewVal;
- {{Lb,_Ub},[]} when StrLen >= Lb ->
- NewVal;
- {{Lb,_Ub},_Ext=[MinExt|_]} when StrLen >= Lb; StrLen >= MinExt ->
- NewVal;
- {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
- StrLen =< Ub2, StrLen >= Lb2 ->
- NewVal;
- StrLen -> % fixed length constraint
- NewVal;
- {_,_} ->
- exit({error,{asn1,{length,Range,Val}}});
- _Len when is_integer(_Len) ->
- exit({error,{asn1,{length,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- NewVal
- end.
-
-%%=============================================================================
-%% Common routines for several string types including bit string
-%% handles indefinite length
-%%=============================================================================
-
-
-decode_restricted_string_notag(Buffer, _Range, StringType, TagsIn,
- _, NamedNumberList, OptOrMand, BinOrOld) ->
- %%-----------------------------------------------------------
- %% Get inner (the implicit tag or no tag) and
- %% outer (the explicit tag) lengths.
- %%-----------------------------------------------------------
- {RestTags, {FormLength={_,_Len01}, Buffer0, Rb0}} =
- check_tags_i(TagsIn, Buffer, OptOrMand),
-
- case FormLength of
- {?CONSTRUCTED,Len} ->
- {Buffer00, RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_restricted_parts(Buffer00, RestBytes, [], StringType,
- RestTags,
- Len, NamedNumberList,
- OptOrMand,
- BinOrOld, 0, []),
- {Val01, Buffer01, Rb0+Rb01};
- {_, Len} ->
- {Val01, Buffer01, Rb01} =
- decode_restricted(Buffer0, Len, StringType,
- NamedNumberList, BinOrOld),
- {Val01, Buffer01, Rb0+Rb01}
- end.
-
-
-decode_restricted_parts(Buffer, RestBytes, [], StringType, RestTags, Len, NNList,
- OptOrMand, BinOrOld, AccRb, AccVal) ->
- DecodeFun = case RestTags of
- [] -> fun decode_restricted_string_tag/8;
- _ -> fun decode_restricted_string_notag/8
- end,
- {Val, Buffer1, Rb} =
- DecodeFun(Buffer, [], StringType, RestTags,
- no_length, NNList,
- OptOrMand, BinOrOld),
- {Buffer2,More} =
- case Buffer1 of
- <<0,0,Buffer10/binary>> when Len == indefinite ->
- {Buffer10,false};
- <<>> ->
- {RestBytes,false};
- _ ->
- {Buffer1,true}
- end,
- {NewVal, NewRb} =
- case StringType of
- ?N_BIT_STRING when BinOrOld == bin ->
- {concat_bit_binaries(AccVal, Val), AccRb+Rb};
- _ when is_binary(Val),is_binary(AccVal) ->
- {<<AccVal/binary,Val/binary>>,AccRb+Rb};
- _ when is_binary(Val), AccVal =:= [] ->
- {Val,AccRb+Rb};
- _ ->
- {AccVal++Val, AccRb+Rb}
- end,
- case More of
- false ->
- {NewVal, Buffer2, NewRb};
- true ->
- decode_restricted_parts(Buffer2, RestBytes, [], StringType, RestTags, Len, NNList,
- OptOrMand, BinOrOld, NewRb, NewVal)
- end.
-
-
-
-decode_restricted(Buffer, InnerLen, StringType, NamedNumberList,BinOrOld) ->
-
- case StringType of
- ?N_BIT_STRING ->
- decode_bit_string2(InnerLen,Buffer,NamedNumberList,InnerLen,BinOrOld);
-
- ?N_UniversalString ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- UniString = mk_universal_string(binary_to_list(PreBuff)),
- {UniString,RestBuff,InnerLen};
- ?N_BMPString ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- BMP = mk_BMP_string(binary_to_list(PreBuff)),
- {BMP,RestBuff,InnerLen};
- _ ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- {PreBuff, RestBuff, InnerLen}
- end.
-
-
-
-%%============================================================================
-%% encode Universal string
-%%============================================================================
-
-encode_universal_string(C, {Name, Universal}, DoTag) when is_atom(Name) ->
- encode_universal_string(C, Universal, DoTag);
-encode_universal_string(_C, Universal, []) ->
- OctetList = mk_uni_list(Universal),
- dotag_universal(?N_UniversalString,OctetList,length(OctetList));
-encode_universal_string(_C, Universal, DoTag) ->
- OctetList = mk_uni_list(Universal),
- dotag(DoTag, ?N_UniversalString, {OctetList,length(OctetList)}).
-
-mk_uni_list(In) ->
- mk_uni_list(In,[]).
-
-mk_uni_list([],List) ->
- lists:reverse(List);
-mk_uni_list([{A,B,C,D}|T],List) ->
- mk_uni_list(T,[D,C,B,A|List]);
-mk_uni_list([H|T],List) ->
- mk_uni_list(T,[H,0,0,0|List]).
-
-%%===========================================================================
-%% decode Universal strings
-%% (Buffer, Range, StringType, HasTag, LenIn) ->
-%% {String, Remain, RemovedBytes}
-%%===========================================================================
-
-decode_universal_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_UniversalString}),
- decode_restricted_string(Buffer, Range, ?N_UniversalString,
- Tags, LenIn, [], OptOrMand,old).
-
-
-mk_universal_string(In) ->
- mk_universal_string(In,[]).
-
-mk_universal_string([],Acc) ->
- lists:reverse(Acc);
-mk_universal_string([0,0,0,D|T],Acc) ->
- mk_universal_string(T,[D|Acc]);
-mk_universal_string([A,B,C,D|T],Acc) ->
- mk_universal_string(T,[{A,B,C,D}|Acc]).
-
-
-%%============================================================================
-%% encode UTF8 string
-%%============================================================================
-encode_UTF8_string(_,UTF8String,[]) when is_binary(UTF8String) ->
- dotag_universal(?N_UTF8String,UTF8String,byte_size(UTF8String));
-encode_UTF8_string(_,UTF8String,DoTag) when is_binary(UTF8String) ->
- dotag(DoTag,?N_UTF8String,{UTF8String,byte_size(UTF8String)});
-encode_UTF8_string(_,UTF8String,[]) ->
- dotag_universal(?N_UTF8String,UTF8String,length(UTF8String));
-encode_UTF8_string(_,UTF8String,DoTag) ->
- dotag(DoTag,?N_UTF8String,{UTF8String,length(UTF8String)}).
-
-%%============================================================================
-%% decode UTF8 string
-%%============================================================================
-
-decode_UTF8_string(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags, #tag{class=?UNIVERSAL,number=?N_UTF8String}),
- decode_UTF8_string_notag(Buffer, NewTags, OptOrMand).
-
-decode_UTF8_string_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
- case FormLen of
- {?CONSTRUCTED,Len} ->
- %% an UTF8String may be encoded as a constructed type
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_UTF8_string_notag(Buffer00,RestTags,OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- <<Result:Len/binary,RestBuff/binary>> = Buffer0,
- {Result,RestBuff,Rb0 + Len}
- end.
-
-
-%%============================================================================
-%% encode BMP string
-%%============================================================================
-
-encode_BMP_string(C, {Name,BMPString}, DoTag) when is_atom(Name) ->
- encode_BMP_string(C, BMPString, DoTag);
-encode_BMP_string(_C, BMPString, []) ->
- OctetList = mk_BMP_list(BMPString),
- dotag_universal(?N_BMPString,OctetList,length(OctetList));
-encode_BMP_string(_C, BMPString, DoTag) ->
- OctetList = mk_BMP_list(BMPString),
- dotag(DoTag, ?N_BMPString, {OctetList,length(OctetList)}).
-
-mk_BMP_list(In) ->
- mk_BMP_list(In,[]).
-
-mk_BMP_list([],List) ->
- lists:reverse(List);
-mk_BMP_list([{0,0,C,D}|T],List) ->
- mk_BMP_list(T,[D,C|List]);
-mk_BMP_list([H|T],List) ->
- mk_BMP_list(T,[H,0|List]).
-
-%%============================================================================
-%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-decode_BMP_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_BMPString}),
- decode_restricted_string(Buffer, Range, ?N_BMPString,
- Tags, LenIn, [], OptOrMand,old).
-
-mk_BMP_string(In) ->
- mk_BMP_string(In,[]).
-
-mk_BMP_string([],US) ->
- lists:reverse(US);
-mk_BMP_string([0,B|T],US) ->
- mk_BMP_string(T,[B|US]);
-mk_BMP_string([C,D|T],US) ->
- mk_BMP_string(T,[{0,0,C,D}|US]).
-
-
-%%============================================================================
-%% Generalized time, ITU_T X.680 Chapter 39
-%%
-%% encode Generalized time
-%%============================================================================
-
-encode_generalized_time(C, {Name,OctetList}, DoTag) when is_atom(Name) ->
- encode_generalized_time(C, OctetList, DoTag);
-encode_generalized_time(_C, OctetList, []) ->
- dotag_universal(?N_GeneralizedTime,OctetList,length(OctetList));
-encode_generalized_time(_C, OctetList, DoTag) ->
- dotag(DoTag, ?N_GeneralizedTime, {OctetList,length(OctetList)}).
-
-%%============================================================================
-%% decode Generalized time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_generalized_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
- number=?N_GeneralizedTime}),
- decode_generalized_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
-
-decode_generalized_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_generalized_time_notag(Buffer00, Range,
- RestTags, TotalLen,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
- {binary_to_list(PreBuff), RestBuff, Rb0+Len}
- end.
-
-%%============================================================================
-%% Universal time, ITU_T X.680 Chapter 40
-%%
-%% encode UTC time
-%%============================================================================
-
-encode_utc_time(C, {Name,OctetList}, DoTag) when is_atom(Name) ->
- encode_utc_time(C, OctetList, DoTag);
-encode_utc_time(_C, OctetList, []) ->
- dotag_universal(?N_UTCTime, OctetList,length(OctetList));
-encode_utc_time(_C, OctetList, DoTag) ->
- dotag(DoTag, ?N_UTCTime, {OctetList,length(OctetList)}).
-
-%%============================================================================
-%% decode UTC time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_utc_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_UTCTime}),
- decode_utc_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
-
-decode_utc_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_utc_time_notag(Buffer00, Range,
- RestTags, TotalLen,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
- {binary_to_list(PreBuff), RestBuff, Rb0+Len}
- end.
-
-
-%%============================================================================
-%% Length handling
-%%
-%% Encode length
-%%
-%% encode_length(Int | indefinite) ->
-%% [<127]| [128 + Int (<127),OctetList] | [16#80]
-%%============================================================================
-
-encode_length(indefinite) ->
- {[16#80],1}; % 128
-encode_length(L) when L =< 16#7F ->
- {[L],1};
-encode_length(L) ->
- Oct = minimum_octets(L),
- Len = length(Oct),
- if
- Len =< 126 ->
- {[ (16#80+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 16#FF | Acc]).
-
-
-%%===========================================================================
-%% Decode length
-%%
-%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
-%% {{Length, RestOctetsL}, NoRemovedBytes}
-%%===========================================================================
-
-decode_length(<<1:1,0:7,T/binary>>) ->
- {{indefinite, T}, 1};
-decode_length(<<0:1,Length:7,T/binary>>) ->
- {{Length,T},1};
-decode_length(<<1:1,LL:7,T/binary>>) ->
- <<Length:LL/unit:8,Rest/binary>> = T,
- {{Length,Rest}, LL+1}.
-
-%decode_length([128 | T]) ->
-% {{indefinite, T},1};
-%decode_length([H | T]) when H =< 127 ->
-% {{H, T},1};
-%decode_length([H | T]) ->
-% dec_long_length(H band 16#7F, T, 0, 1).
-
-
-%%dec_long_length(0, Buffer, Acc, Len) ->
-%% {{Acc, Buffer},Len};
-%%dec_long_length(Bytes, [H | T], Acc, Len) ->
-%% dec_long_length(Bytes - 1, T, (Acc bsl 8) + H, Len+1).
-
-%%===========================================================================
-%% Decode tag and length
-%%
-%% decode_tag_and_length(Buffer) -> {Tag, Len, RemainingBuffer, RemovedBytes}
-%%
-%%===========================================================================
-
-decode_tag_and_length(Buffer) ->
- {Tag, Buffer2, RemBytesTag} = decode_tag(Buffer),
- {{Len, Buffer3}, RemBytesLen} = decode_length(Buffer2),
- {Tag, Len, Buffer3, RemBytesTag+RemBytesLen}.
-
-
-%%============================================================================
-%% Check if valid tag
-%%
-%% check_if_valid_tag(Tag, List_of_valid_tags, OptOrMand) -> name of the tag
-%%============================================================================
-
-check_if_valid_tag(<<0,0,_/binary>>,_,_) ->
- asn1_EOC;
-check_if_valid_tag(<<>>, _, OptOrMand) ->
- check_if_valid_tag2_error([], OptOrMand);
-check_if_valid_tag(Bytes, ListOfTags, OptOrMand) when is_binary(Bytes) ->
- {Tag, _, _} = decode_tag(Bytes),
- check_if_valid_tag(Tag, ListOfTags, OptOrMand);
-
-%% This alternative should be removed in the near future
-%% Bytes as input should be the only necessary call
-check_if_valid_tag(Tag, ListOfTags, OptOrMand) ->
- {Class, _Form, TagNo} = Tag,
- C = code_class(Class),
- T = case C of
- 'UNIVERSAL' ->
- code_type(TagNo);
- _ ->
- TagNo
- end,
- check_if_valid_tag2({C,T}, ListOfTags, Tag, OptOrMand).
-
-check_if_valid_tag2(_Class_TagNo, [], Tag, MandOrOpt) ->
- check_if_valid_tag2_error(Tag,MandOrOpt);
-check_if_valid_tag2(Class_TagNo, [{TagName,TagList}|T], Tag, OptOrMand) ->
- case check_if_valid_tag_loop(Class_TagNo, TagList) of
- true ->
- TagName;
- false ->
- check_if_valid_tag2(Class_TagNo, T, Tag, OptOrMand)
- end.
-
--spec check_if_valid_tag2_error(term(), atom()) -> no_return().
-
-check_if_valid_tag2_error(Tag,mandatory) ->
- exit({error,{asn1,{invalid_tag,Tag}}});
-check_if_valid_tag2_error(Tag,_) ->
- exit({error,{asn1,{no_optional_tag,Tag}}}).
-
-check_if_valid_tag_loop(_Class_TagNo,[]) ->
- false;
-check_if_valid_tag_loop(Class_TagNo,[H|T]) ->
- %% It is not possible to distinguish between SEQUENCE OF and SEQUENCE, and
- %% between SET OF and SET because both are coded as 16 and 17, respectively.
- H_without_OF = case H of
- {C, 'SEQUENCE OF'} ->
- {C, 'SEQUENCE'};
- {C, 'SET OF'} ->
- {C, 'SET'};
- Else ->
- Else
- end,
-
- case H_without_OF of
- Class_TagNo ->
- true;
- {_,_} ->
- check_if_valid_tag_loop(Class_TagNo,T);
- _ ->
- check_if_valid_tag_loop(Class_TagNo,H),
- check_if_valid_tag_loop(Class_TagNo,T)
- end.
-
-
-
-code_class(0) -> 'UNIVERSAL';
-code_class(16#40) -> 'APPLICATION';
-code_class(16#80) -> 'CONTEXT';
-code_class(16#C0) -> 'PRIVATE'.
-
-
-code_type(1) -> 'BOOLEAN';
-code_type(2) -> 'INTEGER';
-code_type(3) -> 'BIT STRING';
-code_type(4) -> 'OCTET STRING';
-code_type(5) -> 'NULL';
-code_type(6) -> 'OBJECT IDENTIFIER';
-code_type(7) -> 'ObjectDescriptor';
-code_type(8) -> 'EXTERNAL';
-code_type(9) -> 'REAL';
-code_type(10) -> 'ENUMERATED';
-code_type(11) -> 'EMBEDDED_PDV';
-code_type(16) -> 'SEQUENCE';
-% code_type(16) -> 'SEQUENCE OF';
-code_type(17) -> 'SET';
-% code_type(17) -> 'SET OF';
-code_type(18) -> 'NumericString';
-code_type(19) -> 'PrintableString';
-code_type(20) -> 'TeletexString';
-code_type(21) -> 'VideotexString';
-code_type(22) -> 'IA5String';
-code_type(23) -> 'UTCTime';
-code_type(24) -> 'GeneralizedTime';
-code_type(25) -> 'GraphicString';
-code_type(26) -> 'VisibleString';
-code_type(27) -> 'GeneralString';
-code_type(28) -> 'UniversalString';
-code_type(30) -> 'BMPString';
-code_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-
-%%-------------------------------------------------------------------------
-%% decoding of the components of a SET
-%%-------------------------------------------------------------------------
-
-decode_set(Rb, indefinite, <<0,0,Bytes/binary>>, _OptOrMand, _Fun3, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_set(Rb, indefinite, Bytes, OptOrMand, Fun3, Acc) ->
- case Fun3(Bytes, OptOrMand) of
- {_Term, _Remain, 0} ->
- {lists:reverse(Acc),Bytes,Rb};
- {Term, Remain, Rb1} ->
- Fun3(Bytes, OptOrMand),
- decode_set(Rb+Rb1, indefinite, Remain, OptOrMand, Fun3, [Term|Acc])
- end;
-%% {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
-%% decode_set(Rb+Rb1, indefinite, Remain, OptOrMand, Fun3, [Term|Acc]);
-
-decode_set(Rb, Num, Bytes, _OptOrMand, _Fun3, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_set(_, Num, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET'}}});
-
-decode_set(Rb, Num, Bytes, OptOrMand, Fun3, Acc) ->
- case Fun3(Bytes, OptOrMand) of
- {_Term, _Remain, 0} ->
- {lists:reverse(Acc),Bytes,Rb};
- {Term, Remain, Rb1} ->
- Fun3(Bytes, OptOrMand),
- decode_set(Rb+Rb1, Num-Rb1, Remain, OptOrMand, Fun3, [Term|Acc])
- end.
-%% {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
-%% decode_set(Rb+Rb1, Num-Rb1, Remain, OptOrMand, Fun3, [Term|Acc]).
-
-
-%%-------------------------------------------------------------------------
-%% decoding of SEQUENCE OF and SET OF
-%%-------------------------------------------------------------------------
-
-decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun3, _TagIn, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, Bytes, Fun3, TagIn, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
- decode_components(Rb+Rb1, indefinite, Remain, Fun3, TagIn, [Term|Acc]);
-
-decode_components(Rb, Num, Bytes, _Fun3, _TagIn, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_components(_, Num, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
-
-decode_components(Rb, Num, Bytes, Fun3, TagIn, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
- decode_components(Rb+Rb1, Num-Rb1, Remain, Fun3, TagIn, [Term|Acc]).
-
-%%decode_components(Rb, indefinite, [0,0|Bytes], _Fun3, _TagIn, Acc) ->
-%% {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun4, _TagIn, _Fun, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, Bytes, _Fun4, TagIn, _Fun, Acc) ->
- {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
- decode_components(Rb+Rb1, indefinite, Remain, _Fun4, TagIn, _Fun, [Term|Acc]);
-
-decode_components(Rb, Num, Bytes, _Fun4, _TagIn, _Fun, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_components(_, Num, _, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
-
-decode_components(Rb, Num, Bytes, _Fun4, TagIn, _Fun, Acc) ->
- {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
- decode_components(Rb+Rb1, Num-Rb1, Remain, _Fun4, TagIn, _Fun, [Term|Acc]).
-
-
-
-%%-------------------------------------------------------------------------
-%% INTERNAL HELPER FUNCTIONS (not exported)
-%%-------------------------------------------------------------------------
-
-
-%%==========================================================================
-%% Encode tag
-%%
-%% dotag(tag | notag, TagValpattern | TagValTuple, [Length, Value]) -> [Tag]
-%% TagValPattern is a correct bitpattern for a tag
-%% TagValTuple is a tuple of three bitpatterns, Class, Form and TagNo where
-%% Class = UNIVERSAL | APPLICATION | CONTEXT | PRIVATE
-%% Form = Primitive | Constructed
-%% TagNo = Number of tag
-%%==========================================================================
-
-
-dotag([], Tag, {Bytes,Len}) ->
- dotag_universal(Tag,Bytes,Len);
-dotag(Tags, Tag, {Bytes,Len}) ->
- encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
- Bytes, Len);
-
-dotag(Tags, Tag, Bytes) ->
- encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
- Bytes, size(Bytes)).
-
-dotag_universal(UniversalTag,Bytes,Len) when Len =< 16#7F->
- {[UniversalTag,Len,Bytes],2+Len};
-dotag_universal(UniversalTag,Bytes,Len) ->
- {EncLen,LenLen}=encode_length(Len),
- {[UniversalTag,EncLen,Bytes],1+LenLen+Len}.
-
-%% decoding postitive integer values.
-decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>,RemovedBytes) ->
- <<Int:Len/unit:8,Buffer2/binary>> = Bin,
- {Int,Buffer2,RemovedBytes};
-%% decoding negative integer values.
-decode_integer2(Len,<<1:1,B2:7,Bs/binary>>,RemovedBytes) ->
- <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
- Int = N - (1 bsl (8 * Len - 1)),
- {Int,Buffer2,RemovedBytes}.
-
-%%decode_integer2(Len,Buffer,Acc,RemovedBytes) when (hd(Buffer) band 16#FF) =< 16#7F ->
-%% {decode_integer_pos(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes};
-%%decode_integer2(Len,Buffer,Acc,RemovedBytes) ->
-%% {decode_integer_neg(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes}.
-
-%%decode_integer_pos([Byte|Tail], Shift) ->
-%% (Byte bsl Shift) bor decode_integer_pos(Tail, Shift-8);
-%%decode_integer_pos([], _) -> 0.
-
-
-%%decode_integer_neg([Byte|Tail], Shift) ->
-%% (-128 + (Byte band 127) bsl Shift) bor decode_integer_pos(Tail, Shift-8).
-
-
-concat_bit_binaries([],Bin={_,_}) ->
- Bin;
-concat_bit_binaries({0,B1},{U2,B2}) ->
- {U2,<<B1/binary,B2/binary>>};
-concat_bit_binaries({U1,B1},{U2,B2}) ->
- S1 = (size(B1) * 8) - U1,
- S2 = (size(B2) * 8) - U2,
- PadBits = 8 - ((S1+S2) rem 8),
- {PadBits, <<B1:S1/binary-unit:1,B2:S2/binary-unit:1,0:PadBits>>};
-concat_bit_binaries(L1,L2) when is_list(L1), is_list(L2) ->
- %% this case occur when decoding with NNL
- L1 ++ L2.
-
-
-get_constraint(C,Key) ->
- case lists:keyfind(Key,1,C) of
- false ->
- no;
- {_, V} ->
- V
- end.
-
-%%skip(Buffer, 0) ->
-%% Buffer;
-%%skip([H | T], Len) ->
-%% skip(T, Len-1).
-
-new_tags([],LastTag) ->
- [LastTag];
-new_tags(Tags = [#tag{type='IMPLICIT'}],_LastTag) ->
- Tags;
-new_tags([T1 = #tag{type='IMPLICIT'},#tag{type=T2Type}|Rest],LastTag) ->
- new_tags([T1#tag{type=T2Type}|Rest],LastTag);
-new_tags(Tags,LastTag) ->
- case lists:last(Tags) of
- #tag{type='IMPLICIT'} ->
- Tags;
- _ ->
- Tags ++ [LastTag]
- end.
diff --git a/lib/asn1/src/asn1rt_ber_bin_v2.erl b/lib/asn1/src/asn1rt_ber_bin_v2.erl
deleted file mode 100644
index 9ff5017c68..0000000000
--- a/lib/asn1/src/asn1rt_ber_bin_v2.erl
+++ /dev/null
@@ -1,2035 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2012. 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%
-%%
-%%
--module(asn1rt_ber_bin_v2).
-
-%% encoding / decoding of BER
-
--export([decode/1, decode/2, match_tags/2, encode/1, encode/2]).
--export([fixoptionals/2, cindex/3,
- list_to_record/2,
- encode_tag_val/1,
- encode_tags/3,
- skip_ExtensionAdditions/2]).
--export([encode_boolean/2,decode_boolean/2,
- encode_integer/3,encode_integer/4,
- decode_integer/3, decode_integer/4,
- encode_enumerated/2,
- encode_enumerated/4,decode_enumerated/4,
- encode_real/3,decode_real/2,
- encode_bit_string/4,decode_bit_string/4,
- decode_compact_bit_string/4,
- encode_octet_string/3,decode_octet_string/3,
- encode_null/2,decode_null/2,
- encode_relative_oid/2,decode_relative_oid/2,
- encode_object_identifier/2,decode_object_identifier/2,
- encode_restricted_string/4,decode_restricted_string/4,
- encode_universal_string/3,decode_universal_string/3,
- encode_UTF8_string/3,decode_UTF8_string/2,
- encode_BMP_string/3,decode_BMP_string/3,
- encode_generalized_time/3,decode_generalized_time/3,
- encode_utc_time/3,decode_utc_time/3,
- encode_length/1,decode_length/1,
- decode_tag_and_length/1]).
-
--export([encode_open_type/1,encode_open_type/2,
- decode_open_type/2,decode_open_type/3,
- decode_open_type_as_binary/2,
- decode_open_type_as_binary/3]).
-
--export([decode_primitive_incomplete/2,decode_selective/2]).
-
--export([is_nif_loadable/0]).
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-%%% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-%%% The tag-number for universal types
--define(N_BOOLEAN, 1).
--define(N_INTEGER, 2).
--define(N_BIT_STRING, 3).
--define(N_OCTET_STRING, 4).
--define(N_NULL, 5).
--define(N_OBJECT_IDENTIFIER, 6).
--define(N_OBJECT_DESCRIPTOR, 7).
--define(N_EXTERNAL, 8).
--define(N_REAL, 9).
--define(N_ENUMERATED, 10).
--define(N_EMBEDDED_PDV, 11).
--define(N_SEQUENCE, 16).
--define(N_SET, 17).
--define(N_NumericString, 18).
--define(N_PrintableString, 19).
--define(N_TeletexString, 20).
--define(N_VideotexString, 21).
--define(N_IA5String, 22).
--define(N_UTCTime, 23).
--define(N_GeneralizedTime, 24).
--define(N_GraphicString, 25).
--define(N_VisibleString, 26).
--define(N_GeneralString, 27).
--define(N_UniversalString, 28).
--define(N_BMPString, 30).
-
-
-% the complete tag-word of built-in types
--define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
--define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
--define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
--define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
--define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
--define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
--define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
--define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
--define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
--define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
--define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
--define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
--define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
--define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
--define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
--define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
-
-% encode(Tlv={_Tag={?PRIMITIVE,_},_VList}) ->
-% encode_primitive(Tlv);
-% encode(Tlv) ->
-% encode_constructed(Tlv).
-
-encode(Tlv) ->
- encode(Tlv,erlang).
-
-encode(Tlv,_) when is_binary(Tlv) ->
- Tlv;
-encode([Tlv],Method) ->
- encode(Tlv,Method);
-encode(Tlv, nif) ->
- case is_nif_loadable() of
- true ->
- asn1rt_nif:encode_ber_tlv(Tlv);
- false ->
- encode_erl(Tlv)
- end;
-encode(Tlv, _) ->
- encode_erl(Tlv).
-
-encode_erl({TlvTag,TlvVal}) when is_list(TlvVal) ->
- %% constructed form of value
- encode_tlv(TlvTag,TlvVal,?CONSTRUCTED);
-encode_erl({TlvTag,TlvVal}) ->
- encode_tlv(TlvTag,TlvVal,?PRIMITIVE).
-
-encode_tlv(TlvTag,TlvVal,Form) ->
- Tag = encode_tlv_tag(TlvTag,Form),
- {Val,VLen} = encode_tlv_val(TlvVal),
- {Len,_LLen} = encode_length(VLen),
- BinLen = list_to_binary(Len),
- <<Tag/binary,BinLen/binary,Val/binary>>.
-
-encode_tlv_tag(ClassTagNo,Form) ->
- Class = ClassTagNo bsr 16,
- encode_tag_val({Class bsl 6,Form,(ClassTagNo - (Class bsl 16))}).
-
-encode_tlv_val(TlvL) when is_list(TlvL) ->
- encode_tlv_list(TlvL,[]);
-encode_tlv_val(Bin) ->
- {Bin,size(Bin)}.
-
-encode_tlv_list([Tlv|Tlvs],Acc) ->
- EncTlv = encode_erl(Tlv),
- encode_tlv_list(Tlvs,[EncTlv|Acc]);
-encode_tlv_list([],Acc) ->
- Bin=list_to_binary(lists:reverse(Acc)),
- {Bin,size(Bin)}.
-
-decode(B) ->
- decode(B, erlang).
-
-%% asn1-1.7
-decode(B, nif) ->
- case is_nif_loadable() of
- true ->
- case asn1rt_nif:decode_ber_tlv(B) of
- {error, Reason} -> handle_error(Reason, B);
- Else -> Else
- end;
- false ->
- decode(B)
- end;
-decode(B,erlang) when is_binary(B) ->
- decode_primitive(B);
-decode(Tlv,erlang) ->
- {Tlv,<<>>}.
-
-%% Have to check this since asn1 is not guaranteed to be available
-is_nif_loadable() ->
- case application:get_env(asn1, nif_loadable) of
- {ok,R} ->
- R;
- undefined ->
- case catch code:load_file(asn1rt_nif) of
- {module, asn1rt_nif} ->
- application:set_env(asn1, nif_loadable, true),
- true;
- _Else ->
- application:set_env(asn1, nif_loadable, false),
- false
- end
- end.
-
-handle_error([],_)->
- exit({error,{asn1,{"memory allocation problem"}}});
-handle_error({$1,_},L) -> % error in nif
- exit({error,{asn1,L}});
-handle_error({$2,T},L) -> % error in nif due to wrong tag
- exit({error,{asn1,{"bad tag after byte:",error_pos(T),L}}});
-handle_error({$3,T},L) -> % error in driver due to length error
- exit({error,{asn1,{"bad length field after byte:",
- error_pos(T),L}}});
-handle_error({$4,T},L) -> % error in driver due to indefinite length error
- exit({error,{asn1,
- {"indefinite length without end bytes after byte:",
- error_pos(T),L}}});
-handle_error({$5,T},L) -> % error in driver due to indefinite length error
- exit({error,{asn1,{"bad encoded value after byte:",
- error_pos(T),L}}});
-handle_error(ErrL,L) ->
- exit({error,{asn1,ErrL,L}}).
-
-error_pos([]) ->
- "unknown position";
-error_pos([B])->
- B;
-error_pos([B|Bs]) ->
- BS = 8 * length(Bs),
- B bsl BS + error_pos(Bs).
-
-decode_primitive(Bin) ->
- {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
- case Form of
- 1 -> % constructed
- {{TagNo,decode_constructed(V)},Rest};
- 0 -> % primitive
- {{TagNo,V},Rest};
- 2 -> % constructed indefinite
- {Vlist,Rest2} = decode_constructed_indefinite(V,[]),
- {{TagNo,Vlist},Rest2}
- end.
-
-decode_constructed(Bin) when byte_size(Bin) =:= 0 ->
- [];
-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_primitive_incomplete/2 decodes an encoded message incomplete
-%% by help of the pattern attribute (first argument).
-decode_primitive_incomplete([[default,TagNo]],Bin) -> %default
- case decode_tag_and_length(Bin) of
- {Form,TagNo,V,Rest} ->
- decode_incomplete2(Form,TagNo,V,[],Rest);
- _ ->
- %{asn1_DEFAULT,Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[default,TagNo,Directives]],Bin) -> %default, constructed type, Directives points into this type
- case decode_tag_and_length(Bin) of
- {Form,TagNo,V,Rest} ->
- decode_incomplete2(Form,TagNo,V,Directives,Rest);
- _ ->
- %{asn1_DEFAULT,Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[opt,TagNo]],Bin) -> %optional
- case decode_tag_and_length(Bin) of
- {Form,TagNo,V,Rest} ->
- decode_incomplete2(Form,TagNo,V,[],Rest);
- _ ->
- %{{TagNo,asn1_NOVALUE},Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[opt,TagNo,Directives]],Bin) -> %optional
- case decode_tag_and_length(Bin) of
- {Form,TagNo,V,Rest} ->
- decode_incomplete2(Form,TagNo,V,Directives,Rest);
- _ ->
- %{{TagNo,asn1_NOVALUE},Bin}
- asn1_NOVALUE
- end;
-%% An optional that shall be undecoded
-decode_primitive_incomplete([[opt_undec,Tag]],Bin) ->
- case decode_tag_and_length(Bin) of
- {_,Tag,_,_} ->
- decode_incomplete_bin(Bin);
- _ ->
- asn1_NOVALUE
- end;
-%% A choice alternative that shall be undecoded
-decode_primitive_incomplete([[alt_undec,TagNo]|RestAlts],Bin) ->
-% decode_incomplete_bin(Bin);
-% case decode_tlv(Bin) of
- case decode_tag_and_length(Bin) of
-% {{_Form,TagNo,_Len,_V},_R} ->
- {_,TagNo,_,_} ->
- decode_incomplete_bin(Bin);
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt,TagNo]|RestAlts],Bin) ->
- case decode_tag_and_length(Bin) of
- {_Form,TagNo,V,Rest} ->
- {{TagNo,V},Rest};
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt,TagNo,Directives]|RestAlts],Bin) ->
- case decode_tag_and_length(Bin) of
- {Form,TagNo,V,Rest} ->
- decode_incomplete2(Form,TagNo,V,Directives,Rest);
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt_parts,TagNo]],Bin) ->
- case decode_tag_and_length(Bin) of
- {_Form,TagNo,V,Rest} ->
- {{TagNo,V},Rest};
- _ ->
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[alt_parts,TagNo]|RestAlts],Bin) ->
- case decode_tag_and_length(Bin) of
- {_Form,TagNo,V,Rest} ->
- {{TagNo,decode_parts_incomplete(V)},Rest};
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[undec,_TagNo]|_RestTag],Bin) -> %incomlete decode
- decode_incomplete_bin(Bin);
-decode_primitive_incomplete([[parts,TagNo]|_RestTag],Bin) ->
- case decode_tag_and_length(Bin) of
- {_Form,TagNo,V,Rest} ->
- {{TagNo,decode_parts_incomplete(V)},Rest};
- Err ->
- {error,{asn1,"tag failure",TagNo,Err}}
- end;
-decode_primitive_incomplete([mandatory|RestTag],Bin) ->
- {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
- decode_incomplete2(Form,TagNo,V,RestTag,Rest);
-%% A choice that is a toptype or a mandatory component of a
-%% SEQUENCE or SET.
-decode_primitive_incomplete([[mandatory|Directives]],Bin) ->
- {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
- decode_incomplete2(Form,TagNo,V,Directives,Rest);
-decode_primitive_incomplete([],Bin) ->
- decode_primitive(Bin).
-
-%% decode_parts_incomplete/1 receives a number of values encoded in
-%% sequence and returns the parts as unencoded binaries
-decode_parts_incomplete(<<>>) ->
- [];
-decode_parts_incomplete(Bin) ->
- {ok,Rest} = skip_tag(Bin),
- {ok,Rest2} = skip_length_and_value(Rest),
- LenPart = size(Bin) - size(Rest2),
- <<Part:LenPart/binary,RestBin/binary>> = Bin,
- [Part|decode_parts_incomplete(RestBin)].
-
-
-%% decode_incomplete2 checks if V is a value of a constructed or
-%% primitive type, and continues the decode propeerly.
-decode_incomplete2(_Form=2,TagNo,V,TagMatch,_) ->
- %% constructed indefinite length
- {Vlist,Rest2} = decode_constr_indef_incomplete(TagMatch,V,[]),
- {{TagNo,Vlist},Rest2};
-decode_incomplete2(1,TagNo,V,[TagMatch],Rest) when is_list(TagMatch) ->
- {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
-decode_incomplete2(1,TagNo,V,TagMatch,Rest) ->
- {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
-decode_incomplete2(0,TagNo,V,_TagMatch,Rest) ->
- {{TagNo,V},Rest}.
-
-decode_constructed_incomplete([Tags=[Ts]],Bin) when is_list(Ts) ->
- decode_constructed_incomplete(Tags,Bin);
-decode_constructed_incomplete(_TagMatch,<<>>) ->
- [];
-decode_constructed_incomplete([mandatory|RestTag],Bin) ->
- {Tlv,Rest} = decode_primitive(Bin),
- [Tlv|decode_constructed_incomplete(RestTag,Rest)];
-decode_constructed_incomplete(Directives=[[Alt,_]|_],Bin)
- when Alt == alt_undec; Alt == alt; Alt == alt_parts ->
- {_Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
- case incomplete_choice_alt(TagNo,Directives) of
- {alt_undec,_} ->
- LenA = size(Bin)-size(Rest),
- <<A:LenA/binary,Rest/binary>> = Bin,
- A;
- {alt,InnerDirectives} ->
- {Tlv,Rest} = decode_primitive_incomplete(InnerDirectives,V),
- {TagNo,Tlv};
- {alt_parts,_} ->
- [{TagNo,decode_parts_incomplete(V)}];
- no_match -> %% if a choice alternative was encoded that
- %% was not specified in the config file,
- %% thus decode component anonomous.
- {Tlv,_}=decode_primitive(Bin),
- Tlv
- end;
-decode_constructed_incomplete([TagNo|RestTag],Bin) ->
-%% {Tlv,Rest} = decode_primitive_incomplete([TagNo],Bin),
- case decode_primitive_incomplete([TagNo],Bin) of
- {Tlv,Rest} ->
- [Tlv|decode_constructed_incomplete(RestTag,Rest)];
- asn1_NOVALUE ->
- decode_constructed_incomplete(RestTag,Bin)
- end;
-decode_constructed_incomplete([],Bin) ->
- {Tlv,Rest}=decode_primitive(Bin),
- [Tlv|decode_constructed_incomplete([],Rest)].
-
-decode_constr_indef_incomplete(_TagMatch,<<0,0,Rest/binary>>,Acc) ->
- {lists:reverse(Acc),Rest};
-decode_constr_indef_incomplete([Tag|RestTags],Bin,Acc) ->
-% {Tlv,Rest} = decode_primitive_incomplete([Tag],Bin),
- case decode_primitive_incomplete([Tag],Bin) of
- {Tlv,Rest} ->
- decode_constr_indef_incomplete(RestTags,Rest,[Tlv|Acc]);
- asn1_NOVALUE ->
- decode_constr_indef_incomplete(RestTags,Bin,Acc)
- end.
-
-
-decode_incomplete_bin(Bin) ->
- {ok,Rest} = skip_tag(Bin),
- {ok,Rest2} = skip_length_and_value(Rest),
- IncLen = size(Bin) - size(Rest2),
- <<IncBin:IncLen/binary,Ret/binary>> = Bin,
- {IncBin,Ret}.
-
-incomplete_choice_alt(TagNo,[[Alt,TagNo]|Directives]) ->
- {Alt,Directives};
-incomplete_choice_alt(TagNo,[D]) when is_list(D) ->
- incomplete_choice_alt(TagNo,D);
-incomplete_choice_alt(TagNo,[_H|Directives]) ->
- incomplete_choice_alt(TagNo,Directives);
-incomplete_choice_alt(_,[]) ->
- no_match.
-
-
-
-
-%% decode_selective(Pattern, Binary) the first argument is a pattern that tells
-%% what to do with the next element the second is the BER encoded
-%% message as a binary
-%% Returns {ok,Value} or {error,Reason}
-%% Value is a binary that in turn must be decoded to get the decoded
-%% value.
-decode_selective([],Binary) ->
- {ok,Binary};
-decode_selective([skip|RestPattern],Binary)->
- {ok,RestBinary}=skip_tag(Binary),
- {ok,RestBinary2}=skip_length_and_value(RestBinary),
- decode_selective(RestPattern,RestBinary2);
-decode_selective([[skip_optional,Tag]|RestPattern],Binary) ->
- case skip_optional_tag(Tag,Binary) of
- {ok,RestBinary} ->
- {ok,RestBinary2}=skip_length_and_value(RestBinary),
- decode_selective(RestPattern,RestBinary2);
- missing ->
- decode_selective(RestPattern,Binary)
- end;
-decode_selective([[choosen,Tag]],Binary) ->
- return_value(Tag,Binary);
-% case skip_optional_tag(Tag,Binary) of %may be optional/default
-% {ok,RestBinary} ->
-% {ok,Value} = get_value(RestBinary);
-% missing ->
-% {ok,<<>>}
-% end;
-decode_selective([[choosen,Tag]|RestPattern],Binary) ->
- case skip_optional_tag(Tag,Binary) of
- {ok,RestBinary} ->
- {ok,Value} = get_value(RestBinary),
- decode_selective(RestPattern,Value);
- missing ->
- {ok,<<>>}
- end;
-decode_selective(P,_) ->
- {error,{asn1,{partial_decode,"bad pattern",P}}}.
-
-return_value(Tag,Binary) ->
- {ok,{Tag,RestBinary}}=get_tag(Binary),
- {ok,{LenVal,_RestBinary2}} = get_length_and_value(RestBinary),
- {ok,<<Tag/binary,LenVal/binary>>}.
-
-
-%% skip_tag and skip_length_and_value are rutines used both by
-%% decode_partial_incomplete and decode_selective (decode/2).
-
-skip_tag(<<_:3,31:5,Rest/binary>>)->
- skip_long_tag(Rest);
-skip_tag(<<_:3,_Tag:5,Rest/binary>>) ->
- {ok,Rest}.
-
-skip_long_tag(<<1:1,_:7,Rest/binary>>) ->
- skip_long_tag(Rest);
-skip_long_tag(<<0:1,_:7,Rest/binary>>) ->
- {ok,Rest}.
-
-skip_optional_tag(<<>>,Binary) ->
- {ok,Binary};
-skip_optional_tag(<<Tag,RestTag/binary>>,<<Tag,Rest/binary>>) ->
- skip_optional_tag(RestTag,Rest);
-skip_optional_tag(_,_) ->
- missing.
-
-
-
-
-skip_length_and_value(Binary) ->
- case decode_length(Binary) of
- {indefinite,RestBinary} ->
- skip_indefinite_value(RestBinary);
- {Length,RestBinary} ->
- <<_:Length/unit:8,Rest/binary>> = RestBinary,
- {ok,Rest}
- end.
-
-skip_indefinite_value(<<0,0,Rest/binary>>) ->
- {ok,Rest};
-skip_indefinite_value(Binary) ->
- {ok,RestBinary}=skip_tag(Binary),
- {ok,RestBinary2} = skip_length_and_value(RestBinary),
- skip_indefinite_value(RestBinary2).
-
-get_value(Binary) ->
- case decode_length(Binary) of
- {indefinite,RestBinary} ->
- get_indefinite_value(RestBinary,[]);
- {Length,RestBinary} ->
- <<Value:Length/binary,_Rest/binary>> = RestBinary,
- {ok,Value}
- end.
-
-get_indefinite_value(<<0,0,_Rest/binary>>,Acc) ->
- {ok,list_to_binary(lists:reverse(Acc))};
-get_indefinite_value(Binary,Acc) ->
- {ok,{Tag,RestBinary}}=get_tag(Binary),
- {ok,{LenVal,RestBinary2}} = get_length_and_value(RestBinary),
- get_indefinite_value(RestBinary2,[LenVal,Tag|Acc]).
-
-get_tag(<<H:1/binary,Rest/binary>>) ->
- case H of
- <<_:3,31:5>> ->
- get_long_tag(Rest,[H]);
- _ -> {ok,{H,Rest}}
- end.
-get_long_tag(<<H:1/binary,Rest/binary>>,Acc) ->
- case H of
- <<0:1,_:7>> ->
- {ok,{list_to_binary(lists:reverse([H|Acc])),Rest}};
- _ ->
- get_long_tag(Rest,[H|Acc])
- end.
-
-get_length_and_value(Bin = <<0:1,Length:7,_T/binary>>) ->
- <<Len,Val:Length/binary,Rest/binary>> = Bin,
- {ok,{<<Len,Val/binary>>, Rest}};
-get_length_and_value(Bin = <<1:1,0:7,_T/binary>>) ->
- get_indefinite_length_and_value(Bin);
-get_length_and_value(<<1:1,LL:7,T/binary>>) ->
- <<Length:LL/unit:8,Rest/binary>> = T,
- <<Value:Length/binary,Rest2/binary>> = Rest,
- {ok,{<<1:1,LL:7,Length:LL/unit:8,Value/binary>>,Rest2}}.
-
-get_indefinite_length_and_value(<<H,T/binary>>) ->
- get_indefinite_length_and_value(T,[H]).
-
-get_indefinite_length_and_value(<<0,0,Rest/binary>>,Acc) ->
- {ok,{list_to_binary(lists:reverse(Acc)),Rest}};
-get_indefinite_length_and_value(Binary,Acc) ->
- {ok,{Tag,RestBinary}}=get_tag(Binary),
- {ok,{LenVal,RestBinary2}}=get_length_and_value(RestBinary),
- get_indefinite_length_and_value(RestBinary2,[LenVal,Tag|Acc]).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 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]) ->
- V;
-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(Tlv = {Tag,_V},[T|_Tt]) ->
- exit({error,{asn1,{wrong_tag,{{expected,T},{got,Tag,Tlv}}}}}).
-
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%%%
-%% skips components that do not match a tag in Tags
-skip_ExtensionAdditions([],_Tags) ->
- [];
-skip_ExtensionAdditions(TLV=[{Tag,_}|Rest],Tags) ->
- case [X||X=T<-Tags,T==Tag] of
- [] ->
- %% skip this TLV and continue with next
- skip_ExtensionAdditions(Rest,Tags);
- _ ->
- TLV
- end.
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Optionals, preset not filled optionals with asn1_NOVALUE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when is_list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when is_tuple(Tuple) ->
- Tuple.
-
-
-fixoptionals(OptList,Val) when is_list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,_Acc1,Acc2) ->
- % return Val as a record
- list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
-
-
-%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%% 8bit Int | binary
-encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
- <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
-
-encode_tag_val({Class, Form, TagNo}) ->
- {Octets,_Len} = mk_object_val(TagNo),
- BinOct = list_to_binary(Octets),
- <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>.
-
-
-%%===============================================================================
-%% 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, V:Length/binary, RestBuffer/binary>>) when TagNo < 31 ->
- {Form, (Class bsl 16) + TagNo, V, RestBuffer};
-decode_tag_and_length(<<Class:2, 1:1, TagNo:5, 1:1, 0:7, T/binary>>) when TagNo < 31 ->
- {2, (Class bsl 16) + TagNo, T, <<>>};
-decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, LL:7, Length:LL/unit:8,V:Length/binary, T/binary>>) when TagNo < 31 ->
- {Form, (Class bsl 16) + TagNo, V, T};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 0:1, Length:7, V:Length/binary, RestBuffer/binary>>) ->
- {Form, (Class bsl 16) + TagNo, V, RestBuffer};
-decode_tag_and_length(<<Class:2, 1:1, 31:5, 0:1, TagNo:7, 1:1, 0:7, T/binary>>) ->
- {2, (Class bsl 16) + TagNo, T, <<>>};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, LL:7, Length:LL/unit:8, V:Length/binary, T/binary>>) ->
- {Form, (Class bsl 16) + TagNo, V, T};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 1:1, TagPart1:7, 0:1, TagPartLast, Buffer/binary>>) ->
- TagNo = (TagPart1 bsl 7) bor TagPartLast,
- {Length, RestBuffer} = decode_length(Buffer),
- << V:Length/binary, RestBuffer2/binary>> = RestBuffer,
- {Form, (Class bsl 16) + TagNo, V, RestBuffer2};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
- {TagNo, Buffer1} = decode_tag(Buffer, 0),
- {Length, RestBuffer} = decode_length(Buffer1),
- << V:Length/binary, RestBuffer2/binary>> = RestBuffer,
- {Form, (Class bsl 16) + TagNo, V, RestBuffer2}.
-
-
-
-%% 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
-
-%%
-encode_open_type(Val) when is_list(Val) ->
-% {Val,length(Val)};
- encode_open_type(list_to_binary(Val));
-encode_open_type(Val) ->
- {Val, size(Val)}.
-
-%%
-encode_open_type(Val, T) when is_list(Val) ->
- encode_open_type(list_to_binary(Val),T);
-encode_open_type(Val,[]) ->
- {Val, size(Val)};
-encode_open_type(Val,Tag) ->
- encode_tags(Tag,Val, size(Val)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Tlv, TagIn) -> Value
-%% Tlv = {Tag,V} | V where V -> binary()
-%% TagIn = [TagVal] where TagVal -> int()
-%% Value = binary with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Tlv, TagIn) ->
- decode_open_type(Tlv, TagIn, erlang).
-decode_open_type(Tlv, TagIn, Method) ->
- case match_tags(Tlv,TagIn) of
- Bin when is_binary(Bin) ->
- {InnerTlv,_} = decode(Bin,Method),
- InnerTlv;
- TlvBytes -> TlvBytes
- end.
-
-
-decode_open_type_as_binary(Tlv, TagIn) ->
- decode_open_type_as_binary(Tlv, TagIn, erlang).
-decode_open_type_as_binary(Tlv,TagIn, Method)->
- case match_tags(Tlv,TagIn) of
- V when is_binary(V) ->
- V;
- [Tlv2] -> encode(Tlv2, Method);
- Tlv2 -> encode(Tlv2, Method)
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Boolean, ITU_T X.690 Chapter 8.2
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len}
-%%===============================================================================
-
-encode_boolean({Name, Val}, TagIn) when is_atom(Name) ->
- encode_boolean(Val, TagIn);
-encode_boolean(true, TagIn) ->
- encode_tags(TagIn, [16#FF],1);
-encode_boolean(false, TagIn) ->
- encode_tags(TagIn, [0],1);
-encode_boolean(X,_) ->
- exit({error,{asn1, {encode_boolean, X}}}).
-
-
-%%===============================================================================
-%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
-%% {false, Remain, RemovedBytes}
-%%===============================================================================
-decode_boolean(Tlv,TagIn) ->
- Val = match_tags(Tlv, TagIn),
- case Val of
- <<0:8>> ->
- false;
- <<_:8>> ->
- true;
- _ ->
- exit({error,{asn1, {decode_boolean, Val}}})
- end.
-
-
-%%===========================================================================
-%% 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(C, Val, NamedNumberList, Tag) when is_atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value,{_, NewVal}} ->
- encode_tags(Tag, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {encode_integer_namednumber, Val}}})
- end;
-encode_integer(C,{_Name,Val},NamedNumberList,Tag) ->
- encode_integer(C,Val,NamedNumberList,Tag);
-encode_integer(C, Val, _NamedNumberList, Tag) ->
- encode_tags(Tag, encode_integer(C, 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 16#ff| 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 16#ff|Acc]).
-
-%%===============================================================================
-%% decode integer
-%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%===============================================================================
-
-decode_integer(Tlv,Range,NamedNumberList,TagIn) ->
- V = match_tags(Tlv,TagIn),
- Int = decode_integer(V),
- range_check_integer(Int,Range),
- number2name(Int,NamedNumberList).
-
-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.
-
-number2name(Int,[]) ->
- Int;
-number2name(Int,NamedNumberList) ->
- case lists:keysearch(Int, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- Int
- end.
-
-
-%%============================================================================
-%% Enumerated value, ITU_T X.690 Chapter 8.4
-
-%% encode enumerated value
-%%============================================================================
-encode_enumerated(Val, TagIn) when is_integer(Val)->
- encode_tags(TagIn, encode_integer(false,Val));
-encode_enumerated({Name,Val}, TagIn) when is_atom(Name) ->
- encode_enumerated(Val, TagIn).
-
-%% 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)
-
-encode_enumerated(C, Val, {NamedNumberList,ExtList}, TagIn) when is_atom(Val) ->
- case catch encode_enumerated(C, Val, NamedNumberList, TagIn) of
- {'EXIT',_} -> encode_enumerated(C, Val, ExtList, TagIn);
- Result -> Result
- end;
-
-encode_enumerated(C, Val, NamedNumberList, TagIn) when is_atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value, {_, NewVal}} ->
- encode_tags(TagIn, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {enumerated_not_in_range, Val}}})
- end;
-
-encode_enumerated(C, {asn1_enum, Val}, {_,_}, TagIn) when is_integer(Val) ->
- encode_tags(TagIn, encode_integer(C,Val));
-
-encode_enumerated(C, {Name,Val}, NamedNumberList, TagIn) when is_atom(Name) ->
- encode_enumerated(C, Val, NamedNumberList, TagIn);
-
-encode_enumerated(_C, Val, _NamedNumberList, _TagIn) ->
- exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
-
-
-
-%%============================================================================
-%% decode enumerated value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value
-%%===========================================================================
-decode_enumerated(Tlv, Range, NamedNumberList, Tags) ->
- Buffer = match_tags(Tlv,Tags),
- decode_enumerated_notag(Buffer, Range, NamedNumberList, Tags).
-
-decode_enumerated_notag(Buffer, _Range, {NamedNumberList,ExtList}, _Tags) ->
-
- IVal = decode_integer2(size(Buffer), Buffer),
- case decode_enumerated1(IVal, NamedNumberList) of
- {asn1_enum,IVal} ->
- decode_enumerated1(IVal,ExtList);
- EVal ->
- EVal
- end;
-decode_enumerated_notag(Buffer, _Range, NNList, _Tags) ->
- IVal = decode_integer2(size(Buffer), Buffer),
- case decode_enumerated1(IVal, NNList) of
- {asn1_enum,_} ->
- exit({error,{asn1, {illegal_enumerated, IVal}}});
- EVal ->
- EVal
- end.
-
-decode_enumerated1(Val, NamedNumberList) ->
- %% it must be a named integer
- case lists:keysearch(Val, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- {asn1_enum,Val}
- end.
-
-
-%%============================================================================
-%%
-%% Real value, ITU_T X.690 Chapter 8.5
-%%============================================================================
-%%
-%% encode real value
-%%============================================================================
-
-%% only base 2 internally so far!!
-encode_real(_C,0, TagIn) ->
- encode_tags(TagIn, {[],0});
-encode_real(_C,'PLUS-INFINITY', TagIn) ->
- encode_tags(TagIn, {[64],1});
-encode_real(_C,'MINUS-INFINITY', TagIn) ->
- encode_tags(TagIn, {[65],1});
-encode_real(C,Val, TagIn) when is_tuple(Val); is_list(Val) ->
- encode_tags(TagIn, encode_real(C,Val)).
-
-
-
-encode_real(C,Val) ->
- asn1rt_ber_bin:encode_real(C,Val).
-
-
-%%============================================================================
-%% 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!!
-%%============================================================================
-
-decode_real(Tlv, Tags) ->
- Buffer = match_tags(Tlv,Tags),
- decode_real_notag(Buffer).
-
-decode_real_notag(Buffer) ->
- Len =
- case Buffer of
- Bin when is_binary(Bin) ->
- size(Bin);
- {_T,_V} ->
- exit({error,{asn1,{real_not_in_primitive_form,Buffer}}})
- end,
- {Val,_Rest,Len} = asn1rt_ber_bin:decode_real(Buffer,Len),
- Val.
-%% 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_bit_string(C,Bin={Unused,BinBits},NamedBitList,TagIn) when is_integer(Unused), is_binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList,TagIn);
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList, TagIn) when is_atom(FirstVal) ->
- encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, TagIn) ->
- encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(C, [FirstVal| RestVal], NamedBitList, TagIn) when is_integer(FirstVal) ->
- encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(_C, 0, _NamedBitList, TagIn) ->
- encode_tags(TagIn, <<0>>,1);
-
-encode_bit_string(_C, [], _NamedBitList, TagIn) ->
- encode_tags(TagIn, <<0>>,1);
-
-encode_bit_string(C, IntegerVal, NamedBitList, TagIn) when is_integer(IntegerVal) ->
- BitListVal = int_to_bitlist(IntegerVal),
- encode_bit_string_bits(C, BitListVal, NamedBitList, TagIn);
-
-encode_bit_string(C, {Name,BitList}, NamedBitList, TagIn) when is_atom(Name) ->
- encode_bit_string(C, BitList, NamedBitList, TagIn).
-
-
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when is_integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-
-%%=================================================================
-%% Encode BIT STRING of the form {Unused,BinBits}.
-%% Unused is the number of unused bits in the last byte in BinBits
-%% and BinBits is a binary representing the BIT STRING.
-%%=================================================================
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,TagIn)->
- case get_constraint(C,'SizeConstraint') of
- no ->
- remove_unused_then_dotag(TagIn, Unused, BinBits);
- {_Min,Max} ->
- BBLen = (size(BinBits)*8)-Unused,
- if
- BBLen > Max ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBLen},{maximum,Max}}}}});
- true ->
- remove_unused_then_dotag(TagIn, Unused, BinBits)
- end;
- Size ->
- case ((size(BinBits)*8)-Unused) of
- BBSize when BBSize =< Size ->
- remove_unused_then_dotag(TagIn, Unused, BinBits);
- BBSize ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBSize},{should_be,Size}}}}})
- end
- end.
-
-remove_unused_then_dotag(TagIn,Unused,BinBits) ->
- case Unused of
- 0 when (size(BinBits) == 0) ->
- encode_tags(TagIn,<<0>>,1);
- 0 ->
- Bin = <<Unused,BinBits/binary>>,
- encode_tags(TagIn,Bin,size(Bin));
- Num ->
- N = (size(BinBits)-1),
- <<BBits:N/binary,LastByte>> = BinBits,
- encode_tags(TagIn,
- [Unused,binary_to_list(BBits) ++[(LastByte bsr Num) bsl Num]],
- 1+size(BinBits))
- end.
-
-
-%%=================================================================
-%% Encode named bits
-%%=================================================================
-
-encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
- Size =
- case get_constraint(C,'SizeConstraint') of
- no ->
- lists:max(ToSetPos)+1;
- {_Min,Max} ->
- Max;
- TSize ->
- TSize
- end,
- BitList = make_and_set_list(Size, ToSetPos, 0),
- {Len, Unused, OctetList} = encode_bitstring(BitList),
- encode_tags(TagIn, [Unused|OctetList],Len+1).
-
-
-%%----------------------------------------
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-%%----------------------------------------
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-get_all_bitposes([Val | Rest], NamedBitList, Ack) when is_atom(Val) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-
-%%----------------------------------------
-%% 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),
-%%----------------------------------------
-
-make_and_set_list(0, [], _) -> [];
-make_and_set_list(0, _, _) ->
- exit({error,{asn1,bitstring_sizeconstraint}});
-make_and_set_list(Len, [XPos|SetPos], XPos) ->
- [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
-make_and_set_list(Len, [Pos|SetPos], XPos) ->
- [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
-make_and_set_list(Len, [], XPos) ->
- [0 | make_and_set_list(Len - 1, [], XPos + 1)].
-
-
-
-
-
-
-%%=================================================================
-%% Encode bit string for lists of ones and zeroes
-%%=================================================================
-encode_bit_string_bits(C, BitListVal, _NamedBitList, TagIn) when is_list(BitListVal) ->
- case get_constraint(C,'SizeConstraint') of
- no ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- Constr={Min,_Max} when is_integer(Min) ->
- %% Max may be an integer or 'MAX'
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- {Constr={_,_},[]} ->%Constr={Min,Max}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- Size ->
- case length(BitListVal) of
- BitSize when BitSize == Size ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- BitSize when BitSize < Size ->
- PaddedList = pad_bit_list(Size-BitSize,BitListVal),
- {Len, Unused, OctetList} = encode_bitstring(PaddedList),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- BitSize ->
- exit({error,{asn1,
- {bitstring_length, {{was,BitSize},{should_be,Size}}}}})
- end
-
- end.
-
-encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,TagIn) ->
- BitLen = length(BitListVal),
- case BitLen of
- Len when Len > Max2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max2}}}}});
- Len when Len > Max1, Len < Min2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {not_allowed_interval,
- Max1,Min2}}}}});
- _ ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused, OctetList], Len+1)
- end;
-encode_constr_bit_str_bits({Min,Max},BitListVal,TagIn) ->
- BitLen = length(BitListVal),
- if
- BitLen > Max ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max}}}}});
- BitLen < Min ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {minimum,Max}}}}});
- true ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused, OctetList], Len+1)
- end.
-
-
-%% returns a list of length Size + length(BitListVal), with BitListVal
-%% as the most significant elements followed by padded zero elements
-pad_bit_list(Size,BitListVal) ->
- Tail = lists:duplicate(Size,0),
- lists:append(BitListVal,Tail).
-
-%%=================================================================
-%% Do the actual encoding
-%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
-%%=================================================================
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Val], 1);
-encode_bitstring(Val) ->
- {Unused, Octet} = unused_bitlist(Val, 7, 0),
- {1, Unused, [Octet]}.
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Ack | [Val]], Len + 1);
-%%even multiple of 8 bits..
-encode_bitstring([], Ack, Len) ->
- {Len, 0, Ack};
-%% unused bits in last octet
-encode_bitstring(Rest, Ack, Len) ->
-% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
- {Unused, Val} = unused_bitlist(Rest, 7, 0),
- {Len + 1, Unused, [Ack | [Val]]}.
-
-%%%%%%%%%%%%%%%%%%
-%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
-%% {Unused bits, Last octet with bits moved to right}
-unused_bitlist([], Trail, Ack) ->
- {Trail + 1, Ack};
-unused_bitlist([Bit | Rest], Trail, Ack) ->
-%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
- unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
-
-
-%%============================================================================
-%% decode bitstring value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%============================================================================
-
-decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
- NamedNumberList,bin).
-
-decode_bit_string(Buffer, Range, NamedNumberList, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
- NamedNumberList,old).
-
-
-decode_bit_string2(<<0>>,_NamedNumberList,BinOrOld) ->
- case BinOrOld of
- bin ->
- {0,<<>>};
- _ ->
- []
- end;
-decode_bit_string2(<<Unused,Bits/binary>>,NamedNumberList,BinOrOld) ->
- case NamedNumberList of
- [] ->
- case BinOrOld of
- bin ->
- {Unused,Bits};
- _ ->
- decode_bitstring2(size(Bits), Unused, Bits)
- end;
- _ ->
- BitString = decode_bitstring2(size(Bits), Unused, Bits),
- decode_bitstring_NNL(BitString,NamedNumberList)
- end.
-
-%%----------------------------------------
-%% Decode the in buffer to bits
-%%----------------------------------------
-decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
-decode_bitstring2(Len, Unused,
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
- [B7, B6, B5, B4, B3, B2, B1, B0 |
- decode_bitstring2(Len - 1, Unused, Buffer)].
-
-%%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
-%%----------------------------------------
-
-
-decode_bitstring_NNL(BitList,NamedNumberList) ->
- decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
-
-
-decode_bitstring_NNL([],_,_No,Result) ->
- lists:reverse(Result);
-
-decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
- if
- B == 0 ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
- true ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
- end;
-decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
-decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
-
-
-%%============================================================================
-%% Octet string, ITU_T X.690 Chapter 8.7
-%%
-%% encode octet string
-%% The OctetList must be a flat list of integers in the range 0..255
-%% the function does not check this because it takes to much time
-%%============================================================================
-encode_octet_string(_C, OctetList, TagIn) when is_binary(OctetList) ->
- encode_tags(TagIn, OctetList, size(OctetList));
-encode_octet_string(_C, OctetList, TagIn) when is_list(OctetList) ->
- encode_tags(TagIn, OctetList, length(OctetList));
-encode_octet_string(C, {Name,OctetList}, TagIn) when is_atom(Name) ->
- encode_octet_string(C, OctetList, TagIn).
-
-
-%%============================================================================
-%% decode octet string
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%
-%% Octet string is decoded as a restricted string
-%%============================================================================
-decode_octet_string(Buffer, Range, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
- decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
- Tags, [], old).
-
-%%============================================================================
-%% Null value, ITU_T X.690 Chapter 8.8
-%%
-%% encode NULL value
-%%============================================================================
-
-encode_null({Name, _Val}, TagIn) when is_atom(Name) ->
- encode_tags(TagIn, [], 0);
-encode_null(_Val, TagIn) ->
- encode_tags(TagIn, [], 0).
-
-%%============================================================================
-%% decode NULL value
-%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
-%%============================================================================
-
-decode_null(Tlv, Tags) ->
- Val = match_tags(Tlv, Tags),
- case Val of
- <<>> ->
- 'NULL';
- _ ->
- exit({error,{asn1,{decode_null,Val}}})
- end.
-
-%%============================================================================
-%% Object identifier, ITU_T X.690 Chapter 8.19
-%%
-%% encode Object Identifier value
-%%============================================================================
-
-encode_object_identifier({Name,Val}, TagIn) when is_atom(Name) ->
- encode_object_identifier(Val, TagIn);
-encode_object_identifier(Val, TagIn) ->
- encode_tags(TagIn, e_object_identifier(Val)).
-
-e_object_identifier({'OBJECT IDENTIFIER', V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname, V}) when is_atom(Cname), is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname, V}) when is_atom(Cname), is_list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%%%%%%%%%%%%%%%
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-e_object_identifier([E1, E2 | Tail]) ->
- Head = 40*E1 + E2, % wow!
- {H,Lh} = mk_object_val(Head),
- {R,Lr} = lists:mapfoldl(fun enc_obj_id_tail/2,0,Tail),
- {[H|R], Lh+Lr}.
-
-enc_obj_id_tail(H, Len) ->
- {B, L} = mk_object_val(H),
- {B,Len+L}.
-
-
-%%%%%%%%%%%
-%% 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
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-
-%%============================================================================
-%% decode Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-
-decode_object_identifier(Tlv, Tags) ->
- Val = match_tags(Tlv, Tags),
- [AddedObjVal|ObjVals] = dec_subidentifiers(Val,0,[]),
- {Val1, Val2} = if
- AddedObjVal < 40 ->
- {0, AddedObjVal};
- AddedObjVal < 80 ->
- {1, AddedObjVal - 40};
- true ->
- {2, AddedObjVal - 80}
- end,
- list_to_tuple([Val1, Val2 | ObjVals]).
-
-dec_subidentifiers(<<>>,_Av,Al) ->
- lists:reverse(Al);
-dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) ->
- dec_subidentifiers(T,(Av bsl 7) + H,Al);
-dec_subidentifiers(<<H,T/binary>>,Av,Al) ->
- dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
-
-%%============================================================================
-%% RELATIVE-OID, ITU_T X.690 Chapter 8.20
-%%
-%% encode Relative Object Identifier
-%%============================================================================
-encode_relative_oid({Name,Val},TagIn) when is_atom(Name) ->
- encode_relative_oid(Val,TagIn);
-encode_relative_oid(Val,TagIn) when is_tuple(Val) ->
- encode_relative_oid(tuple_to_list(Val),TagIn);
-encode_relative_oid(Val,TagIn) ->
- encode_tags(TagIn, enc_relative_oid(Val)).
-
-enc_relative_oid(Tuple) when is_tuple(Tuple) ->
- enc_relative_oid(tuple_to_list(Tuple));
-enc_relative_oid(Val) ->
- lists:mapfoldl(fun(X,AccIn) ->
- {SO,L}=mk_object_val(X),
- {SO,L+AccIn}
- end
- ,0,Val).
-
-%%============================================================================
-%% decode Relative Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-decode_relative_oid(Tlv, Tags) ->
- Val = match_tags(Tlv, Tags),
- ObjVals = dec_subidentifiers(Val,0,[]),
- list_to_tuple(ObjVals).
-
-%%============================================================================
-%% Restricted character string types, ITU_T X.690 Chapter 8.20
-%%
-%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%%============================================================================
-%% The StringType arg is kept for future use but might be removed
-encode_restricted_string(_C, OctetList, _StringType, TagIn)
- when is_binary(OctetList) ->
- encode_tags(TagIn, OctetList, size(OctetList));
-encode_restricted_string(_C, OctetList, _StringType, TagIn)
- when is_list(OctetList) ->
- encode_tags(TagIn, OctetList, length(OctetList));
-encode_restricted_string(C,{Name,OctetL}, StringType, TagIn) when is_atom(Name)->
- encode_restricted_string(C, OctetL, StringType, TagIn).
-
-%%============================================================================
-%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_restricted_string(Buffer, Range, StringType, Tags) ->
- decode_restricted_string(Buffer, Range, StringType, Tags, [], old).
-
-
-decode_restricted_string(Tlv, Range, StringType, TagsIn,
- NamedNumberList, BinOrOld) ->
- Val = match_tags(Tlv, TagsIn),
- Val2 =
- case Val of
- PartList = [_H|_T] -> % constructed val
- Bin = collect_parts(PartList),
- decode_restricted(Bin, StringType,
- NamedNumberList, BinOrOld);
- Bin ->
- decode_restricted(Bin, StringType,
- NamedNumberList, BinOrOld)
- end,
- check_and_convert_restricted_string(Val2,StringType,Range,NamedNumberList,BinOrOld).
-
-
-
-% case StringType of
-% ?N_BIT_STRING when BinOrOld == bin ->
-% {concat_bit_binaries(AccVal, Val), AccRb+Rb};
-% _ when is_binary(Val),is_binary(AccVal) ->
-% {<<AccVal/binary,Val/binary>>,AccRb+Rb};
-% _ when is_binary(Val), AccVal==[] ->
-% {Val,AccRb+Rb};
-% _ ->
-% {AccVal++Val, AccRb+Rb}
-% end,
-
-
-
-decode_restricted(Bin, StringType, NamedNumberList,BinOrOld) ->
- case StringType of
- ?N_BIT_STRING ->
- decode_bit_string2(Bin, NamedNumberList, BinOrOld);
- ?N_UniversalString ->
- mk_universal_string(binary_to_list(Bin));
- ?N_BMPString ->
- mk_BMP_string(binary_to_list(Bin));
- _ ->
- Bin
- end.
-
-
-check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
- {StrLen,NewVal} = case StringType of
- ?N_BIT_STRING when NamedNumberList /= [] ->
- {no_check,Val};
- ?N_BIT_STRING when is_list(Val) ->
- {length(Val),Val};
- ?N_BIT_STRING when is_tuple(Val) ->
- {(size(element(2,Val))*8) - element(1,Val),Val};
- _ when is_binary(Val) ->
- {size(Val),binary_to_list(Val)};
- _ when is_list(Val) ->
- {length(Val), Val}
- end,
- case Range of
- _ when StrLen == no_check ->
- NewVal;
- [] -> % No length constraint
- NewVal;
- {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
- NewVal;
- {{Lb,_Ub},[]} when StrLen >= Lb ->
- NewVal;
- {{Lb,_Ub},_Ext=[Min|_]} when StrLen >= Lb; StrLen >= Min ->
- NewVal;
- {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
- StrLen =< Ub2, StrLen >= Lb2 ->
- NewVal;
- StrLen -> % fixed length constraint
- NewVal;
- {_,_} ->
- exit({error,{asn1,{length,Range,Val}}});
- _Len when is_integer(_Len) ->
- exit({error,{asn1,{length,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- NewVal
- end.
-
-
-%%============================================================================
-%% encode Universal string
-%%============================================================================
-
-encode_universal_string(C, {Name, Universal}, TagIn) when is_atom(Name) ->
- encode_universal_string(C, Universal, TagIn);
-encode_universal_string(_C, Universal, TagIn) ->
- OctetList = mk_uni_list(Universal),
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-mk_uni_list(In) ->
- mk_uni_list(In,[]).
-
-mk_uni_list([],List) ->
- lists:reverse(List);
-mk_uni_list([{A,B,C,D}|T],List) ->
- mk_uni_list(T,[D,C,B,A|List]);
-mk_uni_list([H|T],List) ->
- mk_uni_list(T,[H,0,0,0|List]).
-
-%%===========================================================================
-%% decode Universal strings
-%% (Buffer, Range, StringType, HasTag, LenIn) ->
-%% {String, Remain, RemovedBytes}
-%%===========================================================================
-
-decode_universal_string(Buffer, Range, Tags) ->
- decode_restricted_string(Buffer, Range, ?N_UniversalString,
- Tags, [], old).
-
-
-mk_universal_string(In) ->
- mk_universal_string(In,[]).
-
-mk_universal_string([],Acc) ->
- lists:reverse(Acc);
-mk_universal_string([0,0,0,D|T],Acc) ->
- mk_universal_string(T,[D|Acc]);
-mk_universal_string([A,B,C,D|T],Acc) ->
- mk_universal_string(T,[{A,B,C,D}|Acc]).
-
-
-%%============================================================================
-%% encode UTF8 string
-%%============================================================================
-
-encode_UTF8_string(_C,UTF8String,TagIn) when is_binary(UTF8String) ->
- encode_tags(TagIn, UTF8String, size(UTF8String));
-encode_UTF8_string(_C,UTF8String,TagIn) ->
- encode_tags(TagIn, UTF8String, length(UTF8String)).
-
-
-%%============================================================================
-%% decode UTF8 string
-%%============================================================================
-
-decode_UTF8_string(Tlv,TagsIn) ->
- Val = match_tags(Tlv, TagsIn),
- case Val of
- PartList = [_H|_T] -> % constructed val
- collect_parts(PartList);
- Bin ->
- Bin
- end.
-
-
-%%============================================================================
-%% encode BMP string
-%%============================================================================
-
-encode_BMP_string(C, {Name,BMPString}, TagIn) when is_atom(Name)->
- encode_BMP_string(C, BMPString, TagIn);
-encode_BMP_string(_C, BMPString, TagIn) ->
- OctetList = mk_BMP_list(BMPString),
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-mk_BMP_list(In) ->
- mk_BMP_list(In,[]).
-
-mk_BMP_list([],List) ->
- lists:reverse(List);
-mk_BMP_list([{0,0,C,D}|T],List) ->
- mk_BMP_list(T,[D,C|List]);
-mk_BMP_list([H|T],List) ->
- mk_BMP_list(T,[H,0|List]).
-
-%%============================================================================
-%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-decode_BMP_string(Buffer, Range, Tags) ->
- decode_restricted_string(Buffer, Range, ?N_BMPString,
- Tags, [], old).
-
-mk_BMP_string(In) ->
- mk_BMP_string(In,[]).
-
-mk_BMP_string([],US) ->
- lists:reverse(US);
-mk_BMP_string([0,B|T],US) ->
- mk_BMP_string(T,[B|US]);
-mk_BMP_string([C,D|T],US) ->
- mk_BMP_string(T,[{0,0,C,D}|US]).
-
-
-%%============================================================================
-%% Generalized time, ITU_T X.680 Chapter 39
-%%
-%% encode Generalized time
-%%============================================================================
-
-encode_generalized_time(C, {Name,OctetList}, TagIn) when is_atom(Name) ->
- encode_generalized_time(C, OctetList, TagIn);
-encode_generalized_time(_C, OctetList, TagIn) ->
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-%%============================================================================
-%% decode Generalized time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_generalized_time(Tlv, _Range, Tags) ->
- Val = match_tags(Tlv, Tags),
- NewVal = case Val of
- PartList = [_H|_T] -> % constructed
- collect_parts(PartList);
- Bin ->
- Bin
- end,
- binary_to_list(NewVal).
-
-%%============================================================================
-%% Universal time, ITU_T X.680 Chapter 40
-%%
-%% encode UTC time
-%%============================================================================
-
-encode_utc_time(C, {Name,OctetList}, TagIn) when is_atom(Name) ->
- encode_utc_time(C, OctetList, TagIn);
-encode_utc_time(_C, OctetList, TagIn) ->
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-%%============================================================================
-%% decode UTC time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_utc_time(Tlv, _Range, Tags) ->
- Val = match_tags(Tlv, Tags),
- NewVal = case Val of
- PartList = [_H|_T] -> % constructed
- collect_parts(PartList);
- Bin ->
- Bin
- end,
- binary_to_list(NewVal).
-
-
-%%============================================================================
-%% Length handling
-%%
-%% Encode length
-%%
-%% encode_length(Int | indefinite) ->
-%% [<127]| [128 + Int (<127),OctetList] | [16#80]
-%%============================================================================
-
-encode_length(indefinite) ->
- {[16#80],1}; % 128
-encode_length(L) when L =< 16#7F ->
- {[L],1};
-encode_length(L) ->
- Oct = minimum_octets(L),
- Len = length(Oct),
- if
- Len =< 126 ->
- {[ (16#80+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 16#FF | 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)
-%%-------------------------------------------------------------------------
-
-
-%% decoding postitive integer values.
-decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>) ->
- <<Int:Len/unit:8>> = Bin,
- Int;
-%% decoding negative integer values.
-decode_integer2(Len,<<1:1,B2:7,Bs/binary>>) ->
- <<N:Len/unit:8>> = <<B2,Bs/binary>>,
- Int = N - (1 bsl (8 * Len - 1)),
- Int.
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-collect_parts(TlvList) ->
- collect_parts(TlvList,[]).
-
-collect_parts([{_,L}|Rest],Acc) when is_list(L) ->
- collect_parts(Rest,[collect_parts(L)|Acc]);
-collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],_Acc) ->
- collect_parts_bit(Rest,[Bits],Unused);
-collect_parts([{_T,V}|Rest],Acc) ->
- collect_parts(Rest,[V|Acc]);
-collect_parts([],Acc) ->
- list_to_binary(lists:reverse(Acc)).
-
-collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) ->
- collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc);
-collect_parts_bit([],Acc,Uacc) ->
- list_to_binary([Uacc|lists:reverse(Acc)]).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/asn1/src/asn1rt_check.erl b/lib/asn1/src/asn1rt_check.erl
deleted file mode 100644
index 35b993fc71..0000000000
--- a/lib/asn1/src/asn1rt_check.erl
+++ /dev/null
@@ -1,360 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. 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%
-%%
-%%
--module(asn1rt_check).
-
--export([check_bool/2,
- check_int/3,
- check_bitstring/3,
- check_octetstring/2,
- check_null/2,
- check_objectidentifier/2,
- check_objectdescriptor/2,
- check_real/2,
- check_enum/3,
- check_restrictedstring/2]).
-
--export([transform_to_EXTERNAL1990/1,
- transform_to_EXTERNAL1994/1]).
-
--export([dynamicsort_SET_components/1,
- dynamicsort_SETOF/1]).
-
-check_bool(_Bool,asn1_DEFAULT) ->
- true;
-check_bool(Bool,Bool) when Bool == true; Bool == false ->
- true;
-check_bool(_Bool1,Bool2) ->
- throw({error,Bool2}).
-
-check_int(_,asn1_DEFAULT,_) ->
- true;
-check_int(Value,Value,_) when is_integer(Value) ->
- true;
-check_int(DefValue,Value,NNL) when is_atom(Value) ->
- case lists:keysearch(Value,1,NNL) of
- {value,{_,DefValue}} ->
- true;
- _ ->
- throw({error,DefValue})
- end;
-check_int(DefaultValue,_Value,_) ->
- throw({error,DefaultValue}).
-
-% check_bitstring([H|T],[H|T],_) when is_integer(H) ->
-% true;
-% check_bitstring(V,V,_) when is_integer(V) ->
-% true;
-%% Two equal lists or integers
-check_bitstring(_,asn1_DEFAULT,_) ->
- true;
-check_bitstring(V,V,_) ->
- true;
-%% Default value as a list of 1 and 0 and user value as an integer
-check_bitstring(L=[H|T],Int,_) when is_integer(Int),is_integer(H) ->
- case bit_list_to_int(L,length(T)) of
- Int -> true;
- _ -> throw({error,L,Int})
- end;
-%% Default value as an integer, val as list
-check_bitstring(Int,Val,NBL) when is_integer(Int),is_list(Val) ->
- BL = int_to_bit_list(Int,[],length(Val)),
- check_bitstring(BL,Val,NBL);
-%% Default value and user value as lists of ones and zeros
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL=[_H|_T]) when is_integer(H1),is_integer(H2) ->
- L2new = remove_trailing_zeros(L2),
- check_bitstring(L1,L2new,NBL);
-%% Default value as a list of 1 and 0 and user value as a list of atoms
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when is_integer(H1),is_atom(H2) ->
- L3 = bit_list_to_nbl(L1,NBL,0,[]),
- check_bitstring(L3,L2,NBL);
-%% Both default value and user value as a list of atoms
-check_bitstring(L1=[H1|T1],L2=[H2|_T2],_)
- when is_atom(H1),is_atom(H2),length(L1) == length(L2) ->
- case lists:member(H1,L2) of
- true ->
- check_bitstring1(T1,L2);
- false -> throw({error,L2})
- end;
-%% Default value as a list of atoms and user value as a list of 1 and 0
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when is_atom(H1),is_integer(H2) ->
- L3 = bit_list_to_nbl(L2,NBL,0,[]),
- check_bitstring(L1,L3,NBL);
-%% User value in compact format
-check_bitstring(DefVal,CBS={_,_},NBL) ->
- NewVal = cbs_to_bit_list(CBS),
- check_bitstring(DefVal,NewVal,NBL);
-check_bitstring(DV,V,_) ->
- throw({error,DV,V}).
-
-
-bit_list_to_int([0|Bs],ShL)->
- bit_list_to_int(Bs,ShL-1) + 0;
-bit_list_to_int([1|Bs],ShL) ->
- bit_list_to_int(Bs,ShL-1) + (1 bsl ShL);
-bit_list_to_int([],_) ->
- 0.
-
-int_to_bit_list(0,Acc,0) ->
- Acc;
-int_to_bit_list(Int,Acc,Len) ->
- int_to_bit_list(Int bsr 1,[Int band 1|Acc],Len - 1).
-
-bit_list_to_nbl([0|T],NBL,Pos,Acc) ->
- bit_list_to_nbl(T,NBL,Pos+1,Acc);
-bit_list_to_nbl([1|T],NBL,Pos,Acc) ->
- case lists:keysearch(Pos,2,NBL) of
- {value,{N,_}} ->
- bit_list_to_nbl(T,NBL,Pos+1,[N|Acc]);
- _ ->
- throw({error,{no,named,element,at,pos,Pos}})
- end;
-bit_list_to_nbl([],_,_,Acc) ->
- Acc.
-
-remove_trailing_zeros(L2) ->
- remove_trailing_zeros1(lists:reverse(L2)).
-remove_trailing_zeros1(L) ->
- lists:reverse(lists:dropwhile(fun(0)->true;
- (_) ->false
- end,
- L)).
-
-check_bitstring1([H|T],NBL) ->
- case lists:member(H,NBL) of
- true ->
- check_bitstring1(T,NBL);
- V -> throw({error,V})
- end;
-check_bitstring1([],_) ->
- true.
-
-cbs_to_bit_list({Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when size(Rest) >= 1 ->
- [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})];
-cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) ->
- [B7,B6,B5,B4,B3,B2,B1,B0];
-cbs_to_bit_list({Unused,Bin}) when size(Bin) == 1 ->
- Used = 8-Unused,
- <<Int:Used,_:Unused>> = Bin,
- int_to_bit_list(Int,[],Used).
-
-
-check_octetstring(_,asn1_DEFAULT) ->
- true;
-check_octetstring(L,L) ->
- true;
-check_octetstring(L,Int) when is_list(L),is_integer(Int) ->
- case integer_to_octetlist(Int) of
- L -> true;
- V -> throw({error,V})
- end;
-check_octetstring(_,V) ->
- throw({error,V}).
-
-integer_to_octetlist(Int) ->
- integer_to_octetlist(Int,[]).
-integer_to_octetlist(0,Acc) ->
- Acc;
-integer_to_octetlist(Int,Acc) ->
- integer_to_octetlist(Int bsr 8,[(Int band 255)|Acc]).
-
-check_null(_,asn1_DEFAULT) ->
- true;
-check_null('NULL','NULL') ->
- true;
-check_null(_,V) ->
- throw({error,V}).
-
-check_objectidentifier(_,asn1_DEFAULT) ->
- true;
-check_objectidentifier(OI,OI) ->
- true;
-check_objectidentifier(DOI,OI) when is_tuple(DOI),is_tuple(OI) ->
- check_objectidentifier1(tuple_to_list(DOI),tuple_to_list(OI));
-check_objectidentifier(_,OI) ->
- throw({error,OI}).
-
-check_objectidentifier1([V|Rest1],[V|Rest2]) ->
- check_objectidentifier1(Rest1,Rest2,V);
-check_objectidentifier1([V1|Rest1],[V2|Rest2]) ->
- case reserved_objectid(V2,[]) of
- V1 ->
- check_objectidentifier1(Rest1,Rest2,[V1]);
- V ->
- throw({error,V})
- end.
-check_objectidentifier1([V|Rest1],[V|Rest2],Above) ->
- check_objectidentifier1(Rest1,Rest2,[V|Above]);
-check_objectidentifier1([V1|Rest1],[V2|Rest2],Above) ->
- case reserved_objectid(V2,Above) of
- V1 ->
- check_objectidentifier1(Rest1,Rest2,[V1|Above]);
- V ->
- throw({error,V})
- end;
-check_objectidentifier1([],[],_) ->
- true;
-check_objectidentifier1(_,V,_) ->
- throw({error,object,identifier,V}).
-
-%% ITU-T Rec. X.680 Annex B - D
-reserved_objectid('itu-t',[]) -> 0;
-reserved_objectid('ccitt',[]) -> 0;
-%% arcs below "itu-t"
-reserved_objectid('recommendation',[0]) -> 0;
-reserved_objectid('question',[0]) -> 1;
-reserved_objectid('administration',[0]) -> 2;
-reserved_objectid('network-operator',[0]) -> 3;
-reserved_objectid('identified-organization',[0]) -> 4;
-
-reserved_objectid(iso,[]) -> 1;
-%% arcs below "iso", note that number 1 is not used
-reserved_objectid('standard',[1]) -> 0;
-reserved_objectid('member-body',[1]) -> 2;
-reserved_objectid('identified-organization',[1]) -> 3;
-
-reserved_objectid('joint-iso-itu-t',[]) -> 2;
-reserved_objectid('joint-iso-ccitt',[]) -> 2;
-
-reserved_objectid(_,_) -> false.
-
-
-check_objectdescriptor(_,asn1_DEFAULT) ->
- true;
-check_objectdescriptor(OD,OD) ->
- true;
-check_objectdescriptor(OD,OD) ->
- throw({error,{not_implemented_yet,check_objectdescriptor}}).
-
-check_real(_,asn1_DEFAULT) ->
- true;
-check_real(R,R) ->
- true;
-check_real(_,_) ->
- throw({error,{not_implemented_yet,check_real}}).
-
-check_enum(_,asn1_DEFAULT,_) ->
- true;
-check_enum(Val,Val,_) ->
- true;
-check_enum(Int,Atom,Enumerations) when is_integer(Int),is_atom(Atom) ->
- case lists:keysearch(Atom,1,Enumerations) of
- {value,{_,Int}} -> true;
- _ -> throw({error,{enumerated,Int,Atom}})
- end;
-check_enum(DefVal,Val,_) ->
- throw({error,{enumerated,DefVal,Val}}).
-
-
-check_restrictedstring(_,asn1_DEFAULT) ->
- true;
-check_restrictedstring(Val,Val) ->
- true;
-check_restrictedstring([V|Rest1],[V|Rest2]) ->
- check_restrictedstring(Rest1,Rest2);
-check_restrictedstring([V1|Rest1],[V2|Rest2]) ->
- check_restrictedstring(V1,V2),
- check_restrictedstring(Rest1,Rest2);
-%% tuple format of value
-check_restrictedstring({V1,V2},[V1,V2]) ->
- true;
-check_restrictedstring([V1,V2],{V1,V2}) ->
- true;
-%% quadruple format of value
-check_restrictedstring({V1,V2,V3,V4},[V1,V2,V3,V4]) ->
- true;
-check_restrictedstring([V1,V2,V3,V4],{V1,V2,V3,V4}) ->
- true;
-%% character string list
-check_restrictedstring(V1,V2) when is_list(V1),is_tuple(V2) ->
- check_restrictedstring(V1,tuple_to_list(V2));
-check_restrictedstring(V1,V2) ->
- throw({error,{restricted,string,V1,V2}}).
-
-transform_to_EXTERNAL1990(Val) when is_tuple(Val),size(Val) == 4 ->
- transform_to_EXTERNAL1990(tuple_to_list(Val),[]);
-transform_to_EXTERNAL1990(Val) when is_tuple(Val) ->
- %% Data already in ASN1 1990 format
- Val.
-
-transform_to_EXTERNAL1990(['EXTERNAL'|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,['EXTERNAL'|Acc]);
-transform_to_EXTERNAL1990([{syntax,Syntax}|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE,Syntax|Acc]);
-transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[PCid,asn1_NOVALUE|Acc]);
-transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest],Acc) ->
- {_,Presentation_Cid,Transfer_syntax} = Context_negot,
- transform_to_EXTERNAL1990(Rest,[Presentation_Cid,Transfer_syntax|Acc]);
-transform_to_EXTERNAL1990([asn1_NOVALUE|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE|Acc]);
-transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc) when is_list(Data_value)->
- list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
- Data_val_desc|Acc]));
-transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc)
- when is_binary(Data_value)->
- list_to_tuple(lists:reverse([{'single-ASN1-type',Data_value},
- Data_val_desc|Acc]));
-transform_to_EXTERNAL1990([Data_value],Acc)
- when is_list(Data_value); is_binary(Data_value) ->
- list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
-
-
-transform_to_EXTERNAL1994(V={'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}) ->
- Identification =
- case {DRef,IndRef} of
- {DRef,asn1_NOVALUE} ->
- {syntax,DRef};
- {asn1_NOVALUE,IndRef} ->
- {'presentation-context-id',IndRef};
- _ ->
- {'context-negotiation',
- {'EXTERNAL_identification_context-negotiation',IndRef,DRef}}
- end,
- case Encoding of
- {_,Val} when is_list(Val);is_binary(Val) ->
- {'EXTERNAL',Identification,Data_v_desc,Val};
-
- _ ->
- V
- end.
-
-
-%% dynamicsort_SET_components(Arg) ->
-%% Res Arg -> list()
-%% Res -> list()
-%% Sorts the elements in Arg according to the encoded tag in
-%% increasing order.
-dynamicsort_SET_components(ListOfEncCs) ->
- BinL = lists:map(fun(X) -> list_to_binary(X) end,ListOfEncCs),
- TagBinL = lists:map(fun(X) ->
- {{T,_,TN},_,_} = asn1rt_ber_bin:decode_tag(X),
- {{T,TN},X}
- end,BinL),
- ClassTagNoSorted = lists:keysort(1,TagBinL),
- lists:map(fun({_,El}) -> El end,ClassTagNoSorted).
-
-%% dynamicsort_SETOF(Arg) -> Res
-%% Arg -> list()
-%% Res -> list()
-%% Sorts the elements in Arg in increasing size
-dynamicsort_SETOF(ListOfEncVal) ->
- BinL = lists:map(fun(L) when is_list(L) -> list_to_binary(L);
- (B) -> B end,ListOfEncVal),
- lists:sort(BinL).
diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl
index de1fb94816..c1879e3dcf 100644
--- a/lib/asn1/src/asn1rt_nif.erl
+++ b/lib/asn1/src/asn1rt_nif.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -77,10 +77,31 @@ load_nif() ->
Status
end.
-encode_per_complete(_TagValueList) ->
+decode_ber_tlv(Binary) ->
+ case decode_ber_tlv_raw(Binary) of
+ {error,Reason} ->
+ exit({error,{asn1,Reason}});
+ Other ->
+ Other
+ end.
+
+encode_per_complete(TagValueList) ->
+ case encode_per_complete_raw(TagValueList) of
+ {error,Reason} -> handle_error(Reason, TagValueList);
+ Other when is_binary(Other) -> Other
+ end.
+
+handle_error([], _)->
+ exit({error,{asn1,enomem}});
+handle_error($1, L) -> % error in complete in driver
+ exit({error,{asn1,L}});
+handle_error(ErrL, L) ->
+ exit({error,{asn1,ErrL,L}}).
+
+encode_per_complete_raw(_TagValueList) ->
erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
-decode_ber_tlv(_Binary) ->
+decode_ber_tlv_raw(_Binary) ->
erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
encode_ber_tlv(_TagValueList) ->
diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl
deleted file mode 100644
index 1f8c9729e7..0000000000
--- a/lib/asn1/src/asn1rt_per_bin.erl
+++ /dev/null
@@ -1,2316 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2012. 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%
-%%
-%%
--module(asn1rt_per_bin).
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/2, fixoptionals/3,
- fixextensions/2,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/2, getoptionals2/2, set_choice/3, encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_small_number/1, encode_boolean/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
--export([decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- encode_real/1, decode_real/1,
- encode_relative_oid/1, decode_relative_oid/1,
- complete/1]).
-
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([encode_UniversalString/2, decode_UniversalString/2,
- encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_VisibleString/2, decode_VisibleString/2,
- encode_UTF8String/1, decode_UTF8String/1,
- encode_BMPString/2, decode_BMPString/2,
- encode_IA5String/2, decode_IA5String/2,
- encode_NumericString/2, decode_NumericString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
- ]).
--export([complete_bytes/1, getbits/2, getoctets/2, minimum_bits/1]).
-
--define('16K',16384).
--define('32K',32768).
--define('64K',65536).
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%% converts a list to a record if necessary
-list_to_record(_Name,Tuple) when is_tuple(Tuple) ->
- Tuple;
-list_to_record(Name,List) when is_list(List) ->
- list_to_tuple([Name|List]).
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
- [{debug,choiceext},{bits,1,0}];
-setchoiceext(false) ->
- [{debug,choiceext},{bits,1,1}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(false) ->
- [{debug,ext},{bits,1,0}];
-setext(true) ->
- [{debug,ext},{bits,1,1}].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This version of fixoptionals/2 are left only because of
-%% backward compatibility with older generates
-
-fixoptionals(OptList,Val) when is_tuple(Val) ->
- fixoptionals1(OptList,Val,[]);
-
-fixoptionals(OptList,Val) when is_list(Val) ->
- fixoptionals1(OptList,Val,1,[],[]).
-
-fixoptionals1([],Val,Acc) ->
- %% return {Val,Opt}
- {Val,lists:reverse(Acc)};
-fixoptionals1([{_,Pos}|Ot],Val,Acc) ->
- case element(Pos+1,Val) of
- asn1_NOVALUE -> fixoptionals1(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals1(Ot,Val,[0|Acc]);
- _ -> fixoptionals1(Ot,Val,[1|Acc])
- end.
-
-
-fixoptionals1([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals1(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals1([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals1(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals1(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals1(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals1([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals1([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals1([],[],_,Acc1,Acc2) ->
- % return {Val,Opt}
- {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This is the new fixoptionals/3 which is used by the new generates
-%%
-fixoptionals(OptList,OptLength,Val) when is_tuple(Val) ->
- Bits = fixoptionals(OptList,Val,0),
- {Val,{bits,OptLength,Bits}};
-
-fixoptionals([],_Val,Acc) ->
- %% Optbits
- Acc;
-fixoptionals([{Pos,DefVal}|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
- DefVal -> fixoptionals(Ot,Val,Acc bsl 1);
- _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- end;
-fixoptionals([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
- asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
- _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- end.
-
-
-getext(Bytes) when is_tuple(Bytes) ->
- getbit(Bytes);
-getext(Bytes) when is_binary(Bytes) ->
- getbit({0,Bytes}).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_constrained_number(Bytes,{0,NumChoices-1}).
-
-%% old version kept for backward compatibility with generates from R7B
-getoptionals(Bytes,NumOpt) ->
- {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
- {list_to_tuple(Blist),Bytes1}.
-
-%% new version used in generates from r8b_patch/3 and later
-getoptionals2(Bytes,NumOpt) ->
- getbits(Bytes,NumOpt).
-
-
-%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
-%% Num = integer(),
-%% Bytes = list() | tuple(),
-%% Unused = integer(),
-%% BinBits = binary(),
-%% RestBytes = tuple()
-getbits_as_binary(Num,Bytes) when is_binary(Bytes) ->
- getbits_as_binary(Num,{0,Bytes});
-getbits_as_binary(0,Buffer) ->
- {{0,<<>>},Buffer};
-getbits_as_binary(Num,{0,Bin}) when Num > 16 ->
- Used = Num rem 8,
- Pad = (8 - Used) rem 8,
-% Nbytes = Num div 8,
- <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
- {{Pad,<<Bits:Num,0:Pad>>},RestBin};
-getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
- %% Num =< 16,
- {Bits2,Buffer2} = getbits(Buffer,Num),
- Pad = (8 - (Num rem 8)) rem 8,
- {{Pad,<<Bits2:Num,0:Pad>>},Buffer2}.
-
-
-% integer_from_list(Int,[],BigInt) ->
-% BigInt;
-% integer_from_list(Int,[H|T],BigInt) when Int < 8 ->
-% (BigInt bsl Int) bor (H bsr (8-Int));
-% integer_from_list(Int,[H|T],BigInt) ->
-% integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
-
-getbits_as_list(Num,Bytes) when is_binary(Bytes) ->
- getbits_as_list(Num,{0,Bytes},[]);
-getbits_as_list(Num,Bytes) ->
- getbits_as_list(Num,Bytes,[]).
-
-%% If buffer is empty and nothing more will be picked.
-getbits_as_list(0, B, Acc) ->
- {lists:reverse(Acc),B};
-%% If first byte in buffer is full and at least one byte will be picked,
-%% then pick one byte.
-getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
- getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
- NewUsed = Used + 4,
- Rem = 8 - NewUsed,
- <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6 ->
- NewUsed = Used + 2,
- Rem = 8 - NewUsed,
- <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
- NewUsed = Used + 1,
- Rem = 8 - NewUsed,
- <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
-
-
-getbit({7,<<_:7,B:1,Rest/binary>>}) ->
- {B,{0,Rest}};
-getbit({0,Buffer = <<B:1,_:7,_/binary>>}) ->
- {B,{1,Buffer}};
-getbit({Used,Buffer}) ->
- Unused = (8 - Used) - 1,
- <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
- {B,{Used+1,Buffer}};
-getbit(Buffer) when is_binary(Buffer) ->
- getbit({0,Buffer}).
-
-
-getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
- <<Bits:Num,Rest/binary>> = Buffer,
- {Bits,{0,Rest}};
-getbits({Used,Bin},Num) ->
- NumPlusUsed = Num + Used,
- NewUsed = NumPlusUsed rem 8,
- Unused = (8-NewUsed) rem 8,
- case Unused of
- 0 ->
- <<_:Used,Bits:Num,Rest/binary>> = Bin,
- {Bits,{0,Rest}};
- _ ->
- Bytes = NumPlusUsed div 8,
- <<_:Used,Bits:Num,_UBits:Unused,_/binary>> = Bin,
- <<_:Bytes/binary,Rest/binary>> = Bin,
- {Bits,{NewUsed,Rest}}
- end;
-getbits(Bin,Num) when is_binary(Bin) ->
- getbits({0,Bin},Num).
-
-
-
-% getoctet(Bytes) when is_list(Bytes) ->
-% getoctet({0,Bytes});
-% getoctet(Bytes) ->
-% %% io:format("getoctet:Buffer = ~p~n",[Bytes]),
-% getoctet1(Bytes).
-
-% getoctet1({0,[H|T]}) ->
-% {H,{0,T}};
-% getoctet1({Pos,[_,H|T]}) ->
-% {H,{0,T}}.
-
-align({0,L}) ->
- {0,L};
-align({_Pos,<<_H,T/binary>>}) ->
- {0,T};
-align(Bytes) ->
- {0,Bytes}.
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as an integer with bit significance as in buffer.
-getoctets({0,Buffer},Num) ->
- <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
- {Val,{0,RestBin}};
-getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
- getoctets({0,Rest},Num);
-getoctets(Buffer,Num) when is_binary(Buffer) ->
- getoctets({0,Buffer},Num).
-% getoctets(Buffer,Num) ->
-% %% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
-% getoctets(Buffer,Num,0).
-
-% getoctets(Buffer,0,Acc) ->
-% {Acc,Buffer};
-% getoctets(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
-
-% getoctets_as_list(Buffer,Num) ->
-% getoctets_as_list(Buffer,Num,[]).
-
-% getoctets_as_list(Buffer,0,Acc) ->
-% {lists:reverse(Acc),Buffer};
-% getoctets_as_list(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as a binary
-getoctets_as_bin({0,Bin},Num)->
- <<Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin({_U,Bin},Num) ->
- <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin(Bin,Num) when is_binary(Bin) ->
- getoctets_as_bin({0,Bin},Num).
-
-%% same as above but returns octets as a List
-getoctets_as_list(Buffer,Num) ->
- {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
- {binary_to_list(Bin),Buffer2}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when is_integer(N), Len1 > 1 ->
- [{bits,1,0}, % the value is in the root set
- encode_integer([{'ValueRange',{0,Len1-1}}],N)];
- N when is_integer(N) ->
- [{bits,1,0}]; % no encoding if only 0 or 1 alternative
- false ->
- [{bits,1,1}, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when is_integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when is_integer(N), Len > 1 ->
- encode_integer([{'ValueRange',{0,Len-1}}],N);
- N when is_integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_fragmented_XXX; decode of values encoded fragmented according
-%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
-%% characters or number of components (in a choice,sequence or similar).
-%% Buffer is a buffer {Used, Bin}.
-%% C is the constrained length.
-%% If the buffer is not aligned, this function does that.
-decode_fragmented_bits({0,Buffer},C) ->
- decode_fragmented_bits(Buffer,C,[]);
-decode_fragmented_bits({_N,<<_,Bs/binary>>},C) ->
- decode_fragmented_bits(Bs,C,[]).
-
-decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
- decode_fragmented_bits(Bin2,C,[Value,Acc]);
-decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- BinBits = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int),C == size(BinBits) ->
- {BinBits,{0,Bin}};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}})
- end;
-decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- Result = {BinBits,{Used,_Rest}} =
- case (Len rem 8) of
- 0 ->
- <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
- Rem ->
- Bytes = Len div 8,
- U = 8 - Rem,
- <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
- {Rem,<<Bits2,Bin2/binary>>}}
- end,
- case C of
- Int when is_integer(Int),C == (size(BinBits) - ((8 - Used) rem 8)) ->
- Result;
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}})
- end.
-
-
-decode_fragmented_octets({0,Bin},C) ->
- decode_fragmented_octets(Bin,C,[]).
-
-decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
- decode_fragmented_octets(Bin2,C,[Value,Acc]);
-decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- Octets = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int), C == size(Octets) ->
- {Octets,{0,Bin}};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,Octets}}})
- end;
-decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
- BinOctets = list_to_binary(lists:reverse([Value|Acc])),
- case C of
- Int when is_integer(Int),size(BinOctets) == Int ->
- {BinOctets,Bin2};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinOctets}}})
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when is_list(Val) ->
- encode_open_type_1(list_to_binary(Val));
-encode_open_type(_Constraint, Val) when is_binary(Val) ->
- encode_open_type_1(Val).
-
-encode_open_type_1(Val0) ->
- case byte_size(Val0) of
- Size when Size < 16384 ->
- [encode_length(undefined, Size),{octets,Val0}];
- Size ->
- F = min(Size bsr 14, 4),
- SegSz = F * ?'16K',
- <<Val:SegSz/binary,T/binary>> = Val0,
- [{octets,<<3:2,F:6>>},{octets,Val}|encode_open_type_1(T)]
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- decode_open_type_1(Bytes, []).
-
-decode_open_type_1(Bytes0, Acc) ->
- case decode_length_unlimited(Bytes0) of
- {Len,Bytes} when Len < ?'16K', Acc =:= [] ->
- getoctets_as_bin(Bytes, Len);
- {Len,Bytes1} when Len < ?'16K' ->
- {Bin,Bytes} = getoctets_as_bin(Bytes1, Len),
- {iolist_to_binary([Acc,Bin]),Bytes};
- {Len,Bytes1} ->
- {Bin,Bytes} = getoctets_as_bin(Bytes1, Len),
- decode_open_type_1(Bytes, [Acc,Bin])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when is_atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when is_integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when is_atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when is_atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer([{Rc,_Ec}],Val) when is_tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
- case (catch encode_integer([Rc],Val)) of
- {'EXIT',{error,{asn1,_}}} ->
- [{bits,1,1},encode_unconstrained_number(Val)];
- Encoded ->
- [{bits,1,0},Encoded]
- end;
-encode_integer(C,Val ) when is_list(C) ->
- case get_constraint(C,'SingleValue') of
- no ->
- encode_integer1(C,Val);
- V when is_integer(V),V == Val ->
- []; % a type restricted to a single value encodes to nothing
- V when is_list(V) ->
- case lists:member(Val,V) of
- true ->
- encode_integer1(C,Val);
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end.
-
-encode_integer1(C, Val) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- encode_unconstrained_number(Val);
- {Lb,'MAX'} ->
- encode_semi_constrained_number(Lb,Val);
- %% positive with range
- {Lb,Ub} when Val >= Lb,
- Ub >= Val ->
- encode_constrained_number(VR,Val);
- _ ->
- exit({error,{asn1,{illegal_value,VR,Val}}})
- end.
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,[{Rc,_Ec}]) when is_tuple(Rc) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,[Rc]);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when is_integer(V) ->
- {V,Buffer};
- V when is_list(V) ->
- {Val,Buffer2} = decode_integer1(Buffer,C),
- case lists:member(Val,V) of
- true ->
- {Val,Buffer2};
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_,_} ->
- decode_constrained_number(Buffer,VR)
- end.
-
- % X.691:10.6 Encoding of a normally small non-negative whole number
- % Use this for encoding of CHOICE index if there is an extension marker in
- % the CHOICE
-encode_small_number({Name,Val}) when is_atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
-% [{bits,1,0},{bits,6,Val}];
- [{bits,7,Val}]; % same as above but more efficient
-encode_small_number(Val) ->
- [{bits,1,1},encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,0)
- end.
-
-%% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when is_atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Oct = eint_positive(Val2),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end.
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number(Range,{Name,Val}) when is_atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 1 ->
- [];
- Range == 2 ->
- {bits,1,Val2};
- Range =< 4 ->
- {bits,2,Val2};
- Range =< 8 ->
- {bits,3,Val2};
- Range =< 16 ->
- {bits,4,Val2};
- Range =< 32 ->
- {bits,5,Val2};
- Range =< 64 ->
- {bits,6,Val2};
- Range =< 128 ->
- {bits,7,Val2};
- Range =< 255 ->
- {bits,8,Val2};
- Range =< 256 ->
- {octets,[Val2]};
- Range =< 65536 ->
- {octets,<<Val2:16>>};
- Range =< (1 bsl (255*8)) ->
- Octs = binary:encode_unsigned(Val2),
- RangeOcts = binary:encode_unsigned(Range - 1),
- OctsLen = erlang:byte_size(Octs),
- RangeOctsLen = erlang:byte_size(RangeOcts),
- LengthBitsNeeded = minimum_bits(RangeOctsLen - 1),
- [{bits, LengthBitsNeeded, OctsLen - 1}, {octets, Octs}];
- true ->
- exit({not_supported,{integer_range,Range}})
- end;
-encode_constrained_number(Range,Val) ->
- exit({error,{asn1,{integer_range,Range,value,Val}}}).
-
-%% For some reason the minimum bits needed in the length field in encoding of
-%% constrained whole numbers must always be atleast 2?
-minimum_bits(N) when N < 4 -> 2;
-minimum_bits(N) when N < 8 -> 3;
-minimum_bits(N) when N < 16 -> 4;
-minimum_bits(N) when N < 32 -> 5;
-minimum_bits(N) when N < 64 -> 6;
-minimum_bits(N) when N < 128 -> 7;
-minimum_bits(_N) -> 8.
-
-decode_constrained_number(Buffer,{Lb,Ub}) ->
- Range = Ub - Lb + 1,
- % Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 1 ->
- {0,Buffer};
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< (1 bsl (255*8)) ->
- OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)),
- RangeOctLen = length(OList),
- {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}),
- {Octs, RestBytes} = getoctets_as_list(Bytes, Len),
- {binary:decode_unsigned(binary:list_to_bin(Octs)), RestBytes};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-%% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end;
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end.
-
-
-%% used for positive Values which don't need a sign bit
-%% returns a binary
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
- decpint(Ints, 8 * (length(Ints) - 1));
-dec_integer(Ints) -> %% Negative
- decnint(Ints, 8 * (length(Ints) - 1)).
-
-decpint([Byte|Tail], Shift) ->
- (Byte bsl Shift) bor decpint(Tail, Shift-8);
-decpint([], _) -> 0.
-
-decnint([Byte|Tail], Shift) ->
- (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
-
-% minimum_octets(Val) ->
-% minimum_octets(Val,[]).
-
-% minimum_octets(Val,Acc) when Val > 0 ->
-% minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
-% minimum_octets(0,Acc) ->
-% Acc.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
- {octets,[Len]};
- Len < 16384 ->
- {octets,<<2:2,Len:14>>};
- true -> % should be able to endode length >= 16384
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number(Vr,Len);
-encode_length({Lb,_Ub},Len) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- encode_length(undefined,Len);
-encode_length({Vr={Lb,Ub},Ext},Len)
- when Ub =< 65535 ,Lb >= 0, Len=<Ub, is_list(Ext) ->
- %% constrained extensible
- [{bits,1,0},encode_constrained_number(Vr,Len)];
-encode_length({{Lb,_Ub},Ext},Len) when is_list(Ext) ->
- [{bits,1,1},encode_semi_constrained_number(Lb,Len)];
-encode_length(SingleValue,_Len) when is_integer(SingleValue) ->
- [].
-
-%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
-%% additions in a sequence or set
-encode_small_length(Len) when Len =< 64 ->
-%% [{bits,1,0},{bits,6,Len-1}];
- {bits,7,Len-1}; % the same as above but more efficient
-encode_small_length(Len) ->
- [{bits,1,1},encode_length(undefined,Len)].
-
-% decode_small_length({Used,<<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>>}) ->
-% case Buffer of
-% <<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>> ->
-% {Num,
-% case getbit(Buffer) of
-% {0,Remain} ->
-% {Bits,Remain2} = getbits(Remain,6),
-% {Bits+1,Remain2};
-% {1,Remain} ->
-% decode_length(Remain,undefined)
-% end.
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length_unlimited(Buffer) ->
- case align(Buffer) of
- {0,<<0:1,Oct:7,Rest/binary>>} ->
- {Oct,{0,Rest}};
- {0,<<1:1,0:1,Val:14,Rest/binary>>} ->
- {Val,{0,Rest}};
- {0,<<1:1,1:1,F:6,Rest/binary>>} ->
- SegSz = F * ?'16K',
- {SegSz,{0,Rest}}
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- {0,Buffer2} = align(Buffer),
- case Buffer2 of
- <<0:1,Oct:7,Rest/binary>> ->
- {Oct,{0,Rest}};
- <<2:2,Val:14,Rest/binary>> ->
- {Val,{0,Rest}};
- <<3:2,_:14,_Rest/binary>> ->
- %% this case should be fixed
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
- end;
-%% {Bits,_} = getbits(Buffer2,2),
-% case Bits of
-% 2 ->
-% {Val,Bytes3} = getoctets(Buffer2,2),
-% {(Val band 16#3FFF),Bytes3};
-% 3 ->
-% exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
-% _ ->
-% {Val,Bytes3} = getoctet(Buffer2),
-% {Val band 16#7F,Bytes3}
-% end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-decode_length(Buffer,{Lb,_}) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- decode_length(Buffer,undefined);
-decode_length(Buffer,{VR={_Lb,_Ub},Ext}) when is_list(Ext) ->
- case getbit(Buffer) of
- {0,Buffer2} ->
- decode_length(Buffer2, VR);
- {1,Buffer2} ->
- decode_length(Buffer2, undefined)
- end;
-%% {0,Buffer2} = getbit(Buffer),
-%% decode_length(Buffer2, VR);
-
-
-%When does this case occur with {_,_Lb,Ub} ??
-% X.691:10.9.3.5
-decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
- Unused = (8-Used) rem 8,
- case Bin of
- <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
- {Val,{Used,<<R,Rest/binary>>}};
- <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
- {Val, {0,Rest}};
- <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
- exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
- end;
-% decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
-% case getbit(Buffer) of
-% {0,Remain} ->
-% getbits(Remain,7);
-% {1,Remain} ->
-% {Val,Remain2} = getoctets(Buffer,2),
-% {Val band 2#0111111111111111, Remain2}
-% end;
-decode_length(Buffer,SingleValue) when is_integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
- % X.691:11
-encode_boolean(true) ->
- {bits,1,1};
-encode_boolean(false) ->
- {bits,1,0};
-encode_boolean({Name,Val}) when is_atom(Name) ->
- encode_boolean(Val);
-encode_boolean(Val) ->
- exit({error,{asn1,{encode_boolean,Val}}}).
-
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when is_tuple(Ntup1), is_tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when is_tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% 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 constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when is_integer(Unused),
- is_binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList);
-
-%% when the value is a list of named bits
-encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when is_atom(FirstVal) ->
- ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-encode_bit_string(C, BL=[{bit,_No} | _RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes(BL, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-
-% encode_bit_string(C, BitListValue, NamedBitList) when is_list(BitListValue) ->
-% Bl1 =
-% case NamedBitList of
-% [] -> % dont remove trailing zeroes
-% BitListValue;
-% _ -> % first remove any trailing zeroes
-% lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
-% lists:reverse(BitListValue)))
-% end,
-% BitList = [{bit,X} || X <- Bl1],
-% %% BListLen = length(BitList),
-% case get_constraint(C,'SizeConstraint') of
-% 0 -> % fixed length
-% []; % nothing to encode
-% V when is_integer(V),V=<16 -> % fixed length 16 bits or less
-% pad_list(V,BitList);
-% V when is_integer(V) -> % fixed length 16 bits or more
-% [align,pad_list(V,BitList)]; % should be another case for V >= 65537
-% {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
-% [encode_length({Lb,Ub},length(BitList)),align,BitList];
-% no ->
-% [encode_length(undefined,length(BitList)),align,BitList];
-% Sc -> % extension marker
-% [encode_length(Sc,length(BitList)),align,BitList]
-% end;
-encode_bit_string(C, BitListValue, NamedBitList) when is_list(BitListValue) ->
- BitListToBinary =
- %% fun that transforms a list of 1 and 0 to a tuple:
- %% {UnusedBitsInLastByte, Binary}
- fun([1|T],Acc,N,Fun) ->
- Fun(T,(Acc bsl 1)+1,N+1,Fun);
- ([0|T],Acc,N,Fun) ->
- Fun(T,(Acc bsl 1),N+1,Fun);
- ([_H|_T],_,_,_) ->
- exit({error,{asn1,{bitstring_bitlist,BitListValue}}});
- ([],Acc,N,_) ->
- Unused = (8 - (N rem 8)) rem 8,
- {Unused,<<Acc:N,0:Unused>>}
- end,
- UnusedAndBin =
- case NamedBitList of
- [] -> % dont remove trailing zeroes
- BitListToBinary(BitListValue,0,0,BitListToBinary);
- _ ->
- BitListToBinary(lists:reverse(
- lists:dropwhile(fun(0)->true;(_)->false end,
- lists:reverse(BitListValue))),
- 0,0,BitListToBinary)
- end,
- encode_bin_bit_string(C,UnusedAndBin,NamedBitList);
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) when is_integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string(C,{Name,Val}, NamedBitList) when is_atom(Name) ->
- encode_bit_string(C,Val,NamedBitList).
-
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),i.e. number unused bits in least sign. byte of
-%% BinBits = binary().
-
-
-encode_bin_bit_string(C,UnusedAndBin={_Unused,_BinBits},NamedBitList) ->
- Constr = get_constraint(C,'SizeConstraint'),
- UnusedAndBin1 = {Unused1,Bin1} =
- remove_trailing_bin(NamedBitList,UnusedAndBin,lower_bound(Constr)),
- case Constr of
- 0 ->
- [];
- V when is_integer(V),V=<16 ->
- {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
- <<BitVal:V,_:Unused2>> = Bin2,
- {bits,V,BitVal};
- V when is_integer(V) ->
- [align, pad_list(V, UnusedAndBin1)];
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
- align,UnusedAndBin1];
- {{Fix,Fix},L} when is_integer(Fix),is_list(L) ->
- %% X.691 � 15.6, the rest of this paragraph is covered by
- %% the last, ie. Sc, clause in this case
- case (size(Bin1)*8)-Unused1 of
- Size when Size =< Fix, Fix =< 16 ->
- {Unused2,Bin2} = pad_list(Fix,UnusedAndBin),
- <<BitVal:Fix,_:Unused2>> = Bin2,
- [{bits,1,0},{bits,Fix,BitVal}];
- Size when Size =< Fix ->
- [{bits,1,0},align, pad_list(Fix, UnusedAndBin1)];
- Size ->
- [{bits,1,1},encode_length(undefined,Size),
- align,UnusedAndBin1]
- end;
- no ->
- [encode_length(undefined,size(Bin1)*8 - Unused1),
- align,UnusedAndBin1];
- Sc ->
- [encode_length(Sc,size(Bin1)*8 - Unused1),
- align,UnusedAndBin1]
- end.
-
-
-remove_trailing_bin([], {Unused,Bin},_) ->
- {Unused,Bin};
-remove_trailing_bin(_NamedNumberList,{_Unused,<<>>},C) ->
- case C of
- Int when is_integer(Int),Int > 0 ->
- %% this padding see OTP-4353
- pad_list(Int,{0,<<>>});
- _ -> {0,<<>>}
- end;
-remove_trailing_bin(NamedNumberList, {_Unused,Bin},C) ->
- Size = size(Bin)-1,
- <<Bfront:Size/binary, LastByte:8>> = Bin,
- %% clear the Unused bits to be sure
- Unused1 = trailingZeroesInNibble(LastByte band 15),
- Unused2 =
- case Unused1 of
- 4 ->
- 4 + trailingZeroesInNibble(LastByte bsr 4);
- _ -> Unused1
- end,
- case Unused2 of
- 8 ->
- remove_trailing_bin(NamedNumberList,{0,Bfront},C);
- _ ->
- case C of
- Int when is_integer(Int),Int > ((size(Bin)*8)-Unused2) ->
- %% this padding see OTP-4353
- pad_list(Int,{Unused2,Bin});
- _ -> {Unused2,Bin}
- end
- end.
-
-
-trailingZeroesInNibble(0) ->
- 4;
-trailingZeroesInNibble(1) ->
- 0;
-trailingZeroesInNibble(2) ->
- 1;
-trailingZeroesInNibble(3) ->
- 0;
-trailingZeroesInNibble(4) ->
- 2;
-trailingZeroesInNibble(5) ->
- 0;
-trailingZeroesInNibble(6) ->
- 1;
-trailingZeroesInNibble(7) ->
- 0;
-trailingZeroesInNibble(8) ->
- 3;
-trailingZeroesInNibble(9) ->
- 0;
-trailingZeroesInNibble(10) ->
- 1;
-trailingZeroesInNibble(11) ->
- 0;
-trailingZeroesInNibble(12) -> %#1100
- 2;
-trailingZeroesInNibble(13) ->
- 0;
-trailingZeroesInNibble(14) ->
- 1;
-trailingZeroesInNibble(15) ->
- 0.
-
-lower_bound({{Lb,_},_}) when is_integer(Lb) ->
- Lb;
-lower_bound({Lb,_}) when is_integer(Lb) ->
- Lb;
-lower_bound(C) ->
- C.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{8,0},Buffer};
- V when is_integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 -> %fixed length > 16 bits
- Bytes2 = align(Buffer),
- compact_bit_string(Bytes2,V,NamedNumberList);
- V when is_integer(V) -> % V > 65536 => fragmented value
- {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
- case Buffer2 of
- {0,_} -> {{0,Bin},Buffer2};
- {U,_} -> {{8-U,Bin},Buffer2}
- end;
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- no ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- {{Fix,Fix},L} = Sc when is_list(L), is_integer(Fix), Fix =< 16 ->
- %% X.691 �15.6, special case of extension marker
- case decode_length(Buffer,Sc) of
- {Len,Bytes2} when Len > Fix ->
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} ->
- compact_bit_string(Bytes2,Len,NamedNumberList)
- end;
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when is_integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 ->
- Bytes2 = align(Buffer),
- bit_list_or_named(Bytes2,V,NamedNumberList);
- V when is_integer(V) ->
- Bytes2 = align(Buffer),
- {BinBits,_} = decode_fragmented_bits(Bytes2,V),
- bit_list_or_named(BinBits,V,NamedNumberList);
- {{Fix,Fix},L} = Sc when is_list(L), is_integer(Fix), Fix =< 16 ->
- %% X.691 �15.6, special case of extension marker
- case decode_length(Buffer,Sc) of
- {Len,Bytes2} when Len > Fix ->
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} when Len > 16 ->
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} ->
- bit_list_or_named(Bytes2,Len,NamedNumberList)
- end;
- Sc -> %% X.691 �15.6, extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_or_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_or_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_or_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_or_named1(Pos+1,Bt,Names,Acc);
-bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_or_named1(_,[],_,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(Int) when is_integer(Int), Int > 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)];
-int_to_bitlist(0) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-%%%%%%%%%%%%%%%%%
-%% pad_list(N,BitList) -> PaddedList
-%% returns a padded (with trailing {bit,0} elements) list of length N
-%% if Bitlist contains more than N significant bits set an exit asn1_error
-%% is generated
-
-pad_list(N,In={Unused,Bin}) ->
- pad_list(N, size(Bin)*8 - Unused, In).
-
-pad_list(N,Size,In={_,_}) when N < Size ->
- exit({error,{asn1,{range_error,{bit_string,In}}}});
-pad_list(N,Size,{Unused,Bin}) when N > Size, Unused > 0 ->
- pad_list(N,Size+1,{Unused-1,Bin});
-pad_list(N,Size,{_Unused,Bin}) when N > Size ->
- pad_list(N,Size+1,{7,<<Bin/binary,0>>});
-pad_list(N,N,In={_,_}) ->
- In.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,Val) ->
- encode_octet_string2(C,Val).
-
-encode_octet_string2(C,{_Name,Val}) ->
- encode_octet_string2(C,Val);
-encode_octet_string2(C,Val) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- [];
- 1 ->
- [V] = Val,
- {bits,8,V};
- 2 ->
- [V1,V2] = Val,
- [{bits,8,V1},{bits,8,V2}];
- Sv when Sv =<65535, Sv == length(Val) -> % fixed length
- {octets,Val};
- {Lb,Ub} ->
- [encode_length({Lb,Ub},length(Val)),{octets,Val}];
- Sv when is_list(Sv) ->
- [encode_length({hd(Sv),lists:max(Sv)},length(Val)),{octets,Val}];
- no ->
- [encode_length(undefined,length(Val)),{octets,Val}]
- end.
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(Bytes,C,false) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- {[],Bytes};
- 1 ->
- {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes2};
- 2 ->
- {Bs,Bytes2}= getbits(Bytes,16),
- {binary_to_list(<<Bs:16>>),Bytes2};
- {_,0} ->
- {[],Bytes};
- Sv when is_integer(Sv), Sv =<65535 -> % fixed length
- getoctets_as_list(Bytes,Sv);
- Sv when is_integer(Sv) -> % fragmented encoding
- Bytes2 = align(Bytes),
- decode_fragmented_octets(Bytes2,Sv);
- {Lb,Ub} ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- getoctets_as_list(Bytes2,Len);
- Sv when is_list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- getoctets_as_list(Bytes2,Len);
- no ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string(aligned,{Name,Val}) when is_atom(Name) ->
- encode_restricted_string(aligned,Val);
-
-encode_restricted_string(aligned,Val) when is_list(Val)->
- [encode_length(undefined,length(Val)),{octets,Val}].
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,{Name,Val}) when is_atom(Name) ->
- encode_known_multiplier_string(aligned,StringType,C,false,Val);
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,Val) ->
- Result = chars_encode(C,StringType,Val),
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- Result;
- 0 ->
- [];
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- [align,Result];
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),align,Result];
- Vl when is_list(Vl) ->
- [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
- no ->
- [encode_length(undefined,length(Val)),align,Result]
- end.
-
-decode_restricted_string(Bytes,aligned) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-decode_known_multiplier_string(Bytes,aligned,StringType,C,_Ext) ->
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,C,Ub);
- 0 ->
- {[],Bytes};
- Vl when is_list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len)
- end.
-
-
-encode_NumericString(C,Val) ->
- encode_known_multiplier_string(aligned,'NumericString',C,false,Val).
-decode_NumericString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'NumericString',C,false).
-
-encode_PrintableString(C,Val) ->
- encode_known_multiplier_string(aligned,'PrintableString',C,false,Val).
-decode_PrintableString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'PrintableString',C,false).
-
-encode_VisibleString(C,Val) -> % equivalent with ISO646String
- encode_known_multiplier_string(aligned,'VisibleString',C,false,Val).
-decode_VisibleString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'VisibleString',C,false).
-
-encode_IA5String(C,Val) ->
- encode_known_multiplier_string(aligned,'IA5String',C,false,Val).
-decode_IA5String(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'IA5String',C,false).
-
-encode_BMPString(C,Val) ->
- encode_known_multiplier_string(aligned,'BMPString',C,false,Val).
-decode_BMPString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'BMPString',C,false).
-
-encode_UniversalString(C,Val) ->
- encode_known_multiplier_string(aligned,'UniversalString',C,false,Val).
-decode_UniversalString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'UniversalString',C,false).
-
-
-%% end of known-multiplier strings for which PER visible constraints are
-%% applied
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{0,0,O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-chars_encode(C,StringType,Value) ->
- case {StringType,get_constraint(C,'PermittedAlphabet')} of
- {'UniversalString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
- {'BMPString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
- _ ->
- {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
- chars_encode2(Value,NumBits,CharOutTab)
- end.
-
-chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
- [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
- [{bits,NumBits,exit_if_false(H,element(H-Min+1,Tab))}|chars_encode2(T,NumBits,{Min,Max,Tab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab))}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_,{_,_,_}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-exit_if_false(V,false)->
- exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
-exit_if_false(_,V) ->V.
-
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv),aligned);
- no ->
- case StringType of
- 'IA5String' ->
- charbits(128,aligned); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95,aligned); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11,aligned); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-%%Maybe used later
-%%get_MaxChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% lists:nth(length(Sv),Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#7F; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#7E; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $9; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#ffffffff;
-%% 'BMPString' ->
-%% 16#ffff
-%% end
-%% end.
-
-%%Maybe used later
-%%get_MinChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% hd(Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#00; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#20; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $\s; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#00;
-%% 'BMPString' ->
-%% 16#00
-%% end
-%% end.
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-%% This very inefficient and should be moved to compiletime
-charbits(NumOfChars,aligned) ->
- case charbits(NumOfChars) of
- 1 -> 1;
- 2 -> 2;
- B when B =< 4 -> 4;
- B when B =< 8 -> 8;
- B when B =< 16 -> 16;
- B when B =< 32 -> 32
- end.
-
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when is_integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',C,Len) ->
- case get_constraint(C,'PermittedAlphabet') of
- no ->
- getBMPChars(Bytes,Len);
- _ ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet constraint"}}})
- end;
-chars_decode(Bytes,NumBits,StringType,C,Len) ->
- CharInTab = get_CharInTab(C,StringType),
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result =
- if
- Char < 256 -> Char;
- true ->
- list_to_tuple(binary_to_list(<<Char:32>>))
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-% chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
-% {Char,Bytes2} = getbits(Bytes,NumBits),
-% Result = case minimum_octets(Char+Min) of
-% [NewChar] -> NewChar;
-% [C1,C2] -> {0,0,C1,C2};
-% [C1,C2,C3] -> {0,C1,C2,C3};
-% [C1,C2,C3,C4] -> {C1,C2,C3,C4}
-% end,
-% chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
-%% UTF8String
-encode_UTF8String(Val) when is_binary(Val) ->
- [encode_length(undefined,size(Val)),{octets,Val}];
-encode_UTF8String(Val) ->
- Bin = list_to_binary(Val),
- encode_UTF8String(Bin).
-
-decode_UTF8String(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {list_to_binary(Octs),Bytes3}.
-
-
- % X.691:17
-encode_null(_) -> []. % encodes to nothing
-%encode_null({Name,Val}) when is_atom(Name) ->
-% encode_null(Val).
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier({Name,Val}) when is_atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- OctetList = e_object_identifier(Val),
- Octets = list_to_binary(OctetList), % performs a flatten at the same time
- [{debug,object_identifier},encode_length(undefined,size(Octets)),{octets,Octets}].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname,V}) when is_atom(Cname),is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname,V}) when is_atom(Cname),is_list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
- Head = 40*E1 + E2, % weird
- e_object_elements([Head|Tail],[]);
-e_object_identifier(Oid=[_,_|_Tail]) ->
- exit({error,{asn1,{'illegal_value',Oid}}}).
-
-e_object_elements([],Acc) ->
- lists:reverse(Acc);
-e_object_elements([H|T],Acc) ->
- e_object_elements(T,[e_object_element(H)|Acc]).
-
-e_object_element(Num) when Num < 128 ->
- [Num];
-e_object_element(Num) ->
- [e_o_e(Num bsr 7)|[Num band 2#1111111]].
-e_o_e(Num) when Num < 128 ->
- Num bor 2#10000000;
-e_o_e(Num) ->
- [e_o_e(Num bsr 7)|[(Num band 2#1111111) bor 2#10000000]].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_relative_oid(Val) -> CompleteList
-%% encode_relative_oid({Name,Val}) -> CompleteList
-encode_relative_oid({Name,Val}) when is_atom(Name) ->
- encode_relative_oid(Val);
-encode_relative_oid(Val) when is_tuple(Val) ->
- encode_relative_oid(tuple_to_list(Val));
-encode_relative_oid(Val) when is_list(Val) ->
- Octets = list_to_binary([e_object_element(X)||X <- Val]),
- [encode_length(undefined,size(Octets)),{octets,Octets}].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_relative_oid(Val) -> {ROID,Rest}
-%% decode_relative_oid({Name,Val}) -> {ROID,Rest}
-decode_relative_oid(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- ObjVals = dec_subidentifiers(Octs,0,[]),
- {list_to_tuple(ObjVals),Bytes3}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_real(Val) -> CompleteList
-%% encode_real({Name,Val}) -> CompleteList
-encode_real({Name,Val}) when is_atom(Name) ->
- encode_real(Val);
-encode_real(Real) ->
- {EncVal,Len} = ?RT_COMMON:encode_real([],Real),
- [encode_length(undefined,Len),{octets,EncVal}].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_real(Val) -> {REALvalue,Rest}
-%% decode_real({Name,Val}) -> {REALvalue,Rest}
-decode_real(Bytes) ->
- {Len,{0,Bytes2}} = decode_length(Bytes,undefined),
- {RealVal,Rest,Len} = ?RT_COMMON:decode_real(Bytes2,Len),
- {RealVal,{0,Rest}}.
-
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_Key) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
-% complete(L) ->
-% case complete1(L) of
-% {[],0} ->
-% <<0>>;
-% {Acc,0} ->
-% lists:reverse(Acc);
-% {[Hacc|Tacc],Acclen} -> % Acclen >0
-% Rest = 8 - Acclen,
-% NewHacc = Hacc bsl Rest,
-% lists:reverse([NewHacc|Tacc])
-% end.
-
-
-% complete1(InList) when is_list(InList) ->
-% complete1(InList,[]);
-% complete1(InList) ->
-% complete1([InList],[]).
-
-% complete1([{debug,_}|T], Acc) ->
-% complete1(T,Acc);
-% complete1([H|T],Acc) when is_list(H) ->
-% {NewH,NewAcclen} = complete1(H,Acc),
-% complete1(T,NewH,NewAcclen);
-
-% complete1([{0,Bin}|T],Acc,0) when is_binary(Bin) ->
-% complete1(T,[Bin|Acc],0);
-% complete1([{Unused,Bin}|T],Acc,0) when is_integer(Unused),is_binary(Bin) ->
-% Size = size(Bin)-1,
-% <<Bs:Size/binary,B>> = Bin,
-% complete1(T,[(B bsr Unused),Bs|Acc],8-Unused);
-% complete1([{Unused,Bin}|T],[Hacc|Tacc],Acclen) when is_integer(Unused),is_binary(Bin) ->
-% Rest = 8 - Acclen,
-% Used = 8 - Unused,
-% case size(Bin) of
-% 1 ->
-% if
-% Rest >= Used ->
-% <<B:Used,_:Unused>> = Bin,
-% complete1(T,[(Hacc bsl Used) + B|Tacc],
-% (Acclen+Used) rem 8);
-% true ->
-% LeftOver = 8 - Rest - Unused,
-% <<Val2:Rest,Val1:LeftOver,_:Unused>> = Bin,
-% complete1(T,[Val1,(Hacc bsl Rest) + Val2|Tacc],
-% (Acclen+Used) rem 8)
-% end;
-% N ->
-% if
-% Rest == Used ->
-% N1 = N - 1,
-% <<B:Rest,Bs:N1/binary,_:Unused>> = Bin,
-% complete1(T,[Bs,(Hacc bsl Rest) + B|Tacc],0);
-% Rest > Used ->
-% N1 = N - 2,
-% N2 = (8 - Rest) + Used,
-% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
-% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
-% (Acclen + Used) rem 8);
-% true -> % Rest < Used
-% N1 = N - 1,
-% N2 = Used - Rest,
-% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
-% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
-% (Acclen + Used) rem 8)
-% end
-% end;
-
-% %complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,is_integer(Val) ->
-% % complete1([{octets,<<Val:N/unit:8>>}|T],Acc,Acclen);
-% complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,is_integer(Val) ->
-% Newval = case N of
-% 1 ->
-% Val4 = Val band 16#FF,
-% [Val4];
-% 2 ->
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val3,Val4];
-% 3 ->
-% Val2 = (Val bsr 16) band 16#FF,
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val2,Val3,Val4];
-% 4 ->
-% Val1 = (Val bsr 24) band 16#FF,
-% Val2 = (Val bsr 16) band 16#FF,
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val1,Val2,Val3,Val4]
-% end,
-% complete1([{octets,Newval}|T],Acc,Acclen);
-
-% complete1([{octets,Bin}|T],Acc,Acclen) when is_binary(Bin) ->
-% Rest = 8 - Acclen,
-% if
-% Rest == 8 ->
-% complete1(T,[Bin|Acc],0);
-% true ->
-% [Hacc|Tacc]=Acc,
-% complete1(T,[Bin, Hacc bsl Rest|Tacc],0)
-% end;
-
-% complete1([{octets,Oct}|T],Acc,Acclen) when is_list(Oct) ->
-% Rest = 8 - Acclen,
-% if
-% Rest == 8 ->
-% complete1(T,[list_to_binary(Oct)|Acc],0);
-% true ->
-% [Hacc|Tacc]=Acc,
-% complete1(T,[list_to_binary(Oct), Hacc bsl Rest|Tacc],0)
-% end;
-
-% complete1([{bit,Val}|T], Acc, Acclen) ->
-% complete1([{bits,1,Val}|T],Acc,Acclen);
-% complete1([{octet,Val}|T], Acc, Acclen) ->
-% complete1([{octets,1,Val}|T],Acc,Acclen);
-
-% complete1([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
-% complete1(T,[Val|Acc],N);
-% complete1([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
-% Rest = 8 - Acclen,
-% if
-% Rest >= N ->
-% complete1(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
-% true ->
-% Diff = N - Rest,
-% NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
-% Mask = element(Diff,{1,3,7,15,31,63,127,255}),
-% complete1(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
-% end;
-% complete1([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
-% complete1([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
-
-% complete1([align|T],Acc,0) ->
-% complete1(T,Acc,0);
-% complete1([align|T],[Hacc|Tacc],Acclen) ->
-% Rest = 8 - Acclen,
-% complete1(T,[Hacc bsl Rest|Tacc],0);
-% complete1([{octets,N,Val}|T],Acc,Acclen) when is_list(Val) -> % no security check here
-% complete1([{octets,Val}|T],Acc,Acclen);
-
-% complete1([],Acc,Acclen) ->
-% {Acc,Acclen}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
-complete(L) ->
- case complete1(L) of
- {[],[]} ->
- <<0>>;
- {Acc,[]} ->
- Acc;
- {Acc,Bacc} ->
- [Acc|complete_bytes(Bacc)]
- end.
-
-%% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
-%% this is done because it is efficient and that the result always will be sent on a port or
-%% converted by means of list_to_binary/1
-complete1(InList) when is_list(InList) ->
- complete1(InList,[],[]);
-complete1(InList) ->
- complete1([InList],[],[]).
-
-complete1([],Acc,Bacc) ->
- {Acc,Bacc};
-complete1([H|T],Acc,Bacc) when is_list(H) ->
- {NewH,NewBacc} = complete1(H,Acc,Bacc),
- complete1(T,NewH,NewBacc);
-
-complete1([{octets,Bin}|T],Acc,[]) ->
- complete1(T,[Acc|Bin],[]);
-
-complete1([{octets,Bin}|T],Acc,Bacc) ->
- complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
-
-complete1([{debug,_}|T], Acc,Bacc) ->
- complete1(T,Acc,Bacc);
-
-complete1([{bits,N,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,N));
-
-complete1([{bit,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,1));
-
-complete1([align|T],Acc,[]) ->
- complete1(T,Acc,[]);
-complete1([align|T],Acc,Bacc) ->
- complete1(T,[Acc|complete_bytes(Bacc)],[]);
-complete1([{0,Bin}|T],Acc,[]) when is_binary(Bin) ->
- complete1(T,[Acc|Bin],[]);
-complete1([{Unused,Bin}|T],Acc,[]) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8-Unused,
- complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
-complete1([{Unused,Bin}|T],Acc,Bacc) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8 - Unused,
- Bf = complete_bytes(Bacc),
- complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
-
-
-complete_update_byte([],Val,Len) ->
- complete_update_byte([[0]|0],Val,Len);
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
- [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
- Rem = 8 - NumBits,
- Rest = Len - Rem,
- complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
- [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
-
-
-complete_bytes([[_Byte|Bacc]|0]) ->
- lists:reverse(Bacc);
-complete_bytes([[Byte|Bacc]|NumBytes]) ->
- lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
-complete_bytes([]) ->
- [].
-
-% complete_bytes(L) ->
-% complete_bytes1(lists:reverse(L),[],[],0,0).
-
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when ((NumBits+B) rem 8) == 0 ->
-% NewReplyAcc = [complete_bytes2([H|Acc],0)|ReplyAcc],
-% complete_bytes1(T,[],NewReplyAcc,0,0);
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when NumFields == 7; (NumBits+B) div 8 > 0 ->
-% Rem = (NumBits+B) rem 8,
-% NewReplyAcc = [complete_bytes2([{V bsr Rem,B - Rem}|Acc],0)|ReplyAcc],
-% complete_bytes1([{V,Rem}|T],[],NewReplyAcc,0,0);
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) ->
-% complete_bytes1(T,[H|Acc],ReplyAcc,NumBits+B,NumFields+1);
-% complete_bytes1([],[],ReplyAcc,_,_) ->
-% lists:reverse(ReplyAcc);
-% complete_bytes1([],Acc,ReplyAcc,NumBits,_) ->
-% PadBits = case NumBits rem 8 of
-% 0 -> 0;
-% Rem -> 8 - Rem
-% end,
-% lists:reverse([complete_bytes2(Acc,PadBits)|ReplyAcc]).
-
-
-% complete_bytes2([{V1,B1}],PadBits) ->
-% <<V1:B1,0:PadBits>>;
-% complete_bytes2([{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,0:PadBits>>;
-% complete_bytes2([{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,0:PadBits>>;
-% complete_bytes2([{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,0:PadBits>>;
-% complete_bytes2([{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,0:PadBits>>;
-% complete_bytes2([{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,0:PadBits>>;
-% complete_bytes2([{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,0:PadBits>>;
-% complete_bytes2([{V8,B8},{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,V8:B8,0:PadBits>>.
-
-
-
-
-
-
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
deleted file mode 100644
index 9ce5b086cd..0000000000
--- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
+++ /dev/null
@@ -1,1781 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2012. 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%
-%%
-%%
--module(asn1rt_per_bin_rt2ct).
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/3, fixextensions/2,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/2, getoptionals2/2,
- set_choice/3, encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_small_number/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
--export([decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- encode_real/1, decode_real/1,
- encode_relative_oid/1, decode_relative_oid/1,
- complete/1]).
-
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1,
- encode_UTF8String/1,decode_UTF8String/1
- ]).
-
--export([decode_constrained_number/2,
- decode_constrained_number/3,
- decode_unconstrained_number/1,
- decode_semi_constrained_number/2,
- encode_unconstrained_number/1,
- decode_constrained_number/4,
- encode_octet_string/3,
- decode_octet_string/3,
- encode_known_multiplier_string/5,
- decode_known_multiplier_string/5,
- getoctets/2, getbits/2
-% start_drv/1,start_drv2/1,init_drv/1
- ]).
-
-
--export([eint_positive/1]).
--export([pre_complete_bits/2]).
-
--define('16K',16384).
--define('32K',32768).
--define('64K',65536).
-
-%%-define(nodriver,true).
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%% converts a list to a record if necessary
-list_to_record(_,Tuple) when is_tuple(Tuple) ->
- Tuple;
-list_to_record(Name,List) when is_list(List) ->
- list_to_tuple([Name|List]).
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
- [0];
-setchoiceext(false) ->
- [1].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(false) ->
-% [{debug,ext},{bits,1,0}];
- [0];
-setext(true) ->
-% [{debug,ext},{bits,1,1}];
- [1].
-
-fixoptionals(OptList,_OptLength,Val) when is_tuple(Val) ->
-% Bits = fixoptionals(OptList,Val,0),
-% {Val,{bits,OptLength,Bits}};
-% {Val,[10,OptLength,Bits]};
- {Val,fixoptionals(OptList,Val,[])};
-
-fixoptionals([],_,Acc) ->
- %% Optbits
- lists:reverse(Acc);
-fixoptionals([{Pos,DefVal}|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
- DefVal -> fixoptionals(Ot,Val,[0|Acc]);
- _ -> fixoptionals(Ot,Val,[1|Acc])
- end;
-fixoptionals([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
- _ -> fixoptionals(Ot,Val,[1|Acc])
- end.
-
-
-getext(Bytes) when is_bitstring(Bytes) ->
- getbit(Bytes).
-
-getextension(0, Bytes) ->
- {<<>>,Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- getbits_as_binary(Len,Bytes2).% {Bin,Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),pre_complete_bits(ExtNum,ExtBits)]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
- Prev = Nr - 1,
- case ExtensionBitstr of
- <<_:Prev,1:1,_/bitstring>> ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitstr);
- <<_:Prev,0:1,_/bitstring>> ->
- skipextensions(Bytes, Nr+1, ExtensionBitstr);
- _ ->
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_constrained_number(Bytes,{0,NumChoices-1}).
-
-%% old version kept for backward compatibility with generates from R7B01
-getoptionals(Bytes,NumOpt) ->
- getbits_as_binary(NumOpt,Bytes).
-
-%% new version used in generates from r8b_patch/3 and later
-getoptionals2(Bytes,NumOpt) ->
- {_,_} = getbits(Bytes,NumOpt).
-
-
-%% getbits_as_binary(Num,Bytes) -> {Bin,Rest}
-%% Num = integer(),
-%% Bytes = bitstring(),
-%% Bin = bitstring(),
-%% Rest = bitstring()
-getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) ->
- <<BS:Num/bitstring,Rest/bitstring>> = Bytes,
- {BS,Rest}.
-
-getbits_as_list(Num,Bytes) when is_bitstring(Bytes) ->
- <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes,
- {[ B || <<B:1>> <= BitStr],Rest}.
-
-
-getbit(Buffer) ->
- <<B:1,Rest/bitstring>> = Buffer,
- {B,Rest}.
-
-
-getbits(Buffer,Num) when is_bitstring(Buffer) ->
- <<Bs:Num,Rest/bitstring>> = Buffer,
- {Bs,Rest}.
-
-align(Bin) when is_binary(Bin) ->
- Bin;
-align(BitStr) when is_bitstring(BitStr) ->
- AlignBits = bit_size(BitStr) rem 8,
- <<_:AlignBits,Rest/binary>> = BitStr,
- Rest.
-
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as an integer with bit significance as in buffer.
-getoctets(Buffer,Num) when is_binary(Buffer) ->
- <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
- {Val,RestBin};
-getoctets(Buffer,Num) when is_bitstring(Buffer) ->
- AlignBits = bit_size(Buffer) rem 8,
- <<_:AlignBits,Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
- {Val,RestBin}.
-
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as a binary
-getoctets_as_bin(Bin,Num) when is_binary(Bin) ->
- <<Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,RestBin};
-getoctets_as_bin(Bin,Num) when is_bitstring(Bin) ->
- AlignBits = bit_size(Bin) rem 8,
- <<_:AlignBits,Val:Num/binary,RestBin/binary>> = Bin,
- {Val,RestBin}.
-
-
-%% same as above but returns octets as a List
-getoctets_as_list(Buffer,Num) ->
- {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
- {binary_to_list(Bin),Buffer2}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when is_integer(N), Len1 > 1 ->
-% [{bits,1,0}, % the value is in the root set
-% encode_constrained_number({0,Len1-1},N)];
- [0, % the value is in the root set
- encode_constrained_number({0,Len1-1},N)];
- N when is_integer(N) ->
-% [{bits,1,0}]; % no encoding if only 0 or 1 alternative
- [0]; % no encoding if only 0 or 1 alternative
- false ->
-% [{bits,1,1}, % extension value
- [1, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when is_integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when is_integer(N), Len > 1 ->
- encode_constrained_number({0,Len-1},N);
- N when is_integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_fragmented_XXX; decode of values encoded fragmented according
-%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
-%% characters or number of components (in a choice,sequence or similar).
-%% Buffer is a buffer binary().
-%% C is the constrained length.
-%% If the buffer is not aligned, this function does that.
-decode_fragmented_bits(Buffer,C) when is_binary(Buffer) ->
- decode_fragmented_bits(Buffer,C,[]);
-decode_fragmented_bits(Buffer,C) when is_bitstring(Buffer) ->
- AlignBits = bit_size(Buffer) rem 8,
- <<_:AlignBits,Rest/binary>> = Buffer,
- decode_fragmented_bits(Rest,C,[]).
-
-decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin, Len * ?'16K'), % Len = 1 | 2 | 3 | 4
- decode_fragmented_bits(Bin2,C,[Value|Acc]);
-decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- BinBits = erlang:list_to_bitstring(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int),C == bit_size(BinBits) ->
- {BinBits,Bin};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}})
- end;
-decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- <<Value:Len/bitstring,Rest/bitstring>> = Bin,
- BinBits = erlang:list_to_bitstring([Value|Acc]),
- case C of
- Int when is_integer(Int),C == bit_size(BinBits) ->
- {BinBits,Rest};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}})
- end.
-
-
-decode_fragmented_octets(Bin,C) ->
- decode_fragmented_octets(Bin,C,[]).
-
-decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
- decode_fragmented_octets(Bin2,C,[Value|Acc]);
-decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- Octets = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int), C == size(Octets) ->
- {Octets,Bin};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,Octets}}})
- end;
-decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
- BinOctets = list_to_binary(lists:reverse([Value|Acc])),
- case C of
- Int when is_integer(Int),size(BinOctets) == Int ->
- {BinOctets,Bin2};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinOctets}}})
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when is_list(Val) ->
- encode_open_type_1(list_to_binary(Val));
-encode_open_type(_Constraint, Val) when is_binary(Val) ->
- encode_open_type_1(Val).
-
-encode_open_type_1(Val) ->
- case byte_size(Val) of
- Size when Size < 256 ->
- [encode_length(undefined, Size),20,Size,Val];
- Size when Size < 16384 ->
- [encode_length(undefined, Size),21,<<Size:16>>,Val];
- Size ->
- encode_fragmented(Val, Size)
- end.
-
-encode_fragmented(Val0, Size) ->
- case Size bsr 14 of
- F when F >= 4 ->
- <<Val1:16#8000/binary,Val2:16#8000/binary,T/binary>> = Val0,
- [20,1,16#C4,<<21,16#8000:16>>,Val1,
- <<21,16#8000:16>>,Val2|encode_open_type_1(T)];
- F ->
- SegSz = F * ?'16K',
- <<Val:SegSz/binary,T/binary>> = Val0,
- [<<20,1,3:2,F:6,21,SegSz:16>>,Val|encode_open_type_1(T)]
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- decode_open_type_1(Bytes, []).
-
-decode_open_type_1(Bytes0, Acc) ->
- case decode_length_unlimited(Bytes0) of
- {Len,Bytes} when Len < ?'16K', Acc =:= [] ->
- getoctets_as_bin(Bytes, Len);
- {Len,Bytes1} when Len < ?'16K' ->
- {Bin,Bytes} = getoctets_as_bin(Bytes1, Len),
- {iolist_to_binary([Acc,Bin]),Bytes};
- {Len,Bytes1} ->
- <<Bin:Len/binary,Bytes/binary>> = Bytes1,
- decode_open_type_1(Bytes, [Acc,Bin])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when is_atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when is_integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when is_atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when is_atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer([{Rc,_Ec}],Val) when is_tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
- case (catch encode_integer([Rc],Val)) of
- {'EXIT',{error,{asn1,_}}} ->
-% [{bits,1,1},encode_unconstrained_number(Val)];
- [1,encode_unconstrained_number(Val)];
- Encoded ->
-% [{bits,1,0},Encoded]
- [0,Encoded]
- end;
-
-encode_integer([],Val) ->
- encode_unconstrained_number(Val);
-%% The constraint is the effective constraint, and in this case is a number
-encode_integer([{'SingleValue',V}],V) ->
- [];
-encode_integer([{'ValueRange',VR={Lb,Ub},Range,PreEnc}],Val) when Val >= Lb,
- Ub >= Val ->
- %% this case when NamedNumberList
- encode_constrained_number(VR,Range,PreEnc,Val);
-encode_integer([{'ValueRange',{Lb,'MAX'}}],Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_integer([{'ValueRange',{'MIN',_}}],Val) ->
- encode_unconstrained_number(Val);
-encode_integer([{'ValueRange',VR={_Lb,_Ub}}],Val) ->
- encode_constrained_number(VR,Val);
-encode_integer(_,Val) ->
- exit({error,{asn1,{illegal_value,Val}}}).
-
-
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,[{Rc,_Ec}]) when is_tuple(Rc) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,[Rc]);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when is_integer(V) ->
- {V,Buffer};
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_Lb,_Ub} ->
- decode_constrained_number(Buffer,VR)
- end.
-
-%% X.691:10.6 Encoding of a normally small non-negative whole number
-%% Use this for encoding of CHOICE index if there is an extension marker in
-%% the CHOICE
-encode_small_number({Name,Val}) when is_atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
-% [{bits,1,0},{bits,6,Val}];
-% [{bits,7,Val}]; % same as above but more efficient
- [10,7,Val]; % same as above but more efficient
-encode_small_number(Val) ->
-% [{bits,1,1},encode_semi_constrained_number(0,Val)].
- [1,encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,0)
- end.
-
-%% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when is_atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Oct = eint_positive(Val2),
- Len = length(Oct),
- if
- Len < 128 ->
- %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];
- Len < 256 ->
- [encode_length(undefined,Len),[20,Len,Oct]];
- true ->
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end.
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number({Lb,_Ub},_Range,{bits,N},Val) ->
- Val2 = Val-Lb,
-% {bits,N,Val2};
- [10,N,Val2];
-encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) when N < 256->
- %% N is 8 or 16 (1 or 2 octets)
- Val2 = Val-Lb,
-% {octets,<<Val2:N/unit:8>>};
- [20,N,Val2];
-encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) -> % N>255
- %% N is 8 or 16 (1 or 2 octets)
- Val2 = Val-Lb,
-% {octets,<<Val2:N/unit:8>>};
- [21,<<N:16>>,Val2];
-encode_constrained_number({Lb,_Ub},Range,_,Val) ->
- Val2 = Val-Lb,
- if
- Range =< 16#1000000 -> % max 3 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,3},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,3},L),[20,L,Octs]];
- Range =< 16#100000000 -> % max 4 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,4},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,4},L),[20,L,Octs]];
- Range =< 16#10000000000 -> % max 5 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,5},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,5},L),[20,L,Octs]];
- true ->
- exit({not_supported,{integer_range,Range}})
- end.
-
-encode_constrained_number(Range,{Name,Val}) when is_atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 1 -> [];
- Range == 2 ->
-% Size = {bits,1,Val2};
- [Val2];
- Range =< 4 ->
-% Size = {bits,2,Val2};
- [10,2,Val2];
- Range =< 8 ->
- [10,3,Val2];
- Range =< 16 ->
- [10,4,Val2];
- Range =< 32 ->
- [10,5,Val2];
- Range =< 64 ->
- [10,6,Val2];
- Range =< 128 ->
- [10,7,Val2];
- Range =< 255 ->
- [10,8,Val2];
- Range =< 256 ->
-% Size = {octets,[Val2]};
- [20,1,Val2];
- Range =< 65536 ->
-% Size = {octets,<<Val2:16>>};
- [20,2,<<Val2:16>>];
- Range =< (1 bsl (255*8)) ->
- Octs = binary:encode_unsigned(Val2),
- RangeOcts = binary:encode_unsigned(Range - 1),
- OctsLen = erlang:byte_size(Octs),
- RangeOctsLen = erlang:byte_size(RangeOcts),
- LengthBitsNeeded = asn1rt_per_bin:minimum_bits(RangeOctsLen - 1),
- [10,LengthBitsNeeded,OctsLen-1,20,OctsLen,Octs];
- true ->
- exit({not_supported,{integer_range,Range}})
- end;
-encode_constrained_number({_,_},Val) ->
- exit({error,{asn1,{illegal_value,Val}}}).
-
-decode_constrained_number(Buffer,VR={Lb,Ub}) ->
- Range = Ub - Lb + 1,
- decode_constrained_number(Buffer,VR,Range).
-
-decode_constrained_number(Buffer,{Lb,_Ub},_Range,{bits,N}) ->
- {Val,Remain} = getbits(Buffer,N),
- {Val+Lb,Remain};
-decode_constrained_number(Buffer,{Lb,_Ub},_Range,{octets,N}) ->
- {Val,Remain} = getoctets(Buffer,N),
- {Val+Lb,Remain}.
-
-decode_constrained_number(Buffer,{Lb,_Ub},Range) ->
- % Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 1 ->
- {0,Buffer};
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< (1 bsl (255*8)) ->
- OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)),
- RangeOctLen = length(OList),
- {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}),
- {Octs, RestBytes} = getoctets_as_bin(Bytes, Len),
- {binary:decode_unsigned(Octs), RestBytes};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-%% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];
- Len < 256 ->
-% [encode_length(undefined,Len),20,Len,Oct];
- [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
- true ->
-% [encode_length(undefined,Len),{octets,Oct}]
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end;
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
-% {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];% equiv with encode_length(undefined,Len) but faster
- Len < 256 ->
-% [encode_length(undefined,Len),20,Len,Oct];
- [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
- true ->
- %[encode_length(undefined,Len),{octets,Oct}]
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end.
-
-
-%% used for positive Values which don't need a sign bit
-%% returns a list
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_bin(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_integer(Bin = <<0:1,_:7,_/binary>>) ->
- decpint(Bin);
-dec_integer(<<_:1,B:7,BitStr/bitstring>>) ->
- Size = bit_size(BitStr),
- <<I:Size>> = BitStr,
- (-128 + B) bsl bit_size(BitStr) bor I.
-
-decpint(Bin) ->
- Size = bit_size(Bin),
- <<Int:Size>> = Bin,
- Int.
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
-% {octets,[Len]};
- [20,1,Len];
- Len < 16384 ->
- %{octets,<<2:2,Len:14>>};
- [20,2,<<2:2,Len:14>>];
- true -> % should be able to endode length >= 16384 i.e. fragmented length
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number(Vr,Len);
-encode_length({Lb,_Ub},Len) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- encode_length(undefined,Len);
-encode_length({Vr={Lb,Ub},Ext},Len)
- when Ub =< 65535 ,Lb >= 0,Len=<Ub, is_list(Ext) ->
- %% constrained extensible
- [0,encode_constrained_number(Vr,Len)];
-encode_length({{Lb,_},Ext},Len) when is_list(Ext) ->
- [1,encode_semi_constrained_number(Lb,Len)];
-encode_length(SingleValue,_Len) when is_integer(SingleValue) ->
- [].
-
-%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
-%% additions in a sequence or set
-encode_small_length(Len) when Len =< 64 ->
-%% [{bits,1,0},{bits,6,Len-1}];
-% {bits,7,Len-1}; % the same as above but more efficient
- [10,7,Len-1];
-encode_small_length(Len) ->
-% [{bits,1,1},encode_length(undefined,Len)].
- [1,encode_length(undefined,Len)].
-
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length_unlimited(Buffer) ->
- case align(Buffer) of
- <<0:1,Oct:7,Rest/binary>> ->
- {Oct,Rest};
- <<1:1,0:1,Val:14,Rest/binary>> ->
- {Val,Rest};
- <<1:1,1:1,F:6,Rest/binary>> ->
- SegSz = F * ?'16K',
- {SegSz,Rest}
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- case align(Buffer) of
- <<0:1,Oct:7,Rest/binary>> ->
- {Oct,Rest};
- <<2:2,Val:14,Rest/binary>> ->
- {Val,Rest};
- <<3:2,_Val:14,_Rest/binary>> ->
- %% this case should be fixed
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
- end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-decode_length(Buffer,{Lb,_Ub}) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- decode_length(Buffer,undefined);
-decode_length(Buffer,{{Lb,Ub},Ext}) when is_list(Ext) ->
- case getbit(Buffer) of
- {0,Buffer2} ->
- decode_length(Buffer2, {Lb,Ub});
- {1,Buffer2} ->
- decode_length(Buffer2, undefined)
- end;
-
-
-%When does this case occur with {_,_Lb,Ub} ??
-% X.691:10.9.3.5
-decode_length(Bin,{_,_Lb,_Ub}) -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
- case Bin of
- <<0:1,Val:7,Rest/bitstring>> ->
- {Val,Rest};
- _ ->
- case align(Bin) of
- <<2:2,Val:14,Rest/binary>> ->
- {Val,Rest};
- <<3:2,_:14,_Rest/binary>> ->
- exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
- end
- end;
-decode_length(Buffer,SingleValue) when is_integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
- % X.691:11
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when is_tuple(Ntup1), is_tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when is_tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% 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 constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when is_integer(Unused),
- is_binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList);
-
-%% when the value is a list of named bits
-
-encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when is_atom(FirstVal) ->
- ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);% consider the constraint
-
-encode_bit_string(C, BL=[{bit,_} | _RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes(BL, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-encode_bit_string(Int, BitListValue, _)
- when is_list(BitListValue),is_integer(Int),Int =< 16 ->
- %% The type is constrained by a single value size constraint
- %% range_check(Int,length(BitListValue)),
- [40,Int,length(BitListValue),BitListValue];
-encode_bit_string(Int, BitListValue, _)
- when is_list(BitListValue),is_integer(Int), Int =< 255 ->
- %% The type is constrained by a single value size constraint
- %% range_check(Int,length(BitListValue)),
- [2,40,Int,length(BitListValue),BitListValue];
-encode_bit_string(Int, BitListValue, _)
- when is_list(BitListValue),is_integer(Int), Int < ?'64K' ->
- {Code,DesiredLength,Length} =
- case length(BitListValue) of
- B1 when B1 > Int ->
- exit({error,{'BIT_STRING_length_greater_than_SIZE',
- Int,BitListValue}});
- B1 when B1 =< 255,Int =< 255 ->
- {40,Int,B1};
- B1 when B1 =< 255 ->
- {42,<<Int:16>>,B1};
- B1 ->
- {43,<<Int:16>>,<<B1:16>>}
- end,
- %% The type is constrained by a single value size constraint
- [2,Code,DesiredLength,Length,BitListValue];
-encode_bit_string(no, BitListValue,[])
- when is_list(BitListValue) ->
- [encode_length(undefined,length(BitListValue)),
- 2,BitListValue];
-encode_bit_string({{Fix,Fix},Ext}, BitListValue,[])
- when is_integer(Fix), is_list(Ext) ->
- case length(BitListValue) of
- Len when Len =< Fix ->
- [0,encode_bit_string(Fix,BitListValue,[])];
- _ ->
- [1,encode_bit_string(no,BitListValue,[])]
- end;
-encode_bit_string(C, BitListValue,[])
- when is_list(BitListValue) ->
- [encode_length(C,length(BitListValue)),
- 2,BitListValue];
-encode_bit_string(no, BitListValue,_NamedBitList)
- when is_list(BitListValue) ->
- %% this case with an unconstrained BIT STRING can be made more efficient
- %% if the complete driver can take a special code so the length field
- %% is encoded there.
- NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitListValue))),
- [encode_length(undefined,length(NewBitLVal)),
- 2,NewBitLVal];
-encode_bit_string({{Fix,Fix},Ext}, BitListValue,_NamedBitList)
- when is_integer(Fix), is_list(Ext) ->
- case length(BitListValue) of
- Len when Len =< Fix ->
- [0,encode_bit_string(Fix,BitListValue,_NamedBitList)];
- _ ->
- [1,encode_bit_string(no,BitListValue,_NamedBitList)]
- end;
-encode_bit_string(C,BitListValue,_NamedBitList)
- when is_list(BitListValue) ->% C = {_,'MAX'}
-% NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
-% lists:reverse(BitListValue))),
- NewBitLVal = bit_string_trailing_zeros(BitListValue,C),
- [encode_length(C,length(NewBitLVal)),
- 2,NewBitLVal];
-
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) when is_integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string(C,{Name,Val}, NamedBitList) when is_atom(Name) ->
- encode_bit_string(C,Val,NamedBitList).
-
-bit_string_trailing_zeros(BitList,C) when is_integer(C) ->
- bit_string_trailing_zeros1(BitList,C,C);
-bit_string_trailing_zeros(BitList,{Lb,Ub}) when is_integer(Lb) ->
- bit_string_trailing_zeros1(BitList,Lb,Ub);
-bit_string_trailing_zeros(BitList,{{Lb,Ub},_}) when is_integer(Lb) ->
- bit_string_trailing_zeros1(BitList,Lb,Ub);
-bit_string_trailing_zeros(BitList,_) ->
- BitList.
-
-bit_string_trailing_zeros1(BitList,Lb,Ub) ->
- case length(BitList) of
- Lb -> BitList;
- B when B<Lb -> BitList++lists:duplicate(Lb-B,0);
- D -> F = fun(L,LB,LB,_,_)->lists:reverse(L);
- ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
- (L,L1,_,UB,_)when L1 =< UB -> lists:reverse(L);
- (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
- BitList}}) end,
- F(lists:reverse(BitList),D,Lb,Ub,F)
- end.
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),i.e. number unused bits in least sign. byte of
-%% BinBits = binary().
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList)
- when is_integer(C),C=<16 ->
- range_check(C,bit_size(BinBits) - Unused),
- [45,C,size(BinBits),BinBits];
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList)
- when is_integer(C), C =< 255 ->
- range_check(C,bit_size(BinBits) - Unused),
- [2,45,C,size(BinBits),BinBits];
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList)
- when is_integer(C), C =< 65535 ->
- range_check(C,bit_size(BinBits) - Unused),
- case size(BinBits) of
- Size when Size =< 255 ->
- [2,46,<<C:16>>,Size,BinBits];
- Size ->
- [2,47,<<C:16>>,<<Size:16>>,BinBits]
- end;
-%% encode_bin_bit_string(C,{_Unused,BinBits},_NamedBitList)
-%% when is_integer(C) ->
-%% exit({error,{asn1, {bitstring_size, not_supported, C}}});
-encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
-% UnusedAndBin1 = {Unused1,Bin1} =
- {Unused1,Bin1} =
- %% removes all trailing bits if NamedBitList is not empty
- remove_trailing_bin(NamedBitList,UnusedAndBin),
- case C of
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
-% [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
-% align,UnusedAndBin1];
- Size=size(Bin1),
- [encode_length({Lb,Ub},Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)];
- no ->
- Size=size(Bin1),
- [encode_length(undefined,Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)];
- {{Fix,Fix},Ext} when is_integer(Fix),is_list(Ext) ->
- %%[encode_length(Sc,size(Bin1)*8 - Unused1),
- case size(Bin1)*8 - Unused1 of
- Size when Size =< Fix ->
- [0,encode_bin_bit_string(Fix,UnusedAndBin,NamedBitList)];
- _Size ->
- [1,encode_bin_bit_string(no,UnusedAndBin,NamedBitList)]
- end;
- Sc ->
- Size=size(Bin1),
- [encode_length(Sc,Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)]
- end.
-
-range_check(C,C) when is_integer(C) ->
- ok;
-range_check(C1,C2) when is_integer(C1) ->
- exit({error,{asn1,{bit_string_out_of_range,{C1,C2}}}}).
-
-remove_trailing_bin([], {Unused,Bin}) ->
- {Unused,Bin};
-remove_trailing_bin(_NamedNumberList,{_Unused,<<>>}) ->
- {0,<<>>};
-remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
- Size = size(Bin)-1,
- <<Bfront:Size/binary, LastByte:8>> = Bin,
- %% clear the Unused bits to be sure
-% LastByte1 = LastByte band (((1 bsl Unused) -1) bxor 255),% why this???
- Unused1 = trailingZeroesInNibble(LastByte band 15),
- Unused2 =
- case Unused1 of
- 4 ->
- 4 + trailingZeroesInNibble(LastByte bsr 4);
- _ -> Unused1
- end,
- case Unused2 of
- 8 ->
- remove_trailing_bin(NamedNumberList,{0,Bfront});
- _ ->
- {Unused2,Bin}
- end.
-
-
-trailingZeroesInNibble(0) ->
- 4;
-trailingZeroesInNibble(1) ->
- 0;
-trailingZeroesInNibble(2) ->
- 1;
-trailingZeroesInNibble(3) ->
- 0;
-trailingZeroesInNibble(4) ->
- 2;
-trailingZeroesInNibble(5) ->
- 0;
-trailingZeroesInNibble(6) ->
- 1;
-trailingZeroesInNibble(7) ->
- 0;
-trailingZeroesInNibble(8) ->
- 3;
-trailingZeroesInNibble(9) ->
- 0;
-trailingZeroesInNibble(10) ->
- 1;
-trailingZeroesInNibble(11) ->
- 0;
-trailingZeroesInNibble(12) -> %#1100
- 2;
-trailingZeroesInNibble(13) ->
- 0;
-trailingZeroesInNibble(14) ->
- 1;
-trailingZeroesInNibble(15) ->
- 0.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{8,0},Buffer};
- V when is_integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 -> %fixed length > 16 bits
- Bytes2 = align(Buffer),
- compact_bit_string(Bytes2,V,NamedNumberList);
- V when is_integer(V) -> % V > 65536 => fragmented value
- {BitStr,Buffer2} = decode_fragmented_bits(Buffer,V),
- case bit_size(BitStr) band 7 of
- 0 -> {{0,BitStr},Buffer2};
- N -> {{8-N,<<BitStr/bitstring,0:(8-N)>>},Buffer2}
- end;
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- no ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- {{Fix,Fix},Ext} = Sc when is_integer(Fix), is_list(Ext) ->
- case decode_length(Buffer,Sc) of
- {Len,Bytes2} when Len > Fix ->
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} when Len > 16 ->
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} ->
- compact_bit_string(Bytes2,Len,NamedNumberList)
- end;
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when is_integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 ->
- Bytes2 = align(Buffer),
- bit_list_or_named(Bytes2,V,NamedNumberList);
- V when is_integer(V) ->
- Bytes2 = align(Buffer),
- {BinBits,_Bytes3} = decode_fragmented_bits(Bytes2,V),
- bit_list_or_named(BinBits,V,NamedNumberList);
- {{Fix,Fix},Ext} =Sc when is_integer(Fix), is_list(Ext) ->
- case decode_length(Buffer,Sc) of
- {Len,Bytes2} when Len > Fix ->
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} when Len > 16 ->
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- {Len,Bytes2} ->
- bit_list_or_named(Bytes2,Len,NamedNumberList)
- end;
- Sc -> % extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- {BitStr,Rest} = getbits_as_binary(Len,Buffer), % {{Unused,BinBits},NewBuffer}
- PadLen = (8 - (bit_size(BitStr) rem 8)) rem 8,
- {{PadLen,<<BitStr/bitstring,0:PadLen>>},Rest};
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_or_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_or_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_or_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_or_named1(Pos+1,Bt,Names,Acc);
-bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_or_named1(_Pos,[],_Names,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(Int) when is_integer(Int), Int > 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)];
-int_to_bitlist(0) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,Val) ->
- encode_octet_string(C,false,Val).
-
-encode_octet_string(C,Bool,{_Name,Val}) ->
- encode_octet_string(C,Bool,Val);
-encode_octet_string(_C,true,_Val) ->
- exit({error,{asn1,{'not_supported',extensionmarker}}});
-encode_octet_string(SZ={_,_},false,Val) ->
-% [encode_length(SZ,length(Val)),align,
-% {octets,Val}];
- Len = length(Val),
- [encode_length(SZ,Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(SZ,false,Val) when is_list(SZ) ->
- Len = length(Val),
- [encode_length({hd(SZ),lists:max(SZ)},Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(no,false,Val) ->
- Len = length(Val),
- [encode_length(undefined,Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(C,_,_) ->
- exit({error,{not_implemented,C}}).
-
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(<<B1,Bytes/bitstring>>,1,false) ->
-%% {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes};
-decode_octet_string(<<B1,B2,Bytes/bitstring>>,2,false) ->
-%% {Bs,Bytes2}= getbits(Bytes,16),
-%% {binary_to_list(<<Bs:16>>),Bytes2};
- {[B1,B2],Bytes};
-decode_octet_string(Bytes,Sv,false) when is_integer(Sv),Sv=<65535 ->
- %% Bytes2 = align(Bytes),
- %% getoctets_as_list aligns buffer before it picks octets
- getoctets_as_list(Bytes,Sv);
-decode_octet_string(Bytes,Sv,false) when is_integer(Sv) ->
- Bytes2 = align(Bytes),
- decode_fragmented_octets(Bytes2,Sv);
-decode_octet_string(Bytes,{Lb,Ub},false) ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
-%% Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes2,Len);
-decode_octet_string(Bytes,Sv,false) when is_list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
-%% Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes2,Len);
-decode_octet_string(Bytes,no,false) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
-%% Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes2,Len).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string(aligned,{Name,Val}) when is_atom(Name) ->
- encode_restricted_string(aligned,Val);
-
-encode_restricted_string(aligned,Val) when is_list(Val)->
- Len = length(Val),
- [encode_length(undefined,Len),octets_to_complete(Len,Val)].
-
-
-encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,{Name,Val}) when is_atom(Name) ->
- encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,Val);
-encode_known_multiplier_string(_StringType,SizeC,NumBits,CharOutTab,Val) ->
- Result = chars_encode2(Val,NumBits,CharOutTab),
- case SizeC of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- Result;
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- [2,Result];
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),2,Result];
- no ->
- [encode_length(undefined,length(Val)),2,Result]
- end.
-
-decode_restricted_string(Bytes,aligned) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-decode_known_multiplier_string(StringType,SizeC,NumBits,CharInTab,Bytes) ->
- case SizeC of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,CharInTab,Ub);
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,CharInTab,Ub);
- Vl when is_list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len)
- end.
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(<<T/binary>>, 0, Acc) ->
- {lists:reverse(Acc),T};
-getBMPChars(<<0,O2,Bytes1/bitstring>>, Len, Acc) ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
-getBMPChars(<<O1,O2,Bytes1/bitstring>>, Len, Acc) ->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-% chars_encode(C,StringType,Value) ->
-% case {StringType,get_constraint(C,'PermittedAlphabet')} of
-% {'UniversalString',{_,Sv}} ->
-% exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
-% {'BMPString',{_,Sv}} ->
-% exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
-% _ ->
-% {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
-% chars_encode2(Value,NumBits,CharOutTab)
-% end.
-
-
-chars_encode2([H|T],NumBits,T1={Min,Max,notab}) when H =< Max, H >= Min ->
-% [[10,NumBits,H-Min]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,H-Min)|chars_encode2(T,NumBits,T1)];
-chars_encode2([H|T],NumBits,T1={Min,Max,Tab}) when H =< Max, H >= Min ->
-% [[10,NumBits,element(H-Min+1,Tab)]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,exit_if_false(H,element(H-Min+1,Tab)))|
- chars_encode2(T,NumBits,T1)];
-chars_encode2([{A,B,C,D}|T],NumBits,T1={Min,_Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-% [[10,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,
- ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min)|
- chars_encode2(T,NumBits,T1)];
-chars_encode2([H={A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
- [pre_complete_bits(NumBits,exit_if_false(H,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)))|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-exit_if_false(V,false)->
- exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
-exit_if_false(_,V) ->V.
-
-pre_complete_bits(NumBits,Val) when NumBits =< 8 ->
- [10,NumBits,Val];
-pre_complete_bits(NumBits,Val) when NumBits =< 16 ->
- [10,NumBits-8,Val bsr 8,10,8,(Val band 255)];
-pre_complete_bits(NumBits,Val) when NumBits =< 2040 -> % 255 * 8
-% LBUsed = NumBits rem 8,
-% {Unused,Len} = case (8 - LBUsed) of
-% 8 -> {0,NumBits div 8};
-% U -> {U,(NumBits div 8) + 1}
-% end,
-% NewVal = Val bsr LBUsed,
-% [30,Unused,Len,<<NewVal:Len/unit:8,Val:LBUsed,0:Unused>>].
- Unused = (8 - (NumBits rem 8)) rem 8,
- Len = NumBits + Unused,
- [30,Unused,Len div 8,<<(Val bsl Unused):Len>>].
-
-
-chars_decode(Bytes,_,'BMPString',_,Len) ->
- getBMPChars(Bytes,Len,[]);
-chars_decode(Bytes,NumBits,_StringType,CharInTab,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result =
- if
- Char < 256 -> Char;
- true ->
- list_to_tuple(binary_to_list(<<Char:32>>))
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
- % X.691:17
-encode_null(_Val) -> []. % encodes to nothing
-%encode_null({Name,Val}) when is_atom(Name) ->
-% encode_null(Val).
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_UTF8String(Val) -> CompleteList
-%% Val -> <<utf8encoded binary>>
-%% CompleteList -> [apropriate codes and values for driver complete]
-%%
-encode_UTF8String(Val) when is_binary(Val) ->
- [encode_length(undefined,size(Val)),
- octets_to_complete(size(Val),Val)];
-encode_UTF8String(Val) ->
- encode_UTF8String(list_to_binary(Val)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_UTF8String(Bytes) -> {Utf8Binary,RemainingBytes}
-%% Utf8Binary -> <<utf8 encoded binary>>
-%% RemainingBytes -> <<buffer>>
-decode_UTF8String(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {_Bin,_Bytes3} = getoctets_as_bin(Bytes2,Len).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier({Name,Val}) when is_atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- OctetList = e_object_identifier(Val),
- Octets = list_to_binary(OctetList),
- [encode_length(undefined,size(Octets)),
- octets_to_complete(size(Octets),Octets)].
-
-e_object_identifier({'OBJECT IDENTIFIER',V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname,V}) when is_atom(Cname),is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname,V}) when is_atom(Cname),is_list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
- Head = 40*E1 + E2, % weird
- e_object_elements([Head|Tail],[]);
-e_object_identifier(Oid=[_,_|_Tail]) ->
- exit({error,{asn1,{'illegal_value',Oid}}}).
-
-e_object_elements([],Acc) ->
- lists:reverse(Acc);
-e_object_elements([H|T],Acc) ->
- e_object_elements(T,[e_object_element(H)|Acc]).
-
-e_object_element(Num) when Num < 128 ->
- [Num];
-e_object_element(Num) ->
- [e_o_e(Num bsr 7)|[Num band 2#1111111]].
-e_o_e(Num) when Num < 128 ->
- Num bor 2#10000000;
-e_o_e(Num) ->
- [e_o_e(Num bsr 7)|[(Num band 2#1111111) bor 2#10000000]].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_relative_oid(Val) -> CompleteList
-%% encode_relative_oid({Name,Val}) -> CompleteList
-encode_relative_oid({Name,Val}) when is_atom(Name) ->
- encode_relative_oid(Val);
-encode_relative_oid(Val) when is_tuple(Val) ->
- encode_relative_oid(tuple_to_list(Val));
-encode_relative_oid(Val) when is_list(Val) ->
- Octets = list_to_binary([e_object_element(X)||X <- Val]),
- [encode_length(undefined,size(Octets)),
- octets_to_complete(size(Octets),Octets)].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_relative_oid(Val) -> CompleteList
-%% decode_relative_oid({Name,Val}) -> CompleteList
-decode_relative_oid(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- ObjVals = dec_subidentifiers(Octs,0,[]),
- {list_to_tuple(ObjVals),Bytes3}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_real(Val) -> CompleteList
-%% encode_real({Name,Val}) -> CompleteList
-encode_real({Name,Val}) when is_atom(Name) ->
- encode_real(Val);
-encode_real(Real) ->
- {EncVal,Len} = ?RT_COMMON:encode_real([],Real),
- [encode_length(undefined,Len),octets_to_complete(size(EncVal),EncVal)].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_real(Val) -> {REALvalue,Rest}
-%% decode_real({Name,Val}) -> {REALvalue,Rest}
-decode_real(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {RealVal,Rest,Len} = ?RT_COMMON:decode_real(Bytes2,Len),
- {RealVal,Rest}.
-
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
--ifdef(nodriver).
-
-complete(L) ->
- erlang_complete(L).
-
--else.
-
-%% asn1-1.7
-complete(L) ->
- case asn1rt_nif:encode_per_complete(L) of
- {error, Reason} -> handle_error(Reason, L);
- Else when is_binary(Else) -> Else
- end.
-
-handle_error([],_)->
- exit({error,{asn1,{"memory allocation problem in driver"}}});
-handle_error($1,L) -> % error in complete in driver
- exit({error,{asn1,L}});
-handle_error(ErrL,L) ->
- exit({error,{asn1,ErrL,L}}).
-
--endif.
-
-
-octets_to_complete(Len,Val) when Len < 256 ->
- [20,Len,Val];
-octets_to_complete(Len,Val) ->
- [21,<<Len:16>>,Val].
-
-octets_unused_to_complete(Unused,Len,Val) when Len < 256 ->
- [30,Unused,Len,Val];
-octets_unused_to_complete(Unused,Len,Val) ->
- [31,Unused,<<Len:16>>,Val].
diff --git a/lib/asn1/src/asn1rt_uper_bin.erl b/lib/asn1/src/asn1rt_uper_bin.erl
deleted file mode 100644
index 4e18753a16..0000000000
--- a/lib/asn1/src/asn1rt_uper_bin.erl
+++ /dev/null
@@ -1,1648 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2010. 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%
-%%
-%%
--module(asn1rt_uper_bin).
-
-%% encoding / decoding of PER unaligned
-
--include("asn1_records.hrl").
-
-%%-compile(export_all).
-
- -export([cindex/3, list_to_record/2]).
- -export([setext/1, fixoptionals/3,
- fixextensions/2,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
- -export([getoptionals2/2, set_choice/3, encode_integer/2, encode_integer/3 ]).
- -export([decode_integer/2, decode_integer/3, encode_small_number/1, encode_boolean/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
- -export([decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
- -export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_relative_oid/1, decode_relative_oid/1,
- encode_object_identifier/1, decode_object_identifier/1,
- encode_real/1, decode_real/1,
- complete/1, complete_NFP/1]).
-
-
- -export([encode_open_type/2, decode_open_type/2]).
-
- -export([encode_UniversalString/2, decode_UniversalString/2,
- encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_VisibleString/2, decode_VisibleString/2,
- encode_UTF8String/1, decode_UTF8String/1,
- encode_BMPString/2, decode_BMPString/2,
- encode_IA5String/2, decode_IA5String/2,
- encode_NumericString/2, decode_NumericString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
- ]).
-
--define('16K',16384).
--define('32K',32768).
--define('64K',65536).
-
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%% converts a list to a record if necessary
-list_to_record(_Name,Tuple) when is_tuple(Tuple) ->
- Tuple;
-list_to_record(Name,List) when is_list(List) ->
- list_to_tuple([Name|List]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(false) ->
- <<0:1>>;
-setext(true) ->
- <<1:1>>.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This is the new fixoptionals/3 which is used by the new generates
-%%
-fixoptionals(OptList,OptLength,Val) when is_tuple(Val) ->
- Bits = fixoptionals(OptList,Val,0),
- {Val,<<Bits:OptLength>>};
-
-fixoptionals([],_Val,Acc) ->
- %% Optbits
- Acc;
-fixoptionals([{Pos,DefVal}|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
- DefVal -> fixoptionals(Ot,Val,Acc bsl 1);
- _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- end;
-fixoptionals([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
- asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
- _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- end.
-
-
-getext(Bytes) when is_bitstring(Bytes) ->
- getbit(Bytes).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),<<ExtBits:ExtNum>>]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_constrained_number(Bytes,{0,NumChoices-1}).
-
-
-%%%%%%%%%%%%%%%
-getoptionals2(Bytes,NumOpt) ->
- getbits(Bytes,NumOpt).
-
-
-%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
-%% Num = integer(),
-%% Bytes = list() | tuple(),
-%% Unused = integer(),
-%% BinBits = binary(),
-%% RestBytes = tuple()
-getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) ->
- <<BS:Num/bitstring,Rest/bitstring>> = Bytes,
- {BS,Rest}.
-
-getbits_as_list(Num,Bytes) when is_bitstring(Bytes) ->
- <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes,
- {[ B || <<B:1>> <= BitStr],Rest}.
-
-getbit(Buffer) ->
- <<B:1,Rest/bitstring>> = Buffer,
- {B,Rest}.
-
-
-getbits(Buffer,Num) when is_bitstring(Buffer) ->
- <<Bs:Num,Rest/bitstring>> = Buffer,
- {Bs,Rest}.
-
-
-
-%% Pick the first Num octets.
-%% Returns octets as an integer with bit significance as in buffer.
-getoctets(Buffer,Num) when is_bitstring(Buffer) ->
- <<Val:Num/integer-unit:8,RestBitStr/bitstring>> = Buffer,
- {Val,RestBitStr}.
-
-%% Pick the first Num octets.
-%% Returns octets as a binary
-getoctets_as_bin(Bin,Num) when is_bitstring(Bin) ->
- <<Octets:Num/binary,RestBin/bitstring>> = Bin,
- {Octets,RestBin}.
-
-%% same as above but returns octets as a List
-getoctets_as_list(Buffer,Num) ->
- {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
- {binary_to_list(Bin),Buffer2}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when is_integer(N), Len1 > 1 ->
- [<<0:1>>, % the value is in the root set
- encode_integer([{'ValueRange',{0,Len1-1}}],N)];
- N when is_integer(N) ->
- <<0:1>>; % no encoding if only 0 or 1 alternative
- false ->
- [<<1:1>>, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when is_integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when is_integer(N), Len > 1 ->
- encode_integer([{'ValueRange',{0,Len-1}}],N);
- N when is_integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_fragmented_XXX; decode of values encoded fragmented according
-%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
-%% characters or number of components (in a choice,sequence or similar).
-%% Buffer is a buffer {Used, Bin}.
-%% C is the constrained length.
-%% If the buffer is not aligned, this function does that.
-decode_fragmented_bits(Buffer,C) ->
- decode_fragmented_bits(Buffer,C,[]).
-decode_fragmented_bits(<<3:2,Len:6,BitStr/bitstring>>,C,Acc) ->
-%% {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
- FragLen = (Len*?'16K') div 8,
- <<Value:FragLen/binary,BitStr2/bitstring>> = BitStr,
- decode_fragmented_bits(BitStr2,C,[Value|Acc]);
-decode_fragmented_bits(<<0:1,0:7,BitStr/bitstring>>,C,Acc) ->
- BinBits = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int),C == size(BinBits) ->
- {BinBits,BitStr};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}})
- end;
-decode_fragmented_bits(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) ->
- <<Val:Len/bitstring,Rest/bitstring>> = BitStr,
-%% <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
- ResBitStr = list_to_bitstring(lists:reverse([Val|Acc])),
- case C of
- Int when is_integer(Int),C == bit_size(ResBitStr) ->
- {ResBitStr,Rest};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,ResBitStr}}})
- end.
-
-
-decode_fragmented_octets({0,Bin},C) ->
- decode_fragmented_octets(Bin,C,[]).
-
-decode_fragmented_octets(<<3:2,Len:6,BitStr/bitstring>>,C,Acc) ->
- FragLen = Len * ?'16K',
- <<Value:FragLen/binary,Rest/bitstring>> = BitStr,
- decode_fragmented_octets(Rest,C,[Value|Acc]);
-decode_fragmented_octets(<<0:1,0:7,Bin/bitstring>>,C,Acc) ->
- Octets = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when is_integer(Int), C == size(Octets) ->
- {Octets,Bin};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,Octets}}})
- end;
-decode_fragmented_octets(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) ->
- <<Value:Len/binary-unit:8,BitStr2/binary>> = BitStr,
- BinOctets = list_to_binary(lists:reverse([Value|Acc])),
- case C of
- Int when is_integer(Int),size(BinOctets) == Int ->
- {BinOctets,BitStr2};
- Int when is_integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinOctets}}})
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when is_list(Val) ->
- encode_open_type_1(list_to_binary(Val));
-encode_open_type(_Constraint, Val) when is_binary(Val) ->
- encode_open_type_1(Val).
-
-encode_open_type_1(Val0) ->
- case byte_size(Val0) of
- Size when Size < 16384 ->
- [encode_length(undefined, Size),Val0];
- Size ->
- F = min(Size bsr 14, 4),
- SegSz = F * ?'16K',
- <<Val:SegSz/binary,T/binary>> = Val0,
- [<<3:2,F:6>>,Val|encode_open_type_1(T)]
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- decode_open_type_1(Bytes, []).
-
-decode_open_type_1(Bytes0, Acc) ->
- case decode_length_unlimited(Bytes0) of
- {Len,Bytes} when Len < ?'16K', Acc =:= [] ->
- getoctets_as_bin(Bytes, Len);
- {Len,Bytes1} when Len < ?'16K' ->
- {Bin,Bytes} = getoctets_as_bin(Bytes1, Len),
- {iolist_to_binary([Acc,Bin]),Bytes};
- {Len,Bytes1} ->
- <<Bin:Len/binary,Bytes/bitstring>> = Bytes1,
- decode_open_type_1(Bytes, [Acc,Bin])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when is_atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when is_integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when is_atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when is_atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer([{Rc,_Ec}],Val) when is_tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
- case (catch encode_integer([Rc],Val)) of
- {'EXIT',{error,{asn1,_}}} ->
- [<<1:1>>,encode_unconstrained_number(Val)];
- Encoded ->
- [<<0:1>>,Encoded]
- end;
-encode_integer(C,Val ) when is_list(C) ->
- case get_constraint(C,'SingleValue') of
- no ->
- encode_integer1(C,Val);
- V when is_integer(V),V == Val ->
- []; % a type restricted to a single value encodes to nothing
- V when is_list(V) ->
- case lists:member(Val,V) of
- true ->
- encode_integer1(C,Val);
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end.
-
-encode_integer1(C, Val) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- encode_unconstrained_number(Val);
- {Lb,'MAX'} ->
- encode_semi_constrained_number(Lb,Val);
- %% positive with range
- {Lb,Ub} when Val >= Lb,
- Ub >= Val ->
- encode_constrained_number(VR,Val);
- _ ->
- exit({error,{asn1,{illegal_value,VR,Val}}})
- end.
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,[{Rc,_Ec}]) when is_tuple(Rc) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,[Rc]); %% Value in root of constraint
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when is_integer(V) ->
- {V,Buffer};
- V when is_list(V) ->
- {Val,Buffer2} = decode_integer1(Buffer,C),
- case lists:member(Val,V) of
- true ->
- {Val,Buffer2};
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_,_} ->
- decode_constrained_number(Buffer,VR)
- end.
-
-%% X.691:10.6 Encoding of a normally small non-negative whole number
-%% Use this for encoding of CHOICE index if there is an extension marker in
-%% the CHOICE
-encode_small_number({Name,Val}) when is_atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
- <<Val:7>>;
-encode_small_number(Val) ->
- [<<1:1>>,encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,0)
- end.
-
-%% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when is_atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- %% encoding in minimum no of octets preceeded by a length
- Val2 = Val - Lb,
-%% NumBits = num_bits(Val2),
- Bin = eint_bin_positive(Val2),
- Size = size(Bin),
- if
- Size < 128 ->
- [<<Size>>,Bin]; % equiv with encode_length(undefined,Len) but faster
- Size < 16384 ->
- [<<2:2,Size:14>>,Bin];
- true ->
- [encode_length(undefined,Size),Bin]
- end.
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number(Range,{Name,Val}) when is_atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- NumBits = num_bits(Range),
- <<Val2:NumBits>>;
-encode_constrained_number(Range,Val) ->
- exit({error,{asn1,{integer_range,Range,value,Val}}}).
-
-
-decode_constrained_number(Buffer,{Lb,Ub}) ->
- Range = Ub - Lb + 1,
- NumBits = num_bits(Range),
- {Val,Remain} = getbits(Buffer,NumBits),
- {Val+Lb,Remain}.
-
-%% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint_bin_2Cs(Val),
- Len = size(Oct),
- if
- Len < 128 ->
- [<<Len>>,Oct]; % equiv with encode_length(undefined,Len) but faster
- Len < 16384 ->
- [<<2:2,Len:14>>,Oct];
- true ->
- [encode_length(undefined,Len),<<Len:16>>,Oct]
- end;
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- Len = size(Oct),
- if
- Len < 128 ->
- [<<Len>>,Oct]; % equiv with encode_length(undefined,Len) but faster
- Len < 16384 ->
- [<<2:2,Len:14>>,Oct];
- true ->
- [encode_length(undefined,Len),Oct]
- end.
-
-
-eint_bin_2Cs(Int) ->
- case eint_bin_positive(Int) of
- Bin = <<B,_/binary>> when B > 16#7f ->
- <<0,Bin/binary>>;
- Bin -> Bin
- end.
-
-%% returns the integer as a binary
-eint_bin_positive(Val) when Val < 16#100 ->
- <<Val>>;
-eint_bin_positive(Val) when Val < 16#10000 ->
- <<Val:16>>;
-eint_bin_positive(Val) when Val < 16#1000000 ->
- <<Val:24>>;
-eint_bin_positive(Val) when Val < 16#100000000 ->
- <<Val:32>>;
-eint_bin_positive(Val) ->
- list_to_binary([eint_bin_positive2(Val bsr 32)|<<Val:32>>]).
-eint_bin_positive2(Val) when Val < 16#100 ->
- <<Val>>;
-eint_bin_positive2(Val) when Val < 16#10000 ->
- <<Val:16>>;
-eint_bin_positive2(Val) when Val < 16#1000000 ->
- <<Val:24>>;
-eint_bin_positive2(Val) when Val < 16#100000000 ->
- <<Val:32>>;
-eint_bin_positive2(Val) ->
- [eint_bin_positive2(Val bsr 32)|<<Val:32>>].
-
-
-
-
-enint(-1, [B1|T]) when B1 > 127 ->
- list_to_binary([B1|T]);
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_bin(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_integer(Bin = <<0:1,_:7,_/bitstring>>) ->
- decpint(Bin);
-dec_integer(<<_:1,B:7,BitStr/bitstring>>) ->
- Size = bit_size(BitStr),
- <<I:Size>> = BitStr,
- (-128 + B) bsl bit_size(BitStr) bor I.
-
-decpint(Bin) ->
- Size = bit_size(Bin),
- <<Int:Size>> = Bin,
- Int.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
- <<Len>>;
- Len < 16384 ->
- <<2:2,Len:14>>;
- true -> % should be able to endode length >= 16384
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number(Vr,Len);
-encode_length({Lb,_Ub},Len) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- encode_length(undefined,Len);
-encode_length({Vr={Lb,Ub},Ext},Len)
- when Ub =< 65535 ,Lb >= 0, Len=<Ub, is_list(Ext) ->
- %% constrained extensible
- [<<0:1>>,encode_constrained_number(Vr,Len)];
-encode_length({{Lb,_Ub},Ext},Len) when is_list(Ext) ->
- [<<1:1>>,encode_semi_constrained_number(Lb,Len)];
-encode_length(SingleValue,_Len) when is_integer(SingleValue) ->
- [].
-
-%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
-%% additions in a sequence or set
-encode_small_length(Len) when Len =< 64 ->
- <<(Len-1):7>>;
-encode_small_length(Len) ->
- [<<1:1>>,encode_length(undefined,Len)].
-
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length_unlimited(<<0:1,Oct:7,Rest/bitstring>>) ->
- {Oct,Rest};
-decode_length_unlimited(<<1:1,0:1,Val:14,Rest/bitstring>>) ->
- {Val,Rest};
-decode_length_unlimited(<<1:1,1:1,F:6,Rest/bitstring>>) ->
- SegSz = F * ?'16K',
- {SegSz,Rest}.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-%% un-constrained
-decode_length(<<0:1,Oct:7,Rest/bitstring>>,undefined) ->
- {Oct,Rest};
-decode_length(<<2:2,Val:14,Rest/bitstring>>,undefined) ->
- {Val,Rest};
-decode_length(<<3:2,_:14,_Rest/bitstring>>,undefined) ->
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-decode_length(Buffer,{Lb,_}) when is_integer(Lb), Lb >= 0 -> % Ub > 65535
- decode_length(Buffer,undefined);
-decode_length(Buffer,{VR={_Lb,_Ub},Ext}) when is_list(Ext) ->
- {0,Buffer2} = getbit(Buffer),
- decode_length(Buffer2, VR);
-
-
-%When does this case occur with {_,_Lb,Ub} ??
-% X.691:10.9.3.5
-decode_length(Bin,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
- case Bin of
- <<0:1,Val:7,Rest/bitstring>> ->
- {Val,Rest};
- <<2:2,Val:14,Rest/bitstring>> ->
- {Val,Rest};
- <<3:2,_:14,_Rest/bitstring>> ->
- exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
- end;
-decode_length(Buffer,SingleValue) when is_integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
- % X.691:11
-encode_boolean(true) ->
- <<1:1>>;
-encode_boolean(false) ->
- <<0:1>>;
-encode_boolean({Name,Val}) when is_atom(Name) ->
- encode_boolean(Val);
-encode_boolean(Val) ->
- exit({error,{asn1,{encode_boolean,Val}}}).
-
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when is_tuple(Ntup1), is_tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when is_tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when is_atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-
-%%============================================================================
-%%============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%============================================================================
-%%============================================================================
-
-%%============================================================================
-%% 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 constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when is_integer(Unused),
- is_binary(BinBits) ->
- encode_bin_bit_string(get_constraint(C,'SizeConstraint'),Bin,NamedBitList);
-
-encode_bit_string(C, BitListVal, NamedBitList) ->
- encode_bit_string1(get_constraint(C,'SizeConstraint'), BitListVal, NamedBitList).
-%% when the value is a list of named bits
-encode_bit_string1(C, LoNB=[FirstVal | _RestVal], NamedBitList) when is_atom(FirstVal) ->
- ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string1(C,BitList,NamedBitList);
-
-encode_bit_string1(C, BL=[{bit,_No} | _RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes(BL, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string1(C,BitList,NamedBitList);
-%% when the value is a list of ones and zeroes
-encode_bit_string1(Int, BitListValue, _)
- when is_list(BitListValue),is_integer(Int) ->
- %% The type is constrained by a single value size constraint
- bit_list2bitstr(Int,BitListValue);
-encode_bit_string1(no, BitListValue,[])
- when is_list(BitListValue) ->
- Len = length(BitListValue),
- [encode_length(undefined,Len),bit_list2bitstr(Len,BitListValue)];
-encode_bit_string1(C, BitListValue,[])
- when is_list(BitListValue) ->
- Len = length(BitListValue),
- [encode_length(C,Len),bit_list2bitstr(Len,BitListValue)];
-encode_bit_string1(no, BitListValue,_NamedBitList)
- when is_list(BitListValue) ->
- %% this case with an unconstrained BIT STRING can be made more efficient
- %% if the complete driver can take a special code so the length field
- %% is encoded there.
- NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitListValue))),
- Len = length(NewBitLVal),
- [encode_length(undefined,Len),bit_list2bitstr(Len,NewBitLVal)];
-encode_bit_string1(C,BitListValue,_NamedBitList)
- when is_list(BitListValue) ->% C = {_,'MAX'}
- NewBitStr = bitstr_trailing_zeros(BitListValue,C),
- [encode_length(C,bit_size(NewBitStr)),NewBitStr];
-
-
-%% when the value is an integer
-encode_bit_string1(C, IntegerVal, NamedBitList) when is_integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string1(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string1(C,{Name,Val}, NamedBitList) when is_atom(Name) ->
- encode_bit_string1(C,Val,NamedBitList).
-
-bit_list2bitstr(Len,BitListValue) ->
- case length(BitListValue) of
- Len ->
- << <<B:1>> ||B <- BitListValue>>;
- L when L > Len -> % truncate
- << << <<B:1>> ||B <- BitListValue>> :Len/bitstring>>;
- L -> % Len > L -> pad
- << << <<B:1>> ||B <- BitListValue>>/bitstring ,0:(Len-L)>>
- end.
-
-adjust_trailing_zeros(Len,Bin) when Len == bit_size(Bin) ->
- Bin;
-adjust_trailing_zeros(Len,Bin) when Len > bit_size(Bin) ->
- <<Bin/bitstring,0:(Len-bit_size(Bin))>>;
-adjust_trailing_zeros(Len,Bin) ->
- <<Bin:Len/bitstring>>.
-
-bitstr_trailing_zeros(BitList,C) when is_integer(C) ->
- bitstr_trailing_zeros1(BitList,C,C);
-bitstr_trailing_zeros(BitList,{Lb,Ub}) when is_integer(Lb) ->
- bitstr_trailing_zeros1(BitList,Lb,Ub);
-bitstr_trailing_zeros(BitList,{{Lb,Ub},_}) when is_integer(Lb) ->
- bitstr_trailing_zeros1(BitList,Lb,Ub);
-bitstr_trailing_zeros(BitList,_) ->
- bit_list2bitstr(length(BitList),BitList).
-
-bitstr_trailing_zeros1(BitList,Lb,Ub) ->
- case length(BitList) of
- Lb -> bit_list2bitstr(Lb,BitList);
- B when B<Lb -> bit_list2bitstr(Lb,BitList);
- D -> F = fun(L,LB,LB,_,_)->bit_list2bitstr(LB,lists:reverse(L));
- ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
- (L,L1,_,UB,_)when L1 =< UB ->
- bit_list2bitstr(L1,lists:reverse(L));
- (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
- BitList}}) end,
- F(lists:reverse(BitList),D,Lb,Ub,F)
- end.
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),i.e. number unused bits in least sign. byte of
-%% BinBits = binary().
-encode_bin_bit_string(C,{_,BinBits},_NamedBitList)
- when is_integer(C),C=<16 ->
- adjust_trailing_zeros(C,BinBits);
-encode_bin_bit_string(C,{_Unused,BinBits},_NamedBitList)
- when is_integer(C) ->
- adjust_trailing_zeros(C,BinBits);
-encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
- %% removes all trailing bits if NamedBitList is not empty
- BitStr = remove_trailing_bin(NamedBitList,UnusedAndBin),
- case C of
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- [encode_length({Lb,Ub},bit_size(BitStr)),BitStr];
- no ->
- [encode_length(undefined,bit_size(BitStr)),BitStr];
- Sc ->
- [encode_length(Sc,bit_size(BitStr)),BitStr]
- end.
-
-
-remove_trailing_bin([], {Unused,Bin}) ->
- BS = bit_size(Bin)-Unused,
- <<BitStr:BS/bitstring,_:Unused>> = Bin,
- BitStr;
-remove_trailing_bin(_NamedNumberList,{_Unused,<<>>}) ->
- <<>>;
-remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
- Size = size(Bin)-1,
- <<Bfront:Size/binary, LastByte:8>> = Bin,
-
- %% clear the Unused bits to be sure
- Unused1 = trailingZeroesInNibble(LastByte band 15),
- Unused2 =
- case Unused1 of
- 4 ->
- 4 + trailingZeroesInNibble(LastByte bsr 4);
- _ -> Unused1
- end,
- case Unused2 of
- 8 ->
- remove_trailing_bin(NamedNumberList,{0,Bfront});
- _ ->
- BS = bit_size(Bin) - Unused2,
- <<BitStr:BS/bitstring,_:Unused2>> = Bin,
- BitStr
- end.
-
-trailingZeroesInNibble(0) ->
- 4;
-trailingZeroesInNibble(1) ->
- 0;
-trailingZeroesInNibble(2) ->
- 1;
-trailingZeroesInNibble(3) ->
- 0;
-trailingZeroesInNibble(4) ->
- 2;
-trailingZeroesInNibble(5) ->
- 0;
-trailingZeroesInNibble(6) ->
- 1;
-trailingZeroesInNibble(7) ->
- 0;
-trailingZeroesInNibble(8) ->
- 3;
-trailingZeroesInNibble(9) ->
- 0;
-trailingZeroesInNibble(10) ->
- 1;
-trailingZeroesInNibble(11) ->
- 0;
-trailingZeroesInNibble(12) -> %#1100
- 2;
-trailingZeroesInNibble(13) ->
- 0;
-trailingZeroesInNibble(14) ->
- 1;
-trailingZeroesInNibble(15) ->
- 0.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{8,0},Buffer};
- V when is_integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 -> %fixed length > 16 bits
- compact_bit_string(Buffer,V,NamedNumberList);
- V when is_integer(V) -> % V > 65536 => fragmented value
- {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
- PadLen = (8 - (bit_size(Bin) rem 8)) rem 8,
- {{PadLen,<<Bin/bitstring,0:PadLen>>},Buffer2};
-%% {0,_} -> {{0,Bin},Buffer2};
-%% {U,_} -> {{8-U,Bin},Buffer2}
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- compact_bit_string(Bytes2,Len,NamedNumberList);
- no ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,undefined),
- compact_bit_string(Bytes2,Len,NamedNumberList);
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- compact_bit_string(Bytes2,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- bit_list_or_named(Bytes2,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- bit_list_or_named(Bytes2,Len,NamedNumberList);
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when is_integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when is_integer(V),V=<65536 ->
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when is_integer(V) ->
- {BinBits,_} = decode_fragmented_bits(Buffer,V),
- bit_list_or_named(BinBits,V,NamedNumberList);
- Sc -> % extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- bit_list_or_named(Bytes2,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- {BitStr,Rest} = getbits_as_binary(Len,Buffer), % {{Unused,BinBits},NewBuffer}
- PadLen = (8 - (bit_size(BitStr) rem 8)) rem 8,
- {{PadLen,<<BitStr/bitstring,0:PadLen>>},Rest};
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_or_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_or_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_or_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_or_named1(Pos+1,Bt,Names,Acc);
-bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_or_named1(_,[],_,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(Int) when is_integer(Int), Int > 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)];
-int_to_bitlist(0) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,{_Name,Val}) ->
- encode_octet_string(C,Val);
-encode_octet_string(C,Val) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- <<>>;
- 1 ->
- list_to_binary(Val);
- 2 ->
- list_to_binary(Val);
- Sv when Sv =<65535, Sv == length(Val) -> % fixed length
- list_to_binary(Val);
- VR = {_,_} ->
- [encode_length(VR,length(Val)),list_to_binary(Val)];
- Sv when is_list(Sv) ->
- [encode_length({hd(Sv),lists:max(Sv)},length(Val)),list_to_binary(Val)];
- no ->
- [encode_length(undefined,length(Val)),list_to_binary(Val)]
- end.
-
-decode_octet_string(Bytes,C) ->
- decode_octet_string1(Bytes,get_constraint(C,'SizeConstraint')).
-decode_octet_string1(<<B1,Bytes/bitstring>>,1) ->
- {[B1],Bytes};
-decode_octet_string1(<<B1,B2,Bytes/bitstring>>,2) ->
- {[B1,B2],Bytes};
-decode_octet_string1(Bytes,Sv) when is_integer(Sv),Sv=<65535 ->
- getoctets_as_list(Bytes,Sv);
-decode_octet_string1(Bytes,Sv) when is_integer(Sv) ->
- decode_fragmented_octets(Bytes,Sv);
-decode_octet_string1(Bytes,{Lb,Ub}) ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- getoctets_as_list(Bytes2,Len);
-decode_octet_string1(Bytes,Sv) when is_list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- getoctets_as_list(Bytes2,Len);
-decode_octet_string1(Bytes,no) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string('BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string({Name,Val}) when is_atom(Name) ->
- encode_restricted_string(Val);
-
-encode_restricted_string(Val) when is_list(Val)->
- [encode_length(undefined,length(Val)),list_to_binary(Val)].
-
-encode_known_multiplier_string(StringType,C,{Name,Val}) when is_atom(Name) ->
- encode_known_multiplier_string(StringType,C,Val);
-
-encode_known_multiplier_string(StringType,C,Val) ->
- Result = chars_encode(C,StringType,Val),
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- Result;
- 0 ->
- [];
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- Result;
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),Result];
- Vl when is_list(Vl) ->
- [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),Result];
- no ->
- [encode_length(undefined,length(Val)),Result]
- end.
-
-decode_restricted_string(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-decode_known_multiplier_string(Bytes,StringType,C,_Ext) ->
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when is_integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- Ub when is_integer(Ub),Ub =<65535 -> % fixed length
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- 0 ->
- {[],Bytes};
- Vl when is_list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- chars_decode(Bytes1,NumBits,StringType,C,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- chars_decode(Bytes1,NumBits,StringType,C,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- chars_decode(Bytes1,NumBits,StringType,C,Len)
- end.
-
-
-encode_NumericString(C,Val) ->
- encode_known_multiplier_string('NumericString',C,Val).
-decode_NumericString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'NumericString',C,false).
-
-encode_PrintableString(C,Val) ->
- encode_known_multiplier_string('PrintableString',C,Val).
-decode_PrintableString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'PrintableString',C,false).
-
-encode_VisibleString(C,Val) -> % equivalent with ISO646String
- encode_known_multiplier_string('VisibleString',C,Val).
-decode_VisibleString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'VisibleString',C,false).
-
-encode_IA5String(C,Val) ->
- encode_known_multiplier_string('IA5String',C,Val).
-decode_IA5String(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'IA5String',C,false).
-
-encode_BMPString(C,Val) ->
- encode_known_multiplier_string('BMPString',C,Val).
-decode_BMPString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'BMPString',C,false).
-
-encode_UniversalString(C,Val) ->
- encode_known_multiplier_string('UniversalString',C,Val).
-decode_UniversalString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,'UniversalString',C,false).
-
-
-%% end of known-multiplier strings for which PER visible constraints are
-%% applied
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{0,0,O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-chars_encode(C,StringType,Value) ->
- case {StringType,get_constraint(C,'PermittedAlphabet')} of
- {'UniversalString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
- {'BMPString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
- _ ->
- {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
- chars_encode2(Value,NumBits,CharOutTab)
- end.
-
-chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
- %%[{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [<<(H-Min):NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
-%% [{bits,NumBits,exit_if_false(H,element(H-Min+1,Tab))}|chars_encode2(T,NumBits,{Min,Max,Tab})];
- Ch = exit_if_false(H,element(H-Min+1,Tab)),
- [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,Tab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-%% [{bits,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
- Ch = ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,
- [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
-%% [{bits,NumBits,exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab))}|chars_encode2(T,NumBits,{Min,Max,notab})];
- Ch = exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)),
- [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_,{_,_,_}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-exit_if_false(V,false)->
- exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
-exit_if_false(_,V) ->V.
-
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv));
- no ->
- case StringType of
- 'IA5String' ->
- charbits(128); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-%% See Table 20.3 in Dubuisson
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when is_integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',C,Len) ->
- case get_constraint(C,'PermittedAlphabet') of
- no ->
- getBMPChars(Bytes,Len);
- _ ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet constraint"}}})
- end;
-chars_decode(Bytes,NumBits,StringType,C,Len) ->
- CharInTab = get_CharInTab(C,StringType),
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result =
- if
- Char < 256 -> Char;
- true ->
- list_to_tuple(binary_to_list(<<Char:32>>))
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
-%% UTF8String
-encode_UTF8String(Val) when is_binary(Val) ->
- [encode_length(undefined,size(Val)),Val];
-encode_UTF8String(Val) ->
- Bin = list_to_binary(Val),
- encode_UTF8String(Bin).
-
-decode_UTF8String(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_bin(Bytes2,Len).
-
-
- % X.691:17
-encode_null(_) -> []. % encodes to nothing
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [binary()|bitstring()|list()]
-%%
-encode_object_identifier({Name,Val}) when is_atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- OctetList = e_object_identifier(Val),
- Octets = list_to_binary(OctetList), % performs a flatten at the same time
- [encode_length(undefined,size(Octets)),Octets].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname,V}) when is_atom(Cname),is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname,V}) when is_atom(Cname),is_list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when is_tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
- Head = 40*E1 + E2, % weird
- e_object_elements([Head|Tail],[]);
-e_object_identifier(Oid=[_,_|_Tail]) ->
- exit({error,{asn1,{'illegal_value',Oid}}}).
-
-e_object_elements([],Acc) ->
- lists:reverse(Acc);
-e_object_elements([H|T],Acc) ->
- e_object_elements(T,[e_object_element(H)|Acc]).
-
-e_object_element(Num) when Num < 128 ->
- [Num];
-e_object_element(Num) ->
- [e_o_e(Num bsr 7)|[Num band 2#1111111]].
-e_o_e(Num) when Num < 128 ->
- Num bor 2#10000000;
-e_o_e(Num) ->
- [e_o_e(Num bsr 7)|[(Num band 2#1111111) bor 2#10000000]].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_relative_oid(Val) -> CompleteList
-%% encode_relative_oid({Name,Val}) -> CompleteList
-encode_relative_oid({Name,Val}) when is_atom(Name) ->
- encode_relative_oid(Val);
-encode_relative_oid(Val) when is_tuple(Val) ->
- encode_relative_oid(tuple_to_list(Val));
-encode_relative_oid(Val) when is_list(Val) ->
- Octets = list_to_binary([e_object_element(X)||X <- Val]),
- [encode_length(undefined,size(Octets)),Octets].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_relative_oid(Val) -> CompleteList
-%% decode_relative_oid({Name,Val}) -> CompleteList
-decode_relative_oid(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- ObjVals = dec_subidentifiers(Octs,0,[]),
- {list_to_tuple(ObjVals),Bytes3}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_real(Val) -> CompleteList
-%% encode_real({Name,Val}) -> CompleteList
-encode_real({Name,Val}) when is_atom(Name) ->
- encode_real(Val);
-encode_real(Real) ->
- {EncVal,Len} = ?RT_COMMON:encode_real([],Real),
- [encode_length(undefined,Len),EncVal].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_real(Val) -> {REALvalue,Rest}
-%% decode_real({Name,Val}) -> {REALvalue,Rest}
-decode_real(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- <<Bytes3:Len/binary,Rest/bitstring>> = Bytes2,
- {RealVal,Rest,Len} = ?RT_COMMON:decode_real(Bytes3,Len),
- {RealVal,Rest}.
-
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_Key) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-complete(InList) when is_list(InList) ->
- case complete1(InList) of
- <<>> ->
- <<0>>;
- Res ->
- case bit_size(Res) band 7 of
- 0 -> Res;
- Bits -> <<Res/bitstring,0:(8-Bits)>>
- end
- end;
-complete(InList) when is_binary(InList) ->
- InList;
-complete(InList) when is_bitstring(InList) ->
- PadLen = 8 - (bit_size(InList) band 7),
- <<InList/bitstring,0:PadLen>>.
-
-complete1(L) when is_list(L) ->
- list_to_bitstring(L).
-
-%% Special version of complete that does not align the completed message.
-complete_NFP(InList) when is_list(InList) ->
- list_to_bitstring(InList);
-complete_NFP(InList) when is_bitstring(InList) ->
- InList.
-
-%% unaligned helpers
-
-%% 10.5.6 NOTE: If "range" satisfies the inequality 2^m < "range" =<
-%% 2^(m+1) then the number of bits = m + 1
-
-num_bits(N) ->
- num_bits(N,1,0).
-num_bits(N,T,B) when N=<T->B;
-num_bits(N,T,B) ->num_bits(N,T bsl 1, B+1).
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
new file mode 100644
index 0000000000..b5429fe324
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -0,0 +1,1487 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+
+-module(asn1rtt_ber).
+
+%% encoding / decoding of BER
+
+-export([ber_decode_nif/1,ber_decode_erlang/1,match_tags/2,ber_encode/1]).
+-export([encode_tags/2,
+ encode_tags/3,
+ skip_ExtensionAdditions/2]).
+-export([encode_boolean/2,decode_boolean/2,
+ encode_integer/2,encode_integer/3,
+ decode_integer/2,decode_integer/3,
+ decode_named_integer/3,decode_named_integer/4,
+ encode_enumerated/2,decode_enumerated/3,
+ encode_bit_string/4,
+ decode_named_bit_string/3,
+ decode_compact_bit_string/3,
+ decode_legacy_bit_string/3,
+ decode_native_bit_string/3,
+ encode_null/2,decode_null/2,
+ encode_relative_oid/2,decode_relative_oid/2,
+ encode_object_identifier/2,decode_object_identifier/2,
+ encode_restricted_string/2,
+ decode_restricted_string/2,decode_restricted_string/3,
+ encode_universal_string/2,decode_universal_string/3,
+ encode_UTF8_string/2,decode_UTF8_string/2,
+ encode_BMP_string/2,decode_BMP_string/3]).
+
+-export([encode_open_type/2,decode_open_type/2,
+ decode_open_type_as_binary/2]).
+
+-export([decode_primitive_incomplete/2,decode_selective/2]).
+
+%% For DER.
+-export([dynamicsort_SET_components/1,dynamicsort_SETOF/1]).
+
+%% the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+%%% primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+%%% The tag-number for universal types
+-define(N_BOOLEAN, 1).
+-define(N_INTEGER, 2).
+-define(N_BIT_STRING, 3).
+-define(N_OCTET_STRING, 4).
+-define(N_NULL, 5).
+-define(N_OBJECT_IDENTIFIER, 6).
+-define(N_OBJECT_DESCRIPTOR, 7).
+-define(N_EXTERNAL, 8).
+-define(N_REAL, 9).
+-define(N_ENUMERATED, 10).
+-define(N_EMBEDDED_PDV, 11).
+-define(N_SEQUENCE, 16).
+-define(N_SET, 17).
+-define(N_NumericString, 18).
+-define(N_PrintableString, 19).
+-define(N_TeletexString, 20).
+-define(N_VideotexString, 21).
+-define(N_IA5String, 22).
+-define(N_UTCTime, 23).
+-define(N_GeneralizedTime, 24).
+-define(N_GraphicString, 25).
+-define(N_VisibleString, 26).
+-define(N_GeneralString, 27).
+-define(N_UniversalString, 28).
+-define(N_BMPString, 30).
+
+
+% the complete tag-word of built-in types
+-define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
+-define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
+-define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
+-define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
+-define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
+-define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
+-define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
+-define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
+-define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
+-define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
+-define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
+-define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
+-define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
+-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
+-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
+-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
+-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
+-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
+-define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
+-define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
+-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
+-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
+-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
+-define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
+-define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
+
+ber_encode([Tlv]) ->
+ ber_encode(Tlv);
+ber_encode(Tlv) when is_binary(Tlv) ->
+ Tlv;
+ber_encode(Tlv) ->
+ asn1rt_nif:encode_ber_tlv(Tlv).
+
+ber_decode_nif(B) ->
+ asn1rt_nif:decode_ber_tlv(B).
+
+ber_decode_erlang(B) when is_binary(B) ->
+ decode_primitive(B);
+ber_decode_erlang(Tlv) ->
+ {Tlv,<<>>}.
+
+decode_primitive(Bin) ->
+ {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
+ case Form of
+ 1 -> % constructed
+ {{TagNo,decode_constructed(V)},Rest};
+ 0 -> % primitive
+ {{TagNo,V},Rest};
+ 2 -> % constructed indefinite
+ {Vlist,Rest2} = decode_constructed_indefinite(V,[]),
+ {{TagNo,Vlist},Rest2}
+ end.
+
+decode_constructed(Bin) when byte_size(Bin) =:= 0 ->
+ [];
+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_primitive_incomplete/2 decodes an encoded message incomplete
+%% by help of the pattern attribute (first argument).
+decode_primitive_incomplete([[default,TagNo]],Bin) -> %default
+ case decode_tag_and_length(Bin) of
+ {Form,TagNo,V,Rest} ->
+ decode_incomplete2(Form,TagNo,V,[],Rest);
+ _ ->
+ %{asn1_DEFAULT,Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[default,TagNo,Directives]],Bin) -> %default, constructed type, Directives points into this type
+ case decode_tag_and_length(Bin) of
+ {Form,TagNo,V,Rest} ->
+ decode_incomplete2(Form,TagNo,V,Directives,Rest);
+ _ ->
+ %{asn1_DEFAULT,Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[opt,TagNo]],Bin) -> %optional
+ case decode_tag_and_length(Bin) of
+ {Form,TagNo,V,Rest} ->
+ decode_incomplete2(Form,TagNo,V,[],Rest);
+ _ ->
+ %{{TagNo,asn1_NOVALUE},Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[opt,TagNo,Directives]],Bin) -> %optional
+ case decode_tag_and_length(Bin) of
+ {Form,TagNo,V,Rest} ->
+ decode_incomplete2(Form,TagNo,V,Directives,Rest);
+ _ ->
+ %{{TagNo,asn1_NOVALUE},Bin}
+ asn1_NOVALUE
+ end;
+%% An optional that shall be undecoded
+decode_primitive_incomplete([[opt_undec,Tag]],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_,Tag,_,_} ->
+ decode_incomplete_bin(Bin);
+ _ ->
+ asn1_NOVALUE
+ end;
+%% A choice alternative that shall be undecoded
+decode_primitive_incomplete([[alt_undec,TagNo]|RestAlts],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_,TagNo,_,_} ->
+ decode_incomplete_bin(Bin);
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt,TagNo]|RestAlts],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_Form,TagNo,V,Rest} ->
+ {{TagNo,V},Rest};
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt,TagNo,Directives]|RestAlts],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {Form,TagNo,V,Rest} ->
+ decode_incomplete2(Form,TagNo,V,Directives,Rest);
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt_parts,TagNo]],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_Form,TagNo,V,Rest} ->
+ {{TagNo,V},Rest};
+ _ ->
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[alt_parts,TagNo]|RestAlts],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_Form,TagNo,V,Rest} ->
+ {{TagNo,decode_parts_incomplete(V)},Rest};
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[undec,_TagNo]|_RestTag],Bin) -> %incomlete decode
+ decode_incomplete_bin(Bin);
+decode_primitive_incomplete([[parts,TagNo]|_RestTag],Bin) ->
+ case decode_tag_and_length(Bin) of
+ {_Form,TagNo,V,Rest} ->
+ {{TagNo,decode_parts_incomplete(V)},Rest};
+ Err ->
+ {error,{asn1,"tag failure",TagNo,Err}}
+ end;
+decode_primitive_incomplete([mandatory|RestTag],Bin) ->
+ {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
+ decode_incomplete2(Form,TagNo,V,RestTag,Rest);
+%% A choice that is a toptype or a mandatory component of a
+%% SEQUENCE or SET.
+decode_primitive_incomplete([[mandatory|Directives]],Bin) ->
+ {Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
+ decode_incomplete2(Form,TagNo,V,Directives,Rest);
+decode_primitive_incomplete([],Bin) ->
+ decode_primitive(Bin).
+
+%% decode_parts_incomplete/1 receives a number of values encoded in
+%% sequence and returns the parts as unencoded binaries
+decode_parts_incomplete(<<>>) ->
+ [];
+decode_parts_incomplete(Bin) ->
+ {ok,Rest} = skip_tag(Bin),
+ {ok,Rest2} = skip_length_and_value(Rest),
+ LenPart = byte_size(Bin) - byte_size(Rest2),
+ <<Part:LenPart/binary,RestBin/binary>> = Bin,
+ [Part|decode_parts_incomplete(RestBin)].
+
+
+%% decode_incomplete2 checks if V is a value of a constructed or
+%% primitive type, and continues the decode propeerly.
+decode_incomplete2(_Form=2,TagNo,V,TagMatch,_) ->
+ %% constructed indefinite length
+ {Vlist,Rest2} = decode_constr_indef_incomplete(TagMatch,V,[]),
+ {{TagNo,Vlist},Rest2};
+decode_incomplete2(1,TagNo,V,[TagMatch],Rest) when is_list(TagMatch) ->
+ {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
+decode_incomplete2(1,TagNo,V,TagMatch,Rest) ->
+ {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
+decode_incomplete2(0,TagNo,V,_TagMatch,Rest) ->
+ {{TagNo,V},Rest}.
+
+decode_constructed_incomplete([Tags=[Ts]],Bin) when is_list(Ts) ->
+ decode_constructed_incomplete(Tags,Bin);
+decode_constructed_incomplete(_TagMatch,<<>>) ->
+ [];
+decode_constructed_incomplete([mandatory|RestTag],Bin) ->
+ {Tlv,Rest} = decode_primitive(Bin),
+ [Tlv|decode_constructed_incomplete(RestTag,Rest)];
+decode_constructed_incomplete(Directives=[[Alt,_]|_],Bin)
+ when Alt =:= alt_undec; Alt =:= alt; Alt =:= alt_parts ->
+ {_Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
+ case incomplete_choice_alt(TagNo, Directives) of
+ {alt_undec,_} ->
+ LenA = byte_size(Bin) - byte_size(Rest),
+ <<A:LenA/binary,Rest/binary>> = Bin,
+ A;
+ {alt,InnerDirectives} ->
+ {Tlv,Rest} = decode_primitive_incomplete(InnerDirectives,V),
+ {TagNo,Tlv};
+ {alt_parts,_} ->
+ [{TagNo,decode_parts_incomplete(V)}];
+ no_match -> %% if a choice alternative was encoded that
+ %% was not specified in the config file,
+ %% thus decode component anonomous.
+ {Tlv,_}=decode_primitive(Bin),
+ Tlv
+ end;
+decode_constructed_incomplete([TagNo|RestTag],Bin) ->
+ case decode_primitive_incomplete([TagNo],Bin) of
+ {Tlv,Rest} ->
+ [Tlv|decode_constructed_incomplete(RestTag,Rest)];
+ asn1_NOVALUE ->
+ decode_constructed_incomplete(RestTag,Bin)
+ end;
+decode_constructed_incomplete([],Bin) ->
+ {Tlv,Rest}=decode_primitive(Bin),
+ [Tlv|decode_constructed_incomplete([],Rest)].
+
+decode_constr_indef_incomplete(_TagMatch,<<0,0,Rest/binary>>,Acc) ->
+ {lists:reverse(Acc),Rest};
+decode_constr_indef_incomplete([Tag|RestTags],Bin,Acc) ->
+ case decode_primitive_incomplete([Tag],Bin) of
+ {Tlv,Rest} ->
+ decode_constr_indef_incomplete(RestTags,Rest,[Tlv|Acc]);
+ asn1_NOVALUE ->
+ decode_constr_indef_incomplete(RestTags,Bin,Acc)
+ end.
+
+
+decode_incomplete_bin(Bin) ->
+ {ok,Rest} = skip_tag(Bin),
+ {ok,Rest2} = skip_length_and_value(Rest),
+ IncLen = byte_size(Bin) - byte_size(Rest2),
+ <<IncBin:IncLen/binary,Ret/binary>> = Bin,
+ {IncBin,Ret}.
+
+incomplete_choice_alt(TagNo,[[Alt,TagNo]|Directives]) ->
+ {Alt,Directives};
+incomplete_choice_alt(TagNo,[D]) when is_list(D) ->
+ incomplete_choice_alt(TagNo,D);
+incomplete_choice_alt(TagNo,[_H|Directives]) ->
+ incomplete_choice_alt(TagNo,Directives);
+incomplete_choice_alt(_,[]) ->
+ no_match.
+
+
+%% decode_selective(Pattern, Binary) the first argument is a pattern that tells
+%% what to do with the next element the second is the BER encoded
+%% message as a binary
+%% Returns {ok,Value} or {error,Reason}
+%% Value is a binary that in turn must be decoded to get the decoded
+%% value.
+decode_selective([],Binary) ->
+ {ok,Binary};
+decode_selective([skip|RestPattern],Binary)->
+ {ok,RestBinary}=skip_tag(Binary),
+ {ok,RestBinary2}=skip_length_and_value(RestBinary),
+ decode_selective(RestPattern,RestBinary2);
+decode_selective([[skip_optional,Tag]|RestPattern],Binary) ->
+ case skip_optional_tag(Tag,Binary) of
+ {ok,RestBinary} ->
+ {ok,RestBinary2}=skip_length_and_value(RestBinary),
+ decode_selective(RestPattern,RestBinary2);
+ missing ->
+ decode_selective(RestPattern,Binary)
+ end;
+decode_selective([[choosen,Tag]],Binary) ->
+ return_value(Tag,Binary);
+decode_selective([[choosen,Tag]|RestPattern],Binary) ->
+ case skip_optional_tag(Tag,Binary) of
+ {ok,RestBinary} ->
+ {ok,Value} = get_value(RestBinary),
+ decode_selective(RestPattern,Value);
+ missing ->
+ {ok,<<>>}
+ end;
+decode_selective(P,_) ->
+ {error,{asn1,{partial_decode,"bad pattern",P}}}.
+
+return_value(Tag,Binary) ->
+ {ok,{Tag,RestBinary}}=get_tag(Binary),
+ {ok,{LenVal,_RestBinary2}} = get_length_and_value(RestBinary),
+ {ok,<<Tag/binary,LenVal/binary>>}.
+
+
+%% skip_tag and skip_length_and_value are rutines used both by
+%% decode_partial_incomplete and decode_selective (decode/2).
+
+skip_tag(<<_:3,31:5,Rest/binary>>)->
+ skip_long_tag(Rest);
+skip_tag(<<_:3,_Tag:5,Rest/binary>>) ->
+ {ok,Rest}.
+
+skip_long_tag(<<1:1,_:7,Rest/binary>>) ->
+ skip_long_tag(Rest);
+skip_long_tag(<<0:1,_:7,Rest/binary>>) ->
+ {ok,Rest}.
+
+skip_optional_tag(<<>>,Binary) ->
+ {ok,Binary};
+skip_optional_tag(<<Tag,RestTag/binary>>,<<Tag,Rest/binary>>) ->
+ skip_optional_tag(RestTag,Rest);
+skip_optional_tag(_,_) ->
+ missing.
+
+
+skip_length_and_value(Binary) ->
+ case decode_length(Binary) of
+ {indefinite,RestBinary} ->
+ skip_indefinite_value(RestBinary);
+ {Length,RestBinary} ->
+ <<_:Length/unit:8,Rest/binary>> = RestBinary,
+ {ok,Rest}
+ end.
+
+skip_indefinite_value(<<0,0,Rest/binary>>) ->
+ {ok,Rest};
+skip_indefinite_value(Binary) ->
+ {ok,RestBinary}=skip_tag(Binary),
+ {ok,RestBinary2} = skip_length_and_value(RestBinary),
+ skip_indefinite_value(RestBinary2).
+
+get_value(Binary) ->
+ case decode_length(Binary) of
+ {indefinite,RestBinary} ->
+ get_indefinite_value(RestBinary,[]);
+ {Length,RestBinary} ->
+ <<Value:Length/binary,_Rest/binary>> = RestBinary,
+ {ok,Value}
+ end.
+
+get_indefinite_value(<<0,0,_Rest/binary>>,Acc) ->
+ {ok,list_to_binary(lists:reverse(Acc))};
+get_indefinite_value(Binary,Acc) ->
+ {ok,{Tag,RestBinary}}=get_tag(Binary),
+ {ok,{LenVal,RestBinary2}} = get_length_and_value(RestBinary),
+ get_indefinite_value(RestBinary2,[LenVal,Tag|Acc]).
+
+get_tag(<<H:1/binary,Rest/binary>>) ->
+ case H of
+ <<_:3,31:5>> ->
+ get_long_tag(Rest,[H]);
+ _ -> {ok,{H,Rest}}
+ end.
+get_long_tag(<<H:1/binary,Rest/binary>>,Acc) ->
+ case H of
+ <<0:1,_:7>> ->
+ {ok,{list_to_binary(lists:reverse([H|Acc])),Rest}};
+ _ ->
+ get_long_tag(Rest,[H|Acc])
+ end.
+
+get_length_and_value(Bin = <<0:1,Length:7,_T/binary>>) ->
+ <<Len,Val:Length/binary,Rest/binary>> = Bin,
+ {ok,{<<Len,Val/binary>>, Rest}};
+get_length_and_value(Bin = <<1:1,0:7,_T/binary>>) ->
+ get_indefinite_length_and_value(Bin);
+get_length_and_value(<<1:1,LL:7,T/binary>>) ->
+ <<Length:LL/unit:8,Rest/binary>> = T,
+ <<Value:Length/binary,Rest2/binary>> = Rest,
+ {ok,{<<1:1,LL:7,Length:LL/unit:8,Value/binary>>,Rest2}}.
+
+get_indefinite_length_and_value(<<H,T/binary>>) ->
+ get_indefinite_length_and_value(T,[H]).
+
+get_indefinite_length_and_value(<<0,0,Rest/binary>>,Acc) ->
+ {ok,{list_to_binary(lists:reverse(Acc)),Rest}};
+get_indefinite_length_and_value(Binary,Acc) ->
+ {ok,{Tag,RestBinary}}=get_tag(Binary),
+ {ok,{LenVal,RestBinary2}}=get_length_and_value(RestBinary),
+ get_indefinite_length_and_value(RestBinary2,[LenVal,Tag|Acc]).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 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]) ->
+ V;
+match_tags({T,V}, [T|Tt]) ->
+ match_tags(V,Tt);
+match_tags([{T,V}], [T|Tt]) ->
+ match_tags(V, Tt);
+match_tags([{T,_V}|_]=Vlist, [T]) ->
+ Vlist;
+match_tags(Tlv, []) ->
+ Tlv;
+match_tags({Tag,_V}=Tlv, [T|_Tt]) ->
+ exit({error,{asn1,{wrong_tag,{{expected,T},{got,Tag,Tlv}}}}}).
+
+%%%
+%% skips components that do not match a tag in Tags
+skip_ExtensionAdditions([], _Tags) ->
+ [];
+skip_ExtensionAdditions([{Tag,_}|Rest]=TLV, Tags) ->
+ case [X || X=T <- Tags, T =:= Tag] of
+ [] ->
+ %% skip this TLV and continue with next
+ skip_ExtensionAdditions(Rest,Tags);
+ _ ->
+ TLV
+ end.
+
+
+%%===============================================================================
+%% 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, V:Length/binary, RestBuffer/binary>>) when TagNo < 31 ->
+ {Form, (Class bsl 16) bor TagNo, V, RestBuffer};
+decode_tag_and_length(<<Class:2, 1:1, TagNo:5, 1:1, 0:7, T/binary>>) when TagNo < 31 ->
+ {2, (Class bsl 16) + TagNo, T, <<>>};
+decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, LL:7, Length:LL/unit:8,V:Length/binary, T/binary>>) when TagNo < 31 ->
+ {Form, (Class bsl 16) bor TagNo, V, T};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 0:1, Length:7, V:Length/binary, RestBuffer/binary>>) ->
+ {Form, (Class bsl 16) bor TagNo, V, RestBuffer};
+decode_tag_and_length(<<Class:2, 1:1, 31:5, 0:1, TagNo:7, 1:1, 0:7, T/binary>>) ->
+ {2, (Class bsl 16) bor TagNo, T, <<>>};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, LL:7, Length:LL/unit:8, V:Length/binary, T/binary>>) ->
+ {Form, (Class bsl 16) bor TagNo, V, T};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 1:1, TagPart1:7, 0:1, TagPartLast, Buffer/binary>>) ->
+ TagNo = (TagPart1 bsl 7) bor TagPartLast,
+ {Length, RestBuffer} = decode_length(Buffer),
+ << V:Length/binary, RestBuffer2/binary>> = RestBuffer,
+ {Form, (Class bsl 16) bor TagNo, V, RestBuffer2};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
+ {TagNo, Buffer1} = decode_tag(Buffer, 0),
+ {Length, RestBuffer} = decode_length(Buffer1),
+ << V:Length/binary, RestBuffer2/binary>> = RestBuffer,
+ {Form, (Class bsl 16) bor TagNo, V, RestBuffer2}.
+
+
+
+%% last partial tag
+decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck) ->
+ TagNo = (TagAck bsl 7) bor PartialTag,
+ {TagNo, Buffer};
+% more tags
+decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck) ->
+ TagAck1 = (TagAck bsl 7) bor PartialTag,
+ 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) ->
+ {Bytes2,L2} = encode_length(LenSoFar),
+ encode_tags(Trest, [Tag,Bytes2|BytesSoFar],
+ LenSoFar + byte_size(Tag) + L2);
+encode_tags([], BytesSoFar, LenSoFar) ->
+ {BytesSoFar,LenSoFar}.
+
+encode_tags(TagIn, {BytesSoFar,LenSoFar}) ->
+ encode_tags(TagIn, BytesSoFar, LenSoFar).
+
+%%===============================================================================
+%%
+%% 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
+
+encode_open_type(Val, T) when is_list(Val) ->
+ encode_open_type(list_to_binary(Val), T);
+encode_open_type(Val, []) ->
+ {Val,byte_size(Val)};
+encode_open_type(Val, Tag) ->
+ encode_tags(Tag, Val, byte_size(Val)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Tlv, TagIn) -> Value
+%% Tlv = {Tag,V} | V where V -> binary()
+%% TagIn = [TagVal] where TagVal -> int()
+%% Value = binary with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Tlv, TagIn) ->
+ case match_tags(Tlv, TagIn) of
+ Bin when is_binary(Bin) ->
+ {InnerTlv,_} = ber_decode_nif(Bin),
+ InnerTlv;
+ TlvBytes -> TlvBytes
+ end.
+
+decode_open_type_as_binary(Tlv, TagIn)->
+ ber_encode(match_tags(Tlv, TagIn)).
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Boolean, ITU_T X.690 Chapter 8.2
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len}
+%%===============================================================================
+
+encode_boolean(true, TagIn) ->
+ encode_tags(TagIn, [16#FF],1);
+encode_boolean(false, TagIn) ->
+ encode_tags(TagIn, [0],1);
+encode_boolean(X,_) ->
+ exit({error,{asn1, {encode_boolean, X}}}).
+
+
+%%===============================================================================
+%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
+%% {false, Remain, RemovedBytes}
+%%===============================================================================
+decode_boolean(Tlv,TagIn) ->
+ Val = match_tags(Tlv, TagIn),
+ case Val of
+ <<0:8>> ->
+ false;
+ <<_:8>> ->
+ true;
+ _ ->
+ exit({error,{asn1, {decode_boolean, Val}}})
+ end.
+
+
+%%===========================================================================
+%% 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(Val, Tag) when is_integer(Val) ->
+ encode_tags(Tag, encode_integer(Val));
+encode_integer(Val, _Tag) ->
+ exit({error,{asn1,{encode_integer,Val}}}).
+
+
+encode_integer(Val, NamedNumberList, Tag) when is_atom(Val) ->
+ case lists:keyfind(Val, 1, NamedNumberList) of
+ {_, NewVal} ->
+ encode_tags(Tag, encode_integer(NewVal));
+ _ ->
+ exit({error,{asn1, {encode_integer_namednumber, Val}}})
+ end;
+encode_integer(Val, _NamedNumberList, Tag) ->
+ encode_tags(Tag, 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, [B|_Acc]=L) when B < 128 ->
+ L;
+encode_integer_pos(N, Acc) ->
+ encode_integer_pos((N bsr 8), [N band 16#ff| Acc]).
+
+encode_integer_neg(-1, [B1|_T]=L) when B1 > 127 ->
+ L;
+encode_integer_neg(N, Acc) ->
+ encode_integer_neg(N bsr 8, [N band 16#ff|Acc]).
+
+%%===============================================================================
+%% decode integer
+%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%%===============================================================================
+
+decode_named_integer(Tlv, NamedNumberList, TagIn) ->
+ V = match_tags(Tlv, TagIn),
+ Int = decode_integer(V),
+ number2name(Int, NamedNumberList).
+
+decode_named_integer(Tlv, Range, NamedNumberList, TagIn) ->
+ V = match_tags(Tlv, TagIn),
+ Int = range_check_integer(decode_integer(V), Range),
+ number2name(Int, NamedNumberList).
+
+decode_integer(Tlv, TagIn) ->
+ V = match_tags(Tlv, TagIn),
+ decode_integer(V).
+
+decode_integer(Tlv, Range, TagIn) ->
+ V = match_tags(Tlv, TagIn),
+ Int = decode_integer(V),
+ range_check_integer(Int, Range).
+
+decode_integer(Bin) ->
+ Len = byte_size(Bin),
+ <<Int:Len/signed-unit:8>> = Bin,
+ Int.
+
+range_check_integer(Int, {Lb,Ub}) when Lb =< Int, Int =< Ub ->
+ Int;
+range_check_integer(Int, Range) ->
+ exit({error,{asn1,{integer_range,Range,Int}}}).
+
+number2name(Int, []) ->
+ Int;
+number2name(Int, NamedNumberList) ->
+ case lists:keyfind(Int, 2, NamedNumberList) of
+ {NamedVal,_} ->
+ NamedVal;
+ _ ->
+ Int
+ end.
+
+
+%%============================================================================
+%% Enumerated value, ITU_T X.690 Chapter 8.4
+
+%% encode enumerated value
+%%============================================================================
+encode_enumerated(Val, TagIn) when is_integer(Val) ->
+ encode_tags(TagIn, encode_integer(Val)).
+
+%%============================================================================
+%% decode enumerated value
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value
+%%===========================================================================
+decode_enumerated(Tlv, NamedNumberList, Tags) ->
+ Buffer = match_tags(Tlv, Tags),
+ decode_enumerated_notag(Buffer, NamedNumberList, Tags).
+
+decode_enumerated_notag(Buffer, {NamedNumberList,ExtList}, _Tags) ->
+ IVal = decode_integer(Buffer),
+ case decode_enumerated1(IVal, NamedNumberList) of
+ {asn1_enum,IVal} ->
+ decode_enumerated1(IVal,ExtList);
+ EVal ->
+ EVal
+ end;
+decode_enumerated_notag(Buffer, NNList, _Tags) ->
+ IVal = decode_integer(Buffer),
+ case decode_enumerated1(IVal, NNList) of
+ {asn1_enum,_} ->
+ exit({error,{asn1, {illegal_enumerated, IVal}}});
+ EVal ->
+ EVal
+ end.
+
+decode_enumerated1(Val, NamedNumberList) ->
+ %% it must be a named integer
+ case lists:keyfind(Val, 2, NamedNumberList) of
+ {NamedVal, _} ->
+ NamedVal;
+ _ ->
+ {asn1_enum,Val}
+ 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_bit_string(C, Bits, NamedBitList, TagIn) when is_bitstring(Bits) ->
+ PadLen = (8 - (bit_size(Bits) band 7)) band 7,
+ Compact = {PadLen,<<Bits/bitstring,0:PadLen>>},
+ encode_bin_bit_string(C, Compact, NamedBitList, TagIn);
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,TagIn) when is_integer(Unused), is_binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList,TagIn);
+encode_bit_string(C, [FirstVal | RestVal], NamedBitList, TagIn) when is_atom(FirstVal) ->
+ encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, TagIn) ->
+ encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(C, [FirstVal| RestVal], NamedBitList, TagIn) when is_integer(FirstVal) ->
+ encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(_C, 0, _NamedBitList, TagIn) ->
+ encode_tags(TagIn, <<0>>,1);
+
+encode_bit_string(_C, [], _NamedBitList, TagIn) ->
+ encode_tags(TagIn, <<0>>,1);
+
+encode_bit_string(C, IntegerVal, NamedBitList, TagIn) when is_integer(IntegerVal) ->
+ BitListVal = int_to_bitlist(IntegerVal),
+ encode_bit_string_bits(C, BitListVal, NamedBitList, TagIn).
+
+
+int_to_bitlist(0) ->
+ [];
+int_to_bitlist(Int) when is_integer(Int), Int >= 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)].
+
+
+%%=================================================================
+%% Encode BIT STRING of the form {Unused,BinBits}.
+%% Unused is the number of unused bits in the last byte in BinBits
+%% and BinBits is a binary representing the BIT STRING.
+%%=================================================================
+encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,TagIn)->
+ case C of
+ [] ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits);
+ {_Min,Max} ->
+ BBLen = (byte_size(BinBits)*8)-Unused,
+ if
+ BBLen > Max ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBLen},{maximum,Max}}}}});
+ true ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits)
+ end;
+ Size ->
+ case ((byte_size(BinBits)*8)-Unused) of
+ BBSize when BBSize =< Size ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits);
+ BBSize ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBSize},{should_be,Size}}}}})
+ end
+ end.
+
+remove_unused_then_dotag(TagIn,Unused,BinBits) ->
+ case Unused of
+ 0 when byte_size(BinBits) =:= 0 ->
+ encode_tags(TagIn, <<0>>, 1);
+ 0 ->
+ Bin = <<Unused,BinBits/binary>>,
+ encode_tags(TagIn, Bin, byte_size(Bin));
+ Num ->
+ N = byte_size(BinBits)-1,
+ <<BBits:N/binary,LastByte>> = BinBits,
+ encode_tags(TagIn,
+ [Unused,binary_to_list(BBits) ++[(LastByte bsr Num) bsl Num]],
+ 1+byte_size(BinBits))
+ end.
+
+
+%%=================================================================
+%% Encode named bits
+%%=================================================================
+
+encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ Size =
+ case C of
+ [] ->
+ lists:max(ToSetPos)+1;
+ {_Min,Max} ->
+ Max;
+ TSize ->
+ TSize
+ end,
+ BitList = make_and_set_list(Size, ToSetPos, 0),
+ {Len, Unused, OctetList} = encode_bitstring(BitList),
+ encode_tags(TagIn, [Unused|OctetList],Len+1).
+
+
+%%----------------------------------------
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+%%----------------------------------------
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+get_all_bitposes([Val | Rest], NamedBitList, Ack) when is_atom(Val) ->
+ case lists:keyfind(Val, 1, NamedBitList) of
+ {_ValName, ValPos} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+
+%%----------------------------------------
+%% 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),
+%%----------------------------------------
+
+make_and_set_list(0, [], _) -> [];
+make_and_set_list(0, _, _) ->
+ exit({error,{asn1,bitstring_sizeconstraint}});
+make_and_set_list(Len, [XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
+make_and_set_list(Len, [Pos|SetPos], XPos) ->
+ [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
+make_and_set_list(Len, [], XPos) ->
+ [0 | make_and_set_list(Len - 1, [], XPos + 1)].
+
+
+
+
+
+
+%%=================================================================
+%% Encode bit string for lists of ones and zeroes
+%%=================================================================
+encode_bit_string_bits(C, BitListVal, _NamedBitList, TagIn) when is_list(BitListVal) ->
+ case C of
+ [] ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ Constr={Min,_Max} when is_integer(Min) ->
+ %% Max may be an integer or 'MAX'
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ {Constr={_,_},[]} ->%Constr={Min,Max}
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ Size when is_integer(Size) ->
+ case length(BitListVal) of
+ BitSize when BitSize == Size ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ BitSize when BitSize < Size ->
+ PaddedList = pad_bit_list(Size-BitSize,BitListVal),
+ {Len, Unused, OctetList} = encode_bitstring(PaddedList),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ BitSize ->
+ exit({error,{asn1,
+ {bitstring_length, {{was,BitSize},{should_be,Size}}}}})
+ end
+
+ end.
+
+encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,TagIn) ->
+ BitLen = length(BitListVal),
+ case BitLen of
+ Len when Len > Max2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max2}}}}});
+ Len when Len > Max1, Len < Min2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {not_allowed_interval,
+ Max1,Min2}}}}});
+ _ ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused, OctetList], Len+1)
+ end;
+encode_constr_bit_str_bits({Min,Max},BitListVal,TagIn) ->
+ BitLen = length(BitListVal),
+ if
+ BitLen > Max ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max}}}}});
+ BitLen < Min ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {minimum,Max}}}}});
+ true ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused, OctetList], Len+1)
+ end.
+
+
+%% returns a list of length Size + length(BitListVal), with BitListVal
+%% as the most significant elements followed by padded zero elements
+pad_bit_list(Size, BitListVal) ->
+ Tail = lists:duplicate(Size,0),
+ lists:append(BitListVal, Tail).
+
+%%=================================================================
+%% Do the actual encoding
+%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
+%%=================================================================
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Val], 1);
+encode_bitstring(Val) ->
+ {Unused, Octet} = unused_bitlist(Val, 7, 0),
+ {1, Unused, [Octet]}.
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Ack | [Val]], Len + 1);
+%%even multiple of 8 bits..
+encode_bitstring([], Ack, Len) ->
+ {Len, 0, Ack};
+%% unused bits in last octet
+encode_bitstring(Rest, Ack, Len) ->
+ {Unused, Val} = unused_bitlist(Rest, 7, 0),
+ {Len + 1, Unused, [Ack | [Val]]}.
+
+%%%%%%%%%%%%%%%%%%
+%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
+%% {Unused bits, Last octet with bits moved to right}
+unused_bitlist([], Trail, Ack) ->
+ {Trail + 1, Ack};
+unused_bitlist([Bit | Rest], Trail, Ack) ->
+ unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
+
+
+%%============================================================================
+%% decode bitstring value
+%%============================================================================
+
+decode_compact_bit_string(Buffer, Range, Tags) ->
+ case match_and_collect(Buffer, Tags) of
+ <<0>> ->
+ check_restricted_string({0,<<>>}, 0, Range);
+ <<Unused,Bits/binary>> ->
+ Val = {Unused,Bits},
+ Len = bit_size(Bits) - Unused,
+ check_restricted_string(Val, Len, Range)
+ end.
+
+decode_legacy_bit_string(Buffer, Range, Tags) ->
+ Val = case match_and_collect(Buffer, Tags) of
+ <<0>> ->
+ [];
+ <<Unused,Bits/binary>> ->
+ decode_bitstring2(byte_size(Bits), Unused, Bits)
+ end,
+ check_restricted_string(Val, length(Val), Range).
+
+decode_native_bit_string(Buffer, Range, Tags) ->
+ case match_and_collect(Buffer, Tags) of
+ <<0>> ->
+ check_restricted_string(<<>>, 0, Range);
+ <<Unused,Bits/binary>> ->
+ Size = bit_size(Bits) - Unused,
+ <<Val:Size/bitstring,_:Unused/bitstring>> = Bits,
+ check_restricted_string(Val, Size, Range)
+ end.
+
+decode_named_bit_string(Buffer, NamedNumberList, Tags) ->
+ case match_and_collect(Buffer, Tags) of
+ <<0>> ->
+ [];
+ <<Unused,Bits/binary>> ->
+ BitString = decode_bitstring2(byte_size(Bits), Unused, Bits),
+ decode_bitstring_NNL(BitString, NamedNumberList)
+ end.
+
+%%----------------------------------------
+%% Decode the in buffer to bits
+%%----------------------------------------
+decode_bitstring2(1, Unused,
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
+ lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0], 8-Unused);
+decode_bitstring2(Len, Unused,
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
+ [B7,B6,B5,B4,B3,B2,B1,B0|
+ decode_bitstring2(Len - 1, Unused, Buffer)].
+
+%%----------------------------------------
+%% Decode the bitlist to names
+%%----------------------------------------
+
+decode_bitstring_NNL(BitList, NamedNumberList) ->
+ decode_bitstring_NNL(BitList, NamedNumberList, 0, []).
+
+
+decode_bitstring_NNL([],_,_No,Result) ->
+ lists:reverse(Result);
+decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
+ if
+ B =:= 0 ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
+ true ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
+ end;
+decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
+decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
+
+%%============================================================================
+%% Null value, ITU_T X.690 Chapter 8.8
+%%
+%% encode NULL value
+%%============================================================================
+
+encode_null(_Val, TagIn) ->
+ encode_tags(TagIn, [], 0).
+
+%%============================================================================
+%% decode NULL value
+%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
+%%============================================================================
+
+decode_null(Tlv, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ case Val of
+ <<>> ->
+ 'NULL';
+ _ ->
+ exit({error,{asn1,{decode_null,Val}}})
+ end.
+
+%%============================================================================
+%% Object identifier, ITU_T X.690 Chapter 8.19
+%%
+%% encode Object Identifier value
+%%============================================================================
+
+encode_object_identifier(Val, TagIn) ->
+ encode_tags(TagIn, e_object_identifier(Val)).
+
+e_object_identifier({'OBJECT IDENTIFIER', V}) ->
+ e_object_identifier(V);
+e_object_identifier(V) when is_tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%%%%%%%%%%%%%%%
+%% e_object_identifier([List of Obect Identifiers]) ->
+%% {[Encoded Octetlist of ObjIds], IntLength}
+%%
+e_object_identifier([E1,E2|Tail]) ->
+ Head = 40*E1 + E2, % wow!
+ {H,Lh} = mk_object_val(Head),
+ {R,Lr} = lists:mapfoldl(fun enc_obj_id_tail/2, 0, Tail),
+ {[H|R],Lh+Lr}.
+
+enc_obj_id_tail(H, Len) ->
+ {B,L} = mk_object_val(H),
+ {B,Len+L}.
+
+
+%%%%%%%%%%%
+%% mk_object_val(Value) -> {OctetList, Len}
+%% returns a Val as a list of octets, the 8th bit is always set to one
+%% except for the last octet, where it's 0
+%%
+
+
+mk_object_val(Val) when Val =< 127 ->
+ {[255 band Val], 1};
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [Val band 127], 1).
+mk_object_val(0, Ack, Len) ->
+ {Ack, Len};
+mk_object_val(Val, Ack, Len) ->
+ mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
+
+
+
+%%============================================================================
+%% decode Object Identifier value
+%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
+%%============================================================================
+
+decode_object_identifier(Tlv, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ [AddedObjVal|ObjVals] = dec_subidentifiers(Val,0,[]),
+ {Val1, Val2} = if
+ AddedObjVal < 40 ->
+ {0, AddedObjVal};
+ AddedObjVal < 80 ->
+ {1, AddedObjVal - 40};
+ true ->
+ {2, AddedObjVal - 80}
+ end,
+ list_to_tuple([Val1, Val2 | ObjVals]).
+
+dec_subidentifiers(<<>>,_Av,Al) ->
+ lists:reverse(Al);
+dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) ->
+ dec_subidentifiers(T,(Av bsl 7) + H,Al);
+dec_subidentifiers(<<H,T/binary>>,Av,Al) ->
+ dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
+
+%%============================================================================
+%% RELATIVE-OID, ITU_T X.690 Chapter 8.20
+%%
+%% encode Relative Object Identifier
+%%============================================================================
+
+encode_relative_oid(Val,TagIn) when is_tuple(Val) ->
+ encode_relative_oid(tuple_to_list(Val),TagIn);
+encode_relative_oid(Val,TagIn) ->
+ encode_tags(TagIn, enc_relative_oid(Val)).
+
+enc_relative_oid(Tuple) when is_tuple(Tuple) ->
+ enc_relative_oid(tuple_to_list(Tuple));
+enc_relative_oid(Val) ->
+ lists:mapfoldl(fun(X,AccIn) ->
+ {SO,L} = mk_object_val(X),
+ {SO,L+AccIn}
+ end, 0, Val).
+
+%%============================================================================
+%% decode Relative Object Identifier value
+%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
+%%============================================================================
+decode_relative_oid(Tlv, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ ObjVals = dec_subidentifiers(Val,0,[]),
+ list_to_tuple(ObjVals).
+
+%%============================================================================
+%% Restricted character string types, ITU_T X.690 Chapter 8.20
+%%
+%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%%============================================================================
+encode_restricted_string(OctetList, TagIn) when is_binary(OctetList) ->
+ encode_tags(TagIn, OctetList, byte_size(OctetList));
+encode_restricted_string(OctetList, TagIn) when is_list(OctetList) ->
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+%%============================================================================
+%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%%============================================================================
+
+decode_restricted_string(Tlv, TagsIn) ->
+ Bin = match_and_collect(Tlv, TagsIn),
+ binary_to_list(Bin).
+
+decode_restricted_string(Tlv, Range, TagsIn) ->
+ Bin = match_and_collect(Tlv, TagsIn),
+ check_restricted_string(binary_to_list(Bin), byte_size(Bin), Range).
+
+check_restricted_string(Val, _Len, []) ->
+ Val;
+check_restricted_string(Val, Len, {Lb,Ub}) when Lb =< Len, Len =< Ub ->
+ Val;
+check_restricted_string(Val, Len, Len) ->
+ Val;
+check_restricted_string(Val, _Len, Range) ->
+ exit({error,{asn1,{length,Range,Val}}}).
+
+%%============================================================================
+%% encode Universal string
+%%============================================================================
+
+encode_universal_string(Universal, TagIn) ->
+ OctetList = mk_uni_list(Universal),
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+mk_uni_list(In) ->
+ mk_uni_list(In,[]).
+
+mk_uni_list([],List) ->
+ lists:reverse(List);
+mk_uni_list([{A,B,C,D}|T],List) ->
+ mk_uni_list(T,[D,C,B,A|List]);
+mk_uni_list([H|T],List) ->
+ mk_uni_list(T,[H,0,0,0|List]).
+
+%%===========================================================================
+%% decode Universal strings
+%% (Buffer, Range, StringType, HasTag, LenIn) ->
+%% {String, Remain, RemovedBytes}
+%%===========================================================================
+
+decode_universal_string(Buffer, Range, Tags) ->
+ Bin = match_and_collect(Buffer, Tags),
+ Val = mk_universal_string(binary_to_list(Bin)),
+ check_restricted_string(Val, length(Val), Range).
+
+mk_universal_string(In) ->
+ mk_universal_string(In, []).
+
+mk_universal_string([], Acc) ->
+ lists:reverse(Acc);
+mk_universal_string([0,0,0,D|T], Acc) ->
+ mk_universal_string(T, [D|Acc]);
+mk_universal_string([A,B,C,D|T], Acc) ->
+ mk_universal_string(T, [{A,B,C,D}|Acc]).
+
+
+%%============================================================================
+%% encode UTF8 string
+%%============================================================================
+
+encode_UTF8_string(UTF8String, TagIn) when is_binary(UTF8String) ->
+ encode_tags(TagIn, UTF8String, byte_size(UTF8String));
+encode_UTF8_string(UTF8String, TagIn) ->
+ encode_tags(TagIn, UTF8String, length(UTF8String)).
+
+
+%%============================================================================
+%% decode UTF8 string
+%%============================================================================
+
+decode_UTF8_string(Tlv,TagsIn) ->
+ Val = match_tags(Tlv, TagsIn),
+ case Val of
+ [_|_]=PartList -> % constructed val
+ collect_parts(PartList);
+ Bin ->
+ Bin
+ end.
+
+
+%%============================================================================
+%% encode BMP string
+%%============================================================================
+
+encode_BMP_string(BMPString, TagIn) ->
+ OctetList = mk_BMP_list(BMPString),
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+mk_BMP_list(In) ->
+ mk_BMP_list(In, []).
+
+mk_BMP_list([],List) ->
+ lists:reverse(List);
+mk_BMP_list([{0,0,C,D}|T], List) ->
+ mk_BMP_list(T, [D,C|List]);
+mk_BMP_list([H|T], List) ->
+ mk_BMP_list(T, [H,0|List]).
+
+%%============================================================================
+%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
+%% (Buffer, Range, StringType, HasTag, TotalLen) ->
+%% {String, Remain, RemovedBytes}
+%%============================================================================
+decode_BMP_string(Buffer, Range, Tags) ->
+ Bin = match_and_collect(Buffer, Tags),
+ Val = mk_BMP_string(binary_to_list(Bin)),
+ check_restricted_string(Val, length(Val), Range).
+
+mk_BMP_string(In) ->
+ mk_BMP_string(In,[]).
+
+mk_BMP_string([], US) ->
+ lists:reverse(US);
+mk_BMP_string([0,B|T], US) ->
+ mk_BMP_string(T, [B|US]);
+mk_BMP_string([C,D|T], US) ->
+ mk_BMP_string(T, [{0,0,C,D}|US]).
+
+%%============================================================================
+%% Length handling
+%%
+%% Encode length
+%%
+%% encode_length(Int) ->
+%% [<127]| [128 + Int (<127),OctetList] | [16#80]
+%%============================================================================
+
+encode_length(L) when L =< 16#7F ->
+ {[L],1};
+encode_length(L) ->
+ Oct = minimum_octets(L),
+ Len = length(Oct),
+ if
+ Len =< 126 ->
+ {[16#80 bor Len|Oct],Len+1};
+ true ->
+ exit({error,{asn1, too_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 16#FF|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,Length:LL/unit:8,T/binary>>) ->
+ {Length,T}.
+
+%% dynamicsort_SET_components(Arg) ->
+%% Res Arg -> list()
+%% Res -> list()
+%% Sorts the elements in Arg according to the encoded tag in
+%% increasing order.
+dynamicsort_SET_components(ListOfEncCs) ->
+ TagBinL = [begin
+ Bin = list_to_binary(L),
+ {dynsort_decode_tag(Bin),Bin}
+ end || L <- ListOfEncCs],
+ [E || {_,E} <- lists:keysort(1, TagBinL)].
+
+%% dynamicsort_SETOF(Arg) -> Res
+%% Arg -> list()
+%% Res -> list()
+%% Sorts the elements in Arg in increasing size
+dynamicsort_SETOF(ListOfEncVal) ->
+ BinL = lists:map(fun(L) when is_list(L) -> list_to_binary(L);
+ (B) -> B end, ListOfEncVal),
+ lists:sort(BinL).
+
+%% multiple octet tag
+dynsort_decode_tag(<<Class:2,_Form:1,31:5,Buffer/binary>>) ->
+ TagNum = dynsort_decode_tag(Buffer, 0),
+ {Class,TagNum};
+
+%% single tag (< 31 tags)
+dynsort_decode_tag(<<Class:2,_Form:1,TagNum:5,_/binary>>) ->
+ {Class,TagNum}.
+
+dynsort_decode_tag(<<0:1,PartialTag:7,_/binary>>, TagAcc) ->
+ (TagAcc bsl 7) bor PartialTag;
+dynsort_decode_tag(<<_:1,PartialTag:7,Buffer/binary>>, TagAcc0) ->
+ TagAcc = (TagAcc0 bsl 7) bor PartialTag,
+ dynsort_decode_tag(Buffer, TagAcc).
+
+
+%%-------------------------------------------------------------------------
+%% INTERNAL HELPER FUNCTIONS (not exported)
+%%-------------------------------------------------------------------------
+
+match_and_collect(Tlv, TagsIn) ->
+ Val = match_tags(Tlv, TagsIn),
+ case Val of
+ [_|_]=PartList -> % constructed val
+ collect_parts(PartList);
+ Bin when is_binary(Bin) ->
+ Bin
+ end.
+
+collect_parts(TlvList) ->
+ collect_parts(TlvList, []).
+
+collect_parts([{_,L}|Rest], Acc) when is_list(L) ->
+ collect_parts(Rest, [collect_parts(L)|Acc]);
+collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest], _Acc) ->
+ collect_parts_bit(Rest, [Bits], Unused);
+collect_parts([{_T,V}|Rest], Acc) ->
+ collect_parts(Rest, [V|Acc]);
+collect_parts([], Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest], Acc, Uacc) ->
+ collect_parts_bit(Rest, [Bits|Acc], Unused+Uacc);
+collect_parts_bit([], Acc, Uacc) ->
+ list_to_binary([Uacc|lists:reverse(Acc)]).
diff --git a/lib/asn1/src/asn1rtt_check.erl b/lib/asn1/src/asn1rtt_check.erl
new file mode 100644
index 0000000000..e78b65a8fb
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_check.erl
@@ -0,0 +1,276 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. 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%
+%%
+-module(asn1rtt_check).
+
+-export([check_bool/2,
+ check_int/3,
+ check_bitstring/3,
+ check_octetstring/2,
+ check_null/2,
+ check_objectidentifier/2,
+ check_objectdescriptor/2,
+ check_real/2,
+ check_enum/3,
+ check_restrictedstring/2]).
+
+check_bool(_Bool, asn1_DEFAULT) ->
+ true;
+check_bool(Bool, Bool) when is_boolean(Bool) ->
+ true;
+check_bool(_Bool1, Bool2) ->
+ throw({error,Bool2}).
+
+check_int(_, asn1_DEFAULT, _) ->
+ true;
+check_int(Value, Value, _) when is_integer(Value) ->
+ true;
+check_int(DefValue, Value, NNL) when is_atom(Value) ->
+ case lists:keyfind(Value, 1, NNL) of
+ {_,DefValue} ->
+ true;
+ _ ->
+ throw({error,DefValue})
+ end;
+check_int(DefaultValue, _Value, _) ->
+ throw({error,DefaultValue}).
+
+%% Two equal lists or integers
+check_bitstring(_, asn1_DEFAULT, _) ->
+ true;
+check_bitstring(V, V, _) ->
+ true;
+%% Default value as a list of 1 and 0 and user value as an integer
+check_bitstring(L=[H|T], Int, _) when is_integer(Int), is_integer(H) ->
+ case bit_list_to_int(L, length(T)) of
+ Int -> true;
+ _ -> throw({error,L,Int})
+ end;
+%% Default value as an integer, val as list
+check_bitstring(Int, Val, NBL) when is_integer(Int), is_list(Val) ->
+ BL = int_to_bit_list(Int, [], length(Val)),
+ check_bitstring(BL, Val, NBL);
+%% Default value and user value as lists of ones and zeros
+check_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL=[_H|_T]) when is_integer(H1), is_integer(H2) ->
+ L2new = remove_trailing_zeros(L2),
+ check_bitstring(L1, L2new, NBL);
+%% Default value as a list of 1 and 0 and user value as a list of atoms
+check_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL) when is_integer(H1), is_atom(H2) ->
+ L3 = bit_list_to_nbl(L1, NBL, 0, []),
+ check_bitstring(L3, L2, NBL);
+%% Both default value and user value as a list of atoms
+check_bitstring(L1=[H1|T1], L2=[H2|_T2], _)
+ when is_atom(H1), is_atom(H2), length(L1) =:= length(L2) ->
+ case lists:member(H1, L2) of
+ true ->
+ check_bitstring1(T1, L2);
+ false -> throw({error,L2})
+ end;
+%% Default value as a list of atoms and user value as a list of 1 and 0
+check_bitstring(L1=[H1|_T1], L2=[H2|_T2], NBL) when is_atom(H1), is_integer(H2) ->
+ L3 = bit_list_to_nbl(L2, NBL, 0, []),
+ check_bitstring(L1, L3, NBL);
+%% User value in compact format
+check_bitstring(DefVal,CBS={_,_}, NBL) ->
+ NewVal = cbs_to_bit_list(CBS),
+ check_bitstring(DefVal, NewVal, NBL);
+check_bitstring(DV, V, _) ->
+ throw({error,DV,V}).
+
+
+bit_list_to_int([0|Bs], ShL)->
+ bit_list_to_int(Bs, ShL-1) + 0;
+bit_list_to_int([1|Bs], ShL) ->
+ bit_list_to_int(Bs, ShL-1) + (1 bsl ShL);
+bit_list_to_int([], _) ->
+ 0.
+
+int_to_bit_list(0, Acc, 0) ->
+ Acc;
+int_to_bit_list(Int, Acc, Len) ->
+ int_to_bit_list(Int bsr 1, [Int band 1|Acc], Len - 1).
+
+bit_list_to_nbl([0|T], NBL, Pos, Acc) ->
+ bit_list_to_nbl(T, NBL, Pos+1, Acc);
+bit_list_to_nbl([1|T], NBL, Pos, Acc) ->
+ case lists:keyfind(Pos, 2, NBL) of
+ {N,_} ->
+ bit_list_to_nbl(T, NBL, Pos+1, [N|Acc]);
+ _ ->
+ throw({error,{no,named,element,at,pos,Pos}})
+ end;
+bit_list_to_nbl([], _, _, Acc) ->
+ Acc.
+
+remove_trailing_zeros(L2) ->
+ remove_trailing_zeros1(lists:reverse(L2)).
+remove_trailing_zeros1(L) ->
+ lists:reverse(lists:dropwhile(fun(0)->true;
+ (_) ->false
+ end,
+ L)).
+
+check_bitstring1([H|T], NBL) ->
+ case lists:member(H, NBL) of
+ true -> check_bitstring1(T, NBL);
+ V -> throw({error,V})
+ end;
+check_bitstring1([], _) ->
+ true.
+
+cbs_to_bit_list({Unused, <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when byte_size(Rest) >= 1 ->
+ [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})];
+cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) ->
+ [B7,B6,B5,B4,B3,B2,B1,B0];
+cbs_to_bit_list({Unused,Bin}) when byte_size(Bin) =:= 1 ->
+ Used = 8-Unused,
+ <<Int:Used,_:Unused>> = Bin,
+ int_to_bit_list(Int, [], Used).
+
+
+check_octetstring(_, asn1_DEFAULT) ->
+ true;
+check_octetstring(L, L) ->
+ true;
+check_octetstring(L, Int) when is_list(L), is_integer(Int) ->
+ case integer_to_octetlist(Int) of
+ L -> true;
+ V -> throw({error,V})
+ end;
+check_octetstring(_, V) ->
+ throw({error,V}).
+
+integer_to_octetlist(Int) ->
+ integer_to_octetlist(Int, []).
+integer_to_octetlist(0, Acc) ->
+ Acc;
+integer_to_octetlist(Int, Acc) ->
+ integer_to_octetlist(Int bsr 8, [(Int band 255)|Acc]).
+
+check_null(_, asn1_DEFAULT) ->
+ true;
+check_null('NULL', 'NULL') ->
+ true;
+check_null(_, V) ->
+ throw({error,V}).
+
+check_objectidentifier(_, asn1_DEFAULT) ->
+ true;
+check_objectidentifier(OI, OI) ->
+ true;
+check_objectidentifier(DOI, OI) when is_tuple(DOI), is_tuple(OI) ->
+ check_objectidentifier1(tuple_to_list(DOI), tuple_to_list(OI));
+check_objectidentifier(_, OI) ->
+ throw({error,OI}).
+
+check_objectidentifier1([V|Rest1], [V|Rest2]) ->
+ check_objectidentifier1(Rest1, Rest2, V);
+check_objectidentifier1([V1|Rest1], [V2|Rest2]) ->
+ case reserved_objectid(V2, []) of
+ V1 ->
+ check_objectidentifier1(Rest1, Rest2, [V1]);
+ V ->
+ throw({error,V})
+ end.
+check_objectidentifier1([V|Rest1], [V|Rest2], Above) ->
+ check_objectidentifier1(Rest1, Rest2, [V|Above]);
+check_objectidentifier1([V1|Rest1], [V2|Rest2], Above) ->
+ case reserved_objectid(V2, Above) of
+ V1 ->
+ check_objectidentifier1(Rest1, Rest2, [V1|Above]);
+ V ->
+ throw({error,V})
+ end;
+check_objectidentifier1([], [], _) ->
+ true;
+check_objectidentifier1(_, V, _) ->
+ throw({error,object,identifier,V}).
+
+%% ITU-T Rec. X.680 Annex B - D
+reserved_objectid('itu-t', []) -> 0;
+reserved_objectid('ccitt', []) -> 0;
+%% arcs below "itu-t"
+reserved_objectid('recommendation', [0]) -> 0;
+reserved_objectid('question', [0]) -> 1;
+reserved_objectid('administration', [0]) -> 2;
+reserved_objectid('network-operator', [0]) -> 3;
+reserved_objectid('identified-organization', [0]) -> 4;
+
+reserved_objectid(iso, []) -> 1;
+%% arcs below "iso", note that number 1 is not used
+reserved_objectid('standard', [1]) -> 0;
+reserved_objectid('member-body', [1]) -> 2;
+reserved_objectid('identified-organization', [1]) -> 3;
+
+reserved_objectid('joint-iso-itu-t', []) -> 2;
+reserved_objectid('joint-iso-ccitt', []) -> 2;
+
+reserved_objectid(_, _) -> false.
+
+
+check_objectdescriptor(_, asn1_DEFAULT) ->
+ true;
+check_objectdescriptor(OD, OD) ->
+ true;
+check_objectdescriptor(OD, OD) ->
+ throw({error,{not_implemented_yet,check_objectdescriptor}}).
+
+check_real(_, asn1_DEFAULT) ->
+ true;
+check_real(R, R) ->
+ true;
+check_real(_, _) ->
+ throw({error,{not_implemented_yet,check_real}}).
+
+check_enum(_, asn1_DEFAULT, _) ->
+ true;
+check_enum(Val, Val, _) ->
+ true;
+check_enum(Int, Atom, Enumerations) when is_integer(Int), is_atom(Atom) ->
+ case lists:keyfind(Atom, 1, Enumerations) of
+ {_,Int} -> true;
+ _ -> throw({error,{enumerated,Int,Atom}})
+ end;
+check_enum(DefVal, Val, _) ->
+ throw({error,{enumerated,DefVal,Val}}).
+
+
+check_restrictedstring(_, asn1_DEFAULT) ->
+ true;
+check_restrictedstring(Val, Val) ->
+ true;
+check_restrictedstring([V|Rest1], [V|Rest2]) ->
+ check_restrictedstring(Rest1, Rest2);
+check_restrictedstring([V1|Rest1], [V2|Rest2]) ->
+ check_restrictedstring(V1, V2),
+ check_restrictedstring(Rest1, Rest2);
+%% tuple format of value
+check_restrictedstring({V1,V2}, [V1,V2]) ->
+ true;
+check_restrictedstring([V1,V2], {V1,V2}) ->
+ true;
+%% quadruple format of value
+check_restrictedstring({V1,V2,V3,V4}, [V1,V2,V3,V4]) ->
+ true;
+check_restrictedstring([V1,V2,V3,V4], {V1,V2,V3,V4}) ->
+ true;
+%% character string list
+check_restrictedstring(V1, V2) when is_list(V1), is_tuple(V2) ->
+ check_restrictedstring(V1, tuple_to_list(V2));
+check_restrictedstring(V1, V2) ->
+ throw({error,{restricted,string,V1,V2}}).
diff --git a/lib/asn1/src/asn1rtt_ext.erl b/lib/asn1/src/asn1rtt_ext.erl
new file mode 100644
index 0000000000..46adb2007d
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_ext.erl
@@ -0,0 +1,72 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+
+-module(asn1rtt_ext).
+-export([transform_to_EXTERNAL1990/1,transform_to_EXTERNAL1994/1]).
+
+transform_to_EXTERNAL1990({_,_,_,_}=Val) ->
+ transform_to_EXTERNAL1990(tuple_to_list(Val), []);
+transform_to_EXTERNAL1990(Val) when is_tuple(Val) ->
+ %% Data already in ASN1 1990 format
+ Val.
+
+transform_to_EXTERNAL1990(['EXTERNAL'|Rest], Acc) ->
+ transform_to_EXTERNAL1990(Rest, ['EXTERNAL'|Acc]);
+transform_to_EXTERNAL1990([{syntax,Syntax}|Rest], Acc) ->
+ transform_to_EXTERNAL1990(Rest, [asn1_NOVALUE,Syntax|Acc]);
+transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest], Acc) ->
+ transform_to_EXTERNAL1990(Rest, [PCid,asn1_NOVALUE|Acc]);
+transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest], Acc) ->
+ {_,Presentation_Cid,Transfer_syntax} = Context_negot,
+ transform_to_EXTERNAL1990(Rest, [Presentation_Cid,Transfer_syntax|Acc]);
+transform_to_EXTERNAL1990([asn1_NOVALUE|Rest], Acc) ->
+ transform_to_EXTERNAL1990(Rest, [asn1_NOVALUE|Acc]);
+transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc)
+ when is_list(Data_value)->
+ list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
+ Data_val_desc|Acc]));
+transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc)
+ when is_binary(Data_value) ->
+ list_to_tuple(lists:reverse([{'single-ASN1-type',Data_value},
+ Data_val_desc|Acc]));
+transform_to_EXTERNAL1990([Data_value], Acc)
+ when is_list(Data_value); is_binary(Data_value) ->
+ list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
+
+
+transform_to_EXTERNAL1994({'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}=V) ->
+ Identification =
+ case {DRef,IndRef} of
+ {DRef,asn1_NOVALUE} ->
+ {syntax,DRef};
+ {asn1_NOVALUE,IndRef} ->
+ {'presentation-context-id',IndRef};
+ _ ->
+ {'context-negotiation',
+ {'EXTERNAL_identification_context-negotiation',IndRef,DRef}}
+ end,
+ case Encoding of
+ {'octet-aligned',Val} when is_list(Val); is_binary(Val) ->
+ %% Transform to the EXTERNAL 1994 definition.
+ {'EXTERNAL',Identification,Data_v_desc,Val};
+ _ ->
+ %% Keep the EXTERNAL 1990 definition to avoid losing
+ %% information.
+ V
+ end.
diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl
new file mode 100644
index 0000000000..9f4b7500d8
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_per.erl
@@ -0,0 +1,880 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+-module(asn1rtt_per).
+
+-export([setext/1, fixextensions/2,
+ skipextensions/3,
+ set_choice/3,encode_integer/2,
+ encode_small_number/1,
+ encode_constrained_number/2,
+ encode_length/1,
+ encode_length/2,
+ encode_bit_string/3,
+ encode_object_identifier/1,
+ encode_relative_oid/1,
+ complete/1,
+ encode_open_type/1,
+ encode_GeneralString/2,
+ encode_GraphicString/2,
+ encode_TeletexString/2,
+ encode_VideotexString/2,
+ encode_ObjectDescriptor/2,
+ encode_UTF8String/1,
+ encode_octet_string/2,
+ encode_known_multiplier_string/4,
+ octets_to_complete/2]).
+
+-define('16K',16384).
+-define('32K',32768).
+-define('64K',65536).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(false) ->
+ [0];
+setext(true) ->
+ [1].
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+ [encode_small_length(ExtNum)|pre_complete_bits(ExtNum,ExtBits)]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
+ Prev = Nr - 1,
+ case ExtensionBitstr of
+ <<_:Prev,1:1,_/bitstring>> ->
+ {Len,Bytes1} = decode_length(Bytes0),
+ <<_:Len/binary,Bytes2/bitstring>> = Bytes1,
+ skipextensions(Bytes2, Nr+1, ExtensionBitstr);
+ <<_:Prev,0:1,_/bitstring>> ->
+ skipextensions(Bytes0, Nr+1, ExtensionBitstr);
+ _ ->
+ Bytes0
+ end.
+
+align(Bin) when is_binary(Bin) ->
+ Bin;
+align(BitStr) when is_bitstring(BitStr) ->
+ AlignBits = bit_size(BitStr) rem 8,
+ <<_:AlignBits,Rest/binary>> = BitStr,
+ Rest.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
+ case set_choice_tag(Alt,L1) of
+ N when is_integer(N), Len1 > 1 ->
+ [0, % the value is in the root set
+ encode_constrained_number({0,Len1-1},N)];
+ N when is_integer(N) ->
+ [0]; % no encoding if only 0 or 1 alternative
+ false ->
+ [1, % extension value
+ case set_choice_tag(Alt, L2) of
+ N2 when is_integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt, L, Len) ->
+ case set_choice_tag(Alt, L) of
+ N when is_integer(N), Len > 1 ->
+ encode_constrained_number({0,Len-1},N);
+ N when is_integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_Alt,[],_Tag) ->
+ false.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(Val) ->
+ case byte_size(Val) of
+ Size when Size > 255 ->
+ [encode_length(Size),21,<<Size:16>>,Val]; % octets implies align
+ Size ->
+ [encode_length(Size),20,Size,Val]
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint, Value) -> CompleteList
+%%
+encode_integer([{Rc,_Ec}],Val) when is_tuple(Rc) ->
+ try
+ [0|encode_integer([Rc], Val)]
+ catch
+ _:{error,{asn1,_}} ->
+ [1|encode_unconstrained_number(Val)]
+ end;
+encode_integer([], Val) ->
+ encode_unconstrained_number(Val);
+%% The constraint is the effective constraint, and in this case is a number
+encode_integer([{'SingleValue',V}], V) ->
+ [];
+encode_integer([{'ValueRange',{Lb,Ub}=VR,Range,PreEnc}],Val)
+ when Val >= Lb, Ub >= Val ->
+ %% this case when NamedNumberList
+ encode_constrained_number(VR, Range, PreEnc, Val);
+encode_integer([{'ValueRange',{Lb,'MAX'}}], Val) when Lb =< Val ->
+ encode_semi_constrained_number(Lb, Val);
+encode_integer([{'ValueRange',{'MIN',_}}], Val) ->
+ encode_unconstrained_number(Val);
+encode_integer([{'ValueRange',VR={_Lb,_Ub}}], Val) ->
+ encode_constrained_number(VR, Val);
+encode_integer(_,Val) ->
+ exit({error,{asn1,{illegal_value,Val}}}).
+
+
+%% X.691:10.6 Encoding of a normally small non-negative whole number
+%% Use this for encoding of CHOICE index if there is an extension marker in
+%% the CHOICE
+encode_small_number(Val) when Val < 64 ->
+ [10,7,Val];
+encode_small_number(Val) ->
+ [1|encode_semi_constrained_number(0, Val)].
+
+%% X.691:10.7 Encoding of a semi-constrained whole number
+encode_semi_constrained_number(Lb, Val) ->
+ Val2 = Val - Lb,
+ Oct = eint_positive(Val2),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ [20,Len+1,Len|Oct];
+ Len < 256 ->
+ [encode_length(Len),20,Len|Oct];
+ true ->
+ [encode_length(Len),21,<<Len:16>>|Oct]
+ end.
+
+encode_constrained_number({Lb,_Ub},_Range,{bits,N},Val) ->
+ Val2 = Val-Lb,
+ [10,N,Val2];
+encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) when N < 256->
+ %% N is 8 or 16 (1 or 2 octets)
+ Val2 = Val-Lb,
+ [20,N,Val2];
+encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) -> % N>255
+ %% N is 8 or 16 (1 or 2 octets)
+ Val2 = Val-Lb,
+ [21,<<N:16>>,Val2];
+encode_constrained_number({Lb,_Ub},Range,_,Val) ->
+ Val2 = Val-Lb,
+ if
+ Range =< 16#1000000 -> % max 3 octets
+ Octs = eint_positive(Val2),
+ L = length(Octs),
+ [encode_length({1,3},L),[20,L,Octs]];
+ Range =< 16#100000000 -> % max 4 octets
+ Octs = eint_positive(Val2),
+ L = length(Octs),
+ [encode_length({1,4},L),[20,L,Octs]];
+ Range =< 16#10000000000 -> % max 5 octets
+ Octs = eint_positive(Val2),
+ L = length(Octs),
+ [encode_length({1,5},L),[20,L,Octs]];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end.
+
+encode_constrained_number({Lb,Ub}, Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ if
+ Range == 1 -> [];
+ Range == 2 ->
+ [Val2];
+ Range =< 4 ->
+ [10,2,Val2];
+ Range =< 8 ->
+ [10,3,Val2];
+ Range =< 16 ->
+ [10,4,Val2];
+ Range =< 32 ->
+ [10,5,Val2];
+ Range =< 64 ->
+ [10,6,Val2];
+ Range =< 128 ->
+ [10,7,Val2];
+ Range =< 255 ->
+ [10,8,Val2];
+ Range =< 256 ->
+ [20,1,Val2];
+ Range =< 65536 ->
+ [20,2,<<Val2:16>>];
+ Range =< (1 bsl (255*8)) ->
+ Octs = binary:encode_unsigned(Val2),
+ RangeOcts = binary:encode_unsigned(Range - 1),
+ OctsLen = byte_size(Octs),
+ RangeOctsLen = byte_size(RangeOcts),
+ LengthBitsNeeded = minimum_bits(RangeOctsLen - 1),
+ [10,LengthBitsNeeded,OctsLen-1,20,OctsLen,Octs];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end;
+encode_constrained_number({_,_},Val) ->
+ exit({error,{asn1,{illegal_value,Val}}}).
+
+%% For some reason the minimum bits needed in the length field in
+%% the encoding of constrained whole numbers must always be at least 2?
+minimum_bits(N) when N < 4 -> 2;
+minimum_bits(N) when N < 8 -> 3;
+minimum_bits(N) when N < 16 -> 4;
+minimum_bits(N) when N < 32 -> 5;
+minimum_bits(N) when N < 64 -> 6;
+minimum_bits(N) when N < 128 -> 7;
+minimum_bits(_N) -> 8.
+
+%% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) ->
+ Oct = if
+ Val >= 0 ->
+ eint(Val, []);
+ true ->
+ enint(Val, [])
+ end,
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ [20,Len + 1,Len|Oct];
+ Len < 256 ->
+ [20,Len + 2,<<2:2,Len:14>>|Oct];
+ true ->
+ [encode_length(Len),21,<<Len:16>>|Oct]
+ end.
+
+%% used for positive Values which don't need a sign bit
+%% returns a list
+eint_positive(Val) ->
+ case eint(Val,[]) of
+ [0,B1|T] ->
+ [B1|T];
+ T ->
+ T
+ end.
+
+
+eint(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+eint(N, Acc) ->
+ eint(N bsr 8, [N band 16#ff| Acc]).
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(Len) -> % unconstrained
+ if
+ Len < 128 ->
+ [20,1,Len];
+ Len < 16384 ->
+ <<20,2,2:2,Len:14>>;
+ true -> % should be able to endode length >= 16384 i.e. fragmented length
+ exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end.
+
+encode_length({C,[]}, Len) ->
+ case C of
+ {Lb,Ub}=Vr when Lb =< Len, Len =< Ub ->
+ [0|encode_constrained_number(Vr, Len)];
+ _ ->
+ [1|encode_length(Len)]
+ end;
+encode_length(Len, Len) ->
+ [];
+encode_length(Vr, Len) ->
+ encode_constrained_number(Vr, Len).
+
+%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
+%% additions in a sequence or set
+encode_small_length(Len) when Len =< 64 ->
+ [10,7,Len-1];
+encode_small_length(Len) ->
+ [1,encode_length(Len)].
+
+
+decode_length(Buffer) -> % un-constrained
+ case align(Buffer) of
+ <<0:1,Oct:7,Rest/binary>> ->
+ {Oct,Rest};
+ <<2:2,Val:14,Rest/binary>> ->
+ {Val,Rest};
+ <<3:2,_Val:14,_Rest/binary>> ->
+ %% this case should be fixed
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 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 constraint Len, only valid when identifiers
+
+
+%% when the value is a list of {Unused,BinBits}, where
+%% Unused = integer(),
+%% BinBits = binary().
+
+encode_bit_string(C, Bits, NamedBitList) when is_bitstring(Bits) ->
+ PadLen = (8 - (bit_size(Bits) band 7)) band 7,
+ Compact = {PadLen,<<Bits/bitstring,0:PadLen>>},
+ encode_bin_bit_string(C, Compact, NamedBitList);
+encode_bit_string(C, {Unused,BinBits}=Bin, NamedBitList)
+ when is_integer(Unused), is_binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList);
+
+%% when the value is a list of named bits
+
+encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when is_atom(FirstVal) ->
+ ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);% consider the constraint
+
+encode_bit_string(C, BL=[{bit,_} | _RestVal], NamedBitList) ->
+ ToSetPos = get_all_bitposes(BL, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a list of ones and zeroes
+encode_bit_string(Int, BitListValue, _)
+ when is_list(BitListValue),is_integer(Int),Int =< 16 ->
+ %% The type is constrained by a single value size constraint
+ %% range_check(Int,length(BitListValue)),
+ [40,Int,length(BitListValue),BitListValue];
+encode_bit_string(Int, BitListValue, _)
+ when is_list(BitListValue),is_integer(Int), Int =< 255 ->
+ %% The type is constrained by a single value size constraint
+ %% range_check(Int,length(BitListValue)),
+ [2,40,Int,length(BitListValue),BitListValue];
+encode_bit_string(Int, BitListValue, _)
+ when is_list(BitListValue),is_integer(Int), Int < ?'64K' ->
+ {Code,DesiredLength,Length} =
+ case length(BitListValue) of
+ B1 when B1 > Int ->
+ exit({error,{'BIT_STRING_length_greater_than_SIZE',
+ Int,BitListValue}});
+ B1 when B1 =< 255,Int =< 255 ->
+ {40,Int,B1};
+ B1 when B1 =< 255 ->
+ {42,<<Int:16>>,B1};
+ B1 ->
+ {43,<<Int:16>>,<<B1:16>>}
+ end,
+ %% The type is constrained by a single value size constraint
+ [2,Code,DesiredLength,Length,BitListValue];
+encode_bit_string(no, BitListValue,[])
+ when is_list(BitListValue) ->
+ [encode_length(length(BitListValue)),
+ 2|BitListValue];
+encode_bit_string({{Fix,Fix},Ext}, BitListValue,[])
+ when is_integer(Fix), is_list(Ext) ->
+ case length(BitListValue) of
+ Len when Len =< Fix ->
+ [0|encode_bit_string(Fix, BitListValue, [])];
+ _ ->
+ [1|encode_bit_string(no, BitListValue, [])]
+ end;
+encode_bit_string(C, BitListValue,[])
+ when is_list(BitListValue) ->
+ [encode_length(C, length(BitListValue)),
+ 2|BitListValue];
+encode_bit_string(no, BitListValue,_NamedBitList)
+ when is_list(BitListValue) ->
+ %% this case with an unconstrained BIT STRING can be made more efficient
+ %% if the complete driver can take a special code so the length field
+ %% is encoded there.
+ NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitListValue))),
+ [encode_length(length(NewBitLVal)),2|NewBitLVal];
+encode_bit_string({{Fix,Fix},Ext}, BitListValue, NamedBitList)
+ when is_integer(Fix), is_list(Ext) ->
+ case length(BitListValue) of
+ Len when Len =< Fix ->
+ [0|encode_bit_string(Fix, BitListValue, NamedBitList)];
+ _ ->
+ [1|encode_bit_string(no, BitListValue, NamedBitList)]
+ end;
+encode_bit_string(C, BitListValue, _NamedBitList)
+ when is_list(BitListValue) -> % C = {_,'MAX'}
+ NewBitLVal = bit_string_trailing_zeros(BitListValue, C),
+ [encode_length(C, length(NewBitLVal)),2|NewBitLVal];
+
+
+%% when the value is an integer
+encode_bit_string(C, IntegerVal, NamedBitList) when is_integer(IntegerVal)->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string(C,BitList,NamedBitList).
+
+bit_string_trailing_zeros(BitList,C) when is_integer(C) ->
+ bit_string_trailing_zeros1(BitList,C,C);
+bit_string_trailing_zeros(BitList,{Lb,Ub}) when is_integer(Lb) ->
+ bit_string_trailing_zeros1(BitList,Lb,Ub);
+bit_string_trailing_zeros(BitList,{{Lb,Ub},_}) when is_integer(Lb) ->
+ bit_string_trailing_zeros1(BitList,Lb,Ub);
+bit_string_trailing_zeros(BitList,_) ->
+ BitList.
+
+bit_string_trailing_zeros1(BitList,Lb,Ub) ->
+ case length(BitList) of
+ Lb -> BitList;
+ B when B < Lb -> BitList++lists:duplicate(Lb-B, 0);
+ D -> F = fun(L,LB,LB,_,_)->lists:reverse(L);
+ ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
+ (L,L1,_,UB,_)when L1 =< UB -> lists:reverse(L);
+ (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
+ BitList}}) end,
+ F(lists:reverse(BitList),D,Lb,Ub,F)
+ end.
+
+%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
+%% Unused = integer(),i.e. number unused bits in least sign. byte of
+%% BinBits = binary().
+encode_bin_bit_string(C, {Unused,BinBits}, _NamedBitList)
+ when is_integer(C),C=<16 ->
+ range_check(C, bit_size(BinBits) - Unused),
+ [45,C,byte_size(BinBits),BinBits];
+encode_bin_bit_string(C, {Unused,BinBits}, _NamedBitList)
+ when is_integer(C), C =< 255 ->
+ range_check(C, bit_size(BinBits) - Unused),
+ [2,45,C,byte_size(BinBits),BinBits];
+encode_bin_bit_string(C, {Unused,BinBits}, _NamedBitList)
+ when is_integer(C), C =< 65535 ->
+ range_check(C, bit_size(BinBits) - Unused),
+ case byte_size(BinBits) of
+ Size when Size =< 255 ->
+ [2,46,<<C:16>>,Size,BinBits];
+ Size ->
+ [2,47,<<C:16>>,<<Size:16>>,BinBits]
+ end;
+encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
+ {Unused1,Bin1} =
+ %% removes all trailing bits if NamedBitList is not empty
+ remove_trailing_bin(NamedBitList,UnusedAndBin),
+ case C of
+ {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
+ Size = byte_size(Bin1),
+ [encode_length({Lb,Ub}, Size*8 - Unused1),
+ 2,octets_unused_to_complete(Unused1,Size,Bin1)];
+ no ->
+ Size = byte_size(Bin1),
+ [encode_length(Size*8 - Unused1),
+ 2|octets_unused_to_complete(Unused1, Size, Bin1)];
+ {{Fix,Fix},Ext} when is_integer(Fix),is_list(Ext) ->
+ case byte_size(Bin1)*8 - Unused1 of
+ Size when Size =< Fix ->
+ [0|encode_bin_bit_string(Fix,UnusedAndBin,NamedBitList)];
+ _Size ->
+ [1|encode_bin_bit_string(no,UnusedAndBin,NamedBitList)]
+ end;
+ Sc ->
+ Size = byte_size(Bin1),
+ [encode_length(Sc, Size*8 - Unused1),
+ 2|octets_unused_to_complete(Unused1,Size,Bin1)]
+ end.
+
+range_check(C,C) when is_integer(C) ->
+ ok;
+range_check(C1,C2) when is_integer(C1) ->
+ exit({error,{asn1,{bit_string_out_of_range,{C1,C2}}}}).
+
+remove_trailing_bin([], {Unused,Bin}) ->
+ {Unused,Bin};
+remove_trailing_bin(_NamedNumberList,{_Unused,<<>>}) ->
+ {0,<<>>};
+remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
+ Size = byte_size(Bin)-1,
+ <<Bfront:Size/binary, LastByte:8>> = Bin,
+ %% clear the Unused bits to be sure
+ Unused1 = trailingZeroesInNibble(LastByte band 15),
+ Unused2 =
+ case Unused1 of
+ 4 ->
+ 4 + trailingZeroesInNibble(LastByte bsr 4);
+ _ -> Unused1
+ end,
+ case Unused2 of
+ 8 ->
+ remove_trailing_bin(NamedNumberList,{0,Bfront});
+ _ ->
+ {Unused2,Bin}
+ end.
+
+
+trailingZeroesInNibble(0) ->
+ 4;
+trailingZeroesInNibble(1) ->
+ 0;
+trailingZeroesInNibble(2) ->
+ 1;
+trailingZeroesInNibble(3) ->
+ 0;
+trailingZeroesInNibble(4) ->
+ 2;
+trailingZeroesInNibble(5) ->
+ 0;
+trailingZeroesInNibble(6) ->
+ 1;
+trailingZeroesInNibble(7) ->
+ 0;
+trailingZeroesInNibble(8) ->
+ 3;
+trailingZeroesInNibble(9) ->
+ 0;
+trailingZeroesInNibble(10) ->
+ 1;
+trailingZeroesInNibble(11) ->
+ 0;
+trailingZeroesInNibble(12) -> %#1100
+ 2;
+trailingZeroesInNibble(13) ->
+ 0;
+trailingZeroesInNibble(14) ->
+ 1;
+trailingZeroesInNibble(15) ->
+ 0.
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(Int) when is_integer(Int), Int > 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)];
+int_to_bitlist(0) ->
+ [].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keyfind(Val, 1, NamedBitList) of
+ {_ValName, ValPos} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ false ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _) ->
+ [].
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Constraint, Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string({{Sv,Sv},Ext}=SZ, Val) when is_list(Ext), Sv =< 2 ->
+ Len = length(Val),
+ try
+ case encode_length(SZ, Len) of
+ [0|_]=EncLen ->
+ [EncLen,45,Sv*8,Sv,Val];
+ [_|_]=EncLen ->
+ [EncLen|octets_to_complete(Len, Val)]
+ end
+ catch
+ exit:{error,{asn1,{encode_length,_}}} ->
+ encode_fragmented_octet_string(Val)
+ end;
+encode_octet_string({_,_}=SZ, Val) ->
+ Len = length(Val),
+ try
+ [encode_length(SZ, Len),2|octets_to_complete(Len, Val)]
+ catch
+ exit:{error,{asn1,{encode_length,_}}} ->
+ encode_fragmented_octet_string(Val)
+ end;
+encode_octet_string(Sv, Val) when is_integer(Sv) ->
+ encode_fragmented_octet_string(Val);
+encode_octet_string(no, Val) ->
+ Len = length(Val),
+ try
+ [encode_length(Len),2|octets_to_complete(Len, Val)]
+ catch
+ exit:{error,{asn1,{encode_length,_}}} ->
+ encode_fragmented_octet_string(Val)
+ end.
+
+encode_fragmented_octet_string(Val) ->
+ Bin = iolist_to_binary(Val),
+ efos_1(Bin).
+
+efos_1(<<B1:16#C000/binary,B2:16#4000/binary,T/binary>>) ->
+ [20,1,<<3:2,4:6>>,
+ octets_to_complete(16#C000, B1),
+ octets_to_complete(16#4000, B2)|efos_1(T)];
+efos_1(<<B:16#C000/binary,T/binary>>) ->
+ [20,1,<<3:2,3:6>>,octets_to_complete(16#C000, B)|efos_1(T)];
+efos_1(<<B:16#8000/binary,T/binary>>) ->
+ [20,1,<<3:2,2:6>>,octets_to_complete(16#8000, B)|efos_1(T)];
+efos_1(<<B:16#4000/binary,T/binary>>) ->
+ [20,1,<<3:2,1:6>>,octets_to_complete(16#4000, B)|efos_1(T)];
+efos_1(<<>>) ->
+ [20,1,0];
+efos_1(<<B/bitstring>>) ->
+ Len = byte_size(B),
+ [encode_length(Len)|octets_to_complete(Len, B)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+
+encode_restricted_string(Val) when is_list(Val)->
+ Len = length(Val),
+ [encode_length(Len)|octets_to_complete(Len, Val)].
+
+encode_known_multiplier_string(SizeC, NumBits, CharOutTab, Val) ->
+ Result = chars_encode2(Val, NumBits, CharOutTab),
+ case SizeC of
+ Ub when is_integer(Ub), Ub*NumBits < 16 ->
+ Result;
+ Ub when is_integer(Ub) ->
+ [2,Result];
+ {{_,Ub},Ext}=SZ when is_list(Ext) ->
+ Len = length(Val),
+ case encode_length(SZ, Len) of
+ [0|_]=EncLen when Ub*NumBits < 16 ->
+ [EncLen,45,Len*NumBits,Len,Val];
+ [_|_]=EncLen ->
+ [EncLen,2|Result]
+ end;
+ {_,Ub}=Range ->
+ [encode_length(Range, length(Val))|
+ if
+ Ub*NumBits < 16 -> Result;
+ true -> [2|Result]
+ end];
+ no ->
+ [encode_length(length(Val)),2,Result]
+ end.
+
+encode_GeneralString(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_GraphicString(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_ObjectDescriptor(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_TeletexString(_C,Val) -> % equivalent with T61String
+ encode_restricted_string(Val).
+
+encode_VideotexString(_C,Val) ->
+ encode_restricted_string(Val).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint
+%% PermittedAlphabet into account.
+%%
+%% This function only encodes the value part and NOT the length.
+
+chars_encode2([H|T],NumBits,T1={Min,Max,notab}) when H =< Max, H >= Min ->
+ [pre_complete_bits(NumBits,H-Min)|chars_encode2(T,NumBits,T1)];
+chars_encode2([H|T],NumBits,T1={Min,Max,Tab}) when H =< Max, H >= Min ->
+ [pre_complete_bits(NumBits,exit_if_false(H,element(H-Min+1,Tab)))|
+ chars_encode2(T,NumBits,T1)];
+chars_encode2([{A,B,C,D}|T],NumBits,T1={Min,_Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ [pre_complete_bits(NumBits,
+ ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min)|
+ chars_encode2(T,NumBits,T1)];
+chars_encode2([H={A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ [pre_complete_bits(NumBits,exit_if_false(H,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)))|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+exit_if_false(V,false)->
+ exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
+exit_if_false(_,V) ->V.
+
+pre_complete_bits(NumBits,Val) when NumBits =< 8 ->
+ [10,NumBits,Val];
+pre_complete_bits(NumBits,Val) when NumBits =< 16 ->
+ [10,NumBits-8,Val bsr 8,10,8,(Val band 255)];
+pre_complete_bits(NumBits,Val) when NumBits =< 2040 -> % 255 * 8
+ Unused = (8 - (NumBits rem 8)) rem 8,
+ Len = NumBits + Unused,
+ [30,Unused,Len div 8,<<(Val bsl Unused):Len>>].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_UTF8String(Val) -> CompleteList
+%% Val -> <<utf8encoded binary>>
+%% CompleteList -> [apropriate codes and values for driver complete]
+%%
+encode_UTF8String(Val) when is_binary(Val) ->
+ Sz = byte_size(Val),
+ [encode_length(Sz),octets_to_complete(Sz, Val)];
+encode_UTF8String(Val) ->
+ encode_UTF8String(list_to_binary(Val)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
+%%
+encode_object_identifier(Val) ->
+ OctetList = e_object_identifier(Val),
+ Octets = list_to_binary(OctetList),
+ Sz = byte_size(Octets),
+ [encode_length(Sz),
+ octets_to_complete(Sz, Octets)].
+
+e_object_identifier({'OBJECT IDENTIFIER',V}) ->
+ e_object_identifier(V);
+e_object_identifier(V) when is_tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
+ Head = 40*E1 + E2, % weird
+ e_object_elements([Head|Tail],[]);
+e_object_identifier(Oid=[_,_|_Tail]) ->
+ exit({error,{asn1,{'illegal_value',Oid}}}).
+
+e_object_elements([],Acc) ->
+ lists:reverse(Acc);
+e_object_elements([H|T],Acc) ->
+ e_object_elements(T,[e_object_element(H)|Acc]).
+
+e_object_element(Num) when Num < 128 ->
+ [Num];
+e_object_element(Num) ->
+ [e_o_e(Num bsr 7)|[Num band 2#1111111]].
+e_o_e(Num) when Num < 128 ->
+ Num bor 2#10000000;
+e_o_e(Num) ->
+ [e_o_e(Num bsr 7)|[(Num band 2#1111111) bor 2#10000000]].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_relative_oid(Val) -> CompleteList
+%% encode_relative_oid({Name,Val}) -> CompleteList
+encode_relative_oid(Val) when is_tuple(Val) ->
+ encode_relative_oid(tuple_to_list(Val));
+encode_relative_oid(Val) when is_list(Val) ->
+ Octets = list_to_binary([e_object_element(X)||X <- Val]),
+ Sz = byte_size(Octets),
+ [encode_length(Sz)|octets_to_complete(Sz, Octets)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+
+complete(L) ->
+ case asn1rt_nif:encode_per_complete(L) of
+ <<>> -> <<0>>;
+ Bin -> Bin
+ end.
+
+octets_to_complete(Len,Val) when Len < 256 ->
+ [20,Len,Val];
+octets_to_complete(Len,Val) ->
+ [21,<<Len:16>>,Val].
+
+octets_unused_to_complete(Unused,Len,Val) when Len < 256 ->
+ [30,Unused,Len,Val];
+octets_unused_to_complete(Unused,Len,Val) ->
+ [31,Unused,<<Len:16>>,Val].
diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl
new file mode 100644
index 0000000000..e7edc2b65f
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_per_common.erl
@@ -0,0 +1,126 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+%%
+-module(asn1rtt_per_common).
+
+-include("asn1_records.hrl").
+
+-export([decode_fragmented/3,
+ decode_compact_bit_string/1,
+ decode_legacy_bit_string/1,
+ decode_named_bit_string/2,
+ decode_chars/2,decode_chars/3,
+ decode_chars_16bit/1,
+ decode_big_chars/2,
+ decode_oid/1,decode_relative_oid/1]).
+
+-define('16K',16384).
+
+decode_fragmented(SegSz0, Buf0, Unit) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Res:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ decode_fragmented_1(Buf, Unit, Res).
+
+decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) ->
+ Sz = N*Unit,
+ <<S:Sz/bitstring,Buf/bitstring>> = Buf0,
+ {<<Res/bitstring,S/bitstring>>,Buf};
+decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) ->
+ SegSz = SegSz0 * Unit * ?'16K',
+ <<Frag:SegSz/bitstring,Buf/bitstring>> = Buf0,
+ Res = <<Res0/bitstring,Frag/bitstring>>,
+ decode_fragmented_1(Buf, Unit, Res).
+
+decode_named_bit_string(Val, NNL) ->
+ Bits = [B || <<B:1>> <= Val],
+ decode_named_bit_string_1(0, Bits, NNL, []).
+
+decode_legacy_bit_string(Val) ->
+ [B || <<B:1>> <= Val].
+
+decode_compact_bit_string(Val) ->
+ PadLen = (8 - (bit_size(Val) band 7)) band 7,
+ {PadLen,<<Val/bitstring,0:PadLen>>}.
+
+decode_chars(Val, N) ->
+ [C || <<C:N>> <= Val].
+
+decode_chars(Val, N, Chars) ->
+ [element(C+1, Chars) || <<C:N>> <= Val].
+
+decode_chars_16bit(Val) ->
+ Cs = [C || <<C:16>> <= Val],
+ decode_chars_16bit_1(Cs).
+
+decode_big_chars(Val, N) ->
+ decode_big_chars_1(decode_chars(Val, N)).
+
+decode_oid(Octets) ->
+ [First|Rest] = dec_subidentifiers(Octets, 0, []),
+ Idlist = if
+ First < 40 ->
+ [0,First|Rest];
+ First < 80 ->
+ [1,First - 40|Rest];
+ true ->
+ [2,First - 80|Rest]
+ end,
+ list_to_tuple(Idlist).
+
+decode_relative_oid(Octets) ->
+ list_to_tuple(dec_subidentifiers(Octets, 0, [])).
+
+%%%
+%%% Internal functions.
+%%%
+
+decode_named_bit_string_1(Pos, [0|Bt], Names, Acc) ->
+ decode_named_bit_string_1(Pos+1, Bt, Names, Acc);
+decode_named_bit_string_1(Pos, [1|Bt], Names, Acc) ->
+ case lists:keyfind(Pos, 2, Names) of
+ {Name,_} ->
+ decode_named_bit_string_1(Pos+1, Bt, Names, [Name|Acc]);
+ false ->
+ decode_named_bit_string_1(Pos+1, Bt, Names, [{bit,Pos}|Acc])
+ end;
+decode_named_bit_string_1(_Pos, [], _Names, Acc) ->
+ lists:reverse(Acc).
+
+decode_chars_16bit_1([H|T]) when H < 256 ->
+ [H|decode_chars_16bit_1(T)];
+decode_chars_16bit_1([H|T]) ->
+ [{0,0,H bsr 8,H band 255}|decode_chars_16bit_1(T)];
+decode_chars_16bit_1([]) -> [].
+
+decode_big_chars_1([H|T]) when H < 256 ->
+ [H|decode_big_chars_1(T)];
+decode_big_chars_1([H|T]) ->
+ [list_to_tuple(binary_to_list(<<H:32>>))|decode_big_chars_1(T)];
+decode_big_chars_1([]) -> [].
+
+dec_subidentifiers([H|T], Av, Al) when H >=16#80 ->
+ dec_subidentifiers(T, (Av bsl 7) bor (H band 16#7F), Al);
+dec_subidentifiers([H|T], Av, Al) ->
+ dec_subidentifiers(T, 0, [(Av bsl 7) bor H|Al]);
+dec_subidentifiers([], _Av, Al) ->
+ lists:reverse(Al).
diff --git a/lib/asn1/src/asn1rtt_real_common.erl b/lib/asn1/src/asn1rtt_real_common.erl
new file mode 100644
index 0000000000..22a1f4c4dd
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_real_common.erl
@@ -0,0 +1,292 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+-module(asn1rtt_real_common).
+
+-export([encode_real/1,decode_real/1,
+ ber_encode_real/1]).
+
+%%============================================================================
+%%
+%% Real value, ITU_T X.690 Chapter 8.5
+%%============================================================================
+%%
+%% encode real value
+%%============================================================================
+
+ber_encode_real(0) ->
+ {[],0};
+ber_encode_real('PLUS-INFINITY') ->
+ {[64],1};
+ber_encode_real('MINUS-INFINITY') ->
+ {[65],1};
+ber_encode_real(Val) when is_tuple(Val); is_list(Val) ->
+ encode_real(Val).
+
+%%%%%%%%%%%%%%
+%% only base 2 encoding!
+%% binary encoding:
+%% +------------+ +------------+ +-+-+-+-+---+---+
+%% | (tag)9 | | n + p + 1 | |1|S|BB |FF |EE |
+%% +------------+ +------------+ +-+-+-+-+---+---+
+%%
+%% +------------+ +------------+
+%% | | | |
+%% +------------+ ...+------------+
+%% n octets for exponent
+%%
+%% +------------+ +------------+
+%% | | | |
+%% +------------+ ...+------------+
+%% p octets for pos mantissa
+%%
+%% S is 0 for positive sign
+%% 1 for negative sign
+%% BB: encoding base, 00 = 2, (01 = 8, 10 = 16)
+%% 01 and 10 not used
+%% FF: scale factor 00 = 0 (used in base 2 encoding)
+%% EE: encoding of the exponent:
+%% 00 - on the following octet
+%% 01 - on the 2 following octets
+%% 10 - on the 3 following octets
+%% 11 - encoding of the length of the two's-complement encoding of
+%% exponent on the following octet, and two's-complement
+%% encoding of exponent on the other octets.
+%%
+%% In DER and base 2 encoding the mantissa is encoded as value 0 or
+%% bit shifted until it is an odd number. Thus, do this for BER as
+%% well.
+
+encode_real(Real) ->
+ encode_real([], Real).
+
+encode_real(_C, {Mantissa, Base, Exponent}) when Base =:= 2 ->
+%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
+ {Man,ExpAdd} = truncate_zeros(Mantissa), %% DER adjustment
+ Exp = Exponent + ExpAdd,
+ OctExp = if Exp >= 0 -> list_to_binary(encode_pos_integer(Exp, []));
+ true -> list_to_binary(encode_neg_integer(Exp, []))
+ end,
+%% ok = io:format("OctExp: ~w~n",[OctExp]),
+ SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
+ true -> 1
+ end,
+%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
+ SFactor = 0,
+ OctExpLen = byte_size(OctExp),
+ if OctExpLen > 255 ->
+ exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
+ true -> true %% make real assert later..
+ end,
+ {LenCode, EOctets} = case OctExpLen of % bit 2,1
+ 1 -> {0, OctExp};
+ 2 -> {1, OctExp};
+ 3 -> {2, OctExp};
+ _ -> {3, <<OctExpLen, OctExp/binary>>}
+ end,
+ BB = 0, %% 00 for base 2
+ FirstOctet = <<1:1,SignBit:1,BB:2,SFactor:2,LenCode:2>>,
+ OctMantissa = if Man > 0 -> list_to_binary(real_mininum_octets(Man));
+ true -> list_to_binary(real_mininum_octets(-(Man))) % signbit keeps track of sign
+ end,
+ %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
+ Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
+ {Bin, size(Bin)};
+encode_real(C, {Mantissa,Base,Exponent})
+ when Base =:= 10, is_integer(Mantissa), is_integer(Exponent) ->
+ %% always encode as NR3 due to DER on the format
+ %% mmmm.Eseeee where
+ %% m := digit
+ %% s := '-' | '+' | []
+ %% '+' only allowed in +0
+ %% e := digit
+ %% ex: 1234.E-5679
+ ManStr = integer_to_list(Mantissa),
+
+ encode_real_as_string(C,ManStr,Exponent);
+encode_real(_C, {_,Base,_}) ->
+ exit({error,{asn1, {encode_real_non_supported_encoding, Base}}});
+%% base 10
+encode_real(C, Real) when is_list(Real) ->
+ %% The Real string may come in as a NR1, NR2 or NR3 string.
+ {Mantissa, Exponent} =
+ case string:tokens(Real,"Ee") of
+ [NR2] ->
+ {NR2,0};
+ [NR3MB,NR3E] ->
+ %% remove beginning zeros
+ {NR3MB,list_to_integer(NR3E)}
+ end,
+
+ %% .Decimal | Number | Number.Decimal
+ ZeroDecimal =
+ fun("0") -> "";
+ (L) -> L
+ end,
+ {NewMantissa,LenDecimal} =
+ case Mantissa of
+ [$.|Dec] ->
+ NewMan = remove_trailing_zeros(Dec),
+ {NewMan,length(ZeroDecimal(NewMan))};
+ _ ->
+ case string:tokens(Mantissa,",.") of
+ [Num] -> %% No decimal-mark
+ {integer_to_list(list_to_integer(Num)),0};
+ [Num,Dec] ->
+ NewDec = ZeroDecimal(remove_trailing_zeros(Dec)),
+ NewMan = integer_to_list(list_to_integer(Num)) ++ NewDec,
+ {integer_to_list(list_to_integer(NewMan)),
+ length(NewDec)}
+ end
+ end,
+
+ encode_real_as_string(C, NewMantissa, Exponent - LenDecimal).
+
+encode_real_as_string(_C, Mantissa, Exponent)
+ when is_list(Mantissa), is_integer(Exponent) ->
+ %% Remove trailing zeros in Mantissa and add this to Exponent
+ TruncMant = remove_trailing_zeros(Mantissa),
+
+ ExpIncr = length(Mantissa) - length(TruncMant),
+
+ ExpStr = integer_to_list(Exponent + ExpIncr),
+
+ ExpBin =
+ case ExpStr of
+ "0" ->
+ <<"E+0">>;
+ _ ->
+ ExpB = list_to_binary(ExpStr),
+ <<$E,ExpB/binary>>
+ end,
+ ManBin = list_to_binary(TruncMant),
+ NR3 = 3,
+ {<<NR3,ManBin/binary,$.,ExpBin/binary>>,
+ 2 + byte_size(ManBin) + byte_size(ExpBin)}.
+
+remove_trailing_zeros(IntStr) ->
+ case lists:dropwhile(fun($0)-> true;
+ (_) -> false
+ end, lists:reverse(IntStr)) of
+ [] ->
+ "0";
+ ReversedIntStr ->
+ lists:reverse(ReversedIntStr)
+ end.
+
+truncate_zeros(Num) ->
+ truncate_zeros(Num, 0).
+truncate_zeros(0, Sum) ->
+ {0,Sum};
+truncate_zeros(M, Sum) ->
+ case M band 16#f =:= M band 16#e of
+ true -> truncate_zeros(M bsr 1, Sum+1);
+ _ -> {M,Sum}
+ end.
+
+
+%%============================================================================
+%% decode real value
+%%
+%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
+%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
+%% RestBuff}
+%%
+%% only for base 2 decoding sofar!!
+%%============================================================================
+
+decode_real(Buffer) ->
+ Sz = byte_size(Buffer),
+ {RealVal,<<>>,Sz} = decode_real2(Buffer, [], Sz, 0),
+ RealVal.
+
+decode_real2(Buffer, _C, 0, _RemBytes) ->
+ {0,Buffer};
+decode_real2(Buffer0, _C, Len, RemBytes1) ->
+ <<First, Buffer2/binary>> = Buffer0,
+ if
+ First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
+ First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
+ First =:= 1 orelse First =:= 2 orelse First =:= 3 ->
+ %% charcter string encoding of base 10
+ {NRx,Rest} = split_binary(Buffer2,Len-1),
+ {binary_to_list(NRx),Rest,Len};
+ true ->
+ %% have some check here to verify only supported bases (2)
+ %% not base 8 or 16
+ <<_B7:1,Sign:1,BB:2,_FF:2,EE:2>> = <<First>>,
+ Base =
+ case BB of
+ 0 -> 2; % base 2, only one so far
+ _ -> exit({error,{asn1, {non_supported_base, BB}}})
+ end,
+ {FirstLen, {Exp, Buffer3,_Rb2}, RemBytes2} =
+ case EE of
+ 0 -> {2, decode_integer2(1, Buffer2, RemBytes1), RemBytes1+1};
+ 1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2};
+ 2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3};
+ 3 ->
+ <<ExpLen1,RestBuffer/binary>> = Buffer2,
+ { ExpLen1 + 2,
+ decode_integer2(ExpLen1, RestBuffer, RemBytes1),
+ RemBytes1+ExpLen1}
+ end,
+ %% io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n",
+
+ Length = Len - FirstLen,
+ <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
+ {{Mantissa, Buffer4}, RemBytes3} =
+ if Sign =:= 0 ->
+ %% io:format("sign plus~n"),
+ {{LongInt, RestBuff}, 1 + Length};
+ true ->
+ %% io:format("sign minus~n"),
+ {{-LongInt, RestBuff}, 1 + Length}
+ end,
+ {{Mantissa, Base, Exp}, Buffer4, RemBytes2+RemBytes3}
+ end.
+
+encode_pos_integer(0, [B|_Acc]=L) when B < 128 ->
+ L;
+encode_pos_integer(N, Acc) ->
+ encode_pos_integer(N bsr 8, [N band 16#ff| Acc]).
+
+encode_neg_integer(-1, [B1|_T]=L) when B1 > 127 ->
+ L;
+encode_neg_integer(N, Acc) ->
+ encode_neg_integer(N bsr 8, [N band 16#ff|Acc]).
+
+
+%% Val must be >= 0
+real_mininum_octets(Val) ->
+ real_mininum_octets(Val, []).
+
+real_mininum_octets(0, Acc) ->
+ Acc;
+real_mininum_octets(Val, Acc) ->
+ real_mininum_octets(Val bsr 8, [Val band 16#FF | Acc]).
+
+%% decoding postitive integer values.
+decode_integer2(Len, <<0:1,_:7,_Bs/binary>> = Bin, RemovedBytes) ->
+ <<Int:Len/unit:8,Buffer2/binary>> = Bin,
+ {Int,Buffer2,RemovedBytes};
+%% decoding negative integer values.
+decode_integer2(Len, <<1:1,B2:7,Bs/binary>>, RemovedBytes) ->
+ <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
+ Int = N - (1 bsl (8 * Len - 1)),
+ {Int,Buffer2,RemovedBytes}.
diff --git a/lib/asn1/src/asn1rtt_uper.erl b/lib/asn1/src/asn1rtt_uper.erl
new file mode 100644
index 0000000000..a5035c6660
--- /dev/null
+++ b/lib/asn1/src/asn1rtt_uper.erl
@@ -0,0 +1,973 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2013. 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%
+%%
+%%
+-module(asn1rtt_uper).
+
+-export([setext/1, fixoptionals/3,
+ fixextensions/2,
+ skipextensions/3]).
+-export([set_choice/3, encode_integer/2, encode_integer/3]).
+-export([encode_small_number/1, encode_constrained_number/2,
+ encode_boolean/1,
+ encode_length/1, encode_length/2,
+ encode_bit_string/3]).
+-export([encode_octet_string/1,encode_octet_string/2,
+ encode_relative_oid/1,
+ encode_object_identifier/1,
+ complete/1, complete_NFP/1]).
+
+ -export([encode_open_type/1]).
+
+ -export([encode_UniversalString/3,
+ encode_PrintableString/3,
+ encode_GeneralString/2,
+ encode_GraphicString/2,
+ encode_TeletexString/2,
+ encode_VideotexString/2,
+ encode_VisibleString/3,
+ encode_UTF8String/1,
+ encode_BMPString/3,
+ encode_IA5String/3,
+ encode_NumericString/3,
+ encode_ObjectDescriptor/2
+ ]).
+
+-define('16K',16384).
+-define('32K',32768).
+-define('64K',65536).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(false) ->
+ <<0:1>>;
+setext(true) ->
+ <<1:1>>.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This is the new fixoptionals/3 which is used by the new generates
+%%
+fixoptionals(OptList,OptLength,Val) when is_tuple(Val) ->
+ Bits = fixoptionals(OptList,Val,0),
+ {Val,<<Bits:OptLength>>};
+
+fixoptionals([],_Val,Acc) ->
+ %% Optbits
+ Acc;
+fixoptionals([{Pos,DefVal}|Ot],Val,Acc) ->
+ case element(Pos,Val) of
+ asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
+ DefVal -> fixoptionals(Ot,Val,Acc bsl 1);
+ _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
+ end;
+fixoptionals([Pos|Ot],Val,Acc) ->
+ case element(Pos,Val) of
+ asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
+ asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
+ _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
+ end.
+
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+ [encode_small_length(ExtNum),<<ExtBits:ExtNum>>]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
+ Prev = Nr - 1,
+ case ExtensionBitstr of
+ <<_:Prev,1:1,_/bitstring>> ->
+ {Len,Bytes1} = decode_length(Bytes0),
+ <<_:Len/binary,Bytes2/bitstring>> = Bytes1,
+ skipextensions(Bytes2, Nr+1, ExtensionBitstr);
+ <<_:Prev,0:1,_/bitstring>> ->
+ skipextensions(Bytes0, Nr+1, ExtensionBitstr);
+ _ ->
+ Bytes0
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt, {L1,L2}, {Len1,_Len2}) ->
+ case set_choice_tag(Alt, L1) of
+ N when is_integer(N), Len1 > 1 ->
+ [<<0:1>>, % the value is in the root set
+ encode_integer([{'ValueRange',{0,Len1-1}}],N)];
+ N when is_integer(N) ->
+ <<0:1>>; % no encoding if only 0 or 1 alternative
+ false ->
+ [<<1:1>>, % extension value
+ case set_choice_tag(Alt,L2) of
+ N2 when is_integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt,L,Len) ->
+ case set_choice_tag(Alt,L) of
+ N when is_integer(N), Len > 1 ->
+ encode_integer([{'ValueRange',{0,Len-1}}],N);
+ N when is_integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_Alt,[],_Tag) ->
+ false.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(Val) ->
+ [encode_length(byte_size(Val)),Val].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
+%% encode_integer(Constraint,Value) -> CompleteList
+%% encode_integer(Constraint,{Name,Value}) -> CompleteList
+%%
+%%
+encode_integer(C, V, NamedNumberList) when is_atom(V) ->
+ case lists:keyfind(V, 1, NamedNumberList) of
+ {_,NewV} ->
+ encode_integer(C, NewV);
+ false ->
+ exit({error,{asn1,{namednumber,V}}})
+ end;
+encode_integer(C, V, _NamedNumberList) when is_integer(V) ->
+ encode_integer(C, V).
+
+encode_integer([{Rc,_Ec}],Val) when is_tuple(Rc) ->
+ try
+ [<<0:1>>,encode_integer([Rc], Val)]
+ catch
+ _:{error,{asn1,_}} ->
+ [<<1:1>>,encode_unconstrained_number(Val)]
+ end;
+encode_integer(C, Val) when is_list(C) ->
+ case get_constraint(C, 'SingleValue') of
+ no ->
+ encode_integer1(C,Val);
+ V when is_integer(V), V =:= Val ->
+ []; % a type restricted to a single value encodes to nothing
+ V when is_list(V) ->
+ case lists:member(Val,V) of
+ true ->
+ encode_integer1(C,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end.
+
+encode_integer1(C, Val) ->
+ case VR = get_constraint(C, 'ValueRange') of
+ no ->
+ encode_unconstrained_number(Val);
+ {Lb,'MAX'} when Lb =< Val ->
+ encode_semi_constrained_number(Lb, Val);
+ %% positive with range
+ {Lb,Ub} when Val >= Lb, Ub >= Val ->
+ encode_constrained_number(VR,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,VR,Val}}})
+ end.
+
+%% X.691:10.6 Encoding of a normally small non-negative whole number
+%% Use this for encoding of CHOICE index if there is an extension marker in
+%% the CHOICE
+encode_small_number(Val) when Val < 64 ->
+ <<Val:7>>;
+encode_small_number(Val) ->
+ [<<1:1>>|encode_semi_constrained_number(0, Val)].
+
+%% X.691:10.7 Encoding of a semi-constrained whole number
+encode_semi_constrained_number(Lb, Val) ->
+ %% encoding in minimum number of octets preceeded by a length
+ Val2 = Val - Lb,
+ Bin = eint_bin_positive(Val2),
+ Size = byte_size(Bin),
+ if
+ Size < 128 ->
+ [<<Size>>,Bin];
+ Size < 16384 ->
+ [<<2:2,Size:14>>,Bin];
+ true ->
+ [encode_length(Size),Bin]
+ end.
+
+encode_constrained_number({Lb,Ub}, Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ NumBits = num_bits(Range),
+ <<Val2:NumBits>>;
+encode_constrained_number(Range,Val) ->
+ exit({error,{asn1,{integer_range,Range,value,Val}}}).
+
+%% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ Oct = eint_bin_2Cs(Val),
+ Len = byte_size(Oct),
+ if
+ Len < 128 ->
+ [<<Len>>,Oct]; % equiv with encode_length(undefined,Len) but faster
+ Len < 16384 ->
+ [<<2:2,Len:14>>,Oct];
+ true ->
+ [encode_length(Len),<<Len:16>>,Oct]
+ end;
+encode_unconstrained_number(Val) -> % negative
+ Oct = enint(Val,[]),
+ Len = byte_size(Oct),
+ if
+ Len < 128 ->
+ [<<Len>>,Oct]; % equiv with encode_length(undefined,Len) but faster
+ Len < 16384 ->
+ [<<2:2,Len:14>>,Oct];
+ true ->
+ [encode_length(Len),Oct]
+ end.
+
+
+eint_bin_2Cs(Int) ->
+ case eint_bin_positive(Int) of
+ <<B,_/binary>> = Bin when B > 16#7f ->
+ <<0,Bin/binary>>;
+ Bin -> Bin
+ end.
+
+%% returns the integer as a binary
+eint_bin_positive(Val) when Val < 16#100 ->
+ <<Val>>;
+eint_bin_positive(Val) when Val < 16#10000 ->
+ <<Val:16>>;
+eint_bin_positive(Val) when Val < 16#1000000 ->
+ <<Val:24>>;
+eint_bin_positive(Val) when Val < 16#100000000 ->
+ <<Val:32>>;
+eint_bin_positive(Val) ->
+ list_to_binary([eint_bin_positive2(Val bsr 32),<<Val:32>>]).
+
+eint_bin_positive2(Val) when Val < 16#100 ->
+ <<Val>>;
+eint_bin_positive2(Val) when Val < 16#10000 ->
+ <<Val:16>>;
+eint_bin_positive2(Val) when Val < 16#1000000 ->
+ <<Val:24>>;
+eint_bin_positive2(Val) when Val < 16#100000000 ->
+ <<Val:32>>;
+eint_bin_positive2(Val) ->
+ [eint_bin_positive2(Val bsr 32),<<Val:32>>].
+
+
+
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ list_to_binary([B1|T]);
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(Len) -> % un-constrained
+ if
+ Len < 128 ->
+ <<Len>>;
+ Len < 16384 ->
+ <<2:2,Len:14>>;
+ true -> % should be able to endode length >= 16384
+ error({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end.
+
+encode_length({C,[]}, Len) ->
+ case C of
+ {Lb,Ub}=Vr when Lb =< Len, Len =< Ub ->
+ [<<0:1>>|encode_constrained_number(Vr, Len)];
+ _ ->
+ [<<1:1>>|encode_length(Len)]
+ end;
+encode_length(Len, Len) ->
+ [];
+encode_length(Vr, Len) ->
+ encode_constrained_number(Vr, Len).
+
+
+%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
+%% additions in a sequence or set
+encode_small_length(Len) when Len =< 64 ->
+ <<(Len-1):7>>;
+encode_small_length(Len) ->
+ [<<1:1>>,encode_length(Len)].
+
+
+%% un-constrained
+decode_length(<<0:1,Oct:7,Rest/bitstring>>) ->
+ {Oct,Rest};
+decode_length(<<2:2,Val:14,Rest/bitstring>>) ->
+ {Val,Rest};
+decode_length(<<3:2,_:14,_Rest/bitstring>>) ->
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}}).
+
+ % X.691:11
+encode_boolean(true) ->
+ <<1:1>>;
+encode_boolean(false) ->
+ <<0:1>>;
+encode_boolean(Val) ->
+ exit({error,{asn1,{encode_boolean,Val}}}).
+
+
+%%============================================================================
+%%============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.5
+%%============================================================================
+%%============================================================================
+
+%%============================================================================
+%% 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 constraint Len, only valid when identifiers are present
+
+
+%% when the value is a list of {Unused,BinBits}, where
+%% Unused = integer(),
+%% BinBits = binary().
+
+encode_bit_string(C, Bits, NamedBitList) when is_bitstring(Bits) ->
+ PadLen = (8 - (bit_size(Bits) band 7)) band 7,
+ Compact = {PadLen,<<Bits/bitstring,0:PadLen>>},
+ encode_bit_string(C, Compact, NamedBitList);
+encode_bit_string(C, {Unused,BinBits}=Bin, NamedBitList)
+ when is_integer(Unused), is_binary(BinBits) ->
+ encode_bin_bit_string(C, Bin, NamedBitList);
+
+encode_bit_string(C, BitListVal, NamedBitList) ->
+ encode_bit_string1(C, BitListVal, NamedBitList).
+
+%% when the value is a list of named bits
+encode_bit_string1(C, [FirstVal|_RestVal]=LoNB, NamedBitList)
+ when is_atom(FirstVal) ->
+ ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos, 0),
+ encode_bit_string1(C, BitList, NamedBitList);
+encode_bit_string1(C, [{bit,_No}|_RestVal]=BL, NamedBitList) ->
+ ToSetPos = get_all_bitposes(BL, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos, 0),
+ encode_bit_string1(C, BitList, NamedBitList);
+%% when the value is a list of ones and zeroes
+encode_bit_string1(Int, BitListValue, _)
+ when is_list(BitListValue), is_integer(Int) ->
+ %% The type is constrained by a single value size constraint
+ bit_list2bitstr(Int, BitListValue);
+encode_bit_string1(no, BitListValue, [])
+ when is_list(BitListValue) ->
+ Len = length(BitListValue),
+ [encode_length(Len),bit_list2bitstr(Len,BitListValue)];
+encode_bit_string1(C, BitListValue,[])
+ when is_list(BitListValue) ->
+ Len = length(BitListValue),
+ [encode_length(C, Len),bit_list2bitstr(Len,BitListValue)];
+encode_bit_string1(no, BitListValue,_NamedBitList)
+ when is_list(BitListValue) ->
+ NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitListValue))),
+ Len = length(NewBitLVal),
+ [encode_length(Len),bit_list2bitstr(Len,NewBitLVal)];
+encode_bit_string1(C, BitListValue, _NamedBitList)
+ when is_list(BitListValue) ->% C = {_,'MAX'}
+ NewBitStr = bitstr_trailing_zeros(BitListValue, C),
+ [encode_length(C, bit_size(NewBitStr)),NewBitStr];
+
+
+%% when the value is an integer
+encode_bit_string1(C, IntegerVal, NamedBitList) when is_integer(IntegerVal)->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string1(C, BitList, NamedBitList).
+
+bit_list2bitstr(Len,BitListValue) ->
+ case length(BitListValue) of
+ Len ->
+ << <<B:1>> || B <- BitListValue>>;
+ L when L > Len -> % truncate
+ <<(<< <<B:1>> || B <- BitListValue>>):Len/bitstring>>;
+ L -> % Len > L -> pad
+ <<(<< <<B:1>> || B <- BitListValue>>)/bitstring,0:(Len-L)>>
+ end.
+
+adjust_trailing_zeros(Len, Bin) when Len =:= bit_size(Bin) ->
+ Bin;
+adjust_trailing_zeros(Len, Bin) when Len > bit_size(Bin) ->
+ <<Bin/bitstring,0:(Len-bit_size(Bin))>>;
+adjust_trailing_zeros(Len,Bin) ->
+ <<Bin:Len/bitstring>>.
+
+bitstr_trailing_zeros(BitList, C) when is_integer(C) ->
+ bitstr_trailing_zeros1(BitList, C, C);
+bitstr_trailing_zeros(BitList, {Lb,Ub}) when is_integer(Lb) ->
+ bitstr_trailing_zeros1(BitList,Lb,Ub);
+bitstr_trailing_zeros(BitList, {{Lb,Ub},_}) when is_integer(Lb) ->
+ bitstr_trailing_zeros1(BitList, Lb, Ub);
+bitstr_trailing_zeros(BitList, _) ->
+ bit_list2bitstr(length(BitList), BitList).
+
+bitstr_trailing_zeros1(BitList, Lb, Ub) ->
+ case length(BitList) of
+ Lb -> bit_list2bitstr(Lb, BitList);
+ B when B < Lb -> bit_list2bitstr(Lb, BitList);
+ D -> F = fun(L,LB,LB,_,_)->bit_list2bitstr(LB,lists:reverse(L));
+ ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
+ (L,L1,_,UB,_)when L1 =< UB ->
+ bit_list2bitstr(L1,lists:reverse(L));
+ (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
+ BitList}}) end,
+ F(lists:reverse(BitList),D,Lb,Ub,F)
+ end.
+
+%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
+%% Unused = integer(),i.e. number unused bits in least sign. byte of
+%% BinBits = binary().
+encode_bin_bit_string(C, {_,BinBits}, _NamedBitList)
+ when is_integer(C), C =< 16 ->
+ adjust_trailing_zeros(C, BinBits);
+encode_bin_bit_string(C, {_Unused,BinBits}, _NamedBitList)
+ when is_integer(C) ->
+ adjust_trailing_zeros(C, BinBits);
+encode_bin_bit_string(C, {_,_}=UnusedAndBin, NamedBitList) ->
+ %% removes all trailing bits if NamedBitList is not empty
+ BitStr = remove_trailing_bin(NamedBitList, UnusedAndBin),
+ case C of
+ {Lb,Ub} when is_integer(Lb),is_integer(Ub) ->
+ [encode_length({Lb,Ub},bit_size(BitStr)),BitStr];
+ no ->
+ [encode_length(bit_size(BitStr)),BitStr];
+ Sc ->
+ [encode_length(Sc,bit_size(BitStr)),BitStr]
+ end.
+
+
+remove_trailing_bin([], {Unused,Bin}) ->
+ BS = bit_size(Bin)-Unused,
+ <<BitStr:BS/bitstring,_:Unused>> = Bin,
+ BitStr;
+remove_trailing_bin(_NamedNumberList, {_Unused,<<>>}) ->
+ <<>>;
+remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
+ Size = byte_size(Bin)-1,
+ <<Bfront:Size/binary, LastByte:8>> = Bin,
+
+ %% clear the Unused bits to be sure
+ Unused1 = trailingZeroesInNibble(LastByte band 15),
+ Unused2 =
+ case Unused1 of
+ 4 ->
+ 4 + trailingZeroesInNibble(LastByte bsr 4);
+ _ -> Unused1
+ end,
+ case Unused2 of
+ 8 ->
+ remove_trailing_bin(NamedNumberList,{0,Bfront});
+ _ ->
+ BS = bit_size(Bin) - Unused2,
+ <<BitStr:BS/bitstring,_:Unused2>> = Bin,
+ BitStr
+ end.
+
+trailingZeroesInNibble(0) ->
+ 4;
+trailingZeroesInNibble(1) ->
+ 0;
+trailingZeroesInNibble(2) ->
+ 1;
+trailingZeroesInNibble(3) ->
+ 0;
+trailingZeroesInNibble(4) ->
+ 2;
+trailingZeroesInNibble(5) ->
+ 0;
+trailingZeroesInNibble(6) ->
+ 1;
+trailingZeroesInNibble(7) ->
+ 0;
+trailingZeroesInNibble(8) ->
+ 3;
+trailingZeroesInNibble(9) ->
+ 0;
+trailingZeroesInNibble(10) ->
+ 1;
+trailingZeroesInNibble(11) ->
+ 0;
+trailingZeroesInNibble(12) -> %#1100
+ 2;
+trailingZeroesInNibble(13) ->
+ 0;
+trailingZeroesInNibble(14) ->
+ 1;
+trailingZeroesInNibble(15) ->
+ 0.
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(Int) when is_integer(Int), Int > 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)];
+int_to_bitlist(0) ->
+ [].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keyfind(Val, 1, NamedBitList) of
+ {_ValName, ValPos} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ false ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _) ->
+ [].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Val)
+%% encode_octet_string(Constraint, Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string(Val) ->
+ try
+ [encode_length(length(Val)),list_to_binary(Val)]
+ catch
+ error:{error,{asn1,{encode_length,_}}} ->
+ encode_fragmented_octet_string(Val)
+ end.
+
+encode_octet_string(C, Val) ->
+ case C of
+ {_,_}=VR ->
+ try
+ [encode_length(VR, length(Val)),list_to_binary(Val)]
+ catch
+ error:{error,{asn1,{encode_length,_}}} ->
+ encode_fragmented_octet_string(Val)
+ end;
+ Sv when is_integer(Sv), Sv =:= length(Val) -> % fixed length
+ list_to_binary(Val)
+ end.
+
+
+encode_fragmented_octet_string(Val) ->
+ Bin = list_to_binary(Val),
+ efos_1(Bin).
+
+efos_1(<<B:16#10000/binary,T/binary>>) ->
+ [<<3:2,4:6>>,B|efos_1(T)];
+efos_1(<<B:16#C000/binary,T/binary>>) ->
+ [<<3:2,3:6>>,B|efos_1(T)];
+efos_1(<<B:16#8000/binary,T/binary>>) ->
+ [<<3:2,2:6>>,B|efos_1(T)];
+efos_1(<<B:16#4000/binary,T/binary>>) ->
+ [<<3:2,1:6>>,B|efos_1(T)];
+efos_1(<<B/bitstring>>) ->
+ Len = byte_size(B),
+ [encode_length(Len),B].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+%%encode_restricted_string('BMPString',Constraints,Extension,Val)
+
+
+encode_restricted_string(Val) when is_list(Val)->
+ [encode_length(length(Val)),list_to_binary(Val)].
+
+encode_known_multiplier_string(StringType, C, Pa, Val) ->
+ Result = chars_encode(Pa, StringType, Val),
+ case C of
+ Ub when is_integer(Ub) ->
+ Result;
+ {_,_}=Range ->
+ [encode_length(Range, length(Val)),Result];
+ no ->
+ [encode_length(length(Val)),Result]
+ end.
+
+encode_NumericString(C, Pa, Val) ->
+ encode_known_multiplier_string('NumericString', C, Pa, Val).
+
+encode_PrintableString(C, Pa, Val) ->
+ encode_known_multiplier_string('PrintableString', C, Pa, Val).
+
+encode_VisibleString(C, Pa, Val) -> % equivalent with ISO646String
+ encode_known_multiplier_string('VisibleString', C, Pa, Val).
+
+encode_IA5String(C, Pa, Val) ->
+ encode_known_multiplier_string('IA5String', C, Pa, Val).
+
+encode_BMPString(C, Pa, Val) ->
+ encode_known_multiplier_string('BMPString', C, Pa, Val).
+
+encode_UniversalString(C, Pa, Val) ->
+ encode_known_multiplier_string('UniversalString', C, Pa, Val).
+
+
+%% end of known-multiplier strings for which PER visible constraints are
+%% applied
+
+encode_GeneralString(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_GraphicString(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_ObjectDescriptor(_C,Val) ->
+ encode_restricted_string(Val).
+
+encode_TeletexString(_C,Val) -> % equivalent with T61String
+ encode_restricted_string(Val).
+
+encode_VideotexString(_C,Val) ->
+ encode_restricted_string(Val).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint PermittedAlphabet
+%% into account.
+%% This function does only encode the value part and NOT the length
+
+chars_encode(Pa, StringType, Value) ->
+ case {StringType,Pa} of
+ {'UniversalString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
+ {'BMPString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
+ _ ->
+ {NumBits,CharOutTab} = {get_NumBits(Pa, StringType),
+ get_CharOutTab(Pa, StringType)},
+ chars_encode2(Value,NumBits,CharOutTab)
+ end.
+
+chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
+ [<<(H-Min):NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
+ Ch = exit_if_false(H,element(H-Min+1,Tab)),
+ [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,Tab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ Ch = ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,
+ [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ Ch = exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)),
+ [<<Ch:NumBits>>|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_,{_,_,_}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+exit_if_false(V,false)->
+ exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
+exit_if_false(_,V) ->V.
+
+
+get_NumBits(Pa, StringType) ->
+ case Pa of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv));
+ no ->
+ case StringType of
+ 'IA5String' ->
+ charbits(128); % 16#00..16#7F
+ 'VisibleString' ->
+ charbits(95); % 16#20..16#7E
+ 'PrintableString' ->
+ charbits(74); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+ 'NumericString' ->
+ charbits(11); % $ ,"0123456789"
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+get_CharOutTab(Pa, StringType) ->
+ case Pa of
+ {'SingleValue',Sv} ->
+ get_CharTab2(Pa, StringType, hd(Sv), lists:max(Sv), Sv);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ {0,16#7F,notab};
+ 'VisibleString' ->
+ get_CharTab2(Pa, StringType, 16#20, 16#7F, notab);
+ 'PrintableString' ->
+ Chars = lists:sort(
+ " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+ get_CharTab2(Pa, StringType, hd(Chars),
+ lists:max(Chars), Chars);
+ 'NumericString' ->
+ get_CharTab2(Pa, StringType, 16#20, $9, " 0123456789");
+ 'UniversalString' ->
+ {0,16#FFFFFFFF,notab};
+ 'BMPString' ->
+ {0,16#FFFF,notab}
+ end
+ end.
+
+get_CharTab2(C,StringType,Min,Max,Chars) ->
+ BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+ if
+ Max =< BitValMax ->
+ {0,Max,notab};
+ true ->
+ {Min,Max,create_char_tab(Min,Chars)}
+ end.
+
+create_char_tab(Min,L) ->
+ list_to_tuple(create_char_tab(Min,L,0)).
+create_char_tab(Min,[Min|T],V) ->
+ [V|create_char_tab(Min+1,T,V+1)];
+create_char_tab(_Min,[],_V) ->
+ [];
+create_char_tab(Min,L,V) ->
+ [false|create_char_tab(Min+1,L,V)].
+
+%% See Table 20.3 in Dubuisson
+charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+charbits(NumOfChars) when is_integer(NumOfChars) ->
+ 16 + charbits1(NumOfChars bsr 16).
+
+charbits1(0) ->
+ 0;
+charbits1(NumOfChars) ->
+ 1 + charbits1(NumOfChars bsr 1).
+
+
+%% UTF8String
+encode_UTF8String(Val) when is_binary(Val) ->
+ [encode_length(byte_size(Val)),Val];
+encode_UTF8String(Val) ->
+ Bin = list_to_binary(Val),
+ encode_UTF8String(Bin).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [binary()|bitstring()|list()]
+%%
+encode_object_identifier(Val) ->
+ OctetList = e_object_identifier(Val),
+ Octets = list_to_binary(OctetList), % performs a flatten at the same time
+ [encode_length(byte_size(Octets)),Octets].
+
+%% This code is copied from asn1_encode.erl (BER) and corrected and modified
+
+e_object_identifier({'OBJECT IDENTIFIER',V}) ->
+ e_object_identifier(V);
+e_object_identifier(V) when is_tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
+ Head = 40*E1 + E2, % weird
+ e_object_elements([Head|Tail],[]);
+e_object_identifier(Oid=[_,_|_Tail]) ->
+ exit({error,{asn1,{'illegal_value',Oid}}}).
+
+e_object_elements([],Acc) ->
+ lists:reverse(Acc);
+e_object_elements([H|T],Acc) ->
+ e_object_elements(T,[e_object_element(H)|Acc]).
+
+e_object_element(Num) when Num < 128 ->
+ [Num];
+e_object_element(Num) ->
+ [e_o_e(Num bsr 7)|[Num band 2#1111111]].
+e_o_e(Num) when Num < 128 ->
+ Num bor 2#10000000;
+e_o_e(Num) ->
+ [e_o_e(Num bsr 7)|[(Num band 2#1111111) bor 2#10000000]].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_relative_oid(Val) -> CompleteList
+%% encode_relative_oid({Name,Val}) -> CompleteList
+encode_relative_oid(Val) when is_tuple(Val) ->
+ encode_relative_oid(tuple_to_list(Val));
+encode_relative_oid(Val) when is_list(Val) ->
+ Octets = list_to_binary([e_object_element(X)||X <- Val]),
+ [encode_length(byte_size(Octets)),Octets].
+
+
+get_constraint([{Key,V}],Key) ->
+ V;
+get_constraint([],_Key) ->
+ no;
+get_constraint(C,Key) ->
+ case lists:keyfind(Key, 1, C) of
+ false ->
+ no;
+ {_,V} ->
+ V
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+complete(InList) when is_list(InList) ->
+ case complete1(InList) of
+ <<>> ->
+ <<0>>;
+ Res ->
+ case bit_size(Res) band 7 of
+ 0 -> Res;
+ Bits -> <<Res/bitstring,0:(8-Bits)>>
+ end
+ end;
+complete(Bin) when is_binary(Bin) ->
+ case Bin of
+ <<>> -> <<0>>;
+ _ -> Bin
+ end;
+complete(InList) when is_bitstring(InList) ->
+ PadLen = 8 - (bit_size(InList) band 7),
+ <<InList/bitstring,0:PadLen>>.
+
+complete1(L) when is_list(L) ->
+ list_to_bitstring(L).
+
+%% Special version of complete that does not align the completed message.
+complete_NFP(InList) when is_list(InList) ->
+ list_to_bitstring(InList);
+complete_NFP(InList) when is_bitstring(InList) ->
+ InList.
+
+%% unaligned helpers
+
+%% 10.5.6 NOTE: If "range" satisfies the inequality 2^m < "range" =<
+%% 2^(m+1) then the number of bits = m + 1
+
+num_bits(N) -> num_bits(N, 1, 0).
+
+num_bits(N,T,B) when N =< T -> B;
+num_bits(N,T,B) -> num_bits(N, T bsl 1, B+1).
diff --git a/lib/asn1/src/prepare_templates.erl b/lib/asn1/src/prepare_templates.erl
new file mode 100644
index 0000000000..83155b2e52
--- /dev/null
+++ b/lib/asn1/src/prepare_templates.erl
@@ -0,0 +1,135 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. 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%
+%%
+
+-module(prepare_templates).
+-export([gen_asn1ct_rtt/1,gen_asn1ct_eval/1]).
+
+gen_asn1ct_rtt(Ms) ->
+ io:format("%% Generated by ~s. DO NOT EDIT THIS FILE.\n"
+ "%%\n"
+ "%% Input files:\n", [?MODULE]),
+ [io:put_chars(["%% ",M,$\n]) || M <- Ms],
+ io:nl(),
+ io:put_chars("-module(asn1ct_rtt).\n"
+ "-export([assert_defined/1,dependencies/1,code/0]).\n"
+ "\n"),
+ Forms = lists:sort(lists:append([abstract(M) || M <- Ms])),
+ Exp = lists:sort(exports(Forms)),
+ defined(Exp),
+ io:nl(),
+ Calls = calls(Forms),
+ R = sofs:relation(Calls),
+ Fam0 = sofs:relation_to_family(R),
+ Fam = sofs:to_external(Fam0),
+ dependencies(Fam),
+ io:nl(),
+ Funcs = [begin
+ Bin = list_to_binary([$\n|erl_pp:function(Func)]),
+ {{M,F,A},Bin}
+ end || {M,{function,_,F,A,_}=Func} <- Forms],
+ io:format("code() ->\n~p.\n\n", [Funcs]),
+ halt(0).
+
+gen_asn1ct_eval([File]) ->
+ {ok,Funcs} = file:consult(File),
+ asn1ct_func:start_link(),
+ [asn1ct_func:need(MFA) || MFA <- Funcs],
+ io:format("%% Generated by ~s. DO NOT EDIT THIS FILE.\n"
+ "%%\n"
+ "%% Input file: ~s\n\n", [?MODULE,File]),
+ io:format("-module(~s).\n", [filename:rootname(File)]),
+ gen_asn1ct_eval_exp(Funcs),
+ asn1ct_func:generate(group_leader()),
+ halt(0).
+
+gen_asn1ct_eval_exp(Funcs) ->
+ io:put_chars("-export(["),
+ gen_asn1ct_eval_exp_1(Funcs, ""),
+ io:put_chars("]).\n").
+
+gen_asn1ct_eval_exp_1([{_,F,A}|T], Sep) ->
+ io:put_chars(Sep),
+ io:format("~p/~p", [F,A]),
+ gen_asn1ct_eval_exp_1(T, ",\n");
+gen_asn1ct_eval_exp_1([], _) -> ok.
+
+defined([H|T]) ->
+ io:format("assert_defined(~p) -> ok", [H]),
+ case T of
+ [] ->
+ io:put_chars(".\n");
+ [_|_] ->
+ io:put_chars(";\n"),
+ defined(T)
+ end.
+
+dependencies([{K,V}|T]) ->
+ io:format("dependencies(~p) ->\n~p;\n", [K,V]),
+ dependencies(T);
+dependencies([]) ->
+ io:put_chars("dependencies(_) -> [].\n").
+
+abstract(File) ->
+ {ok,{M0,[{abstract_code,Abstract}]}} =
+ beam_lib:chunks(File, [abstract_code]),
+ {raw_abstract_v1,Forms} = Abstract,
+ M = module(M0),
+ [{M,F} || F <- Forms].
+
+module(M0) ->
+ "asn1rtt_" ++ M = atom_to_list(M0),
+ list_to_atom(M).
+
+exports([{M,{attribute,_,export,L}}|T]) ->
+ [{M,F,A} || {F,A} <- L] ++ exports(T);
+exports([_|T]) ->
+ exports(T);
+exports([]) -> [].
+
+calls([{M,{function,_,F,A,Body}}|T]) ->
+ MFA = {M,F,A},
+ case find_calls(Body, M) -- [MFA] of
+ [] ->
+ calls(T);
+ [_|_]=Calls ->
+ [{MFA,Callee} || Callee <- Calls] ++ calls(T)
+ end;
+calls([_|T]) ->
+ calls(T);
+calls([]) -> [].
+
+find_calls([{call,_,{atom,_,F},Args}|T], M) ->
+ Calls = find_calls(Args, M) ++ find_calls(T, M),
+ Arity = length(Args),
+ case is_bif(F, Arity) of
+ false ->
+ [{M,F,Arity}|Calls];
+ true ->
+ Calls
+ end;
+find_calls([{'fun',_,{function,F,A}}|T], M) ->
+ [{M,F,A}|find_calls(T, M)];
+find_calls([H|T], M) ->
+ find_calls(H, M) ++ find_calls(T, M);
+find_calls(Tuple, M) when is_tuple(Tuple) ->
+ find_calls(tuple_to_list(Tuple), M);
+find_calls(_, _) -> [].
+
+is_bif(F, Arity) ->
+ erl_internal:bif(F, Arity).
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index 69b95b40d5..15b97df972 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2013. 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
@@ -83,6 +83,7 @@ MODULES= \
testInfObj \
testParameterizedInfObj \
testMergeCompile \
+ testMultipleLevels \
testDeepTConstr \
testTimer \
testMegaco \
@@ -101,7 +102,6 @@ MODULES= \
test_driver_load \
testSelectionTypes \
test_undecoded_rest \
- test_inline \
testTcapsystem \
testNBAPsystem \
test_compile_options \
@@ -109,12 +109,13 @@ MODULES= \
test_modified_x420 \
testX420 \
test_x691 \
- testFragmented \
+ testWSParamClass \
asn1_test_lib \
asn1_app_test \
asn1_appup_test \
asn1_wrapper \
- asn1_SUITE
+ asn1_SUITE \
+ error_SUITE
SUITE= asn1_SUITE.erl
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index b052529ebd..f00b23a8b2 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -1,6 +1,7 @@
+%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -19,28 +20,9 @@
-module(asn1_SUITE).
--define(only_per(Func),
- if Rule == per orelse Rule == per_bin -> Func;
- true -> ok
- end).
-define(only_ber(Func),
- if Rule == ber orelse Rule == ber_bin orelse Rule == ber_bin_v2 -> Func;
- true -> ok
- end).
--define(only_uper(Func),
- case Rule of
- uper_bin -> Func;
- _ -> ok
- end).
--define(only_per_nif(Func),
- case {Rule, lists:member(optimize, Opts)} of
- {per_bin, true} -> Func;
- _ -> ok
- end).
--define(only_ber_nif(Func),
- case {Rule, lists:member(nif, Opts)} of
- {ber_bin_v2, true} -> Func;
- _ -> ok
+ if Rule =:= ber -> Func;
+ true -> ok
end).
-compile(export_all).
@@ -51,11 +33,11 @@
%% Suite definition
%%------------------------------------------------------------------------------
-suite() -> [{ct_hooks, [ts_install_cth]},
- {timetrap,{minutes,60}}].
+suite() -> [{ct_hooks, [ts_install_cth]}].
all() ->
- [{group, parallel},
+ [{group, compile},
+ {group, parallel},
{group, app_test},
{group, appup_test},
@@ -71,26 +53,25 @@ groups() ->
[{compile, parallel([]),
[c_syntax,
c_string,
- c_implicit_before_choice]},
+ c_implicit_before_choice,
+ constraint_equivalence]},
{ber, parallel([]),
[ber_choiceinseq,
% Uses 'SOpttest'
- {group, [], [ber_optional,
- ber_optional_keyed_list]}]},
+ ber_optional]},
{app_test, [], [{asn1_app_test, all}]},
{appup_test, [], [{asn1_appup_test, all}]},
{parallel, parallel([]),
- [{group, compile},
+ [cover,
{group, ber},
% Uses 'P-Record', 'Constraints', 'MEDIA-GATEWAY-CONTROL'...
{group, [], [parse,
test_driver_load,
test_undecoded_rest,
- test_inline,
specialized_decodes,
special_decode_performance,
testMegaco,
@@ -105,6 +86,7 @@ groups() ->
testInvokeMod,
per,
ber_other,
+ der,
h323test,
per_GeneralString]},
testChoPrim,
@@ -116,6 +98,7 @@ groups() ->
testChoTypeRefPrim,
testChoTypeRefSeq,
testChoTypeRefSet,
+ testMultipleLevels,
testDef,
testOpt,
testSeqDefault,
@@ -156,7 +139,6 @@ groups() ->
testSetOfCho,
testEnumExt,
value_test,
- value_bad_enum_test,
testSeq2738,
% Uses 'Constructed'
{group, [], [constructed,
@@ -168,7 +150,6 @@ groups() ->
per_open_type,
testInfObjectClass,
testParameterizedInfObj,
- testFragmented,
testMergeCompile,
testobj,
testDeepTConstr,
@@ -185,32 +166,27 @@ groups() ->
testINSTANCE_OF,
testTCAP,
test_ParamTypeInfObj,
- test_WS_ParamClass,
test_Defed_ObjectIdentifier,
testSelectionType,
testSSLspecs,
testNortel,
- % Uses 'PKCS7'
- {group, [], [test_modified_x420,
+ % Uses 'PKCS7', 'InformationFramework'
+ {group, [], [test_WS_ParamClass,
+ test_modified_x420,
testX420]},
testTcapsystem,
testNBAPsystem,
+ testS1AP,
test_compile_options,
testDoubleEllipses,
test_x691,
ticket_6143,
- testExtensionAdditionGroup,
test_OTP_9688]},
{performance, [],
[testTimer_ber,
- testTimer_ber_bin,
- testTimer_ber_bin_opt,
- testTimer_ber_bin_opt_driver,
testTimer_per,
- testTimer_per_bin,
- testTimer_per_bin_opt,
- testTimer_uper_bin,
+ testTimer_uper,
smp]}].
parallel(Options) ->
@@ -225,8 +201,6 @@ parallel(Options) ->
%%------------------------------------------------------------------------------
init_per_suite(Config) ->
- PrivDir = ?config(priv_dir, Config),
- true = code:add_patha(PrivDir),
Config.
end_per_suite(_Config) ->
@@ -239,11 +213,15 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(Func, Config) ->
- CaseDir = filename:join([?config(priv_dir, Config), ?MODULE, Func]),
+ CaseDir = filename:join(?config(priv_dir, Config), Func),
ok = filelib:ensure_dir(filename:join([CaseDir, dummy_file])),
true = code:add_patha(CaseDir),
- [{case_dir, CaseDir}|Config].
+ Dog = case Func of
+ testX420 -> ct:timetrap({minutes, 90});
+ _ -> ct:timetrap({minutes, 60})
+ end,
+ [{case_dir, CaseDir}, {watchdog, Dog}|Config].
end_per_testcase(_Func, Config) ->
code:del_path(?config(case_dir, Config)).
@@ -254,14 +232,8 @@ end_per_testcase(_Func, Config) ->
test(Config, TestF) ->
test(Config, TestF, [per,
- per_bin,
- {per_bin, [optimize]},
- uper_bin,
- ber,
- ber_bin,
- ber_bin_v2,
- % TODO: {ber_bin_v2, [optimize, nif]} ?
- {ber_bin_v2, [nif]}]).
+ uper,
+ ber]).
test(Config, TestF, Rules) ->
Fun = fun(C, R, O) ->
@@ -323,6 +295,28 @@ case_dir([C|Config], Opt) ->
%% Test cases
%%------------------------------------------------------------------------------
+%% Cover run-time functions that are only called by the ASN.1 compiler
+%% (if any).
+cover(_) ->
+ Wc = filename:join([code:lib_dir(asn1),"ebin","asn1ct_eval_*.beam"]),
+ Beams = filelib:wildcard(Wc),
+ true = Beams =/= [],
+ [begin
+ M0 = filename:basename(Beam),
+ M1 = filename:rootname(M0),
+ M = list_to_atom(M1),
+ "asn1ct_eval_" ++ Group0 = M1,
+ Group = list_to_atom(Group0),
+ io:format("%%\n"
+ "%% ~s\n"
+ "%%\n", [M]),
+ asn1ct_func:start_link(),
+ [asn1ct_func:need({Group,F,A}) ||
+ {F,A} <- M:module_info(exports), F =/= module_info],
+ asn1ct_func:generate(group_leader())
+ end || Beam <- Beams],
+ ok.
+
testPrim(Config) -> test(Config, fun testPrim/3).
testPrim(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["Prim", "Real"], Config, [Rule|Opts]),
@@ -339,22 +333,27 @@ testCompactBitString(Config, Rule, Opts) ->
asn1_test_lib:compile("PrimStrings", Config,
[Rule, compact_bit_string|Opts]),
testCompactBitString:compact_bit_string(Rule),
- ?only_uper(testCompactBitString:bit_string_unnamed(Rule)),
- ?only_per(testCompactBitString:bit_string_unnamed(Rule)),
- ?only_per_nif(testCompactBitString:ticket_7734(Rule)),
- ?only_per_nif(asn1_test_lib:compile("Constraints", Config,
- [Rule, compact_bit_string|Opts])),
- ?only_per_nif(testCompactBitString:otp_4869(Rule)).
+ testCompactBitString:bit_string_unnamed(Rule),
+ testCompactBitString:bit_string_unnamed(Rule),
+ testCompactBitString:ticket_7734(Rule),
+ asn1_test_lib:compile("Constraints", Config,
+ [Rule, compact_bit_string|Opts]),
+ testCompactBitString:otp_4869(Rule).
testPrimStrings(Config) -> test(Config, fun testPrimStrings/3).
testPrimStrings(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]),
testPrimStrings_cases(Rule),
- ?only_ber(testPrimStrings:more_strings(Rule)).
+ asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
+ [legacy_bit_string,Rule|Opts]),
+ testPrimStrings:bit_string(Rule),
+ asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
+ [compact_bit_string,Rule|Opts]),
+ testPrimStrings:bit_string(Rule),
+ testPrimStrings:more_strings(Rule).
testPrimStrings_cases(Rule) ->
testPrimStrings:bit_string(Rule),
- testPrimStrings:bit_string_unnamed(Rule),
testPrimStrings:octet_string(Rule),
testPrimStrings:numeric_string(Rule),
testPrimStrings:other_strings(Rule),
@@ -368,10 +367,10 @@ testPrimExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "PrimExternal"], Config,
[Rule|Opts]),
testPrimExternal:external(Rule),
- ?only_ber_nif(asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
- [Rule|Opts])),
- ?only_ber_nif(testPrimStrings_cases(Rule)),
- ?only_ber_nif(testPrimStrings:more_strings(Rule)).
+ asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
+ [Rule|Opts]),
+ testPrimStrings_cases(Rule),
+ testPrimStrings:more_strings(Rule).
testChoPrim(Config) -> test(Config, fun testChoPrim/3).
testChoPrim(Config, Rule, Opts) ->
@@ -396,7 +395,7 @@ testChoOptional(Config, Rule, Opts) ->
testChoOptionalImplicitTag(Config) ->
test(Config, fun testChoOptionalImplicitTag/3,
- [ber, ber_bin, ber_bin_v2]).
+ [ber]).
testChoOptionalImplicitTag(Config, Rule, Opts) ->
%% Only meaningful for ber & co
asn1_test_lib:compile("ChoOptionalImplicitTag", Config, [Rule|Opts]),
@@ -427,6 +426,11 @@ testChoTypeRefSet(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoTypeRefSet", Config, [Rule|Opts]),
testChoTypeRefSet:set(Rule).
+testMultipleLevels(Config) -> test(Config, fun testMultipleLevels/3).
+testMultipleLevels(Config, Rule, Opts) ->
+ asn1_test_lib:compile("MultipleLevels", Config, [Rule|Opts]),
+ testMultipleLevels:main(Rule).
+
testDef(Config) -> test(Config, fun testDef/3).
testDef(Config, Rule, Opts) ->
asn1_test_lib:compile("Def", Config, [Rule|Opts]),
@@ -450,9 +454,13 @@ testSeqDefault(Config, Rule, Opts) ->
testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
testSeqExtension(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqExtension"], Config,
+ asn1_test_lib:compile_all(["External",
+ "SeqExtension",
+ "SeqExtension2"],
+ Config,
[Rule|Opts]),
- testSeqExtension:main(Rule).
+ DataDir = ?config(data_dir, Config),
+ testSeqExtension:main(Rule, DataDir, [Rule|Opts]).
testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
testSeqExternal(Config, Rule, Opts) ->
@@ -512,8 +520,7 @@ testSeqOfCho(Config, Rule, Opts) ->
testSeqOfCho:main(Rule).
testSeqOfIndefinite(Config) ->
- test(Config, fun testSeqOfIndefinite/3,
- [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]).
+ test(Config, fun testSeqOfIndefinite/3, [ber]).
testSeqOfIndefinite(Config, Rule, Opts) ->
Files = ["Mvrasn-Constants-1", "Mvrasn-DataTypes-1", "Mvrasn-21-4",
"Mvrasn-20-4", "Mvrasn-19-4", "Mvrasn-18-4", "Mvrasn-17-4",
@@ -629,32 +636,62 @@ c_syntax(Config) ->
"SeqBadComma"]].
c_string(Config) ->
- test(Config, fun c_string/3, [per, per_bin, ber, ber_bin, ber_bin_v2]).
+ test(Config, fun c_string/3).
c_string(Config, Rule, Opts) ->
- asn1_test_lib:compile("String", Config, [Rule|Opts]).
+ asn1_test_lib:compile("String", Config, [Rule|Opts]),
+ asn1ct:test('String').
c_implicit_before_choice(Config) ->
- test(Config, fun c_implicit_before_choice/3,
- [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun c_implicit_before_choice/3, [ber]).
c_implicit_before_choice(Config, Rule, Opts) ->
DataDir = ?config(data_dir, Config),
CaseDir = ?config(case_dir, Config),
{error, _R2} = asn1ct:compile(filename:join(DataDir, "CCSNARG3"),
[Rule, {outdir, CaseDir}|Opts]).
+constraint_equivalence(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ Asn1Spec = "ConstraintEquivalence",
+ Asn1Src = filename:join(DataDir, Asn1Spec),
+ ok = asn1ct:compile(Asn1Src, [abs,{outdir,CaseDir}]),
+ AbsFile = filename:join(CaseDir, Asn1Spec++".abs"),
+ {ok,Terms} = file:consult(AbsFile),
+ Cs = [begin
+ Constraints = element(4, Type),
+ Name1 = atom_to_list(Name0),
+ {Name,_} = lists:splitwith(fun(C) -> C =/= $X end, Name1),
+ {Name,Constraints}
+ end || {typedef,_,_,Name0,Type} <- Terms],
+ R = sofs:relation(Cs, [{name,constraint}]),
+ F0 = sofs:relation_to_family(R),
+ F = sofs:to_external(F0),
+ Diff = [E || {_,L}=E <- F, length(L) > 1],
+ case Diff of
+ [] ->
+ ok;
+ [_|_] ->
+ io:put_chars("Not equivalent:\n"),
+ [io:format("~s: ~p\n", [N,D]) || {N,D} <- Diff],
+ test_server:fail(length(Diff))
+ end.
+
parse(Config) ->
[asn1_test_lib:compile(M, Config, [abs]) || M <- test_modules()].
per(Config) ->
- test(Config, fun per/3, [per, per_bin, {per_bin, [optimize]}]).
+ test(Config, fun per/3, [per,uper]).
per(Config, Rule, Opts) ->
[module_test(M, Config, Rule, Opts) || M <- per_modules()].
ber_other(Config) ->
- test(Config, fun ber_other/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun ber_other/3, [ber]).
+
ber_other(Config, Rule, Opts) ->
[module_test(M, Config, Rule, Opts) || M <- ber_modules()].
+der(Config) ->
+ asn1_test_lib:compile_all(ber_modules(), Config, [der]).
module_test(M, Config, Rule, Opts) ->
asn1_test_lib:compile(M, Config, [Rule|Opts]),
@@ -666,12 +703,12 @@ module_test(M, Config, Rule, Opts) ->
ber_choiceinseq(Config) ->
- test(Config, fun ber_choiceinseq/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun ber_choiceinseq/3, [ber]).
ber_choiceinseq(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoiceInSeq", Config, [Rule|Opts]).
ber_optional(Config) ->
- test(Config, fun ber_optional/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun ber_optional/3, [ber]).
ber_optional(Config, Rule, Opts) ->
asn1_test_lib:compile("SOpttest", Config, [Rule|Opts]),
V = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
@@ -682,21 +719,6 @@ ber_optional(Config, Rule, Opts) ->
V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
V = element(2, V2).
-ber_optional_keyed_list(Config) ->
- test(Config, fun ber_optional_keyed_list/3, [ber, ber_bin]).
-ber_optional_keyed_list(Config, Rule, Opts) ->
- asn1_test_lib:compile("SOpttest", Config, [Rule, keyed_list|Opts]),
- Vrecord = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
- {'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE},
- {'C', asn1_NOVALUE, 111, asn1_NOVALUE}},
- V = [{a, [{scriptKey, 10}]},
- {b, []},
- {c, [{callingPartysCategory, 111}]}],
- {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V),
- Bytes = lists:flatten(B),
- V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
- Vrecord = element(2, V2).
-
%% records used by test-case default
-record('Def1', {bool0,
bool1 = asn1_DEFAULT,
@@ -721,17 +743,8 @@ value_test(Config, Rule, Opts) ->
{ok, _} = asn1ct:test('ObjIdValues', 'ObjIdType',
'ObjIdValues':'mobileDomainId'()).
-value_bad_enum_test(Config) ->
- case ?MODULE of
- asn1_SUITE ->
- {error, _} = asn1ct:compile(?config(data_dir, Config)
- ++ "BadEnumValue1",
- [{outdir, ?config(case_dir, Config)}]);
- _ -> {skip, "Runs in asn1_SUITE only"}
- end.
-
constructed(Config) ->
- test(Config, fun constructed/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun constructed/3, [ber]).
constructed(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
{ok, B} = asn1_wrapper:encode('Constructed', 'S', {'S', false}),
@@ -742,7 +755,7 @@ constructed(Config, Rule, Opts) ->
[136, 1, 10] = lists:flatten(B2).
ber_decode_error(Config) ->
- test(Config, fun ber_decode_error/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun ber_decode_error/3, [ber]).
ber_decode_error(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
ber_decode_error:run(Opts).
@@ -755,14 +768,14 @@ h323test(Config, Rule, Opts) ->
h323test:run(Rule).
per_GeneralString(Config) ->
- test(Config, fun per_GeneralString/3, [per, per_bin]).
+ test(Config, fun per_GeneralString/3, [per]).
per_GeneralString(Config, Rule, Opts) ->
asn1_test_lib:compile("MULTIMEDIA-SYSTEM-CONTROL", Config, [Rule|Opts]),
UI = [109, 64, 1, 57],
{ok, _V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
'MultimediaSystemControlMessage', UI).
-per_open_type(Config) -> test(Config, fun per_open_type/3, [per, per_bin]).
+per_open_type(Config) -> test(Config, fun per_open_type/3, [per]).
per_open_type(Config, Rule, Opts) ->
asn1_test_lib:compile("OpenType", Config, [Rule|Opts]),
{ok, _} = asn1ct:test('OpenType', 'Ot', {'Stype', 10, true}).
@@ -775,24 +788,24 @@ testConstraints(Config, Rule, Opts) ->
testSeqIndefinite(Config) ->
- test(Config, fun testSeqIndefinite/3, [ber, ber_bin, ber_bin_v2,
- {ber_bin_v2, [nif]}]).
+ test(Config, fun testSeqIndefinite/3, [ber]).
+
testSeqIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
testSeqIndefinite:main(Rule).
testSetIndefinite(Config) ->
- test(Config, fun testSetIndefinite/3, [ber, ber_bin, ber_bin_v2,
- {ber_bin_v2, [nif]}]).
+ test(Config, fun testSetIndefinite/3, [ber]).
+
testSetIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
testSetIndefinite:main(Rule).
testChoiceIndefinite(Config) ->
- test(Config, fun testChoiceIndefinite/3, [ber, ber_bin, ber_bin_v2,
- {ber_bin_v2, [nif]}]).
+ test(Config, fun testChoiceIndefinite/3, [ber]).
+
testChoiceIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoiceIndef", Config, [Rule|Opts]),
testChoiceIndefinite:main(Rule).
@@ -817,12 +830,6 @@ testParameterizedInfObj(Config, Rule, Opts) ->
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
testParameterizedInfObj:main(Config, Rule).
-testFragmented(Config) ->
- test(Config, fun testFragmented/3).
-testFragmented(Config, Rule, Opts) ->
- asn1_test_lib:compile("Fragmented", Config, [Rule|Opts]),
- testFragmented:main(Rule).
-
testMergeCompile(Config) -> test(Config, fun testMergeCompile/3).
testMergeCompile(Config, Rule, Opts) ->
Files = ["MS.set.asn", "RANAPSET.set.asn1", "Mvrasn4.set.asn",
@@ -850,18 +857,13 @@ testInvokeMod(Config, Rule, Opts) ->
{ok, _Result2} = 'PrimStrings':encode('Bs1', [1, 0, 1, 0]).
testExport(Config) ->
- case ?MODULE of
- asn1_SUITE ->
- {error, {asn1, _Reason}} =
- asn1ct:compile(filename:join(?config(data_dir, Config),
- "IllegalExport"),
- [{outdir, ?config(case_dir, Config)}]);
- _ ->
- {skip, "Runs in asn1_SUITE only"}
- end.
+ {error, _} =
+ asn1ct:compile(filename:join(?config(data_dir, Config),
+ "IllegalExport"),
+ [{outdir, ?config(case_dir, Config)}]).
testImport(Config) ->
- test(Config, fun testImport/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun testImport/3).
testImport(Config, Rule, Opts) ->
{error, _} = asn1ct:compile(filename:join(?config(data_dir, Config),
"ImportsFrom"),
@@ -899,19 +901,14 @@ testOpenTypeImplicitTag(Config, Rule, Opts) ->
testOpenTypeImplicitTag:main(Rule).
duplicate_tags(Config) ->
- case ?MODULE of
- asn1_SUITE ->
- DataDir = ?config(data_dir, Config),
- CaseDir = ?config(case_dir, Config),
- {error, {asn1, [{error, {type, _, _, 'SeqOpt1Imp', {asn1, {duplicates_of_the_tags, _}}}}]}} =
- asn1ct:compile(filename:join(DataDir, "SeqOptional2"),
- [abs, {outdir, CaseDir}]);
- _ ->
- {skip, "Runs in asn1_SUITE only"}
- end.
+ DataDir = ?config(data_dir, Config),
+ CaseDir = ?config(case_dir, Config),
+ {error, [{error, {type, _, _, 'SeqOpt1Imp',
+ {asn1, {duplicates_of_the_tags, _}}}}]} =
+ asn1ct:compile(filename:join(DataDir, "SeqOptional2"),
+ [abs, {outdir, CaseDir}]).
-rtUI(Config) -> test(Config, fun rtUI/3, [per, per_bin, ber,
- ber_bin, ber_bin_v2]).
+rtUI(Config) -> test(Config, fun rtUI/3).
rtUI(Config, Rule, Opts) ->
asn1_test_lib:compile("Prim", Config, [Rule|Opts]),
{ok, _} = asn1rt:info('Prim').
@@ -927,19 +924,19 @@ testINSTANCE_OF(Config, Rule, Opts) ->
testINSTANCE_OF:main(Rule).
testTCAP(Config) ->
- test(Config, fun testTCAP/3,
- [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]).
+ test(Config, fun testTCAP/3).
testTCAP(Config, Rule, Opts) ->
testTCAP:compile(Config, [Rule|Opts]),
testTCAP:test(Rule, Config),
case Rule of
- ber_bin_v2 -> testTCAP:compile_asn1config(Config, [Rule, asn1config]),
- testTCAP:test_asn1config();
- _ -> ok
+ ber ->
+ testTCAP:compile_asn1config(Config, [Rule, asn1config]),
+ testTCAP:test_asn1config();
+ _ -> ok
end.
testDER(Config) ->
- test(Config, fun testDER/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun testDER/3, [ber]).
testDER(Config, Rule, Opts) ->
asn1_test_lib:compile("DERSpec", Config, [Rule, der|Opts]),
testDER:test(),
@@ -949,7 +946,7 @@ testDER(Config, Rule, Opts) ->
testSeqSetDefaultVal:main(Rule).
specialized_decodes(Config) ->
- test(Config, fun specialized_decodes/3, [ber_bin_v2]).
+ test(Config, fun specialized_decodes/3, [ber]).
specialized_decodes(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["PartialDecSeq.asn",
"PartialDecSeq2.asn",
@@ -957,13 +954,12 @@ specialized_decodes(Config, Rule, Opts) ->
"PartialDecMyHTTP.asn",
"MEDIA-GATEWAY-CONTROL.asn",
"P-Record"],
- Config, [Rule, optimize, asn1config|Opts]),
+ Config, [Rule, asn1config|Opts]),
test_partial_incomplete_decode:test(Config),
test_selective_decode:test().
special_decode_performance(Config) ->
- test(Config, fun special_decode_performance/3,
- [{ber_bin, [optimize]}, {ber_bin_v2, [optimize, nif]}]).
+ test(Config, fun special_decode_performance/3, [ber]).
special_decode_performance(Config, Rule, Opts) ->
Files = ["MEDIA-GATEWAY-CONTROL", "PartialDecSeq"],
asn1_test_lib:compile_all(Files, Config, [Rule, asn1config|Opts]),
@@ -971,19 +967,24 @@ special_decode_performance(Config, Rule, Opts) ->
test_driver_load(Config) ->
- test(Config, fun test_driver_load/3, [{per_bin, [optimize]}]).
+ test(Config, fun test_driver_load/3, [per]).
test_driver_load(Config, Rule, Opts) ->
asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
test_driver_load:test(5).
test_ParamTypeInfObj(Config) ->
- asn1_test_lib:compile("IN-CS-1-Datatypes", Config, [ber_bin]).
+ asn1_test_lib:compile("IN-CS-1-Datatypes", Config, [ber]).
-test_WS_ParamClass(Config) ->
- asn1_test_lib:compile("InformationFramework", Config, [ber_bin]).
+test_WS_ParamClass(Config) -> test(Config, fun test_WS_ParamClass/3).
+test_WS_ParamClass(Config, Rule, Opts) ->
+ asn1_test_lib:compile("InformationFramework", Config, [Rule|Opts]),
+ ?only_ber(testWSParamClass:main(Rule)),
+ ok.
test_Defed_ObjectIdentifier(Config) ->
- asn1_test_lib:compile("UsefulDefinitions", Config, [ber_bin]).
+ test(Config, fun test_Defed_ObjectIdentifier/3).
+test_Defed_ObjectIdentifier(Config, Rule, Opts) ->
+ asn1_test_lib:compile("UsefulDefinitions", Config, [Rule|Opts]).
testSelectionType(Config) -> test(Config, fun testSelectionType/3).
testSelectionType(Config, Rule, Opts) ->
@@ -991,19 +992,13 @@ testSelectionType(Config, Rule, Opts) ->
{ok, _} = testSelectionTypes:test().
testSSLspecs(Config) ->
- test(Config, fun testSSLspecs/3, [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [optimize]}]).
+ test(Config, fun testSSLspecs/3, [ber]).
testSSLspecs(Config, Rule, Opts) ->
ok = testSSLspecs:compile(Config,
[Rule, compact_bit_string, der|Opts]),
testSSLspecs:run(Rule),
-
- case code:which(asn1ct) of
- cover_compiled ->
- ok;
- _ ->
- ok = testSSLspecs:compile_inline(Config, Rule),
- ok = testSSLspecs:run_inline(Rule)
- end.
+ ok = testSSLspecs:compile_combined(Config, Rule),
+ ok = testSSLspecs:run_combined(Rule).
testNortel(Config) -> test(Config, fun testNortel/3).
testNortel(Config, Rule, Opts) ->
@@ -1014,47 +1009,35 @@ test_undecoded_rest(Config, Rule, Opts) ->
asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
ok = test_undecoded_rest:test([], Config),
asn1_test_lib:compile("P-Record", Config, [Rule,undec_rest|Opts]),
- case Rule of
- ber_bin_v2 -> ok;
- _ -> test_undecoded_rest:test(undec_rest, Config)
- end.
-
-test_inline(Config) ->
- test(Config, fun test_inline/3, [ber, ber_bin, ber_bin_v2]).
-test_inline(Config, Rule, Opts) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip, "Not runnable when cover compiled"};
- _ ->
- test_inline:compile(Config, Opts),
- test_inline:main(Config, Rule),
- test_inline:inline1(Config, Rule, Opts),
- test_inline:performance2()
- end.
+ test_undecoded_rest:test(undec_rest, Config).
testTcapsystem(Config) ->
- test(Config, fun testTcapsystem/3, [ber, ber_bin, ber_bin_v2]).
+ test(Config, fun testTcapsystem/3).
testTcapsystem(Config, Rule, Opts) ->
testTcapsystem:compile(Config, [Rule|Opts]).
-testNBAPsystem(Config) -> test(Config, fun testNBAPsystem/3,
- [per, per_bin, {per_bin, [optimize]}]).
+testNBAPsystem(Config) -> test(Config, fun testNBAPsystem/3, [per]).
testNBAPsystem(Config, Rule, Opts) ->
testNBAPsystem:compile(Config, [Rule|Opts]),
testNBAPsystem:test(Rule, Config).
+testS1AP(Config) -> test(Config, fun testS1AP/3).
+testS1AP(Config, Rule, Opts) ->
+ S1AP = ["S1AP-CommonDataTypes",
+ "S1AP-Constants",
+ "S1AP-Containers",
+ "S1AP-IEs",
+ "S1AP-PDU-Contents",
+ "S1AP-PDU-Descriptions"],
+ asn1_test_lib:compile_all(S1AP, Config, [Rule|Opts]).
+
test_compile_options(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip, "Not runnable when cover compiled"};
- _ ->
- ok = test_compile_options:wrong_path(Config),
- ok = test_compile_options:path(Config),
- ok = test_compile_options:noobj(Config),
- ok = test_compile_options:record_name_prefix(Config),
- ok = test_compile_options:verbose(Config),
- ok = test_compile_options:warnings_as_errors(Config)
- end.
+ ok = test_compile_options:wrong_path(Config),
+ ok = test_compile_options:path(Config),
+ ok = test_compile_options:noobj(Config),
+ ok = test_compile_options:record_name_prefix(Config),
+ ok = test_compile_options:verbose(Config),
+ ok = test_compile_options:warnings_as_errors(Config).
testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3).
testDoubleEllipses(Config, Rule, Opts) ->
@@ -1062,8 +1045,7 @@ testDoubleEllipses(Config, Rule, Opts) ->
testDoubleEllipses:main(Rule).
test_modified_x420(Config) ->
- test(Config, fun test_modified_x420/3,
- [ber,ber_bin,ber_bin_v2,{ber_bin_v2,[nif]}]).
+ test(Config, fun test_modified_x420/3, [ber]).
test_modified_x420(Config, Rule, Opts) ->
Files = [filename:join(modified_x420, F) || F <- ["PKCS7",
"InformationFramework",
@@ -1079,7 +1061,7 @@ testX420(Config) ->
"sparc-sun-solaris2.10" ->
{skip,"Too slow for an old Sparc"};
_ ->
- test(Config, fun testX420/3, [ber, ber_bin, ber_bin_v2])
+ test(Config, fun testX420/3, [ber])
end.
testX420(Config, Rule, Opts) ->
testX420:compile(Rule, [der|Opts], Config),
@@ -1087,13 +1069,12 @@ testX420(Config, Rule, Opts) ->
testX420:compile(Rule, Opts, Config).
test_x691(Config) ->
- test(Config, fun test_x691/3,
- [per, per_bin, uper_bin, {per_bin, [optimize]}]).
+ test(Config, fun test_x691/3, [per, uper]).
test_x691(Config, Rule, Opts) ->
Files = ["P-RecordA1", "P-RecordA2", "P-RecordA3"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
test_x691:cases(Rule, case Rule of
- uper_bin -> unaligned;
+ uper -> unaligned;
_ -> aligned
end),
asn1_test_lib:ticket_7708(Config, []),
@@ -1103,18 +1084,14 @@ ticket_6143(Config) ->
ok = test_compile_options:ticket_6143(Config).
testExtensionAdditionGroup(Config) ->
- %% FIXME problems with automatic tags [ber_bin], [ber_bin, optimize]
- test(Config, fun testExtensionAdditionGroup/3,
- [per_bin, {per_bin, [optimize]}, uper_bin]).
+ test(Config, fun testExtensionAdditionGroup/3).
testExtensionAdditionGroup(Config, Rule, Opts) ->
asn1_test_lib:compile("Extension-Addition-Group", Config, [Rule|Opts]),
asn1_test_lib:compile_erlang("extensionAdditionGroup", Config,
[debug_info]),
- extensionAdditionGroup:run([Rule|Opts]),
- extensionAdditionGroup:run2([Rule|Opts]),
- extensionAdditionGroup:run3(),
- asn1_test_lib:compile("EUTRA-RRC-Definitions", Config, [Rule, {record_name_prefix, "RRC-"}|Opts]),
- extensionAdditionGroup:run3([Rule|Opts]).
+ asn1_test_lib:compile("EUTRA-RRC-Definitions", Config,
+ [Rule,{record_name_prefix,"RRC-"}|Opts]),
+ extensionAdditionGroup:run(Rule).
% parse_modules() ->
% ["ImportsFrom"].
@@ -1124,11 +1101,8 @@ per_modules() ->
ber_modules() ->
[X || X <- test_modules(),
- X =/= "CommonDataTypes",
- X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
X =/= "H323-MESSAGES",
- X =/= "H235-SECURITY-MESSAGES",
- X =/= "MULTIMEDIA-SYSTEM-CONTROL"].
+ X =/= "H235-SECURITY-MESSAGES"].
test_modules() ->
["BitStr",
@@ -1145,6 +1119,7 @@ test_modules() ->
"Int",
"MAP-commonDataTypes",
"Null",
+ "NullTest",
"Octetstr",
"One",
"P-Record",
@@ -1195,46 +1170,17 @@ timer_compile(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"],
Config, [Rule|Opts]).
-testTimer_ber(suite) -> [];
testTimer_ber(Config) ->
timer_compile(Config,ber,[]),
testTimer:go(Config,ber).
-testTimer_ber_bin(suite) -> [];
-testTimer_ber_bin(Config) ->
- timer_compile(Config,ber_bin,[]),
- testTimer:go(Config,ber_bin).
-
-testTimer_ber_bin_opt(suite) -> [];
-testTimer_ber_bin_opt(Config) ->
- timer_compile(Config,ber_bin,[optimize]),
- testTimer:go(Config,ber_bin).
-
-testTimer_ber_bin_opt_driver(suite) -> [];
-testTimer_ber_bin_opt_driver(Config) ->
- timer_compile(Config,ber_bin,[optimize,driver]),
- testTimer:go(Config,ber_bin).
-
-testTimer_per(suite) -> [];
testTimer_per(Config) ->
timer_compile(Config,per,[]),
testTimer:go(Config,per).
-testTimer_per_bin(suite) -> [];
-testTimer_per_bin(Config) ->
- timer_compile(Config,per_bin,[]),
- testTimer:go(Config,per_bin).
-
-testTimer_per_bin_opt(suite) -> [];
-testTimer_per_bin_opt(Config) ->
- timer_compile(Config,per_bin,[optimize]),
- testTimer:go(Config,per_bin).
-
-
-testTimer_uper_bin(suite) -> [];
-testTimer_uper_bin(Config) ->
- timer_compile(Config,uper_bin,[]),
- {comment,_} = testTimer:go(Config,uper_bin).
+testTimer_uper(Config) ->
+ timer_compile(Config,uper,[]),
+ {comment,_} = testTimer:go(Config,uper).
%% Test of multiple-line comment, OTP-8043
testComment(suite) -> [];
@@ -1277,11 +1223,11 @@ testName2Number(Config) ->
ok.
ticket_7407(Config) ->
- asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper_bin]),
+ asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper]),
asn1_test_lib:ticket_7407_code(true),
asn1_test_lib:compile("EUTRA-extract-7407", Config,
- [uper_bin, no_final_padding]),
+ [uper, no_final_padding]),
asn1_test_lib:ticket_7407_code(false).
smp(suite) -> [];
@@ -1292,7 +1238,7 @@ smp(Config) ->
io:format("smp starting ~p workers\n",[NumOfProcs]),
Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
- ok = testNBAPsystem:compile(Config, [per_bin, optimize]),
+ ok = testNBAPsystem:compile(Config, [per]),
enc_dec(NumOfProcs,Msg,2),
@@ -1301,7 +1247,7 @@ smp(Config) ->
{Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
{Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
- ok = testNBAPsystem:compile(Config, [ber_bin, optimize, nif]),
+ ok = testNBAPsystem:compile(Config, [ber]),
{Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
{Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
@@ -1315,191 +1261,6 @@ smp(Config) ->
{skipped,"No smp support"}
end.
-per_performance(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- NifDir = filename:join(PrivDir,"nif"),
- ErlDir = filename:join(PrivDir,"erl"),
- file:make_dir(NifDir),file:make_dir(ErlDir),
-
- Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
- ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config],
- [per_bin, optimize]),
- ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config],
- [per_bin]),
-
- Modules = ['NBAP-CommonDataTypes',
- 'NBAP-Constants',
- 'NBAP-Containers',
- 'NBAP-IEs',
- 'NBAP-PDU-Contents',
- 'NBAP-PDU-Discriptions'],
-
-
- PreNif = fun() ->
- code:add_patha(NifDir),
- lists:foreach(fun(M) ->
- code:purge(M),
- code:load_file(M)
- end,Modules)
- end,
-
- PreErl = fun() ->
- code:add_patha(ErlDir),
- lists:foreach(fun(M) ->
- code:purge(M),
- code:load_file(M)
- end,Modules)
- end,
-
- Func = fun() ->
- element(1,timer:tc(
- asn1_wrapper,encode,['NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg]))
- end,
-
- nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}).
-
-ber_performance(Config) ->
-
- Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
- ok = testNBAPsystem:compile(Config, [ber_bin, optimize, nif]),
-
-
- BerFun = fun() ->
- {ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU', Msg),
- asn1_wrapper:decode(
- 'NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B)
- end,
- nif_vs_erlang_performance({BerFun,100000,32}).
-
-cert_pem_performance(Config) when is_list(Config) ->
- cert_pem_performance({100000, 32});
-cert_pem_performance({N,S}) ->
- nif_vs_erlang_performance({fun pem_performance:cert_pem/0,N,S}).
-
-dsa_pem_performance(Config) when is_list(Config) ->
- dsa_pem_performance({100000, 32});
-dsa_pem_performance({N,S}) ->
- nif_vs_erlang_performance({fun pem_performance:dsa_pem/0,N,S}).
-
-
-nif_vs_erlang_performance({{TC1,TC2},N,Sched}) ->
- random:seed({123,456,789}),
- io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]),
-
- {True,False} = exec(TC1,TC2,Sched,N+1),
-
- io:format("~ndone!~n"),
-
- io:format("~n"),TStats = print_stats(strip(True,N div 20)),
- io:format("~n"),FStats = print_stats(strip(False,N div 20)),
- Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n",
- [(element(2,FStats) - element(2,TStats)) /
- element(2,FStats) * 100]),
- io:format(Str),
- {comment, lists:flatten(Str)};
-nif_vs_erlang_performance({T,N,Sched}) ->
- PTC1 = fun() ->
- application:set_env(asn1, nif_loadable, true)
- end,
- PTC2 = fun() ->
- application:set_env(asn1, nif_loadable, false)
- end,
- TC = fun() ->
- element(1,timer:tc(T))
- end,
- nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}).
-
-
-print_stats(Data) ->
- Length = length(Data),
- Mean = lists:sum(Data) / Length,
- Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data),
- StdDev = math:sqrt(Variance / Length),
- Median = lists:nth(round(Length/2),Data),
- Min = lists:min(Data),
- Max = lists:max(Data),
- if Length < 20 ->
- io:format("Data: ~w~n",[Data]);
- true ->
- ok
- end,
- io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n",
- [Length,Mean,StdDev,Median,Min,Max]),
- {Length,Mean,StdDev,Median,Min,Max}.
-
-collect(Acc) ->
- receive
- {Tag,Val} ->
- Prev = proplists:get_value(Tag,Acc,[]),
- collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]}))
- after 100 ->
- Acc
- end.
-
-exec(One,Two,Max,N) ->
- exec(One,Two,Max,N,{[],[]}).
-exec(_,_,_,1,{D1,D2}) ->
- {lists:flatten(D1),lists:flatten(D2)};
-exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) ->
- Num = random:uniform(round(N/2)),
- if Num rem 3 == 0 ->
- timer:sleep(Num rem 1000);
- true ->
- ok
- end,
- Procs = random:uniform(MaxProcs),
- io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]),
- if Num rem 2 == 1 ->
- erlang:garbage_collect(),
- PreOne(),
- MoreOne = pexec(One, Num, Procs, []),
- erlang:garbage_collect(),
- PreTwo(),
- MoreTwo = pexec(Two, Num, Procs, []);
- true ->
- erlang:garbage_collect(),
- PreTwo(),
- MoreTwo = pexec(Two, Num, Procs, []),
- erlang:garbage_collect(),
- PreOne(),
- MoreOne = pexec(One, Num, Procs, [])
- end,
- exec(O,T,MaxProcs,N-Num,{[MoreOne|D1],
- [MoreTwo|D2]}).
-
-pexec(_Fun, _, 0, []) ->
- [];
-pexec(Fun, _, 0, [{Ref,Pid}|Rest]) ->
- receive
- {data,D} ->
- [D|pexec(Fun,0,0,[{Ref,Pid}|Rest])];
- {'DOWN', Ref, process, Pid, normal} ->
- pexec(Fun, 0,0,Rest)
- end;
-pexec(Fun, 0, 1, AccProcs) ->
- pexec(Fun, 0, 0, AccProcs);
-pexec(Fun, N, 1, AccProcs) ->
- [Fun()|pexec(Fun, N - 1, 1, AccProcs)];
-pexec(Fun, N, Procs, AccProcs) ->
- S = self(),
- Pid = spawn(fun() ->
- S ! {data,pexec(Fun,N,1,[])}
- end),
- Ref = erlang:monitor(process, Pid),
- pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]).
-
-strip(Data,Num) ->
- {_,R} = lists:split(Num,lists:sort(Data)),
- element(2,lists:split(Num,lists:reverse(R))).
-
-faster(A,B) ->
- (B - A)/B * 100.
-
enc_dec(1, Msg, N) ->
worker_loop(N, Msg);
enc_dec(NumOfProcs,Msg, N) ->
@@ -1537,7 +1298,7 @@ pforeach(_Fun,[],[]) ->
-record('Iu-ReleaseCommand',{first,second}).
ticket7904(Config) ->
- asn1_test_lib:compile("RANAPextract1", Config, [per_bin, optimize]),
+ asn1_test_lib:compile("RANAPextract1", Config, [per]),
Val1 = #'InitiatingMessage'{procedureCode=1,
criticality=ignore,
diff --git a/lib/asn1/test/asn1_SUITE_data/BadEnumValue1.asn b/lib/asn1/test/asn1_SUITE_data/BadEnumValue1.asn
deleted file mode 100644
index dbc224a74b..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/BadEnumValue1.asn
+++ /dev/null
@@ -1,8 +0,0 @@
-BadEnumValue1 DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-E3 ::= ENUMERATED {monday,thuesday(0)}
-enumWrongVal E3 ::= sunday
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Certificate.asn b/lib/asn1/test/asn1_SUITE_data/Certificate.asn
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Certificate.asn
+++ /dev/null
diff --git a/lib/asn1/test/asn1_SUITE_data/ChoExtension.asn1 b/lib/asn1/test/asn1_SUITE_data/ChoExtension.asn1
index 18473bae30..f6fe18be10 100644
--- a/lib/asn1/test/asn1_SUITE_data/ChoExtension.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ChoExtension.asn1
@@ -41,4 +41,10 @@ ChoExt4 ::= CHOICE
str OCTET STRING
}
+ChoEmptyRoot ::= CHOICE {
+ ...,
+ bool BOOLEAN,
+ int INTEGER (0..7)
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1 b/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1
new file mode 100644
index 0000000000..8b3d151502
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1
@@ -0,0 +1,62 @@
+ConstraintEquivalence DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+ SingleValueX42 ::= INTEGER (42)
+ SingleValueX1 ::= INTEGER ((42) ^ (42))
+ SingleValueX2 ::= INTEGER ((42) INTERSECTION (42))
+ SingleValueX3 ::= INTEGER ((42) | (42))
+ SingleValueX4 ::= INTEGER ((42) UNION (42))
+ SingleValueX5 ::= INTEGER ((42) INTERSECTION (MIN..MAX))
+ SingleValueX6 ::= INTEGER ((42) INTERSECTION (40..49))
+ SingleValueX7 ::= INTEGER (42..42)
+ SingleValueX8 ::= INTEGER (integer42)
+ SingleValueX9 ::= INTEGER (integer42..integer42)
+ SingleValueX10 ::= INTEGER ((integer42) INTERSECTION (40..49))
+
+ UnconstrainedX0 ::= INTEGER
+ UnconstrainedX1 ::= INTEGER (MIN..MAX)
+ UnconstrainedX2 ::= INTEGER (1|(MIN..MAX))
+ UnconstrainedX3 ::= INTEGER (1..10|(MIN..MAX))
+ UnconstrainedX4 ::= INTEGER ((MIN..MAX)|9|10)
+ UnconstrainedX5 ::= INTEGER ((MIN..MAX)|10..20)
+ UnconstrainedX6 ::= INTEGER ((MIN..MAX) UNION (10..20))
+
+ RangeX00 ::= INTEGER (5..10)
+ RangeX01 ::= INTEGER (4<..<11)
+ RangeX02 ::= INTEGER (5..<11)
+ RangeX03 ::= INTEGER (4<..10)
+ RangeX04 ::= INTEGER (5|6|7|8|9|10)
+ RangeX05 ::= INTEGER (10|9|8|7|6|5)
+ RangeX06 ::= INTEGER (5|6|7..10)
+ RangeX07 ::= INTEGER (integer4<..<integer11)
+
+ RangeX10 ::= INTEGER ((5..6) UNION (7..8) UNION (9|10))
+ RangeX11 ::= INTEGER ((5|6) UNION (7..8) UNION (9|10))
+ RangeX12 ::= INTEGER ((5|6) UNION (7|8) UNION (9|10))
+ RangeX13 ::= INTEGER ((5|6) UNION (7) UNION (8..10))
+ RangeX14 ::= INTEGER ((5|6) UNION (7) UNION (8..10))
+ RangeX15 ::= INTEGER ((5|6) UNION (7) UNION ((8..8)|(9..9)|(10)))
+ RangeX16 ::= INTEGER ((5|6) UNION (7) UNION (7<..<11))
+
+ RangeX20 ::= INTEGER (0..20) (5..10)
+ RangeX21 ::= INTEGER (0..10) (5..20)
+ RangeX22 ::= INTEGER (0..10) (5..20) (MIN..MAX)
+ RangeX23 ::= INTEGER ((0..10) INTERSECTION (5..20) ^ (MIN..MAX))
+ RangeX24 ::= INTEGER ((5|6|7|8|9|10) INTERSECTION (5..20) ^ (MIN..MAX))
+
+ UnconstrainedStringX00 ::= IA5String
+ UnconstrainedStringX01 ::= IA5String (SIZE (0..MAX))
+
+ ConstrainedStringX00 ::= IA5String (SIZE (0..5))
+ ConstrainedStringX01 ::= IA5String (SIZE (0|1|2|3|4|5))
+
+ -- Note: None of the back-ends care about the exact values
+ -- outside of the root range.
+ ExtConstrainedStringX00 ::= IA5String (SIZE (1..2, ...))
+ ExtConstrainedStringX01 ::= IA5String (SIZE (1|2, ..., 3))
+ ExtConstrainedStringX02 ::= IA5String (SIZE (1|2, ..., 3|4|5))
+
+ integer4 INTEGER ::= 4
+ integer11 INTEGER ::= 11
+ integer42 INTEGER ::= 42
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py
index 87243121f7..e4bc987e4c 100644
--- a/lib/asn1/test/asn1_SUITE_data/Constraints.py
+++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py
@@ -12,6 +12,12 @@ ContainedSubtype ::= INTEGER (INCLUDES Range10to20)
-- Some ranges for additional constrained number testing.
LongLong ::= INTEGER (0..18446744073709551615)
Range256to65536 ::= INTEGER (256..65536)
+SemiConstrained ::= INTEGER (100..MAX)
+NegSemiConstrained ::= INTEGER (-128..MAX)
+SemiConstrainedExt ::= INTEGER (42..MAX, ...)
+NegSemiConstrainedExt ::= INTEGER (-128..MAX, ...)
+
+-- Other constraints
FixedSize ::= OCTET STRING (SIZE(10))
FixedSize2 ::= OCTET STRING (SIZE(10|20))
VariableSize ::= OCTET STRING (SIZE(1..10))
@@ -86,5 +92,6 @@ Document ::= OCTET STRING (ENCODED BY pdf)
pdf OBJECT IDENTIFIER ::= {1,2,3,4,5}
+ShorterExt ::= IA5String (SIZE (5, ...))
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Def.py b/lib/asn1/test/asn1_SUITE_data/Def.py
deleted file mode 100644
index ff08ed6386..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Def.py
+++ /dev/null
@@ -1,31 +0,0 @@
-Def DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
-Def1 ::= SEQUENCE
-{
- bool0 [0] BOOLEAN,
- bool1 [1] BOOLEAN DEFAULT false,
- bool2 [2] BOOLEAN DEFAULT false,
- bool3 [3] BOOLEAN DEFAULT false
-}
-
-
-Def2 ::= SEQUENCE
-{
- bool10 [10] BOOLEAN,
- bool11 [11] BOOLEAN DEFAULT false,
- bool12 [12] BOOLEAN DEFAULT false,
- bool13 [13] BOOLEAN
-}
-
-
-Def3 ::= SEQUENCE
-{
- bool30 [30] BOOLEAN DEFAULT false,
- bool31 [31] BOOLEAN DEFAULT false,
- bool32 [32] BOOLEAN DEFAULT false,
- bool33 [33] BOOLEAN DEFAULT false
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/EUTRA-InterNodeDefinitions.asn b/lib/asn1/test/asn1_SUITE_data/EUTRA-InterNodeDefinitions.asn
deleted file mode 100644
index 5e6313dc02..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/EUTRA-InterNodeDefinitions.asn
+++ /dev/null
@@ -1,123 +0,0 @@
--- 3GPP TS 36.331 V8.8.0 (2009-12)
--- $Id$
---
-EUTRA-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-
-HandoverCommand ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE{
- handoverCommand-r8 HandoverCommand-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-HandoverCommand-r8-IEs ::= SEQUENCE {
- handoverCommandMessage OCTET STRING (CONTAINING DL-DCCH-Message),
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-HandoverPreparationInformation ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE{
- handoverPreparationInformation-r8 HandoverPreparationInformation-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-HandoverPreparationInformation-r8-IEs ::= SEQUENCE {
- ue-RadioAccessCapabilityInfo UE-CapabilityRAT-ContainerList,
- as-Config AS-Config OPTIONAL, -- Cond HO
- rrm-Config RRM-Config OPTIONAL,
- as-Context AS-Context OPTIONAL, -- Cond HO
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-UERadioAccessCapabilityInformation ::= SEQUENCE {
- criticalExtensions CHOICE {
- c1 CHOICE{
- ueRadioAccessCapabilityInformation-r8
- UERadioAccessCapabilityInformation-r8-IEs,
- spare7 NULL,
- spare6 NULL, spare5 NULL, spare4 NULL,
- spare3 NULL, spare2 NULL, spare1 NULL
- },
- criticalExtensionsFuture SEQUENCE {}
- }
-}
-
-UERadioAccessCapabilityInformation-r8-IEs ::= SEQUENCE {
- ue-RadioAccessCapabilityInfo OCTET STRING (CONTAINING UECapabilityInformation),
- nonCriticalExtension SEQUENCE {} OPTIONAL
-}
-
-
-AS-Config ::= SEQUENCE {
- sourceMeasConfig MeasConfig,
- sourceRadioResourceConfig RadioResourceConfigDedicated,
- sourceSecurityAlgorithmConfig SecurityAlgorithmConfig,
- sourceUE-Identity C-RNTI,
- sourceMasterInformationBlock MasterInformationBlock,
- sourceSystemInformationBlockType1 SystemInformationBlockType1,
- sourceSystemInformationBlockType2 SystemInformationBlockType2,
- antennaInfoCommon AntennaInfoCommon,
- sourceDl-CarrierFreq ARFCN-ValueEUTRA,
- ...
-}
-
-
-AS-Context ::= SEQUENCE {
- reestablishmentInfo ReestablishmentInfo OPTIONAL -- Cond HO
-}
-
-
-ReestablishmentInfo ::= SEQUENCE {
- sourcePhysCellId PhysCellId,
- targetCellShortMAC-I ShortMAC-I,
- additionalReestabInfoList AdditionalReestabInfoList OPTIONAL,
- ...
-}
-
-AdditionalReestabInfoList ::= SEQUENCE ( SIZE (1..maxReestabInfo) ) OF AdditionalReestabInfo
-
-AdditionalReestabInfo ::= SEQUENCE{
- cellIdentity CellIdentity,
- key-eNodeB-Star Key-eNodeB-Star,
- shortMAC-I ShortMAC-I
-}
-
-Key-eNodeB-Star ::= BIT STRING (SIZE (256))
-
-
-RRM-Config ::= SEQUENCE {
- ue-InactiveTime ENUMERATED {
- s1, s2, s3, s5, s7, s10, s15, s20,
- s25, s30, s40, s50, min1, min1s20c, min1s40,
- min2, min2s30, min3, min3s30, min4, min5, min6,
- min7, min8, min9, min10, min12, min14, min17, min20,
- min24, min28, min33, min38, min44, min50, hr1,
- hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6,
- hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2,
- day2hr12, day3, day4, day5, day7, day10, day14, day19,
- day24, day30, dayMoreThan30} OPTIONAL,
- ...
-}
-
-
-maxReestabInfo INTEGER ::= 32 -- Maximum number of KeNB* and shortMAC-I forwarded
- -- at handover for re-establishment preparation
-
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/EUTRA-UE-Variables.asn b/lib/asn1/test/asn1_SUITE_data/EUTRA-UE-Variables.asn
deleted file mode 100644
index 414140a6fb..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/EUTRA-UE-Variables.asn
+++ /dev/null
@@ -1,49 +0,0 @@
--- 3GPP TS 36.331 V8.8.0 (2009-12)
--- $Id$
---
-EUTRA-UE-Variables DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-
-VarMeasConfig ::= SEQUENCE {
- -- Measurement identities
- measIdList MeasIdToAddModList OPTIONAL,
- -- Measurement objects
- measObjectList MeasObjectToAddModList OPTIONAL,
- -- Reporting configurations
- reportConfigList ReportConfigToAddModList OPTIONAL,
- -- Other parameters
- quantityConfig QuantityConfig OPTIONAL,
- s-Measure RSRP-Range OPTIONAL,
- speedStatePars CHOICE {
- release NULL,
- setup SEQUENCE {
- mobilityStateParameters MobilityStateParameters,
- timeToTrigger-SF SpeedStateScaleFactors
- }
- } OPTIONAL
-}
-
-
-VarMeasReportList ::= SEQUENCE (SIZE (1..maxMeasId)) OF VarMeasReport
-
-VarMeasReport ::= SEQUENCE {
- -- List of measurement that have been triggered
- measId MeasId,
- cellsTriggeredList CellsTriggeredList OPTIONAL,
- numberOfReportsSent INTEGER
-}
-
-CellsTriggeredList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF PhysCellId
-
-
-VarShortMAC-Input ::= SEQUENCE {
- cellIdentity CellIdentity,
- physCellId PhysCellId,
- c-RNTI C-RNTI
-}
-
-
-
-END \ No newline at end of file
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
index 9ad1f6299e..8dc5f3d7e1 100644
--- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
@@ -1,28 +1,55 @@
-EnumExt DEFINITIONS AUTOMATIC TAGS ::=
-BEGIN
-
-Ext ::= ENUMERATED {
- blue(0),
- red(1),
- green(2),
- ...
-}
-
-Ext1 ::= ENUMERATED {
- blue(0),
- red(1),
- green(2),
- ...,
- orange(7)
-}
-
-Noext ::= ENUMERATED {
- blue(0),
- red(1),
- green(2)
-}
-
-Globalstate ::= ENUMERATED {def(1),com(2),preop(3),oper(4),noop(5),fail(6)}
-
-END
-
+EnumExt DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+Ext ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2),
+ ...
+}
+
+Ext1 ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2),
+ ...,
+ orange(7),
+ black(8),
+ magenta(9)
+}
+
+Noext ::= ENUMERATED {
+ blue(0),
+ red(1),
+ green(2)
+}
+
+Globalstate ::= ENUMERATED {def(1),com(2),preop(3),oper(4),noop(5),fail(6)}
+
+Seq ::= SEQUENCE {
+ e Ext1,
+ i INTEGER
+}
+
+EnumExtBig ::= ENUMERATED {
+ base,
+ ...,
+ e00,e01,e02,e03,e04,e05,e06,e07,e08,e09,e0a,e0b,e0c,e0d,e0e,e0f,
+ e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e1a,e1b,e1c,e1d,e1e,e1f,
+ e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e2a,e2b,e2c,e2d,e2e,e2f,
+ e30,e31,e32,e33,e34,e35,e36,e37,e38,e39,e3a,e3b,e3c,e3d,e3e,e3f,
+ e40,e41,e42,e43,e44,e45,e46,e47,e48,e49,e4a,e4b,e4c,e4d,e4e,e4f,
+ e50,e51,e52,e53,e54,e55,e56,e57,e58,e59,e5a,e5b,e5c,e5d,e5e,e5f,
+ e60,e61,e62,e63,e64,e65,e66,e67,e68,e69,e6a,e6b,e6c,e6d,e6e,e6f,
+ e70,e71,e72,e73,e74,e75,e76,e77,e78,e79,e7a,e7b,e7c,e7d,e7e,e7f,
+ e80
+}
+
+SeqBig ::= SEQUENCE {
+ b BOOLEAN,
+ e EnumExtBig,
+ i INTEGER
+}
+
+END
+
diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
index b7cc74ab07..0e905d8839 100644
--- a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
@@ -1,7 +1,7 @@
--
-- %CopyrightBegin%
--
--- Copyright Ericsson AB 2001-2012. All Rights Reserved.
+-- Copyright Ericsson AB 2001-2013. 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
@@ -118,4 +118,23 @@ AC-BarringConfig ::= SEQUENCE {
ac-BarringForSpecialAC BIT STRING (SIZE(5))
}
+InlinedSeq ::= SEQUENCE {
+ ...,
+ [[
+ s SEQUENCE {
+ a INTEGER,
+ b BOOLEAN
+ }
+ ]]
+}
+
+-- 'ExtAddGroup1' is used internally to represent fake sequences for
+-- extension addition groups. Make sure that a real sequence with that
+-- name at the top-level doesn't cause a problem.
+
+ExtAddGroup1 ::= SEQUENCE {
+ x INTEGER,
+ y INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1 b/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
deleted file mode 100644
index bfc939737f..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
+++ /dev/null
@@ -1,24 +0,0 @@
-Fragmented DEFINITIONS AUTOMATIC TAGS ::=
-BEGIN
-
-FUNCTION ::= CLASS {
- &code INTEGER UNIQUE,
- &b BOOLEAN,
- &ArgumentType
-}
-
-SS ::= SEQUENCE OF OCTET STRING
-
-val1 FUNCTION ::= {
- &code 1, &b FALSE, &ArgumentType SS
-}
-
-ObjSet FUNCTION ::= { val1 }
-
-PDU ::= SEQUENCE {
- code FUNCTION.&code ({ObjSet}),
- b FUNCTION.&b ({ObjSet}{@code}),
- arg FUNCTION.&ArgumentType ({ObjSet}{@code})
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/InfObj.asn b/lib/asn1/test/asn1_SUITE_data/InfObj.asn
index 0a437e12df..53e5043cb7 100644
--- a/lib/asn1/test/asn1_SUITE_data/InfObj.asn
+++ b/lib/asn1/test/asn1_SUITE_data/InfObj.asn
@@ -39,21 +39,6 @@ RANAP-PDU ::= CHOICE {
CLASS2 ::= RANAP-ELEMENTARY-PROCEDURE
-MY-CLASS ::= CLASS {
- &integerValue INTEGER UNIQUE,
- &booleanValue BOOLEAN,
- &stringValue PrintableString
- }
-
-myobject MY-CLASS ::= {
- &integerValue 12,
- &booleanValue TRUE,
- &stringValue "hejsan"
- }
-MyObjectSet MY-CLASS ::= {
- myobject
- }
-
InitiatingMessage ::= SEQUENCE {
procedureCode RANAP-ELEMENTARY-PROCEDURE.&procedureCode ({RANAP-ELEMENTARY-PROCEDURES}),
criticality RANAP-ELEMENTARY-PROCEDURE.&criticality ({RANAP-ELEMENTARY-PROCEDURES}{@procedureCode}),
@@ -148,6 +133,83 @@ id-Iu-Release3 INTEGER ::= 3
id-Iu-Release4 INTEGER ::= 4
id-Iu-Release5 INTEGER ::= 5
+--
+-- MY-CLASS
+--
+
+Seq ::= SEQUENCE {
+ int INTEGER,
+ str OCTET STRING
+}
+
+MY-CLASS ::= CLASS {
+ &Count DEFAULT INTEGER,
+ &integerValue INTEGER UNIQUE,
+ &booleanValue BOOLEAN,
+ &stringValue PrintableString
+}
+
+myobject MY-CLASS ::= {
+ &integerValue 12,
+ &booleanValue TRUE,
+ &stringValue "hejsan"
+}
+
+myotherobject MY-CLASS ::= {
+ &Count Seq,
+ &integerValue 42,
+ &booleanValue FALSE,
+ &stringValue "hoppsan"
+}
+
+MyObjectSet MY-CLASS ::= {
+ myobject | myotherobject |
+ {
+ -- Each character will be encoded in 3 bits in UPER, 4 bits in PER.
+ &Count NumericString (FROM("01234567") ^ SIZE(8)),
+ &integerValue 43,
+ &booleanValue TRUE,
+ &stringValue "tjosan"
+ }
+}
+
+MyPdu ::= SEQUENCE {
+ count MY-CLASS.&Count ({MyObjectSet}{@int}),
+ int MY-CLASS.&integerValue ({MyObjectSet}),
+ bool MY-CLASS.&booleanValue ({MyObjectSet}{@int}),
+ str MY-CLASS.&stringValue ({MyObjectSet}{@int})
+}
+
+Seq2 ::= SEQUENCE {
+ int MY-CLASS.&integerValue ({MyObjectSet}),
+ seqof SEQUENCE (1..10) OF MY-CLASS.&booleanValue ({MyObjectSet}{@int}),
+ setof SET (1..10) OF MY-CLASS.&booleanValue ({MyObjectSet}{@int})
+}
+
+--
+-- Class with constructed default
+--
+
+CONSTRUCTED-DEFAULT ::= CLASS {
+ &id INTEGER UNIQUE,
+ &Type DEFAULT SEQUENCE { a INTEGER, b BOOLEAN },
+ &ok BOOLEAN DEFAULT TRUE
+}
+
+constructed1 CONSTRUCTED-DEFAULT ::= { &id 1 }
+constructed2 CONSTRUCTED-DEFAULT ::= { &id 2, &ok false }
+
+ConstructedDefaultSet CONSTRUCTED-DEFAULT ::= {
+ constructed1 |
+ constructed2 |
+ { &id 3, &Type BOOLEAN }
+}
+
+ConstructedPdu ::= SEQUENCE {
+ id CONSTRUCTED-DEFAULT.&id ({ConstructedDefaultSet}),
+ content CONSTRUCTED-DEFAULT.&Type ({ConstructedDefaultSet}{@id})
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/InfObj2.asn b/lib/asn1/test/asn1_SUITE_data/InfObj2.asn
deleted file mode 100644
index faba7371a4..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/InfObj2.asn
+++ /dev/null
@@ -1,156 +0,0 @@
-InfObj2 DEFINITIONS ::=
-BEGIN
-
-
-RANAP-ELEMENTARY-PROCEDURE ::= CLASS {
- &InitiatingMessage ,
- &SuccessfulOutcome OPTIONAL,
- &Outcome DEFAULT NULL,
- &vartypvalue &Outcome,
- &FixTypeValSet PrintableString,
- &VarTypeValSet &InitiatingMessage,
- &infoObject RANAP-ELEMENTARY-PROCEDURE,
- &InfObjectSet CLASS2,
- &UnsuccessfulOutcome OPTIONAL,
- &procedureCode ProcedureCode UNIQUE,
- &criticality Criticality DEFAULT ignore
-}
-WITH SYNTAX {
- INITIATING MESSAGE &InitiatingMessage
- [SUCCESSFUL OUTCOME &SuccessfulOutcome]
- [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome]
- [OUTCOME &Outcome]
- PROCEDURE CODE &procedureCode
- [CRITICALITY &criticality]
-}
-
-RANAP-PDU ::= CHOICE {
- initiatingMessage [0] InitiatingMessage,
- substrings [1] SEQUENCE {
- type RANAP-ELEMENTARY-PROCEDURE.&procedureCode({RANAP-ELEMENTARY-PROCEDURES}),
- strings SEQUENCE OF CHOICE {
- initial [0] RANAP-ELEMENTARY-PROCEDURE.&Outcome({
- RANAP-ELEMENTARY-PROCEDURES}{@substrings.type}),
- final [1] RANAP-ELEMENTARY-PROCEDURE.&Outcome({RANAP-ELEMENTARY-PROCEDURES}{@substrings.type})
- }
- },
--- successfulOutcome SuccessfulOutcome,
--- unsuccessfulOutcome UnsuccessfulOutcome,
--- outcome Outcome,
- ...
- }
-
-CLASS2 ::= RANAP-ELEMENTARY-PROCEDURE
-
-MY-CLASS ::= CLASS {
- &integerValue INTEGER UNIQUE,
- &booleanValue BOOLEAN,
- &stringValue PrintableString
- }
-
-myobject MY-CLASS ::= {
- &integerValue 12,
- &booleanValue TRUE,
- &stringValue "hejsan"
- }
-MyObjectSet MY-CLASS ::= {
- myobject
- }
-
-InitiatingMessage ::= SEQUENCE {
- procedureCode RANAP-ELEMENTARY-PROCEDURE.&procedureCode ({RANAP-ELEMENTARY-PROCEDURES}),
- criticality RANAP-ELEMENTARY-PROCEDURE.&criticality ({RANAP-ELEMENTARY-PROCEDURES}{@procedureCode}),
- value RANAP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({RANAP-ELEMENTARY-PROCEDURES}{@procedureCode})
- }
-
-iu-Release RANAP-ELEMENTARY-PROCEDURE ::= {
- INITIATING MESSAGE Iu-ReleaseCommand
- SUCCESSFUL OUTCOME Iu-ReleaseComplete
- PROCEDURE CODE id-Iu-Release1
- CRITICALITY ignore
- }
-
-relocationPreparation RANAP-ELEMENTARY-PROCEDURE ::= {
- INITIATING MESSAGE INTEGER --Iu-ReleaseCommand
- SUCCESSFUL OUTCOME Iu-ReleaseComplete
- PROCEDURE CODE id-Iu-Release2
- CRITICALITY notify
- }
-
-object3 RANAP-ELEMENTARY-PROCEDURE ::= {
- &InitiatingMessage Iu-ReleaseCommand,
- &SuccessfulOutcome Iu-ReleaseComplete,
- &procedureCode id-Iu-Release3,
- &criticality reject
- }
-
-object4 RANAP-ELEMENTARY-PROCEDURE ::= {
- &InitiatingMessage INTEGER,
- &SuccessfulOutcome PrintableString,
- &procedureCode id-Iu-Release4,
- &criticality reject
- }
-
-object5 RANAP-ELEMENTARY-PROCEDURE ::= {
- &InitiatingMessage INTEGER,
- &SuccessfulOutcome PrintableString,
- &Outcome ProcedureCode,
- &vartypvalue 12,
- &infoObject object4,
- &InfObjectSet MyObjectSet,
- &procedureCode id-Iu-Release5,
- &criticality reject
- }
-
-
-RANAP-ELEMENTARY-PROCEDURES RANAP-ELEMENTARY-PROCEDURE ::= {
- iu-Release |
- relocationPreparation ,
- ...
- }
-
-RANAP-ELEMENTARY-PROCEDURES2 RANAP-ELEMENTARY-PROCEDURE ::= {
- iu-Release |
- relocationPreparation
- }
-
-
-OBJECTSET1 RANAP-ELEMENTARY-PROCEDURE ::= {
- {INITIATING MESSAGE Iu-ReleaseCommand SUCCESSFUL OUTCOME Iu-ReleaseComplete PROCEDURE CODE id-Iu-Release1 CRITICALITY ignore} | {INITIATING MESSAGE Iu-ReleaseCommand PROCEDURE CODE id-Iu-Release2}
- }
-
-OBJECTSET2 RANAP-ELEMENTARY-PROCEDURE ::= {
- iu-Release |
- {INITIATING MESSAGE Iu-ReleaseCommand SUCCESSFUL OUTCOME Iu-ReleaseComplete PROCEDURE CODE id-Iu-Release4 CRITICALITY ignore} |
- relocationPreparation |
- {INITIATING MESSAGE Iu-ReleaseCommand PROCEDURE CODE id-Iu-Release5} ,
- ...
- }
-
-OBJECTSET3 RANAP-ELEMENTARY-PROCEDURE ::= {
- iu-Release,
- ...
- }
-
-OBJECTSET4 RANAP-ELEMENTARY-PROCEDURE ::= {
- iu-Release
- }
-
-Iu-ReleaseCommand ::= SEQUENCE {
- first INTEGER,
- second BOOLEAN
- }
-
-Iu-ReleaseComplete ::= INTEGER (1..510)
-
-ProcedureCode ::= INTEGER (0..255)
-Criticality ::= ENUMERATED { reject, ignore, notify }
-id-Iu-Release1 INTEGER ::= 1
-id-Iu-Release2 INTEGER ::= 2
-id-Iu-Release3 INTEGER ::= 3
-id-Iu-Release4 INTEGER ::= 4
-id-Iu-Release5 INTEGER ::= 5
-
-END
-
-
diff --git a/lib/asn1/test/asn1_SUITE_data/MAP-insertSubscriberData-def.py b/lib/asn1/test/asn1_SUITE_data/MAP-insertSubscriberData-def.py
deleted file mode 100644
index 298319b0ed..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/MAP-insertSubscriberData-def.py
+++ /dev/null
@@ -1,102 +0,0 @@
-MAP-insertSubscriberData-def
- { ccitt (0) identified-organization( 4) etsi( 0) mobileDomain(0)
- gsm-Network( 1) modules( 3) map-Protocol( 4) version2(2) }
-DEFINITIONS ::=
-
-BEGIN
-
-EXPORTS
-InsertSubsDataArg, InsertSubsDatRes;
-IMPORTS
-IMSI, ISDN-AddressString, LMSI FROM MAP-commonDataTypes;
-
-InsertSubsDataArg ::= SEQUENCE{
- imsi [0] IMPLICIT IMSI OPTIONAL,
- msisdn [1] IMPLICIT ISDN-AddressString OPTIONAL,
- category [2] IMPLICIT OCTET STRING (SIZE(1)) OPTIONAL,
- subscriberStatus [3] IMPLICIT SubscriberStatus OPTIONAL,
- bearerServiceList [4] IMPLICIT SEQUENCE OF
- OCTET STRING(SIZE(1)) OPTIONAL,
- teleServiceList [6] IMPLICIT SEQUENCE OF
- OCTET STRING(SIZE(1)) OPTIONAL,
- provisionedSS [7] IMPLICIT SEQUENCE OF SS-Information OPTIONAL
- }
-
-SS-Information ::= CHOICE{
- forwardingInfo [0] IMPLICIT ForwardingInfo,
- callBarringInfoInfo [1] IMPLICIT CallBarringInfoInfo,
- ss-Data [3] IMPLICIT SS-Data }
-
-SS-Data ::= SEQUENCE {
- ss-Code OCTET STRING (SIZE(1)),
- ss-Status [4] IMPLICIT OCTET STRING (SIZE(1))
- }
-
-
-ForwardingInfo ::= SEQUENCE {
- ss-Code OCTET STRING(SIZE(1)) OPTIONAL,
- forwardingFeatureList ForwardingFeatureList
- }
-
-CallBarringInfoInfo ::= SEQUENCE {
- ss-Code OCTET STRING(SIZE(1)) OPTIONAL,
- callBarringFeatureList CallBarringFeatureList}
-
-CallBarringFeatureList ::= SEQUENCE OF CallBarringFeature
-
-CallBarringFeature ::= SEQUENCE{
- basicService BasicServiceCode OPTIONAL,
- ss-Status [2] IMPLICIT OCTET STRING(SIZE(1)) OPTIONAL
- }
-
-InsertSubsDatRes ::=
- SEQUENCE {
- teleServiceList [1] IMPLICIT SEQUENCE OF
- OCTET STRING (SIZE(1)) OPTIONAL,
- bearerServiceList [2] IMPLICIT SEQUENCE OF
- OCTET STRING (SIZE(1)) OPTIONAL,
- ss-List [3] IMPLICIT SEQUENCE OF
- OCTET STRING (SIZE(1)) OPTIONAL,
- odb-GeneralData [4] IMPLICIT BIT STRING {
- allOG-CallsBarred (0),
- internationalOGCallsBarred (1),
- internationalOGCallsNotToHPLMN-CountryBarred (2),
- premiumRateInformationOGCallsBarred (3),
- premiumRateEntertainementOGCallsBarred (4),
- ss-AccessBarred (5) } (SIZE(6)) OPTIONAL,
- regionalSubscriptionResponse [5] IMPLICIT ENUMERATED{
- msc-AreaRestricted (0),
- tooManyZoneCodes (1),
- zoneCodeConflict (2),
- regionalSubscNotSupported (3) } OPTIONAL
- }
-
-
-ForwardingFeatureList ::= SEQUENCE OF ForwardingFeature
-
-ForwardingFeature ::= SEQUENCE{
- basicService BasicServiceCode OPTIONAL,
- ss-Status [4] IMPLICIT OCTET STRING(SIZE(1)) OPTIONAL,
- forwardedToNumber [5] ISDN-AddressString OPTIONAL,
- forwardingOptions [6] IMPLICIT OCTET STRING(SIZE(1)) OPTIONAL,
- noReplyConditionTime [7] IMPLICIT INTEGER(5..30) OPTIONAL
- }
-
-
-BasicServiceCode ::= CHOICE {
- bearerService [2] IMPLICIT OCTET STRING(SIZE(1)),
- teleService [3] IMPLICIT OCTET STRING(SIZE(1))
- }
-
-
-BasicServiceGroupList ::= SEQUENCE OF
- BasicServiceCode
-
-
-SubscriberStatus ::= ENUMERATED {
- serviceGranted (0),
- operatorDeterminedBarring (1)
- }
-
-END -- of MAP-insertSubscriberData-def
-
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod.set.asn b/lib/asn1/test/asn1_SUITE_data/Mod.set.asn
deleted file mode 100644
index 5dcd8706ae..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod.set.asn
+++ /dev/null
@@ -1,5 +0,0 @@
-Mod1.asn
-Mod2.asn
-Mod3.asn
-Mod4.asn
-Mod5.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod1.asn b/lib/asn1/test/asn1_SUITE_data/Mod1.asn
deleted file mode 100644
index cb29997985..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod1.asn
+++ /dev/null
@@ -1,18 +0,0 @@
-Mod1 DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- Co,Reg
- FROM Mod5
- Name
- FROM Mod4;
-
-
-L ::= SEQUENCE {
- country Co,
- region Reg,
- name Name
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod2.asn b/lib/asn1/test/asn1_SUITE_data/Mod2.asn
deleted file mode 100644
index cc22c6f13c..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod2.asn
+++ /dev/null
@@ -1,43 +0,0 @@
-Mod2 DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- Stat,Country
- FROM Mod3
- L
- FROM Mod1
- Time,LocName,ThingName,Name
- FROM Mod4;
-
-T ::= SEQUENCE {
- unit ENUMERATED{celsius,fahrenheit,kelvin},
- degree INTEGER,
- location L,
- time Time,
- statistics Stat
-}
-
-OtherName ::= SEQUENCE {
- locationName LocName,
- thingName ThingName
-}
-
-FirstName ::= CHOICE {
- firstname PrintableString,
- nickname PrintableString
-}
-
-FamilyName ::= SEQUENCE{
- prefix ENUMERATED{none,von,af},
- secondname PrintableString
-}
-
-Lang ::= SEQUENCE{
- l PrintableString}
-
-Inhabitant ::= SEQUENCE {
- name Name,
- country Country}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod3.asn b/lib/asn1/test/asn1_SUITE_data/Mod3.asn
deleted file mode 100644
index 8069bedcf9..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod3.asn
+++ /dev/null
@@ -1,33 +0,0 @@
-Mod3 DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- Name
- FROM Mod4
- Lang, Inhabitant,FirstName,FamilyName
- FROM Mod2
- TS, RFS, WS, HS
- FROM Mod5;
-
-Stat ::= SEQUENCE {
- tempstat TS,
- rainfallstat RFS,
- windstat WS,
- humiditystat HS
-}
-
-Country ::= SEQUENCE{
- name Name,
- language Lang
-}
-
-RegionName ::= Name
-Inhabitants ::= SEQUENCE OF Inhabitant
-
-PersonName ::= SEQUENCE {
- name1 FirstName,
- name2 FamilyName
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod4.asn b/lib/asn1/test/asn1_SUITE_data/Mod4.asn
deleted file mode 100644
index 4a1aaff9dc..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod4.asn
+++ /dev/null
@@ -1,33 +0,0 @@
-Mod4 DEFINITIONS AUTOMATIC TAGS ::=
-
-
-BEGIN
-
-IMPORTS
- PersonName
- FROM Mod3
- OtherName,FirstName,FamilyName
- FROM Mod2;
-
-Time ::= SEQUENCE {
- year OCTET STRING(SIZE(4)),
- month OCTET STRING(SIZE(2)),
- hour INTEGER,
- minute INTEGER
-}
-
-Name ::= CHOICE {
- person PersonName,
- othername OtherName
-}
-
-
-
-LocName ::= SEQUENCE {
- region ENUMERATED{gotaland,svealand,norrland},
- name PrintableString
-}
-
-ThingName ::= PrintableString
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Mod5.asn b/lib/asn1/test/asn1_SUITE_data/Mod5.asn
deleted file mode 100644
index 71b483d0e0..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mod5.asn
+++ /dev/null
@@ -1,37 +0,0 @@
-Mod5 DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- Country,RegionName,Inhabitants
- FROM Mod3;
-TS ::= SEQUENCE {
- average INTEGER,
- highest INTEGER,
- lowest INTEGER
-}
-
-RFS ::= SEQUENCE {
- average INTEGER,
- highest INTEGER
-}
-
-WS ::= SEQUENCE {
- average INTEGER,
- highest INTEGER
-}
-
-HS ::= SEQUENCE {
- average INTEGER,
- highest INTEGER,
- lowest INTEGER
-}
-
-Co ::= Country
-
-Reg ::= SEQUENCE {
- name RegionName,
- inhabitants Inhabitants
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/MultipleLevels.asn b/lib/asn1/test/asn1_SUITE_data/MultipleLevels.asn
new file mode 100644
index 0000000000..1824e1fa5a
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/MultipleLevels.asn
@@ -0,0 +1,19 @@
+MultipleLevels DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+Top ::= SEQUENCE {
+ country CountryName,
+ region Name
+}
+
+CountryName ::= CountryName0
+
+CountryName0 ::= Name
+
+Name ::= CHOICE {
+ short PrintableString (SIZE (0..10)),
+ long PrintableString
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Mvrasn.set.asn b/lib/asn1/test/asn1_SUITE_data/Mvrasn.set.asn
deleted file mode 100644
index 8a61da0160..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Mvrasn.set.asn
+++ /dev/null
@@ -1,7 +0,0 @@
-Mvrasn-11-6.asn
-Mvrasn-21-4.asn
-Mvrasn-20-6.asn
-Mvrasn-19-6.asn
-Mvrasn-15-6.asn
-Mvrasn-18-6.asn
-Mvrasn-14-6.asn
diff --git a/lib/asn1/test/asn1_SUITE_data/NullTest.asn1 b/lib/asn1/test/asn1_SUITE_data/NullTest.asn1
new file mode 100644
index 0000000000..041b20a4c1
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/NullTest.asn1
@@ -0,0 +1,14 @@
+NullTest DEFINITIONS ::=
+BEGIN
+
+NullTestData ::= SEQUENCE {
+ body NullBody,
+ tail INTEGER
+}
+
+NullBody ::= CHOICE {
+ null [0] NULL,
+ notNull [1] INTEGER
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/Opt.py b/lib/asn1/test/asn1_SUITE_data/Opt.py
deleted file mode 100644
index 48c2a09b64..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Opt.py
+++ /dev/null
@@ -1,31 +0,0 @@
-Opt DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
-Opt1 ::= SEQUENCE
-{
- bool0 [0] BOOLEAN,
- bool1 [1] BOOLEAN OPTIONAL,
- bool2 [2] BOOLEAN OPTIONAL,
- bool3 [3] BOOLEAN OPTIONAL
-}
-
-
-Opt2 ::= SEQUENCE
-{
- bool10 [10] BOOLEAN,
- bool11 [11] BOOLEAN OPTIONAL,
- bool12 [12] BOOLEAN OPTIONAL,
- bool13 [13] BOOLEAN
-}
-
-
-Opt3 ::= SEQUENCE
-{
- bool30 [30] BOOLEAN OPTIONAL,
- bool31 [31] BOOLEAN OPTIONAL,
- bool32 [32] BOOLEAN OPTIONAL,
- bool33 [33] BOOLEAN OPTIONAL
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/P-Record.asn1db b/lib/asn1/test/asn1_SUITE_data/P-Record.asn1db
deleted file mode 100644
index 13e1162c64..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/P-Record.asn1db
+++ /dev/null
Binary files differ
diff --git a/lib/asn1/test/asn1_SUITE_data/P-Record.erl b/lib/asn1/test/asn1_SUITE_data/P-Record.erl
deleted file mode 100644
index 9fc6f50d64..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/P-Record.erl
+++ /dev/null
@@ -1,244 +0,0 @@
-%% Generated by the Erlang ASN.1 BER-compiler version, utilizing bit-syntax:1.3.1.4
-%% Purpose: encoder and decoder to the types in mod P-Record
-
--module('P-Record').
--include("P-Record.hrl").
--define('RT_PER',asn1rt_per_bin).
--export([encoding_rule/0]).
--export([
-'enc_PersonnelRecord'/1,
-'enc_ChildInformation'/1,
-'enc_Name'/1,
-'enc_EmployeeNumber'/1,
-'enc_Date'/1
-]).
-
--export([
-'dec_PersonnelRecord'/2,
-'dec_ChildInformation'/2,
-'dec_Name'/2,
-'dec_EmployeeNumber'/2,
-'dec_Date'/2
-]).
-
--export([
-'v'/0
-]).
-
-
-
--export([encode/2,decode/2,encode_disp/2,decode_disp/2]).
-
-encoding_rule() ->
- per_bin.
-
-encode(Type,Data) ->
-case catch ?RT_PER:complete(encode_disp(Type,Data)) of
- {'EXIT',{error,Reason}} ->
- {error,Reason};
- {'EXIT',Reason} ->
- {error,{asn1,Reason}};
- {Bytes,Len} ->
- {ok,Bytes};
- X ->
- {ok,X}
-end.
-
-decode(Type,Data) ->
-case catch decode_disp(Type,Data) of
- {'EXIT',{error,Reason}} ->
- {error,Reason};
- {'EXIT',Reason} ->
- {error,{asn1,Reason}};
- {X,_Rest} ->
- {ok,X};
- {X,_Rest,_Len} ->
- {ok,X}
-end.
-
-encode_disp('PersonnelRecord',Data) -> 'enc_PersonnelRecord'(Data);
-encode_disp('ChildInformation',Data) -> 'enc_ChildInformation'(Data);
-encode_disp('Name',Data) -> 'enc_Name'(Data);
-encode_disp('EmployeeNumber',Data) -> 'enc_EmployeeNumber'(Data);
-encode_disp('Date',Data) -> 'enc_Date'(Data);
-encode_disp(Type,Data) -> exit({error,{asn1,{undefined_type,Type}}}).
-
-
-decode_disp('PersonnelRecord',Data) -> 'dec_PersonnelRecord'(Data,mandatory);
-decode_disp('ChildInformation',Data) -> 'dec_ChildInformation'(Data,mandatory);
-decode_disp('Name',Data) -> 'dec_Name'(Data,mandatory);
-decode_disp('EmployeeNumber',Data) -> 'dec_EmployeeNumber'(Data,mandatory);
-decode_disp('Date',Data) -> 'dec_Date'(Data,mandatory);
-decode_disp(Type,Data) -> exit({error,{asn1,{undefined_type,Type}}}).
-
-
-
-
-
-'enc_PersonnelRecord'(Val) ->
-{Val1,Opt} = ?RT_PER:fixoptionals([{children,6}],Val),
-[
-?RT_PER:setoptionals(Opt),
-
-%% attribute number 1 with type Externaltypereference6P-RecordName
-'enc_Name'(?RT_PER:cindex(2,Val1,name)),
-
-%% attribute number 2 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(3,Val1,title)),
-
-%% attribute number 3 with type INTEGER
-?RT_PER:encode_integer([],?RT_PER:cindex(4,Val1,number)),
-
-%% attribute number 4 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(5,Val1,dateOfHire)),
-
-%% attribute number 5 with type Externaltypereference10P-RecordName
-'enc_Name'(?RT_PER:cindex(6,Val1,nameOfSpouse)),
-case ?RT_PER:cindex(7,Val1,children) of
-asn1_DEFAULT -> [];
-_ ->
-
-%% attribute number 6 with type SEQUENCE OF
-'enc_PersonnelRecord_children'(?RT_PER:cindex(7,Val1,children))
-end].
-
-'enc_PersonnelRecord_children'({'PersonnelRecord_children',Val}) ->
-'enc_PersonnelRecord_children'(Val);
-
-'enc_PersonnelRecord_children'(Val) ->
-[
-
- ?RT_PER:encode_length(undefined,length(Val)),
- 'enc_PersonnelRecord_children_components'(Val, [])
-].
-'enc_PersonnelRecord_children_components'([], Acc) -> lists:reverse(Acc);
-
-'enc_PersonnelRecord_children_components'([H|T], Acc) ->
-'enc_PersonnelRecord_children_components'(T, ['enc_ChildInformation'(H)
-
- | Acc]).
-
-'dec_PersonnelRecord_children'(Bytes,Telltype) ->
-
-{Num,Bytes1} = ?RT_PER:decode_length(Bytes,undefined),
-'dec_PersonnelRecord_children_components'(Num, Bytes1, Telltype, []).
-'dec_PersonnelRecord_children_components'(0, Bytes, Telltype, Acc) ->
- {lists:reverse(Acc), Bytes};
-'dec_PersonnelRecord_children_components'(Num, Bytes, Telltype, Acc) ->
- {Term,Remain} = 'P-Record':'dec_ChildInformation'(Bytes,Telltype),
- 'dec_PersonnelRecord_children_components'(Num-1, Remain, Telltype, [Term|Acc]).
-
-
-'dec_PersonnelRecord'(Bytes,Telltype) ->
-{Opt,Bytes1} = ?RT_PER:getoptionals(Bytes,1),
-%% attribute number 1 with type Name
-{Term1,Bytes2} = 'dec_Name'(Bytes1,telltype),
-
-%% attribute number 2 with type VisibleString
-{Term2,Bytes3} = ?RT_PER:decode_VisibleString(Bytes2,[]),
-
-%% attribute number 3 with type INTEGER
-{Term3,Bytes4} = ?RT_PER:decode_integer(Bytes3,[]),
-
-%% attribute number 4 with type VisibleString
-{Term4,Bytes5} = ?RT_PER:decode_VisibleString(Bytes4,[]),
-
-%% attribute number 5 with type Name
-{Term5,Bytes6} = 'dec_Name'(Bytes5,telltype),
-
-%% attribute number 6 with type SEQUENCE OF
-{Term6,Bytes7} = case element(1,Opt) of
-1 ->'dec_PersonnelRecord_children'(Bytes6, Telltype);
-0 ->{[],Bytes6}
-
-end,
-{{'PersonnelRecord',Term1,Term2,Term3,Term4,Term5,Term6},Bytes7}.
-
-'enc_ChildInformation'(Val) ->
-{Val1,Opt} = ?RT_PER:fixoptionals([{name,1},{dateOfBirth,2}],Val),
-[
-?RT_PER:setoptionals(Opt),
-case ?RT_PER:cindex(2,Val1,name) of
-asn1_NOVALUE -> [];
-_ ->
-
-%% attribute number 1 with type Externaltypereference15P-RecordName
-'enc_Name'(?RT_PER:cindex(2,Val1,name))
-end,
-case ?RT_PER:cindex(3,Val1,dateOfBirth) of
-asn1_NOVALUE -> [];
-_ ->
-
-%% attribute number 2 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(3,Val1,dateOfBirth))
-end].
-
-
-'dec_ChildInformation'(Bytes,Telltype) ->
-{Opt,Bytes1} = ?RT_PER:getoptionals(Bytes,2),
-%% attribute number 1 with type Name
-{Term1,Bytes2} = case element(1,Opt) of
-1 ->'dec_Name'(Bytes1,telltype);
-0 ->{asn1_NOVALUE,Bytes1}
-
-end,
-
-%% attribute number 2 with type VisibleString
-{Term2,Bytes3} = case element(2,Opt) of
-1 ->?RT_PER:decode_VisibleString(Bytes2,[]);
-0 ->{asn1_NOVALUE,Bytes2}
-
-end,
-{{'ChildInformation',Term1,Term2},Bytes3}.
-
-'enc_Name'(Val) ->
-Val1 = ?RT_PER:list_to_record('Name', Val),
-[
-
-%% attribute number 1 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(2,Val1,givenName)),
-
-%% attribute number 2 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(3,Val1,initial)),
-
-%% attribute number 3 with type VisibleString
-?RT_PER:encode_VisibleString([],?RT_PER:cindex(4,Val1,familyName))].
-
-
-'dec_Name'(Bytes,Telltype) ->
-
-%% attribute number 1 with type VisibleString
-{Term1,Bytes1} = ?RT_PER:decode_VisibleString(Bytes,[]),
-
-%% attribute number 2 with type VisibleString
-{Term2,Bytes2} = ?RT_PER:decode_VisibleString(Bytes1,[]),
-
-%% attribute number 3 with type VisibleString
-{Term3,Bytes3} = ?RT_PER:decode_VisibleString(Bytes2,[]),
-{{'Name',Term1,Term2,Term3},Bytes3}.
-
-
-'enc_EmployeeNumber'({'EmployeeNumber',Val}) ->
-'enc_EmployeeNumber'(Val);
-
-'enc_EmployeeNumber'(Val) ->
-?RT_PER:encode_integer([],Val).
-
-
-'dec_EmployeeNumber'(Bytes,Telltype) ->
-?RT_PER:decode_integer(Bytes,[]).
-
-
-'enc_Date'({'Date',Val}) ->
-'enc_Date'(Val);
-
-'enc_Date'(Val) ->
-?RT_PER:encode_VisibleString([],Val).
-
-
-'dec_Date'(Bytes,Telltype) ->
-?RT_PER:decode_VisibleString(Bytes,[]).
-
-'v'() ->
-{'PersonnelRecord',{'Name',{74,111,104,110},[80],[83,109,105,116,104]},[68,105,114,101,99,116,111,114],51,[49,57,55,49,48,57,49,55],{'Name',{77,97,114,121},[84],[83,109,105,116,104]},[{'ChildInformation',{'Name',[82,97,108,112,104],[84],[83,109,105,116,104]},[49,57,53,55,49,49,49,49]},{'ChildInformation',{'Name',[83,117,115,97,110],[66],[74,111,110,101,115]},[49,57,53,57,48,55,49,55]}]}.
-
diff --git a/lib/asn1/test/asn1_SUITE_data/P-Record.hrl b/lib/asn1/test/asn1_SUITE_data/P-Record.hrl
deleted file mode 100644
index 92aa1a44e2..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/P-Record.hrl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% Generated by the Erlang ASN.1 compiler version:1.3.1.4
-%% Purpose: Erlang record definitions for each named and unnamed
-%% SEQUENCE and SET, and macro definitions for each value
-%% definition,in module P-Record
-
-
-
--record('PersonnelRecord',{
-name, title, number, dateOfHire, nameOfSpouse, children = asn1_DEFAULT}).
-
--record('ChildInformation',{
-name = asn1_NOVALUE, dateOfBirth = asn1_NOVALUE}).
-
--record('Name',{
-givenName, initial, familyName}).
-
--define('v', {'PersonnelRecord',{'Name',{74,111,104,110},[80],[83,109,105,116,104]},[68,105,114,101,99,116,111,114],51,[49,57,55,49,48,57,49,55],{'Name',{77,97,114,121},[84],[83,109,105,116,104]},[{'ChildInformation',{'Name',[82,97,108,112,104],[84],[83,109,105,116,104]},[49,57,53,55,49,49,49,49]},{'ChildInformation',{'Name',[83,117,115,97,110],[66],[74,111,110,101,115]},[49,57,53,57,48,55,49,55]}]}).
diff --git a/lib/asn1/test/asn1_SUITE_data/PDUs.py b/lib/asn1/test/asn1_SUITE_data/PDUs.py
deleted file mode 100644
index 907348193f..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/PDUs.py
+++ /dev/null
@@ -1,325 +0,0 @@
-PDUs DEFINITIONS ::=
-
--- Search for 'org' to find changes for erlang.
-
--- SnmpMgmtCom and PDUs only for dbg.
-
-
-BEGIN
-EXPORTS SnmpPrivMsg, SnmpAuthMsg, SnmpMgmtCom, PDUs;
-
--- From RFC 1442
-
- -- names of objects
-
- ObjectName ::=
- OBJECT IDENTIFIER
-
-
- -- syntax of objects
-
- ObjectSyntax ::=
- CHOICE {
- simple
- SimpleSyntax,
-
- -- note that SEQUENCEs for conceptual tables and
- -- rows are not mentioned here...
-
- applicationWide
- ApplicationSyntax
- }
-
-
- -- built-in ASN.1 types
-
- SimpleSyntax ::=
- CHOICE {
- -- INTEGERs with a more restrictive range
- -- may also be used
- integerValue
- INTEGER,
-
- stringValue
- OCTET STRING,
-
- objectIDValue
- OBJECT IDENTIFIER,
-
- -- only the enumerated form is allowed
- bitValue
- BIT STRING
- }
-
-
- -- indistinguishable from INTEGER, but never needs more than
- -- 32Bits for a two's complement representation
- Integer32 ::=
- [UNIVERSAL 2]
- IMPLICIT INTEGER (-2147483648..2147483647)
-
-
- -- applicationWide types
-
- ApplicationSyntax ::=
- CHOICE {
- ipAddressValue
- IpAddress,
-
- counterValue
- Counter32,
-
- gaugeValue
- Gauge32,
-
- timeticksValue
- TimeTicks,
-
- arbitraryValue
- Opaque,
-
- nsapAddressValue
- NsapAddress,
-
- bigCounterValue
- Counter64,
-
- unsignedIntegerValue
- UInteger32
- }
-
- -- in networkByte order
- -- (this is a tagged type for historical reasons)
- IpAddress ::=
- [APPLICATION 0]
- IMPLICIT OCTET STRING (SIZE (4))
-
-
-
-
- -- this wraps
- Counter32 ::=
- [APPLICATION 1]
- IMPLICIT INTEGER (0..4294967295)
-
- -- this doesn't wrap
- Gauge32 ::=
- [APPLICATION 2]
- IMPLICIT INTEGER (0..4294967295)
-
- -- hundredths of seconds since an epoch
- TimeTicks ::=
- [APPLICATION 3]
- IMPLICIT INTEGER (0..4294967295)
-
- -- for backwardCompatibility only
- Opaque ::=
- [APPLICATION 4]
- IMPLICIT OCTET STRING
-
- -- for OSI NSAP addresses
- -- (this is a tagged type for historical reasons)
- NsapAddress ::=
- [APPLICATION 5]
--- org: IMPLICIT OCTET STRING (SIZE (1 | 4..21))
- IMPLICIT OCTET STRING
-
- -- for counters that wrap in less than one hour with only 32 bits
- Counter64 ::=
- [APPLICATION 6]
- IMPLICIT INTEGER (0..18446744073709551615)
-
- -- an unsigned 32Bit quantity
- UInteger32 ::=
- [APPLICATION 7]
- IMPLICIT INTEGER (0..4294967295)
-
-
--- From RFC 1445
-
- SnmpPrivMsg ::= [1] IMPLICIT SEQUENCE {
- privDst
- OBJECT IDENTIFIER,
- privData
- [1] IMPLICIT OCTET STRING
- }
-
- SnmpAuthMsg ::= [1] IMPLICIT SEQUENCE {
- authInfo
- ANY, -- defined by authentication protocol
- authData
- SnmpMgmtCom
- }
-
- SnmpMgmtCom ::= [2] IMPLICIT SEQUENCE {
- dstParty
- OBJECT IDENTIFIER,
- srcParty
- OBJECT IDENTIFIER,
- context
- OBJECT IDENTIFIER,
- pdu
- PDUs
- }
-
-
--- From RFC 1448
-
- -- org: no tag at all. we need a tag to test 'PDUs'.
- PDUs ::= [PRIVATE 1]
- -- remove tag when 'PDUs' only is used in another type.
- CHOICE {
- getRequest
- GetRequestPdu,
-
- getNextRequest
- GetNextRequestPdu,
-
- getBulkRequest
- GetBulkRequestPdu,
-
- response
- ResponsePdu,
-
- setRequest
- SetRequestPdu,
-
- informRequest
- InformRequestPdu,
-
- snmpV2Trap
- SNMPv2TrapPdu
- }
-
- -- PDUs
-
- GetRequestPdu ::=
- [0]
- IMPLICIT PDU
-
- GetNextRequestPdu ::=
- [1]
- IMPLICIT PDU
-
- ResponsePdu ::=
- [2]
- IMPLICIT PDU
-
- SetRequestPdu ::=
- [3]
- IMPLICIT PDU
-
- -- [4] is obsolete
-
- GetBulkRequestPdu ::=
- [5]
- IMPLICIT BulkPDU
-
- InformRequestPdu ::=
- [6]
- IMPLICIT PDU
-
- SNMPv2TrapPdu ::=
- [7]
- IMPLICIT PDU
-
-
- maxBindings
- INTEGER ::= 2147483647
-
- PDU ::=
- SEQUENCE {
- requestId
- Integer32,
-
- errorStatus -- sometimes ignored
- INTEGER {
- noError(0),
- tooBig(1),
- noSuchName(2), -- for proxy compatibility
- badValue(3), -- for proxy compatibility
- readOnly(4), -- for proxy compatibility
- genErr(5),
- noAccess(6),
- wrongType(7),
- wrongLength(8),
- wrongEncoding(9),
- wrongValue(10),
- noCreation(11),
- inconsistentValue(12),
- resourceUnavailable(13),
- commitFailed(14),
- undoFailed(15),
- authorizationError(16),
- notWritable(17),
- inconsistentName(18)
- },
-
- errorIndex -- sometimes ignored
- INTEGER (0..maxBindings),
-
- variableBindings -- values are sometimes ignored
- VarBindList
- }
-
-
- BulkPDU ::= -- MUST be identical in
- SEQUENCE { -- structure to PDU
- requestId
- Integer32,
-
- nonRepeaters
- INTEGER (0..maxBindings),
-
- maxRepetitions
- INTEGER (0..maxBindings),
-
- variableBindings -- values are ignored
- VarBindList
- }
-
-
- VarBind ::=
- SEQUENCE {
- name
- ObjectName,
-
- data CHOICE {
- value
- ObjectSyntax,
-
- unSpecified -- in retrieval requests
- NULL,
-
- -- exceptions in responses
- noSuchObject[0]
- IMPLICIT NULL,
-
- noSuchInstance[1]
- IMPLICIT NULL,
-
- endOfMibView[2]
- IMPLICIT NULL
- }
- }
-
-
- -- variableBinding list
-
- VarBindList ::=
- SEQUENCE OF VarBind
-
--- org:
--- VarBindList ::=
--- SEQUENCE (SIZE (0..maxBindings)) OF
--- VarBind
-
-END
-
-
-
-
-
-
-
-
diff --git a/lib/asn1/test/asn1_SUITE_data/PartialDecSeq.asn1config b/lib/asn1/test/asn1_SUITE_data/PartialDecSeq.asn1config
index 19fa3c990e..0d91e0c3b3 100644
--- a/lib/asn1/test/asn1_SUITE_data/PartialDecSeq.asn1config
+++ b/lib/asn1/test/asn1_SUITE_data/PartialDecSeq.asn1config
@@ -4,19 +4,11 @@
{selected_decode_F3,['F',fb,b,[1]]},
{selected_decode_F4,['F',fb,d,da,[1],b,a]},
{selected_decode_E1,['E',d,dc,dcc,dcca]}]}}.
-%% partial_incomplete_decode tuplen inneh�ller tv� element. Den
-%% f�rsta �r bara en nyckel den andra �r en tupel med modulnamnet i
-%% en tupel {module,Name} och det andra elementet �r en lista av tupler:
-%% D�r varje tupel beskriver en partiell ofullst�ndig dekod. F�rsta
-%% elementet i den tupeln �r namnet p� funktionen som ska g�ra den
-%% partiella dekodningen. Det andra elementet �r en lista av typnamn/
-%% komponentnamn som �r en sekvens (path) till de element som ej skall
-%% avkodas.
{exclusive_decode,{'PartialDecSeq',
[{decode_F_fb_incomplete,['F',[{fb,[{b,parts},{d,undecoded}]}]]},
{decode_D_incomplete,['D',[{a,undecoded}]]},
{decode_F_fb_exclusive2,['F',[{fb,[{b,parts},{d,[{da,parts}]}]}]]}, {decode_F_fb_exclusive3,['F',[{fb,[{b,parts},{d,[{da,parts},{dc,[{dcc,undecoded}]}]}]}]]}]}}.
{module_name,'Seq.asn1'}.
-{compile_options,[ber_bin,optimize,debug_info]}.
+{compile_options,[ber,debug_info]}.
{multifile_compile,['M1.asn','M2.asn']}.
diff --git a/lib/asn1/test/asn1_SUITE_data/Pattern.asn b/lib/asn1/test/asn1_SUITE_data/Pattern.asn
deleted file mode 100644
index 730b4ba32a..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Pattern.asn
+++ /dev/null
@@ -1,8 +0,0 @@
-Pattern DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-DateAndTime ::= VisibleString (PATTERN "\d#2/\d#2/\d#4-\d#2:\d#2")
--- DD/MM/YYY-HH:MM
-
-END \ No newline at end of file
diff --git a/lib/asn1/test/asn1_SUITE_data/Prim.asn1 b/lib/asn1/test/asn1_SUITE_data/Prim.asn1
index 1a905988f5..cc0e61422a 100644
--- a/lib/asn1/test/asn1_SUITE_data/Prim.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/Prim.asn1
@@ -22,6 +22,8 @@ BEGIN
Enum ::= ENUMERATED {monday(1),tuesday(2),wednesday(3),thursday(4),
friday(5),saturday(6),sunday(7)}
+ SingleEnumVal ::= ENUMERATED {true}
+ SingleEnumValExt ::= ENUMERATED {true, ...}
ObjId ::= OBJECT IDENTIFIER
@@ -29,4 +31,31 @@ BEGIN
Null ::= NULL
+ -- Test that REAL numbers can co-exist with other data types.
+ App-X-Real ::= REAL (WITH COMPONENTS {
+ mantissa (-16777215..16777215),
+ base (2),
+ exponent (-125..128) } )
+
+ Seq ::= SEQUENCE {
+ n Null,
+ i1 INTEGER (0..63),
+ e1 SingleEnumVal,
+ i2 INTEGER (0..63),
+ e2 SingleEnumVal,
+ i3 INTEGER (0..63),
+ b Bool,
+ i4 INTEGER (0..63)
+ }
+
+ ASeq ::= SEQUENCE {
+ e254 BOOLEAN,
+ i254 INTEGER (0..254),
+ e255 BOOLEAN,
+ i255 INTEGER (0..255),
+ e256 BOOLEAN,
+ i256 INTEGER (0..256),
+ e BOOLEAN,
+ magic INTEGER
+ }
END
diff --git a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
index d287840f30..08e7f94ab6 100644
--- a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
@@ -5,7 +5,7 @@ BEGIN
Bs1 ::= BIT STRING
Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7))
Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7))
- Bs4 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..32))
+ Bs4 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) }
Bs5 ::= BIT STRING {su(0), mo(17), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..32))
Bs6 ::= BIT STRING {su(0), mo(17), tu(2), we(3), th(4), fr(5), sa(6)} (SIZE (16..32))
Bs7 ::= BIT STRING (SIZE (24))
@@ -56,19 +56,125 @@ BS1024 ::= BIT STRING (SIZE (1024))
OsExpPri ::= [PRIVATE 61] EXPLICIT OCTET STRING
OsExpApp ::= [APPLICATION 62] EXPLICIT OCTET STRING
+ OsFrag ::= OCTET STRING (SIZE (0..100000))
+ FixedOs65536 ::= OCTET STRING (SIZE (65536))
+ FixedOs65537 ::= OCTET STRING (SIZE (65537))
+
+ OsFragExt ::= OCTET STRING (SIZE (0..100000, ...))
+ FixedOs65536Ext ::= OCTET STRING (SIZE (65536, ...))
+ FixedOs65537Ext ::= OCTET STRING (SIZE (65537, ...))
+
+ OsFixedStrings ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 OCTET STRING (SIZE (0)),
+ s1 OCTET STRING (SIZE (1)),
+ s2 OCTET STRING (SIZE (2)),
+ s3 OCTET STRING (SIZE (3)),
+ b2 BOOLEAN, -- Unalign
+ s255 OCTET STRING (SIZE (255)),
+ s256 OCTET STRING (SIZE (256)),
+ s257 OCTET STRING (SIZE (257)),
+ i INTEGER (0..1024)
+ }
+
+ OsFixedStringsExt ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 OCTET STRING (SIZE (0, ...)),
+ s1 OCTET STRING (SIZE (1, ...)),
+ s2 OCTET STRING (SIZE (2, ...)),
+ s3 OCTET STRING (SIZE (3, ...)),
+ b2 BOOLEAN, -- Unalign
+ s255 OCTET STRING (SIZE (255, ...)),
+ s256 OCTET STRING (SIZE (256, ...)),
+ s257 OCTET STRING (SIZE (257, ...)),
+ i INTEGER (0..1024)
+ }
+
+ OsVarStringsExt ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 OCTET STRING (SIZE (0, ...)),
+ s1 OCTET STRING (SIZE (0..1, ...)),
+ s2 OCTET STRING (SIZE (1..2, ...)),
+ s3 OCTET STRING (SIZE (2..3, ...)),
+ b2 BOOLEAN, -- Unalign
+ s255 OCTET STRING (SIZE (254..255, ...)),
+ s256 OCTET STRING (SIZE (255..256, ...)),
+ s257 OCTET STRING (SIZE (256..257, ...)),
+ i INTEGER (0..1024)
+ }
+
+ OsAlignment ::= SEQUENCE {
+ b1 BOOLEAN,
+ s1 Os,
+ b2 BOOLEAN,
+ s2 OsFrag,
+ b3 BOOLEAN,
+ s3 FixedOs65536,
+ i INTEGER (0..63)
+ }
+
+ IA5FixedStrings ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 IA5String (SIZE (0)),
+ s1 IA5String (SIZE (1)),
+ s2 IA5String (SIZE (2)),
+ s3 IA5String (SIZE (3)),
+ b2 BOOLEAN, -- Unalign
+ s4 IA5String (SIZE (4)),
+ b3 BOOLEAN, -- Unalign
+ s255 IA5String (SIZE (255)),
+ s256 IA5String (SIZE (256)),
+ s257 IA5String (SIZE (257)),
+ i INTEGER (0..1024)
+ }
+
+ IA5FixedStringsExt ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 IA5String (SIZE (0, ...)),
+ s1 IA5String (SIZE (1, ...)),
+ s2 IA5String (SIZE (2, ...)),
+ s3 IA5String (SIZE (3, ...)),
+ b2 BOOLEAN, -- Unalign
+ s4 IA5String (SIZE (4, ...)),
+ b3 BOOLEAN, -- Unalign
+ s255 IA5String (SIZE (255, ...)),
+ s256 IA5String (SIZE (256, ...)),
+ s257 IA5String (SIZE (257, ...)),
+ i INTEGER (0..1024)
+ }
+
+ IA5VarStringsExt ::= SEQUENCE {
+ b1 BOOLEAN, -- Unalign
+ s0 IA5String (SIZE (0, ...)),
+ s1 IA5String (SIZE (0..1, ...)),
+ s2 IA5String (SIZE (1..2, ...)),
+ s3 IA5String (SIZE (2..3, ...)),
+ b2 BOOLEAN, -- Unalign
+ s4 IA5String (SIZE (3..4, ...)),
+ b3 BOOLEAN, -- Unalign
+ s255 IA5String (SIZE (254..255, ...)),
+ s256 IA5String (SIZE (255..256, ...)),
+ s257 IA5String (SIZE (256..257, ...)),
+ i INTEGER (0..1024)
+ }
+
+
Ns ::= NumericString
NsCon ::= [70] NumericString
NsExpCon ::= [71] EXPLICIT NumericString
Ps ::= PrintableString
+ Ps11 ::= PrintableString (FROM ("0123456789*"))
Ts ::= TeletexString
Vxs ::= VideotexString
Vis ::= VisibleString
+ Vis8 ::= VisibleString (FROM ("01234567"))
IA5 ::= IA5String
+ IA5Visible ::= IA5String (FROM (" ".."~"))
Grs ::= GraphicString
diff --git a/lib/asn1/test/asn1_SUITE_data/ROSE.asn1 b/lib/asn1/test/asn1_SUITE_data/ROSE.asn1
deleted file mode 100644
index 2fefae3caf..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/ROSE.asn1
+++ /dev/null
@@ -1,449 +0,0 @@
-ROSE DEFINITIONS IMPLICIT TAGS ::=
-
-
-BEGIN
-
-OPERATION ::= CLASS
-{
- &ArgumentType OPTIONAL,
- &argumentTypeOptional BOOLEAN OPTIONAL,
- &returnResult BOOLEAN DEFAULT TRUE,
- &ResultType OPTIONAL,
- &resultTypeOptional BOOLEAN OPTIONAL,
- &Errors ERROR OPTIONAL,
- &Linked OPERATION OPTIONAL,
- &synchronous BOOLEAN DEFAULT FALSE,
- &idempotent BOOLEAN DEFAULT FALSE,
- &alwaysReturns BOOLEAN DEFAULT TRUE,
- &InvokePriority Priority OPTIONAL,
- &ResultPriority Priority OPTIONAL,
- &operationCode Code UNIQUE OPTIONAL
- }
-WITH SYNTAX
- {
- [ARGUMENT &ArgumentType [OPTIONAL &argumentTypeOptional]]
- [RESULT &ResultType [OPTIONAL &resultTypeOptional]]
- [RETURN RESULT &returnResult]
- [ERRORS &Errors]
- [LINKED &Linked]
- [SYNCHRONOUS &synchronous]
- [IDEMPOTENT &idempotent]
- [ALWAYS RESPONDS &alwaysReturns]
- [INVOKE PRIORITY &InvokePriority]
- [RESULT-PRIORITY &ResultPriority]
- [CODE &operationCode]
- }
-
-ERROR ::= CLASS
-{
- &ParameterType OPTIONAL,
- &parameterTypeOptional BOOLEAN OPTIONAL,
- &ErrorPriority Priority OPTIONAL,
- &errorCode Code UNIQUE OPTIONAL
- }
-WITH SYNTAX
-{
- [PARAMETER &ParameterType [OPTIONAL &parameterTypeOptional]]
- [PRIORITY &ErrorPriority]
- [CODE &errorCode]
- }
-
-OPERATION-PACKAGE ::= CLASS
-{
- &Both OPERATION OPTIONAL,
- &Consumer OPERATION OPTIONAL,
- &Supplier OPERATION OPTIONAL,
- &id OBJECT IDENTIFIER UNIQUE OPTIONAL
- }
-WITH SYNTAX
-{
- [OPERATIONS &Both]
- [CONSUMER INVOKES &Supplier]
- [SUPPLIER INVOKES &Consumer]
- [ID &id]
- }
-
-CONNECTION-PACKAGE ::= CLASS
-{
- &bind OPERATION DEFAULT emptyBind,
- &unbind OPERATION DEFAULT emptyUnbind,
- &responderCanUnbind BOOLEAN DEFAULT FALSE,
- &unbindCanFail BOOLEAN DEFAULT FALSE,
- &id OBJECT IDENTIFIER UNIQUE OPTIONAL
- }
-WITH SYNTAX
-{
- [BIND &bind]
- [UNBIND &unbind]
- [RESPONDER UNBIND &responderCanUnbind]
- [FAILURE TO UNBIND &unbindCanFail]
- [ID &id]
- }
-
-CONTRACT ::= CLASS
-{
- &connection CONNECTION-PACKAGE OPTIONAL,
- &OperationsOf OPERATION-PACKAGE OPTIONAL,
- &InitiatorConsumerOf OPERATION-PACKAGE OPTIONAL,
- &InitiatorSupplierOf OPERATION-PACKAGE OPTIONAL,
- &id OBJECT IDENTIFIER UNIQUE OPTIONAL
- }
-WITH SYNTAX
-{
- [CONNECTION &connection]
- [OPERATIONS OF &OperationsOf]
- [INITIATOR CONSUMER OF &InitiatorConsumerOf]
- [RESPONDER CONSUMER OF &InitiatorSupplierOf]
- [ID &id]
-}
-
-ROS-OBJECT-CLASS ::= CLASS
-{
- &Is ROS-OBJECT-CLASS OPTIONAL,
- &Initiates CONTRACT OPTIONAL,
- &Responds CONTRACT OPTIONAL,
- &InitiatesAndResponds CONTRACT OPTIONAL,
- &id OBJECT IDENTIFIER UNIQUE
- }
-WITH SYNTAX
-{
- [IS &Is]
- [BOTH &InitiatesAndResponds]
- [INITIATES &Initiates]
- [RESPONDS &Responds]
- ID &id
- }
-
-Code ::= CHOICE
-{
- local INTEGER,
- global OBJECT IDENTIFIER
- }
-
-Priority ::= INTEGER (0..MAX)
-
-ROS {InvokeId:InvokeIdSet,OPERATION:Invokable,OPERATION:Returnable} ::= CHOICE
- {
- invoke [1] Invoke {{InvokeIdSet}, {Invokable}},
- returnResult [2] ReturnResult {{Returnable}},
- returnError [3] ReturnError {{Errors{{Returnable}}}},
- reject [4] Reject
- }
-(CONSTRAINED BY {-- must conform to the above definition --}
- ! RejectProblem : general-unrecognizedPDU)
-
-Invoke {InvokeId:InvokeIdSet, OPERATION:Operations} ::= SEQUENCE
-{
- invokeId InvokeId (InvokeIdSet)
- (CONSTRAINED BY {-- must be unambiguous --}
- ! RejectProblem : invoke-duplicateInvocation),
- linkedId CHOICE {
- present [0] IMPLICIT present < InvokeId,
- absent [1] IMPLICIT NULL
- }
- (CONSTRAINED BY {-- must identify an outstanding operation --}
- ! RejectProblem : invoke-unrecognizedLinkedId)
- (CONSTRAINED BY {-- which has one or more linked operations--}
- ! RejectProblem : invoke-linkedResponseUnexpected)
- OPTIONAL,
- opcode OPERATION.&operationCode
- ({Operations}
- ! RejectProblem : invoke-unrecognizedOperation),
- argument OPERATION.&ArgumentType
- ({Operations} {@opcode}
- ! RejectProblem : invoke-mistypedArgument)
- OPTIONAL
- }
-(CONSTRAINED BY {-- must conform to the above definition --}
- ! RejectProblem : general-mistypedPDU)
-(
-WITH COMPONENTS
-{...,
- linkedId ABSENT
- }
-| WITH COMPONENTS
-{...,
- linkedId PRESENT,
- opcode
- (CONSTRAINED BY {-- must be in the &Linked field of the associated operation --
- }
- ! RejectProblem : invoke-unexpectedLinkedOperation)
- }
-)
-
-ReturnResult {OPERATION:Operations}::= SEQUENCE
-{
- invokeId InvokeId
- (CONSTRAINED BY {-- must be that for an outstanding operation --}
- ! RejectProblem:returnResult-unrecognizedInvocation)
- (CONSTRAINED BY {-- which returns a result --}
- ! RejectProblem:returnResult-resultResponseUnexpected),
- result SEQUENCE
- {
- opcode OPERATION.&operationCode
- ({Operations})(CONSTRAINED BY {-- identified by invokeId --}
- ! RejectProblem:returnResult-unrecognizedInvocation),
- result OPERATION.&ResultType ({Operations} {@.opcode}
- ! RejectProblem:returnResult-mistypedResult)
- }
- OPTIONAL
- }
-(CONSTRAINED BY {-- must conform to the above definition --
- }
-! RejectProblem:general-mistypedPDU)
-
-ReturnError {ERROR:Errors} ::= SEQUENCE
-{
- invokeId InvokeId
- (CONSTRAINED BY {-- must be that for an outstanding operation --
- }
- ! RejectProblem : returnError-unrecognizedInvocation)
- (CONSTRAINED BY {-- which returns an error --
- }
- ! RejectProblem : returnError-errorResponseUnexpected),
- errcode ERROR.&errorCode
- ({Errors}
- ! RejectProblem : returnError-unrecognizedError)
- (CONSTRAINED BY {-- must be in the &Errors field of the associated operation --
- }
- ! RejectProblem : returnError-unexpectedError),
- parameter ERROR.&ParameterType
- ({Errors}{@errcode}
- ! RejectProblem : returnError-mistypedParameter) OPTIONAL
- }
-(CONSTRAINED BY {-- must conform to the above definition --
- }
-! RejectProblem : general-mistypedPDU)
-
-Reject ::= SEQUENCE
-{
- invokeId InvokeId,
- problem CHOICE
- {
- general [0] GeneralProblem,
- invoke [1] InvokeProblem,
- returnResult [2] ReturnResultProblem,
- returnError [3] ReturnErrorProblem
- }
- }
-(CONSTRAINED BY {-- must conform to the above definition --
- }
-! RejectProblem : general-mistypedPDU)
-
-GeneralProblem ::= INTEGER
-{
- unrecognizedPDU (0),
- mistypedPDU (1),
- badlyStructuredPDU (2)
- }
-
-InvokeProblem ::= INTEGER
-{
- duplicateInvocation (0),
- unrecognizedOperation (1),
- mistypedArgument (2),
- resourceLimitation (3),
- releaseInProgress (4),
- unrecognizedLinkedId (5),
- linkedResponseUnexpected (6),
- unexpectedLinkedOperation (7)
- }
-
-ReturnResultProblem ::= INTEGER
-{
- unrecognizedInvocation (0),
- resultResponseUnexpected (1),
- mistypedResult (2)
- }
-
-ReturnErrorProblem ::= INTEGER
-{
- unrecognizedInvocation (0),
- errorResponseUnexpected (1),
- unrecognizedError (2),
- unexpectedError (3),
- mistypedParameter (4)
- }
-
-RejectProblem ::= INTEGER
-{
- general-unrecognizedPDU (0),
- general-mistypedPDU (1),
- general-badlyStructuredPDU (2),
- invoke-duplicateInvocation (10),
- invoke-unrecognizedOperation (11),
- invoke-mistypedArgument (12),
- invoke-resourceLimitation (13),
- invoke-releaseInProgress (14),
- invoke-unrecognizedLinkedId (15),
- invoke-linkedResponseUnexpected (16),
- invoke-unexpectedLinkedOperation (17),
- returnResult-unrecognizedInvocation (20),
- returnResult-resultResponseUnexpected (21),
- returnResult-mistypedResult (22),
- returnError-unrecognizedInvocation (30),
- returnError-errorResponseUnexpected (31),
- returnError-unrecognizedError (32),
- returnError-unexpectedError (33),
- returnError-mistypedParameter (34)
- }
-
-InvokeId ::= CHOICE
-{
- present INTEGER,
- absent NULL
- }
-
-noInvokeId InvokeId ::= absent:NULL
-
-NoInvokeId InvokeId ::= {noInvokeId}
-
-Errors {OPERATION:Operations} ERROR ::= {Operations.&Errors}
-
-Bind {OPERATION:operation} ::= CHOICE
-{
- bind-invoke [16] OPERATION.&ArgumentType({operation}),
- bind-result [17] OPERATION.&ResultType ({operation}),
- bind-error [18] OPERATION.&Errors.&ParameterType ({operation})
- }
-
-Unbind {OPERATION:operation} ::= CHOICE
-{
- unbind-invoke [19] OPERATION.&ArgumentType({operation}),
- unbind-result [20] OPERATION.&ResultType ({operation}),
- unbind-error [21] OPERATION.&Errors.&ParameterType ({operation})
- }
-
-emptyBind OPERATION ::= {ERRORS {refuse} SYNCHRONOUS TRUE}
-
-emptyUnbind OPERATION ::= { SYNCHRONOUS TRUE }
-
-refuse ERROR ::= {CODE local:-1}
-
-no-op OPERATION ::=
- {
- IDEMPOTENT TRUE
- ALWAYS RESPONDS FALSE
- CODE local:-1
- }
-
-Forward {OPERATION:OperationSet} OPERATION ::=
-{
- OperationSet |
- OperationSet.&Linked.&Linked |
- OperationSet.&Linked.&Linked.&Linked.&Linked
- }
-
-Reverse {OPERATION:OperationSet} OPERATION ::=
-{Forward{{OperationSet.&Linked}}}
-
-ConsumerPerforms {OPERATION-PACKAGE:package} OPERATION ::=
-{
- Forward{{package.&Consumer}} |
- Forward{{package.&Both}} |
- Reverse{{package.&Supplier}} |
- Reverse{{package.&Both}}
- }
-
-SupplierPerforms {OPERATION-PACKAGE:package} OPERATION ::=
-{
- Forward{{package.&Supplier}} |
- Forward{{package.&Both}} |
- Reverse{{package.&Consumer}} |
- Reverse{{package.&Both}}
- }
-
-AllOperations {OPERATION-PACKAGE:package} OPERATION ::=
-{
- ConsumerPerforms {package} |
- SupplierPerforms {package}
- }
-
-recode {OPERATION:operation, Code:code} OPERATION ::=
-{
- ARGUMENT operation.&ArgumentType
- OPTIONAL operation.&argumentTypeOptional
- RESULT operation.&ResultType
- OPTIONAL operation.&resultTypeOptional
- RETURN RESULT operation.&returnResult
- ERRORS {operation.&Errors}
- LINKED {operation.&Linked}
- SYNCHRONOUS operation.&synchronous
- ALWAYS RESPONDS operation.&alwaysReturns
- INVOKE PRIORITY {operation.&InvokePriority}
- RESULT-PRIORITY {operation.&ResultPriority}
- CODE code
- }
-
-switch {OPERATION-PACKAGE:package, OBJECT IDENTIFIER:id} OPERATION-PACKAGE ::=
-{
- OPERATIONS {package.&Both}
- CONSUMER INVOKES {package.&Consumer}
- SUPPLIER INVOKES {package.&Supplier}
- ID id
- }
-
-combine {OPERATION-PACKAGE:ConsumerConsumes,OPERATION-PACKAGE:ConsumerSupplies,
- OPERATION-PACKAGE:base
- } OPERATION-PACKAGE ::=
-{
- OPERATIONS {ConsumerConsumes.&Both | ConsumerSupplies.&Both}
- CONSUMER INVOKES {ConsumerConsumes.&Consumer | ConsumerSupplies.&Supplier}
- SUPPLIER INVOKES {ConsumerConsumes.&Supplier | ConsumerSupplies.&Consumer}
- ID base.&id
- }
-
-ROS-SingleAS {InvokeId:InvokeIdSet, OPERATION-PACKAGE:package} ::= ROS
-{{InvokeIdSet}, {AllOperations{package}}, {AllOperations{package}}}
-
-ROS-ConsumerAS {InvokeId:InvokeIdSet, OPERATION-PACKAGE:package} ::= ROS
-{{InvokeIdSet}, {ConsumerPerforms{package}}, {SupplierPerforms{package}}}
-
-ROS-SupplierAS {InvokeId:InvokeIdSet, OPERATION-PACKAGE:package} ::= ROS
-{{InvokeIdSet}, {SupplierPerforms{package}}, {ConsumerPerforms{package}}}
-
-probe OPERATION ::=
- {
- ARGUMENT SEQUENCE
- {
- invokeId [0] InvokeId
- }
- RESULT ENUMERATED{running(0), finished(1), unknown(2), ...}
- IDEMPOTENT TRUE
- CODE local:-2
- }
-
-acknowledge OPERATION ::=
- {
- ARGUMENT InvokeId
- RESULT ENUMERATED{acknowledged(0), unknown(1), ...}
- IDEMPOTENT TRUE
- CODE local:-3
- }
-
-ProbeAndAcknowledge OPERATION ::= {probe | acknowledge}
-
-cancel OPERATION ::=
- {
- ARGUMENT InvokeId
- ERRORS {cancelFailed}
- IDEMPOTENT TRUE
- CODE local:-4
- }
-
-cancelFailed ERROR ::=
- {
- PARAMETER SET
- {
- problem [0] CancelProblem,
- operation [1] InvokeId
- }
- CODE local:-2
- }
-
-CancelProblem ::= ENUMERATED
-{unknownOperation(0), tooLate(1), operationNotCancellable(2), ...}
-
-cancelled ERROR ::= {CODE local:-3}
-
-END -- end of useful definitions.
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqDefault.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqDefault.asn1
index 99e79da972..5c8583884a 100644
--- a/lib/asn1/test/asn1_SUITE_data/SeqDefault.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SeqDefault.asn1
@@ -74,4 +74,15 @@ SeqIn ::= SEQUENCE
intIn INTEGER DEFAULT 12
}
+SeqExp ::= SEQUENCE
+{
+ bool BOOLEAN,
+ ...,
+ int INTEGER
+}
+
+SeqDef4 ::= SEQUENCE {
+ seq SeqExp DEFAULT { bool TRUE, int 42 }
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1
index bb0a7cca3a..5fda19303a 100644
--- a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1
@@ -31,7 +31,35 @@ SeqExt4 ::= SEQUENCE
int INTEGER
}
+SeqExt5 ::= SEQUENCE
+{
+ ...,
+ [[ name OCTET STRING (SIZE (1..8)),
+ shoesize INTEGER ]]
+}
+
+SeqExt6 ::= SEQUENCE
+{
+ -- The spaces between the ellipsis and the comma will prevent them
+ -- from being removed.
+ ... ,
+ [[ i1 [100] INTEGER, i2 [101] INTEGER, i3 [102] INTEGER ]],
+ [[ i4 [104] INTEGER, i5 [105] INTEGER ]],
+ [[ i6 [106] INTEGER, i7 [107] INTEGER ]]
+}
+
SeqExt1X ::= XSeqExt1
SeqExt2X ::= XSeqExt2
+SuperSeq ::= SEQUENCE
+{
+ s1 SeqExt1,
+ s2 SeqExt2,
+ s3 SeqExt3,
+ s4 SeqExt4,
+ s5 SeqExt5,
+ s6 SeqExt6,
+ i INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
new file mode 100644
index 0000000000..44900d9d39
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
@@ -0,0 +1,208 @@
+SeqExtension2 DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+SeqExt66 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..127) OPTIONAL,
+ i1 INTEGER (0..127) OPTIONAL,
+ i2 INTEGER (0..127) OPTIONAL,
+ i3 INTEGER (0..127) OPTIONAL,
+ i4 INTEGER (0..127) OPTIONAL,
+ i5 INTEGER (0..127) OPTIONAL,
+ i6 INTEGER (0..127) OPTIONAL,
+ i7 INTEGER (0..127) OPTIONAL,
+ i8 INTEGER (0..127) OPTIONAL,
+ i9 INTEGER (0..127) OPTIONAL,
+ i10 INTEGER (0..127) OPTIONAL,
+ i11 INTEGER (0..127) OPTIONAL,
+ i12 INTEGER (0..127) OPTIONAL,
+ i13 INTEGER (0..127) OPTIONAL,
+ i14 INTEGER (0..127) OPTIONAL,
+ i15 INTEGER (0..127) OPTIONAL,
+ i16 INTEGER (0..127) OPTIONAL,
+ i17 INTEGER (0..127) OPTIONAL,
+ i18 INTEGER (0..127) OPTIONAL,
+ i19 INTEGER (0..127) OPTIONAL,
+ i20 INTEGER (0..127) OPTIONAL,
+ i21 INTEGER (0..127) OPTIONAL,
+ i22 INTEGER (0..127) OPTIONAL,
+ i23 INTEGER (0..127) OPTIONAL,
+ i24 INTEGER (0..127) OPTIONAL,
+ i25 INTEGER (0..127) OPTIONAL,
+ i26 INTEGER (0..127) OPTIONAL,
+ i27 INTEGER (0..127) OPTIONAL,
+ i28 INTEGER (0..127) OPTIONAL,
+ i29 INTEGER (0..127) OPTIONAL,
+ i30 INTEGER (0..127) OPTIONAL,
+ i31 INTEGER (0..127) OPTIONAL,
+ i32 INTEGER (0..127) OPTIONAL,
+ i33 INTEGER (0..127) OPTIONAL,
+ i34 INTEGER (0..127) OPTIONAL,
+ i35 INTEGER (0..127) OPTIONAL,
+ i36 INTEGER (0..127) OPTIONAL,
+ i37 INTEGER (0..127) OPTIONAL,
+ i38 INTEGER (0..127) OPTIONAL,
+ i39 INTEGER (0..127) OPTIONAL,
+ i40 INTEGER (0..127) OPTIONAL,
+ i41 INTEGER (0..127) OPTIONAL,
+ i42 INTEGER (0..127) OPTIONAL,
+ i43 INTEGER (0..127) OPTIONAL,
+ i44 INTEGER (0..127) OPTIONAL,
+ i45 INTEGER (0..127) OPTIONAL,
+ i46 INTEGER (0..127) OPTIONAL,
+ i47 INTEGER (0..127) OPTIONAL,
+ i48 INTEGER (0..127) OPTIONAL,
+ i49 INTEGER (0..127) OPTIONAL,
+ i50 INTEGER (0..127) OPTIONAL,
+ i51 INTEGER (0..127) OPTIONAL,
+ i52 INTEGER (0..127) OPTIONAL,
+ i53 INTEGER (0..127) OPTIONAL,
+ i54 INTEGER (0..127) OPTIONAL,
+ i55 INTEGER (0..127) OPTIONAL,
+ i56 INTEGER (0..127) OPTIONAL,
+ i57 INTEGER (0..127) OPTIONAL,
+ i58 INTEGER (0..127) OPTIONAL,
+ i59 INTEGER (0..127) OPTIONAL,
+ i60 INTEGER (0..127) OPTIONAL,
+ i61 INTEGER (0..127) OPTIONAL,
+ i62 INTEGER (0..127) OPTIONAL,
+ i63 INTEGER (0..127) OPTIONAL,
+ i64 INTEGER (0..127) OPTIONAL,
+ i65 INTEGER (0..127) OPTIONAL
+}
+
+SeqExt130 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..255) OPTIONAL,
+ i1 INTEGER (0..255) OPTIONAL,
+ i2 INTEGER (0..255) OPTIONAL,
+ i3 INTEGER (0..255) OPTIONAL,
+ i4 INTEGER (0..255) OPTIONAL,
+ i5 INTEGER (0..255) OPTIONAL,
+ i6 INTEGER (0..255) OPTIONAL,
+ i7 INTEGER (0..255) OPTIONAL,
+ i8 INTEGER (0..255) OPTIONAL,
+ i9 INTEGER (0..255) OPTIONAL,
+ i10 INTEGER (0..255) OPTIONAL,
+ i11 INTEGER (0..255) OPTIONAL,
+ i12 INTEGER (0..255) OPTIONAL,
+ i13 INTEGER (0..255) OPTIONAL,
+ i14 INTEGER (0..255) OPTIONAL,
+ i15 INTEGER (0..255) OPTIONAL,
+ i16 INTEGER (0..255) OPTIONAL,
+ i17 INTEGER (0..255) OPTIONAL,
+ i18 INTEGER (0..255) OPTIONAL,
+ i19 INTEGER (0..255) OPTIONAL,
+ i20 INTEGER (0..255) OPTIONAL,
+ i21 INTEGER (0..255) OPTIONAL,
+ i22 INTEGER (0..255) OPTIONAL,
+ i23 INTEGER (0..255) OPTIONAL,
+ i24 INTEGER (0..255) OPTIONAL,
+ i25 INTEGER (0..255) OPTIONAL,
+ i26 INTEGER (0..255) OPTIONAL,
+ i27 INTEGER (0..255) OPTIONAL,
+ i28 INTEGER (0..255) OPTIONAL,
+ i29 INTEGER (0..255) OPTIONAL,
+ i30 INTEGER (0..255) OPTIONAL,
+ i31 INTEGER (0..255) OPTIONAL,
+ i32 INTEGER (0..255) OPTIONAL,
+ i33 INTEGER (0..255) OPTIONAL,
+ i34 INTEGER (0..255) OPTIONAL,
+ i35 INTEGER (0..255) OPTIONAL,
+ i36 INTEGER (0..255) OPTIONAL,
+ i37 INTEGER (0..255) OPTIONAL,
+ i38 INTEGER (0..255) OPTIONAL,
+ i39 INTEGER (0..255) OPTIONAL,
+ i40 INTEGER (0..255) OPTIONAL,
+ i41 INTEGER (0..255) OPTIONAL,
+ i42 INTEGER (0..255) OPTIONAL,
+ i43 INTEGER (0..255) OPTIONAL,
+ i44 INTEGER (0..255) OPTIONAL,
+ i45 INTEGER (0..255) OPTIONAL,
+ i46 INTEGER (0..255) OPTIONAL,
+ i47 INTEGER (0..255) OPTIONAL,
+ i48 INTEGER (0..255) OPTIONAL,
+ i49 INTEGER (0..255) OPTIONAL,
+ i50 INTEGER (0..255) OPTIONAL,
+ i51 INTEGER (0..255) OPTIONAL,
+ i52 INTEGER (0..255) OPTIONAL,
+ i53 INTEGER (0..255) OPTIONAL,
+ i54 INTEGER (0..255) OPTIONAL,
+ i55 INTEGER (0..255) OPTIONAL,
+ i56 INTEGER (0..255) OPTIONAL,
+ i57 INTEGER (0..255) OPTIONAL,
+ i58 INTEGER (0..255) OPTIONAL,
+ i59 INTEGER (0..255) OPTIONAL,
+ i60 INTEGER (0..255) OPTIONAL,
+ i61 INTEGER (0..255) OPTIONAL,
+ i62 INTEGER (0..255) OPTIONAL,
+ i63 INTEGER (0..255) OPTIONAL,
+ i64 INTEGER (0..255) OPTIONAL,
+ i65 INTEGER (0..255) OPTIONAL,
+ i66 INTEGER (0..255) OPTIONAL,
+ i67 INTEGER (0..255) OPTIONAL,
+ i68 INTEGER (0..255) OPTIONAL,
+ i69 INTEGER (0..255) OPTIONAL,
+ i70 INTEGER (0..255) OPTIONAL,
+ i71 INTEGER (0..255) OPTIONAL,
+ i72 INTEGER (0..255) OPTIONAL,
+ i73 INTEGER (0..255) OPTIONAL,
+ i74 INTEGER (0..255) OPTIONAL,
+ i75 INTEGER (0..255) OPTIONAL,
+ i76 INTEGER (0..255) OPTIONAL,
+ i77 INTEGER (0..255) OPTIONAL,
+ i78 INTEGER (0..255) OPTIONAL,
+ i79 INTEGER (0..255) OPTIONAL,
+ i80 INTEGER (0..255) OPTIONAL,
+ i81 INTEGER (0..255) OPTIONAL,
+ i82 INTEGER (0..255) OPTIONAL,
+ i83 INTEGER (0..255) OPTIONAL,
+ i84 INTEGER (0..255) OPTIONAL,
+ i85 INTEGER (0..255) OPTIONAL,
+ i86 INTEGER (0..255) OPTIONAL,
+ i87 INTEGER (0..255) OPTIONAL,
+ i88 INTEGER (0..255) OPTIONAL,
+ i89 INTEGER (0..255) OPTIONAL,
+ i90 INTEGER (0..255) OPTIONAL,
+ i91 INTEGER (0..255) OPTIONAL,
+ i92 INTEGER (0..255) OPTIONAL,
+ i93 INTEGER (0..255) OPTIONAL,
+ i94 INTEGER (0..255) OPTIONAL,
+ i95 INTEGER (0..255) OPTIONAL,
+ i96 INTEGER (0..255) OPTIONAL,
+ i97 INTEGER (0..255) OPTIONAL,
+ i98 INTEGER (0..255) OPTIONAL,
+ i99 INTEGER (0..255) OPTIONAL,
+ i100 INTEGER (0..255) OPTIONAL,
+ i101 INTEGER (0..255) OPTIONAL,
+ i102 INTEGER (0..255) OPTIONAL,
+ i103 INTEGER (0..255) OPTIONAL,
+ i104 INTEGER (0..255) OPTIONAL,
+ i105 INTEGER (0..255) OPTIONAL,
+ i106 INTEGER (0..255) OPTIONAL,
+ i107 INTEGER (0..255) OPTIONAL,
+ i108 INTEGER (0..255) OPTIONAL,
+ i109 INTEGER (0..255) OPTIONAL,
+ i110 INTEGER (0..255) OPTIONAL,
+ i111 INTEGER (0..255) OPTIONAL,
+ i112 INTEGER (0..255) OPTIONAL,
+ i113 INTEGER (0..255) OPTIONAL,
+ i114 INTEGER (0..255) OPTIONAL,
+ i115 INTEGER (0..255) OPTIONAL,
+ i116 INTEGER (0..255) OPTIONAL,
+ i117 INTEGER (0..255) OPTIONAL,
+ i118 INTEGER (0..255) OPTIONAL,
+ i119 INTEGER (0..255) OPTIONAL,
+ i120 INTEGER (0..255) OPTIONAL,
+ i121 INTEGER (0..255) OPTIONAL,
+ i122 INTEGER (0..255) OPTIONAL,
+ i123 INTEGER (0..255) OPTIONAL,
+ i124 INTEGER (0..255) OPTIONAL,
+ i125 INTEGER (0..255) OPTIONAL,
+ i126 INTEGER (0..255) OPTIONAL,
+ i127 INTEGER (0..255) OPTIONAL,
+ i128 INTEGER (0..255) OPTIONAL,
+ i129 INTEGER (0..255) OPTIONAL
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
index 330944cf5c..888dbe5dd7 100644
--- a/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
@@ -62,4 +62,13 @@ Empty ::= SEQUENCE
{
}
+SeqExt ::= SEQUENCE
+{
+ b1 BOOLEAN,
+ s1 SEQUENCE SIZE (1..3, ...) OF SeqIn,
+ b2 BOOLEAN,
+ s2 SEQUENCE SIZE (0..1024, ...) OF SeqIn,
+ magic INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqOf.py b/lib/asn1/test/asn1_SUITE_data/SeqOf.py
deleted file mode 100644
index c941418934..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/SeqOf.py
+++ /dev/null
@@ -1,45 +0,0 @@
-SeqOf DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
-
-Seq1 ::= SEQUENCE
-{
- bool1 BOOLEAN,
- int1 INTEGER,
- seq1 SEQUENCE OF SeqIn DEFAULT {}
-}
-
-Seq2 ::= SEQUENCE
-{
- seq2 SEQUENCE OF SeqIn DEFAULT {},
- bool2 BOOLEAN,
- int2 INTEGER
-}
-
-Seq3 ::= SEQUENCE
-{
- bool3 BOOLEAN,
- seq3 SEQUENCE OF SeqIn DEFAULT {},
- int3 INTEGER
-}
-
-Seq4 ::= SEQUENCE
-{
- seq41 [41] SEQUENCE OF SeqIn DEFAULT {},
- seq42 [42] SEQUENCE OF SeqIn DEFAULT {},
- seq43 [43] SEQUENCE OF SeqIn DEFAULT {}
-}
-
-
-
-SeqIn ::= SEQUENCE
-{
- boolIn BOOLEAN,
- intIn INTEGER
-}
-
-
-
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/SetDefault.asn1 b/lib/asn1/test/asn1_SUITE_data/SetDefault.asn1
index cb9e0ead62..0bbe301ae7 100644
--- a/lib/asn1/test/asn1_SUITE_data/SetDefault.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SetDefault.asn1
@@ -30,4 +30,15 @@ SetIn ::= SET
intIn INTEGER DEFAULT 12
}
+SetDef4 ::= SET {
+ set SetExt DEFAULT { intIn 42, boolIn TRUE }
+}
+
+SetExt ::= SET
+{
+ boolIn BOOLEAN,
+ ...,
+ intIn INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SetOf.py b/lib/asn1/test/asn1_SUITE_data/SetOf.py
deleted file mode 100644
index 4e2ea16fcc..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/SetOf.py
+++ /dev/null
@@ -1,42 +0,0 @@
-SetOf DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
-
-Set1 ::= SET
-{
- bool1 BOOLEAN,
- int1 INTEGER,
- set1 SET OF SetIn DEFAULT {}
-}
-
-Set2 ::= SET
-{
- set2 SET OF SetIn DEFAULT {},
- bool2 BOOLEAN,
- int2 INTEGER
-}
-
-Set3 ::= SET
-{
- bool3 BOOLEAN,
- set3 SET OF SetIn DEFAULT {},
- int3 INTEGER
-}
-
-Set4 ::= SET
-{
- set41 [41] SET OF SetIn DEFAULT {},
- set42 [42] SET OF SetIn DEFAULT {},
- set43 [43] SET OF SetIn DEFAULT {}
-}
-
-
-
-SetIn ::= SET
-{
- boolIn BOOLEAN,
- intIn INTEGER
-}
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/TConstr.asn1 b/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
index 63f5dbde77..e2e0a11dc4 100644
--- a/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
@@ -51,6 +51,12 @@ Seq2 ::= SEQUENCE {
}
}
+Deeper ::= SEQUENCE {
+ a SEQUENCE {aa INTEGER,
+ s SEQUENCE { ab MYCLASS.&id ({ObjectSet}),
+ ac INTEGER }},
+ b SEQUENCE {ba INTEGER, bb MYCLASS.&Type ({ObjectSet}{@a.s.ab})}
+}
-- following from Peter's definitions
diff --git a/lib/asn1/test/asn1_SUITE_data/Tst.py b/lib/asn1/test/asn1_SUITE_data/Tst.py
deleted file mode 100644
index d80b32dad5..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Tst.py
+++ /dev/null
@@ -1,153 +0,0 @@
-Tst { 2 6 6 24 7 1 } DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
---EXPORTS SomeSet , Id0 , Aset,Id1 ,A,B,C,
--- Uhh ,Foo ,Cho,Person,Hobbe,Robbe,X,Y;
-
-IMPORTS Fooo FROM Bobby;
-
-
-Robbe ::= SET {
- ttt TT }
-
-Koo ::= SET {
- c CHOICE {
- a INTEGER,
- b BOOLEAN },
- s SET OF Id0 }
-
-
-Hobbe ::= [APPLICATION 1] SET {
- aaa [0] SET OF INTEGER,
- bbb [1] UU
- }
-
-UU ::= PP
-PP ::= CHOICE {
- cc [1] CHOICE {
- a [0] INTEGER,
- b [1] BOOLEAN,
- c [2] BIT STRING },
- ii [0] Id0
- }
-
-
-TT ::= SS
-SS ::= SET {
- b BOOLEAN DEFAULT TRUE
- }
-
-Aset ::= [PRIVATE 2] SET OF Uhh
-
-
-
-SomeSet ::= [PRIVATE 3] IMPLICIT SET {
- aaaa [2] SET{
- ggg [0] INTEGER},
- kkkk [1] SET OF Id2,
- booby [4] OCTET STRING,
- puck [3] INTEGER {red(0),blue(1),yellow(-2)},
- baby [5] IMPLICIT Id1,
- bool [6] BOOLEAN }
-
-
-Id0 ::= INTEGER (4 .. 99)
-
-Id1 ::= Id0
-
-Id2 ::= [PRIVATE 4] EXPLICIT Id1
-
-
-Uhh ::= SET {
- a [1] IMPLICIT Id1}
-
-
-
-Soon ::= [PRIVATE 5] Moon
-
-Moon ::= [PRIVATE 6] IMPLICIT Person
-
-
-Person ::= [PRIVATE 7] IMPLICIT SEQUENCE {
- szzzs SET OF SET {
- aaa [0] INTEGER,
- bbb [1] Id0},
- cho Cho,
- name OCTET STRING ,
- location INTEGER,
- asss Aset,
- oops [2] IMPLICIT SET {
- q [0] INTEGER,
- p [1] Uhh},
- on INTEGER,
- mybits [3] IMPLICIT BIT STRING,
- foo Foo,
- age INTEGER,
- hobbe [5] SEQUENCE {
- a [4] CHOICE {
- a INTEGER,
- b BOOLEAN },
- b [5] Id0}}
-
-
-
-
-
-Foo ::= [PRIVATE 8] IMPLICIT SEQUENCE {
- goofy [3] INTEGER OPTIONAL,
- somestring [10] IMPLICIT OCTET STRING DEFAULT '77BB'H,
- hoohoo [11] IMPLICIT SEQUENCE {
- bar [1] Id1 OPTIONAL,
- foo INTEGER,
- zombie [9] CHOICE {
- a [1] IMPLICIT INTEGER,
- b [2] IMPLICIT BOOLEAN }
- },
- moon [4] IMPLICIT INTEGER }
-
-
-
-Cho ::= [PRIVATE 9] EXPLICIT CHOICE {
- somestring [2] IMPLICIT OCTET STRING,
- goofy [9] INTEGER,
- moon [4] IMPLICIT INTEGER }
-
-
-A ::= [APPLICATION 2] SET {
- ppp IA5String ,
- a [0] INTEGER {aaa(6),bbb(77)} DEFAULT 998,
- b [1] Id1 OPTIONAL,
- c [2] OCTET STRING (SIZE(8)),
- dd [3] BIT STRING DEFAULT '11001'B }
-
-B ::= [APPLICATION 3] SET {
- ww [1] SET {
- a A OPTIONAL,
- goofy [3] INTEGER OPTIONAL,
- somestring [10] IMPLICIT OCTET STRING DEFAULT '77BB'H }
- }
-
-
-C::= [APPLICATION 4] SEQUENCE OF X
-
-Y ::= OBJECT IDENTIFIER
-
-X ::= SET {
- a NULL,
- b GeneralString,
- c UTCTime,
- d VideotexString,
- g GeneralizedTime,
- h GraphicString,
- i VisibleString,
- j IA5String,
- k PrintableString,
- l OCTET STRING,
- e TeletexString,
- m ANY,
- n ObjectDescriptor,
- o OBJECT IDENTIFIER,
- f NumericString }
-
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/Two.py b/lib/asn1/test/asn1_SUITE_data/Two.py
deleted file mode 100644
index c8e6f1a55b..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/Two.py
+++ /dev/null
@@ -1,34 +0,0 @@
-Two { 1 2 3} DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-EXPORTS A, D,Boo,Szz;
-
-
-
-D ::= [PRIVATE 1] SEQUENCE {
- a INTEGER,
- b Boo,
- c ANY DEFINED BY a ,
- d ANY }
-
-
-Boo ::= SEQUENCE OF INTEGER (198..200)
-
-A ::= [PRIVATE 2] SEQUENCE {
- a INTEGER (1..1),
- b INTEGER (3..3) }
-
-
-Szz ::= CHOICE {
- one INTEGER,
- two BOOLEAN }
-
-C ::= SET {
- a [0] INTEGER (0..8),
- xx [4] CHOICE {
- [7] INTEGER (9..10),
- a INTEGER (11 ..13) },
- f Boo,
- r [2] INTEGER (20..22)}
-END
-
diff --git a/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn b/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn
deleted file mode 100644
index 7b81a0e09f..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn
+++ /dev/null
@@ -1,18 +0,0 @@
-UPERDefault DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
--- OTP-7681
-Int ::= INTEGER (0..32767)
-
-Seq ::= SEQUENCE {
- a Int,
- b INTEGER (-27..27) DEFAULT 0, -- OTP-7678
- c INTEGER OPTIONAL
-}
-
-seq Seq ::=
-{a 12,
- b 0}
-
-END \ No newline at end of file
diff --git a/lib/asn1/test/asn1_SUITE_data/UndefType.py b/lib/asn1/test/asn1_SUITE_data/UndefType.py
deleted file mode 100644
index cdbe083803..0000000000
--- a/lib/asn1/test/asn1_SUITE_data/UndefType.py
+++ /dev/null
@@ -1,14 +0,0 @@
-Person DEFINITIONS IMPLICIT TAGS ::=
-BEGIN
-EXPORTS Person;
-IMPORTS
- ImportedFromUndefined FROM UndefinedModule;
-
-Feltyp ::= UndefinedType
-Feltyp2 ::= ImportedFromUndefined
-Person ::= [PRIVATE 19] SEQUENCE {
- name Undefined,
- location INTEGER {home(0),field(1),roving(2)},
- age ImportedFromUndefined OPTIONAL
- }
-END
diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
index 8148381d92..8e21e6ca84 100644
--- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
+++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
@@ -1,13 +1,7 @@
-%%%-------------------------------------------------------------------
-%%% File : extensionAdditionGroup.erl
-%%% Author : Kenneth Lundin
-%%% Description :
-%%%
-%%% Created : 18 May 2010 by kenneth
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -25,36 +19,41 @@
%%%-------------------------------------------------------------------
-module(extensionAdditionGroup).
-include("Extension-Addition-Group.hrl").
-
+-export([run/1]).
-compile(export_all).
run(Erule) ->
- Val = #'Ax'{a=253, b = true, c= {e,true}, g="123", h = true},
- io:format("~p:~p~n",[Erule,Val]),
- {ok,List}= asn1rt:encode('Extension-Addition-Group','Ax',Val),
- Enc = iolist_to_binary(List),
- io:format("~p~n",[Enc]),
- {ok,Val2} = asn1rt:decode('Extension-Addition-Group','Ax',Enc),
- io:format("~p~n",[Val2]),
- case Val2 of
- Val -> ok;
- _ -> exit({expected,Val, got, Val2})
- end.
+ Val = #'Ax'{a=253,b=true,c={e,true},g="123",h=true},
+ Enc = hex_to_binary(encoded_ax(Erule)),
+ roundtrip('Ax', Val, Enc),
-run2(Erule) ->
- Val = #'Ax3'{a=253, b = true, s = #'Ax3_s'{sa = 11, sb = true, sextaddgroup = 17}},
- io:format("~p:~p~n",[Erule,Val]),
- {ok,List}= asn1rt:encode('Extension-Addition-Group','Ax3',Val),
- Enc = iolist_to_binary(List),
- io:format("~p~n",[Enc]),
- {ok,Val2} = asn1rt:decode('Extension-Addition-Group','Ax3',Enc),
- io:format("~p~n",[Val2]),
- case Val2 of
- Val -> ok;
- _ -> exit({expected,Val, got, Val2})
- end.
+ Val2 = #'Ax3'{a=253,b=true,s=#'Ax3_s'{sa=11,sb=true,sextaddgroup=17}},
+ roundtrip('Ax3', Val2),
+
+ run3(),
+ run3(Erule),
+
+ roundtrip('InlinedSeq', #'InlinedSeq'{s=#'InlinedSeq_s'{a=42,b=true}}),
+ roundtrip('ExtAddGroup1', #'ExtAddGroup1'{x=42,y=1023}),
+
+ ok.
+%% From X.691 (07/2002) A.4.
+encoded_ax(per) -> "9E000180 010291A4";
+encoded_ax(uper) -> "9E000600 040A4690";
+encoded_ax(ber) -> none.
+
+hex_to_binary(none) ->
+ none;
+hex_to_binary(L) ->
+ << <<(hex_digit_to_binary(D)):4>> || D <- L, D =/= $\s >>.
+
+hex_digit_to_binary(D) ->
+ if
+ $0 =< D, D =< $9 -> D - $0;
+ $A =< D, D =< $F -> D - ($A-10)
+ end.
run3(Erule) ->
Val =
{'RRC-DL-DCCH-Message',
@@ -140,16 +139,24 @@ run3() ->
Barring = #'AC-BarringConfig'{
'ac-BarringFactor' = p00,
'ac-BarringTime' = s4,
- 'ac-BarringForSpecialAC' = [0,0,0,0,0]},
- roundtrip(SI),
- roundtrip(SI#'SystemInformationBlockType2'{
- 'ssac-BarringForMMTEL-Voice-r9'=Barring}),
- roundtrip(SI#'SystemInformationBlockType2'{
+ 'ac-BarringForSpecialAC' = <<0:5>>},
+ T = 'SystemInformationBlockType2',
+ roundtrip(T, SI),
+ roundtrip(T, SI#'SystemInformationBlockType2'{
+ 'ssac-BarringForMMTEL-Voice-r9'=Barring}),
+ roundtrip(T, SI#'SystemInformationBlockType2'{
'ssac-BarringForMMTEL-Video-r9'=Barring}),
- roundtrip(SI#'SystemInformationBlockType2'{
- 'ac-BarringForCSFB-r10'=Barring}).
+ roundtrip(T, SI#'SystemInformationBlockType2'{
+ 'ac-BarringForCSFB-r10'=Barring}).
-roundtrip(V) ->
+roundtrip(T, V) ->
+ roundtrip(T, V, none).
+
+roundtrip(T, V, Expected) ->
Mod = 'Extension-Addition-Group',
- {ok,E} = Mod:encode('SystemInformationBlockType2', V),
- {ok,V} = Mod:decode('SystemInformationBlockType2', iolist_to_binary(E)).
+ {ok,E} = Mod:encode(T, V),
+ {ok,V} = Mod:decode(T, E),
+ case Expected of
+ none -> ok;
+ E -> ok
+ end.
diff --git a/lib/asn1/test/asn1_SUITE_data/testobj.erl b/lib/asn1/test/asn1_SUITE_data/testobj.erl
index be7ceee7d1..2cc909c35e 100644
--- a/lib/asn1/test/asn1_SUITE_data/testobj.erl
+++ b/lib/asn1/test/asn1_SUITE_data/testobj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -639,7 +639,7 @@ run_reset_res() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% Kod f�r att s�tta ihop RANAP-meddelanden
+%% Code for constructing RANAP messages
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -883,7 +883,7 @@ initial_ue_ies() ->
cn_domain_indicator() ->
- {'CN-DomainIndicator', 'ps-domain'}.
+ 'ps-domain'.
init_lai() ->
#'ProtocolIE-Field'{
@@ -1279,11 +1279,11 @@ reset() ->
protocolIEs = reset_ies()
}.
reset_ies() ->
- {'Reset_protocolIEs', % this identifier is very unneccesary here
- [reset_cause(),
- cn_domain_ind(), % Se initial Ue
- init_global_rnc_id() % ---- " ----
- ]}.
+ [reset_cause(),
+ cn_domain_ind(), % Se initial Ue
+ init_global_rnc_id() % ---- " ----
+ ].
+
init_global_rnc_id() ->
#'ProtocolIE-Field'{
id = 86, % 86 = id-GlobalRNC-ID
@@ -1323,8 +1323,7 @@ reset_ack() ->
protocolIEs = reset_ack_ies()
}.
reset_ack_ies() ->
- {'ResetAcknowledge_protocolIEs', % very unneccesary
- [cn_domain_ind()]}. % Se initial Ue
+ [cn_domain_ind()]. % Se initial Ue
@@ -1336,13 +1335,12 @@ reset_res(IuSCId) ->
}.
reset_res_ies(IuSCId) ->
- {'ResetResource_protocolIEs', % very unneccesary
- [
- cn_domain_ind() % Se initial Ue
- ,reset_cause() % Se reset
- ,reset_res_list(IuSCId)
- ,init_global_rnc_id_reset_res() % ---- " ----
- ]}.
+ [
+ cn_domain_ind() % Se initial Ue
+ ,reset_cause() % Se reset
+ ,reset_res_list(IuSCId)
+ ,init_global_rnc_id_reset_res() % ---- " ----
+ ].
init_global_rnc_id_reset_res() ->
#'ProtocolIE-Field'{
@@ -1420,24 +1418,7 @@ wrapper_encode(Module,Type,Value) ->
Error
end.
-wrapper_decode(Module,Type,Bytes) ->
- case Module:encoding_rule() of
- ber ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin when binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- ber_bin_v2 when binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin_v2 ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- per ->
- asn1rt:decode(Module,Type,Bytes);
- per_bin when binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- per_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- uper_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes))
- end.
+wrapper_decode(Module, Type, Bytes) when is_binary(Bytes) ->
+ asn1rt:decode(Module, Type, Bytes);
+wrapper_decode(Module, Type, Bytes) when is_list(Bytes) ->
+ asn1rt:decode(Module, Type, list_to_binary(Bytes)).
diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl
index 2c31c3259d..1225e36778 100644
--- a/lib/asn1/test/asn1_app_test.erl
+++ b/lib/asn1/test/asn1_app_test.erl
@@ -138,7 +138,9 @@ check_asn1ct_modules(Extra) ->
asn1ct_name,asn1ct_constructed_per,asn1ct_constructed_ber,
asn1ct_gen_ber,asn1ct_constructed_ber_bin_v2,
asn1ct_gen_ber_bin_v2,asn1ct_value,
- asn1ct_tok,asn1ct_parser2,asn1ct_table],
+ asn1ct_tok,asn1ct_parser2,asn1ct_table,
+ asn1ct_imm,asn1ct_func,asn1ct_rtt,
+ asn1ct_eval_ext,asn1ct_eval_per,asn1ct_eval_uper],
case Extra -- ASN1CTMods of
[] ->
ok;
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 96c04a9436..60b2b2b42e 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. 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
@@ -22,6 +22,7 @@
-export([compile/3]).
-export([compile_all/3]).
-export([compile_erlang/3]).
+-export([hex_to_bin/1]).
-export([ticket_7407_compile/2,ticket_7407_code/1, ticket_7678/2,
ticket_7708/2, ticket_7763/1, ticket_7876/3]).
@@ -39,17 +40,18 @@ compile_all(Files, Config, Options) ->
compile_file(File, Options) ->
try
- ok = asn1ct:compile(File, Options),
+ ok = asn1ct:compile(File, [warnings_as_errors|Options]),
case should_load(File, Options) of
false ->
ok;
{module, Module} ->
code:purge(Module),
- true = code:soft_purge(Module),
- {module, Module} = code:load_file(Module)
+ {module, Module} = code:load_file(Module),
+ code:purge(Module)
end
catch
Class:Reason ->
+ ct:print("Failed to compile ~s\n", [File]),
erlang:error({compile_failed, {File, Options}, {Class, Reason}})
end.
@@ -58,18 +60,22 @@ compile_erlang(Mod, Config, Options) ->
CaseDir = ?config(case_dir, Config),
M = list_to_atom(Mod),
{ok, M} = compile:file(filename:join(DataDir, Mod),
- [{i, CaseDir}, {outdir, CaseDir}|Options]).
+ [report,{i,CaseDir},{outdir,CaseDir}|Options]).
-should_load(File, Options) ->
- should_load(File, lists:member(abs, Options),
- proplists:lookup(inline, Options)).
+hex_to_bin(S) ->
+ << <<(hex2num(C)):4>> || C <- S, C =/= $\s >>.
-should_load(_File, true, _Inline) ->
- false;
-should_load(_File, _Abs, {inline, Module}) when Module /= true ->
- {module, Module};
-should_load(File, _Abs, _Inline) ->
- {module, list_to_atom(strip_extension(filename:basename(File)))}.
+%%%
+%%% Internal functions.
+%%%
+
+should_load(File, Options) ->
+ case lists:member(abs, Options) of
+ true ->
+ false;
+ false ->
+ {module,list_to_atom(strip_extension(filename:basename(File)))}
+ end.
strip_extension(File) ->
strip_extension(File, filename:extension(File)).
@@ -81,20 +87,24 @@ strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"->
strip_extension(File, _Ext) ->
File.
+hex2num(C) when $0 =< C, C =< $9 -> C - $0;
+hex2num(C) when $A =< C, C =< $F -> C - $A + 10;
+hex2num(C) when $a =< C, C =< $f -> C - $a + 10.
+
ticket_7407_compile(Config,Option) ->
?line DataDir = ?config(data_dir,Config),
?line OutDir = ?config(priv_dir,Config),
?line ok = asn1ct:compile(DataDir ++ "EUTRA-extract-7407",
- [uper_bin, {outdir,OutDir}]++Option).
+ [uper, {outdir,OutDir}]++Option).
ticket_7708(Config,Option) ->
?line DataDir = ?config(data_dir,Config),
?line OutDir = ?config(priv_dir,Config),
?line ok = asn1ct:compile(DataDir ++ "EUTRA-extract-55",
- [uper_bin, {outdir,OutDir}]++Option).
+ [uper, {outdir,OutDir}]++Option).
ticket_7407_code(FinalPadding) ->
@@ -154,7 +164,7 @@ ticket_7678(Config, Option) ->
?line OutDir = ?config(priv_dir,Config),
?line ok = asn1ct:compile(DataDir ++ "UPERDefault",
- [uper_bin, {outdir,OutDir}]++Option),
+ [uper, {outdir,OutDir}]++Option),
?line Val = 'UPERDefault':seq(),
?line {ok,<<0,6,0>>} = 'UPERDefault':encode('Seq',Val),
@@ -167,12 +177,12 @@ ticket_7763(Config) ->
?line OutDir = ?config(priv_dir,Config),
?line ok = asn1ct:compile(DataDir ++ "EUTRA-extract-55",
- [uper_bin, {outdir,OutDir}]),
+ [uper, {outdir,OutDir}]),
Val = {'Seq',15,lists:duplicate(8,0),[0],lists:duplicate(28,0),15,true},
?line {ok,Bin} = 'EUTRA-extract-55':encode('Seq',Val),
?line ok = asn1ct:compile(DataDir ++ "EUTRA-extract-55",
- [uper_bin,compact_bit_string,{outdir,OutDir}]),
+ [uper,compact_bit_string,{outdir,OutDir}]),
CompactVal = {'Seq',15,{0,<<0>>},{7,<<0>>},{4,<<0,0,0,0>>},15,true},
{ok,CompactBin} = 'EUTRA-extract-55':encode('Seq',CompactVal),
diff --git a/lib/asn1/test/asn1_wrapper.erl b/lib/asn1/test/asn1_wrapper.erl
index d515b99ac2..ac194fe38b 100644
--- a/lib/asn1/test/asn1_wrapper.erl
+++ b/lib/asn1/test/asn1_wrapper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -34,41 +34,16 @@ encode(Module,Type,Value) ->
Error
end.
-decode(Module,Type,Bytes) ->
- case Module:encoding_rule() of
- ber ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin when is_binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- ber_bin_v2 when is_binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- ber_bin_v2 ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- per ->
- asn1rt:decode(Module,Type,Bytes);
- per_bin when is_binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- per_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes));
- uper_bin when is_binary(Bytes) ->
- asn1rt:decode(Module,Type,Bytes);
- uper_bin ->
- asn1rt:decode(Module,Type,list_to_binary(Bytes))
- end.
+decode(Module, Type, Bytes) when is_binary(Bytes) ->
+ asn1rt:decode(Module, Type, Bytes);
+decode(Module, Type, Bytes) when is_list(Bytes) ->
+ asn1rt:decode(Module, Type, list_to_binary(Bytes)).
erule(ber) ->
ber;
-erule(ber_bin) ->
- ber;
-erule(ber_bin_v2) ->
- ber;
erule(per) ->
per;
-erule(per_bin) ->
- per;
-erule(uper_bin) ->
+erule(uper) ->
per.
diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl
index ff6e386a88..1c4b4c6894 100644
--- a/lib/asn1/test/ber_decode_error.erl
+++ b/lib/asn1/test/ber_decode_error.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. 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
@@ -21,31 +21,34 @@
-export([run/1]).
--include_lib("test_server/include/test_server.hrl").
-
run([]) ->
- ?line {ok,B} = asn1_wrapper:encode('Constructed','S3',{'S3',17}),
- ?line [T,L|V] = lists:flatten(B),
- ?line Bytes = [T,L+3|V] ++ [2,1,3],
- ?line case asn1_wrapper:decode('Constructed','S3',Bytes) of
- {error,{asn1,{unexpected,_}}} -> ok
- end,
- %% Unexpected bytes must be accepted if there is an extensionmark
- ?line {ok,{'S3ext',17}} = asn1_wrapper:decode('Constructed','S3ext',Bytes),
- ok;
-run([driver]) ->
- %% test of OTP-4797, bad indata to driver does not cause an EXIT
- ?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
- ok;
-run([nif]) ->
- %% test of OTP-4797, bad indata to driver does not cause an EXIT
- ?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
- ok.
-
+ {ok,B} = asn1_wrapper:encode('Constructed','S3',{'S3',17}),
+ [T,L|V] = lists:flatten(B),
+ Bytes = [T,L+3|V] ++ [2,1,3],
+ case asn1_wrapper:decode('Constructed','S3',Bytes) of
+ {error,{asn1,{unexpected,_}}} -> ok
+ end,
+ %% Unexpected bytes must be accepted if there is an extensionmark
+ {ok,{'S3ext',17}} = asn1_wrapper:decode('Constructed','S3ext',Bytes),
+ %% Truncated tag.
+ {error,{asn1,{invalid_tag,_}}} =
+ (catch 'Constructed':decode('I', <<31,255,255>>)),
+ %% Overlong tag.
+ {error,{asn1,{invalid_tag,_}}} =
+ (catch 'Constructed':decode('I', <<31,255,255,255,127>>)),
+ %% Invalid length.
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('I', <<8,255>>)),
+ %% Other errors.
+ {error,{asn1,{invalid_value,_}}} =
+ (catch 'Constructed':decode('I', <<>>)),
+ {error,{asn1,{invalid_value,_}}} =
+ (catch 'Constructed':decode('I', <<8,7>>)),
+ ok.
diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl
new file mode 100644
index 0000000000..a94a6d95a0
--- /dev/null
+++ b/lib/asn1/test/error_SUITE.erl
@@ -0,0 +1,104 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. 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%
+%%
+
+-module(error_SUITE).
+-export([suite/0,all/0,groups/0,
+ already_defined/1,enumerated/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+suite() -> [{ct_hooks, [ts_install_cth]}].
+
+all() ->
+ [{group,p}].
+
+groups() ->
+ [{p,parallel(),[already_defined,
+ enumerated]}].
+
+parallel() ->
+ case erlang:system_info(schedulers) > 1 of
+ true -> [parallel];
+ false -> []
+ end.
+
+already_defined(Config) ->
+ M = 'Already',
+ P = {M,
+ <<"Already DEFINITIONS ::= BEGIN\n"
+ " I ::= INTEGER\n"
+ " i I ::= 42\n"
+ " I ::= OCTET STRING\n"
+ " I ::= CLASS { &Type }\n"
+ " MYCLASS ::= CLASS { &Type }\n"
+ " i MYCLASS ::= { &Type INTEGER }\n"
+ " o MYCLASS ::= { &Type INTEGER }\n"
+ " I MYCLASS ::= { o }\n"
+ " I{T} ::= SEQUENCE OF T\n"
+ " I{INTEGER:x} INTEGER ::= { 1 | 2 | x }\n"
+ " i{T} MYCLASS ::= { &Type T }\n"
+ "END\n">>},
+ {error,
+ [
+ {structured_error,{M,4},asn1ct_check,{already_defined,'I',2}},
+ {structured_error,{M,5},asn1ct_check,{already_defined,'I',2}},
+ {structured_error,{M,7},asn1ct_check,{already_defined,'i',3}},
+ {structured_error,{M,9},asn1ct_check,{already_defined,'I',2}},
+ {structured_error,{M,10},asn1ct_check,{already_defined,'I',2}},
+ {structured_error,{M,11},asn1ct_check,{already_defined,'I',2}},
+ {structured_error,{M,12},asn1ct_check,{already_defined,'i',3}}
+ ]
+ } = run(P, Config),
+ ok.
+
+enumerated(Config) ->
+ M = 'Enumerated',
+ P = {M,
+ <<"Enumerated DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " Enum ::= ENUMERATED { a, b, c }\n"
+ " e Enum ::= d\n"
+ " EnumExt ::= ENUMERATED { x, ..., y }\n"
+ " ext EnumExt ::= z\n"
+ " S1 ::= SEQUENCE {\n"
+ " ge1 Enum DEFAULT a,\n"
+ " ge2 EnumExt DEFAULT x,\n"
+ " ge3 EnumExt DEFAULT y,\n"
+ " e Enum DEFAULT aa\n"
+ " }\n"
+ " S2 ::= SEQUENCE {\n"
+ " e2 EnumExt DEFAULT xyz\n"
+ " }\n"
+ "END\n">>},
+ {error,
+ [
+ {structured_error,{'Enumerated',3},asn1ct_check,{undefined,d}},
+ {structured_error,{'Enumerated',5},asn1ct_check,{undefined,z}},
+ {structured_error,{'Enumerated',10},asn1ct_check,{undefined,aa}},
+ {structured_error,{'Enumerated',13},asn1ct_check,{undefined,xyz}}
+ ]
+ } = run(P, Config),
+ ok.
+
+
+
+run({Mod,Spec}, Config) ->
+ Base = atom_to_list(Mod) ++ ".asn1",
+ File = filename:join(?config(priv_dir, Config), Base),
+ ok = file:write_file(File, Spec),
+ asn1ct:compile(File).
diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl
index b7a7d6e4df..426ae16994 100644
--- a/lib/asn1/test/h323test.erl
+++ b/lib/asn1/test/h323test.erl
@@ -22,7 +22,6 @@
-export([run/1]).
-include_lib("test_server/include/test_server.hrl").
-run(per_bin) -> run();
run(per) -> run();
run(_Rules) -> ok.
diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl
index b75cfb6831..c6a07646c2 100644
--- a/lib/asn1/test/testChoExtension.erl
+++ b/lib/asn1/test/testChoExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -25,42 +25,32 @@
extension(_Rules) ->
-
- ?line {ok,Bytes1} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{bool,true}}),
- ?line {ok,{bool,true}} =
- asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{int,33}}),
- ?line {ok,{int,33}} =
- asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes2)),
+ roundtrip('ChoExt1', {bool,true}),
+ roundtrip('ChoExt1', {int,33}),
%% A trick to encode with another compatible CHOICE type to test reception
%% extension alternative
- ?line {ok,Bytes2x} = asn1_wrapper:encode('ChoExtension','ChoExt1x',{str,"abc"}),
- ?line {ok,Val2x} =
+ {ok,Bytes2x} = asn1_wrapper:encode('ChoExtension','ChoExt1x',{str,"abc"}),
+ {ok,Val2x} =
asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes2x)),
io:format("Choice extension alternative = ~p~n",[Val2x]),
- ?line {ok,Bytes3} = asn1_wrapper:encode('ChoExtension','ChoExt2',{'ChoExt2',{bool,true}}),
- ?line {ok,{bool,true}} =
- asn1_wrapper:decode('ChoExtension','ChoExt2',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('ChoExtension','ChoExt2',{'ChoExt2',{int,33}}),
- ?line {ok,{int,33}} =
- asn1_wrapper:decode('ChoExtension','ChoExt2',lists:flatten(Bytes4)),
+ roundtrip('ChoExt2', {bool,true}),
+ roundtrip('ChoExt2', {int,33}),
+ roundtrip('ChoExt3', {bool,true}),
+ roundtrip('ChoExt3', {int,33}),
+ roundtrip('ChoExt4', {str,"abc"}),
- ?line {ok,Bytes5} = asn1_wrapper:encode('ChoExtension','ChoExt3',{'ChoExt3',{bool,true}}),
- ?line {ok,{bool,true}} =
- asn1_wrapper:decode('ChoExtension','ChoExt3',lists:flatten(Bytes5)),
+ roundtrip('ChoEmptyRoot', {bool,false}),
+ roundtrip('ChoEmptyRoot', {bool,true}),
+ roundtrip('ChoEmptyRoot', {int,0}),
+ roundtrip('ChoEmptyRoot', {int,7}),
- ?line {ok,Bytes6} = asn1_wrapper:encode('ChoExtension','ChoExt3',{'ChoExt3',{int,33}}),
- ?line {ok,{int,33}} =
- asn1_wrapper:decode('ChoExtension','ChoExt3',lists:flatten(Bytes6)),
-
- Val7 = {str,"abc"},
- ?line {ok,Bytes7} = asn1_wrapper:encode('ChoExtension','ChoExt4',Val7),
- ?line {ok,Val7} = asn1_wrapper:decode('ChoExtension','ChoExt4',lists:flatten(Bytes7)),
+ ok.
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'ChoExtension':encode(Type, Value),
+ {ok,Value} = 'ChoExtension':decode(Type, Encoded),
ok.
diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl
index b2d171f9c7..5fdee48add 100644
--- a/lib/asn1/test/testChoExternal.erl
+++ b/lib/asn1/test/testChoExternal.erl
@@ -38,62 +38,27 @@ compile(Config, Rules, Optimize) ->
external(_Rules) ->
+ roundtrip('ChoXCho', {boolCho,true}),
+ roundtrip('ChoXCho', {intCho,77}),
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoExternal','ChoXCho',{'ChoXCho',{boolCho,true}}),
- ?line {ok,{boolCho,true}} = asn1_wrapper:decode('ChoExternal','ChoXCho',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoExternal','ChoXCho',{'ChoXCho',{intCho,77}}),
- ?line {ok,{intCho,77}} = asn1_wrapper:decode('ChoExternal','ChoXCho',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xbool,true}}),
- ?line {ok,{xbool,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xboolImp,true}}),
- ?line {ok,{xboolImp,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes22)),
-
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xboolExp,true}}),
- ?line {ok,{xboolExp,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('ChoExternal','NT',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NT',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('ChoExternal','Exp',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','Exp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('ChoExternal','NTNT',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NTNT',lists:flatten(Bytes33)),
-
- ?line {ok,Bytes34} = asn1_wrapper:encode('ChoExternal','NTExp',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NTExp',lists:flatten(Bytes34)),
-
- ?line {ok,Bytes35} = asn1_wrapper:encode('ChoExternal','ExpNT',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','ExpNT',lists:flatten(Bytes35)),
-
- ?line {ok,Bytes36} = asn1_wrapper:encode('ChoExternal','ExpExp',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','ExpExp',lists:flatten(Bytes36)),
-
-
-
-
-
- ?line {ok,Bytes41} = asn1_wrapper:encode('ChoExternal','XNTNT',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XNTNT',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('ChoExternal','XNTExp',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XNTExp',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} = asn1_wrapper:encode('ChoExternal','XExpNT',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XExpNT',lists:flatten(Bytes43)),
-
- ?line {ok,Bytes44} = asn1_wrapper:encode('ChoExternal','XExpExp',{os,"kalle"}),
- ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XExpExp',lists:flatten(Bytes44)),
+ roundtrip('ChoXBool', {xbool,true}),
+ roundtrip('ChoXBool', {xboolImp,true}),
+ roundtrip('ChoXBool', {xboolExp,true}),
+
+ roundtrip('NT', {os,"kalle"}),
+ roundtrip('Exp', {os,"kalle"}),
+ roundtrip('NTNT', {os,"kalle"}),
+ roundtrip('NTExp', {os,"kalle"}),
+ roundtrip('ExpNT', {os,"kalle"}),
+ roundtrip('ExpExp', {os,"kalle"}),
+ roundtrip('XNTNT', {os,"kalle"}),
+ roundtrip('XNTExp', {os,"kalle"}),
+ roundtrip('XExpNT', {os,"kalle"}),
+ roundtrip('XExpExp', {os,"kalle"}),
ok.
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'ChoExternal':encode(Type, Value),
+ {ok,Value} = 'ChoExternal':decode(Type, Encoded),
+ ok.
diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl
index 22be26cbce..ee26d124a9 100644
--- a/lib/asn1/test/testChoRecursive.erl
+++ b/lib/asn1/test/testChoRecursive.erl
@@ -28,38 +28,21 @@
-record('ChoRec2_something',{a, b, c}).
recursive(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{something,
- #'ChoRec_something'{a = 77,
- b = "some octets here",
- c = {'ChoRec',{nothing,'NULL'}}}}}),
- ?line {ok,{something,{'ChoRec_something',77,"some octets here",{nothing,'NULL'}}}} =
- asn1_wrapper:decode('ChoRecursive','ChoRec',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{nothing,'NULL'}}),
- ?line {ok,{nothing,'NULL'}} =
- asn1_wrapper:decode('ChoRecursive','ChoRec',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('ChoRecursive','ChoRec2',{'ChoRec2',
- {something,
- #'ChoRec2_something'{a = 77,
- b = "some octets here",
- c = {'ChoRec2',
- {nothing,'NULL'}}}}}),
- ?line {ok,{something,{'ChoRec2_something',77,"some octets here",{nothing,'NULL'}}}} =
- asn1_wrapper:decode('ChoRecursive','ChoRec2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('ChoRecursive','ChoRec2',{'ChoRec2',{nothing,'NULL'}}),
- ?line {ok,{nothing,'NULL'}} =
- asn1_wrapper:decode('ChoRecursive','ChoRec2',lists:flatten(Bytes22)),
-
-
-
-
+ roundtrip('ChoRec',
+ {something,
+ #'ChoRec_something'{a = 77,
+ b = "some octets here",
+ c = {nothing,'NULL'}}}),
+ roundtrip('ChoRec', {nothing,'NULL'}),
+ roundtrip('ChoRec2',
+ {something,
+ #'ChoRec2_something'{a = 77,
+ b = "some octets here",
+ c = {nothing,'NULL'}}}),
+ roundtrip('ChoRec2', {nothing,'NULL'}),
+ ok.
+
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'ChoRecursive':encode(Type, Value),
+ {ok,Value} = 'ChoRecursive':decode(Type, Encoded),
ok.
diff --git a/lib/asn1/test/testChoiceIndefinite.erl b/lib/asn1/test/testChoiceIndefinite.erl
index 630efcf27a..b5832c985a 100644
--- a/lib/asn1/test/testChoiceIndefinite.erl
+++ b/lib/asn1/test/testChoiceIndefinite.erl
@@ -23,12 +23,7 @@
-include_lib("test_server/include/test_server.hrl").
-main(per_bin) -> ok;
main(per) -> ok;
-main(ber_bin_v2) ->
- main(ber);
-main(ber_bin) ->
- main(ber);
main(ber) ->
%% Test case related to OTP-4358
%% normal encoding
diff --git a/lib/asn1/test/testCompactBitString.erl b/lib/asn1/test/testCompactBitString.erl
index 9563a31bf3..f74992a79e 100644
--- a/lib/asn1/test/testCompactBitString.erl
+++ b/lib/asn1/test/testCompactBitString.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -22,240 +22,134 @@
-export([compact_bit_string/1, bit_string_unnamed/1,otp_4869/1,
ticket_7734/1]).
--include_lib("test_server/include/test_server.hrl").
-
compact_bit_string(Rules) ->
%%==========================================================
%% Bs1 ::= BIT STRING
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('PrimStrings','Bs1',0),
- ?line {ok,{0,<<>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('PrimStrings','Bs1',4),
- ?line {ok,{5,<<32>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','Bs1',15),
- ?line {ok,{4,<<240>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','Bs1',255),
- ?line {ok,{0,<<255>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','Bs1',256),
- ?line {ok,{7,<<0,128>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes5)),
-
- ?line {ok,Bytes6} = asn1_wrapper:encode('PrimStrings','Bs1',257),
- ?line {ok,{7,<<128,128>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes6)),
-
- ?line {ok,Bytes7} = asn1_wrapper:encode('PrimStrings','Bs1',444),
- ?line {ok,{7,<<61,128>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes7)),
-
- ?line {ok,Bytes8} = asn1_wrapper:encode('PrimStrings','Bs1',
- 12345678901234567890),
- ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes8)),
-
-%% Removed due to beam cannot handle this big integers
-%% Bs1_1 = 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890,
-%% ?line {ok,Bytes9} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_1),
-%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes9)),
-
-%% Bs1_2 = 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890,
-%% ?line {ok,Bytes10} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_2),
-%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes10)),
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('PrimStrings','Bs1',
- [1,1,1,1,1,1,1,1]),
- ?line {ok,{0,<<255>>}} = asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings',
- 'Bs1',
- [0,1,0,0,1,0]),
- ?line {ok,{2,<<72>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('PrimStrings', 'Bs1',
- [1,0,0,0,0,0,0,0,0]),
- ?line {ok,{7,<<128,0>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes13)),
-
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('PrimStrings','Bs1',
- [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes14)),
-
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line Bytes15 = [35,8,3,2,0,73,3,2,4,32],
- ?line {ok,{4,<<73,32>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes15)),
-
- ?line Bytes16 = [35,9,3,2,0,234,3,3,7,156,0],
- ?line {ok,{7,<<234,156,0>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes16)),
-
- ?line Bytes17 = [35,128,3,2,0,73,3,2,4,32,0,0],
- ?line {ok,{4,<<73,32>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes17)),
-
- ?line Bytes18 = [35,128,3,2,0,234,3,3,7,156,0,0,0],
- ?line {ok,{7,<<234,156,0>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',
- lists:flatten(Bytes18)),
- ok;
-
- per ->
- ok
- end,
+ roundtrip('Bs1', 0, {0,<<>>}),
+ roundtrip('Bs1', 4, {5,<<2#00100000>>}),
+ roundtrip('Bs1', 15, {4,<<2#11110000>>}),
+ roundtrip('Bs1', 255, {0,<<2#11111111>>}),
+ roundtrip('Bs1', 256, {7,<<16#00,16#80>>}),
+ roundtrip('Bs1', 257, {7,<<16#80,16#80>>}),
+ roundtrip('Bs1', 444, {7,<<16#3D,16#80>>}),
+ roundtrip('Bs1', 12345678901234567890,
+ {0,<<75,80,248,215,49,149,42,213>>}),
+
+ roundtrip('Bs1', [1,1,1,1,1,1,1,1], {0,<<255>>}),
+ roundtrip('Bs1', [0,1,0,0,1,0], {2,<<16#48>>}),
+ roundtrip('Bs1', [1,0,0,0,0,0,0,0,0], {7,<<16#80,0>>}),
+ roundtrip('Bs1', [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1],
+ {5,<<75,226,96>>}),
- %% The following case to test OTP-4200
- ?line {ok,Bytes19} =
- asn1_wrapper:encode('PrimStrings','Bs1',{0,<<0,0,1,1>>}),
- ?line {ok,{0,<<0,0,1,1>>}} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes19)),
+ case Rules of
+ ber ->
+ {ok,{4,<<73,32>>}} =
+ 'PrimStrings':decode('Bs1', <<35,8,3,2,0,73,3,2,4,32>>),
+ {ok,{7,<<234,156,0>>}} =
+ 'PrimStrings':decode('Bs1', <<35,9,3,2,0,234,3,3,7,156,0>>),
+ {ok,{4,<<73,32>>}} =
+ 'PrimStrings':decode('Bs1', <<35,128,3,2,0,73,3,2,4,32,0,0>>),
+ {ok,{7,<<234,156,0>>}} =
+ 'PrimStrings':decode('Bs1',
+ <<35,128,3,2,0,234,3,3,7,156,0,0,0>>);
+ _ ->
+ ok
+ end,
+
+ %% Test OTP-4200
+ roundtrip('Bs1', {0,<<0,0,1,1>>}),
%%==========================================================
%% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7))
%%==========================================================
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('PrimStrings','Bs2',[mo,tu,fr]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('PrimStrings','Bs2',[0,1,1,0,0,1,0]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes22)),
-
- % ?line case asn1_wrapper:erule(Rules) of
-% ber ->
-% ?line {ok,[mo,tu,fr,su,mo,th]} =
-% asn1_wrapper:decode('PrimStrings','Bs2',[35,8,3,2,1,100,3,2,2,200]),
-
-% ?line {ok,[mo,tu,fr,su,mo,th]} =
-% asn1_wrapper:decode('PrimStrings','Bs2',[35,128,3,2,1,100,3,2,2,200,0,0]),
-% ok;
-
-% per ->
-% ok
-% end,
-
-
+
+ roundtrip('Bs2', [mo,tu,fr]),
+ roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]),
%%==========================================================
%% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7))
%%==========================================================
- ?line {ok,Bytes31} = asn1_wrapper:encode('PrimStrings','Bs3',[mo,tu,fr]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('PrimStrings','Bs3',[0,1,1,0,0,1,0]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes32)),
-
-
+ roundtrip('Bs3', [mo,tu,fr]),
+ roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]),
%%==========================================================
%% BsPri ::= [PRIVATE 61] BIT STRING
%%==========================================================
-
- ?line {ok,Bytes41} = asn1_wrapper:encode('PrimStrings','BsPri',45),
- ?line {ok,{2,<<180>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('PrimStrings','BsPri',211),
- ?line {ok,{0,<<203>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes42)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',
- [223,61,4,5,75,226,96]),
-
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',
- [255,61,128,3,4,5,75,226,96,0,0]),
-
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',
- [255,61,9,3,2,0,75,3,3,5,226,96]),
-
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','BsPri',
- [255,61,128,3,2,0,75,3,3,5,226,96,0,0]),
- ok;
-
- per ->
- ok
- end,
-
+
+ roundtrip('BsPri', 45, {2,<<180>>}),
+ roundtrip('BsPri', 211, {0,<<203>>}),
+
+ case Rules of
+ ber ->
+ {ok,{5,<<75,226,96>>}} =
+ 'PrimStrings':decode('BsPri',
+ <<223,61,4,5,75,226,96>>),
+
+ {ok,{5,<<75,226,96>>}} =
+ 'PrimStrings':decode('BsPri',
+ <<255,61,128,3,4,5,75,226,96,0,0>>),
+
+ {ok,{5,<<75,226,96>>}} =
+ 'PrimStrings':decode('BsPri',
+ <<255,61,9,3,2,0,75,3,3,5,226,96>>),
+
+ {ok,{5,<<75,226,96>>}} =
+ 'PrimStrings':decode('BsPri',
+ <<255,61,128,3,2,0,75,3,3,5,226,96,0,0>>),
+ ok;
+ _ ->
+ ok
+ end,
%%==========================================================
%% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING
%%==========================================================
-
- ?line {ok,Bytes51} = asn1_wrapper:encode('PrimStrings','BsExpPri',45),
- ?line {ok,{2,<<180>>}} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes51)),
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('PrimStrings','BsExpPri',211),
- ?line {ok,{0,<<203>>}} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes52)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,{5,<<75,226,96>>}} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',[255,61,6,3,4,5,75,226,96]),
- ok;
-
- per ->
- ok
- end,
-
- ok.
-ticket_7734(per_bin) ->
- ?line BS = {0,list_to_binary(lists:duplicate(128,0))},
- ?line {ok,BSEnc} = asn1_wrapper:encode('PrimStrings','BS1024',BS),
- ?line {ok,BS} = asn1_wrapper:decode('PrimStrings','BS1024',BSEnc).
+ roundtrip('BsExpPri', 45, {2,<<180>>}),
+ roundtrip('BsExpPri', 211, {0,<<203>>}),
-bit_string_unnamed(Rules) ->
- case asn1_wrapper:erule(Rules) of
+ case Rules of
ber ->
- ok;
- per ->
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('PrimStrings','TransportLayerAddress',
- [0,1,1,0]),
- ?line {ok,{4,<<96>>}} =
- asn1_wrapper:decode('PrimStrings','TransportLayerAddress',
- lists:flatten(Bytes1))
- end.
+ {ok,{5,<<75,226,96>>}} =
+ 'PrimStrings':decode('BsExpPri', <<255,61,6,3,4,5,75,226,96>>);
+ _ ->
+ ok
+ end,
-otp_4869(per_bin) ->
- ?line Val1={'IP',[0],{0,<<62,235,90,50,0,0,0,0,0,0,0,0,0,0,0,0>>},asn1_NOVALUE},
- ?line Val2 = {'IP',[0],[0,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,0,0,1,1,0,0,1,0] ++ lists:duplicate(128 - 32,0),asn1_NOVALUE},
+ ok.
- ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','IP',Val1),
- ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','IP',Val2);
+ticket_7734(_) ->
+ BS = {0,list_to_binary(lists:duplicate(128, 0))},
+ roundtrip('BS1024', BS).
+
+bit_string_unnamed(_Rules) ->
+ roundtrip('TransportLayerAddress', [0,1,1,0], {4,<<96>>}).
+
+otp_4869(per) ->
+ Val1 = {'IP',[0],{0,<<62,235,90,50,0,0,0,0,0,0,0,0,0,0,0,0>>},asn1_NOVALUE},
+ Val2 = {'IP',[0],[0,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,
+ 1,0,0,0,1,1,0,0,1,0] ++
+ lists:duplicate(128 - 32, 0),asn1_NOVALUE},
+ {ok,Encoded} = 'Constraints':encode('IP', Val1),
+ {ok,Encoded} = 'Constraints':encode('IP', Val2),
+ ok;
otp_4869(_) ->
ok.
+
+roundtrip(Type, Val) ->
+ roundtrip_1('PrimStrings', Type, Val, Val).
+
+roundtrip(Type, Val1, Val2) ->
+ roundtrip_1('PrimStrings', Type, Val1, Val2).
+
+roundtrip_1(Mod, Type, In, Out) ->
+ {ok,Encoded} = Mod:encode(Type, In),
+ {ok,Out} = Mod:decode(Type, Encoded),
+ %% Test that compact BIT STRINGs can be encoded.
+ {ok,Encoded} = Mod:encode(Type, Out),
+ ok.
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index 543c106e8a..03a09492af 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -30,59 +30,20 @@ int_constraints(Rules) ->
%% SingleValue ::= INTEGER (1)
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','SingleValue',1),
- ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue',
- lists:flatten(Bytes1)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('Constraints','SingleValue',0),
- ?line {error,{asn1,{integer_range,_,0}}} =
- asn1_wrapper:decode('Constraints','SingleValue',
- lists:flatten(Bytes2)),
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('Constraints','SingleValue',1000),
- ?line {error,{asn1,{integer_range,_,1000}}} =
- asn1_wrapper:decode('Constraints','SingleValue',
- lists:flatten(Bytes3));
- per ->
- ?line {error,_Reason1} =
- asn1_wrapper:encode('Constraints','SingleValue',0),
- ?line {error,_Reason2} =
- asn1_wrapper:encode('Constraints','SingleValue',1000)
- end,
+ range_error(Rules, 'SingleValue', 0),
+ roundtrip('SingleValue', 1),
+ range_error(Rules, 'SingleValue', 2),
+ range_error(Rules, 'SingleValue', 1000),
%%==========================================================
%% SingleValue2 ::= INTEGER (1..20)
%%==========================================================
- ?line {ok,Bytes4} = asn1_wrapper:encode('Constraints','SingleValue2',1),
- ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue2',
- lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('Constraints','SingleValue2',20),
- ?line {ok,20} = asn1_wrapper:decode('Constraints','SingleValue2',
- lists:flatten(Bytes5)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('Constraints','SingleValue2',0),
- ?line {error,{asn1,{integer_range,{1,20},0}}} =
- asn1_wrapper:decode('Constraints','SingleValue2',
- lists:flatten(Bytes6)),
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('Constraints','SingleValue2',21),
- ?line {error,{asn1,{integer_range,{1,20},21}}} =
- asn1_wrapper:decode('Constraints','SingleValue2',
- lists:flatten(Bytes7));
- per ->
- ?line {error,_Reason3} =
- asn1_wrapper:encode('Constraints','SingleValue',0),
- ?line {error,_Reason4} =
- asn1_wrapper:encode('Constraints','SingleValue',1000)
- end,
+ range_error(Rules, 'SingleValue2', 0),
+ roundtrip('SingleValue2', 1),
+ roundtrip('SingleValue2', 20),
+ range_error(Rules, 'SingleValue2', 21),
+ range_error(Rules, 'SingleValue2', 1000),
%%==========================================================
%% SingleValue3 ::= INTEGER (Predefined | 5 | 10)
@@ -90,136 +51,192 @@ int_constraints(Rules) ->
%% where one value is predefined.
%%==========================================================
- ?line {ok,BytesSV3} = asn1_wrapper:encode('Constraints','SingleValue3',1),
- ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue3',
- lists:flatten(BytesSV3)),
- ?line {ok,BytesSV3_2} = asn1_wrapper:encode('Constraints','SingleValue3',5),
- ?line {ok,5} = asn1_wrapper:decode('Constraints','SingleValue3',
- lists:flatten(BytesSV3_2)),
- ?line {ok,BytesSV3_3} = asn1_wrapper:encode('Constraints','SingleValue3',10),
- ?line {ok,10} = asn1_wrapper:decode('Constraints','SingleValue3',
- lists:flatten(BytesSV3_3)),
+ roundtrip('SingleValue3', 1),
+ roundtrip('SingleValue3', 5),
+ roundtrip('SingleValue3', 10),
%%==========================================================
%% Range2to19 ::= INTEGER (1<..<20)
%%==========================================================
- ?line {ok,Bytes8} = asn1_wrapper:encode('Constraints','Range2to19',2),
- ?line {ok,2} = asn1_wrapper:decode('Constraints','Range2to19',lists:flatten(Bytes8)),
-
- ?line {ok,Bytes9} = asn1_wrapper:encode('Constraints','Range2to19',19),
- ?line {ok,19} = asn1_wrapper:decode('Constraints','Range2to19',lists:flatten(Bytes9)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,Bytes10} =
- asn1_wrapper:encode('Constraints','Range2to19',1),
- ?line {error,{asn1,{integer_range,{2,19},1}}} =
- asn1_wrapper:decode('Constraints','Range2to19',
- lists:flatten(Bytes10)),
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('Constraints','Range2to19',20),
- ?line {error,{asn1,{integer_range,{2,19},20}}} =
- asn1_wrapper:decode('Constraints','Range2to19',
- lists:flatten(Bytes11));
- per ->
- ?line {error,_Reason5} =
- asn1_wrapper:encode('Constraints','Range2to19',1),
- ?line {error,_Reason6} =
- asn1_wrapper:encode('Constraints','Range2to19',20)
- end,
+ range_error(Rules, 'Range2to19', 1),
+ roundtrip('Range2to19', 2),
+ roundtrip('Range2to19', 19),
+ range_error(Rules, 'Range2to19', 20),
%%==========================================================
%% Tests for Range above 16^4 up to maximum supported by asn1 assuming the
%% octet length field is encoded on max 8 bits
%%==========================================================
LastNumWithoutLengthEncoding = 65536,
- ?line {ok,BytesFoo} = asn1_wrapper:encode('Constraints','Range256to65536',
- LastNumWithoutLengthEncoding),
- ?line {ok,LastNumWithoutLengthEncoding} =
- asn1_wrapper:decode('Constraints','Range256to65536',lists:flatten(BytesFoo)),
+ roundtrip('Range256to65536', LastNumWithoutLengthEncoding),
FirstNumWithLengthEncoding = 65537,
- ?line {ok,BytesBar} = asn1_wrapper:encode('LargeConstraints','RangeMax',
- FirstNumWithLengthEncoding),
- ?line {ok,FirstNumWithLengthEncoding} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBar)),
+ roundtrip('LargeConstraints', 'RangeMax', FirstNumWithLengthEncoding),
FirstNumOver16_6 = 16777217,
- ?line {ok, BytesBaz} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_6),
- ?line {ok, FirstNumOver16_6} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBaz)),
+ roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_6),
FirstNumOver16_8 = 4294967297,
- ?line {ok, BytesQux} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_8),
- ?line {ok, FirstNumOver16_8} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesQux)),
+ roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_8),
FirstNumOver16_10 = 1099511627776,
- ?line {ok, BytesBur} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10),
- ?line {ok, FirstNumOver16_10} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)),
+ roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10),
FirstNumOver16_10 = 1099511627776,
- ?line {ok, BytesBur} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10),
- ?line {ok, FirstNumOver16_10} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)),
+ roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10),
HalfMax = 1 bsl (128*8),
- ?line {ok, BytesHalfMax} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', HalfMax),
- ?line {ok, HalfMax} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesHalfMax)),
+ roundtrip('LargeConstraints', 'RangeMax', HalfMax),
Max = 1 bsl (255*8),
- ?line {ok, BytesMax} =
- asn1_wrapper:encode('LargeConstraints','RangeMax', Max),
- ?line {ok, Max} =
- asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesMax)),
+ roundtrip('LargeConstraints', 'RangeMax', Max),
%% Random number within longlong range
LongLong = 12672809400538808320,
- ?line {ok, BytesLongLong} =
- asn1_wrapper:encode('Constraints','LongLong', LongLong),
- ?line {ok, LongLong} =
- asn1_wrapper:decode('Constraints','LongLong',lists:flatten(BytesLongLong)),
+ roundtrip('LongLong', LongLong),
%%==========================================================
%% Constraint Combinations (Duboisson p. 285)
%% I ::= INTEGER (0|15..269)
%%==========================================================
- ?line {ok,Bytes12} = asn1_wrapper:encode('Constraints','I',0),
- ?line {ok,0} = asn1_wrapper:decode('Constraints','I',Bytes12),
- ?line {ok,Bytes13} = asn1_wrapper:encode('Constraints','I',20),
- ?line {ok,20} = asn1_wrapper:decode('Constraints','I',Bytes13),
+ range_error(Rules, 'I', -1),
+ roundtrip('I', 0),
+ roundtrip('I', 15),
+ roundtrip('I', 20),
+ roundtrip('I', 269),
+ range_error(Rules, 'I', 270),
%%==========================================================
%% Constraint Combinations (Duboisson p. 285)
%% X1 ::= INTEGER (1..4|8|10|20)
%%==========================================================
- ?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','X1',1),
- ?line {ok,1} = asn1_wrapper:decode('Constraints','X1',Bytes14),
- ?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','X1',20),
- ?line {ok,20} = asn1_wrapper:decode('Constraints','X1',Bytes15),
+ range_error(Rules, 'X1', 0),
+ roundtrip('X1', 1),
+ roundtrip('X1', 4),
+ roundtrip('X1', 8),
+ roundtrip('X1', 10),
+ roundtrip('X1', 20),
+ range_error(Rules, 'X1', 21),
+
+ %%==========================================================
+ %% SemiConstrained
+ %%==========================================================
+
+ roundtrip('SemiConstrained', 100),
+ v_roundtrip(Rules, 'SemiConstrained', 100+128),
+ roundtrip('SemiConstrained', 397249742397243),
+ roundtrip('SemiConstrained', 100 + 1 bsl 128*8),
+ roundtrip('SemiConstrained', 100 + 1 bsl 256*8),
+
+ roundtrip('NegSemiConstrained', -128),
+ v_roundtrip(Rules, 'NegSemiConstrained', 0),
+ roundtrip('NegSemiConstrained', -1),
+ roundtrip('NegSemiConstrained', 500),
+
+ roundtrip('SemiConstrainedExt', -65536),
+ roundtrip('SemiConstrainedExt', 0),
+ roundtrip('SemiConstrainedExt', 42),
+ v_roundtrip(Rules, 'SemiConstrainedExt', 42+128),
+ roundtrip('SemiConstrainedExt', 100),
+ roundtrip('SemiConstrainedExt', 47777789),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 128*8),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 256*8),
+
+ roundtrip('NegSemiConstrainedExt', -1023),
+ roundtrip('NegSemiConstrainedExt', -128),
+ roundtrip('NegSemiConstrainedExt', -1),
+ v_roundtrip(Rules, 'NegSemiConstrainedExt', 0),
+ roundtrip('NegSemiConstrainedExt', 500),
+
%%==========================================================
%% SIZE Constraint (Duboisson p. 268)
%% T ::= IA5String (SIZE (1|2, ..., SIZE (1|2|3)))
%% T2 ::= IA5String (SIZE (1|2, ..., 3))
%%==========================================================
- ?line {ok,Bytes16} = asn1_wrapper:encode('Constraints','T',"IA"),
- ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes16),
- ?line {ok,Bytes17} = asn1_wrapper:encode('Constraints','T2',"IA"),
- ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes17).
+ roundtrip('T', "IA"),
+ roundtrip('T', "IAB"),
+ roundtrip('T', "IABC"),
+ roundtrip('T2', "IA"),
+ roundtrip('T2', "IAB"),
+ roundtrip('T2', "IABC"),
+ %%==========================================================
+ %% More SIZE Constraints
+ %%==========================================================
+
+ roundtrip('FixedSize', "0123456789"),
+ roundtrip('FixedSize2', "0123456789"),
+ roundtrip('FixedSize2', "0123456789abcdefghij"),
+
+ range_error(Rules, 'FixedSize', "short"),
+ range_error(Rules, 'FixedSize2', "short"),
+
+ [roundtrip('VariableSize', lists:seq($A, $A+L-1)) ||
+ L <- lists:seq(1, 10)],
+
+ roundtrip_enc('ShorterExt', "a", shorter_ext(Rules, "a")),
+ roundtrip('ShorterExt', "abcde"),
+ roundtrip('ShorterExt', "abcdef"),
+
+ ok.
+
+%% PER: Ensure that if the lower bound is Lb, Lb+16#80 is encoded
+%% in two bytes as 16#0180. (Not in three bytes as 16#010080.)
+v(ber, 'SemiConstrained', 100+128) -> "020200E4";
+v(per, 'SemiConstrained', 100+128) -> "0180";
+v(uper, 'SemiConstrained', 100+128) -> "0180";
+v(ber, 'NegSemiConstrained', 0) -> "020100";
+v(per, 'NegSemiConstrained', 0) -> "0180";
+v(uper, 'NegSemiConstrained', 0) -> "0180";
+v(ber, 'SemiConstrainedExt', 42+128) -> "020200AA";
+v(per, 'SemiConstrainedExt', 42+128) -> "000180";
+v(uper, 'SemiConstrainedExt', 42+128) -> "00C000";
+v(ber, 'NegSemiConstrainedExt', 0) -> "020100";
+v(per, 'NegSemiConstrainedExt', 0) -> "000180";
+v(uper, 'NegSemiConstrainedExt', 0) -> "00C000".
+
+shorter_ext(per, "a") -> <<16#80,16#01,16#61>>;
+shorter_ext(uper, "a") -> <<16#80,16#E1>>;
+shorter_ext(ber, _) -> none.
refed_NNL_name(_Erule) ->
?line {ok,_} = asn1_wrapper:encode('Constraints','AnotherThing',fred),
?line {error,_Reason} =
asn1_wrapper:encode('Constraints','AnotherThing',fred3).
+
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
+ Encoded = roundtrip('Constraints', Type, Value).
+
+roundtrip(Type, Value) ->
+ roundtrip('Constraints', Type, Value).
+
+roundtrip(Module, Type, Value) ->
+ {ok,Encoded} = Module:encode(Type, Value),
+ {ok,Value} = Module:decode(Type, Encoded),
+ Encoded.
+
+roundtrip_enc(Type, Value, Enc) ->
+ Module = 'Constraints',
+ {ok,Encoded} = Module:encode(Type, Value),
+ {ok,Value} = Module:decode(Type, Encoded),
+ case Enc of
+ none -> ok;
+ Encoded -> ok
+ end.
+
+range_error(ber, Type, Value) ->
+ %% BER: Values outside the effective range should be rejected
+ %% on decode.
+ {ok,Encoded} = 'Constraints':encode(Type, Value),
+ {error,{asn1,_}} = 'Constraints':decode(Type, Encoded),
+ ok;
+range_error(Per, Type, Value) when Per =:= per; Per =:= uper ->
+ %% (U)PER: Values outside the effective range should be rejected
+ %% on encode.
+ {error,_} = 'Constraints':encode(Type, Value),
+ ok.
diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl
index 4f67942922..40dbe25015 100644
--- a/lib/asn1/test/testContextSwitchingTypes.erl
+++ b/lib/asn1/test/testContextSwitchingTypes.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -52,22 +52,36 @@ test(Config) ->
check_EXTERNAL({'EXTERNAL',Identif,DVD,DV})->
- ?line ok=check_EXTERNAL_Idef(Identif),
- ?line ok = check_EXTERNAL_DVD(DVD),
- ?line ok = check_EXTERNAL_DV(DV).
-check_EXTERNAL_Idef({Alt,_}) when Alt=='context-negotiation';
- Alt=='presentation-context-id';
- Alt==syntax ->
- ok;
-check_EXTERNAL_Idef(I) ->
- {error,"failed on identification alternative",I}.
-check_EXTERNAL_DVD(DVD) when is_list(DVD) ->
- ok;
-check_EXTERNAL_DVD(asn1_NOVALUE) ->
- ok;
-check_EXTERNAL_DVD(DVD) ->
- {error,"failed on data-value-descriptor alternative",DVD}.
-check_EXTERNAL_DV(DV) when is_list(DV);is_binary(DV) ->
- ok;
-check_EXTERNAL_DV(DV) ->
- {error,"failed on data-value alternative",DV}.
+ %% EXTERNAL in the 1994 format.
+ case Identif of
+ {'context-negotiation',_} ->
+ ok;
+ {'presentation-context-id',Id} ->
+ true = is_integer(Id);
+ {syntax,ObjId} ->
+ check_object_identifier(ObjId)
+ end,
+ check_EXTERNAL_DVD(DVD),
+ check_EXTERNAL_DV(DV);
+check_EXTERNAL({'EXTERNAL',ObjId,IndirectRef,Descriptor,Enc})->
+ %% EXTERNAL in the 1990 format.
+ check_object_identifier(ObjId),
+ true = is_integer(IndirectRef),
+ true = is_binary(Descriptor) orelse is_list(Descriptor),
+ case Enc of
+ {arbitrary,_} -> ok;
+ {'single-ASN1-type',_} -> ok;
+ {'octet-aligned',_} -> ok
+ end.
+
+check_EXTERNAL_DVD(DVD) when is_list(DVD) -> ok;
+check_EXTERNAL_DVD(asn1_NOVALUE) -> ok.
+
+check_EXTERNAL_DV(DV) when is_list(DV); is_binary(DV) -> ok.
+
+check_object_identifier(Tuple) when is_tuple(Tuple) ->
+ %% An OBJECT IDENTIFIER is a tuple with integer elements.
+ case [E || E <- tuple_to_list(Tuple),
+ not is_integer(E)] of
+ [] -> ok
+ end.
diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl
index aa3afbb58f..f17dedc043 100644
--- a/lib/asn1/test/testDeepTConstr.erl
+++ b/lib/asn1/test/testDeepTConstr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -26,69 +26,54 @@
-include_lib("test_server/include/test_server.hrl").
main(_Erule) ->
- Val1 = {'FilterItem',
- {substrings,
- {'FilterItem_substrings',
- {2,6},
- [{initial,"SE"},
- {any,"DK"},
- {final,"N"}]}}},
+ Val1 = {substrings,
+ {'FilterItem_substrings',
+ {2,6},
+ [{initial,"SE"},
+ {any,"DK"},
+ {final,"N"}]}},
- Val2 = {'FilterItem',
- {substrings,
- {'FilterItem_substrings',
- {2,6},
- [{initial,"SE"},
- {any,"DK"},
- {final,"NO"}]}}},
+ Val2 = {substrings,
+ {'FilterItem_substrings',
+ {2,6},
+ [{initial,"SE"},
+ {any,"DK"},
+ {final,"NO"}]}},
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('TConstrChoice','FilterItem',Val1),
-
- ?line {error,Reason} = asn1_wrapper:decode('TConstrChoice','FilterItem',Bytes1),
-
+ {ok,Bytes1} = 'TConstrChoice':encode('FilterItem', Val1),
+ {error,Reason} = asn1_wrapper:decode('TConstrChoice','FilterItem',Bytes1),
io:format("Reason: ~p~n~n",[Reason]),
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('TConstrChoice','FilterItem',Val2),
-
- ?line {ok,Res} = asn1_wrapper:decode('TConstrChoice','FilterItem',Bytes2),
-
-
+ {ok,Bytes2} = 'TConstrChoice':encode('FilterItem', Val2),
+ {ok,Res} = 'TConstrChoice':decode('FilterItem', Bytes2),
%% test of OTP-4248.
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('TConstrChoice','Seq',{'Seq',3,Bytes2}),
-
- ?line {ok,{'Seq',3,Bytes4}} =
- asn1_wrapper:decode('TConstrChoice','Seq',Bytes3),
-
- ?line {ok,Res} = asn1_wrapper:decode('TConstrChoice','FilterItem',Bytes4),
+ {ok,Bytes3} = 'TConstrChoice':encode('Seq', {'Seq',3,Bytes2}),
+ {ok,{'Seq',3,Bytes4}} = 'TConstrChoice':decode('Seq', Bytes3),
+ {ok,Res} = 'TConstrChoice':decode('FilterItem', Bytes4),
%% test of TConstr
- Seq1Val = {'Seq1',{'Seq1_a',12,{2,4}},{'Seq1_b',13,{'Type-object1',14,true}}},
- ?line {ok,Bytes5} =
- asn1_wrapper:encode('TConstr','Seq1',Seq1Val),
-
- ?line {ok,Seq1Val} =
- asn1_wrapper:decode('TConstr','Seq1',Bytes5),
+ Seq1Val = {'Seq1',{'Seq1_a',12,{2,4}},
+ {'Seq1_b',13,{'Type-object1',14,true}}},
+ roundtrip('TConstr', 'Seq1', Seq1Val),
Seq2Val = {'Seq2',123,{'Seq2_content',{2,6,7},
{first,{'Type-object3_first',false,47}},
false}},
-
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('TConstr','Seq2',Seq2Val),
+ roundtrip('TConstr', 'Seq2', Seq2Val),
- ?line {ok,Seq2Val} =
- asn1_wrapper:decode('TConstr','Seq2',Bytes6),
+ roundtrip('TConstr', 'Info', {'Info',{'Info_xyz',{1,2}},1234}),
+
+ roundtrip('TConstr', 'Deeper',
+ {'Deeper',
+ {'Deeper_a',12,
+ {'Deeper_a_s',{2,4},42}},
+ {'Deeper_b',13,{'Type-object1',14,true}}}),
+ ok.
- InfoVal = {'Info',{'Info_xyz',{1,2}},1234},
-
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('TConstr','Info',InfoVal),
- ?line {ok,InfoVal} =
- asn1_wrapper:decode('TConstr','Info',Bytes7).
+roundtrip(M, T, V) ->
+ {ok,E} = M:encode(T, V),
+ {ok,V} = M:decode(T, E),
+ ok.
diff --git a/lib/asn1/test/testDoubleEllipses.erl b/lib/asn1/test/testDoubleEllipses.erl
index 9030a99ce2..1032156b91 100644
--- a/lib/asn1/test/testDoubleEllipses.erl
+++ b/lib/asn1/test/testDoubleEllipses.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. 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
@@ -51,7 +51,7 @@ main(_Rules) ->
b = [1,0,1,0], e = true,
c = false, f = 14, g = 16}),
?line {ok,#'SeqAltV2'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
+ b = <<2#1010:4>>, e = true,
h = asn1_NOVALUE, i = asn1_NOVALUE,
c = false, f = 14, g = 16}} =
asn1_wrapper:decode('DoubleEllipses','SeqAltV2',Bytes3),
@@ -62,7 +62,7 @@ main(_Rules) ->
h = "PS", i = 13,
c = false, f = 14, g = 16}),
?line {ok,#'SeqAlt'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
+ b = <<2#1010:4>>, e = true,
c = false, f = 14, g = 16}} =
asn1_wrapper:decode('DoubleEllipses','SeqAlt',Bytes4),
@@ -83,7 +83,7 @@ main(_Rules) ->
b = [1,0,1,0], e = true,
c = false, f = 14, g = 16}),
?line {ok,#'SetAltV2'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
+ b = <<2#1010:4>>, e = true,
h = asn1_NOVALUE, i = asn1_NOVALUE,
c = false, f = 14, g = 16}} =
asn1_wrapper:decode('DoubleEllipses','SetAltV2',Bytes7),
@@ -94,7 +94,7 @@ main(_Rules) ->
h = "PS", i = 13,
c = false, f = 14, g = 16}),
?line {ok,#'SetAlt'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
+ b = <<2#1010:4>>, e = true,
c = false, f = 14, g = 16}} =
asn1_wrapper:decode('DoubleEllipses','SetAlt',Bytes8),
ok.
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index c97116413a..cbc13ee6da 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. 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
@@ -23,64 +23,71 @@
-include_lib("test_server/include/test_server.hrl").
-main(Rules) when Rules == per; Rules == per_bin; Rules == uper_bin ->
- io:format("main(~p)~n",[Rules]),
- B32=[32],B64=[64],
+main(Rule) when Rule =:= per; Rule =:= uper ->
+ io:format("main(~p)~n",[Rule]),
+
%% ENUMERATED with extensionmark (value is in root set)
- ?line {ok,B32} = asn1_wrapper:encode('EnumExt','Ext',red),
- ?line {ok,red} = asn1_wrapper:decode('EnumExt','Ext',B32),
+ B32 = <<32>>,
+ B32 = roundtrip('Ext', red),
%% ENUMERATED with extensionmark (value is an extensionvalue)
- ?line {ok,Or} = asn1_wrapper:encode('EnumExt','Ext1',orange),
- ?line {ok,orange} = asn1_wrapper:decode('EnumExt','Ext1',Or),
+ Or = roundtrip('Ext1', orange),
%% unknown extensionvalue
- ?line {ok,{asn1_enum,0}} = asn1_wrapper:decode('EnumExt','Ext',Or),
-
+ {ok,{asn1_enum,0}} = asn1_wrapper:decode('EnumExt','Ext',Or),
%% ENUMERATED no extensionmark
- ?line {ok,B64} = asn1_wrapper:encode('EnumExt','Noext',red),
- ?line {ok,red} = asn1_wrapper:decode('EnumExt','Noext',B64),
- ok;
-
-main(ber_bin_v2) ->
- main(ber);
-main(ber_bin) ->
- main(ber);
+ B64 = <<64>>,
+ B64 = roundtrip('Noext', red),
+ common(Rule);
main(ber) ->
io:format("main(ber)~n",[]),
%% ENUMERATED with extensionmark (value is in root set)
- ?line {ok,Bytes1} = asn1_wrapper:encode('EnumExt','Ext',red),
- ?line {ok,red} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1)),
+ roundtrip('Ext', red),
%% value is an extensionvalue
- ?line {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext1',orange),
- ?line {ok,{asn1_enum,7}} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1_1)),
-%% ?line {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext',{asn1_enum,7}),
+ {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext1',orange),
+ {ok,{asn1_enum,7}} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1_1)),
- %% ENUMERATED no extensionmark
- ?line {ok,Bytes2} = asn1_wrapper:encode('EnumExt','Noext',red),
- ?line {ok,red} = asn1_wrapper:decode('EnumExt','Noext',lists:flatten(Bytes2)),
+ %% ENUMERATED no extensionmark
+ roundtrip('Noext', red),
?line {error,{asn1,_}} = (catch asn1_wrapper:encode('EnumExt','Noext',orange)),
-%% ?line {error,{asn1,_}} = (catch asn1_wrapper:encode('EnumExt','Noext',{asn1_enum,7})),
- ok,
%% ENUMERATED with atom 'com'
- ?line {ok,Bytes3} = asn1_wrapper:encode('EnumExt','Globalstate',{'Globalstate',preop}),
- ?line {ok,preop} = asn1_wrapper:decode('EnumExt','Globalstate',
- lists:flatten(Bytes3)),
- ?line {ok,Bytes4} = asn1_wrapper:encode('EnumExt','Globalstate',{'Globalstate',com}),
- ?line {ok,com} = asn1_wrapper:decode('EnumExt','Globalstate',
- lists:flatten(Bytes4)).
-
-
-
-
-
-
-
-
-
-
-
-
-
+ roundtrip('Globalstate', preop),
+ roundtrip('Globalstate', com),
+
+ common(ber).
+
+common(Erule) ->
+ roundtrip('Seq', {'Seq',blue,42}),
+ roundtrip('Seq', {'Seq',red,42}),
+ roundtrip('Seq', {'Seq',green,42}),
+ roundtrip('Seq', {'Seq',orange,47}),
+ roundtrip('Seq', {'Seq',black,4711}),
+ roundtrip('Seq', {'Seq',magenta,4712}),
+
+ [begin
+ S = io_lib:format("e~2.016.0b", [I]),
+ E = list_to_atom(lists:flatten(S)),
+ roundtrip('SeqBig', {'SeqBig',true,E,9357})
+ end || I <- lists:seq(0, 128)],
+
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e40,9357}),
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e80,9357}),
+ ok.
+
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'EnumExt':encode(Type, Value),
+ {ok,Value} = 'EnumExt':decode(Type, Encoded),
+ Encoded.
+
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = roundtrip(Type, Value),
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Value)).
+
+v(ber, {'SeqBig',true,e40,9357}) -> "300A8001 FF810141 8202248D";
+v(ber, {'SeqBig',true,e80,9357}) -> "300B8001 FF810200 81820224 8D";
+v(per, {'SeqBig',true,e40,9357}) -> "E0014002 248D";
+v(per, {'SeqBig',true,e80,9357}) -> "E0018002 248D";
+v(uper, {'SeqBig',true,e40,9357}) -> "E0280044 91A0";
+v(uper, {'SeqBig',true,e80,9357}) -> "E0300044 91A0".
diff --git a/lib/asn1/test/testFragmented.erl b/lib/asn1/test/testFragmented.erl
deleted file mode 100644
index 17995a05bf..0000000000
--- a/lib/asn1/test/testFragmented.erl
+++ /dev/null
@@ -1,42 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2013. 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%
-%%
-%%
--module(testFragmented).
-
--export([main/1]).
-
-main(_Erule) ->
- roundtrip('PDU', {'PDU',1,false,["abc","def"]}),
- B256 = lists:seq(0, 255),
- K1 = lists:duplicate(4, B256),
- K8 = binary_to_list(iolist_to_binary(lists:duplicate(8, K1))),
- roundtrip('PDU', {'PDU',1,false,[K8,K8]}),
- roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8]}),
- roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8]}),
- roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8,K8,K8]}),
- roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8,K8,K8,
- K8,K8,K8,K8,K8,K8]}),
- roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8,K8,K8,
- K8,K8,K8,K8,K8,K8,K8,K8]}),
- ok.
-
-roundtrip(T, V) ->
- {ok,E} = asn1_wrapper:encode('Fragmented', T, V),
- {ok,V} = asn1_wrapper:decode('Fragmented', T, E),
- ok.
diff --git a/lib/asn1/test/testINSTANCE_OF.erl b/lib/asn1/test/testINSTANCE_OF.erl
index 5986a00ec5..ce411beb92 100644
--- a/lib/asn1/test/testINSTANCE_OF.erl
+++ b/lib/asn1/test/testINSTANCE_OF.erl
@@ -26,7 +26,7 @@
main(Erule) ->
?line {ok,Integer} = asn1_wrapper:encode('INSTANCEOF','Int',3),
- Int = wrap(Erule,Integer),
+ Int = list_to_binary(Integer),
ValotherName = {otherName,{'INSTANCE OF',{2,4},Int}},
VallastName1 = {lastName,{'GeneralName_lastName',{2,4},12}},
VallastName2 = {lastName,{'GeneralName_lastName',{2,3,4},
@@ -61,18 +61,3 @@ test_encdec(_Erule,{lastName,{'GeneralName_lastName',{2,3,4},
ok;
test_encdec(Erule,Res) ->
{error,{Erule,Res}}.
-
-wrap(ber,Int) when is_list(Int) ->
- binary_to_list(list_to_binary(Int));
-wrap(per,Int) when is_list(Int) ->
- binary_to_list(list_to_binary(Int));
-wrap(ber_bin,Int) when is_list(Int) ->
- list_to_binary(Int);
-wrap(ber_bin_v2,Int) when is_list(Int) ->
- list_to_binary(Int);
-wrap(per_bin,Int) when is_list(Int) ->
- list_to_binary(Int);
-wrap(uper_bin,Int) when is_list(Int) ->
- list_to_binary(Int);
-wrap(_,Int) ->
- Int.
diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl
index 03e70c730a..c7b19a0cbb 100644
--- a/lib/asn1/test/testInfObj.erl
+++ b/lib/asn1/test/testInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -22,8 +22,6 @@
-export([main/1]).
--include_lib("test_server/include/test_server.hrl").
-
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('InitiatingMessage2',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
@@ -34,22 +32,11 @@ main(_Erule) ->
value=#'Iu-ReleaseCommand'{
first=13,
second=true}},
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('RANAPextract1','InitiatingMessage',Val1),
-
- ?line {ok,{'InitiatingMessage',1,ignore,{'Iu-ReleaseCommand',13,true}}}=
- asn1_wrapper:decode('RANAPextract1','InitiatingMessage',Bytes1),
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('InfObj','InitiatingMessage',Val1),
-
- ?line {ok,Val1} =
- asn1_wrapper:decode('InfObj','InitiatingMessage',Bytes2),
+ roundtrip('RANAPextract1', 'InitiatingMessage', Val1),
+ roundtrip('InfObj', 'InitiatingMessage', Val1),
Val2 = Val1#'InitiatingMessage'{procedureCode=2},
-
- ?line {error,_R1} =
- asn1_wrapper:encode('InfObj','InitiatingMessage',Val2),
+ {error,_R1} = 'InfObj':encode('InitiatingMessage', Val2),
%% Test case for OTP-4275
@@ -59,10 +46,26 @@ main(_Erule) ->
first=13,
second=true}},
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('RANAPextract1','InitiatingMessage2',Val3),
+ roundtrip('RANAPextract1', 'InitiatingMessage2', Val3),
-
- ?line {ok,{'InitiatingMessage2',3,reject,{'Iu-ReleaseCommand',13,true}}}=
- asn1_wrapper:decode('RANAPextract1','InitiatingMessage2',Bytes3).
-
+ roundtrip('InfObj', 'MyPdu', {'MyPdu',42,12,false,"string"}),
+ roundtrip('InfObj', 'MyPdu', {'MyPdu',{'Seq',1023,"hello"},
+ 42,true,"longer string"}),
+ roundtrip('InfObj', 'MyPdu', {'MyPdu',"75712346",43,true,"string"}),
+
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',1,{'CONSTRUCTED-DEFAULT_Type',-2001,true}}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',2,{'CONSTRUCTED-DEFAULT_Type',999,false}}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',3,true}),
+
+ roundtrip('InfObj', 'Seq2',
+ {'Seq2',42,[true,false,false,true],
+ [false,true,false]}).
+
+
+roundtrip(M, T, V) ->
+ {ok,Enc} = M:encode(T, V),
+ {ok,V} = M:decode(T, Enc),
+ ok.
diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl
index e639066246..98408502c6 100644
--- a/lib/asn1/test/testInfObjectClass.erl
+++ b/lib/asn1/test/testInfObjectClass.erl
@@ -37,15 +37,12 @@ main(Rule) ->
{component,'ArgumentType'},
{value,_},_}}} = asn1_wrapper:encode('InfClass','Seq',
{'Seq',12,13,1}),
- Bytes2 =
- if
- Rule==per;Rule==per_bin ->
- [1,12,1,11,1,1];
- Rule == uper_bin ->
- <<1,12,1,11,1,1>>;
- true ->
- [48,9,2,1,12,2,1,11,2,1,1]
- end,
+ Bytes2 = case Rule of
+ ber ->
+ <<48,9,2,1,12,2,1,11,2,1,1>>;
+ _ ->
+ <<1,12,1,11,1,1>>
+ end,
?line {error,{asn1,{'Type not compatible with table constraint',
{{component,_},
{value,_B},_}}}} =
diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl
index 31aa3518f6..8ef7ba3458 100644
--- a/lib/asn1/test/testMergeCompile.erl
+++ b/lib/asn1/test/testMergeCompile.erl
@@ -37,23 +37,17 @@ main(Erule) ->
%% test of RANAP.set.asn1
?line _PIEVal = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,{'CauseRadioNetwork','rab-pre-empted'}}}}],
- ?line PIEVal2 = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,'rab-pre-empted'}}}],
+ PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}],
?line _PEVal = [{'ProtocolExtensionField',[0]}],
%% ?line EncVal = asn1rt_per_v1:encode_integer([],100),
?line EncVal =
case Erule of
per ->
- [1,100];
- per_bin ->
<<1,100>>;
- uper_bin ->
+ uper ->
<<1,100>>;
ber ->
- [2,1,1];
- ber_bin ->
- <<2,1,1>>;
- ber_bin_v2 ->
- <<2,1,1>>
+ [2,1,1]
end,
?line PEVal2 = [{dummy,1,ignore,EncVal},{dummy,2,reject,EncVal}],
?line Val2 =
@@ -76,7 +70,7 @@ main(Erule) ->
mvrasn(Erule) ->
case Erule of
- Ber when Ber == ber;Ber == ber_bin ->
+ ber ->
?line ok = test(isd),
?line ok = test(isd2),
?line ok = test(dsd),
diff --git a/lib/asn1/test/testMultipleLevels.erl b/lib/asn1/test/testMultipleLevels.erl
new file mode 100644
index 0000000000..ff6d023440
--- /dev/null
+++ b/lib/asn1/test/testMultipleLevels.erl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. 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%
+%%
+%%
+
+-module(testMultipleLevels).
+-export([main/1]).
+
+main(_) ->
+ Data = {'Top',{short,"abc"},{long,"a long string follows here"}},
+ {ok,B} = 'MultipleLevels':encode('Top', Data),
+ {ok,Data} = 'MultipleLevels':decode('Top', iolist_to_binary(B)).
diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl
index 4e8381e51e..0f4459f5b2 100644
--- a/lib/asn1/test/testNBAPsystem.erl
+++ b/lib/asn1/test/testNBAPsystem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2013. 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
@@ -142,8 +142,7 @@ audit_req() ->
protocolIEs =
[#'ProtocolIE-Field'{id=114,
criticality=ignore,
- value={'Start-Of-Audit-Sequence-Indicator',
- 'start-of-audit-sequence' }
+ value='start-of-audit-sequence'
}
]
}.
diff --git a/lib/asn1/test/testParamBasic.erl b/lib/asn1/test/testParamBasic.erl
index b5780195b8..a10468d592 100644
--- a/lib/asn1/test/testParamBasic.erl
+++ b/lib/asn1/test/testParamBasic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -40,8 +40,8 @@ main(Rules) ->
?line {ok,Bytes12} =
asn1_wrapper:encode('ParamBasic','T12',
#'T12'{number = 11,
- string = [1,0,1,0,1]}),
- ?line {ok,{'T12',11,[1,0,1,0,1]}} =
+ string = <<2#10101:5>>}),
+ {ok,{'T12',11,<<2#10101:5>>}} =
asn1_wrapper:decode('ParamBasic','T12',Bytes12),
?line {ok,Bytes13} =
@@ -54,8 +54,8 @@ main(Rules) ->
?line {ok,Bytes14} =
asn1_wrapper:encode('ParamBasic','T22',
#'T22'{number = 11,
- string = [1,0,1,0,1]}),
- ?line {ok,{'T22',11,[1,0,1,0,1]}} =
+ string = <<2#10101:5>>}),
+ {ok,{'T22',11,<<2#10101:5>>}} =
asn1_wrapper:decode('ParamBasic','T22',Bytes14),
case Rules of
diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl
index 940b96a339..1dfa52f401 100644
--- a/lib/asn1/test/testParameterizedInfObj.erl
+++ b/lib/asn1/test/testParameterizedInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -89,7 +89,7 @@ param(Erule) ->
ok.
ranap(_Erule) ->
- ?line PIEVal2 = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,'rab-pre-empted'}}}],
+ PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}],
?line Val2 =
#'InitiatingMessage'{procedureCode=1,
criticality=ignore,
@@ -101,7 +101,7 @@ ranap(_Erule) ->
ok.
-open_type(uper_bin,Val) when is_list(Val) ->
+open_type(uper,Val) when is_list(Val) ->
list_to_binary(Val);
open_type(_,Val) ->
Val.
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index 0d4427ba69..a6e68a9fe0 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -30,465 +30,57 @@
-include_lib("test_server/include/test_server.hrl").
bool(Rules) ->
-
- %%==========================================================
- %% Bool ::= BOOLEAN
- %%==========================================================
-
- ?line {ok,Bytes1} = asn1_wrapper:encode('Prim','Bool',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','Bool',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Prim','Bool',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','Bool',lists:flatten(Bytes2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','Bool',517)),
- ok;
- per ->
- ok
- end,
-
-
-
-
-
- %%==========================================================
- %% BoolCon ::= [20] BOOLEAN
- %%==========================================================
-
-
- ?line {ok,BytesCon1} = asn1_wrapper:encode('Prim','BoolCon',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolCon',lists:flatten(BytesCon1)),
-
- ?line {ok,BytesCon2} = asn1_wrapper:encode('Prim','BoolCon',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolCon',lists:flatten(BytesCon2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolCon',517)),
- ok;
- per ->
- ok
- end,
-
-
-
-
-
- %%==========================================================
- %% BoolPri ::= [PRIVATE 21] BOOLEAN
- %%==========================================================
-
- ?line {ok,BytesPri1} = asn1_wrapper:encode('Prim','BoolPri',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolPri',lists:flatten(BytesPri1)),
-
- ?line {ok,BytesPri2} = asn1_wrapper:encode('Prim','BoolPri',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolPri',lists:flatten(BytesPri2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolPri',517)),
- ok;
- per ->
- ok
- end,
-
-
- %%==========================================================
- %% BoolApp ::= [APPLICATION 22] BOOLEAN
- %%==========================================================
-
- ?line {ok,BytesApp1} = asn1_wrapper:encode('Prim','BoolApp',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolApp',lists:flatten(BytesApp1)),
-
- ?line {ok,BytesApp2} = asn1_wrapper:encode('Prim','BoolApp',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolApp',lists:flatten(BytesApp2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolApp',517)),
- ok;
- per ->
- ok
- end,
-
-
- %%==========================================================
- %% BoolExpCon ::= [30] EXPLICIT BOOLEAN
- %%==========================================================
-
- ?line {ok,BytesExpCon1} = asn1_wrapper:encode('Prim','BoolExpCon',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolExpCon',lists:flatten(BytesExpCon1)),
-
- ?line {ok,BytesExpCon2} = asn1_wrapper:encode('Prim','BoolExpCon',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolExpCon',lists:flatten(BytesExpCon2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolExpCon',517)),
- ok;
- per ->
- ok
- end,
-
-
-
- %%==========================================================
- %% BoolExpPri ::= [PRIVATE 31] EXPLICIT BOOLEAN
- %%==========================================================
-
- ?line {ok,BytesExpPri1} = asn1_wrapper:encode('Prim','BoolExpPri',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolExpPri',lists:flatten(BytesExpPri1)),
-
- ?line {ok,BytesExpPri2} = asn1_wrapper:encode('Prim','BoolExpPri',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolExpPri',lists:flatten(BytesExpPri2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolExpPri',517)),
- ok;
- per ->
- ok
- end,
-
-
- %%==========================================================
- %% BoolExpApp ::= [APPLICATION 32] EXPLICIT BOOLEAN
- %%==========================================================
-
- ?line {ok,BytesExpApp1} = asn1_wrapper:encode('Prim','BoolExpApp',true),
- ?line {ok,true} = asn1_wrapper:decode('Prim','BoolExpApp',lists:flatten(BytesExpApp1)),
-
- ?line {ok,BytesExpApp2} = asn1_wrapper:encode('Prim','BoolExpApp',false),
- ?line {ok,false} = asn1_wrapper:decode('Prim','BoolExpApp',lists:flatten(BytesExpApp2)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{encode_boolean,517}}} =
- (catch asn1_wrapper:encode('Prim','BoolExpApp',517)),
- ok;
- per ->
- ok
- end,
-
- ok.
+ Types = ['Bool','BoolCon','BoolPri','BoolApp',
+ 'BoolExpCon','BoolExpPri','BoolExpApp'],
+ [roundtrip(T, V) || T <- Types, V <- [true,false]],
+ case Rules of
+ ber ->
+ [begin
+ {error,{asn1,{encode_boolean,517}}} =
+ (catch 'Prim':encode(T, 517))
+ end || T <- Types],
+ ok;
+ _ ->
+ ok
+ end.
int(Rules) ->
-
-
- %%==========================================================
- %% Int ::= INTEGER
- %%==========================================================
-
- %% test of OTP-2666 encoding should use minimum number of octets x.690 8.3.2
- ?line {ok,Bytes0} = asn1_wrapper:encode('Prim','Int',-128),
- ?line L0 = lists:flatten(Bytes0),
- ?line {ok,-128} = asn1_wrapper:decode('Prim','Int',lists:flatten(L0)),
- case asn1_wrapper:erule(Rules) of
+ %% OTP-2666: encoding should use minimum number of octets; x.690 8.3.2
+ Bytes0 = roundtrip('Int', -128),
+ case Rules of
ber ->
- ?line [_,1,128] = L0;
- per -> ok
+ <<_,1,128>> = Bytes0;
+ _ ->
+ ok
end,
- ?line {ok,Bytes1} = asn1_wrapper:encode('Prim','Int',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Prim','Int',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Prim','Int',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('Prim','Int',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('Prim','Int',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes5)),
-
- ?line {ok,Bytes6} = asn1_wrapper:encode('Prim','Int',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes6)),
-
- ?line {ok,Bytes7} = asn1_wrapper:encode('Prim','Int',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes7)),
-
- ?line {ok,Bytes8} = asn1_wrapper:encode('Prim','Int',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes8)),
-
- ?line {ok,Bytes9} = asn1_wrapper:encode('Prim','Int',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes9)),
-
- ?line {ok,Bytes10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(Bytes10)),
-
-
-
-
-
- %%==========================================================
- %% IntCon ::= [40] INTEGER
- %%==========================================================
-
- ?line {ok,BytesCon1} = asn1_wrapper:encode('Prim','IntCon',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon1)),
-
- ?line {ok,BytesCon2} = asn1_wrapper:encode('Prim','IntCon',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon2)),
-
- ?line {ok,BytesCon3} = asn1_wrapper:encode('Prim','IntCon',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon3)),
-
- ?line {ok,BytesCon4} = asn1_wrapper:encode('Prim','IntCon',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon4)),
-
- ?line {ok,BytesCon5} = asn1_wrapper:encode('Prim','IntCon',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon5)),
-
- ?line {ok,BytesCon6} = asn1_wrapper:encode('Prim','IntCon',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon6)),
-
- ?line {ok,BytesCon7} = asn1_wrapper:encode('Prim','IntCon',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon7)),
-
- ?line {ok,BytesCon8} = asn1_wrapper:encode('Prim','IntCon',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon8)),
-
- ?line {ok,BytesCon9} = asn1_wrapper:encode('Prim','IntCon',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntCon',lists:flatten(BytesCon9)),
-
- ?line {ok,BytesCon10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesCon10)),
-
-
-
- %%==========================================================
- %% IntPri ::= [PRIVATE 41] INTEGER
- %%==========================================================
-
- ?line {ok,BytesPri1} = asn1_wrapper:encode('Prim','IntPri',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri1)),
-
- ?line {ok,BytesPri2} = asn1_wrapper:encode('Prim','IntPri',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri2)),
-
- ?line {ok,BytesPri3} = asn1_wrapper:encode('Prim','IntPri',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri3)),
-
- ?line {ok,BytesPri4} = asn1_wrapper:encode('Prim','IntPri',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri4)),
-
- ?line {ok,BytesPri5} = asn1_wrapper:encode('Prim','IntPri',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri5)),
-
- ?line {ok,BytesPri6} = asn1_wrapper:encode('Prim','IntPri',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri6)),
-
- ?line {ok,BytesPri7} = asn1_wrapper:encode('Prim','IntPri',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri7)),
-
- ?line {ok,BytesPri8} = asn1_wrapper:encode('Prim','IntPri',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri8)),
-
- ?line {ok,BytesPri9} = asn1_wrapper:encode('Prim','IntPri',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntPri',lists:flatten(BytesPri9)),
-
- ?line {ok,BytesPri10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesPri10)),
-
-
-
- %%==========================================================
- %% IntApp ::= [APPLICATION 42] INTEGER
- %%==========================================================
-
- ?line {ok,BytesApp1} = asn1_wrapper:encode('Prim','IntApp',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp1)),
-
- ?line {ok,BytesApp2} = asn1_wrapper:encode('Prim','IntApp',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp2)),
-
- ?line {ok,BytesApp3} = asn1_wrapper:encode('Prim','IntApp',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp3)),
-
- ?line {ok,BytesApp4} = asn1_wrapper:encode('Prim','IntApp',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp4)),
-
- ?line {ok,BytesApp5} = asn1_wrapper:encode('Prim','IntApp',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp5)),
-
- ?line {ok,BytesApp6} = asn1_wrapper:encode('Prim','IntApp',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp6)),
-
- ?line {ok,BytesApp7} = asn1_wrapper:encode('Prim','IntApp',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp7)),
-
- ?line {ok,BytesApp8} = asn1_wrapper:encode('Prim','IntApp',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp8)),
-
- ?line {ok,BytesApp9} = asn1_wrapper:encode('Prim','IntApp',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntApp',lists:flatten(BytesApp9)),
-
- ?line {ok,BytesApp10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesApp10)),
-
-
- %%==========================================================
- %% IntExpCon ::= [50] EXPLICIT INTEGER
- %%==========================================================
-
- ?line {ok,BytesExpCon1} = asn1_wrapper:encode('Prim','IntExpCon',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon1)),
-
- ?line {ok,BytesExpCon2} = asn1_wrapper:encode('Prim','IntExpCon',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon2)),
-
- ?line {ok,BytesExpCon3} = asn1_wrapper:encode('Prim','IntExpCon',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon3)),
-
- ?line {ok,BytesExpCon4} = asn1_wrapper:encode('Prim','IntExpCon',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon4)),
-
- ?line {ok,BytesExpCon5} = asn1_wrapper:encode('Prim','IntExpCon',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon5)),
-
- ?line {ok,BytesExpCon6} = asn1_wrapper:encode('Prim','IntExpCon',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon6)),
-
- ?line {ok,BytesExpCon7} = asn1_wrapper:encode('Prim','IntExpCon',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon7)),
-
- ?line {ok,BytesExpCon8} = asn1_wrapper:encode('Prim','IntExpCon',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon8)),
-
- ?line {ok,BytesExpCon9} = asn1_wrapper:encode('Prim','IntExpCon',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntExpCon',lists:flatten(BytesExpCon9)),
-
- ?line {ok,BytesExpCon10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesExpCon10)),
-
- %%==========================================================
- %% IntExpPri ::= [PRIVATE 51] EXPLICIT INTEGER
- %%==========================================================
-
- ?line {ok,BytesExpPri1} = asn1_wrapper:encode('Prim','IntExpPri',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri1)),
-
- ?line {ok,BytesExpPri2} = asn1_wrapper:encode('Prim','IntExpPri',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri2)),
-
- ?line {ok,BytesExpPri3} = asn1_wrapper:encode('Prim','IntExpPri',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri3)),
-
- ?line {ok,BytesExpPri4} = asn1_wrapper:encode('Prim','IntExpPri',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri4)),
-
- ?line {ok,BytesExpPri5} = asn1_wrapper:encode('Prim','IntExpPri',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri5)),
-
- ?line {ok,BytesExpPri6} = asn1_wrapper:encode('Prim','IntExpPri',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri6)),
-
- ?line {ok,BytesExpPri7} = asn1_wrapper:encode('Prim','IntExpPri',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri7)),
-
- ?line {ok,BytesExpPri8} = asn1_wrapper:encode('Prim','IntExpPri',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri8)),
-
- ?line {ok,BytesExpPri9} = asn1_wrapper:encode('Prim','IntExpPri',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntExpPri',lists:flatten(BytesExpPri9)),
-
- ?line {ok,BytesExpPri10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesExpPri10)),
-
- %%==========================================================
- %% IntExpApp ::= [APPLICATION 52] EXPLICIT INTEGER
- %%==========================================================
-
- ?line {ok,BytesExpApp1} = asn1_wrapper:encode('Prim','IntExpApp',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp1)),
-
- ?line {ok,BytesExpApp2} = asn1_wrapper:encode('Prim','IntExpApp',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp2)),
-
- ?line {ok,BytesExpApp3} = asn1_wrapper:encode('Prim','IntExpApp',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp3)),
-
- ?line {ok,BytesExpApp4} = asn1_wrapper:encode('Prim','IntExpApp',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp4)),
-
- ?line {ok,BytesExpApp5} = asn1_wrapper:encode('Prim','IntExpApp',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp5)),
-
- ?line {ok,BytesExpApp6} = asn1_wrapper:encode('Prim','IntExpApp',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp6)),
-
- ?line {ok,BytesExpApp7} = asn1_wrapper:encode('Prim','IntExpApp',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp7)),
-
- ?line {ok,BytesExpApp8} = asn1_wrapper:encode('Prim','IntExpApp',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp8)),
-
- ?line {ok,BytesExpApp9} = asn1_wrapper:encode('Prim','IntExpApp',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntExpApp',lists:flatten(BytesExpApp9)),
-
- ?line {ok,BytesExpApp10} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesExpApp10)),
-
+ Values = [0,2,3,4,127,128,254,255,256,257,444,
+ 16383,16384,16385,65534,65535,65536,65537,
+ 123456789,12345678901234567890,
+ -1,-2,-3,-4,-100,-127,-255,-256,-257,
+ -1234567890,-2147483648],
+ [roundtrip(T, V) ||
+ T <- ['Int','IntCon','IntPri','IntApp',
+ 'IntExpCon','IntExpPri','IntExpApp'],
+ V <- [1|Values]],
%%==========================================================
%% IntEnum ::= INTEGER {first(1),last(31)}
%%==========================================================
- ?line {ok,BytesEnum1} = asn1_wrapper:encode('Prim','IntEnum',4),
- ?line {ok,4} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum1)),
-
- ?line {ok,BytesEnum2} = asn1_wrapper:encode('Prim','IntEnum',444),
- ?line {ok,444} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum2)),
-
- ?line {ok,BytesEnum3} = asn1_wrapper:encode('Prim','IntEnum',123456789),
- ?line {ok,123456789} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum3)),
-
- ?line {ok,BytesEnum4} = asn1_wrapper:encode('Prim','IntEnum',12345678901234567890),
- ?line {ok,12345678901234567890} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum4)),
-
- ?line {ok,BytesEnum5} = asn1_wrapper:encode('Prim','IntEnum',-100),
- ?line {ok,-100} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum5)),
-
- ?line {ok,BytesEnum6} = asn1_wrapper:encode('Prim','IntEnum',-255),
- ?line {ok,-255} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum6)),
+ [roundtrip('IntEnum', V) || V <- Values],
- ?line {ok,BytesEnum7} = asn1_wrapper:encode('Prim','IntEnum',-256),
- ?line {ok,-256} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum7)),
-
- ?line {ok,BytesEnum8} = asn1_wrapper:encode('Prim','IntEnum',-257),
- ?line {ok,-257} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum8)),
-
- ?line {ok,BytesEnum9} = asn1_wrapper:encode('Prim','IntEnum',-1234567890),
- ?line {ok,-1234567890} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum9)),
-
- ?line {ok,BytesEnum910} = asn1_wrapper:encode('Prim','Int',-2147483648),
- ?line {ok,-2147483648} = asn1_wrapper:decode('Prim','Int',lists:flatten(BytesEnum910)),
-
-
- ?line {ok,BytesEnum10} = asn1_wrapper:encode('Prim','IntEnum',first),
- ?line {ok,first} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum10)),
-
- ?line {ok,BytesEnum11} = asn1_wrapper:encode('Prim','IntEnum',last),
- ?line {ok,last} = asn1_wrapper:decode('Prim','IntEnum',lists:flatten(BytesEnum11)),
-
+ roundtrip('IntEnum', first),
+ roundtrip('IntEnum', last),
+ roundtrip('ASeq', {'ASeq',true,254,false,255,true,256,true,68789}),
+ roundtrip('ASeq', {'ASeq',false,250,true,200,true,199,true,77788}),
+ roundtrip('ASeq', {'ASeq',true,0,false,0,true,0,true,68789}),
ok.
-
enum(Rules) ->
%%==========================================================
@@ -496,108 +88,55 @@ enum(Rules) ->
%% friday(5),saturday(6),sunday(7)}
%%==========================================================
- ?line {ok,BytesEnum1} = asn1_wrapper:encode('Prim','Enum',monday),
- ?line {ok,monday} = asn1_wrapper:decode('Prim','Enum',lists:flatten(BytesEnum1)),
-
- ?line {ok,BytesEnum2} = asn1_wrapper:encode('Prim','Enum',thursday),
- ?line {ok,thursday} = asn1_wrapper:decode('Prim','Enum',lists:flatten(BytesEnum2)),
+ roundtrip('Enum', monday),
+ roundtrip('Enum', thursday),
+ {error,{asn1,{_,4}}} = (catch 'Prim':encode('Enum', 4)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{_,4}}} =
- case catch asn1_wrapper:encode('Prim','Enum',4) of Enum -> Enum end,
- ok;
- per ->
- ?line {error,{asn1,{_,4}}} =
- case catch asn1_wrapper:encode('Prim','Enum',4) of Enum -> Enum end,
- ok
- end,
+ case Rules of
+ Per when Per =:= per; Per =:= uper ->
+ {ok,<<0>>} = 'Prim':encode('SingleEnumVal', true),
+ {ok,<<0>>} = 'Prim':encode('SingleEnumValExt', true);
+ ber ->
+ ok
+ end,
ok.
-
-obj_id(Rules) ->
+obj_id(_) ->
%%==========================================================
%% ObjId ::= OBJECT IDENTIFIER
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('Prim','ObjId',{0,22,3}),
- ?line {ok,{0,22,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Prim','ObjId',{1,39,3}),
- ?line {ok,{1,39,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Prim','ObjId',{2,100,3}),
- ?line {ok,{2,100,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('Prim','ObjId',{2,16303,3}),
- ?line {ok,{2,16303,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes4)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,Bytes5} = asn1_wrapper:encode('Prim','ObjId',{2,16304,3}),
- ?line {ok,{2,16304,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes5)),
- ok;
- per ->
- ?line {ok,Bytes5} = asn1_wrapper:encode('Prim','ObjId',{2,16304,3}),
- ?line {ok,{2,16304,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes5)),
-%% ?line test_server:format("~p~n",[Kurt]),
-% ?line {ok,{2,16304,3}} = asn1_wrapper:decode('Prim','ObjId',lists:flatten(Bytes5)),
- ok
- end,
-
-
-
+ [roundtrip('ObjId', V) ||
+ V <- [{0,22,3},{1,39,3},{2,100,3},{2,16303,3},{2,16304,3}]],
ok.
rel_oid(_Rules) ->
-
%%==========================================================
%% RelOid ::= RELATIVE-OID
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('Prim','RelOid',{0,22,3}),
- ?line {ok,{0,22,3}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Prim','RelOid',{1,39,3}),
- ?line {ok,{1,39,3}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Prim','RelOid',{2,100,3}),
- ?line {ok,{2,100,3}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('Prim','RelOid',{2,16303,3}),
- ?line {ok,{2,16303,3}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('Prim','RelOid',{2,16304,3}),
- ?line {ok,{2,16304,3}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes5)),
-
- ?line {ok,Bytes6} = asn1_wrapper:encode('Prim','RelOid',{8,16304,16#ffff}),
- ?line {ok,{8,16304,16#ffff}} = asn1_wrapper:decode('Prim','RelOid',lists:flatten(Bytes6)),
-
-
-
+ [roundtrip('RelOid', V) ||
+ V <- [{0,22,3},{1,39,3},{2,100,3},{2,16303,3},
+ {2,16304,3},{8,16304,16#ffff}]],
ok.
-
-
-
null(_Rules) ->
%%==========================================================
%% Null ::= NULL
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('Prim','Null',monday),
- ?line {ok,'NULL'} = asn1_wrapper:decode('Prim','Null',lists:flatten(Bytes1)),
-
-
-
-ok.
-
+ {ok,Bytes1} = asn1_wrapper:encode('Prim','Null',monday),
+ {ok,'NULL'} = asn1_wrapper:decode('Prim','Null',lists:flatten(Bytes1)),
+ ok.
+roundtrip(T, V) ->
+ {ok,E} = 'Prim':encode(T, V),
+ {ok,V} = 'Prim':decode(T, E),
+ E.
real(_Rules) ->
%%==========================================================
diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl
index b1c5172b95..e2322c92a9 100644
--- a/lib/asn1/test/testPrimStrings.erl
+++ b/lib/asn1/test/testPrimStrings.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -20,7 +20,6 @@
-module(testPrimStrings).
-export([bit_string/1]).
--export([bit_string_unnamed/1]).
-export([octet_string/1]).
-export([numeric_string/1]).
-export([other_strings/1]).
@@ -37,225 +36,119 @@ bit_string(Rules) ->
%%==========================================================
%% Bs1 ::= BIT STRING
%%==========================================================
+
+ bs_roundtrip('Bs1', 0, <<>>),
+ bs_roundtrip('Bs1', 4, <<1:3>>),
+ bs_roundtrip('Bs1', 15, <<15:4>>),
+ bs_roundtrip('Bs1', 255, <<255:8>>),
+
+ bs_roundtrip('Bs1', 256, [0,0,0,0,0,0,0,0,1]),
+ bs_roundtrip('Bs1', 257, [1,0,0,0,0,0,0,0,1]),
+ bs_roundtrip('Bs1', 444, [0,0,1,1,1,1,0,1,1]),
- ?line {ok,Bytes1} = asn1_wrapper:encode('PrimStrings','Bs1',0),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('PrimStrings','Bs1',4),
- ?line {ok,[0,0,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','Bs1',15),
- ?line {ok,[1,1,1,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','Bs1',255),
- ?line {ok,[1,1,1,1,1,1,1,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','Bs1',256),
- ?line {ok,[0,0,0,0,0,0,0,0,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes5)),
-
- ?line {ok,Bytes6} = asn1_wrapper:encode('PrimStrings','Bs1',257),
- ?line {ok,[1,0,0,0,0,0,0,0,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes6)),
-
- ?line {ok,Bytes7} = asn1_wrapper:encode('PrimStrings','Bs1',444),
- ?line {ok,[0,0,1,1,1,1,0,1,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes7)),
-
- ?line {ok,Bytes8} = asn1_wrapper:encode('PrimStrings','Bs1',12345678901234567890),
- ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes8)),
-
-%% Removed due to beam cannot handle this big integers
-%% Bs1_1 = 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890,
-%% ?line {ok,Bytes9} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_1),
-%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes9)),
-
-%% Bs1_2 = 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890,
-%% ?line {ok,Bytes10} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_2),
-%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes10)),
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('PrimStrings','Bs1',[1,1,1,1,1,1,1,1]),
- ?line {ok,[1,1,1,1,1,1,1,1]} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes11)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings','Bs1',[0,1,0,0,1,0]),
- ?line {ok,[0,1,0,0,1,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('PrimStrings','Bs1',[1,0,0,0,0,0,0,0,0]),
- ?line {ok,[1,0,0,0,0,0,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes13)),
- ok;
- per ->
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings','Bs1',[0,1,0,0,1,0]),
- ?line {ok,[0,1,0,0,1,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('PrimStrings','Bs1',[1,0,0,0,0,0,0,0,0]),
- ?line {ok,[1,0,0,0,0,0,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes13)),
- ok
- end,
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('PrimStrings','Bs1',[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes14)),
-
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line Bytes15 = [35,8,3,2,0,73,3,2,4,32],
- ?line {ok,[0,1,0,0,1,0,0,1,0,0,1,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes15)),
-
- ?line Bytes16 = [35,9,3,2,0,234,3,3,7,156,0],
- ?line {ok,[1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes16)),
-
- ?line Bytes17 = [35,128,3,2,0,73,3,2,4,32,0,0],
- ?line {ok,[0,1,0,0,1,0,0,1,0,0,1,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes17)),
-
- ?line Bytes18 = [35,128,3,2,0,234,3,3,7,156,0,0,0],
- ?line {ok,[1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes18)),
- ok;
-
- per ->
- ok
- end,
+ {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890),
+ {ok,_} = 'PrimStrings':decode('Bs1', Enc1),
+
+ bs_roundtrip('Bs1', [1,1,1,1,1,1,1,1]),
+ bs_roundtrip('Bs1', [0,1,0,0,1,0]),
+ bs_roundtrip('Bs1', [1,0,0,0,0,0,0,0,0]),
+ bs_roundtrip('Bs1', [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
+ case Rules of
+ ber ->
+ bs_decode('Bs1', <<35,8,3,2,0,73,3,2,4,32>>,
+ [0,1,0,0,1,0,0,1,0,0,1,0]),
+ bs_decode('Bs1', <<35,9,3,2,0,234,3,3,7,156,0>>,
+ [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]),
+ bs_decode('Bs1', <<35,128,3,2,0,234,3,3,7,156,0,0,0>>,
+ [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]);
+ _ ->
+ ok
+ end,
%%==========================================================
%% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7))
%%==========================================================
- ?line {ok,Bytes21} = asn1_wrapper:encode('PrimStrings','Bs2',[mo,tu,fr]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('PrimStrings','Bs2',[0,1,1,0,0,1,0]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes22)),
- ok,
-%% skip this because it is wrong
-% ?line case asn1_wrapper:erule(Rules) of
-% ber ->
-% ?line {ok,[mo,tu,fr,su,mo,th]} =
-% asn1_wrapper:decode('PrimStrings','Bs2',[35,8,3,2,0,101,3,2,2,200]),
-
-% ?line {ok,[mo,tu,fr,su,mo,th]} =
-% asn1_wrapper:decode('PrimStrings','Bs2',[35,128,3,2,1,100,3,2,2,200,0,0]),
-% ok;
-
-% per ->
-% ok
-% end,
-
-
-
+ roundtrip('Bs2', [mo,tu,fr]),
+ roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]),
+
%%==========================================================
%% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7))
%%==========================================================
- ?line {ok,Bytes31} = asn1_wrapper:encode('PrimStrings','Bs3',[mo,tu,fr]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('PrimStrings','Bs3',[0,1,1,0,0,1,0]),
- ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes32)),
-
-
+ roundtrip('Bs3', [mo,tu,fr]),
+ bs_roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]),
+
%%==========================================================
%% Bs7 ::= BIT STRING (SIZE (24))
%%==========================================================
- ?line {ok,Bytes33} = asn1_wrapper:encode('PrimStrings','Bs7',53245),
- ?line {ok,[1,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs7',Bytes33),
-
- ?line {ok,Bytes34} = asn1_wrapper:encode('PrimStrings','Bs7',[1,0,1,0]),
- ?line {ok,[1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]} =
- asn1_wrapper:decode('PrimStrings','Bs7',Bytes34),
+ bs_roundtrip('Bs7', 53245,
+ [1,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0]),
+ bs_roundtrip('Bs7', [1,0,1,0],
+ [1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
%%==========================================================
%% BsPri ::= [PRIVATE 61] BIT STRING
%%==========================================================
- ?line {ok,Bytes41} = asn1_wrapper:encode('PrimStrings','BsPri',45),
- ?line {ok,[1,0,1,1,0,1]} = asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('PrimStrings','BsPri',211),
- ?line {ok,[1,1,0,0,1,0,1,1]} = asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes42)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsPri',[223,61,4,5,75,226,96]),
-
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsPri',[255,61,128,3,4,5,75,226,96,0,0]),
-
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsPri',[255,61,9,3,2,0,75,3,3,5,226,96]),
-
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsPri',[255,61,128,3,2,0,75,3,3,5,226,96,0,0]),
- ok;
-
- per ->
- ok
- end,
+ bs_roundtrip('BsPri', 45, [1,0,1,1,0,1]),
+ bs_roundtrip('BsPri', 211, [1,1,0,0,1,0,1,1]),
+ case Rules of
+ ber ->
+ bs_decode('BsPri', <<223,61,4,5,75,226,96>>,
+ [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
+ bs_decode('BsPri', <<255,61,128,3,4,5,75,226,96,0,0>>,
+ [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
+ bs_decode('BsPri', <<255,61,9,3,2,0,75,3,3,5,226,96>>,
+ [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]),
+ bs_decode('BsPri', <<255,61,128,3,2,0,75,3,3,5,226,96,0,0>>,
+ [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]);
+ _ ->
+ ok
+ end,
%%==========================================================
%% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING
%%==========================================================
- ?line {ok,Bytes51} = asn1_wrapper:encode('PrimStrings','BsExpPri',45),
- ?line {ok,[1,0,1,1,0,1]} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes51)),
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('PrimStrings','BsExpPri',211),
- ?line {ok,[1,1,0,0,1,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes52)),
+ bs_roundtrip('BsExpPri', 45, [1,0,1,1,0,1]),
+ bs_roundtrip('BsExpPri', 211, [1,1,0,0,1,0,1,1]),
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,[0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]} =
- asn1_wrapper:decode('PrimStrings','BsExpPri',[255,61,6,3,4,5,75,226,96]),
- ok;
-
- per ->
- ok
- end,
+ case Rules of
+ ber ->
+ bs_decode('BsExpPri', <<255,61,6,3,4,5,75,226,96>>,
+ [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]);
+ _ ->
+ ok
+ end,
%%==========================================================
%% TestS ::= BIT STRING {a(0),b(1)} (SIZE (3..8)), test case for OTP-4353
%%==========================================================
- ?line {ok,Bytes53} = asn1_wrapper:encode('PrimStrings','TestS',[a]),
- ?line {ok,[a]} =
- asn1_wrapper:decode('PrimStrings','TestS',lists:flatten(Bytes53)),
+ roundtrip('TestS', [a]),
%%==========================================================
%% PersonalStatus ::= BIT STRING {married(0),employed(1),
%% veteran(2), collegeGraduate(3)}, test case for OTP-5710
%%==========================================================
- ?line {ok,Bytes54} = asn1_wrapper:encode('BitStr','PersonalStatus',[]),
- ?line {ok,[]} = asn1_wrapper:decode('BitStr','PersonalStatus',Bytes54),
+ {ok,Bytes54} = 'BitStr':encode('PersonalStatus', []),
+ {ok,[]} = 'BitStr':decode('PersonalStatus', Bytes54),
%%==========================================================
%% BS5932 ::= BIT STRING (SIZE (5..MAX))
%% test case for OTP-5932
%%==========================================================
- case asn1_wrapper:erule(Rules) of
+ bs_roundtrip('BSMAX', [1,0,1,0,1]),
+ case Rules of
ber ->
- ?line {error,_} = asn1_wrapper:encode('PrimStrings','BSMAX',
- [1,0,1]),
- ?line {ok,Bytes55} =
- asn1_wrapper:encode('PrimStrings','BSMAX',[1,0,1,0,1]),
- ?line {ok,[1,0,1,0,1]} =
- asn1_wrapper:decode('PrimStrings','BSMAX',Bytes55);
+ {error,_} = 'PrimStrings':encode('BSMAX', [1,0,1]);
_ ->
ok
end,
@@ -274,241 +167,293 @@ bit_string(Rules) ->
end,
BSList255 = BSmaker(BSmaker,0,255,{1,0},[]),
+ bs_roundtrip('BS255', BSList255),
BSList256 = BSmaker(BSmaker,0,256,{1,0},[]),
+ bs_roundtrip('BS256', BSList256),
BSList1024 = BSmaker(BSmaker,0,1024,{1,0},[]),
- ?line {ok,Bytes56} =
- asn1_wrapper:encode('PrimStrings','BS255',BSList255),
- ?line {ok,BSList255} =
- asn1_wrapper:decode('PrimStrings','BS255',Bytes56),
- ?line {ok,Bytes57} =
- asn1_wrapper:encode('PrimStrings','BS256',BSList256),
- ?line {ok,BSList256} =
- asn1_wrapper:decode('PrimStrings','BS256',Bytes57),
- ?line {ok,Bytes58} =
- asn1_wrapper:encode('PrimStrings','BS1024',BSList1024),
- ?line {ok,BSList1024} =
- asn1_wrapper:decode('PrimStrings','BS1024',Bytes58).
-
-
+ bs_roundtrip('BS1024', BSList1024),
-bit_string_unnamed(Rules) ->
- case asn1_wrapper:erule(Rules) of
- ber ->
- ok;
- per ->
- ?line {ok,Bytes1} =
- case catch asn1_wrapper:encode('PrimStrings','TransportLayerAddress',[0,1,1,0]) of
- Ret = {ok,_} -> Ret;
- Err ->
- Config = file:consult(test_config),
- ?line OutDir = ?config(priv_dir,Config),
- MyOut = "/home/bertil/daily_build",
- file:copy(filename:join([OutDir,"PrimStrings.erl"]),
- filename:join([MyOut,"PrimStrings.erl"])),
- file:copy(filename:join([OutDir,"PrimStrings.beam"]),
- filename:join([MyOut,"PrimStrings.beam"])),
- file:copy(code:which(asn1rt_per_v1),
- filename:join([MyOut,"asn1rt_per_v1.beam"])),
- file:copy(filename:join([code:lib_dir(asn1),src,"asn1rt_per_v1.erl"]),filename:join([MyOut,"asn1rt_per_v1.erl"])),
- io:format("Err: ~p~n",[Err]),
- Err
- end,
- ?line {ok,[0,1,1,0]} = asn1_wrapper:decode('PrimStrings','TransportLayerAddress',lists:flatten(Bytes1))
+ bs_roundtrip('TransportLayerAddress', [0,1,1,0]),
+
+ case Rules of
+ ber -> ok;
+ _ -> per_bs_strings()
end.
-octet_string(Rules) ->
+%% The PER encoding rules requires that a BIT STRING with
+%% named positions should never have any trailing zeroes
+%% (except to reach the minimum number of bits as given by
+%% a SIZE constraint).
- %%==========================================================
- %% Os ::= OCTET STRING
- %%==========================================================
+per_bs_strings() ->
+ bs_roundtrip('Bs3', [0,0,1,0,0,0,0], [tu]),
+ bs_roundtrip('Bs3', <<2#0010000:7>>, [tu]),
+ bs_roundtrip('Bs3', {1,<<2#00100000:8>>}, [tu]),
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,"Jones"} =
- asn1_wrapper:decode('PrimStrings','Os',[4,5,16#4A,16#6F,16#6E,16#65,16#73]),
+ bs_roundtrip('Bs4', [0,1,1,0,0,1,0], [mo,tu,fr]),
+ bs_roundtrip('Bs4', <<2#0110010:7>>, [mo,tu,fr]),
+ bs_roundtrip('Bs4', {1,<<2#01100100:8>>}, [mo,tu,fr]),
- ?line {ok,"Jones"} =
- asn1_wrapper:decode('PrimStrings','Os',[36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73]),
-
- ?line {ok,"Jones"} =
- asn1_wrapper:decode('PrimStrings','Os',[36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0]),
- ok;
-
- per ->
- ok
- end,
+ bs_roundtrip('Bs4', [0,1,1,0,0,0,0], [mo,tu]),
+ bs_roundtrip('Bs4', <<2#011:3,0:32>>, [mo,tu]),
+ bs_roundtrip('Bs4', {5,<<2#011:3,0:32,0:5>>}, [mo,tu]),
+ [per_trailing_zeroes(B) || B <- lists:seq(0, 255)],
+ ok.
-
- ?line {ok,Bytes4} =
- asn1_wrapper:encode('PrimStrings','Os',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','Os',lists:flatten(Bytes4)),
+%% Trailing zeroes should be removed from BIT STRINGs with named
+%% bit positions.
- ?line {ok,Bytes5} =
- asn1_wrapper:encode('PrimStrings','OsCon',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsCon',lists:flatten(Bytes5)),
+per_trailing_zeroes(Byte) ->
+ L = lists:reverse(make_bit_list(Byte+16#10000)),
+ L = make_bit_list(Byte+16#10000, []),
+ Pos = positions(L, 0),
+ ExpectedSz = case lists:last(Pos) of
+ su -> 1;
+ {bit,LastBitPos} -> LastBitPos+1
+ end,
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('PrimStrings','OsPri',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsPri',lists:flatten(Bytes6)),
+ %% List of zeroes and ones.
+ named_roundtrip(L, Pos, ExpectedSz),
+ named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz),
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('PrimStrings','OsApp',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsApp',lists:flatten(Bytes7)),
+ %% Bitstrings.
+ Bs = << <<B:1>> || B <- L >>,
+ Sz = bit_size(Bs),
+ named_roundtrip(Bs, Pos, ExpectedSz),
+ Bin = <<Bs:Sz/bits,0:16,0:7>>,
+ named_roundtrip(Bin, Pos, ExpectedSz),
- ?line {ok,Bytes8} =
- asn1_wrapper:encode('PrimStrings','OsExpCon',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsExpCon',lists:flatten(Bytes8)),
+ %% Compact bitstring.
+ named_roundtrip({7,Bin}, Pos, ExpectedSz),
- ?line {ok,Bytes9} =
- asn1_wrapper:encode('PrimStrings','OsExpPri',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsExpPri',lists:flatten(Bytes9)),
+ %% Integer bitstring (obsolete).
+ IntBs = intlist_to_integer(L, 0, 0),
+ named_roundtrip(IntBs, Pos, ExpectedSz),
- ?line {ok,Bytes10} =
- asn1_wrapper:encode('PrimStrings','OsExpApp',[47,23,99,255,1]),
- ?line {ok,[47,23,99,255,1]} = asn1_wrapper:decode('PrimStrings','OsExpApp',lists:flatten(Bytes10)),
+ ok.
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('PrimStrings','Os',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Os',lists:flatten(Bytes11)),
+make_bit_list(0) -> [];
+make_bit_list(B) -> [B band 1|make_bit_list(B bsr 1)].
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('PrimStrings','OsApp',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','OsApp',lists:flatten(Bytes12)),
+make_bit_list(0, Acc) -> Acc;
+make_bit_list(B, Acc) -> make_bit_list(B bsr 1, [B band 1|Acc]).
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('PrimStrings','OsExpApp',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','OsExpApp',lists:flatten(Bytes13)),
+positions([1|T], 0) -> [su|positions(T, 1)];
+positions([1|T], Pos) -> [{bit,Pos}|positions(T, Pos+1)];
+positions([0|T], Pos) -> positions(T, Pos+1);
+positions([], _) -> [].
+intlist_to_integer([B|T], Shift, Acc) ->
+ intlist_to_integer(T, Shift+1, (B bsl Shift) + Acc);
+intlist_to_integer([], _, Acc) -> Acc.
+named_roundtrip(Value, Expected, ExpectedSz) ->
+ M = 'PrimStrings',
+ Type = 'Bs4',
+ {ok,Encoded} = M:encode(Type, Value),
+ {ok,Encoded} = M:encode(Type, Expected),
+ {ok,Expected} = M:decode(Type, Encoded),
+ %% Verify the size in the first byte.
+ <<ExpectedSz:8,_/bits>> = Encoded,
+ ok.
+octet_string(Rules) ->
+ %%==========================================================
+ %% Os ::= OCTET STRING
+ %%==========================================================
+ case Rules of
+ ber ->
+ {ok,"Jones"} =
+ 'PrimStrings':decode('Os', <<4,5,16#4A,16#6F,16#6E,16#65,16#73>>),
+ {ok,"Jones"} =
+ 'PrimStrings':decode('Os', <<36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>),
+ {ok,"Jones"} =
+ 'PrimStrings':decode('Os', <<36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0>>),
+ ok;
+ _ ->
+ ok
+ end,
+
+ roundtrip('Os', [47,23,99,255,1]),
+ roundtrip('OsCon', [47,23,99,255,1]),
+ roundtrip('OsPri', [47,23,99,255,1]),
+ roundtrip('OsApp', [47,23,99,255,1]),
+
+ roundtrip('OsExpCon', [47,23,99,255,1]),
+ roundtrip('OsExpPri', [47,23,99,255,1]),
+ roundtrip('OsExpApp', [47,23,99,255,1]),
+
+ roundtrip('Os', []),
+ roundtrip('OsApp', []),
+ roundtrip('OsExpApp',[]),
OsR = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('PrimStrings','Os',OsR),
- ?line {ok,Os1} = asn1_wrapper:decode('PrimStrings','Os',lists:flatten(Bytes21)),
- ?line Os1 = OsR,
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('PrimStrings','OsCon',OsR),
- ?line {ok,Os2} = asn1_wrapper:decode('PrimStrings','OsCon',lists:flatten(Bytes22)),
- ?line Os2 = OsR,
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('PrimStrings','OsExpApp',OsR),
- ?line {ok,Os3} = asn1_wrapper:decode('PrimStrings','OsExpApp',lists:flatten(Bytes23)),
- ?line Os3 = OsR,
-
+ roundtrip('Os', OsR),
+ roundtrip('OsCon', OsR),
+ roundtrip('OsExpApp', OsR),
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','OsExpApp',[127,62,7,4,5,16#4A,16#6F,16#6E,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','OsExpApp',[127,62,11,36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','OsExpApp',[127,62,13,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','OsExpApp',[127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0]),
- ?line {ok,"JonesJones"} = asn1_wrapper:decode('PrimStrings','OsExpApp',[127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0]),
- ok;
-
- per ->
- ok
- end,
+ case Rules of
+ ber ->
+ {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,7,4,5,16#4A,16#6F,16#6E,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,11,36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,13,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0>>),
+ {ok,"Jones"} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>),
+ {ok,"JonesJones"} = 'PrimStrings':decode('OsExpApp', <<127,62,128,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,36,128,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73,0,0,0,0>>),
+ ok;
+ _->
+ ok
+ end,
+ fragmented_octet_string(Rules),
+
+ S255 = lists:seq(1, 255),
+ Strings = {type,true,"","1","12","345",true,
+ S255,[$a|S255],[$a,$b|S255],397},
+ p_roundtrip('OsFixedStrings', Strings),
+ p_roundtrip('OsFixedStringsExt', Strings),
+ p_roundtrip('OsVarStringsExt', Strings),
+ ShortenedStrings = shorten_by_two(Strings),
+ p_roundtrip('OsFixedStringsExt', ShortenedStrings),
+ p_roundtrip('OsVarStringsExt', ShortenedStrings),
ok.
-
+fragmented_octet_string(Erules) ->
+ K16 = 1 bsl 14,
+ K32 = K16 + K16,
+ K48 = K32 + K16,
+ K64 = K48 + K16,
+ Lens = [0,1,14,15,16,17,127,128,
+ K16-1,K16,K16+1,K16+(1 bsl 7)-1,K16+(1 bsl 7),K16+(1 bsl 7)+1,
+ K32-1,K32,K32+1,K32+(1 bsl 7)-1,K32+(1 bsl 7),K32+(1 bsl 7)+1,
+ K48-1,K48,K48+1,K48+(1 bsl 7)-1,K48+(1 bsl 7),K48+(1 bsl 7)+1,
+ K64-1,K64,K64+1,K64+(1 bsl 7)-1,K64+(1 bsl 7),K64+(1 bsl 7)+1,
+ K64+K16-1,K64+K16,K64+K16+1],
+ Types = ['Os','OsFrag','OsFragExt'],
+ [fragmented_octet_string(Erules, Types, L) || L <- Lens],
+ fragmented_octet_string(Erules, ['FixedOs65536'], 65536),
+ fragmented_octet_string(Erules, ['FixedOs65537'], 65537),
+ fragmented_octet_string(Erules, ['FixedOs65536Ext'], 65536),
+ fragmented_octet_string(Erules, ['FixedOs65537Ext'], 65537),
+
+ %% Make sure that octet alignment works.
+ roundtrip('OsAlignment',
+ {'OsAlignment',false,make_value(70000),true,make_value(66666),
+ false,make_value(65536),42}),
+ roundtrip('OsAlignment',
+ {'OsAlignment',false,make_value(0),true,make_value(0),
+ false,make_value(65536),42}),
+ ok.
+fragmented_octet_string(Erules, Types, L) ->
+ Value = make_value(L),
+ [begin
+ Encoded = enc_frag(Erules, Type, Value),
+ {ok,Value} = 'PrimStrings':decode(Type, Encoded)
+ end || Type <- Types],
+ ok.
-
-numeric_string(Rules) ->
+enc_frag(Erules, Type, Value) ->
+ {ok,Encoded} = 'PrimStrings':encode(Type, Value),
+ case Erules of
+ ber ->
+ Encoded;
+ _ ->
+ %% Validate encoding with our own encoder.
+ Encoded = enc_frag_1(<<>>, list_to_binary(Value))
+ end.
- %%==========================================================
- %% Ns ::= NumericString
- %%==========================================================
+enc_frag_1(Res, Bin0) ->
+ K16 = 1 bsl 14,
+ Sz = byte_size(Bin0),
+ if
+ Sz >= K16 ->
+ F = min(Sz div K16, 4),
+ FragSize = F * K16,
+ <<Frag:FragSize/binary-unit:8,Bin/binary>> = Bin0,
+ enc_frag_1(<<Res/binary,3:2,F:6,Frag/binary>>, Bin);
+ Sz >= 128 ->
+ <<Res/binary,1:1,0:1,Sz:14,Bin0/binary>>;
+ true ->
+ <<Res/binary,0:1,Sz:7,Bin0/binary>>
+ end.
- ?line {ok,BytesNs2} = asn1_wrapper:encode('PrimStrings','Ns',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Ns',lists:flatten(BytesNs2)),
+make_value(L) ->
+ make_value(L, 0, []).
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,BytesNs1} = asn1_wrapper:encode('PrimStrings','Ns',[48,49,32,51,52]),
- ?line {ok,[48,49,32,51,52]} = asn1_wrapper:decode('PrimStrings','Ns',lists:flatten(BytesNs1)),
+make_value(0, _, Acc) ->
+ Acc;
+make_value(N, Byte, Acc) when Byte =< 255 ->
+ make_value(N-1, Byte+7, [Byte|Acc]);
+make_value(N, Byte, Acc) ->
+ make_value(N, Byte band 16#FF, Acc).
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','Ns',[16#12,5,16#4A,16#6F,16#6E,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','Ns',[16#32,9,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','Ns',[16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0]),
- ok;
-
- per ->
- ?line {ok,BytesNs1} = asn1_wrapper:encode('PrimStrings','Ns',[48,49,32,51,52]),
- ?line {ok,"01 34"} = asn1_wrapper:decode('PrimStrings','Ns',lists:flatten(BytesNs1)),
- ok
- end,
-
+numeric_string(Rules) ->
-
%%==========================================================
- %% NsCon ::= [70] NumericString
+ %% Ns ::= NumericString
%%==========================================================
- ?line {ok,BytesNs12} = asn1_wrapper:encode('PrimStrings','NsCon',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','NsCon',lists:flatten(BytesNs12)),
+ roundtrip('Ns', []),
+ roundtrip('Ns', "01 34"),
+ case Rules of
+ ber ->
+ {ok,"Jones"} = 'PrimStrings':decode('Ns',
+ <<16#12,5,16#4A,16#6F,
+ 16#6E,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('Ns',
+ <<16#32,9,18,3,16#4A,16#6F,
+ 16#6E,18,2,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('Ns',
+ <<16#32,128,18,3,16#4A,16#6F,
+ 16#6E,18,2,16#65,16#73,0,0>>),
+ ok;
+ _ ->
+ ok
+ end,
-
+ %%==========================================================
+ %% NsCon ::= [70] NumericString
+ %%==========================================================
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,BytesNs11} = asn1_wrapper:encode('PrimStrings','NsCon',[48,49,32,51,52]),
- ?line {ok,[48,49,32,51,52]} = asn1_wrapper:decode('PrimStrings','NsCon',lists:flatten(BytesNs11)),
-
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsCon',[16#9F,16#46,5,16#4A,16#6F,16#6E,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsCon',[16#BF,16#46,9,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsCon',[16#BF,16#46,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0]),
- ok;
-
- per ->
- ?line {ok,BytesNs11} = asn1_wrapper:encode('PrimStrings','NsCon',[48,49,32,51,52]),
- ?line {ok,"01 34"} = asn1_wrapper:decode('PrimStrings','NsCon',lists:flatten(BytesNs11)),
- ok
- end,
+ roundtrip('NsCon', []),
+ roundtrip('NsCon', "01 34"),
+ case Rules of
+ ber ->
+ {ok,"Jones"} = 'PrimStrings':decode('NsCon', <<16#9F,16#46,5,16#4A,16#6F,16#6E,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('NsCon', <<16#BF,16#46,9,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('NsCon', <<16#BF,16#46,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0>>),
+ ok;
+ _ ->
+ ok
+ end,
-
%%==========================================================
%% NsExpCon ::= [71] EXPLICIT NumericString
%%==========================================================
- ?line {ok,BytesNs22} = asn1_wrapper:encode('PrimStrings','NsExpCon',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','NsExpCon',lists:flatten(BytesNs22)),
-
-
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,BytesNs21} = asn1_wrapper:encode('PrimStrings','NsExpCon',[48,49,32,51,52]),
- ?line {ok,[48,49,32,51,52]} = asn1_wrapper:decode('PrimStrings','NsExpCon',lists:flatten(BytesNs21)),
-
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsExpCon',[16#BF,16#47,16#07,16#12,16#05,16#4A,16#6F,16#6E,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsExpCon',[16#BF,16#47,11,16#32,9,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73]),
- ?line {ok,"Jones"} = asn1_wrapper:decode('PrimStrings','NsExpCon',[16#BF,16#47,128,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,0,0]),
- ?line {ok,"JonesJones"} = asn1_wrapper:decode('PrimStrings','NsExpCon',[16#BF,16#47,26,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0]),
- ?line {ok,"JonesJones"} = asn1_wrapper:decode('PrimStrings','NsExpCon',[16#BF,16#47,128,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,0,0]),
- ok;
-
- per ->
- ?line {ok,BytesNs21} = asn1_wrapper:encode('PrimStrings','NsExpCon',[48,49,32,51,52]),
- ?line {ok,"01 34"} = asn1_wrapper:decode('PrimStrings','NsExpCon',lists:flatten(BytesNs21)),
- ok
- end,
-
- ok.
-
-
+ roundtrip('NsExpCon', []),
+ roundtrip('NsExpCon', "01 34"),
+ case Rules of
+ ber ->
+ {ok,"Jones"} = 'PrimStrings':decode('NsExpCon', <<16#BF,16#47,16#07,16#12,16#05,16#4A,16#6F,16#6E,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('NsExpCon', <<16#BF,16#47,11,16#32,9,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73>>),
+ {ok,"Jones"} = 'PrimStrings':decode('NsExpCon', <<16#BF,16#47,128,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,0,0>>),
+ {ok,"JonesJones"} = 'PrimStrings':decode('NsExpCon', <<16#BF,16#47,26,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0>>),
+ {ok,"JonesJones"} = 'PrimStrings':decode('NsExpCon', <<16#BF,16#47,128,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,16#32,128,18,3,16#4A,16#6F,16#6E,18,2,16#65,16#73,0,0,0,0>>),
+ ok;
+ _ ->
+ ok
+ end.
other_strings(_Rules) ->
@@ -517,48 +462,39 @@ other_strings(_Rules) ->
%% Ps ::= PrintableString
%%==========================================================
- ?line {ok,BytesPs1} = asn1_wrapper:encode('PrimStrings','Ps',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Ps',lists:flatten(BytesPs1)),
-
- ?line {ok,BytesPs2} = asn1_wrapper:encode('PrimStrings','Ps',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Ps',lists:flatten(BytesPs2)),
-
-
+ roundtrip('Ps', [47,23,99,75,47]),
+ roundtrip('Ps', []),
+ roundtrip('Ps11', "*0123456789*"),
%%==========================================================
%% Vis ::= VisibleString
%%==========================================================
- ?line {ok,BytesVis1} = asn1_wrapper:encode('PrimStrings','Vis',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Vis',lists:flatten(BytesVis1)),
-
- ?line {ok,BytesVis2} = asn1_wrapper:encode('PrimStrings','Vis',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Vis',lists:flatten(BytesVis2)),
-
-
+ roundtrip('Vis', [47,23,99,75,47]),
+ roundtrip('Vis', []),
+ roundtrip('Vis8', "7654321001234567"),
+ roundtrip('Vis8', []),
%%==========================================================
%% IA5 ::= IA5String
%%==========================================================
- ?line {ok,BytesIA51} = asn1_wrapper:encode('PrimStrings','IA5',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','IA5',lists:flatten(BytesIA51)),
+ roundtrip('IA5', [47,23,99,75,47]),
+ roundtrip('IA5', []),
- ?line {ok,BytesIA52} = asn1_wrapper:encode('PrimStrings','IA5',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','IA5',lists:flatten(BytesIA52)),
-
-
IA5_1 = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ roundtrip('IA5', IA5_1),
- ?line {ok,BytesIA53} = asn1_wrapper:encode('PrimStrings','IA5',IA5_1),
- ?line {ok,IA5_1r} = asn1_wrapper:decode('PrimStrings','IA5',lists:flatten(BytesIA53)),
- ?line IA5_1 = IA5_1r,
+ roundtrip('IA5Visible', lists:seq($\s, $~)),
-
-
+ S255 = lists:seq(0, 127) ++ lists:seq(1, 127),
+ Strings = {type,true,"","1","12","345",true,"6789",true,
+ S255,[$a|S255],[$a,$b|S255],397},
+ p_roundtrip('IA5FixedStrings', Strings),
+ p_roundtrip('IA5FixedStringsExt', Strings),
+ p_roundtrip('IA5VarStringsExt', Strings),
+ ShortenedStrings = shorten_by_two(Strings),
+ p_roundtrip('IA5VarStringsExt', ShortenedStrings),
ok.
@@ -568,184 +504,115 @@ more_strings(_Rules) ->
%% Ts ::= TeletexString
%%==========================================================
- ?line {ok,BytesTs1} = asn1_wrapper:encode('PrimStrings','Ts',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Ts',lists:flatten(BytesTs1)),
-
- ?line {ok,BytesTs2} = asn1_wrapper:encode('PrimStrings','Ts',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Ts',lists:flatten(BytesTs2)),
-
+ roundtrip('Ts', [47,23,99,75,47]),
+ roundtrip('Ts', []),
%%==========================================================
%% Vxs ::= VideotexString
%%==========================================================
- ?line {ok,BytesVxs1} = asn1_wrapper:encode('PrimStrings','Vxs',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Vxs',lists:flatten(BytesVxs1)),
-
- ?line {ok,BytesVxs2} = asn1_wrapper:encode('PrimStrings','Vxs',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Vxs',lists:flatten(BytesVxs2)),
-
+ roundtrip('Vxs', [47,23,99,75,47]),
+ roundtrip('Vxs', []),
%%==========================================================
%% Grs ::= GraphicString
%%==========================================================
- ?line {ok,BytesGrs1} = asn1_wrapper:encode('PrimStrings','Grs',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Grs',lists:flatten(BytesGrs1)),
-
- ?line {ok,BytesGrs2} = asn1_wrapper:encode('PrimStrings','Grs',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Grs',lists:flatten(BytesGrs2)),
+ roundtrip('Grs',[47,23,99,75,47]),
+ roundtrip('Grs', []),
%%==========================================================
%% ODesc ::= ObjectDescriptor, test case for OTP-4161
%%==========================================================
- ?line {ok,BytesODesc1} = asn1_wrapper:encode('PrimStrings','ODesc',[79,98,106,101,99,116,68,101,115,99,114,105,112,116,111,114]),
- ?line {ok,[79,98,106,101,99,116,68,101,115,99,114,105,112,116,111,114]} =
- asn1_wrapper:decode('PrimStrings','ODesc',lists:flatten(BytesODesc1)),
-
- ?line {ok,BytesODesc2} = asn1_wrapper:encode('PrimStrings','ODesc',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','ODesc',lists:flatten(BytesODesc2)),
+ roundtrip('ODesc', [79,98,106,101,99,116,68,101,115,99,114,
+ 105,112,116,111,114]),
+ roundtrip('ODesc', []),
%%==========================================================
%% Ges ::= GeneralString
%%==========================================================
- ?line {ok,BytesGes1} = asn1_wrapper:encode('PrimStrings','Ges',[47,23,99,75,47]),
- ?line {ok,[47,23,99,75,47]} =
- asn1_wrapper:decode('PrimStrings','Ges',lists:flatten(BytesGes1)),
-
- ?line {ok,BytesGes2} = asn1_wrapper:encode('PrimStrings','Ges',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Ges',lists:flatten(BytesGes2)),
-
- ok.
+ roundtrip('Ges', [47,23,99,75,47]),
+ roundtrip('Ges', []),
+ ok.
universal_string(Rules) ->
-
%%==========================================================
%% Us ::= UniversalString
%%==========================================================
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('PrimStrings','Us',[{47,23,99,47},{0,0,55,66}]),
- ?line {ok,[{47,23,99,47},{0,0,55,66}]} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('PrimStrings','Us',[{47,23,99,255},{0,0,0,201}]),
- ?line {ok,[{47,23,99,255},201]} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','Us',"Universal String"),
- ?line {ok,"Universal String"} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','Us',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','Us',lists:flatten(Bytes4)),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','Us',[{47,23,99,47}]),
- ?line {ok,[{47,23,99,47}]} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten(Bytes5)),
-
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
+ roundtrip('Us', [{47,23,99,47},{0,0,55,66}]),
+ roundtrip('Us',
+ [{47,23,99,255},{0,0,0,201}],
+ [{47,23,99,255},201]),
+ roundtrip('Us', "Universal String"),
+ roundtrip('Us', []),
+ roundtrip('Us', [{47,23,99,47}]),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten([16#3C,12,28,4,47,23,99,255,28,4,0,0,2,201])),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','Us',lists:flatten([16#3C,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0]));
+ case Rules of
+ ber ->
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('Us', <<16#3C,12,28,4,47,23,99,255,28,4,0,0,2,201>>),
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('Us', <<16#3C,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0>>);
_ ->
ok
end,
Us1 = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
- ?line {ok,Bytes15} = asn1_wrapper:encode('PrimStrings','IA5',Us1),
- ?line {ok,Us1r} = asn1_wrapper:decode('PrimStrings','IA5',lists:flatten(Bytes15)),
- ?line Us1 = Us1r,
-
+ roundtrip('IA5', Us1),
%%==========================================================
%% UsCon ::= [70] UniversalString
%%==========================================================
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('PrimStrings','UsCon',[{47,23,99,255},{0,0,2,201}]),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('PrimStrings','UsCon',[{47,23,99,255},{0,0,0,201}]),
- ?line {ok,[{47,23,99,255},201]} =
- asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten(Bytes12)),
+ roundtrip('UsCon', [{47,23,99,255},{0,0,2,201}]),
+ roundtrip('UsCon',
+ [{47,23,99,255},{0,0,0,201}],
+ [{47,23,99,255},201]),
+ roundtrip('UsCon', "Universal String"),
+ roundtrip('UsCon', []),
- ?line {ok,Bytes13} = asn1_wrapper:encode('PrimStrings','UsCon',"Universal String"),
- ?line {ok,"Universal String"} =
- asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('PrimStrings','UsCon',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten(Bytes14)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten([16#BF,16#46,12,28,4,47,23,99,255,28,4,0,0,2,201])),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsCon',lists:flatten([16#BF,16#46,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0]));
- _ -> ok
- end,
-
+ case Rules of
+ ber ->
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('UsCon', <<16#BF,16#46,12,28,4,47,23,99,255,28,4,0,0,2,201>>),
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('UsCon', <<16#BF,16#46,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0>>);
+ _ ->
+ ok
+ end,
%%==========================================================
%% UsExpCon ::= [71] EXPLICIT UniversalString
%%==========================================================
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('PrimStrings','UsExpCon',[{47,23,99,255},{0,0,2,201}]),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('PrimStrings','UsExpCon',[{47,23,99,255},{0,0,0,201}]),
- ?line {ok,[{47,23,99,255},201]} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('PrimStrings','UsExpCon',"Universal String"),
- ?line {ok,"Universal String"} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten(Bytes23)),
+ roundtrip('UsExpCon', [{47,23,99,255},{0,0,2,201}]),
+ roundtrip('UsExpCon',
+ [{47,23,99,255},{0,0,0,201}],
+ [{47,23,99,255},201]),
+ roundtrip('UsExpCon', "Universal String"),
+ roundtrip('UsExpCon', []),
- ?line {ok,Bytes24} =
- asn1_wrapper:encode('PrimStrings','UsExpCon',[]),
- ?line {ok,[]} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten(Bytes24)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten([16#BF,16#47,14,60,12,28,4,47,23,99,255,28,4,0,0,2,201])),
- ?line {ok,[{47,23,99,255},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','UsExpCon',lists:flatten([16#BF,16#47,16,60,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0]));
- _ -> ok
- end,
-
-
-ok.
-
-
-
+ case Rules of
+ ber ->
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('UsExpCon', <<16#BF,16#47,14,60,12,28,4,47,23,99,255,28,4,0,0,2,201>>),
+ {ok,[{47,23,99,255},{0,0,2,201}]} =
+ 'PrimStrings':decode('UsExpCon', <<16#BF,16#47,16,60,16#80,28,4,47,23,99,255,28,4,0,0,2,201,0,0>>);
+ _ ->
+ ok
+ end.
bmp_string(_Rules) ->
@@ -754,35 +621,18 @@ bmp_string(_Rules) ->
%% BMP ::= BMPString
%%==========================================================
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('PrimStrings','BMP',[{0,0,99,48},{0,0,2,201}]),
- ?line {ok,[{0,0,99,48},{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','BMP',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('PrimStrings','BMP',[{0,0,0,48},{0,0,2,201}]),
- ?line {ok,[48,{0,0,2,201}]} =
- asn1_wrapper:decode('PrimStrings','BMP',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','BMP',"BMP String"),
- ?line {ok,"BMP String"} =
- asn1_wrapper:decode('PrimStrings','BMP',lists:flatten(Bytes3)),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','BMP',[]),
- ?line {ok,[]} = asn1_wrapper:decode('PrimStrings','BMP',lists:flatten(Bytes4)),
-
+ roundtrip('BMP', [{0,0,99,48},{0,0,2,201}]),
+ roundtrip('BMP',
+ [{0,0,0,48},{0,0,2,201}],
+ [48,{0,0,2,201}]),
+ roundtrip('BMP', "BMP String"),
+ roundtrip('BMP', []),
BMP1 = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
- ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','BMP',BMP1),
- ?line {ok,BMP1r} = asn1_wrapper:decode('PrimStrings','BMP',lists:flatten(Bytes5)),
- ?line BMP1 = BMP1r,
-
+ roundtrip('BMP', BMP1),
ok.
-
-
-
times(_Rules) ->
@@ -790,35 +640,17 @@ times(_Rules) ->
%% Gt ::= GeneralizedTime
%%==========================================================
- ?line {ok,Bytes1} = asn1_wrapper:encode('PrimStrings','Gt',"19970923110723.2"),
- ?line {ok,"19970923110723.2"} =
- asn1_wrapper:decode('PrimStrings','Gt',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('PrimStrings','Gt',"19970923110723.2Z"),
- ?line {ok,"19970923110723.2Z"} =
- asn1_wrapper:decode('PrimStrings','Gt',lists:flatten(Bytes2)),
+ roundtrip('Gt', "19970923110723.2"),
+ roundtrip('Gt', "19970923110723.2Z"),
+ roundtrip('Gt', "19970923110723.2-0500"),
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','Gt',"19970923110723.2-0500"),
- ?line {ok,"19970923110723.2-0500"} =
- asn1_wrapper:decode('PrimStrings','Gt',lists:flatten(Bytes3)),
-
-
-
-
-
-
%%==========================================================
%% UTC ::= UTCTime
%%==========================================================
- ?line {ok,Bytes11} = asn1_wrapper:encode('PrimStrings','UTC',"9709211107Z"),
- ?line {ok,"9709211107Z"} =
- asn1_wrapper:decode('PrimStrings','UTC',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings','UTC',"9709211107-0500"),
- ?line {ok,"9709211107-0500"} =
- asn1_wrapper:decode('PrimStrings','UTC',lists:flatten(Bytes12)),
+ roundtrip('UTC', "9709211107Z"),
+ roundtrip('UTC', "9709211107-0500"),
ok.
@@ -829,91 +661,84 @@ utf8_string(_Rules) ->
%% UTF ::= UTF8String
%%==========================================================
- %% test values in all ranges
-
- ValLbR1 = [16#00],
- ValUbR1 = [16#7f],
- ValLbR2 = [16#80],
- ValUbR2 = [16#7ff],
- ValLbR3 = [16#800],
- ValUbR3 = [16#ffff],
- ValLbR4 = [16#10000],
- ValUbR4 = [16#1fffff],
- ValLbR5 = [16#200000],
- ValUbR5 = [16#3ffffff],
- ValLbR6 = [16#4000000],
- ValUbR6 = [16#7fffffff],
-
- ?line {ok,UTF8L1} = asn1rt:utf8_list_to_binary(ValLbR1),
- ?line {ok,Bytes1} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L1),
- ?line {ok,Bin1} = asn1_wrapper:decode('PrimStrings','UTF',Bytes1),
- ?line {ok,ValLbR1} = wrapper_utf8_binary_to_list(Bin1),
-
- ?line {ok,UTF8L2} = asn1rt:utf8_list_to_binary(ValUbR1),
- ?line {ok,Bytes2} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L2),
- ?line {ok,Bin2} = asn1_wrapper:decode('PrimStrings','UTF',Bytes2),
- ?line {ok,ValUbR1} = wrapper_utf8_binary_to_list(Bin2),
-
- ?line {ok,UTF8L3} = asn1rt:utf8_list_to_binary(ValLbR2),
- ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L3),
- ?line {ok,Bin3} = asn1_wrapper:decode('PrimStrings','UTF',Bytes3),
- ?line {ok,ValLbR2} = wrapper_utf8_binary_to_list(Bin3),
-
- ?line {ok,UTF8L4} = asn1rt:utf8_list_to_binary(ValUbR2),
- ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L4),
- ?line {ok,Bin4} = asn1_wrapper:decode('PrimStrings','UTF',Bytes4),
- ?line {ok,ValUbR2} = wrapper_utf8_binary_to_list(Bin4),
-
- ?line {ok,UTF8L5} = asn1rt:utf8_list_to_binary(ValLbR3),
- ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L5),
- ?line {ok,Bin5} = asn1_wrapper:decode('PrimStrings','UTF',Bytes5),
- ?line {ok,ValLbR3} = wrapper_utf8_binary_to_list(Bin5),
-
- ?line {ok,UTF8L6} = asn1rt:utf8_list_to_binary(ValUbR3),
- ?line {ok,Bytes6} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L6),
- ?line {ok,Bin6} = asn1_wrapper:decode('PrimStrings','UTF',Bytes6),
- ?line {ok,ValUbR3} = wrapper_utf8_binary_to_list(Bin6),
-
- ?line {ok,UTF8L7} = asn1rt:utf8_list_to_binary(ValLbR4),
- ?line {ok,Bytes7} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L7),
- ?line {ok,Bin7} = asn1_wrapper:decode('PrimStrings','UTF',Bytes7),
- ?line {ok,ValLbR4} = wrapper_utf8_binary_to_list(Bin7),
-
- ?line {ok,UTF8L8} = asn1rt:utf8_list_to_binary(ValUbR4),
- ?line {ok,Bytes8} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L8),
- ?line {ok,Bin8} = asn1_wrapper:decode('PrimStrings','UTF',Bytes8),
- ?line {ok,ValUbR4} = wrapper_utf8_binary_to_list(Bin8),
-
- ?line {ok,UTF8L9} = asn1rt:utf8_list_to_binary(ValLbR5),
- ?line {ok,Bytes9} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L9),
- ?line {ok,Bin9} = asn1_wrapper:decode('PrimStrings','UTF',Bytes9),
- ?line {ok,ValLbR5} = wrapper_utf8_binary_to_list(Bin9),
-
- ?line {ok,UTF8L10} = asn1rt:utf8_list_to_binary(ValUbR5),
- ?line {ok,Bytes10} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L10),
- ?line {ok,Bin10} = asn1_wrapper:decode('PrimStrings','UTF',Bytes10),
- ?line {ok,ValUbR5} = wrapper_utf8_binary_to_list(Bin10),
-
- ?line {ok,UTF8L11} = asn1rt:utf8_list_to_binary(ValLbR6),
- ?line {ok,Bytes11} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L11),
- ?line {ok,Bin11} = asn1_wrapper:decode('PrimStrings','UTF',Bytes11),
- ?line {ok,ValLbR6} = wrapper_utf8_binary_to_list(Bin11),
-
- ?line {ok,UTF8L12} = asn1rt:utf8_list_to_binary(ValUbR6),
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L12),
- ?line {ok,Bin12} = asn1_wrapper:decode('PrimStrings','UTF',Bytes12),
- ?line {ok,ValUbR6} = wrapper_utf8_binary_to_list(Bin12),
-
- LVal = ValLbR1++ValUbR1++ValLbR2++ValUbR2++ValLbR3++ValUbR3++
- ValLbR4++ValUbR4++ValLbR5++ValUbR5++ValLbR6++ValUbR6,
- LongVal = LVal++LVal++LVal++LVal++LVal++LVal++LVal++"hello",
-
- ?line {ok,UTF8L13} = asn1rt:utf8_list_to_binary(LongVal),
- ?line {ok,Bytes13} = asn1_wrapper:encode('PrimStrings','UTF',UTF8L13),
- ?line {ok,Bin13} = asn1_wrapper:decode('PrimStrings','UTF',Bytes13),
- ?line {ok,LongVal} = wrapper_utf8_binary_to_list(Bin13).
-
-wrapper_utf8_binary_to_list(L) when is_list(L) ->
- asn1rt:utf8_binary_to_list(list_to_binary(L));
-wrapper_utf8_binary_to_list(B) ->
- asn1rt:utf8_binary_to_list(B).
+ AllRanges = [16#00,
+ 16#7f,
+ 16#80,
+ 16#7ff,
+ 16#800,
+ 16#ffff,
+ 16#10000,
+ 16#1fffff,
+ 16#200000,
+ 16#3ffffff,
+ 16#4000000,
+ 16#7fffffff],
+ [begin
+ {ok,UTF8} = asn1rt:utf8_list_to_binary([Char]),
+ {ok,[Char]} = asn1rt:utf8_binary_to_list(UTF8),
+ roundtrip('UTF', UTF8)
+ end || Char <- AllRanges],
+
+ {ok,UTF8} = asn1rt:utf8_list_to_binary(AllRanges),
+ {ok,AllRanges} = asn1rt:utf8_binary_to_list(UTF8),
+ roundtrip('UTF', UTF8),
+ ok.
+
+
+shorten_by_two(Tuple) ->
+ L = [case E of
+ [_,_|T] -> T;
+ _ -> E
+ end || E <- tuple_to_list(Tuple)],
+ list_to_tuple(L).
+
+p_roundtrip(Type, Value0) ->
+ Value = setelement(1, Value0, Type),
+ roundtrip(Type, Value).
+
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'PrimStrings':encode(Type, Value),
+ {ok,Value} = 'PrimStrings':decode(Type, Encoded),
+ ok.
+
+roundtrip(Type, Value, Expected) ->
+ {ok,Encoded} = 'PrimStrings':encode(Type, Value),
+ {ok,Expected} = 'PrimStrings':decode(Type, Encoded),
+ ok.
+
+bs_roundtrip(Type, Value) ->
+ bs_roundtrip(Type, Value, Value).
+
+bs_roundtrip(Type, Value, Expected) ->
+ M = 'PrimStrings',
+ {ok,Encoded} = M:encode(Type, Value),
+ {ok,Encoded} = M:encode(Type, Expected),
+ case M:decode(Type, Encoded) of
+ {ok,Expected} ->
+ ok;
+ {ok,Other} ->
+ Expected = convert(Other, Expected)
+ end.
+
+bs_decode(Type, Encoded, Expected) ->
+ M = 'PrimStrings',
+ case M:decode(Type, Encoded) of
+ {ok,Expected} ->
+ ok;
+ {ok,Other} ->
+ Expected = convert(Other, Expected)
+ end.
+
+convert(Val, E) when is_bitstring(Val) ->
+ convert_1(Val, E);
+convert({Unused,Bin}, E) ->
+ Sz = bit_size(Bin) - Unused,
+ <<Val:Sz/bitstring,_:Unused>> = Bin,
+ convert_1(Val, E);
+convert(List, E) when is_list(List) ->
+ Val = << <<B:1>> || B <- List >>,
+ convert_1(Val, E).
+
+convert_1(Val, E) when is_list(E) ->
+ [B || <<B:1>> <= Val];
+convert_1(Val, E) when is_bitstring(E) -> Val.
diff --git a/lib/asn1/test/testSSLspecs.erl b/lib/asn1/test/testSSLspecs.erl
index 51ef134e5f..08da92243e 100644
--- a/lib/asn1/test/testSSLspecs.erl
+++ b/lib/asn1/test/testSSLspecs.erl
@@ -20,7 +20,7 @@
-module(testSSLspecs).
--export([compile/2,run/1,compile_inline/2,run_inline/1]).
+-export([compile/2,run/1,compile_combined/2,run_combined/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -42,15 +42,13 @@ compile(Config, Options) ->
asn1_test_lib:compile_all(["PKIX1Explicit93", "PKIX1Implicit93"],
Config, NewOptions).
-compile_inline(Config, Rule) when Rule == ber_bin; Rule == ber_bin_v2 ->
+compile_combined(Config, ber=Rule) ->
DataDir = ?config(data_dir, Config),
CaseDir = ?config(case_dir, Config),
Options = [{i, CaseDir}, {i, DataDir}, Rule,
- der, compact_bit_string, optimize, asn1config, inline],
- ok = remove_db_file_inline(CaseDir),
- asn1_test_lib:compile("OTP-PKIX.set.asn", Config, Options);
-compile_inline(_Config, _Rule) ->
- ok.
+ der, compact_bit_string, asn1config],
+ ok = remove_db_files_combined(CaseDir),
+ asn1_test_lib:compile("OTP-PKIX.set.asn", Config, Options).
remove_db_files(Dir) ->
?line ok = remove_db_file(Dir ++ "PKIX1Explicit93.asn1db"),
@@ -65,7 +63,7 @@ remove_db_file(File) ->
Err
end.
-remove_db_file_inline(Dir) ->
+remove_db_files_combined(Dir) ->
?line ok = remove_db_file(Dir ++ "OTP-PKIX.asn1db"),
?line ok = remove_db_file(Dir ++ "SSL-PKIX.asn1db"),
?line ok = remove_db_file(Dir ++ "PKIXAttributeCertificate.asn1db"),
@@ -73,15 +71,12 @@ remove_db_file_inline(Dir) ->
?line ok = remove_db_file(Dir ++ "PKIX1Explicit88.asn1db"),
?line ok = remove_db_file(Dir ++ "PKIX1Implicit88.asn1db").
-run(BER) when BER==ber_bin;BER==ber_bin_v2 ->
- run1(1);
-run(_) ->
- ok.
+run(ber) ->
+ run1(1).
run1(6) ->
?line f1(6),
?line f2(6),
-%% ?line transform3(ex(7)),
?line transform4(ex(7));
run1(N) ->
?line f1(N),
@@ -100,20 +95,20 @@ transform1(ATAV) ->
?line {ok, ATAVEnc} = 'PKIX1Explicit88':encode('AttributeTypeAndValue',
ATAV),
?line {ok, _ATAVDec} = 'SSL-PKIX':decode('AttributeTypeAndValue',
- list_to_binary(ATAVEnc)).
+ ATAVEnc).
transform2(ATAV) ->
?line {ok, ATAVEnc} = 'PKIX1Explicit88':encode('AttributeTypeAndValue',
ATAV),
?line {ok, _ATAVDec} = 'PKIX1Explicit88':decode('AttributeTypeAndValue',
- list_to_binary(ATAVEnc)).
+ ATAVEnc).
transform4(ATAV) ->
?line {ok, ATAVEnc} = 'PKIX1Explicit88':encode('Attribute',
ATAV),
?line {ok, _ATAVDec} = 'PKIX1Explicit88':decode('Attribute',
- list_to_binary(ATAVEnc)).
+ ATAVEnc).
ex(1) ->
@@ -146,12 +141,10 @@ ex(7) ->
{1,2,840,113549,1,9,1},
[[19,5,111,116,112,67,65]]}.
-run_inline(Rule) when Rule==ber_bin;Rule==ber_bin_v2 ->
+run_combined(ber) ->
Cert = cert(),
?line {ok,{'CertificatePKIX1Explicit88',{Type,UnDec},_,_}} = 'OTP-PKIX':decode_TBSCert_exclusive(Cert),
?line {ok,_} = 'OTP-PKIX':decode_part(Type,UnDec),
- ok;
-run_inline(_) ->
ok.
cert() ->
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index 7c77ab87e9..b996634996 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -20,7 +20,7 @@
-module(testSeqExtension).
-include("External.hrl").
--export([main/1]).
+-export([main/3]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,70 +28,102 @@
-record('SeqExt2',{bool, int}).
-record('SeqExt3',{bool, int}).
-record('SeqExt4',{bool, int}).
-
-
-main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqExtension','SeqExt1',#'SeqExt1'{}),
- ?line {ok,{'SeqExt1'}} =
- asn1_wrapper:decode('SeqExtension','SeqExt1',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{bool = true,int = 99}),
- ?line {ok,{'SeqExt2',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{int = 99,bool = true}),
- ?line {ok,{'SeqExt2',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqExtension','SeqExt3',#'SeqExt3'{bool = true,int = 99}),
- ?line {ok,{'SeqExt3',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqExtension','SeqExt3',#'SeqExt3'{int = 99,bool = true}),
- ?line {ok,{'SeqExt3',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqExtension','SeqExt4',#'SeqExt4'{bool = true,int = 99}),
- ?line {ok,{'SeqExt4',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt4',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SeqExtension','SeqExt4',#'SeqExt4'{int = 99,bool = true}),
- ?line {ok,{'SeqExt4',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt4',lists:flatten(Bytes42)),
-
-
- % test of extension , not ready
-
- ?line {ok,BytesX11} =
- asn1_wrapper:encode('SeqExtension','SeqExt1',#'SeqExt1'{}),
- ?line {ok,{'SeqExt1'}} =
- asn1_wrapper:decode('SeqExtension','SeqExt1',lists:flatten(BytesX11)),
-
- ?line {ok,BytesX21} =
- asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{bool = true,int = 99}),
- ?line {ok,{'SeqExt2',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(BytesX21)),
-
- ?line {ok,BytesX22} =
- asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{int = 99,bool = true}),
- ?line {ok,{'SeqExt2',true,99}} =
- asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(BytesX22)),
-
-
-
-
-
+-record('SeqExt5',{name, shoesize}).
+-record('SeqExt6',{i1,i2,i3,i4,i5,i6,i7}).
+-record('SuperSeq',{s1,s2,s3,s4,s5,s6,i}).
+
+main(Erule, DataDir, Opts) ->
+ roundtrip('SeqExt1', #'SeqExt1'{}),
+
+ roundtrip('SeqExt2', #'SeqExt2'{bool=true,int=99}),
+ roundtrip('SeqExt2', #'SeqExt2'{bool=false,int=42}),
+
+ roundtrip('SeqExt3', #'SeqExt3'{bool=true,int=-77777}),
+ roundtrip('SeqExt3', #'SeqExt3'{bool=false,int=-42000}),
+
+ roundtrip('SeqExt4', #'SeqExt4'{bool=true,int=12345}),
+ roundtrip('SeqExt4', #'SeqExt4'{bool=false,int=123456}),
+
+ roundtrip('SeqExt5', #'SeqExt5'{name="Arne",shoesize=47}),
+
+ %% Encode a value with this version of the specification.
+ BigInt = 128638468966,
+ SuperSeq = #'SuperSeq'{s1=#'SeqExt1'{},
+ s2=#'SeqExt2'{bool=true,int=2345},
+ s3=#'SeqExt3'{bool=false,int=17},
+ s4=#'SeqExt4'{bool=true,int=38739739},
+ s5=#'SeqExt5'{name="Arne",shoesize=47},
+ s6=#'SeqExt6'{i1=531,i2=601,i3=999,
+ i4=777,i5=11953,
+ i6=13553,i7=77777},
+ i=BigInt
+ },
+ {ok,SuperSeqEnc} = 'SeqExtension':encode('SuperSeq', SuperSeq),
+ {ok,SuperSeq} = 'SeqExtension':decode('SuperSeq', SuperSeqEnc),
+
+ %% Remove all extensions from the ASN.1 specification and compile it.
+ CaseDir = filename:dirname(code:which('SeqExtension')),
+ Asn1SrcBase = "SeqExtension.asn1",
+ Asn1SrcFile0 = filename:join(DataDir, Asn1SrcBase),
+ {ok,Src0} = file:read_file(Asn1SrcFile0),
+ %% Remove all declarations following "...," up to the end
+ %% of the SEQUENCE.
+ Src1 = re:replace(Src0, "[.][.][.],[^}]*", "...\n",
+ [global,{return,binary}]),
+ %% Remove the last double bracket group in the SEQUENCE.
+ Src = re:replace(Src1, ",\\s*\\[\\[.*?\\]\\]\\s*\\}", "\n}",
+ [global,{return,binary}]),
+ io:format("~s\n\n", [Src]),
+ Asn1SrcFile = filename:join(CaseDir, Asn1SrcBase),
+ ok = file:write_file(Asn1SrcFile, Src),
+ ok = asn1ct:compile(Asn1SrcFile,
+ [{i,DataDir},{outdir,CaseDir}|Opts]),
+
+ %% Decode the encoded sequence with the version of the spec
+ %% with no extensions following the extension marks
+ %% (except in SeqExt6). The integer 'i' at the end
+ %% of the sequence must still be the correct integer (otherwise
+ %% some extension has not been skipped correctly).
+ {ok,DecodedSuperSeq} = 'SeqExtension':decode('SuperSeq', SuperSeqEnc),
+ #'SuperSeq'{s1={'SeqExt1'},
+ s2=#'SeqExt2'{bool=true,int=2345},
+ s3={'SeqExt3'},
+ s4={'SeqExt4',true},
+ s5={'SeqExt5'},
+ s6={'SeqExt6',531,601,999,777,11953},
+ i=BigInt} = DecodedSuperSeq,
+
+
+ %% Test more than 64 extensions.
+ roundtrip2('SeqExt66',
+ list_to_tuple(['SeqExt66'|lists:seq(0, 65)])),
+ v_roundtrip2(Erule, 'SeqExt66',
+ list_to_tuple(['SeqExt66'|
+ lists:duplicate(65, asn1_NOVALUE)++[125]])),
+ roundtrip2('SeqExt130',
+ list_to_tuple(['SeqExt130'|lists:seq(0, 129)])),
+ v_roundtrip2(Erule, 'SeqExt130',
+ list_to_tuple(['SeqExt130'|
+ lists:duplicate(129, asn1_NOVALUE)++[199]])),
ok.
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'SeqExtension':encode(Type, Value),
+ {ok,Value} = 'SeqExtension':decode(Type, Encoded),
+ ok.
-
-
-
+v_roundtrip2(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type)),
+ Encoded = roundtrip2(Type, Value).
+
+roundtrip2(Type, Value) ->
+ {ok,Encoded} = 'SeqExtension2':encode(Type, Value),
+ {ok,Value} = 'SeqExtension2':decode(Type, Encoded),
+ Encoded.
+
+v(ber, 'SeqExt66') -> "30049F41 017D";
+v(per, 'SeqExt66') -> "C0420000 00000000 00004001 FA";
+v(uper, 'SeqExt66') -> "D0800000 00000000 00101FA0";
+v(ber, 'SeqExt130') -> "30069F81 010200C7";
+v(per, 'SeqExt130') -> "C0808200 00000000 00000000 00000000 00000040 01C7";
+v(uper, 'SeqExt130') -> "E0208000 00000000 00000000 00000000 0000101C 70".
diff --git a/lib/asn1/test/testSeqIndefinite.erl b/lib/asn1/test/testSeqIndefinite.erl
index 25742474bb..c7b8aba523 100644
--- a/lib/asn1/test/testSeqIndefinite.erl
+++ b/lib/asn1/test/testSeqIndefinite.erl
@@ -23,13 +23,7 @@
-include_lib("test_server/include/test_server.hrl").
-
-main(per_bin) -> ok;
main(per) -> ok;
-main(ber_bin_v2) ->
- main(ber);
-main(ber_bin) ->
- main(ber);
main(ber) ->
%% normal encoding
diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl
index 0c0bbc3e66..db537b1478 100644
--- a/lib/asn1/test/testSeqOf.erl
+++ b/lib/asn1/test/testSeqOf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -28,202 +28,110 @@
-record('Seq3',{bool3, seq3 = asn1_DEFAULT, int3}).
-record('Seq4',{seq41 = asn1_DEFAULT, seq42 = asn1_DEFAULT, seq43 = asn1_DEFAULT}).
-record('SeqIn',{boolIn, intIn}).
-%-record('SeqCho',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('SeqChoInline',{bool1, int1, seq1 = asn1_DEFAULT}).
-%-record('SeqChoOfInline_SEQOF',{bool1, int1, seq1 = asn1_DEFAULT}).
-record('SeqEmp',{seq1}).
-record('Empty',{}).
-main(Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqOf','Seq1',#'Seq1'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'Seq1',true,17,[]}} =
- asn1_wrapper:decode('SeqOf','Seq1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqOf','Seq1',#'Seq1'{bool1 = true,
- int1 = 17,
- seq1 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq1',true,17,[{'SeqIn',true,25}]}} =
- asn1_wrapper:decode('SeqOf','Seq1',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqOf','Seq1',#'Seq1'{bool1 = true,
- int1 = 17,
- seq1 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq1',true,17,[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}]}} =
- asn1_wrapper:decode('SeqOf','Seq1',lists:flatten(Bytes13)),
-
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqOf','Seq2',#'Seq2'{bool2 = true,
- int2 = 17}),
-
- ?line {ok,{'Seq2',[],true,17}} =
- asn1_wrapper:decode('SeqOf','Seq2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqOf','Seq2',#'Seq2'{bool2 = true,
- int2 = 17,
- seq2 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq2',[{'SeqIn',true,25}],true,17}} =
- asn1_wrapper:decode('SeqOf','Seq2',lists:flatten(Bytes22)),
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqOf','Seq2',#'Seq2'{bool2 = true,
- int2 = 17,
- seq2 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq2',[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}],true,17}} =
- asn1_wrapper:decode('SeqOf','Seq2',lists:flatten(Bytes23)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqOf','Seq3',#'Seq3'{bool3 = true,
- int3 = 17}),
- ?line {ok,{'Seq3',true,[],17}} =
- asn1_wrapper:decode('SeqOf','Seq3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqOf','Seq3',#'Seq3'{bool3 = true,
- int3 = 17,
- seq3 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq3',true,[{'SeqIn',true,25}],17}} =
- asn1_wrapper:decode('SeqOf','Seq3',lists:flatten(Bytes32)),
-
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SeqOf','Seq3',#'Seq3'{bool3 = true,
- int3 = 17,
- seq3 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq3',true,[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}],17}} =
- asn1_wrapper:decode('SeqOf','Seq3',lists:flatten(Bytes33)),
-
-
+main(_Rules) ->
+ SeqIn3 = [#'SeqIn'{boolIn=true,intIn=25},
+ #'SeqIn'{boolIn=false,intIn=125},
+ #'SeqIn'{boolIn=false,intIn=225}],
+
+ roundtrip('Seq1', #'Seq1'{bool1=true,int1=17},
+ #'Seq1'{bool1=true,int1=17,seq1=[]}),
+
+ roundtrip('Seq1', #'Seq1'{bool1=true,int1 = 17,
+ seq1=[#'SeqIn'{boolIn=true,
+ intIn=25}]}),
+ roundtrip('Seq1', #'Seq1'{bool1=true,
+ int1=17,
+ seq1=SeqIn3}),
+
+ roundtrip('Seq2', #'Seq2'{bool2=true,int2=17},
+ #'Seq2'{seq2=[],bool2=true,int2=17}),
+ roundtrip('Seq2',#'Seq2'{bool2=true,int2=17,
+ seq2=[#'SeqIn'{boolIn=true,
+ intIn=25}]}),
+ roundtrip('Seq2', #'Seq2'{bool2=true,
+ int2=17,
+ seq2=SeqIn3}),
+
+ roundtrip('Seq3', #'Seq3'{bool3=true,int3=17},
+ #'Seq3'{bool3=true,seq3=[],int3=17}),
+ roundtrip('Seq3',#'Seq3'{bool3=true,
+ int3=17,
+ seq3=[#'SeqIn'{boolIn=true,
+ intIn=25}]}),
+ roundtrip('Seq3', #'Seq3'{bool3=true,int3=17,seq3=SeqIn3}),
+
+ roundtrip('Seq4', #'Seq4'{}, #'Seq4'{seq41=[],seq42=[],seq43=[]}),
+
+ roundtrip('Seq4', #'Seq4'{seq41=[#'SeqIn'{boolIn=true,intIn=25}]},
+ #'Seq4'{seq41=[#'SeqIn'{boolIn=true,intIn=25}],
+ seq42=[],seq43=[]}),
+
+ roundtrip('Seq4', #'Seq4'{seq41=SeqIn3},
+ #'Seq4'{seq41=SeqIn3,seq42=[],seq43=[]}),
+ roundtrip('Seq4', #'Seq4'{seq42=[#'SeqIn'{boolIn=true,intIn=25}]},
+ #'Seq4'{seq41=[],seq42=[#'SeqIn'{boolIn=true,intIn=25}],
+ seq43=[]}),
+ roundtrip('Seq4', #'Seq4'{seq42=SeqIn3},
+ #'Seq4'{seq41=[],seq42=SeqIn3,seq43=[]}),
+
+ roundtrip('Seq4', #'Seq4'{seq43=[#'SeqIn'{boolIn=true,intIn=25}]},
+ #'Seq4'{seq41=[],seq42=[],
+ seq43=[#'SeqIn'{boolIn=true,intIn=25}]}),
+ roundtrip('Seq4', #'Seq4'{seq43=SeqIn3},
+ #'Seq4'{seq41=[],seq42=[],
+ seq43=SeqIn3}),
+
+ roundtrip('SeqEmp', #'SeqEmp'{seq1=[#'Empty'{}]}),
+
+ %% Test constrained, extensible size.
+
+ SeqIn = #'SeqIn'{boolIn=true,intIn=978654321},
+ roundtrip('SeqExt', {'SeqExt',true,[],true,[],789}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(1, SeqIn),
+ true,lists:duplicate(0, SeqIn),777}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(1, SeqIn),
+ true,lists:duplicate(1, SeqIn),777}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(1, SeqIn),
+ true,lists:duplicate(127, SeqIn),777}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(2, SeqIn),
+ true,lists:duplicate(128, SeqIn),1777}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(2, SeqIn),
+ true,lists:duplicate(255, SeqIn),7773}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(2, SeqIn),
+ true,lists:duplicate(256, SeqIn),77755}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(2, SeqIn),
+ true,lists:duplicate(257, SeqIn),8888}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(3, SeqIn),
+ true,lists:duplicate(1024, SeqIn),999988888}),
+ roundtrip('SeqExt', {'SeqExt',true,lists:duplicate(15, SeqIn),
+ true,lists:duplicate(2000, SeqIn),555555}),
+
+ %% Test OTP-4590: correct encoding of the length of SEQUENC OF.
+ DayNames = ["Monday","Tuesday","Wednesday",
+ "Thursday","Friday","Saturday","Sunday"],
+ xroundtrip('DayNames1', 'DayNames3', DayNames),
+ xroundtrip('DayNames2', 'DayNames4', DayNames),
+ xroundtrip('DayNames2', 'DayNames4', [hd(DayNames)]),
+ xroundtrip('DayNames2', 'DayNames4', tl(DayNames)),
+ ok.
+roundtrip(T, V) ->
+ roundtrip(T, V, V).
-
-
- ?line {ok,Bytes41} = asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{}),
- ?line {ok,{'Seq4',[],[],[]}} = asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes41)),
-
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq41 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq4',[{'SeqIn',true,25}],[],[]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes42)),
-
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq41 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq4',[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}],[],[]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes43)),
-
-
- ?line {ok,Bytes44} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq42 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq4',[],[{'SeqIn',true,25}],[]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes44)),
-
-
- ?line {ok,Bytes45} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq42 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq4',[],[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}],[]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes45)),
-
-
- ?line {ok,Bytes46} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq43 = [#'SeqIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Seq4',[],[],[{'SeqIn',true,25}]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes46)),
-
-
- ?line {ok,Bytes47} =
- asn1_wrapper:encode('SeqOf','Seq4',#'Seq4'{seq43 = [#'SeqIn'{boolIn = true,
- intIn = 25},
- #'SeqIn'{boolIn = false,
- intIn = 125},
- #'SeqIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Seq4',[],[],[{'SeqIn',true,25},{'SeqIn',false,125},{'SeqIn',false,225}]}} =
- asn1_wrapper:decode('SeqOf','Seq4',lists:flatten(Bytes47)),
-
-
- ?line {ok,Bytes51} = asn1_wrapper:encode('SeqOf','SeqEmp',#'SeqEmp'{seq1 = [#'Empty'{}]}),
- ?line {ok,{'SeqEmp',[{'Empty'}]}} = asn1_wrapper:decode('SeqOf','SeqEmp',lists:flatten(Bytes51)),
-
- case Rules of
- ber ->
- ?line {ok,Bytes52} = asn1_wrapper:encode('SeqOfEnum','SeqOfEnum',
- {'SeqOfEnum',[{'Enum',a},{'Enum',b}]}),
- ?line {ok,[a,b]} = asn1_wrapper:decode('SeqOfEnum','SeqOfEnum',
- lists:flatten(Bytes52));
- _ -> ok
- end,
-
- %% tests of OTP-4590
- case Rules of
- PER when PER == per; PER == per_bin ->
- DayNames = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
- ?line {ok,Bytes60} = asn1_wrapper:encode('XSeqOf','DayNames2',DayNames),
- ?line {ok,Bytes60} = asn1_wrapper:encode('XSeqOf','DayNames4',DayNames),
- ?line {ok,DayNames} = asn1_wrapper:decode('XSeqOf','DayNames2',Bytes60),
- ?line {ok,DayNames} = asn1_wrapper:decode('XSeqOf','DayNames4',Bytes60),
- ?line {ok,Bytes61} = asn1_wrapper:encode('XSeqOf','DayNames1',DayNames),
- ?line {ok,Bytes61} = asn1_wrapper:encode('XSeqOf','DayNames3',DayNames),
- ?line {ok,DayNames} = asn1_wrapper:decode('XSeqOf','DayNames1',Bytes61),
- ?line {ok,DayNames} = asn1_wrapper:decode('XSeqOf','DayNames3',Bytes61);
- _ ->
- ok
- end,
-
+roundtrip(Type, Val, Expected) ->
+ M = 'SeqOf',
+ {ok,Enc} = M:encode(Type, Val),
+ {ok,Expected} = M:decode(Type, Enc),
ok.
-
+xroundtrip(T1, T2, Val) ->
+ M = 'XSeqOf',
+ {ok,Enc} = M:encode(T1, Val),
+ {ok,Enc} = M:encode(T2, Val),
+ {ok,Val} = M:decode(T1, Enc),
+ {ok,Val} = M:decode(T2, Enc),
+ ok.
diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl
index ab484db5f2..bd6c9428e2 100644
--- a/lib/asn1/test/testSeqSetDefaultVal.erl
+++ b/lib/asn1/test/testSeqSetDefaultVal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -134,7 +134,7 @@ main(_Rules) ->
c={5,<<64>>},
d=0}),
- ?line {ok,{'SeqBS',[1,0,1,0,1,1,0],2698,[second],[]}} =
+ {ok,{'SeqBS',[1,0,1,0,1,1,0],2698,[second],<<>>}} =
asn1_wrapper:decode('Default','SeqBS',[48,3,131,1,0]),
?line {ok,{'SeqBS',[1,0,1,0,1,1,0],2698,[second],[1,0,0,1]}} =
@@ -161,7 +161,7 @@ main(_Rules) ->
c={5,<<64>>},
d=0}),
- ?line {ok,{'SetBS',[1,0,1,0,1,1,0],2698,[second],[]}} =
+ {ok,{'SetBS',[1,0,1,0,1,1,0],2698,[second],<<>>}} =
asn1_wrapper:decode('Default','SetBS',[49,3,131,1,0]),
?line {ok,{'SetBS',[1,0,1,0,1,1,0],2698,[second],[1,0,0,1]}} =
diff --git a/lib/asn1/test/testSetIndefinite.erl b/lib/asn1/test/testSetIndefinite.erl
index d8e2b6a9cf..73006da62b 100644
--- a/lib/asn1/test/testSetIndefinite.erl
+++ b/lib/asn1/test/testSetIndefinite.erl
@@ -24,12 +24,7 @@
-include_lib("test_server/include/test_server.hrl").
-main(per_bin) -> ok;
main(per) -> ok;
-main(ber_bin_v2) ->
- main(ber);
-main(ber_bin) ->
- main(ber);
main(ber) ->
%% normal encoding
diff --git a/lib/asn1/test/testSetOptional.erl b/lib/asn1/test/testSetOptional.erl
index 4692941524..bb43ff0a96 100644
--- a/lib/asn1/test/testSetOptional.erl
+++ b/lib/asn1/test/testSetOptional.erl
@@ -21,8 +21,7 @@
-include("External.hrl").
-export([main/1]).
--export([ticket_7533/1,decoder/4]).
--include_lib("test_server/include/test_server.hrl").
+-export([ticket_7533/1]).
-record('SetOpt1',{bool1 = asn1_NOVALUE, int1, set1 = asn1_NOVALUE}).
-record('SetOpt1Imp',{bool1 = asn1_NOVALUE, int1, set1 = asn1_NOVALUE}).
@@ -36,171 +35,64 @@
-record('SetIn',{boolIn, intIn}).
main(_Rules) ->
+ roundtrip('SetOpt1',
+ #'SetOpt1'{bool1=true,int1=15,
+ set1=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt1', #'SetOpt1'{int1=15}),
+
+ roundtrip('SetOpt2', #'SetOpt2'{bool2=true,int2=15,
+ set2=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt2', #'SetOpt2'{int2=15,bool2=true}),
+
+ roundtrip('SetOpt3', #'SetOpt3'{bool3=true,int3=15,
+ set3=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt3', #'SetOpt3'{int3=15}),
+
+ roundtrip('SetOpt1Imp',
+ #'SetOpt1Imp'{bool1=true,int1 = 15,
+ set1=#'SetIn'{boolIn = true,intIn = 66}}),
+ roundtrip('SetOpt1Imp', #'SetOpt1Imp'{int1=15}),
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetOptional','SetOpt1',#'SetOpt1'{bool1 = true,
- int1 = 15,
- set1 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt1',true,15,{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetOptional','SetOpt1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('SetOptional','SetOpt1',#'SetOpt1'{int1 = 15}),
- ?line {ok,{'SetOpt1',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SetOptional','SetOpt1',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetOptional','SetOpt2',#'SetOpt2'{bool2 = true,
- int2 = 15,
- set2 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt2',{'SetIn',true,66},true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('SetOptional','SetOpt2',#'SetOpt2'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SetOpt2',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetOptional','SetOpt3',#'SetOpt3'{bool3 = true,
- int3 = 15,
- set3 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt3',true,{'SetIn',true,66},15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('SetOptional','SetOpt3',#'SetOpt3'{int3 = 15}),
- ?line {ok,{'SetOpt3',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3',lists:flatten(Bytes32)),
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetOptional','SetOpt1Imp',#'SetOpt1Imp'{bool1 = true,
- int1 = 15,
- set1 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt1Imp',true,15,{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetOptional','SetOpt1Imp',lists:flatten(Bytes41)),
-
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('SetOptional','SetOpt1Imp',#'SetOpt1Imp'{int1 = 15}),
- ?line {ok,{'SetOpt1Imp',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SetOptional','SetOpt1Imp',lists:flatten(Bytes42)),
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SetOptional','SetOpt2Imp',#'SetOpt2Imp'{bool2 = true,
- int2 = 15,
- set2 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt2Imp',{'SetIn',true,66},true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2Imp',lists:flatten(Bytes51)),
-
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('SetOptional','SetOpt2Imp',#'SetOpt2Imp'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SetOpt2Imp',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2Imp',lists:flatten(Bytes52)),
-
-
-
- ?line {ok,Bytes61} =
- asn1_wrapper:encode('SetOptional','SetOpt3Imp',#'SetOpt3Imp'{bool3 = true,
- int3 = 15,
- set3 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt3Imp',true,{'SetIn',true,66},15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3Imp',lists:flatten(Bytes61)),
-
-
- ?line {ok,Bytes62} = asn1_wrapper:encode('SetOptional','SetOpt3Imp',#'SetOpt3Imp'{int3 = 15}),
- ?line {ok,{'SetOpt3Imp',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3Imp',lists:flatten(Bytes62)),
-
-
-
-
-
-
- ?line {ok,Bytes71} =
- asn1_wrapper:encode('SetOptional','SetOpt1Exp',#'SetOpt1Exp'{bool1 = true,
- int1 = 15,
- set1 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt1Exp',true,15,{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetOptional','SetOpt1Exp',lists:flatten(Bytes71)),
-
-
- ?line {ok,Bytes72} = asn1_wrapper:encode('SetOptional','SetOpt1Exp',#'SetOpt1Exp'{int1 = 15}),
- ?line {ok,{'SetOpt1Exp',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SetOptional','SetOpt1Exp',lists:flatten(Bytes72)),
-
-
- ?line {ok,Bytes81} =
- asn1_wrapper:encode('SetOptional','SetOpt2Exp',#'SetOpt2Exp'{bool2 = true,
- int2 = 15,
- set2 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt2Exp',{'SetIn',true,66},true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2Exp',lists:flatten(Bytes81)),
-
-
- ?line {ok,Bytes82} = asn1_wrapper:encode('SetOptional','SetOpt2Exp',#'SetOpt2Exp'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SetOpt2Exp',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt2Exp',lists:flatten(Bytes82)),
-
-
-
- ?line {ok,Bytes91} =
- asn1_wrapper:encode('SetOptional','SetOpt3Exp',#'SetOpt3Exp'{bool3 = true,
- int3 = 15,
- set3 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetOpt3Exp',true,{'SetIn',true,66},15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3Exp',lists:flatten(Bytes91)),
-
-
- ?line {ok,Bytes92} = asn1_wrapper:encode('SetOptional','SetOpt3Exp',#'SetOpt3Exp'{int3 = 15}),
- ?line {ok,{'SetOpt3Exp',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SetOptional','SetOpt3Exp',lists:flatten(Bytes92)),
-
+
+ roundtrip('SetOpt2Imp',
+ #'SetOpt2Imp'{bool2=true,int2=15,
+ set2=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt2Imp',#'SetOpt2Imp'{int2=15,bool2=true}),
+
+ roundtrip('SetOpt3Imp',
+ #'SetOpt3Imp'{bool3=true,int3=15,
+ set3=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt3Imp', #'SetOpt3Imp'{int3=15}),
+
+ roundtrip('SetOpt1Exp',
+ #'SetOpt1Exp'{bool1=true,int1=15,
+ set1=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt1Exp', #'SetOpt1Exp'{int1=15}),
+
+ roundtrip('SetOpt2Exp',
+ #'SetOpt2Exp'{bool2=true,int2=15,
+ set2=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt2Exp', #'SetOpt2Exp'{int2=15,bool2=true}),
+ roundtrip('SetOpt3Exp',
+ #'SetOpt3Exp'{bool3=true,int3=15,
+ set3=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetOpt3Exp', #'SetOpt3Exp'{int3=15}),
ok.
-ticket_7533(Ber) when Ber == ber; Ber == ber_bin ->
- Val = #'SetOpt1'{bool1 = true,int1=12,set1=#'SetIn'{boolIn=false,intIn=13}},
- ?line {ok,B} = asn1_wrapper:encode('SetOptional','SetOpt1',Val),
- ?line {ok,Val} = asn1_wrapper:decode('SetOptional','SetOpt1',B),
-
- CorruptVal = [49,14,1,1,255,2,1,12] ++ lists:duplicate(8,0),
- Pid = spawn(?MODULE,decoder,[self(),'SetOptional','SetOpt1',CorruptVal]),
- receive
- {ok,Pid,Result} ->
- io:format("Decode result: ~p~n",[Result]),
- ok
- after 10000 ->
- io:format("Decode timeout~n",[]),
- exit(Pid,normal)
- end;
+ticket_7533(Ber) when Ber == ber ->
+ Val = #'SetOpt1'{bool1=true,int1=12,set1=#'SetIn'{boolIn=false,intIn=13}},
+ roundtrip('SetOpt1', Val),
+ CorruptVal = <<49,14,1,1,255,2,1,12,0:8/unit:8>>,
+ {error,_} = 'SetOptional':decode('SetOpt1', CorruptVal),
+ ok;
ticket_7533(_) ->
ok.
-decoder(Parent,Module,Type,Val) ->
- io:format("Decoding~n",[]),
- ?line {ok,Res} = asn1_wrapper:decode(Module,Type,Val),
- io:format("Decode res: ~p~n",[Res]),
- Parent ! {ok,self(),Res}.
+roundtrip(Type, Value) ->
+ {ok,Encoded} = 'SetOptional':encode(Type, Value),
+ {ok,Value} = 'SetOptional':decode(Type, Encoded),
+ ok.
diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl
index 878ce7c070..aba13c94de 100644
--- a/lib/asn1/test/testTCAP.erl
+++ b/lib/asn1/test/testTCAP.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -37,7 +37,7 @@ compile_asn1config(Config, Options) ->
asn1_test_lib:compile_all(Files, Config, Options),
asn1_test_lib:compile_erlang("TCAPPackage_msg", Config, []).
-test(Erule,_Config) when Erule==ber;Erule==ber_bin;Erule==ber_bin_v2 ->
+test(Erule,_Config) ->
% ?line OutDir = ?config(priv_dir,Config),
%% testing OTP-4798, open type encoded with indefinite length
?line {ok,_Res} = asn1_wrapper:decode('TCAPMessages-simple','MessageType', val_OTP_4798(Erule)),
@@ -81,7 +81,7 @@ test_asn1config() ->
?line Val2 = 'TCAPPackage_msg':val('TransactionPDU'),
?line {ok,B2} = 'TCAPPackage':encode('TransactionPDU',Val2),
- ?line {ok,ExMsg2}='TCAPPackage':decode_TransactionPDU(list_to_binary(B2)),
+ {ok,ExMsg2}='TCAPPackage':decode_TransactionPDU(B2),
?line {_,_,_,{Key2,ExVal2}}=ExMsg2,
?line {ok,_Parts2}='TCAPPackage':decode_part(Key2,ExVal2),
diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl
index 2d3b777558..cd7ceb5630 100644
--- a/lib/asn1/test/testTimer.erl
+++ b/lib/asn1/test/testTimer.erl
@@ -133,23 +133,7 @@ go(Config,Enc) ->
Module = 'H323-MESSAGES',
Type = 'H323-UserInformation',
Value = val(),
-%% ok = asn1ct:compile(HelpModule,[Enc]),
-
-%% ok = asn1ct:compile(Module,[Enc]),
- ?line {ok,B} = asn1rt:encode(Module,Type,Value),
- Bytes = case Enc of
- ber_bin ->
- list_to_binary(B);
- per_bin when is_list(B) ->
- list_to_binary(B);
- per_bin ->
- B;
- uper_bin ->
- B;
- _ ->
- %%lists:flatten(B)
- list_to_binary(B)
- end,
+ {ok,Bytes} = asn1rt:encode(Module,Type,Value),
CompileOptions = compile_options(),
@@ -181,35 +165,18 @@ encode(N, Module,Type,Value) ->
decode(0, _Module,_Type,_Value,_Erule) ->
done;
decode(N, Module,Type,Value,Erule) ->
- case Erule of
- ber ->
- ?line {ok,_B} = asn1rt:decode(Module,Type,binary_to_list(Value));
- per ->
- ?line {ok,_B} = asn1rt:decode(Module,Type,binary_to_list(Value));
- _ ->
- ?line {ok,_B} = asn1rt:decode(Module,Type,Value)
- end,
+ {ok,_B} = asn1rt:decode(Module,Type,Value),
decode(N-1, Module,Type,Value,Erule).
compile_options() ->
- ?line {ok,Info} = asn1rt:info('H323-MESSAGES'),
- case lists:keysearch(options,1,Info) of
- {_,{_,Opts}} ->
- Opts2 =
- case lists:member(ber_bin_v2,Opts) of
- true ->
- [ber_bin,optimize] ++ lists:delete(optimize,Opts);
- _ ->
- Opts
- end,
- Opts3 = [X||X <- Opts2,
- (X == ber orelse
- X == ber_bin orelse
- X == per orelse
- X == per_bin orelse
- X == optimize orelse
- X == driver)],
- lists:flatten(io_lib:format("~p",[Opts3]));
+ {ok,Info} = asn1rt:info('H323-MESSAGES'),
+ case lists:keyfind(options, 1, Info) of
+ {_,Opts0} ->
+ Opts1 = [X || X <- Opts0,
+ (X =:= ber orelse
+ X =:= per orelse
+ X =:= uper)],
+ lists:flatten(io_lib:format("~p", [Opts1]));
_ ->
"[]"
end.
diff --git a/lib/asn1/test/testTypeValueNotation.erl b/lib/asn1/test/testTypeValueNotation.erl
index cd5223ef23..61d69edd0e 100644
--- a/lib/asn1/test/testTypeValueNotation.erl
+++ b/lib/asn1/test/testTypeValueNotation.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -21,41 +21,16 @@
-export([main/2]).
--include_lib("test_server/include/test_server.hrl").
-
-record('Seq', {octstr, int, bool, enum, bitstr, null, oid, vstr}).
-main(Rule, Option) ->
+main(_Rule, _Option) ->
Value1 = #'Seq'{octstr = [1, 2, 3, 4],
int = 12,
bool = true,
enum = a,
- bitstr = [1, 0, 1, 0],
+ bitstr = <<2#1010:4>>,
null = 'NULL',
oid = {1, 2, 55},
vstr = "Hello World"},
- Value2 = #'Seq'{octstr = {'OctStr', [1, 2, 3, 4]},
- int = {'Int', 12},
- bool = {'Bool', true},
- enum = {'Enum', a},
- bitstr = {'BitStr', [1, 0, 1, 0]},
- null = {'Null', 'NULL'},
- oid = {'OId', {1, 2, 55}},
- vstr = {'VStr', "Hello World"}},
- main(Rule, Option, Value1, Value2).
-
-%% Value2 will fail for ber_bin_v2, per_bin with nifs (optimize) and uper_bin
-main(ber_bin_v2, _, Value1, Value2) -> encode_fail(Value1, Value2);
-main(per_bin, [optimize], Value1, Value2) -> encode_fail(Value1, Value2);
-main(uper_bin, [], Value1, Value2) -> encode_fail(Value1, Value2);
-main(_, _, Value1, Value2) -> encode_normal(Value1, Value2).
-
-encode_normal(Value1, Value2) ->
- {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
- {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2),
- {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
-
-encode_fail(Value1, Value2) ->
- {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
- {error, _Reason} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2),
- {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
+ {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
+ {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
diff --git a/lib/asn1/test/testWSParamClass.erl b/lib/asn1/test/testWSParamClass.erl
new file mode 100644
index 0000000000..ae67ca8b81
--- /dev/null
+++ b/lib/asn1/test/testWSParamClass.erl
@@ -0,0 +1,17 @@
+-module(testWSParamClass).
+-export([main/1]).
+
+main(_) ->
+ IF = 'InformationFramework',
+ roundtrip({'Attribute',IF:'id-at-objectClass'(),
+ [IF:'id-at-objectClass'()],
+ asn1_NOVALUE}),
+ roundtrip({'Attribute',IF:'id-at-objectClass'(),
+ [],[]}),
+ ok.
+
+roundtrip(Data) ->
+ IF = 'InformationFramework',
+ {ok,Enc} = asn1_wrapper:encode(IF, 'Attribute', Data),
+ {ok,Data} = IF:decode('Attribute', Enc),
+ ok.
diff --git a/lib/asn1/test/testX420.erl b/lib/asn1/test/testX420.erl
index b222b15204..70bdb0640d 100644
--- a/lib/asn1/test/testX420.erl
+++ b/lib/asn1/test/testX420.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. 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
@@ -34,7 +34,7 @@ compile(Erule, Options, Config) ->
compile_loop(_Erule, [], _Options, _Config) ->
ok;
compile_loop(Erule, [Spec|Specs], Options, Config)
- when Erule == ber; Erule == ber_bin; Erule == ber_bin_v2; Erule == per ->
+ when Erule =:= ber; Erule =:= per ->
CaseDir = ?config(case_dir, Config),
asn1_test_lib:compile(filename:join([x420, Spec]), Config,
[Erule, {i, CaseDir} | Options]),
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 4e732308d8..179299c78d 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -51,14 +51,13 @@ path(Config) ->
{ok,CWD} = file:get_cwd(),
?line file:set_cwd(filename:join([DataDir,subdir])),
- %%?line ok=asn1ct:compile(filename:join([DataDir,"../MyMerge.set.asn"]),[{inline,mymerge},{outdir,OutDir}]),
- ?line ok=asn1ct:compile("../MyMerge.set.asn",[{inline,mymerge},{outdir,OutDir}]),
+ ok = asn1ct:compile("../MyMerge.set.asn",[{outdir,OutDir}]),
?line ok=outfiles_check(OutDir),
?line outfiles_remove(OutDir),
file:set_cwd(filename:join([DataDir,subdir,subsubdir])),
- ?line ok = asn1ct:compile('../../MyMerge.set.asn',[{inline,mymerge},{i,'..'},{outdir,OutDir}]),
+ ok = asn1ct:compile('../../MyMerge.set.asn',[{i,'..'},{outdir,OutDir}]),
?line ok=outfiles_check(OutDir,outfiles2()),
file:set_cwd(CWD),
@@ -92,7 +91,8 @@ noobj(Config) ->
file:delete(filename:join([OutDir,'P-Record.beam'])),
file:delete(filename:join([OutDir,'p_record.erl'])),
file:delete(filename:join([OutDir,'p_record.beam'])),
- ?line ok=asn1ct:compile(filename:join([DataDir,"p_record.set.asn"]),[asn1config,ber_bin,optimize,noobj,{outdir,OutDir}]),
+ ok = asn1ct:compile(filename:join([DataDir,"p_record.set.asn"]),
+ [asn1config,ber,noobj,{outdir,OutDir}]),
%% ?line false = code:is_loaded('P-Record'),
%% ?line false = code:is_loaded('p_record'),
?line {error,enoent} =
@@ -181,11 +181,10 @@ outfiles_check(OutDir,[H|T]) ->
outfiles_check(OutDir,T).
outfiles1() ->
- ["mymerge.erl","mymerge.beam","MyMerge.asn1db","MyMerge.beam",
+ ["MyMerge.asn1db","MyMerge.beam",
"MyMerge.erl","MyMerge.hrl"].
outfiles2() ->
- ["MyMerge.beam","mymerge.erl","MyMerge.asn1db","MyMerge.erl",
- "mymerge.beam"].
+ ["MyMerge.beam","MyMerge.asn1db","MyMerge.erl"].
outfiles_remove(OutDir) ->
lists:foreach(fun(F)-> file:delete(filename:join([OutDir,F])) end,
diff --git a/lib/asn1/test/test_inline.erl b/lib/asn1/test/test_inline.erl
deleted file mode 100644
index 62625572e3..0000000000
--- a/lib/asn1/test/test_inline.erl
+++ /dev/null
@@ -1,270 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2012. 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%
-%%
-%%
--module(test_inline).
-
--export([compile/2,main/2,inline1/3,performance/1,performance2/0]).
--export([mvrasn_inlined_encdec/2,mvrasn_encdec/2,
- mi_encdec/2,m_encdec/2]).
-
--include_lib("test_server/include/test_server.hrl").
--define(times, 5000).
--define(times2, 50000).
-
-compile(Config, Options) ->
- CaseDir = ?config(case_dir, Config),
- asn1_test_lib:compile("Mvrasn.set.asn", Config, [{inline, mvrasn_inlined}|Options]),
- asn1_test_lib:compile("Mod.set.asn", Config, [{inline, m}|Options]),
- ok = remove_inlined_files(CaseDir, [filename:join([CaseDir, X])||X<-["m.erl", "m.beam"]]),
- asn1_test_lib:compile("Mod.set.asn", Config, [inline|Options]),
- ok = remove_inlined_files(CaseDir, []).
-
-inline1(Config, Rule, Opt) ->
- CaseDir = ?config(case_dir, Config),
-
- asn1_test_lib:compile("P-Record", Config, [{inline, 'inlined_P_Record'}|Opt]),
- test_inline1(),
-
- ok=remove_inlined_files2(CaseDir, ber_bin_v2),
-
- case Rule of
- ber_bin_v2 ->
- asn1_test_lib:compile("P-Record", Config,
- [ber_bin, inline, asn1config, optimize|Opt]),
- test_inline2(Rule, 'P-Record'),
- remove_inlined_files3(CaseDir, Rule),
- asn1_test_lib:compile("p_record.set.asn", Config,
- [ber_bin, inline, asn1config, optimize|Opt]),
- test_inline2(Rule, 'p_record'),
- remove_inlined_files4(CaseDir, Rule);
- _ ->
- ok
- end.
-
-main(Config, _Erule) ->
- Val = val(Config),
- ?line {ok,Bytes}=asn1_wrapper:encode(mvrasn_inlined,'InsertSubscriberDataArg',Val),
- ?line {ok,_Val2}=asn1_wrapper:decode(mvrasn_inlined,'InsertSubscriberDataArg',Bytes).
-
-test_inline1() ->
- PRecMsg = {'PersonnelRecord',{'Name',"Sven","S","Svensson"},
- "manager",123,"20000202",{'Name',"Inga","K","Svensson"},
- asn1_DEFAULT},
- ?line {ok,Bytes}=asn1_wrapper:encode('inlined_P_Record','PersonnelRecord',
- PRecMsg),
- ?line {ok,_}=asn1_wrapper:decode('inlined_P_Record',
- 'PersonnelRecord',Bytes).
-
-test_inline2(ber_bin_v2,Mod) ->
- PRecMsg = {'PersonnelRecord',{'Name',"Sven","S","Svensson"},
- "manager",123,"20000202",{'Name',"Inga","K","Svensson"},
- asn1_DEFAULT},
- ?line {ok,Bytes} = Mod:encode('PersonnelRecord',PRecMsg),
- ?line {ok,_} = Mod:sel_dec(list_to_binary(Bytes));
-test_inline2(_,_) ->
- ok.
-
-val(Config) ->
- {ok,Val} = asn1ct:value('Mvrasn','InsertSubscriberDataArg',
- [{i, ?config(case_dir, Config)}]),
- Val.
-
-performance(Config) ->
- Val = val(Config),
- %% warm up
- timer:tc(?MODULE,mvrasn_inlined_encdec,[2,Val]),
- %% performance test
- ?line {Time1,ok}=timer:tc(?MODULE,mvrasn_inlined_encdec,[?times,Val]),
- %% warm up
- timer:tc(?MODULE,mvrasn_encdec,[2,Val]),
- %% performance test
- ?line {Time2,ok}=timer:tc(?MODULE,mvrasn_encdec,[?times,Val]),
-
- ?line Comment = "inlined_code: "++
- integer_to_list(round(Time1/?times))++
- " micro,<br>original_code: "++
- integer_to_list(round(Time2/?times))++
-% " micro,~ninlined_code[inline]: "++
-% integer_to_list(round(Time3/?times))++
- " micro",
- {comment,Comment}.
-
-
-mvrasn_inlined_encdec(0,_) ->
- ok;
-mvrasn_inlined_encdec(N,V) ->
- ?line {ok,B}=mvrasn_inlined:encode('InsertSubscriberDataArg',V),
- ?line {ok,_R}=mvrasn_inlined:decode('InsertSubscriberDataArg',B),
- mvrasn_inlined_encdec(N-1,V).
-
-mvrasn_encdec(0,_) ->
- ok;
-mvrasn_encdec(N,V) ->
- ?line {ok,B}='Mvrasn-11-6':encode('InsertSubscriberDataArg',V),
- ?line {ok,_R}='Mvrasn-11-6':decode('InsertSubscriberDataArg',B),
- mvrasn_encdec(N-1,V).
-
-%% mvrasn_inlined_i_encdec(0,_) ->
-%% ok;
-%% mvrasn_inlined_i_encdec(N,V) ->
-%% {ok,B}=mvrasn_inlined_i:encode('InsertSubscriberDataArg',V),
-%% {ok,_R}=mvrasn_inlined_i:decode('InsertSubscriberDataArg',B),
-%% mvrasn_inlined_i_encdec(N-1,V).
-
-performance2() ->
- Val = mval(),
- %% warm up
- timer:tc(?MODULE,mi_encdec,[?times,Val]),
- %% performance test
- {Time1,_R1}=timer:tc(?MODULE,mi_encdec,[?times2,Val]),
- %% warm up
- timer:tc(?MODULE,m_encdec,[?times,Val]),
- %% performance test
- {Time2,_R2}=timer:tc(?MODULE,m_encdec,[?times2,Val]),
- ?line Comment = "inlined_code: "++
- integer_to_list(round(Time1/?times2))++
- " micro,<br>original_code: "++
- integer_to_list(round(Time2/?times2))++
- " micro<br>"++
- "The inlined code was "++
- integer_to_list(round(((Time2-Time1)/Time2)*100))++
- " % faster than the original code.",
- {comment,Comment}.
-
-mi_encdec(0,_) ->
- ok;
-mi_encdec(N,Val) ->
- {ok,B}=m:encode('L',Val),
- {ok,_R}=m:decode('L',B),
-% io:format("a"),
- mi_encdec(N-1,Val).
-
-m_encdec(0,_) ->
- ok;
-m_encdec(N,Val) ->
- {ok,B}='Mod':encode('L',Val),
- {ok,_R}='Mod':decode('L',B),
- m_encdec(N-1,Val).
-
-
--record('L', {country, region, name}).
--record('OtherName', {locationName, thingName}).
--record('FamilyName', {prefix, secondname}).
--record('Lang', {l}).
--record('Inhabitant', {name, country}).
--record('Country', {name, language}).
--record('PersonName', {name1, name2}).
--record('LocName', {region, name}).
--record('Reg', {name, inhabitants}).
-
-
-mval() ->
- 'L'().
-'L'() ->
- #'L'{
- country='Co'(),
- region='Reg'(),
- name='Name'(othername)}.
-'Co'() ->
- 'Country'().
-'Country'()->
- #'Country'{name='Name'(othername),
- language='Lang'()}.
-'Lang'()->
- #'Lang'{l="englsh"}.
-'Reg'() ->
- #'Reg'{
- name='Name'(othername),
- inhabitants='Inhabitants'()}.
-'Inhabitants'()->
- lists:duplicate(5,'Inhabitant'()).
-'Inhabitant'()->
- #'Inhabitant'{name='Name'(person),
- country='Country'()}.
-'Name'(person) ->
- {person,'PersonName'()};
-'Name'(othername) ->
- {othername,'OtherName'()}.
-'PersonName'()->
- #'PersonName'{name1='FirstName'(firstname),
- name2='FamilyName'()}.
-'OtherName'()->
- #'OtherName'{locationName='LocName'(),
- thingName='ThingName'()}.
-'FirstName'(firstname)->
- {firstname,"Henry"};
-'FirstName'(nickname) ->
- {nickname,"nick"}.
-'FamilyName'() ->
- #'FamilyName'{prefix=none,
- secondname="Lloyd"}.
-'ThingName'()->
- "Enkoping".
-'LocName'()->
- #'LocName'{
- region=svealand,
- name="Enkoping"}.
-
-remove_inlined_files(Dir,Files) ->
- ModList=[filename:join([Dir,X])||X<-["Mod"]],
- FileList=Files++ mods2files(ModList,".asn1db")++
- mods2files(ModList,".beam")++
- mods2files(ModList,".erl")++mods2files(ModList,".hrl"),
- lists:foreach(fun(X) ->
- io:format("X: ~p~n",[X]),
- ?line ok=file:delete(X)
- end,FileList),
- ok.
-mods2files(ModList,Extension) ->
- [X++Extension||X<-ModList].
-
-
-remove_inlined_files2(Dir,Rule) ->
- ?line ok=remove_inlined_files3(Dir,Rule),
- TargetErl=filename:join([Dir,"inlined_P_Record.erl"]),
- TargetBeam=filename:join([Dir,"inlined_P_Record.beam"]),
- lists:foreach(fun(X) ->
- ?line ok=file:delete(X)
- end,[TargetErl,TargetBeam]),
- ok.
-remove_inlined_files3(Dir,ber_bin_v2) ->
- Erl=filename:join([Dir,"P-Record.erl"]),
- Beam=filename:join([Dir,"P-Record.beam"]),
- Asn1DB=filename:join([Dir,"P-Record.asn1db"]),
- Hrl=filename:join([Dir,"P-Record.hrl"]),
- lists:foreach(fun(X) ->
- ?line ok=file:delete(X)
- end,[Erl,Beam,Asn1DB,Hrl]),
- ok;
-remove_inlined_files3(_,_) ->
- ok.
-
-remove_inlined_files4(Dir,ber_bin_v2) ->
- Erl=filename:join([Dir,"p_record.erl"]),
- Beam=filename:join([Dir,"p_record.beam"]),
- Asn1DB=filename:join([Dir,"p_record.asn1db"]),
- Hrl=filename:join([Dir,"p_record.hrl"]),
- ErlBak=filename:join([Dir,"p_record.erl.bak"]),
- file:delete(ErlBak),
- lists:foreach(fun(X) ->
- ?line ok=file:delete(X)
- end,[Erl,Beam,Asn1DB,Hrl]),
- ok;
-remove_inlined_files4(_,_) ->
- ok.
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index ae9d1989fb..a525fd6ae1 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. 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
diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl
index df56c27115..8ede06938d 100644
--- a/lib/asn1/test/test_partial_incomplete_decode.erl
+++ b/lib/asn1/test/test_partial_incomplete_decode.erl
@@ -188,7 +188,7 @@ decode_parts('S1_2',PartDecMsg) ->
msg('F') ->
- {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}};
+ {fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}};
msg('F3') ->
{fb,{'E',10,[{'D',11,true},{'D',12,false}],false,{dc,{'E_d_dc',13,true,{'E_d_dc_dcc',14,15}}}}};
diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl
index bb348611da..ebe1296cf3 100644
--- a/lib/asn1/test/test_selective_decode.erl
+++ b/lib/asn1/test/test_selective_decode.erl
@@ -53,7 +53,7 @@ test() ->
msg('F') ->
- {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}};
+ {fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}};
msg('E') ->
{'E',10,[{'D',11,true},{'D',12,false}],false,{dc,{'E_d_dc',13,true,{'E_d_dc_dcc',14,15}}}};
diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl
index 4ac0ff2b27..7dfab1f25a 100644
--- a/lib/asn1/test/test_special_decode_performance.erl
+++ b/lib/asn1/test/test_special_decode_performance.erl
@@ -31,9 +31,9 @@ go(all) ->
{Time_S_c,Time_MGC_c}).
go(N,Mod) ->
- ?line Val = val(Mod),
- ?line {ok,B} = Mod:encode(element(1,Val),Val),
- ?line go(Mod,list_to_binary(B),N).
+ {Type,Val} = val(Mod),
+ {ok,B} = Mod:encode(Type, Val),
+ ?line go(Mod,B,N).
go(Mod,Bin,N) ->
?line FsS = get_selective_funcs(Mod),
@@ -92,7 +92,7 @@ val('PartialDecSeq') ->
{'F',{fb,{'E',12,[{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false},{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false},{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false}],true,{da,[{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}}]}}}};
val('MEDIA-GATEWAY-CONTROL') ->
- {'MegacoMessage',asn1_NOVALUE,{'Message',1,{ip4Address,{'IP4Address',[125,125,125,111],55555}},{transactions,[{transactionReply,{'TransactionReply',50007,asn1_NOVALUE,{actionReplies,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,[{auditValueReply,{auditResult,{'AuditResult',{'TerminationID',[],[255,255,255]},[{mediaDescriptor,{'MediaDescriptor',asn1_NOVALUE,{multiStream,[{'StreamDescriptor',1,{'StreamParms',{'LocalControlDescriptor',sendRecv,asn1_NOVALUE,asn1_NOVALUE,[{'PropertyParm',[0,11,0,7],[[52,48]],asn1_NOVALUE}]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,53,46,49,50,53,46,49,50,53,46,49,49,49]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,49,49,49,49,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,52,46,49,50,52,46,49,50,52,46,50,50,50]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,50,50,50,50,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]}}}]}}},{packagesDescriptor,[{'PackagesItem',[0,11],1},{'PackagesItem',[0,11],1}]},{statisticsDescriptor,[{'StatisticsParameter',[0,12,0,4],[[49,50,48,48]]},{'StatisticsParameter',[0,11,0,2],[[54,50,51,48,48]]},{'StatisticsParameter',[0,12,0,5],[[55,48,48]]},{'StatisticsParameter',[0,11,0,3],[[52,53,49,48,48]]},{'StatisticsParameter',[0,12,0,6],[[48,46,50]]},{'StatisticsParameter',[0,12,0,7],[[50,48]]},{'StatisticsParameter',[0,12,0,8],[[52,48]]}]}]}}}]}]}}}]}}}.
+ {'MegacoMessage',{'MegacoMessage',asn1_NOVALUE,{'Message',1,{ip4Address,{'IP4Address',[125,125,125,111],55555}},{transactions,[{transactionReply,{'TransactionReply',50007,asn1_NOVALUE,{actionReplies,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,[{auditValueReply,{auditResult,{'AuditResult',{'TerminationID',[],[255,255,255]},[{mediaDescriptor,{'MediaDescriptor',asn1_NOVALUE,{multiStream,[{'StreamDescriptor',1,{'StreamParms',{'LocalControlDescriptor',sendRecv,asn1_NOVALUE,asn1_NOVALUE,[{'PropertyParm',[0,11,0,7],[[52,48]],asn1_NOVALUE}]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,53,46,49,50,53,46,49,50,53,46,49,49,49]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,49,49,49,49,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,52,46,49,50,52,46,49,50,52,46,50,50,50]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,50,50,50,50,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]}}}]}}},{packagesDescriptor,[{'PackagesItem',[0,11],1},{'PackagesItem',[0,11],1}]},{statisticsDescriptor,[{'StatisticsParameter',[0,12,0,4],[[49,50,48,48]]},{'StatisticsParameter',[0,11,0,2],[[54,50,51,48,48]]},{'StatisticsParameter',[0,12,0,5],[[55,48,48]]},{'StatisticsParameter',[0,11,0,3],[[52,53,49,48,48]]},{'StatisticsParameter',[0,12,0,6],[[48,46,50]]},{'StatisticsParameter',[0,12,0,7],[[50,48]]},{'StatisticsParameter',[0,12,0,8],[[52,48]]}]}]}}}]}]}}}]}}}}.
%% val('PartialDecSeq') ->
%% {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{dc,{'E_d_dc',15,true,{'E_d_dc_dcc',17,4711}}}}}}.
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 3db25c7839..b75de179dc 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1,2 +1,2 @@
#next version number to use is 2.0
-ASN1_VSN = 1.8.1.2
+ASN1_VSN = 2.0.2