aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1')
-rw-r--r--lib/asn1/Makefile4
-rw-r--r--lib/asn1/c_src/Makefile45
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c128
-rw-r--r--lib/asn1/doc/src/asn1_spec.xmlsrc4
-rw-r--r--lib/asn1/doc/src/asn1_ug.xml932
-rw-r--r--lib/asn1/doc/src/asn1ct.xml47
-rw-r--r--lib/asn1/doc/src/asn1rt.xml32
-rw-r--r--lib/asn1/doc/src/book.xml4
-rw-r--r--lib/asn1/doc/src/fascicules.xml2
-rw-r--r--lib/asn1/doc/src/notes.xml294
-rw-r--r--lib/asn1/doc/src/part.xml4
-rw-r--r--lib/asn1/doc/src/ref_man.xml4
-rw-r--r--lib/asn1/src/Makefile10
-rw-r--r--lib/asn1/src/asn1.app.src3
-rw-r--r--lib/asn1/src/asn1.appup.src30
-rw-r--r--lib/asn1/src/asn1_db.erl116
-rw-r--r--lib/asn1/src/asn1_records.hrl12
-rw-r--r--lib/asn1/src/asn1ct.erl146
-rw-r--r--lib/asn1/src/asn1ct_check.erl939
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl120
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl1229
-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.erl73
-rw-r--r--lib/asn1/src/asn1ct_gen.erl620
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl464
-rw-r--r--lib/asn1/src/asn1ct_gen_check.erl271
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl949
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl461
-rw-r--r--lib/asn1/src/asn1ct_imm.erl2099
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl31
-rw-r--r--lib/asn1/src/asn1ct_table.erl34
-rw-r--r--lib/asn1/src/asn1ct_tok.erl4
-rw-r--r--lib/asn1/src/asn1ct_value.erl34
-rw-r--r--lib/asn1/src/asn1rt.erl3
-rw-r--r--lib/asn1/src/asn1rt_nif.erl2
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl213
-rw-r--r--lib/asn1/src/asn1rtt_check.erl331
-rw-r--r--lib/asn1/src/asn1rtt_ext.erl2
-rw-r--r--lib/asn1/src/asn1rtt_per.erl876
-rw-r--r--lib/asn1/src/asn1rtt_per_common.erl420
-rw-r--r--lib/asn1/src/asn1rtt_real_common.erl6
-rw-r--r--lib/asn1/src/asn1rtt_uper.erl915
-rw-r--r--lib/asn1/src/prepare_templates.erl72
-rw-r--r--lib/asn1/test/Makefile14
-rw-r--r--lib/asn1/test/asn1_SUITE.erl579
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Constraints.py55
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Constructed.asn6
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ContextSwitchingTypes.asn14
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Default.asn26
-rw-r--r--lib/asn1/test/asn1_SUITE_data/DoubleEllipses.asn31
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumExt.asn12
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Fragmented.asn124
-rw-r--r--lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn14
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn114
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn17
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn14
-rw-r--r--lib/asn1/test/asn1_SUITE_data/InfObj.asn92
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Param.asn122
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ParamBasic.asn122
-rw-r--r--lib/asn1/test/asn1_SUITE_data/PrimStrings.asn18
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqOf.asn139
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqPrim.asn17
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Set.py4
-rw-r--r--lib/asn1/test/asn1_SUITE_data/TAGDEFAULT-AUTOMATIC.asn25
-rw-r--r--lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl36
-rw-r--r--lib/asn1/test/asn1_SUITE_data/TConstr.asn134
-rw-r--r--lib/asn1/test/asn1_SUITE_data/UPERDefault.asn18
-rw-r--r--lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl4
-rw-r--r--lib/asn1/test/asn1_app_test.erl4
-rw-r--r--lib/asn1/test/asn1_appup_test.erl359
-rw-r--r--lib/asn1/test/asn1_test_lib.erl279
-rw-r--r--lib/asn1/test/asn1_wrapper.erl49
-rw-r--r--lib/asn1/test/ber_decode_error.erl28
-rw-r--r--lib/asn1/test/choice_extension.erl37
-rw-r--r--lib/asn1/test/error_SUITE.erl164
-rw-r--r--lib/asn1/test/h323test.erl86
-rw-r--r--lib/asn1/test/pem_performance.erl37
-rw-r--r--lib/asn1/test/testChoExtension.erl11
-rw-r--r--lib/asn1/test/testChoExternal.erl38
-rw-r--r--lib/asn1/test/testChoOptional.erl103
-rw-r--r--lib/asn1/test/testChoOptionalImplicitTag.erl101
-rw-r--r--lib/asn1/test/testChoPrim.erl106
-rw-r--r--lib/asn1/test/testChoRecursive.erl8
-rw-r--r--lib/asn1/test/testChoTypeRefCho.erl50
-rw-r--r--lib/asn1/test/testChoTypeRefPrim.erl72
-rw-r--r--lib/asn1/test/testChoTypeRefSeq.erl100
-rw-r--r--lib/asn1/test/testChoTypeRefSet.erl101
-rw-r--r--lib/asn1/test/testChoiceIndefinite.erl4
-rw-r--r--lib/asn1/test/testConstraints.erl107
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl52
-rw-r--r--lib/asn1/test/testDER.erl34
-rw-r--r--lib/asn1/test/testDeepTConstr.erl32
-rw-r--r--lib/asn1/test/testDef.erl118
-rw-r--r--lib/asn1/test/testDoubleEllipses.erl98
-rw-r--r--lib/asn1/test/testEnumExt.erl16
-rw-r--r--lib/asn1/test/testFragmented.erl40
-rw-r--r--lib/asn1/test/testINSTANCE_OF.erl43
-rw-r--r--lib/asn1/test/testInfObj.erl100
-rw-r--r--lib/asn1/test/testInfObjectClass.erl24
-rw-r--r--lib/asn1/test/testMegaco.erl161
-rw-r--r--lib/asn1/test/testMergeCompile.erl150
-rw-r--r--lib/asn1/test/testNBAPsystem.erl40
-rw-r--r--lib/asn1/test/testOpenTypeImplicitTag.erl19
-rw-r--r--lib/asn1/test/testOpt.erl111
-rw-r--r--lib/asn1/test/testParamBasic.erl67
-rw-r--r--lib/asn1/test/testParameterizedInfObj.erl125
-rw-r--r--lib/asn1/test/testPrim.erl132
-rw-r--r--lib/asn1/test/testPrimExternal.erl105
-rw-r--r--lib/asn1/test/testPrimStrings.erl397
-rw-r--r--lib/asn1/test/testSelectionTypes.erl15
-rw-r--r--lib/asn1/test/testSeq2738.erl19
-rw-r--r--lib/asn1/test/testSeqDefault.erl198
-rw-r--r--lib/asn1/test/testSeqExtension.erl12
-rw-r--r--lib/asn1/test/testSeqExternal.erl131
-rw-r--r--lib/asn1/test/testSeqIndefinite.erl48
-rw-r--r--lib/asn1/test/testSeqOf.erl38
-rw-r--r--lib/asn1/test/testSeqOfCho.erl150
-rw-r--r--lib/asn1/test/testSeqOfExternal.erl197
-rw-r--r--lib/asn1/test/testSeqOfIndefinite.erl78
-rw-r--r--lib/asn1/test/testSeqOfTag.erl185
-rw-r--r--lib/asn1/test/testSeqOptional.erl199
-rw-r--r--lib/asn1/test/testSeqPrim.erl67
-rw-r--r--lib/asn1/test/testSeqSetDefaultVal.erl711
-rw-r--r--lib/asn1/test/testSeqSetIndefinite.erl52
-rw-r--r--lib/asn1/test/testSeqTag.erl86
-rw-r--r--lib/asn1/test/testSeqTypeRefCho.erl21
-rw-r--r--lib/asn1/test/testSeqTypeRefPrim.erl42
-rw-r--r--lib/asn1/test/testSeqTypeRefSeq.erl166
-rw-r--r--lib/asn1/test/testSeqTypeRefSet.erl45
-rw-r--r--lib/asn1/test/testSetDefault.erl76
-rw-r--r--lib/asn1/test/testSetExtension.erl85
-rw-r--r--lib/asn1/test/testSetExternal.erl119
-rw-r--r--lib/asn1/test/testSetIndefinite.erl41
-rw-r--r--lib/asn1/test/testSetOf.erl282
-rw-r--r--lib/asn1/test/testSetOfCho.erl150
-rw-r--r--lib/asn1/test/testSetOfExternal.erl169
-rw-r--r--lib/asn1/test/testSetOfTag.erl185
-rw-r--r--lib/asn1/test/testSetOptional.erl4
-rw-r--r--lib/asn1/test/testSetPrim.erl66
-rw-r--r--lib/asn1/test/testSetTag.erl87
-rw-r--r--lib/asn1/test/testSetTypeRefCho.erl21
-rw-r--r--lib/asn1/test/testSetTypeRefPrim.erl30
-rw-r--r--lib/asn1/test/testSetTypeRefSeq.erl38
-rw-r--r--lib/asn1/test/testSetTypeRefSet.erl163
-rw-r--r--lib/asn1/test/testTCAP.erl52
-rw-r--r--lib/asn1/test/testTcapsystem.erl78
-rw-r--r--lib/asn1/test/testTimer.erl257
-rw-r--r--lib/asn1/test/testTypeValueNotation.erl22
-rw-r--r--lib/asn1/test/testWSParamClass.erl5
-rw-r--r--lib/asn1/test/testX420.erl24
-rw-r--r--lib/asn1/test/test_compile_options.erl2
-rw-r--r--lib/asn1/test/test_driver_load.erl45
-rw-r--r--lib/asn1/test/test_modified_x420.erl5
-rw-r--r--lib/asn1/test/test_partial_incomplete_decode.erl116
-rw-r--r--lib/asn1/test/test_selective_decode.erl45
-rw-r--r--lib/asn1/test/test_special_decode_performance.erl6
-rw-r--r--lib/asn1/test/test_undecoded_rest.erl52
-rw-r--r--lib/asn1/test/test_x691.erl183
-rw-r--r--lib/asn1/vsn.mk2
160 files changed, 9831 insertions, 11817 deletions
diff --git a/lib/asn1/Makefile b/lib/asn1/Makefile
index 9c1b19605c..18e95a2471 100644
--- a/lib/asn1/Makefile
+++ b/lib/asn1/Makefile
@@ -26,6 +26,9 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
SUB_DIRECTORIES = src doc/src c_src
+static_lib: SUB_DIRECTORIES = c_src
+
+
include vsn.mk
VSN = $(ASN1_VSN)
@@ -60,7 +63,6 @@ info:
version:
@echo "$(VSN)"
-
# ----------------------------------------------------
# Application (source) release targets
# ----------------------------------------------------
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 70238335c4..a7cd03f516 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -46,12 +46,11 @@ else
TYPEMARKER =
endif
-EI_LIBDIR = $(ERL_TOP)/lib/erl_interface/obj$(TYPEMARKER)/$(TARGET)
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_CFLAGS)
+STATIC_CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_STATIC_CFLAGS)
LDFLAGS += $(DED_LDFLAGS)
# ----------------------------------------------------
@@ -59,28 +58,55 @@ LDFLAGS += $(DED_LDFLAGS)
# ----------------------------------------------------
NIF_OBJ_FILES = $(OBJDIR)/asn1_erl_nif.o
+NIF_STATIC_OBJ_FILES = $(OBJDIR)/asn1_erl_nif_static.o
-
+# Module and shared lib have to have same name of
+# static nifs to work
ifeq ($(TARGET),win32)
-NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.dll
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1rt_nif.dll
+NIF_LIB_FILE = $(LIBDIR)/asn1rt_nif.lib
CLIB_FLAGS =
LN=cp
else
-NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.so
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1rt_nif.so
+NIF_LIB_FILE = $(LIBDIR)/asn1rt_nif.a
CLIB_FLAGS = -lc
LN= ln -s
endif
+ifeq ($(USING_VC),yes)
+AR_OUT=-out:
+AR_FLAGS=
+else
+AR_OUT=
+ifeq ($(V),0)
+AR_FLAGS=rc
+else
+AR_FLAGS=rcv
+endif
+endif
+
+ifndef RANLIB
+RANLIB=true
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+ifneq ($(findstring ose,$(TARGET)),ose)
opt: $(NIF_SHARED_OBJ_FILE)
+else
+# Do not build dynamic files on OSE
+opt:
+endif
debug: opt
+static_lib: $(NIF_LIB_FILE)
+
clean:
rm -f core *~
rm -f $(LIBDIR)/*
@@ -96,6 +122,13 @@ docs:
$(OBJDIR)/%.o: %.c
$(V_CC) -c $(CFLAGS) -O3 -o $@ $<
+$(OBJDIR)/%_static.o: %.c
+ $(V_CC) -c $(STATIC_CFLAGS) -O3 -o $@ $<
+
+$(NIF_LIB_FILE): $(NIF_STATIC_OBJ_FILES)
+ $(V_AR) $(AR_FLAGS) $(AR_OUT)$@ $(NIF_STATIC_OBJ_FILES)
+ $(V_RANLIB) $@
+
$(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES)
$(V_LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS)
@@ -106,7 +139,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) "$(RELSYSDIR)/priv/lib"
+endif
$(INSTALL_DIR) "$(RELSYSDIR)/c_src"
$(INSTALL_DATA) *.c "$(RELSYSDIR)/c_src"
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index b3dd312fed..317a464060 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -57,54 +57,54 @@
#define MASK(X,M) (X & M)
/* PER COMPLETE */
-int per_complete(ErlNifBinary *, unsigned char *, int);
+static int per_complete(ErlNifBinary *, unsigned char *, int);
-int per_insert_octets(int, unsigned char **, unsigned char **, int *);
+static int per_insert_octets(int, unsigned char **, unsigned char **, int *);
-int per_insert_octets_except_unused(int, unsigned char **, unsigned char **,
+static int per_insert_octets_except_unused(int, unsigned char **, unsigned char **,
int *, int);
-int per_insert_octets_as_bits_exact_len(int, int, unsigned char **,
+static int per_insert_octets_as_bits_exact_len(int, int, unsigned char **,
unsigned char **, int *);
-int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *);
+static int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *);
-int per_pad_bits(int, unsigned char **, int *);
+static int per_pad_bits(int, unsigned char **, int *);
-int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
+static int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
-int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
+static int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
-int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
+static int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
-int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
+static int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
-int per_realloc_memory(ErlNifBinary *, int, unsigned char **);
+static int per_realloc_memory(ErlNifBinary *, int, unsigned char **);
/* BER DECODE */
-int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int,
+static int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int,
unsigned int *);
-int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int);
+static int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int);
-int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *);
+static int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *);
-int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int,
+static int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int,
int);
/* BER ENCODE */
typedef struct ber_encode_mem_chunk mem_chunk_t;
-int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *);
+static int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *);
-void ber_free_chunks(mem_chunk_t *chunk);
-mem_chunk_t *ber_new_chunk(unsigned int length);
-int ber_check_memory(mem_chunk_t **curr, unsigned int needed);
+static void ber_free_chunks(mem_chunk_t *chunk);
+static mem_chunk_t *ber_new_chunk(unsigned int length);
+static int ber_check_memory(mem_chunk_t **curr, unsigned int needed);
-int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int ,
+static int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int ,
mem_chunk_t **, unsigned int *);
-int ber_encode_length(size_t , mem_chunk_t **, unsigned int *);
+static int ber_encode_length(size_t , mem_chunk_t **, unsigned int *);
/*
*
@@ -113,7 +113,7 @@ int ber_encode_length(size_t , mem_chunk_t **, unsigned int *);
*
*/
-int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
+static int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
int in_buf_len) {
int counter = in_buf_len;
/* counter keeps track of number of bytes left in the
@@ -489,7 +489,7 @@ int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
}
}
-int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) {
+static int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) {
int i = *ptr - binary->data;
@@ -502,7 +502,7 @@ int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) {
return ASN1_OK;
}
-int per_insert_most_sign_bits(int no_bits, unsigned char val,
+static int per_insert_most_sign_bits(int no_bits, unsigned char val,
unsigned char **output_ptr, int *unused) {
unsigned char *ptr = *output_ptr;
@@ -523,7 +523,7 @@ int per_insert_most_sign_bits(int no_bits, unsigned char val,
return ASN1_OK;
}
-int per_insert_least_sign_bits(int no_bits, unsigned char val,
+static int per_insert_least_sign_bits(int no_bits, unsigned char val,
unsigned char **output_ptr, int *unused) {
unsigned char *ptr = *output_ptr;
int ret = 0;
@@ -552,7 +552,7 @@ int per_insert_least_sign_bits(int no_bits, unsigned char val,
/* per_pad_bits adds no_bits bits in the buffer that output_ptr
points at.
*/
-int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) {
+static int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) {
unsigned char *ptr = *output_ptr;
int ret = 0;
@@ -575,7 +575,7 @@ int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) {
The unused parameter tells how many bits that are not set in the
actual byte in the output buffer. If desired_no is more bits than the
input buffer has in no_bytes bytes, then zero bits is padded.*/
-int per_insert_bits_as_bits(int desired_no, int no_bytes,
+static int per_insert_bits_as_bits(int desired_no, int no_bytes,
unsigned char **input_ptr, unsigned char **output_ptr, int *unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char val;
@@ -615,7 +615,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes,
}
/* per_insert_octets_as_bits_exact_len */
-int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len,
+static int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len,
unsigned char **in_ptr, unsigned char **ptr, int *unused) {
int ret = 0;
int ret2 = 0;
@@ -653,7 +653,7 @@ int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len,
otherwise the function returns ASN1_ERROR. The output buffer is concatenated
without alignment.
*/
-int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr,
+static int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr,
unsigned char **output_ptr, int *unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char *ptr = *output_ptr;
@@ -693,7 +693,7 @@ int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr,
into the output buffer, *output_ptr. Before the first byte is
inserted the input buffer is aligned.
*/
-int per_insert_octets(int no_bytes, unsigned char **input_ptr,
+static int per_insert_octets(int no_bytes, unsigned char **input_ptr,
unsigned char **output_ptr, int *unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char *ptr = *output_ptr;
@@ -718,7 +718,7 @@ int per_insert_octets(int no_bytes, unsigned char **input_ptr,
/* per_insert_octets_unaligned inserts bytes from the input buffer, *input_ptr,
into the output buffer, *output_ptr.No alignment is done.
*/
-int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr,
+static int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr,
unsigned char **output_ptr, int unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char *ptr = *output_ptr;
@@ -742,7 +742,7 @@ int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr,
return no_bytes;
}
-int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr,
+static int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr,
unsigned char **output_ptr, int *unused, int in_unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char *ptr = *output_ptr;
@@ -835,7 +835,7 @@ int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr,
* is the empty binary.
* If some error occured during the decoding of the in_buf an error is returned.
*/
-int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+static int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
int in_buf_len, unsigned int *err_pos) {
int maybe_ret;
int ib_index = 0;
@@ -857,7 +857,7 @@ int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
return ASN1_OK;
}
-int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+static int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
int *ib_index, int in_buf_len) {
int maybe_ret;
int form;
@@ -889,7 +889,7 @@ int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
* decode_tag decodes the BER encoded tag in in_buf and creates an
* nif term tag
*/
-int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf,
+static int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf,
int in_buf_len, int *ib_index) {
int tag_no, tmp_tag, form;
@@ -936,21 +936,36 @@ int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf,
* in_buf and puts the value part in the decode_buf as an Erlang
* nif term into value
*/
-int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf,
+static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf,
int *ib_index, int form, int in_buf_len) {
int maybe_ret;
unsigned int len = 0;
unsigned int lenoflen = 0;
- int indef = 0;
unsigned char *tmp_out_buff;
ERL_NIF_TERM term = 0, curr_head = 0;
if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
len = in_buf[*ib_index];
- } else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH
- )
- indef = 1;
- else /* long definite length */{
+ } else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH) {
+ (*ib_index)++;
+ curr_head = enif_make_list(env, 0);
+ if (*ib_index+1 >= in_buf_len || form == ASN1_PRIMITIVE) {
+ return ASN1_INDEF_LEN_ERROR;
+ }
+ while (!(in_buf[*ib_index] == 0 && in_buf[*ib_index + 1] == 0)) {
+ maybe_ret = ber_decode(env, &term, in_buf, ib_index, in_buf_len);
+ if (maybe_ret <= ASN1_ERROR) {
+ return maybe_ret;
+ }
+ curr_head = enif_make_list_cell(env, term, curr_head);
+ if (*ib_index+1 >= in_buf_len) {
+ return ASN1_INDEF_LEN_ERROR;
+ }
+ }
+ enif_make_reverse_list(env, curr_head, value);
+ (*ib_index) += 2; /* skip the indefinite length end bytes */
+ return ASN1_OK;
+ } else /* long definite length */{
lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */
if (lenoflen > (in_buf_len - (*ib_index + 1)))
return ASN1_LEN_ERROR;
@@ -965,23 +980,7 @@ int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf,
if (len > (in_buf_len - (*ib_index + 1)))
return ASN1_VALUE_ERROR;
(*ib_index)++;
- if (indef == 1) { /* in this case it is desireably to check that indefinite length
- end bytes exist in inbuffer */
- curr_head = enif_make_list(env, 0);
- while (!(in_buf[*ib_index] == 0 && in_buf[*ib_index + 1] == 0)) {
- if (*ib_index >= in_buf_len)
- return ASN1_INDEF_LEN_ERROR;
-
- if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index, in_buf_len))
- <= ASN1_ERROR
- )
- return maybe_ret;
- curr_head = enif_make_list_cell(env, term, curr_head);
- }
- enif_make_reverse_list(env, curr_head, value);
- (*ib_index) += 2; /* skip the indefinite length end bytes */
- } else if (form == ASN1_CONSTRUCTED)
- {
+ if (form == ASN1_CONSTRUCTED) {
int end_index = *ib_index + len;
if (end_index > in_buf_len)
return ASN1_LEN_ERROR;
@@ -1012,7 +1011,7 @@ struct ber_encode_mem_chunk {
char *curr;
};
-int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) {
+static int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) {
const ERL_NIF_TERM *tv;
unsigned int form;
@@ -1087,7 +1086,7 @@ int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned i
return ASN1_OK;
}
-int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form,
+static int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form,
mem_chunk_t **curr, unsigned int *count) {
unsigned int class_tag_no, head_tag;
if (!enif_get_uint(env, tag, &class_tag_no))
@@ -1122,7 +1121,7 @@ int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form,
}
}
-int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
+static int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
if (size < 128) {
if (ber_check_memory(curr, 1u))
return ASN1_ERROR;
@@ -1150,7 +1149,7 @@ int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
return ASN1_OK;
}
-mem_chunk_t *ber_new_chunk(unsigned int length) {
+static mem_chunk_t *ber_new_chunk(unsigned int length) {
mem_chunk_t *new = enif_alloc(sizeof(mem_chunk_t));
if (new == NULL)
return NULL;
@@ -1165,7 +1164,7 @@ mem_chunk_t *ber_new_chunk(unsigned int length) {
return new;
}
-void ber_free_chunks(mem_chunk_t *chunk) {
+static void ber_free_chunks(mem_chunk_t *chunk) {
mem_chunk_t *curr, *next = chunk;
while (next != NULL) {
curr = next;
@@ -1175,7 +1174,7 @@ void ber_free_chunks(mem_chunk_t *chunk) {
}
}
-int ber_check_memory(mem_chunk_t **curr, unsigned int needed) {
+static int ber_check_memory(mem_chunk_t **curr, unsigned int needed) {
mem_chunk_t *new;
if ((*curr)->curr-needed >= (*curr)->top)
return ASN1_OK;
@@ -1320,6 +1319,7 @@ static void unload(ErlNifEnv* env, void* priv_data) {
}
+
static ErlNifFunc nif_funcs[] = {
{ "encode_per_complete", 1, encode_per_complete },
{ "decode_ber_tlv_raw", 1, decode_ber_tlv_raw },
diff --git a/lib/asn1/doc/src/asn1_spec.xmlsrc b/lib/asn1/doc/src/asn1_spec.xmlsrc
index 07cba17816..9001aca65c 100644
--- a/lib/asn1/doc/src/asn1_spec.xmlsrc
+++ b/lib/asn1/doc/src/asn1_spec.xmlsrc
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml
index 362ca9330f..8b33497dd3 100644
--- a/lib/asn1/doc/src/asn1_ug.xml
+++ b/lib/asn1/doc/src/asn1_ug.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -34,23 +34,25 @@
<section>
<title>Features</title>
- <p>The Asn1 application provides:
- </p>
+ <p>The Asn1 application provides:</p>
<list type="bulleted">
<item>An ASN.1 compiler for Erlang, which generates encode and
decode functions to be used by Erlang programs sending and
receiving ASN.1 specified data.</item>
<item>Run-time functions used by the generated code.</item>
- <item>The supported encoding rules are:
+ <item>Support for the following encoding rules:
<list>
<item>
Basic Encoding Rules (<em>BER</em>)
</item>
<item>
- Distinguished Encoding Rules (<em>DER</em>), a specialized form of BER that is used in security-conscious applications.
+ Distinguished Encoding Rules (<em>DER</em>), a specialized
+ form of BER that is used in security-conscious
+ applications.
</item>
<item>
- Packed Encoding Rules (<em>PER</em>) both the aligned and unaligned variant.
+ Packed Encoding Rules (<em>PER</em>); both the aligned and
+ unaligned variant.
</item>
</list>
</item>
@@ -59,71 +61,41 @@
<section>
<title>Overview</title>
- <p>ASN.1 (Abstract Syntax Notation 1) is a formal language for describing data structures to be exchanged between distributed computer systems.
- The purpose of ASN.1 is to have
- a platform and programming language independent notation to express
- types using a
- standardized set of rules for the transformation of values of
- a defined type, into a stream of bytes. This stream of bytes
- can then be sent on a communication channel set up by the
- lower layers in the stack of communication protocols e.g.
- TCP/IP or encapsulated within UDP packets. This way, two
- different applications written in two completely different
- programming languages running on different computers with
- different internal representation of data can exchange
- instances of structured data types (instead of exchanging
- bytes or bits). This makes programming faster and easier since no code
- has to be written to process the transport format of the
- data.
- </p>
- <p>To write a network application which processes ASN.1 encoded
- messages, it is prudent and sometimes essential to have a set
- of off-line development tools such as an ASN.1 compiler which
- can generate the encode and decode logic for the specific ASN.1
- data types. It is also necessary to combine this with some
- general language-specific runtime support for ASN.1 encoding and
- decoding.
- </p>
- <p>The ASN.1 compiler must be directed towards a target language
- or a set of closely related languages. This manual describes a
- compiler which is directed towards the functional language
- Erlang. In order to use this compiler, familiarity with the
- language Erlang is essential. Therefore, the runtime support for ASN.1 is
- also closely related to the language Erlang and
- consist of a number of functions, which the
- compiler uses. The types in ASN.1 and how to represent
- values of those types in Erlang are described in this manual.
- </p>
- <p>The following document is structured so that the first part describes
- how to use ASN.1 compiler, and then there are descriptions of all
- the primitive and constructed ASN.1 types and their representation
- in Erlang,
- </p>
+ <p>ASN.1 (Abstract Syntax Notation One) is a formal language for
+ describing data structures to be exchanged between distributed
+ computer systems. The purpose of ASN.1 is to have a platform
+ and programming language independent notation to express types
+ using a standardized set of rules for the transformation of
+ values of a defined type into a stream of bytes. This stream of
+ bytes can then be sent on any type of communication
+ channel. This way, two applications written in different
+ programming languages running on different computers with
+ different internal representation of data can exchange instances
+ of structured data types.</p>
</section>
<section>
<title>Prerequisites</title>
- <p>It is assumed that the reader is familiar with the ASN.1 notation
- as documented in the standard definition [<cite id="X.680"></cite>] which is
- the primary text. It may also be helpful, but not necessary,
- to read the standard definitions
- [<cite id="X.681"></cite>] [<cite id="X.682"></cite>] [<cite id="X.683"></cite>]
- [<cite id="X.690"></cite>] [<cite id="X.691"></cite>]. </p>
- <p>A very good book explaining those reference texts is
- [<cite id="DUBUISSON"></cite>], free to download at
- <url href="http://www.oss.com/asn1/dubuisson.html">http://www.oss.com/asn1/dubuisson.html </url>.
+ <p>It is assumed that the reader is familiar with the ASN.1
+ notation as documented in the standard definition [<cite
+ id="X.680"></cite>] which is the primary text. It may also be
+ helpful, but not necessary, to read the standard definitions
+ [<cite id="X.681"></cite>] [<cite id="X.682"></cite>] [<cite
+ id="X.683"></cite>] [<cite id="X.690"></cite>] [<cite
+ id="X.691"></cite>]. </p>
+ <p>A good book explaining those reference texts is
+ [<cite id="DUBUISSON"></cite>], which is free to download at
+ <url href="http://www.oss.com/asn1/dubuisson.html">http://www.oss.com/asn1/dubuisson.html</url>.
</p>
</section>
<section>
- <title>Capability</title>
+ <title>Capabilities</title>
<p>This application covers all features of ASN.1 up to the 1997
- edition of the specification. In the 2002 edition of ASN.1 a number of
- new features where introduced of which some are supported while
- others are not. For example the
- ECN (Encoding Control Notation) and XML notation are still
- unsupported. Though, the other features of the 2002 edition are
- fully or partly supported as shown below:</p>
+ edition of the specification. In the 2002 edition of ASN.1 a
+ number of new features were introduced. The following features
+ of the 2002 edition are fully or partly supported as shown
+ below:</p>
<list type="bulleted">
<item>
<p>Decimal notation (e.g., "1.5e3") for REAL values. The
@@ -131,7 +103,7 @@
supported.</p>
</item>
<item>
- <p>The RELATIVE-OID type for relative object identifiers are
+ <p>The RELATIVE-OID type for relative object identifiers is
fully supported.</p>
</item>
<item>
@@ -141,16 +113,16 @@
constraint is not a PER-visible constraint.</p>
</item>
<item>
- <p>The subtype constraint by regular expressions (PATTERN) for character string types is parsed when compiling, but no further action is taken. This constraint is not a PER-visible constraint.</p>
+ <p>The subtype constraint by regular expressions (PATTERN)
+ for character string types is parsed when compiling, but no
+ further action is taken. This constraint is not a
+ PER-visible constraint.</p>
</item>
<item>
<p>Multiple-line comments as in C, <c>/* ... */</c>, are
supported.</p>
</item>
</list>
- <p>It should also be added here that the encoding formats
- supported are <em>BER</em>, <em>DER</em>, <em>PER aligned
- basic</em> variant and <em>PER unaligned basic</em> variant.</p>
</section>
</section>
@@ -162,19 +134,17 @@
<title>A First Example</title>
<p>The following example demonstrates the basic functionality used to run
the Erlang ASN.1 compiler.</p>
- <p>First, create a file called <c>People.asn</c> containing the following:</p>
+ <p>Create a file called <c>People.asn</c> containing the following:</p>
<pre>
-People DEFINITIONS IMPLICIT TAGS ::=
-
+People DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
-EXPORTS Person;
-
-Person ::= [PRIVATE 19] SEQUENCE {
- name PrintableString,
- location INTEGER {home(0),field(1),roving(2)},
- age INTEGER OPTIONAL }
+ Person ::= SEQUENCE {
+ name PrintableString,
+ location INTEGER {home(0),field(1),roving(2)},
+ age INTEGER OPTIONAL
+ }
END </pre>
- <p>This file (<c>people.asn</c>) must be compiled before it can be
+ <p>This file (<c>People.asn</c>) must be compiled before it can be
used.
The ASN.1 compiler checks that the syntax is correct and that the
text represents proper ASN.1 code before generating an abstract
@@ -186,14 +156,14 @@ END </pre>
The following shows how the compiler
can be called from the Erlang shell:</p>
<pre>
-1><input>asn1ct:compile("People", [ber]).</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>
+2><input> asn1ct:compile("People", [ber,verbose]).</input>
Erlang ASN.1 compiling "People.asn"
--{generated,"People.asn1db"}--
--{generated,"People.hrl"}--
@@ -201,20 +171,17 @@ Erlang ASN.1 compiling "People.asn"
ok
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
- loaded into the Erlang runtime system. Now there is a user interface
- of encode/2 and decode/2 in the module People, which is invoked by:
- <br></br>
-<c><![CDATA['People':encode(<Type name>,<Value>),]]></c> <br></br>
-
+ <p>The ASN.1 module <c>People</c> 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 loaded into the Erlang run-time system. Now there is an API
+ for <c>encode/2</c> and <c>decode/2</c> in the module
+ <c>People</c>, which is invoked by: <br></br>
+ <c><![CDATA['People':encode(<Type name>, <Value>)]]></c>
+ <br></br>
or <br></br>
-<c><![CDATA['People':decode(<Type name>,<Value>),]]></c> <br></br>
+<c><![CDATA['People':decode(<Type name>, <Value>)]]></c></p>
- Alternatively one can use the <c><![CDATA[asn1rt:encode(<Module name> ,<Type name>,<Value>)]]></c> and <c><![CDATA[asn1rt:decode(< Module name>,<Type name>,<Value>)]]></c> calls.
- However, they are not as efficient as the previous methods since they
- result in an additional <c>apply/3</c> call.</p>
<p>Assume there is a network
application which receives instances of the ASN.1 defined
type Person, modifies and sends them back again:</p>
@@ -237,33 +204,30 @@ 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
- binary according to the BER or PER
- encoding-rules.
+ binary according to the BER or PER encoding rules.
<br></br>
The encoder and the decoder can also be run from
- the shell. The following dialogue with the shell illustrates
- how the functions
- <c>asn1rt:encode/3</c> and <c>asn1rt:decode/3</c> are used.</p>
+ the shell.</p>
<pre>
2> <input>Rockstar = {'Person',"Some Name",roving,50}.</input>
{'Person',"Some Name",roving,50}
-3> <input>{ok,Bin} = asn1rt:encode('People','Person',Rockstar).</input>
+3> <input>{ok,Bin} = 'People':encode('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>
+4> <input>{ok,Person} = 'People':decode('Person',Bin).</input>
{ok,{'Person',"Some Name",roving,50}}
5> </pre>
</section>
<section>
<title>Module dependencies</title>
- <p>It is common that asn1 modules import defined types, values and
- other entities from another asn1 module.</p>
- <p>Earlier versions of the asn1 compiler required that modules that
+ <p>It is common that ASN.1 modules import defined types, values and
+ other entities from another ASN.1 module.</p>
+ <p>Earlier versions of the ASN.1 compiler required that modules that
were imported from had to be compiled before the module that
- imported. This caused problems when asn1 modules had circular
+ imported. This caused problems when ASN.1 modules had circular
dependencies.</p>
- <p>Now are referenced modules parsed when the compiler finds an
+ <p>Referenced modules are now parsed when the compiler finds an
entity that is imported. There will not be any code generated for
the referenced module. However, the compiled module rely on
that the referenced modules also will be compiled.</p>
@@ -279,11 +243,8 @@ The encoder and the decoder can also be run from
(including the compiler).</p>
</item>
<item>
- <p>The module <c>asn1rt</c> which provides the run-time functions.
- However, it is preferable to use the generated <c>encode/2</c> and
- <c>decode/2</c> functions in each module, ie.
- Module:encode(Type,Value), in favor of the <c>asn1rt</c>
- interface.</p>
+ <p>The module <c>asn1rt_nif</c> which provides the run-time functions
+ for the ASN.1 decoder for the BER back-end.</p>
</item>
</list>
<p>The reason for the division of the interface into compile-time
@@ -318,7 +279,7 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
</item>
<tag><c>-I IncludeDir</c></tag>
<item>
- <p>Where to search for <c>.asn1db</c> files and asn1
+ <p>Where to search for <c>.asn1db</c> files and ASN.1
source specs in order to resolve references to other
modules. This option can be repeated many times if there
are several places to search in. The compiler will always
@@ -330,26 +291,26 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
</item>
<tag><c>+asn1config</c></tag>
<item>
- <p>This functionality works together with the flags
- <c>ber</c>. It enables the
+ <p>This functionality works together with the
+ <c>ber</c> option. It enables the
specialized decodes, see the <seealso marker="asn1_spec">Specialized Decode</seealso> chapter.
</p>
</item>
<tag><c>+undec_rest</c></tag>
<item>
- <p>A buffer that holds a message, being decoded may
- also have some following bytes. Now it is possible to get
- those following bytes returned together with the decoded
- value. If an asn1 spec is compiled with this option a tuple
- <c>{ok,Value,Rest}</c> is returned. <c>Rest</c> may be a
- list or a binary. Earlier versions of the compiler ignored
- those following bytes.</p>
+ <p>A buffer that holds a message being decoded may also have
+ trailing bytes. If those trailing bytes are important they
+ can be returned along with the decoded value by compiling
+ the ASN.1 specification with the <c>+undec_rest</c> option.
+ The return value from the decoder will be
+ <c>{ok,Value,Rest}</c> where <c>Rest</c> is a binary
+ containing the trailing bytes.</p>
</item>
<tag><c>+'Any Erlc Option'</c></tag>
<item>
<p>You may add any option to the Erlang compiler when
compiling the generated Erlang files. Any option
- unrecognised by the asn1 compiler will be passed to the
+ unrecognized by the ASN.1 compiler will be passed to the
Erlang compiler.</p>
</item>
</taglist>
@@ -374,35 +335,15 @@ asn1ct:compile("H323-MESSAGES.asn1",[ber]). </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"}).
-asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
- <p>Or, preferable like:</p>
- <pre>
'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}).
'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre>
</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
- <seealso marker="asn1rt"> the Asn1 Reference Manual</seealso>, the <c>asn1rt</c> module.</p>
- <p>The generic run-time encode and decode functions can be invoked as below:</p>
- <pre>
-asn1rt:encode('H323-MESSAGES','SomeChoiceType',{call,"octetstring"}).
-asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
- <p>Or, preferable like:</p>
- <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</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
- to load the nif separately by loading the <c>asn1rt_nif</c> module.</p>
+ <p>When an ASN.1 specification is compiled with the <c>ber</c>
+ option, the module <c>asn1rt_nif</c> module and the NIF library in
+ <c>asn1/priv_dir</c> will be needed at run-time.</p>
<p>By invoking the function <c>info/0</c> in a generated module, one
gets information about which compiler options were used.</p>
</section>
@@ -413,9 +354,9 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
compile time appear on the screen together with
a line number indicating where in the source file the error
was detected. If no errors are found, an Erlang ASN.1 module will
- be created as default.</p>
- <p>The run-time encoders and decoders (in the <c>asn1rt</c> module) do
- execute within a catch and returns <c>{ok, Data}</c> or
+ be created.</p>
+ <p>The run-time encoders and decoders execute within a catch and
+ returns <c>{ok, Data}</c> or
<c>{error, {asn1, Description}}</c> where
<c>Description</c> is
an Erlang term describing the error. </p>
@@ -424,18 +365,18 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<section>
<marker id="inlineExamples"></marker>
- <title>Multi File Compilation</title>
- <p>There are various reasons for using a multi file compilation:</p>
+ <title>Multi-file Compilation</title>
+ <p>There are various reasons for using multi-file compilation:</p>
<list type="bulleted">
- <item>You want to choose name for the generated module by
- any reason. Maybe you need to compile the same specs for
- different encoding/decoding standards.</item>
+ <item>You want to choose the name for the generated module,
+ perhaps because you need to compile the same specs for
+ different encoding rules.</item>
<item>You want only one resulting module.</item>
</list>
- <p>You need to specify which asn1 specs you will
+ <p>You need to specify which ASN.1 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
+ names of the ASN.1 specs. For instance, if you have the specs
<c>File1.asn</c>, <c>File2.asn</c> and <c>File3.asn</c> your
module <c>MyModule.set.asn</c> will look like:</p>
<pre>
@@ -446,11 +387,45 @@ 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.
+ the generated code from the three ASN.1 specs.
</p>
</section>
<section>
+ <title>A quick note about tags</title>
+
+ <p>Tags used to be important for all users of ASN.1, because it
+ was necessary to manually add tags to certain constructs in order
+ for the ASN.1 specification to be valid. Here is an example of
+ an old-style specification:</p>
+
+ <pre>
+Tags DEFINITIONS ::=
+BEGIN
+ Afters ::= CHOICE { cheese [0] IA5String,
+ dessert [1] IA5String }
+END </pre>
+
+ <p>Without the tags (the numbers in square brackets) the ASN.1
+ compiler would refuse to compile the file.</p>
+
+ <p>In 1994 the global tagging mode AUTOMATIC TAGS was introduced.
+ By putting AUTOMATIC TAGS in the module header, the ASN.1 compiler
+ will automatically add tags when needed. Here is the same
+ specification in AUTOMATIC TAGS mode:</p>
+
+ <pre>
+Tags DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+ Afters ::= CHOICE { cheese IA5String,
+ dessert IA5String }
+END
+</pre>
+
+ <p>Tags will not be mentioned any more in this manual.</p>
+ </section>
+
+ <section>
<marker id="ASN1Types"></marker>
<title>The ASN.1 Types</title>
<p>This section describes the ASN.1 types including their
@@ -521,7 +496,7 @@ Operational ::= BOOLEAN --ASN.1 definition </pre>
<p>In Erlang code it may look like:</p>
<pre>
Val = true,
-{ok,Bytes}=asn1rt:encode(MyModule,'Operational',Val), </pre>
+{ok,Bytes} = MyModule:encode('Operational', Val), </pre>
<p>Below follows a description of how
values of each type can be represented in Erlang.
</p>
@@ -587,20 +562,18 @@ T6value3 = white
<section>
<marker id="REAL"></marker>
<title>REAL</title>
- <p>In this version reals are not implemented. When they are,
- the following
- ASN.1 type is used:</p>
+ <p>The following ASN.1 type is used for real numbers:</p>
<pre>
R1 ::= REAL
</pre>
- <p>Can be assigned a value in Erlang as:</p>
+ <p>It can be assigned a value in Erlang as:</p>
<pre>
-R1value1 = 2.14,
+R1value1 = "2.14",
R1value2 = {256,10,-2},
</pre>
<p>In the last line note that the tuple {256,10,-2} is the real number
2.56 in a special notation, which will encode faster than simply
- stating the number as 2.56. The arity three tuple is
+ stating the number as <c>"2.56"</c>. The arity three tuple is
<c>{Mantissa,Base,Exponent}</c> i.e. Mantissa * Base^Exponent.</p>
</section>
@@ -653,7 +626,7 @@ Day1 = saturday,
Bits1 ::= BIT STRING
Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}
</pre>
- <p>There are five different notations available for representation of
+ <p>There are two notations available for representation of
BIT STRING values in Erlang and as input to the encode functions.</p>
<list type="ordered">
<item>A bitstring. By default, a BIT STRING with no
@@ -661,43 +634,10 @@ Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}
<item>A list of atoms corresponding to atoms in the <c>NamedBitList</c>
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 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>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>
+ <p>Example:</p>
<pre>
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;},
-Bits1Val4 = [0,1,0,1,1]
- </pre>
- <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 = &lt;&lt;2#1110:4&gt;&gt;,
Bits2Val3 = [bar,gnu,gnome],
@@ -708,37 +648,60 @@ Bits2Val3 = [bar,gnu,gnome],
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><![CDATA[<<>>]]></c>, <c>[]</c>, or
- <c>0</c>.</p>
<p>BIT STRINGS may also be sub-typed with, for example, a SIZE
specification:</p>
<pre>
Bits3 ::= BIT STRING (SIZE(0..31)) </pre>
<p>This means that no bit higher than 31 can ever be set.</p>
+
+ <section>
+ <title>Deprecated representations for BIT STRING</title>
+ <p>In addition to the representations described above, the
+ following deprecated representations are available if the
+ specification has been compiled with the
+ <c>legacy_erlang_types</c> option:</p>
+ <list type="ordered">
+ <item>A list of binary digits (0 or 1). This format is
+ accepted as input to the encode functions, and a BIT STRING
+ will be decoded to this format if the
+ <em>legacy_bit_string</em> option has been given.
+ </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 format is
+ accepted as input to the encode functions, and a <c>BIT
+ STRING</c> will be decoded to this format if
+ <em>compact_bit_string</em> has been given.
+ </item>
+ <item>A hexadecimal number (or an integer). This format
+ should be avoided, since it is easy to misinterpret a BIT
+ STRING value in this format.
+ </item>
+ </list>
+ </section>
</section>
<section>
<marker id="OCTET STRING"></marker>
<title>OCTET STRING</title>
- <p>The OCTET STRING is the simplest of all ASN.1 types The OCTET STRING
- only moves or transfers e.g. binary files or other unstructured
- information complying to two rules.
- Firstly, the bytes consist of octets and secondly, encoding is
- not required.</p>
+ <p>The OCTET STRING is the simplest of all ASN.1 types. The
+ OCTET STRING only moves or transfers e.g. binary files or other
+ unstructured information complying to two rules. Firstly, the
+ bytes consist of octets and secondly, encoding is not
+ required.</p>
<p>It is possible to have the following ASN.1 type definitions:</p>
<pre>
O1 ::= OCTET STRING
O2 ::= OCTET STRING (SIZE(28)) </pre>
<p>With the following example assignments in Erlang:</p>
<pre>
-O1Val = [17,13,19,20,0,0,255,254],
-O2Val = "must be exactly 28 chars....", </pre>
- <p>Observe that <c>O1Val</c> is assigned a series of numbers between 0
- and 255 i.e. octets.
- <c>O2Val</c> is assigned using the string notation.
- </p>
+O1Val = &lt;&lt;17,13,19,20,0,0,255,254&gt;&gt;,
+O2Val = &lt;&lt;"must be exactly 28 chars...."&gt;&gt;,</pre>
+ <p>By default, an OCTET STRING is always represented as
+ an Erlang binary. If the specification has been compiled with
+ the <c>legacy_erlang_types</c> option, the encode functions
+ will accept both lists and binaries, and the decode functions
+ will decode an OCTET STRING to a list.</p>
</section>
<section>
@@ -770,13 +733,11 @@ O2Val = "must be exactly 28 chars....", </pre>
specified for a type are especially important for PER, where
they affect the encoding.
</p>
- <p>Please note that <em>all</em> the Character strings are
- supported and it is possible to use the following ASN.1 type
- definitions:</p>
+ <p>Here are some examples:</p>
<pre>
Digs ::= NumericString (SIZE(1..3))
TextFile ::= IA5String (SIZE(0..64000)) </pre>
- <p>and the following Erlang assignments:</p>
+ <p>with corresponding Erlang assignments:</p>
<pre>
DigsVal1 = "456",
DigsVal2 = "123",
@@ -789,70 +750,86 @@ TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]
characters are all represented by quadruples beginning with
three zeros like {0,0,0,65} for the 'A' character. When
decoding a value for these strings the result is a list of
- quadruples, or integers when the value is an ASCII character.
- 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</c>
- option)the input/output format will be:</p>
+ quadruples, or integers when the value is an ASCII character.</p>
+
+ <p>The following example shows how it works. We have the following
+ specification in the file <c>PrimStrings.asn1</c>.</p>
+ <pre>
+PrimStrings DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+ BMP ::= BMPString
+END
+ </pre>
+
+ <p>Encoding and decoding some strings:</p>
+
<pre>
-1> <input>{ok,Bytes1} = asn1rt:encode('PrimStrings','BMP',[{0,0,53,53},{0,0,45,56}]).</input>
-{ok,[30,4,"55-8"]}
-2> <input>asn1rt:decode('PrimStrings','BMP',list_to_binary(Bytes1)).</input>
+1> <input>asn1ct:compile('PrimStrings', [ber]).</input>
+ok
+2> <input>{ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]).</input>
+{ok,&lt;&lt;30,4,53,54,45,56>>}
+3> <input>'PrimStrings':decode('BMP', Bytes1).</input>
{ok,[{0,0,53,53},{0,0,45,56}]}
-3> <input>{ok,Bytes2} = asn1rt:encode('PrimStrings','BMP',[{0,0,53,53},{0,0,0,65}]).</input>
-{ok,[30,4,[53,53,0,65]]}
-4> <input>asn1rt:decode('PrimStrings','BMP',list_to_binary(Bytes2)).</input>
+4> <input>{ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]).</input>
+{ok,&lt;&lt;30,4,53,53,0,65>>}
+5> <input>'PrimStrings':decode('BMP', Bytes2).</input>
{ok,[{0,0,53,53},65]}
-5> <input>{ok,Bytes3} = asn1rt:encode('PrimStrings','BMP',"BMP string").</input>
-{ok,[30,20,[0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103]]}
-6> <input>asn1rt:decode('PrimStrings','BMP',list_to_binary(Bytes3)).</input>
+6> <input>{ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string").</input>
+{ok,&lt;&lt;30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>}
+7> <input>'PrimStrings':decode('BMP', Bytes3).</input>
{ok,"BMP string"} </pre>
- <p>The UTF8String is represented in Erlang as a list of integers,
- where each integer represents the unicode value of one
- character. When a value shall be encoded one first has to
- transform it to a UTF8 encoded binary, then it can be encoded by
- asn1. When decoding the result is a UTF8 encoded binary, which
- may be transformed to an integer list. The transformation
- functions, <c>utf8_binary_to_list</c> and
- <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>
+
+ <p>The UTF8String type is represented as a UTF-8 encoded binary in
+ Erlang. Such binaries can be created directly using the binary syntax
+ or by converting from a list of Unicode code points using the
+ <c>unicode:characters_to_binary/1</c> function.</p>
+
+ <p>Here are some examples showing how UTF-8 encoded binaries can
+ be created and manipulated:</p>
+
+ <pre>
+1> <input>Gs = "Мой маленький Гном".</input>
+[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
+ 1081,32,1043,1085,1086,1084]
+2> <input>Gbin = unicode:characters_to_binary(Gs).</input>
+&lt;&lt;208,156,208,190,208,185,32,208,188,208,176,208,187,208,
+ 181,208,189,209,140,208,186,208,184,208,185,32,208,147,
+ 208,...>>
+3> <input>Gbin = &lt;&lt;"Мой маленький Гном"/utf8>>.</input>
+&lt;&lt;208,156,208,190,208,185,32,208,188,208,176,208,187,208,
+ 181,208,189,209,140,208,186,208,184,208,185,32,208,147,
+ 208,...>>
+4> <input>Gs = unicode:characters_to_list(Gbin).</input>
+[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
+ 1081,32,1043,1085,1086,1084]
+ </pre>
+
+ <p>See the <seealso marker="stdlib:unicode">unicode</seealso> module
+ for more details.</p>
+
+ <p>In the following example we will use this ASN.1 specification:</p>
+ <pre>
+UTF DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+ UTF ::= UTF8String
+END
+ </pre>
+
+ <p>Encoding and decoding a string with Unicode characters:</p>
+
<pre>
-1> <input>asn1ct:compile('UTF',[ber]).</input>
-Erlang ASN.1 version "1.4.3.3" compiling "UTF.asn"
-Compiler Options: [ber]
---{generated,"UTF.asn1db"}--
---{generated,"UTF.erl"}--
+5> <input>asn1ct:compile('UTF', [ber]).</input>
ok
-2> <input>UTF8Val1 = "hello".</input>
-"hello"
-3> <input>{ok,UTF8bin1} = asn1rt:utf8_list_to_binary(UTF8Val1).</input>
-{ok,&lt;&lt;104,101,108,108,111&gt;&gt;}
-4> <input>{ok,B}='UTF':encode('UTF',UTF8bin1).</input>
-{ok,[12,
- 5,
- &lt;&lt;104,101,108,108,111&gt;&gt;]}
-5> <input>Bin = list_to_binary(B).</input>
-&lt;&lt;12,5,104,101,108,108,111&gt;&gt;
-6> <input>{ok,UTF8bin1}='UTF':decode('UTF',Bin).</input>
-{ok,&lt;&lt;104,101,108,108,111&gt;&gt;}
-7> <input>asn1rt:utf8_binary_to_list(UTF8bin1).</input>
-{ok,"hello"}
-8> <input>UTF8Val2 = [16#00,16#100,16#ffff,16#ffffff].</input>
-[0,256,65535,16777215]
-9> <input>{ok,UTF8bin2} = asn1rt:utf8_list_to_binary(UTF8Val2).</input>
-{ok,&lt;&lt;0,196,128,239,191,191,248,191,191,191,191&gt;&gt;}
-10> <input>{ok,B2} = 'UTF':encode('UTF',UTF8bin2).</input>
-{ok,[12,
- 11,
- &lt;&lt;0,196,128,239,191,191,248,191,191,191,191&gt;&gt;]}
-11> <input>Bin2 = list_to_binary(B2).</input>
-&lt;&lt;12,11,0,196,128,239,191,191,248,191,191,191,191&gt;&gt;
-12> <input>{ok,UTF8bin2} = 'UTF':decode('UTF',Bin2).</input>
-{ok,&lt;&lt;0,196,128,239,191,191,248,191,191,191,191&gt;&gt;}
-13> <input>asn1rt:utf8_binary_to_list(UTF8bin2).</input>
-{ok,[0,256,65535,16777215]}
-14> </pre>
+6> <input>{ok,Bytes1} = 'UTF':encode('UTF', &lt;&lt;"Гном"/utf8>>).</input>
+{ok,&lt;&lt;12,8,208,147,208,189,208,190,208,188>>}
+7> <input>{ok,Bin1} = 'UTF':decode('UTF', Bytes1).</input>
+{ok,&lt;&lt;208,147,208,189,208,190,208,188>>}
+8> <input>io:format("~ts\n", [Bin1]).</input>
+Гном
+ok
+9> <input>unicode:characters_to_list(Bin1).</input>
+[1043,1085,1086,1084]
+ </pre>
</section>
<section>
@@ -887,9 +864,11 @@ OidVal1 = {1,2,55},
<section>
<marker id="Object Descriptor"></marker>
<title>Object Descriptor</title>
- <p>Values of this type can be assigned a value as an ordinary string i.e. <br></br>
+ <p>Values of this type can be assigned a value as an ordinary string
+ like this:</p>
- "This is the value of an Object descriptor"</p>
+ <pre>
+ "This is the value of an Object descriptor"</pre>
</section>
<section>
@@ -932,19 +911,31 @@ Pdu ::= SEQUENCE {
<pre>
MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}. </pre>
<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>
-</p>
- <p>A <c>SEQUENCE</c> and a <c>SET</c> may contain a component with a
- <c>DEFAULT</c> key word followed by the actual value that is the
- default value. In case of BER encoding it is optional to encode the
- value if it equals the default value. If the application uses the
- atom asn1_DEFAULT as value or if the value is a primitive value
- that equals the default value the encoding omits the bytes for
- this value, which is more efficient and it results in fever
- bytes to send to the receiving application.</p>
- <p>For instance, if the following types exists in a file "File.asn":</p>
+ a <c>SEQUENCE</c> or a <c>SET</c>.</p>
+
+ <p>A <c>SEQUENCE</c> and a <c>SET</c> may contain a component
+ with a <c>DEFAULT</c> key word followed by the actual value that
+ is the default value. The <c>DEFAULT</c> keyword means that the
+ application doing the encoding can omit encoding of the value,
+ thus resulting in fewer bytes to send to the receiving
+ application.</p>
+
+ <p>An application can use the atom <c>asn1_DEFAULT</c> to indicate
+ that the encoding should be omitted for that position in
+ the SEQUENCE.</p>
+
+ <p>Depending on the encoding rules, the encoder may also compare
+ the given value to the default value and automatically omit the
+ encoding if they are equal. How much effort the encoder makes to
+ to compare the values depends on the encoding rules. The DER
+ encoding rules forbids encoding a value equal to the default value,
+ so it has a more thorough and time-consuming comparison than the
+ encoders for the other encoding rules.</p>
+
+ <p>In the following example we will use this ASN.1 specification:</p>
<pre>
+File DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
Seq1 ::= SEQUENCE {
a INTEGER DEFAULT 1,
b Seq2 DEFAULT {aa TRUE, bb 15}
@@ -954,131 +945,50 @@ Seq2 ::= SEQUENCE {
aa BOOLEAN,
bb INTEGER
}
- </pre>
- <p>Some values and the corresponding encoding in an Erlang terminal
- is shown below:</p>
+
+Seq3 ::= SEQUENCE {
+ bs BIT STRING {a(0), b(1), c(2)} DEFAULT {a, c}
+}
+END </pre>
+ <p>Here is an example where the BER encoder is able to omit encoding
+ of the default values:</p>
<pre>
-1> <input>asn1ct:compile('File').</input>
-Erlang ASN.1 version "1.3.2" compiling "File.asn1"
-Compiler Options: []
---{generated,"File.asn1db"}--
---{generated,"File.hrl"}--
---{generated,"File.erl"}--
+1> <input>asn1ct:compile('File', [ber]).</input>
ok
-2> <input>'File':encode('Seq1',{'Seq1',asn1_DEFAULT,asn1_DEFAULT}).</input>
-{ok,["0",[0],[[],[]]]}
-3> <input>lists:flatten(["0",[0],[[],[]]]).</input>
-[48,0]
-4> <input>'File':encode('Seq1',{'Seq1',1,{'Seq2',true,15}}).</input>
-{ok,["0","\\b",[[],["\\241",[6],[[[128],[1],"\\377"],[[129],[1],[15]]]]]]}
-5> <input>lists:flatten(["0","\\b",[[],["\\241",[6],[[[128],[1],"\\377"],[[129],[1],[15]]]]]]).</input>
-[48,8,161,6,128,1,255,129,1,15]
-6> </pre>
- <p>The result after command line 3, in the example above,shows that the
- encoder omits the encoding of default values when they are specific
- by asn1_DEFAULT. Line 5 shows that even primitive values that equals
- the default value are detected and not encoded. But the constructed
- value of component <c>b</c> in <c>Seq1</c> is not recognized as the
- default value. Checking of default values in <c>BER</c> is not done
- in case of complex values, because it would be to expensive.
- <marker id="DEFAULT DER"></marker>
-</p>
- <p>But, the DER encoding format has stronger requirements regarding
- default values both for SET and SEQUENCE. A more elaborate and time
- expensive check of default values will take place. The following is
- an example with the same types and values as above but with der
- encoding format.</p>
- <pre>
-1> <input>asn1ct:compile('File',[der]).</input>
-Erlang ASN.1 version "1.3.2" compiling "File.asn1"
-Compiler Options: [der]
---{generated,"File.asn1db"}--
---{generated,"File.hrl"}--
---{generated,"File.erl"}--
+2> <input>'File':encode('Seq1', {'Seq1',asn1_DEFAULT,asn1_DEFAULT}).</input>
+{ok,&lt;&lt;48,0>>}
+3> <input>'File':encode('Seq1', {'Seq1',1,{'Seq2',true,15}}).</input>
+{ok,&lt;&lt;48,0>>} </pre>
+
+ <p>And here is an example with a named BIT STRING where the BER
+ encoder will not omit the encoding:</p>
+ <pre>
+4> <input>'File':encode('Seq3', {'Seq3',asn1_DEFAULT).</input>
+{ok,&lt;&lt;48,0>>}
+5> <input>'File':encode('Seq3', {'Seq3',&lt;&lt;16#101:3>>).</input>
+{ok,&lt;&lt;48,4,128,2,5,160>>} </pre>
+
+ <p>The DER encoder will omit the encoding for the same BIT STRING:</p>
+ <pre>
+6> <input>asn1ct:compile('File', [ber,der]).</input>
ok
-2> <input>'File':encode('Seq1',{'Seq1',asn1_DEFAULT,asn1_DEFAULT}).</input>
-{ok,["0",[0],[[],[]]]}
-3> <input>lists:flatten(["0",[0],[[],[]]]).</input>
-[48,0]
-4> <input>'File':encode('Seq1',{'Seq1',1,{'Seq2',true,15}}).</input>
-{ok,["0",[0],[[],[]]]}
-5> <input>lists:flatten(["0",[0],[[],[]]]).</input>
-[48,0]
-6>
- </pre>
- <p>Line 5 shows that even values of constructed types is checked and if
- it equals the default value it will not be encoded.</p>
+7> <input>'File':encode('Seq3', {'Seq3',asn1_DEFAULT).</input>
+{ok,&lt;&lt;48,0>>}
+8> <input>'File':encode('Seq3', {'Seq3',&lt;&lt;16#101:3>>).</input>
+{ok,&lt;&lt;48,0>>} </pre>
</section>
<section>
<marker id="SET"></marker>
<title>SET</title>
- <p>The SET type is an unusual construct and normally the SEQUENCE
- type is more appropriate to use. Set is also inefficient compared with SEQUENCE, as the components can be in any order. Hence, it must be possible
- to distinguish every component in 'SET', both when
- encoding and decoding a value of a type defined to be a SET.
- The tags of all components must be different from each other
- in order to be easily recognizable.</p>
- <p>A SET may be defined as:</p>
- <pre>
-Pdu2 ::= SET {
- a INTEGER,
- b BOOLEAN,
- c ENUMERATED {on(0),off(1)} } </pre>
- <p>A SET is represented as an Erlang record.
- For each SEQUENCE and <c>SET</c> in
- an ASN.1 module an Erlang record declaration is generated. For
- <c>Pdu2</c> above a record is defined like this:</p>
- <pre>
--record('Pdu2',{a, b, c}). </pre>
- <p>The record declarations for a module <c>M</c> are placed in a
- separate <c>M.hrl</c> file.</p>
- <p>Values can be assigned in Erlang as demonstrated below:</p>
- <pre>
-V = #'Pdu2'{a=44,b=false,c=off}. </pre>
- <p>The decode functions will return a record as result when decoding
- a SET.
- </p>
- <p>The difference between SET and SEQUENCE is that the order of
- the components (in the BER encoded format) is undefined for SET
- and defined as the lexical order from the ASN.1 definition for
- SEQUENCE. The ASN.1 compiler for Erlang will always encode a
- SET in the lexical order. The decode routines can handle SET
- components encoded in any order but will always return the
- result as a record. Since all components of the SET must be
- distinguishable both in the encoding phase as well as the
- decoding phase the following type is not allowed in a module
- with EXPLICIT or IMPLICIT as tag-default :</p>
- <p></p>
- <pre>
-Bad ::= SET {i INTEGER,
- j INTEGER } </pre>
- <p>The ASN.1 to Erlang compiler rejects the above type. We
- shall not explain the concept of tag further here, we refer to
- [<cite id="X.680"></cite>].
- </p>
- <p>Encoding of a SET with components with DEFAULT values behaves
- similar as a SEQUENCE, <seealso marker="#DEFAULT">see above</seealso>. The DER encoding format restrictions on DEFAULT
- values is the same for SET as for SEQUENCE, and is supported by
- the compiler, <seealso marker="#DEFAULT DER">see above</seealso>.</p>
- <p>Moreover, in DER the elements of a SET will be sorted. If a
- component is an un-tagged choice the sorting have to take place
- in run-time. This fact emphasizes the following recommendation
- if DER encoding format is used.</p>
- <p>The concept of SET is an unusual
- construct and one cannot think of one single application
- where the set type is essential. (Imagine if someone
- "invented'' the shuffled array in 'C') People tend to think
- that 'SET' sounds nicer and more mathematical than 'SEQUENCE'
- and hence use it when 'SEQUENCE' would have been more
- appropriate. It is also most inefficient, since every correct
- implementation of SET must always be prepared to accept the
- components in any order. So, if possible use SEQUENCE instead
- of SET.</p>
+ <p>In Erlang, the SET type is used exactly as SEQUENCE. Note
+ that if the BER or DER encoding rules are used, decoding a
+ SET is slower than decoding a SEQUENCE because the components
+ must be sorted.</p>
</section>
<section>
- <title>Notes about Extend-ability for SEQUENCE and SET</title>
+ <title>Notes about extensibility for SEQUENCE and SET</title>
<p>When a SEQUENCE or SET contains an extension marker and
extension components like this:</p>
<pre>
@@ -1105,51 +1015,28 @@ SExt ::= SEQUENCE {
<marker id="CHOICE"></marker>
<title>CHOICE</title>
<p>The CHOICE type is a space saver and is similar to the concept of a
- 'union' in the C-language. As with the previous SET-type, the
- tags of all components of a CHOICE need to be distinct. If
- AUTOMATIC TAGS are defined for the module (which is
- preferable) the tags can be omitted completely in the ASN.1
- specification of a CHOICE.
- </p>
+ 'union' in the C language.</p>
<p>Assume:</p>
<pre>
+SomeModuleName DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
T ::= CHOICE {
- x [0] REAL,
- y [1] INTEGER,
- z [2] OBJECT IDENTIFIER }
- </pre>
+ x REAL,
+ y INTEGER,
+ z OBJECT IDENTIFIER }
+END </pre>
<p>It is then possible to assign values:</p>
<pre>
TVal1 = {y,17},
TVal2 = {z,{0,1,2}},
</pre>
- <p>A CHOICE value is always represented as the tuple
+ <p>A CHOICE value is always represented as the tuple
<c>{ChoiceAlternative, Val}</c> where <c>ChoiceAlternative</c>
- is an atom denoting the selected choice
- alternative.
- </p>
- <p>It is also allowed to have a CHOICE type tagged as follow:</p>
- <p></p>
- <pre>
-C ::= [PRIVATE 111] CHOICE {
- C1,
- C2 }
-
-C1 ::= CHOICE {
- a [0] INTEGER,
- b [1] BOOLEAN }
-
-C2 ::= CHOICE {
- c [2] INTEGER,
- d [3] OCTET STRING } </pre>
- <p>In this case, the top type C appears to have no tags at all in
- its components, however, both C1 and C2 are also defined as
- CHOICE types and they have distinct tags among themselves.
- Hence, the above type C is both legal and allowed.
+ is an atom denoting the selected choice alternative.
</p>
<section>
- <title>Extendable CHOICE</title>
+ <title>Extensible CHOICE</title>
<p>When a CHOICE contains an extension marker and the decoder detects
an unknown alternative of the CHOICE the value is represented as:</p>
<pre>
@@ -1226,26 +1113,29 @@ Arr2Val = ["abc",[14,34,54],"Octets"], </pre>
Where <c>Value</c> may be a value of yet another type T2.</p>
<p>For example:</p>
<pre>
+EmbeddedExample DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
B ::= SEQUENCE {
a Arr1,
- b [0] T }
+ b T }
Arr1 ::= SET SIZE (5) OF INTEGER (4..9)
T ::= CHOICE {
- x [0] REAL,
- y [1] INTEGER,
- z [2] OBJECT IDENTIFIER } </pre>
- <p>The above example can be assigned like this in Erlang:</p>
+ x REAL,
+ y INTEGER,
+ z OBJECT IDENTIFIER }
+ END </pre>
+ <p>The SEQUENCE b can be encoded like this in Erlang:</p>
<pre>
-V2 = #'B'{a=[4,5,6,7,8], b={x,7.77}}.
- </pre>
+1> 'EmbeddedExample':encode('B', {'B',[4,5,6,7,8],{x,"7.77"}}).
+{ok,&lt;&lt;5,56,0,8,3,55,55,55,46,69,45,50>>} </pre>
</section>
</section>
<section>
<title>Naming of Records in .hrl Files</title>
- <p>When an asn1 specification is compiled all defined types of
+ <p>When an ASN.1 specification is compiled all defined types of
type SET or SEQUENCE will result in a corresponding record in the
generated hrl file. This is because the values for SET/SEQUENCE
as mentioned in sections above are represented as records.</p>
@@ -1261,8 +1151,8 @@ V2 = #'B'{a=[4,5,6,7,8], b={x,7.77}}.
Emb ::= SEQUENCE {
a SEQUENCE OF OCTET STRING,
b SET {
- a [0] INTEGER,
- b [1] INTEGER DEFAULT 66},
+ a INTEGER,
+ b INTEGER DEFAULT 66},
c CHOICE {
a INTEGER,
b FooType } }
@@ -1333,7 +1223,7 @@ PType{T} ::= SEQUENCE{
<p>Types may refer to themselves. Suppose:</p>
<pre>
Rec ::= CHOICE {
- nothing [0] NULL,
+ nothing NULL,
something SEQUENCE {
a INTEGER,
b OCTET STRING,
@@ -1365,7 +1255,7 @@ tt TT ::= {a 77,b {"kalle","kula"}} </pre>
Firstly, it could be used as the value in some DEFAULT component:</p>
<pre>
SS ::= SET {
- s [0] OBJECT IDENTIFIER,
+ s OBJECT IDENTIFIER,
val TT DEFAULT tt } </pre>
<p>It could also be used from inside an Erlang program. If the above ASN.1
code was defined in ASN.1 module <c>Values</c>, then the ASN.1 value
@@ -1399,8 +1289,8 @@ SS ::= SET {
<marker id="Information Object"></marker>
<title>ASN.1 Information Objects (X.681)</title>
<p>Information Object Classes, Information Objects and Information
- Object Sets, (in the following called classes, objects and
- object sets respectively), are defined in the standard
+ Object Sets (in the following called classes, objects and
+ object sets respectively) are defined in the standard
definition [<cite id="X.681"></cite>]. In the following only a brief
explanation is given. </p>
<p>These constructs makes it possible to define open types,
@@ -1469,9 +1359,26 @@ StartMessage ::= SEQUENCE {
<p><c>StartMessage</c> can in the <c>content</c> field be
encoded with a value of any type that an object in the
<c>GENERAL-PROCEDURES</c> object set has in its <c>NEW MESSAGE</c> field. This field refers to a type field
- <c><![CDATA[&amp;Message]]></c> in the class. The <c>msgId</c> field is always
+ <c>&amp;Message</c> in the class. The <c>msgId</c> field is always
encoded as a PrintableString, since the field refers to a fixed type
in the class.</p>
+ <p>In practice, object sets are usually declared to be extensible so
+ so that more objects can be added to the set later. Extensibility is
+ indicated like this:</p>
+ <pre>
+GENERAL-PROCEDURES GENERAL-PROCEDURE ::= {
+ object1 | object2, ...} </pre>
+ <p>When decoding a type that uses an extensible set constraint,
+ there is always the possibility that the value in the UNIQUE
+ field is unknown (i.e. the type has been encoded with a later
+ version of the ASN.1 specification). When that happens, the
+ unencoded data will be returned wrapped in a tuple like this:</p>
+
+ <pre>
+{asn1_OPENTYPE,Binary}</pre>
+ <p>where <c>Binary</c> is an Erlang binary that contains the encoded
+ data. (If the option <c>legacy_erlang_types</c> has been given,
+ just the binary will be returned.)</p>
</section>
<section>
@@ -1483,7 +1390,7 @@ StartMessage ::= SEQUENCE {
instance, if a Type is used in a definition with certain
purpose, one want the type-name to express the intention. This
can be done with parameterization.</p>
- <p>When many types (or an other ASN.1 entity) only differs in some
+ <p>When many types (or another ASN.1 entity) only differs in some
minor cases, but the structure of the types are similar, only
one general type can be defined and the differences may be supplied
through parameters. </p>
@@ -1500,132 +1407,11 @@ T1 ::= General{PrintableString}
T2 ::= General{BIT STRING}
</pre>
<p>An example of a value that can be encoded as type T1 is {12,"hello"}.</p>
- <p>Observe that the compiler not generates encode/decode functions for
- parameterized types, only for the instances of the parameterized
- types. So, if a file contains the types General{}, T1 and T2 above,
+ <p>Note that the compiler does not generate encode/decode functions for
+ parameterized types, but only for the instances of the parameterized
+ types. Therefore, if a file contains the types General{}, T1 and T2 above,
encode/decode functions will only be generated for T1 and T2.
</p>
</section>
-
- <section>
- <title>Tags</title>
- <p>Every built-in ASN.1 type, except CHOICE and ANY have a universal tag.
- This is a unique number that clearly identifies the type. <br></br>
-
- It is essential for all users of ASN.1 to
- understand all the details about tags.</p>
- <p>Tags are implicitly encoded in the BER encoding as shown below, but
- are hardly not accounted for in the PER encoding. In PER tags are
- used for instance to sort the components of a SET.</p>
- <p>There are four different types of tags.</p>
- <taglist>
- <tag><em>universal</em></tag>
- <item>
- <p>For types whose meaning is the same in all
- applications. Such as integers, sequences and so on; that is, all the built in
- types.</p>
- </item>
- <tag><em>application</em></tag>
- <item>
- <p>For application specific types for example, the types in
- X.400 Message handling service have this sort of tag.</p>
- </item>
- <tag><em>private</em></tag>
- <item>
- <p>For your own private types.</p>
- </item>
- <tag><em>context</em></tag>
- <item>
- <p>This is used to distinguish otherwise indistinguishable
- types in a specific context. For example, if we have two
- components of a
- CHOICE type that are both <c>INTEGER</c> values, there is no
- way for the decoder to
- decipher which component was actually chosen, since both
- components will be
- tagged as <c>INTEGER</c>. When this or similar situations occur,
- one or both of the components should be given a context specific
- to resolve the ambiguity.</p>
- </item>
- </taglist>
- <p>The tag in the case of the 'Apdu' type [PRIVATE 1] is encoded to a
- sequence of bytes making it possible for a
- decoder to look at the (initial) bytes that arrive and determine
- whether the rest of the bytes must be of the type associated
- with that particular sequence of bytes. This means that each
- tag must be uniquely associated with <em>only</em> one ASN.1
- type.
- </p>
- <p>Immediately following the tag is a sequence of bytes
- informing the decoder of the length of the instance. This is
- sometimes referred to as TLV (Tag length value) encoding.
- Hence, the structure of a BER encoded series of bytes is as shown in the table below.</p>
- <p></p>
- <table>
- <row>
- <cell align="left" valign="middle">Tag</cell>
- <cell align="left" valign="middle">Len</cell>
- <cell align="left" valign="middle">Value</cell>
- </row>
- <tcaption>Structure of a BER encoded series of bytes</tcaption>
- </table>
- </section>
-
- <section>
- <title>Encoding Rules</title>
- <p>When the first recommendation on ASN.1 was released 1988 it was
- accompanied with the Basic Encoding Rules, BER, as the only
- alternative for encoding.
- BER is a somewhat verbose protocol. It adopts a so-called TLV (type,
- length, value) approach to encoding in which every element of the
- encoding carries some type information, some length information and
- then the value of that element. Where the element is itself
- structured, then the Value part of the element is itself a series of
- embedded TLV components, to whatever depth is necessary. In summary,
- BER is not a compact encoding but is relatively fast and easy to
- produce.</p>
- <p>The DER (Distinguished Encoding Rule) encoding format was included in
- the standard in 1994. It is a specialized form of BER, which gives
- the encoder the option to encode some entities differently. For
- instance, is the value for TRUE any octet with any bit set to one. But,
- DER does not leave any such choices. The value for TRUE in the DER
- case is encoded as the octet <c>11111111</c>. So, the same value
- encoded by two different DER encoders must result in the same bit
- stream.</p>
- <p>A more compact encoding is achieved with the Packed Encoding
- Rules PER which was introduced together with the revised
- recommendation in 1994. PER takes a rather different approach from
- that taken by BER. The first difference is that the tag part in
- the TLV is omitted from the encodings, and any tags in the
- notation are not encoded. The potential ambiguities are resolved
- as follows:</p>
- <list type="bulleted">
- <item>
- <p>A CHOICE is encoded by first encoding a choice index which
- identifies the chosen
- alternative by its position in the notation.</p>
- </item>
- <item>
- <p>The elements of a SEQUENCE are transmitted in textual
- order. OPTIONAL or DEFAULT elements are preceded by a bit map
- to identify which elements are present. After sorting the
- elements of a SET in the "canonical tag order" as defined in
- X.680 8.6 they are treated as a SEQUENCE regarding OPTIONAL
- and DEFAULT elements. A SET is transferred in the sorted
- order.</p>
- </item>
- </list>
- <p>A second difference is that PER takes full account of the sub-typing
- information in that the encoded bytes are affected by the constraints.
- The BER encoded bytes are unaffected by the constraints.
- PER uses the sub-typing information to for example omit length fields
- whenever possible. </p>
- <p>The run-time functions, sometimes take the constraints into account
- both for BER and PER. For instance are SIZE constrained strings checked.</p>
- <p>There are two variants of PER, <em>aligned</em> and <em>unaligned</em>.
- In summary, PER results in compact encodings which require much more
- computation to produce than BER.
- </p>
- </section>
</chapter>
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index f04bac9fec..32ff2d52cf 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -42,6 +42,18 @@
can be used in during development of applications which handles ASN.1
data (encoded as BER or PER).</p>
<note>
+ <p>By default in OTP 17, the representation of the BIT STRING
+ and OCTET STRING types as Erlang terms have changed. BIT
+ STRING values are now Erlang bitstrings and OCTET STRING values
+ are binaries. Also, an undecoded open type will now be wrapped in
+ a <c>asn1_OPENTYPE</c> tuple. For details see <seealso
+ marker="asn1_ug#BIT STRING">BIT STRING</seealso>, <seealso
+ marker="asn1_ug#OCTET STRING">OCTET STRING</seealso>, and
+ <seealso marker="asn1_ug#Information%20Object">ASN.1 Information Objects</seealso> in User's Guide.</p>
+ <p>To revert to the old representation of the types, use the
+ <c>legacy_erlang_types</c> option.</p>
+ </note>
+ <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
@@ -50,7 +62,7 @@
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.
+ function always returns a binary.
The <c>encode/2</c> function for the BER back-end used to return
an iolist.</p>
</note>
@@ -64,9 +76,9 @@
<v>Asn1module = atom() | string()</v>
<v>Options = [Option| OldOption]</v>
<v>Option = ber | per | uper | der | compact_bit_string |
- legacy_bit_string |
+ legacy_bit_string | legacy_erlang_types |
noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} |
- asn1config | undec_rest |
+ asn1config | undec_rest | no_ok_wrapper |
{macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
@@ -163,6 +175,7 @@ File3.asn </pre>
BIT STRING type section in the Users Guide
</seealso>.
</p>
+ <p>This option implies the <c>legacy_erlang_types</c> option.</p>
</item>
<tag><c>legacy_bit_string</c></tag>
<item>
@@ -175,8 +188,19 @@ File3.asn </pre>
<seealso marker="asn1_ug#BIT STRING">
BIT STRING type section in the Users Guide
</seealso>.
+ <p>This option implies the <c>legacy_erlang_types</c> option.</p>
</p>
</item>
+ <tag><c>legacy_erlang_types</c></tag>
+ <item>
+ <p>Use the same Erlang types to represent BIT STRING and
+ OCTET STRING as in R16. For details see <seealso
+ marker="asn1_ug#BIT STRING">BIT STRING</seealso> and
+ <seealso marker="asn1_ug#OCTET STRING">OCTET
+ STRING</seealso> in User's Guide.</p>
+ <p><em>This option is not recommended for
+ new code.</em></p>
+ </item>
<tag><c>{n2n, EnumTypeName}</c></tag>
<item>
<p>
@@ -238,6 +262,13 @@ File3.asn </pre>
list or a binary. Earlier versions of the compiler ignored
those following bytes.</p>
</item>
+ <tag><c>no_ok_wrapper</c></tag>
+ <item>
+ <p>If this option is given, the generated <c>encode/2</c>
+ and <c>decode/2</c> functions will not wrap a successful
+ return value in an <c>{ok,...}</c> tuple. If any error
+ occurs, there will be an exception.</p>
+ </item>
<tag><c>{macro_name_prefix, Prefix}</c></tag>
<item>
<p>All macro names generated by the compiler are prefixed with
@@ -296,6 +327,8 @@ File3.asn </pre>
not always checked. Returns <c>{ok, Bytes}</c> if successful or
<c>{error, Reason}</c> if an error occurred.
</p>
+ <p>This function is deprecated.
+ Use <c>Module:encode(Type, Value)</c> instead.</p>
</desc>
</func>
<func>
@@ -309,6 +342,8 @@ File3.asn </pre>
<desc>
<p>Decodes <c>Type</c> from <c>Module</c> from the binary
<c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p>
+ <p>This function is deprecated.
+ Use <c>Module:decode(Type, Bytes)</c> instead.</p>
</desc>
</func>
<func>
@@ -356,11 +391,11 @@ File3.asn </pre>
</item>
</list>
- <p>Schematically the following happens for each type in the module:
+ <p>Schematically the following happens for each type in the module:</p>
<code type="none">
{ok, Value} = asn1ct:value(Module, Type),
{ok, Bytes} = asn1ct:encode(Module, Type, Value),
-{ok, Value} = asn1ct:decode(Module, Type, Bytes).</code></p>
+{ok, Value} = asn1ct:decode(Module, Type, Bytes).</code>
<p>The <c>test</c> functions utilizes the <c>*.asn1db</c> files
for all included modules. If they are located in a different
diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml
index 2b1b108ab1..3cf56b01ca 100644
--- a/lib/asn1/doc/src/asn1rt.xml
+++ b/lib/asn1/doc/src/asn1rt.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -34,9 +34,12 @@
<module>asn1rt</module>
<modulesummary>ASN.1 runtime support functions</modulesummary>
<description>
- <p>This module is the interface module for the ASN.1 runtime support functions.
- To encode and decode ASN.1 types in runtime the functions in this module
- should be used.</p>
+ <warning>
+ <p>
+ All functions in this module are deprecated and will be
+ removed in a future release.
+ </p>
+ </warning>
</description>
<funcs>
@@ -52,6 +55,7 @@
<desc>
<p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>.
Returns <c>{ok,Value}</c> if successful.</p>
+ <p>Use <c>Module:decode(Type, Bytes)</c> instead of this function.</p>
</desc>
</func>
@@ -65,16 +69,13 @@
<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. 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>
+ <p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1
+ module <c>Module</c>. Returns a binary 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>
+ <p>Use <c>Module:encode(Type, Value)</c> instead of this function.</p>
</desc>
</func>
@@ -90,6 +91,7 @@
<p><c>info/1</c> returns the version of the asn1 compiler that was
used to compile the module. It also returns the compiler options
that was used.</p>
+ <p>Use <c>Module:info()</c> instead of this function.</p>
</desc>
</func>
@@ -106,6 +108,7 @@
to a list of integers, where each integer represents one
character as its unicode value. The function fails if the binary
is not a properly encoded UTF8 string.</p>
+ <p>Use <seealso marker="stdlib:unicode#characters_to_list-1">unicode:characters_to_list/1</seealso> instead of this function.</p>
</desc>
</func>
@@ -121,6 +124,7 @@
<p><c>utf8_list_to_binary/1</c> Transforms a list of integers,
where each integer represents one character as its unicode
value, to a UTF8 encoded binary.</p>
+ <p>Use <seealso marker="stdlib:unicode#characters_to_binary-1">unicode:characters_to_binary/1</seealso> instead of this function.</p>
</desc>
</func>
diff --git a/lib/asn1/doc/src/book.xml b/lib/asn1/doc/src/book.xml
index 718e6e7b17..2399267cb0 100644
--- a/lib/asn1/doc/src/book.xml
+++ b/lib/asn1/doc/src/book.xml
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE book SYSTEM "book.dtd">
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/asn1/doc/src/fascicules.xml b/lib/asn1/doc/src/fascicules.xml
index 2488e7b57e..837b4f57f4 100644
--- a/lib/asn1/doc/src/fascicules.xml
+++ b/lib/asn1/doc/src/fascicules.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
<fascicules>
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 4b5bba742c..9feb673c04 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -31,6 +31,298 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 3.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The ASN.1 compiler would crash if a SEQUENCE ended
+ with a double set of ellipses (<c>...</c>).</p>
+ <p>
+ Own Id: OTP-12546 Aux Id: seq12815 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 3.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When decoding BER, primitives with an indefinite length
+ will be immediately rejected. (Thanks to Simon Cornish
+ for reporting this bug.)</p>
+ <p>
+ Own Id: OTP-12205</p>
+ </item>
+ <item>
+ <p>
+ BER: A bug with compliance to X.680 (200811) s31.2.7 has
+ been fixed. Basically, when TagDefault is AUTOMATIC then
+ tags are IMPLICIT unless EXPLICIT is given.</p>
+ <p>
+ Own Id: OTP-12318</p>
+ </item>
+ <item>
+ <p>
+ Usage of the <c>EXTERNAL</c> 1994 variant type was
+ broken.</p>
+ <p>
+ Own Id: OTP-12326</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 3.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Several problems where the ASN.1 compiler would crash
+ when attempting to compile correct specifications have
+ been corrected.</p>
+ <p>
+ Own Id: OTP-12125</p>
+ </item>
+ <item>
+ <p>
+ Robustness when decoding incorrect BER messages has been
+ improved.</p>
+ <p>
+ Own Id: OTP-12145</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 3.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The ASN.1 compiler now generates code that don't trigger
+ Dialyzer warnings. Along the way, a few minor bugs were
+ fixed.</p>
+ <p>
+ Own Id: OTP-11372 Aux Id: seq12397 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 3.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Subtyping an extensible ENUMERATED would cause an
+ compilation error. (Thanks to Morten Nygaard Ã…snes for
+ reporting this bug.)</p>
+ <p>
+ Own Id: OTP-11700</p>
+ </item>
+ <item>
+ <p>When specifying the value for an OCTET STRING in a
+ specification, the ASN.1 standard clearly states that the
+ value must be either a bstring or an hstring, but NOT a
+ cstring. The ASN.1 compiler will now generate a
+ compilation error if the value of an OCTET STRING is
+ given as a character string.</p>
+ <p>That is, the following example is now illegal:</p>
+ <p><c>string OCTET STRING ::= "Now illegal"</c></p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-11727</p>
+ </item>
+ <item>
+ <p>
+ Application upgrade (appup) files are corrected for the
+ following applications: </p>
+ <p>
+ <c>asn1, common_test, compiler, crypto, debugger,
+ dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe,
+ inets, observer, odbc, os_mon, otp_mibs, parsetools,
+ percept, public_key, reltool, runtime_tools, ssh,
+ syntax_tools, test_server, tools, typer, webtool, wx,
+ xmerl</c></p>
+ <p>
+ A new test utility for testing appup files is added to
+ test_server. This is now used by most applications in
+ OTP.</p>
+ <p>
+ (Thanks to Tobias Schlager)</p>
+ <p>
+ Own Id: OTP-11744</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ By giving --enable-static-{nifs,drivers} to configure it
+ is now possible to statically linking of nifs and drivers
+ to the main Erlang VM binary. At the moment only the asn1
+ and crypto nifs of the Erlang/OTP nifs and drivers have
+ been prepared to be statically linked. For more details
+ see the Installation Guide in the System documentation.</p>
+ <p>
+ Own Id: OTP-11258</p>
+ </item>
+ <item>
+ <p>Code generation for the <c>per</c> and <c>uper</c>
+ backends has been somewhat improved.</p>
+ <p>
+ Own Id: OTP-11573</p>
+ </item>
+ <item>
+ <p>The OCTET STRING and BIT STRING types now have a more
+ natural mapping to Erlang types (binary and bitstring,
+ respectively), which is more efficient and will avoid
+ useless conversions between lists and
+ binaries/bitstrings.</p>
+ <p>This is an incompatible change. To revert to the old
+ mapping to support existing applications, use the
+ <c>legacy_erlang_types</c> option.</p>
+ <p>Impact: There is a potential for better performance,
+ as it is now possible to avoid conversions between lists
+ and binaries both in the generated ASN.1 encode/decode
+ code and in the application itself.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-11594</p>
+ </item>
+ <item>
+ <p>All functions in the <c>asn1rt</c> module, as well as
+ <c>asn1ct:decode/3</c> and <c>asn1ct:encode/3</c>, are
+ now deprecated.</p>
+ <p>
+ Own Id: OTP-11731</p>
+ </item>
+ <item>
+ <p>
+ Generated .hrl files are now protected from being
+ included more than once.</p>
+ <p>
+ Own Id: OTP-11804</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 2.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The default value for a <c>BIT STRING</c> would not
+ always be recognized, causing the encoding to be
+ incorrect for the DER/PER/UPER encodings.</p>
+ <p>
+ Own Id: OTP-11319</p>
+ </item>
+ <item>
+ <p>
+ The <c>asn1</c> application would fail to build if the
+ <c>.erlang</c> file printed something to standard output.</p>
+ <p>
+ Own Id: OTP-11360</p>
+ </item>
+ <item>
+ <p>An union of integer ranges in an INTEGER constraint
+ could sometimes be interpreted as the intersection of the
+ range.</p>
+ <p>
+ Own Id: OTP-11411 Aux Id: seq12443 </p>
+ </item>
+ <item>
+ <p>
+ Extensible, multiple single value constraints (such as
+ <c>INTEGER (1|17, ...)</c>) would be incorrectly encoded.</p>
+ <p>
+ Own Id: OTP-11415</p>
+ </item>
+ <item>
+ <p>
+ The ASN.1 compiler would fail to compile a constraint
+ with values given for for the extension part (such as
+ <c>INTEGER (1..10, ..., 11..20)</c>).</p>
+ <p>
+ Own Id: OTP-11504</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The new option '<c>no_ok_wrapper</c>' generates
+ M:encode/2 and M:decode/2 functions that don't wrap the
+ return value in an {ok,...} tuple.</p>
+ <p>
+ Own Id: OTP-11314</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 2.0.3</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>
+ <p>
+ Own Id: OTP-11262 Aux Id: seq12386, OTP-11223 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>For the PER and UPER formats, code generation
+ especially for encoding has been improved.</p>
+ <p>When encoding BIT STRINGs, values longer than the
+ maximum size for the BIT STRING type would be truncated
+ silently - they now cause an exception.</p>
+ <p>Open types greater than 16383 bytes will now be
+ correctly encoded and decoded.</p>
+ <p>IMPORTANT NOTE: For ASN.1 specifications that depend
+ on each other, such as the S1AP-* specifications, it is
+ important to recompile all specifications (compiling some
+ with this version of the compiler and some with an older
+ version will not work).</p>
+ <p>
+ Own Id: OTP-11300</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 2.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/doc/src/part.xml b/lib/asn1/doc/src/part.xml
index 19ee64b4a0..735ec2e616 100644
--- a/lib/asn1/doc/src/part.xml
+++ b/lib/asn1/doc/src/part.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE part SYSTEM "part.dtd">
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/asn1/doc/src/ref_man.xml b/lib/asn1/doc/src/ref_man.xml
index a0af1f5be3..0a0ed5416a 100644
--- a/lib/asn1/doc/src/ref_man.xml
+++ b/lib/asn1/doc/src/ref_man.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="iso-8859-1" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE application SYSTEM "application.dtd">
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 33cd3cc4c3..6798da0072 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -43,9 +43,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/asn1-$(VSN)
EBIN = ../ebin
-EVAL_CT_MODULES = asn1ct_eval_ext \
- asn1ct_eval_per \
- asn1ct_eval_uper
+EVAL_CT_MODULES = asn1ct_eval_ext
CT_MODULES= \
asn1ct \
@@ -54,8 +52,8 @@ CT_MODULES= \
asn1ct_pretty_format \
asn1ct_func \
asn1ct_gen \
+ asn1ct_gen_check \
asn1ct_gen_per \
- asn1ct_gen_per_rt2ct \
asn1ct_name \
asn1ct_constructed_per \
asn1ct_constructed_ber_bin_v2 \
@@ -138,7 +136,7 @@ $(EBIN)/asn1ct_func.$(EMULATOR): asn1ct_func.erl
asn1ct_eval_%.erl: asn1ct_eval_%.funcs
$(gen_verbose)erl -pa $(EBIN) -noshell -noinput \
- -run prepare_templates gen_asn1ct_eval $< >$@
+ -run prepare_templates gen_asn1ct_eval $<
$(APP_TARGET): $(APP_SRC) ../vsn.mk
$(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
@@ -183,7 +181,7 @@ 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
+ $(RT_TEMPLATES_TARGET)
prepare_templates.$(EMULATOR): prepare_templates.erl
$(V_ERLC) prepare_templates.erl
diff --git a/lib/asn1/src/asn1.app.src b/lib/asn1/src/asn1.app.src
index f2ee8deb75..02cbba0f10 100644
--- a/lib/asn1/src/asn1.app.src
+++ b/lib/asn1/src/asn1.app.src
@@ -10,5 +10,6 @@
asn1db
]},
{env, []},
- {applications, [kernel, stdlib]}
+ {applications, [kernel, stdlib]},
+ {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]}
]}.
diff --git a/lib/asn1/src/asn1.appup.src b/lib/asn1/src/asn1.appup.src
index 2d11eddfbf..e4b3508cc4 100644
--- a/lib/asn1/src/asn1.appup.src
+++ b/lib/asn1/src/asn1.appup.src
@@ -1,11 +1,21 @@
+%% -*- erlang -*-
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014. 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%
{"%VSN%",
-% This version does not change anything of the runtime modules
-% Only changes in compile time modules and thus no need for upgrade on target
-[
- ],
- [
- ]}.
-
-
-
-
+ [{<<".*">>,[{restart_application, asn1}]}],
+ [{<<".*">>,[{restart_application, asn1}]}]
+}.
diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl
index 869b36ddbd..48d9dd16d7 100644
--- a/lib/asn1/src/asn1_db.erl
+++ b/lib/asn1/src/asn1_db.erl
@@ -19,25 +19,37 @@
%%
-module(asn1_db).
--export([dbstart/1,dbnew/1,dbsave/2,dbput/3,dbget/2]).
+-export([dbstart/1,dbnew/2,dbload/1,dbload/3,dbsave/2,dbput/3,dbget/2]).
-export([dbstop/0]).
-record(state, {parent, monitor, includes, table}).
%% Interface
-dbstart(Includes) ->
+dbstart(Includes0) ->
+ Includes = case Includes0 of
+ [] -> ["."];
+ [_|_] -> Includes0
+ end,
Parent = self(),
undefined = get(?MODULE), %Assertion.
put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)),
ok.
-dbnew(Module) -> req({new, Module}).
+dbload(Module, Erule, Mtime) ->
+ req({load, Module, Erule, Mtime}).
+
+dbload(Module) ->
+ req({load, Module, any, {{0,0,0},{0,0,0}}}).
+
+dbnew(Module, Erule) -> req({new, Module, Erule}).
dbsave(OutFile, Module) -> cast({save, OutFile, Module}).
dbput(Module, K, V) -> cast({set, Module, K, V}).
dbget(Module, K) -> req({get, Module, K}).
dbstop() -> Resp = req(stop), erase(?MODULE), Resp.
%% Internal functions
+-define(MAGIC_KEY, '__version_and_erule__').
+
req(Request) ->
DbPid = get(?MODULE),
Ref = erlang:monitor(process,DbPid),
@@ -71,47 +83,57 @@ loop(#state{parent = Parent, monitor = MRef, table = Table,
ets:insert(Modtab, {K2, V}),
loop(State);
{From, {get, Mod, K2}} ->
- Result = case ets:lookup(Table, Mod) of
- [] -> opentab(Table, Mod, Includes);
- [{_, Modtab}] -> {ok, Modtab}
- end,
- case Result of
- {ok, Newtab} -> reply(From, lookup(Newtab, K2));
- _Error -> reply(From, undefined)
+ %% XXX If there is no information for Mod, get_table/3
+ %% will attempt to load information from an .asn1db
+ %% file, without comparing its timestamp against the
+ %% source file. This is known to happen when check_*
+ %% functions for DER are generated, but it could possibly
+ %% happen in other circumstances. Ideally, this issue should
+ %% be rectified in some way, perhaps by ensuring that
+ %% the module has been loaded (using dbload/4) prior
+ %% to calling dbget/2.
+ case get_table(Table, Mod, Includes) of
+ {ok,Tab} -> reply(From, lookup(Tab, K2));
+ error -> reply(From, undefined)
end,
loop(State);
{save, OutFile, Mod} ->
[{_,Mtab}] = ets:lookup(Table, Mod),
ok = ets:tab2file(Mtab, OutFile),
loop(State);
- {From, {new, Mod}} ->
+ {From, {new, Mod, Erule}} ->
[] = ets:lookup(Table, Mod), %Assertion.
ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []),
ets:insert(Table, {Mod, ModTableId}),
+ ets:insert(ModTableId, {?MAGIC_KEY, info(Erule)}),
reply(From, ok),
loop(State);
+ {From, {load, Mod, Erule, Mtime}} ->
+ case ets:member(Table, Mod) of
+ true ->
+ reply(From, ok);
+ false ->
+ case load_table(Mod, Erule, Mtime, Includes) of
+ {ok, ModTableId} ->
+ ets:insert(Table, {Mod, ModTableId}),
+ reply(From, ok);
+ error ->
+ reply(From, error)
+ end
+ end,
+ loop(State);
{From, stop} ->
reply(From, stopped); %% Nothing to store
{'DOWN', MRef, process, Parent, Reason} ->
exit(Reason)
end.
-opentab(Tab, Mod, []) ->
- opentab(Tab, Mod, ["."]);
-opentab(Tab, Mod, Includes) ->
- Base = lists:concat([Mod, ".asn1db"]),
- opentab2(Tab, Base, Mod, Includes, ok).
-
-opentab2(_Tab, _Base, _Mod, [], Error) ->
- Error;
-opentab2(Tab, Base, Mod, [Ih|It], _Error) ->
- File = filename:join(Ih, Base),
- case ets:file2tab(File) of
- {ok, Modtab} ->
- ets:insert(Tab, {Mod, Modtab}),
- {ok, Modtab};
- NewErr ->
- opentab2(Tab, Base, Mod, It, NewErr)
+get_table(Table, Mod, Includes) ->
+ case ets:lookup(Table, Mod) of
+ [{Mod,Tab}] ->
+ {ok,Tab};
+ [] ->
+ load_table(Mod, any, {{0,0,0},{0,0,0}}, Includes)
end.
lookup(Tab, K) ->
@@ -119,3 +141,43 @@ lookup(Tab, K) ->
[] -> undefined;
[{K,V}] -> V
end.
+
+info(Erule) ->
+ {asn1ct:vsn(),Erule}.
+
+load_table(Mod, Erule, Mtime, Includes) ->
+ Base = lists:concat([Mod, ".asn1db"]),
+ case path_find(Includes, Mtime, Base) of
+ error ->
+ error;
+ {ok,ModTab} when Erule =:= any ->
+ {ok,ModTab};
+ {ok,ModTab} ->
+ Vsn = asn1ct:vsn(),
+ case ets:lookup(ModTab, ?MAGIC_KEY) of
+ [{_,{Vsn,Erule}}] ->
+ %% Correct version and encoding rule.
+ {ok,ModTab};
+ _ ->
+ %% Missing key or wrong version/encoding rule.
+ ets:delete(ModTab),
+ error
+ end
+ end.
+
+path_find([H|T], Mtime, Base) ->
+ File = filename:join(H, Base),
+ case filelib:last_modified(File) of
+ 0 ->
+ path_find(T, Mtime, Base);
+ DbMtime when DbMtime >= Mtime ->
+ case ets:file2tab(File) of
+ {ok,_}=Ret ->
+ Ret;
+ _ ->
+ path_find(T, Mtime, Base)
+ end;
+ _ ->
+ path_find(T, Mtime, Base)
+ end;
+path_find([], _, _) -> error.
diff --git a/lib/asn1/src/asn1_records.hrl b/lib/asn1/src/asn1_records.hrl
index 396ba0fcfa..6c1cf1b12a 100644
--- a/lib/asn1/src/asn1_records.hrl
+++ b/lib/asn1/src/asn1_records.hrl
@@ -37,7 +37,7 @@
-record('ObjectClassFieldType',{classname,class,fieldname,type}).
-record(typedef,{checked=false,pos,name,typespec}).
--record(classdef,{checked=false,pos,name,typespec}).
+-record(classdef, {checked=false,pos,name,module,typespec}).
-record(valuedef,{checked=false,pos,name,type,value,module}).
-record(ptypedef,{checked=false,pos,name,args,typespec}).
-record(pvaluedef,{checked=false,pos,name,args,type,value}).
@@ -45,7 +45,6 @@
-record(pobjectdef,{checked=false,pos,name,args,class,def}).
-record(pobjectsetdef,{checked=false,pos,name,args,class,def}).
--record(identifier,{pos,val}).
-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,
@@ -73,6 +72,15 @@
% Externalvaluereference -> modulename '.' typename
-record('Externalvaluereference',{pos,module,value}).
+%% Used to hold a tag for a field in a SEQUENCE/SET. It can also
+%% be used for identifiers in OBJECT IDENTIFIER values, since the
+%% parser cannot always distinguish a SEQUENCE with one element from
+%% an OBJECT IDENTIFIER.
+-record(seqtag,
+ {pos :: integer(),
+ module :: atom(),
+ val :: atom()}).
+
-record(state,{module,mname,type,tname,value,vname,erule,parameters=[],
inputmodules,abscomppath=[],recordtopname=[],options,
sourcedir}).
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index 8e71a5697c..df341e5aab 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -19,6 +19,10 @@
%%
%%
-module(asn1ct).
+-deprecated([decode/3,encode/3]).
+-compile([{nowarn_deprecated_function,{asn1rt,decode,3}},
+ {nowarn_deprecated_function,{asn1rt,encode,2}},
+ {nowarn_deprecated_function,{asn1rt,encode,3}}]).
%% Compile Time functions for ASN.1 (e.g ASN.1 compiler).
@@ -39,8 +43,8 @@
add_tobe_refed_func/1,add_generated_refed_func/1,
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]).
+ parse_and_save/2,verbose/3,warning/3,warning/4,error/3,format_error/1]).
+-export([get_bit_string_format/0,use_legacy_types/0]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -139,7 +143,8 @@ parse_and_save_passes() ->
{pass,save,fun save_pass/1}].
common_passes() ->
- [{pass,check,fun check_pass/1},
+ [{iff,parse,{pass,parse_listing,fun parse_listing/1}},
+ {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}}].
@@ -239,6 +244,16 @@ save_pass(#st{code=M,erule=Erule,dbfile=DbFile}=St) ->
asn1_db:dbsave(DbFile,M#module.name),
{ok,St}.
+parse_listing(#st{code=Code,outfile=OutFile0}=St) ->
+ OutFile = OutFile0 ++ ".parse",
+ case file:write_file(OutFile, io_lib:format("~p\n", [Code])) of
+ ok ->
+ done;
+ {error,Reason} ->
+ Error = {write_error,OutFile,Reason},
+ {error,St#st{error=[{structured_error,{OutFile0,none},?MODULE,Error}]}}
+ end.
+
abs_listing(#st{code={M,_},outfile=OutFile}) ->
pretty2(M#module.name, OutFile++".abs"),
done.
@@ -333,8 +348,7 @@ print_structured_errors([_|_]=Errors) ->
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),
+ compiler_verbose(File, Opts),
Passes = single_passes(),
Base = filename:rootname(filename:basename(File)),
OutFile = outfile(Base, "", Opts),
@@ -349,8 +363,7 @@ compile1(File, #st{opts=Opts}=St0) ->
%% 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),
+ compiler_verbose(Files, Opts),
OutFile = outfile(SetBase, "", Opts),
DbFile = outfile(SetBase, "asn1db", Opts),
InputModules = [begin
@@ -363,6 +376,11 @@ compile_set(SetBase, Files, #st{opts=Opts}=St0) ->
Passes = set_passes(),
run_passes(Passes, St).
+compiler_verbose(What, Opts) ->
+ verbose("Erlang ASN.1 compiler ~s\n", [?vsn], Opts),
+ verbose("Compiling: ~p\n", [What], Opts),
+ verbose("Options: ~p\n", [Opts], Opts).
+
%% 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
@@ -559,6 +577,8 @@ get_pos_of_def(#pobjectdef{pos=Pos}) ->
Pos;
get_pos_of_def(#pobjectsetdef{pos=Pos}) ->
Pos;
+get_pos_of_def(#'Externaltypereference'{pos=Pos}) ->
+ Pos;
get_pos_of_def(#'Externalvaluereference'{pos=Pos}) ->
Pos;
get_pos_of_def(_) ->
@@ -838,6 +858,7 @@ delete_double_of_symbol1([],Acc) ->
generate({M,GenTOrV}, OutFile, EncodingRule, Options) ->
debug_on(Options),
setup_bit_string_format(Options),
+ setup_legacy_erlang_types(Options),
put(encoding_options,Options),
asn1ct_table:new(check_functions),
@@ -866,6 +887,31 @@ generate({M,GenTOrV}, OutFile, EncodingRule, Options) ->
asn1ct_table:delete(check_functions),
Result.
+setup_legacy_erlang_types(Opts) ->
+ F = case lists:member(legacy_erlang_types, Opts) of
+ false ->
+ case get_bit_string_format() of
+ bitstring ->
+ false;
+ compact ->
+ legacy_forced_info(compact_bit_string),
+ true;
+ legacy ->
+ legacy_forced_info(legacy_bit_string),
+ true
+ end;
+ true ->
+ true
+ end,
+ put(use_legacy_erlang_types, F).
+
+legacy_forced_info(Opt) ->
+ io:format("Info: The option 'legacy_erlang_types' "
+ "is implied by the '~s' option.\n", [Opt]).
+
+use_legacy_types() ->
+ get(use_legacy_erlang_types).
+
setup_bit_string_format(Opts) ->
Format = case {lists:member(compact_bit_string, Opts),
lists:member(legacy_bit_string, Opts)} of
@@ -893,17 +939,23 @@ parse_and_save(Module,S) ->
Options = S#state.options,
SourceDir = S#state.sourcedir,
Includes = [I || {i,I} <- Options],
+ Erule = S#state.erule,
case get_input_file(Module, [SourceDir|Includes]) of
%% search for asn1 source
{file,SuffixedASN1source} ->
- case dbfile_uptodate(SuffixedASN1source,Options) of
- false ->
- parse_and_save1(S, SuffixedASN1source, Options);
- _ -> ok
+ Mtime = filelib:last_modified(SuffixedASN1source),
+ case asn1_db:dbload(Module, Erule, Mtime) of
+ ok -> ok;
+ error -> parse_and_save1(S, SuffixedASN1source, Options)
end;
Err ->
- warning("could not do a consistency check of the ~p file: no asn1 source file was found.~n",
- [lists:concat([Module,".asn1db"])],Options),
+ case asn1_db:dbload(Module) of
+ ok ->
+ warning("could not do a consistency check of the ~p file: no asn1 source file was found.~n",
+ [lists:concat([Module,".asn1db"])],Options);
+ error ->
+ ok
+ end,
{error,{asn1,input_file_error,Err}}
end.
@@ -929,48 +981,6 @@ get_input_file(Module,[I|Includes]) ->
get_input_file(Module,Includes)
end.
-dbfile_uptodate(File,Options) ->
- EncodingRule = get_rule(Options),
- Ext = filename:extension(File),
- Base = filename:basename(File,Ext),
- DbFile = outfile(Base,"asn1db",Options),
- case file:read_file_info(DbFile) of
- {error,enoent} ->
- false;
- {ok,FileInfoDb} ->
- %% file exists, check date and finally encodingrule
- {ok,FileInfoAsn} = file:read_file_info(File),
- case FileInfoDb#file_info.mtime < FileInfoAsn#file_info.mtime of
- true ->
- %% date of asn1 spec newer than db file
- false;
- _ ->
- %% date ok,check that same erule was used
- Obase = case lists:keysearch(outdir, 1, Options) of
- {value, {outdir, Odir}} ->
- Odir;
- _NotFound -> ""
- end,
- BeamFileName = outfile(Base,"beam",Options),
- case file:read_file_info(BeamFileName) of
- {ok,_} ->
- code:add_path(Obase),
- BeamFile = list_to_atom(Base),
- BeamInfo = (catch BeamFile:info()),
- case catch lists:keysearch(options,1,BeamInfo) of
- {value,{options,OldOptions}} ->
- case get_rule(OldOptions) of
- EncodingRule -> true;
- _ -> false
- end;
- _ -> false
- end;
- _ -> false
- end
- end
- end.
-
-
input_file_type(Name,I) ->
case input_file_type(Name) of
{error,_} -> input_file_type2(filename:basename(Name),I);
@@ -1047,7 +1057,7 @@ get_file_list1(Stream,Dir,Includes,Acc) ->
Ret = io:get_line(Stream,''),
case Ret of
eof ->
- file:close(Stream),
+ ok = file:close(Stream),
lists:reverse(Acc);
FileName ->
SuffixedNameList =
@@ -1108,6 +1118,7 @@ remove_asn_flags(Options) ->
X /= optimize,
X /= compact_bit_string,
X /= legacy_bit_string,
+ X /= legacy_erlang_types,
X /= debug,
X /= asn1config,
X /= record_name_prefix].
@@ -1374,10 +1385,11 @@ get_value(Module, Type) ->
end.
check(Module, Includes) ->
- case asn1_db:dbget(Module,'MODULE') of
- undefined ->
- {error, {file_not_found, lists:concat([Module, ".asn1db"])}};
- M ->
+ case asn1_db:dbload(Module) of
+ error ->
+ {error,asn1db_missing_or_out_of_date};
+ ok ->
+ M = asn1_db:dbget(Module, 'MODULE'),
TypeOrVal = M#module.typeorval,
State = #state{mname = M#module.name,
module = M#module{typeorval=[]},
@@ -1931,8 +1943,9 @@ read_config_file(ModuleName) ->
Includes = [I || {i,I} <- Options],
read_config_file1(ModuleName,Includes);
{error,Reason} ->
- file:format_error(Reason),
- throw({error,{"error reading asn1 config file",Reason}})
+ Error = "error reading asn1 config file: " ++
+ file:format_error(Reason),
+ throw({error,Error})
end.
read_config_file1(ModuleName,[]) ->
case filename:extension(ModuleName) of
@@ -1950,8 +1963,9 @@ read_config_file1(ModuleName,[H|T]) ->
{error,enoent} ->
read_config_file1(ModuleName,T);
{error,Reason} ->
- file:format_error(Reason),
- throw({error,{"error reading asn1 config file",Reason}})
+ Error = "error reading asn1 config file: " ++
+ file:format_error(Reason),
+ throw({error,Error})
end.
get_config_info(CfgList,InfoType) ->
@@ -2427,6 +2441,10 @@ verbose(Format, Args, S) ->
ok
end.
+format_error({write_error,File,Reason}) ->
+ io_lib:format("writing output file ~s failed: ~s",
+ [File,file:format_error(Reason)]).
+
is_error(S) when is_record(S, state) ->
is_error(S#state.options);
is_error(O) ->
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index f94550b0a4..240f1cbb16 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -91,7 +91,7 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
save_asn1db_uptodate(S,S#state.erule,S#state.mname),
put(top_module,S#state.mname),
- _ = checkp(S, ParameterizedTypes), %must do this before the templates are used
+ ParamError = 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),
@@ -160,8 +160,10 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
Exporterror = check_exports(S,S#state.module),
ImportError = check_imports(S,S#state.module),
- case {Terror3,Verror5,Cerror,Oerror,Exporterror,ImportError} of
- {[],[],[],[],[],[]} ->
+ AllErrors = lists:flatten([ParamError,Terror3,Verror5,Cerror,
+ Oerror,Exporterror,ImportError]),
+ case AllErrors of
+ [] ->
ContextSwitchTs = context_switch_in_spec(),
InstanceOf = instance_of_in_spec(S#state.mname),
NewTypes = lists:subtract(Types,AddClasses) ++ ContextSwitchTs
@@ -175,8 +177,7 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
lists:subtract(NewObjects,ExclO)++InlinedObjects,
lists:subtract(NewObjectSets,ExclOS)++ParObjectSetNames}};
_ ->
- {error,lists:flatten([Terror3,Verror5,Cerror,
- Oerror,Exporterror,ImportError])}
+ {error,AllErrors}
end.
context_switch_in_spec() ->
@@ -270,46 +271,30 @@ check_exports(S,Module = #module{}) ->
end
end.
-check_imports(S,Module = #module{ }) ->
- case Module#module.imports of
- {imports,[]} ->
- [];
- {imports,ImportList} when is_list(ImportList) ->
- check_imports2(S,ImportList,[]);
- _ ->
- []
- end.
-check_imports2(_S,[],Acc) ->
+check_imports(S, #module{imports={imports,Imports}}) ->
+ check_imports_1(S, Imports, []).
+
+check_imports_1(_S, [], Acc) ->
Acc;
-check_imports2(S,[#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs],Acc) ->
- NameOfDef =
- fun(#'Externaltypereference'{type=N}) -> N;
- (#'Externalvaluereference'{value=N}) -> N
- end,
- Module = NameOfDef(ModuleRef),
- Refs = [{M,R}||{{M,_},R} <- [{catch get_referenced_type(S,Ref),Ref}||Ref <- Imports]],
- {Illegal,Other} = lists:splitwith(fun({error,_}) -> true;(_) -> false end,
- Refs),
- ChainedRefs = [R||{M,R} <- Other, M =/= Module],
- IllegalRefs = [R||{error,R} <- Illegal] ++
- [R||{M,R} <- ChainedRefs,
- ok =/= chained_import(S,Module,M,NameOfDef(R))],
- ReportError =
- fun(Ref) ->
- NewS=S#state{type=Ref,tname=NameOfDef(Ref)},
- error({import,"imported undefined entity",NewS})
- end,
- check_imports2(S,SFMs,[ReportError(Err)||Err <- IllegalRefs]++Acc).
+check_imports_1(S, [#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs], Acc0) ->
+ Module = name_of_def(ModuleRef),
+ Refs0 = [{catch get_referenced_type(S, Ref),Ref} || Ref <- Imports],
+ Refs = [{M,R} || {{M,_},R} <- Refs0],
+ {Illegal,Other} = lists:splitwith(fun({error,_}) -> true;
+ (_) -> false
+ end, Refs),
+ ChainedRefs = [R || {M,R} <- Other, M =/= Module],
+ IllegalRefs = [R || {error,R} <- Illegal] ++
+ [R || {M,R} <- ChainedRefs,
+ ok =/= chained_import(S, Module, M, name_of_def(R))],
+ Acc = [return_asn1_error(S, Ref, {undefined_import,name_of_def(Ref),Module}) ||
+ Ref <- IllegalRefs] ++ Acc0,
+ check_imports_1(S, SFMs, Acc).
chained_import(S,ImpMod,DefMod,Name) ->
%% Name is a referenced structure that is not defined in ImpMod,
%% but must be present in the Imports list of ImpMod. The chain of
%% imports of Name must end in DefMod.
- NameOfDef =
- fun(#'Externaltypereference'{type=N}) -> N;
- (#'Externalvaluereference'{value=N}) -> N;
- (Other) -> Other
- end,
GetImports =
fun(_M_) ->
case asn1_db:dbget(_M_,'MODULE') of
@@ -321,9 +306,9 @@ chained_import(S,ImpMod,DefMod,Name) ->
FindNameInImports =
fun([],N,_) -> {no_mod,N};
([#'SymbolsFromModule'{symbols=Imports,module=ModuleRef}|SFMs],N,F) ->
- case [NameOfDef(X)||X <- Imports, NameOfDef(X) =:= N] of
+ case [name_of_def(X) || X <- Imports, name_of_def(X) =:= N] of
[] -> F(SFMs,N,F);
- [N] -> {NameOfDef(ModuleRef),N}
+ [N] -> {name_of_def(ModuleRef),N}
end
end,
case GetImports(ImpMod) of
@@ -565,14 +550,10 @@ check_class(S = #state{mname=M,tname=T},ClassSpec)
#objectclass{fields=Def}; % in case of recursive definitions
Tref = #'Externaltypereference'{type=TName} ->
{MName,RefType} = get_referenced_type(S,Tref),
- case is_class(S,RefType) of
- true ->
- NewState = update_state(S#state{type=RefType,
- tname=TName},MName),
- check_class(NewState,get_class_def(S,RefType));
- _ ->
- error({class,{internal_error,RefType},S})
- end;
+ #classdef{} = CD = get_class_def(S, RefType),
+ NewState = update_state(S#state{type=RefType,
+ tname=TName}, MName),
+ check_class(NewState, CD);
{pt,ClassRef,Params} ->
%% parameterized class
{_,PClassDef} = get_referenced_type(S,ClassRef),
@@ -966,6 +947,8 @@ prepare_objset(ObjDef={object,definedsyntax,_ObjFields}) ->
{set,[ObjDef],false};
prepare_objset({ObjDef=#type{},Ext}) when is_list(Ext) ->
{set,[ObjDef|Ext],true};
+prepare_objset({#type{}=Type,#type{}=Ext}) ->
+ {set,[Type,Ext],true};
prepare_objset(Ret) ->
Ret.
@@ -1293,10 +1276,25 @@ get_fieldname_element(_S,Def,[{_RefType,_FieldName}|_RestFName])
check_fieldname_element(S,{value,{_,Def}}) ->
check_fieldname_element(S,Def);
-check_fieldname_element(S,TDef) when is_record(TDef,typedef) ->
- check_type(S,TDef,TDef#typedef.typespec);
-check_fieldname_element(S,VDef) when is_record(VDef,valuedef) ->
- check_value(S,VDef);
+check_fieldname_element(S, #typedef{typespec=Ts}=TDef) ->
+ case Ts of
+ #'Object'{} ->
+ check_object(S, TDef, Ts);
+ _ ->
+ check_type(S, TDef, Ts)
+ end;
+check_fieldname_element(S, #valuedef{}=VDef) ->
+ try
+ check_value(S, VDef)
+ catch
+ throw:{objectdef} ->
+ #valuedef{checked=C,pos=Pos,name=N,type=Type,
+ value=Def} = VDef,
+ ClassName = Type#type.def,
+ NewSpec = #'Object'{classname=ClassName,def=Def},
+ NewDef = #typedef{checked=C,pos=Pos,name=N,typespec=NewSpec},
+ check_fieldname_element(S, NewDef)
+ end;
check_fieldname_element(S,Eref)
when is_record(Eref,'Externaltypereference');
is_record(Eref,'Externalvaluereference') ->
@@ -1557,21 +1555,32 @@ check_objectdefn(S,Def,CDef) when is_record(CDef,classdef) ->
exit({error,{objectdefn,Other}})
end.
-check_defaultfields(S,Fields,ClassFields) ->
- check_defaultfields(S,Fields,ClassFields,[]).
+check_defaultfields(S, Fields, ClassFields) ->
+ Present = ordsets:from_list([F || {F,_} <- Fields]),
+ Mandatory0 = get_mandatory_class_fields(ClassFields),
+ Mandatory = ordsets:from_list(Mandatory0),
+ All = ordsets:from_list([element(2, F) || F <- ClassFields]),
+ #state{type=T,tname=Obj} = S,
+ case ordsets:subtract(Present, All) of
+ [] ->
+ ok;
+ [_|_]=Invalid ->
+ asn1_error(S, T, {invalid_fields,Invalid,Obj})
+ end,
+ case ordsets:subtract(Mandatory, Present) of
+ [] ->
+ check_defaultfields_1(S, Fields, ClassFields, []);
+ [_|_]=Missing ->
+ asn1_error(S, T, {missing_mandatory_fields,Missing,Obj})
+ end.
-check_defaultfields(_S,[],_ClassFields,Acc) ->
+check_defaultfields_1(_S, [], _ClassFields, Acc) ->
{object,defaultsyntax,lists:reverse(Acc)};
-check_defaultfields(S,[{FName,Spec}|Fields],ClassFields,Acc) ->
- case lists:keysearch(FName,2,ClassFields) of
- {value,CField} ->
- {NewField,RestFields} =
- convert_to_defaultfield(S,FName,[Spec|Fields],CField),
- check_defaultfields(S,RestFields,ClassFields,[NewField|Acc]);
- _ ->
- throw({error,{asn1,{'unvalid field in object',FName}}})
- end.
-%% {object,defaultsyntax,Fields}.
+check_defaultfields_1(S, [{FName,Spec}|Fields], ClassFields, Acc) ->
+ CField = lists:keyfind(FName, 2, ClassFields),
+ {NewField,RestFields} =
+ convert_to_defaultfield(S, FName, [Spec|Fields], CField),
+ check_defaultfields_1(S, RestFields, ClassFields, [NewField|Acc]).
convert_definedsyntax(_S,[],[],_ClassFields,Acc) ->
lists:reverse(Acc);
@@ -1587,6 +1596,23 @@ convert_definedsyntax(S,Fields,WithSyntax,ClassFields,Acc) ->
[MatchedField|Acc])
end.
+get_mandatory_class_fields([{fixedtypevaluefield,Name,_,_,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([{objectfield,Name,_,_,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([{objectsetfield,Name,_,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([{typefield,Name,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([{variabletypevaluefield,Name,_,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([{variabletypevaluesetfield,
+ Name,_,'MANDATORY'}|T]) ->
+ [Name|get_mandatory_class_fields(T)];
+get_mandatory_class_fields([_|T]) ->
+ get_mandatory_class_fields(T);
+get_mandatory_class_fields([]) -> [].
+
match_field(S,Fields,WithSyntax,ClassFields) ->
match_field(S,Fields,WithSyntax,ClassFields,[]).
@@ -1791,12 +1817,10 @@ convert_to_defaultfield(S,ObjFieldName,[OFS|RestOFS],CField)->
FieldName);
ValSetting = #valuedef{} ->
ValSetting;
- ValSetting = {'CHOICE',{Alt,_ChVal}} when is_atom(Alt) ->
- #valuedef{type=element(3,CField),
- value=ValSetting,
- module=S#state.mname};
ValSetting ->
- #identifier{val=ValSetting}
+ #valuedef{type=element(3,CField),
+ value=ValSetting,
+ module=S#state.mname}
end,
?dbg("fixedtypevaluefield ValRef: ~p~n",[ValRef]),
case ValRef of
@@ -2124,11 +2148,9 @@ check_valuedef(#state{recordtopname=TopName}=S0, V0) ->
{'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)};
+ #'SEQUENCE'{} ->
+ {ok,SeqVal} = convert_external(SVal, Value),
+ V#valuedef{value=normalize_value(SVal, Vtype, SeqVal, TopName)};
{'SelectionType',SelName,SelT} ->
CheckedT = check_selectiontype(SVal, SelName, SelT),
NewV = V#valuedef{type=CheckedT},
@@ -2280,22 +2302,23 @@ validate_oid(_, S, OID, [Id|Vrest], Acc)
error({value, {"illegal "++to_string(OID),[Id,Vrest],Acc}, S})
end
end;
-validate_oid(_, S, OID, [{Atom,Value}],[])
+validate_oid(_, S, OID, [{#seqtag{module=Mod,val=Atom},Value}], [])
when is_atom(Atom),is_integer(Value) ->
%% this case when an OBJECT IDENTIFIER value has been parsed as a
%% SEQUENCE value
- Rec = #'Externalvaluereference'{module=S#state.mname,
+ Rec = #'Externalvaluereference'{module=Mod,
value=Atom},
validate_objectidentifier1(S, OID, [Rec,Value]);
-validate_oid(_, S, OID, [{Atom,EVRef}],[])
+validate_oid(_, S, OID, [{#seqtag{module=Mod,val=Atom},EVRef}], [])
when is_atom(Atom),is_record(EVRef,'Externalvaluereference') ->
%% this case when an OBJECT IDENTIFIER value has been parsed as a
%% SEQUENCE value OTP-4354
- Rec = #'Externalvaluereference'{module=EVRef#'Externalvaluereference'.module,
+ Rec = #'Externalvaluereference'{module=Mod,
value=Atom},
validate_objectidentifier1(S, OID, [Rec,EVRef]);
-validate_oid(_, S, OID, [Atom|Rest],Acc) when is_atom(Atom) ->
- Rec = #'Externalvaluereference'{module=S#state.mname,
+validate_oid(_, S, OID, [#seqtag{module=Mod,val=Atom}|Rest], Acc)
+ when is_atom(Atom) ->
+ Rec = #'Externalvaluereference'{module=Mod,
value=Atom},
validate_oid(true,S, OID, [Rec|Rest],Acc);
validate_oid(_, S, OID, V, Acc) ->
@@ -2387,13 +2410,13 @@ valid_objectid(o_id,_I,[1]) -> false;
valid_objectid(o_id,_I,[2]) -> true;
valid_objectid(_,_,_) -> true.
-validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
+convert_external(S=#state{type=Vtype}, Value) ->
case Vtype of
#type{tag=[{tag,'UNIVERSAL',8,'IMPLICIT',32}]} ->
%% this is an 'EXTERNAL' (or INSTANCE OF)
case Value of
- [{identification,_}|_RestVal] ->
- {ok,to_EXTERNAL1990(S,Value)};
+ [{#seqtag{val=identification},_}|_] ->
+ {ok,to_EXTERNAL1990(S, Value)};
_ ->
{ok,Value}
end;
@@ -2401,21 +2424,25 @@ validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
{ok,Value}
end.
-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]) ->
- to_EXTERNAL1990(S,Rest,[{'indirect-reference',I}]);
-to_EXTERNAL1990(S,[{identification,{'CHOICE',{'context-negotiation',[{_,PCid},{_,TrStx}]}}}|Rest]) ->
- to_EXTERNAL1990(S,Rest,[{'indirect-reference',PCid},{'direct-reference',TrStx}]);
-to_EXTERNAL1990(S,_) ->
+to_EXTERNAL1990(S, [{#seqtag{val=identification}=T,
+ {'CHOICE',{syntax,Stx}}}|Rest]) ->
+ to_EXTERNAL1990(S, Rest, [{T#seqtag{val='direct-reference'},Stx}]);
+to_EXTERNAL1990(S, [{#seqtag{val=identification}=T,
+ {'CHOICE',{'presentation-context-id',I}}}|Rest]) ->
+ to_EXTERNAL1990(S, Rest, [{T#seqtag{val='indirect-reference'},I}]);
+to_EXTERNAL1990(S, [{#seqtag{val=identification}=T,
+ {'CHOICE',{'context-negotiation',[{_,PCid},{_,TrStx}]}}}|Rest]) ->
+ to_EXTERNAL1990(S, Rest, [{T#seqtag{val='indirect-reference'},PCid},
+ {T#seqtag{val='direct-reference'},TrStx}]);
+to_EXTERNAL1990(S, _) ->
error({value,"illegal value in EXTERNAL type",S}).
-to_EXTERNAL1990(S,[V={'data-value-descriptor',_}|Rest],Acc) ->
- to_EXTERNAL1990(S,Rest,[V|Acc]);
-to_EXTERNAL1990(_S,[{'data-value',Val}],Acc) ->
- Encoding = {encoding,{'CHOICE',{'octet-aligned',Val}}},
+to_EXTERNAL1990(S, [V={#seqtag{val='data-value-descriptor'},_}|Rest], Acc) ->
+ to_EXTERNAL1990(S, Rest, [V|Acc]);
+to_EXTERNAL1990(_S, [{#seqtag{val='data-value'}=T,Val}], Acc) ->
+ Encoding = {T#seqtag{val=encoding},{'CHOICE',{'octet-aligned',Val}}},
lists:reverse([Encoding|Acc]);
-to_EXTERNAL1990(S,_,_) ->
+to_EXTERNAL1990(S, _, _) ->
error({value,"illegal value in EXTERNAL type",S}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2436,7 +2463,7 @@ normalize_value(S0, Type, {'DEFAULT',Value}, NameList) ->
{'BIT STRING',CType,_} ->
normalize_bitstring(S,Value,CType);
{'OCTET STRING',CType,_} ->
- normalize_octetstring(S,Value,CType);
+ normalize_octetstring(S0, Value, CType);
{'NULL',_CType,_} ->
%%normalize_null(Value);
'NULL';
@@ -2506,89 +2533,66 @@ normalize_integer(S,Int=#'Externalvaluereference'{value=Name},Type) ->
normalize_integer(_,Int,_) ->
exit({'Unknown INTEGER value',Int}).
-normalize_bitstring(S,Value,Type)->
- %% There are four different Erlang formats of BIT STRING:
- %% 1 - a list of ones and zeros.
- %% 2 - a list of atoms.
- %% 3 - as an integer, for instance in hexadecimal form.
- %% 4 - as a tuple {Unused, Binary} where Unused is an integer
- %% and tells how many bits of Binary are unused.
- %%
- %% normalize_bitstring/3 transforms Value according to:
- %% A to 3,
- %% B to 1,
- %% C to 1 or 3
- %% D to 2,
- %% Value can be on format:
- %% A - {hstring, String}, where String is a hexadecimal string.
- %% B - {bstring, String}, where String is a string on bit format
- %% C - #'Externalvaluereference'{value=V}, where V is a defined value
- %% D - list of #'Externalvaluereference', where each value component
- %% is an identifier corresponing to NamedBits in Type.
- %% E - list of ones and zeros, if Value already is normalized.
+%% normalize_bitstring(S, Value, Type) -> bitstring()
+%% Convert a literal value for a BIT STRING to an Erlang bit string.
+%%
+normalize_bitstring(S, Value, Type)->
case Value of
{hstring,String} when is_list(String) ->
- hstring_to_int(String);
+ hstring_to_bitstring(String);
{bstring,String} when is_list(String) ->
- bstring_to_bitlist(String);
- Rec when is_record(Rec,'Externalvaluereference') ->
- get_normalized_value(S,Value,Type,
- fun normalize_bitstring/3,[]);
+ bstring_to_bitstring(String);
+ #'Externalvaluereference'{} ->
+ get_normalized_value(S, Value, Type,
+ fun normalize_bitstring/3, []);
RecList when is_list(RecList) ->
- case Type of
- NBL when is_list(NBL) ->
- F = fun(#'Externalvaluereference'{value=Name}) ->
- case lists:keysearch(Name,1,NBL) of
- {value,{Name,_}} ->
- Name;
- Other ->
- throw({error,Other})
- end;
- (I) when I =:= 1; I =:= 0 ->
- I;
- (Other) ->
- throw({error,Other})
- end,
- case catch lists:map(F,RecList) of
- {error,Reason} ->
- asn1ct:warning("default value not "
- "compatible with type definition ~p~n",
- [Reason],S,
- "default value not "
- "compatible with type definition"),
- Value;
- NewList ->
- NewList
- end;
- _ ->
+ F = fun(#'Externalvaluereference'{value=Name}) ->
+ case lists:keymember(Name, 1, Type) of
+ true -> Name;
+ false -> throw({error,false})
+ end;
+ (Name) when is_atom(Name) ->
+ %% Already normalized.
+ Name;
+ (Other) ->
+ throw({error,Other})
+ end,
+ try
+ lists:map(F, RecList)
+ catch
+ throw:{error,Reason} ->
asn1ct:warning("default value not "
"compatible with type definition ~p~n",
- [RecList],S,
+ [Reason],S,
"default value not "
"compatible with type definition"),
Value
end;
- {Name,String} when is_atom(Name) ->
- normalize_bitstring(S,String,Type);
- Other ->
- asn1ct:warning("illegal default value ~p~n",[Other],S,
- "illegal default value"),
- Value
+ Bs when is_bitstring(Bs) ->
+ %% Already normalized.
+ Bs
end.
-hstring_to_int(L) when is_list(L) ->
- hstring_to_int(L,0).
-hstring_to_int([H|T],Acc) when H >= $A, H =< $F ->
- hstring_to_int(T,(Acc bsl 4) + (H - $A + 10) ) ;
-hstring_to_int([H|T],Acc) when H >= $0, H =< $9 ->
- hstring_to_int(T,(Acc bsl 4) + (H - $0));
-hstring_to_int([],Acc) ->
- Acc.
+hstring_to_binary(L) ->
+ byte_align(hstring_to_bitstring(L)).
-bstring_to_bitlist([H|T]) when H == $0; H == $1 ->
- [H - $0 | bstring_to_bitlist(T)];
-bstring_to_bitlist([]) ->
- [].
+bstring_to_binary(L) ->
+ byte_align(bstring_to_bitstring(L)).
+
+byte_align(Bs) ->
+ case bit_size(Bs) rem 8 of
+ 0 -> Bs;
+ N -> <<Bs/bitstring,0:(8-N)>>
+ end.
+
+hstring_to_bitstring(L) ->
+ << <<(hex_to_int(D)):4>> || D <- L >>.
+
+bstring_to_bitstring(L) ->
+ << <<(D-$0):1>> || D <- L >>.
+
+hex_to_int(D) when $0 =< D, D =< $9 -> D - $0;
+hex_to_int(D) when $A =< D, D =< $F -> D - ($A - 10).
%% normalize_octetstring/1 changes representation of input Value to a
%% list of octets.
@@ -2599,59 +2603,19 @@ bstring_to_bitlist([]) ->
normalize_octetstring(S,Value,CType) ->
case Value of
{bstring,String} ->
- bstring_to_octetlist(String);
+ bstring_to_binary(String);
{hstring,String} ->
- hstring_to_octetlist(String);
+ hstring_to_binary(String);
Rec when is_record(Rec,'Externalvaluereference') ->
get_normalized_value(S,Value,CType,
fun normalize_octetstring/3,[]);
{Name,String} when is_atom(Name) ->
normalize_octetstring(S,String,CType);
- List when is_list(List) ->
- %% check if list elements are valid octet values
- lists:map(fun([])-> ok;
- (H)when H > 255->
- asn1ct:warning("not legal octet value ~p in OCTET STRING, ~p~n",
- [H,List],S,
- "not legal octet value ~p in OCTET STRING");
- (_)-> ok
- end, List),
- List;
- Other ->
- asn1ct:warning("unknown default value ~p~n",[Other],S,
- "unknown default value"),
- Value
+ _ ->
+ Item = S#state.value,
+ asn1_error(S, Item, illegal_octet_string_value)
end.
-
-bstring_to_octetlist([]) ->
- [];
-bstring_to_octetlist([H|T]) when H == $0 ; H == $1 ->
- bstring_to_octetlist(T,6,[(H - $0) bsl 7]).
-bstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H == $0; H == $1 ->
- bstring_to_octetlist(T, 7, [0,Hacc + (H -$0)| Tacc]);
-bstring_to_octetlist([H|T],BSL,[Hacc|Tacc]) when H == $0; H == $1 ->
- bstring_to_octetlist(T, BSL-1, [Hacc + ((H - $0) bsl BSL)| Tacc]);
-bstring_to_octetlist([],7,[0|Acc]) ->
- lists:reverse(Acc);
-bstring_to_octetlist([],_,Acc) ->
- lists:reverse(Acc).
-
-hstring_to_octetlist([]) ->
- [];
-hstring_to_octetlist(L) ->
- hstring_to_octetlist(L,4,[]).
-hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $A, H =< $F ->
- hstring_to_octetlist(T,4,[Hacc + (H - $A + 10)|Tacc]);
-hstring_to_octetlist([H|T],BSL,Acc) when H >= $A, H =< $F ->
- hstring_to_octetlist(T,0,[(H - $A + 10) bsl BSL|Acc]);
-hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $0; H =< $9 ->
- hstring_to_octetlist(T,4,[Hacc + (H - $0)|Tacc]);
-hstring_to_octetlist([H|T],BSL,Acc) when H >= $0; H =< $9 ->
- hstring_to_octetlist(T,0,[(H - $0) bsl BSL|Acc]);
-hstring_to_octetlist([],_,Acc) ->
- lists:reverse(Acc).
-
normalize_objectidentifier(S, Value) ->
{ok,Val} = validate_objectidentifier(S, o_id, Value, []),
Val.
@@ -2666,18 +2630,21 @@ normalize_objectdescriptor(Value) ->
normalize_real(Value) ->
Value.
-normalize_enumerated(S, Id, {Base,Ext}) ->
+normalize_enumerated(S, Id0, NNL) ->
+ {Id,_} = lookup_enum_value(S, Id0, NNL),
+ Id.
+
+lookup_enum_value(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;
+ lookup_enum_value(S, Id, Base++Ext);
+lookup_enum_value(S, #'Externalvaluereference'{value=Id}, NNL) ->
+ lookup_enum_value(S, Id, NNL);
+lookup_enum_value(S, Id, NNL) when is_atom(Id) ->
+ case lists:keyfind(Id, 1, NNL) of
+ {_,_}=Ret ->
+ Ret;
false ->
- throw(asn1_error(S, S#state.value, {undefined,Id}))
+ asn1_error(S, S#state.value, {undefined,Id})
end.
normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when is_atom(C) ->
@@ -2737,20 +2704,20 @@ normalize_set(S,Value,Components,NameList) ->
normalized_record('SET',S,SortedVal,Components,NameList)
end.
-sort_value(Components,Value) ->
- ComponentNames = lists:map(fun(#'ComponentType'{name=Cname}) -> Cname end,
- Components),
- sort_value1(ComponentNames,Value,[]).
-sort_value1(_,V=#'Externalvaluereference'{},_) ->
- %% sort later, get the value in normalize_seq_or_set
- V;
-sort_value1([N|Ns],Value,Acc) ->
- case lists:keysearch(N,1,Value) of
- {value,V} ->sort_value1(Ns,Value,[V|Acc]);
- _ -> sort_value1(Ns,Value,Acc)
- end;
-sort_value1([],_,Acc) ->
- lists:reverse(Acc).
+sort_value(Components, Value0) when is_list(Value0) ->
+ {Keys0,_} = lists:mapfoldl(fun(#'ComponentType'{name=N}, I) ->
+ {{N,I},I+1}
+ end, 0, Components),
+ Keys = gb_trees:from_orddict(orddict:from_list(Keys0)),
+ Value1 = [{case gb_trees:lookup(N, Keys) of
+ {value,K} -> K;
+ none -> 'end'
+ end,Pair} || {#seqtag{val=N},_}=Pair <- Value0],
+ Value = lists:sort(Value1),
+ [Pair || {_,Pair} <- Value];
+sort_value(_Components, #'Externalvaluereference'{}=Value) ->
+ %% Sort later.
+ Value.
sort_val_if_set(['SET'|_],Val,Type) ->
sort_value(Type,Val);
@@ -2783,9 +2750,9 @@ is_record_normalized(_S,Name,Value,NumComps) when is_tuple(Value) ->
is_record_normalized(_,_,_,_) ->
false.
-normalize_seq_or_set(SorS,S,[{Cname,V}|Vs],
+normalize_seq_or_set(SorS, S, [{#seqtag{val=Cname},V}|Vs],
[#'ComponentType'{name=Cname,typespec=TS}|Cs],
- NameList,Acc) ->
+ NameList, Acc) ->
NewNameList =
case TS#type.def of
#'Externaltypereference'{type=TName} ->
@@ -2963,8 +2930,7 @@ get_canonic_type(S,Type,NameList) ->
check_ptype(S,Type,Ts) when is_record(Ts,type) ->
- %Tag = Ts#type.tag,
- %Constr = Ts#type.constraint,
+ check_formal_parameters(S, Type#ptypedef.args),
Def = Ts#type.def,
NewDef=
case Def of
@@ -2990,6 +2956,16 @@ check_ptype(S,Type,Ts) when is_record(Ts,type) ->
check_ptype(_S,_PTDef,Ts) when is_record(Ts,objectclass) ->
throw({asn1_param_class,Ts}).
+check_formal_parameters(S, Args) ->
+ _ = [check_formal_parameter(S, A) || A <- Args],
+ ok.
+
+check_formal_parameter(_, {_,_}) ->
+ ok;
+check_formal_parameter(_, #'Externaltypereference'{}) ->
+ ok;
+check_formal_parameter(S, #'Externalvaluereference'{value=Name}=Ref) ->
+ asn1_error(S, Ref, {illegal_typereference,Name}).
% check_type(S,Type,ObjSpec={{objectclassname,_},_}) ->
% check_class(S,ObjSpec);
@@ -3037,9 +3013,9 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
{TmpRefMod,TmpRefDef} ->
{TmpRefMod,TmpRefDef,false}
end,
- case is_class(S,RefTypeDef) of
- true -> throw({asn1_class,RefTypeDef});
- _ -> ok
+ case get_class_def(S, RefTypeDef) of
+ none -> ok;
+ #classdef{} -> throw({asn1_class,RefTypeDef})
end,
Ct = TestFun(Ext),
{RefType,ExtRef} =
@@ -3112,12 +3088,11 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
Ct=maybe_illicit_implicit_tag(open_type,Tag),
TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
'INTEGER' ->
- check_integer(S,[],Constr),
TempNewDef#newt{tag=
merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
{'INTEGER',NamedNumberList} ->
- TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList,Constr)},
+ TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList)},
tag=
merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
'REAL' ->
@@ -3125,8 +3100,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
TempNewDef#newt{tag=merge_tags(Tag,?TAG_PRIMITIVE(?N_REAL))};
{'BIT STRING',NamedNumberList} ->
- NewL = check_bitstring(S,NamedNumberList,Constr),
-%% erlang:display({asn1ct_check,NamedNumberList,NewL}),
+ NewL = check_bitstring(S, NamedNumberList),
TempNewDef#newt{type={'BIT STRING',NewL},
tag=
merge_tags(Tag,?TAG_PRIMITIVE(?N_BIT_STRING))};
@@ -3422,23 +3396,17 @@ get_type_from_object(S,Object,TypeField)
ObjSpec = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
get_fieldname_element(S,ObjectDef#typedef{typespec=ObjSpec},TypeField).
-is_class(_S,#classdef{}) ->
- true;
-is_class(S,#typedef{typespec=#type{def=Eref}})
- when is_record(Eref,'Externaltypereference')->
- is_class(S,Eref);
-is_class(S,Eref) when is_record(Eref,'Externaltypereference')->
- {_,NextDef} = get_referenced_type(S,Eref),
- is_class(S,NextDef);
-is_class(_,_) ->
- false.
-
-get_class_def(_S,CD=#classdef{}) ->
+%% get_class_def(S, Type) -> #classdef{} | 'none'.
+get_class_def(S, #typedef{typespec=#type{def=#'Externaltypereference'{}=Eref}}) ->
+ {_,NextDef} = get_referenced_type(S, Eref),
+ get_class_def(S, NextDef);
+get_class_def(S, #'Externaltypereference'{}=Eref) ->
+ {_,NextDef} = get_referenced_type(S, Eref),
+ get_class_def(S, NextDef);
+get_class_def(_S, #classdef{}=CD) ->
CD;
-get_class_def(S,#typedef{typespec=#type{def=Eref}})
- when is_record(Eref,'Externaltypereference') ->
- {_,NextDef} = get_referenced_type(S,Eref),
- get_class_def(S,NextDef).
+get_class_def(_S, _) ->
+ none.
maybe_illicit_implicit_tag(Kind,Tag) ->
case Tag of
@@ -3645,109 +3613,54 @@ match_args(_,_, _, _) ->
%% categorize_arg(S,FormalArg,ActualArg) -> {FormalArg,CatgorizedActualArg}
%%
categorize_arg(S,{Governor,Param},ActArg) ->
- case {governor_category(S,Governor),parameter_name_style(Param,ActArg)} of
-%% {absent,beginning_uppercase} -> %% a type
-%% categorize(S,type,ActArg);
- {type,beginning_lowercase} -> %% a value
- categorize(S,value,Governor,ActArg);
- {type,beginning_uppercase} -> %% a value set
- categorize(S,value_set,ActArg);
-%% {absent,entirely_uppercase} -> %% a class
-%% categorize(S,class,ActArg);
+ case {governor_category(S, Governor),parameter_name_style(Param)} of
+ {type,beginning_lowercase} -> %a value
+ categorize(S, value, Governor, ActArg);
+ {type,beginning_uppercase} -> %a value set
+ categorize(ActArg);
{{class,ClassRef},beginning_lowercase} ->
- categorize(S,object,ActArg,ClassRef);
+ categorize(S, object, ActArg, ClassRef);
{{class,ClassRef},beginning_uppercase} ->
- categorize(S,object_set,ActArg,ClassRef);
- _ ->
- [ActArg]
+ categorize(S, object_set, ActArg, ClassRef)
end;
-categorize_arg(S,FormalArg,ActualArg) ->
- %% governor is absent => a type or a class
- case FormalArg of
- #'Externaltypereference'{type=Name} ->
- case is_class_name(Name) of
- true ->
- categorize(S,class,ActualArg);
- _ ->
- categorize(S,type,ActualArg)
- end;
- FA ->
- throw({error,{unexpected_formal_argument,FA}})
- end.
-
-governor_category(S,#type{def=Eref})
- when is_record(Eref,'Externaltypereference') ->
- governor_category(S,Eref);
-governor_category(_S,#type{}) ->
+categorize_arg(_S, _FormalArg, ActualArg) ->
+ %% Governor is absent -- must be a type or a class. We have already
+ %% checked that the FormalArg begins with an uppercase letter.
+ categorize(ActualArg).
+
+%% governor_category(S, Item) -> type | {class,#'Externaltypereference'{}}
+%% Determine whether Item is a type or a class.
+governor_category(S, #type{def=#'Externaltypereference'{}=Eref}) ->
+ governor_category(S, Eref);
+governor_category(_S, #type{}) ->
type;
-governor_category(S,Ref) when is_record(Ref,'Externaltypereference') ->
- case is_class(S,Ref) of
- true ->
- {class,Ref};
- _ ->
+governor_category(S, #'Externaltypereference'{}=Ref) ->
+ case get_class_def(S, Ref) of
+ #classdef{pos=Pos,module=Mod,name=Name} ->
+ {class,#'Externaltypereference'{pos=Pos,module=Mod,type=Name}};
+ none ->
type
- end;
-governor_category(_,Class)
- when Class == 'TYPE-IDENTIFIER'; Class == 'ABSTRACT-SYNTAX' ->
- class.
-%% governor_category(_,_) ->
-%% absent.
+ end.
%% parameter_name_style(Param,Data) -> Result
%% gets the Parameter and the name of the Data and if it exists tells
%% whether it begins with a lowercase letter or is partly or entirely
%% spelled with uppercase letters. Otherwise returns undefined
%%
-parameter_name_style(_,#'Externaltypereference'{type=Name}) ->
- name_category(Name);
-parameter_name_style(_,#'Externalvaluereference'{value=Name}) ->
- name_category(Name);
-parameter_name_style(_,{valueset,_}) ->
- %% It is a object set or value set
+parameter_name_style(#'Externaltypereference'{}) ->
beginning_uppercase;
-parameter_name_style(#'Externalvaluereference'{},_) ->
- beginning_lowercase;
-parameter_name_style(#'Externaltypereference'{type=Name},_) ->
- name_category(Name);
-parameter_name_style(_,_) ->
- undefined.
-
-name_category(Atom) when is_atom(Atom) ->
- name_category(atom_to_list(Atom));
-name_category([H|T]) ->
- case is_lowercase(H) of
- true ->
- beginning_lowercase;
- _ ->
- case is_class_name(T) of
- true ->
- entirely_uppercase;
- _ ->
- beginning_uppercase
- end
- end;
-name_category(_) ->
- undefined.
+parameter_name_style(#'Externalvaluereference'{}) ->
+ beginning_lowercase.
is_lowercase(X) when X >= $A,X =< $W ->
false;
is_lowercase(_) ->
true.
-
-is_class_name(Name) when is_atom(Name) ->
- is_class_name(atom_to_list(Name));
-is_class_name(Name) ->
- case [X||X <- Name, X >= $a,X =< $w] of
- [] ->
- true;
- _ ->
- false
- end.
-%% categorize(S,Category,Parameter) -> CategorizedParameter
+%% categorize(Parameter) -> CategorizedParameter
%% If Parameter has an abstract syntax of another category than
%% Category, transform it to a known syntax.
-categorize(_S,type,{object,_,Type}) ->
+categorize({object,_,Type}) ->
%% One example of this case is an object with a parameterized type
%% having a locally defined type as parameter.
Def = fun(D = #type{}) ->
@@ -3759,11 +3672,12 @@ categorize(_S,type,{object,_,Type}) ->
D
end,
[Def(X)||X<-Type];
-categorize(_S,type,Def) when is_record(Def,type) ->
+categorize(#type{}=Def) ->
[#typedef{name = new_reference_name("type_argument"),
typespec = Def#type{inlined=yes}}];
-categorize(_,_,Def) ->
+categorize(Def) ->
[Def].
+
categorize(S,object_set,Def,ClassRef) ->
NewObjSetSpec =
check_object(S,Def,#'ObjectSet'{class = ClassRef,
@@ -3810,8 +3724,9 @@ resolv_value(S,Val) ->
resolv_value1(S,Id).
resolv_value1(S, ERef = #'Externalvaluereference'{value=Name}) ->
- case catch resolve_namednumber(S,S#state.type,Name) of
- V when is_integer(V) -> V;
+ case catch resolve_namednumber(S, S#state.type, Name) of
+ V when is_integer(V) ->
+ V;
_ ->
case get_referenced_type(S,ERef) of
{Err,_Reason} when Err == error; Err == 'EXIT' ->
@@ -3864,21 +3779,20 @@ resolve_value_from_object(S,Object,FieldName) ->
end.
-
resolve_namednumber(S,#typedef{typespec=Type},Name) ->
case Type#type.def of
{'ENUMERATED',NameList} ->
- NamedNumberList=check_enumerated(S,NameList,Type#type.constraint),
- N = normalize_enumerated(S,Name,NamedNumberList),
- {value,{_,V}} = lists:keysearch(N,1,NamedNumberList),
- V;
+ resolve_namednumber_1(S, Name, NameList, Type);
{'INTEGER',NameList} ->
- NamedNumberList = check_enumerated(S,NameList,Type#type.constraint),
- {value,{_,V}} = lists:keysearch(Name,1,NamedNumberList),
- V;
+ resolve_namednumber_1(S, Name, NameList, Type);
_ ->
not_enumerated
end.
+
+resolve_namednumber_1(S, Name, NameList, Type) ->
+ NamedNumberList = check_enumerated(S, NameList, Type#type.constraint),
+ {_,N} = lookup_enum_value(S, Name, NamedNumberList),
+ N.
check_constraints(S,[{'ContainedSubtype',Type} | Rest], Acc) ->
{RefMod,CTDef} = get_referenced_type(S,Type#type.def),
@@ -3959,9 +3873,9 @@ check_constraint(S,{simpletable,Type}) ->
#'Externaltypereference'{} ->
ERef = check_externaltypereference(S,C),
{simpletable,ERef#'Externaltypereference'.type};
- #type{def=#'Externaltypereference'{type=T}} ->
- check_externaltypereference(S,C#type.def),
- {simpletable,T};
+ #type{def=#'Externaltypereference'{}=ExtTypeRef} ->
+ ERef = check_externaltypereference(S, ExtTypeRef),
+ {simpletable,ERef#'Externaltypereference'.type};
{valueset,#type{def=ERef=#'Externaltypereference'{}}} -> % this is an object set
{_,TDef} = get_referenced_type(S,ERef),
case TDef#typedef.typespec of
@@ -4201,9 +4115,10 @@ constraint_union(S,C) when is_list(C) ->
constraint_union(_S,C) ->
[C].
-constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) ->
- AunionB = constraint_union_vr([A,B]),
- constraint_union1(S, AunionB++Rest, Acc);
+constraint_union1(S, [{'ValueRange',{Lb1,Ub1}},union,
+ {'ValueRange',{Lb2,Ub2}}|Rest], Acc) ->
+ AunionB = {'ValueRange',{c_min(Lb1, Lb2),max(Ub1, Ub2)}},
+ 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);
@@ -4227,42 +4142,9 @@ constraint_union_sv(_S,SV) ->
[N] -> [{'SingleValue',N}];
L -> [{'SingleValue',L}]
end.
-
-%% REMOVE????
-%%constraint_union(S,VR,'ValueRange') ->
-%% constraint_union_vr(VR).
-
-%% constraint_union_vr(VR)
-%% VR = [{'ValueRange',{Lb,Ub}},...]
-%% Lb = 'MIN' | integer()
-%% Ub = 'MAX' | integer()
-%% Returns if possible only one ValueRange tuple with a range that
-%% is a union of all ranges in VR.
-constraint_union_vr(VR) ->
- %% Sort VR by Lb in first hand and by Ub in second hand
- Fun=fun({_,{'MIN',_B1}},{_,{A2,_B2}}) when is_integer(A2)->true;
- ({_,{A1,_B1}},{_,{'MAX',_B2}}) when is_integer(A1) -> true;
- ({_,{A1,_B1}},{_,{A2,_B2}}) when is_integer(A1),is_integer(A2),A1<A2 -> true;
- ({_,{A,B1}},{_,{A,B2}}) when B1=<B2->true;
- (_,_)->false end,
- SortedVR = lists:usort(Fun,VR),
- constraint_union_vr(SortedVR, []).
-
-constraint_union_vr([],Acc) ->
- lists:reverse(Acc);
-constraint_union_vr([C|Rest],[]) ->
- constraint_union_vr(Rest,[C]);
-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 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);
-constraint_union_vr([VR|Rest],Acc) ->
- constraint_union_vr(Rest,[VR|Acc]).
+c_min('MIN', _) -> 'MIN';
+c_min(_, 'MIN') -> 'MIN';
+c_min(A, B) -> min(A, B).
union_sv_vr(_S,{'SingleValue',SV},VR)
when is_integer(SV) ->
@@ -4628,55 +4510,43 @@ check_reference(S,#'Externaltypereference'{pos=Pos,module=Emod,type=Name}) ->
#'Externaltypereference'{pos=Pos,module=ModName,type=Name}
end.
+get_referenced_type(S, T) ->
+ case do_get_referenced_type(S, T) of
+ {_,#type{def=#'Externaltypereference'{}=ERef}} ->
+ get_referenced_type(S, ERef);
+ {_,#type{def=#'Externalvaluereference'{}=VRef}} ->
+ get_referenced_type(S, VRef);
+ {_,_}=Res ->
+ Res
+ end.
-get_referenced_type(S,Ext) when is_record(Ext,'Externaltypereference') ->
- case match_parameters(S,Ext, S#state.parameters) of
- Ext ->
- #'Externaltypereference'{pos=Pos,module=Emod,type=Etype} = Ext,
- case S#state.mname of
- Emod -> % a local reference in this module
- get_referenced1(S,Emod,Etype,Pos);
- _ ->% always when multi file compiling
- case lists:member(Emod,S#state.inputmodules) of
- true ->
- get_referenced1(S,Emod,Etype,Pos);
- false ->
- get_referenced(S,Emod,Etype,Pos)
- end
- end;
- ERef = #'Externaltypereference'{} ->
- get_referenced_type(S,ERef);
- Other ->
- {undefined,Other}
- end;
-get_referenced_type(S=#state{mname=Emod},
- ERef=#'Externalvaluereference'{pos=P,module=Emod,
- value=Eval}) ->
- case match_parameters(S,ERef,S#state.parameters) of
- ERef ->
- get_referenced1(S,Emod,Eval,P);
- OtherERef when is_record(OtherERef,'Externalvaluereference') ->
- get_referenced_type(S,OtherERef);
- Value ->
- {Emod,Value}
- end;
-get_referenced_type(S,ERef=#'Externalvaluereference'{pos=Pos,module=Emod,
- value=Eval}) ->
- case match_parameters(S,ERef,S#state.parameters) of
- ERef ->
- case lists:member(Emod,S#state.inputmodules) of
- true ->
- get_referenced1(S,Emod,Eval,Pos);
- false ->
- get_referenced(S,Emod,Eval,Pos)
- end;
- OtherERef ->
- get_referenced_type(S,OtherERef)
- end;
-get_referenced_type(S,#identifier{val=Name,pos=Pos}) ->
- get_referenced1(S,undefined,Name,Pos);
-get_referenced_type(_S,Type) ->
- {undefined,Type}.
+do_get_referenced_type(#state{parameters=Ps}=S, T0) ->
+ case match_parameters(S, T0, Ps) of
+ T0 ->
+ do_get_ref_type_1(S, T0);
+ T ->
+ do_get_referenced_type(S, T)
+ end.
+
+do_get_ref_type_1(S, #'Externaltypereference'{pos=P,
+ module=M,
+ type=T}) ->
+ do_get_ref_type_2(S, P, M, T);
+do_get_ref_type_1(S, #'Externalvaluereference'{pos=P,
+ module=M,
+ value=V}) ->
+ do_get_ref_type_2(S, P, M, V);
+do_get_ref_type_1(_, T) ->
+ {undefined,T}.
+
+do_get_ref_type_2(#state{mname=Current,inputmodules=Modules}=S,
+ Pos, M, T) ->
+ case M =:= Current orelse lists:member(M, Modules) of
+ true ->
+ get_referenced1(S, M, T, Pos);
+ false ->
+ get_referenced(S, M, T, Pos)
+ end.
%% get_referenced/3
%% The referenced entity Ename may in case of an imported parameterized
@@ -4975,73 +4845,46 @@ imported1(Name,
end;
imported1(_Name,[]) ->
false.
-
-check_integer(_S,[],_C) ->
+%% Check the named number list for an INTEGER or a BIT STRING.
+check_named_number_list(_S, []) ->
[];
-check_integer(S,NamedNumberList,_C) ->
- case [X || X <- NamedNumberList, tuple_size(X) =:= 2] of
- NamedNumberList ->
- %% An already checked integer with NamedNumberList
- NamedNumberList;
- _ ->
- case check_unique(NamedNumberList,2) of
- [] ->
- check_int(S,NamedNumberList,[]);
- L when is_list(L) ->
- error({type,{duplicates,L},S}),
- unchanged
- end
+check_named_number_list(_S, [{_,_}|_]=NNL) ->
+ %% The named number list has already been checked.
+ NNL;
+check_named_number_list(S, NNL0) ->
+ %% Check that the names are unique.
+ T = S#state.type,
+ case check_unique(NNL0, 2) of
+ [] ->
+ NNL1 = [{Id,resolve_valueref(S, Val)} || {'NamedNumber',Id,Val} <- NNL0],
+ NNL = lists:keysort(2, NNL1),
+ case check_unique(NNL, 2) of
+ [] ->
+ NNL;
+ [Val|_] ->
+ asn1_error(S, T, {value_reused,Val})
+ end;
+ [H|_] ->
+ asn1_error(S, T, {namelist_redefinition,H})
end.
-
-check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when is_integer(Num) ->
- check_int(S,T,[{Id,Num}|Acc]);
-check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
- Val = dbget_ex(S,S#state.mname,Name),
- check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
-check_int(S,[{'NamedNumber',Id,{'Externalvaluereference',_,Mod,Name}}|T],Acc) ->
- Val = dbget_ex(S,Mod,Name),
- check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
-check_int(_S,[],Acc) ->
- lists:keysort(2,Acc).
+resolve_valueref(S, #'Externalvaluereference'{module=Mod,value=Name}) ->
+ dbget_ex(S, Mod, Name);
+resolve_valueref(_, Val) when is_integer(Val) ->
+ Val.
-check_real(_S,_Constr) ->
- ok.
+check_integer(S, NNL) ->
+ check_named_number_list(S, NNL).
-check_bitstring(_S,[],_Constr) ->
- [];
-check_bitstring(S,NamedNumberList,_Constr) ->
- case check_unique(NamedNumberList,2) of
- [] ->
- check_bitstr(S,NamedNumberList,[]);
- L when is_list(L) ->
- error({type,{duplicates,L},S}),
- unchanged
- end.
+check_bitstring(S, NNL0) ->
+ NNL = check_named_number_list(S, NNL0),
+ _ = [asn1_error(S, S#state.type, {invalid_bit_number,Bit}) ||
+ {_,Bit} <- NNL, Bit < 0],
+ NNL.
-check_bitstr(S,[{'NamedNumber',Id,Num}|T],Acc)when is_integer(Num) ->
- check_bitstr(S,T,[{Id,Num}|Acc]);
-check_bitstr(S,[{'NamedNumber',Id,Name}|T],Acc) when is_atom(Name) ->
-%%check_bitstr(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
-%% io:format("asn1ct_check:check_bitstr/3 hej hop ~w~n",[Name]),
- Val = dbget_ex(S,S#state.mname,Name),
-%% io:format("asn1ct_check:check_bitstr/3: ~w~n",[Val]),
- check_bitstr(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
-check_bitstr(S,[],Acc) ->
- case check_unique(Acc,2) of
- [] ->
- lists:keysort(2,Acc);
- L when is_list(L) ->
- error({type,{duplicate_values,L},S}),
- unchanged
- end;
-%% When a BIT STRING already is checked, for instance a COMPONENTS OF S
-%% where S is a sequence that has a component that is a checked BS, the
-%% NamedNumber list is a list of {atom(),integer()} elements.
-check_bitstr(S,[El={Id,Num}|Rest],Acc) when is_atom(Id),is_integer(Num) ->
- check_bitstr(S,Rest,[El|Acc]).
-
+check_real(_S,_Constr) ->
+ ok.
%% Check INSTANCE OF
%% check that DefinedObjectClass is of TYPE-IDENTIFIER class
@@ -5052,20 +4895,16 @@ check_instance_of(S,DefinedObjectClass,Constraint) ->
check_type_identifier(S,DefinedObjectClass),
iof_associated_type(S,Constraint).
-
-check_type_identifier(_S,'TYPE-IDENTIFIER') ->
- ok;
-check_type_identifier(S,Eref=#'Externaltypereference'{}) ->
- case get_referenced_type(S,Eref) of
- {_,#classdef{name='TYPE-IDENTIFIER'}} -> ok;
- {_,#classdef{typespec=NextEref}}
- when is_record(NextEref,'Externaltypereference') ->
- check_type_identifier(S,NextEref);
+check_type_identifier(S, Eref=#'Externaltypereference'{type=Class}) ->
+ case get_referenced_type(S, Eref) of
+ {_,#classdef{name='TYPE-IDENTIFIER'}} ->
+ ok;
+ {_,#classdef{typespec=#'Externaltypereference'{}=NextEref}} ->
+ check_type_identifier(S, NextEref);
{_,TD=#typedef{typespec=#type{def=#'Externaltypereference'{}}}} ->
- check_type_identifier(S,(TD#typedef.typespec)#type.def);
- Err ->
- error({type,{"object set in type INSTANCE OF "
- "not of class TYPE-IDENTIFIER",Eref,Err},S})
+ check_type_identifier(S, (TD#typedef.typespec)#type.def);
+ _ ->
+ asn1_error(S, S#state.type, {illegal_instance_of,Class})
end.
iof_associated_type(S,[]) ->
@@ -5195,9 +5034,6 @@ check_enumerated(S,NamedNumberList,_Constr) ->
%% the latter is returned if the ENUMERATION contains EXTENSIONMARK
check_enum(S,[{'NamedNumber',Id,Num}|T],Acc1,Acc2,Root) when is_integer(Num) ->
check_enum(S,T,[{Id,Num}|Acc1],Acc2,Root);
-check_enum(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc1,Acc2,Root) ->
- Val = dbget_ex(S,S#state.mname,Name),
- check_enum(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc1,Acc2,Root);
check_enum(S,['EXTENSIONMARK'|T],Acc1,Acc2,_Root) ->
NewAcc2 = lists:keysort(2,Acc1),
NewList = enum_number(lists:reverse(Acc2),NewAcc2,0,[],[]),
@@ -6747,6 +6583,8 @@ merge_tags2([T1= #tag{type='IMPLICIT'}, T2 |Rest], Acc) ->
merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
merge_tags2([T1= #tag{type={default,'IMPLICIT'}}, T2 |Rest], Acc) ->
merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
+merge_tags2([T1= #tag{type={default,'AUTOMATIC'}}, T2 |Rest], Acc) ->
+ merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
merge_tags2([H|T],Acc) ->
merge_tags2(T, [H|Acc]);
merge_tags2([], Acc) ->
@@ -6798,7 +6636,7 @@ merge_tags2([], Acc) ->
storeindb(S,M) when is_record(M,module) ->
TVlist = M#module.typeorval,
NewM = M#module{typeorval=findtypes_and_values(TVlist)},
- asn1_db:dbnew(NewM#module.name),
+ asn1_db:dbnew(NewM#module.name, S#state.erule),
asn1_db:dbput(NewM#module.name,'MODULE', NewM),
Res = storeindb(#state{mname=NewM#module.name}, TVlist, []),
include_default_class(S,NewM#module.name),
@@ -6813,7 +6651,7 @@ storeindb(#state{mname=Module}=S, [H|T], Errors) ->
storeindb(S, T, Errors);
Prev ->
PrevLine = asn1ct:get_pos_of_def(Prev),
- {error,Error} = asn1_error(S, H, {already_defined,Name,PrevLine}),
+ Error = return_asn1_error(S, H, {already_defined,Name,PrevLine}),
storeindb(S, T, [Error|Errors])
end;
storeindb(_, [], []) ->
@@ -6860,32 +6698,54 @@ 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) ->
+return_asn1_error(#state{mname=Where}, Item, Error) ->
Pos = asn1ct:get_pos_of_def(Item),
- {error,{structured_error,{Where,Pos},?MODULE,Error}}.
+ {structured_error,{Where,Pos},?MODULE,Error}.
+
+asn1_error(S, Item, Error) ->
+ throw({error,return_asn1_error(S, Item, Error)}).
format_error({already_defined,Name,PrevLine}) ->
io_lib:format("the name ~p has already been defined at line ~p",
[Name,PrevLine]);
+format_error({illegal_instance_of,Class}) ->
+ io_lib:format("using INSTANCE OF on class '~s' is illegal, "
+ "because INSTANCE OF may only be used on the class TYPE-IDENTFIER",
+ [Class]);
+format_error(illegal_octet_string_value) ->
+ "expecting a bstring or an hstring as value for an OCTET STRING";
+format_error({illegal_typereference,Name}) ->
+ io_lib:format("'~p' is used as a typereference, but does not start with an uppercase letter", [Name]);
+format_error({invalid_fields,Fields,Obj}) ->
+ io_lib:format("invalid ~s in ~p", [format_fields(Fields),Obj]);
+format_error({invalid_bit_number,Bit}) ->
+ io_lib:format("the bit number '~p' is invalid", [Bit]);
+format_error({missing_mandatory_fields,Fields,Obj}) ->
+ io_lib:format("missing mandatory ~s in ~p",
+ [format_fields(Fields),Obj]);
+format_error({namelist_redefinition,Name}) ->
+ io_lib:format("the name '~s' can not be redefined", [Name]);
format_error({undefined,Name}) ->
io_lib:format("'~s' is referenced, but is not defined", [Name]);
+format_error({undefined_import,Ref,Module}) ->
+ io_lib:format("'~s' is not exported from ~s", [Ref,Module]);
+format_error({value_reused,Val}) ->
+ io_lib:format("the value '~p' is used more than once", [Val]);
format_error(Other) ->
io_lib:format("~p", [Other]).
+format_fields([F]) ->
+ io_lib:format("field &~s", [F]);
+format_fields([H|T]) ->
+ [io_lib:format("fields &~s", [H])|
+ [io_lib:format(", &~s", [F]) || F <- T]].
+
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]),
{error,{export,Pos,Mname,Typename,Msg}};
-error({import,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) ->
- PosOfDef =
- fun(#'Externaltypereference'{pos=P}) -> P;
- (#'Externalvaluereference'{pos=P}) -> P
- end,
- Pos = PosOfDef(Ref),
- io:format("asn1error:~p:~p:~p~n~p~n",[Pos,Mname,Typename,Msg]),
- {error,{import,Pos,Mname,Typename,Msg}};
% error({type,{Msg1,Msg2},#state{mname=Mname,type=Type,tname=Typename}})
% when is_record(Type,typedef) ->
% io:format("asn1error:~p:~p:~p ~p~n",
@@ -7102,7 +6962,7 @@ include_default_class1(_,[]) ->
include_default_class1(Module,[{Name,TS}|Rest]) ->
case asn1_db:dbget(Module,Name) of
undefined ->
- C = #classdef{checked=true,name=Name,
+ C = #classdef{checked=true,module=Module,name=Name,
typespec=TS},
asn1_db:dbput(Module,Name,C);
_ -> ok
@@ -7186,3 +7046,6 @@ check_fold(S, [H|T], Check) ->
[Error|check_fold(S, T, Check)]
end;
check_fold(_, [], Check) when is_function(Check, 3) -> [].
+
+name_of_def(#'Externaltypereference'{type=N}) -> N;
+name_of_def(#'Externalvaluereference'{value=N}) -> N.
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index 761faa53c5..820d19b85c 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-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2014. 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
@@ -122,8 +122,8 @@ gen_encode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
AttrN])),
emit([ObjectEncode," = ",nl,
- " ",{asis,ObjSetMod},":'getenc_",ObjSetName,
- "'(",{asis,UniqueFieldName},", ",nl]),
+ " ",{asis,ObjSetMod},":'getenc_",ObjSetName,
+ "'("]),
ValueMatch = value_match(ValueIndex,
lists:concat(["Cindex",N])),
emit([indent(35),ValueMatch,"),",nl]),
@@ -198,7 +198,7 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:new(tlv),
asn1ct_name:new(v),
- {DecObjInf,UniqueFName,ValueIndex} =
+ {DecObjInf,ValueIndex} =
case TableConsInfo of
#simpletableattributes{objectsetname=ObjectSetRef,
c_name=AttrN,
@@ -217,12 +217,12 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
%% relation from a component to another components
%% subtype component
{{AttrN,{deep,ObjectSetRef,UniqueFieldName,ValIndex}},
- UniqueFieldName,ValIndex};
+ ValIndex};
false ->
- {{AttrN,ObjectSetRef},UniqueFieldName,ValIndex}
+ {{AttrN,ObjectSetRef},ValIndex}
end;
_ ->
- {false,false,false}
+ {false,false}
end,
RecordName = lists:concat([get_record_name_prefix(),
asn1ct_gen:list2rname(Typename)]),
@@ -234,7 +234,7 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:new(rb),
emit([" {'",RecordName,"'}.",nl,nl]);
{LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
+ emit([nl]),
case {LeadingAttrTerm,PostponedDecArgs} of
{[],[]} ->
ok;
@@ -246,7 +246,7 @@ gen_decode_sequence(Erules,Typename,D) when is_record(D,type) ->
{ObjSetMod,ObjSetName} = ObjSetRef,
emit([DecObj," =",nl,
" ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
+ ValueMatch,"),",nl]),
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
end,
demit(["Result = "]), %dbg
@@ -357,7 +357,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:new(v),
- {DecObjInf,UniqueFName,ValueIndex} =
+ {DecObjInf,ValueIndex} =
case TableConsInfo of
%% {ObjectSetRef,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
#simpletableattributes{objectsetname=ObjectSetRef,
@@ -378,12 +378,12 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
%% relation from a component to another components
%% subtype component
{{AttrN,{deep,ObjectSetRef,UniqueFieldName,ValIndex}},
- UniqueFieldName,ValIndex};
+ ValIndex};
false ->
- {{AttrN,ObjectSetRef},UniqueFieldName,ValIndex}
+ {{AttrN,ObjectSetRef},ValIndex}
end;
_ ->
- {false,false,false}
+ {false,false}
end,
case CompList of
@@ -413,7 +413,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
%% return value as record
emit([" {'",RecordName,"'}.",nl]);
{LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
+ emit([nl]),
case {LeadingAttrTerm,PostponedDecArgs} of
{[],[]} ->
ok;
@@ -425,7 +425,7 @@ gen_decode_set(Erules,Typename,D) when is_record(D,type) ->
{ObjSetMod,ObjSetName} = ObjSetRef,
emit([DecObj," =",nl,
" ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
+ ValueMatch,"),",nl]),
gen_dec_postponed_decs(DecObj,PostponedDecArgs)
end,
demit(["Result = "]), %dbg
@@ -577,6 +577,8 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
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),
+ asn1ct_name:new(tmpBytes),
+ asn1ct_name:new(tmpLen),
CindexPos =
case Order of
undefined ->
@@ -615,18 +617,20 @@ gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type
{LA,PostponedDec} =
gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
Ext,DecObjInf),
+ emit([com,nl]),
case Rest of
[] ->
{LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
_ ->
- emit([com,nl]),
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.
+ no_terms;
+gen_dec_sequence_call1(_, _, [], _Num, _, _, LA, PostponedDec) ->
+ {LA, PostponedDec}.
gen_dec_sequence_call2(_Erules,_TopType, {[], [], []}, _Ext,_DecObjInf) ->
no_terms;
@@ -641,7 +645,6 @@ gen_dec_sequence_call2(Erules,TopType,{Root1,EList,Root2},_Ext,DecObjInf) ->
%% 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}),
emit([{curr,tlv}," = ",
{call,ber,skip_ExtensionAdditions,
[{prev,tlv},{asis,TagList}]},com,nl]),
@@ -706,8 +709,6 @@ emit_term_tlv('OPTIONAL',InnerType,DecObjInf) ->
emit_term_tlv(opt_or_def,InnerType,DecObjInf);
emit_term_tlv(Prop,{typefield,_},DecObjInf) ->
emit_term_tlv(Prop,type_or_object_field,DecObjInf);
-emit_term_tlv(Prop,{objectfield,_,_},DecObjInf) ->
- emit_term_tlv(Prop,type_or_object_field,DecObjInf);
emit_term_tlv(opt_or_def,type_or_object_field,NotFalse)
when NotFalse /= false ->
asn1ct_name:new(tmpterm),
@@ -789,6 +790,7 @@ gen_enc_choice2(Erules,TopType,[H1|T]) when is_record(H1,'ComponentType') ->
componentrelation)} of
{#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
asn1ct_name:new(tmpBytes),
+ asn1ct_name:new(tmpLen),
asn1ct_name:new(encBytes),
asn1ct_name:new(encLen),
Emit = ["{",{curr,tmpBytes},", _} = "],
@@ -929,7 +931,6 @@ gen_enc_line(Erules,TopType,Cname,
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);
_ ->
@@ -962,8 +963,7 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
WhatKind = asn1ct_gen:type(InnerType),
emit(IndDeep),
emit(Assign),
- gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
- Element),
+ gen_optormand_case(OptOrMand, Erules, TopType, Cname, Type, Element),
case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
componentrelation)} of
% #type{constraint=[{tableconstraint_info,RefedFieldName}],
@@ -991,12 +991,8 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
{call,ber,encode_open_type,
[{curr,tmpBytes},{asis,Tag}]},nl]);
_ ->
- emit(["{",{next,tmpBytes},",",{curr,tmpLen},
- "} = ",
- {call,ber,encode_open_type,
- [{curr,tmpBytes},{asis,Tag}]},com,nl]),
- emit(IndDeep),
- emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
+ emit([{call,ber,encode_open_type,
+ [{curr,tmpBytes},{asis,Tag}]}])
end;
Err ->
throw({asn1,{'internal error',Err}})
@@ -1033,26 +1029,19 @@ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
emit([nl,indent(7),"end"])
end.
-gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
- _Element) ->
+gen_optormand_case(mandatory, _Erules, _TopType, _Cname, _Type, _Element) ->
ok;
-gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
- Element) ->
+gen_optormand_case('OPTIONAL', Erules, _TopType, _Cname, _Type, 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) ->
+gen_optormand_case({'DEFAULT',DefaultValue}, Erules, _TopType,
+ _Cname, Type, 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]);
+ asn1ct_gen_check:emit(Type, DefaultValue, Element);
_ ->
emit([" case ",Element," of",nl]),
emit([indent(9),"asn1_DEFAULT -> {",
@@ -1067,10 +1056,9 @@ gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
emit([indent(9),{asis,
DefaultValue}," -> {",
empty_lb(Erules),",0};",nl])
- end
- end,
- emit([indent(9),"_ ->",nl,indent(12)]).
-
+ end,
+ emit([indent(9),"_ ->",nl,indent(12)])
+ end.
gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
@@ -1159,7 +1147,8 @@ gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
emit([indent(4),"_ ->",nl]),
case OptOrMand of
- {'DEFAULT', Def} ->
+ {'DEFAULT', Def0} ->
+ Def = asn1ct_gen:conform_value(Type, Def0),
emit([indent(8),"{",{asis,Def},",",{prev,tlv},"}",nl]);
'OPTIONAL' ->
emit([indent(8),"{ asn1_NOVALUE, ",{prev,tlv},"}",nl])
@@ -1213,28 +1202,25 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC
(Type#type.def)#'ObjectClassFieldType'.fieldname,
[{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) ->
- 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,
- OptOrMand,DecObjInf,_) ->
+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),
+ gen_dec_call1(WhatKind, InnerType, TopType, Cname,
+ Type, BytesVar, Tag),
case DecObjInf of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ {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,")"]);
+ "'(",ValueMatch,")"]);
_ ->
ok
end,
[].
-gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
- Tag,OptOrMand,_) ->
+
+gen_dec_call1({primitive,bif}, InnerType, TopType, Cname,
+ Type, BytesVar, Tag) ->
case {asn1ct:get_gen_state_field(namelist),InnerType} of
{[{Cname,undecoded}|Rest],_} ->
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
@@ -1243,11 +1229,10 @@ gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
BytesVar,"}"]);
_ ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand)
+ ?ASN1CT_GEN_BER:gen_dec_prim(Type, BytesVar, Tag)
end;
-gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
- Tag,OptOrMand,_) ->
+gen_dec_call1('ASN1_OPEN_TYPE', _InnerType, TopType, Cname,
+ Type, BytesVar, Tag) ->
case {asn1ct:get_gen_state_field(namelist),Type#type.def} of
{[{Cname,undecoded}|Rest],_} ->
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
@@ -1256,15 +1241,12 @@ gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
BytesVar,"}"]);
{_,#'ObjectClassFieldType'{type=OpenType}} ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
- BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand);
+ ?ASN1CT_GEN_BER:gen_dec_prim(#type{def=OpenType},
+ BytesVar, Tag);
_ ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand)
+ ?ASN1CT_GEN_BER:gen_dec_prim(Type, BytesVar, Tag)
end;
-gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar,
- Tag,_,_OptOrMand) ->
+gen_dec_call1(WhatKind, _, TopType, Cname, Type, BytesVar, Tag) ->
case asn1ct:get_gen_state_field(namelist) of
[{Cname,undecoded}|Rest] ->
asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index d279e9697f..a91404ed54 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -43,10 +43,13 @@ gen_encode_set(Erules,TypeName,D) ->
gen_encode_sequence(Erules,TypeName,D) ->
gen_encode_constructed(Erules,TypeName,D).
-gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
+gen_encode_constructed(Erule, Typename, #type{}=D) ->
asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
+ Imm = gen_encode_constructed_imm(Erule, Typename, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
+
+gen_encode_constructed_imm(Erule, Typename, #type{}=D) ->
{ExtAddGroup,TmpCompList,TableConsInfo} =
case D#type.def of
#'SEQUENCE'{tablecinf=TCI,components=CL,extaddgroup=ExtAddGroup0} ->
@@ -65,74 +68,36 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
[Comp#'ComponentType'{textual_order=undefined}||
Comp<-TmpCompList]
end,
- case Typename of
- ['EXTERNAL'] ->
- emit([{next,val}," = ",
- {call,ext,transform_to_EXTERNAL1990,
- [{curr,val}]},com,nl]),
- asn1ct_name:new(val);
- _ ->
- ok
- end,
- case {Optionals = optionals(to_textual_order(CompList)),CompList,
- is_optimized(Erule)} of
- {[],EmptyCL,_} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
- ok;
- {[],_,_} ->
- emit([{next,val}," = ",{curr,val},",",nl]);
- {_,_,true} ->
- gen_fixoptionals(Optionals),
- FixOpts = param_map(fun(Var) ->
- {var,Var}
- end,asn1ct_name:all(fixopt)),
- emit({"{",{next,val},",Opt} = {",{curr,val},",[",FixOpts,"]},",nl});
- {_,_,false} ->
- asn1ct_func:need({Erule,fixoptionals,3}),
- Fixoptcall = ",Opt} = fixoptionals(",
- emit({"{",{next,val},Fixoptcall,
- {asis,Optionals},",",length(Optionals),
- ",",{curr,val},"),",nl})
- end,
- asn1ct_name:new(val),
+ ExternalImm =
+ case Typename of
+ ['EXTERNAL'] ->
+ Next = asn1ct_gen:mk_var(asn1ct_name:next(val)),
+ Curr = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ asn1ct_name:new(val),
+ [{call,ext,transform_to_EXTERNAL1990,[{var,Curr}],{var,Next}}];
+ _ ->
+ []
+ end,
+ Aligned = is_aligned(Erule),
+ Value0 = make_var(val),
+ Optionals = optionals(to_textual_order(CompList)),
+ ImmOptionals = [asn1ct_imm:per_enc_optional(Value0, Opt, Aligned) ||
+ Opt <- Optionals],
Ext = extensible_enc(CompList),
- case Ext of
- {ext,_,NumExt} when NumExt > 0 ->
- case extgroup_pos_and_length(CompList) of
- {extgrouppos,[]} -> % no extenstionAdditionGroup
- ok;
- {extgrouppos,ExtGroupPosLenList} ->
- ExtGroupFun =
- fun({ExtActualGroupPos,ExtGroupVirtualPos,ExtGroupLen}) ->
- Elements =
- make_elements(ExtGroupVirtualPos+1,
- "Val1",
- lists:seq(1,ExtGroupLen)),
- emit([
- {next,val}," = case [X || X <- [",Elements,
- "],X =/= asn1_NOVALUE] of",nl,
- "[] -> setelement(",
- {asis,ExtActualGroupPos+1},",",
- {curr,val},",",
- "asn1_NOVALUE);",nl,
- "_ -> setelement(",{asis,ExtActualGroupPos+1},",",
- {curr,val},",",
- "{extaddgroup,", Elements,"})",nl,
- "end,",nl]),
- asn1ct_name:new(val)
- end,
- lists:foreach(ExtGroupFun,ExtGroupPosLenList)
- end,
- asn1ct_name:new(tmpval),
- emit(["Extensions = ",
- {call,Erule,fixextensions,[{asis,Ext},{curr,val}]},
- com,nl]);
- _ -> true
- end,
- EncObj =
+ ExtImm = case Ext of
+ {ext,ExtPos,NumExt} when NumExt > 0 ->
+ gen_encode_extaddgroup(CompList),
+ Value = make_var(val),
+ asn1ct_imm:per_enc_extensions(Value, ExtPos,
+ NumExt, Aligned);
+ _ ->
+ []
+ end,
+ {EncObj,ObjSetImm} =
case TableConsInfo of
#simpletableattributes{usedclassfield=Used,
uniqueclassfield=Unique} when Used /= Unique ->
- false;
+ {false,[]};
%% ObjectSet, name of the object set in constraints
%%
%%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
@@ -141,24 +106,19 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
c_index=N,
usedclassfield=UniqueFieldName,
uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex
+ valueindex=ValueIndex0
} -> %% N is index of attribute that determines constraint
{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])),
- 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};
+ ValueIndex = ValueIndex0 ++ [{N+1,top}],
+ Val = make_var(val),
+ {ObjSetImm0,Dst} = enc_dig_out_value(ValueIndex, Val),
+ {{AttrN,Dst},ObjSetImm0};
false ->
- false
+ {false,[]}
end;
_ ->
case D#type.tablecinf of
@@ -166,34 +126,52 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
%% when the simpletableattributes was at an outer
%% level and the objfun has been passed through the
%% function call
- {"got objfun through args","ObjFun"};
+ {{"got objfun through args",{var,"ObjFun"}},[]};
_ ->
- false
+ {false,[]}
end
end,
- emit({"[",nl}),
- MaybeComma1 =
+ ImmSetExt =
case Ext of
- {ext,_Pos,NumExt2} when NumExt2 > 0 ->
- call(Erule, setext, ["Extensions =/= []"]),
- ", ";
- {ext,_Pos,_} ->
- call(Erule, setext, ["false"]),
- ", ";
- _ ->
- ""
- end,
- MaybeComma2 =
- case optionals(CompList) of
- [] -> MaybeComma1;
- _ ->
- emit(MaybeComma1),
- emit("Opt"),
- {",",nl}
+ {ext,_Pos,NumExt2} when NumExt2 > 0 ->
+ asn1ct_imm:per_enc_extension_bit({var,"Extensions"}, Aligned);
+ {ext,_Pos,_} ->
+ asn1ct_imm:per_enc_extension_bit([], Aligned);
+ _ ->
+ []
end,
- gen_enc_components_call(Erule,Typename,CompList,MaybeComma2,EncObj,Ext),
- emit({"].",nl}).
+ ImmBody = gen_enc_components_call(Erule, Typename, CompList, EncObj, Ext),
+ ExternalImm ++ ExtImm ++ ObjSetImm ++
+ asn1ct_imm:enc_append([ImmSetExt] ++ ImmOptionals ++ ImmBody).
+
+gen_encode_extaddgroup(CompList) ->
+ case extgroup_pos_and_length(CompList) of
+ {extgrouppos,[]} ->
+ ok;
+ {extgrouppos,ExtGroupPosLenList} ->
+ _ = [do_gen_encode_extaddgroup(G) || G <- ExtGroupPosLenList],
+ ok
+ end.
+do_gen_encode_extaddgroup({ActualGroupPos,GroupVirtualPos,GroupLen}) ->
+ Val = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ Elements = make_elements(GroupVirtualPos+1,
+ Val,
+ lists:seq(1, GroupLen)),
+ Expr = any_non_value(GroupVirtualPos+1, Val, GroupLen, ""),
+ emit([{next,val}," = case ",Expr," of",nl,
+ "false -> setelement(",{asis,ActualGroupPos+1},", ",
+ {curr,val},", asn1_NOVALUE);",nl,
+ "true -> setelement(",{asis,ActualGroupPos+1},", ",
+ {curr,val},", {extaddgroup,", Elements,"})",nl,
+ "end,",nl]),
+ asn1ct_name:new(val).
+
+any_non_value(_, _, 0, _) ->
+ [];
+any_non_value(Pos, Val, N, Sep) ->
+ Sep ++ [make_element(Pos, Val)," =/= asn1_NOVALUE"] ++
+ any_non_value(Pos+1, Val, N-1, [" orelse",nl]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% generate decode function for SEQUENCE and SET
@@ -328,28 +306,29 @@ gen_dec_constructed_imm(Erule, Typename, #type{}=D) ->
EmitComp = gen_dec_components_call(Erule, Typename, CompList,
DecObjInf, Ext, length(Optionals)),
EmitRest = fun({AccTerm,AccBytes}) ->
- gen_dec_constructed_imm_2(Typename, CompList,
+ gen_dec_constructed_imm_2(Erule, Typename,
+ CompList,
ObjSetInfo,
AccTerm, AccBytes)
end,
[EmitExt,EmitOpt|EmitComp++[{safe,EmitRest}]].
-gen_dec_constructed_imm_2(Typename, CompList,
+gen_dec_constructed_imm_2(Erule, Typename, CompList,
ObjSetInfo, AccTerm, AccBytes) ->
- {_,UniqueFName,ValueIndex} = ObjSetInfo,
+ {_,_UniqueFName,ValueIndex} = ObjSetInfo,
case {AccTerm,AccBytes} of
{[],[]} ->
ok;
{_,[]} ->
ok;
{[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- {ObjSetMod,ObjSetName} = ObjSet,
- emit([DecObj," =",nl,
- " ",{asis,ObjSetMod},":'getdec_",ObjSetName,"'(",
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
- gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
+ ValueMatch = value_match(ValueIndex, Term),
+ _ = [begin
+ gen_dec_open_type(Erule, ValueMatch, ObjSet,
+ LeadingAttr, T),
+ emit([com,nl])
+ end || T <- ListOfOpenTypes],
+ ok
end,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
@@ -423,67 +402,147 @@ to_textual_order(Cs) when is_list(Cs) ->
to_textual_order(Cs) ->
Cs.
-gen_dec_listofopentypes(_,[],_) ->
- emit(nl);
-gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
+gen_dec_open_type(Erule, Val, {Xmod,Xtype}, LeadingAttr,
+ {_,{Name,RestFieldNames},Term,TmpTerm,Prop}) ->
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({decode,ObjSet,RestFieldNames,
+ Prop,Extensible})),
+ Typename = [Name,ClType],
+ Gen = fun(_Fd, N) ->
+ dec_objset_optional(N, Prop),
+ dec_objset(Erule, N, ObjSet, RestFieldNames, Typename),
+ dec_objset_default(N, Name, LeadingAttr, Extensible)
+ end,
+ Prefix = lists:concat(["dec_os_",Name]),
+ F = asn1ct_func:call_gen(Prefix, Key, Gen),
+ emit([Term," = ",{asis,F},"(",TmpTerm,", ",Val,")"]).
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
+dec_objset_optional(N, {'DEFAULT',Val}) ->
+ dec_objset_optional_1(N, Val);
+dec_objset_optional(N, 'OPTIONAL') ->
+ dec_objset_optional_1(N, asn1_NOVALUE);
+dec_objset_optional(_N, mandatory) -> ok.
- emit([Term," = ",nl]),
+dec_objset_optional_1(N, Val) ->
+ emit([{asis,N},"(",{asis,Val},", _Id) ->",nl,
+ {asis,Val},";",nl]).
- N = case Prop of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
+dec_objset(_Erule, _N, [], _, _) ->
+ ok;
+dec_objset(Erule, N, [Obj|Objs], RestFields, Cl) ->
+ dec_objset_1(Erule, N, Obj, RestFields, Cl),
+ emit([";",nl]),
+ dec_objset(Erule, N, Objs, RestFields, Cl).
+
+dec_objset_default(N, C, LeadingAttr, false) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl,
+ "exit({'Type not compatible with table constraint',"
+ "{{component,",{asis,C},"},"
+ "{value,Bytes},"
+ "{unique_name_and_value,",{asis,LeadingAttr},",Id}}}).",nl,nl]);
+dec_objset_default(N, _, _, true) ->
+ emit([{asis,N},"(Bytes, Id) ->",nl|
+ case asn1ct:use_legacy_types() of
+ false ->
+ ["{asn1_OPENTYPE,Bytes}.",nl,nl];
+ true ->
+ ["Bytes.",nl,nl]
+ end]).
+
+dec_objset_1(Erule, N, {Id,Obj}, RestFields, Typename) ->
+ emit([{asis,N},"(Bytes, ",{asis,Id},") ->",nl]),
+ dec_objset_2(Erule, Obj, RestFields, Typename).
+
+dec_objset_2(Erule, Obj, RestFields0, Typename) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Type} ->
+ Imm = asn1ct_gen_per:gen_dec_imm(Erule, Type),
+ {Term,_} = asn1ct_imm:dec_slim_cg(Imm, 'Bytes'),
+ emit([com,nl,Term]);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ {'CHOICE',CompList} = Def#type.def,
+ Ext = extensible_enc(CompList),
+ emit(["{Result,_} = begin",nl]),
+ gen_dec_choice(Erule, Typename, CompList, Ext),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SET OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SET OF',
+ Def, false);
+ 'SEQUENCE' ->
+ Imm0 = gen_dec_constructed_imm(Erule, Typename, Def),
+ Imm = opt_imm(Imm0),
+ asn1ct_name:start(),
+ emit(["{Result,_} = begin",nl]),
+ emit_gen_dec_imm(Imm),
+ emit([nl,
+ "end",com,nl,
+ "Result"]);
+ 'SEQUENCE OF' ->
+ asn1ct_name:start(),
+ do_gen_decode_sof(Erule, Typename, 'SEQUENCE OF',
+ Def, false)
+ end;
+ #typedef{name=Type} ->
+ emit(["{Result,_} = ",{asis,enc_func("dec_", Type)},"(Bytes),",nl,
+ "Result"]);
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ emit("{Term,_} = "),
+ Func = enc_func("dec_", Type),
+ case get(currmod) of
+ Mod ->
+ emit([{asis,Func},"(Bytes)"]);
+ _ ->
+ emit([{asis,Mod},":",{asis,Func},"(Bytes)"])
+ end,
+ emit([com,nl,
+ "Term"]);
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFields] = RestFields0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ dec_objset_2(Erule, Typedef, RestFields, Typename)
+ end
+ end.
- emit([indent(N+3),"case (catch ",DecObj,"(",
- {asis,FirstPFN},", ",TmpTerm,", telltype,",{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 Prop of
- mandatory ->
- emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
- gen_dec_listofopentypes(DecObj,Rest,true).
-
-
-emit_opt_or_mand_check(Val,Term) ->
- emit([indent(3),"case ",Term," of",nl,
- indent(6),{asis,Val}," ->",{asis,Val},";",nl,
- indent(6),"_ ->",nl]).
-
-%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
-%% assume Val = {Alternative,AltType}
-%% generate
-%%[
-%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
-%%case element(1,Val) of
-%% alt1 ->
-%% encode_alt1(element(2,Val));
-%% alt2 ->
-%% encode_alt2(element(2,Val))
-%%end
-%%].
-
-gen_encode_choice(Erule,Typename,D) when is_record(D,type) ->
- {'CHOICE',CompList} = D#type.def,
- emit({"[",nl}),
+gen_encode_choice(Erule, TopType, D) ->
+ asn1ct_name:start(),
+ Imm = gen_encode_choice_imm(Erule, TopType, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl]).
+
+gen_encode_choice_imm(Erule, TopType, #type{def={'CHOICE',CompList}}) ->
Ext = extensible_enc(CompList),
- gen_enc_choice(Erule,Typename,CompList,Ext),
- emit({nl,"].",nl}).
+ Aligned = is_aligned(Erule),
+ Cs = gen_enc_choice(Erule, TopType, CompList, Ext),
+ [{assign,{expr,"{ChoiceTag,ChoiceVal}"},"Val"}|
+ asn1ct_imm:per_enc_choice({var,"ChoiceTag"}, Cs, Aligned)].
gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
asn1ct_name:start(),
@@ -496,72 +555,50 @@ gen_decode_choice(Erules,Typename,D) when is_record(D,type) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Encode generator for SEQUENCE OF type
-
-gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_encode_sof(Erule, Typename, SeqOrSetOf, D) ->
asn1ct_name:start(),
- {_SeqOrSetOf,ComponentType} = D#type.def,
- emit({"[",nl}),
- SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
- D#type.constraint),
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _->
- ""
- end,
- gen_encode_length(Erule, SizeConstraint),
- emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",ObjFun,", [])"}),
- emit({nl,"].",nl}),
- gen_encode_sof_components(Erule, Typename, SeqOrSetOf, ComponentType).
-
-
-%% Logic copied from asn1_per_bin_rt2ct:encode_constrained_number
-gen_encode_length(per, {Lb,Ub}) when Ub =< 65535, Lb >= 0 ->
- Range = Ub - Lb + 1,
- V2 = ["(length(Val) - ",Lb,")"],
- Encode = if
- Range == 1 ->
- "[]";
- Range == 2 ->
- {"[",V2,"]"};
- Range =< 4 ->
- {"[10,2,",V2,"]"};
- Range =< 8 ->
- {"[10,3,",V2,"]"};
- Range =< 16 ->
- {"[10,4,",V2,"]"};
- Range =< 32 ->
- {"[10,5,",V2,"]"};
- Range =< 64 ->
- {"[10,6,",V2,"]"};
- Range =< 128 ->
- {"[10,7,",V2,"]"};
- Range =< 255 ->
- {"[10,8,",V2,"]"};
- Range =< 256 ->
- {"[20,1,",V2,"]"};
- Range =< 65536 ->
- {"[20,2,<<",V2,":16>>]"};
- true ->
- {call,per,encode_length,
- [{asis,{Lb,Ub}},"length(Val)"]}
- end,
- emit({nl,Encode,",",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]).
+ Imm = gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, D),
+ asn1ct_imm:enc_cg(Imm, is_aligned(Erule)),
+ emit([".",nl,nl]).
-gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
+gen_encode_sof_imm(Erule, Typename, SeqOrSetOf, #type{}=D) ->
+ {_SeqOrSetOf,ComponentType} = D#type.def,
+ Aligned = is_aligned(Erule),
+ CompType = ComponentType#type.def,
+ Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf, CompType),
+ Conttype = asn1ct_gen:get_inner(CompType),
+ Currmod = get(currmod),
+ Imm0 = case asn1ct_gen:type(Conttype) of
+ {primitive,bif} ->
+ asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"},
+ ComponentType, Aligned);
+ {constructed,bif} ->
+ TypeName = [Constructed_Suffix|Typename],
+ Enc = enc_func(asn1ct_gen:list2name(TypeName)),
+ ObjArg = case D#type.tablecinf of
+ [{objfun,_}|_] -> [{var,"ObjFun"}];
+ _ -> []
+ end,
+ [{apply,{local,Enc,CompType},
+ [{var,"Comp"}|ObjArg]}];
+ #'Externaltypereference'{module=Currmod,type=Ename} ->
+ [{apply,{local,enc_func(Ename),CompType},[{var,"Comp"}]}];
+ #'Externaltypereference'{module=EMod,type=Ename} ->
+ [{apply,{EMod,enc_func(Ename),CompType},[{var,"Comp"}]}];
+ 'ASN1_OPEN_TYPE' ->
+ asn1ct_gen_per:gen_encode_prim_imm({var,"Comp"},
+ #type{def='ASN1_OPEN_TYPE'},
+ Aligned)
+ end,
+ asn1ct_imm:per_enc_sof({var,"Val"}, D#type.constraint, 'Comp',
+ Imm0, Aligned).
+
+gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) ->
asn1ct_name:start(),
+ do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, true),
+ emit([".",nl,nl]).
+
+do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D, NeedRest) ->
{_SeqOrSetOf,ComponentType} = D#type.def,
SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
D#type.constraint),
@@ -573,10 +610,16 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
""
end,
{Num,Buf} = gen_decode_length(SizeConstraint, Erules),
+ Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,
+ ComponentType,NeedRest})),
+ Gen = fun(_Fd, Name) ->
+ gen_decode_sof_components(Erules, Name,
+ Typename, SeqOrSetOf,
+ ComponentType, NeedRest)
+ end,
+ F = asn1ct_func:call_gen("dec_components", Key, Gen),
emit([",",nl,
- "'dec_",asn1ct_gen:list2name(Typename),
- "_components'(",Num,", ",Buf,ObjFun,", []).",nl,nl]),
- gen_decode_sof_components(Erules, Typename, SeqOrSetOf, ComponentType).
+ {asis,F},"(",Num,", ",Buf,ObjFun,", [])"]).
is_aligned(per) -> true;
is_aligned(uper) -> false.
@@ -586,7 +629,7 @@ gen_decode_length(Constraint, Erule) ->
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) ->
+gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont, NeedRest) ->
{ObjFun,ObjFun_Var} =
case Cont#type.tablecinf of
[{objfun,_}|_R] ->
@@ -594,76 +637,38 @@ gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
_ ->
{"",""}
end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
- ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
- ObjFun,", Acc) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
- emit({ObjFun,", ["}),
- %% the component encoder
- Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
- Cont#type.def),
-
- Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Currmod = get(currmod),
- case asn1ct_gen:type(Conttype) of
- {primitive,bif} ->
- asn1ct_gen_per:gen_encode_prim(Erule, Cont, "H");
- {constructed,bif} ->
- NewTypename = [Constructed_Suffix|Typename],
- emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
- ObjFun,")",nl,nl});
- #'Externaltypereference'{module=Currmod,type=Ename} ->
- emit({"'enc_",Ename,"'(H)",nl,nl});
- #'Externaltypereference'{module=EMod,type=EType} ->
- emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
- 'ASN1_OPEN_TYPE' ->
- asn1ct_gen_per:gen_encode_prim(Erule,
- #type{def='ASN1_OPEN_TYPE'},
- "H");
- _ ->
- emit({"'enc_",Conttype,"'(H)",nl,nl})
+ case NeedRest of
+ false ->
+ emit([{asis,Name},"(0, _Bytes",ObjFun_Var,", Acc) ->",nl,
+ "lists:reverse(Acc);",nl]);
+ true ->
+ emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl,
+ "{lists:reverse(Acc),Bytes};",nl])
end,
- emit({" | Acc]).",nl}).
-
-gen_decode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
- {ObjFun,ObjFun_Var} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _"};
- _ ->
- {"",""}
- end,
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_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}),
- emit({indent(3),"{Term,Remain} = "}),
+ emit([{asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl,
+ "{Term,Remain} = "]),
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
Cont#type.def),
Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Ctgenmod = asn1ct_gen:ct_gen_module(Erule),
case asn1ct_gen:type(Conttype) of
{primitive,bif} ->
- Ctgenmod:gen_dec_prim(Erule,Cont,"Bytes"),
+ asn1ct_gen_per:gen_dec_prim(Erule, Cont, "Bytes"),
emit({com,nl});
{constructed,bif} ->
NewTypename = [Constructed_Suffix|Typename],
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(Bytes, telltype",ObjFun,"),",nl});
+ "'(Bytes",ObjFun,"),",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"),
+ asn1ct_gen_per:gen_dec_prim(Erule, #type{def='ASN1_OPEN_TYPE'},
+ "Bytes"),
emit({com,nl});
_ ->
- emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
+ emit({"'dec_",Conttype,"'(Bytes),",nl})
end,
- emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num-1, Remain",ObjFun,", [Term|Acc]).",nl}).
+ emit([{asis,Name},"(Num-1, Remain",ObjFun,", [Term|Acc]).",nl]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -754,27 +759,6 @@ gen_dec_optionals(Optionals) ->
end,
{imm,Imm0,E}.
-gen_fixoptionals([{Pos,Def}|R]) ->
- asn1ct_name:new(fixopt),
- emit({{curr,fixopt}," = case element(",{asis,Pos},",",{curr,val},") of",nl,
- "asn1_DEFAULT -> 0;",nl,
- {asis,Def}," -> 0;",nl,
- "_ -> 1",nl,
- "end,",nl}),
- gen_fixoptionals(R);
-gen_fixoptionals([Pos|R]) ->
- gen_fixoptionals([{Pos,asn1_NOVALUE}|R]);
-gen_fixoptionals([]) ->
- ok.
-
-
-param_map(Fun, [H]) ->
- [Fun(H)];
-param_map(Fun, [H|T]) ->
- [Fun(H),","|param_map(Fun,T)].
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Produce a list with positions (in the Value record) where
%% there are optional components, start with 2 because first element
@@ -788,15 +772,15 @@ optionals({L1,Ext,L2}) ->
optionals({L,_Ext}) -> optionals(L,[],2);
optionals(L) -> optionals(L,[],2).
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[Pos|Acc],Pos+1);
-optionals([#'ComponentType'{prop={'DEFAULT',Val}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Pos,Val}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
+optionals([#'ComponentType'{prop='OPTIONAL'}|Rest], Acc, Pos) ->
+ optionals(Rest, [Pos|Acc], Pos+1);
+optionals([#'ComponentType'{typespec=T,prop={'DEFAULT',Val}}|Rest],
+ Acc, Pos) ->
+ Vals = def_values(T, Val),
+ optionals(Rest, [{Pos,Vals}|Acc], Pos+1);
+optionals([#'ComponentType'{}|Rest], Acc, Pos) ->
+ optionals(Rest, Acc, Pos+1);
+optionals([], Acc, _) ->
lists:reverse(Acc).
%%%%%%%%%%%%%%%%%%%%%%
@@ -858,33 +842,32 @@ add_textual_order1(Cs,NumIn) ->
end,
NumIn,Cs).
-gen_enc_components_call(Erule,TopType,{Root,ExtList},MaybeComma,DynamicEnc,Ext) ->
- gen_enc_components_call(Erule,TopType,{Root,ExtList,[]},MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2},MaybeComma,DynamicEnc,Ext) ->
+gen_enc_components_call(Erule,TopType,{Root,ExtList}, DynamicEnc,Ext) ->
+ gen_enc_components_call(Erule,TopType,{Root,ExtList,[]}, DynamicEnc,Ext);
+gen_enc_components_call(Erule,TopType,CL={Root,ExtList,Root2}, DynamicEnc,Ext) ->
%% The type has extensionmarker
- Rpos = gen_enc_components_call1(Erule,TopType,Root++Root2,1,MaybeComma,DynamicEnc,noext),
- case Ext of
- {ext,_,ExtNum} when ExtNum > 0 ->
- emit([nl,
- ",Extensions",nl]);
-
- _ -> true
- end,
+ {Imm0,Rpos} = gen_enc_components_call1(Erule,TopType,Root++Root2,1, DynamicEnc,noext,[]),
+ ExtImm = case Ext of
+ {ext,_,ExtNum} when ExtNum > 0 ->
+ [{var,"Extensions"}];
+ _ ->
+ []
+ end,
%handle extensions
{extgrouppos,ExtGroupPosLen} = extgroup_pos_and_length(CL),
NewExtList = wrap_extensionAdditionGroups(ExtList,ExtGroupPosLen),
- gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(Erule,TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
+ {Imm1,_} = gen_enc_components_call1(Erule,TopType,NewExtList,Rpos,DynamicEnc,Ext,[]),
+ Imm0 ++ [ExtImm|Imm1];
+gen_enc_components_call(Erule,TopType, CompList, DynamicEnc, Ext) ->
%% The type has no extensionmarker
- gen_enc_components_call1(Erule,TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
+ {Imm,_} = gen_enc_components_call1(Erule,TopType,CompList,1,DynamicEnc,Ext,[]),
+ Imm.
gen_enc_components_call1(Erule,TopType,
[C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
Tpos,
- MaybeComma, DynamicEnc, Ext) ->
+ DynamicEnc, Ext, Acc) ->
- put(component_type,{true,C}),
- %% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
TermNo =
case C#'ComponentType'.textual_order of
undefined ->
@@ -892,90 +875,91 @@ gen_enc_components_call1(Erule,TopType,
CanonicalNum ->
CanonicalNum
end,
- emit(MaybeComma),
- case Prop of
- 'OPTIONAL' ->
- gen_enc_component_optional(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext);
- {'DEFAULT',DefVal} ->
- gen_enc_component_default(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext,DefVal);
+ Val = make_var(val),
+ {Imm0,Element} = asn1ct_imm:enc_element(TermNo+1, Val),
+ Imm1 = gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext),
+ Category = case {Prop,Ext} of
+ {'OPTIONAL',_} ->
+ optional;
+ {{'DEFAULT',DefVal},_} ->
+ {default,DefVal};
+ {_,{ext,ExtPos,_}} when Tpos >= ExtPos ->
+ optional;
+ {_,_} ->
+ mandatory
+ end,
+ Imm2 = case Category of
+ mandatory ->
+ Imm1;
+ optional ->
+ asn1ct_imm:enc_absent(Element, [asn1_NOVALUE], Imm1);
+ {default,Def} ->
+ DefValues = def_values(Type, Def),
+ asn1ct_imm:enc_absent(Element, DefValues, Imm1)
+ end,
+ Imm = case Imm2 of
+ [] -> [];
+ _ -> Imm0 ++ Imm2
+ end,
+ gen_enc_components_call1(Erule, TopType, Rest, Tpos+1, DynamicEnc, Ext, [Imm|Acc]);
+gen_enc_components_call1(_Erule,_TopType,[],Pos,_,_, Acc) ->
+ ImmList = lists:reverse(Acc),
+ {ImmList,Pos}.
+
+def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) ->
+ #typedef{typespec=T} = asn1_db:dbget(Mod, Type),
+ def_values(T, Def);
+def_values(#type{def={'BIT STRING',[]}}, Bs) when is_bitstring(Bs) ->
+ case asn1ct:use_legacy_types() of
+ false ->
+ [asn1_DEFAULT,Bs];
+ true ->
+ ListBs = [B || <<B:1>> <= Bs],
+ IntBs = lists:foldl(fun(B, A) ->
+ (A bsl 1) bor B
+ end, 0, lists:reverse(ListBs)),
+ Sz = bit_size(Bs),
+ Compact = case 8 - Sz rem 8 of
+ 8 ->
+ {0,Bs};
+ Unused ->
+ {Unused,<<Bs:Sz/bits,0:Unused>>}
+ end,
+ [asn1_DEFAULT,Bs,Compact,ListBs,IntBs]
+ end;
+def_values(#type{def={'BIT STRING',[_|_]=Ns}}, List) when is_list(List) ->
+ Bs = asn1ct_gen:named_bitstring_value(List, Ns),
+ As = case asn1ct:use_legacy_types() of
+ false ->
+ [List,Bs];
+ true ->
+ ListBs = [B || <<B:1>> <= Bs],
+ IntBs = lists:foldl(fun(B, A) ->
+ (A bsl 1) bor B
+ end, 0, lists:reverse(ListBs)),
+ [List,Bs,ListBs,IntBs]
+ end,
+ {call,per_common,is_default_bitstring,As};
+def_values(#type{def={'INTEGER',Ns}}, Def) ->
+ [asn1_DEFAULT,Def|case lists:keyfind(Def, 2, Ns) of
+ false -> [];
+ {Val,Def} -> [Val]
+ end];
+def_values(_, Def) ->
+ [asn1_DEFAULT,Def].
+
+gen_enc_line_imm(Erule, TopType, Cname, Type, Element, DynamicEnc, Ext) ->
+ Imm0 = gen_enc_line_imm_1(Erule, TopType, Cname, Type,
+ Element, DynamicEnc),
+ Aligned = is_aligned(Erule),
+ case Ext of
+ {ext,_Ep2,_} ->
+ asn1ct_imm:per_enc_open_type(Imm0, Aligned);
_ ->
- case Ext of
- {ext,ExtPos,_} when Tpos >= ExtPos ->
- gen_enc_component_optional(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext);
- _ ->
- gen_enc_component_mandatory(Erule,TopType,Cname,Type,TermNo,DynamicEnc,Ext)
- end
- end,
-
- erase(component_type),
+ Imm0
+ end.
- case Rest of
- [] ->
- Tpos+1;
- _ ->
- emit({com,nl}),
- gen_enc_components_call1(Erule,TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
- end;
-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))),
- emit({"case ",Element," of",nl}),
-% emit({"asn1_DEFAULT -> [];",nl}),
- emit({"DFLT when DFLT == asn1_DEFAULT; DFLT == ",{asis,DefaultVal}," -> [];",nl}),
-
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_optional(Erule,TopType,Cname,
- Type=#type{def=#'SEQUENCE'{
- extaddgroup=Number,
- components=_ExtGroupCompList}},
- Pos,DynamicEnc,Ext) when is_integer(Number) ->
-
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val))),
- emit({"case ",Element," of",nl}),
-
- emit({"asn1_NOVALUE -> [];",nl}),
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- 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))),
- emit({"case ",Element," of",nl}),
-
- emit({"asn1_NOVALUE -> [];",nl}),
- asn1ct_name:new(tmpval),
- emit({{curr,tmpval}," ->",nl}),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- NextElement = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- gen_enc_line(Erule,TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_mandatory(Erule,TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- 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))),
- gen_enc_line(Erule,TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
-gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
+gen_enc_line_imm_1(Erule, TopType, Cname, Type, Element, DynamicEnc) ->
Atype =
case Type of
#type{def=#'ObjectClassFieldType'{type=InnerType}} ->
@@ -983,81 +967,164 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
_ ->
asn1ct_gen:get_inner(Type#type.def)
end,
-
- case Ext of
- {ext,_Ep1,_} ->
- asn1ct_func:need({Erule,encode_open_type,1}),
- asn1ct_func:need({Erule,complete,1}),
- emit(["encode_open_type(complete("]);
- _ -> true
- end,
-
+ Aligned = is_aligned(Erule),
case Atype of
{typefield,_} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
- case (Type#type.def)#'ObjectClassFieldType'.fieldname of
- {Name,RestFieldNames} when is_atom(Name) ->
- 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 ->
- throw({asn1,{'internal error',Other}})
- end
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
- 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},")))"})
+ {_LeadingAttrName,Fun} = DynamicEnc,
+ case (Type#type.def)#'ObjectClassFieldType'.fieldname of
+ {Name,RestFieldNames} when is_atom(Name) ->
+ Imm = enc_var_type_call(Erule, Name, RestFieldNames,
+ Type, Fun, Element),
+ asn1ct_imm:per_enc_open_type(Imm, Aligned)
end;
_ ->
CurrMod = get(currmod),
case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=Mod,type=EType} when
- (CurrMod==Mod) ->
- emit({"'enc_",EType,"'(",Element,")"});
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ [{apply,{local,enc_func(EType),Atype},[Element]}];
#'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'enc_",
- EType,"'(",Element,")"});
+ [{apply,{Mod,enc_func(EType),Atype},[Element]}];
{primitive,bif} ->
- asn1ct_gen_per:gen_encode_prim(Erule, Type, Element);
+ asn1ct_gen_per:gen_encode_prim_imm(Element, Type, Aligned);
'ASN1_OPEN_TYPE' ->
case Type#type.def of
#'ObjectClassFieldType'{type=OpenType} ->
- asn1ct_gen_per:gen_encode_prim(Erule,
- #type{def=OpenType},
- Element);
+ asn1ct_gen_per:gen_encode_prim_imm(Element,
+ #type{def=OpenType},
+ Aligned);
_ ->
- asn1ct_gen_per:gen_encode_prim(Erule, Type,
- Element)
+ asn1ct_gen_per:gen_encode_prim_imm(Element,
+ Type,
+ Aligned)
end;
{constructed,bif} ->
NewTypename = [Cname|TopType],
+ Enc = enc_func(asn1ct_gen:list2name(NewTypename)),
case {Type#type.tablecinf,DynamicEnc} of
{[{objfun,_}|_R],{_,EncFun}} ->
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,", ",EncFun,")"});
+ [{apply,{local,Enc,Type},[Element,EncFun]}];
_ ->
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,")"})
+ [{apply,{local,Enc,Type},[Element]}]
end
end
- end,
- case Ext of
- {ext,_Ep2,_} ->
- emit("))");
- _ -> true
end.
+enc_func(Type) ->
+ enc_func("enc_", Type).
+
+enc_func(Prefix, Name) ->
+ list_to_atom(lists:concat([Prefix,Name])).
+
+enc_var_type_call(Erule, Name, RestFieldNames,
+ #type{tablecinf=TCI}, Fun, Val) ->
+ [{objfun,#'Externaltypereference'{module=Xmod,type=Xtype}}] = TCI,
+ #typedef{typespec=ObjSet0} = asn1_db:dbget(Xmod, Xtype),
+ #'ObjectSet'{class=Class,set=ObjSet1} = ObjSet0,
+ #'Externaltypereference'{module=ClMod,type=ClType} = Class,
+ #classdef{typespec=ClassDef} = asn1_db:dbget(ClMod, ClType),
+ #objectclass{fields=ClassFields} = ClassDef,
+ Extensible = lists:member('EXTENSIONMARK', ObjSet1),
+ ObjSet2 = [{Key,fix_object_code(Name, Code, ClassFields)} ||
+ {_,Key,Code} <- ObjSet1],
+ ObjSet = lists:sort([P || {_,B}=P <- ObjSet2, B =/= none]),
+ Key = erlang:md5(term_to_binary({encode,ObjSet,RestFieldNames,Extensible})),
+ Imm = enc_objset_imm(Erule, Name, ObjSet, RestFieldNames, Extensible),
+ Lambda = {lambda,[{var,"Val"},{var,"Id"}],Imm},
+ Gen = fun(_Fd, N) ->
+ Aligned = is_aligned(Erule),
+ emit([{asis,N},"(Val, Id) ->",nl]),
+ asn1ct_imm:enc_cg(Imm, Aligned),
+ emit([".",nl])
+ end,
+ Prefix = lists:concat(["enc_os_",Name]),
+ [{call_gen,Prefix,Key,Gen,Lambda,[Val,Fun]}].
+
+fix_object_code(Name, [{Name,B}|_], _ClassFields) ->
+ B;
+fix_object_code(Name, [_|T], ClassFields) ->
+ fix_object_code(Name, T, ClassFields);
+fix_object_code(Name, [], ClassFields) ->
+ case lists:keyfind(Name, 2, ClassFields) of
+ {typefield,Name,'OPTIONAL'} ->
+ none;
+ {objectfield,Name,_,_,'OPTIONAL'} ->
+ none;
+ {typefield,Name,{'DEFAULT',#type{}=Type}} ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ #typedef{name={primitive,bif},typespec=Type};
+ {constructed,bif} ->
+ #typedef{name={constructed,bif},typespec=Type}
+ end
+ end.
+
+enc_objset_imm(Erule, Component, ObjSet, RestFieldNames, Extensible) ->
+ Aligned = is_aligned(Erule),
+ E = {error,
+ fun() ->
+ emit(["exit({'Type not compatible with table constraint',"
+ "{component,",{asis,Component},"},"
+ "{value,Val},"
+ "{unique_name_and_value,'_'}})",nl])
+ end},
+ [{'cond',
+ [[{eq,{var,"Id"},Key}|
+ enc_obj(Erule, Obj, RestFieldNames, Aligned)] ||
+ {Key,Obj} <- ObjSet] ++
+ [['_',case Extensible of
+ false ->
+ E;
+ true ->
+ case asn1ct:use_legacy_types() of
+ false ->
+ {call,per_common,open_type_to_binary,
+ [{var,"Val"}]};
+ true ->
+ {call,per_common,legacy_open_type_to_binary,
+ [{var,"Val"}]}
+ end
+ end]]}].
+
+enc_obj(Erule, Obj, RestFieldNames0, Aligned) ->
+ case Obj of
+ #typedef{name={primitive,bif},typespec=Def} ->
+ asn1ct_gen_per:gen_encode_prim_imm({var,"Val"}, Def, Aligned);
+ #typedef{name={constructed,bif},typespec=Def} ->
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'CHOICE' ->
+ gen_encode_choice_imm(Erule, name, Def);
+ 'SET' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SET OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def);
+ 'SEQUENCE' ->
+ gen_encode_constructed_imm(Erule, name, Def);
+ 'SEQUENCE OF' ->
+ gen_encode_sof_imm(Erule, name, InnerType, Def)
+ end;
+ #typedef{name=Type} ->
+ [{apply,{local,enc_func(Type),Type},[{var,"Val"}]}];
+ #'Externalvaluereference'{module=Mod,value=Value} ->
+ case asn1_db:dbget(Mod, Value) of
+ #typedef{typespec=#'Object'{def=Def}} ->
+ {object,_,Fields} = Def,
+ [NextField|RestFieldNames] = RestFieldNames0,
+ {NextField,Typedef} = lists:keyfind(NextField, 1, Fields),
+ enc_obj(Erule, Typedef, RestFieldNames, Aligned)
+ end;
+ #'Externaltypereference'{module=Mod,type=Type} ->
+ Func = enc_func(Type),
+ case get(currmod) of
+ Mod ->
+ [{apply,{local,Func,Obj},[{var,"Val"}]}];
+ _ ->
+ [{apply,{Mod,Func,Obj},[{var,"Val"}]}]
+ end
+ end.
+
+
gen_dec_components_call(Erule, TopType, {Root,ExtList},
DecInfObj, Ext, NumberOfOptionals) ->
gen_dec_components_call(Erule,TopType,{Root,ExtList,[]},
@@ -1163,14 +1230,6 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj,
emit(["{",{curr,tmpterm},", ",{next,bytes},"} = "]),
St
end;
- %%{objectfield,_,_} when Ext == noext, Prop == mandatory ->
- {{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'{
@@ -1204,7 +1263,8 @@ gen_dec_comp_call(Comp, Erule, TopType, Tpos, OptTable, DecInfObj,
comp_call_pre_post(noext, mandatory, _, _, _, _, _, _) ->
{[],[]};
-comp_call_pre_post(noext, Prop, _, _, TextPos, OptTable, NumOptionals, Ext) ->
+comp_call_pre_post(noext, Prop, _, Type, TextPos,
+ OptTable, NumOptionals, Ext) ->
%% OPTIONAL or DEFAULT
OptPos = get_optionality_pos(TextPos, OptTable),
Element = case NumOptionals - OptPos of
@@ -1222,7 +1282,7 @@ comp_call_pre_post(noext, Prop, _, _, TextPos, OptTable, NumOptionals, Ext) ->
emit([";",nl,
"0 ->",nl,
"{"]),
- gen_dec_component_no_val(Ext, Prop),
+ gen_dec_component_no_val(Ext, Type, Prop),
emit([",",{curr,bytes},"}",nl,
"end"]),
St
@@ -1244,10 +1304,10 @@ comp_call_pre_post({ext,_,_}, Prop, Pos, Type, _, _, _, Ext) ->
components=ExtGroupCompList2}}
when is_integer(Number2)->
emit("{extAddGroup,"),
- gen_dec_extaddGroup_no_val(Ext, ExtGroupCompList2),
+ gen_dec_extaddGroup_no_val(Ext, Type, ExtGroupCompList2),
emit("}");
_ ->
- gen_dec_component_no_val(Ext, Prop)
+ gen_dec_component_no_val(Ext, Type, Prop)
end,
emit([",",{curr,bytes},"}",nl,
"end"]),
@@ -1262,21 +1322,22 @@ is_mandatory_predef_tab_c(_, _, {"got objfun through args","ObjFun"}) ->
is_mandatory_predef_tab_c(_,_,_) ->
true.
-gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}])->
- gen_dec_component_no_val(Ext,Prop),
+gen_dec_extaddGroup_no_val(Ext, Type, [#'ComponentType'{prop=Prop}])->
+ gen_dec_component_no_val(Ext, Type, Prop),
ok;
-gen_dec_extaddGroup_no_val(Ext,[#'ComponentType'{prop=Prop}|Rest])->
- gen_dec_component_no_val(Ext,Prop),
- emit({","}),
- gen_dec_extaddGroup_no_val(Ext,Rest);
-gen_dec_extaddGroup_no_val(_, []) ->
+gen_dec_extaddGroup_no_val(Ext, Type, [#'ComponentType'{prop=Prop}|Rest])->
+ gen_dec_component_no_val(Ext, Type, Prop),
+ emit(","),
+ gen_dec_extaddGroup_no_val(Ext, Type, Rest);
+gen_dec_extaddGroup_no_val(_, _, []) ->
ok.
-gen_dec_component_no_val(_,{'DEFAULT',DefVal}) ->
+gen_dec_component_no_val(_, Type, {'DEFAULT',DefVal0}) ->
+ DefVal = asn1ct_gen:conform_value(Type, DefVal0),
emit([{asis,DefVal}]);
-gen_dec_component_no_val(_,'OPTIONAL') ->
+gen_dec_component_no_val(_, _, 'OPTIONAL') ->
emit({"asn1_NOVALUE"});
-gen_dec_component_no_val({ext,_,_},mandatory) ->
+gen_dec_component_no_val({ext,_,_}, _, mandatory) ->
emit({"asn1_NOVALUE"}).
@@ -1350,25 +1411,19 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
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]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ 'Result',TmpTerm,mandatory}),
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"]),
+ "{",{asis,Cname},",{Result,",TempBuf,"}}"]),
{[],PrevSt};
{"got objfun through args","ObjFun"} ->
%% this is when the generated code gots the
@@ -1388,27 +1443,22 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
asn1ct_imm:dec_code_gen(Imm, BytesVar),
emit([com,nl]),
+ #type{tablecinf=[{objfun,
+ #'Externaltypereference'{module=Xmod,
+ type=Xtype}}]} =
+ Type,
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ TmpTerm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
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;
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ Term,TmpTerm,Prop});
true ->
+ emit([" {"]),
+ gen_dec_open_type(Erule, "ObjFun", {Xmod,Xtype},
+ '_', {'_',{Name,RestFieldNames},
+ '_',TmpTerm,Prop}),
emit([",",nl,{curr,tmpbytes},"}"])
end,
{[],PrevSt};
@@ -1425,19 +1475,6 @@ gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp,
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) ->
@@ -1458,14 +1495,11 @@ gen_dec_line_special(Erule, Atype, TopType, Comp, DecInfObj) ->
gen_dec_line_dec_inf(Comp, DecInfObj) ->
#'ComponentType'{name=Cname} = Comp,
case DecInfObj of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ {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,")"]);
+ "ObjFun = ",ValueMatch]);
_ ->
ok
end.
@@ -1492,86 +1526,67 @@ gen_dec_line_other(Erule, Atype, TopType, Comp) ->
[{objfun,_}|_R] ->
fun(BytesVar) ->
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype, ObjFun)"})
+ "'(",BytesVar,", ObjFun)"})
end;
_ ->
fun(BytesVar) ->
emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype)"})
+ "'(",BytesVar,")"})
end
end
end.
-gen_enc_choice(Erule,TopType,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(Erule, {C1,C2}, _, _) ->
- N1 = get_name_list(C1),
- N2 = get_name_list(C2),
- 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,
- 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),
- call(Erule,set_choice,
- ["element(1, Val)",
- {asis,N},{asis,length(N)}]).
-
-get_name_list(L) ->
- get_name_list(L,[]).
-
-get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
- get_name_list(T,[Name|Acc]);
-get_name_list([], Acc) ->
- lists:reverse(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, L, Ext) ->
- gen_enc_choice2(Erule,TopType, L, 0, [], Ext).
+gen_enc_choice(Erule, TopType, {Root,Exts}, Ext) ->
+ Constr = choice_constraint(Root),
+ gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext) ++
+ gen_enc_choices(Exts, Erule, TopType, 0, ext, Ext);
+gen_enc_choice(Erule, TopType, {Root,Exts,[]}, Ext) ->
+ gen_enc_choice(Erule, TopType, {Root,Exts}, Ext);
+gen_enc_choice(Erule, TopType, Root, Ext) when is_list(Root) ->
+ Constr = choice_constraint(Root),
+ gen_enc_choices(Root, Erule, TopType, 0, Constr, Ext).
+
+choice_constraint(L) ->
+ case length(L) of
+ 0 -> [{'SingleValue',0}];
+ Len -> [{'ValueRange',{0,Len-1}}]
+ end.
-gen_enc_choice2(Erule, TopType, [H|T], Pos, Sep0, Ext) ->
+gen_enc_choices([H|T], Erule, TopType, Pos, Constr, Ext) ->
#'ComponentType'{name=Cname,typespec=Type} = H,
+ Aligned = is_aligned(Erule),
EncObj =
case asn1ct_gen:get_constraint(Type#type.constraint,
componentrelation) of
no ->
case Type#type.tablecinf of
[{objfun,_}|_] ->
- {"got objfun through args","ObjFun"};
+ {"got objfun through args",{var,"ObjFun"}};
_ ->
false
end;
_ ->
- {no_attr,"ObjFun"}
+ {no_attr,{var,"ObjFun"}}
end,
- emit([Sep0,{asis,Cname}," ->",nl]),
- DoExt = case Ext of
- {ext,ExtPos,_} when Pos + 1 < ExtPos -> noext;
- _ -> Ext
+ DoExt = case Constr of
+ ext -> Ext;
+ _ -> noext
end,
- 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.
+ Tag = case {Ext,Constr} of
+ {noext,_} ->
+ asn1ct_imm:per_enc_integer(Pos, Constr, Aligned);
+ {{ext,_,_},ext} ->
+ [{put_bits,1,1,[1]}|
+ asn1ct_imm:per_enc_small_number(Pos, Aligned)];
+ {{ext,_,_},_} ->
+ [{put_bits,0,1,[1]}|
+ asn1ct_imm:per_enc_integer(Pos, Constr, Aligned)]
+ end,
+ Body = gen_enc_line_imm(Erule, TopType, Cname, Type, {var,"ChoiceVal"},
+ EncObj, DoExt),
+ Imm = Tag ++ Body,
+ [{Cname,Imm}|gen_enc_choices(T, Erule, TopType, Pos+1, Constr, Ext)];
+gen_enc_choices([], _, _, _, _, _) -> [].
%% Generate the code for CHOICE. If the CHOICE is extensible,
%% the structure of the generated code is as follows:
@@ -1704,9 +1719,6 @@ gen_dec_choice2(Erule, TopType, [H0|T], Pos, Sep0, Pre) ->
gen_dec_choice2(Erule, TopType, T, Pos+1, Sep, Pre);
gen_dec_choice2(_, _, [], _, _, _) -> ok.
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
make_elements(I,Val,ExtCnames) ->
make_elements(I,Val,ExtCnames,[]).
@@ -1720,7 +1732,7 @@ make_elements(_I,_,[],Acc) ->
lists:reverse(Acc).
make_element(I, Val) ->
- io_lib:format("element(~w,~s)", [I,Val]).
+ lists:flatten(io_lib:format("element(~w, ~s)", [I,Val])).
emit_extaddgroupTerms(VarSeries,[_]) ->
asn1ct_name:new(VarSeries),
@@ -1788,5 +1800,12 @@ value_match1(Value,[],Acc,Depth) ->
value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
-is_optimized(per) -> true;
-is_optimized(uper) -> false.
+enc_dig_out_value([], Value) ->
+ {[],Value};
+enc_dig_out_value([{N,_}|T], Value) ->
+ {Imm0,Dst0} = enc_dig_out_value(T, Value),
+ {Imm,Dst} = asn1ct_imm:enc_element(N, Dst0),
+ {Imm0++Imm,Dst}.
+
+make_var(Base) ->
+ {var,atom_to_list(asn1ct_gen:mk_var(asn1ct_name:curr(Base)))}.
diff --git a/lib/asn1/src/asn1ct_eval_per.funcs b/lib/asn1/src/asn1ct_eval_per.funcs
deleted file mode 100644
index a1ea5cd043..0000000000
--- a/lib/asn1/src/asn1ct_eval_per.funcs
+++ /dev/null
@@ -1,2 +0,0 @@
-{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
deleted file mode 100644
index 884a486f40..0000000000
--- a/lib/asn1/src/asn1ct_eval_uper.funcs
+++ /dev/null
@@ -1,2 +0,0 @@
-{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
index ab0dbcce8f..fb94f65b32 100644
--- a/lib/asn1/src/asn1ct_func.erl
+++ b/lib/asn1/src/asn1ct_func.erl
@@ -19,7 +19,8 @@
%%
-module(asn1ct_func).
--export([start_link/0,need/1,call/3,generate/1]).
+-export([start_link/0,need/1,call/3,call_gen/3,call_gen/4,
+ generate/1,is_used/1]).
-export([init/1,handle_call/3,handle_cast/2,terminate/2]).
start_link() ->
@@ -28,15 +29,33 @@ start_link() ->
ok.
call(M, F, Args) ->
- MFA = {M,F,length(Args)},
+ A = length(Args),
+ MFA = {M,F,A},
need(MFA),
- asn1ct_gen:emit([F,"(",call_args(Args, ""),")"]).
+ case M of
+ binary ->
+ asn1ct_gen:emit(["binary:",F,"(",call_args(Args, ""),")"]);
+ _ ->
+ asn1ct_gen:emit([F,"(",call_args(Args, ""),")"])
+ end.
+need({binary,_,_}) ->
+ ok;
+need({erlang,_,_}) ->
+ ok;
need(MFA) ->
asn1ct_rtt:assert_defined(MFA),
cast({need,MFA}).
+call_gen(Prefix, Key, Gen, Args) when is_function(Gen, 2) ->
+ F = req({gen_func,Prefix,Key,Gen}),
+ asn1ct_gen:emit([{asis,F},"(",call_args(Args, ""),")"]).
+
+call_gen(Prefix, Key, Gen) when is_function(Gen, 2) ->
+ req({gen_func,Prefix,Key,Gen}).
+
generate(Fd) ->
+ do_generate(Fd),
Used0 = req(get_used),
erase(?MODULE),
Used = sofs:set(Used0, [mfa]),
@@ -45,6 +64,10 @@ generate(Fd) ->
Funcs = sofs:to_external(Funcs0),
ok = file:write(Fd, Funcs).
+is_used({_,_,_}=MFA) ->
+ req({is_used,MFA}).
+
+
req(Req) ->
gen_server:call(get(?MODULE), Req, infinity).
@@ -53,10 +76,13 @@ cast(Req) ->
%%% Internal functions.
--record(st, {used}).
+-record(st, {used, %Used functions
+ gen, %Dynamically generated functions
+ gc=1 %Counter for generated functions
+ }).
init([]) ->
- St = #st{used=gb_sets:empty()},
+ St = #st{used=gb_sets:empty(),gen=gb_trees:empty()},
{ok,St}.
handle_cast({need,MFA}, #st{used=Used0}=St) ->
@@ -69,7 +95,23 @@ handle_cast({need,MFA}, #st{used=Used0}=St) ->
end.
handle_call(get_used, _From, #st{used=Used}=St) ->
- {stop,normal,gb_sets:to_list(Used),St}.
+ {stop,normal,gb_sets:to_list(Used),St};
+handle_call(get_gen, _From, #st{gen=G0}=St) ->
+ {L,G} = do_get_gen(gb_trees:to_list(G0), [], []),
+ {reply,L,St#st{gen=gb_trees:from_orddict(G)}};
+handle_call({gen_func,Prefix,Key,GenFun}, _From, #st{gen=G0,gc=Gc0}=St) ->
+ case gb_trees:lookup(Key, G0) of
+ none ->
+ Name = list_to_atom(Prefix ++ integer_to_list(Gc0)),
+ Gc = Gc0 + 1,
+ G = gb_trees:insert(Key, {Name,GenFun}, G0),
+ {reply,Name,St#st{gen=G,gc=Gc}};
+ {value,{Name,_}} ->
+ {reply,Name,St}
+ end;
+handle_call({is_used,MFA}, _From, #st{used=Used}=St) ->
+ {reply,gb_sets:is_member(MFA, Used),St}.
+
terminate(_, _) ->
ok.
@@ -98,3 +140,22 @@ update_worklist([H|T], Used, Ws) ->
update_worklist(T, Used, Ws)
end;
update_worklist([], _, Ws) -> Ws.
+
+do_get_gen([{_,{_,done}}=Keep|T], Gacc, Kacc) ->
+ do_get_gen(T, Gacc, [Keep|Kacc]);
+do_get_gen([{K,{Name,_}=V}|T], Gacc, Kacc) ->
+ do_get_gen(T, [V|Gacc], [{K,{Name,done}}|Kacc]);
+do_get_gen([], Gacc, Kacc) ->
+ {lists:sort(Gacc),lists:reverse(Kacc)}.
+
+do_generate(Fd) ->
+ case req(get_gen) of
+ [] ->
+ ok;
+ [_|_]=Gen ->
+ _ = [begin
+ ok = file:write(Fd, "\n"),
+ GenFun(Fd, Name)
+ end || {Name,GenFun} <- Gen],
+ do_generate(Fd)
+ end.
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 9095e145a3..2ef8466309 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -23,23 +23,27 @@
-export([demit/1,
emit/1,
+ open_output_file/1,close_output_file/0,
get_inner/1,type/1,def_to_tag/1,prim_bif/1,
list2name/1,
list2rname/1,
constructed_suffix/2,
unify_if_string/1,
- gen_check_call/7,
get_constraint/2,
insert_once/2,
ct_gen_module/1,
index2suffix/1,
- get_record_name_prefix/0]).
+ get_record_name_prefix/0,
+ conform_value/2,
+ named_bitstring_value/2]).
-export([pgen/5,
mk_var/1,
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
gen_decode_constructed/4]).
+-define(SUPPRESSION_FUNC, 'dialyzer-suppressions').
+
%% 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
@@ -68,8 +72,7 @@ pgen_module(OutFile,Erules,Module,
HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent),
asn1ct_name:start(),
ErlFile = lists:concat([OutFile,".erl"]),
- Fid = fopen(ErlFile),
- put(gen_file_out,Fid),
+ _ = open_output_file(ErlFile),
asn1ct_func:start_link(),
gen_head(Erules,Module,HrlGenerated),
pgen_exports(Erules,Module,TypeOrVal),
@@ -83,10 +86,18 @@ pgen_module(OutFile,Erules,Module,
"%%%",nl,
"%%% Run-time functions.",nl,
"%%%",nl]),
- asn1ct_func:generate(Fid),
- file:close(Fid),
+ dialyzer_suppressions(Erules),
+ Fd = get(gen_file_out),
+ asn1ct_func:generate(Fd),
+ close_output_file(),
+ _ = erase(outfile),
asn1ct:verbose("--~p--~n",[{generated,ErlFile}],Options).
+dialyzer_suppressions(Erules) ->
+ emit([nl,
+ {asis,?SUPPRESSION_FUNC},"(Arg) ->",nl]),
+ Rtmod = ct_gen_module(Erules),
+ Rtmod:dialyzer_suppressions(Erules).
pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
Rtmod = ct_gen_module(Erules),
@@ -94,11 +105,6 @@ pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects
pgen_values(Erules,Module,Values),
pgen_objects(Rtmod,Erules,Module,Objects),
pgen_objectsets(Rtmod,Erules,Module,ObjectSets),
- case catch lists:member(der,get(encoding_options)) of
- true ->
- pgen_check_defaultval(Erules,Module);
- _ -> ok
- end,
pgen_partial_decode(Rtmod,Erules,Module).
pgen_values(_,_,[]) ->
@@ -174,23 +180,6 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) ->
Rtmod:gen_objectset_code(Erules,TypeDef),
pgen_objectsets(Rtmod,Erules,Module,T).
-pgen_check_defaultval(Erules,Module) ->
- CheckObjects = asn1ct_table:to_list(check_functions),
- case get(asndebug) of
- true ->
- FileName = lists:concat([Module,".table"]),
- {ok,IoDevice} = file:open(FileName,[write]),
- Fun =
- fun(X)->
- io:format(IoDevice,"~n~n************~n~n~p~n~n*****"
- "********~n~n",[X])
- end,
- lists:foreach(Fun,CheckObjects),
- file:close(IoDevice);
- _ -> ok
- end,
- gen_check_defaultval(Erules,Module,CheckObjects).
-
pgen_partial_decode(Rtmod,Erule,Module) when Erule == ber ->
pgen_partial_inc_dec(Rtmod,Erule,Module),
pgen_partial_dec(Rtmod,Erule,Module);
@@ -538,8 +527,7 @@ gen_part_decode_funcs({constructed,bif},TypeName,
emit([" 'dec_",TypeName,"'(Data,",{asis,Tag},")"]);
gen_part_decode_funcs({primitive,bif},_TypeName,
{_Name,undecoded,Tag,Type}) ->
- % Argument no 6 is 0, i.e. bit 6 for primitive encoding.
- asn1ct_gen_ber_bin_v2:gen_dec_prim(ber_bin_v2,Type,"Data",Tag,[],0,", mandatory, ");
+ asn1ct_gen_ber_bin_v2:gen_dec_prim(Type, "Data", Tag);
gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) ->
throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}).
@@ -572,131 +560,6 @@ gen_types(Erules,Tname,Type) when is_record(Type,type) ->
asn1ct_name:clear(),
Rtmod:gen_decode(Erules,Tname,Type).
-gen_check_defaultval(Erules,Module,[{Name,Type}|Rest]) ->
- gen_check_func(Name,Type),
- gen_check_defaultval(Erules,Module,Rest);
-gen_check_defaultval(_,_,[]) ->
- ok.
-
-gen_check_func(Name,FType = #type{def=Def}) ->
- EncName = ensure_atom(Name),
- emit({{asis,EncName},"(_V,asn1_DEFAULT) ->",nl," true;",nl}),
- emit({{asis,EncName},"(V,V) ->",nl," true;",nl}),
- emit({{asis,EncName},"(V,{_,V}) ->",nl," true;",nl}),
- case Def of
- {'SEQUENCE OF',Type} ->
- gen_check_sof(Name,'SEQOF',Type);
- {'SET OF',Type} ->
- gen_check_sof(Name,'SETOF',Type);
- #'SEQUENCE'{components=Components} ->
- gen_check_sequence(Name,Components);
- #'SET'{components=Components} ->
- gen_check_sequence(Name,Components);
- {'CHOICE',Components} ->
- gen_check_choice(Name,Components);
- #'Externaltypereference'{type=T} ->
- emit({{asis,EncName},"(DefaultValue,Value) ->",nl}),
- emit({" '",list2name([T,check]),"'(DefaultValue,Value).",nl});
- MaybePrim ->
- InnerType = get_inner(MaybePrim),
- case type(InnerType) of
- {primitive,bif} ->
- emit({{asis,EncName},"(DefaultValue,Value) ->",nl," "}),
- gen_prim_check_call(get_inner(InnerType),"DefaultValue","Value",
- FType),
- emit({".",nl,nl});
- _ ->
- throw({asn1_error,{unknown,type,MaybePrim}})
- end
- end.
-
-gen_check_sof(Name,SOF,Type) ->
- EncName = ensure_atom(Name),
- NewName = ensure_atom(list2name([sorted,Name])),
- emit({{asis,EncName},"(V1,V2) ->",nl}),
- emit({" ",{asis,NewName},"(lists:sort(V1),lists:sort(V2)).",nl,nl}),
- emit({{asis,NewName},"([],[]) ->",nl," true;",nl}),
- emit({{asis,NewName},"([DV|DVs],[V|Vs]) ->",nl," "}),
- InnerType = get_inner(Type#type.def),
- case type(InnerType) of
- {primitive,bif} ->
- gen_prim_check_call(get_inner(InnerType),"DV","V",Type),
- emit({",",nl});
- {constructed,bif} ->
- emit([{asis,ensure_atom(list2name([SOF,Name]))},"(DV, V),",nl]);
- #'Externaltypereference'{type=T} ->
- emit([{asis,ensure_atom(list2name([T,check]))},"(DV,V),",nl]);
- 'ASN1_OPEN_TYPE' ->
- emit(["DV = V,",nl]);
- _ ->
- emit(["DV = V,",nl])
- 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)"],
- NthV = ["element(",Num+1,",Value)"],
- gen_check_func_call(Name,Type,InnerType,NthDefV,NthV,N),
- case Cs of
- [] ->
- emit({".",nl,nl});
- _ ->
- emit({",",nl}),
- gen_check_sequence(Name,Cs,Num+1)
- end.
-
-gen_check_choice(Name,CList=[#'ComponentType'{}|_Cs]) ->
- emit([{asis,ensure_atom(Name)},"({Id,DefaultValue},{Id,Value}) ->",nl]),
- emit([" case Id of",nl]),
- gen_check_choice_components(Name,CList,1).
-
-gen_check_choice_components(_,[],_)->
- ok;
-gen_check_choice_components(Name,[#'ComponentType'{name=N,typespec=Type}|
- Cs],Num) ->
- Ind6 = " ",
- InnerType = get_inner(Type#type.def),
- emit({Ind6,"'",N,"' ->",nl,Ind6}),
- gen_check_func_call(Name,Type,InnerType,{var,"defaultValue"},
- {var,"value"},N),
- case Cs of
- [] ->
- emit({nl," end.",nl,nl});
- _ ->
- emit({";",nl}),
- gen_check_choice_components(Name,Cs,Num+1)
- end.
-
-gen_check_func_call(Name,Type,InnerType,DefVal,Val,N) ->
- case type(InnerType) of
- {primitive,bif} ->
- emit(" "),
- gen_prim_check_call(get_inner(InnerType),DefVal,Val,Type);
- #'Externaltypereference'{type=T} ->
- emit({" ",{asis,ensure_atom(list2name([T,check]))},"(",DefVal,",",Val,")"});
- 'ASN1_OPEN_TYPE' ->
- emit([" if",nl,
- " ",DefVal," == ",Val," -> true;",nl,
- " true -> throw({error,{asn1_open_type}})",nl,
- " end",nl]);
- {constructed,bif} ->
- emit([" ",{asis,ensure_atom(list2name([N,Name]))},"(",DefVal,",",Val,")"]);
- _ ->
- emit([" if",nl,
- " ",DefVal," == ",Val," -> true;",nl,
- " true -> throw({error,{asn1_open_type}})",nl,
- " end",nl])
- end.
-
-
%% VARIOUS GENERATOR STUFF
%% *************************************************
%%**************************************************
@@ -786,7 +649,9 @@ 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,bit_string_format/0]).",nl]),
+ emit(["-export([encoding_rule/0,bit_string_format/0,",nl,
+ " legacy_erlang_types/0]).",nl]),
+ emit(["-export([",{asis,?SUPPRESSION_FUNC},"/1]).",nl]),
case Types of
[] -> ok;
_ ->
@@ -798,7 +663,12 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
gen_exports1(Types,"enc_",1)
end,
emit({"-export([",nl}),
- gen_exports1(Types,"dec_",2)
+ case Erules of
+ ber ->
+ gen_exports1(Types, "dec_", 2);
+ _ ->
+ gen_exports1(Types, "dec_", 1)
+ end
end,
case [X || {n2n,X} <- get(encoding_options)] of
[] -> ok;
@@ -819,10 +689,7 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
_ ->
case erule(Erules) of
per ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",3),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",4);
+ ok;
ber ->
emit({"-export([",nl}),
gen_exports1(Objects,"enc_",3),
@@ -833,10 +700,15 @@ pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
case ObjectSets of
[] -> ok;
_ ->
- emit({"-export([",nl}),
- gen_exports1(ObjectSets,"getenc_",2),
- emit({"-export([",nl}),
- gen_exports1(ObjectSets,"getdec_",2)
+ case erule(Erules) of
+ per ->
+ ok;
+ ber ->
+ emit({"-export([",nl}),
+ gen_exports1(ObjectSets, "getenc_",1),
+ emit({"-export([",nl}),
+ gen_exports1(ObjectSets, "getdec_",1)
+ end
end,
emit({"-export([info/0]).",nl}),
gen_partial_inc_decode_exports(),
@@ -900,41 +772,45 @@ pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
emit(["-export([encode/2,decode/2]).",nl,nl]),
gen_info_functions(Erules),
- NoFinalPadding = lists:member(no_final_padding,get(encoding_options)),
- {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,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl,
- " {Bytes,_Len} ->",nl,
- " {ok,",BytesAsBinary,"};",nl,
- " Bytes ->",nl,
- " {ok,",BytesAsBinary,"}",nl,
- "end.",nl,nl]),
-
- Return_rest = lists:member(undec_rest,get(encoding_options)),
+
+ Options = get(encoding_options),
+ NoFinalPadding = lists:member(no_final_padding, Options),
+ NoOkWrapper = proplists:get_bool(no_ok_wrapper, Options),
+
+ Call = case Erules of
+ per ->
+ asn1ct_func:need({Erules,complete,1}),
+ "complete(encode_disp(Type, Data))";
+ ber ->
+ "iolist_to_binary(element(1, encode_disp(Type, Data)))";
+ uper when NoFinalPadding == true ->
+ asn1ct_func:need({Erules,complete_NFP,1}),
+ "complete_NFP(encode_disp(Type, Data))";
+ uper ->
+ asn1ct_func:need({Erules,complete,1}),
+ "complete(encode_disp(Type, Data))"
+ end,
+
+ emit(["encode(Type, Data) ->",nl]),
+ case NoOkWrapper of
+ true ->
+ emit([" ",Call,"."]);
+ false ->
+ emit(["try ",Call," of",nl,
+ " Bytes ->",nl,
+ " {ok,Bytes}",nl,
+ try_catch()])
+ end,
+ emit([nl,nl]),
+
+ Return_rest = proplists:get_bool(undec_rest, Options),
Data = case {Erules,Return_rest} of
{ber,true} -> "Data0";
_ -> "Data"
end,
emit(["decode(Type,",Data,") ->",nl]),
- DecAnonymous =
+ DecWrap =
case {Erules,Return_rest} of
{ber,false} ->
asn1ct_func:need({ber,ber_decode_nif,1}),
@@ -946,49 +822,26 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
_ ->
"Data"
end,
- DecWrap = case Erules of
- ber ->
- DecAnonymous;
- _ -> "Data"
- end,
-
- emit(["case catch decode_disp(Type,",DecWrap,") of",nl,
- " {'EXIT',{error,Reason}} ->",nl,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl]),
- case {Erules,Return_rest} of
- {ber,false} ->
- emit([" Result ->",nl,
- " {ok,Result}",nl]);
- {ber,true} ->
- emit([" Result ->",nl,
- " {ok,Result,Rest}",nl]);
- {_,false} ->
- emit([" {X,_Rest} ->",nl,
- " {ok,X};",nl,
- " {X,_Rest,_Len} ->",nl,
- " {ok,X}",nl]);
- {per,true} ->
- emit([" {X,{_,Rest}} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,{_,Rest},_Len} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,Rest} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,Rest,_Len} ->",nl,
- " {ok,X,Rest}",nl]);
- {uper,true} ->
- emit([" {X,{_,Rest}} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,{_,Rest},_Len} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,Rest} ->",nl,
- " {ok,X,Rest};",nl,
- " {X,Rest,_Len} ->",nl,
- " {ok,X,Rest}",nl])
+ emit([case NoOkWrapper of
+ false -> "try";
+ true -> "case"
+ end, " decode_disp(Type, ",DecWrap,") of",nl]),
+ case erule(Erules) of
+ ber ->
+ emit([" Result ->",nl]);
+ per ->
+ emit([" {Result,Rest} ->",nl])
+ end,
+ case Return_rest of
+ false -> result_line(NoOkWrapper, ["Result"]);
+ true -> result_line(NoOkWrapper, ["Result","Rest"])
+ end,
+ case NoOkWrapper of
+ false ->
+ emit([nl,try_catch(),nl,nl]);
+ true ->
+ emit([nl,"end.",nl,nl])
end,
- emit(["end.",nl,nl]),
gen_decode_partial_incomplete(Erules),
@@ -999,16 +852,40 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
gen_partial_inc_dispatcher();
_PerOrPer_bin ->
gen_dispatcher(Types,"encode_disp","enc_",""),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory")
+ gen_dispatcher(Types,"decode_disp","dec_","")
end,
- emit([nl]),
- emit({nl,nl}).
+ emit([nl,nl]).
+
+result_line(NoOkWrapper, Items) ->
+ S = [" "|case NoOkWrapper of
+ false -> result_line_1(["ok"|Items]);
+ true -> result_line_1(Items)
+ end],
+ emit(lists:flatten(S)).
+
+result_line_1([SingleItem]) ->
+ SingleItem;
+result_line_1(Items) ->
+ ["{",string:join(Items, ","),"}"].
+
+try_catch() ->
+ [" catch",nl,
+ " Class:Exception when Class =:= error; Class =:= exit ->",nl,
+ " case Exception of",nl,
+ " {error,Reason}=Error ->",nl,
+ " Error;",nl,
+ " Reason ->",nl,
+ " {error,{asn1,Reason}}",nl,
+ " end",nl,
+ "end."].
gen_info_functions(Erules) ->
emit(["encoding_rule() -> ",
{asis,Erules},".",nl,nl,
"bit_string_format() -> ",
- {asis,asn1ct:get_bit_string_format()},".",nl,nl]).
+ {asis,asn1ct:get_bit_string_format()},".",nl,nl,
+ "legacy_erlang_types() -> ",
+ {asis,asn1ct:use_legacy_types()},".",nl,nl]).
gen_decode_partial_incomplete(ber) ->
case {asn1ct:read_config_data(partial_incomplete_decode),
@@ -1060,9 +937,10 @@ gen_partial_inc_dispatcher() ->
ok;
{Data1,Data2} ->
% io:format("partial_incomplete_decode: ~p~ninc_type_pattern: ~p~n",[Data,Data2]),
- gen_partial_inc_dispatcher(Data1,Data2)
+ gen_partial_inc_dispatcher(Data1, Data2, "")
end.
-gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest],TypePattern) ->
+
+gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest], TypePattern, Sep) ->
TPattern =
case lists:keysearch(FuncName,1,TypePattern) of
{value,{_,TP}} -> TP;
@@ -1076,13 +954,13 @@ gen_partial_inc_dispatcher([{FuncName,TopType,_Pattern}|Rest],TypePattern) ->
_ ->
atom_to_list(TopType)
end,
- emit(["decode_partial_inc_disp('",TopTypeName,"',Data) ->",nl,
+ emit([Sep,
+ "decode_partial_inc_disp('",TopTypeName,"',Data) ->",nl,
" ",{asis,list_to_atom(lists:concat(["dec-inc-",FuncName2]))},
- "(Data);",nl]),
- gen_partial_inc_dispatcher(Rest,TypePattern);
-gen_partial_inc_dispatcher([],_) ->
- emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
- " exit({error,{asn1,{undefined_type,Type}}}).",nl]).
+ "(Data)"]),
+ gen_partial_inc_dispatcher(Rest, TypePattern, ";\n");
+gen_partial_inc_dispatcher([], _, _) ->
+ emit([".",nl]).
gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) ->
emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]),
@@ -1107,9 +985,23 @@ pgen_info() ->
open_hrl(OutFile,Module) ->
File = lists:concat([OutFile,".hrl"]),
- Fid = fopen(File),
- put(gen_file_out,Fid),
- gen_hrlhead(Module).
+ _ = open_output_file(File),
+ gen_hrlhead(Module),
+ Protector = hrl_protector(OutFile),
+ emit(["-ifndef(",Protector,").\n",
+ "-define(",Protector,", true).\n"
+ "\n"]).
+
+hrl_protector(OutFile) ->
+ BaseName = filename:basename(OutFile),
+ P = "_" ++ string:to_upper(BaseName) ++ "_HRL_",
+ [if
+ $A =< C, C =< $Z -> C;
+ $a =< C, C =< $a -> C;
+ $0 =< C, C =< $9 -> C;
+ true -> $_
+ end || C <- P].
+
%% EMIT functions ************************
%% ***************************************
@@ -1181,15 +1073,19 @@ call_args([A|As], Sep) ->
[Sep,do_emit(A)|call_args(As, ", ")];
call_args([], _) -> [].
-fopen(F) ->
+open_output_file(F) ->
case file:open(F, [write,raw,delayed_write]) of
- {ok, Fd} ->
+ {ok,Fd} ->
+ put(gen_file_out, Fd),
Fd;
{error, Reason} ->
io:format("** Can't open file ~p ~n", [F]),
exit({error,Reason})
end.
+close_output_file() ->
+ ok = file:close(erase(gen_file_out)).
+
pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) ->
put(currmod,Module),
{Types,Values,Ptypes,_,_,_} = TypeOrVal,
@@ -1212,8 +1108,9 @@ pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) ->
0 ->
0;
Y ->
- Fid = get(gen_file_out),
- file:close(Fid),
+ Protector = hrl_protector(get(outfile)),
+ emit(["-endif. %% ",Protector,"\n"]),
+ close_output_file(),
asn1ct:verbose("--~p--~n",
[{generated,lists:concat([get(outfile),".hrl"])}],
Options),
@@ -1331,15 +1228,23 @@ gen_record(TorPtype,Name,Type,Num) when is_record(Type,type) ->
emit({"}).",nl,nl}),
Tr ++ ExtensionList2;
{Rootl1,Extl,Rootl2} ->
+ case Rootl1 =/= [] andalso Extl++Rootl2 =/= [] of
+ true -> emit([com]);
+ false -> ok
+ end,
case Rootl1 of
- [] -> true;
- _ -> emit([",",nl])
+ [_|_] -> emit([nl]);
+ [] -> ok
end,
emit(["%% with extensions",nl]),
gen_record2(Name,'SEQUENCE',Extl,"",ext),
+ case Extl =/= [] andalso Rootl2 =/= [] of
+ true -> emit([com]);
+ false -> ok
+ end,
case Extl of
- [_H|_] when Rootl2 /= [] -> emit([",",nl]);
- _ -> ok
+ [_|_] -> emit([nl]);
+ [] -> ok
end,
emit(["%% end of extensions",nl]),
gen_record2(Name,'SEQUENCE',Rootl2,"",noext),
@@ -1429,165 +1334,6 @@ to_textual_order(Cs=[#'ComponentType'{textual_order=undefined}|_]) ->
to_textual_order(Cs) when is_list(Cs) ->
lists:keysort(#'ComponentType'.textual_order,Cs).
-
-gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
- case WhatKind of
- {primitive,bif} ->
- gen_prim_check_call(InnerType,DefaultValue,Element,Type);
- #'Externaltypereference'{module=M,type=T} ->
- %% generate function call
- Name = list2name([T,check]),
- emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- %% insert in ets table and do look ahead check
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- InType = asn1ct_gen:get_inner(RefType#type.def),
- case insert_once(check_functions,{Name,RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
- _ ->
- ok
- end;
- {constructed,bif} ->
- NameList = [Cname|TopType],
- Name = list2name(NameList ++ [check]),
- emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- asn1ct_table:insert(check_functions, {Name, Type}),
- %% Must look for check functions in InnerType,
- %% that may be referenced or internal defined
- %% constructed types not used elsewhere.
- lookahead_innertype(NameList,InnerType,Type);
- _ ->
- %% Generate Dummy function call i.e. anything is accepted
- emit(["fun() -> true end ()"])
- end.
-
-gen_prim_check_call(PrimType, Default, Element, Type) ->
- case unify_if_string(PrimType) of
- 'BOOLEAN' ->
- check_call(check_bool, [Default,Element]);
- 'INTEGER' ->
- NNL = case Type#type.def of
- {_,NamedNumberList} -> NamedNumberList;
- _ -> []
- end,
- check_call(check_int, [Default,Element,{asis,NNL}]);
- 'BIT STRING' ->
- {_,NBL} = Type#type.def,
- check_call(check_bitstring, [Default,Element,{asis,NBL}]);
- 'OCTET STRING' ->
- check_call(check_octetstring, [Default,Element]);
- 'NULL' ->
- check_call(check_null, [Default,Element]);
- 'OBJECT IDENTIFIER' ->
- check_call(check_objectidentifier, [Default,Element]);
- 'RELATIVE-OID' ->
- check_call(check_objectidentifier, [Default,Element]);
- 'ObjectDescriptor' ->
- check_call(check_objectdescriptor, [Default,Element]);
- 'REAL' ->
- check_call(check_real, [Default,Element]);
- 'ENUMERATED' ->
- {_,Enumerations} = Type#type.def,
- check_call(check_enum, [Default,Element,{asis,Enumerations}]);
- restrictedstring ->
- 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) ->
- Components = (Type#type.def)#'SEQUENCE'.components,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'SET',Type) ->
- Components = (Type#type.def)#'SET'.components,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'CHOICE',Type) ->
- {_,Components} = Type#type.def,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'SEQUENCE OF',SeqOf) ->
- lookahead_sof(Name,'SEQOF',SeqOf);
-lookahead_innertype(Name,'SET OF',SeqOf) ->
- lookahead_sof(Name,'SETOF',SeqOf);
-lookahead_innertype(_Name,#'Externaltypereference'{module=M,type=T},_) ->
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- insert_once(check_functions,{list2name([T,check]),RefType}),
- InType = asn1ct_gen:get_inner(RefType#type.def),
- case type(InType) of
- {constructed,bif} ->
- lookahead_innertype([T],InType,RefType);
- Ref = #'Externaltypereference'{} ->
- lookahead_reference(Ref);
- _ ->
- ok
- end;
-lookahead_innertype(_,_,_) ->
- ok.
-
-lookahead_components(_,[]) -> ok;
-lookahead_components(Name,[C|Cs]) ->
- #'ComponentType'{name=Cname,typespec=Type} = C,
- InType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InType) of
- {constructed,bif} ->
- case insert_once(check_functions,
- {list2name([Cname|Name] ++ [check]),Type}) of
- true ->
- lookahead_innertype([Cname|Name],InType,Type);
- _ ->
- ok
- end;
- #'Externaltypereference'{module=RefMod,type=RefName} ->
- Typedef = asn1_db:dbget(RefMod,RefName),
- RefType = Typedef#typedef.typespec,
- case insert_once(check_functions,{list2name([RefName,check]),
- RefType}) of
- true ->
- lookahead_innertype([RefName],InType,RefType);
- _ ->
- ok
- end;
- _ ->
- ok
- end,
- lookahead_components(Name,Cs).
-
-lookahead_sof(Name,SOF,SOFType) ->
- Type = case SOFType#type.def of
- {_,_Type} -> _Type;
- _Type -> _Type
- end,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- %% this is if a constructed type is defined in
- %% the SEQUENCE OF type
- NameList = [SOF|Name],
- insert_once(check_functions,
- {list2name(NameList ++ [check]),Type}),
- lookahead_innertype(NameList,InnerType,Type);
- Ref = #'Externaltypereference'{} ->
- lookahead_reference(Ref);
- _ ->
- ok
- end.
-
-lookahead_reference(#'Externaltypereference'{module=M,type=T}) ->
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- InType = get_inner(RefType#type.def),
- case insert_once(check_functions,
- {list2name([T,check]),RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
- _ ->
- ok
- end.
-
insert_once(Table,Object) ->
case asn1ct_table:lookup(Table, element(1, Object)) of
[] ->
@@ -1628,9 +1374,38 @@ unify_if_string(PrimType) ->
Other -> Other
end.
+conform_value(#type{def={'BIT STRING',[]}}, Bs) ->
+ case asn1ct:get_bit_string_format() of
+ compact when is_binary(Bs) ->
+ {0,Bs};
+ compact when is_bitstring(Bs) ->
+ Sz = bit_size(Bs),
+ Unused = 8 - bit_size(Bs),
+ {Unused,<<Bs:Sz/bits,0:Unused>>};
+ legacy ->
+ [B || <<B:1>> <= Bs];
+ bitstring when is_bitstring(Bs) ->
+ Bs
+ end;
+conform_value(#type{def='OCTET STRING'}, String) ->
+ case asn1ct:use_legacy_types() of
+ false -> String;
+ true -> binary_to_list(String)
+ end;
+conform_value(_, Value) -> Value.
+
+named_bitstring_value(List, Names) ->
+ Int = lists:foldl(fun(N, A) ->
+ {N,Pos} = lists:keyfind(N, 1, Names),
+ A bor (1 bsl Pos)
+ end, 0, List),
+ named_bitstring_value_1(<<>>, Int).
-
-
+named_bitstring_value_1(Bs, 0) ->
+ Bs;
+named_bitstring_value_1(Bs, Int) ->
+ B = Int band 1,
+ named_bitstring_value_1(<<Bs/bitstring,B:1>>, Int bsr 1).
get_inner(A) when is_atom(A) -> A;
get_inner(Ext) when is_record(Ext,'Externaltypereference') -> Ext;
@@ -1835,11 +1610,6 @@ get_constraint(C,Key) ->
{value,Cnstr} ->
Cnstr
end.
-
-ensure_atom(Atom) when is_atom(Atom) ->
- Atom;
-ensure_atom(List) when is_list(List) ->
- list_to_atom(List).
get_record_name_prefix() ->
case lists:keysearch(record_name_prefix,1,get(encoding_options)) of
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 8ab49aec2c..e51b0898be 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -27,11 +27,12 @@
-export([decode_class/1, decode_type/1]).
-export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
-export([gen_encode_prim/4]).
--export([gen_dec_prim/7]).
+-export([gen_dec_prim/3]).
-export([gen_objectset_code/2, gen_obj_code/3]).
-export([encode_tag_val/3]).
-export([gen_inc_decode/2,gen_decode_selected/3]).
-export([extaddgroup2sequence/1]).
+-export([dialyzer_suppressions/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
@@ -65,6 +66,23 @@
%%===============================================================================
%%===============================================================================
+dialyzer_suppressions(_) ->
+ case asn1ct:use_legacy_types() of
+ false -> ok;
+ true -> suppress({ber,encode_bit_string,4})
+ end,
+ suppress({ber,decode_selective,2}),
+ emit([" ok.",nl]).
+
+suppress({M,F,A}=MFA) ->
+ case asn1ct_func:is_used(MFA) of
+ false ->
+ ok;
+ true ->
+ Args = [lists:concat(["element(",I,", Arg)"]) || I <- lists:seq(1, A)],
+ emit([" ",{call,M,F,Args},com,nl])
+ end.
+
%%===============================================================================
%% encode #{typedef, {pos, name, typespec}}
%%===============================================================================
@@ -163,6 +181,12 @@ gen_encode_user(Erules, #typedef{}=D, Wrapper) ->
gen_encode_prim(_Erules, #type{}=D, DoTag, Value) ->
BitStringConstraint = get_size_constraint(D#type.constraint),
+ MaxBitStrSize = case BitStringConstraint of
+ [] -> none;
+ {_,'MAX'} -> none;
+ {_,Max} -> Max;
+ Max when is_integer(Max) -> Max
+ end,
asn1ct_name:new(enumval),
Type = case D#type.def of
'OCTET STRING' -> restricted_string;
@@ -196,12 +220,42 @@ gen_encode_prim(_Erules, #type{}=D, DoTag, Value) ->
emit(["case ",Value," of",nl]),
emit_enc_enumerated_cases(NamedNumberList,DoTag);
'REAL' ->
- emit([{call,ber,encode_tags,
- [DoTag,{call,real_common,ber_encode_real,[Value]}]}]);
+ asn1ct_name:new(realval),
+ asn1ct_name:new(realsize),
+ emit(["begin",nl,
+ {curr,realval}," = ",
+ {call,real_common,ber_encode_real,[Value]},com,nl,
+ {curr,realsize}," = ",
+ {call,erlang,byte_size,[{curr,realval}]},com,nl,
+ {call,ber,encode_tags,
+ [DoTag,{curr,realval},{curr,realsize}]},nl,
+ "end"]);
+ {'BIT STRING',[]} ->
+ case asn1ct:use_legacy_types() of
+ false when MaxBitStrSize =:= none ->
+ call(encode_unnamed_bit_string, [Value,DoTag]);
+ false ->
+ call(encode_unnamed_bit_string,
+ [{asis,MaxBitStrSize},Value,DoTag]);
+ true ->
+ call(encode_bit_string,
+ [{asis,BitStringConstraint},Value,
+ {asis,[]},DoTag])
+ end;
{'BIT STRING',NamedNumberList} ->
- call(encode_bit_string,
- [{asis,BitStringConstraint},Value,
- {asis,NamedNumberList},DoTag]);
+ case asn1ct:use_legacy_types() of
+ false when MaxBitStrSize =:= none ->
+ call(encode_named_bit_string,
+ [Value,{asis,NamedNumberList},DoTag]);
+ false ->
+ call(encode_named_bit_string,
+ [{asis,MaxBitStrSize},Value,
+ {asis,NamedNumberList},DoTag]);
+ true ->
+ call(encode_bit_string,
+ [{asis,BitStringConstraint},Value,
+ {asis,NamedNumberList},DoTag])
+ end;
'NULL' ->
call(encode_null, [Value,DoTag]);
'OBJECT IDENTIFIER' ->
@@ -224,14 +278,20 @@ emit_enc_enumerated_cases(L, Tags) ->
emit_enc_enumerated_cases(L, Tags, noext).
emit_enc_enumerated_cases([{EnumName,EnumVal}|T], Tags, Ext) ->
+ Bytes = encode_pos_integer(EnumVal, []),
+ Len = length(Bytes),
emit([{asis,EnumName}," -> ",
- {call,ber,encode_enumerated,[EnumVal,Tags]},";",nl]),
+ {call,ber,encode_tags,[Tags,{asis,Bytes},Len]},";",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"]).
+encode_pos_integer(0, [B|_Acc] = L) when B < 128 ->
+ L;
+encode_pos_integer(N, Acc) ->
+ encode_pos_integer(N bsr 8, [N band 255|Acc]).
%%===============================================================================
%%===============================================================================
@@ -309,15 +369,11 @@ gen_decode_selected_type(_Erules,TypeDef) ->
case asn1ct_gen:type(InnerType) of
'ASN1_OPEN_TYPE' ->
asn1ct_name:new(len),
- gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'},
- BytesVar,Tag, [] ,
- ?PRIMITIVE,"OptOrMand");
-% emit({";",nl});
+ gen_dec_prim(Def#type{def='ASN1_OPEN_TYPE'},
+ BytesVar, Tag);
{primitive,bif} ->
asn1ct_name:new(len),
- gen_dec_prim(ber, Def, BytesVar,Tag,[] ,
- ?PRIMITIVE,"OptOrMand");
-% emit([";",nl]);
+ gen_dec_prim(Def, BytesVar, Tag);
{constructed,bif} ->
TopType = case TypeDef#typedef.name of
A when is_atom(A) -> [A];
@@ -431,14 +487,12 @@ gen_decode_user(Erules,D) when is_record(D,typedef) ->
case asn1ct_gen:type(InnerType) of
'ASN1_OPEN_TYPE' ->
asn1ct_name:new(len),
- gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'},
- BytesVar,{string,"TagIn"}, [] ,
- ?PRIMITIVE,"OptOrMand"),
+ gen_dec_prim(Def#type{def='ASN1_OPEN_TYPE'},
+ BytesVar, {string,"TagIn"}),
emit({".",nl,nl});
{primitive,bif} ->
asn1ct_name:new(len),
- gen_dec_prim(ber, Def, BytesVar,{string,"TagIn"},[] ,
- ?PRIMITIVE,"OptOrMand"),
+ gen_dec_prim(Def, BytesVar, {string,"TagIn"}),
emit([".",nl,nl]);
{constructed,bif} ->
asn1ct:update_namelist(D#typedef.name),
@@ -451,19 +505,11 @@ gen_decode_user(Erules,D) when is_record(D,typedef) ->
end.
-gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) ->
+gen_dec_prim(Att, BytesVar, DoTag) ->
Typename = Att#type.def,
-%% Currently not used for BER replaced with [] as place holder
-%% Constraint = Att#type.constraint,
-%% Constraint = [],
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
- 'OCTET STRING' -> restricted_string;
'NumericString' -> restricted_string;
'TeletexString' -> restricted_string;
'T61String' -> restricted_string;
@@ -476,85 +522,40 @@ gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) ->
'ObjectDescriptor'-> restricted_string;
'UTCTime' -> restricted_string;
'GeneralizedTime' -> restricted_string;
+ 'OCTET STRING' ->
+ case asn1ct:use_legacy_types() of
+ true -> restricted_string;
+ false -> Typename
+ end;
_ -> Typename
end,
- case NewTypeName of
- 'BOOLEAN'->
- emit(["decode_boolean(",BytesVar,","]),
- need(decode_boolean, 2);
- 'INTEGER' ->
- case IntConstr of
- [] ->
- emit(["decode_integer(",BytesVar,","]),
- need(decode_integer, 2);
- {_,_} ->
- emit(["decode_integer(",BytesVar,",",
- {asis,IntConstr},","]),
- need(decode_integer, 3)
- end;
- {'INTEGER',NamedNumberList} ->
- 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(["decode_enumerated(",BytesVar,",",
- {asis,NamedNumberList},","]),
- need(decode_enumerated, 3);
- 'REAL' ->
- ok;
- {'BIT STRING',_NamedNumberList} ->
- ok;
- 'NULL' ->
- emit(["decode_null(",BytesVar,","]),
- need(decode_null, 2);
- 'OBJECT IDENTIFIER' ->
- emit(["decode_object_identifier(",BytesVar,","]),
- need(decode_object_identifier, 2);
- 'RELATIVE-OID' ->
- 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(["decode_universal_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","]),
- need(decode_universal_string, 3);
- 'UTF8String' ->
- emit(["decode_UTF8_string",AsBin,"(",
- BytesVar,","]),
- need(decode_UTF8_string, 2);
- 'BMPString' ->
- emit(["decode_BMP_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","]),
- need(decode_BMP_string, 3);
- 'ASN1_OPEN_TYPE' ->
- emit(["decode_open_type_as_binary(",
- BytesVar,","]),
- need(decode_open_type_as_binary, 2)
- end,
-
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);
+ 'BOOLEAN'->
+ call(decode_boolean, [BytesVar,TagStr]);
+ 'INTEGER' ->
+ check_constraint(decode_integer, [BytesVar,TagStr],
+ IntConstr,
+ identity,
+ identity);
+ {'INTEGER',NNL} ->
+ check_constraint(decode_integer,
+ [BytesVar,TagStr],
+ IntConstr,
+ identity,
+ fun(Val) ->
+ asn1ct_name:new(val),
+ emit([{curr,val}," = "]),
+ Val(),
+ emit([com,nl,
+ {call,ber,number2name,
+ [{curr,val},{asis,NNL}]}])
+ end);
+ {'ENUMERATED',NNL} ->
+ gen_dec_enumerated(BytesVar, NNL, TagStr);
'REAL' ->
asn1ct_name:new(tmpbuf),
emit(["begin",nl,
@@ -562,8 +563,36 @@ gen_dec_prim(_Erules, Att, BytesVar, DoTag, _TagIn, _Form, _OptOrMand) ->
{call,ber,match_tags,[BytesVar,TagStr]},com,nl,
{call,real_common,decode_real,[{curr,tmpbuf}]},nl,
"end",nl]);
- _ ->
- emit([TagStr,")"])
+ {'BIT STRING',NNL} ->
+ gen_dec_bit_string(BytesVar, Constraint, NNL, TagStr);
+ 'NULL' ->
+ call(decode_null, [BytesVar,TagStr]);
+ 'OBJECT IDENTIFIER' ->
+ call(decode_object_identifier, [BytesVar,TagStr]);
+ 'RELATIVE-OID' ->
+ call(decode_relative_oid, [BytesVar,TagStr]);
+ 'OCTET STRING' ->
+ check_constraint(decode_octet_string, [BytesVar,TagStr],
+ Constraint, {erlang,byte_size}, identity);
+ restricted_string ->
+ check_constraint(decode_restricted_string, [BytesVar,TagStr],
+ Constraint,
+ {erlang,byte_size},
+ fun(Val) ->
+ emit("binary_to_list("),
+ Val(),
+ emit(")")
+ end);
+ 'UniversalString' ->
+ check_constraint(decode_universal_string, [BytesVar,TagStr],
+ Constraint, {erlang,length}, identity);
+ 'UTF8String' ->
+ call(decode_UTF8_string, [BytesVar,TagStr]);
+ 'BMPString' ->
+ check_constraint(decode_BMP_string, [BytesVar,TagStr],
+ Constraint, {erlang,length}, identity);
+ 'ASN1_OPEN_TYPE' ->
+ call(decode_open_type_as_binary, [BytesVar,TagStr])
end.
%% Simplify an integer constraint so that we can efficiently test it.
@@ -579,7 +608,7 @@ int_constr(C) ->
[{'ValueRange',{_,_}=Range}] ->
Range;
[{'SingleValue',Sv}] ->
- {Sv,Sv};
+ Sv;
[] ->
[]
end.
@@ -590,16 +619,108 @@ gen_dec_bit_string(BytesVar, _Constraint, [_|_]=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]);
+ check_constraint(decode_compact_bit_string,
+ [BytesVar,TagStr],
+ Constraint,
+ {ber,compact_bit_string_size},
+ identity);
legacy ->
- call(decode_legacy_bit_string,
- [BytesVar,{asis,Constraint},TagStr]);
+ check_constraint(decode_native_bit_string,
+ [BytesVar,TagStr],
+ Constraint,
+ {erlang,bit_size},
+ fun(Val) ->
+ asn1ct_name:new(val),
+ emit([{curr,val}," = "]),
+ Val(),
+ emit([com,nl,
+ {call,ber,native_to_legacy_bit_string,
+ [{curr,val}]}])
+ end);
bitstring ->
- call(decode_native_bit_string,
- [BytesVar,{asis,Constraint},TagStr])
+ check_constraint(decode_native_bit_string,
+ [BytesVar,TagStr],
+ Constraint,
+ {erlang,bit_size},
+ identity)
end.
+check_constraint(F, Args, Constr, PreConstr0, ReturnVal0) ->
+ PreConstr = case PreConstr0 of
+ identity ->
+ fun(V) -> V end;
+ {Mod,Name} ->
+ fun(V) ->
+ asn1ct_name:new(c),
+ emit([{curr,c}," = ",
+ {call,Mod,Name,[V]},com,nl]),
+ {curr,c}
+ end
+ end,
+ ReturnVal = case ReturnVal0 of
+ identity -> fun(Val) -> Val() end;
+ _ -> ReturnVal0
+ end,
+ case Constr of
+ [] when ReturnVal0 =:= identity ->
+ %% No constraint, no complications.
+ call(F, Args);
+ [] ->
+ %% No constraint, but the return value could consist
+ %% of more than one statement.
+ emit(["begin",nl]),
+ ReturnVal(fun() -> call(F, Args) end),
+ emit([nl,
+ "end",nl]);
+ _ ->
+ %% There is a constraint.
+ asn1ct_name:new(val),
+ emit(["begin",nl,
+ {curr,val}," = ",{call,ber,F,Args},com,nl]),
+ PreVal0 = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ PreVal = PreConstr(PreVal0),
+ emit("if "),
+ case Constr of
+ {Min,Max} ->
+ emit([{asis,Min}," =< ",PreVal,", ",
+ PreVal," =< ",{asis,Max}]);
+ Sv when is_integer(Sv) ->
+ emit([PreVal," =:= ",{asis,Sv}])
+ end,
+ emit([" ->",nl]),
+ ReturnVal(fun() -> emit(PreVal0) end),
+ emit([";",nl,
+ "true ->",nl,
+ "exit({error,{asn1,bad_range}})",nl,
+ "end",nl,
+ "end"])
+ end.
+
+gen_dec_enumerated(BytesVar, NNL0, TagStr) ->
+ asn1ct_name:new(enum),
+ emit(["case ",
+ {call,ber,decode_integer,[BytesVar,TagStr]},
+ " of",nl]),
+ NNL = case NNL0 of
+ {L1,L2} ->
+ L1 ++ L2 ++ [accept];
+ [_|_] ->
+ NNL0 ++ [error]
+ end,
+ gen_dec_enumerated_1(NNL),
+ emit("end").
+
+gen_dec_enumerated_1([accept]) ->
+ asn1ct_name:new(default),
+ emit([{curr,default}," -> {asn1_enum,",{curr,default},"}",nl]);
+gen_dec_enumerated_1([error]) ->
+ asn1ct_name:new(default),
+ emit([{curr,default}," -> exit({error,{asn1,{illegal_enumerated,",
+ {curr,default},"}}})",nl]);
+gen_dec_enumerated_1([{V,K}|T]) ->
+ emit([{asis,K}," -> ",{asis,V},";",nl]),
+ gen_dec_enumerated_1(T).
+
%% Object code generating for encoding and decoding
%% ------------------------------------------------
@@ -637,9 +758,6 @@ gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
% ", Val, 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("Val"),
emit([" {Val,0}"]),
@@ -672,9 +790,6 @@ gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
% 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},
@@ -807,9 +922,6 @@ gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
% ", 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"]),
@@ -844,9 +956,6 @@ gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
% ", Bytes,[H|T]) ->",nl]),
% emit_tlv_format("Bytes"),
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},
@@ -956,9 +1065,8 @@ gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number ||
X <- OTag],
case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",?PRIMITIVE,
- opt_or_default),
+ {primitive,bif} ->
+ gen_dec_prim(Def, Bytes, Tag),
[];
{constructed,bif} ->
emit({" 'dec_",ObjName,'_',FieldName,
@@ -986,8 +1094,7 @@ gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
FieldName])),
typespec=Type}];
{primitive,bif} ->
- gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",
- ?PRIMITIVE,opt_or_default),
+ gen_dec_prim(Type, Bytes, Tag),
[];
#'Externaltypereference'{module=CurrentMod,type=Etype} ->
emit([" 'dec_",Etype,"'(",Bytes, " ,",{asis,Tag},")",nl]),
@@ -1072,8 +1179,7 @@ gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
gen_objset_enc(Erules, ObjSetName, UniqueName,
[{ObjName,Val,Fields}|T], ClName, ClFields,
NthObj,Acc)->
- emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl]),
+ emit(["'getenc_",ObjSetName,"'(",{asis,Val},") ->",nl]),
CurrMod = get(currmod),
{InternalFunc,NewNthObj}=
case ObjName of
@@ -1095,13 +1201,11 @@ gen_objset_enc(Erules, ObjSetName, UniqueName,
%% 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) -> byte_size(Bin);",nl,indent(9),
- "_ -> length(Val)",nl,indent(6),"end,"}),
- emit({indent(6),"{Val,Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
+ emit(["'getenc_",ObjSetName,"'(_) ->",nl,
+ indent(2),"fun(_, Val, _RestPrimFieldName) ->",nl]),
+ emit_enc_open_type(4),
+ emit([nl,
+ indent(2),"end.",nl,nl]),
Acc;
gen_objset_enc(_, ObjSetName, UniqueName, [], _, _, _, Acc) ->
emit_default_getenc(ObjSetName, UniqueName),
@@ -1113,7 +1217,7 @@ emit_ext_fun(EncDec,ModuleName,Name) ->
Name,"'(T,V,O) end"]).
emit_default_getenc(ObjSetName,UniqueName) ->
- emit(["'getenc_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
+ emit(["'getenc_",ObjSetName,"'(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
@@ -1163,13 +1267,8 @@ gen_inlined_enc_funs1(Fields, [{typefield,Name,_}|Rest], ObjSetName,
%% were no type in the table and we therefore generate
%% code that returns the input for application
%% treatment.
- 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}"]),
+ emit([indent(9),{asis,Name}," ->",nl]),
+ emit_enc_open_type(11),
{Acc0,0}
end,
gen_inlined_enc_funs1(Fields, Rest, ObjSetName, Sep, NthObj+NAdd, Acc);
@@ -1180,6 +1279,25 @@ gen_inlined_enc_funs1(_, [], _, _, NthObj, Acc) ->
indent(3),"end"]),
{Acc,NthObj}.
+emit_enc_open_type(I) ->
+ Indent = indent(I),
+ S = [Indent, "case Val of",nl,
+ Indent,indent(2),"{asn1_OPENTYPE,Bin} when is_binary(Bin) ->",nl,
+ Indent,indent(4),"{Bin,byte_size(Bin)}"|
+ case asn1ct:use_legacy_types() of
+ false ->
+ [nl,
+ Indent,"end"];
+ true ->
+ [";",nl,
+ Indent,indent(2),"Bin when is_binary(Bin) ->",nl,
+ Indent,indent(4),"{Bin,byte_size(Bin)};",nl,
+ Indent,indent(2),"_ ->",nl,
+ Indent,indent(4),"{Val,length(Val)}",nl,
+ Indent, "end"]
+ end],
+ emit(S).
+
emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
InternalDefFunName) ->
OTag = Type#type.tag,
@@ -1240,8 +1358,7 @@ gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
ok;
gen_objset_dec(Erules, ObjSName, UniqueName, [{ObjName,Val,Fields}|T],
ClName, ClFields, NthObj)->
- emit(["'getdec_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl]),
+ emit(["'getdec_",ObjSName,"'(",{asis,Val},") ->",nl]),
CurrMod = get(currmod),
NewNthObj=
case ObjName of
@@ -1262,16 +1379,11 @@ gen_objset_dec(Erules, ObjSName, UniqueName, [{ObjName,Val,Fields}|T],
ClFields, NewNthObj);
gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj) ->
- emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
+ emit(["'getdec_",ObjSetName,"'(_) ->",nl]),
emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
-
- 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]),
+ emit_dec_open_type(4),
+ emit([nl,
+ indent(2),"end.",nl,nl]),
ok;
gen_objset_dec(_, ObjSetName, UniqueName, [], _, _, _) ->
emit_default_getdec(ObjSetName, UniqueName),
@@ -1279,7 +1391,7 @@ gen_objset_dec(_, ObjSetName, UniqueName, [], _, _, _) ->
ok.
emit_default_getdec(ObjSetName,UniqueName) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
+ emit(["'getdec_",ObjSetName,"'(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, ClFields, ObjSetName, NthObj) ->
@@ -1318,12 +1430,8 @@ gen_inlined_dec_funs1(Fields, [{typefield,Name,Prop}|Rest],
end,
0;
false ->
- emit([indent(9),{asis,Name}," ->",nl,
- indent(12),"Len = case Bytes of",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}"]),
+ emit([indent(9),{asis,Name}," ->",nl]),
+ emit_dec_open_type(11),
0
end,
gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N);
@@ -1334,7 +1442,28 @@ gen_inlined_dec_funs1(_, [], _, _, NthObj) ->
indent(3),"end"]),
NthObj.
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
+emit_dec_open_type(I) ->
+ Indent = indent(I),
+ S = case asn1ct:use_legacy_types() of
+ false ->
+ [Indent, "case Bytes of",nl,
+ Indent,indent(2),"Bin when is_binary(Bin) -> ",nl,
+ Indent,indent(4),"{asn1_OPENTYPE,Bin};",nl,
+ Indent,indent(2),"_ ->",nl,
+ Indent,indent(4),"{asn1_OPENTYPE,",
+ {call,ber,ber_encode,["Bytes"]},"}",nl,
+ Indent, "end"];
+ true ->
+ [Indent, "case Bytes of",nl,
+ Indent,indent(2),"Bin when is_binary(Bin) -> ",nl,
+ Indent,indent(4),"Bin;",nl,
+ Indent,indent(2),"_ ->",nl,
+ Indent,indent(4),{call,ber,ber_encode,["Bytes"]},nl,
+ Indent, "end"]
+ end,
+ emit(S).
+
+emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type}, _Prop,
InternalDefFunName) ->
OTag = Type#type.tag,
%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
@@ -1342,8 +1471,7 @@ emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
case {ExtName,Name} of
{primitive,bif} ->
emit(indent(12)),
- gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
- ?PRIMITIVE,Prop),
+ gen_dec_prim(Type, "Bytes", Tag),
0;
{constructed,bif} ->
emit([indent(12),"'dec_",
@@ -1360,7 +1488,7 @@ emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
emit_inner_of_decfun(#typedef{name=Name},_Prop,_) ->
emit([indent(12),"'dec_",Name,"'(Bytes)"]),
0;
-emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) ->
+emit_inner_of_decfun(#type{}=Type, _Prop, _) ->
OTag = Type#type.tag,
%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
@@ -1371,8 +1499,7 @@ emit_inner_of_decfun(Type,Prop,_) when is_record(Type,type) ->
case WhatKind of
{primitive,bif} ->
emit([indent(9),Def," ->",nl,indent(12)]),
- gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
- ?PRIMITIVE,Prop);
+ gen_dec_prim(Type, "Bytes", Tag);
#'Externaltypereference'{module=CurrMod,type=T} ->
emit([indent(9),T," ->",nl,indent(12),"'dec_",T,
% "'(Bytes, ",Prop,")"]);
@@ -1509,6 +1636,3 @@ extaddgroup2sequence(ExtList) when is_list(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_check.erl b/lib/asn1/src/asn1ct_gen_check.erl
new file mode 100644
index 0000000000..d80a02dfbf
--- /dev/null
+++ b/lib/asn1/src/asn1ct_gen_check.erl
@@ -0,0 +1,271 @@
+%% vim: tabstop=8:shiftwidth=4
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2014. 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_check).
+-export([emit/3]).
+
+-import(asn1ct_gen, [emit/1]).
+-include("asn1_records.hrl").
+
+emit(Type, Default, Value) ->
+ Key = {Type,Default},
+ Gen = fun(Fd, Name) ->
+ file:write(Fd, gen(Name, Type, Default))
+ end,
+ emit(" case "),
+ asn1ct_func:call_gen("is_default_", Key, Gen, [Value]),
+ emit([" of",nl,
+ "true -> {[],0};",nl,
+ "false ->",nl]).
+
+gen(Name, #type{def=T}, Default) ->
+ NameStr = atom_to_list(Name),
+ [NameStr,"(asn1_DEFAULT) ->\n",
+ "true;\n"|case do_gen(T, Default) of
+ {literal,Literal} ->
+ [NameStr,"(",term2str(Literal),") ->\n","true;\n",
+ NameStr,"(_) ->\n","false.\n\n"];
+ {exception,Func,Args} ->
+ [NameStr,"(Value) ->\n",
+ "try ",Func,"(Value",arg2str(Args),") of\n",
+ "_ -> true\n"
+ "catch throw:false -> false\n"
+ "end.\n\n"]
+ end].
+
+do_gen(_, asn1_NOVALUE) ->
+ {literal,asn1_NOVALUE};
+do_gen(#'Externaltypereference'{module=M,type=T}, Default) ->
+ #typedef{typespec=#type{def=Td}} = asn1_db:dbget(M, T),
+ do_gen(Td, Default);
+do_gen('BOOLEAN', Default) ->
+ {literal,Default};
+do_gen({'BIT STRING',[]}, Default) ->
+ true = is_bitstring(Default), %Assertion.
+ case asn1ct:use_legacy_types() of
+ false ->
+ {literal,Default};
+ true ->
+ {exception,need(check_legacy_bitstring, 2),[Default]}
+ end;
+do_gen({'BIT STRING',[_|_]=NBL}, Default) ->
+ do_named_bitstring(NBL, Default);
+do_gen({'ENUMERATED',_}, Default) ->
+ {literal,Default};
+do_gen('INTEGER', Default) ->
+ {literal,Default};
+do_gen({'INTEGER',NNL}, Default) ->
+ {exception,need(check_int, 3),[Default,NNL]};
+do_gen('NULL', Default) ->
+ {literal,Default};
+do_gen('OCTET STRING', Default) ->
+ true = is_binary(Default), %Assertion.
+ case asn1ct:use_legacy_types() of
+ false ->
+ {literal,Default};
+ true ->
+ {exception,need(check_octetstring, 2),[Default]}
+ end;
+do_gen('OBJECT IDENTIFIER', Default0) ->
+ Default = pre_process_oid(Default0),
+ {exception,need(check_objectidentifier, 2),[Default]};
+do_gen({'CHOICE',Cs}, Default) ->
+ {Tag,Value} = Default,
+ [Type] = [Type || #'ComponentType'{name=T,typespec=Type} <- Cs,
+ T =:= Tag],
+ case do_gen(Type#type.def, Value) of
+ {literal,Lit} ->
+ {literal,{Tag,Lit}};
+ {exception,Func0,Args} ->
+ Key = {Tag,Func0,Args},
+ Gen = fun(Fd, Name) ->
+ S = gen_choice(Name, Tag, Func0, Args),
+ ok = file:write(Fd, S)
+ end,
+ Func = asn1ct_func:call_gen("is_default_choice", Key, Gen),
+ {exception,atom_to_list(Func),[]}
+ end;
+do_gen(#'SEQUENCE'{components=Cs}, Default) ->
+ do_seq_set(Cs, Default);
+do_gen({'SEQUENCE OF',Type}, Default) ->
+ do_sof(Type, Default);
+do_gen(#'SET'{components=Cs}, Default) ->
+ do_seq_set(Cs, Default);
+do_gen({'SET OF',Type}, Default) ->
+ do_sof(Type, Default);
+do_gen(Type, Default) ->
+ case asn1ct_gen:unify_if_string(Type) of
+ restrictedstring ->
+ {exception,need(check_restrictedstring, 2),[Default]};
+ _ ->
+ %% Open type. Do our best.
+ {literal,Default}
+ end.
+
+do_named_bitstring(NBL, Default0) when is_list(Default0) ->
+ Default = lists:sort(Default0),
+ Bs = asn1ct_gen:named_bitstring_value(Default, NBL),
+ Func = case asn1ct:use_legacy_types() of
+ false -> check_named_bitstring;
+ true -> check_legacy_named_bitstring
+ end,
+ {exception,need(Func, 4),[Default,Bs,bit_size(Bs)]};
+do_named_bitstring(_, Default) when is_bitstring(Default) ->
+ Func = case asn1ct:use_legacy_types() of
+ false -> check_named_bitstring;
+ true -> check_legacy_named_bitstring
+ end,
+ {exception,need(Func, 3),[Default,bit_size(Default)]}.
+
+do_seq_set(Cs0, Default) ->
+ Tag = element(1, Default),
+ Cs1 = [T || #'ComponentType'{typespec=T} <- Cs0],
+ Cs = components(Cs1, tl(tuple_to_list(Default))),
+ case are_all_literals(Cs) of
+ true ->
+ Literal = list_to_tuple([Tag|[L || {literal,L} <- Cs]]),
+ {literal,Literal};
+ false ->
+ Key = {Cs,Default},
+ Gen = fun(Fd, Name) ->
+ S = gen_components(Name, Tag, Cs),
+ ok = file:write(Fd, S)
+ end,
+ Func = asn1ct_func:call_gen("is_default_cs_", Key, Gen),
+ {exception,atom_to_list(Func),[]}
+ end.
+
+do_sof(Type, Default0) ->
+ Default = lists:sort(Default0),
+ Cs0 = lists:duplicate(length(Default), Type),
+ Cs = components(Cs0, Default),
+ case are_all_literals(Cs) of
+ true ->
+ Literal = [Lit || {literal,Lit} <- Cs],
+ {exception,need(check_literal_sof, 2),[Literal]};
+ false ->
+ Key = Cs,
+ Gen = fun(Fd, Name) ->
+ S = gen_sof(Name, Cs),
+ ok = file:write(Fd, S)
+ end,
+ Func = asn1ct_func:call_gen("is_default_sof", Key, Gen),
+ {exception,atom_to_list(Func),[]}
+ end.
+
+are_all_literals([{literal,_}|T]) ->
+ are_all_literals(T);
+are_all_literals([_|_]) ->
+ false;
+are_all_literals([]) -> true.
+
+gen_components(Name, Tag, Cs) ->
+ [atom_to_list(Name),"(Value) ->\n",
+ "case Value of\n",
+ "{",term2str(Tag)|gen_cs_1(Cs, 1, [])].
+
+gen_cs_1([{literal,Lit}|T], I, Acc) ->
+ [",\n",term2str(Lit)|gen_cs_1(T, I, Acc)];
+gen_cs_1([H|T], I, Acc) ->
+ Var = "E"++integer_to_list(I),
+ [",\n",Var|gen_cs_1(T, I+1, [{Var,H}|Acc])];
+gen_cs_1([], _, Acc) ->
+ ["} ->\n"|gen_cs_2(Acc, "")].
+
+gen_cs_2([{Var,{exception,Func,Args}}|T], Sep) ->
+ [Sep,Func,"(",Var,arg2str(Args),")"|gen_cs_2(T, ",\n")];
+gen_cs_2([], _) ->
+ [";\n",
+ "_ ->\n"
+ "throw(false)\n"
+ "end.\n"].
+
+gen_sof(Name, Cs) ->
+ [atom_to_list(Name),"(Value) ->\n",
+ "case length(Value) of\n",
+ integer_to_list(length(Cs))," -> ok;\n"
+ "_ -> throw(false)\n"
+ "end,\n"
+ "T0 = lists:sort(Value)"|gen_sof_1(Cs, 1)].
+
+gen_sof_1([{exception,Func,Args}|Cs], I) ->
+ NumStr = integer_to_list(I),
+ H = "H" ++ NumStr,
+ T = "T" ++ NumStr,
+ Prev = "T" ++ integer_to_list(I-1),
+ [",\n",
+ "[",H,case Cs of
+ [] -> [];
+ [_|_] -> ["|",T]
+ end,"] = ",Prev,",\n",
+ Func,"(",H,arg2str(Args),")"|gen_sof_1(Cs, I+1)];
+gen_sof_1([], _) ->
+ ".\n".
+
+components([#type{def=Def}|Ts], [V|Vs]) ->
+ [do_gen(Def, V)|components(Ts, Vs)];
+components([], []) -> [].
+
+gen_choice(Name, Tag, Func, Args) ->
+ NameStr = atom_to_list(Name),
+ [NameStr,"({",term2str(Tag),",Value}) ->\n"
+ " ",Func,"(Value",arg2str(Args),");\n",
+ NameStr,"(_) ->\n"
+ " throw(false).\n"].
+
+pre_process_oid(Oid) ->
+ Reserved = reserved_oid(),
+ pre_process_oid(tuple_to_list(Oid), Reserved, []).
+
+pre_process_oid([H|T]=Tail, Res0, Acc) ->
+ case lists:keyfind(H, 2, Res0) of
+ false ->
+ {lists:reverse(Acc),Tail};
+ {Names0,H,Res} ->
+ Names = case is_list(Names0) of
+ false -> [Names0];
+ true -> Names0
+ end,
+ Keys = [H|Names],
+ pre_process_oid(T, Res, [Keys|Acc])
+ end.
+
+reserved_oid() ->
+ [{['itu-t',ccitt],0,
+ [{recommendation,0,[]},
+ {question,1,[]},
+ {administration,2,[]},
+ {'network-operator',3,[]},
+ {'identified-organization',4,[]}]},
+ {iso,1,[{standard,0,[]},
+ {'member-body',2,[]},
+ {'identified-organization',3,[]}]},
+ {['joint-iso-itu-t','joint-iso-ccitt'],2,[]}].
+
+arg2str(Args) ->
+ [", "++term2str(Arg) || Arg <- Args].
+
+term2str(T) ->
+ io_lib:format("~w", [T]).
+
+need(F, A) ->
+ asn1ct_func:need({check,F,A}),
+ atom_to_list(F).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 69d9d51bf1..39cc0536f8 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -26,12 +26,13 @@
%-compile(export_all).
-export([gen_dec_imm/2]).
--export([gen_dec_prim/3,gen_encode_prim/3]).
+-export([gen_dec_prim/3,gen_encode_prim_imm/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([gen_dec_external/2]).
-export([extaddgroup2sequence/1]).
+-export([dialyzer_suppressions/1]).
-import(asn1ct_gen, [emit/1,demit/1]).
-import(asn1ct_func, [call/3]).
@@ -40,6 +41,15 @@
%% Generate ENCODING ******************************
%%****************************************x
+dialyzer_suppressions(Erules) ->
+ case asn1ct_func:is_used({Erules,complete,1}) of
+ false ->
+ ok;
+ true ->
+ emit([" _ = complete(Arg),",nl])
+ end,
+ emit([" ok.",nl]).
+
gen_encode(Erules,Type) when is_record(Type,typedef) ->
gen_encode_user(Erules,Type).
@@ -99,835 +109,122 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
gen_encode_prim(Erules, D) ->
- Value = asn1ct_gen:mk_var(asn1ct_name:curr(val)),
+ Value = {var,atom_to_list(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,
- 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
+ Aligned = case Erules of
+ uper -> false;
+ per -> true
+ end,
+ Imm = gen_encode_prim_imm(Value, D, Aligned),
+ asn1ct_imm:enc_cg(Imm, Aligned).
+
+gen_encode_prim_imm(Val, #type{def=Type0,constraint=Constraint}, Aligned) ->
+ case simplify_type(Type0) of
+ k_m_string ->
+ Type = case Type0 of
+ 'GeneralizedTime' -> 'VisibleString';
+ 'UTCTime' -> 'VisibleString';
+ _ -> Type0
+ end,
+ asn1ct_imm:per_enc_k_m_string(Val, Type, Constraint, Aligned);
+ restricted_string ->
+ ToBinary = {erlang,iolist_to_binary},
+ asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned);
+ {'ENUMERATED',NNL} ->
+ asn1ct_imm:per_enc_enumerated(Val, NNL, Aligned);
'INTEGER' ->
- Args = [{asis,asn1ct_imm:effective_constraint(integer,Constraint)},
- Value],
- call(Erules, encode_integer, Args);
- {'INTEGER',NamedNumberList} ->
- Args = [{asis,asn1ct_imm:effective_constraint(integer,Constraint)},
- Value,{asis,NamedNumberList}],
- call(Erules, encode_integer, Args);
+ asn1ct_imm:per_enc_integer(Val, Constraint, Aligned);
+ {'INTEGER',NNL} ->
+ asn1ct_imm:per_enc_integer(Val, NNL, Constraint, Aligned);
'REAL' ->
- emit_enc_real(Erules, Value);
-
- {'BIT STRING',NamedNumberList} ->
- call(Erules, encode_bit_string,
- [{asis,SizeConstr},Value,
- {asis,NamedNumberList}]);
+ ToBinary = {real_common,encode_real},
+ asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned);
+ {'BIT STRING',NNL} ->
+ case asn1ct:use_legacy_types() of
+ false ->
+ asn1ct_imm:per_enc_bit_string(Val, NNL,
+ Constraint, Aligned);
+ true ->
+ asn1ct_imm:per_enc_legacy_bit_string(Val, NNL,
+ Constraint, Aligned)
+ end;
'NULL' ->
- emit("[]");
+ asn1ct_imm:per_enc_null(Val, Aligned);
'OBJECT IDENTIFIER' ->
- call(Erules, encode_object_identifier, [Value]);
+ ToBinary = {per_common,encode_oid},
+ asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned);
'RELATIVE-OID' ->
- call(Erules, encode_relative_oid, [Value]);
- 'ObjectDescriptor' ->
- call(Erules, encode_ObjectDescriptor,
- [{asis,Constraint},Value]);
+ ToBinary = {per_common,encode_relative_oid},
+ asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned);
'BOOLEAN' ->
- call(Erules, encode_boolean, [Value]);
+ asn1ct_imm:per_enc_boolean(Val, Aligned);
'OCTET STRING' ->
- case SizeConstr of
- 0 ->
- emit("[]");
- no ->
- call(Erules, encode_octet_string, [Value]);
- C ->
- call(Erules, encode_octet_string, [{asis,C},Value])
+ case asn1ct:use_legacy_types() of
+ false ->
+ asn1ct_imm:per_enc_octet_string(Val, Constraint, Aligned);
+ true ->
+ asn1ct_imm:per_enc_legacy_octet_string(Val, Constraint,
+ Aligned)
end;
- 'NumericString' ->
- call(Erules, encode_NumericString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- call(Erules, encode_TeletexString, [{asis,Constraint},Value]);
- 'VideotexString' ->
- call(Erules, encode_VideotexString, [{asis,Constraint},Value]);
- 'UTCTime' ->
- call(Erules, encode_VisibleString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'GeneralizedTime' ->
- call(Erules, encode_VisibleString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'GraphicString' ->
- call(Erules, encode_GraphicString, [{asis,Constraint},Value]);
- 'VisibleString' ->
- call(Erules, encode_VisibleString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'GeneralString' ->
- call(Erules, encode_GeneralString, [{asis,Constraint},Value]);
- 'PrintableString' ->
- call(Erules, encode_PrintableString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'IA5String' ->
- call(Erules, encode_IA5String, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'BMPString' ->
- call(Erules, encode_BMPString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'UniversalString' ->
- call(Erules, encode_UniversalString, [{asis,SizeConstr},
- {asis,Pa},Value]);
- 'UTF8String' ->
- call(Erules, encode_UTF8String, [Value]);
'ASN1_OPEN_TYPE' ->
- NewValue = case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- 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(
- "complete(enc_~s(~s))",
- [Tname,Value]);
- _ ->
- io_lib:format("iolist_to_binary(~s)",
- [Value])
- end,
- 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}]},",",
- {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(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(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
-%% ------------------------------------------------
-
-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(Erules, ClassName, get_class_fields(Class),
- ObjName, Fields, []),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit(nl).
-
-
-gen_encode_objectfields(Erule, ClassName,
- [{typefield,Name,OptOrMand}|Rest],
- ObjName, ObjectFields, ConstrAcc) ->
- EmitFuncClause =
- fun(V) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",V,",_RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, _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("Val"),
- case Erule of
- uper ->
- emit(" 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(Erule, ClassName, Name, DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(Erule, ObjName, Name, TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(Erule,ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(Erule,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(Erule,ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(Erule,ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(Erule,ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_, _,[],_,_,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;
- _ ->
-%% FuncName = list_to_atom(lists:concat(["enc_",TypeDef#typedef.name])),
- FuncName = asn1ct_gen:list2rname(TypeDef#typedef.name ++ [enc]),
- emit(["'",FuncName,"'(Val) ->",nl]),
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_encode_constructed(Erules,TypeDef#typedef.name,
- InnerType,Def),
- gen_encode_constr_type(Erules,Rest)
- end;
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(_Erules, _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(Erules, ObjName, FieldName, Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_encode_prim(Erules, Def, "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val)"}),
-%% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- [Type#typedef{name=[FieldName,ObjName]}];
- {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])),
- [#typedef{name=[FieldName,ClassName],
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(Erules, Type, "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(Erules, ClassName,
- [{typefield,Name,OptOrMand}|Rest],
- ObjName, ObjectFields, ConstrAcc) ->
- EmitFuncClause =
- fun(Bytes) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
- ",_,_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("Bytes"),
- emit([" {Bytes,[]}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- 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(Erules, ObjName, Name, "Bytes", TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- 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) ->
- 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)"})
+ case Constraint of
+ [#'Externaltypereference'{type=Tname}] ->
+ EncFunc = enc_func(Tname),
+ Imm = [{apply,{local,EncFunc,[]},[Val]}],
+ asn1ct_imm:per_enc_open_type(Imm, Aligned);
+ [] ->
+ Imm = [{call,erlang,iolist_to_binary,[Val]}],
+ asn1ct_imm:per_enc_open_type(Imm, Aligned)
end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- 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(_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(Erules, Def, Bytes),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",telltype)"}),
-%% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- [Type#typedef{name=[FieldName,ObjName]}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", telltype)"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
- []
end.
-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} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
-%% [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- [#typedef{name=[FieldName,ClassName],
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(Erules, Type, Bytes),
- [];
- #'Externaltypereference'{}=Etype ->
- asn1ct_gen_per:gen_dec_external(Etype, Bytes),
- []
+dec_func(Tname) ->
+ list_to_atom(lists:concat(["dec_",Tname])).
+
+enc_func(Tname) ->
+ list_to_atom(lists:concat(["enc_",Tname])).
+
+simplify_type(Type) ->
+ case Type of
+ 'BMPString' -> k_m_string;
+ 'IA5String' -> k_m_string;
+ 'NumericString' -> k_m_string;
+ 'PrintableString' -> k_m_string;
+ 'VisibleString' -> k_m_string;
+ 'UniversalString' -> k_m_string;
+ 'GeneralizedTime' -> k_m_string;
+ 'UTCTime' -> k_m_string;
+ 'TeletexString' -> restricted_string;
+ 'T61String' -> restricted_string;
+ 'VideotexString' -> restricted_string;
+ 'GraphicString' -> restricted_string;
+ 'GeneralString' -> restricted_string;
+ 'UTF8String' -> restricted_string;
+ 'ObjectDescriptor' -> restricted_string;
+ Other -> Other
end.
+%% Object code generating for encoding and decoding
+%% ------------------------------------------------
-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#typedef{name=asn1ct_gen:list2rname(TypeDef#typedef.name)})
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
+gen_obj_code(_Erules, _Module, #typedef{}) ->
ok.
-
-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(Erules,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(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,
- ObjSetName, NthObj);
- {CurrMod,Name} ->
- emit({" fun 'enc_",Name,"'/3"}),
- {[],0};
- {ModName,Name} ->
- emit_ext_encfun(ModName,Name),
- {[],0};
- _Other ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],0}
- end,
- emit({";",nl}),
- 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}),
- emit([indent(6),"Val",nl,
- indent(3),"end.",nl,nl]),
- 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) ->
- 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,_,_}|_]=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,
- Sep0, NthObj, Acc0) ->
- emit(Sep0),
- Sep = [";",nl],
- CurrentMod = get(currmod),
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {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, 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(Erule, #typedef{name={ExtMod,Name},typespec=Type}=TDef,
- InternalDefFunName) ->
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(Erule, Type, "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{}=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, "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(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(Erule, Fields, ClFields,
- ObjSName, NthObj);
- {CurrMod,Name} ->
- emit([" fun 'dec_",Name,"'/4"]),
- NthObj;
- {ModName,Name} ->
- emit_ext_decfun(ModName,Name),
- NthObj;
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- 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),"{Bytes,Attr1}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_Erule, ObjSetName, UniqueName, [], _, _, _) ->
- emit_default_getdec(ObjSetName, UniqueName),
- emit([".",nl,nl]),
+gen_objectset_code(_Erules, _ObjSet) ->
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(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(Erule, Fields, [{typefield,Name,_}|Rest],
- ObjSetName, Sep0, NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- 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(Erule, #typedef{name={ExtName,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(Erule, 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(_Erule, #typedef{name=Name}, _) ->
- emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
- 0;
-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(Erule, Type, "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(_,[]) ->
- 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}),
+gen_decode(Erules, #typedef{}=Type) ->
+ DecFunc = dec_func(Type#typedef.name),
+ emit([nl,nl,{asis,DecFunc},"(Bytes) ->",nl]),
dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
+ gen_decode_user(Erules, Type).
gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
NewTname = [Cname|Tname],
@@ -944,8 +241,9 @@ gen_decode(Erules,Typename,Type) when is_record(Type,type) ->
_ ->
""
end,
- emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
- "'(Bytes,_",ObjFun,") ->",nl}),
+ emit([nl,
+ {asis,dec_func(asn1ct_gen:list2name(Typename))},
+ "(Bytes",ObjFun,") ->",nl]),
dbdec(Typename),
asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
_ ->
@@ -982,8 +280,8 @@ gen_dec_external(Ext, BytesVar) ->
#'Externaltypereference'{module=Mod,type=Type} = Ext,
emit([case CurrMod of
Mod -> [];
- _ -> ["'",Mod,"':"]
- end,"'dec_",Type,"'(",BytesVar,",telltype)"]).
+ _ -> [{asis,Mod},":"]
+ end,{asis,dec_func(Type)},"(",BytesVar,")"]).
gen_dec_imm(Erule, #type{def=Name,constraint=C}) ->
Aligned = case Erule of
@@ -1050,7 +348,10 @@ gen_dec_imm_1('GeneralizedTime', 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};
+ case asn1ct:use_legacy_types() of
+ false -> {convert,{binary,copy},Imm};
+ true -> {convert,binary_to_list,Imm}
+ end;
gen_dec_imm_1('TeletexString', _Constraint, Aligned) ->
gen_dec_restricted_string(Aligned);
gen_dec_imm_1('T61String', _Constraint, Aligned) ->
@@ -1103,35 +404,6 @@ 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
- 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 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
@@ -1170,11 +442,8 @@ imm_dec_open_type_1(Type, Aligned) ->
asn1ct_name:new(tmpval),
emit(["begin",nl,
"{",{curr,tmpval},",_} = ",
- "dec_",Type,"(",OpenType,", mandatory),",nl,
+ {asis,dec_func(Type)},"(",OpenType,"),",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
deleted file mode 100644
index 012d54e7a1..0000000000
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ /dev/null
@@ -1,461 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% 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
-%% 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_per_rt2ct).
-
-%% Handle encoding of primitives for aligned PER.
-
--include("asn1_records.hrl").
-
--export([gen_encode_prim/3]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
--import(asn1ct_func, [call/3]).
-
-gen_encode_prim(Erules, #type{}=D, Value) ->
- Constraint = D#type.constraint,
- case D#type.def of
- 'INTEGER' ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit([" %%INTEGER with effective constraint: ",
- {asis,EffectiveConstr},nl]),
- emit_enc_integer(Erules,EffectiveConstr,Value);
- {'INTEGER',NamedNumberList} ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- %% maybe an emit_enc_NNL_integer
- emit([" %%INTEGER with effective constraint: ",
- {asis,EffectiveConstr},nl]),
- emit_enc_integer_NNL(Erules,EffectiveConstr,Value,NamedNumberList);
- 'REAL' ->
- emit_enc_real(Erules, Value);
-
- {'BIT STRING',NamedNumberList} ->
- EffectiveC = effective_constraint(bitstring,Constraint),
- case EffectiveC of
- 0 ->
- emit({"[]"});
- _ ->
- call(Erules, encode_bit_string,
- [{asis,EffectiveC},Value,
- {asis,NamedNumberList}])
- end;
- 'NULL' ->
- emit("[]");
- 'OBJECT IDENTIFIER' ->
- call(Erules, encode_object_identifier, [Value]);
- 'RELATIVE-OID' ->
- call(Erules, encode_relative_oid, [Value]);
- 'ObjectDescriptor' ->
- call(Erules, encode_ObjectDescriptor,
- [{asis,Constraint},Value]);
- 'BOOLEAN' ->
- emit({"case ",Value," of",nl,
- " true -> [1];",nl,
- " false -> [0];",nl,
- " _ -> exit({error,{asn1,{encode_boolean,",Value,"}}})",nl,
- "end"});
- 'OCTET STRING' ->
- emit_enc_octet_string(Erules,Constraint,Value);
-
- 'NumericString' ->
- emit_enc_known_multiplier_string('NumericString',Constraint,Value);
- TString when TString == 'TeletexString';
- TString == 'T61String' ->
- call(Erules, encode_TeletexString, [{asis,Constraint},Value]);
- 'VideotexString' ->
- 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' ->
- call(Erules, encode_GraphicString, [{asis,Constraint},Value]);
- 'VisibleString' ->
- emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
- 'GeneralString' ->
- call(Erules, encode_GeneralString, [{asis,Constraint},Value]);
- 'PrintableString' ->
- emit_enc_known_multiplier_string('PrintableString',Constraint,Value);
- 'IA5String' ->
- emit_enc_known_multiplier_string('IA5String',Constraint,Value);
- 'BMPString' ->
- emit_enc_known_multiplier_string('BMPString',Constraint,Value);
- 'UniversalString' ->
- emit_enc_known_multiplier_string('UniversalString',Constraint,Value);
- 'UTF8String' ->
- call(Erules, encode_UTF8String, [Value]);
- 'ASN1_OPEN_TYPE' ->
- NewValue = case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- 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(
- "complete(enc_~s(~s))",
- [Tname,Value]);
- _ ->
- io_lib:format("iolist_to_binary(~s)",
- [Value])
- end,
- 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 = effective_constraint(bitstring, C),
- PAlphabC = get_constraint(C,'PermittedAlphabet'),
- case {StringType,PAlphabC} of
- {'UniversalString',{_,_}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with "
- "PermittedAlphabet constraint"}}});
- {'BMPString',{_,_}} ->
- exit({error,{asn1,{'not implemented',"BMPString with "
- "PermittedAlphabet constraint"}}});
- _ -> ok
- end,
- NumBits = get_NumBits(C,StringType),
- CharOutTab = get_CharOutTab(C,StringType),
- %% NunBits and CharOutTab for chars_encode
- emit_enc_k_m_string(SizeC, NumBits, CharOutTab, Value).
-
-emit_enc_k_m_string(0, _NumBits, _CharOutTab, _Value) ->
- emit({"[]"});
-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) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- 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);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C, StringType, hd(Chars),
- lists:max(Chars), Chars);
- 'NumericString' ->
- get_CharTab2(C, 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)].
-
-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.
-
-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).
-
-%% copied from run time module
-
-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(" end");
- 2 ->
- asn1ct_name:new(tmpval),
- 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),
- 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),
- 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 ->
- call(Erules, encode_octet_string,
- [{asis,C},Value])
- end.
-
-emit_enc_integer_case(Value) ->
- case get(component_type) of
- {true,#'ComponentType'{prop=Prop}} ->
- emit({" begin",nl}),
- case Prop of
- Opt when Opt=='OPTIONAL';
- is_tuple(Opt),element(1,Opt)=='DEFAULT' ->
- emit({" case ",Value," of",nl}),
- ok;
- _ ->
- emit({" ",{curr,tmpval},"=",Value,",",nl}),
- emit({" case ",{curr,tmpval}," of",nl}),
- asn1ct_name:new(tmpval)
- end;
-% asn1ct_name:new(tmpval);
- _ ->
- emit({" case ",Value," of ",nl})
- end.
-emit_enc_integer_end_case() ->
- case get(component_type) of
- {true,_} ->
- emit({nl," end"}); % end of begin ... end
- _ -> ok
- end.
-
-
-emit_enc_integer_NNL(Erules,C,Value,NNL) ->
- EncVal = enc_integer_NNL_cases(Value,NNL),
- emit_enc_integer(Erules,C,EncVal).
-
-enc_integer_NNL_cases(Value,NNL) ->
- asn1ct_name:new(tmpval),
- TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- Cases=enc_integer_NNL_cases1(NNL),
- lists:flatten(io_lib:format("(case ~s of "++Cases++
- "~s when is_atom(~s)->exit({error,{asn1,{namednumber,~s}}});_->~s end)",[Value,TmpVal,TmpVal,TmpVal,Value])).
-
-enc_integer_NNL_cases1([{NNo,No}|Rest]) ->
- io_lib:format("~w->~w;",[NNo,No])++enc_integer_NNL_cases1(Rest);
-enc_integer_NNL_cases1([]) ->
- "".
-
-emit_enc_integer(_Erule,[{'SingleValue',Int}],Value) ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),% emit([" case ",Value," of",nl]),
- emit([" ",Int," -> [];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer(_Erule,[{_,{Lb,Ub},_Range,{bits,NoBs}}],Value) -> % Range =< 255
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [10,",NoBs,",",{curr,tmpval},"- ",Lb,"];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",
- {curr,tmpval},"}})",nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer(_Erule,[{_,{Lb,Ub},Range,_}],Value) when Range =< 256 ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [20,1,",{curr,tmpval},"- ",Lb,"];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer(_Erule,[{_,{Lb,Ub},Range,_}],Value) when Range =< 65536 ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [20,2,<<(",{curr,tmpval},"- ",Lb,"):16>>];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- 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) ->
- call(Erule, encode_integer, [{asis,C},Value]).
-
-
-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.
-
-%% 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) ->
- pre_encode(integer, asn1ct_imm:effective_constraint(integer, C));
-effective_constraint(bitstring,C) ->
- asn1ct_imm:effective_constraint(bitstring, C).
-
-pre_encode(integer,[]) ->
- [];
-pre_encode(integer,C=[{'SingleValue',_}]) ->
- C;
-pre_encode(integer,C=[{'ValueRange',VR={Lb,Ub}}]) when is_integer(Lb),is_integer(Ub)->
- Range = Ub-Lb+1,
- if
- Range =< 255 ->
- NoBits = no_bits(Range),
- [{'ValueRange',VR,Range,{bits,NoBits}}];
- Range =< 256 ->
- [{'ValueRange',VR,Range,{octets,1}}];
- Range =< 65536 ->
- [{'ValueRange',VR,Range,{octets,2}}];
- true ->
- C
- end;
-pre_encode(integer,C) ->
- C.
-
-no_bits(2) -> 1;
-no_bits(N) when N=<4 -> 2;
-no_bits(N) when N=<8 -> 3;
-no_bits(N) when N=<16 -> 4;
-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.
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index bf362db843..bdd14871d1 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -26,6 +26,20 @@
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([per_enc_bit_string/4,per_enc_legacy_bit_string/4,
+ per_enc_boolean/2,
+ per_enc_choice/3,per_enc_enumerated/3,
+ per_enc_integer/3,per_enc_integer/4,
+ per_enc_null/2,
+ per_enc_k_m_string/4,per_enc_octet_string/3,
+ per_enc_legacy_octet_string/3,
+ per_enc_open_type/2,
+ per_enc_restricted_string/3,
+ per_enc_small_number/2]).
+-export([per_enc_extension_bit/2,per_enc_extensions/4,per_enc_optional/3]).
+-export([per_enc_sof/5]).
+-export([enc_absent/3,enc_append/1,enc_element/2]).
+-export([enc_cg/2]).
-export([optimize_alignment/1,optimize_alignment/2,
dec_slim_cg/2,dec_code_gen/2]).
-export([effective_constraint/2]).
@@ -68,15 +82,8 @@ 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}.
+ NamedList = per_dec_enumerated_fix_list(NamedList0, [enum_error], 0),
+ {map,Int,opt_map(NamedList, Int)}.
per_dec_enumerated(BaseNamedList, NamedListExt0, Aligned) ->
Base = per_dec_enumerated(BaseNamedList, Aligned),
@@ -110,34 +117,23 @@ per_dec_length(no, 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}.
+ {map,Int,opt_map(NamedList, Int)}.
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),
+ Imm = dec_string(SzConstr, N, Aligned, k_m_string),
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).
+ dec_string(Constraint, 8, Aligned, 'OCTET STRING').
per_dec_raw_bitstring(Constraint, Aligned) ->
- dec_string(Constraint, 1, Aligned,
- fun(Sv, Sv) -> Sv > 16;
- (_, _) -> true
- end).
+ dec_string(Constraint, 1, Aligned, 'BIT STRING').
per_dec_open_type(Aligned) ->
- {get_bits,decode_unconstrained_length(true, Aligned),
- [8,binary,{align,Aligned}]}.
+ dec_string(no, 8, Aligned, open_type).
per_dec_real(Aligned) ->
Dec = fun(V, Buf) ->
@@ -152,26 +148,332 @@ per_dec_restricted_string(Aligned) ->
DecLen = decode_unconstrained_length(true, Aligned),
{get_bits,DecLen,[8,binary]}.
+%%%
+%%% Encoding.
+%%%
+
+per_enc_bit_string(Val, [], Constraint0, Aligned) ->
+ {B,[[],Bits]} = mk_vars([], [bits]),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ B ++ [{call,erlang,bit_size,[Val],Bits}|
+ per_enc_length(Val, 1, Bits, Constraint, Aligned, 'BIT STRING')];
+per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) ->
+ {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]),
+ NNL = lists:keysort(2, NNL0),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ ExtraArgs = case constr_min_size(Constraint) of
+ no -> [];
+ Lb -> [Lb]
+ end,
+ ToBs = case ExtraArgs of
+ [] ->
+ {call,per_common,bs_drop_trailing_zeroes,[Val]};
+ [0] ->
+ {call,per_common,bs_drop_trailing_zeroes,[Val]};
+ [Lower] ->
+ {call,per_common,adjust_trailing_zeroes,[Val,Lower]}
+ end,
+ B ++ [{'try',
+ [bit_string_name2pos_fun(NNL, Val)],
+ {Positions,
+ [{call,per_common,bitstring_from_positions,
+ [Positions|ExtraArgs]}]},
+ [ToBs],Bs},
+ {call,erlang,bit_size,[Bs],Bits}|
+ per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')].
+
+per_enc_legacy_bit_string(Val0, [], Constraint0, Aligned) ->
+ {B,[Val,Bs,Bits]} = mk_vars(Val0, [bs,bits]),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ ExtraArgs = case constr_min_size(Constraint) of
+ no -> [];
+ Lb -> [Lb]
+ end,
+ B ++ [{call,per_common,to_bitstring,[Val|ExtraArgs],Bs},
+ {call,erlang,bit_size,[Bs],Bits}|
+ per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')];
+per_enc_legacy_bit_string(Val0, NNL0, Constraint0, Aligned) ->
+ {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]),
+ NNL = lists:keysort(2, NNL0),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ ExtraArgs = case constr_min_size(Constraint) of
+ no -> [];
+ 0 -> [];
+ Lb -> [Lb]
+ end,
+ B ++ [{'try',
+ [bit_string_name2pos_fun(NNL, Val)],
+ {Positions,
+ [{call,per_common,bitstring_from_positions,
+ [Positions|ExtraArgs]}]},
+ [{call,per_common,to_named_bitstring,[Val|ExtraArgs]}],Bs},
+ {call,erlang,bit_size,[Bs],Bits}|
+ per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')].
+
+per_enc_boolean(Val0, _Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ B++build_cond([[{eq,Val,false},{put_bits,0,1,[1]}],
+ [{eq,Val,true},{put_bits,1,1,[1]}]]).
+
+per_enc_choice(Val0, Cs0, _Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ Cs = [[{eq,Val,Tag}|opt_choice(Imm)] || {Tag,Imm} <- Cs0],
+ B++build_cond(Cs).
+
+per_enc_enumerated(Val0, {Root,Ext}, Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ Constr = enumerated_constraint(Root),
+ RootCs = per_enc_enumerated_root(Root, [{put_bits,0,1,[1]}],
+ Val, Constr, Aligned),
+ ExtCs = per_enc_enumerated_ext(Ext, Val, Aligned),
+ B++[{'cond',RootCs++ExtCs++enumerated_error(Val)}];
+per_enc_enumerated(Val0, Root, Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ Constr = enumerated_constraint(Root),
+ Cs = per_enc_enumerated_root(Root, [], Val, Constr, Aligned),
+ B++[{'cond',Cs++enumerated_error(Val)}].
+
+enumerated_error(Val) ->
+ [['_',{error,Val}]].
+
+per_enc_integer(Val0, Constraint0, Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ Constraint = effective_constraint(integer, Constraint0),
+ B ++ per_enc_integer_1(Val, Constraint, Aligned).
+
+per_enc_integer(Val0, NNL, Constraint0, Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ Constraint = effective_constraint(integer, Constraint0),
+ Cs = [[{eq,Val,N}|per_enc_integer_1(V, Constraint, Aligned)] ||
+ {N,V} <- NNL],
+ case per_enc_integer_1(Val, Constraint, Aligned) of
+ [{'cond',IntCs}] ->
+ B ++ [{'cond',Cs++IntCs}];
+ Other ->
+ B ++ [{'cond',Cs++[['_'|Other]]}]
+ end.
+
+per_enc_null(_Val, _Aligned) ->
+ [].
+
+per_enc_k_m_string(Val0, StringType, Constraint, Aligned) ->
+ {B,[Val,Bin,Len]} = mk_vars(Val0, [bin,len]),
+ SzConstraint = effective_constraint(bitstring, Constraint),
+ Unit = string_num_bits(StringType, Constraint, Aligned),
+ Chars0 = char_tab(Constraint, StringType, Unit),
+ Enc = case Unit of
+ 16 ->
+ {call,per_common,encode_chars_16bit,[Val],Bin};
+ 32 ->
+ {call,per_common,encode_big_chars,[Val],Bin};
+ 8 ->
+ {call,erlang,list_to_binary,[Val],Bin};
+ _ ->
+ case enc_char_tab(Chars0) of
+ notab ->
+ {call,per_common,encode_chars,[Val,Unit],Bin};
+ {tab,Tab} ->
+ {call,per_common,encode_chars,[Val,Unit,Tab],Bin};
+ {compact_map,Map} ->
+ {call,per_common,encode_chars_compact_map,
+ [Val,Unit,Map],Bin}
+ end
+ end,
+ case Unit of
+ 8 ->
+ B ++ [Enc,{call,erlang,byte_size,[Bin],Len}];
+ _ ->
+ B ++ [{call,erlang,length,[Val],Len},Enc]
+ end ++ per_enc_length(Bin, Unit, Len, SzConstraint, Aligned, k_m_string).
+
+per_enc_open_type(Imm0, Aligned) ->
+ Imm = case Aligned of
+ true ->
+ %% Temporarily make the implicit 'align' done by
+ %% complete/1 explicit to facilitate later
+ %% optimizations: the absence of 'align' can be used
+ %% as an indication that complete/1 can be replaced
+ %% with a cheaper operation such as
+ %% iolist_to_binary/1. The redundant 'align' will be
+ %% optimized away later.
+ Imm0 ++ [{put_bits,0,0,[1,align]}];
+ false ->
+ Imm0
+ end,
+ {[],[[],Val,Len,Bin]} = mk_vars([], [output,len,bin]),
+ [{list,Imm,Val},
+ {call,enc_mod(Aligned),complete,[Val],Bin},
+ {call,erlang,byte_size,[Bin],Len}|
+ per_enc_length(Bin, 8, Len, Aligned)].
+
+per_enc_octet_string(Bin, Constraint0, Aligned) ->
+ {B,[[],Len]} = mk_vars([], [len]),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ B ++ [{call,erlang,byte_size,[Bin],Len}|
+ per_enc_length(Bin, 8, Len, Constraint, Aligned, 'OCTET STRING')].
+
+per_enc_legacy_octet_string(Val0, Constraint0, Aligned) ->
+ {B,[Val,Bin,Len]} = mk_vars(Val0, [bin,len]),
+ Constraint = effective_constraint(bitstring, Constraint0),
+ B ++ [{call,erlang,iolist_to_binary,[Val],Bin},
+ {call,erlang,byte_size,[Bin],Len}|
+ per_enc_length(Bin, 8, Len, Constraint, Aligned, 'OCTET STRING')].
+
+per_enc_restricted_string(Val0, {M,F}, Aligned) ->
+ {B,[Val,Bin,Len]} = mk_vars(Val0, [bin,len]),
+ B ++ [{call,M,F,[Val],Bin},
+ {call,erlang,byte_size,[Bin],Len}|
+ per_enc_length(Bin, 8, Len, Aligned)].
+
+per_enc_small_number(Val, Aligned) ->
+ build_cond([[{lt,Val,64},{put_bits,Val,7,[1]}],
+ ['_',{put_bits,1,1,[1]}|
+ per_enc_unsigned(Val, Aligned)]]).
+
+per_enc_extension_bit(Val0, _Aligned) ->
+ {B,[Val]} = mk_vars(Val0, []),
+ B++build_cond([[{eq,Val,[]},{put_bits,0,1,[1]}],
+ ['_',{put_bits,1,1,[1]}]]).
+
+per_enc_extensions(Val0, Pos0, NumBits, Aligned) when NumBits > 0 ->
+ Pos = Pos0 + 1,
+ {B,[Val,Bitmap]} = mk_vars(Val0, [bitmap]),
+ Length = per_enc_small_length(NumBits, Aligned),
+ PutBits = case NumBits of
+ 1 -> [{put_bits,1,1,[1]}];
+ _ -> [{put_bits,Bitmap,NumBits,[1]}]
+ end,
+ B++[{call,per_common,extension_bitmap,[Val,Pos,Pos+NumBits],Bitmap},
+ {list,[{'cond',[[{eq,Bitmap,0}],
+ ['_'|Length ++ PutBits]]}],
+ {var,"Extensions"}}].
+
+per_enc_optional(Val0, {Pos,DefVals}, _Aligned) when is_integer(Pos),
+ is_list(DefVals) ->
+ {B,Val} = enc_element(Pos, Val0),
+ Zero = {put_bits,0,1,[1]},
+ One = {put_bits,1,1,[1]},
+ B++[{'cond',
+ [[{eq,Val,DefVal},Zero] || DefVal <- DefVals] ++ [['_',One]]}];
+per_enc_optional(Val0, {Pos,{call,M,F,A}}, _Aligned) when is_integer(Pos) ->
+ {B,Val} = enc_element(Pos, Val0),
+ {[],[[],Tmp]} = mk_vars([], [tmp]),
+ Zero = {put_bits,0,1,[1]},
+ One = {put_bits,1,1,[1]},
+ B++[{call,M,F,[Val|A],Tmp},
+ {'cond',
+ [[{eq,Tmp,true},Zero],['_',One]]}];
+per_enc_optional(Val0, Pos, _Aligned) when is_integer(Pos) ->
+ {B,Val} = enc_element(Pos, Val0),
+ Zero = {put_bits,0,1,[1]},
+ One = {put_bits,1,1,[1]},
+ B++[{'cond',[[{eq,Val,asn1_NOVALUE},Zero],
+ ['_',One]]}].
+
+per_enc_sof(Val0, Constraint, ElementVar, ElementImm, Aligned) ->
+ {B,[Val,Len]} = mk_vars(Val0, [len]),
+ SzConstraint = effective_constraint(bitstring, Constraint),
+ LenImm = enc_length(Len, SzConstraint, Aligned),
+ Lc0 = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
+ Lc = opt_lc(Lc0, LenImm),
+ PreBlock = B ++ [{call,erlang,length,[Val],Len}],
+ case LenImm of
+ [{'cond',[[C|Action]]}] ->
+ PreBlock ++ [{'cond',[[C|Action++Lc]]}];
+ [{sub,_,_,_}=Sub,{'cond',[[C|Action]]}] ->
+ PreBlock ++
+ [Sub,{'cond',[[C|Action++Lc]]}];
+ EncLen ->
+ PreBlock ++ EncLen ++ Lc
+ end.
+
+enc_absent(Val0, {call,M,F,A}, Body) ->
+ {B,[Var,Tmp]} = mk_vars(Val0, [tmp]),
+ B++[{call,M,F,[Var|A],Tmp},
+ {'cond',
+ [[{eq,Tmp,true}],['_'|Body]]}];
+enc_absent(Val0, AbsVals, Body) when is_list(AbsVals) ->
+ {B,[Var]} = mk_vars(Val0, []),
+ Cs = [[{eq,Var,Aval}] || Aval <- AbsVals] ++ [['_'|Body]],
+ B++build_cond(Cs).
+
+enc_append([[]|T]) ->
+ enc_append(T);
+enc_append([[{put_bits,_,_,_}|_]=Pb|[Imm|T]=T0]) ->
+ case opt_choice(Pb++Imm) of
+ [{put_bits,_,_,_}|_] ->
+ [{block,Pb}|enc_append(T0)];
+ Opt ->
+ enc_append([Opt|T])
+ end;
+enc_append([Imm0|[Imm1|T]=T0]) ->
+ try combine_imms(Imm0, Imm1) of
+ Imm ->
+ enc_append([Imm|T])
+ catch
+ throw:impossible ->
+ [{block,Imm0}|enc_append(T0)]
+ end;
+enc_append([H|T]) ->
+ [{block,H}|enc_append(T)];
+enc_append([]) -> [].
+
+enc_element(N, Val0) ->
+ {[],[Val,Dst]} = mk_vars(Val0, [element]),
+ {[{call,erlang,element,[N,Val],Dst}],Dst}.
+
+enc_cg(Imm0, false) ->
+ Imm1 = enc_cse(Imm0),
+ Imm2 = enc_pre_cg(Imm1),
+ Imm = enc_opt(Imm2),
+ enc_cg(Imm);
+enc_cg(Imm0, true) ->
+ Imm1 = enc_cse(Imm0),
+ Imm2 = enc_hoist_align(Imm1),
+ Imm3 = enc_opt_al(Imm2),
+ Imm4 = per_fixup(Imm3),
+ Imm5 = enc_pre_cg(Imm4),
+ Imm = enc_opt(Imm5),
+ enc_cg(Imm).
%%%
%%% Local functions.
%%%
-dec_string(Sv, U, Aligned0, AF) when is_integer(Sv) ->
+%% is_aligned(StringType, LowerBound, UpperBound) -> boolean()
+%% StringType = 'OCTET STRING' | 'BIT STRING' | k_m_string
+%% LowerBound = UpperBound = number of bits
+%% Determine whether a string should be aligned in PER.
+
+is_aligned(T, Lb, Ub) when T =:= 'OCTET STRING'; T =:= 'BIT STRING' ->
+ %% OCTET STRINGs and BIT STRINGs are aligned to a byte boundary
+ %% unless the size is fixed and less than or equal to 16 bits.
+ Lb =/= Ub orelse Lb > 16;
+is_aligned(k_m_string, _Lb, Ub) ->
+ %% 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.
+ Ub >= 16.
+
+%%%
+%%% Generating the intermediate format format for decoding.
+%%%
+
+dec_string(Sv, U, Aligned0, T) when is_integer(Sv) ->
Bits = U*Sv,
- Aligned = Aligned0 andalso AF(Bits, Bits),
+ Aligned = Aligned0 andalso is_aligned(T, 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) ->
+dec_string({{Sv,Sv},[]}, U, Aligned, T) ->
+ bit_case(dec_string(Sv, U, Aligned, T),
+ dec_string(no, U, Aligned, T));
+dec_string({{_,_}=C,[]}, U, Aligned, T) ->
+ bit_case(dec_string(C, U, Aligned, T),
+ dec_string(no, U, Aligned, T));
+dec_string({Lb,Ub}, U, Aligned0, T) ->
Len = per_dec_constrained(Lb, Ub, Aligned0),
- Aligned = Aligned0 andalso AF(Lb*U, Ub*U),
+ Aligned = Aligned0 andalso is_aligned(T, Lb*U, Ub*U),
{get_bits,Len,[U,binary,{align,Aligned}]};
-dec_string(_, U, Aligned, _AF) ->
+dec_string(_, U, Aligned, _T) ->
Al = [{align,Aligned}],
DecRest = fun(V, Buf) ->
asn1ct_func:call(per_common,
@@ -279,14 +581,42 @@ per_num_bits(N) when N =< 64 -> 6;
per_num_bits(N) when N =< 128 -> 7;
per_num_bits(N) when N =< 255 -> 8.
+opt_map(Map, Imm) ->
+ case matched_range(Imm) of
+ unknown -> Map;
+ {Lb,Ub} -> opt_map_1(Map, Lb, Ub)
+ end.
+
+opt_map_1([{I,_}=Pair|T], Lb, Ub) ->
+ if
+ I =:= Lb, I =< Ub ->
+ [Pair|opt_map_1(T, Lb+1, Ub)];
+ Lb < I, I =< Ub ->
+ [Pair|opt_map_1(T, Lb, Ub)];
+ true ->
+ opt_map_1(T, Lb, Ub)
+ end;
+opt_map_1(Map, Lb, Ub) ->
+ if
+ Lb =< Ub ->
+ Map;
+ true ->
+ []
+ end.
+
matched_range({get_bits,Bits0,[U|Flags]}) when is_integer(U) ->
- case lists:member(signed, Flags) of
- false ->
+ case not lists:member(signed, Flags) andalso is_integer(Bits0) of
+ true ->
Bits = U*Bits0,
{0,(1 bsl Bits) - 1};
- true ->
+ false ->
unknown
end;
+matched_range({add,Imm,Add}) ->
+ case matched_range(Imm) of
+ unknown -> unknown;
+ {Lb,Ub} -> {Lb+Add,Ub+Add}
+ end;
matched_range(_Op) -> unknown.
string_num_bits(StringType, Constraint, Aligned) ->
@@ -608,6 +938,9 @@ 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,{M,F},V,Dst}|T]) ->
+ emit([Dst," = ",{asis,M},":",{asis,F},"(",V,")"]),
+ iter_dcg_list_outside(T);
dcg_list_outside([{convert,Op,V,Dst}|T]) ->
emit([Dst," = ",Op,"(",V,")"]),
iter_dcg_list_outside(T);
@@ -692,6 +1025,1688 @@ mk_dest(I) when is_integer(I) ->
integer_to_list(I);
mk_dest(S) -> S.
+%%%
+%%% Constructing the intermediate format for encoding.
+%%%
+
+split_off_nonbuilding(Imm) ->
+ lists:splitwith(fun is_nonbuilding/1, Imm).
+
+is_nonbuilding({assign,_,_}) -> true;
+is_nonbuilding({call,_,_,_,_}) -> true;
+is_nonbuilding({lc,_,_,_,_}) -> true;
+is_nonbuilding({set,_,_}) -> true;
+is_nonbuilding({list,_,_}) -> true;
+is_nonbuilding({sub,_,_,_}) -> true;
+is_nonbuilding({'try',_,_,_,_}) -> true;
+is_nonbuilding(_) -> false.
+
+mk_vars(Input0, Temps) ->
+ asn1ct_name:new(enc),
+ Curr = asn1ct_name:curr(enc),
+ [H|T] = atom_to_list(Curr),
+ Base = [H - ($a - $A)|T ++ "@"],
+ case Input0 of
+ {var,Name} when is_list(Name) ->
+ {[],[Input0|mk_vars_1(Base, Temps)]};
+ [] ->
+ {[],[Input0|mk_vars_1(Base, Temps)]};
+ _ when is_integer(Input0) ->
+ {[],[Input0|mk_vars_1(Base, Temps)]}
+ end.
+
+mk_vars_1(Base, Vars) ->
+ [mk_var(Base, V) || V <- Vars].
+
+mk_var(Base, V) ->
+ {var,Base ++ atom_to_list(V)}.
+
+per_enc_integer_1(Val, [], Aligned) ->
+ [{'cond',[['_'|per_enc_unconstrained(Val, Aligned)]]}];
+per_enc_integer_1(Val, [{{'SingleValue',[_|_]=Svs}=Constr,[]}], Aligned) ->
+ %% An extensible constraint such as (1|17, ...).
+ %%
+ %% A subtle detail is that the extension root as described in the
+ %% ASN.1 spec should be used to determine whether a particular value
+ %% belongs to the extension root (as opposed to the effective
+ %% constraint, which will be used for the actual encoding).
+ %%
+ %% So for the example above, only the integers 1 and 17 should be
+ %% encoded as root values (extension bit = 0).
+
+ [{'ValueRange',{Lb,Ub}}] = effective_constraint(integer, [Constr]),
+ Root = [begin
+ {[],_,Put} = per_enc_constrained(Sv, Lb, Ub, Aligned),
+ [{eq,Val,Sv},{put_bits,0,1,[1]}|Put]
+ end || Sv <- Svs],
+ Cs = Root ++ [['_',{put_bits,1,1,[1]}|
+ per_enc_unconstrained(Val, Aligned)]],
+ build_cond(Cs);
+per_enc_integer_1(Val0, [{{_,_}=Constr,[]}], Aligned) ->
+ {Prefix,Check,Action} = per_enc_integer_2(Val0, Constr, Aligned),
+ Prefix++build_cond([[Check,{put_bits,0,1,[1]}|Action],
+ ['_',{put_bits,1,1,[1]}|
+ per_enc_unconstrained(Val0, Aligned)]]);
+per_enc_integer_1(Val0, [Constr], Aligned) ->
+ {Prefix,Check,Action} = per_enc_integer_2(Val0, Constr, Aligned),
+ Prefix++build_cond([[Check|Action],
+ ['_',{error,Val0}]]).
+
+per_enc_integer_2(Val, {'SingleValue',Sv}, Aligned) when is_integer(Sv) ->
+ per_enc_constrained(Val, Sv, Sv, Aligned);
+per_enc_integer_2(Val0, {'ValueRange',{Lb,'MAX'}}, Aligned)
+ when is_integer(Lb) ->
+ {Prefix,Val} = sub_lb(Val0, Lb),
+ {Prefix,{ge,Val,0},per_enc_unsigned(Val, Aligned)};
+per_enc_integer_2(Val, {'ValueRange',{Lb,Ub}}, Aligned)
+ when is_integer(Lb), is_integer(Ub) ->
+ per_enc_constrained(Val, Lb, Ub, Aligned).
+
+per_enc_constrained(Val, Sv, Sv, _Aligned) ->
+ {[],{eq,Val,Sv},[]};
+per_enc_constrained(Val0, Lb, Ub, false) ->
+ {Prefix,Val} = sub_lb(Val0, Lb),
+ Range = Ub - Lb + 1,
+ NumBits = uper_num_bits(Range),
+ Check = {ult,Val,Range},
+ Put = [{put_bits,Val,NumBits,[1]}],
+ {Prefix,Check,Put};
+per_enc_constrained(Val0, Lb, Ub, true) ->
+ {Prefix,Val} = sub_lb(Val0, Lb),
+ Range = Ub - Lb + 1,
+ if
+ Range < 256 ->
+ NumBits = per_num_bits(Range),
+ Check = {ult,Val,Range},
+ Put = [{put_bits,Val,NumBits,[1]}],
+ {Prefix,Check,Put};
+ Range =:= 256 ->
+ NumBits = 8,
+ Check = {ult,Val,Range},
+ Put = [{put_bits,Val,NumBits,[1,align]}],
+ {Prefix,Check,Put};
+ Range =< 65536 ->
+ Check = {ult,Val,Range},
+ Put = [{put_bits,Val,16,[1,align]}],
+ {Prefix,Check,Put};
+ true ->
+ {var,VarBase} = Val,
+ Bin = {var,VarBase++"@bin"},
+ BinSize0 = {var,VarBase++"@bin_size0"},
+ BinSize = {var,VarBase++"@bin_size"},
+ Check = {ult,Val,Range},
+ RangeOctsLen = byte_size(binary:encode_unsigned(Range - 1)),
+ BitsNeeded = per_num_bits(RangeOctsLen),
+ Enc = [{call,binary,encode_unsigned,[Val],Bin},
+ {call,erlang,byte_size,[Bin],BinSize0},
+ {sub,BinSize0,1,BinSize},
+ {'cond',[['_',
+ {put_bits,BinSize,BitsNeeded,[1]},
+ {put_bits,Bin,binary,[8,align]}]]}],
+ {Prefix,Check,Enc}
+ end.
+
+per_enc_unconstrained(Val, Aligned) ->
+ case Aligned of
+ false -> [];
+ true -> [{put_bits,0,0,[1,align]}]
+ end ++ [{call,per_common,encode_unconstrained_number,[Val]}].
+
+per_enc_unsigned(Val, Aligned) ->
+ case is_integer(Val) of
+ false ->
+ {var,VarBase} = Val,
+ Bin = {var,VarBase++"@bin"},
+ BinSize = {var,VarBase++"@bin_size"},
+ [{call,binary,encode_unsigned,[Val],Bin},
+ {call,erlang,byte_size,[Bin],BinSize}|
+ per_enc_length(Bin, 8, BinSize, Aligned)];
+ true ->
+ Bin = binary:encode_unsigned(Val),
+ Len = byte_size(Bin),
+ per_enc_length(Bin, 8, Len, Aligned)
+ end.
+
+%% Encode a length field without any constraint.
+per_enc_length(Bin, Unit, Len, Aligned) ->
+ U = unit(1, Aligned),
+ PutBits = put_bits_binary(Bin, Unit, Aligned),
+ EncFragmented = {call,per_common,encode_fragmented,[Bin,Unit]},
+ Al = case Aligned of
+ false -> [];
+ true -> [{put_bits,0,0,[1,align]}]
+ end,
+ build_cond([[{lt,Len,128},
+ {put_bits,Len,8,U},PutBits],
+ [{lt,Len,16384},
+ {put_bits,2,2,U},{put_bits,Len,14,[1]},PutBits],
+ ['_'|Al++[EncFragmented]]]).
+
+per_enc_length(Bin, Unit, Len, no, Aligned, _Type) ->
+ per_enc_length(Bin, Unit, Len, Aligned);
+per_enc_length(Bin, Unit, Len, {{Lb,Ub},[]}, Aligned, Type) ->
+ {Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
+ NoExt = {put_bits,0,1,[1]},
+ U = unit(Unit, Aligned, Type, Lb*Unit, Ub*Unit),
+ PutBits = [{put_bits,Bin,binary,U}],
+ [{'cond',ExtConds0}] = per_enc_length(Bin, Unit, Len, Aligned),
+ Ext = {put_bits,1,1,[1]},
+ ExtConds = prepend_to_cond(ExtConds0, Ext),
+ build_length_cond(Prefix, [[Check,NoExt|PutLen++PutBits]|ExtConds]);
+per_enc_length(Bin, Unit, Len, {Lb,Ub}, Aligned, Type)
+ when is_integer(Lb) ->
+ {Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
+ U = unit(Unit, Aligned, Type, Lb*Unit, Ub*Unit),
+ PutBits = [{put_bits,Bin,binary,U}],
+ build_length_cond(Prefix, [[Check|PutLen++PutBits]]);
+per_enc_length(Bin, Unit0, Len, Sv, Aligned, Type) when is_integer(Sv) ->
+ NumBits = Sv*Unit0,
+ Unit = case NumBits rem 8 of
+ 0 ->
+ %% Help out the alignment optimizer.
+ 8;
+ _ ->
+ Unit0
+ end,
+ U = unit(Unit, Aligned, Type, NumBits, NumBits),
+ Pb = {put_bits,Bin,binary,U},
+ [{'cond',[[{eq,Len,Sv},Pb]]}].
+
+enc_length(Len, no, Aligned) ->
+ U = unit(1, Aligned),
+ build_cond([[{lt,Len,128},
+ {put_bits,Len,8,U}],
+ [{lt,Len,16384},
+ {put_bits,2,2,U},{put_bits,Len,14,[1]}]]);
+enc_length(Len, {{Lb,Ub},[]}, Aligned) ->
+ {Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
+ NoExt = {put_bits,0,1,[1]},
+ [{'cond',ExtConds0}] = enc_length(Len, no, Aligned),
+ Ext = {put_bits,1,1,[1]},
+ ExtConds = prepend_to_cond(ExtConds0, Ext),
+ build_length_cond(Prefix, [[Check,NoExt|PutLen]|ExtConds]);
+enc_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) ->
+ {Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
+ build_length_cond(Prefix, [[Check|PutLen]]);
+enc_length(Len, Sv, _Aligned) when is_integer(Sv) ->
+ [{'cond',[[{eq,Len,Sv}]]}].
+
+put_bits_binary(Bin, _Unit, Aligned) when is_binary(Bin) ->
+ Sz = byte_size(Bin),
+ <<Int:Sz/unit:8>> = Bin,
+ {put_bits,Int,8*Sz,unit(1, Aligned)};
+put_bits_binary(Bin, Unit, Aligned) ->
+ {put_bits,Bin,binary,unit(Unit, Aligned)}.
+
+sub_lb(Val, 0) ->
+ {[],Val};
+sub_lb({var,Var}=Val0, Lb) ->
+ Val = {var,Var++"@sub"},
+ {[{sub,Val0,Lb,Val}],Val};
+sub_lb(Val, Lb) when is_integer(Val) ->
+ {[],Val-Lb}.
+
+build_length_cond([{sub,Var0,Base,Var}]=Prefix, Cs) ->
+ %% Non-zero lower bound, such as: SIZE (50..200, ...)
+ Prefix++[{'cond',opt_length_nzlb(Cs, {Var0,Var,Base}, 0)}];
+build_length_cond([], Cs) ->
+ %% Zero lower bound, such as: SIZE (0..200, ...)
+ [{'cond',opt_length_zlb(Cs, 0)}].
+
+opt_length_zlb([[{ult,Var,Val}|Actions]|T], Ub) ->
+ %% Since the SIZE constraint is zero-based, Var
+ %% must be greater than zero, and we can use
+ %% the slightly cheaper signed less than operator.
+ opt_length_zlb([[{lt,Var,Val}|Actions]|T], Ub);
+opt_length_zlb([[{lt,_,Val}|_]=H|T], Ub) ->
+ if
+ Val =< Ub ->
+ %% A previous test has already matched.
+ opt_length_zlb(T, Ub);
+ true ->
+ [H|opt_length_zlb(T, max(Ub, Val))]
+ end;
+opt_length_zlb([H|T], Ub) ->
+ [H|opt_length_zlb(T, Ub)];
+opt_length_zlb([], _) -> [].
+
+opt_length_nzlb([[{ult,Var,Val}|_]=H|T], {_,Var,Base}=St, _Ub) ->
+ [H|opt_length_nzlb(T, St, Base+Val)];
+opt_length_nzlb([[{lt,Var0,Val}|_]=H|T], {Var0,_,_}=St, Ub) ->
+ if
+ Val =< Ub ->
+ %% A previous test has already matched.
+ opt_length_nzlb(T, St, Ub);
+ true ->
+ [H|opt_length_nzlb(T, St, Val)]
+ end;
+opt_length_nzlb([H|T], St, Ub) ->
+ [H|opt_length_nzlb(T, St, Ub)];
+opt_length_nzlb([], _, _) -> [].
+
+build_cond(Conds0) ->
+ case eval_cond(Conds0, gb_sets:empty()) of
+ [['_'|Actions]] ->
+ Actions;
+ Conds ->
+ [{'cond',Conds}]
+ end.
+
+eval_cond([['_',{'cond',Cs}]], Seen) ->
+ eval_cond(Cs, Seen);
+eval_cond([[Cond|Actions]=H|T], Seen0) ->
+ case gb_sets:is_element(Cond, Seen0) of
+ false ->
+ Seen = gb_sets:insert(Cond, Seen0),
+ case eval_cond_1(Cond) of
+ false ->
+ eval_cond(T, Seen);
+ true ->
+ [['_'|Actions]];
+ maybe ->
+ [H|eval_cond(T, Seen)]
+ end;
+ true ->
+ eval_cond(T, Seen0)
+ end;
+eval_cond([], _) -> [].
+
+eval_cond_1({ult,I,N}) when is_integer(I), is_integer(N) ->
+ 0 =< I andalso I < N;
+eval_cond_1({eq,[],[]}) ->
+ true;
+eval_cond_1({eq,I,N}) when is_integer(I), is_integer(N) ->
+ I =:= N;
+eval_cond_1({ge,I,N}) when is_integer(I), is_integer(N) ->
+ I >= N;
+eval_cond_1({lt,I,N}) when is_integer(I), is_integer(N) ->
+ I < N;
+eval_cond_1(_) -> maybe.
+
+prepend_to_cond([H|T], Code) ->
+ [prepend_to_cond_1(H, Code)|prepend_to_cond(T, Code)];
+prepend_to_cond([], _) -> [].
+
+prepend_to_cond_1([Check|T], Code) ->
+ [Check,Code|T].
+
+enc_char_tab(notab) ->
+ notab;
+enc_char_tab(Tab0) ->
+ Tab1 = tuple_to_list(Tab0),
+ First = hd(Tab1),
+ Tab = enc_char_tab_1(Tab1, First, 0),
+ case lists:member(ill, Tab) of
+ false ->
+ {compact_map,{First,tuple_size(Tab0)}};
+ true ->
+ {tab,{First-1,list_to_tuple(Tab)}}
+ end.
+
+enc_char_tab_1([H|T], H, I) ->
+ [I|enc_char_tab_1(T, H+1, I+1)];
+enc_char_tab_1([_|_]=T, H, I) ->
+ [ill|enc_char_tab_1(T, H+1, I)];
+enc_char_tab_1([], _, _) -> [].
+
+enumerated_constraint([_]) ->
+ [{'SingleValue',0}];
+enumerated_constraint(Root) ->
+ [{'ValueRange',{0,length(Root)-1}}].
+
+per_enc_enumerated_root(NNL, Prefix, Val, Constr, Aligned) ->
+ per_enc_enumerated_root_1(NNL, Prefix, Val, Constr, Aligned, 0).
+
+per_enc_enumerated_root_1([{H,_}|T], Prefix, Val, Constr, Aligned, N) ->
+ [[{eq,Val,H}|Prefix++per_enc_integer_1(N, Constr, Aligned)]|
+ per_enc_enumerated_root_1(T, Prefix, Val, Constr, Aligned, N+1)];
+per_enc_enumerated_root_1([], _, _, _, _, _) -> [].
+
+per_enc_enumerated_ext(NNL, Val, Aligned) ->
+ per_enc_enumerated_ext_1(NNL, Val, Aligned, 0).
+
+per_enc_enumerated_ext_1([{H,_}|T], Val, Aligned, N) ->
+ [[{eq,Val,H},{put_bits,1,1,[1]}|per_enc_small_number(N, Aligned)]|
+ per_enc_enumerated_ext_1(T, Val, Aligned, N+1)];
+per_enc_enumerated_ext_1([], _, _, _) -> [].
+
+per_enc_small_length(Val0, Aligned) ->
+ {Sub,Val} = sub_lb(Val0, 1),
+ U = unit(1, Aligned),
+ Sub ++ build_cond([[{lt,Val,64},{put_bits,Val,7,[1]}],
+ [{lt,Val0,128},{put_bits,1,1,[1]},
+ {put_bits,Val0,8,U}],
+ ['_',{put_bits,1,1,[1]},
+ {put_bits,2,2,U},{put_bits,Val0,14,[1]}]]).
+
+constr_min_size(no) -> no;
+constr_min_size({{Lb,_},[]}) when is_integer(Lb) -> Lb;
+constr_min_size({Lb,_}) when is_integer(Lb) -> Lb;
+constr_min_size(Sv) when is_integer(Sv) -> Sv.
+
+enc_mod(false) -> uper;
+enc_mod(true) -> per.
+
+unit(U, false) -> [U];
+unit(U, true) -> [U,align].
+
+unit(U, Aligned, Type, Lb, Ub) ->
+ case Aligned andalso is_aligned(Type, Lb, Ub) of
+ true -> [U,align];
+ false -> [U]
+ end.
+
+opt_choice(Imm) ->
+ {Pb,T0} = lists:splitwith(fun({put_bits,V,_,_}) when is_integer(V) ->
+ true;
+ (_) ->
+ false
+ end, Imm),
+ try
+ {Prefix,T} = split_off_nonbuilding(T0),
+ Prefix ++ opt_choice_1(T, Pb)
+ catch
+ throw:impossible ->
+ Imm
+ end.
+
+opt_choice_1([{'cond',Cs0}], Pb) ->
+ case Cs0 of
+ [[C|Act]] ->
+ [{'cond',[[C|Pb++Act]]}];
+ [[C|Act],['_',{error,_}]=Error] ->
+ [{'cond',[[C|Pb++Act],Error]}];
+ _ ->
+ [{'cond',opt_choice_2(Cs0, Pb)}]
+ end;
+opt_choice_1(_, _) -> throw(impossible).
+
+opt_choice_2([[C|[{put_bits,_,_,_}|_]=Act]|T], Pb) ->
+ [[C|Pb++Act]|opt_choice_2(T, Pb)];
+opt_choice_2([[_,{error,_}]=H|T], Pb) ->
+ [H|opt_choice_2(T, Pb)];
+opt_choice_2([_|_], _) ->
+ throw(impossible);
+opt_choice_2([], _) -> [].
+
+%%%
+%%% Optimize list comprehensions (SEQUENCE OF/SET OF).
+%%%
+
+opt_lc([{lc,[{call,erlang,iolist_to_binary,[Var],Bin},
+ {call,erlang,byte_size,[Bin],LenVar},
+ {'cond',[[{eq,LenVar,Len},{put_bits,Bin,_,[_|Align]}]]}],
+ Var,Val}]=Lc, LenImm) ->
+ %% Given a sequence of a fixed length string, such as
+ %% SEQUENCE OF OCTET STRING (SIZE (4)), attempt to rewrite to
+ %% a list comprehension that just checks the size, followed by
+ %% a conversion to binary:
+ %%
+ %% _ = [if length(Comp) =:= 4; byte_size(Comp) =:= 4 -> [] end ||
+ %% Comp <- Sof],
+ %% [align|iolist_to_binary(Sof)]
+
+ CheckImm = [{'cond',[[{eq,{expr,"length("++mk_val(Var)++")"},Len}],
+ [{eq,{expr,"byte_size("++mk_val(Var)++")"},Len}]]}],
+ Al = case Align of
+ [] ->
+ [];
+ [align] ->
+ [{put_bits,0,0,[1|Align]}]
+ end,
+ case Al =:= [] orelse
+ is_end_aligned(LenImm) orelse
+ lb_is_nonzero(LenImm) of
+ false ->
+ %% Not possible because an empty SEQUENCE OF would be
+ %% improperly aligned. Example:
+ %%
+ %% SEQUENCE (SIZE (0..3)) OF ...
+
+ Lc;
+ true ->
+ %% Examples:
+ %%
+ %% SEQUENCE (SIZE (1..4)) OF ...
+ %% (OK because there must be at least one element)
+ %%
+ %% SEQUENCE OF ...
+ %% (OK because the length field will force alignment)
+ %%
+ Al ++ [{lc,CheckImm,Var,Val,{var,"_"}},
+ {call,erlang,iolist_to_binary,[Val]}]
+ end;
+opt_lc([{lc,ElementImm0,V,L}]=Lc, LenImm) ->
+ %% Attempt to hoist the alignment, putting after the length
+ %% and before the list comprehension:
+ %%
+ %% [Length,
+ %% align,
+ %% [Encode(Comp) || Comp <- Sof]]
+ %%
+
+ case enc_opt_al_1(ElementImm0, 0) of
+ {ElementImm,0} ->
+ case is_end_aligned(LenImm) orelse
+ (is_beginning_aligned(ElementImm0) andalso
+ lb_is_nonzero(LenImm)) of
+ false ->
+ %% Examples:
+ %%
+ %% SEQUENCE (SIZE (0..3)) OF OCTET STRING
+ %% (An empty SEQUENCE OF would be improperly aligned)
+ %%
+ %% SEQUENCE (SIZE (1..3)) OF OCTET STRING (SIZE (0..4))
+ %% (There would be an improper alignment before the
+ %% first element)
+
+ Lc;
+ true ->
+ %% Examples:
+ %%
+ %% SEQUENCE OF INTEGER
+ %% SEQUENCE (SIZE (1..4)) OF INTEGER
+ %% SEQUENCE (SIZE (1..4)) OF INTEGER (0..256)
+
+ [{put_bits,0,0,[1,align]},{lc,ElementImm,V,L}]
+ end;
+ _ ->
+ %% Unknown alignment, no alignment, or not aligned at the end.
+ %% Examples:
+ %%
+ %% SEQUENCE OF SomeConstructedType
+ %% SEQUENCE OF INTEGER (0..15)
+
+ Lc
+ end.
+
+is_beginning_aligned([{'cond',Cs}]) ->
+ lists:all(fun([_|Act]) -> is_beginning_aligned(Act) end, Cs);
+is_beginning_aligned([{error,_}|_]) -> true;
+is_beginning_aligned([{put_bits,_,_,U}|_]) ->
+ case U of
+ [_,align] -> true;
+ [_] -> false
+ end;
+is_beginning_aligned(Imm0) ->
+ case split_off_nonbuilding(Imm0) of
+ {[],_} -> false;
+ {[_|_],Imm} -> is_beginning_aligned(Imm)
+ end.
+
+is_end_aligned(Imm) ->
+ case enc_opt_al_1(Imm, unknown) of
+ {_,0} -> true;
+ {_,_} -> false
+ end.
+
+lb_is_nonzero([{sub,_,_,_}|_]) -> true;
+lb_is_nonzero(_) -> false.
+
+%%%
+%%% Attempt to combine two chunks of intermediate code.
+%%%
+
+combine_imms(ImmA0, ImmB0) ->
+ {Prefix0,ImmA} = split_off_nonbuilding(ImmA0),
+ {Prefix1,ImmB} = split_off_nonbuilding(ImmB0),
+ Prefix = Prefix0 ++ Prefix1,
+ Combined = do_combine(ImmA ++ ImmB, 3.0),
+ Prefix ++ Combined.
+
+do_combine([{error,_}=Imm|_], _Budget) ->
+ [Imm];
+do_combine([{'cond',Cs0}|T], Budget0) ->
+ Budget = debit(Budget0, num_clauses(Cs0, 0)),
+ Cs = [[C|do_combine(Act++T, Budget)] || [C|Act] <- Cs0],
+ [{'cond',Cs}];
+do_combine([{put_bits,V,_,_}|_]=L, Budget) when is_integer(V) ->
+ {Pb,T} = collect_put_bits(L),
+ do_combine_put_bits(Pb, T,Budget);
+do_combine(_, _) ->
+ throw(impossible).
+
+do_combine_put_bits(Pb, [], _Budget) ->
+ Pb;
+do_combine_put_bits(Pb, [{'cond',Cs0}|T], Budget) ->
+ Cs = [case Act of
+ [{error,_}] ->
+ [C|Act];
+ _ ->
+ [C|do_combine(Pb++Act, Budget)]
+ end || [C|Act] <- Cs0],
+ do_combine([{'cond',Cs}|T], Budget);
+do_combine_put_bits(_, _, _) ->
+ throw(impossible).
+
+debit(Budget0, Alternatives) ->
+ case Budget0 - log2(Alternatives) of
+ Budget when Budget > 0.0 ->
+ Budget;
+ _ ->
+ throw(impossible)
+ end.
+
+num_clauses([[_,{error,_}]|T], N) ->
+ num_clauses(T, N);
+num_clauses([_|T], N) ->
+ num_clauses(T, N+1);
+num_clauses([], N) -> N.
+
+log2(N) ->
+ math:log(N) / math:log(2.0).
+
+collect_put_bits(Imm) ->
+ lists:splitwith(fun({put_bits,V,_,_}) when is_integer(V) -> true;
+ (_) -> false
+ end, Imm).
+
+%%%
+%%% Simple common subexpression elimination to avoid fetching
+%%% the same element twice.
+%%%
+
+enc_cse([{call,erlang,element,Args,V}=H|T]) ->
+ [H|enc_cse_1(T, Args, V)];
+enc_cse(Imm) -> Imm.
+
+enc_cse_1([{call,erlang,element,Args,Dst}|T], Args, V) ->
+ [{set,V,Dst}|enc_cse_1(T, Args, V)];
+enc_cse_1([{block,Bl}|T], Args, V) ->
+ [{block,enc_cse_1(Bl, Args, V)}|enc_cse_1(T, Args, V)];
+enc_cse_1([H|T], Args, V) ->
+ [H|enc_cse_1(T, Args, V)];
+enc_cse_1([], _, _) -> [].
+
+
+%%%
+%%% Pre-process the intermediate code to simplify code generation.
+%%%
+
+enc_pre_cg(Imm) ->
+ enc_pre_cg_1(Imm, outside_list, in_seq).
+
+enc_pre_cg_1([], _StL, _StB) ->
+ nil;
+enc_pre_cg_1([H], StL, StB) ->
+ enc_pre_cg_2(H, StL, StB);
+enc_pre_cg_1([H0|T0], StL, StB) ->
+ case is_nonbuilding(H0) of
+ true ->
+ H = enc_pre_cg_nonbuilding(H0, StL),
+ Seq = {seq,H,enc_pre_cg_1(T0, StL, in_seq)},
+ case StB of
+ outside_seq -> {block,Seq};
+ in_seq -> Seq
+ end;
+ false ->
+ H = enc_pre_cg_2(H0, in_head, outside_seq),
+ T = enc_pre_cg_1(T0, in_tail, outside_seq),
+ enc_make_cons(H, T)
+ end.
+
+enc_pre_cg_2(align, StL, _StB) ->
+ case StL of
+ in_head -> align;
+ in_tail -> {cons,align,nil}
+ end;
+enc_pre_cg_2({apply,_,_}=Imm, _, _) ->
+ Imm;
+enc_pre_cg_2({block,Bl0}, StL, StB) ->
+ enc_pre_cg_1(Bl0, StL, StB);
+enc_pre_cg_2({call,_,_,_}=Imm, _, _) ->
+ Imm;
+enc_pre_cg_2({call_gen,_,_,_,_,_}=Imm, _, _) ->
+ Imm;
+enc_pre_cg_2({'cond',Cs0}, StL, _StB) ->
+ Cs = [{C,enc_pre_cg_1(Act, StL, outside_seq)} || [C|Act] <- Cs0],
+ {'cond',Cs};
+enc_pre_cg_2({error,_}=E, _, _) ->
+ E;
+enc_pre_cg_2({lc,B0,V,L}, StL, _StB) ->
+ B = enc_pre_cg_1(B0, StL, outside_seq),
+ {lc,B,V,L};
+enc_pre_cg_2({put_bits,V,8,[1]}, StL, _StB) ->
+ case StL of
+ in_head -> {integer,V};
+ in_tail -> {cons,{integer,V},nil};
+ outside_list -> {cons,{integer,V},nil}
+ end;
+enc_pre_cg_2({put_bits,V,binary,_}, _StL, _StB) ->
+ V;
+enc_pre_cg_2({put_bits,_,_,[_]}=PutBits, _StL, _StB) ->
+ {binary,[PutBits]};
+enc_pre_cg_2({var,_}=Imm, _, _) -> Imm.
+
+enc_make_cons({binary,H}, {binary,T}) ->
+ {binary,H++T};
+enc_make_cons({binary,H0}, {cons,{binary,H1},T}) ->
+ enc_make_cons({binary,H0++H1}, T);
+enc_make_cons({binary,H}, {cons,{integer,Int},T}) ->
+ enc_make_cons({binary,H++[{put_bits,Int,8,[1]}]}, T);
+enc_make_cons({integer,Int}, {binary,T}) ->
+ {binary,[{put_bits,Int,8,[1]}|T]};
+enc_make_cons({integer,Int}, {cons,{binary,H},T}) ->
+ enc_make_cons({binary,[{put_bits,Int,8,[1]}|H]}, T);
+enc_make_cons(H, T) ->
+ {cons,H,T}.
+
+enc_pre_cg_nonbuilding({lc,B0,Var,List,Dst}, StL) ->
+ B = enc_pre_cg_1(B0, StL, outside_seq),
+ {lc,B,Var,List,Dst};
+enc_pre_cg_nonbuilding({list,List0,Dst}, _StL) ->
+ List = enc_pre_cg_1(List0, outside_list, outside_seq),
+ {list,List,Dst};
+enc_pre_cg_nonbuilding({'try',Try0,{P,Succ0},Else0,Dst}, StL) ->
+ Try = enc_pre_cg_1(Try0, StL, outside_seq),
+ Succ = enc_pre_cg_1(Succ0, StL, outside_seq),
+ Else = enc_pre_cg_1(Else0, StL, outside_seq),
+ {'try',Try,{P,Succ},Else,Dst};
+enc_pre_cg_nonbuilding(Imm, _) -> Imm.
+
+%%%
+%%% Optimize calls to complete/1 and surrounding code. There are
+%%% several opportunities for optimizations.
+%%%
+%%% It may be possible to replace the call to complete/1 with
+%%% something cheaper (most important for the PER back-end which has
+%%% an expensive complete/1 implementation). If we can be sure that
+%%% complete/1 will be called with an iolist (no 'align' atoms or
+%%% bitstrings in the list), we can call iolist_to_binary/1
+%%% instead. If the list may include bitstrings, we can can call
+%%% list_to_bitstring/1 (note that list_to_bitstring/1 does not accept
+%%% a binary or bitstring, so we MUST be sure that we only pass it a
+%%% list). If complete/1 is called with a binary, we can omit the
+%%% call altogether.
+%%%
+%%% A call to byte_size/1 that follows complete/1 can be eliminated
+%%% if the size of the binary produced by complete/1 can be determined
+%%% and is constant.
+%%%
+%%% The code that encodes the length descriptor (a 'cond' instruction)
+%%% for a binary produced by complete/1 can be simplified if the lower
+%%% and upper bounds for the size of the binary are known.
+%%%
+
+-record(ost,
+ {sym,
+ t
+ }).
+
+enc_opt(Imm0) ->
+ {Imm,_} = enc_opt(Imm0, #ost{sym=gb_trees:empty()}),
+ Imm.
+
+enc_opt(align, St) ->
+ {align,St#ost{t=t_align({0,7})}};
+enc_opt({apply,What,As}, St) ->
+ {{apply,What,subst_list(As, St)},St#ost{t=t_any()}};
+enc_opt({assign,_,_}=Imm, St) ->
+ {Imm,St};
+enc_opt({binary,PutBits0}, St) ->
+ PutBits = [{put_bits,subst(V, St),Sz,F} ||
+ {put_bits,V,Sz,F} <- PutBits0],
+ NumBits = lists:foldl(fun({put_bits,_,Bits,_}, Sum) ->
+ Sum+Bits
+ end, 0, PutBits),
+ {{binary,PutBits},St#ost{t=t_bitstring(NumBits)}};
+enc_opt({block,Bl0}, St0) ->
+ {Bl,St} = enc_opt(Bl0, St0),
+ {{block,Bl},St};
+enc_opt({call,binary,encode_unsigned,[Int],Bin}=Imm, St0) ->
+ Type = get_type(Int, St0),
+ St = case t_range(Type) of
+ any ->
+ set_type(Bin, t_binary(), St0);
+ {Lb0,Ub0} ->
+ Lb = bit_size(binary:encode_unsigned(Lb0)),
+ Ub = bit_size(binary:encode_unsigned(Ub0)),
+ set_type(Bin, t_binary({Lb,Ub}), St0)
+ end,
+ {Imm,St};
+enc_opt({call,erlang,bit_size,[Bin],Dst}=Imm0, St0) ->
+ Type = get_type(Bin, St0),
+ case t_range(Type) of
+ any ->
+ St1 = set_type(Bin, t_bitstring(), St0),
+ St = propagate(Dst,
+ fun(T, S) ->
+ bit_size_propagate(Bin, T, S)
+ end, St1),
+ {Imm0,St};
+ {Lb,Ub}=Range ->
+ St = set_type(Dst, t_integer(Range), St0),
+ Imm = case Lb of
+ Ub -> none;
+ _ -> Imm0
+ end,
+ {Imm,St}
+ end;
+enc_opt({call,erlang,byte_size,[Bin],Dst}=Imm0, St0) ->
+ Type = get_type(Bin, St0),
+ case t_range(Type) of
+ any ->
+ St1 = set_type(Bin, t_binary(), St0),
+ St = propagate(Dst,
+ fun(T, S) ->
+ byte_size_propagate(Bin, T, S)
+ end, St1),
+ {Imm0,St};
+ {Lb0,Ub0} ->
+ Lb = (Lb0+7) div 8,
+ Ub = (Ub0+7) div 8,
+ St = set_type(Dst, t_integer({Lb,Ub}), St0),
+ Imm = case Lb of
+ Ub -> none;
+ _ -> Imm0
+ end,
+ {Imm,St}
+ end;
+enc_opt({call,erlang,iolist_to_binary,_}=Imm, St) ->
+ {Imm,St#ost{t=t_binary()}};
+enc_opt({call,erlang,length,[List],Dst}=Imm0, St0) ->
+ St1 = propagate(Dst,
+ fun(T, S) ->
+ length_propagate(List, T, S)
+ end, St0),
+ {Imm0,St1};
+enc_opt({call,per,complete,[Data],Dst}, St0) ->
+ Type = get_type(Data, St0),
+ St = set_type(Dst, t_binary(t_range(Type)), St0),
+ case t_type(Type) of
+ binary ->
+ {{set,Data,Dst},St};
+ bitlist ->
+ %% We KNOW that list_to_bitstring/1 will construct
+ %% a binary (the number of bits is divisible by 8)
+ %% because per_enc_open_type/2 added an 'align' atom
+ %% at the end. If that 'align' atom had not been
+ %% optimized away, the type would have been 'align'
+ %% instead of 'bitlist'.
+ {{call,erlang,list_to_bitstring,[Data],Dst},St};
+ iolist ->
+ {{call,erlang,iolist_to_binary,[Data],Dst},St};
+ nil ->
+ Imm = {list,{binary,[{put_bits,0,8,[1]}]},Dst},
+ enc_opt(Imm, St0);
+ _ ->
+ {{call,per,complete,[Data],Dst},St}
+ end;
+enc_opt({call,uper,complete,[Data],Dst}, St0) ->
+ Type = get_type(Data, St0),
+ St = set_type(Dst, t_binary(t_range(Type)), St0),
+ case t_type(Type) of
+ binary ->
+ {{set,Data,Dst},St0};
+ iolist ->
+ {{call,erlang,iolist_to_binary,[Data],Dst},St};
+ nil ->
+ Imm = {list,{binary,[{put_bits,0,8,[1]}]},Dst},
+ enc_opt(Imm, St0);
+ _ ->
+ %% 'bitlist' or 'any'.
+ {{call,uper,complete,[Data],Dst},St}
+ end;
+enc_opt({call,per_common,encode_chars,[List,NumBits|_],Dst}=Imm, St0) ->
+ %% Note: Never used when NumBits =:= 8 (list_to_binary/1 will
+ %% be used instead).
+ St1 = set_type(Dst, t_bitstring(), St0),
+ St = propagate(List,
+ fun(T, S) ->
+ char_propagate(Dst, T, NumBits, S)
+ end, St1),
+ {Imm,St};
+enc_opt({call,per_common,encode_chars_16bit,[List],Dst}=Imm, St0) ->
+ St1 = set_type(Dst, t_binary(), St0),
+ St = propagate(List,
+ fun(T, S) ->
+ char_propagate(Dst, T, 16, S)
+ end, St1),
+ {Imm,St};
+enc_opt({call,per_common,encode_big_chars,[List],Dst}=Imm, St0) ->
+ St1 = set_type(Dst, t_binary(), St0),
+ St = propagate(List,
+ fun(T, S) ->
+ char_propagate(Dst, T, 32, S)
+ end, St1),
+ {Imm,St};
+enc_opt({call,per_common,encode_fragmented,[_,Unit]}=Imm, St) ->
+ T = case Unit rem 8 of
+ 0 -> t_iolist();
+ _ -> t_bitlist()
+ end,
+ {Imm,St#ost{t=T}};
+enc_opt({call,per_common,encode_unconstrained_number,_}=Imm, St) ->
+ {Imm,St#ost{t=t_iolist()}};
+enc_opt({call,per_common,bitstring_from_positions,_}=Imm, St) ->
+ {Imm,St#ost{t=t_bitstring()}};
+enc_opt({call,per_common,to_named_bitstring,_}=Imm, St) ->
+ {Imm,St#ost{t=t_bitstring()}};
+enc_opt({call,_,_,_}=Imm, St) ->
+ {Imm,St#ost{t=t_any()}};
+enc_opt({call,_,_,_,_}=Imm, St) ->
+ {Imm,St#ost{t=undefined}};
+enc_opt({call_gen,N,K,F,L,As}, St) ->
+ {{call_gen,N,K,F,L,subst(As, St)},St#ost{t=t_any()}};
+enc_opt({'cond',Cs0}, St0) ->
+ case enc_opt_cs(Cs0, St0) of
+ [{'_',Imm,Type}] ->
+ {Imm,St0#ost{t=Type}};
+ [{Cond,Imm,Type0}|Cs1] ->
+ {Cs,Type} = enc_opt_cond_1(Cs1, Type0, [{Cond,Imm}]),
+ {{'cond',Cs},St0#ost{t=Type}}
+ end;
+enc_opt({cons,H0,T0}, St0) ->
+ {H,#ost{t=TypeH}=St1} = enc_opt(H0, St0),
+ {T,#ost{t=TypeT}=St} = enc_opt(T0, St1),
+ {{cons,H,T},St#ost{t=t_cons(TypeH, TypeT)}};
+enc_opt({error,_}=Imm, St) ->
+ {Imm,St#ost{t=t_any()}};
+enc_opt({integer,V}, St) ->
+ {{integer,subst(V, St)},St#ost{t=t_integer()}};
+enc_opt({lc,E0,B,C}, St) ->
+ {E,_} = enc_opt(E0, St),
+ {{lc,E,B,C},St#ost{t=t_any()}};
+enc_opt({lc,E0,B,C,Dst}, St) ->
+ {E,_} = enc_opt(E0, St),
+ {{lc,E,B,C,Dst},St#ost{t=undefined}};
+enc_opt({list,Imm0,Dst}, St0) ->
+ {Imm,#ost{t=Type}=St1} = enc_opt(Imm0, St0),
+ St = set_type(Dst, Type, St1),
+ {{list,Imm,Dst},St#ost{t=undefined}};
+enc_opt(nil, St) ->
+ {nil,St#ost{t=t_nil()}};
+enc_opt({seq,H0,T0}, St0) ->
+ {H,St1} = enc_opt(H0, St0),
+ {T,St} = enc_opt(T0, St1),
+ case {H,T} of
+ {none,_} ->
+ {T,St};
+ {{list,Imm,Data},
+ {seq,{call,per,complete,[Data],_},_}} ->
+ %% Get rid of any explicit 'align' added by per_enc_open_type/2.
+ {{seq,{list,remove_trailing_align(Imm),Data},T},St};
+ {_,_} ->
+ {{seq,H,T},St}
+ end;
+enc_opt({set,_,_}=Imm, St) ->
+ {Imm,St#ost{t=undefined}};
+enc_opt({sub,Src0,Int,Dst}, St0) ->
+ Src = subst(Src0, St0),
+ Type = get_type(Src, St0),
+ St = case t_range(Type) of
+ any ->
+ propagate(Dst,
+ fun(T, S) ->
+ set_type(Src, t_add(T, Int), S)
+ end,
+ St0);
+ {Lb,Ub} ->
+ set_type(Dst, t_integer({Lb-Int,Ub-Int}), St0)
+ end,
+ {{sub,Src,Int,Dst},St#ost{t=undefined}};
+enc_opt({'try',Try0,{P,Succ0},Else0,Dst}, St0) ->
+ {Try,_} = enc_opt(Try0, St0),
+ {Succ,_} = enc_opt(Succ0, St0),
+ {Else,_} = enc_opt(Else0, St0),
+ {{'try',Try,{P,Succ},Else,Dst},St0#ost{t=undefined}};
+enc_opt({var,_}=Imm, St) ->
+ Type = get_type(Imm, St),
+ {subst(Imm, St),St#ost{t=Type}}.
+
+remove_trailing_align({block,Bl}) ->
+ {block,remove_trailing_align(Bl)};
+remove_trailing_align({cons,H,{cons,align,nil}}) ->
+ H;
+remove_trailing_align({seq,H,T}) ->
+ {seq,H,remove_trailing_align(T)};
+remove_trailing_align(Imm) -> Imm.
+
+bit_size_propagate(Bin, Type, St) ->
+ case t_range(Type) of
+ any ->
+ St;
+ {Lb,Ub} ->
+ set_type(Bin, t_bitstring({Lb,Ub}), St)
+ end.
+
+byte_size_propagate(Bin, Type, St) ->
+ case t_range(Type) of
+ any ->
+ St;
+ {Lb,Ub} ->
+ set_type(Bin, t_binary({Lb*8,Ub*8}), St)
+ end.
+
+char_propagate(Dst, T, NumBits, St) ->
+ case t_range(T) of
+ any ->
+ St;
+ {Sz,Sz} when Sz*NumBits rem 8 =:= 0 ->
+ Bits = Sz*NumBits,
+ set_type(Dst, t_binary({Bits,Bits}), St);
+ {Lb,Ub} ->
+ Range = {Lb*NumBits,Ub*NumBits},
+ case NumBits rem 8 of
+ 0 ->
+ set_type(Dst, t_binary(Range), St);
+ _ ->
+ set_type(Dst, t_bitstring(Range), St)
+ end
+ end.
+
+length_propagate(List, Type, St) ->
+ set_type(List, t_list(t_range(Type)), St).
+
+enc_opt_cond_1([{Cond,{error,_}=Imm,_}|T], St, Acc) ->
+ enc_opt_cond_1(T, St, [{Cond,Imm}|Acc]);
+enc_opt_cond_1([{Cond,Imm,Curr0}|T], Curr1, Acc) ->
+ Curr = t_join(Curr0, Curr1),
+ enc_opt_cond_1(T, Curr, [{Cond,Imm}|Acc]);
+enc_opt_cond_1([], St, Acc) ->
+ {lists:reverse(Acc),St}.
+
+enc_opt_cs([{Cond,Imm0}|T], St0) ->
+ case eo_eval_cond(Cond, St0) of
+ false ->
+ enc_opt_cs(T, St0);
+ true ->
+ {Imm,#ost{t=Type}} = enc_opt(Imm0, St0),
+ [{'_',Imm,Type}];
+ maybe ->
+ St = update_type_info(Cond, St0),
+ {Imm,#ost{t=Type}} = enc_opt(Imm0, St),
+ [{Cond,Imm,Type}|enc_opt_cs(T, St0)]
+ end;
+enc_opt_cs([], _) -> [].
+
+eo_eval_cond('_', _) ->
+ true;
+eo_eval_cond({Op,{var,_}=Var,Val}, St) ->
+ Type = get_type(Var, St),
+ case t_range(Type) of
+ any -> maybe;
+ {_,_}=Range -> eval_cond_range(Op, Range, Val)
+ end;
+eo_eval_cond({_Op,{expr,_},_Val}, _St) -> maybe.
+
+eval_cond_range(lt, {Lb,Ub}, Val) ->
+ if
+ Ub < Val -> true;
+ Val =< Lb -> false;
+ true -> maybe
+ end;
+eval_cond_range(_Op, _Range, _Val) -> maybe.
+
+update_type_info({ult,{var,_}=Var,Val}, St) ->
+ Int = t_integer({0,Val-1}),
+ Type = t_meet(get_type(Var, St), Int),
+ set_type(Var, Type, St);
+update_type_info({lt,{var,_}=Var,Val}, St) ->
+ Int = t_integer({0,Val-1}),
+ Type = t_meet(get_type(Var, St), Int),
+ set_type(Var, Type, St);
+update_type_info({eq,{var,_}=Var,Val}, St) when is_integer(Val) ->
+ Int = t_integer(Val),
+ Type = t_meet(get_type(Var, St), Int),
+ set_type(Var, Type, St);
+update_type_info({eq,_,_}, St) ->
+ St;
+update_type_info({ge,_,_}, St) -> St.
+
+subst_list(As, St) ->
+ [subst(A, St) || A <- As].
+
+subst({var,_}=Var, St) ->
+ Type = get_type(Var, St),
+ case t_type(Type) of
+ integer ->
+ case t_range(Type) of
+ any -> Var;
+ {Val,Val} -> Val;
+ {_,_} -> Var
+ end;
+ _ ->
+ Var
+ end;
+subst(V, _St) -> V.
+
+set_type({var,Var}, {_,_}=Type, #ost{sym=Sym0}=St0) ->
+ Sym1 = gb_trees:enter(Var, Type, Sym0),
+ case gb_trees:lookup({propagate,Var}, Sym1) of
+ none ->
+ St0#ost{sym=Sym1};
+ {value,Propagate} ->
+ Sym = gb_trees:delete({propagate,Var}, Sym1),
+ St = St0#ost{sym=Sym},
+ Propagate(Type, St)
+ end.
+
+get_type({var,V}, #ost{sym=Sym}) ->
+ case gb_trees:lookup(V, Sym) of
+ none -> t_any();
+ {value,T} -> T
+ end.
+
+propagate({var,Var}, Propagate, #ost{sym=Sym0}=St) when is_function(Propagate, 2) ->
+ Sym = gb_trees:enter({propagate,Var}, Propagate, Sym0),
+ St#ost{sym=Sym}.
+
+%%%
+%%% A simple type system.
+%%%
+%%% Each type descriptions is a tuple {Type,Range}.
+%%% Type is one of the following atoms:
+%%%
+%%% Type name Description
+%%% --------- -----------
+%%% any Anything.
+%%%
+%%% align Basically iodata, but the list may contain bitstrings
+%%% and the the atom 'align'. Can be passed to complete/1
+%%% to construct a binary. Only used for aligned PER (per).
+%%%
+%%% bitstring An Erlang bitstring.
+%%%
+%%% bitlist A list that may be passed to list_to_bitstring/1 to
+%%% construct a bitstring.
+%%% NOTE: When analysing aligned PER (per), the number
+%%% of bits in the bitlist is always divisible by 8 (if
+%%% not, the type will be 'align' instead).
+%%%
+%%% binary An Erlang binary (the number of bits is divisible by 8).
+%%%
+%%% iolist An Erlang iolist.
+%%%
+%%% nil []
+%%%
+%%% integer An integer.
+%%%
+%%%
+%%% Range is one of:
+%%%
+%%% any
+%%% {LowerBound,UpperBound}
+%%%
+%%%
+
+t_align(Range) ->
+ {align,t__range(Range)}.
+
+t_any() ->
+ {any,any}.
+
+t_binary() ->
+ {binary,any}.
+
+t_binary(Range) ->
+ {binary,t__range(Range)}.
+
+t_bitlist() ->
+ {bitlist,any}.
+
+t_bitstring() ->
+ {bitstring,any}.
+
+t_bitstring(Range0) ->
+ case t__range(Range0) of
+ {Bits,Bits}=Range when Bits rem 8 =:= 0 ->
+ {binary,Range};
+ Range ->
+ {bitstring,Range}
+ end.
+
+t_add({integer,{Lb,Ub}}, N) ->
+ {integer,{Lb+N,Ub+N}}.
+
+t_cons({_,_}=T1, {_,_}=T2) ->
+ T = case {t__cons_type(T1),t__cons_type(T2)} of
+ {_,any} -> any;
+ {any,_} -> any;
+ {align,_} -> align;
+ {_,align} -> align;
+ {binary,binary} -> iolist;
+ {binary,bitstring} -> bitlist;
+ {bitstring,binary} -> bitlist;
+ {bitstring,bitstring} -> bitlist
+ end,
+ {T,t__cons_ranges(t__cons_range(T1), t__cons_range(T2))}.
+
+t_integer() ->
+ {integer,any}.
+
+t_integer(Range) ->
+ {integer,t__range(Range)}.
+
+t_iolist() ->
+ {iolist,any}.
+
+t_list(Range) ->
+ {list,t__range(Range)}.
+
+t_nil() ->
+ {nil,{0,0}}.
+
+t_meet({T1,Range1}, {T2,Range2}) ->
+ {t_meet_types(T1, T2),t_meet_ranges(Range1, Range2)}.
+
+t_meet_types(integer, integer) -> integer;
+t_meet_types(any, integer) -> integer.
+
+t_meet_ranges(any, Range) ->
+ Range;
+t_meet_ranges({Lb1,Ub1}, {Lb2,Ub2}) ->
+ if
+ Lb1 =< Ub2, Lb2 =< Ub1 ->
+ {max(Lb1, Lb2),Ub1};
+ Lb2 =< Ub1, Lb1 =< Ub2 ->
+ {max(Lb1, Lb2),Ub2}
+ end.
+
+t_join({T1,Range1}, {T2,Range2}) ->
+ T = t_join_types(lists:sort([T1,T2])),
+ Range = t_join_ranges(Range1, Range2),
+ {T,Range}.
+
+t_join_ranges({Lb1,Ub1}, {Lb2,Ub2}) ->
+ {min(Lb1, Lb2),max(Ub1, Ub2)};
+t_join_ranges(any, _) -> any;
+t_join_ranges(_, any) -> any.
+
+t_join_types([T,T]) -> T;
+t_join_types([align,any]) -> any;
+t_join_types([align,_]) -> align;
+t_join_types([any,_]) -> any;
+t_join_types([bitlist,bitstring]) -> any;
+t_join_types([bitlist,integer]) -> any;
+t_join_types([bitlist,iolist]) -> bitlist;
+t_join_types([bitlist,nil]) -> bitlist;
+t_join_types([binary,bitlist]) -> bitlist;
+t_join_types([binary,bitstring]) -> bitstring;
+t_join_types([binary,integer]) -> binary;
+t_join_types([binary,iolist]) -> iolist;
+t_join_types([binary,nil]) -> iolist;
+t_join_types([bitstring,integer]) -> any;
+t_join_types([bitstring,iolist]) -> any;
+t_join_types([bitstring,nil]) -> any;
+t_join_types([integer,_]) -> any;
+t_join_types([iolist,nil]) -> iolist.
+
+t_type({T,_}) -> T.
+
+t_range({_,Range}) -> Range.
+
+t__cons_type({align,_}) -> align;
+t__cons_type({any,_}) -> any;
+t__cons_type({binary,_}) -> binary;
+t__cons_type({bitstring,_}) -> bitstring;
+t__cons_type({bitlist,_}) -> bitstring;
+t__cons_type({integer,_}) -> binary;
+t__cons_type({iolist,_}) -> binary;
+t__cons_type({nil,_}) -> binary.
+
+t__cons_range({integer,_}) -> {8,8};
+t__cons_range({_,Range}) -> Range.
+
+t__cons_ranges({Lb1,Ub1}, {Lb2,Ub2}) ->
+ {Lb1+Lb2,Ub1+Ub2};
+t__cons_ranges(any, _) -> any;
+t__cons_ranges(_, any) -> any.
+
+t__range({Lb,Ub}=Range) when is_integer(Lb), is_integer(Ub) ->
+ Range;
+t__range(any) ->
+ any;
+t__range(Val) when is_integer(Val) ->
+ {Val,Val}.
+
+
+%%%
+%%% Code generation for encoding.
+%%%
+
+enc_cg({cons,_,_}=Cons) ->
+ enc_cg_cons(Cons);
+enc_cg({block,Imm}) ->
+ emit(["begin",nl]),
+ enc_cg(Imm),
+ emit([nl,
+ "end"]);
+enc_cg({seq,First,Then}) ->
+ enc_cg(First),
+ emit([com,nl]),
+ enc_cg(Then);
+enc_cg(align) ->
+ emit(align);
+enc_cg({apply,F0,As0}) ->
+ As = enc_call_args(As0, ""),
+ case F0 of
+ {local,F,_} when is_atom(F) ->
+ emit([{asis,F},"(",As,")"]);
+ {M,F,_} ->
+ emit([{asis,M},":",{asis,F},"(",As,")"])
+ end;
+enc_cg({assign,Dst0,Expr}) ->
+ Dst = mk_val(Dst0),
+ emit([Dst," = ",Expr]);
+enc_cg({binary,PutBits}) ->
+ emit(["<<",enc_cg_put_bits(PutBits, ""),">>"]);
+enc_cg({call,M,F,As0}) ->
+ As = [mk_val(A) || A <- As0],
+ asn1ct_func:call(M, F, As);
+enc_cg({call,M,F,As0,Dst}) ->
+ As = [mk_val(A) || A <- As0],
+ emit([mk_val(Dst)," = "]),
+ asn1ct_func:call(M, F, As);
+enc_cg({call_gen,Prefix,Key,Gen,_,As0}) ->
+ As = [mk_val(A) || A <- As0],
+ asn1ct_func:call_gen(Prefix, Key, Gen, As);
+enc_cg({'cond',Cs}) ->
+ enc_cg_cond(Cs);
+enc_cg({error,Error}) when is_function(Error, 0) ->
+ Error();
+enc_cg({error,Var0}) ->
+ Var = mk_val(Var0),
+ emit(["exit({error,{asn1,{illegal_value,",Var,"}}})"]);
+enc_cg({integer,Int}) ->
+ emit(mk_val(Int));
+enc_cg({lc,Body,Var,List}) ->
+ emit("["),
+ enc_cg(Body),
+ emit([" || ",mk_val(Var)," <- ",mk_val(List),"]"]);
+enc_cg({lc,Body,Var,List,Dst}) ->
+ emit([mk_val(Dst)," = ["]),
+ enc_cg(Body),
+ emit([" || ",mk_val(Var)," <- ",mk_val(List),"]"]);
+enc_cg({list,List,Dst}) ->
+ emit([mk_val(Dst)," = "]),
+ enc_cg(List);
+enc_cg(nil) ->
+ emit("[]");
+enc_cg({sub,Src0,Int,Dst0}) ->
+ Src = mk_val(Src0),
+ Dst = mk_val(Dst0),
+ emit([Dst," = ",Src," - ",Int]);
+enc_cg({set,{var,Src},{var,Dst}}) ->
+ emit([Dst," = ",Src]);
+enc_cg({'try',Try,{P,Succ},Else,Dst}) ->
+ emit([mk_val(Dst)," = try "]),
+ enc_cg(Try),
+ emit([" of",nl,
+ mk_val(P)," ->",nl]),
+ enc_cg(Succ),
+ emit([nl,
+ "catch throw:invalid ->",nl]),
+ enc_cg(Else),
+ emit([nl,
+ "end"]);
+enc_cg({var,V}) ->
+ emit(V).
+
+enc_cg_cons(Cons) ->
+ emit("["),
+ enc_cg_cons_1(Cons),
+ emit("]").
+
+enc_cg_cons_1({cons,H,{cons,_,_}=T}) ->
+ enc_cg(H),
+ emit([com,nl]),
+ enc_cg_cons_1(T);
+enc_cg_cons_1({cons,H,nil}) ->
+ enc_cg(H);
+enc_cg_cons_1({cons,H,T}) ->
+ enc_cg(H),
+ emit("|"),
+ enc_cg(T).
+
+enc_call_args([A|As], Sep) ->
+ [Sep,mk_val(A)|enc_call_args(As, ", ")];
+enc_call_args([], _) -> [].
+
+enc_cg_cond(Cs) ->
+ emit("if "),
+ enc_cg_cond(Cs, ""),
+ emit([nl,
+ "end"]).
+
+enc_cg_cond([C|Cs], Sep) ->
+ emit(Sep),
+ enc_cg_cond_1(C),
+ enc_cg_cond(Cs, [";",nl]);
+enc_cg_cond([], _) -> ok.
+
+enc_cg_cond_1({Cond,Action}) ->
+ enc_cond_term(Cond),
+ emit([" ->",nl]),
+ enc_cg(Action).
+
+enc_cond_term('_') ->
+ emit("true");
+enc_cond_term({ult,Var0,Int}) ->
+ Var = mk_val(Var0),
+ N = uper_num_bits(Int),
+ case 1 bsl N of
+ Int ->
+ emit([Var," bsr ",N," =:= 0"]);
+ _ ->
+ emit(["0 =< ",Var,", ",Var," < ",Int])
+ end;
+enc_cond_term({eq,Var0,Term}) ->
+ Var = mk_val(Var0),
+ emit([Var," =:= ",{asis,Term}]);
+enc_cond_term({ge,Var0,Int}) ->
+ Var = mk_val(Var0),
+ emit([Var," >= ",Int]);
+enc_cond_term({lt,Var0,Int}) ->
+ Var = mk_val(Var0),
+ emit([Var," < ",Int]).
+
+enc_cg_put_bits([{put_bits,Val0,N,[1]}|T], Sep) ->
+ Val = mk_val(Val0),
+ [[Sep,Val,":",integer_to_list(N)]|enc_cg_put_bits(T, ",")];
+enc_cg_put_bits([], _) -> [].
+
+mk_val({var,Str}) -> Str;
+mk_val({expr,Str}) -> Str;
+mk_val(Int) when is_integer(Int) -> integer_to_list(Int);
+mk_val(Other) -> {asis,Other}.
+
+%%%
+%%% Generate a function that maps a name of a bit position
+%%% to the bit position.
+%%%
+
+bit_string_name2pos_fun(NNL, Src) ->
+ {call_gen,"bit_string_name2pos_",NNL,
+ fun(Fd, Name) -> gen_name2pos(Fd, Name, NNL) end,[],[Src]}.
+
+gen_name2pos(Fd, Name, Names) ->
+ Cs0 = gen_name2pos_cs(Names, Name),
+ Cs = Cs0 ++ [bit_clause(Name),nil_clause(),invalid_clause()],
+ F = {function,1,Name,1,Cs},
+ file:write(Fd, [erl_pp:function(F)]).
+
+gen_name2pos_cs([{K,V}|T], Name) ->
+ P = [{cons,0,{atom,0,K},{var,0,'T'}}],
+ B = [{cons,0,{integer,0,V},{call,0,{atom,0,Name},[{var,0,'T'}]}}],
+ [{clause,0,P,[],B}|gen_name2pos_cs(T, Name)];
+gen_name2pos_cs([], _) -> [].
+
+bit_clause(Name) ->
+ VarT = {var,0,'T'},
+ VarPos = {var,0,'Pos'},
+ P = [{cons,0,{tuple,0,[{atom,0,bit},VarPos]},VarT}],
+ G = [[{call,0,{atom,0,is_integer},[VarPos]}]],
+ B = [{cons,0,VarPos,{call,0,{atom,0,Name},[VarT]}}],
+ {clause,0,P,G,B}.
+
+nil_clause() ->
+ P = B = [{nil,0}],
+ {clause,0,P,[],B}.
+
+invalid_clause() ->
+ P = [{var,0,'_'}],
+ B = [{call,0,{atom,0,throw},[{atom,0,invalid}]}],
+ {clause,0,P,[],B}.
+
+%%%
+%%% Hoist alignment to reduce the number of list elements in
+%%% encode. Fewer lists elements means faster traversal in
+%%% complete/{2,3}.
+%%%
+%%% For example, the following data sequence:
+%%%
+%%% [align,<<1:1,0:1>>,[align,<<Len:16>>|Data]]
+%%%
+%%% can be rewritten to:
+%%%
+%%% [align,<<1:1,0:1,0:6>>,[<<Len:16>>|Data]]
+%%%
+%%% The change from the literal <<1:1,0:1>> to <<1:1,0:1,0:6>>
+%%% comes for free, and we have eliminated one element of the
+%%% sub list.
+%%%
+%%% We must be careful not to rewrite:
+%%%
+%%% [<<1:1,0:1>>,[align,<<Len:16>>|Data]]
+%%%
+%%% to:
+%%%
+%%% [[<<1:1,0:1>>,align],[<<Len:16>>|Data]]
+%%%
+%%% because even though [<<1:0,0:1>>,align] is a literal and does
+%%% not add any additional construction cost, there is one more
+%%% sub list that needs to be traversed.
+%%%
+
+enc_hoist_align(Imm0) ->
+ Imm = enc_hoist_align_reverse(Imm0, []),
+ enc_hoist_align(Imm, false, []).
+
+enc_hoist_align_reverse([H|T], Acc) ->
+ case enc_opt_al_1([H], 0) of
+ {[H],_} ->
+ enc_hoist_align_reverse(T, [H|Acc]);
+ {_,_} ->
+ lists:reverse(T, [H,stop|Acc])
+ end;
+enc_hoist_align_reverse([], Acc) -> Acc.
+
+enc_hoist_align([stop|T], _Aligned, Acc) ->
+ lists:reverse(T, Acc);
+enc_hoist_align([{block,Bl0}|T], Aligned, Acc) ->
+ Bl = case Aligned of
+ false -> Bl0;
+ true -> enc_hoist_block(Bl0)
+ end,
+ case is_beginning_aligned(Bl) of
+ false ->
+ enc_hoist_align(T, false, [{block,Bl}|Acc]);
+ true ->
+ enc_hoist_align(T, true, [{put_bits,0,0,[1,align]},
+ {block,Bl}|Acc])
+ end;
+enc_hoist_align([H|T], _, Acc) ->
+ enc_hoist_align(T, false, [H|Acc]);
+enc_hoist_align([], _, Acc) -> Acc.
+
+enc_hoist_block(Bl) ->
+ try
+ enc_hoist_block_1(lists:reverse(Bl))
+ catch
+ throw:impossible ->
+ Bl
+ end.
+
+enc_hoist_block_1([{'cond',Cs0}|T]) ->
+ Cs = [[C|enc_hoist_block_2(Act)] || [C|Act] <- Cs0],
+ H = {'cond',Cs},
+ lists:reverse(T, [H]);
+enc_hoist_block_1(_) ->
+ throw(impossible).
+
+enc_hoist_block_2([{'cond',_}|_]=L) ->
+ enc_hoist_block(L);
+enc_hoist_block_2([{error,_}]=L) ->
+ L;
+enc_hoist_block_2([]) ->
+ [{put_bits,0,0,[1,align]}];
+enc_hoist_block_2(L) ->
+ case lists:last(L) of
+ {put_bits,_,_,_} ->
+ L ++ [{put_bits,0,0,[1,align]}];
+ _ ->
+ throw(impossible)
+ end.
+
+%%%
+%%% Optimize alignment for encoding.
+%%%
+
+enc_opt_al(Imm0) ->
+ {Imm,_} = enc_opt_al_1(Imm0, unknown),
+ Imm.
+
+enc_opt_al_1([H0|T0], Al0) ->
+ {H,Al1} = enc_opt_al(H0, Al0),
+ {T,Al} = enc_opt_al_1(T0, Al1),
+ {H++T,Al};
+enc_opt_al_1([], Al) -> {[],Al}.
+
+enc_opt_al({assign,_,_}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al({block,Bl0}, Al0) ->
+ {Bl,Al} = enc_opt_al_1(Bl0, Al0),
+ {[{block,Bl}],Al};
+enc_opt_al({call,erlang,iolist_to_binary,[_]}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al({call,per_common,encode_fragmented,[_,U]}=Call, Al) ->
+ case U rem 8 of
+ 0 -> {[Call],Al};
+ _ -> {[Call],unknown}
+ end;
+enc_opt_al({call,per_common,encode_unconstrained_number,[_]}=Call, _) ->
+ {[Call],0};
+enc_opt_al({call,_,_,_,_}=Call, Al) ->
+ {[Call],Al};
+enc_opt_al({'cond',Cs0}, Al0) ->
+ {Cs,Al} = enc_opt_al_cond(Cs0, Al0),
+ {[{'cond',Cs}],Al};
+enc_opt_al({error,_}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al({list,Imm0,Dst}, Al) ->
+ Imm1 = enc_opt_hoist_align(Imm0),
+ {Imm,_} = enc_opt_al_1(Imm1, 0),
+ {[{list,Imm,Dst}],Al};
+enc_opt_al({put_bits,V,N,[U,align]}, Al0) when Al0 rem 8 =:= 0 ->
+ Al = if
+ is_integer(N) -> N*U;
+ N =:= binary, U rem 8 =:= 0 -> 0;
+ true -> unknown
+ end,
+ {[{put_bits,V,N,[U]}],Al};
+enc_opt_al({put_bits,V,binary,[U,align]}, Al0) when is_integer(Al0) ->
+ N = 8 - (Al0 rem 8),
+ Al = case U rem 8 of
+ 0 -> 0;
+ _ -> unknown
+ end,
+ {[{put_bits,0,N,[1]},{put_bits,V,binary,[U]}],Al};
+enc_opt_al({put_bits,V,N0,[U,align]}, Al0) when is_integer(N0), is_integer(Al0) ->
+ N = N0 + (8 - Al0 rem 8),
+ Al = N0*U,
+ {[{put_bits,V,N,[1]}],Al};
+enc_opt_al({put_bits,_,N,[U,align]}=PutBits, _) when is_integer(N) ->
+ {[PutBits],N*U};
+enc_opt_al({put_bits,_,binary,[U,align]}=PutBits, _) when U rem 8 =:= 0 ->
+ {[PutBits],0};
+enc_opt_al({put_bits,_,N,[U]}=PutBits, Al) when is_integer(N), is_integer(Al) ->
+ {[PutBits],Al+N*U};
+enc_opt_al({put_bits,_,binary,[U]}=PutBits, Al) when U rem 8 =:= 0 ->
+ {[PutBits],Al};
+enc_opt_al({set,_,_}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al({sub,_,_,_}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al({'try',_,_,_,_}=Imm, Al) ->
+ {[Imm],Al};
+enc_opt_al(Imm, _) ->
+ {[Imm],unknown}.
+
+enc_opt_al_cond(Cs0, Al0) ->
+ enc_opt_al_cond_1(Cs0, Al0, [], []).
+
+enc_opt_al_cond_1([['_',{error,_}]=C|Cs], Al, CAcc, AAcc) ->
+ enc_opt_al_cond_1(Cs, Al, [C|CAcc], AAcc);
+enc_opt_al_cond_1([[C|Act0]|Cs0], Al0, CAcc, AAcc) ->
+ {Act,Al1} = enc_opt_al_1(Act0, Al0),
+ Al = if
+ Al1 =:= unknown -> Al1;
+ true -> Al1 rem 8
+ end,
+ enc_opt_al_cond_1(Cs0, Al0, [[C|Act]|CAcc], [Al|AAcc]);
+enc_opt_al_cond_1([], _, CAcc, AAcc) ->
+ Al = case lists:usort(AAcc) of
+ [] -> unknown;
+ [Al0] -> Al0;
+ [_|_] -> unknown
+ end,
+ {lists:reverse(CAcc),Al}.
+
+enc_opt_hoist_align([{'cond',Cs0},{put_bits,0,0,[1,align]}]=Imm) ->
+ try
+ Cs = [insert_align_last(C) || C <- Cs0],
+ [{'cond',Cs}]
+ catch
+ throw:impossible ->
+ Imm
+ end;
+enc_opt_hoist_align(Imm) -> Imm.
+
+insert_align_last([_,{error,_}]=C) ->
+ C;
+insert_align_last([H|T]) ->
+ case lists:last(T) of
+ {put_bits,_,_,_} ->
+ [H|T ++ [{put_bits,0,0,[1,align]}]];
+ _ ->
+ throw(impossible)
+ end.
+
+%%%
+%%% For the aligned PER format, fix up the intermediate format
+%%% before code generation. Code generation will be somewhat
+%%% easier if 'align' appear as a separate instruction.
+%%%
+
+per_fixup([{apply,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{block,Block}|T]) ->
+ [{block,per_fixup(Block)}|per_fixup(T)];
+per_fixup([{'assign',_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{'cond',Cs0}|T]) ->
+ Cs = [[C|per_fixup(Act)] || [C|Act] <- Cs0],
+ [{'cond',Cs}|per_fixup(T)];
+per_fixup([{call,_,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{call,_,_,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{call_gen,_,_,_,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{error,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{lc,B,V,L}|T]) ->
+ [{lc,per_fixup(B),V,L}|per_fixup(T)];
+per_fixup([{lc,B,V,L,Dst}|T]) ->
+ [{lc,per_fixup(B),V,L,Dst}|per_fixup(T)];
+per_fixup([{list,Imm,Dst}|T]) ->
+ [{list,per_fixup(Imm),Dst}|per_fixup(T)];
+per_fixup([{set,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{sub,_,_,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([{'try',Try0,{P,Succ0},Else0,Dst}|T]) ->
+ Try = per_fixup(Try0),
+ Succ = per_fixup(Succ0),
+ Else = per_fixup(Else0),
+ [{'try',Try,{P,Succ},Else,Dst}|per_fixup(T)];
+per_fixup([{put_bits,_,_,_}|_]=L) ->
+ fixup_put_bits(L);
+per_fixup([{var,_}=H|T]) ->
+ [H|per_fixup(T)];
+per_fixup([]) -> [].
+
+fixup_put_bits([{put_bits,0,0,[_,align]}|T]) ->
+ [align|fixup_put_bits(T)];
+fixup_put_bits([{put_bits,0,0,_}|T]) ->
+ fixup_put_bits(T);
+fixup_put_bits([{put_bits,V,N,[U,align]}|T]) ->
+ [align,{put_bits,V,N,[U]}|fixup_put_bits(T)];
+fixup_put_bits([{put_bits,_,_,_}=H|T]) ->
+ [H|fixup_put_bits(T)];
+fixup_put_bits(Other) -> per_fixup(Other).
+
%% effective_constraint(Type,C)
%% Type = atom()
%% C = [C1,...]
@@ -705,8 +2720,10 @@ mk_dest(S) -> S.
%% 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, [{{_,_}=Root,_}|_Rest]) ->
+ %% Normalize extension. Note that any range given for the
+ %% extension should be ignored anyway.
+ [{Root,[]}];
effective_constraint(integer, C) ->
SVs = get_constraints(C, 'SingleValue'),
SV = effective_constr('SingleValue', SVs),
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 1abccc8626..3891fce8d3 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -25,7 +25,8 @@
%% Only used internally within this module.
-record(typereference, {pos,val}).
--record(constraint,{c,e}).
+-record(constraint, {c,e}).
+-record(identifier, {pos,val}).
%% parse all types in module
parse(Tokens) ->
@@ -38,6 +39,7 @@ parse(Tokens) ->
{error,{Reason,hd(Tokens)}};
{ModuleDefinition,Rest1} ->
{Types,Rest2} = parse_AssignmentList(Rest1),
+ clean_process_dictionary(),
case Rest2 of
[{'END',_}|_Rest3] ->
{ok,ModuleDefinition#module{typeorval = Types}};
@@ -48,6 +50,13 @@ parse(Tokens) ->
end
end.
+clean_process_dictionary() ->
+ Mod = erase(asn1_module),
+ _ = erase({Mod,imports}),
+ _ = erase(tagdefault),
+ _ = erase(extensiondefault),
+ ok.
+
parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->
put(asn1_module,ModuleIdentifier),
{_DefinitiveIdentifier,Rest02} =
@@ -104,6 +113,9 @@ parse_ModuleDefinition(Tokens) ->
parse_Exports([{'EXPORTS',_L1},{';',_L2}|Rest]) ->
{{exports,[]},Rest};
+parse_Exports([{'EXPORTS',_},{'ALL',_},{';',_}|Rest]) ->
+ %% Same as no exports definition.
+ {{exports,all},Rest};
parse_Exports([{'EXPORTS',_L1}|Rest]) ->
{SymbolList,Rest2} = parse_SymbolList(Rest),
case Rest2 of
@@ -1029,10 +1041,6 @@ parse_DefinedObjectClass([{typereference,_,_ModName},{'.',_},Tr={typereference,_
parse_DefinedObjectClass([Tr={typereference,_,_ObjClName}|Rest]) ->
% {{objectclassname,tref2Exttref(Tr)},Rest};
{tref2Exttref(Tr),Rest};
-parse_DefinedObjectClass([{'TYPE-IDENTIFIER',_}|Rest]) ->
- {'TYPE-IDENTIFIER',Rest};
-parse_DefinedObjectClass([{'ABSTRACT-SYNTAX',_}|Rest]) ->
- {'ABSTRACT-SYNTAX',Rest};
parse_DefinedObjectClass(Tokens) ->
throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
[got,get_token(hd(Tokens)),expected,
@@ -1043,7 +1051,8 @@ parse_DefinedObjectClass(Tokens) ->
parse_ObjectClassAssignment([{typereference,L1,ObjClName},{'::=',_}|Rest]) ->
{Type,Rest2} = parse_ObjectClass(Rest),
- {#classdef{pos=L1,name=ObjClName,typespec=Type},Rest2};
+ {#classdef{pos=L1,name=ObjClName,module=resolve_module(Type),
+ typespec=Type},Rest2};
parse_ObjectClassAssignment(Tokens) ->
throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
[got,get_token(hd(Tokens)),expected,
@@ -2126,8 +2135,7 @@ parse_ParameterizedObjectSetAssignment(Tokens) ->
%% Parameter = {Governor,Reference} | Reference
%% Governor = Type | DefinedObjectClass
%% Type = #type{}
-%% DefinedObjectClass = #'Externaltypereference'{} |
-%% 'ABSTRACT-SYNTAX' | 'TYPE-IDENTIFIER'
+%% DefinedObjectClass = #'Externaltypereference'{}
%% Reference = #'Externaltypereference'{} | #'Externalvaluereference'{}
parse_ParameterList([{'{',_}|Rest]) ->
parse_ParameterList(Rest,[]);
@@ -2855,13 +2863,14 @@ parse_SequenceValue(Tokens) ->
throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
[got,get_token(hd(Tokens)),expected,'{']}}).
-parse_SequenceValue([{identifier,_,IdName}|Rest],Acc) ->
+parse_SequenceValue([{identifier,Pos,IdName}|Rest],Acc) ->
{Value,Rest2} = parse_Value(Rest),
+ SeqTag = #seqtag{pos=Pos,module=get(asn1_module),val=IdName},
case Rest2 of
[{',',_}|Rest3] ->
- parse_SequenceValue(Rest3,[{IdName,Value}|Acc]);
+ parse_SequenceValue(Rest3, [{SeqTag,Value}|Acc]);
[{'}',_}|Rest3] ->
- {lists:reverse([{IdName,Value}|Acc]),Rest3};
+ {lists:reverse(Acc, [{SeqTag,Value}]),Rest3};
_ ->
throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
[got,get_token(hd(Rest2)),expected,'}']}})
diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl
index a5eb6d0413..2eca80eda3 100644
--- a/lib/asn1/src/asn1ct_table.erl
+++ b/lib/asn1/src/asn1ct_table.erl
@@ -22,34 +22,25 @@
%% Table abstraction module for ASN.1 compiler
-export([new/1]).
--export([new/2]).
-export([new_reuse/1]).
--export([new_reuse/2]).
-export([exists/1]).
-export([size/1]).
-export([insert/2]).
-export([lookup/2]).
-export([match/2]).
-export([to_list/1]).
--export([delete/1]). % TODO: Remove (since we run in a separate process)
+-export([delete/1]).
-%% Always creates a new table
-new(Table) -> new(Table, []).
-new(Table, Options) ->
- TableId = case get(Table) of
- undefined ->
- ets:new(Table, Options);
- _ ->
- delete(Table),
- ets:new(Table, Options)
- end,
+%% Always create a new table.
+new(Table) ->
+ undefined = get(Table), %Assertion.
+ TableId = ets:new(Table, []),
put(Table, TableId).
-%% Only create it if it doesn't exist yet
-new_reuse(Table) -> new_reuse(Table, []).
-new_reuse(Table, Options) ->
- not exists(Table) andalso new(Table, Options).
+%% Only create it if it doesn't exist yet.
+new_reuse(Table) ->
+ not exists(Table) andalso new(Table).
exists(Table) -> get(Table) =/= undefined.
@@ -63,14 +54,17 @@ match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec).
to_list(Table) -> ets:tab2list(get(Table)).
+%% Deleting tables is no longer strictly necessary since each compilation
+%% runs in separate process, but it will reduce memory consumption
+%% especially when many compilations are run in parallel.
+
delete(Tables) when is_list(Tables) ->
[delete(T) || T <- Tables],
true;
delete(Table) when is_atom(Table) ->
- case get(Table) of
+ case erase(Table) of
undefined ->
true;
TableId ->
- ets:delete(TableId),
- erase(Table)
+ ets:delete(TableId)
end.
diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl
index 85199c65ec..8687ed955c 100644
--- a/lib/asn1/src/asn1ct_tok.erl
+++ b/lib/asn1/src/asn1ct_tok.erl
@@ -36,7 +36,7 @@ process(Stream,Lno,R) ->
process(io:get_line(Stream, ''), Stream,Lno+1,R).
process(eof, Stream,Lno,R) ->
- file:close(Stream),
+ ok = file:close(Stream),
lists:flatten(lists:reverse([{'$end',Lno}|R]));
@@ -309,7 +309,6 @@ check_hex(_) ->
%% returns rstrtype if A is a reserved word in the group
%% RestrictedCharacterStringType
reserved_word('ABSENT') -> true;
-%reserved_word('ABSTRACT-SYNTAX') -> true; % impl as predef item
reserved_word('ALL') -> true;
reserved_word('ANY') -> true;
reserved_word('APPLICATION') -> true;
@@ -380,7 +379,6 @@ reserved_word('T61String') -> rstrtype;
reserved_word('TAGS') -> true;
reserved_word('TeletexString') -> rstrtype;
reserved_word('TRUE') -> true;
-%% reserved_word('TYPE-IDENTIFIER') -> true; % impl as predef item
reserved_word('UNION') -> true;
reserved_word('UNIQUE') -> true;
reserved_word('UNIVERSAL') -> true;
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index ecdfa3f645..221cd991a7 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -18,6 +18,7 @@
%%
%%
-module(asn1ct_value).
+-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}}]).
%% Generate Erlang values for ASN.1 types.
%% The value is randomized within it's constraints
@@ -32,11 +33,11 @@
from_type(M,Typename) ->
- case asn1_db:dbget(M,Typename) of
- undefined ->
+ case asn1_db:dbload(M) of
+ error ->
{error,{not_found,{M,Typename}}};
- Tdef when is_record(Tdef,typedef) ->
- Type = Tdef#typedef.typespec,
+ ok ->
+ #typedef{typespec=Type} = asn1_db:dbget(M, Typename),
from_type(M,[Typename],Type);
Vdef when is_record(Vdef,valuedef) ->
from_value(Vdef);
@@ -167,17 +168,16 @@ from_type_prim(M, D) ->
case D#type.def of
'INTEGER' ->
i_random(C);
- {'INTEGER',NamedNumberList} ->
- NN = [X||{X,_} <- NamedNumberList],
- case NN of
+ {'INTEGER',[_|_]=NNL} ->
+ case C of
[] ->
- i_random(C);
+ {N,_} = lists:nth(random(length(NNL)), NNL),
+ N;
_ ->
- case C of
- [] ->
- lists:nth(random(length(NN)),NN);
- _ ->
- lists:nth((fun(0)->1;(X)->X end(i_random(C))),NN)
+ V = i_random(C),
+ case lists:keyfind(V, 2, NNL) of
+ false -> V;
+ {N,V} -> N
end
end;
Enum when is_tuple(Enum),element(1,Enum)=='ENUMERATED' ->
@@ -261,7 +261,11 @@ from_type_prim(M, D) ->
'BOOLEAN' ->
true;
'OCTET STRING' ->
- adjust_list(size_random(C),c_string(C,"OCTET STRING"));
+ S0 = adjust_list(size_random(C), c_string(C, "OCTET STRING")),
+ case M:legacy_erlang_types() of
+ false -> list_to_binary(S0);
+ true -> S0
+ end;
'NumericString' ->
adjust_list(size_random(C),c_string(C,"0123456789"));
'TeletexString' ->
@@ -349,7 +353,7 @@ random_unnamed_bit_string(M, C) ->
random(Upper) ->
{A1,A2,A3} = erlang:now(),
- random:seed(A1,A2,A3),
+ _ = random:seed(A1, A2, A3),
random:uniform(Upper).
size_random(C) ->
diff --git a/lib/asn1/src/asn1rt.erl b/lib/asn1/src/asn1rt.erl
index d18f81346a..ad8b879c38 100644
--- a/lib/asn1/src/asn1rt.erl
+++ b/lib/asn1/src/asn1rt.erl
@@ -18,14 +18,13 @@
%%
%%
-module(asn1rt).
+-deprecated(module).
%% Runtime functions for ASN.1 (i.e encode, decode)
-export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]).
-export([utf8_binary_to_list/1,utf8_list_to_binary/1]).
-
--deprecated([load_driver/0,unload_driver/0]).
encode(Module,{Type,Term}) ->
encode(Module,Type,Term).
diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl
index c1879e3dcf..1a44f1a27c 100644
--- a/lib/asn1/src/asn1rt_nif.erl
+++ b/lib/asn1/src/asn1rt_nif.erl
@@ -30,7 +30,7 @@
-define(ASN1_NIF_VSN,1).
load_nif() ->
- LibBaseName = "asn1_erl_nif",
+ LibBaseName = "asn1rt_nif",
PrivDir = code:priv_dir(asn1),
LibName = case erlang:system_info(build_type) of
opt ->
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
index b5429fe324..c4cd872368 100644
--- a/lib/asn1/src/asn1rtt_ber.erl
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -22,27 +22,28 @@
%% 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,
+-export([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,
+ decode_integer/2,
+ number2name/2,
+ encode_unnamed_bit_string/2,encode_unnamed_bit_string/3,
+ encode_named_bit_string/3,encode_named_bit_string/4,
encode_bit_string/4,
decode_named_bit_string/3,
- decode_compact_bit_string/3,
- decode_legacy_bit_string/3,
- decode_native_bit_string/3,
+ decode_compact_bit_string/2,compact_bit_string_size/1,
+ decode_native_bit_string/2,
+ native_to_legacy_bit_string/1,
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,
+ decode_octet_string/2,
+ decode_restricted_string/2,
+ encode_universal_string/2,decode_universal_string/2,
encode_UTF8_string/2,decode_UTF8_string/2,
- encode_BMP_string/2,decode_BMP_string/3]).
+ encode_BMP_string/2,decode_BMP_string/2]).
-export([encode_open_type/2,decode_open_type/2,
decode_open_type_as_binary/2]).
@@ -589,8 +590,6 @@ encode_tags(TagIn, {BytesSoFar,LenSoFar}) ->
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)).
@@ -695,41 +694,14 @@ encode_integer_neg(N, 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) ->
+ Bin = match_tags(Tlv, TagIn),
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,_} ->
@@ -738,49 +710,56 @@ number2name(Int, NamedNumberList) ->
Int
end.
-
%%============================================================================
-%% Enumerated value, ITU_T X.690 Chapter 8.4
-
-%% encode enumerated value
+%% Bitstring value, ITU_T X.690 Chapter 8.6
+%%
+%% encode bitstring 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.
+encode_unnamed_bit_string(Bits, TagIn) ->
+ Unused = (8 - (bit_size(Bits) band 7)) band 7,
+ Bin = <<Unused,Bits/bitstring,0:Unused>>,
+ encode_tags(TagIn, Bin, byte_size(Bin)).
-decode_enumerated1(Val, NamedNumberList) ->
- %% it must be a named integer
- case lists:keyfind(Val, 2, NamedNumberList) of
- {NamedVal, _} ->
- NamedVal;
- _ ->
- {asn1_enum,Val}
+encode_unnamed_bit_string(MaxBits, Bits, TagIn) ->
+ NumBits = bit_size(Bits),
+ Unused = (8 - (NumBits band 7)) band 7,
+ Bin = <<Unused,Bits/bitstring,0:Unused>>,
+ if
+ NumBits > MaxBits ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,NumBits},{maximum,MaxBits}}}}});
+ true ->
+ encode_tags(TagIn, Bin, byte_size(Bin))
end.
+encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) ->
+ do_encode_named_bit_string(Bits, NamedBitList, TagIn);
+encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) ->
+ do_encode_named_bit_string(Bits, NamedBitList, TagIn);
+encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) ->
+ encode_unnamed_bit_string(Bits, TagIn).
+
+encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) ->
+ do_encode_named_bit_string(C, Bits, NamedBitList, TagIn);
+encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) ->
+ do_encode_named_bit_string(C, Bits, NamedBitList, TagIn);
+encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) ->
+ encode_unnamed_bit_string(C, Bits, TagIn).
+
+do_encode_named_bit_string([FirstVal | RestVal], NamedBitList, TagIn) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ Size = lists:max(ToSetPos) + 1,
+ BitList = make_and_set_list(Size, ToSetPos, 0),
+ {Len,Unused,OctetList} = encode_bitstring(BitList),
+ encode_tags(TagIn, [Unused|OctetList],Len+1).
+
+do_encode_named_bit_string(Size, [FirstVal | RestVal], NamedBitList, TagIn) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ BitList = make_and_set_list(Size, ToSetPos, 0),
+ {Len, Unused, OctetList} = encode_bitstring(BitList),
+ encode_tags(TagIn, [Unused|OctetList], Len+1).
%%============================================================================
%% Bitstring value, ITU_T X.690 Chapter 8.6
@@ -881,15 +860,14 @@ remove_unused_then_dotag(TagIn,Unused,BinBits) ->
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,
+ 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).
@@ -1047,33 +1025,23 @@ unused_bitlist([Bit | Rest], Trail, Ack) ->
%% decode bitstring value
%%============================================================================
-decode_compact_bit_string(Buffer, Range, Tags) ->
+decode_compact_bit_string(Buffer, 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)
+ <<0>> -> {0,<<>>};
+ <<Unused,Bits/binary>> -> {Unused,Bits}
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).
+compact_bit_string_size({Unused,Bits}) ->
+ bit_size(Bits) - Unused.
-decode_native_bit_string(Buffer, Range, Tags) ->
+decode_native_bit_string(Buffer, 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)
+ Val
end.
decode_named_bit_string(Buffer, NamedNumberList, Tags) ->
@@ -1096,6 +1064,9 @@ decode_bitstring2(Len, Unused,
[B7,B6,B5,B4,B3,B2,B1,B0|
decode_bitstring2(Len - 1, Unused, Buffer)].
+native_to_legacy_bit_string(Bits) ->
+ [B || <<B:1>> <= Bits].
+
%%----------------------------------------
%% Decode the bitlist to names
%%----------------------------------------
@@ -1252,25 +1223,19 @@ 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 OCTET STRING to binary
%%============================================================================
-decode_restricted_string(Tlv, TagsIn) ->
+decode_octet_string(Tlv, TagsIn) ->
Bin = match_and_collect(Tlv, TagsIn),
- binary_to_list(Bin).
+ binary:copy(Bin).
-decode_restricted_string(Tlv, Range, TagsIn) ->
- Bin = match_and_collect(Tlv, TagsIn),
- check_restricted_string(binary_to_list(Bin), byte_size(Bin), Range).
+%%============================================================================
+%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%%============================================================================
-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}}}).
+decode_restricted_string(Tlv, TagsIn) ->
+ match_and_collect(Tlv, TagsIn).
%%============================================================================
%% encode Universal string
@@ -1296,10 +1261,9 @@ mk_uni_list([H|T],List) ->
%% {String, Remain, RemovedBytes}
%%===========================================================================
-decode_universal_string(Buffer, Range, Tags) ->
+decode_universal_string(Buffer, 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(binary_to_list(Bin)).
mk_universal_string(In) ->
mk_universal_string(In, []).
@@ -1359,10 +1323,9 @@ mk_BMP_list([H|T], List) ->
%% (Buffer, Range, StringType, HasTag, TotalLen) ->
%% {String, Remain, RemovedBytes}
%%============================================================================
-decode_BMP_string(Buffer, Range, Tags) ->
+decode_BMP_string(Buffer, 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(binary_to_list(Bin)).
mk_BMP_string(In) ->
mk_BMP_string(In,[]).
diff --git a/lib/asn1/src/asn1rtt_check.erl b/lib/asn1/src/asn1rtt_check.erl
index e78b65a8fb..0083867a10 100644
--- a/lib/asn1/src/asn1rtt_check.erl
+++ b/lib/asn1/src/asn1rtt_check.erl
@@ -18,210 +18,150 @@
%%
-module(asn1rtt_check).
--export([check_bool/2,
+-export([check_fail/1,
check_int/3,
- check_bitstring/3,
+ check_legacy_bitstring/2,
+ check_legacy_named_bitstring/3,
+ check_legacy_named_bitstring/4,
+ check_named_bitstring/3,
+ check_named_bitstring/4,
+ check_literal_sof/2,
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_fail(_) ->
+ throw(false).
-check_int(_, asn1_DEFAULT, _) ->
- true;
check_int(Value, Value, _) when is_integer(Value) ->
true;
-check_int(DefValue, Value, NNL) when is_atom(Value) ->
+check_int(Value, DefValue, 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})
+ throw(false)
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})
+check_int(_, _, _) ->
+ throw(false).
+
+check_legacy_bitstring(Value, Default) ->
+ check_bitstring(Default, Value).
+
+%% check_bitstring(Default, UserBitstring) -> true|false
+%% Default = bitstring()
+%% UserBitstring = integeger() | list(0|1) | {Unused,binary()} | bitstring()
+check_bitstring(DefVal, {Unused,Binary}) ->
+ %% User value in compact format.
+ Sz = bit_size(Binary) - Unused,
+ <<Val:Sz/bitstring,_:Unused>> = Binary,
+ check_bitstring(DefVal, Val);
+check_bitstring(DefVal, Val) when is_bitstring(Val) ->
+ case Val =:= DefVal of
+ false -> throw(false);
+ true -> true
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]);
+check_bitstring(Def, Val) when is_list(Val) ->
+ check_bitstring_list(Def, Val);
+check_bitstring(Def, Val) when is_integer(Val) ->
+ check_bitstring_integer(Def, Val).
+
+check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) ->
+ check_bitstring_list(T1, T2);
+check_bitstring_list(<<>>, []) ->
+ true;
+check_bitstring_list(_, _) ->
+ throw(false).
+
+check_bitstring_integer(<<H:1,T1/bitstring>>, Int) when H =:= Int band 1 ->
+ check_bitstring_integer(T1, Int bsr 1);
+check_bitstring_integer(<<>>, 0) ->
+ true;
+check_bitstring_integer(_, _) ->
+ throw(false).
+
+check_legacy_named_bitstring([Int|_]=Val, Bs, BsSize) when is_integer(Int) ->
+ check_named_bitstring(<< <<B:1>> || B <- Val >>, Bs, BsSize);
+check_legacy_named_bitstring({Unused,Val0}, Bs, BsSize) ->
+ Sz = bit_size(Val0) - Unused,
+ <<Val:Sz/bits,_/bits>> = Val0,
+ check_named_bitstring(Val, Bs, BsSize);
+check_legacy_named_bitstring(Val, Bs, BsSize) when is_integer(Val) ->
+ L = legacy_int_to_bitlist(Val),
+ check_named_bitstring(<< <<B:1>> || B <- L >>, Bs, BsSize);
+check_legacy_named_bitstring(Val, Bs, BsSize) ->
+ check_named_bitstring(Val, Bs, BsSize).
+
+check_legacy_named_bitstring([Int|_]=Val, Names, Bs, BsSize) when is_integer(Int) ->
+ check_named_bitstring(<< <<B:1>> || B <- Val >>, Names, Bs, BsSize);
+check_legacy_named_bitstring({Unused,Val0}, Names, Bs, BsSize) ->
+ Sz = bit_size(Val0) - Unused,
+ <<Val:Sz/bits,_/bits>> = Val0,
+ check_named_bitstring(Val, Names, Bs, BsSize);
+check_legacy_named_bitstring(Val, Names, Bs, BsSize) when is_integer(Val) ->
+ L = legacy_int_to_bitlist(Val),
+ check_named_bitstring(<< <<B:1>> || B <- L >>, Names, Bs, BsSize);
+check_legacy_named_bitstring(Val, Names, Bs, BsSize) ->
+ check_named_bitstring(Val, Names, Bs, BsSize).
+
+legacy_int_to_bitlist(0) ->
+ [];
+legacy_int_to_bitlist(Int) ->
+ [Int band 1|legacy_int_to_bitlist(Int bsr 1)].
+
+check_named_bitstring(Bs, Bs, _) ->
+ true;
+check_named_bitstring(Val, Bs, BsSize) ->
+ Rest = bit_size(Val) - BsSize,
+ case Val of
+ <<Bs:BsSize/bits,0:Rest>> ->
+ true;
_ ->
- 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).
-
+ throw(false)
+ end.
-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})
+check_named_bitstring([_|_]=Val, Names, _, _) ->
+ case lists:sort(Val) of
+ Names -> true;
+ _ -> throw(false)
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) ->
+check_named_bitstring(Bs, _, Bs, _) ->
true;
-check_null('NULL', 'NULL') ->
- true;
-check_null(_, V) ->
- throw({error,V}).
+check_named_bitstring(Val, _, Bs, BsSize) ->
+ Rest = bit_size(Val) - BsSize,
+ case Val of
+ <<Bs:BsSize/bits,0:Rest>> ->
+ true;
+ _ ->
+ throw(false)
+ end.
-check_objectidentifier(_, asn1_DEFAULT) ->
- true;
-check_objectidentifier(OI, OI) ->
+check_octetstring(V, V) ->
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})
+check_octetstring(V, Def) when is_list(V) ->
+ case list_to_binary(V) of
+ Def -> true;
+ _ -> throw(false)
+ end;
+check_octetstring(_, _) ->
+ throw(false).
+
+check_objectidentifier(Value, {Prefix,Tail}) when is_tuple(Value) ->
+ check_oid(tuple_to_list(Value), Prefix, Tail);
+check_objectidentifier(_, _) ->
+ throw(false).
+
+check_oid([H|T], [K|Ks], Tail) ->
+ case lists:member(H, K) of
+ false -> throw(false);
+ true -> check_oid(T, Ks, Tail)
end;
-check_objectidentifier1([], [], _) ->
+check_oid(Tail, [], Tail) ->
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_oid(_, _, _) ->
+ throw(false).
check_objectdescriptor(_, asn1_DEFAULT) ->
true;
@@ -237,21 +177,6 @@ check_real(R, R) ->
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]) ->
@@ -270,7 +195,15 @@ check_restrictedstring({V1,V2,V3,V4}, [V1,V2,V3,V4]) ->
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}}).
+check_restrictedstring(V1, V2) when is_tuple(V1) ->
+ check_restrictedstring(tuple_to_list(V1), V2);
+check_restrictedstring(_, _) ->
+ throw(false).
+
+check_literal_sof(Value, Default) ->
+ case lists:sort(Value) of
+ Default ->
+ true;
+ _ ->
+ throw(false)
+ end.
diff --git a/lib/asn1/src/asn1rtt_ext.erl b/lib/asn1/src/asn1rtt_ext.erl
index 46adb2007d..f3eee1cdd5 100644
--- a/lib/asn1/src/asn1rtt_ext.erl
+++ b/lib/asn1/src/asn1rtt_ext.erl
@@ -38,7 +38,7 @@ transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest], 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)->
+ when is_list(Data_value); is_binary(Data_value) ->
list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
Data_val_desc|Acc]));
transform_to_EXTERNAL1990([Data_val_desc,Data_value], Acc)
diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl
index 9f4b7500d8..672c84593c 100644
--- a/lib/asn1/src/asn1rtt_per.erl
+++ b/lib/asn1/src/asn1rtt_per.erl
@@ -18,62 +18,7 @@
%%
-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).
+-export([skipextensions/3,complete/1]).
skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
Prev = Nr - 1,
@@ -95,270 +40,6 @@ align(BitStr) when is_bitstring(BitStr) ->
<<_: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>> ->
@@ -370,511 +51,70 @@ decode_length(Buffer) -> % un-constrained
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
+complete(L0) ->
+ L = complete(L0, []),
+ case list_to_bitstring(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].
+complete([], []) ->
+ [];
+complete([], [H|More]) ->
+ complete(H, More);
+complete([align|T], More) ->
+ complete(T, More);
+complete([[]|T], More) ->
+ complete(T, More);
+complete([[_|_]=H], More) ->
+ complete(H, More);
+complete([[_|_]=H|T], More) ->
+ complete(H, [T|More]);
+complete([H|T], More) when is_integer(H); is_binary(H) ->
+ [H|complete(T, More)];
+complete([H|T], More) ->
+ [H|complete(T, bit_size(H), More)];
+complete(Bin, More) when is_binary(Bin) ->
+ [Bin|complete([], More)];
+complete(Bin, More) ->
+ [Bin|complete([], bit_size(Bin), More)].
+
+complete([], Bits, []) ->
+ case Bits band 7 of
+ 0 -> [];
+ N -> [<<0:(8-N)>>]
+ end;
+complete([], Bits, [H|More]) ->
+ complete(H, Bits, More);
+complete([align|T], Bits, More) ->
+ case Bits band 7 of
+ 0 -> complete(T, More);
+ 1 -> [<<0:7>>|complete(T, More)];
+ 2 -> [<<0:6>>|complete(T, More)];
+ 3 -> [<<0:5>>|complete(T, More)];
+ 4 -> [<<0:4>>|complete(T, More)];
+ 5 -> [<<0:3>>|complete(T, More)];
+ 6 -> [<<0:2>>|complete(T, More)];
+ 7 -> [<<0:1>>|complete(T, More)]
+ end;
+complete([[]|T], Bits, More) ->
+ complete(T, Bits, More);
+complete([[_|_]=H], Bits, More) ->
+ complete(H, Bits, More);
+complete([[_|_]=H|T], Bits, More) ->
+ complete(H, Bits, [T|More]);
+complete([H|T], Bits, More) when is_integer(H);
+ is_binary(H) ->
+ [H|complete(T, Bits, More)];
+complete([H|T], Bits, More) ->
+ [H|complete(T, Bits+bit_size(H), More)];
+complete(Bin, Bits, More) when is_binary(Bin) ->
+ [Bin|complete([], Bits, More)];
+complete(Bin, Bits, More) ->
+ [Bin|complete([], Bits+bit_size(Bin), More)].
diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl
index e7edc2b65f..0290c75a28 100644
--- a/lib/asn1/src/asn1rtt_per_common.erl
+++ b/lib/asn1/src/asn1rtt_per_common.erl
@@ -28,7 +28,20 @@
decode_chars/2,decode_chars/3,
decode_chars_16bit/1,
decode_big_chars/2,
- decode_oid/1,decode_relative_oid/1]).
+ decode_oid/1,decode_relative_oid/1,
+ encode_chars/2,encode_chars/3,
+ encode_chars_compact_map/3,
+ encode_chars_16bit/1,encode_big_chars/1,
+ encode_fragmented/2,
+ encode_oid/1,encode_relative_oid/1,
+ encode_unconstrained_number/1,
+ bitstring_from_positions/1,bitstring_from_positions/2,
+ to_bitstring/1,to_bitstring/2,
+ to_named_bitstring/1,to_named_bitstring/2,
+ bs_drop_trailing_zeroes/1,adjust_trailing_zeroes/2,
+ is_default_bitstring/3,is_default_bitstring/5,
+ extension_bitmap/3,
+ open_type_to_binary/1,legacy_open_type_to_binary/1]).
-define('16K',16384).
@@ -90,6 +103,244 @@ decode_oid(Octets) ->
decode_relative_oid(Octets) ->
list_to_tuple(dec_subidentifiers(Octets, 0, [])).
+encode_chars(Val, NumBits) ->
+ << <<C:NumBits>> || C <- Val >>.
+
+encode_chars(Val, NumBits, {Lb,Tab}) ->
+ << <<(enc_char(C, Lb, Tab)):NumBits>> || C <- Val >>.
+
+encode_chars_compact_map(Val, NumBits, {Lb,Limit}) ->
+ << <<(enc_char_cm(C, Lb, Limit)):NumBits>> || C <- Val >>.
+
+encode_chars_16bit(Val) ->
+ L = [case C of
+ {0,0,A,B} -> [A,B];
+ C when is_integer(C) -> [0,C]
+ end || C <- Val],
+ iolist_to_binary(L).
+
+encode_big_chars(Val) ->
+ L = [case C of
+ {_,_,_,_} -> tuple_to_list(C);
+ C when is_integer(C) -> [<<0,0,0>>,C]
+ end || C <- Val],
+ iolist_to_binary(L).
+
+encode_fragmented(Bin, Unit) ->
+ encode_fragmented_1(Bin, Unit, 4).
+
+encode_oid(Val) when is_tuple(Val) ->
+ encode_oid(tuple_to_list(Val));
+encode_oid(Val) ->
+ iolist_to_binary(e_object_identifier(Val)).
+
+encode_relative_oid(Val) when is_tuple(Val) ->
+ encode_relative_oid(tuple_to_list(Val));
+encode_relative_oid(Val) when is_list(Val) ->
+ list_to_binary([e_object_element(X)||X <- Val]).
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ if
+ Val < 16#80 ->
+ [1,Val];
+ Val < 16#100 ->
+ [<<2,0>>,Val];
+ true ->
+ case binary:encode_unsigned(Val) of
+ <<0:1,_/bitstring>>=Bin ->
+ case byte_size(Bin) of
+ Sz when Sz < 128 ->
+ [Sz,Bin];
+ Sz when Sz < 16384 ->
+ [<<2:2,Sz:14>>,Bin]
+ end;
+ <<1:1,_/bitstring>>=Bin ->
+ case byte_size(Bin)+1 of
+ Sz when Sz < 128 ->
+ [Sz,0,Bin];
+ Sz when Sz < 16384 ->
+ [<<2:2,Sz:14,0:8>>,Bin]
+ end
+ end
+ end;
+encode_unconstrained_number(Val) ->
+ Oct = enint(Val, []),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ [Len|Oct];
+ Len < 16384 ->
+ [<<2:2,Len:14>>|Oct]
+ end.
+
+%% bitstring_from_positions([Position]) -> BitString
+%% Given an unsorted list of bit positions (0..MAX), construct
+%% a BIT STRING. The rightmost bit will always be a one.
+
+bitstring_from_positions([]) -> <<>>;
+bitstring_from_positions([_|_]=L0) ->
+ L1 = lists:sort(L0),
+ L = diff(L1, -1),
+ << <<1:(N+0)>> || N <- L >>.
+
+%% bitstring_from_positions([Position], Lb) -> BitString
+%% Given an unsorted list of bit positions (0..MAX) and a lower bound
+%% for the number of bits, construct BIT STRING (zero-padded on the
+%% right side if needed).
+
+bitstring_from_positions(L0, Lb) ->
+ L1 = lists:sort(L0),
+ L = diff(L1, -1, Lb-1),
+ << <<B:(N+0)>> || {B,N} <- L >>.
+
+%% to_bitstring(Val) -> BitString
+%% Val = BitString | {Unused,Binary} | [OneOrZero] | Integer
+%% Given one of the possible representations for a BIT STRING,
+%% return a bitstring (without adding or removing any zero bits
+%% at the right end).
+
+to_bitstring({0,Bs}) when is_binary(Bs) ->
+ Bs;
+to_bitstring({Unused,Bs0}) when is_binary(Bs0) ->
+ Sz = bit_size(Bs0) - Unused,
+ <<Bs:Sz/bits,_/bits>> = Bs0,
+ Bs;
+to_bitstring(Bs) when is_bitstring(Bs) ->
+ Bs;
+to_bitstring(Int) when is_integer(Int), Int >= 0 ->
+ L = int_to_bitlist(Int),
+ << <<B:1>> || B <- L >>;
+to_bitstring(L) when is_list(L) ->
+ << <<B:1>> || B <- L >>.
+
+%% to_bitstring(Val, Lb) -> BitString
+%% Val = BitString | {Unused,Binary} | [OneOrZero] | Integer
+%% Lb = Integer
+%% Given one of the possible representations for a BIT STRING
+%% and the lower bound for the number of bits,
+%% return a bitstring at least Lb bits long (padded with zeroes
+%% if needed).
+
+to_bitstring({0,Bs}, Lb) when is_binary(Bs) ->
+ case bit_size(Bs) of
+ Sz when Sz < Lb ->
+ <<Bs/bits,0:(Lb-Sz)>>;
+ _ ->
+ Bs
+ end;
+to_bitstring({Unused,Bs0}, Lb) when is_binary(Bs0) ->
+ Sz = bit_size(Bs0) - Unused,
+ if
+ Sz < Lb ->
+ <<Bs0:Sz/bits,0:(Lb-Sz)>>;
+ true ->
+ <<Bs:Sz/bits,_/bits>> = Bs0,
+ Bs
+ end;
+to_bitstring(Bs, Lb) when is_bitstring(Bs) ->
+ adjust_size(Bs, Lb);
+to_bitstring(Int, Lb) when is_integer(Int), Int >= 0 ->
+ L = int_to_bitlist(Int),
+ Bs = << <<B:1>> || B <- L >>,
+ adjust_size(Bs, Lb);
+to_bitstring(L, Lb) when is_list(L) ->
+ Bs = << <<B:1>> || B <- L >>,
+ adjust_size(Bs, Lb).
+
+%% to_named_bitstring(Val) -> BitString
+%% Val = BitString | {Unused,Binary} | [OneOrZero] | Integer
+%% Given one of the possible representations for a BIT STRING,
+%% return a bitstring where any trailing zeroes have been stripped.
+
+to_named_bitstring(Val) ->
+ Bs = to_bitstring(Val),
+ bs_drop_trailing_zeroes(Bs).
+
+%% to_named_bitstring(Val, Lb) -> BitString
+%% Val = BitString | {Unused,Binary} | [OneOrZero] | Integer
+%% Lb = Integer
+%% Given one of the possible representations for a BIT STRING
+%% and the lower bound for the number of bits,
+%% return a bitstring that is at least Lb bits long. There will
+%% be zeroes at the right only if needed to reach the lower bound
+%% for the number of bits.
+
+to_named_bitstring({0,Bs}, Lb) when is_binary(Bs) ->
+ adjust_trailing_zeroes(Bs, Lb);
+to_named_bitstring({Unused,Bs0}, Lb) when is_binary(Bs0) ->
+ Sz = bit_size(Bs0) - Unused,
+ <<Bs:Sz/bits,_/bits>> = Bs0,
+ adjust_trailing_zeroes(Bs, Lb);
+to_named_bitstring(Bs, Lb) when is_bitstring(Bs) ->
+ adjust_trailing_zeroes(Bs, Lb);
+to_named_bitstring(Val, Lb) ->
+ %% Obsolete representations: list or integer. Optimize
+ %% for correctness, not speed.
+ adjust_trailing_zeroes(to_bitstring(Val), Lb).
+
+is_default_bitstring(asn1_DEFAULT, _, _) ->
+ true;
+is_default_bitstring(Named, Named, _) ->
+ true;
+is_default_bitstring(Bs, _, Bs) ->
+ true;
+is_default_bitstring(Val, _, Def) when is_bitstring(Val) ->
+ Sz = bit_size(Def),
+ case Val of
+ <<Def:Sz/bitstring,T/bitstring>> ->
+ NumZeroes = bit_size(T),
+ case T of
+ <<0:NumZeroes>> -> true;
+ _ -> false
+ end;
+ _ ->
+ false
+ end.
+
+is_default_bitstring(asn1_DEFAULT, _, _, _, _) ->
+ true;
+is_default_bitstring({Unused,Bin}, V0, V1, V2, V3) when is_integer(Unused) ->
+ %% Convert compact bitstring to a bitstring.
+ Sz = bit_size(Bin) - Unused,
+ <<Bs:Sz/bitstring,_:Unused>> = Bin,
+ is_default_bitstring(Bs, V0, V1, V2, V3);
+is_default_bitstring(Named, Named, _, _, _) ->
+ true;
+is_default_bitstring(Bs, _, Bs, _, _) ->
+ true;
+is_default_bitstring(List, _, _, List, _) ->
+ true;
+is_default_bitstring(Int, _, _, _, Int) ->
+ true;
+is_default_bitstring(Val, _, Def, _, _) when is_bitstring(Val) ->
+ Sz = bit_size(Def),
+ case Val of
+ <<Def:Sz/bitstring,T/bitstring>> ->
+ NumZeroes = bit_size(T),
+ case T of
+ <<0:NumZeroes>> -> true;
+ _ -> false
+ end;
+ _ ->
+ false
+ end;
+is_default_bitstring(Val, _, _, List, _) when is_list(Val) ->
+ is_default_bitstring_list(List, Val);
+is_default_bitstring(_, _, _, _, _) -> false.
+
+extension_bitmap(Val, Pos, Limit) ->
+ extension_bitmap(Val, Pos, Limit, 0).
+
+open_type_to_binary({asn1_OPENTYPE,Bin}) when is_binary(Bin) ->
+ Bin.
+
+legacy_open_type_to_binary({asn1_OPENTYPE,Bin}) when is_binary(Bin) ->
+ Bin;
+legacy_open_type_to_binary(Bin) when is_binary(Bin) ->
+ Bin;
+legacy_open_type_to_binary(List) when is_list(List) ->
+ List.
+
%%%
%%% Internal functions.
%%%
@@ -124,3 +375,170 @@ dec_subidentifiers([H|T], Av, Al) ->
dec_subidentifiers(T, 0, [(Av bsl 7) bor H|Al]);
dec_subidentifiers([], _Av, Al) ->
lists:reverse(Al).
+
+enc_char(C0, Lb, Tab) ->
+ try element(C0-Lb, Tab) of
+ ill ->
+ illegal_char_error();
+ C ->
+ C
+ catch
+ error:badarg ->
+ illegal_char_error()
+ end.
+
+enc_char_cm(C0, Lb, Limit) ->
+ C = C0 - Lb,
+ if
+ 0 =< C, C < Limit ->
+ C;
+ true ->
+ illegal_char_error()
+ end.
+
+illegal_char_error() ->
+ error({error,{asn1,"value forbidden by FROM constraint"}}).
+
+encode_fragmented_1(Bin, Unit, N) ->
+ SegSz = Unit * N * ?'16K',
+ case Bin of
+ <<B:SegSz/bitstring,T/bitstring>> ->
+ [<<3:2,N:6>>,B|encode_fragmented_1(T, Unit, N)];
+ _ when N > 1 ->
+ encode_fragmented_1(Bin, Unit, N-1);
+ _ ->
+ case bit_size(Bin) div Unit of
+ Len when Len < 128 ->
+ [Len,Bin];
+ Len when Len < 16384 ->
+ [<<2:2,Len:14>>,Bin]
+ end
+ end.
+
+%% 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,
+ e_object_elements([Head|Tail], []);
+e_object_identifier([_,_|_Tail]=Oid) ->
+ 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]].
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+diff([H|T], Prev) ->
+ [H-Prev|diff(T, H)];
+diff([], _) -> [].
+
+diff([H|T], Prev, Last) ->
+ [{1,H-Prev}|diff(T, H, Last)];
+diff([], Prev, Last) when Last >= Prev ->
+ [{0,Last-Prev}];
+diff([], _, _) -> [].
+
+int_to_bitlist(0) -> [];
+int_to_bitlist(Int) -> [Int band 1|int_to_bitlist(Int bsr 1)].
+
+adjust_size(Bs, Lb) ->
+ case bit_size(Bs) of
+ Sz when Sz < Lb ->
+ <<Bs:Sz/bits,0:(Lb-Sz)>>;
+ _ ->
+ Bs
+ end.
+
+adjust_trailing_zeroes(Bs0, Lb) ->
+ case bit_size(Bs0) of
+ Sz when Sz < Lb ->
+ %% Too short - pad with zeroes.
+ <<Bs0:Sz/bits,0:(Lb-Sz)>>;
+ Lb ->
+ %% Exactly the right size - nothing to do.
+ Bs0;
+ _ ->
+ %% Longer than the lower bound - drop trailing zeroes.
+ <<_:Lb/bits,Tail/bits>> = Bs0,
+ Sz = Lb + bit_size(bs_drop_trailing_zeroes(Tail)),
+ <<Bs:Sz/bits,_/bits>> = Bs0,
+ Bs
+ end.
+
+bs_drop_trailing_zeroes(Bs) ->
+ bs_drop_trailing_zeroes(Bs, bit_size(Bs)).
+
+bs_drop_trailing_zeroes(Bs, 0) ->
+ Bs;
+bs_drop_trailing_zeroes(Bs0, Sz0) when Sz0 < 8 ->
+ <<Byte:Sz0>> = Bs0,
+ Sz = Sz0 - ntz(Byte),
+ <<Bs:Sz/bits,_/bits>> = Bs0,
+ Bs;
+bs_drop_trailing_zeroes(Bs0, Sz0) ->
+ Sz1 = Sz0 - 8,
+ <<Bs1:Sz1/bits,Byte:8>> = Bs0,
+ case ntz(Byte) of
+ 8 ->
+ bs_drop_trailing_zeroes(Bs1, Sz1);
+ Ntz ->
+ Sz = Sz0 - Ntz,
+ <<Bs:Sz/bits,_:Ntz/bits>> = Bs0,
+ Bs
+ end.
+
+%% ntz(Byte) -> Number of trailing zeroes.
+ntz(Byte) ->
+ %% The table was calculated like this:
+ %% NTZ = fun (B, N, NTZ) when B band 1 =:= 0 -> NTZ(B bsr 1, N+1, NTZ); (_, N, _) -> N end.
+ %% io:format("~w\n", [list_to_tuple([NTZ(B+256, 0, NTZ) || B <- lists:seq(0, 255)])]).
+ T = {8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0},
+ element(Byte+1, T).
+
+is_default_bitstring_list([H|Def], [H|Val]) ->
+ is_default_bitstring_list(Def, Val);
+is_default_bitstring_list([], []) ->
+ true;
+is_default_bitstring_list([], [_|_]=Val) ->
+ lists:all(fun(0) -> true;
+ (_) -> false
+ end, Val);
+is_default_bitstring_list(_, _) -> false.
+
+extension_bitmap(_Val, Pos, Limit, Acc) when Pos >= Limit ->
+ Acc;
+extension_bitmap(Val, Pos, Limit, Acc) ->
+ Bit = case element(Pos, Val) of
+ asn1_NOVALUE -> 0;
+ _ -> 1
+ end,
+ extension_bitmap(Val, Pos+1, Limit, (Acc bsl 1) bor Bit).
diff --git a/lib/asn1/src/asn1rtt_real_common.erl b/lib/asn1/src/asn1rtt_real_common.erl
index 22a1f4c4dd..12ca165ecd 100644
--- a/lib/asn1/src/asn1rtt_real_common.erl
+++ b/lib/asn1/src/asn1rtt_real_common.erl
@@ -105,8 +105,7 @@ encode_real(_C, {Mantissa, Base, Exponent}) when Base =:= 2 ->
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)};
+ <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>;
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
@@ -176,8 +175,7 @@ encode_real_as_string(_C, Mantissa, Exponent)
end,
ManBin = list_to_binary(TruncMant),
NR3 = 3,
- {<<NR3,ManBin/binary,$.,ExpBin/binary>>,
- 2 + byte_size(ManBin) + byte_size(ExpBin)}.
+ <<NR3,ManBin/binary,$.,ExpBin/binary>>.
remove_trailing_zeros(IntStr) ->
case lists:dropwhile(fun($0)-> true;
diff --git a/lib/asn1/src/asn1rtt_uper.erl b/lib/asn1/src/asn1rtt_uper.erl
index a5035c6660..68a89c70e1 100644
--- a/lib/asn1/src/asn1rtt_uper.erl
+++ b/lib/asn1/src/asn1rtt_uper.erl
@@ -19,95 +19,8 @@
%%
-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).
+-export([skipextensions/3]).
+-export([complete/1, complete_NFP/1]).
skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
Prev = Nr - 1,
@@ -122,249 +35,6 @@ skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(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};
@@ -373,575 +43,20 @@ decode_length(<<2:2,Val:14,Rest/bitstring>>) ->
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
+ case list_to_bitstring(InList) of
<<>> ->
<<0>>;
Res ->
- case bit_size(Res) band 7 of
+ Sz = bit_size(Res),
+ case Sz band 7 of
0 -> Res;
- Bits -> <<Res/bitstring,0:(8-Bits)>>
+ Bits -> <<Res:Sz/bitstring,0:(8-Bits)>>
end
end;
complete(Bin) when is_binary(Bin) ->
@@ -950,24 +65,12 @@ complete(Bin) when is_binary(Bin) ->
_ -> 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).
+ Sz = bit_size(InList),
+ PadLen = 8 - (Sz band 7),
+ <<InList:Sz/bitstring,0:PadLen>>.
%% 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
index 83155b2e52..ccd15548d8 100644
--- a/lib/asn1/src/prepare_templates.erl
+++ b/lib/asn1/src/prepare_templates.erl
@@ -21,69 +21,77 @@
-export([gen_asn1ct_rtt/1,gen_asn1ct_eval/1]).
gen_asn1ct_rtt(Ms) ->
- io:format("%% Generated by ~s. DO NOT EDIT THIS FILE.\n"
+ {ok,Fd} = file:open("asn1ct_rtt.erl", [write]),
+ io:format(Fd,
+ "%% 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"
+ [io:put_chars(Fd, ["%% ",M,$\n]) || M <- Ms],
+ io:nl(Fd),
+ io:put_chars(Fd,
+ "-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(),
+ defined(Fd, Exp),
+ io:nl(Fd),
Calls = calls(Forms),
R = sofs:relation(Calls),
Fam0 = sofs:relation_to_family(R),
Fam = sofs:to_external(Fam0),
- dependencies(Fam),
- io:nl(),
+ dependencies(Fd, Fam),
+ io:nl(Fd),
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]),
+ io:format(Fd, "code() ->\n~p.\n\n", [Funcs]),
+ ok = file:close(Fd),
halt(0).
gen_asn1ct_eval([File]) ->
+ Output = filename:rootname(File, ".funcs") ++ ".erl",
+ {ok,Fd} = file:open(Output, [write]),
{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"
+ io:format(Fd,
+ "%% 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()),
+ io:format(Fd, "-module(~s).\n", [filename:rootname(File)]),
+ gen_asn1ct_eval_exp(Fd, Funcs),
+ asn1ct_func:generate(Fd),
+ ok = file:close(Fd),
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(Fd, Funcs) ->
+ io:put_chars(Fd, "-export(["),
+ gen_asn1ct_eval_exp_1(Fd, Funcs, ""),
+ io:put_chars(Fd, "]).\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.
+gen_asn1ct_eval_exp_1(Fd, [{_,F,A}|T], Sep) ->
+ io:put_chars(Fd, Sep),
+ io:format(Fd, "~p/~p", [F,A]),
+ gen_asn1ct_eval_exp_1(Fd, T, ",\n");
+gen_asn1ct_eval_exp_1(_, [], _) -> ok.
-defined([H|T]) ->
- io:format("assert_defined(~p) -> ok", [H]),
+defined(Fd, [H|T]) ->
+ io:format(Fd, "assert_defined(~p) -> ok", [H]),
case T of
[] ->
- io:put_chars(".\n");
+ io:put_chars(Fd, ".\n");
[_|_] ->
- io:put_chars(";\n"),
- defined(T)
+ io:put_chars(Fd, ";\n"),
+ defined(Fd, T)
end.
-dependencies([{K,V}|T]) ->
- io:format("dependencies(~p) ->\n~p;\n", [K,V]),
- dependencies(T);
-dependencies([]) ->
- io:put_chars("dependencies(_) -> [].\n").
+dependencies(Fd, [{K,V}|T]) ->
+ io:format(Fd, "dependencies(~p) ->\n~p;\n", [K,V]),
+ dependencies(Fd, T);
+dependencies(Fd, []) ->
+ io:put_chars(Fd, "dependencies(_) -> [].\n").
abstract(File) ->
{ok,{M0,[{abstract_code,Abstract}]}} =
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index 15b97df972..b1b08aa9f9 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -26,7 +26,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
h323test \
- choice_extension \
ber_decode_error \
testPrim \
testPrimStrings \
@@ -36,7 +35,6 @@ MODULES= \
testChoExtension \
testChoExternal \
testChoOptional \
- testChoOptionalImplicitTag \
testChoRecursive \
testChoTypeRefCho \
testChoTypeRefPrim \
@@ -51,12 +49,12 @@ MODULES= \
testSeqOptional \
testSeq2738 \
testSeqPrim \
+ testSeqSetIndefinite \
testSeqTag \
testSeqTypeRefCho \
testSeqTypeRefPrim \
testSeqTypeRefSeq \
testSeqTypeRefSet \
- testSeqIndefinite \
testSeqOf \
testSeqOfIndefinite \
testSeqOfCho \
@@ -72,7 +70,6 @@ MODULES= \
testSetTypeRefPrim \
testSetTypeRefSeq \
testSetTypeRefSet \
- testSetIndefinite \
testChoiceIndefinite \
testSetOf \
testSetOfCho \
@@ -82,6 +79,7 @@ MODULES= \
testInfObjectClass \
testInfObj \
testParameterizedInfObj \
+ testFragmented \
testMergeCompile \
testMultipleLevels \
testDeepTConstr \
@@ -99,7 +97,6 @@ MODULES= \
test_special_decode_performance \
testTCAP \
testSSLspecs \
- test_driver_load \
testSelectionTypes \
test_undecoded_rest \
testTcapsystem \
@@ -113,12 +110,9 @@ MODULES= \
asn1_test_lib \
asn1_app_test \
asn1_appup_test \
- asn1_wrapper \
asn1_SUITE \
error_SUITE
-SUITE= asn1_SUITE.erl
-
ERL_FILES= $(MODULES:%=%.erl)
HRL_FILES= External.hrl
@@ -143,7 +137,7 @@ EBIN = .
$(EMAKEFILE): $(ERL_FILES) $(HRL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) $(ERL_FILES) >$(EMAKEFILE)
-tests debug opt: $(SUITE) $(SUITE_BIN) $(SUITE_BIN_V2) $(EMAKEFILE)
+tests debug opt: $(EMAKEFILE)
clean:
rm -f core
@@ -160,7 +154,7 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DIR) "$(RELSYSDIR)/asn1_SUITE_data"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) asn1.spec asn1.cover $(INSTALL_PROGS) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
cd asn1_SUITE_data; tar cfh "$(RELSYSDIR)/asn1_SUITE_data.tar" *
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index f00b23a8b2..432197eec0 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -50,27 +50,29 @@ all() ->
{group, performance}].
groups() ->
- [{compile, parallel([]),
+ Parallel = asn1_test_lib:parallel(),
+ [{compile, Parallel,
[c_syntax,
c_string,
c_implicit_before_choice,
constraint_equivalence]},
- {ber, parallel([]),
+ {ber, Parallel,
[ber_choiceinseq,
% Uses 'SOpttest'
- ber_optional]},
+ ber_optional,
+ tagdefault_automatic]},
{app_test, [], [{asn1_app_test, all}]},
{appup_test, [], [{asn1_appup_test, all}]},
- {parallel, parallel([]),
+ {parallel, Parallel,
[cover,
+ xref,
{group, ber},
% Uses 'P-Record', 'Constraints', 'MEDIA-GATEWAY-CONTROL'...
{group, [], [parse,
- test_driver_load,
test_undecoded_rest,
specialized_decodes,
special_decode_performance,
@@ -83,38 +85,24 @@ groups() ->
{group, [], [testPrim,
rtUI,
testPrimStrings,
- testInvokeMod,
per,
ber_other,
der,
- h323test,
- per_GeneralString]},
+ h323test]},
testChoPrim,
testChoExtension,
testChoOptional,
- testChoOptionalImplicitTag,
testChoRecursive,
testChoTypeRefCho,
testChoTypeRefPrim,
testChoTypeRefSeq,
testChoTypeRefSet,
testMultipleLevels,
- testDef,
testOpt,
testSeqDefault,
% Uses 'External'
- {group, [], [testChoExternal,
- testPrimExternal,
- testSeqExtension,
- testSeqExternal,
- testSeqOfExternal,
- testSeqOfTag,
- testSeqTag,
- testSetExtension,
- testSetExternal,
- testSetOfExternal,
- testSetOfTag,
- testSetTag]},
+ {group, [], [testExternal,
+ testSeqExtension]},
testSeqOptional,
testSeqPrim,
testSeqTypeRefCho,
@@ -143,21 +131,19 @@ groups() ->
% Uses 'Constructed'
{group, [], [constructed,
ber_decode_error]},
- % Uses 'SeqSetIndefinite'
- {group, [], [testSeqIndefinite,
- testSetIndefinite]},
+ testSeqSetIndefinite,
testChoiceIndefinite,
per_open_type,
testInfObjectClass,
- testParameterizedInfObj,
+ testParam,
+ testFragmented,
testMergeCompile,
testobj,
testDeepTConstr,
testExport,
testImport,
- % Uses 'ParamBasic'
- {group, [], [testParamBasic,
- testDER]},
+ testDER,
+ testDEFAULT,
testMvrasn6,
testContextSwitchingTypes,
testOpenTypeImplicitTag,
@@ -186,15 +172,7 @@ groups() ->
{performance, [],
[testTimer_ber,
testTimer_per,
- testTimer_uper,
- smp]}].
-
-parallel(Options) ->
- case erlang:system_info(smp_support) andalso
- erlang:system_info(schedulers) > 1 of
- true -> [parallel|Options];
- false -> Options
- end.
+ testTimer_uper]}].
%%------------------------------------------------------------------------------
%% Init/end
@@ -284,13 +262,6 @@ replace_path(PathA, PathB) ->
join(Rule, Opts) ->
string:join([atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)], "_").
-case_dir([], _Dir) ->
- exit(no_case_dir);
-case_dir([{case_dir, _}|Config], Dir) ->
- [{case_dir, Dir}|Config];
-case_dir([C|Config], Opt) ->
- [C|case_dir(Config, Opt)].
-
%%------------------------------------------------------------------------------
%% Test cases
%%------------------------------------------------------------------------------
@@ -319,7 +290,15 @@ cover(_) ->
testPrim(Config) -> test(Config, fun testPrim/3).
testPrim(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["Prim", "Real"], Config, [Rule|Opts]),
+ Files = ["Prim","Real"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ do_test_prim(Rule, false),
+ asn1_test_lib:compile_all(Files, Config, [no_ok_wrapper,Rule|Opts]),
+ do_test_prim(Rule, true).
+
+do_test_prim(Rule, NoOkWrapper) ->
+ io:format("No ok wrapper: ~p\n", [NoOkWrapper]),
+ put(no_ok_wrapper, NoOkWrapper),
testPrim:bool(Rule),
testPrim:int(Rule),
testPrim:enum(Rule),
@@ -340,37 +319,61 @@ testCompactBitString(Config, Rule, Opts) ->
[Rule, compact_bit_string|Opts]),
testCompactBitString:otp_4869(Rule).
-testPrimStrings(Config) -> test(Config, fun testPrimStrings/3).
+testPrimStrings(Config) ->
+ test(Config, fun testPrimStrings/3, [ber,{ber,[der]},per,uper]).
testPrimStrings(Config, Rule, Opts) ->
+ LegacyOpts = [legacy_erlang_types|Opts],
+ asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
+ [Rule|LegacyOpts]),
+ testPrimStrings_cases(Rule, LegacyOpts),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]),
- testPrimStrings_cases(Rule),
+ testPrimStrings_cases(Rule, Opts),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
[legacy_bit_string,Rule|Opts]),
- testPrimStrings:bit_string(Rule),
+ testPrimStrings:bit_string(Rule, Opts),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
[compact_bit_string,Rule|Opts]),
- testPrimStrings:bit_string(Rule),
+ testPrimStrings:bit_string(Rule, Opts),
testPrimStrings:more_strings(Rule).
-testPrimStrings_cases(Rule) ->
- testPrimStrings:bit_string(Rule),
+testPrimStrings_cases(Rule, Opts) ->
+ testPrimStrings:bit_string(Rule, Opts),
testPrimStrings:octet_string(Rule),
testPrimStrings:numeric_string(Rule),
testPrimStrings:other_strings(Rule),
testPrimStrings:universal_string(Rule),
testPrimStrings:bmp_string(Rule),
testPrimStrings:times(Rule),
- testPrimStrings:utf8_string(Rule).
+ testPrimStrings:utf8_string(Rule),
+ testPrimStrings:fragmented(Rule).
-testPrimExternal(Config) -> test(Config, fun testPrimExternal/3).
-testPrimExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "PrimExternal"], Config,
- [Rule|Opts]),
+testExternal(Config) -> test(Config, fun testExternal/3).
+testExternal(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["External",
+ "ChoExternal",
+ "PrimExternal",
+ "SeqExternal",
+ "SeqOfExternal",
+ "SeqOfTag",
+ "SeqTag",
+ "SetExtension",
+ "SetExternal",
+ "SetOfExternal",
+ "SetOfTag",
+ "SetTag"],
+ Config, [Rule|Opts]),
+ testChoExternal:external(Rule),
testPrimExternal:external(Rule),
- asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
- [Rule|Opts]),
- testPrimStrings_cases(Rule),
- testPrimStrings:more_strings(Rule).
+ testSeqExternal:main(Rule),
+ testSeqOfExternal:main(Rule),
+ testSeqOfTag:main(Rule),
+ testSeqTag:main(Rule),
+ testSetExtension:main(Rule),
+ testSetExternal:main(Rule),
+ testSetOfExternal:main(Rule),
+ testSetOfTag:main(Rule),
+ testSetTag:main(Rule).
+
testChoPrim(Config) -> test(Config, fun testChoPrim/3).
testChoPrim(Config, Rule, Opts) ->
@@ -383,23 +386,11 @@ testChoExtension(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoExtension", Config, [Rule|Opts]),
testChoExtension:extension(Rule).
-testChoExternal(Config) -> test(Config, fun testChoExternal/3).
-testChoExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "ChoExternal"], Config, [Rule|Opts]),
- testChoExternal:external(Rule).
-
testChoOptional(Config) -> test(Config, fun testChoOptional/3).
testChoOptional(Config, Rule, Opts) ->
- asn1_test_lib:compile("ChoOptional", Config, [Rule|Opts]),
- testChoOptional:optional(Rule).
-
-testChoOptionalImplicitTag(Config) ->
- test(Config, fun testChoOptionalImplicitTag/3,
- [ber]).
-testChoOptionalImplicitTag(Config, Rule, Opts) ->
- %% Only meaningful for ber & co
- asn1_test_lib:compile("ChoOptionalImplicitTag", Config, [Rule|Opts]),
- testChoOptionalImplicitTag:optional(Rule).
+ asn1_test_lib:compile_all(["ChoOptional",
+ "ChoOptionalImplicitTag"], Config, [Rule|Opts]),
+ testChoOptional:run().
testChoRecursive(Config) -> test(Config, fun testChoRecursive/3).
testChoRecursive(Config, Rule, Opts) ->
@@ -431,10 +422,16 @@ 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]),
- testDef:main(Rule).
+testDEFAULT(Config) ->
+ test(Config, fun testDEFAULT/3, [ber,{ber,[der]},per,uper]).
+testDEFAULT(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["Def","Default"], Config, [Rule|Opts]),
+ testDef:main(Rule),
+ testSeqSetDefaultVal:main(Rule, Opts),
+ asn1_test_lib:compile_all(["Def","Default"], Config,
+ [legacy_erlang_types,Rule|Opts]),
+ testDef:main(Rule),
+ testSeqSetDefaultVal:main(Rule, Opts).
testOpt(Config) -> test(Config, fun testOpt/3).
testOpt(Config, Rule, Opts) ->
@@ -452,7 +449,7 @@ testSeqDefault(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqDefault", Config, [Rule|Opts]),
testSeqDefault:main(Rule).
-testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
+testSeqExtension(Config) -> test(Config, fun testSeqExtension/3, [ber,uper]).
testSeqExtension(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External",
"SeqExtension",
@@ -462,11 +459,6 @@ testSeqExtension(Config, Rule, Opts) ->
DataDir = ?config(data_dir, Config),
testSeqExtension:main(Rule, DataDir, [Rule|Opts]).
-testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
-testSeqExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqExternal"], Config, [Rule|Opts]),
- testSeqExternal:main(Rule).
-
testSeqOptional(Config) -> test(Config, fun testSeqOptional/3).
testSeqOptional(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqOptional", Config, [Rule|Opts]),
@@ -483,11 +475,6 @@ testSeq2738(Config, Rule, Opts) ->
asn1_test_lib:compile("Seq2738", Config, [Rule|Opts]),
testSeq2738:main(Rule).
-testSeqTag(Config) -> test(Config, fun testSeqTag/3).
-testSeqTag(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqTag"], Config, [Rule|Opts]),
- testSeqTag:main(Rule).
-
testSeqTypeRefCho(Config) -> test(Config, fun testSeqTypeRefCho/3).
testSeqTypeRefCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqTypeRefCho", Config, [Rule|Opts]),
@@ -528,38 +515,11 @@ testSeqOfIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
testSeqOfIndefinite:main().
-testSeqOfExternal(Config) -> test(Config, fun testSeqOfExternal/3).
-testSeqOfExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqOfExternal"], Config,
- [Rule|Opts]),
- testSeqOfExternal:main(Rule).
-
-testSeqOfTag(Config) -> test(Config, fun testSeqOfTag/3).
-testSeqOfTag(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqOfTag"], Config, [Rule|Opts]),
- testSeqOfTag:main(Rule).
-
testSetDefault(Config) -> test(Config, fun testSetDefault/3).
testSetDefault(Config, Rule, Opts) ->
asn1_test_lib:compile("SetDefault", Config, [Rule|Opts]),
testSetDefault:main(Rule).
-testParamBasic(Config) -> test(Config, fun testParamBasic/3).
-testParamBasic(Config, Rule, Opts) ->
- asn1_test_lib:compile("ParamBasic", Config, [Rule|Opts]),
- testParamBasic:main(Rule).
-
-testSetExtension(Config) -> test(Config, fun testSetExtension/3).
-testSetExtension(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SetExtension"], Config,
- [Rule|Opts]),
- testSetExtension:main(Rule).
-
-testSetExternal(Config) -> test(Config, fun testSetExternal/3).
-testSetExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SetExternal"], Config, [Rule|Opts]),
- testSetExternal:main(Rule).
-
testSetOptional(Config) -> test(Config, fun testSetOptional/3).
testSetOptional(Config, Rule, Opts) ->
asn1_test_lib:compile("SetOptional", Config, [Rule|Opts]),
@@ -571,11 +531,6 @@ testSetPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("SetPrim", Config, [Rule|Opts]),
testSetPrim:main(Rule).
-testSetTag(Config) -> test(Config, fun testSetTag/3).
-testSetTag(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SetTag"], Config, [Rule|Opts]),
- testSetTag:main(Rule).
-
testSetTypeRefCho(Config) -> test(Config, fun testSetTypeRefCho/3).
testSetTypeRefCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SetTypeRefCho", Config, [Rule|Opts]),
@@ -606,17 +561,6 @@ testSetOfCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SetOfCho", Config, [Rule|Opts]),
testSetOfCho:main(Rule).
-testSetOfExternal(Config) -> test(Config, fun testSetOfExternal/3).
-testSetOfExternal(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SetOfExternal"], Config,
- [Rule|Opts]),
- testSetOfExternal:main(Rule).
-
-testSetOfTag(Config) -> test(Config, fun testSetOfTag/3).
-testSetOfTag(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SetOfTag"], Config, [Rule|Opts]),
- testSetOfTag:main(Rule).
-
c_syntax(Config) ->
DataDir = ?config(data_dir, Config),
[{error, _} = asn1ct:compile(filename:join(DataDir, F))
@@ -714,10 +658,20 @@ ber_optional(Config, Rule, Opts) ->
V = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
{'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE},
{'C', asn1_NOVALUE, 111, asn1_NOVALUE}},
- {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V),
- Bytes = lists:flatten(B),
- V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
- V = element(2, V2).
+ asn1_test_lib:roundtrip('SOpttest', 'S', V).
+
+tagdefault_automatic(Config) ->
+ test(Config, fun tagdefault_automatic/3, [ber]).
+tagdefault_automatic(Config, Rule, Opts) ->
+ asn1_test_lib:compile("TAGDEFAULT-AUTOMATIC", Config, [Rule|Opts]),
+ << 48,8,128,2,100,101,129,2,110,111 >> =
+ asn1_test_lib:roundtrip_enc('TAGDEFAULT-AUTOMATIC', 'Tagged', {'Tagged', << 100,101 >>, << 110,111 >>}),
+ << 48,8,128,2,100,101,129,2,110,111 >> =
+ asn1_test_lib:roundtrip_enc('TAGDEFAULT-AUTOMATIC', 'Untagged', {'Untagged', << 100,101 >>, << 110,111 >>}),
+ << 48,8,4,2,100,101,130,2,110,111 >> =
+ asn1_test_lib:roundtrip_enc('TAGDEFAULT-AUTOMATIC', 'Mixed', {'Mixed', << 100,101 >>, << 110,111 >>}),
+
+ ok.
%% records used by test-case default
-record('Def1', {bool0,
@@ -728,14 +682,16 @@ ber_optional(Config, Rule, Opts) ->
default(Config) -> test(Config, fun default/3).
default(Config, Rule, Opts) ->
asn1_test_lib:compile("Def", Config, [Rule|Opts]),
- {ok, Bytes1} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true}),
- {ok, {'Def1', true, false, false, false}} =
- asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes1)),
-
- {ok, Bytes2} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true,
- bool2 = false}),
- {ok, {'Def1', true, false, false, false}} =
- asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes2)).
+ asn1_test_lib:roundtrip('Def',
+ 'Def1',
+ #'Def1'{bool0=true},
+ #'Def1'{bool0=true,bool1=false,
+ bool2=false,bool3=false}),
+ asn1_test_lib:roundtrip('Def',
+ 'Def1',
+ #'Def1'{bool0=true,bool2=false},
+ #'Def1'{bool0=true,bool1=false,
+ bool2=false,bool3=false}).
value_test(Config) -> test(Config, fun value_test/3).
value_test(Config, Rule, Opts) ->
@@ -747,12 +703,13 @@ constructed(Config) ->
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}),
- [40, 3, 1, 1, 0] = lists:flatten(B),
- {ok, B1} = asn1_wrapper:encode('Constructed', 'S2', {'S2', false}),
- [40, 5, 48, 3, 1, 1, 0] = lists:flatten(B1),
- {ok, B2} = asn1_wrapper:encode('Constructed', 'I', 10),
- [136, 1, 10] = lists:flatten(B2).
+ <<40,3,1,1,0>> =
+ asn1_test_lib:roundtrip_enc('Constructed', 'S', {'S',false}),
+ <<40,5,48,3,1,1,0>> =
+ asn1_test_lib:roundtrip_enc('Constructed', 'S2', {'S2',false}),
+ <<136,1,10>> =
+ asn1_test_lib:roundtrip_enc('Constructed', 'I', 10),
+ ok.
ber_decode_error(Config) ->
test(Config, fun ber_decode_error/3, [ber]).
@@ -767,14 +724,6 @@ h323test(Config, Rule, Opts) ->
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
h323test:run(Rule).
-per_GeneralString(Config) ->
- 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_open_type(Config, Rule, Opts) ->
asn1_test_lib:compile("OpenType", Config, [Rule|Opts]),
@@ -784,24 +733,17 @@ testConstraints(Config) -> test(Config, fun testConstraints/3).
testConstraints(Config, Rule, Opts) ->
asn1_test_lib:compile("Constraints", Config, [Rule|Opts]),
asn1_test_lib:compile("LargeConstraints", Config, [Rule|Opts]),
- testConstraints:int_constraints(Rule).
-
-
-testSeqIndefinite(Config) ->
- 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]).
+ testConstraints:int_constraints(Rule),
+ case Rule of
+ ber -> ok;
+ _ -> testConstraints:refed_NNL_name(Rule)
+ end.
-testSetIndefinite(Config, Rule, Opts) ->
+testSeqSetIndefinite(Config) ->
+ test(Config, fun testSeqSetIndefinite/3, [ber]).
+testSeqSetIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
- testSetIndefinite:main(Rule).
-
+ testSeqSetIndefinite:main().
testChoiceIndefinite(Config) ->
test(Config, fun testChoiceIndefinite/3, [ber]).
@@ -823,12 +765,22 @@ testInfObjectClass(Config, Rule, Opts) ->
testInfObjectClass:main(Rule),
testInfObj:main(Rule).
-testParameterizedInfObj(Config) ->
- test(Config, fun testParameterizedInfObj/3).
-testParameterizedInfObj(Config, Rule, Opts) ->
- Files = ["Param","Param2"],
+testParam(Config) ->
+ test(Config, fun testParam/3, [ber,{ber,[der]},per,uper]).
+testParam(Config, Rule, Opts) ->
+ Files = ["ParamBasic","Param","Param2"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
- testParameterizedInfObj:main(Config, Rule).
+ testParamBasic:main(Rule),
+ testParameterizedInfObj:main(Config, Rule),
+ asn1_test_lib:compile("Param", Config,
+ [legacy_erlang_types,Rule|Opts]),
+ testParameterizedInfObj:param(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) ->
@@ -840,7 +792,8 @@ testMergeCompile(Config, Rule, Opts) ->
testobj(Config) -> test(Config, fun testobj/3).
testobj(Config, Rule, Opts) ->
- asn1_test_lib:compile("RANAP", Config, [Rule|Opts]),
+ asn1_test_lib:compile("RANAP", Config, [legacy_erlang_types,
+ Rule|Opts]),
asn1_test_lib:compile_erlang("testobj", Config, []),
ok = testobj:run(),
ok = testParameterizedInfObj:ranap(Rule).
@@ -851,11 +804,6 @@ testDeepTConstr(Config, Rule, Opts) ->
[Rule|Opts]),
testDeepTConstr:main(Rule).
-testInvokeMod(Config) -> test(Config, fun testInvokeMod/3).
-testInvokeMod(Config, Rule, Opts) ->
- asn1_test_lib:compile("PrimStrings", Config, [Rule|Opts]),
- {ok, _Result2} = 'PrimStrings':encode('Bs1', [1, 0, 1, 0]).
-
testExport(Config) ->
{error, _} =
asn1ct:compile(filename:join(?config(data_dir, Config),
@@ -865,14 +813,15 @@ testExport(Config) ->
testImport(Config) ->
test(Config, fun testImport/3).
testImport(Config, Rule, Opts) ->
- {error, _} = asn1ct:compile(filename:join(?config(data_dir, Config),
- "ImportsFrom"),
- [Rule, {outdir, ?config(priv_dir, Config)}
- |Opts]).
+ Files = ["ImportsFrom","ImportsFrom2","ImportsFrom3"],
+ asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
+ 42 = 'ImportsFrom':i(),
+ ok.
testMegaco(Config) -> test(Config, fun testMegaco/3).
testMegaco(Config, Rule, Opts) ->
- {ok, Module1, Module2} = testMegaco:compile(Config, Rule, Opts),
+ {ok, Module1, Module2} = testMegaco:compile(Config, Rule,
+ [legacy_erlang_types|Opts]),
ok = testMegaco:main(Module1, Config),
ok = testMegaco:main(Module2, Config).
@@ -911,7 +860,10 @@ duplicate_tags(Config) ->
rtUI(Config) -> test(Config, fun rtUI/3).
rtUI(Config, Rule, Opts) ->
asn1_test_lib:compile("Prim", Config, [Rule|Opts]),
- {ok, _} = asn1rt:info('Prim').
+ _ = 'Prim':info(),
+ Rule = 'Prim':encoding_rule(),
+ io:format("Default BIT STRING format: ~p\n",
+ ['Prim':bit_string_format()]).
testROSE(Config) -> test(Config, fun testROSE/3).
testROSE(Config, Rule, Opts) ->
@@ -939,11 +891,7 @@ testDER(Config) ->
test(Config, fun testDER/3, [ber]).
testDER(Config, Rule, Opts) ->
asn1_test_lib:compile("DERSpec", Config, [Rule, der|Opts]),
- testDER:test(),
- asn1_test_lib:compile("ParamBasic", Config, [Rule, der|Opts]),
- testParamBasic:main(der),
- asn1_test_lib:compile("Default", Config, [Rule, der|Opts]),
- testSeqSetDefaultVal:main(Rule).
+ testDER:test().
specialized_decodes(Config) ->
test(Config, fun specialized_decodes/3, [ber]).
@@ -954,7 +902,8 @@ specialized_decodes(Config, Rule, Opts) ->
"PartialDecMyHTTP.asn",
"MEDIA-GATEWAY-CONTROL.asn",
"P-Record"],
- Config, [Rule, asn1config|Opts]),
+ Config,
+ [Rule,legacy_erlang_types,asn1config|Opts]),
test_partial_incomplete_decode:test(Config),
test_selective_decode:test().
@@ -965,13 +914,6 @@ special_decode_performance(Config, Rule, Opts) ->
asn1_test_lib:compile_all(Files, Config, [Rule, asn1config|Opts]),
test_special_decode_performance:go(all).
-
-test_driver_load(Config) ->
- 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]).
@@ -989,7 +931,7 @@ test_Defed_ObjectIdentifier(Config, Rule, Opts) ->
testSelectionType(Config) -> test(Config, fun testSelectionType/3).
testSelectionType(Config, Rule, Opts) ->
asn1_test_lib:compile("SelectionType", Config, [Rule|Opts]),
- {ok, _} = testSelectionTypes:test().
+ testSelectionTypes:test().
testSSLspecs(Config) ->
test(Config, fun testSSLspecs/3, [ber]).
@@ -1006,10 +948,14 @@ testNortel(Config, Rule, Opts) ->
test_undecoded_rest(Config) -> test(Config, fun test_undecoded_rest/3).
test_undecoded_rest(Config, Rule, Opts) ->
+ do_test_undecoded_rest(Config, Rule, Opts),
+ do_test_undecoded_rest(Config, Rule, [no_ok_wrapper|Opts]),
+ do_test_undecoded_rest(Config, Rule, [undec_rest|Opts]),
+ do_test_undecoded_rest(Config, Rule, [no_ok_wrapper,undec_rest|Opts]).
+
+do_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]),
- test_undecoded_rest:test(undec_rest, Config).
+ test_undecoded_rest:test(Opts, Config).
testTcapsystem(Config) ->
test(Config, fun testTcapsystem/3).
@@ -1029,7 +975,20 @@ testS1AP(Config, Rule, Opts) ->
"S1AP-IEs",
"S1AP-PDU-Contents",
"S1AP-PDU-Descriptions"],
- asn1_test_lib:compile_all(S1AP, Config, [Rule|Opts]).
+ asn1_test_lib:compile_all(S1AP, Config, [Rule|Opts]),
+
+ %% OTP-7876.
+ case Rule of
+ per ->
+ Enc = <<0,2,64,49,0,0,5,0,0,0,4,128,106,56,197,0,8,0,3,64,2,134,0,
+ 100,64,8,0,66,240,153,0,7,192,16,0,67,64,6,0,66,240,153,70,
+ 1,0,107,64,5,0,0,0,0,0>>,
+ {ok,{initiatingMessage,_}} = 'S1AP-PDU-Descriptions':decode('S1AP-PDU', Enc);
+ uper ->
+ ok;
+ ber ->
+ ok
+ end.
test_compile_options(Config) ->
ok = test_compile_options:wrong_path(Config),
@@ -1061,24 +1020,39 @@ testX420(Config) ->
"sparc-sun-solaris2.10" ->
{skip,"Too slow for an old Sparc"};
_ ->
- test(Config, fun testX420/3, [ber])
+ Rule = ber,
+ testX420:compile(Rule, [der], Config),
+ ok = testX420:ticket7759(Rule, Config)
end.
-testX420(Config, Rule, Opts) ->
- testX420:compile(Rule, [der|Opts], Config),
- ok = testX420:ticket7759(Rule, Config),
- testX420:compile(Rule, Opts, Config).
test_x691(Config) ->
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 -> unaligned;
- _ -> aligned
- end),
- asn1_test_lib:ticket_7708(Config, []),
- asn1_test_lib:ticket_7763(Config).
+ test_x691:cases(Rule),
+
+ %% OTP-7708.
+ asn1_test_lib:compile("EUTRA-extract-55", Config,
+ [legacy_erlang_types,Rule|Opts]),
+
+ %% OTP-7763.
+ Val = {'Seq',15,lists:duplicate(8, 0),[0],lists:duplicate(28, 0),15,true},
+ CompactVal = {'Seq',15,{0,<<0>>},{7,<<0>>},{4,<<0,0,0,0>>},15,true},
+ {ok,Bin} = 'EUTRA-extract-55':encode('Seq', Val),
+ {ok,Bin} = 'EUTRA-extract-55':encode('Seq', CompactVal),
+
+ %% OTP-7678.
+ asn1_test_lib:compile("UPERDefault", Config, [Rule|Opts]),
+ DefVal = 'UPERDefault':seq(),
+ {ok,DefBin} = 'UPERDefault':encode('Seq', DefVal),
+ {ok,DefVal} = 'UPERDefault':decode('Seq', DefBin),
+ case Rule of
+ uper -> <<0,6,0>> = DefBin;
+ _ -> ok
+ end,
+
+ ok.
ticket_6143(Config) ->
ok = test_compile_options:ticket_6143(Config).
@@ -1166,29 +1140,27 @@ END
ok = asn1ct:compile(File, [{outdir, PrivDir}]).
-timer_compile(Config, Rule, Opts) ->
+timer_compile(Config, Rule) ->
asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"],
- Config, [Rule|Opts]).
+ Config, [no_ok_wrapper,Rule]).
testTimer_ber(Config) ->
- timer_compile(Config,ber,[]),
- testTimer:go(Config,ber).
+ timer_compile(Config, ber),
+ testTimer:go().
testTimer_per(Config) ->
- timer_compile(Config,per,[]),
- testTimer:go(Config,per).
+ timer_compile(Config, per),
+ testTimer:go().
testTimer_uper(Config) ->
- timer_compile(Config,uper,[]),
- {comment,_} = testTimer:go(Config,uper).
+ timer_compile(Config, uper),
+ testTimer:go().
%% Test of multiple-line comment, OTP-8043
testComment(suite) -> [];
testComment(Config) ->
asn1_test_lib:compile("Comment", Config, []),
- {ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}),
- {ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc),
- ok.
+ asn1_test_lib:roundtrip('Comment', 'Seq', {'Seq',12,true}).
testName2Number(suite) -> [];
testName2Number(Config) ->
@@ -1224,76 +1196,67 @@ testName2Number(Config) ->
ticket_7407(Config) ->
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, no_final_padding]),
- asn1_test_lib:ticket_7407_code(false).
-
-smp(suite) -> [];
-smp(Config) ->
- case erlang:system_info(smp_support) of
- true ->
- NumOfProcs = erlang:system_info(schedulers),
- io:format("smp starting ~p workers\n",[NumOfProcs]),
-
- Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
- ok = testNBAPsystem:compile(Config, [per]),
-
- enc_dec(NumOfProcs,Msg,2),
-
- N = 10000,
-
- {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]),
- {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
-
- {Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
-
- {comment,lists:flatten(
- io_lib:format(
- "Encode/decode time parallell with ~p cores: ~p [microsecs]~n"
- "Encode/decode time sequential: ~p [microsecs]",
- [NumOfProcs,Time1+Time3,Time1S+Time3S]))};
- false ->
- {skipped,"No smp support"}
- end.
-
-enc_dec(1, Msg, N) ->
- worker_loop(N, Msg);
-enc_dec(NumOfProcs,Msg, N) ->
- pforeach(fun(_) ->
- worker_loop(N, Msg)
- end, [I || I <- lists:seq(1,NumOfProcs)]).
-
-worker_loop(0, _Msg) ->
- ok;
-worker_loop(N, Msg) ->
- {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg),
- {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
- worker_loop(N - 1, Msg).
-
-
-pforeach(Fun, List) ->
- pforeach(Fun, List, []).
-pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
- receive
- {'DOWN', Ref, process, Pid, normal} ->
- pforeach(Fun, [], Pids)
- end;
-pforeach(Fun, [H|T], Pids) ->
- Pid = spawn(fun() -> Fun(H) end),
- Ref = erlang:monitor(process, Pid),
- pforeach(Fun, T, [{Pid, Ref}|Pids]);
-pforeach(_Fun,[],[]) ->
+ ticket_7407_code(true),
+ asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper,no_final_padding]),
+ ticket_7407_code(false).
+
+ticket_7407_code(FinalPadding) ->
+ Msg1 = {Type1,_} = eutra1(msg),
+ {ok,B1} = 'EUTRA-extract-7407':encode(Type1, Msg1),
+ B1 = eutra1(result, FinalPadding),
+
+ Msg2 = {Type2,_} = eutra2(msg),
+ {ok,B2} = 'EUTRA-extract-7407':encode(Type2, Msg2),
+ B2 = eutra2(result, FinalPadding),
ok.
+eutra1(msg) ->
+ {'BCCH-BCH-Message',
+ {'MasterInformationBlock',<<2#0101:4>>,<<2#1010:4>>,
+ {'PHICH-Configuration',short,ffs},<<2#10100000>>}}.
+
+eutra1(result, true) ->
+ <<90,80,0>>;
+eutra1(result, false) ->
+ <<90,80,0:1>>.
+
+eutra2(msg) ->
+ {'BCCH-DL-SCH-Message',
+ {c1,
+ {systemInformation1,
+ {'SystemInformationBlockType1',
+ {'SystemInformationBlockType1_cellAccessRelatedInformation',
+ [{'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',
+ {'PLMN-Identity'},true},
+ {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',
+ {'PLMN-Identity'},false},
+ {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',
+ {'PLMN-Identity'},true}],
+ {'TrackingAreaCode'},
+ {'CellIdentity'},
+ false,
+ true,
+ true,
+ true
+ },
+ {'SystemInformationBlockType1_cellSelectionInfo',-50},
+ 24,
+ [{'SystemInformationBlockType1_schedulinInformation_SEQOF',
+ {'SystemInformationBlockType1_schedulinInformation_SEQOF_si-MessageType'},
+ ms320,
+ {'SystemInformationBlockType1_schedulinInformation_SEQOF_sib-MappingInfo'}}],
+ 0
+ }
+ }
+ }
+ }.
+
+eutra2(result, true) ->
+%% 55 5C A5 E0
+ <<85,92,165,224>>;
+eutra2(result, false) ->
+ <<85,92,165,14:4>>.
+
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
@@ -1308,3 +1271,17 @@ ticket7904(Config) ->
{ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
{ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).
+
+xref(_Config) ->
+ xref:start(s),
+ xref:set_default(s, [{verbose,false},{warnings,false},{builtins,true}]),
+ Test = filename:dirname(code:which(?MODULE)),
+ {ok,_PMs} = xref:add_directory(s, Test),
+ UnusedExports = "X - XU - asn1_appup_test - asn1_app_test - \".*_SUITE\" : Mod",
+ case xref:q(s, UnusedExports) of
+ {ok,[]} ->
+ ok;
+ {ok,[_|_]=Res} ->
+ io:format("Exported, but unused: ~p\n", [Res]),
+ ?t:fail()
+ end.
diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py
index e4bc987e4c..3495cd841b 100644
--- a/lib/asn1/test/asn1_SUITE_data/Constraints.py
+++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py
@@ -16,6 +16,15 @@ SemiConstrained ::= INTEGER (100..MAX)
NegSemiConstrained ::= INTEGER (-128..MAX)
SemiConstrainedExt ::= INTEGER (42..MAX, ...)
NegSemiConstrainedExt ::= INTEGER (-128..MAX, ...)
+SemiNamed ::= INTEGER {a(100), b(200)} (100..MAX)
+-- Extensions --
+LongLongExt ::= INTEGER (0..18446744073709551615, ..., -5000..-1)
+Range256to65536Ext ::= INTEGER (256..65536, ..., 1000000..9000000)
+
+-- Union of single values
+Sv1 ::= INTEGER (2|3|17)
+Sv2 ::= INTEGER (2|3|17, ...)
+Sv3 ::= INTEGER {a(2),b(3),z(17)} (2|3|17, ...)
-- Other constraints
FixedSize ::= OCTET STRING (SIZE(10))
@@ -57,10 +66,12 @@ Wednesday ::= Day(wednesday)
Thing ::= INTEGER {fred (0),fred2 (1),fred3 (2)}
-
-
AnotherThing ::= Thing (fred | fred2)
+OneMoreThing ::= INTEGER {wilma(0), fred(1), betty(3), barney(2)}
+OneMoreThing-1 ::= OneMoreThing (wilma | fred)
+OneMoreThing-2 ::= OneMoreThing (fred | barney)
+
I ::= INTEGER (0|15..269) -- OTP-5457
X1 ::= INTEGER (1..4 | 8 | 10 | 20) -- OTP-9946
@@ -94,4 +105,44 @@ pdf OBJECT IDENTIFIER ::= {1,2,3,4,5}
ShorterExt ::= IA5String (SIZE (5, ...))
+SeqOverlapping ::= SEQUENCE {
+ v Overlapping
+}
+
+SeqNonOverlapping ::= SEQUENCE {
+ v NonOverlapping
+}
+
+Overlapping ::= INTEGER (7280..7560 |
+7580..7680 |
+7910..8210 |
+8600..8940 |
+9250..9600 |
+14759..15109 |
+15250..15590 |
+18050..18800 |
+19300..19950 |
+21100..21700 |
+26200..26900 |
+18500..19900 |
+20100..20250 |
+21100..21700 |
+23000..24000 |
+24960..26900)
+
+-- The same intervals, but merged and sorted --
+NonOverlapping ::= INTEGER (7280..7560 |
+7580..7680 |
+7910..8210 |
+8600..8940 |
+9250..9600 |
+14759..15109 |
+15250..15590 |
+18050..19950 |
+20100..20250 |
+21100..21700 |
+23000..24000 |
+24960..26900)
+
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Constructed.asn b/lib/asn1/test/asn1_SUITE_data/Constructed.asn
index 09a66d0c0d..bd49741726 100644
--- a/lib/asn1/test/asn1_SUITE_data/Constructed.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Constructed.asn
@@ -1,6 +1,3 @@
-
-
-
Constructed DEFINITIONS ::=
BEGIN
@@ -20,4 +17,7 @@ C ::= CHOICE {
S3 ::= SEQUENCE {i INTEGER}
S3ext ::= SEQUENCE {i INTEGER, ...}
+
+OS ::= OCTET STRING
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/ContextSwitchingTypes.asn1 b/lib/asn1/test/asn1_SUITE_data/ContextSwitchingTypes.asn1
index c8145bad63..e279a180c1 100644
--- a/lib/asn1/test/asn1_SUITE_data/ContextSwitchingTypes.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ContextSwitchingTypes.asn1
@@ -21,6 +21,10 @@ val3-T T ::= {identification context-negotiation:{presentation-context-id 12,
transfer-syntax {1 2 3}},
data-value '123'H}
+val4-T T ::= {identification presentation-context-id:42,
+ data-value-descriptor "FooBar",
+ data-value '123'H}
+
-- EMBEDDED PDV type
EP ::= EMBEDDED PDV
diff --git a/lib/asn1/test/asn1_SUITE_data/Default.asn b/lib/asn1/test/asn1_SUITE_data/Default.asn
index 6604953c1f..b91660381a 100644
--- a/lib/asn1/test/asn1_SUITE_data/Default.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Default.asn
@@ -21,7 +21,12 @@ SeqBS ::= SEQUENCE {
a BIT STRING DEFAULT '1010110'B,
b BIT STRING DEFAULT 'A8A'H,
c BIT STRING {first(0),second(1),third(2)} DEFAULT {second},
- d BIT STRING DEFAULT onelist
+ d BIT STRING DEFAULT onelist,
+ e BIT STRING DEFAULT '01011010'B
+}
+
+SeqBS2 ::= SEQUENCE {
+ bs BIT STRING {a(0), z(25)} DEFAULT '101'B
}
SetBS ::= SET {
@@ -155,4 +160,23 @@ four INTEGER ::= 4
cr IA5String ::= {0,13}
+SeqNamedInts ::= SEQUENCE {
+ i1 INTEGER {first(0), last(31)} DEFAULT 15,
+ i2 INTEGER {first(0), last(31)} DEFAULT 31
+}
+
+S5 ::= SEQUENCE {
+ s3 S3 DEFAULT {},
+ so SEQUENCE OF OBJECT IDENTIFIER DEFAULT {
+ {itu-t question 999},
+ {itu-t question 555}
+ },
+ soe SEQUENCE OF OBJECT IDENTIFIER DEFAULT { }
+}
+
+SOI ::= SEQUENCE {
+ soi SEQUENCE OF OBJECT IDENTIFIER
+ DEFAULT { {iso member-body f(250) 9 55}, {iso member-body f(250) 3 4} }
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/DoubleEllipses.asn b/lib/asn1/test/asn1_SUITE_data/DoubleEllipses.asn
index e90cf55d61..846c3e7569 100644
--- a/lib/asn1/test/asn1_SUITE_data/DoubleEllipses.asn
+++ b/lib/asn1/test/asn1_SUITE_data/DoubleEllipses.asn
@@ -12,6 +12,15 @@ Seq ::= SEQUENCE
c BOOLEAN
}
+SeqV1 ::= SEQUENCE
+ {
+ a INTEGER,
+ ...,
+ b BOOLEAN,
+ ...
+ }
+
+
SeqV2 ::= SEQUENCE
{
a INTEGER,
@@ -50,6 +59,18 @@ SeqAltV2 ::= SEQUENCE
g INTEGER
}
+SeqDoubleEmpty1 ::= SEQUENCE {
+ ...,
+ ...
+}
+
+SeqDoubleEmpty2 ::= SEQUENCE {
+ a BOOLEAN,
+ b INTEGER OPTIONAL,
+ ...,
+ ...
+}
+
Set ::= SET {
a INTEGER,
...,
@@ -57,6 +78,14 @@ Set ::= SET {
c BOOLEAN
}
+
+SetV1 ::= SET {
+ a INTEGER,
+ ...,
+ b BOOLEAN,
+ ...
+ }
+
SetV2 ::= SET
{
a INTEGER,
@@ -96,4 +125,4 @@ SetAltV2 ::= SET
}
-END \ No newline at end of file
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
index 8dc5f3d7e1..74fa97e7aa 100644
--- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
@@ -18,6 +18,8 @@ Ext1 ::= ENUMERATED {
magenta(9)
}
+SubExt1 ::= Ext1 ( blue | orange | black )
+
Noext ::= ENUMERATED {
blue(0),
red(1),
diff --git a/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1 b/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
new file mode 100644
index 0000000000..bfc939737f
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
@@ -0,0 +1,24 @@
+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/INSTANCEOF.asn1 b/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1
index 8c4f3a8f7e..b4ea943040 100644
--- a/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/INSTANCEOF.asn1
@@ -16,7 +16,9 @@ Names ::= SEQUENCE {
thirdName [2] INSTANCE OF OTHER-NAME ({TI})
}
-OTHER-NAME ::= TYPE-IDENTIFIER
+OTHER-NAME ::= YET-ANOTHER-NAME
+
+YET-ANOTHER-NAME ::= TYPE-IDENTIFIER
TI OTHER-NAME ::= {{INTEGER IDENTIFIED BY {2 4}} |
{Seq IDENTIFIED BY {2 3 4}} |
diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
index 896a35d627..32b8f75dde 100644
--- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
@@ -1,16 +1,8 @@
-ImportsFrom DEFINITIONS ::=
-
+ImportsFrom DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
-IMPORTS
-Type1, Type2, Type3
-FROM RemoteFile1 objid
-val1, val2, val3
-FROM RemoteFile2;
-
-objid OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) remote-operations(4) notation(0)}
-
-LocalType ::= INTEGER
+IMPORTS Int FROM ImportsFrom2;
+i Int ::= 42
END
diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1
new file mode 100644
index 0000000000..b0c29d24ae
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1
@@ -0,0 +1,7 @@
+ImportsFrom2 DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+IMPORTS Int FROM ImportsFrom3;
+
+LocalDef ::= OCTET STRING
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1
new file mode 100644
index 0000000000..ca27b20697
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom3.asn1
@@ -0,0 +1,4 @@
+ImportsFrom3 DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+ Int ::= INTEGER (0..63)
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/InfObj.asn b/lib/asn1/test/asn1_SUITE_data/InfObj.asn
index 53e5043cb7..719119f418 100644
--- a/lib/asn1/test/asn1_SUITE_data/InfObj.asn
+++ b/lib/asn1/test/asn1_SUITE_data/InfObj.asn
@@ -202,7 +202,11 @@ constructed2 CONSTRUCTED-DEFAULT ::= { &id 2, &ok false }
ConstructedDefaultSet CONSTRUCTED-DEFAULT ::= {
constructed1 |
constructed2 |
- { &id 3, &Type BOOLEAN }
+ { &id 3, &Type BOOLEAN } |
+ { &id 4, &Type SET { a INTEGER, b BIT STRING } } |
+ { &id 5, &Type CHOICE { i INTEGER, b BIT STRING } } |
+ { &id 6, &Type SEQUENCE OF INTEGER (1..16) } |
+ { &id 7, &Type SET OF INTEGER (1..64) }
}
ConstructedPdu ::= SEQUENCE {
@@ -210,6 +214,92 @@ ConstructedPdu ::= SEQUENCE {
content CONSTRUCTED-DEFAULT.&Type ({ConstructedDefaultSet}{@id})
}
+ConstructedSet ::= SET {
+ id [0] CONSTRUCTED-DEFAULT.&id ({ConstructedDefaultSet}),
+ content [1] CONSTRUCTED-DEFAULT.&Type ({ConstructedDefaultSet}{@id})
+}
+
+-- Test OPTIONAL and DEFAULT
+
+OptionalInSeq ::= SEQUENCE {
+ id CONSTRUCTED-DEFAULT.&id ({ConstructedDefaultSet}),
+ content CONSTRUCTED-DEFAULT.&Type ({ConstructedDefaultSet}{@id}) OPTIONAL
+}
+
+DefaultInSeq ::= SEQUENCE {
+ id CONSTRUCTED-DEFAULT.&id ({ConstructedDefaultSet}),
+ content CONSTRUCTED-DEFAULT.&Type ({ConstructedDefaultSet}{@id})
+ DEFAULT BOOLEAN:TRUE
+}
+
+-- Test more than one optional typefield table constraint in a SEQUENCE.
+
+MULTIPLE-OPTIONALS ::= CLASS {
+ &id INTEGER UNIQUE,
+ &T1,
+ &T2,
+ &T3
+}
+
+multiple-optionals-1 MULTIPLE-OPTIONALS ::=
+ {&id 1, &T1 INTEGER, &T2 BOOLEAN, &T3 OCTET STRING}
+
+Multiple-Optionals-Set MULTIPLE-OPTIONALS ::= {
+ multiple-optionals-1
+}
+
+Multiple-Optionals ::= SEQUENCE {
+ id MULTIPLE-OPTIONALS.&id ({Multiple-Optionals-Set}),
+ t1 [0] MULTIPLE-OPTIONALS.&T1 ({Multiple-Optionals-Set}{@id}) OPTIONAL,
+ t2 [1] MULTIPLE-OPTIONALS.&T2 ({Multiple-Optionals-Set}{@id}) OPTIONAL,
+ t3 [2] MULTIPLE-OPTIONALS.&T3 ({Multiple-Optionals-Set}{@id}) OPTIONAL
+}
+
+-- Test different ways of constructing object sets.
+
+OBJECT-SET-TEST ::= CLASS {
+ &id INTEGER UNIQUE,
+ &Type
+} WITH SYNTAX {
+ &id IS &Type
+}
+
+ObjectSetTest{OBJECT-SET-TEST:ObjectSet} ::=
+ SEQUENCE {
+ id OBJECT-SET-TEST.&id ({ObjectSet}),
+ type OBJECT-SET-TEST.&Type ({ObjectSet}{@id})
+ }
+
+ost1 OBJECT-SET-TEST ::= { 1 IS BIT STRING }
+ost2 OBJECT-SET-TEST ::= { 2 IS OCTET STRING }
+ost3 OBJECT-SET-TEST ::= { 3 IS ENUMERATED {donald,scrooge} }
+ost4 OBJECT-SET-TEST ::= { 4 IS BOOLEAN }
+ost5 OBJECT-SET-TEST ::= { 5 IS INTEGER (0..15) }
+
+Ost12 OBJECT-SET-TEST ::= { ost1 | ost2 }
+Ost123 OBJECT-SET-TEST ::= { ost3 | Ost12 }
+Ost1234 OBJECT-SET-TEST ::= { Ost123 | ost4 }
+Ost45 OBJECT-SET-TEST ::= { ost4 | ost5 }
+Ost12345 OBJECT-SET-TEST ::= { Ost123 | Ost45 }
+
+OstSeq12 ::= ObjectSetTest{ {Ost12} }
+OstSeq123 ::= ObjectSetTest{ {Ost123} }
+OstSeq1234 ::= ObjectSetTest{ {Ost1234} }
+OstSeq45 ::= ObjectSetTest{ {Ost45} }
+OstSeq12345 ::= ObjectSetTest{ {Ost12345} }
+
+ExOst12 OBJECT-SET-TEST ::= { ost1, ..., ost2 }
+ExOst123 OBJECT-SET-TEST ::= { ost3, ..., ExOst12 }
+--ExOst1234 OBJECT-SET-TEST ::= { ExOst123, ..., ost4 }
+ExOst45 OBJECT-SET-TEST ::= { ost4, ..., ost5 }
+ExOst12345 OBJECT-SET-TEST ::= { ExOst123, ..., ExOst45 }
+
+ExOstSeq12 ::= ObjectSetTest{ {ExOst12} }
+ExOstSeq123 ::= ObjectSetTest{ {ExOst123} }
+--ExOstSeq1234 ::= ObjectSetTest{ {ExOst1234} }
+ExOstSeq45 ::= ObjectSetTest{ {ExOst45} }
+ExOstSeq12345 ::= ObjectSetTest{ {ExOst12345} }
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Param.asn1 b/lib/asn1/test/asn1_SUITE_data/Param.asn1
index b2987a7885..4eff0da781 100644
--- a/lib/asn1/test/asn1_SUITE_data/Param.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/Param.asn1
@@ -88,6 +88,28 @@ POS2 {CONFIG-DATA:obj} ::= OCTET STRING (SIZE(obj.&minLevel .. obj.&maxLevel))
OS2 ::= POS2 {config-data}
+--
+-- Test a CLASS without the user-friendly syntax.
+--
+
+CL ::= CLASS {
+ &code INTEGER UNIQUE,
+ &Data
+}
+
+P{T} ::= CHOICE { a INTEGER, b T }
+
+o1 CL ::= {
+ &code 42,
+ &Data P{BOOLEAN}
+}
+
+SetCL CL ::= { o1 }
+
+Scl ::= SEQUENCE {
+ code CL.&code ({SetCL}),
+ data CL.&Data ({SetCL}{@code})
+}
END
diff --git a/lib/asn1/test/asn1_SUITE_data/ParamBasic.asn1 b/lib/asn1/test/asn1_SUITE_data/ParamBasic.asn1
index 491bdf8956..68fc782f33 100644
--- a/lib/asn1/test/asn1_SUITE_data/ParamBasic.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ParamBasic.asn1
@@ -20,4 +20,26 @@ T21 ::= General2{PrintableString}
T22 ::= General2{BIT STRING}
+
+--
+-- Test a class parameter that is the governor for another parameter.
+--
+
+AlgorithmIdentifier{ALGORITHM-TYPE, ALGORITHM-TYPE:AlgorithmSet} ::=
+ SEQUENCE {
+ algorithm ALGORITHM-TYPE.&id ({AlgorithmSet}),
+ type ALGORITHM-TYPE.&Type ({AlgorithmSet}{@algorithm})
+ }
+
+AnAlgorithm ::= AlgorithmIdentifier{ SIGNATURE-ALGORITHM,
+ { {KEY 1 CONTAINING INTEGER} |
+ {KEY 2 CONTAINING BOOLEAN} } }
+
+SIGNATURE-ALGORITHM ::= CLASS {
+ &id INTEGER UNIQUE,
+ &Type
+} WITH SYNTAX {
+ KEY &id CONTAINING &Type
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
index 08e7f94ab6..a5b4c8a53d 100644
--- a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1
@@ -46,7 +46,13 @@ BS256 ::= BIT STRING (SIZE (256))
BS1024 ::= BIT STRING (SIZE (1024))
-
+ BsDef1 ::= SEQUENCE {
+ s BIT STRING DEFAULT '101111'B
+ }
+
+ BsDef2 ::= SEQUENCE {
+ s BIT STRING DEFAULT 'DEADBEEF'H
+ }
Os ::= OCTET STRING
OsCon ::= [60] OCTET STRING
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
index 888dbe5dd7..670f827f5e 100644
--- a/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SeqOf.asn1
@@ -31,7 +31,43 @@ Seq4 ::= SEQUENCE
seq43 [43] SEQUENCE OF SeqIn DEFAULT {}
}
+Seq5 ::= SEQUENCE {
+ b BOOLEAN,
+ s SEQUENCE SIZE (0..3) OF OCTET STRING (SIZE (0..3)),
+ -- If 's' is empty, 'magic' should not be aligned.
+ magic INTEGER (0..127)
+}
+
+Seq6 ::= SEQUENCE {
+ a SEQUENCE OF INTEGER (0..7),
+ b SEQUENCE (SIZE (0..7)) OF INTEGER (0..7),
+ -- 'magic' should never be aligned.
+ magic INTEGER (0..127)
+}
+Seq7 ::= SEQUENCE {
+ a SEQUENCE OF INTEGER (1..512),
+ b SEQUENCE (SIZE (0..255)) OF INTEGER (1..512),
+ i INTEGER
+}
+
+Seq8 ::= SEQUENCE {
+ sof SEQUENCE (SIZE (0..3)) OF OCTET STRING (SIZE (3)),
+ -- Not aligned here if the size of 'sof' is zero.
+ i INTEGER (0..127)
+}
+
+Seq9 ::= SEQUENCE {
+ b BOOLEAN,
+ s SEQUENCE SIZE (0..3) OF OCTET STRING (SIZE (0..3)),
+ magic INTEGER (0..127)
+}
+
+Seq10 ::= SEQUENCE {
+ b BOOLEAN,
+ s SEQUENCE SIZE (1..3) OF OCTET STRING (SIZE (0..3)),
+ magic INTEGER (0..127)
+}
SeqIn ::= SEQUENCE
{
@@ -50,9 +86,6 @@ SeqCho ::= SEQUENCE OF CHOICE {bool BOOLEAN,
SeqOfInt ::= SEQUENCE OF INTEGER
-
-
-
SeqEmp ::= SEQUENCE
{
seq1 SEQUENCE OF Empty DEFAULT {}
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1
index 20c4126c0b..7068674647 100644
--- a/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/SeqPrim.asn1
@@ -16,4 +16,11 @@ Seq ::= SEQUENCE
Empty ::= SEQUENCE {}
+Big ::= SEQUENCE {
+ ...,
+ os1 [1] OCTET STRING (SIZE (120..130)) OPTIONAL,
+ os2 [2] OCTET STRING (SIZE (128..256)) OPTIONAL,
+ os3 [3] OCTET STRING (SIZE (17000..30000)) OPTIONAL
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Set.py b/lib/asn1/test/asn1_SUITE_data/Set.py
index 4062f6b804..3928004e6b 100644
--- a/lib/asn1/test/asn1_SUITE_data/Set.py
+++ b/lib/asn1/test/asn1_SUITE_data/Set.py
@@ -80,8 +80,8 @@ SetOpt3 ::= SET
SetIn ::= SET
{
- boolIn BOOLEAN,
- intIn INTEGER
+ boolIn BOOLEAN OPTIONAL,
+ intIn INTEGER OPTIONAL
}
diff --git a/lib/asn1/test/asn1_SUITE_data/TAGDEFAULT-AUTOMATIC.asn b/lib/asn1/test/asn1_SUITE_data/TAGDEFAULT-AUTOMATIC.asn
new file mode 100644
index 0000000000..2fcba1f71e
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/TAGDEFAULT-AUTOMATIC.asn
@@ -0,0 +1,25 @@
+TAGDEFAULT-AUTOMATIC DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+EXPORTS
+ Tagged,
+ Untagged,
+ Mixed
+;
+
+Tagged ::= SEQUENCE {
+ o0 [0] OCTET STRING,
+ o1 [1] OCTET STRING
+}
+
+Untagged ::= SEQUENCE {
+ o0 OCTET STRING,
+ o1 OCTET STRING
+}
+
+Mixed ::= SEQUENCE {
+ o0 OCTET STRING,
+ o2 [2] OCTET STRING
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl b/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl
index 06eba8b6eb..0bf4425263 100644
--- a/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl
+++ b/lib/asn1/test/asn1_SUITE_data/TCAPPackage_msg.erl
@@ -47,7 +47,7 @@ val('TransactionPDU') ->
dialoguePortion=val('DialoguePortion'),
componentPortion=val('ComponentSequence')};
val('TransactionID') ->
- "OCTET STRING";
+ <<"OCTET STRING">>;
val('DialoguePortion') ->
#'DialoguePortion'{version=val('ProtocolVersion'),
applicationContext={integerApplicationId,12},
@@ -57,23 +57,23 @@ val('DialoguePortion') ->
val('Confidentiality') ->
#'Confidentiality'{confidentialityId={integerConfidentialityId,14}};
val('ProtocolVersion') ->
- "K";
+ <<"K">>;
val('UserInformation') ->
[val('EXTERNAL'),val('EXTERNAL')];
val('EXTERNAL') ->
#'EXTERNAL'{'direct-reference'={0,1,2},
- encoding={'single-ASN1-type',[1,2,3,4]}};
+ encoding={'single-ASN1-type',<<1,2,3,4>>}};
val('ComponentSequence') ->
[val('ComponentPDU',1),val('ComponentPDU',2),val('ComponentPDU',3)];
val('Invoke') ->
- #'Invoke'{componentIDs="AB",
+ #'Invoke'{componentIDs = <<"AB">>,
opcode={local,-2},
parameter=running};
val('ReturnResult') ->
- #'ReturnResult'{componentID="C",
+ #'ReturnResult'{componentID = <<"C">>,
parameter=[1,2,3,4]};
val('ReturnError') ->
- #'ReturnError'{componentID="D",
+ #'ReturnError'{componentID = <<"D">>,
errorCode={local,21},
parameter=true};
val('Abort') ->
@@ -87,8 +87,8 @@ val(Type) ->
check_result('PackageType',unidirectional,Res) ->
{unidirectional,
{'UniTransactionPDU',
- "OCTET STRING",
- {'DialoguePortion',"K",
+ <<"OCTET STRING">>,
+ {'DialoguePortion',<<"K">>,
{integerApplicationId,12},
[_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal},
_],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}],
@@ -96,14 +96,14 @@ check_result('PackageType',unidirectional,Res) ->
{'Confidentiality',
{integerConfidentialityId,14}}},
[{invokeLast,
- {_,"AB",{local,-2},running}},
- {returnResultLast,{_,"C",_}},
- {returnError,{_,"D",{local,21},true}}]}} = Res,
+ {_,<<"AB">>,{local,-2},running}},
+ {returnResultLast,{_,<<"C">>,_}},
+ {returnError,{_,<<"D">>,{local,21},true}}]}} = Res,
ok;
%% check_OT_val(OTVal);
check_result('PackageType',abort,Res)->
- {abort,{'Abort',"OCTET STRING",
- {'DialoguePortion',"K",
+ {abort,{'Abort',<<"OCTET STRING">>,
+ {'DialoguePortion',<<"K">>,
{integerApplicationId,12},
[_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal},
_],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}],
@@ -114,9 +114,9 @@ check_result('PackageType',abort,Res)->
ok;
%% check_OT_val(OTVal);
check_result('PackageType',response,Res) ->
- {response,{'TransactionPDU',"OCTET STRING",
+ {response,{'TransactionPDU',<<"OCTET STRING">>,
{'DialoguePortion',
- "K",
+ <<"K">>,
{integerApplicationId,12},
[_,%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal},
_],%{'EXTERNAL',{syntax,{0,1,2}},asn1_NOVALUE,OTVal}],
@@ -124,11 +124,11 @@ check_result('PackageType',response,Res) ->
{'Confidentiality',
{integerConfidentialityId,14}}},
[{invokeLast,
- {_,"AB",{local,-2},running}},
+ {_,<<"AB">>,{local,-2},running}},
{returnResultLast,
- {_,"C",_}},
+ {_,<<"C">>,_}},
{returnError,
- {_,"D",{local,21},true}}]}} = Res,
+ {_,<<"D">>,{local,21},true}}]}} = Res,
ok.
%% check_OT_val(OTVal).
diff --git a/lib/asn1/test/asn1_SUITE_data/TConstr.asn1 b/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
index e2e0a11dc4..b2b2de2f56 100644
--- a/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/TConstr.asn1
@@ -58,6 +58,40 @@ Deeper ::= SEQUENCE {
b SEQUENCE {ba INTEGER, bb MYCLASS.&Type ({ObjectSet}{@a.s.ab})}
}
+Seq3 ::= SEQUENCE {
+ a SEQUENCE {
+ aa INTEGER,
+ ab MYCLASS.&id ({ObjectSet})
+ },
+ -- Multiple references from the same SEQUENCE...
+ b SEQUENCE {
+ ba MYCLASS.&Type ({ObjectSet}{@a.ab}),
+ bb MYCLASS.&Result ({ObjectSet}{@a.ab}),
+ -- ... and references from multiple SEQUENCEs...
+ bc SEQUENCE {
+ bca MYCLASS.&Result ({ObjectSet}{@a.ab}),
+ bcb MYCLASS.&Type ({ObjectSet}{@a.ab})
+ }
+ }
+}
+
+Seq3-Opt ::= SEQUENCE {
+ a SEQUENCE {
+ aa INTEGER,
+ ab MYCLASS.&id ({ObjectSet})
+ },
+ -- Multiple references from the same SEQUENCE...
+ b SEQUENCE {
+ ba MYCLASS.&Type ({ObjectSet}{@a.ab}) OPTIONAL,
+ bb MYCLASS.&Result ({ObjectSet}{@a.ab}) OPTIONAL,
+ -- ... and references from multiple SEQUENCEs...
+ bc SEQUENCE {
+ bca MYCLASS.&Result ({ObjectSet}{@a.ab}),
+ bcb MYCLASS.&Type ({ObjectSet}{@a.ab})
+ } OPTIONAL
+ }
+}
+
-- following from Peter's definitions
diff --git a/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn b/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn
new file mode 100644
index 0000000000..7b81a0e09f
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/UPERDefault.asn
@@ -0,0 +1,18 @@
+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/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
index 8e21e6ca84..a1e563f6be 100644
--- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
+++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
@@ -67,8 +67,8 @@ run3(Erule) ->
asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
asn1_NOVALUE,asn1_NOVALUE},
asn1_NOVALUE,
- [[80,66,0,5,10,0,5,0,24,11,7,84,54,33,0,1,1,0,0,0,1,39,5,66,127,0,0,1],
- []],
+ [<<80,66,0,5,10,0,5,0,24,11,7,84,54,33,0,1,1,0,0,0,1,39,5,66,127,0,0,1>>,
+ <<>>],
{'RRC-RadioResourceConfigDedicated',
[{'RRC-SRB-ToAddMod',1,
{explicitValue,
diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl
index 1225e36778..d800846b3f 100644
--- a/lib/asn1/test/asn1_app_test.erl
+++ b/lib/asn1/test/asn1_app_test.erl
@@ -134,13 +134,13 @@ get_ebin_mods(App) ->
check_asn1ct_modules(Extra) ->
ASN1CTMods = [asn1ct,asn1ct_check,asn1_db,asn1ct_pretty_format,
- asn1ct_gen,asn1ct_gen_per,asn1ct_gen_per_rt2ct,
+ asn1ct_gen,asn1ct_gen_check,asn1ct_gen_per,
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_imm,asn1ct_func,asn1ct_rtt,
- asn1ct_eval_ext,asn1ct_eval_per,asn1ct_eval_uper],
+ asn1ct_eval_ext],
case Extra -- ASN1CTMods of
[] ->
ok;
diff --git a/lib/asn1/test/asn1_appup_test.erl b/lib/asn1/test/asn1_appup_test.erl
index a2c1423eda..7391959645 100644
--- a/lib/asn1/test/asn1_appup_test.erl
+++ b/lib/asn1/test/asn1_appup_test.erl
@@ -21,8 +21,8 @@
%% Purpose: Verify the application specifics of the asn1 application
%%----------------------------------------------------------------------
-module(asn1_appup_test).
--compile({no_auto_import,[error/1]}).
-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -44,16 +44,9 @@ end_per_group(_GroupName, Config) ->
init_per_suite(suite) -> [];
init_per_suite(doc) -> [];
init_per_suite(Config) when is_list(Config) ->
- AppFile = file_name(asn1, ".app"),
- AppupFile = file_name(asn1, ".appup"),
- [{app_file, AppFile}, {appup_file, AppupFile}|Config].
+ Config.
-file_name(App, Ext) ->
- LibDir = code:lib_dir(App),
- filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]).
-
-
end_per_suite(suite) -> [];
end_per_suite(doc) -> [];
end_per_suite(Config) when is_list(Config) ->
@@ -62,349 +55,7 @@ end_per_suite(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-appup(suite) ->
- [];
-appup(doc) ->
- "perform a simple check of the appup file";
+appup() ->
+ [{doc, "perform a simple check of the asn1 appup file"}].
appup(Config) when is_list(Config) ->
- AppupFile = key1search(appup_file, Config),
- AppFile = key1search(app_file, Config),
- Modules = modules(AppFile),
- check_appup(AppupFile, Modules).
-
-modules(File) ->
- case file:consult(File) of
- {ok, [{application,asn1,Info}]} ->
- case lists:keysearch(modules,1,Info) of
- {value, {modules, Modules}} ->
- Modules;
- false ->
- fail({bad_appinfo, Info})
- end;
- Error ->
- fail({bad_appfile, Error})
- end.
-
-
-check_appup(AppupFile, Modules) ->
- case file:consult(AppupFile) of
- {ok, [{V, UpFrom, DownTo}]} ->
- io:format("V= ~p, UpFrom= ~p, DownTo= ~p, Modules= ~p~n",
- [V, UpFrom, DownTo, Modules]),
- check_appup(V, UpFrom, DownTo, Modules);
- Else ->
- fail({bad_appupfile, Else})
- end.
-
-
-check_appup(V, UpFrom, DownTo, Modules) ->
- check_version(V),
- check_depends(up, UpFrom, Modules),
- check_depends(down, DownTo, Modules),
- ok.
-
-
-check_depends(_, [], _) ->
- ok;
-check_depends(UpDown, [Dep|Deps], Modules) ->
- check_depend(UpDown, Dep, Modules),
- check_depends(UpDown, Deps, Modules).
-
-
-check_depend(up,I={add_application,_App},Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instruction: ~p"
- "~n Modules: ~p", [up,I , Modules]),
- ok;
-check_depend(down,I={remove_application,_App},Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instruction: ~p"
- "~n Modules: ~p", [down,I , Modules]),
- ok;
-check_depend(UpDown, {V, Instructions}, Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n V: ~p"
- "~n Modules: ~p", [UpDown, V, Modules]),
- check_version(V),
- case check_instructions(UpDown,
- Instructions, Instructions, [], [], Modules) of
- {_Good, []} ->
- ok;
- {_, Bad} ->
- fail({bad_instructions, Bad, UpDown})
- end.
-
-
-check_instructions(_, [], _, Good, Bad, _) ->
- {lists:reverse(Good), lists:reverse(Bad)};
-check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) ->
- d("check_instructions(~w) -> entry with"
- "~n Instr: ~p", [UpDown,Instr]),
- case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of
- ok ->
- check_instructions(UpDown, Instrs, AllInstr,
- [Instr|Good], Bad, Modules);
- {error, Reason} ->
- d("check_instructions(~w) -> bad instruction: "
- "~n Reason: ~p", [UpDown,Reason]),
- check_instructions(UpDown, Instrs, AllInstr, Good,
- [{Instr, Reason}|Bad], Modules)
- end.
-
-%% A new module is added
-check_instruction(up, {add_module, Module}, _, Modules)
- when is_atom(Module) ->
- d("check_instruction -> entry when up-add_module instruction with"
- "~n Module: ~p", [Module]),
- check_module(Module, Modules);
-
-%% An old module is re-added
-check_instruction(down, {add_module, Module}, _, Modules)
- when is_atom(Module) ->
- d("check_instruction -> entry when down-add_module instruction with"
- "~n Module: ~p", [Module]),
- case (catch check_module(Module, Modules)) of
- {error, {unknown_module, Module, Modules}} ->
- ok;
- ok ->
- error({existing_readded_module, Module})
- end;
-
-%% Removing a module on upgrade:
-%% - the module has been removed from the app-file.
-%% - check that no module depends on this (removed) module
-check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules)
- when is_atom(Module), is_atom(Pre), is_atom(Post) ->
- d("check_instruction -> entry when up-remove instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p", [Module, Pre, Post]),
- case (catch check_module(Module, Modules)) of
- {error, {unknown_module, Module, Modules}} ->
- check_purge(Pre),
- check_purge(Post);
- ok ->
- error({existing_removed_module, Module})
- end;
-
-%% Removing a module on downgrade: the module exist
-%% in the app-file.
-check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules)
- when is_atom(Module), is_atom(Pre), is_atom(Post) ->
- d("check_instruction -> entry when down-remove instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p", [Module, Pre, Post]),
- case (catch check_module(Module, Modules)) of
- ok ->
- check_purge(Pre),
- check_purge(Post),
- check_no_remove_depends(Module, AllInstr);
- {error, {unknown_module, Module, Modules}} ->
- error({nonexisting_removed_module, Module})
- end;
-
-check_instruction(_, {load_module, Module, Pre, Post, Depend},
- AllInstr, Modules)
- when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
- d("check_instruction -> entry when load_module instruction with"
- "~n Module: ~p"
- "~n Pre: ~p"
- "~n Post: ~p"
- "~n Depend: ~p", [Module, Pre, Post, Depend]),
- check_module(Module, Modules),
- check_module_depend(Module, Depend, Modules),
- check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
- check_purge(Pre),
- check_purge(Post);
-
-check_instruction(_, {update, Module, Change, Pre, Post, Depend},
- AllInstr, Modules)
- when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
- d("check_instruction -> entry when update instruction with"
- "~n Module: ~p"
- "~n Change: ~p"
- "~n Pre: ~p"
- "~n Post: ~p"
- "~n Depend: ~p", [Module, Change, Pre, Post, Depend]),
- check_module(Module, Modules),
- check_module_depend(Module, Depend, Modules),
- check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
- check_change(Change),
- check_purge(Pre),
- check_purge(Post);
-
-check_instruction(_, {apply, {Module, Function, Args}},
- _AllInstr, Modules)
- when is_atom(Module), is_atom(Function), is_list(Args) ->
- d("check_instruction -> entry when apply instruction with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
- check_module(Module, Modules),
- check_apply(Module,Function,Args);
-
-check_instruction(_, Instr, _AllInstr, _Modules) ->
- d("check_instruction -> entry when unknown instruction with"
- "~n Instr: ~p", [Instr]),
- error({error, {unknown_instruction, Instr}}).
-
-
-%% If Module X depends on Module Y, then module Y must have an update
-%% instruction of some sort (otherwise the depend is faulty).
-updated_modules([], Modules) ->
- d("update_modules -> entry when done with"
- "~n Modules: ~p", [Modules]),
- Modules;
-updated_modules([Instr|Instrs], Modules) ->
- d("update_modules -> entry with"
- "~n Instr: ~p"
- "~n Modules: ~p", [Instr,Modules]),
- Module = instruction_module(Instr),
- d("update_modules -> Module: ~p", [Module]),
- updated_modules(Instrs, [Module|Modules]).
-
-instruction_module({add_module, Module}) ->
- Module;
-instruction_module({remove, {Module, _, _}}) ->
- Module;
-instruction_module({load_module, Module, _, _, _}) ->
- Module;
-instruction_module({update, Module, _, _, _, _}) ->
- Module;
-instruction_module({apply, {Module, _, _}}) ->
- Module;
-instruction_module(Instr) ->
- d("instruction_module -> entry when unknown instruction with"
- "~n Instr: ~p", [Instr]),
- error({error, {unknown_instruction, Instr}}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-check_version(V) when is_list(V) ->
- ok;
-check_version(V) ->
- error({bad_version, V}).
-
-
-check_module(M, Modules) when is_atom(M) ->
- case lists:member(M,Modules) of
- true ->
- ok;
- false ->
- error({unknown_module, M, Modules})
- end;
-check_module(M, _) ->
- error({bad_module, M}).
-
-check_apply(Module,Function,Args) ->
- case (catch Module:module_info()) of
- Info when is_list(Info) ->
- check_exported(Function,Args,Info);
- {'EXIT',{undef,_}} ->
- error({not_existing_module,Module})
- end.
-
-check_exported(Function,Args,Info) ->
- case lists:keysearch(exports,1,Info) of
- {value,{exports,FunList}} ->
- case lists:keysearch(Function,1,FunList) of
- {value,{_,Arity}} when Arity==length(Args) ->
- ok;
- _ ->
- error({not_exported_function,Function,length(Args)})
- end;
- _ ->
- error({bad_export,Info})
- end.
-
-check_module_depend(M, [], _) when is_atom(M) ->
- d("check_module_depend -> entry with"
- "~n M: ~p", [M]),
- ok;
-check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) ->
- d("check_module_depend -> entry with"
- "~n M: ~p"
- "~n Deps: ~p"
- "~n Modules: ~p", [M, Deps, Modules]),
- case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of
- [] ->
- ok;
- Unknown ->
- error({unknown_depend_modules, Unknown})
- end;
-check_module_depend(_M, D, _Modules) ->
- d("check_module_depend -> entry when bad depend with"
- "~n D: ~p", [D]),
- error({bad_depend, D}).
-
-
-check_no_remove_depends(_Module, []) ->
- ok;
-check_no_remove_depends(Module, [Instr|Instrs]) ->
- check_no_remove_depend(Module, Instr),
- check_no_remove_depends(Module, Instrs).
-
-check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) ->
- case lists:member(Module, Depend) of
- true ->
- error({removed_module_in_depend, load_module, Mod, Module});
- false ->
- ok
- end;
-check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) ->
- case lists:member(Module, Depend) of
- true ->
- error({removed_module_in_depend, update, Mod, Module});
- false ->
- ok
- end;
-check_no_remove_depend(_, _) ->
- ok.
-
-
-check_change(soft) ->
- ok;
-check_change({advanced, _Something}) ->
- ok;
-check_change(Change) ->
- error({bad_change, Change}).
-
-
-check_purge(soft_purge) ->
- ok;
-check_purge(brutal_purge) ->
- ok;
-check_purge(Purge) ->
- error({bad_purge, Purge}).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-error(Reason) ->
- throw({error, Reason}).
-
-fail(Reason) ->
- exit({suite_failed, Reason}).
-
-key1search(Key, L) ->
- case lists:keysearch(Key, 1, L) of
- undefined ->
- fail({not_found, Key, L});
- {value, {Key, Value}} ->
- Value
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-d(F, A) ->
- d(false, F, A).
-
-d(true, F, A) ->
- io:format(F ++ "~n", A);
-d(_, _, _) ->
- ok.
-
-
+ ok = ?t:appup_test(asn1).
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 60b2b2b42e..da07cd1118 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -19,36 +19,77 @@
%%
-module(asn1_test_lib).
--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]).
+-export([compile/3,compile_all/3,compile_erlang/3,
+ hex_to_bin/1,
+ parallel/0,
+ roundtrip/3,roundtrip/4,roundtrip_enc/3,roundtrip_enc/4]).
-include_lib("test_server/include/test_server.hrl").
+run_dialyzer() ->
+ false.
+
compile(File, Config, Options) -> compile_all([File], Config, Options).
compile_all(Files, Config, Options) ->
DataDir = ?config(data_dir, Config),
CaseDir = ?config(case_dir, Config),
- [compile_file(filename:join(DataDir, F), [{outdir, CaseDir}|Options])
+ [compile_file(filename:join(DataDir, F), [{outdir, CaseDir},
+ debug_info|Options])
|| F <- Files],
+ dialyze(Files, Options),
ok.
+parallel() ->
+ case erlang:system_info(schedulers) > 1 andalso not run_dialyzer() of
+ true -> [parallel];
+ false -> []
+ end.
+
+dialyze(Files, Options) ->
+ case not run_dialyzer() orelse lists:member(abs, Options) of
+ true -> ok;
+ false -> dialyze(Files)
+ end.
+
+dialyze(Files) ->
+ Beams0 = [code:which(module(F)) || F <- Files],
+ Beams = [code:which(asn1rt_nif)|Beams0],
+ case dialyzer:run([{files,Beams},
+ {warnings,[no_improper_lists]},
+ {get_warnings,true}]) of
+ [] ->
+ ok;
+ [_|_]=Ws ->
+ io:put_chars([[B,$\n] || B <- Beams]),
+ io:put_chars([dialyzer:format_warning(W) || W <- Ws]),
+ error(dialyzer_warnings)
+ end.
+
+module(F0) ->
+ F1 = filename:basename(F0),
+ F2 = case filename:extension(F1) of
+ ".asn" ->
+ filename:rootname(F1);
+ ".asn1" ->
+ filename:rootname(F1);
+ ".py" ->
+ filename:rootname(F1);
+ "" ->
+ F1
+ end,
+ F = case filename:extension(F2) of
+ ".set" ->
+ filename:rootname(F2);
+ "" ->
+ F2
+ end,
+ list_to_atom(F).
+%% filename:join(CaseDir, F ++ ".beam").
+
compile_file(File, Options) ->
try
- ok = asn1ct:compile(File, [warnings_as_errors|Options]),
- case should_load(File, Options) of
- false ->
- ok;
- {module, Module} ->
- code:purge(Module),
- {module, Module} = code:load_file(Module),
- code:purge(Module)
- end
+ ok = asn1ct:compile(File, [warnings_as_errors|Options])
catch
Class:Reason ->
ct:print("Failed to compile ~s\n", [File]),
@@ -65,153 +106,77 @@ compile_erlang(Mod, Config, Options) ->
hex_to_bin(S) ->
<< <<(hex2num(C)):4>> || C <- S, C =/= $\s >>.
-%%%
-%%% Internal functions.
-%%%
+roundtrip(Mod, Type, Value) ->
+ roundtrip(Mod, Type, Value, Value).
-should_load(File, Options) ->
- case lists:member(abs, Options) of
- true ->
- false;
- false ->
- {module,list_to_atom(strip_extension(filename:basename(File)))}
- end.
+roundtrip(Mod, Type, Value, ExpectedValue) ->
+ {ok,Encoded} = Mod:encode(Type, Value),
+ {ok,ExpectedValue} = Mod:decode(Type, Encoded),
+ test_ber_indefinite(Mod, Type, Encoded, ExpectedValue),
+ ok.
-strip_extension(File) ->
- strip_extension(File, filename:extension(File)).
+roundtrip_enc(Mod, Type, Value) ->
+ roundtrip_enc(Mod, Type, Value, Value).
-strip_extension(File, "") ->
- File;
-strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"->
- strip_extension(filename:rootname(File));
-strip_extension(File, _Ext) ->
- File.
+roundtrip_enc(Mod, Type, Value, ExpectedValue) ->
+ {ok,Encoded} = Mod:encode(Type, Value),
+ {ok,ExpectedValue} = Mod:decode(Type, Encoded),
+ test_ber_indefinite(Mod, Type, Encoded, ExpectedValue),
+ Encoded.
+
+%%%
+%%% Internal functions.
+%%%
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, {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, {outdir,OutDir}]++Option).
-
-
-ticket_7407_code(FinalPadding) ->
- Msg1 = {Type1,_} = eutra1(msg),
- ?line {ok,B1} = 'EUTRA-extract-7407':encode(Type1,Msg1),
- ?line B1 = eutra1(result,FinalPadding),
-
- Msg2 = {Type2,_} = eutra2(msg),
- ?line {ok,B2} = 'EUTRA-extract-7407':encode(Type2,Msg2),
- ?line B2 = eutra2(result,FinalPadding),
- ok.
-
-eutra1(msg) ->
- {'BCCH-BCH-Message',{'MasterInformationBlock',[0,1,0,1],[1,0,1,0],{'PHICH-Configuration',short,ffs},[1,0,1,0,0,0,0,0]}}.
-eutra1(result,true) ->
- <<90,80,0>>;
-eutra1(result,false) ->
- <<90,80,0:1>>.
-
-eutra2(msg) ->
- {'BCCH-DL-SCH-Message',
- {c1,
- {systemInformation1,
- {'SystemInformationBlockType1',
- {'SystemInformationBlockType1_cellAccessRelatedInformation',
- [{'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},true},
- {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},false},
- {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},true}],
- {'TrackingAreaCode'},
- {'CellIdentity'},
- false,
- true,
- true,
- true
- },
- {'SystemInformationBlockType1_cellSelectionInfo',-50},
- 24,
- [{'SystemInformationBlockType1_schedulinInformation_SEQOF',
- {'SystemInformationBlockType1_schedulinInformation_SEQOF_si-MessageType'},
- ms320,
- {'SystemInformationBlockType1_schedulinInformation_SEQOF_sib-MappingInfo'}}],
- 0
- }
- }
- }
- }.
-eutra2(result,true) ->
-%% 55 5C A5 E0
- <<85,92,165,224>>;
-eutra2(result,false) ->
- <<85,92,165,14:4>>.
-
-
-
-ticket_7678(Config, Option) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok = asn1ct:compile(DataDir ++ "UPERDefault",
- [uper, {outdir,OutDir}]++Option),
-
- ?line Val = 'UPERDefault':seq(),
- ?line {ok,<<0,6,0>>} = 'UPERDefault':encode('Seq',Val),
- ?line {ok,Val} = 'UPERDefault':decode('Seq',<<0,6,0>>),
- ok.
-
-
-ticket_7763(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok = asn1ct:compile(DataDir ++ "EUTRA-extract-55",
- [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,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),
-
- ?line Bin = CompactBin,
-
- io:format("CompactBin:~n~p~nBin:~n~p~nCompactBin == Bin is ~p~n",[CompactBin,Bin,CompactBin == Bin]).
-
-
-ticket_7876(Config,Erule,Options) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok = asn1ct:compile(DataDir ++ "S1AP-CommonDataTypes",
- [Erule,{outdir,OutDir}|Options]),
- ?line ok = asn1ct:compile(DataDir ++ "S1AP-Constants",
- [Erule,{outdir,OutDir}|Options]),
-?line ok = asn1ct:compile(DataDir ++ "S1AP-Containers",
- [Erule,{outdir,OutDir}|Options]),
-?line ok = asn1ct:compile(DataDir ++ "S1AP-IEs",
- [Erule,{outdir,OutDir}|Options]),
-?line ok = asn1ct:compile(DataDir ++ "S1AP-PDU-Contents",
- [Erule,{outdir,OutDir}|Options]),
-?line ok = asn1ct:compile(DataDir ++ "S1AP-PDU-Descriptions",
- [Erule,{outdir,OutDir}|Options]),
+test_ber_indefinite(Mod, Type, Encoded, ExpectedValue) ->
+ case Mod:encoding_rule() of
+ ber ->
+ Indefinite = iolist_to_binary(ber_indefinite(Encoded)),
+ {ok,ExpectedValue} = Mod:decode(Type, Indefinite);
+ _ ->
+ ok
+ end.
- ticket_7876_encdec(Erule),
- ok.
+%% Rewrite all definite lengths for constructed values to an
+%% indefinite length.
+ber_indefinite(Bin0) ->
+ case ber_get_tag(Bin0) of
+ done ->
+ [];
+ primitive ->
+ Bin0;
+ {constructed,Tag,Bin1} ->
+ {Len,Bin2} = ber_get_len(Bin1),
+ <<Val0:Len/binary,Bin/binary>> = Bin2,
+ Val = iolist_to_binary(ber_indefinite(Val0)),
+ [<<Tag/binary,16#80,Val/binary,0,0>>|ber_indefinite(Bin)]
+ end.
-ticket_7876_encdec(per) ->
- ?line {ok,{initiatingMessage,_}} = 'S1AP-PDU-Descriptions':decode('S1AP-PDU', [0,2,64,49,0,0,5,0,0,0,4,128,106,56,197,0,8,0,3,64,2,134,0,100,64,8,0,66,240,153,0,7,192,16,0,67,64,6,0,66,240,153,70,1,0,107,64,5,0,0,0,0,0]);
-ticket_7876_encdec(_) ->
- ?line {ok,{initiatingMessage,_}} = 'S1AP-PDU-Descriptions':decode('S1AP-PDU', <<0,2,64,49,0,0,5,0,0,0,4,128,106,56,197,0,8,0,3,64,2,134,0,100,64,8,0,66,240,153,0,7,192,16,0,67,64,6,0,66,240,153,70,1,0,107,64,5,0,0,0,0,0>>).
+ber_get_tag(<<>>) ->
+ done;
+ber_get_tag(<<_:2,0:1,_:5,_/binary>>) ->
+ primitive;
+ber_get_tag(<<_:2,1:1,_:5,_/binary>>=Bin0) ->
+ TagLen = ber_tag_length(Bin0),
+ <<Tag:TagLen/binary,Bin/binary>> = Bin0,
+ {constructed,Tag,Bin}.
+
+ber_tag_length(<<_:3,2#11111:5,T/binary>>) ->
+ ber_tag_length_1(T, 1);
+ber_tag_length(_) ->
+ 1.
+
+ber_tag_length_1(<<1:1,_:7,T/binary>>, N) ->
+ ber_tag_length_1(T, N+1);
+ber_tag_length_1(<<0:1,_:7,_/binary>>, N) ->
+ N+1.
+
+ber_get_len(<<0:1,L:7,T/binary>>) ->
+ {L,T};
+ber_get_len(<<1:1,Octets:7,T0/binary>>) ->
+ <<L:Octets/unit:8,T/binary>> = T0,
+ {L,T}.
diff --git a/lib/asn1/test/asn1_wrapper.erl b/lib/asn1/test/asn1_wrapper.erl
deleted file mode 100644
index ac194fe38b..0000000000
--- a/lib/asn1/test/asn1_wrapper.erl
+++ /dev/null
@@ -1,49 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% 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
-%% 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(asn1_wrapper).
--author('kenneth@bilbo').
-
--compile(export_all).
-%%-export([Function/Arity, ...]).
-
-
-encode(Module,Type,Value) ->
- case asn1rt:encode(Module,Type,Value) of
- {ok,X} when is_binary(X) ->
- {ok, binary_to_list(X)};
- {ok,X} ->
- {ok, binary_to_list(list_to_binary(X))};
- Error ->
- Error
- 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(per) ->
- per;
-erule(uper) ->
- per.
-
-
diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl
index 1c4b4c6894..ef11717c45 100644
--- a/lib/asn1/test/ber_decode_error.erl
+++ b/lib/asn1/test/ber_decode_error.erl
@@ -22,15 +22,15 @@
-export([run/1]).
run([]) ->
- {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
+ {ok,B} = 'Constructed':encode('S3', {'S3',17}),
+ [T,L|V] = binary_to_list(B),
+ Bytes = list_to_binary([T,L+3|V] ++ [2,1,3]),
+ case 'Constructed':decode('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),
+ {ok,{'S3ext',17}} = 'Constructed':decode('S3ext', Bytes),
%% Truncated tag.
{error,{asn1,{invalid_tag,_}}} =
@@ -51,4 +51,22 @@ run([]) ->
{error,{asn1,{invalid_value,_}}} =
(catch 'Constructed':decode('I', <<8,7>>)),
+ %% Short indefinite length. Make sure that the decoder doesn't look
+ %% beyond the end of binary when looking for a 0,0 terminator.
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('S', sub(<<8,16#80,0,0>>, 3))),
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('S', sub(<<8,16#80,0,0>>, 2))),
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('S', sub(<<40,16#80,1,1,255,0,0>>, 6))),
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('S', sub(<<40,16#80,1,1,255,0,0>>, 5))),
+
+ %% A primitive must not be encoded with an indefinite length.
+ {error,{asn1,{invalid_length,_}}} =
+ (catch 'Constructed':decode('OS', <<4,128,4,3,97,98,99,0,0>>)),
ok.
+
+sub(Bin, Bytes) ->
+ <<B:Bytes/binary,_/binary>> = Bin,
+ B.
diff --git a/lib/asn1/test/choice_extension.erl b/lib/asn1/test/choice_extension.erl
deleted file mode 100644
index 85e0936ebf..0000000000
--- a/lib/asn1/test/choice_extension.erl
+++ /dev/null
@@ -1,37 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-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(choice_extension).
-
--export([run/0, compile/3]).
-
--include_lib("test_server/include/test_server.hrl").
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "ChoExtension",[Rules,{outdir,OutDir}]++Options).
-
-run() ->
- Val = {str,"abc"},
- ?line {ok,B} = asn1_wrapper:encode('ChoExtension','ChoExt4',Val),
- ?line {ok,Val} = asn1_wrapper:decode('ChoExtension','ChoExt4',lists:flatten(B)),
- ok.
diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl
index a94a6d95a0..1edd60f7c8 100644
--- a/lib/asn1/test/error_SUITE.erl
+++ b/lib/asn1/test/error_SUITE.erl
@@ -19,7 +19,9 @@
-module(error_SUITE).
-export([suite/0,all/0,groups/0,
- already_defined/1,enumerated/1]).
+ already_defined/1,bitstrings/1,enumerated/1,
+ imports/1,instance_of/1,integers/1,objects/1,
+ parameterization/1,values/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -29,8 +31,16 @@ all() ->
[{group,p}].
groups() ->
- [{p,parallel(),[already_defined,
- enumerated]}].
+ [{p,parallel(),
+ [already_defined,
+ bitstrings,
+ enumerated,
+ imports,
+ instance_of,
+ integers,
+ objects,
+ parameterization,
+ values]}].
parallel() ->
case erlang:system_info(schedulers) > 1 of
@@ -67,6 +77,23 @@ already_defined(Config) ->
} = run(P, Config),
ok.
+bitstrings(Config) ->
+ M = 'Bitstrings',
+ P = {M,
+ <<"Bitstrings DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " Bs1 ::= BIT STRING {a(1), a(1)}\n"
+ " Bs2 ::= BIT STRING {a(1), b(2), a(3)}\n"
+ " Bs3 ::= BIT STRING {x(1), y(1)}\n"
+ " Bs4 ::= BIT STRING {x(-1), y(0)}\n"
+ "END\n">>},
+ {error,
+ [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}},
+ {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}},
+ {structured_error,{M,4},asn1ct_check,{value_reused,1}},
+ {structured_error,{M,5},asn1ct_check,{invalid_bit_number,-1}}
+ ]} = run(P, Config),
+ ok.
+
enumerated(Config) ->
M = 'Enumerated',
P = {M,
@@ -95,6 +122,137 @@ enumerated(Config) ->
} = run(P, Config),
ok.
+imports(Config) ->
+ Ext = 'ExternalModule',
+ ExtP = {Ext,
+ <<"ExternalModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ "END\n">>},
+ ok = run(ExtP, Config),
+
+ M = 'Imports',
+ P = {M,
+ <<"Imports DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ "IMPORTS NotDefined FROM ExternalModule\n"
+ "X FROM UndefinedModule objid\n"
+ "Y, Z FROM UndefinedModule2;\n"
+ "objid OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) remote-operations(4)\n"
+ " notation(0)}\n"
+ "END\n">>},
+ {error,[{structured_error,{M,2},asn1ct_check,
+ {undefined_import,'NotDefined','ExternalModule'}},
+ {structured_error,{M,3},asn1ct_check,{undefined_import,'X','UndefinedModule'}},
+ {structured_error,{M,4},asn1ct_check,{undefined_import,'Y','UndefinedModule2'}},
+ {structured_error,{M,4},asn1ct_check,{undefined_import,'Z','UndefinedModule2'}}
+ ]} = run(P, Config),
+ ok.
+
+instance_of(Config) ->
+ M = 'InstanceOf',
+ P = {M,
+ <<"InstanceOf DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ "XX ::= INSTANCE OF CL ({TI})\n"
+ "CL ::= CLASS {\n"
+ "&id INTEGER,\n"
+ "&Type\n"
+ "}\n"
+ "o1 CL ::= {&id 1, &Type OCTET STRING}\n"
+ "TI CL ::= { o1 }\n"
+ "END\n">>},
+ {error,
+ [{structured_error,{M,2},asn1ct_check,{illegal_instance_of,'CL'}}
+ ]} = run(P, Config),
+ ok.
+
+integers(Config) ->
+ M = 'Integers',
+ P = {M,
+ <<"Integers DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " Int1 ::= INTEGER {a(1), a(1)}\n"
+ " Int2 ::= INTEGER {a(1), b(2), a(3)}\n"
+ " Int3 ::= INTEGER {x(1), y(1)}\n"
+ "END\n">>},
+ {error,
+ [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}},
+ {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}},
+ {structured_error,{M,4},asn1ct_check,{value_reused,1}}
+ ]} = run(P, Config),
+ ok.
+
+
+objects(Config) ->
+ M = 'Objects',
+ P = {M,
+ <<"Objects DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " obj1 CL ::= { &wrong 42 }\n"
+ " obj2 CL ::= { &wrong 1, &Wrong INTEGER }\n"
+ " obj3 CL ::= { &Data OCTET STRING }\n"
+ " obj4 SMALL ::= { &code 42 }\n"
+ " InvalidSet CL ::= { obj1 }\n"
+
+ " CL ::= CLASS {\n"
+ " &code INTEGER UNIQUE,\n"
+ " &enum ENUMERATED { a, b, c},\n"
+ " &Data,\n"
+ " &object CL,\n"
+ " &Set CL,\n"
+ " &vartypevalue &Data,\n"
+ " &VarTypeValue &Data\n"
+ " }\n"
+
+ " SMALL ::= CLASS {\n"
+ " &code INTEGER UNIQUE,\n"
+ " &i INTEGER\n"
+ " }\n"
+ "END\n">>},
+ {error,
+ [
+ {structured_error,{M,2},asn1ct_check,
+ {invalid_fields,[wrong],obj1}},
+ {structured_error,{M,3},asn1ct_check,
+ {invalid_fields,['Wrong',wrong],obj2}},
+ {structured_error,{M,4},asn1ct_check,
+ {missing_mandatory_fields,['Set','VarTypeValue',code,
+ enum,object,vartypevalue],obj3}},
+ {structured_error,{M,5},asn1ct_check,
+ {missing_mandatory_fields,[i],obj4}},
+ {structured_error,{M,6},asn1ct_check,
+ {invalid_fields,[wrong],'InvalidSet'}}
+ ]
+ } = run(P, Config),
+ ok.
+
+parameterization(Config) ->
+ M = 'Parameterization',
+ P = {M,
+ <<"Parameterization DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " NotUppercase{lowercase} ::= INTEGER (lowercase)\n"
+ "END\n">>},
+ {error,
+ [{structured_error,{'Parameterization',2},asn1ct_check,
+ {illegal_typereference,lowercase}}
+ ]
+ } = run(P, Config),
+ ok.
+
+values(Config) ->
+ M = 'Values',
+ P = {M,
+ <<"Values DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
+ " os1 OCTET STRING ::= \"abc\"\n"
+ " os2 OCTET STRING ::= 42\n"
+ " os3 OCTET STRING ::= { 1, 3 }\n"
+ "END\n">>},
+ {error,
+ [
+ {structured_error,{M,2},asn1ct_check,
+ illegal_octet_string_value},
+ {structured_error,{M,3},asn1ct_check,
+ illegal_octet_string_value},
+ {structured_error,{M,4},asn1ct_check,
+ illegal_octet_string_value}
+ ]
+ } = run(P, Config),
+ ok.
run({Mod,Spec}, Config) ->
diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl
index 426ae16994..7577928493 100644
--- a/lib/asn1/test/h323test.erl
+++ b/lib/asn1/test/h323test.erl
@@ -26,44 +26,62 @@ run(per) -> run();
run(_Rules) -> ok.
run() ->
- alerting(),
- connect(),
+ roundtrip('H323-UserInformation', alerting_val(), alerting_enc()),
+ roundtrip('H323-UserInformation', connect_val(), connect_enc()),
+ general_string(),
ok.
-dec_alerting() ->
- Cs = "0380060008914a0002020120110000000000000000000000000000000000",
- ByteList = hexstr2bytes(Cs),
- asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
+alerting_val() ->
+ {'H323-UserInformation',
+ {'H323-UU-PDU',
+ {alerting,
+ {'Alerting-UUIE',
+ {0,0,8,2250,0,2},
+ {'EndpointType',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ asn1_NOVALUE,asn1_NOVALUE,
+ {'TerminalInfo',asn1_NOVALUE},
+ false,false},
+ asn1_NOVALUE,
+ {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
+ asn1_NOVALUE}.
-enc_alerting(V) ->
- asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V).
+alerting_enc() ->
+ "0380060008914a0002020120110000000000000000000000000000000000".
-alerting() ->
- {ok,V} = dec_alerting(),
- {ok,B} = enc_alerting(V),
- ByteList = lists:flatten(B),
- {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
+connect_val() ->
+ {'H323-UserInformation',
+ {'H323-UU-PDU',
+ {connect,
+ {'Connect-UUIE',
+ {0,0,8,2250,0,2},
+ {ipAddress,
+ {'TransportAddress_ipAddress',<<136,225,41,58>>,1187}},
+ {'EndpointType',asn1_NOVALUE,
+ {'VendorIdentifier',
+ {'H221NonStandard',181,0,21324},
+ <<77,105,99,114,111,115,111,102,116,174,32,78,101,116,
+ 77,101,100,116,105,110,103,174,0>>,
+ <<51,46,48,0>>},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ {'TerminalInfo',asn1_NOVALUE},
+ false,false},
+ <<22,137,237,197,191,35,211,17,140,45,0,192,79,75,28,208>>,
+ {'CallIdentifier',<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
+ asn1_NOVALUE}.
+connect_enc() ->
+ "02c0060008914a00020088e1293a04a322c0b500534c164d6963726f736f6674ae204e65744d656474696e67ae0003332e3000001689edc5bf23d3118c2d00c04f4b1cd00900110000000000000000000000000000000000".
-dec_connect() ->
- Cs = "02c0060008914a00020088e1293a04a322c0b500534c164d6963726f736f6674ae204e65744d656474696e67ae0003332e3000001689edc5bf23d3118c2d00c04f4b1cd00900110000000000000000000000000000000000",
- ByteList = hexstr2bytes(Cs),
- asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
+general_string() ->
+ Type = 'MultimediaSystemControlMessage',
+ UI = <<109,64,1,57>>,
+ {ok, _V} = 'MULTIMEDIA-SYSTEM-CONTROL':decode(Type, UI).
-enc_connect(V) ->
- asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V).
-
-connect() ->
- {ok,V} = dec_connect(),
- {ok,B} = enc_connect(V),
- ByteList = lists:flatten(B),
- {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList).
-
-hexstr2bytes([D1,D2|T]) ->
- [dig2num(D1)*16+dig2num(D2)|hexstr2bytes(T)];
-hexstr2bytes([]) ->
- [].
-
-dig2num(D) when D >= $0, D =< $9 -> D - $0;
-dig2num(D) when D >= $a, D =< $f -> 10 + D - $a;
-dig2num(D) when D >= $A, D =< $F -> 10 + D - $A.
+roundtrip(T, V, HexString) ->
+ Enc = asn1_test_lib:hex_to_bin(HexString),
+ Enc = asn1_test_lib:roundtrip_enc('H323-MESSAGES', T, V),
+ ok.
diff --git a/lib/asn1/test/pem_performance.erl b/lib/asn1/test/pem_performance.erl
deleted file mode 100644
index 87b8cbd61d..0000000000
--- a/lib/asn1/test/pem_performance.erl
+++ /dev/null
@@ -1,37 +0,0 @@
-%% %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([cert_pem/0]).
--module([dsa_pem/0]).
-
-cert_pem() ->
- 'OTP-PUB-KEY':decode('Certificate',<<48,130,3,184,48,130,3,33,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,131,49,14,48,12,6,3,85,4,3,19,5,111,116,112,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,30,23,13,48,56,48,49,48,57,48,56,50,57,51,48,90,23,13,49,55,49,49,49,55,48,56,50,57,51,48,90,48,129,132,49,15,48,13,6,3,85,4,3,19,6,99,108,105,101,110,116,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,245,56,68,254,220,239,193,190,63,221,182,60,67,77,121,163,214,136,137,183,139,8,166,30,100,27,45,17,126,58,15,173,151,218,75,224,148,14,22,164,10,100,186,183,104,175,197,97,96,182,146,150,106,129,140,100,194,106,90,62,133,233,155,46,155,33,101,220,83,193,182,232,240,99,253,249,114,8,159,172,143,77,179,132,229,205,29,110,185,233,224,52,25,149,249,100,80,229,199,125,23,106,146,233,159,26,13,8,161,206,221,43,240,149,42,45,194,190,85,6,235,152,220,219,160,32,144,67,2,3,1,0,1,163,130,1,55,48,130,1,51,48,9,6,3,85,29,19,4,2,48,0,48,11,6,3,85,29,15,4,4,3,2,5,224,48,29,6,3,85,29,14,4,22,4,20,26,59,44,5,72,211,158,214,23,34,30,241,125,27,123,115,93,163,231,120,48,129,179,6,3,85,29,35,4,129,171,48,129,168,128,20,6,171,128,52,58,164,184,118,178,189,157,46,40,229,109,145,222,125,1,155,161,129,140,164,129,137,48,129,134,49,17,48,15,6,3,85,4,3,19,8,101,114,108,97,110,103,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,11,48,9,6,3,85,4,6,19,2,83,69,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,130,1,1,48,33,6,3,85,29,17,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,33,6,3,85,29,18,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,129,129,0,93,11,112,227,121,15,121,179,247,135,110,216,17,197,84,18,149,166,147,142,190,178,0,209,190,0,142,233,144,100,194,205,220,182,73,204,108,42,95,23,48,63,4,120,239,42,194,25,184,35,117,107,96,229,18,45,76,122,125,40,171,210,132,50,146,178,160,55,17,35,255,208,114,30,47,55,185,154,155,165,204,180,14,143,20,234,6,234,201,225,72,235,5,87,61,255,250,23,217,1,144,246,98,221,223,102,49,168,177,13,70,241,26,27,254,251,217,14,244,18,242,197,151,50,186,214,15,42>>).
-
-dsa_pem() ->
- 'OTP-PUB-KEY':decode('DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135,2,20,89,128,159,14,187,249,182,172,15,88,162,110,211,71,179,209,29,125,217,38>>),
- 'OTP-PUB-KEY':decode('SubjectPublicKeyInfo',<<48,130,1,183,48,130,1,44,6,7,42,134,72,206,56,4,1,48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,3,129,132,0,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
- 'OTP-PUB-KEY':decode('DSAParams',<<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>),
- 'OTP-PUB-KEY':decode('DSAPublicKey',<<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
- 'OTP-PUB-KEY':encode('DSAParams',{params,{'Dss-Parms',129000451850199666185842362389296595317127259539517666765336291347244303954511451744518587442120964433734460998523119938005801396466878889993179871123036311260456172022864663021425348874648247531097042575063545128239655736096045972718934778583429973433661785691086624069991876932064334822608460064613803976593,1216700114794736143432235288305776850295620488937,104420402274523493329542694749036577763086597934731674202966304958550599470165597750883637440049774107540742087494301536297571301945349213110548764383811017178451900599240379681904765817950545426764751538502808499880604633364255316249231153053427235538288687666086821781456733226598288985591031656134573747213}}),
- 'OTP-PUB-KEY':encode(
- 'SubjectPublicKeyInfo',
- {'SubjectPublicKeyInfo',
- {'AlgorithmIdentifier',
- {1,2,840,10040,4,1},
- <<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>},
- {0,
- <<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>}}).
diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl
index c6a07646c2..09e19ceebb 100644
--- a/lib/asn1/test/testChoExtension.erl
+++ b/lib/asn1/test/testChoExtension.erl
@@ -31,16 +31,13 @@ extension(_Rules) ->
%% A trick to encode with another compatible CHOICE type to test reception
%% extension alternative
- {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]),
+ roundtrip('ChoExt1x', {str,<<"abc">>}),
roundtrip('ChoExt2', {bool,true}),
roundtrip('ChoExt2', {int,33}),
roundtrip('ChoExt3', {bool,true}),
roundtrip('ChoExt3', {int,33}),
- roundtrip('ChoExt4', {str,"abc"}),
+ roundtrip('ChoExt4', {str,<<"abc">>}),
roundtrip('ChoEmptyRoot', {bool,false}),
roundtrip('ChoEmptyRoot', {bool,true}),
@@ -51,6 +48,4 @@ extension(_Rules) ->
roundtrip(Type, Value) ->
- {ok,Encoded} = 'ChoExtension':encode(Type, Value),
- {ok,Value} = 'ChoExtension':decode(Type, Encoded),
- ok.
+ asn1_test_lib:roundtrip('ChoExtension', Type, Value).
diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl
index 5fdee48add..0914d54f33 100644
--- a/lib/asn1/test/testChoExternal.erl
+++ b/lib/asn1/test/testChoExternal.erl
@@ -18,25 +18,11 @@
%%
%%
-module(testChoExternal).
-
-
--export([compile/3]).
-export([external/1]).
-include_lib("test_server/include/test_server.hrl").
-include("External.hrl").
-
-
-compile(Config, Rules, Optimize) ->
- DataDir = ?config(data_dir, Config),
- CaseDir = ?config(case_dir, Config),
- true = code:add_patha(CaseDir),
- ok = asn1ct:compile(DataDir ++ "ChoExternal",
- [Rules, {outdir, CaseDir}] ++ Optimize).
-
-
-
external(_Rules) ->
roundtrip('ChoXCho', {boolCho,true}),
roundtrip('ChoXCho', {intCho,77}),
@@ -45,20 +31,18 @@ external(_Rules) ->
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"}),
+ 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.
+ asn1_test_lib:roundtrip('ChoExternal', Type, Value).
diff --git a/lib/asn1/test/testChoOptional.erl b/lib/asn1/test/testChoOptional.erl
index cbb8134e51..71a7346e3f 100644
--- a/lib/asn1/test/testChoOptional.erl
+++ b/lib/asn1/test/testChoOptional.erl
@@ -18,83 +18,34 @@
%%
%%
-module(testChoOptional).
+-export([run/0]).
--export([optional/1]).
+-record('Seq1', {bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}).
+-record('Seq2', {int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}).
+-record('Seq3', {cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}).
-%-include("ChoOptional.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("External.hrl").
+run() ->
+ roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,cho=asn1_NOVALUE}),
+ roundtrip('Seq1', #'Seq1'{bool=true,int=233,cho=asn1_NOVALUE}),
+ roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,
+ cho={vsCho,"Vs Str"}}),
+ roundtrip('Seq1', #'Seq1'{bool=true,int=asn1_NOVALUE,
+ cho={ocStrCho,<<"Oct Str">>}}),
+ roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho=asn1_NOVALUE,bool=true}),
+ roundtrip('Seq2', #'Seq2'{int=233,cho=asn1_NOVALUE,bool=true}),
+ roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho={vsCho,"Vs Str"},bool=true}),
+ roundtrip('Seq2', #'Seq2'{int=asn1_NOVALUE,cho={ocStrCho,<<"Oct Str">>},
+ bool=true}),
+ roundtrip('Seq3', #'Seq3'{cho=asn1_NOVALUE,int=asn1_NOVALUE,bool=true}),
+ roundtrip('Seq3', #'Seq3'{cho=asn1_NOVALUE,int=233,bool=true}),
+ roundtrip('Seq3', #'Seq3'{cho={vsCho,"Vs Str"},int=asn1_NOVALUE,bool=true}),
+ roundtrip('Seq3', #'Seq3'{cho={ocStrCho,<<"Oct Str">>},
+ int=asn1_NOVALUE,bool=true}),
+ ok.
--record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}).
--record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}).
--record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}).
+roundtrip(Type, Value) ->
+ roundtrip('ChoOptional', Type, Value),
+ roundtrip('ChoOptionalImplicitTag', Type, Value).
-optional(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,asn1_NOVALUE}} =
- asn1_wrapper:decode('ChoOptional','Seq1',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true,
- int = 233}),
- ?line {ok,{'Seq1',true,233,asn1_NOVALUE}} =
- asn1_wrapper:decode('ChoOptional','Seq1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,{vsCho,"Vs Str"}}} =
- asn1_wrapper:decode('ChoOptional','Seq1',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,{ocStrCho,"Oct Str"}}} =
- asn1_wrapper:decode('ChoOptional','Seq1',lists:flatten(Bytes14)),
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoOptional','Seq2',#'Seq2'{bool = true}),
- ?line {ok,{'Seq2',asn1_NOVALUE,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptional','Seq2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoOptional','Seq2',#'Seq2'{bool = true,
- int = 233}),
- ?line {ok,{'Seq2',233,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptional','Seq2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoOptional','Seq2',#'Seq2'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq2',asn1_NOVALUE,{vsCho,"Vs Str"},true}} =
- asn1_wrapper:decode('ChoOptional','Seq2',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} =
- asn1_wrapper:encode('ChoOptional','Seq2',#'Seq2'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq2',asn1_NOVALUE,{ocStrCho,"Oct Str"},true}} =
- asn1_wrapper:decode('ChoOptional','Seq2',lists:flatten(Bytes24)),
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('ChoOptional','Seq3',#'Seq3'{bool = true}),
- ?line {ok,{'Seq3',asn1_NOVALUE,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptional','Seq3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('ChoOptional','Seq3',#'Seq3'{bool = true,
- int = 233}),
- ?line {ok,{'Seq3',asn1_NOVALUE,233,true}} =
- asn1_wrapper:decode('ChoOptional','Seq3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('ChoOptional','Seq3',#'Seq3'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq3',{vsCho,"Vs Str"},asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptional','Seq3',lists:flatten(Bytes33)),
-
- ?line {ok,Bytes34} =
- asn1_wrapper:encode('ChoOptional','Seq3',#'Seq3'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq3',{ocStrCho,"Oct Str"},asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptional','Seq3',lists:flatten(Bytes34)),
-
-
-
- ok.
+roundtrip(Mod, Type, Value) ->
+ asn1_test_lib:roundtrip(Mod, Type, Value).
diff --git a/lib/asn1/test/testChoOptionalImplicitTag.erl b/lib/asn1/test/testChoOptionalImplicitTag.erl
deleted file mode 100644
index efe335cabd..0000000000
--- a/lib/asn1/test/testChoOptionalImplicitTag.erl
+++ /dev/null
@@ -1,101 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-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(testChoOptionalImplicitTag).
-
-
--export([optional/1]).
-
-%-include("ChoOptional.hrl").
--include_lib("test_server/include/test_server.hrl").
--include("External.hrl").
-
--record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}).
--record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}).
--record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}).
-
-optional(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,asn1_NOVALUE}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq1',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true,
- int = 233}),
- ?line {ok,{'Seq1',true,233,asn1_NOVALUE}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,{vsCho,"Vs Str"}}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq1',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq1',true,asn1_NOVALUE,{ocStrCho,"Oct Str"}}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq1',lists:flatten(Bytes14)),
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq2',#'Seq2'{bool = true}),
- ?line {ok,{'Seq2',asn1_NOVALUE,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq2',#'Seq2'{bool = true,
- int = 233}),
- ?line {ok,{'Seq2',233,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq2',#'Seq2'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq2',asn1_NOVALUE,{vsCho,"Vs Str"},true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq2',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} =
- asn1_wrapper:encode('ChoOptionalImplicitTag','Seq2',#'Seq2'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq2',asn1_NOVALUE,{ocStrCho,"Oct Str"},true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq2',lists:flatten(Bytes24)),
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq3',#'Seq3'{bool = true}),
- ?line {ok,{'Seq3',asn1_NOVALUE,asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq3',#'Seq3'{bool = true,
- int = 233}),
- ?line {ok,{'Seq3',asn1_NOVALUE,233,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq3',#'Seq3'{bool = true,
- cho = {vsCho,"Vs Str"}}),
- ?line {ok,{'Seq3',{vsCho,"Vs Str"},asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq3',lists:flatten(Bytes33)),
-
- ?line {ok,Bytes34} =
- asn1_wrapper:encode('ChoOptionalImplicitTag','Seq3',#'Seq3'{bool = true,
- cho = {ocStrCho,"Oct Str"}}),
- ?line {ok,{'Seq3',{ocStrCho,"Oct Str"},asn1_NOVALUE,true}} =
- asn1_wrapper:decode('ChoOptionalImplicitTag','Seq3',lists:flatten(Bytes34)),
-
-
-
- ok.
diff --git a/lib/asn1/test/testChoPrim.erl b/lib/asn1/test/testChoPrim.erl
index 936a38f76c..4665de6989 100644
--- a/lib/asn1/test/testChoPrim.erl
+++ b/lib/asn1/test/testChoPrim.erl
@@ -25,80 +25,44 @@
-include_lib("test_server/include/test_server.hrl").
bool(Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoPrim','ChoCon',{bool0,true}),
- ?line {ok,{bool0,true}} = asn1_wrapper:decode('ChoPrim','ChoCon',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoPrim','ChoCon',{bool1,true}),
- ?line {ok,{bool1,true}} = asn1_wrapper:decode('ChoPrim','ChoCon',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('ChoPrim','ChoCon',{int2,233}),
- ?line {ok,{int2,233}} = asn1_wrapper:decode('ChoPrim','ChoCon',lists:flatten(Bytes13)),
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,{invalid_choice_type,wrong}}} =
- case catch asn1_wrapper:encode('ChoPrim','ChoCon',{wrong,233}) of
- X1 -> X1 end,
- ?line {error,{asn1,{invalid_choice_tag,_WrongTag}}} =
- case catch asn1_wrapper:decode('ChoPrim','ChoCon',[131,2,0,233]) of
- X2 -> X2 end,
- ok;
-
- per ->
- ok
- end,
-
+ roundtrip('ChoCon', {bool0,true}),
+ roundtrip('ChoCon', {bool1,true}),
+ roundtrip('ChoCon', {int2,233}),
+ case Rules of
+ ber ->
+ {error,{asn1,{invalid_choice_type,wrong}}} =
+ (catch 'ChoPrim':encode('ChoCon', {wrong,233})),
+ {error,{asn1,{invalid_choice_tag,_WrongTag}}} =
+ (catch 'ChoPrim':decode('ChoCon', <<131,2,0,233>>));
+ per ->
+ ok;
+ uper ->
+ ok
+ end,
ok.
-
-
int(Rules) ->
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoPrim','ChoExp',{int10,1}),
- ?line {ok,{int10,first}} = asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoPrim','ChoExp',{int10,first}),
- ?line {ok,{int10,first}} = asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoPrim','ChoExp',{int10,last}),
- ?line {ok,{int10,last}} = asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} = asn1_wrapper:encode('ChoPrim','ChoExp',{bool11,true}),
- ?line {ok,{bool11,true}} = asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes24)),
-
-
- ?line {ok,Bytes26} = asn1_wrapper:encode('ChoPrim','ChoExp',{enum12,one}),
- ?line {ok,{enum12,one}} = asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes26)),
-
- ?line {ok,Bytes25} = asn1_wrapper:encode('ChoPrim','ChoExp',{bool11,true}),
- ?line {ok,{bool11,true}} =
- asn1_wrapper:decode('ChoPrim','ChoExp',lists:flatten(Bytes25)),
-
- ?line {error,{asn1,_}} =
- case catch asn1_wrapper:encode('ChoPrim','ChoExp',{enum12,four}) of
- X3 -> X3 end,
-
- ?line {error,{asn1,_}} =
- case catch asn1_wrapper:encode('ChoPrim','ChoExp',{wrong,233}) of
- X4 -> io:format("error reason = ~p~n",[X4]), X4 end,
-
- ?line case asn1_wrapper:erule(Rules) of
- ber ->
- ?line {error,{asn1,_}} =
- case catch asn1_wrapper:decode('ChoPrim','ChoExp',[107,3,2,1,1]) of
- X5 -> X5 end,
- ok;
-
- per ->
- ok
- end,
+ roundtrip('ChoExp', {int10,1}, {int10,first}),
+ roundtrip('ChoExp', {int10,first}),
+ roundtrip('ChoExp', {int10,last}),
+ roundtrip('ChoExp', {bool11,true}),
+ roundtrip('ChoExp', {enum12,one}),
+ roundtrip('ChoExp', {bool11,true}),
+
+ {error,{asn1,_}} = (catch 'ChoPrim':encode('ChoExp', {enum12,four})),
+ {error,{asn1,_}} = (catch 'ChoPrim':encode('ChoExp', {wrong,233})),
+ case Rules of
+ ber ->
+ {error,{asn1,_}} = (catch 'ChoPrim':decode('ChoExp', <<107,3,2,1,1>>));
+ per ->
+ ok;
+ uper ->
+ ok
+ end,
ok.
+roundtrip(Type, Value) ->
+ roundtrip(Type, Value, Value).
-
-
-
-
-
-
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('ChoPrim', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl
index ee26d124a9..ccd60c2897 100644
--- a/lib/asn1/test/testChoRecursive.erl
+++ b/lib/asn1/test/testChoRecursive.erl
@@ -31,18 +31,16 @@ recursive(_Rules) ->
roundtrip('ChoRec',
{something,
#'ChoRec_something'{a = 77,
- b = "some octets here",
+ b = <<"some octets here">>,
c = {nothing,'NULL'}}}),
roundtrip('ChoRec', {nothing,'NULL'}),
roundtrip('ChoRec2',
{something,
#'ChoRec2_something'{a = 77,
- b = "some octets here",
+ 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.
+ asn1_test_lib:roundtrip('ChoRecursive', Type, Value).
diff --git a/lib/asn1/test/testChoTypeRefCho.erl b/lib/asn1/test/testChoTypeRefCho.erl
index 9bd732f462..636c301403 100644
--- a/lib/asn1/test/testChoTypeRefCho.erl
+++ b/lib/asn1/test/testChoTypeRefCho.erl
@@ -24,43 +24,15 @@
-include_lib("test_server/include/test_server.hrl").
choice(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{choCho,{choInt,88}}),
- ?line {ok,{choCho,{choInt,88}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoTRcho',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{choChoE,{choInt,88}}),
- ?line {ok,{choChoE,{choInt,88}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoTRcho',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{'choCho-E',{choInt,88}}),
- ?line {ok,{'choCho-E',{choInt,88}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoTRcho',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{'choChoE-E',{choInt,88}}),
- ?line {ok,{'choChoE-E',{choInt,88}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoTRcho',lists:flatten(Bytes14)),
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoTypeRefCho','ChoChoInline',{bool1,true}),
- ?line {ok,{bool1,true}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoChoInline',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoTypeRefCho','ChoChoInline',{'choCho',{bool,true}}),
- ?line {ok,{'choCho',{bool,true}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoChoInline',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoTypeRefCho','ChoChoInline',{'choCho',{octStr,"kk"}}),
- ?line {ok,{'choCho',{octStr,"kk"}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoChoInline',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} = asn1_wrapper:encode('ChoTypeRefCho','ChoChoInline',{'choCho',{int,55}}),
- ?line {ok,{'choCho',{int,55}}} =
- asn1_wrapper:decode('ChoTypeRefCho','ChoChoInline',lists:flatten(Bytes24)),
-
-
-
-
-
+ roundtrip('ChoTRcho', {choCho,{choInt,88}}),
+ roundtrip('ChoTRcho', {choChoE,{choInt,88}}),
+ roundtrip('ChoTRcho', {'choCho-E',{choInt,88}}),
+ roundtrip('ChoTRcho', {'choChoE-E',{choInt,88}}),
+ roundtrip('ChoChoInline', {bool1,true}),
+ roundtrip('ChoChoInline', {choCho,{bool,true}}),
+ roundtrip('ChoChoInline', {choCho,{octStr,<<"kk">>}}),
+ roundtrip('ChoChoInline', {choCho,{int,55}}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ChoTypeRefCho', Type, Value).
diff --git a/lib/asn1/test/testChoTypeRefPrim.erl b/lib/asn1/test/testChoTypeRefPrim.erl
index edef6192fe..747baeddd8 100644
--- a/lib/asn1/test/testChoTypeRefPrim.erl
+++ b/lib/asn1/test/testChoTypeRefPrim.erl
@@ -24,60 +24,20 @@
-include_lib("test_server/include/test_server.hrl").
prim(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{bool,true}),
- ?line {ok,{bool,true}} = asn1_wrapper:decode('ChoTypeRefPrim','ChoTR',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{octStr,[11,12,13,14,15,16,17]}),
- ?line {ok,{octStr,[11,12,13,14,15,16,17]}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{int,233}),
- ?line {ok,{int,233}} = asn1_wrapper:decode('ChoTypeRefPrim','ChoTR',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{octStr,"Stringing in the rain"}),
- ?line {ok,{octStr,"Stringing in the rain"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR',lists:flatten(Bytes14)),
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStr',"A string"}),
- ?line {ok,{'octStr',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrI',"A string"}),
- ?line {ok,{'octStrI',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrE',"A string"}),
- ?line {ok,{'octStrE',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStr-I',"A string"}),
- ?line {ok,{'octStr-I',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes24)),
-
- ?line {ok,Bytes25} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrI-I',"A string"}),
- ?line {ok,{'octStrI-I',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes25)),
-
- ?line {ok,Bytes26} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrE-I',"A string"}),
- ?line {ok,{'octStrE-I',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes26)),
-
- ?line {ok,Bytes27} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStr-E',"A string"}),
- ?line {ok,{'octStr-E',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes27)),
-
- ?line {ok,Bytes28} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrI-E',"A string"}),
- ?line {ok,{'octStrI-E',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes28)),
-
- ?line {ok,Bytes29} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR2',{'octStrE-E',"A string"}),
- ?line {ok,{'octStrE-E',"A string"}} =
- asn1_wrapper:decode('ChoTypeRefPrim','ChoTR2',lists:flatten(Bytes29)),
-
-
+ roundtrip('ChoTR', {bool,true}),
+ roundtrip('ChoTR', {octStr,<<11,12,13,14,15,16,17>>}),
+ roundtrip('ChoTR', {int,233}),
+ roundtrip('ChoTR', {octStr,<<"Stringing in the rain">>}),
+ roundtrip('ChoTR2', {octStr,<<"A string">>}),
+ roundtrip('ChoTR2', {octStrI,<<"A string">>}),
+ roundtrip('ChoTR2', {octStrE,<<"A string">>}),
+ roundtrip('ChoTR2', {'octStr-I',<<"A string">>}),
+ roundtrip('ChoTR2', {'octStrI-I',<<"A string">>}),
+ roundtrip('ChoTR2', {'octStrE-I',<<"A string">>}),
+ roundtrip('ChoTR2', {'octStr-E',<<"A string">>}),
+ roundtrip('ChoTR2', {'octStrI-E',<<"A string">>}),
+ roundtrip('ChoTR2', {'octStrE-E',<<"A string">>}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ChoTypeRefPrim', Type, Value).
diff --git a/lib/asn1/test/testChoTypeRefSeq.erl b/lib/asn1/test/testChoTypeRefSeq.erl
index bf2b66c73e..91d0b45e89 100644
--- a/lib/asn1/test/testChoTypeRefSeq.erl
+++ b/lib/asn1/test/testChoTypeRefSeq.erl
@@ -23,82 +23,30 @@
-include_lib("test_server/include/test_server.hrl").
--record('ChoSeq',{seqInt, seqOs}).
--record('ChoSeqImp',{seqInt, seqOs}).
--record('ChoSeqExp',{seqInt, seqOs}).
+-record('ChoSeq', {seqInt, seqOs}).
+-record('ChoSeqImp', {seqInt, seqOs}).
+-record('ChoSeqExp', {seqInt, seqOs}).
seq(_Rules) ->
-
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {choSeq,#'ChoSeq'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{choSeq,{'ChoSeq',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes1)),
-
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {choSeqI,#'ChoSeq'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{choSeqI,{'ChoSeq',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes2)),
-
-
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {choSeqE,#'ChoSeq'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{choSeqE,{'ChoSeq',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes3)),
-
-
- ?line {ok,Bytes4} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeq-I',#'ChoSeqImp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeq-I',{'ChoSeqImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes4)),
-
-
- ?line {ok,Bytes5} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeqI-I',#'ChoSeqImp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeqI-I',{'ChoSeqImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes5)),
-
-
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeqE-I',#'ChoSeqImp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeqE-I',{'ChoSeqImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes6)),
-
-
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeq-E',#'ChoSeqExp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeq-E',{'ChoSeqExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes7)),
-
-
- ?line {ok,Bytes8} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeqI-E',#'ChoSeqExp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeqI-E',{'ChoSeqExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes8)),
-
-
- ?line {ok,Bytes9} =
- asn1_wrapper:encode('ChoTypeRefSeq','ChoTRseq',
- {'choSeqE-E',#'ChoSeqExp'{seqInt = 88,
- seqOs = "A string"}}),
- ?line {ok,{'choSeqE-E',{'ChoSeqExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSeq','ChoTRseq',lists:flatten(Bytes9)),
-
-
+ roundtrip('ChoTRseq', {choSeq,#'ChoSeq'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {choSeqI,#'ChoSeq'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {choSeqE,#'ChoSeq'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeq-I',#'ChoSeqImp'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeqI-I',#'ChoSeqImp'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeqE-I',#'ChoSeqImp'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeq-E',#'ChoSeqExp'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeqI-E',#'ChoSeqExp'{seqInt=88,
+ seqOs = <<"A string">>}}),
+ roundtrip('ChoTRseq', {'choSeqE-E',#'ChoSeqExp'{seqInt=88,
+ seqOs = <<"A string">>}}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ChoTypeRefSeq', Type, Value).
diff --git a/lib/asn1/test/testChoTypeRefSet.erl b/lib/asn1/test/testChoTypeRefSet.erl
index 8a3e8bdbb0..bd9068b53e 100644
--- a/lib/asn1/test/testChoTypeRefSet.erl
+++ b/lib/asn1/test/testChoTypeRefSet.erl
@@ -23,83 +23,30 @@
-include_lib("test_server/include/test_server.hrl").
--record('ChoSet',{setInt, setOs}).
--record('ChoSetImp',{setInt, setOs}).
--record('ChoSetExp',{setInt, setOs}).
+-record('ChoSet', {setInt, setOs}).
+-record('ChoSetImp', {setInt, setOs}).
+-record('ChoSetExp', {setInt, setOs}).
set(_Rules) ->
-
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {choSet,#'ChoSet'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{choSet,{'ChoSet',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes1)),
-
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {choSetI,#'ChoSet'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{choSetI,{'ChoSet',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes2)),
-
-
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {choSetE,#'ChoSet'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{choSetE,{'ChoSet',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes3)),
-
-
- ?line {ok,Bytes4} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSet-I',#'ChoSetImp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSet-I',{'ChoSetImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes4)),
-
-
- ?line {ok,Bytes5} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSetI-I',#'ChoSetImp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSetI-I',{'ChoSetImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes5)),
-
-
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSetE-I',#'ChoSetImp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSetE-I',{'ChoSetImp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes6)),
-
-
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSet-E',#'ChoSetExp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSet-E',{'ChoSetExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes7)),
-
-
- ?line {ok,Bytes8} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSetI-E',#'ChoSetExp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSetI-E',{'ChoSetExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes8)),
-
-
- ?line {ok,Bytes9} =
- asn1_wrapper:encode('ChoTypeRefSet','ChoTRset',
- {'choSetE-E',#'ChoSetExp'{setInt = 88,
- setOs = "A string"}}),
- ?line {ok,{'choSetE-E',{'ChoSetExp',88,"A string"}}} =
- asn1_wrapper:decode('ChoTypeRefSet','ChoTRset',lists:flatten(Bytes9)),
-
-
-
+ roundtrip('ChoTRset', {choSet,#'ChoSet'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {choSetI,#'ChoSet'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {choSetE,#'ChoSet'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSet-I',#'ChoSetImp'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSetI-I',#'ChoSetImp'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSetE-I',#'ChoSetImp'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSet-E',#'ChoSetExp'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSetI-E',#'ChoSetExp'{setInt=88,
+ setOs = <<"A string">>}}),
+ roundtrip('ChoTRset', {'choSetE-E',#'ChoSetExp'{setInt=88,
+ setOs = <<"A string">>}}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ChoTypeRefSet', Type, Value).
diff --git a/lib/asn1/test/testChoiceIndefinite.erl b/lib/asn1/test/testChoiceIndefinite.erl
index b5832c985a..87910cf6ec 100644
--- a/lib/asn1/test/testChoiceIndefinite.erl
+++ b/lib/asn1/test/testChoiceIndefinite.erl
@@ -32,6 +32,6 @@ main(ber) ->
Bi = [48,128,160,128,128,1,11,0,0,129,1,12,0,0],
%% the value which is encoded
V = {'Seq',{ca,11},12},
- ?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',B),
- ?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',Bi),
+ {ok,V} = 'ChoiceIndef':decode('Seq', B),
+ {ok,V} = 'ChoiceIndef':decode('Seq', Bi),
ok.
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index 03a09492af..3ccf883bd6 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -70,6 +70,8 @@ int_constraints(Rules) ->
%%==========================================================
LastNumWithoutLengthEncoding = 65536,
roundtrip('Range256to65536', LastNumWithoutLengthEncoding),
+ roundtrip('Range256to65536Ext', LastNumWithoutLengthEncoding),
+ roundtrip('Range256to65536Ext', 42),
FirstNumWithLengthEncoding = 65537,
roundtrip('LargeConstraints', 'RangeMax', FirstNumWithLengthEncoding),
@@ -95,6 +97,8 @@ int_constraints(Rules) ->
%% Random number within longlong range
LongLong = 12672809400538808320,
roundtrip('LongLong', LongLong),
+ roundtrip('LongLongExt', LongLong),
+ roundtrip('LongLongExt', -10000),
%%==========================================================
%% Constraint Combinations (Duboisson p. 285)
@@ -122,6 +126,42 @@ int_constraints(Rules) ->
range_error(Rules, 'X1', 21),
%%==========================================================
+ %% Union of single values
+ %% Sv1 ::= INTEGER (2|3|17)
+ %% Sv2 ::= INTEGER (2|3|17, ...)
+ %% Sv3 ::= INTEGER {a(2),b(3),z(17)} (2|3|17, ...)
+ %%==========================================================
+
+ range_error(Rules, 'Sv1', 1),
+ range_error(Rules, 'Sv1', 18),
+ roundtrip('Sv1', 2),
+ roundtrip('Sv1', 3),
+ roundtrip('Sv1', 7),
+
+ %% Encoded as root
+ v_roundtrip(Rules, 'Sv2', 2),
+ v_roundtrip(Rules, 'Sv2', 3),
+ v_roundtrip(Rules, 'Sv2', 17),
+
+ %% Encoded as extension
+ v_roundtrip(Rules, 'Sv2', 1),
+ v_roundtrip(Rules, 'Sv2', 4),
+ v_roundtrip(Rules, 'Sv2', 18),
+
+ %% Encoded as root
+ v_roundtrip(Rules, 'Sv3', a),
+ v_roundtrip(Rules, 'Sv3', b),
+ v_roundtrip(Rules, 'Sv3', z),
+ v_roundtrip(Rules, 'Sv3', 2, a),
+ v_roundtrip(Rules, 'Sv3', 3, b),
+ v_roundtrip(Rules, 'Sv3', 17, z),
+
+ %% Encoded as extension
+ v_roundtrip(Rules, 'Sv3', 1),
+ v_roundtrip(Rules, 'Sv3', 4),
+ v_roundtrip(Rules, 'Sv3', 18),
+
+ %%==========================================================
%% SemiConstrained
%%==========================================================
@@ -168,20 +208,29 @@ int_constraints(Rules) ->
%% More SIZE Constraints
%%==========================================================
- roundtrip('FixedSize', "0123456789"),
- roundtrip('FixedSize2', "0123456789"),
- roundtrip('FixedSize2', "0123456789abcdefghij"),
+ 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)) ||
+ [roundtrip('VariableSize', list_to_binary(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"),
+ %%==========================================================
+ %% Unions of INTEGER constraints
+ %%==========================================================
+ seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 7580),
+ seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 9600),
+ seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 18050),
+ seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 19000),
+ seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 26900),
+
ok.
%% PER: Ensure that if the lower bound is Lb, Lb+16#80 is encoded
@@ -197,33 +246,54 @@ 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".
+v(uper, 'NegSemiConstrainedExt', 0) -> "00C000";
+v(ber, 'Sv2', 1) -> "020101";
+v(per, 'Sv2', 1) -> "800101";
+v(uper, 'Sv2', 1) -> "808080";
+v(ber, 'Sv2', 2) -> "020102";
+v(per, 'Sv2', 2) -> "00";
+v(uper, 'Sv2', 2) -> "00";
+v(ber, 'Sv2', 3) -> "020103";
+v(per, 'Sv2', 3) -> "08";
+v(uper, 'Sv2', 3) -> "08";
+v(ber, 'Sv2', 4) -> "020104";
+v(per, 'Sv2', 4) -> "800104";
+v(uper, 'Sv2', 4) -> "808200";
+v(ber, 'Sv2', 17) -> "020111";
+v(per, 'Sv2', 17) -> "78";
+v(uper, 'Sv2', 17) -> "78";
+v(ber, 'Sv2', 18) -> "020112";
+v(per, 'Sv2', 18) -> "800112";
+v(uper, 'Sv2', 18) -> "808900";
+v(Rule, 'Sv3', a) -> v(Rule, 'Sv2', 2);
+v(Rule, 'Sv3', b) -> v(Rule, 'Sv2', 3);
+v(Rule, 'Sv3', z) -> v(Rule, 'Sv2', 17);
+v(Rule, 'Sv3', Val) when is_integer(Val) -> v(Rule, 'Sv2', Val).
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).
+ roundtrip('AnotherThing', fred),
+ {error,_Reason} = 'Constraints':encode('AnotherThing', fred3).
v_roundtrip(Erule, Type, Value) ->
Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
Encoded = roundtrip('Constraints', Type, Value).
+v_roundtrip(Erule, Type, Value, Expected) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
+ Encoded = asn1_test_lib:roundtrip_enc('Constraints', Type, Value, Expected).
+
roundtrip(Type, Value) ->
roundtrip('Constraints', Type, Value).
roundtrip(Module, Type, Value) ->
- {ok,Encoded} = Module:encode(Type, Value),
- {ok,Value} = Module:decode(Type, Encoded),
- Encoded.
+ asn1_test_lib:roundtrip_enc(Module, Type, Value).
roundtrip_enc(Type, Value, Enc) ->
- Module = 'Constraints',
- {ok,Encoded} = Module:encode(Type, Value),
- {ok,Value} = Module:decode(Type, Encoded),
+ Encoded = asn1_test_lib:roundtrip_enc('Constraints', Type, Value),
case Enc of
none -> ok;
Encoded -> ok
@@ -240,3 +310,12 @@ range_error(Per, Type, Value) when Per =:= per; Per =:= uper ->
%% on encode.
{error,_} = 'Constraints':encode(Type, Value),
ok.
+
+seq_roundtrip(Rules, Seq1, Seq2, Val) ->
+ Enc = roundtrip(Seq1, {Seq1,Val}),
+ case Rules of
+ ber ->
+ roundtrip(Seq2, {Seq2,Val});
+ _ ->
+ roundtrip_enc(Seq2, {Seq2,Val}, Enc)
+ end.
diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl
index 40dbe25015..61d1fbdd69 100644
--- a/lib/asn1/test/testContextSwitchingTypes.erl
+++ b/lib/asn1/test/testContextSwitchingTypes.erl
@@ -24,31 +24,31 @@
-include_lib("test_server/include/test_server.hrl").
test(Config) ->
- ?line ValT = 'ContextSwitchingTypes':'val1-T'(),
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('ContextSwitchingTypes','T',ValT),
- ?line {ok,Result1} =
- asn1_wrapper:decode('ContextSwitchingTypes','T',Bytes1),
- ?line ok = check_EXTERNAL(Result1),
- ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T',
- [{i, ?config(case_dir, Config)}]),
- ?line {ok,Bytes1_2} =
- asn1_wrapper:encode('ContextSwitchingTypes','T',ValT2),
- ?line {ok,Result1_2} =
- asn1_wrapper:decode('ContextSwitchingTypes','T',Bytes1_2),
- ?line ok = check_EXTERNAL(Result1_2),
+ ValT_1 = 'ContextSwitchingTypes':'val1-T'(),
+ check_EXTERNAL(enc_dec('T', ValT_1)),
- ?line ValEP = 'ContextSwitchingTypes':'val1-EP'(),
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('ContextSwitchingTypes','EP',ValEP),
- ?line {ok,_Result2} =
- asn1_wrapper:decode('ContextSwitchingTypes','EP',Bytes2),
+ ValT_2 = 'ContextSwitchingTypes':'val2-T'(),
+ check_EXTERNAL(enc_dec('T', ValT_2)),
- ?line ValCS = 'ContextSwitchingTypes':'val1-CS'(),
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('ContextSwitchingTypes','CS',ValCS),
- ?line {ok,_Result3} =
- asn1_wrapper:decode('ContextSwitchingTypes','CS',Bytes3).
+ ValT_3 = 'ContextSwitchingTypes':'val3-T'(),
+ check_EXTERNAL(enc_dec('T', ValT_3)),
+
+ ValT_4 = 'ContextSwitchingTypes':'val4-T'(),
+ check_EXTERNAL(enc_dec('T', ValT_4)),
+
+ {ok,ValT2} = asn1ct:value('ContextSwitchingTypes', 'T',
+ [{i,?config(case_dir, Config)}]),
+ io:format("ValT2 ~p~n",[ValT2]),
+ check_EXTERNAL(enc_dec('T', ValT2)),
+
+ ValEP = 'ContextSwitchingTypes':'val1-EP'(),
+ ValEPDec = enc_dec('EP', ValEP),
+ io:format("~p\n~p\n", [ValEP,ValEPDec]),
+
+ ValCS = 'ContextSwitchingTypes':'val1-CS'(),
+ ValCSDec = enc_dec('EP', ValCS),
+ io:format("~p\n~p\n", [ValCS,ValCSDec]),
+ ok.
check_EXTERNAL({'EXTERNAL',Identif,DVD,DV})->
@@ -85,3 +85,9 @@ check_object_identifier(Tuple) when is_tuple(Tuple) ->
not is_integer(E)] of
[] -> ok
end.
+
+enc_dec(T, V0) ->
+ M = 'ContextSwitchingTypes',
+ {ok,Enc} = M:encode(T, V0),
+ {ok,V} = M:decode(T, Enc),
+ V.
diff --git a/lib/asn1/test/testDER.erl b/lib/asn1/test/testDER.erl
index 395116bd34..3f74a16797 100644
--- a/lib/asn1/test/testDER.erl
+++ b/lib/asn1/test/testDER.erl
@@ -25,26 +25,24 @@
test() ->
Val = {'Set',12,{version,214},true},
- ?line {ok,Bin}=asn1_wrapper:encode('DERSpec','Set',Val),
- ?line ok = match_value('Set',Bin),
- ?line {ok,{'Set',12,{version,214},true}} =
- asn1_wrapper:decode('DERSpec','Set',Bin),
+ roundtrip_enc('Set', Val, <<49,12,1,1,255,2,2,0,214,161,3,2,1,12>>),
- ValSof = [{version,12},{message,"PrintableString"},{message,"Print"},{version,11}],
- ?line {ok,BSof} = asn1_wrapper:encode('DERSpec','SetOf',ValSof),
- ?line ok = match_value('SetOf',BSof),
- ?line {ok,[{version,11},{version,12},{message,"Print"},{message,"PrintableString"}]} = asn1_wrapper:decode('DERSpec','SetOf',BSof),
+ ValSof = [{version,12},{message,"PrintableString"},
+ {message,"Print"},{version,11}],
+ ValSofSorted = [{version,11},{version,12},
+ {message,"Print"},{message,"PrintableString"}],
+ roundtrip_enc('SetOf', ValSof, ValSofSorted,
+ <<49,30,2,1,11,2,1,12,19,5,80,114,105,110,116,19,15,80,
+ 114,105,110,116,97,98,108,101,83,116,114,105,110,103>>),
ValSO = [{'Seq2',1,true},{'Seq2',120000,false},{'Seq2',3,true}],
- ?line {ok,SOB} = asn1_wrapper:encode('DERSpec','SO',ValSO),
- ?line {ok,ValSO} = asn1_wrapper:decode('DERSpec','SO',SOB).
+ roundtrip('SO', ValSO).
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('DERSpec', T, V).
-match_value('Set',<<49,12,1,1,255,2,2,0,214,161,3,2,1,12>>) ->
- ok;
-match_value('Set',[49,12,1,1,255,2,2,0,214,161,3,2,1,12]) ->
- ok;
-match_value('SetOf',<<49,30,2,1,11,2,1,12,19,5,80,114,105,110,116,19,15,80,114,105,110,116,97,98,108,101,83,116,114,105,110,103>>) -> ok;
-match_value('SetOf',[49,30,2,1,11,2,1,12,19,5,80,114,105,110,116,19,15,80,114,105,110,116,97,98,108,101,83,116,114,105,110,103]) -> ok;
-match_value(_,B) ->
- {error,B}.
+roundtrip_enc(T, V, Enc) ->
+ Enc = asn1_test_lib:roundtrip_enc('DERSpec', T, V).
+
+roundtrip_enc(T, V, Expected, Enc) ->
+ Enc = asn1_test_lib:roundtrip_enc('DERSpec', T, V, Expected).
diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl
index f17dedc043..880f15e91a 100644
--- a/lib/asn1/test/testDeepTConstr.erl
+++ b/lib/asn1/test/testDeepTConstr.erl
@@ -40,8 +40,7 @@ main(_Erule) ->
{any,"DK"},
{final,"NO"}]}},
- {ok,Bytes1} = 'TConstrChoice':encode('FilterItem', Val1),
- {error,Reason} = asn1_wrapper:decode('TConstrChoice','FilterItem',Bytes1),
+ Reason = must_fail('TConstrChoice', 'FilterItem', Val1),
io:format("Reason: ~p~n~n",[Reason]),
{ok,Bytes2} = 'TConstrChoice':encode('FilterItem', Val2),
{ok,Res} = 'TConstrChoice':decode('FilterItem', Bytes2),
@@ -70,10 +69,33 @@ main(_Erule) ->
{'Deeper_a',12,
{'Deeper_a_s',{2,4},42}},
{'Deeper_b',13,{'Type-object1',14,true}}}),
+
+ roundtrip('TConstr', 'Seq3',
+ {'Seq3',
+ {'Seq3_a',42,'TConstr':'id-object1'()},
+ {'Seq3_b',
+ {'Type-object1',-777,true},
+ 12345,
+ {'Seq3_b_bc',12345789,{'Type-object1',-999,true}}}}),
+ roundtrip('TConstr', 'Seq3-Opt',
+ {'Seq3-Opt',
+ {'Seq3-Opt_a',42,'TConstr':'id-object1'()},
+ {'Seq3-Opt_b',
+ {'Type-object1',-777,true},
+ 12345,
+ {'Seq3-Opt_b_bc',12345789,{'Type-object1',-999,true}}}}),
ok.
roundtrip(M, T, V) ->
- {ok,E} = M:encode(T, V),
- {ok,V} = M:decode(T, E),
- ok.
+ asn1_test_lib:roundtrip(M, T, V).
+
+%% Either encoding or decoding must fail.
+must_fail(M, T, V) ->
+ case M:encode(T, V) of
+ {ok,E} ->
+ {error,Reason} = M:decode(T, E),
+ Reason;
+ {error,Reason} ->
+ Reason
+ end.
diff --git a/lib/asn1/test/testDef.erl b/lib/asn1/test/testDef.erl
index 48f0015008..b8df3c4f8b 100644
--- a/lib/asn1/test/testDef.erl
+++ b/lib/asn1/test/testDef.erl
@@ -37,81 +37,45 @@
bool33 = asn1_DEFAULT}).
main(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
- bool1 = true,
- bool2 = true,
- bool3 = true}),
- ?line {ok,{'Def1',true,true,true,true}} =
- asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true}),
- ?line {ok,{'Def1',true,false,false,false}} =
- asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
- bool2 = false}),
- ?line {ok,{'Def1',true,false,false,false}} =
- asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = false,
- bool3 = false}),
- ?line {ok,{'Def1',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes14)),
-
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('Def','Def2',#'Def2'{bool10 = false,
- bool11 = false,
- bool12 = false,
- bool13 = false}),
- ?line {ok,{'Def2',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('Def','Def2',#'Def2'{bool10 = true,
- bool13 = false}),
- ?line {ok,{'Def2',true,false,false,false}} =
- asn1_wrapper:decode('Def','Def2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('Def','Def2',#'Def2'{bool10 = true,
- bool11 = false,
- bool13 = false}),
- ?line {ok,{'Def2',true,false,false,false}} =
- asn1_wrapper:decode('Def','Def2',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} = asn1_wrapper:encode('Def','Def2',#'Def2'{bool10 = false,
- bool12 = false,
- bool13 = false}),
- ?line {ok,{'Def2',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def2',lists:flatten(Bytes24)),
-
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('Def','Def3',#'Def3'{bool30 = false,
- bool31 = false,
- bool32 = false,
- bool33 = false}),
- ?line {ok,{'Def3',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('Def','Def3',#'Def3'{}),
- ?line {ok,{'Def3',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('Def','Def3',#'Def3'{bool30 = true}),
- ?line {ok,{'Def3',true,false,false,false}} =
- asn1_wrapper:decode('Def','Def3',lists:flatten(Bytes33)),
-
- ?line {ok,Bytes34} = asn1_wrapper:encode('Def','Def3',#'Def3'{bool32 = false}),
- ?line {ok,{'Def3',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def3',lists:flatten(Bytes34)),
-
- ?line {ok,Bytes35} = asn1_wrapper:encode('Def','Def3',#'Def3'{bool33 = false}),
- ?line {ok,{'Def3',false,false,false,false}} =
- asn1_wrapper:decode('Def','Def3',lists:flatten(Bytes35)),
-
-
-
+ roundtrip('Def1', #'Def1'{bool0=true,bool1=true,bool2=true,bool3=true}),
+ roundtrip('Def1',
+ #'Def1'{bool0=true},
+ #'Def1'{bool0=true,bool1=false,bool2=false,bool3=false}),
+ roundtrip('Def1',
+ #'Def1'{bool0=true,bool2=false},
+ #'Def1'{bool0=true,bool1=false,bool2=false,bool3=false}),
+ roundtrip('Def1',
+ #'Def1'{bool0=false,bool3=false},
+ #'Def1'{bool0=false,bool1=false,bool2=false,bool3=false}),
+
+ roundtrip('Def2', #'Def2'{bool10=false,bool11=false,bool12=false,bool13=false}),
+ roundtrip('Def2',
+ #'Def2'{bool10=true,bool13=false},
+ #'Def2'{bool10=true,bool11=false,bool12=false,bool13=false}),
+ roundtrip('Def2',
+ #'Def2'{bool10=true,bool11=false,bool13=false},
+ #'Def2'{bool10=true,bool11=false,bool12=false,bool13=false}),
+ roundtrip('Def2',
+ #'Def2'{bool10=false,bool12=false,bool13=false},
+ #'Def2'{bool10=false,bool11=false,bool12=false,bool13=false}),
+
+ roundtrip('Def3', #'Def3'{bool30=false,bool31=false,bool32=false,bool33=false}),
+ roundtrip('Def3',
+ #'Def3'{},
+ #'Def3'{bool30=false,bool31=false,bool32=false,bool33=false}),
+ roundtrip('Def3',
+ #'Def3'{bool30=true},
+ #'Def3'{bool30=true,bool31=false,bool32=false,bool33=false}),
+ roundtrip('Def3',
+ #'Def3'{bool32=false},
+ #'Def3'{bool30=false,bool31=false,bool32=false,bool33=false}),
+ roundtrip('Def3',
+ #'Def3'{bool33=false},
+ #'Def3'{bool30=false,bool31=false,bool32=false,bool33=false}),
ok.
+
+roundtrip(Type, Value) ->
+ roundtrip(Type, Value, Value).
+
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('Def', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testDoubleEllipses.erl b/lib/asn1/test/testDoubleEllipses.erl
index 1032156b91..bd6831bf1e 100644
--- a/lib/asn1/test/testDoubleEllipses.erl
+++ b/lib/asn1/test/testDoubleEllipses.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2014. 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,77 +24,49 @@
-include_lib("test_server/include/test_server.hrl").
-record('Seq',{a, c}).
+-record('SeqV1',{a, b}).
-record('SeqV2',{a, b ,c}).
-record('SeqAlt',{a,d,b,e,c,f,g}).
-record('SeqAltV2',{a,d,b,e,h,i,c,f,g}).
-record('Set',{a, c}).
+-record('SetV1',{a, b}).
-record('SetV2',{a, b ,c}).
-record('SetAlt',{a,d,b,e,c,f,g}).
-record('SetAltV2',{a,d,b,e,h,i,c,f,g}).
main(_Rules) ->
- %% SEQUENCE
- ?line {ok,Bytes} =
- asn1_wrapper:encode('DoubleEllipses','Seq',#'Seq'{a = 10,c = true}),
- ?line {ok,#'SeqV2'{a=10,b = asn1_NOVALUE, c = true}} =
- asn1_wrapper:decode('DoubleEllipses','SeqV2',Bytes),
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('DoubleEllipses','SeqV2',
- #'SeqV2'{a=10,b = false, c = true}),
- ?line {ok,#'Seq'{a = 10, c = true}} =
- asn1_wrapper:decode('DoubleEllipses','Seq',Bytes2),
+ roundtrip('Seq', #'Seq'{a=10,c=true}),
+ roundtrip('SeqV1', #'SeqV1'{a=10,b=false}),
+ roundtrip('SeqV2', #'SeqV2'{a=10,b=false,c=true}),
+ roundtrip('SeqAlt',
+ #'SeqAlt'{a=10,d=12,b = <<2#1010:4>>,
+ e=true,c=false,f=14,g=16}),
+ roundtrip('SeqAltV2',
+ #'SeqAltV2'{a=10,d=12,
+ b = <<2#1010:4>>,
+ e=true,h="PS",i=13,c=false,f=14,g=16}),
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('DoubleEllipses','SeqAlt',
- #'SeqAlt'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
- c = false, f = 14, g = 16}),
- ?line {ok,#'SeqAltV2'{a = 10, d = 12,
- b = <<2#1010:4>>, e = true,
- h = asn1_NOVALUE, i = asn1_NOVALUE,
- c = false, f = 14, g = 16}} =
- asn1_wrapper:decode('DoubleEllipses','SeqAltV2',Bytes3),
- ?line {ok,Bytes4} =
- asn1_wrapper:encode('DoubleEllipses','SeqAltV2',
- #'SeqAltV2'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
- h = "PS", i = 13,
- c = false, f = 14, g = 16}),
- ?line {ok,#'SeqAlt'{a = 10, d = 12,
- b = <<2#1010:4>>, e = true,
- c = false, f = 14, g = 16}} =
- asn1_wrapper:decode('DoubleEllipses','SeqAlt',Bytes4),
-
- %% SET
- ?line {ok,Bytes5} =
- asn1_wrapper:encode('DoubleEllipses','Set',#'Set'{a = 10,c = true}),
- ?line {ok,#'SetV2'{a=10,b = asn1_NOVALUE, c = true}} =
- asn1_wrapper:decode('DoubleEllipses','SetV2',Bytes5),
- ?line {ok,Bytes6} =
- asn1_wrapper:encode('DoubleEllipses','SetV2',
- #'SetV2'{a=10,b = false, c = true}),
- ?line {ok,#'Set'{a = 10, c = true}} =
- asn1_wrapper:decode('DoubleEllipses','Set',Bytes6),
-
- ?line {ok,Bytes7} =
- asn1_wrapper:encode('DoubleEllipses','SetAlt',
- #'SetAlt'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
- c = false, f = 14, g = 16}),
- ?line {ok,#'SetAltV2'{a = 10, d = 12,
- b = <<2#1010:4>>, e = true,
- h = asn1_NOVALUE, i = asn1_NOVALUE,
- c = false, f = 14, g = 16}} =
- asn1_wrapper:decode('DoubleEllipses','SetAltV2',Bytes7),
- ?line {ok,Bytes8} =
- asn1_wrapper:encode('DoubleEllipses','SetAltV2',
- #'SetAltV2'{a = 10, d = 12,
- b = [1,0,1,0], e = true,
- h = "PS", i = 13,
- c = false, f = 14, g = 16}),
- ?line {ok,#'SetAlt'{a = 10, d = 12,
- b = <<2#1010:4>>, e = true,
- c = false, f = 14, g = 16}} =
- asn1_wrapper:decode('DoubleEllipses','SetAlt',Bytes8),
+ roundtrip('Set', #'Set'{a=10,c=true}),
+ roundtrip('SetV1', #'SetV1'{a=10,b=false}),
+ roundtrip('SetV2', #'SetV2'{a=10,b=false,c=true}),
+ roundtrip('SetAlt',
+ #'SetAlt'{a=10,d=12,
+ b = <<2#1010:4>>,
+ e=true,c=false,f=14,g=16}),
+ roundtrip('SetAltV2',
+ #'SetAltV2'{a=10,d=12,
+ b = <<2#1010:4>>,
+ e=true,h="PS",i=13,c=false,f=14,g=16}),
+
+ roundtrip('SeqDoubleEmpty1',
+ {'SeqDoubleEmpty1'}),
+ roundtrip('SeqDoubleEmpty2',
+ {'SeqDoubleEmpty2',true,42}),
+ roundtrip('SeqDoubleEmpty2',
+ {'SeqDoubleEmpty2',true,asn1_NOVALUE}),
+
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('DoubleEllipses', T, V).
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index cbc13ee6da..878518be11 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -33,7 +33,7 @@ main(Rule) when Rule =:= per; Rule =:= uper ->
%% ENUMERATED with extensionmark (value is an extensionvalue)
Or = roundtrip('Ext1', orange),
%% unknown extensionvalue
- {ok,{asn1_enum,0}} = asn1_wrapper:decode('EnumExt','Ext',Or),
+ {ok,{asn1_enum,0}} = 'EnumExt':decode('Ext', Or),
%% ENUMERATED no extensionmark
B64 = <<64>>,
@@ -45,12 +45,12 @@ main(ber) ->
roundtrip('Ext', red),
%% value is an extensionvalue
- {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext1',orange),
- {ok,{asn1_enum,7}} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1_1)),
+ {ok,Bytes1_1} = 'EnumExt':encode('Ext1', orange),
+ {ok,{asn1_enum,7}} = 'EnumExt':decode('Ext', Bytes1_1),
%% ENUMERATED no extensionmark
roundtrip('Noext', red),
- ?line {error,{asn1,_}} = (catch asn1_wrapper:encode('EnumExt','Noext',orange)),
+ {error,{asn1,_}} = (catch 'EnumExt':encode('Noext', orange)),
%% ENUMERATED with atom 'com'
roundtrip('Globalstate', preop),
@@ -59,6 +59,10 @@ main(ber) ->
common(ber).
common(Erule) ->
+ roundtrip('SubExt1', blue),
+ roundtrip('SubExt1', orange),
+ roundtrip('SubExt1', black),
+
roundtrip('Seq', {'Seq',blue,42}),
roundtrip('Seq', {'Seq',red,42}),
roundtrip('Seq', {'Seq',green,42}),
@@ -77,9 +81,7 @@ common(Erule) ->
ok.
roundtrip(Type, Value) ->
- {ok,Encoded} = 'EnumExt':encode(Type, Value),
- {ok,Value} = 'EnumExt':decode(Type, Encoded),
- Encoded.
+ asn1_test_lib:roundtrip_enc('EnumExt', Type, Value).
v_roundtrip(Erule, Type, Value) ->
Encoded = roundtrip(Type, Value),
diff --git a/lib/asn1/test/testFragmented.erl b/lib/asn1/test/testFragmented.erl
new file mode 100644
index 0000000000..35b21f90a9
--- /dev/null
+++ b/lib/asn1/test/testFragmented.erl
@@ -0,0 +1,40 @@
+%%
+%% %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 = 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) ->
+ asn1_test_lib:roundtrip('Fragmented', T, V).
diff --git a/lib/asn1/test/testINSTANCE_OF.erl b/lib/asn1/test/testINSTANCE_OF.erl
index ce411beb92..c855ca3c06 100644
--- a/lib/asn1/test/testINSTANCE_OF.erl
+++ b/lib/asn1/test/testINSTANCE_OF.erl
@@ -18,46 +18,23 @@
%%
%%
-module(testINSTANCE_OF).
-
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-main(Erule) ->
+main(_Erule) ->
+ Int = roundtrip('Int', 3),
- ?line {ok,Integer} = asn1_wrapper:encode('INSTANCEOF','Int',3),
- Int = list_to_binary(Integer),
ValotherName = {otherName,{'INSTANCE OF',{2,4},Int}},
+ _ = roundtrip('GeneralName', ValotherName),
+
VallastName1 = {lastName,{'GeneralName_lastName',{2,4},12}},
+ _ = roundtrip('GeneralName', VallastName1),
+
VallastName2 = {lastName,{'GeneralName_lastName',{2,3,4},
{'Seq',12,true}}},
- ?line {ok,BytesoN}=
- asn1_wrapper:encode('INSTANCEOF','GeneralName',ValotherName),
- ?line {ok,Res1={otherName,_}} =
- asn1_wrapper:decode('INSTANCEOF','GeneralName',BytesoN),
- ?line ok = test_encdec(Erule,Int,Res1),
-
- ?line {ok,ByteslN1}=
- asn1_wrapper:encode('INSTANCEOF','GeneralName',VallastName1),
- ?line {ok,Res2={lastName,_}} =
- asn1_wrapper:decode('INSTANCEOF','GeneralName',ByteslN1),
- ?line test_encdec(Erule,Res2),
-
- ?line {ok,ByteslN2}=
- asn1_wrapper:encode('INSTANCEOF','GeneralName',VallastName2),
- ?line {ok,Res3={lastName,_}} =
- asn1_wrapper:decode('INSTANCEOF','GeneralName',ByteslN2),
- ?line test_encdec(Erule,Res3).
-
-test_encdec(_Erule,Int,{otherName,{'INSTANCE OF',{2,4},Int}}) ->
- ok;
-test_encdec(Erule,Int,R={otherName,{'INSTANCE OF',{2,4},_Int2}}) ->
- {error,{Erule,Int,R}}.
+ _ = roundtrip('GeneralName', VallastName2),
+ ok.
-test_encdec(_Erule,{lastName,{'GeneralName_lastName',{2,4},12}}) ->
- ok;
-test_encdec(_Erule,{lastName,{'GeneralName_lastName',{2,3,4},
- {'Seq',12,true}}}) ->
- ok;
-test_encdec(Erule,Res) ->
- {error,{Erule,Res}}.
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip_enc('INSTANCEOF', T, V).
diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl
index c7b19a0cbb..37c134b1b9 100644
--- a/lib/asn1/test/testInfObj.erl
+++ b/lib/asn1/test/testInfObj.erl
@@ -49,7 +49,7 @@ main(_Erule) ->
roundtrip('RANAPextract1', 'InitiatingMessage2', Val3),
roundtrip('InfObj', 'MyPdu', {'MyPdu',42,12,false,"string"}),
- roundtrip('InfObj', 'MyPdu', {'MyPdu',{'Seq',1023,"hello"},
+ roundtrip('InfObj', 'MyPdu', {'MyPdu',{'Seq',1023,<<"hello">>},
42,true,"longer string"}),
roundtrip('InfObj', 'MyPdu', {'MyPdu',"75712346",43,true,"string"}),
@@ -59,13 +59,105 @@ main(_Erule) ->
{'ConstructedPdu',2,{'CONSTRUCTED-DEFAULT_Type',999,false}}),
roundtrip('InfObj', 'ConstructedPdu',
{'ConstructedPdu',3,true}),
+ {'ConstructedPdu',4,{_,42,<<13:7>>}} =
+ enc_dec('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',4,{'',42,<<13:7>>}}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',5,{i,-250138}}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',5,{b,<<13456:15>>}}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',6,[]}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',6,[10,7,16,1,5,13,12]}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',7,[]}),
+ roundtrip('InfObj', 'ConstructedPdu',
+ {'ConstructedPdu',7,[64,1,19,17,35]}),
+
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',1,{'CONSTRUCTED-DEFAULT_Type',-2001,true}}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',2,{'CONSTRUCTED-DEFAULT_Type',999,false}}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',3,true}),
+ {'ConstructedSet',4,{_,42,<<13:7>>}} =
+ enc_dec('InfObj', 'ConstructedSet',
+ {'ConstructedSet',4,{'',42,<<13:7>>}}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',5,{i,-250138}}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',5,{b,<<13456:15>>}}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',6,[]}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',6,[10,7,16,1,5,13,12]}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',7,[]}),
+ roundtrip('InfObj', 'ConstructedSet',
+ {'ConstructedSet',7,[64,1,19,17,35]}),
roundtrip('InfObj', 'Seq2',
{'Seq2',42,[true,false,false,true],
- [false,true,false]}).
+ [false,true,false]}),
+
+ roundtrip('InfObj', 'OptionalInSeq', {'OptionalInSeq',3,true}),
+ roundtrip('InfObj', 'OptionalInSeq', {'OptionalInSeq',3,asn1_NOVALUE}),
+
+ roundtrip('InfObj', 'DefaultInSeq', {'DefaultInSeq',3,false}),
+ roundtrip('InfObj', 'DefaultInSeq', {'DefaultInSeq',3,true}),
+ {'DefaultInSeq',3,true} =
+ enc_dec('InfObj', 'DefaultInSeq', {'DefaultInSeq',3,asn1_DEFAULT}),
+ roundtrip('InfObj', 'Multiple-Optionals',
+ {'Multiple-Optionals',1,42,true,<<"abc">>}),
+ roundtrip('InfObj', 'Multiple-Optionals',
+ {'Multiple-Optionals',1,asn1_NOVALUE,true,<<"abc">>}),
+ roundtrip('InfObj', 'Multiple-Optionals',
+ {'Multiple-Optionals',1,42,asn1_NOVALUE,<<"abc">>}),
+ roundtrip('InfObj', 'Multiple-Optionals',
+ {'Multiple-Optionals',1,42,true,asn1_NOVALUE}),
+ roundtrip('InfObj', 'Multiple-Optionals',
+ {'Multiple-Optionals',1,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}),
+
+ test_objset('OstSeq12', [1,2]),
+ test_objset('OstSeq123', [1,2,3]),
+ test_objset('OstSeq1234', [1,2,3,4]),
+ test_objset('OstSeq45', [4,5]),
+ test_objset('OstSeq12345', [1,2,3,4,5]),
+
+ test_objset('ExOstSeq12', [1,2]),
+ test_objset('ExOstSeq123', [1,2,3]),
+ %%test_objset('ExOstSeq1234', [1,2,3,4]),
+ test_objset('ExOstSeq45', [4,5]),
+ test_objset('ExOstSeq12345', [1,2,3,4,5]),
+
+ ok.
+
+test_objset(Type, Keys) ->
+ _ = [test_object(Type, Key) || Key <- Keys],
+ _ = [(catch test_object(Type, Key)) ||
+ Key <- lists:seq(1, 5) -- Keys],
+ ok.
+
+test_object(T, 1) ->
+ roundtrip('InfObj', T, {T,1,<<42:7>>});
+test_object(T, 2) ->
+ roundtrip('InfObj', T, {T,2,<<"abc">>});
+test_object(T, 3) ->
+ roundtrip('InfObj', T, {T,3,donald}),
+ roundtrip('InfObj', T, {T,3,scrooge});
+test_object(T, 4) ->
+ roundtrip('InfObj', T, {T,4,true}),
+ roundtrip('InfObj', T, {T,4,false});
+test_object(T, 5) ->
+ roundtrip('InfObj', T, {T,5,0}),
+ roundtrip('InfObj', T, {T,5,15}).
roundtrip(M, T, V) ->
- {ok,Enc} = M:encode(T, V),
+ asn1_test_lib:roundtrip(M, T, V).
+
+enc_dec(M, T, V0) ->
+ {ok,Enc} = M:encode(T, V0),
{ok,V} = M:decode(T, Enc),
- ok.
+ V.
diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl
index 98408502c6..c36c05a2ea 100644
--- a/lib/asn1/test/testInfObjectClass.erl
+++ b/lib/asn1/test/testInfObjectClass.erl
@@ -29,24 +29,22 @@ main(Rule) ->
%% this test is added for OTP-4591, to test that elements in decoded
%% value has terms in right order.
Val = {'Seq',12,13,2},
- ?line {ok,Bytes}= asn1_wrapper:encode('InfClass','Seq',Val),
- ?line {ok,Val} = asn1_wrapper:decode('InfClass','Seq',Bytes),
+ roundtrip('Seq', Val),
%% OTP-5783
- ?line {error,{asn1,{'Type not compatible with table constraint',
- {component,'ArgumentType'},
- {value,_},_}}} = asn1_wrapper:encode('InfClass','Seq',
- {'Seq',12,13,1}),
+ {error,{asn1,{'Type not compatible with table constraint',
+ {component,'ArgumentType'},
+ {value,_},_}}} = 'InfClass':encode('Seq', {'Seq',12,13,1}),
Bytes2 = case Rule of
ber ->
<<48,9,2,1,12,2,1,11,2,1,1>>;
_ ->
- <<1,12,1,11,1,1>>
+ <<1,12,1,11,1,1>>
end,
- ?line {error,{asn1,{'Type not compatible with table constraint',
- {{component,_},
- {value,_B},_}}}} =
- asn1_wrapper:decode('InfClass','Seq',Bytes2).
+ {error,{asn1,{'Type not compatible with table constraint',
+ {{component,_},
+ {value,_B},_}}}} = 'InfClass':decode('Seq', Bytes2),
+ ok.
-
-
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('InfClass', T, V).
diff --git a/lib/asn1/test/testMegaco.erl b/lib/asn1/test/testMegaco.erl
index f4edcebb7e..644042b484 100644
--- a/lib/asn1/test/testMegaco.erl
+++ b/lib/asn1/test/testMegaco.erl
@@ -20,165 +20,28 @@
-module(testMegaco).
--export([compile/3,main/2,msg11/0]).
+-export([compile/3,main/2]).
-include_lib("test_server/include/test_server.hrl").
--define(MID, {ip4Address, #'IP4Address'{address = [124, 124, 124, 222],
- portNumber = 55555}}).
--define(A4444, ["11111111"]).
--record('MegacoMessage',
- {
- authHeader = asn1_NOVALUE,
- mess
- }).
-
--record('Message',
- {
- version,
- mId,
- messageBody
- }). % with extension mark
-
--record('IP4Address',
- {
- address,
- portNumber = asn1_NOVALUE
- }).
-
--record('TransactionRequest',
- {
- transactionId,
- actions = []
- }). % with extension mark
-
--record('ActionRequest',
- {
- contextId,
- contextRequest = asn1_NOVALUE,
- contextAttrAuditReq = asn1_NOVALUE,
- commandRequests = []
- }).
-
--record('CommandRequest',
- {
- command,
- optional = asn1_NOVALUE,
- wildcardReturn = asn1_NOVALUE
- }). % with extension mark
-
--record('NotifyRequest',
- {
- terminationID,
- observedEventsDescriptor,
- errorDescriptor = asn1_NOVALUE
- }). % with extension mark
-
--record('ObservedEventsDescriptor',
- {
- requestId,
- observedEventLst = []
- }).
-
--record('ObservedEvent',
- {
- eventName,
- streamID = asn1_NOVALUE,
- eventParList = [],
- timeNotation = asn1_NOVALUE
- }). % with extension mark
-
--record('EventParameter',
- {
- eventParameterName,
- value
- }).
-
--record('TimeNotation',
- {
- date,
- time
- }).
-
--record(megaco_term_id, {contains_wildcards = ["f"], id}).
-
-
-compile(_Config,ber,[optimize]) ->
- {ok,no_module,no_module};
-compile(_Config,per,[optimize]) ->
- {ok,no_module,no_module};
-compile(Config,Erule,Options) ->
+compile(Config, Erule, Options) ->
asn1_test_lib:compile("MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]),
asn1_test_lib:compile("OLD-MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]),
{ok,'OLD-MEDIA-GATEWAY-CONTROL','MEDIA-GATEWAY-CONTROL'}.
-
main(no_module,_) -> ok;
main('OLD-MEDIA-GATEWAY-CONTROL',Config) ->
-% Msg = msg11(),
CaseDir = ?config(case_dir, Config),
{ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage',
[{i, CaseDir}]),
- ?line {ok,Bytes} = asn1_wrapper:encode('OLD-MEDIA-GATEWAY-CONTROL',
- 'MegacoMessage',Msg),
- ?line {ok,Msg} = asn1_wrapper:decode('OLD-MEDIA-GATEWAY-CONTROL',
- 'MegacoMessage',
- Bytes),
+ asn1_test_lib:roundtrip('OLD-MEDIA-GATEWAY-CONTROL', 'MegacoMessage', Msg),
ok;
-main(Mod='MEDIA-GATEWAY-CONTROL',Config) ->
- ?line DataDir = ?config(data_dir,Config),
- io:format("DataDir:~p~n",[DataDir]),
- ?line {ok,FilenameList} = file:list_dir(filename:join([DataDir,
- megacomessages])),
- %% remove any junk files that may be in the megacomessage directory
- Pred = fun(X) ->
- case lists:reverse(X) of
- [$l,$a,$v,$.|_R] ->true;
- _ -> false
- end
- end,
- MegacoMsgFilenameList = lists:filter(Pred,FilenameList),
-
- Fun = fun(F) ->
- M = read_msg(filename:join([DataDir,megacomessages,F])),
- {ok,B} = asn1_wrapper:encode(Mod,element(1,M),M),
- {ok,M} = asn1_wrapper:decode(Mod,element(1,M),B)
- end,
- ?line lists:foreach(Fun,MegacoMsgFilenameList),
- ok.
-
-read_msg(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- binary_to_term(Bin);
- _ ->
- io:format("couldn't read file ~p~n",[File])
- end.
-
-
-request(Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) ->
- Actions = [#'ActionRequest'{contextId = ContextId,
- commandRequests = CmdReq}],
- Req = {transactions,
- [{transactionRequest,
- #'TransactionRequest'{transactionId = TransId,
- actions = Actions}}]},
- #'MegacoMessage'{mess = #'Message'{version = 1,
- mId = Mid,
- messageBody = Req}}.
-
-msg11() ->
- TimeStamp = #'TimeNotation'{date = "19990729",
- time = "22012001"},
- Parm = #'EventParameter'{eventParameterName = "ds",
- value = "916135551212"},
-
- Event = #'ObservedEvent'{eventName = "ddce",
- timeNotation = TimeStamp,
- eventParList = [Parm]},
- Desc = #'ObservedEventsDescriptor'{requestId = 2223,
- observedEventLst = [Event]},
- NotifyReq = #'NotifyRequest'{terminationID = [#megaco_term_id{id = ?A4444}],
- observedEventsDescriptor = Desc},
- CmdReq = #'CommandRequest'{command = {notifyReq, NotifyReq}},
- request(?MID, 10002, 0, [CmdReq]).
+main('MEDIA-GATEWAY-CONTROL'=Mod, Config) ->
+ DataDir = ?config(data_dir, Config),
+ Files = filelib:wildcard(filename:join([DataDir,megacomessages,"*.val"])),
+ lists:foreach(fun(File) ->
+ {ok,Bin} = file:read_file(File),
+ V = binary_to_term(Bin),
+ T = element(1, V),
+ asn1_test_lib:roundtrip(Mod, T, V)
+ end, Files).
diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl
index 8ef7ba3458..b21897cfc2 100644
--- a/lib/asn1/test/testMergeCompile.erl
+++ b/lib/asn1/test/testMergeCompile.erl
@@ -30,42 +30,36 @@
main(Erule) ->
%% test of module MS.set.asn that tests OTP-4492: different tagdefault in
%% modules and types with same name in modules
- ?line MSVal = {'Type4M2',8,true,three,"OCTET STRING"},
- ?line {ok,MSBytes} = asn1_wrapper:encode('MS','Type4M2',MSVal),
- ?line {ok,MSVal} = asn1_wrapper:decode('MS','Type4M2',MSBytes),
-
+ MSVal = {'Type4M2',8,true,three,<<"OCTET STRING">>},
+ asn1_test_lib:roundtrip('MS', 'Type4M2', MSVal),
%% test of RANAP.set.asn1
- ?line _PIEVal = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,{'CauseRadioNetwork','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 =
+ EncVal0 =
case Erule of
per ->
<<1,100>>;
uper ->
<<1,100>>;
ber ->
- [2,1,1]
+ <<2,1,1>>
end,
- ?line PEVal2 = [{dummy,1,ignore,EncVal},{dummy,2,reject,EncVal}],
- ?line Val2 =
+ EncVal = {asn1_OPENTYPE,EncVal0},
+ PEVal2 = [{'ProtocolExtensionField',1,ignore,EncVal},
+ {'ProtocolExtensionField',2,reject,EncVal}],
+ Val2 =
#'InitiatingMessage'{procedureCode=1,
criticality=ignore,
value=#'Iu-ReleaseCommand'{protocolIEs=PIEVal2,
protocolExtensions=asn1_NOVALUE}},
- ?line {ok,Bytes2} = asn1_wrapper:encode('RANAPSET','InitiatingMessage',Val2),
- ?line {ok,_Ret2} = asn1_wrapper:decode('RANAPSET','InitiatingMessage',Bytes2),
-
- ?line Val3 =
+ asn1_test_lib:roundtrip('RANAPSET', 'InitiatingMessage', Val2),
+ Val3 =
#'InitiatingMessage'{procedureCode=1,
criticality=ignore,
value=#'Iu-ReleaseCommand'{protocolIEs=PIEVal2,
protocolExtensions=PEVal2}},
- ?line {ok,Bytes3} = asn1_wrapper:encode('RANAPSET','InitiatingMessage',Val3),
- ?line {ok,_Ret3} = asn1_wrapper:decode('RANAPSET','InitiatingMessage',Bytes3).
+ asn1_test_lib:roundtrip('RANAPSET', 'InitiatingMessage', Val3).
mvrasn(Erule) ->
@@ -83,78 +77,106 @@ mvrasn(Erule) ->
?line ok = test(mvrasn6,'InsertSubscriberDataArg').
test(isd)->
- EncPdu = [48,128,129,7,145,148,113,50,1,0,241,131,1,0,176,128,5,0,161,128,48,22,2,1,1,144,2,241,33,145,4,0,1,2,3,146,3,36,131,16,148,2,1,42,48,35,2,1,2,144,2,241,33,145,4,255,255,255,255,146,3,37,147,18,147,0,148,13,7,67,79,77,80,65,78,89,4,67,79,77,53,48,28,2,1,3,144,2,241,33,146,3,26,98,31,148,14,9,67,79,77,80,65,78,89,49,50,3,67,79,77,0,0,0,0,152,1,2,0,0],
-
- ?line {ok,_} = asn1_wrapper:decode('Mvrasn4',
- 'InsertSubscriberDataArg',
- EncPdu),
+ EncPdu = <<48,128,129,7,145,148,113,50,1,0,241,131,1,0,176,128,5,0,
+ 161,128,48,22,2,1,1,144,2,241,33,145,4,0,1,2,3,146,3,36,
+ 131,16,148,2,1,42,48,35,2,1,2,144,2,241,33,145,4,255,255,
+ 255,255,146,3,37,147,18,147,0,148,13,7,67,79,77,80,65,78,
+ 89,4,67,79,77,53,48,28,2,1,3,144,2,241,33,146,3,26,98,31,
+ 148,14,9,67,79,77,80,65,78,89,49,50,3,67,79,77,0,0,0,0,
+ 152,1,2,0,0>>,
+ {ok,_} = 'Mvrasn4':decode('InsertSubscriberDataArg', EncPdu),
ok;
%
% Problems with indefinite length encoding !!!
%
test(isd2)->
- EncPdu = [48, 128, 128, 8, 98, 2, 50, 1, 0, 0, 0, 241, 176, 128, 161, 128, 48, 128, 2, 1, 1, 144, 2, 241, 33, 145, 4, 255, 23, 12, 1, 146, 3, 9, 17, 1, 147, 0, 148, 13, 7, 67, 79, 77, 80, 65, 78, 89, 4, 67, 79, 77, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn4',
- 'InsertSubscriberDataArg',
- EncPdu),
-
+ EncPdu = <<48,128,128,8,98,2,50,1,0,0,0,241,176,128,161,128,48,128,2,1,1,144,
+ 2,241,33,145,4,255,23,12,1,146,3,9,17,1,147,0,148,13,7,67,79,77,80,
+ 65,78,89,4,67,79,77,53,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ {ok,_DecPdu} = 'Mvrasn4':decode('InsertSubscriberDataArg', EncPdu),
ok;
%
% Is doing fine, although there is indefinite encoding used... !!!
%
test(dsd)->
- EncPdu = [48, 128, 128, 8, 98, 2, 50, 1, 0, 0, 0, 241, 170, 2, 5, 0, 0, 0, 0, 0],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn4',
- 'DeleteSubscriberDataArg',
- EncPdu),
-
+ EncPdu = <<48,128,128,8,98,2,50,1,0,0,0,241,170,2,5,0,0,0,0,0>>,
+ {ok,_DecPdu} = 'Mvrasn4':decode('DeleteSubscriberDataArg', EncPdu),
ok;
%
% Is doing fine !!!
%
test(ul_res)->
- EncPdu = [48, 9, 4, 7, 145, 148, 113, 66, 16, 17, 241],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn4',
- 'UpdateGprsLocationRes',
- EncPdu),
-
+ EncPdu = <<48,9,4,7,145,148,113,66,16,17,241>>,
+ {ok,_DecPdu} = 'Mvrasn4':decode('UpdateGprsLocationRes', EncPdu),
ok;
test(seqofseq) ->
- {ok,_V} = asn1_wrapper:decode('Mvrasn4',
- 'SentParameters',
- [48,129,190,161,128,4,16,176,197,182,68,41,243,188,205,123,13,9,145,206,200,144,102,4,4,176,197,182,68,4,8,41,243,188,205,123,13,9,145,0,0,161,128,4,16,39,0,3,117,35,189,130,21,42,104,49,194,212,24,151,234,4,4,39,0,3,117,4,8,35,189,130,21,42,104,49,194,0,0,161,128,4,16,62,207,166,59,71,29,37,97,120,25,132,80,144,251,161,123,4,4,62,207,166,59,4,8,71,29,37,97,120,25,132,80,0,0,161,128,4,16,95,183,173,151,17,76,148,146,248,102,127,215,102,224,39,60,4,4,95,183,173,151,4,8,17,76,148,146,248,102,127,215,0,0,161,128,4,16,41,198,247,157,117,190,203,170,91,146,88,91,223,220,188,16,4,4,41,198,247,157,4,8,117,190,203,170,91,146,88,91,0,0]),
+ EncPdu = <<48,129,190,161,128,4,16,176,197,182,68,41,243,188,205,123,13,
+ 9,145,206,200,144,102,4,4,176,197,182,68,4,8,41,243,188,205,
+ 123,13,9,145,0,0,161,128,4,16,39,0,3,117,35,189,130,21,42,104,
+ 49,194,212,24,151,234,4,4,39,0,3,117,4,8,35,189,130,21,42,104,
+ 49,194,0,0,161,128,4,16,62,207,166,59,71,29,37,97,120,25,132,
+ 80,144,251,161,123,4,4,62,207,166,59,4,8,71,29,37,97,120,25,
+ 132,80,0,0,161,128,4,16,95,183,173,151,17,76,148,146,248,102,
+ 127,215,102,224,39,60,4,4,95,183,173,151,4,8,17,76,148,146,248,
+ 102,127,215,0,0,161,128,4,16,41,198,247,157,117,190,203,170,91,
+ 146,88,91,223,220,188,16,4,4,41,198,247,157,4,8,117,190,203,170,91,146,88,91,0,0>>,
+ {ok,_V} = 'Mvrasn4':decode('SentParameters', EncPdu),
ok;
test('InsertSubscriberDataArg') ->
- {ok,_V} =
- asn1_wrapper:decode('Mvrasn4','InsertSubscriberDataArg',
- [16#30,16#80,16#81,16#07,16#91,16#94,
- 16#71,16#92,16#00,16#35,16#80,16#83,
- 16#01,16#00,16#A6,16#06,16#04,16#01,
- 16#21,16#04,16#01,16#22,16#B0,16#80,
- 16#05,16#00,16#A1,16#80,16#30,16#1A,
- 16#02,16#01,16#01,16#90,16#02,16#F1,
- 16#21,16#92,16#03,16#0D,16#92,16#1F,
- 16#94,16#0C,16#03,16#53,16#49,16#4D,
- 16#03,16#47,16#53,16#4E,16#03,16#4C,
- 16#4B,16#50,16#00,16#00,16#00,16#00,
- 16#98,16#01,16#00,16#00,16#00]),
+ EncPdu = <<16#30,16#80,16#81,16#07,16#91,16#94,
+ 16#71,16#92,16#00,16#35,16#80,16#83,
+ 16#01,16#00,16#A6,16#06,16#04,16#01,
+ 16#21,16#04,16#01,16#22,16#B0,16#80,
+ 16#05,16#00,16#A1,16#80,16#30,16#1A,
+ 16#02,16#01,16#01,16#90,16#02,16#F1,
+ 16#21,16#92,16#03,16#0D,16#92,16#1F,
+ 16#94,16#0C,16#03,16#53,16#49,16#4D,
+ 16#03,16#47,16#53,16#4E,16#03,16#4C,
+ 16#4B,16#50,16#00,16#00,16#00,16#00,
+ 16#98,16#01,16#00,16#00,16#00>>,
+ {ok,_V} = 'Mvrasn4':decode('InsertSubscriberDataArg', EncPdu),
ok.
test(mvrasn6,'InsertSubscriberDataArg') ->
- Val = {'InsertSubscriberDataArg',"IMSI","Address","C",serviceGranted,["abc","cde"],["tele","serv","ice"],asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,{'NAEA-PreferredCI',"NCC",asn1_NOVALUE},{'GPRSSubscriptionData','NULL',[{'PDP-Context',49,"PT","PDP-Address","QoS",'NULL',"APN",asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],asn1_NOVALUE},'NULL',onlyMSC,{'LSAInformation','NULL',accessOutsideLSAsAllowed,[{'LSAData',"LSA","L",'NULL',asn1_NOVALUE},{'LSAData',"LSA","L",'NULL',asn1_NOVALUE}],asn1_NOVALUE},'NULL',{'LCSInformation',["Addr","ess","string"],[{'LCS-PrivacyClass',"S","ExtSS",notifyLocationAllowed,[{'ExternalClient',{'LCSClientExternalID',"Addr",asn1_NOVALUE},asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],[broadcastService,anonymousLocation,targetMSsubscribedService],asn1_NOVALUE}],asn1_NOVALUE},100,"age",{'MC-SS-Info',"S","ExtSS",5,4,asn1_NOVALUE},"C",{'SGSN-CAMEL-SubscriptionInfo',{'GPRS-CSI',[{'GPRS-CamelTDPData',attach,13,"Addr",continueTransaction,asn1_NOVALUE}],11,asn1_NOVALUE,'NULL','NULL'},{'SMS-CSI',[{'SMS-CAMEL-TDP-DataList','sms-CollectedInfo',13,"Addr",continueTransaction,asn1_NOVALUE}],11,asn1_NOVALUE,'NULL','NULL'},asn1_NOVALUE},"ON"},
-
- {ok,Bytes}=
- asn1_wrapper:encode('Mvrasn6','InsertSubscriberDataArg',Val),
-
- {ok,_Res} =
- asn1_wrapper:decode('Mvrasn6','InsertSubscriberDataArg',Bytes),
-
+ Val = {'InsertSubscriberDataArg',<<"IMSI">>,<<"Address">>,<<"C">>,
+ serviceGranted,[<<"abc">>,<<"cde">>],
+ [<<"tele">>,<<"serv">>,<<"ice">>],
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
+ {'NAEA-PreferredCI',<<"NCC">>,asn1_NOVALUE},
+ {'GPRSSubscriptionData','NULL',
+ [{'PDP-Context',49,<<"PT">>,<<"PDP-Address">>,<<"QoS">>,
+ 'NULL',<<"APN">>,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],
+ asn1_NOVALUE},'NULL',onlyMSC,
+ {'LSAInformation','NULL',accessOutsideLSAsAllowed,
+ [{'LSAData',<<"LSA">>,<<"L">>,'NULL',asn1_NOVALUE},
+ {'LSAData',<<"LSA">>,<<"L">>,'NULL',asn1_NOVALUE}],
+ asn1_NOVALUE},'NULL',
+ {'LCSInformation',[<<"Addr">>,<<"ess">>,<<"string">>],
+ [{'LCS-PrivacyClass',<<"S">>,<<"ExtSS">>,notifyLocationAllowed,
+ [{'ExternalClient',
+ {'LCSClientExternalID',<<"Addr">>,asn1_NOVALUE},
+ asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}],
+ [broadcastService,anonymousLocation,targetMSsubscribedService],
+ asn1_NOVALUE}],asn1_NOVALUE},
+ 100,<<"age">>,
+ {'MC-SS-Info',<<"S">>,<<"ExtSS">>,5,4,asn1_NOVALUE},
+ <<"C">>,
+ {'SGSN-CAMEL-SubscriptionInfo',
+ {'GPRS-CSI',
+ [{'GPRS-CamelTDPData',attach,13,<<"Addr">>,
+ continueTransaction,asn1_NOVALUE}],
+ 11,asn1_NOVALUE,'NULL','NULL'},
+ {'SMS-CSI',
+ [{'SMS-CAMEL-TDP-Data','sms-CollectedInfo',
+ 13,<<"Addr">>,continueTransaction,asn1_NOVALUE}],
+ 11,asn1_NOVALUE,'NULL','NULL'},
+ asn1_NOVALUE},
+ <<"ON">>},
+ asn1_test_lib:roundtrip('Mvrasn6', 'InsertSubscriberDataArg', Val),
ok.
diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl
index 0f4459f5b2..e37e22163a 100644
--- a/lib/asn1/test/testNBAPsystem.erl
+++ b/lib/asn1/test/testNBAPsystem.erl
@@ -19,7 +19,7 @@
%%
-module(testNBAPsystem).
--export([compile/2,test/2,cell_setup_req_msg/0]).
+-export([compile/2,test/2]).
-include_lib("test_server/include/test_server.hrl").
@@ -79,13 +79,14 @@ powerRaiseLimit, dLPowerAveragingWindowSize, 'iE-Extensions' = asn1_NOVALUE}).
compile(Config, Options) ->
- [asn1_test_lib:compile(filename:join([nbapsystem, M]), Config, Options)
- || M <- ["NBAP-CommonDataTypes.asn",
- "NBAP-IEs.asn",
- "NBAP-PDU-Contents.asn",
- "NBAP-PDU-Discriptions.asn",
- "NBAP-Constants.asn",
- "NBAP-Containers.asn"]],
+ Fs = [filename:join("nbapsystem", M) ||
+ M <- ["NBAP-CommonDataTypes.asn",
+ "NBAP-IEs.asn",
+ "NBAP-PDU-Contents.asn",
+ "NBAP-PDU-Discriptions.asn",
+ "NBAP-Constants.asn",
+ "NBAP-Containers.asn"]],
+ asn1_test_lib:compile_all(Fs, Config, Options),
ok.
@@ -96,23 +97,16 @@ test(_Erule,Config) ->
ticket_5812(Config) ->
?line Msg = v_5812(),
- ?line {ok,B2} = asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg),
+ {ok,B2} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg),
V = <<0,28,74,0,3,48,0,0,1,0,123,64,41,0,0,0,126,64,35,95,208,2,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,145,0,1,205,0,0,0,0,2,98,64,1,128>>,
?line ok = compare(V,B2),
- ?line {ok,Msg2} = asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',B2),
+ {ok,Msg2} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B2),
?line ok = check_record_names(Msg2,Config).
enc_audit_req_msg() ->
Msg = {initiatingMessage, audit_req_msg()},
- ?line {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg),
- ?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
+ {ok,B} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg),
+ {ok,_Msg} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B),
?line {initiatingMessage,
#'InitiatingMessage'{value=#'AuditRequest'{protocolIEs=[{_,114,ignore,_}],
protocolExtensions = asn1_NOVALUE}}} = _Msg,
@@ -121,12 +115,8 @@ enc_audit_req_msg() ->
cell_setup_req_msg_test() ->
Msg = {initiatingMessage, cell_setup_req_msg()},
- ?line {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg),
- ?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
+ {ok,B} = 'NBAP-PDU-Discriptions':encode('NBAP-PDU', Msg),
+ {ok,_Msg} = 'NBAP-PDU-Discriptions':decode('NBAP-PDU', B),
io:format("Msg: ~P~n~n_Msg: ~P~n",[Msg,15,_Msg,15]),
ok.
diff --git a/lib/asn1/test/testOpenTypeImplicitTag.erl b/lib/asn1/test/testOpenTypeImplicitTag.erl
index a37d8004ef..0fbf70d037 100644
--- a/lib/asn1/test/testOpenTypeImplicitTag.erl
+++ b/lib/asn1/test/testOpenTypeImplicitTag.erl
@@ -24,18 +24,9 @@
-include_lib("test_server/include/test_server.hrl").
main(_Rules) ->
-
- ?line {ok,Bytes1} =
- asn1_wrapper:encode('OpenTypeImplicitTag','Seq',
- {'Seq',[1,1,255],[1,1,255],12,[1,1,255]}),
- ?line {ok,{'Seq',_,_,12,_}} =
- asn1_wrapper:decode('OpenTypeImplicitTag','Seq',
- lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} =
- asn1_wrapper:encode('OpenTypeImplicitTag','Seq',
- {'Seq',[1,1,255],asn1_NOVALUE,12,[1,1,255]}),
- ?line {ok,{'Seq',_,asn1_NOVALUE,12,_}} =
- asn1_wrapper:decode('OpenTypeImplicitTag','Seq',
- lists:flatten(Bytes2)),
+ roundtrip('Seq', {'Seq',<<1,1,255>>,<<1,1,255>>,12,<<1,1,255>>}),
+ roundtrip('Seq', {'Seq',<<1,1,255>>,asn1_NOVALUE,12,<<1,1,255>>}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('OpenTypeImplicitTag', T, V).
diff --git a/lib/asn1/test/testOpt.erl b/lib/asn1/test/testOpt.erl
index a1ad8099b5..a6dcccad15 100644
--- a/lib/asn1/test/testOpt.erl
+++ b/lib/asn1/test/testOpt.erl
@@ -18,8 +18,6 @@
%%
%%
-module(testOpt).
-
--export([compile/2]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -39,92 +37,29 @@
bool32 = asn1_NOVALUE,
bool33 = asn1_NOVALUE}).
-
-compile(Config,Rules) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Opt",[Rules,{outdir,OutDir}]).
-
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('Opt','Opt1',#'Opt1'{bool0 = true,
- bool1 = true,
- bool2 = true,
- bool3 = true}),
- ?line {ok,{'Opt1',true,true,true,true}} =
- asn1_wrapper:decode('Opt','Opt1',lists:flatten(Bytes11)),
+ roundtrip('Opt1', #'Opt1'{bool0=true,bool1=true,bool2=true,bool3=true}),
+ roundtrip('Opt1', #'Opt1'{bool0=true,bool1=asn1_NOVALUE,bool2=asn1_NOVALUE,
+ bool3=asn1_NOVALUE}),
+ roundtrip('Opt1', #'Opt1'{bool0=true,bool1=asn1_NOVALUE,bool2=false,bool3=asn1_NOVALUE}),
+ roundtrip('Opt1', #'Opt1'{bool0=false,bool1=asn1_NOVALUE,bool2=asn1_NOVALUE,bool3=false}),
- ?line {ok,Bytes12} = asn1_wrapper:encode('Opt','Opt1',#'Opt1'{bool0 = true}),
- ?line {ok,{'Opt1',true,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}} =
- asn1_wrapper:decode('Opt','Opt1',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('Opt','Opt1',#'Opt1'{bool0 = true,
- bool2 = false}),
- ?line {ok,{'Opt1',true,asn1_NOVALUE,false,asn1_NOVALUE}} =
- asn1_wrapper:decode('Opt','Opt1',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('Opt','Opt1',#'Opt1'{bool0 = false,
- bool3 = false}),
- ?line {ok,{'Opt1',false,asn1_NOVALUE,asn1_NOVALUE,false}} =
- asn1_wrapper:decode('Opt','Opt1',lists:flatten(Bytes14)),
-
-
-
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('Opt','Opt2',#'Opt2'{bool10 = false,
- bool11 = false,
- bool12 = false,
- bool13 = false}),
- ?line {ok,{'Opt2',false,false,false,false}} =
- asn1_wrapper:decode('Opt','Opt2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('Opt','Opt2',#'Opt2'{bool10 = true,
- bool13 = false}),
- ?line {ok,{'Opt2',true,asn1_NOVALUE,asn1_NOVALUE,false}} =
- asn1_wrapper:decode('Opt','Opt2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} = asn1_wrapper:encode('Opt','Opt2',#'Opt2'{bool10 = true,
- bool11 = false,
- bool13 = false}),
- ?line {ok,{'Opt2',true,false,asn1_NOVALUE,false}} =
- asn1_wrapper:decode('Opt','Opt2',lists:flatten(Bytes23)),
-
- ?line {ok,Bytes24} = asn1_wrapper:encode('Opt','Opt2',#'Opt2'{bool10 = false,
- bool12 = false,
- bool13 = false}),
- ?line {ok,{'Opt2',false,asn1_NOVALUE,false,false}} =
- asn1_wrapper:decode('Opt','Opt2',lists:flatten(Bytes24)),
-
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('Opt','Opt3',#'Opt3'{bool30 = false,
- bool31 = false,
- bool32 = false,
- bool33 = false}),
- ?line {ok,{'Opt3',false,false,false,false}} =
- asn1_wrapper:decode('Opt','Opt3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('Opt','Opt3',#'Opt3'{}),
- ?line {ok,{'Opt3',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}} =
- asn1_wrapper:decode('Opt','Opt3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('Opt','Opt3',#'Opt3'{bool30 = true}),
- ?line {ok,{'Opt3',true,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}} =
- asn1_wrapper:decode('Opt','Opt3',lists:flatten(Bytes33)),
-
- ?line {ok,Bytes34} = asn1_wrapper:encode('Opt','Opt3',#'Opt3'{bool32 = false}),
- ?line {ok,{'Opt3',asn1_NOVALUE,asn1_NOVALUE,false,asn1_NOVALUE}} =
- asn1_wrapper:decode('Opt','Opt3',lists:flatten(Bytes34)),
-
- ?line {ok,Bytes35} = asn1_wrapper:encode('Opt','Opt3',#'Opt3'{bool33 = false}),
- ?line {ok,{'Opt3',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,false}} =
- asn1_wrapper:decode('Opt','Opt3',lists:flatten(Bytes35)),
-
-
-
+ roundtrip('Opt2', #'Opt2'{bool10=false,bool11=false,bool12=false,bool13=false}),
+ roundtrip('Opt2', #'Opt2'{bool10=true,bool11=asn1_NOVALUE,bool12=asn1_NOVALUE,
+ bool13=false}),
+ roundtrip('Opt2', #'Opt2'{bool10=true,bool11=false,bool12=asn1_NOVALUE,bool13=false}),
+ roundtrip('Opt2', #'Opt2'{bool10=false,bool11=asn1_NOVALUE,bool12=false,bool13=false}),
+
+ roundtrip('Opt3', #'Opt3'{bool30=false,bool31=false,bool32=false,bool33=false}),
+ roundtrip('Opt3', #'Opt3'{bool30=asn1_NOVALUE,bool31=asn1_NOVALUE,bool32=asn1_NOVALUE,
+ bool33=asn1_NOVALUE}),
+ roundtrip('Opt3', #'Opt3'{bool30=true,bool31=asn1_NOVALUE,bool32=asn1_NOVALUE,
+ bool33=asn1_NOVALUE}),
+ roundtrip('Opt3', #'Opt3'{bool30=asn1_NOVALUE,bool31=asn1_NOVALUE,bool32=false,
+ bool33=asn1_NOVALUE}),
+ roundtrip('Opt3', #'Opt3'{bool30=asn1_NOVALUE,bool31=asn1_NOVALUE,bool32=asn1_NOVALUE,
+ bool33=false}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('Opt', Type, Value).
diff --git a/lib/asn1/test/testParamBasic.erl b/lib/asn1/test/testParamBasic.erl
index a10468d592..39f7947e8d 100644
--- a/lib/asn1/test/testParamBasic.erl
+++ b/lib/asn1/test/testParamBasic.erl
@@ -29,53 +29,30 @@
-record('T22',{number, string}).
main(Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('ParamBasic','T11',
- #'T11'{number = 11,
- string = "hello"}),
- ?line {ok,{'T11',11,"hello"}} =
- asn1_wrapper:decode('ParamBasic','T11',Bytes11),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('ParamBasic','T12',
- #'T12'{number = 11,
- string = <<2#10101:5>>}),
- {ok,{'T12',11,<<2#10101:5>>}} =
- asn1_wrapper:decode('ParamBasic','T12',Bytes12),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('ParamBasic','T21',
- #'T21'{number = 11,
- string = "hello"}),
- ?line {ok,{'T21',11,"hello"}} =
- asn1_wrapper:decode('ParamBasic','T21',Bytes13),
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('ParamBasic','T22',
- #'T22'{number = 11,
- string = <<2#10101:5>>}),
- {ok,{'T22',11,<<2#10101:5>>}} =
- asn1_wrapper:decode('ParamBasic','T22',Bytes14),
-
+ roundtrip('T11', #'T11'{number=11,string="hello"}),
+ roundtrip('T12', #'T12'{number=11,string = <<21:5>>}),
+ roundtrip('T21', #'T21'{number=11,string="hello"}),
+ roundtrip('T22', #'T22'{number=11,string = <<21:5>>}),
case Rules of
der ->
-
- ?line {ok,[48,3,128,1,11]} =
- asn1_wrapper:encode('ParamBasic','T11',
- #'T11'{number = 11,
- string = "hej"}),
- ?line {ok,{'T11',11,"hej"}} =
- asn1_wrapper:decode('ParamBasic','T11',[48,3,128,1,11]),
-
- ?line {ok,[48,3,128,1,11]} =
- asn1_wrapper:encode('ParamBasic','T12',
- #'T12'{number = 11,
- string = [1,0,1,0]}),
-
- ?line {ok,{'T12',11,[1,0,1,0]}} =
- asn1_wrapper:decode('ParamBasic','T12',[48,3,128,1,11]);
+ <<48,3,128,1,11>> =
+ roundtrip_enc('T11', #'T11'{number=11,string="hej"}),
+ <<48,3,128,1,11>> =
+ roundtrip_enc('T12',
+ #'T12'{number=11,string=[1,0,1,0]},
+ #'T12'{number=11,string = <<10:4>>});
_ -> ok
end,
-
+ roundtrip('AnAlgorithm', {'AnAlgorithm',1,42}),
+ roundtrip('AnAlgorithm', {'AnAlgorithm',2,true}),
+ roundtrip('AnAlgorithm', {'AnAlgorithm',2,false}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ParamBasic', Type, Value).
+
+roundtrip_enc(Type, Value) ->
+ asn1_test_lib:roundtrip_enc('ParamBasic', Type, Value).
+
+roundtrip_enc(Type, Value, Expected) ->
+ asn1_test_lib:roundtrip_enc('ParamBasic', Type, Value, Expected).
diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl
index 1dfa52f401..2fe900792d 100644
--- a/lib/asn1/test/testParameterizedInfObj.erl
+++ b/lib/asn1/test/testParameterizedInfObj.erl
@@ -20,7 +20,7 @@
-module(testParameterizedInfObj).
--export([main/2,ranap/1]).
+-export([main/2,param/1,ranap/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -36,58 +36,64 @@ main(Config, Erule) ->
param2(Config, Erule).
param(Erule) ->
- PERVal = #'AllocationOrRetentionPriority'
- {priorityLevel = true,
- iE_Extensions =
- [#'ProtocolExtensionField'{id=14,
- criticality=reject,
- extensionValue=open_type(Erule,[0])},
- #'ProtocolExtensionField'{id=2,
- criticality=ignore,
- extensionValue=open_type(Erule,[1])}]},
- BERVal = #'AllocationOrRetentionPriority'
- {priorityLevel = true,
- iE_Extensions =
- [#'ProtocolExtensionField'{id=14,
- criticality=reject,
- extensionValue=[2,1,0]},
- #'ProtocolExtensionField'{id=2,
- criticality=ignore,
- extensionValue=[2,1,1]}]},
- ?line {ok,Bytes1} =
- case asn1_wrapper:erule(Erule) of
- per ->
- asn1_wrapper:encode('Param','AllocationOrRetentionPriority',
- PERVal);
- _ ->
- asn1_wrapper:encode('Param','AllocationOrRetentionPriority',
- BERVal)
- end,
-
- ?line {ok,{'AllocationOrRetentionPriority',true,[_R1,_R2]}} =
- asn1_wrapper:decode('Param','AllocationOrRetentionPriority',Bytes1),
+ Exts0 = case Erule of
+ ber ->
+ %% As implemented, the open type must contain
+ %% valid BER-encoded data.
+ [{14,<<2,1,0>>},{2,<<2,1,0>>}];
+ _ ->
+ %% The PER decoder will not look inside the open type.
+ [{14,<<0>>},{2,<<"anything goes">>}]
+ end,
+ case 'Param':legacy_erlang_types() of
+ false ->
+ Exts = [#'ProtocolExtensionField'{id=Id,
+ criticality=reject,
+ extensionValue={asn1_OPENTYPE,
+ Eval}} ||
+ {Id,Eval} <- Exts0],
+ aor_roundtrip(Exts);
+ true ->
+ Exts = [#'ProtocolExtensionField'{id=Id,
+ criticality=reject,
+ extensionValue=Eval} ||
+ {Id,Eval} <- Exts0],
+ aor_roundtrip(Exts)
+ end,
%% test code for OTP-4242, ValueFromObject
- case asn1_wrapper:erule(Erule) of
+ case Erule of
ber ->
- ?line {ok,_Val3} = asn1_wrapper:decode('Param','OS1',[4,2,1,2]),
- ?line {error,_Reason1} =
- asn1_wrapper:decode('Param','OS1',[4,4,1,2,3,4]),
- ?line {error,_Reason2} =
- asn1_wrapper:decode('Param','OS2',[4,4,1,2,3,4]),
- ?line {ok,_Val4} = asn1_wrapper:decode('Param','OS1',[4,2,1,2]);
- per ->
- ?line {ok,Bytes3} =
- asn1_wrapper:encode('Param','OS1',[1,2]),
- ?line {ok,[1,2]} =
- asn1_wrapper:decode('Param','OS1',Bytes3),
- ?line {error,_Reason3} =
- asn1_wrapper:encode('Param','OS1',[1,2,3,4])
+ {ok,_Val3} = 'Param':decode('OS1', [4,2,1,2]),
+ {error,_Reason1} = 'Param':decode('OS1',[4,4,1,2,3,4]),
+ {error,_Reason2} = 'Param':decode('OS2',[4,4,1,2,3,4]),
+ {ok,_Val4} = 'Param':decode('OS1',[4,2,1,2]);
+ _ -> %per/uper
+ case 'Param':legacy_erlang_types() of
+ false ->
+ roundtrip('OS1', <<1,2>>),
+ {error,_Reason3} = 'Param':encode('OS1', <<1,2,3,4>>);
+ true ->
+ ok
+ end
end,
+ roundtrip('Scl', {'Scl',42,{a,9738654}}),
+ roundtrip('Scl', {'Scl',42,{b,false}}),
+ roundtrip('Scl', {'Scl',42,{b,true}}),
+
ok.
+aor_roundtrip(Exts) ->
+ Val = #'AllocationOrRetentionPriority'{priorityLevel = true,
+ iE_Extensions = Exts},
+ roundtrip('AllocationOrRetentionPriority', Val).
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('Param', T, V).
+
+
ranap(_Erule) ->
PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}],
?line Val2 =
@@ -96,24 +102,19 @@ ranap(_Erule) ->
value=#'Iu-ReleaseCommand'{protocolIEs=PIEVal2,
protocolExtensions=asn1_NOVALUE}},
- ?line {ok,Bytes2} = asn1_wrapper:encode('RANAP','InitiatingMessage',Val2),
- ?line {ok,_Ret2} = asn1_wrapper:decode('RANAP','InitiatingMessage',Bytes2),
+ {ok,Bytes2} = 'RANAP':encode('InitiatingMessage', Val2),
+ {ok,_Ret2} = 'RANAP':decode('InitiatingMessage', Bytes2),
ok.
-open_type(uper,Val) when is_list(Val) ->
- list_to_binary(Val);
-open_type(_,Val) ->
- Val.
-
param2(Config, Erule) ->
roundtrip2('HandoverRequired',
{'HandoverRequired',
- [{'ProtocolIE-Field',1,"ABC"},
+ [{'ProtocolIE-Field',1,<<"ABC">>},
{'ProtocolIE-Field',2,577799}]}),
Enc = roundtrip2('HandoverRequired',
{'HandoverRequired',
- [{'ProtocolIE-Field',1,"ABC"},
+ [{'ProtocolIE-Field',1,<<"ABC">>},
{'ProtocolIE-Field',2,-42},
{'ProtocolIE-Field',100,533},
{'ProtocolIE-Field',101,true}]}),
@@ -134,22 +135,22 @@ param2(Config, Erule) ->
[{i,DataDir},{outdir,CaseDir},Erule]),
%% Decompile extended data.
- {ok,{'HandoverRequired',[{'ProtocolIE-Field',1,"ABC"},
+ {ok,{'HandoverRequired',[{'ProtocolIE-Field',1,<<"ABC">>},
{'ProtocolIE-Field',2,-42},
- {'ProtocolIE-Field',100,Open100},
- {'ProtocolIE-Field',101,Open101}]}} =
- asn1_wrapper:decode('Param2', 'HandoverRequired', Enc),
+ {'ProtocolIE-Field',100,
+ {asn1_OPENTYPE,Open100}},
+ {'ProtocolIE-Field',101,
+ {asn1_OPENTYPE,Open101}}]}} =
+ 'Param2':decode('HandoverRequired', Enc),
true = is_binary(Open100),
true = is_binary(Open101),
%% Test single root.
roundtrip2('SingleRoot',
- {'SingleRoot',[{'ProtocolIE-Field',1,"ABC"},
+ {'SingleRoot',[{'ProtocolIE-Field',1,<<"ABC">>},
{'ProtocolIE-Field',2,9999}]}),
ok.
roundtrip2(T, V) ->
- {ok,Enc} = asn1_wrapper:encode('Param2', T, V),
- {ok,V} = asn1_wrapper:decode('Param2', T, Enc),
- Enc.
+ asn1_test_lib:roundtrip_enc('Param2', T, V).
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index a6e68a9fe0..e07379e634 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -36,8 +36,7 @@ bool(Rules) ->
case Rules of
ber ->
[begin
- {error,{asn1,{encode_boolean,517}}} =
- (catch 'Prim':encode(T, 517))
+ {error,{asn1,{encode_boolean,517}}} = enc_error(T, 517)
end || T <- Types],
ok;
_ ->
@@ -90,12 +89,12 @@ enum(Rules) ->
roundtrip('Enum', monday),
roundtrip('Enum', thursday),
- {error,{asn1,{_,4}}} = (catch 'Prim':encode('Enum', 4)),
+ {error,{asn1,{_,4}}} = enc_error('Enum', 4),
case Rules of
Per when Per =:= per; Per =:= uper ->
- {ok,<<0>>} = 'Prim':encode('SingleEnumVal', true),
- {ok,<<0>>} = 'Prim':encode('SingleEnumValExt', true);
+ <<0>> = roundtrip('SingleEnumVal', true),
+ <<0>> = roundtrip('SingleEnumValExt', true);
ber ->
ok
end,
@@ -128,15 +127,36 @@ null(_Rules) ->
%%==========================================================
%% Null ::= NULL
%%==========================================================
-
- {ok,Bytes1} = asn1_wrapper:encode('Prim','Null',monday),
- {ok,'NULL'} = asn1_wrapper:decode('Prim','Null',lists:flatten(Bytes1)),
+ roundtrip('Null', monday, 'NULL'),
ok.
roundtrip(T, V) ->
- {ok,E} = 'Prim':encode(T, V),
- {ok,V} = 'Prim':decode(T, E),
- E.
+ roundtrip(T, V, V).
+
+roundtrip(Type, Value, ExpectedValue) ->
+ case get(no_ok_wrapper) of
+ false ->
+ asn1_test_lib:roundtrip_enc('Prim', Type, Value, ExpectedValue);
+ true ->
+ M = 'Prim',
+ Enc = M:encode(Type, Value),
+ ExpectedValue = M:decode(Type, Enc),
+ Enc
+ end.
+
+enc_error(T, V) ->
+ case get(no_ok_wrapper) of
+ false ->
+ 'Prim':encode(T, V);
+ true ->
+ try 'Prim':encode(T, V) of
+ _ ->
+ ?t:fail()
+ catch
+ _:Reason ->
+ Reason
+ end
+ end.
real(_Rules) ->
%%==========================================================
@@ -144,67 +164,45 @@ real(_Rules) ->
%%==========================================================
%% Base 2
- ?line {ok,Bytes1} = asn1_wrapper:encode('Real','AngleInRadians',{1,2,1}),
- ?line {ok,{1,2,1}} = asn1_wrapper:decode('Real','AngleInRadians',Bytes1),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Real','AngleInRadians',{129,2,1}),
- ?line {ok,{129,2,1}} = asn1_wrapper:decode('Real','AngleInRadians',Bytes2),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Real','AngleInRadians',{128,2,1}),
- ?line {ok,{1,2,8}} = asn1_wrapper:decode('Real','AngleInRadians',Bytes3),
-
- ?line {ok,Bytes4} = asn1_wrapper:encode('Real','AngleInRadians',{128,2,-7}),
- ?line {ok,{1,2,0}} = asn1_wrapper:decode('Real','AngleInRadians',Bytes4),
-
- ?line {ok,Bytes5} = asn1_wrapper:encode('Real','AngleInRadians',{16#f1f1f1,2,128}),
- ?line {ok,{16#f1f1f1,2,128}} = asn1_wrapper:decode('Real','AngleInRadians',Bytes5),
+ real_roundtrip('AngleInRadians', {1,2,1}),
+ real_roundtrip('AngleInRadians', {129,2,1}),
+ real_roundtrip('AngleInRadians', {128,2,1}, {1,2,8}),
+ real_roundtrip('AngleInRadians', {128,2,-7}, {1,2,0}),
+ real_roundtrip('AngleInRadians', {16#f1f1f1,2,128}),
%% Base 10, tuple format
- ?line {ok,Bytes6} = asn1_wrapper:encode('Real','AngleInRadians',{1,10,1}),
- ?line {ok,"1.E1"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes6),
-
- ?line {ok,Bytes7} = asn1_wrapper:encode('Real','AngleInRadians',{100,10,1}),
- ?line {ok,"1.E3"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes7),
-
- ?line {ok,Bytes8} = asn1_wrapper:encode('Real','AngleInRadians',{-100,10,1}),
- ?line {ok,"-1.E3"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes8),
-
- ?line {ok,Bytes9} = asn1_wrapper:encode('Real','AngleInRadians',{00002,10,1}),
- ?line {ok,"2.E1"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes9),
-
- ?line {ok,Bytes10} = asn1_wrapper:encode('Real','AngleInRadians',{123000,10,0}),
- ?line {ok,"123.E3"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes10),
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('Real','AngleInRadians',{123456789,10,123456789}),
- ?line {ok,"123456789.E123456789"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes11),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('Real','AngleInRadians',{-12345,10,-12345}),
- ?line {ok,"-12345.E-12345"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes12),
+ real_roundtrip('AngleInRadians', {1,10,1}, "1.E1"),
+ real_roundtrip('AngleInRadians', {100,10,1}, "1.E3"),
+ real_roundtrip('AngleInRadians', {-100,10,1}, "-1.E3"),
+ real_roundtrip('AngleInRadians', {2,10,1}, "2.E1"),
+ real_roundtrip('AngleInRadians', {123000,10,0}, "123.E3"),
+ real_roundtrip('AngleInRadians', {123456789,10,123456789},
+ "123456789.E123456789" ),
+ real_roundtrip('AngleInRadians', {-12345,10,-12345}, "-12345.E-12345"),
%% Base 10, string format NR3
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('Real','AngleInRadians',"123.123E123"),
- ?line {ok,"123123.E120"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes13),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('Real','AngleInRadians',"0.0E0"),
- ?line {ok,"0.E+0"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes14),
- ?line {ok,Bytes15} = asn1_wrapper:encode('Real','AngleInRadians',"0.0123"),
- ?line {ok,"123.E-4"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes15),
+ real_roundtrip('AngleInRadians', "123.123E123", "123123.E120"),
+ real_roundtrip('AngleInRadians', "0.0E0", "0.E+0"),
+ real_roundtrip('AngleInRadians', "0.0123", "123.E-4"),
+ real_roundtrip('AngleInRadians', "0", "0.E+0"),
+ real_roundtrip('AngleInRadians', "-123.45", "-12345.E-2"),
+ real_roundtrip('AngleInRadians', "123456789E123456789",
+ "123456789.E123456789"),
+ real_roundtrip('AngleInRadians', "01.000E1", "1.E1"),
+ real_roundtrip('AngleInRadians', "120.0001", "1200001.E-4"),
- ?line {ok,Bytes16} = asn1_wrapper:encode('Real','AngleInRadians',"0"),
- ?line {ok,"0.E+0"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes16),
-
- ?line {ok,Bytes17} = asn1_wrapper:encode('Real','AngleInRadians',"-123.45"),
- ?line {ok,"-12345.E-2"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes17),
-
- ?line {ok,Bytes18} =
- asn1_wrapper:encode('Real','AngleInRadians',"123456789E123456789"),
- ?line {ok,"123456789.E123456789"} =
- asn1_wrapper:decode('Real','AngleInRadians',Bytes18),
+ ok.
- ?line {ok,Bytes19} = asn1_wrapper:encode('Real','AngleInRadians',"01.000E1"),
- ?line {ok,"1.E1"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes19),
+real_roundtrip(T, V) ->
+ real_roundtrip(T, V, V).
- ?line {ok,Bytes20} = asn1_wrapper:encode('Real','AngleInRadians',"120.0001"),
- ?line {ok,"1200001.E-4"} = asn1_wrapper:decode('Real','AngleInRadians',Bytes20).
+real_roundtrip(Type, Value, ExpectedValue) ->
+ case get(no_ok_wrapper) of
+ false ->
+ asn1_test_lib:roundtrip('Real', Type, Value, ExpectedValue);
+ true ->
+ M = 'Real',
+ ExpectedValue = M:decode(Type, M:encode(Type, Value)),
+ ok
+ end.
diff --git a/lib/asn1/test/testPrimExternal.erl b/lib/asn1/test/testPrimExternal.erl
index 65c3c3a31a..a03760976d 100644
--- a/lib/asn1/test/testPrimExternal.erl
+++ b/lib/asn1/test/testPrimExternal.erl
@@ -24,84 +24,27 @@
-include_lib("test_server/include/test_server.hrl").
external(_Rules) ->
-
-
- ?line {ok,Bytes10} = asn1_wrapper:encode('PrimExternal','NT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','NT',lists:flatten(Bytes10)),
-
- ?line {ok,Bytes11} = asn1_wrapper:encode('PrimExternal','Imp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','Imp',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('PrimExternal','Exp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','Exp',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes13} = asn1_wrapper:encode('PrimExternal','NTNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','NTNT',lists:flatten(Bytes13)),
-
- ?line {ok,Bytes14} = asn1_wrapper:encode('PrimExternal','NTImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','NTImp',lists:flatten(Bytes14)),
-
- ?line {ok,Bytes15} = asn1_wrapper:encode('PrimExternal','NTExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','NTExp',lists:flatten(Bytes15)),
-
-
- ?line {ok,Bytes16} = asn1_wrapper:encode('PrimExternal','ImpNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ImpNT',lists:flatten(Bytes16)),
-
- ?line {ok,Bytes17} = asn1_wrapper:encode('PrimExternal','ImpImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ImpImp',lists:flatten(Bytes17)),
-
- ?line {ok,Bytes18} = asn1_wrapper:encode('PrimExternal','ImpExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ImpExp',lists:flatten(Bytes18)),
-
-
- ?line {ok,Bytes19} = asn1_wrapper:encode('PrimExternal','ExpNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ExpNT',lists:flatten(Bytes19)),
-
- ?line {ok,Bytes20} = asn1_wrapper:encode('PrimExternal','ExpImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ExpImp',lists:flatten(Bytes20)),
-
- ?line {ok,Bytes21} = asn1_wrapper:encode('PrimExternal','ExpExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','ExpExp',lists:flatten(Bytes21)),
-
-
-
-
-
- ?line {ok,Bytes31} = asn1_wrapper:encode('PrimExternal','XNTNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XNTNT',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('PrimExternal','XNTImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XNTImp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} = asn1_wrapper:encode('PrimExternal','XNTExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XNTExp',lists:flatten(Bytes33)),
-
-
- ?line {ok,Bytes34} = asn1_wrapper:encode('PrimExternal','XImpNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XImpNT',lists:flatten(Bytes34)),
-
- ?line {ok,Bytes35} = asn1_wrapper:encode('PrimExternal','XImpImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XImpImp',lists:flatten(Bytes35)),
-
- ?line {ok,Bytes36} = asn1_wrapper:encode('PrimExternal','XImpExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XImpExp',lists:flatten(Bytes36)),
-
-
- ?line {ok,Bytes37} = asn1_wrapper:encode('PrimExternal','XExpNT',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XExpNT',lists:flatten(Bytes37)),
-
- ?line {ok,Bytes38} = asn1_wrapper:encode('PrimExternal','XExpImp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XExpImp',lists:flatten(Bytes38)),
-
- ?line {ok,Bytes39} = asn1_wrapper:encode('PrimExternal','XExpExp',"kalle"),
- ?line {ok,"kalle"} = asn1_wrapper:decode('PrimExternal','XExpExp',lists:flatten(Bytes39)),
-
-
-
-
-
-
-
-ok.
+ Types = ['NT',
+ 'Imp',
+ 'Exp',
+ 'NTNT',
+ 'NTImp',
+ 'NTExp',
+ 'ImpNT',
+ 'ImpImp',
+ 'ImpExp',
+ 'ExpNT',
+ 'ExpImp',
+ 'ExpExp',
+ 'XNTNT',
+ 'XNTImp',
+ 'XNTExp',
+ 'XImpNT',
+ 'XImpImp',
+ 'XImpExp',
+ 'XExpNT',
+ 'XExpImp',
+ 'XExpExp'],
+ _ = [asn1_test_lib:roundtrip('PrimExternal', T, <<"kalle">>) ||
+ T <- Types],
+ ok.
diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl
index e2322c92a9..155d6f6ff5 100644
--- a/lib/asn1/test/testPrimStrings.erl
+++ b/lib/asn1/test/testPrimStrings.erl
@@ -18,8 +18,10 @@
%%
%%
-module(testPrimStrings).
+-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}},
+ {nowarn_deprecated_function,{asn1rt,utf8_binary_to_list,1}}]).
--export([bit_string/1]).
+-export([bit_string/2]).
-export([octet_string/1]).
-export([numeric_string/1]).
-export([other_strings/1]).
@@ -28,42 +30,91 @@
-export([bmp_string/1]).
-export([times/1]).
-export([utf8_string/1]).
+-export([fragmented/1]).
-include_lib("test_server/include/test_server.hrl").
-bit_string(Rules) ->
+fragmented(Rules) ->
+ Lens = fragmented_lengths(),
+ case 'PrimStrings':legacy_erlang_types() of
+ false -> fragmented_octet_string(Rules, Lens);
+ true -> ok
+ end,
+ fragmented_strings(Lens).
+
+fragmented_strings(Lens) ->
+ Types = ['Ns','Ps','Ps11','Vis','IA5'],
+ [fragmented_strings(Len, Types) || Len <- Lens],
+ ok.
+
+fragmented_strings(Len, Types) ->
+ Str = make_ns_value(Len),
+ [roundtrip(Type, Str) || Type <- Types],
+ ok.
+
+make_ns_value(0) -> [];
+make_ns_value(N) -> [($0 - 1) + random:uniform(10)|make_ns_value(N-1)].
+
+fragmented_lengths() ->
+ K16 = 1 bsl 14,
+ K32 = K16 + K16,
+ K48 = K32 + K16,
+ K64 = K48 + K16,
+ [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].
+
+bit_string(Rules, Opts) ->
%%==========================================================
%% 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', <<>>),
+ bs_roundtrip('Bs1', <<1:3>>),
+ bs_roundtrip('Bs1', <<15:4>>),
+ bs_roundtrip('Bs1', <<2#010010:6>>),
+ bs_roundtrip('Bs1', <<2#11111111:8>>),
+ bs_roundtrip('Bs1', <<2#100000000:9>>),
+ bs_roundtrip('Bs1', <<2#100000001:9>>),
+ bs_roundtrip('Bs1', <<2#001111011:9>>),
+ bs_roundtrip('Bs1', <<2#0100101111100010011:19>>),
- 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]),
-
- {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890),
- {ok,_} = 'PrimStrings':decode('Bs1', Enc1),
+ case 'PrimStrings':legacy_erlang_types() of
+ false ->
+ ok;
+ true ->
+ {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890),
+ {ok,_} = 'PrimStrings':decode('Bs1', Enc1)
+ end,
- 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 ->
+
+ case {Rules,Opts} of
+ {ber,[legacy_erlang_types]} ->
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
+ {ber,[]} ->
+ %% XXX
+ ok;
+ {_,_} ->
+ %% DER, PER, UPER
+ consistent_def_enc('BsDef1',
+ [2#111101,
+ [1,0,1,1,1,1],
+ {2,<<2#101111:6,0:2>>},
+ <<2#101111:6>>]),
+ consistent_def_enc('BsDef2',
+ [[1,1,0,1, 1,1,1,0, 1,0,1,0, 1,1,0,1,
+ 1,0,1,1, 1,1,1,0, 1,1,1,0, 1,1,1,1],
+ {0,<<16#DEADBEEF:4/unit:8>>},
+ <<16#DEADBEEF:4/unit:8>>])
end,
@@ -72,30 +123,39 @@ bit_string(Rules) ->
%%==========================================================
roundtrip('Bs2', [mo,tu,fr]),
- roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]),
+ bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]),
+ bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]),
%%==========================================================
%% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7))
%%==========================================================
roundtrip('Bs3', [mo,tu,fr]),
- bs_roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]),
+ bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]),
+ bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]),
+ bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]),
+ bs_roundtrip('Bs3', <<2#011001:6>>, [mo,tu,fr]),
+ bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]),
%%==========================================================
%% Bs7 ::= BIT STRING (SIZE (24))
%%==========================================================
- 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]),
+ bs_roundtrip('Bs7', <<23563:24>>),
+ case 'PrimStrings':legacy_erlang_types() of
+ false ->
+%% {error,_} = 'PrimStrings':encode('Bs7', <<2#1010:4>>);
+ ok;
+ true ->
+ ok
+ end,
%%==========================================================
%% BsPri ::= [PRIVATE 61] BIT STRING
%%==========================================================
- bs_roundtrip('BsPri', 45, [1,0,1,1,0,1]),
- bs_roundtrip('BsPri', 211, [1,1,0,0,1,0,1,1]),
+ bs_roundtrip('BsPri', <<2#101101:6>>),
+ bs_roundtrip('BsPri', <<2#11001011:8>>),
case Rules of
ber ->
@@ -116,8 +176,8 @@ bit_string(Rules) ->
%% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING
%%==========================================================
- bs_roundtrip('BsExpPri', 45, [1,0,1,1,0,1]),
- bs_roundtrip('BsExpPri', 211, [1,1,0,0,1,0,1,1]),
+ bs_roundtrip('BsExpPri', <<2#101101:6>>),
+ bs_roundtrip('BsExpPri', <<2#11001011:8>>),
case Rules of
ber ->
@@ -138,14 +198,14 @@ bit_string(Rules) ->
%% veteran(2), collegeGraduate(3)}, test case for OTP-5710
%%==========================================================
- {ok,Bytes54} = 'BitStr':encode('PersonalStatus', []),
+ {ok,Bytes54} = 'BitStr':encode('PersonalStatus', <<>>),
{ok,[]} = 'BitStr':decode('PersonalStatus', Bytes54),
%%==========================================================
%% BS5932 ::= BIT STRING (SIZE (5..MAX))
%% test case for OTP-5932
%%==========================================================
- bs_roundtrip('BSMAX', [1,0,1,0,1]),
+ bs_roundtrip('BSMAX', <<2#10101:5>>),
case Rules of
ber ->
{error,_} = 'PrimStrings':encode('BSMAX', [1,0,1]);
@@ -159,45 +219,68 @@ bit_string(Rules) ->
%% BS1024 ::= BIT STRING (SIZE (1024))
%% test case for OTP-7602
%%==========================================================
- BSmaker =
- fun(_F,S,S,_,Acc) ->
- Acc;
- (F,Ix,S,{A,B},Acc) ->
- F(F,Ix+1,S,{B,A},[A|Acc])
- 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},[]),
- bs_roundtrip('BS1024', BSList1024),
- bs_roundtrip('TransportLayerAddress', [0,1,1,0]),
+ bs_roundtrip('BS255', random_bits(255)),
+ bs_roundtrip('BS256', random_bits(256)),
+ bs_roundtrip('BS1024', random_bits(1024)),
+
+ bs_roundtrip('TransportLayerAddress', <<2#0110:4>>),
case Rules of
ber -> ok;
_ -> per_bs_strings()
end.
+random_bits(N) ->
+ Seed = integer_to_list(erlang:phash2(erlang:now())),
+ random_bits(<<>>, N, Seed).
+
+random_bits(Bin, N, Seed) ->
+ RandomBits = erlang:md5(Seed),
+ Bits = bit_size(RandomBits),
+ if
+ Bits < N ->
+ random_bits(<<Bin/bitstring,RandomBits/bitstring>>,
+ N-Bits, RandomBits);
+ true ->
+ <<LastBits:N/bitstring,_/bitstring>> = RandomBits,
+ <<Bin/bitstring,LastBits/bitstring>>
+ end.
+
+consistent_def_enc(Type, Vs0) ->
+ M = 'PrimStrings',
+ {ok,Enc} = M:encode(Type, {Type,asn1_DEFAULT}),
+ {ok,Val} = M:decode(Type, Enc),
+
+ %% Ensure that the value has the correct format.
+ case {M:bit_string_format(),Val} of
+ {bitstring,{_,Bs}} when is_bitstring(Bs) -> ok;
+ {compact,{_,{Unused,Bin}}} when is_integer(Unused),
+ is_binary(Bin) -> ok;
+ {legacy,{_,Bs}} when is_list(Bs) -> ok
+ end,
+
+ %% If this is not the legacy format, only bitstrings are
+ %% allowed.
+ Vs = case M:legacy_erlang_types() of
+ false -> [V || V <- Vs0, is_bitstring(V)];
+ true -> Vs0
+ end,
+
+ %% All values should be recognized and encoded as the
+ %% the default value (i.e. not encoded at all).
+ _ = [{ok,Enc} = M:encode(Type, {Type,V}) || V <- Vs],
+ ok.
+
%% 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).
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]),
-
- 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]),
-
- 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.
@@ -213,10 +296,6 @@ per_trailing_zeroes(Byte) ->
{bit,LastBitPos} -> LastBitPos+1
end,
- %% List of zeroes and ones.
- named_roundtrip(L, Pos, ExpectedSz),
- named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz),
-
%% Bitstrings.
Bs = << <<B:1>> || B <- L >>,
Sz = bit_size(Bs),
@@ -224,14 +303,22 @@ per_trailing_zeroes(Byte) ->
Bin = <<Bs:Sz/bits,0:16,0:7>>,
named_roundtrip(Bin, Pos, ExpectedSz),
- %% Compact bitstring.
- named_roundtrip({7,Bin}, Pos, ExpectedSz),
+ case 'PrimStrings':legacy_erlang_types() of
+ false ->
+ ok;
+ true ->
+ %% List of zeroes and ones.
+ named_roundtrip(L, Pos, ExpectedSz),
+ named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz),
- %% Integer bitstring (obsolete).
- IntBs = intlist_to_integer(L, 0, 0),
- named_roundtrip(IntBs, Pos, ExpectedSz),
+ %% Compact bitstring.
+ named_roundtrip({7,Bin}, Pos, ExpectedSz),
- ok.
+ %% Integer bitstring (obsolete).
+ IntBs = intlist_to_integer(L, 0, 0),
+ named_roundtrip(IntBs, Pos, ExpectedSz),
+ ok
+ end.
make_bit_list(0) -> [];
make_bit_list(B) -> [B band 1|make_bit_list(B bsr 1)].
@@ -265,76 +352,65 @@ octet_string(Rules) ->
%% Os ::= OCTET STRING
%%==========================================================
+ Legacy = 'PrimStrings':legacy_erlang_types(),
case Rules of
- ber ->
- {ok,"Jones"} =
+ ber when not Legacy ->
+ {ok,<<"Jones">>} =
'PrimStrings':decode('Os', <<4,5,16#4A,16#6F,16#6E,16#65,16#73>>),
- {ok,"Jones"} =
+ {ok,<<"Jones">>} =
'PrimStrings':decode('Os', <<36,9,4,3,16#4A,16#6F,16#6E,4,2,16#65,16#73>>),
- {ok,"Jones"} =
+ {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]),
+ os_roundtrip('Os', <<47,23,99,255,1>>),
+ os_roundtrip('OsCon', <<47,23,99,255,1>>),
+ os_roundtrip('OsPri', <<47,23,99,255,1>>),
+ os_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]),
+ os_roundtrip('OsExpCon', <<47,23,99,255,1>>),
+ os_roundtrip('OsExpPri', <<47,23,99,255,1>>),
+ os_roundtrip('OsExpApp', <<47,23,99,255,1>>),
- roundtrip('Os', []),
- roundtrip('OsApp', []),
- roundtrip('OsExpApp',[]),
+ os_roundtrip('Os', <<>>),
+ os_roundtrip('OsApp', <<>>),
+ os_roundtrip('OsExpApp', <<>>),
- OsR = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ OsR = <<"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890">>,
- roundtrip('Os', OsR),
- roundtrip('OsCon', OsR),
- roundtrip('OsExpApp', OsR),
+ os_roundtrip('Os', OsR),
+ os_roundtrip('OsCon', OsR),
+ os_roundtrip('OsExpApp', OsR),
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>>),
+ ber when not Legacy ->
+ {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),
+ Strings = {type,true,<<"">>,<<"1">>,<<"12">>,<<"345">>,true,
+ list_to_binary(S255),list_to_binary([$a|S255]),
+ list_to_binary([$a,$b|S255]),397},
+ p_os_roundtrip('OsFixedStrings', Strings),
+ p_os_roundtrip('OsFixedStringsExt', Strings),
+ p_os_roundtrip('OsVarStringsExt', Strings),
ShortenedStrings = shorten_by_two(Strings),
- p_roundtrip('OsFixedStringsExt', ShortenedStrings),
- p_roundtrip('OsVarStringsExt', ShortenedStrings),
+ p_os_roundtrip('OsFixedStringsExt', ShortenedStrings),
+ p_os_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],
+fragmented_octet_string(Erules, Lens) ->
Types = ['Os','OsFrag','OsFragExt'],
[fragmented_octet_string(Erules, Types, L) || L <- Lens],
fragmented_octet_string(Erules, ['FixedOs65536'], 65536),
@@ -360,13 +436,14 @@ fragmented_octet_string(Erules, Types, L) ->
ok.
enc_frag(Erules, Type, Value) ->
- {ok,Encoded} = 'PrimStrings':encode(Type, Value),
+ M = 'PrimStrings',
+ {ok,Encoded} = M:encode(Type, Value),
case Erules of
ber ->
Encoded;
_ ->
%% Validate encoding with our own encoder.
- Encoded = enc_frag_1(<<>>, list_to_binary(Value))
+ Encoded = enc_frag_1(<<>>, Value)
end.
enc_frag_1(Res, Bin0) ->
@@ -385,12 +462,12 @@ enc_frag_1(Res, Bin0) ->
end.
make_value(L) ->
- make_value(L, 0, []).
+ make_value(L, 0, <<>>).
make_value(0, _, Acc) ->
Acc;
make_value(N, Byte, Acc) when Byte =< 255 ->
- make_value(N-1, Byte+7, [Byte|Acc]);
+ make_value(N-1, Byte+7, <<Acc/binary,Byte:8>>);
make_value(N, Byte, Acc) ->
make_value(N, Byte band 16#FF, Acc).
@@ -688,36 +765,96 @@ utf8_string(_Rules) ->
shorten_by_two(Tuple) ->
L = [case E of
[_,_|T] -> T;
+ <<_:16,T/binary>> -> T;
_ -> E
end || E <- tuple_to_list(Tuple)],
list_to_tuple(L).
+p_os_roundtrip(Type, Value0) ->
+ Value = setelement(1, Value0, Type),
+ p_os_roundtrip_1(Type, Value).
+
+p_os_roundtrip_1(Type, Value) ->
+ M = 'PrimStrings',
+ case M:legacy_erlang_types() of
+ false ->
+ asn1_test_lib:roundtrip(M, Type, Value);
+ true ->
+ {ok,Encoded} = M:encode(Type, Value),
+ Es0 = tuple_to_list(Value),
+ Es1 = [if
+ is_binary(E) -> binary_to_list(E);
+ true -> E
+ end || E <- Es0],
+ ListValue = list_to_tuple(Es1),
+ {ok,Encoded} = M:encode(Type, ListValue),
+ {ok,ListValue} = M:decode(Type, Encoded)
+ end.
+
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, Value).
roundtrip(Type, Value, Expected) ->
- {ok,Encoded} = 'PrimStrings':encode(Type, Value),
- {ok,Expected} = 'PrimStrings':decode(Type, Encoded),
- ok.
+ asn1_test_lib:roundtrip('PrimStrings', Type, Value, Expected).
bs_roundtrip(Type, Value) ->
bs_roundtrip(Type, Value, Value).
-bs_roundtrip(Type, Value, Expected) ->
+os_roundtrip(Type, Bin) when is_binary(Bin) ->
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)
+ case M:legacy_erlang_types() of
+ false ->
+ asn1_test_lib:roundtrip(M, Type, Bin);
+ true ->
+ {ok,Encoded} = M:encode(Type, Bin),
+ List = binary_to_list(Bin),
+ {ok,Encoded} = M:encode(Type, List),
+ {ok,List} = M:decode(Type, Encoded)
+ end.
+
+bs_roundtrip(Type, Value, Expected) when is_bitstring(Value) ->
+ M = 'PrimStrings',
+ case M:legacy_erlang_types() of
+ false ->
+ asn1_test_lib:roundtrip(M, Type, Value, Expected);
+ true ->
+ {ok,Encoded} = M:encode(Type, Value),
+ BitList = [B || <<B:1>> <= Value],
+ {ok,Encoded} = M:encode(Type, BitList),
+ case BitList of
+ [] ->
+ {ok,Encoded} = M:encode(Type, 0);
+ [_|_] ->
+ case lists:last(BitList) of
+ 1 ->
+ Int = lists:foldr(fun(B, A) ->
+ (A bsl 1) bor B
+ end, 0, BitList),
+ {ok,Encoded} = M:encode(Type, Int);
+ 0 ->
+ %% This BIT STRING cannot be represented
+ %% as an integer.
+ ok
+ end
+ end,
+ Compact = case bit_size(Value) of
+ Bits when Bits rem 8 =:= 0 ->
+ {0,Value};
+ Bits ->
+ Unused = 8 - Bits rem 8,
+ {Unused,<<Value:Bits/bitstring,0:Unused>>}
+ end,
+ {ok,Encoded} = M:encode(Type, Compact),
+ case M:decode(Type, Encoded) of
+ {ok,Expected} ->
+ ok;
+ {ok,Other} ->
+ Expected = convert(Other, Expected)
+ end
end.
bs_decode(Type, Encoded, Expected) ->
diff --git a/lib/asn1/test/testSelectionTypes.erl b/lib/asn1/test/testSelectionTypes.erl
index 6d1641388f..6d060321da 100644
--- a/lib/asn1/test/testSelectionTypes.erl
+++ b/lib/asn1/test/testSelectionTypes.erl
@@ -18,19 +18,16 @@
%%
%%
-module(testSelectionTypes).
-
-export([test/0]).
-include_lib("test_server/include/test_server.hrl").
test() ->
Val = ["PrintableString","PrintableString","PrintableString"],
- ?line {ok,Bin}=asn1_wrapper:encode('SelectionType','MendeleyevTable',Val),
- ?line {ok,Val} = asn1_wrapper:decode('SelectionType','MendeleyevTable',Bin),
-
- ?line Val2 = ['SelectionType':einsteinium()],
- ?line ["Es"] = Val2,
-
- ?line {ok,Bin2}=asn1_wrapper:encode('SelectionType','MendeleyevTable',Val2),
- ?line {ok,Val2} = asn1_wrapper:decode('SelectionType','MendeleyevTable',Bin2).
+ ["Es"] = Val2 = ['SelectionType':einsteinium()],
+ roundtrip('MendeleyevTable', Val),
+ roundtrip('MendeleyevTable', Val2),
+ ok.
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SelectionType', T, V).
diff --git a/lib/asn1/test/testSeq2738.erl b/lib/asn1/test/testSeq2738.erl
index cddfe4b311..9c059f2fc9 100644
--- a/lib/asn1/test/testSeq2738.erl
+++ b/lib/asn1/test/testSeq2738.erl
@@ -18,27 +18,16 @@
%%
%%
-module(testSeq2738).
-
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-%-record('SeqOpt',{int, opt = asn1_NOVALUE}).
-record('SeqOptFake',{int, opt = asn1_NOVALUE}).
-%-record('OptSeq',{int=17}).
-record('OptSeqFake',{bool = false}).
-
-
-
main(_Rules) ->
-
- ?line {ok,Bytes} =
- asn1_wrapper:encode('Seq2738','SeqOptFake',
- #'SeqOptFake'{int = 10,
- opt = #'OptSeqFake'{}}),
- ?line {ok,#'SeqOptFake'{int=10,opt=#'OptSeqFake'{bool=false}}} =
- asn1_wrapper:decode('Seq2738','SeqOptFake',lists:flatten(Bytes)),
- ?line {error,_} =
- asn1_wrapper:decode('Seq2738','SeqOpt',lists:flatten(Bytes)),
+ Enc = asn1_test_lib:roundtrip_enc('Seq2738',
+ 'SeqOptFake',
+ #'SeqOptFake'{int=10,opt=#'OptSeqFake'{}}),
+ {error,_} = 'Seq2738':decode('SeqOpt', Enc),
ok.
diff --git a/lib/asn1/test/testSeqDefault.erl b/lib/asn1/test/testSeqDefault.erl
index a772b749bd..22c1b7ee3a 100644
--- a/lib/asn1/test/testSeqDefault.erl
+++ b/lib/asn1/test/testSeqDefault.erl
@@ -33,148 +33,64 @@
-record('SeqDef3',{bool3 = asn1_DEFAULT, seq3 = asn1_DEFAULT, int3 = asn1_DEFAULT}).
-record('SeqDef3Imp',{bool3 = asn1_DEFAULT, seq3 = asn1_DEFAULT, int3 = asn1_DEFAULT}).
-record('SeqDef3Exp',{bool3 = asn1_DEFAULT, seq3 = asn1_DEFAULT, int3 = asn1_DEFAULT}).
--record('SeqIn',{boolIn, intIn}).
+-record('SeqIn',{boolIn = asn1_NOVALUE, intIn = 12}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqDefault','SeqDef1',#'SeqDef1'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef1',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('SeqDefault','SeqDef1',#'SeqDef1'{int1 = 15}),
- ?line {ok,{'SeqDef1',true,15,{'SeqIn',asn1_NOVALUE,12}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqDefault','SeqDef2',#'SeqDef2'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef2',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('SeqDefault','SeqDef2',#'SeqDef2'{int2 = 15}),
- ?line {ok,{'SeqDef2',{'SeqIn',asn1_NOVALUE,12},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqDefault','SeqDef3',#'SeqDef3'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef3',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('SeqDefault','SeqDef3',#'SeqDef3'{int3 = 15}),
- ?line {ok,{'SeqDef3',true,{'SeqIn',asn1_NOVALUE,12},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3',lists:flatten(Bytes32)),
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqDefault','SeqDef1Imp',#'SeqDef1Imp'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef1Imp',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1Imp',lists:flatten(Bytes41)),
-
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('SeqDefault','SeqDef1Imp',#'SeqDef1Imp'{int1 = 15}),
- ?line {ok,{'SeqDef1Imp',true,15,{'SeqIn',asn1_NOVALUE,12}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1Imp',lists:flatten(Bytes42)),
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SeqDefault','SeqDef2Imp',#'SeqDef2Imp'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef2Imp',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2Imp',lists:flatten(Bytes51)),
-
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('SeqDefault','SeqDef2Imp',#'SeqDef2Imp'{int2 = 15}),
- ?line {ok,{'SeqDef2Imp',{'SeqIn',asn1_NOVALUE,12},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2Imp',lists:flatten(Bytes52)),
-
-
-
- ?line {ok,Bytes61} =
- asn1_wrapper:encode('SeqDefault','SeqDef3Imp',#'SeqDef3Imp'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef3Imp',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3Imp',lists:flatten(Bytes61)),
-
-
- ?line {ok,Bytes62} = asn1_wrapper:encode('SeqDefault','SeqDef3Imp',#'SeqDef3Imp'{int3 = 15}),
- ?line {ok,{'SeqDef3Imp',true,{'SeqIn',asn1_NOVALUE,12},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3Imp',lists:flatten(Bytes62)),
-
-
-
-
-
-
- ?line {ok,Bytes71} =
- asn1_wrapper:encode('SeqDefault','SeqDef1Exp',#'SeqDef1Exp'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef1Exp',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1Exp',lists:flatten(Bytes71)),
-
-
- ?line {ok,Bytes72} = asn1_wrapper:encode('SeqDefault','SeqDef1Exp',#'SeqDef1Exp'{int1 = 15}),
- ?line {ok,{'SeqDef1Exp',true,15,{'SeqIn',asn1_NOVALUE,12}}} =
- asn1_wrapper:decode('SeqDefault','SeqDef1Exp',lists:flatten(Bytes72)),
-
-
- ?line {ok,Bytes81} =
- asn1_wrapper:encode('SeqDefault','SeqDef2Exp',#'SeqDef2Exp'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef2Exp',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2Exp',lists:flatten(Bytes81)),
-
-
- ?line {ok,Bytes82} = asn1_wrapper:encode('SeqDefault','SeqDef2Exp',#'SeqDef2Exp'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SeqDef2Exp',{'SeqIn',asn1_NOVALUE,12},true,15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef2Exp',lists:flatten(Bytes82)),
-
-
-
- ?line {ok,Bytes91} =
- asn1_wrapper:encode('SeqDefault','SeqDef3Exp',#'SeqDef3Exp'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqDef3Exp',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3Exp',lists:flatten(Bytes91)),
-
-
- ?line {ok,Bytes92} = asn1_wrapper:encode('SeqDefault','SeqDef3Exp',#'SeqDef3Exp'{int3 = 15}),
- ?line {ok,{'SeqDef3Exp',true,{'SeqIn',asn1_NOVALUE,12},15}} =
- asn1_wrapper:decode('SeqDefault','SeqDef3Exp',lists:flatten(Bytes92)),
-
-
-
-
+ roundtrip('SeqDef1', #'SeqDef1'{bool1=true,int1=15,seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqDef1',
+ #'SeqDef1'{bool1=asn1_DEFAULT,int1=15,seq1=asn1_DEFAULT},
+ #'SeqDef1'{bool1=true,int1=15,seq1=#'SeqIn'{}}),
+
+ roundtrip('SeqDef2', #'SeqDef2'{seq2=#'SeqIn'{boolIn=true,intIn=66},bool2=true,int2=15}),
+ roundtrip('SeqDef2',
+ #'SeqDef2'{seq2=asn1_DEFAULT,bool2=asn1_DEFAULT,int2=15},
+ #'SeqDef2'{seq2=#'SeqIn'{},bool2=true,int2=15}),
+
+ roundtrip('SeqDef3', #'SeqDef3'{bool3=true,seq3=#'SeqIn'{boolIn=true,intIn=66},int3=15}),
+ roundtrip('SeqDef3',
+ #'SeqDef3'{bool3=asn1_DEFAULT,seq3=asn1_DEFAULT,int3=15},
+ #'SeqDef3'{bool3=true,seq3=#'SeqIn'{},int3=15}),
+
+ roundtrip('SeqDef1Imp', #'SeqDef1Imp'{bool1=true,int1=15,
+ seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqDef1Imp',
+ #'SeqDef1Imp'{bool1=asn1_DEFAULT,int1=15,seq1=asn1_DEFAULT},
+ #'SeqDef1Imp'{bool1=true,int1=15,seq1=#'SeqIn'{}}),
+
+ roundtrip('SeqDef2Imp', #'SeqDef2Imp'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SeqDef2Imp',
+ #'SeqDef2Imp'{seq2=asn1_DEFAULT,bool2=asn1_DEFAULT,int2=15},
+ #'SeqDef2Imp'{seq2=#'SeqIn'{},bool2=true,int2=15}),
+
+ roundtrip('SeqDef3Imp',
+ #'SeqDef3Imp'{bool3=true,seq3=#'SeqIn'{boolIn=true,intIn=66},int3=15}),
+ roundtrip('SeqDef3Imp',
+ #'SeqDef3Imp'{bool3=asn1_DEFAULT,seq3=asn1_DEFAULT,int3=15},
+ #'SeqDef3Imp'{bool3=true,seq3=#'SeqIn'{},int3=15}),
+
+ roundtrip('SeqDef1Exp',
+ #'SeqDef1Exp'{bool1=true,int1=15,seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqDef1Exp',
+ #'SeqDef1Exp'{bool1=asn1_DEFAULT,int1=15,seq1=asn1_DEFAULT},
+ #'SeqDef1Exp'{bool1=true,int1=15,seq1=#'SeqIn'{}}),
+
+ roundtrip('SeqDef2Exp', #'SeqDef2Exp'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SeqDef2Exp',
+ #'SeqDef2Exp'{seq2=asn1_DEFAULT,bool2=true,int2=15},
+ #'SeqDef2Exp'{seq2=#'SeqIn'{},bool2=true,int2=15}),
+
+ roundtrip('SeqDef3Exp',
+ #'SeqDef3Exp'{bool3=true,seq3=#'SeqIn'{boolIn=true,intIn=66},int3=15}),
+ roundtrip('SeqDef3Exp',
+ #'SeqDef3Exp'{bool3=asn1_DEFAULT,seq3=asn1_DEFAULT,int3=15},
+ #'SeqDef3Exp'{bool3=true,seq3=#'SeqIn'{},int3=15}),
ok.
+
+roundtrip(Type, Value) ->
+ roundtrip(Type, Value, Value).
+
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('SeqDefault', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index b996634996..c16e9fcd4c 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -44,7 +44,7 @@ main(Erule, DataDir, Opts) ->
roundtrip('SeqExt4', #'SeqExt4'{bool=true,int=12345}),
roundtrip('SeqExt4', #'SeqExt4'{bool=false,int=123456}),
- roundtrip('SeqExt5', #'SeqExt5'{name="Arne",shoesize=47}),
+ roundtrip('SeqExt5', #'SeqExt5'{name = <<"Arne">>,shoesize=47}),
%% Encode a value with this version of the specification.
BigInt = 128638468966,
@@ -52,7 +52,7 @@ main(Erule, DataDir, Opts) ->
s2=#'SeqExt2'{bool=true,int=2345},
s3=#'SeqExt3'{bool=false,int=17},
s4=#'SeqExt4'{bool=true,int=38739739},
- s5=#'SeqExt5'{name="Arne",shoesize=47},
+ s5=#'SeqExt5'{name = <<"Arne">>,shoesize=47},
s6=#'SeqExt6'{i1=531,i2=601,i3=999,
i4=777,i5=11953,
i6=13553,i7=77777},
@@ -108,18 +108,14 @@ main(Erule, DataDir, Opts) ->
ok.
roundtrip(Type, Value) ->
- {ok,Encoded} = 'SeqExtension':encode(Type, Value),
- {ok,Value} = 'SeqExtension':decode(Type, Encoded),
- ok.
+ asn1_test_lib:roundtrip('SeqExtension', Type, Value).
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.
+ asn1_test_lib:roundtrip_enc('SeqExtension2', Type, Value).
v(ber, 'SeqExt66') -> "30049F41 017D";
v(per, 'SeqExt66') -> "C0420000 00000000 00004001 FA";
diff --git a/lib/asn1/test/testSeqExternal.erl b/lib/asn1/test/testSeqExternal.erl
index b89b98d3fa..0b1d305054 100644
--- a/lib/asn1/test/testSeqExternal.erl
+++ b/lib/asn1/test/testSeqExternal.erl
@@ -20,121 +20,38 @@
-module(testSeqExternal).
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-
-record('SeqXSet1',{set, bool, int}).
-record('SeqXSet2',{bool, set, int}).
-record('SeqXSet3',{bool, int, set}).
-%-record('NT',{os, bool}).
-%-record('Imp',{os, bool}).
-%-record('Exp',{os, bool}).
-
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "SeqExternal",
- [Rules,{outdir,OutDir}]++Options).
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqExternal','XNTNT',#'XSeqNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XNTNT',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqExternal','XImpNT',#'XSeqNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XImpNT',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqExternal','XExpNT',#'XSeqNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XExpNT',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqExternal','XNTImp',#'XSeqImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XNTImp',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqExternal','XImpImp',#'XSeqImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XImpImp',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqExternal','XExpImp',#'XSeqImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XExpImp',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqExternal','XNTExp',#'XSeqExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XNTExp',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqExternal','XImpExp',#'XSeqExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XImpExp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SeqExternal','XExpExp',#'XSeqExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSeqExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SeqExternal','XExpExp',lists:flatten(Bytes33)),
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqExternal','SeqXSet1',
- #'SeqXSet1'{bool = true,
- int = 66,
- set = #'XSet1'{bool1 = true,
- int1 = 77,
- set1 = #'XSetIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SeqXSet1',{'XSet1',true,77,{'XSetIn',false,88}},true,66}} =
- asn1_wrapper:decode('SeqExternal','SeqXSet1',lists:flatten(Bytes41)),
-
-
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SeqExternal','SeqXSet2',
- #'SeqXSet2'{bool = true,
- int = 66,
- set = #'XSet1'{bool1 = true,
- int1 = 77,
- set1 = #'XSetIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SeqXSet2',true,{'XSet1',true,77,{'XSetIn',false,88}},66}} =
- asn1_wrapper:decode('SeqExternal','SeqXSet2',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SeqExternal','SeqXSet3',
- #'SeqXSet3'{bool = true,
- int = 66,
- set = #'XSet1'{bool1 = true,
- int1 = 77,
- set1 = #'XSetIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SeqXSet3',true,66,{'XSet1',true,77,{'XSetIn',false,88}}}} =
- asn1_wrapper:decode('SeqExternal','SeqXSet3',lists:flatten(Bytes43)),
-
-
-
-
+ roundtrip('XNTNT', #'XSeqNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpNT', #'XSeqNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpNT', #'XSeqNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XNTImp', #'XSeqImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpImp', #'XSeqImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpImp', #'XSeqImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XNTExp', #'XSeqExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpExp', #'XSeqExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpExp', #'XSeqExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('SeqXSet1',
+ #'SeqXSet1'{set=#'XSet1'{bool1=true,int1=77,
+ set1=#'XSetIn'{boolIn=false,intIn=88}},
+ bool=true,int=66}),
+ roundtrip('SeqXSet2',
+ #'SeqXSet2'{bool=true,
+ set=#'XSet1'{bool1=true,int1=77,
+ set1=#'XSetIn'{boolIn=false,intIn=88}},
+ int=66}),
+ roundtrip('SeqXSet3',
+ #'SeqXSet3'{bool=true,int=66,
+ set=#'XSet1'{bool1=true,int1=77,
+ set1=#'XSetIn'{boolIn=false,intIn=88}}}),
ok.
-
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqExternal', T, V).
diff --git a/lib/asn1/test/testSeqIndefinite.erl b/lib/asn1/test/testSeqIndefinite.erl
deleted file mode 100644
index c7b8aba523..0000000000
--- a/lib/asn1/test/testSeqIndefinite.erl
+++ /dev/null
@@ -1,48 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-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(testSeqIndefinite).
-
--export([main/1]).
-
--include_lib("test_server/include/test_server.hrl").
-
-main(per) -> ok;
-main(ber) ->
-
- %% normal encoding
- B = [48,20,1,1,255,48,9,1,1,255,2,4,251,35,238,194,2,4,251,55,236,161],
- %% indefinite length encoding
- Bi = [48,22,1,1,255,48,128,1,1,255,2,4,251,35,238,194,0,0,2,4,251,55,236,161],
- %% the value which is encoded
- V = {'SeqS3',true,{'SeqS3_seqS3',true,-81531198},-80221023},
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SeqS3',B),
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SeqS3',Bi),
-
- %% normal encoding but with unknown extension component
- _Be = [48,23,1,1,255,48,12,1,1,255,2,4,251,35,238,194,1,1,255,2,4,251,55,236,161],
- %% indefinite length encoding but with unknown extension component
- _Bei = [48,25,1,1,255,48,128,1,1,255,2,4,251,35,238,194,1,1,255,0,0,2,4,251,55,236,161],
-
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SeqS3',B),
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SeqS3',Bi),
- ok.
-
-
-
diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl
index db537b1478..25059d6052 100644
--- a/lib/asn1/test/testSeqOf.erl
+++ b/lib/asn1/test/testSeqOf.erl
@@ -83,6 +83,32 @@ main(_Rules) ->
roundtrip('Seq4', #'Seq4'{seq43=SeqIn3},
#'Seq4'{seq41=[],seq42=[],
seq43=SeqIn3}),
+
+ roundtrip('Seq5', {'Seq5',true,[],77}),
+ roundtrip('Seq5', {'Seq5',true,[<<"">>],77}),
+ roundtrip('Seq5', {'Seq5',true,[<<"a">>],77}),
+ roundtrip('Seq5', {'Seq5',true,[<<"ab">>],77}),
+ roundtrip('Seq5', {'Seq5',true,[<<"abc">>],77}),
+
+ roundtrip('Seq6', {'Seq6',[],[],101}),
+ roundtrip('Seq6', {'Seq6',[],[7],101}),
+ roundtrip('Seq6', {'Seq6',[],[1,7],101}),
+ roundtrip('Seq6', {'Seq6',[1],[],101}),
+ roundtrip('Seq6', {'Seq6',[2],[7],101}),
+ roundtrip('Seq6', {'Seq6',[3],[1,7],101}),
+
+ roundtrip('Seq8', {'Seq8',[],37}),
+
+ roundtrip('Seq9', {'Seq9',true,[],97}),
+ roundtrip('Seq9', {'Seq9',true,[<<"">>],97}),
+ roundtrip('Seq9', {'Seq9',true,[<<"x">>],97}),
+ roundtrip('Seq9', {'Seq9',true,[<<"xy">>],97}),
+ roundtrip('Seq9', {'Seq9',true,[<<"xyz">>],97}),
+
+ roundtrip('Seq10', {'Seq10',true,[<<"">>],97}),
+ roundtrip('Seq10', {'Seq10',true,[<<"a">>],97}),
+ roundtrip('Seq10', {'Seq10',true,[<<"a">>,<<"b">>],97}),
+ roundtrip('Seq10', {'Seq10',true,[<<"a">>,<<"b">>,<<"c">>],97}),
roundtrip('SeqEmp', #'SeqEmp'{seq1=[#'Empty'{}]}),
@@ -123,15 +149,9 @@ roundtrip(T, V) ->
roundtrip(T, V, V).
roundtrip(Type, Val, Expected) ->
- M = 'SeqOf',
- {ok,Enc} = M:encode(Type, Val),
- {ok,Expected} = M:decode(Type, Enc),
- ok.
+ asn1_test_lib:roundtrip('SeqOf', Type, Val, Expected).
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),
+ Enc = asn1_test_lib:roundtrip_enc('XSeqOf', T1, Val),
+ Enc = asn1_test_lib:roundtrip_enc('XSeqOf', T2, Val),
ok.
diff --git a/lib/asn1/test/testSeqOfCho.erl b/lib/asn1/test/testSeqOfCho.erl
index 5b83c8bf21..f749845bb9 100644
--- a/lib/asn1/test/testSeqOfCho.erl
+++ b/lib/asn1/test/testSeqOfCho.erl
@@ -31,117 +31,45 @@
-record('SeqOfChoEmbOpt_SEQOF',{bool1, int1, seq1 = asn1_NOVALUE}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqOfCho','SeqChoDef',#'SeqChoDef'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SeqChoDef',true,17,[]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoDef',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqOfCho','SeqChoDef',#'SeqChoDef'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SeqChoDef',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoDef',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes15} =
- asn1_wrapper:encode('SeqOfCho','SeqChoOpt',#'SeqChoOpt'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SeqChoOpt',true,17,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoOpt',lists:flatten(Bytes15)),
-
-
- ?line {ok,Bytes16} =
- asn1_wrapper:encode('SeqOfCho','SeqChoOpt',#'SeqChoOpt'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SeqChoOpt',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoOpt',lists:flatten(Bytes16)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqOfCho','SeqChoEmbDef',#'SeqChoEmbDef'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SeqChoEmbDef',true,17,[]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoEmbDef',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqOfCho','SeqChoEmbDef',#'SeqChoEmbDef'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SeqChoEmbDef',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoEmbDef',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes25} =
- asn1_wrapper:encode('SeqOfCho','SeqChoEmbOpt',#'SeqChoEmbOpt'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SeqChoEmbOpt',true,17,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoEmbOpt',lists:flatten(Bytes25)),
-
-
- ?line {ok,Bytes26} =
- asn1_wrapper:encode('SeqOfCho','SeqChoEmbOpt',#'SeqChoEmbOpt'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SeqChoEmbOpt',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SeqOfCho','SeqChoEmbOpt',lists:flatten(Bytes26)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqOfCho','SeqOfChoEmbDef',[#'SeqOfChoEmbDef_SEQOF'{bool1 = true,
- int1 = 17}]),
- ?line {ok,[{'SeqOfChoEmbDef_SEQOF',true,17,[]}]} =
- asn1_wrapper:decode('SeqOfCho','SeqOfChoEmbDef',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqOfCho','SeqOfChoEmbDef',
- [#'SeqOfChoEmbDef_SEQOF'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}]),
- ?line {ok,[{'SeqOfChoEmbDef_SEQOF',true,17,[{boolIn,true},{intIn,25}]}]} =
- asn1_wrapper:decode('SeqOfCho','SeqOfChoEmbDef',lists:flatten(Bytes32)),
-
-
-
- ?line {ok,Bytes35} =
- asn1_wrapper:encode('SeqOfCho','SeqOfChoEmbOpt',[#'SeqOfChoEmbOpt_SEQOF'{bool1 = true,
- int1 = 17}]),
- ?line {ok,[{'SeqOfChoEmbOpt_SEQOF',true,17,asn1_NOVALUE}]} =
- asn1_wrapper:decode('SeqOfCho','SeqOfChoEmbOpt',lists:flatten(Bytes35)),
-
-
- ?line {ok,Bytes36} =
- asn1_wrapper:encode('SeqOfCho','SeqOfChoEmbOpt',
- [#'SeqOfChoEmbOpt_SEQOF'{bool1 = true,
- int1 = 17,
- seq1 = [{boolIn,true},
- {intIn,25}]}]),
- ?line {ok,[{'SeqOfChoEmbOpt_SEQOF',true,17,[{boolIn,true},{intIn,25}]}]} =
- asn1_wrapper:decode('SeqOfCho','SeqOfChoEmbOpt',lists:flatten(Bytes36)),
-
-
-
-
+ roundtrip('SeqChoDef',
+ #'SeqChoDef'{bool1=true,int1=17,seq1=asn1_DEFAULT},
+ #'SeqChoDef'{bool1=true,int1=17,seq1=[]}),
+ roundtrip('SeqChoDef',
+ #'SeqChoDef'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}),
+ roundtrip('SeqChoOpt',
+ #'SeqChoOpt'{bool1=true,int1=17,seq1=asn1_NOVALUE}),
+ roundtrip('SeqChoOpt',
+ #'SeqChoOpt'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}),
+
+ roundtrip('SeqChoEmbDef',
+ #'SeqChoEmbDef'{bool1=true,int1=17,seq1=asn1_DEFAULT},
+ #'SeqChoEmbDef'{bool1=true,int1=17,seq1=[]}),
+ roundtrip('SeqChoEmbDef',
+ #'SeqChoEmbDef'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}),
+ roundtrip('SeqChoEmbOpt',
+ #'SeqChoEmbOpt'{bool1=true,int1=17,seq1=asn1_NOVALUE}),
+ roundtrip('SeqChoEmbOpt',
+ #'SeqChoEmbOpt'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}),
+
+ roundtrip('SeqOfChoEmbDef',
+ [#'SeqOfChoEmbDef_SEQOF'{bool1=true,int1=17,seq1=asn1_DEFAULT}],
+ [#'SeqOfChoEmbDef_SEQOF'{bool1=true,int1=17,seq1=[]}]),
+ roundtrip('SeqOfChoEmbDef',
+ [#'SeqOfChoEmbDef_SEQOF'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}]),
+ roundtrip('SeqOfChoEmbOpt',
+ [#'SeqOfChoEmbOpt_SEQOF'{bool1=true,int1=17,seq1=asn1_NOVALUE}]),
+ roundtrip('SeqOfChoEmbOpt',
+ [#'SeqOfChoEmbOpt_SEQOF'{bool1=true,int1=17,
+ seq1=[{boolIn,true},{intIn,25}]}]),
ok.
+roundtrip(Type, Value) ->
+ roundtrip(Type, Value, Value).
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('SeqOfCho', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testSeqOfExternal.erl b/lib/asn1/test/testSeqOfExternal.erl
index 4c4c9e2b0f..38b9f0ce7c 100644
--- a/lib/asn1/test/testSeqOfExternal.erl
+++ b/lib/asn1/test/testSeqOfExternal.erl
@@ -18,9 +18,6 @@
%%
%%
-module(testSeqOfExternal).
-
-
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -30,142 +27,62 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "SeqOfExternal",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqOfExternal','NTNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','NTNT',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqOfExternal','ImpNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ImpNT',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqOfExternal','ExpNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ExpNT',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqOfExternal','NTImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','NTImp',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqOfExternal','ImpImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ImpImp',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqOfExternal','ExpImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ExpImp',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqOfExternal','NTExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','NTExp',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqOfExternal','ImpExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ImpExp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SeqOfExternal','ExpExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','ExpExp',lists:flatten(Bytes33)),
-
-
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqOfExternal','XNTNT',[#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XNTNT',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SeqOfExternal','XImpNT',[#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XImpNT',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SeqOfExternal','XExpNT',[#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XExpNT',lists:flatten(Bytes43)),
-
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SeqOfExternal','XNTImp',[#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XNTImp',lists:flatten(Bytes51)),
-
- ?line {ok,Bytes52} =
- asn1_wrapper:encode('SeqOfExternal','XImpImp',[#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XImpImp',lists:flatten(Bytes52)),
-
- ?line {ok,Bytes53} =
- asn1_wrapper:encode('SeqOfExternal','XExpImp',[#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XExpImp',lists:flatten(Bytes53)),
-
-
-
- ?line {ok,Bytes61} =
- asn1_wrapper:encode('SeqOfExternal','XNTExp',[#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XNTExp',lists:flatten(Bytes61)),
-
- ?line {ok,Bytes62} =
- asn1_wrapper:encode('SeqOfExternal','XImpExp',[#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XImpExp',lists:flatten(Bytes62)),
-
- ?line {ok,Bytes63} =
- asn1_wrapper:encode('SeqOfExternal','XExpExp',[#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SeqOfExternal','XExpExp',lists:flatten(Bytes63)),
-
-
-
-
+ roundtrip('NTNT',
+ [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpNT',
+ [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpNT',
+ [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('NTImp',
+ [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpImp',
+ [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpImp',
+ [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('NTExp',
+ [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpExp',
+ [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpExp',
+ [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTNT',
+ [#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpNT',
+ [#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpNT',
+ [#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTImp',
+ [#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpImp',
+ [#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpImp',
+ [#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTExp',
+ [#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpExp',
+ [#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpExp',
+ [#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqOfExternal', T, V).
diff --git a/lib/asn1/test/testSeqOfIndefinite.erl b/lib/asn1/test/testSeqOfIndefinite.erl
index 01ef36e0b4..b771405d84 100644
--- a/lib/asn1/test/testSeqOfIndefinite.erl
+++ b/lib/asn1/test/testSeqOfIndefinite.erl
@@ -33,60 +33,53 @@ main() ->
?line ok = test('InsertSubscriberDataArg'). % OTP-4232
test(isd)->
- EncPdu = [48,128,129,7,145,148,113,50,1,0,241,131,1,0,176,128,5,0,161,128,48,22,2,1,1,144,2,241,33,145,4,0,1,2,3,146,3,36,131,16,148,2,1,42,48,35,2,1,2,144,2,241,33,145,4,255,255,255,255,146,3,37,147,18,147,0,148,13,7,67,79,77,80,65,78,89,4,67,79,77,53,48,28,2,1,3,144,2,241,33,146,3,26,98,31,148,14,9,67,79,77,80,65,78,89,49,50,3,67,79,77,0,0,0,0,152,1,2,0,0],
-
- ?line {ok,_} = asn1_wrapper:decode('Mvrasn-11-4',
- 'InsertSubscriberDataArg',
- EncPdu),
+ EncPdu = <<48,128,129,7,145,148,113,50,1,0,241,131,1,0,176,128,5,0,
+ 161,128,48,22,2,1,1,144,2,241,33,145,4,0,1,2,3,146,3,36,
+ 131,16,148,2,1,42,48,35,2,1,2,144,2,241,33,145,4,255,255,
+ 255,255,146,3,37,147,18,147,0,148,13,7,67,79,77,80,65,78,
+ 89,4,67,79,77,53,48,28,2,1,3,144,2,241,33,146,3,26,98,31,
+ 148,14,9,67,79,77,80,65,78,89,49,50,3,67,79,77,0,0,0,0,
+ 152,1,2,0,0>>,
+ {ok,_} = 'Mvrasn-11-4':decode('InsertSubscriberDataArg', EncPdu),
ok;
%
% Problems with indefinite length encoding !!!
%
test(isd2)->
- EncPdu = [48, 128, 128, 8, 98, 2, 50, 1, 0, 0, 0, 241, 176, 128, 161, 128, 48, 128, 2, 1, 1, 144, 2, 241, 33, 145, 4, 255, 23, 12, 1, 146, 3, 9, 17, 1, 147, 0, 148, 13, 7, 67, 79, 77, 80, 65, 78, 89, 4, 67, 79, 77, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn-11-4',
- 'InsertSubscriberDataArg',
- EncPdu),
-
+ EncPdu = <<48,128,128,8,98,2,50,1,0,0,0,241,176,128,161,128,48,128,2,1,1,144,
+ 2,241,33,145,4,255,23,12,1,146,3,9,17,1,147,0,148,13,7,67,79,77,80,
+ 65,78,89,4,67,79,77,53,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ {ok,_DecPdu} = 'Mvrasn-11-4':decode('InsertSubscriberDataArg', EncPdu),
ok;
%
% Is doing fine, although there is indefinite encoding used... !!!
%
test(dsd)->
- EncPdu = [48, 128, 128, 8, 98, 2, 50, 1, 0, 0, 0, 241, 170, 2, 5, 0, 0, 0, 0, 0],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn-11-4',
- 'DeleteSubscriberDataArg',
- EncPdu),
-
+ EncPdu = <<48,128,128,8,98,2,50,1,0,0,0,241,170,2,5,0,0,0,0,0>>,
+ {ok,_DecPdu} = 'Mvrasn-11-4':decode('DeleteSubscriberDataArg', EncPdu),
ok;
%
% Is doing fine !!!
%
test(ul_res)->
- EncPdu = [48, 9, 4, 7, 145, 148, 113, 66, 16, 17, 241],
-
- ?line {ok,_DecPdu} = asn1_wrapper:decode('Mvrasn-11-4',
- 'UpdateGprsLocationRes',
- EncPdu),
-
+ EncPdu = <<48,9,4,7,145,148,113,66,16,17,241>>,
+ {ok,_DecPdu} = 'Mvrasn-11-4':decode('UpdateGprsLocationRes', EncPdu),
ok;
test(prim) ->
- ?line {ok,Bytes} = asn1_wrapper:encode('SeqOf','SeqOfInt',[10,20,30]),
- ?line [Tag,_Len|Ints] = lists:flatten(Bytes),
- ?line {ok,[10,20,30]} =
- asn1_wrapper:decode('SeqOf','SeqOfInt',[Tag,128|Ints] ++ [0,0]),
+ Bytes = asn1_test_lib:roundtrip_enc('SeqOf', 'SeqOfInt', [10,20,30]),
+ <<Tag,_Len,Ints/binary>> = Bytes,
+ {ok,[10,20,30]} =
+ 'SeqOf':decode('SeqOfInt', <<Tag,128,Ints/binary,0,0>>),
ok;
test(seqofseq) ->
- {ok,_V} = asn1_wrapper:decode('Mvrasn-DataTypes-1',
- 'SentParameters',
- [48,
+ {ok,_V} = 'Mvrasn-DataTypes-1':decode(
+ 'SentParameters',
+ [48,
129,
190,
161,
@@ -281,17 +274,16 @@ test(seqofseq) ->
0]),
ok;
test('InsertSubscriberDataArg') ->
- {ok,_V} =
- asn1_wrapper:decode('Mvrasn-11-4','InsertSubscriberDataArg',
- [16#30,16#80,16#81,16#07,16#91,16#94,
- 16#71,16#92,16#00,16#35,16#80,16#83,
- 16#01,16#00,16#A6,16#06,16#04,16#01,
- 16#21,16#04,16#01,16#22,16#B0,16#80,
- 16#05,16#00,16#A1,16#80,16#30,16#1A,
- 16#02,16#01,16#01,16#90,16#02,16#F1,
- 16#21,16#92,16#03,16#0D,16#92,16#1F,
- 16#94,16#0C,16#03,16#53,16#49,16#4D,
- 16#03,16#47,16#53,16#4E,16#03,16#4C,
- 16#4B,16#50,16#00,16#00,16#00,16#00,
- 16#98,16#01,16#00,16#00,16#00]),
+ EncPdu = <<16#30,16#80,16#81,16#07,16#91,16#94,
+ 16#71,16#92,16#00,16#35,16#80,16#83,
+ 16#01,16#00,16#A6,16#06,16#04,16#01,
+ 16#21,16#04,16#01,16#22,16#B0,16#80,
+ 16#05,16#00,16#A1,16#80,16#30,16#1A,
+ 16#02,16#01,16#01,16#90,16#02,16#F1,
+ 16#21,16#92,16#03,16#0D,16#92,16#1F,
+ 16#94,16#0C,16#03,16#53,16#49,16#4D,
+ 16#03,16#47,16#53,16#4E,16#03,16#4C,
+ 16#4B,16#50,16#00,16#00,16#00,16#00,
+ 16#98,16#01,16#00,16#00,16#00>>,
+ {ok,_V} = 'Mvrasn-11-4':decode('InsertSubscriberDataArg', EncPdu),
ok.
diff --git a/lib/asn1/test/testSeqOfTag.erl b/lib/asn1/test/testSeqOfTag.erl
index 2359df0c59..f66e29e91d 100644
--- a/lib/asn1/test/testSeqOfTag.erl
+++ b/lib/asn1/test/testSeqOfTag.erl
@@ -44,145 +44,48 @@
-record('Exp',{os, bool}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqOfTag','SeqTagNt',
- #'SeqTagNt'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagNt',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagNt',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqOfTag','SeqTagNtI',
- #'SeqTagNtI'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagNtI',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagNtI',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqOfTag','SeqTagNtE',
- #'SeqTagNtE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagNtE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagNtE',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqOfTag','SeqTagI',
- #'SeqTagI'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagI',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagI',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqOfTag','SeqTagII',
- #'SeqTagII'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagII',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagII',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqOfTag','SeqTagIE',
- #'SeqTagIE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagIE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagIE',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqOfTag','SeqTagE',
- #'SeqTagE'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagE',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagE',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SeqOfTag','SeqTagEI',
- #'SeqTagEI'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagEI',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagEI',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SeqOfTag','SeqTagEE',
- #'SeqTagEE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagEE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagEE',lists:flatten(Bytes33)),
-
-
-
-
+ roundtrip('SeqTagNt', #'SeqTagNt'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagNtI', #'SeqTagNtI'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagNtE', #'SeqTagNtE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagI', #'SeqTagI'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagII', #'SeqTagII'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagIE', #'SeqTagIE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagE', #'SeqTagE'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagEI', #'SeqTagEI'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagEE', #'SeqTagEE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagXNt',
+ #'SeqTagXNt'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagXI',
+ #'SeqTagXI'{ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagXE',
+ #'SeqTagXE'{xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagImpX',
+ #'SeqTagImpX'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}],
+ ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}],
+ xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SeqTagExpX',
+ #'SeqTagExpX'{xnt=[#'XSeqNT'{os = <<"kalle">>,bool=true},
+ #'XSeqNT'{os = <<"kalle">>,bool=true}],
+ ximp=[#'XSeqImp'{os = <<"kalle">>,bool=true},
+ #'XSeqImp'{os = <<"kalle">>,bool=true}],
+ xexp=[#'XSeqExp'{os = <<"kalle">>,bool=true},
+ #'XSeqExp'{os = <<"kalle">>,bool=true}]}),
+ ok.
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqOfTag','SeqTagXNt',
- #'SeqTagXNt'{xnt = [#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagXNt',
- [{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagXNt',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SeqOfTag','SeqTagXI',
- #'SeqTagXI'{ximp = [#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagXI',
- [{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagXI',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SeqOfTag','SeqTagXE',
- #'SeqTagXE'{xexp = [#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagXE',
- [{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagXE',lists:flatten(Bytes43)),
-
-
-
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SeqOfTag','SeqTagImpX',
- #'SeqTagImpX'{xnt = [#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}],
- ximp = [#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}],
- xexp = [#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagImpX',
- [{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}],
- [{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}],
- [{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagImpX',lists:flatten(Bytes51)),
-
-
-
- ?line {ok,Bytes52} =
- asn1_wrapper:encode('SeqOfTag','SeqTagExpX',
- #'SeqTagExpX'{xnt = [#'XSeqNT'{bool = true, os = "kalle"},
- #'XSeqNT'{bool = true, os = "kalle"}],
- ximp = [#'XSeqImp'{bool = true, os = "kalle"},
- #'XSeqImp'{bool = true, os = "kalle"}],
- xexp = [#'XSeqExp'{bool = true, os = "kalle"},
- #'XSeqExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SeqTagExpX',
- [{'XSeqNT',[107,97,108,108,101],true},{'XSeqNT',[107,97,108,108,101],true}],
- [{'XSeqImp',[107,97,108,108,101],true},{'XSeqImp',[107,97,108,108,101],true}],
- [{'XSeqExp',[107,97,108,108,101],true},{'XSeqExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SeqOfTag','SeqTagExpX',lists:flatten(Bytes52)),
-
-ok.
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqOfTag', T, V).
diff --git a/lib/asn1/test/testSeqOptional.erl b/lib/asn1/test/testSeqOptional.erl
index 8013f3c685..c9478105a4 100644
--- a/lib/asn1/test/testSeqOptional.erl
+++ b/lib/asn1/test/testSeqOptional.erl
@@ -37,159 +37,48 @@
-record('SeqChoOpt',{int, cho = asn1_NOVALUE}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqOptional','SeqOpt1',#'SeqOpt1'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt1',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('SeqOptional','SeqOpt1',#'SeqOpt1'{int1 = 15}),
- ?line {ok,{'SeqOpt1',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqOptional','SeqOpt2',#'SeqOpt2'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt2',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('SeqOptional','SeqOpt2',#'SeqOpt2'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SeqOpt2',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqOptional','SeqOpt3',#'SeqOpt3'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt3',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('SeqOptional','SeqOpt3',#'SeqOpt3'{int3 = 15}),
- ?line {ok,{'SeqOpt3',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3',lists:flatten(Bytes32)),
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqOptional','SeqOpt1Imp',#'SeqOpt1Imp'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt1Imp',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1Imp',lists:flatten(Bytes41)),
-
-
- ?line {ok,Bytes42} = asn1_wrapper:encode('SeqOptional','SeqOpt1Imp',#'SeqOpt1Imp'{int1 = 15}),
- ?line {ok,{'SeqOpt1Imp',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1Imp',lists:flatten(Bytes42)),
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SeqOptional','SeqOpt2Imp',#'SeqOpt2Imp'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt2Imp',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2Imp',lists:flatten(Bytes51)),
-
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('SeqOptional','SeqOpt2Imp',#'SeqOpt2Imp'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SeqOpt2Imp',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2Imp',lists:flatten(Bytes52)),
-
-
-
- ?line {ok,Bytes61} =
- asn1_wrapper:encode('SeqOptional','SeqOpt3Imp',#'SeqOpt3Imp'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt3Imp',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3Imp',lists:flatten(Bytes61)),
-
-
- ?line {ok,Bytes62} = asn1_wrapper:encode('SeqOptional','SeqOpt3Imp',#'SeqOpt3Imp'{int3 = 15}),
- ?line {ok,{'SeqOpt3Imp',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3Imp',lists:flatten(Bytes62)),
-
-
-
-
-
-
- ?line {ok,Bytes71} =
- asn1_wrapper:encode('SeqOptional','SeqOpt1Exp',#'SeqOpt1Exp'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt1Exp',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1Exp',lists:flatten(Bytes71)),
-
-
- ?line {ok,Bytes72} = asn1_wrapper:encode('SeqOptional','SeqOpt1Exp',#'SeqOpt1Exp'{int1 = 15}),
- ?line {ok,{'SeqOpt1Exp',asn1_NOVALUE,15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt1Exp',lists:flatten(Bytes72)),
-
-
- ?line {ok,Bytes81} =
- asn1_wrapper:encode('SeqOptional','SeqOpt2Exp',#'SeqOpt2Exp'{bool2 = true,
- int2 = 15,
- seq2 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt2Exp',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2Exp',lists:flatten(Bytes81)),
-
-
- ?line {ok,Bytes82} = asn1_wrapper:encode('SeqOptional','SeqOpt2Exp',#'SeqOpt2Exp'{int2 = 15,
- bool2 = true}),
- ?line {ok,{'SeqOpt2Exp',asn1_NOVALUE,true,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt2Exp',lists:flatten(Bytes82)),
-
-
-
- ?line {ok,Bytes91} =
- asn1_wrapper:encode('SeqOptional','SeqOpt3Exp',#'SeqOpt3Exp'{bool3 = true,
- int3 = 15,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqOpt3Exp',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3Exp',lists:flatten(Bytes91)),
-
-
- ?line {ok,Bytes92} = asn1_wrapper:encode('SeqOptional','SeqOpt3Exp',#'SeqOpt3Exp'{int3 = 15}),
- ?line {ok,{'SeqOpt3Exp',asn1_NOVALUE,asn1_NOVALUE,15}} =
- asn1_wrapper:decode('SeqOptional','SeqOpt3Exp',lists:flatten(Bytes92)),
-
-
-
- ?line {ok,Bytes101} =
- asn1_wrapper:encode('SeqOptional','SeqChoOpt',#'SeqChoOpt'{int = 15,
- cho = {boolC,true}}),
- ?line {ok,{'SeqChoOpt',15,{boolC,true}}} =
- asn1_wrapper:decode('SeqOptional','SeqChoOpt',lists:flatten(Bytes101)),
-
-
- ?line {ok,Bytes102} = asn1_wrapper:encode('SeqOptional','SeqChoOpt',#'SeqChoOpt'{int = 15}),
- ?line {ok,{'SeqChoOpt',15,asn1_NOVALUE}} =
- asn1_wrapper:decode('SeqOptional','SeqChoOpt',lists:flatten(Bytes102)),
-
-
-
-
+ roundtrip('SeqOpt1', #'SeqOpt1'{bool1=true,int1=15,
+ seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqOpt1', #'SeqOpt1'{bool1=asn1_NOVALUE,
+ int1=15,seq1=asn1_NOVALUE}),
+ roundtrip('SeqOpt2', #'SeqOpt2'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SeqOpt2', #'SeqOpt2'{seq2=asn1_NOVALUE,bool2=true,int2=15}),
+ roundtrip('SeqOpt3', #'SeqOpt3'{bool3=true,
+ seq3=#'SeqIn'{boolIn=true,
+ intIn=66},int3=15}),
+ roundtrip('SeqOpt3', #'SeqOpt3'{bool3=asn1_NOVALUE,
+ seq3=asn1_NOVALUE,int3=15}),
+ roundtrip('SeqOpt1Imp', #'SeqOpt1Imp'{bool1=true,int1=15,
+ seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqOpt1Imp', #'SeqOpt1Imp'{bool1=asn1_NOVALUE,
+ int1=15,seq1=asn1_NOVALUE}),
+ roundtrip('SeqOpt2Imp', #'SeqOpt2Imp'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SeqOpt2Imp', #'SeqOpt2Imp'{seq2=asn1_NOVALUE,
+ bool2=true,int2=15}),
+ roundtrip('SeqOpt3Imp', #'SeqOpt3Imp'{bool3=true,
+ seq3=#'SeqIn'{boolIn=true,intIn=66},
+ int3=15}),
+ roundtrip('SeqOpt3Imp', #'SeqOpt3Imp'{bool3=asn1_NOVALUE,
+ seq3=asn1_NOVALUE,int3=15}),
+ roundtrip('SeqOpt1Exp', #'SeqOpt1Exp'{bool1=true,int1=15,
+ seq1=#'SeqIn'{boolIn=true,
+ intIn=66}}),
+ roundtrip('SeqOpt1Exp', #'SeqOpt1Exp'{bool1=asn1_NOVALUE,
+ int1=15,seq1=asn1_NOVALUE}),
+ roundtrip('SeqOpt2Exp', #'SeqOpt2Exp'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SeqOpt2Exp', #'SeqOpt2Exp'{seq2=asn1_NOVALUE,
+ bool2=true,int2=15}),
+ roundtrip('SeqOpt3Exp', #'SeqOpt3Exp'{bool3=true,
+ seq3=#'SeqIn'{boolIn=true,intIn=66},
+ int3=15}),
+ roundtrip('SeqOpt3Exp', #'SeqOpt3Exp'{bool3=asn1_NOVALUE,
+ seq3=asn1_NOVALUE,int3=15}),
+ roundtrip('SeqChoOpt', #'SeqChoOpt'{int=15,cho={boolC,true}}),
+ roundtrip('SeqChoOpt', #'SeqChoOpt'{int=15,cho=asn1_NOVALUE}),
ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('SeqOptional', Type, Value).
diff --git a/lib/asn1/test/testSeqPrim.erl b/lib/asn1/test/testSeqPrim.erl
index c2451a7cd1..7f3ef86ac5 100644
--- a/lib/asn1/test/testSeqPrim.erl
+++ b/lib/asn1/test/testSeqPrim.erl
@@ -25,60 +25,21 @@
-record('Seq',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}).
-record('Empty',{}).
+-record('Big', {os1,os2,os3}).
main(_Rules) ->
-
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqPrim','Seq',#'Seq'{bool = true,
- boolCon = true,
- boolPri = true,
- boolApp = true,
- boolExpCon = true,
- boolExpPri = true,
- boolExpApp = true}),
- ?line {ok,{'Seq',true,true,true,true,true,true,true}} =
- asn1_wrapper:decode('SeqPrim','Seq',lists:flatten(Bytes11)),
-
-
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqPrim','Seq',#'Seq'{bool = false,
- boolCon = false,
- boolPri = false,
- boolApp = false,
- boolExpCon = false,
- boolExpPri = false,
- boolExpApp = false}),
- ?line {ok,{'Seq',false,false,false,false,false,false,false}} =
- asn1_wrapper:decode('SeqPrim','Seq',lists:flatten(Bytes12)),
-
-
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqPrim','Seq',#'Seq'{bool = false,
- boolCon = true,
- boolPri = false,
- boolApp = true,
- boolExpCon = false,
- boolExpPri = true,
- boolExpApp = false}),
- ?line {ok,{'Seq',false,true,false,true,false,true,false}} =
- asn1_wrapper:decode('SeqPrim','Seq',lists:flatten(Bytes13)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqPrim','Empty',#'Empty'{}),
- ?line {ok,{'Empty'}} =
- asn1_wrapper:decode('SeqPrim','Empty',lists:flatten(Bytes21)),
-
-
-
+ roundtrip('Seq', #'Seq'{bool=true,boolCon=true,boolPri=true,boolApp=true,
+ boolExpCon=true,boolExpPri=true,boolExpApp=true}),
+ roundtrip('Seq', #'Seq'{bool=false,boolCon=false,boolPri=false,
+ boolApp=false,boolExpCon=false,
+ boolExpPri=false,boolExpApp=false}),
+ roundtrip('Seq', #'Seq'{bool=false,boolCon=true,boolPri=false,boolApp=true,
+ boolExpCon=false,boolExpPri=true,boolExpApp=false}),
+ roundtrip('Empty', #'Empty'{}),
+ roundtrip('Big', #'Big'{os1=list_to_binary(lists:duplicate(120, 16#A5)),
+ os2=list_to_binary(lists:duplicate(128, 16#A7)),
+ os3=list_to_binary(lists:duplicate(17777, 16#F5))}),
ok.
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('SeqPrim', Type, Value).
diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl
index bd6c9428e2..c3d9ce33b7 100644
--- a/lib/asn1/test/testSeqSetDefaultVal.erl
+++ b/lib/asn1/test/testSeqSetDefaultVal.erl
@@ -18,10 +18,9 @@
%%
%%
-module(testSeqSetDefaultVal).
+-export([main/2]).
-include("External.hrl").
--export([main/1]).
-
-include_lib("test_server/include/test_server.hrl").
-record('SeqInts',{a = asn1_DEFAULT,
@@ -35,7 +34,9 @@
-record('SeqBS',{a = asn1_DEFAULT,
b = asn1_DEFAULT,
c = asn1_DEFAULT,
- d = asn1_DEFAULT}).
+ d = asn1_DEFAULT,
+ e = asn1_DEFAULT}).
+-record('SeqBS2',{bs = asn1_DEFAULT}).
-record('SetBS',{a = asn1_DEFAULT,
b = asn1_DEFAULT,
c = asn1_DEFAULT,
@@ -93,244 +94,470 @@
b = asn1_DEFAULT}).
-record('S4_b',{ba = asn1_DEFAULT,
bb = asn1_DEFAULT}).
+-record('SeqNamedInts',
+ {i1 = asn1_DEFAULT,
+ i2 = asn1_DEFAULT}).
+-record('S5',{s3 = asn1_DEFAULT,
+ so = asn1_DEFAULT,
+ soe = asn1_DEFAULT}).
+-record('SOI', {soi = asn1_DEFAULT}).
+
+main(ber, []) ->
+ %% Nothing to test because plain BER will only use
+ %% default values when explicitly told to do so by
+ %% asn1_DEFAULT.
+ ok;
+main(Rule, Opts) ->
+ %% DER, PER, UPER. These encodings should not encode
+ %% values that are equal to the default value.
+
+ case {Rule,Opts} of
+ {ber,[der]} ->
+ der(),
+ case 'Default':legacy_erlang_types() of
+ false -> der_new_types();
+ true -> der_legacy()
+ end;
+ {_,_} ->
+ ok
+ end,
+
+ Ts = [{#'SeqInts'{},
+ [{#'SeqInts'.c,
+ [asn1_DEFAULT,
+ three,
+ 3]}]},
+
+ {#'SeqBS'{},
+ [{#'SeqBS'.a,
+ [asn1_DEFAULT, %Always.
+ <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>],
+ [2#0110101, %Legacy only.
+ [1,0,1,0,1,1,0],
+ {1,<<16#AC>>}]},
+ {#'SeqBS'.b,
+ [asn1_DEFAULT,
+ <<16#A8:8,16#A:4>>],
+ [2#10100010101,
+ [1,0,1,0,1,0,0,0,1,0,1,0],
+ {4,<<16#A8,16#A0>>}]},
+ {#'SeqBS'.c,
+ [asn1_DEFAULT,
+ [second],
+ <<1:2>>],
+ [[0,1],
+ {6,<<0:1,1:1,0:6>>}]},
+ {#'SeqBS'.c, %Zeroes on the right
+ [asn1_DEFAULT,
+ [second],
+ <<1:2,0:17>>],
+ [[0,1,0,0,0],
+ {4,<<0:1,1:1,0:6>>}]},
+ {#'SeqBS'.d,
+ [asn1_DEFAULT,
+ <<2#1001:4>>],
+ [2#1001,
+ [1,0,0,1],
+ {4,<<2#1001:4,0:4>>}]},
+ {#'SeqBS'.e,
+ [asn1_DEFAULT,
+ <<2#01011010:8>>],
+ [[0,1,0,1,1,0,1,0],
+ {0,<<2#01011010:8>>}]},
+ %% Not EQUAL to DEFAULT.
+ {#'SeqBS'.b,
+ [<<6:3>>],
+ [[1,1,0], %Not equal to DEFAULT
+ {5,<<6:3,0:5>>}]}
+ ]},
+
+ {#'SeqOS'{},
+ [{#'SeqOS'.a,
+ [asn1_DEFAULT,
+ <<172>>]}]},
+
+ {#'SeqOI'{},
+ [{#'SeqOI'.a,
+ [asn1_DEFAULT,
+ {1,2,14,15}]},
+ {#'SeqOI'.b,
+ [asn1_DEFAULT,
+ %% {iso,'member-body',250,3,4},
+ {1,2,250,3,4}]},
+ {#'SeqOI'.c,
+ [asn1_DEFAULT,
+ %% {iso,standard,8571,2,250,4},
+ {1,0,8571,2,250,4}]}]}
+ ],
+ R0 = [[consistency(Rec, PosVs) || PosVs <- Fs] || {Rec,Fs} <- Ts],
+ case lists:flatten(R0) of
+ [] ->
+ ok;
+ [_|_]=R ->
+ io:format("~p\n", [R]),
+ ?t:fail()
+ end.
+
+legacy_filter({_,_}=Keep) ->
+ Keep;
+legacy_filter({Rec,Standard,Legacy}) ->
+ case 'Default':legacy_erlang_types() of
+ false ->
+ {Rec,Standard};
+ true ->
+ {Rec,Standard++Legacy}
+ end.
+
+consistency(Rec0, PosVs) ->
+ {Pos,[V|Vs]=AllVs} = legacy_filter(PosVs),
+ T = element(1, Rec0),
+ io:format("~p: ~p\n", [T,AllVs]),
+ Rec = setelement(Pos, Rec0, V),
+ {ok,Enc} = 'Default':encode(T, Rec),
+ {ok,_SmokeTest} = 'Default':decode(T, Enc),
+ consistency_1(Vs, Rec0, Pos, Enc).
+
+consistency_1([V|Vs], Rec0, Pos, Enc) ->
+ Rec = setelement(Pos, Rec0, V),
+ case 'Default':encode(element(1, Rec), Rec) of
+ {ok,Enc} ->
+ consistency_1(Vs, Rec0, Pos, Enc);
+ {ok,WrongEnc} ->
+ [{Rec,{wrong,WrongEnc},{should_be,Enc}}|
+ consistency_1(Vs, Rec0, Pos, Enc)]
+ end;
+consistency_1([], _, _, _) -> [].
+
+der() ->
+ io:put_chars("Performing DER-specific tests..."),
+ roundtrip(<<48,0>>,
+ 'SeqInts',
+ #'SeqInts'{a=asn1_DEFAULT,b=asn1_DEFAULT,
+ c=asn1_DEFAULT,d=asn1_DEFAULT},
+ #'SeqInts'{a=1,b=-1,c=3,d=1}),
+ roundtrip(<<48,0>>,
+ 'SeqInts',
+ #'SeqInts'{a=1,b=-1,c=three,d=1},
+ #'SeqInts'{a=1,b=-1,c=3,d=1}),
+
+ roundtrip(<<49,0>>,
+ 'SetInts',
+ #'SetInts'{a=asn1_DEFAULT,b=asn1_DEFAULT,
+ c=asn1_DEFAULT,d=asn1_DEFAULT},
+ #'SetInts'{a=1,b=-1,c=3,d=1}),
+ roundtrip(<<49,0>>,
+ 'SetInts',
+ #'SetInts'{a=1,b=-1,c=three,d=1},
+ #'SetInts'{a=1,b=-1,c=3,d=1}),
+
+ roundtrip(<<48,0>>,
+ 'SeqOI',
+ #'SeqOI'{a={1,2,14,15},
+ b={iso,'member-body',250,3,4},
+ c={iso,standard,8571,2,250,4}},
+ #'SeqOI'{a={1,2,14,15},
+ b={1,2,250,3,4},
+ c={1,0,8571,2,250,4}}),
+
+ roundtrip(<<49,0>>,
+ 'SetOI',
+ #'SetOI'{a={1,2,14,15},
+ b={iso,'member-body',250,3,4},
+ c={iso,standard,8571,2,250,4}},
+ #'SetOI'{a={1,2,14,15},
+ b={1,2,250,3,4},
+ c={1,0,8571,2,250,4}}),
+
+ roundtrip(<<48,0>>, 'SeqEnum', #'SeqEnum'{a=b4,b=b2}),
+ roundtrip(<<49,0>>, 'SetEnum', #'SetEnum'{a=b4,b=b2}),
+
+ roundtrip(<<48,0>>,
+ 'SeqIntBool',
+ #'SeqIntBool'{a=#'SeqIntBool_a'{aa=12,ab=13},
+ b=#'S2'{a=14,b=true},
+ c=#'S2'{a=15,b=false}}),
+ roundtrip(<<48,0>>,
+ 'SeqIntBool',
+ #'SeqIntBool'{a=asn1_DEFAULT,b=asn1_DEFAULT,c=asn1_DEFAULT},
+ #'SeqIntBool'{a=#'SeqIntBool_a'{aa=12,ab=13},
+ b=#'S2'{a=14,b=true},
+ c=#'S2'{a=15,b=false}}),
+
+ roundtrip(<<49,0>>,
+ 'SetIntBool',
+ #'SetIntBool'{a=#'SetIntBool_a'{aa=12,ab=13},
+ b=#'S2'{a=14,b=true},
+ c=#'S2'{a=15,b=false}}),
+ roundtrip(<<49,0>>,
+ 'SetIntBool',
+ #'SetIntBool'{a=asn1_DEFAULT,b=asn1_DEFAULT,c=asn1_DEFAULT},
+ #'SetIntBool'{a=#'SetIntBool_a'{aa=12,ab=13},
+ b=#'S2'{a=14,b=true},
+ c=#'S2'{a=15,b=false}}),
+
+ roundtrip(<<48,0>>,
+ 'SeqStrings',
+ #'SeqStrings'{a="123456789",b1="abcdef",
+ b2={0,13},
+ b3={"First line",{0,13},"Second line"},
+ c="Printable string",
+ d={0,0,1,14}},
+ #'SeqStrings'{a="123456789",b1="abcdef",
+ b2=[0,13],
+ b3=["First line",[0,13],"Second line"],
+ c="Printable string",
+ d=[0,0,1,14]}),
+
+ roundtrip(<<49,0>>,
+ 'SetStrings',
+ #'SetStrings'{a="123456789",b1="abcdef",
+ b2={0,13},
+ b3={"First line",{0,13},"Second line"},
+ c="Printable string",
+ d={0,0,1,14}},
+ #'SetStrings'{a="123456789",b1="abcdef",
+ b2=[0,13],
+ b3=["First line",[0,13],"Second line"],
+ c="Printable string",
+ d=[0,0,1,14]}),
+
+ roundtrip(<<48,0>>,
+ 'S1',
+ #'S1'{a=#'S1_a'{aa=1,ab=#'S2'{a=2,b=true}},
+ b=#'S4'{a=#'S2'{a=2,b=true},b=#'S4_b'{ba=true,bb=5}}}),
+
+ roundtrip(<<48,3,129,1,255>>, 'S2', #'S2'{a=1,b=true}),
+
+ roundtrip(<<48,0>>,
+ 'S3',
+ #'S3'{a="\v\f\r",
+ b=[{a,11},{b,true},{c,13}],
+ c=[1,2,3,4],
+ d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}),
+ roundtrip(<<48,0>>,
+ 'S3',
+ #'S3'{a=[11,13,12],
+ b=[{b,true},{a,11},{c,13}],
+ c=[3,4,1,2],
+ d=[#'S2'{a=30,b=false},#'S2'{a=20,b=true}]},
+ #'S3'{a=[11,12,13],
+ b=[{a,11},{b,true},{c,13}],
+ c=[1,2,3,4],
+ d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}),
+ roundtrip(<<48,0>>,
+ 'S3',
+ #'S3'{a=asn1_DEFAULT,b=asn1_DEFAULT,
+ c=asn1_DEFAULT,d=asn1_DEFAULT},
+ #'S3'{a=[11,12,13],
+ b=[{a,11},{b,true},{c,13}],
+ c=[1,2,3,4],
+ d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}),
+
+ roundtrip(<<49,0>>,
+ 'S3set',
+ #'S3set'{a=[{c,#'S2'{a=3,b=true}},{b,17},{a,false}],
+ b=[1,2,3,4]}),
+ roundtrip(<<49,0>>,
+ 'S3set',
+ #'S3set'{a=[{b,17},{c,#'S2'{a=3,b=true}},{a,false}],
+ b=[1,3,4,2]},
+ #'S3set'{a=[{c,#'S2'{a=3,b=true}},{b,17},{a,false}],
+ b=[1,2,3,4]}),
+ roundtrip(<<49,0>>,
+ 'S3set',
+ #'S3set'{a=asn1_DEFAULT,b=asn1_DEFAULT},
+ #'S3set'{a=[{c,#'S2'{a=3,b=true}},{b,17},{a,false}],
+ b=[1,2,3,4]}),
+
+ roundtrip(<<48,0>>,
+ 'S4',
+ #'S4'{a=#'S2'{a=1,b=asn1_NOVALUE},b=#'S4_b'{ba=true,bb=0}},
+ #'S4'{a=#'S2'{a=1,b=asn1_NOVALUE},b=#'S4_b'{ba=true,bb=0}}),
+
+ roundtrip(<<48,0>>,
+ 'SeqBS',
+ #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>,
+ e = <<2#01011010:8>>}),
+ roundtrip(<<49,0>>,
+ 'SetBS',
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>}),
+
+ %% None of the default values are used.
+ roundtrip(<<48,19,128,2,7,128,129,2,5,64,130,2,5,32,131,1,0,132,2,5,224>>,
+ 'SeqBS',
+ #'SeqBS'{a = <<1:1>>,
+ b = <<2:3>>,
+ c = [third],
+ d = <<>>,
+ e = <<7:3>>}),
+ roundtrip(<<49,3,131,1,0>>,
+ 'SetBS',
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<>>}),
+
+ %% SeqNamedInts
+ roundtrip(<<48,0>>,
+ 'SeqNamedInts',
+ #'SeqNamedInts'{i1=15,i2=31}),
+ roundtrip(<<48,0>>,
+ 'SeqNamedInts',
+ #'SeqNamedInts'{},
+ #'SeqNamedInts'{i1=15,i2=31}),
+ roundtrip(<<48,0>>,
+ 'SeqNamedInts',
+ #'SeqNamedInts'{i2=last},
+ #'SeqNamedInts'{i1=15,i2=31}),
+ roundtrip(<<48,3,128,1,0>>,
+ 'SeqNamedInts',
+ #'SeqNamedInts'{i1=first,i2=31},
+ #'SeqNamedInts'{i1=first,i2=31}),
+
+ %% S5
+ roundtrip(<<48,0>>,
+ 'S5',
+ #'S5'{s3=#'S3'{a=[11,12,13],
+ b=[{a,11},{b,true},{c,13}],
+ c=[1,2,3,4],
+ d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]},
+ so=[{0,1,999},{0,1,555}],
+ soe=[]}),
+ roundtrip(<<48,0>>,
+ 'S5',
+ #'S5'{},
+ #'S5'{s3=#'S3'{a=[11,12,13],
+ b=[{a,11},{b,true},{c,13}],
+ c=[1,2,3,4],
+ d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]},
+ so=[{0,1,999},{0,1,555}],
+ soe=[]}),
+
+ %% SOI
+ roundtrip(<<48,0>>,
+ 'SOI',
+ #'SOI'{},
+ #'SOI'{soi=[{1,2,250,9,55},{1,2,250,3,4}]}),
+
+ %% SeqBS2
+ roundtrip(<<48,0>>,
+ 'SeqBS2',
+ #'SeqBS2'{bs= <<16#5:3>>}),
+ roundtrip(<<48,0>>,
+ 'SeqBS2',
+ #'SeqBS2'{bs= <<16#5:3,0:4>>},
+ #'SeqBS2'{bs= <<16#5:3>>}),
+
+ ok.
+
+der_new_types() ->
+ io:put_chars("Performing DER-specific tests with new types..."),
+
+ roundtrip(<<48,0>>, 'SeqOS',
+ #'SeqOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}),
+
+ roundtrip(<<49,0>>, 'SetOS',
+ #'SetOS'{a = <<172>>,b = <<16#A8,16#A0>>,c='NULL'}),
+ ok.
+
+der_legacy() ->
+ io:put_chars("Performing DER-specific tests with legacy types..."),
+
+ roundtrip(<<48,0>>, 'SeqOS',
+ #'SeqOS'{a=[172],b=[16#A8,16#A0],c='NULL'}),
+ roundtrip(<<49,0>>, 'SetOS',
+ #'SetOS'{a=[172],b=[16#A8,16#A0],c='NULL'}),
+
+ roundtrip(<<48,0>>,
+ 'SeqBS',
+ #'SeqBS'{a=2#0110101,
+ b=2#010100010101,
+ c=[second],
+ d=[1,0,0,1]},
+ #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>,
+ e = <<2#01011010:8>>}),
+ roundtrip(<<48,0>>,
+ 'SeqBS',
+ #'SeqBS'{a=[1,0,1,0,1,1,0],
+ b=[1,0,1,0,1,0,0,0,1,0,1,0],
+ c={5,<<64>>},
+ d=2#1001},
+ #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>,
+ e = <<2#01011010:8>>}),
+ roundtrip(<<48,3,131,1,0>>,
+ 'SeqBS',
+ #'SeqBS'{a=[1,0,1,0,1,1,0],
+ b=[1,0,1,0,1,0,0,0,1,0,1,0],
+ c={5,<<64>>},
+ d=0},
+ #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<>>,
+ e = <<2#01011010:8>>}),
+ roundtrip(<<48,3,131,1,0>>,
+ 'SeqBS',
+ #'SeqBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>,
+ b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>,
+ c = <<2:3>>,
+ d=0,
+ e = <<16#5A:8>>},
+ #'SeqBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<>>,
+ e = <<2#01011010:8>>}),
+
+ %% None of the default values are used.
+ roundtrip(<<48,19,128,2,7,128,129,2,5,64,130,2,5,32,131,1,0,132,2,5,224>>,
+ 'SeqBS',
+ #'SeqBS'{a = <<1:1>>,
+ b = {5,<<64>>},
+ c = [third],
+ d = 0,
+ e = <<7:3>>},
+ #'SeqBS'{a = <<1:1>>,
+ b = <<2:3>>,
+ c = [third],
+ d = <<>>,
+ e = <<7:3>>}),
+ roundtrip(<<49,0>>,
+ 'SetBS',
+ #'SetBS'{a=2#0110101,
+ b=2#010100010101,
+ c=[second],
+ d=[1,0,0,1]},
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>}),
+ roundtrip(<<49,0>>,
+ 'SetBS',
+ #'SetBS'{a=[1,0,1,0,1,1,0],
+ b=[1,0,1,0,1,0,0,0,1,0,1,0],
+ c={5,<<64>>},
+ d=9},
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<2#1001:4>>}),
+ roundtrip(<<49,3,131,1,0>>,
+ 'SetBS',
+ #'SetBS'{a=[1,0,1,0,1,1,0],
+ b=[1,0,1,0,1,0,0,0,1,0,1,0],
+ c={5,<<64>>},
+ d=0},
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<>>}),
+ roundtrip(<<49,3,131,1,0>>,
+ 'SetBS',
+ #'SetBS'{a = <<1:1,0:1,1:1,0:1,1:1,1:1,0:1>>,
+ b = <<1:1,0:1,1:1,0:1,1:1,0:1,0:1,0:1,1:1,0:1,1:1,0:1>>,
+ c = <<2:3>>,
+ d=0},
+ #'SetBS'{a = <<2#1010110:7>>, b = <<16#A8A:12>>,
+ c=[second], d = <<>>}),
+
+ ok.
+
+roundtrip(Encoded, Type, Value) ->
+ roundtrip(Encoded, Type, Value, Value).
-main(_Rules) ->
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqInts',#'SeqInts'{}),
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqInts',#'SeqInts'{a=1,b=-1,c=three,
- d=1}),
- ?line {ok,{'SeqInts',1,-1,3,1}} =
- asn1_wrapper:decode('Default','SeqInts',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetInts',#'SetInts'{}),
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetInts',#'SetInts'{a=1,b=-1,c=three,
- d=1}),
- ?line {ok,{'SetInts',1,-1,3,1}} =
- asn1_wrapper:decode('Default','SetInts',[49,0]),
-
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqBS',
- #'SeqBS'{a=2#1010110,
- b=16#A8A,
- c=[second],
- d=[1,0,0,1]}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqBS',
- #'SeqBS'{a=[1,0,1,0,1,1,0],
- b=[1,0,1,0,1,0,0,0,1,0,1,0],
- c={5,<<64>>},
- d=9}),
-
- ?line {ok,[48,3,131,1,0]} =
- asn1_wrapper:encode('Default','SeqBS',
- #'SeqBS'{a=[1,0,1,0,1,1,0],
- b=[1,0,1,0,1,0,0,0,1,0,1,0],
- c={5,<<64>>},
- d=0}),
-
- {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]}} =
- asn1_wrapper:decode('Default','SeqBS',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetBS',
- #'SetBS'{a=2#1010110,
- b=16#A8A,
- c=[second],
- d=[1,0,0,1]}),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetBS',
- #'SetBS'{a=[1,0,1,0,1,1,0],
- b=[1,0,1,0,1,0,0,0,1,0,1,0],
- c={5,<<64>>},
- d=9}),
-
- ?line {ok,[49,3,131,1,0]} =
- asn1_wrapper:encode('Default','SetBS',
- #'SetBS'{a=[1,0,1,0,1,1,0],
- b=[1,0,1,0,1,0,0,0,1,0,1,0],
- c={5,<<64>>},
- d=0}),
-
- {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]}} =
- asn1_wrapper:decode('Default','SetBS',[49,0]),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqOS',
- #'SeqOS'{a=[172],
- b=[16#A8,16#A0],
- c='NULL'}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqOS',
- #'SeqOS'{a=2#10101100,
- b=16#A8A0,
- c='NULL'}),
-
- ?line {ok,{'SeqOS',[172],[16#A8,16#A0],'NULL'}} =
- asn1_wrapper:decode('Default','SeqOS',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetOS',
- #'SetOS'{a=[172],
- b=[16#A8,16#A0],
- c='NULL'}),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetOS',
- #'SetOS'{a=2#10101100,
- b=16#A8A0,
- c='NULL'}),
-
- ?line {ok,{'SetOS',[172],[16#A8,16#A0],'NULL'}} =
- asn1_wrapper:decode('Default','SetOS',[49,0]),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqOI',
- #'SeqOI'{a={1,2,14,15},
- b={iso,'member-body',250,3,4},
- c={iso,standard,8571,2,250,4}}),
-
- ?line {ok,{'SeqOI',{1,2,14,15},{1,2,250,3,4},{1,0,8571,2,250,4}}} =
- asn1_wrapper:decode('Default','SeqOI',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetOI',
- #'SetOI'{a={1,2,14,15},
- b={iso,'member-body',250,3,4},
- c={iso,standard,8571,2,250,4}}),
-
- ?line {ok,{'SetOI',{1,2,14,15},{1,2,250,3,4},{1,0,8571,2,250,4}}} =
- asn1_wrapper:decode('Default','SetOI',[49,0]),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqEnum',#'SeqEnum'{a=b4,b=b2}),
-
- ?line {ok,{'SeqEnum',b4,b2}} =
- asn1_wrapper:decode('Default','SeqEnum',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetEnum',#'SetEnum'{a=b4,b=b2}),
-
- ?line {ok,{'SetEnum',b4,b2}} =
- asn1_wrapper:decode('Default','SetEnum',[49,0]),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqIntBool',
- #'SeqIntBool'{a=#'SeqIntBool_a'{aa=12,ab=13},
- b=#'S2'{a=14,b=true},
- c=#'S2'{a=15,b=false}}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqIntBool',
- #'SeqIntBool'{}),
-
- ?line {ok,{'SeqIntBool',{'SeqIntBool_a',12,13},
- {'S2',14,true},{'S2',15,false}}} =
- asn1_wrapper:decode('Default','SeqIntBool',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetIntBool',
- #'SetIntBool'{a=#'SetIntBool_a'{aa=12,ab=13},
- b=#'S2'{a=14,b=true},
- c=#'S2'{a=15,b=false}}),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetIntBool',
- #'SetIntBool'{}),
-
- ?line {ok,{'SetIntBool',{'SetIntBool_a',12,13},
- {'S2',14,true},{'S2',15,false}}} =
- asn1_wrapper:decode('Default','SetIntBool',[49,0]),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','SeqStrings',
- #'SeqStrings'{a="123456789",
- b1="abcdef",
- b2={0,13},
- b3={"First line",{0,13},"Second line"},
- c="Printable string",
- d={0,0,1,14}}),
-
- ?line {ok,{'SeqStrings',"123456789","abcdef",[0,13],
- ["First line",[0,13],"Second line"],"Printable string",
- [0,0,1,14]}} =
- asn1_wrapper:decode('Default','SeqStrings',[48,0]),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','SetStrings',
- #'SetStrings'{a="123456789",
- b1="abcdef",
- b2={0,13},
- b3={"First line",{0,13},"Second line"},
- c="Printable string",
- d={0,0,1,14}}),
-
- ?line {ok,{'SetStrings',"123456789","abcdef",[0,13],
- ["First line",[0,13],"Second line"],"Printable string",
- [0,0,1,14]}} =
- asn1_wrapper:decode('Default','SetStrings',[49,0]),
-
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','S1',
- #'S1'{a=#'S1_a'{aa=1,
- ab=#'S2'{a=2,b=true}},
- b=#'S4'{a=#'S2'{a=2,b=true},
- b=#'S4_b'{ba=true,
- bb=5}}}),
-
- ?line {ok,{'S1',{'S1_a',1,{'S2',2,true}},
- {'S4',{'S2',2,true},{'S4_b',true,5}}}} =
- asn1_wrapper:decode('Default','S1',[48,0]),
-
- ?line {ok,[48,3,129,1,255]} =
- asn1_wrapper:encode('Default','S2',
- #'S2'{a=1,b=true}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','S3',
- #'S3'{a=[11,12,13],
- b=[{a,11},{b,true},{c,13}],
- c=[1,2,3,4],
- d=[#'S2'{a=20,b=true},#'S2'{a=30,b=false}]}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','S3',
- #'S3'{a=[11,13,12],
- b=[{b,true},{a,11},{c,13}],
- c=[3,4,1,2],
- d=[#'S2'{a=30,b=false},#'S2'{a=20,b=true}]}),
-
- ?line {ok,[48,0]} = asn1_wrapper:encode('Default','S3',#'S3'{}),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','S3set',
- #'S3set'{a=[{c,#'S2'{a=3,b=true}},
- {b,17},{a,false}],
- b=[1,2,3,4]}),
-
- ?line {ok,[49,0]} =
- asn1_wrapper:encode('Default','S3set',
- #'S3set'{a=[{b,17},{c,#'S2'{a=3,b=true}},
- {a,false}],
- b=[1,3,4,2]}),
-
- ?line {ok,[49,0]} = asn1_wrapper:encode('Default','S3set',#'S3set'{}),
-
- ?line {ok,[48,0]} =
- asn1_wrapper:encode('Default','S4',#'S4'{a={'S2',1,asn1_NOVALUE},
- b=#'S4_b'{ba=true,bb=0}}),
+roundtrip(Encoded, Type, Value, ExpectedValue) ->
+ Encoded = asn1_test_lib:roundtrip_enc('Default', Type,
+ Value, ExpectedValue),
ok.
diff --git a/lib/asn1/test/testSeqSetIndefinite.erl b/lib/asn1/test/testSeqSetIndefinite.erl
new file mode 100644
index 0000000000..6becf84e77
--- /dev/null
+++ b/lib/asn1/test/testSeqSetIndefinite.erl
@@ -0,0 +1,52 @@
+%%
+%% %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(testSeqSetIndefinite).
+-export([main/0]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+main() ->
+ seq_indefinite(),
+ set_indefinite().
+
+seq_indefinite() ->
+ %% normal encoding
+ B = <<48,20,1,1,255,48,9,1,1,255,2,4,251,35,238,194,2,4,251,55,236,161>>,
+ %% indefinite length encoding
+ Bi = <<48,22,1,1,255,48,128,1,1,255,2,4,251,35,238,194,0,0,2,4,251,55,236,161>>,
+ %% the value which is encoded
+ V = {'SeqS3',true,{'SeqS3_seqS3',true,-81531198},-80221023},
+ {ok,V} = 'SeqSetIndefinite':decode('SeqS3', B),
+ {ok,V} = 'SeqSetIndefinite':decode('SeqS3', Bi),
+
+ ok.
+
+set_indefinite() ->
+ %% normal encoding
+ B = <<49,20,1,1,255,49,9,1,1,255,2,4,251,35,238,194,2,4,251,55,236,161>>,
+ %% indefinite length encoding
+ Bi = <<49,22,1,1,255,49,128,1,1,255,2,4,251,35,238,194,0,0,2,4,251,55,236,161>>,
+
+ %% the value which is encoded
+ V = {'SetS3',true,{'SetS3_setS3',true,-81531198},-80221023},
+ {ok,V} = 'SeqSetIndefinite':decode('SetS3', B),
+ {ok,V} = 'SeqSetIndefinite':decode('SetS3', Bi),
+
+ ok.
diff --git a/lib/asn1/test/testSeqTag.erl b/lib/asn1/test/testSeqTag.erl
index 9fdaae35dd..6bacca6808 100644
--- a/lib/asn1/test/testSeqTag.erl
+++ b/lib/asn1/test/testSeqTag.erl
@@ -35,69 +35,25 @@
-record('Exp',{os, bool}).
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqTag','SeqTag',#'SeqTag'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTag',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTag',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqTag','SeqTagImp',#'SeqTagImp'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTagImp',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTagImp',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqTag','SeqTagExp',#'SeqTagExp'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTagExp',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTagExp',lists:flatten(Bytes13)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqTag','SeqTagX',
- #'SeqTagX'{xnt = #'XSeqNT'{bool = true, os = "kalle"},
- ximp = #'XSeqImp'{bool = true, os = "kalle"},
- xexp = #'XSeqExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTagX',{'XSeqNT',"kalle",true},
- {'XSeqImp',"kalle",true},
- {'XSeqExp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTagX',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqTag','SeqTagImpX',
- #'SeqTagImpX'{xnt = #'XSeqNT'{bool = true, os = "kalle"},
- ximp = #'XSeqImp'{bool = true, os = "kalle"},
- xexp = #'XSeqExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTagImpX',{'XSeqNT',"kalle",true},
- {'XSeqImp',"kalle",true},
- {'XSeqExp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTagImpX',lists:flatten(Bytes22)),
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqTag','SeqTagExpX',
- #'SeqTagExpX'{xnt = #'XSeqNT'{bool = true, os = "kalle"},
- ximp = #'XSeqImp'{bool = true, os = "kalle"},
- xexp = #'XSeqExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SeqTagExpX',{'XSeqNT',"kalle",true},
- {'XSeqImp',"kalle",true},
- {'XSeqExp',"kalle",true}}} =
- asn1_wrapper:decode('SeqTag','SeqTagExpX',lists:flatten(Bytes23)),
-
-
-
-
-
+ roundtrip('SeqTag', #'SeqTag'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SeqTagImp', #'SeqTagImp'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SeqTagExp', #'SeqTagExp'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SeqTagX', #'SeqTagX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSeqImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SeqTagImpX', #'SeqTagImpX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSeqImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SeqTagExpX', #'SeqTagExpX'{xnt=#'XSeqNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSeqImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSeqExp'{os = <<"kalle">>,bool=true}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTag', T, V).
diff --git a/lib/asn1/test/testSeqTypeRefCho.erl b/lib/asn1/test/testSeqTypeRefCho.erl
index 4b9eac7034..1a921c6f38 100644
--- a/lib/asn1/test/testSeqTypeRefCho.erl
+++ b/lib/asn1/test/testSeqTypeRefCho.erl
@@ -27,17 +27,12 @@
-record('SeqTRcho',{seqCho, seqChoE, 'seqCho-E', 'seqChoE-E'}).
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqTypeRefCho','SeqTRcho',
- #'SeqTRcho'{'seqCho' = {choOs,"A string 1"},
- 'seqChoE' = {choOs,"A string 3"},
- 'seqCho-E' = {choOs,"A string 7"},
- 'seqChoE-E' = {choOs,"A string 9"}}),
- ?line {ok,{'SeqTRcho',{choOs,"A string 1"},{choOs,"A string 3"},{choOs,"A string 7"},{choOs,"A string 9"}}} =
- asn1_wrapper:decode('SeqTypeRefCho','SeqTRcho',lists:flatten(Bytes11)),
-
-
-
+ roundtrip('SeqTRcho',
+ #'SeqTRcho'{'seqCho' = {choOs,<<"A string 1">>},
+ 'seqChoE' = {choOs,<<"A string 3">>},
+ 'seqCho-E' = {choOs,<<"A string 7">>},
+ 'seqChoE-E' = {choOs,<<"A string 9">>}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTypeRefCho', T, V).
diff --git a/lib/asn1/test/testSeqTypeRefPrim.erl b/lib/asn1/test/testSeqTypeRefPrim.erl
index 7d4c2acc0e..d66d1ebcfe 100644
--- a/lib/asn1/test/testSeqTypeRefPrim.erl
+++ b/lib/asn1/test/testSeqTypeRefPrim.erl
@@ -18,40 +18,24 @@
%%
%%
-module(testSeqTypeRefPrim).
-
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-record('SeqTR',{octStr, octStrI, octStrE, 'octStr-I', 'octStrI-I', 'octStrE-I', 'octStr-E', 'octStrI-E', 'octStrE-E'}).
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "SeqTypeRefPrim",[Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqTypeRefPrim','SeqTR',#'SeqTR'{'octStr' = "A string 1",
- 'octStrI' = "A string 2",
- 'octStrE' = "A string 3",
- 'octStr-I' = "A string 4",
- 'octStrI-I' = "A string 5",
- 'octStrE-I' = "A string 6",
- 'octStr-E' = "A string 7",
- 'octStrI-E' = "A string 8",
- 'octStrE-E' = "A string 9"}) ,
- ?line {ok,{'SeqTR',"A string 1","A string 2","A string 3","A string 4","A string 5","A string 6","A string 7","A string 8","A string 9"}} =
- asn1_wrapper:decode('SeqTypeRefPrim','SeqTR',lists:flatten(Bytes11)),
-
-
-
+ roundtrip('SeqTR',
+ #'SeqTR'{'octStr' = <<"A string 1">>,
+ 'octStrI' = <<"A string 2">>,
+ 'octStrE' = <<"A string 3">>,
+ 'octStr-I' = <<"A string 4">>,
+ 'octStrI-I' = <<"A string 5">>,
+ 'octStrE-I' = <<"A string 6">>,
+ 'octStr-E' = <<"A string 7">>,
+ 'octStrI-E' = <<"A string 8">>,
+ 'octStrE-E' = <<"A string 9">>}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTypeRefPrim', T, V).
diff --git a/lib/asn1/test/testSeqTypeRefSeq.erl b/lib/asn1/test/testSeqTypeRefSeq.erl
index 57ec6c19b1..3288511f0a 100644
--- a/lib/asn1/test/testSeqTypeRefSeq.erl
+++ b/lib/asn1/test/testSeqTypeRefSeq.erl
@@ -44,133 +44,43 @@
-record('SeqSeqExp',{seqInt, seqOs}).
-
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SeqTypeRefSeq','Seq1',#'Seq1'{bool1 = true,
- int1 = 15,
- seq1 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'Seq1',true,15,{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqTypeRefSeq','Seq1',lists:flatten(Bytes11)),
-
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SeqTypeRefSeq','Seq2',#'Seq2'{seq2 = #'SeqIn'{boolIn = true,
- intIn = 66},
- bool2 = true,
- int2 = 15}),
- ?line {ok,{'Seq2',{'SeqIn',true,66},true,15}} =
- asn1_wrapper:decode('SeqTypeRefSeq','Seq2',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SeqTypeRefSeq','Seq3',#'Seq3'{bool3 = true,
- seq3 = #'SeqIn'{boolIn = true,
- intIn = 66},
- int3 = 15}),
- ?line {ok,{'Seq3',true,{'SeqIn',true,66},15}} =
- asn1_wrapper:decode('SeqTypeRefSeq','Seq3',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('SeqTypeRefSeq','Seq4',#'Seq4'{seq41 = #'SeqIn'{boolIn = true,
- intIn = 66},
- seq42 = #'SeqIn'{boolIn = true,
- intIn = 66},
- seq43 = #'SeqIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'Seq4',{'SeqIn',true,66},{'SeqIn',true,66},{'SeqIn',true,66}}} =
- asn1_wrapper:decode('SeqTypeRefSeq','Seq4',lists:flatten(Bytes14)),
-
-
-
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SeqTypeRefSeq','SeqS1',#'SeqS1'{boolS1 = true,
- intS1 = 15,
- seqS1 = #'SeqS1_seqS1'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SeqS1',true,15,{'SeqS1_seqS1',true,66}}} =
- asn1_wrapper:decode('SeqTypeRefSeq','SeqS1',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SeqTypeRefSeq','SeqS2',#'SeqS2'{seqS2 = #'SeqS2_seqS2'{boolIn = true,
- intIn = 66},
- boolS2 = true,
- intS2 = 15}),
- ?line {ok,{'SeqS2',{'SeqS2_seqS2',true,66},true,15}} =
- asn1_wrapper:decode('SeqTypeRefSeq','SeqS2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SeqTypeRefSeq','SeqS3',#'SeqS3'{boolS3 = true,
- seqS3 = #'SeqS3_seqS3'{boolIn = true,
- intIn = 66},
- intS3 = 15}),
- ?line {ok,{'SeqS3',true,{'SeqS3_seqS3',true,66},15}} =
- asn1_wrapper:decode('SeqTypeRefSeq','SeqS3',lists:flatten(Bytes23)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SeqTypeRefSeq','SeqSTag',#'SeqSTag'{seqS1 = #'SeqSTag_seqS1'{b1 = true,
- i1 = 11},
- seqS2 = #'SeqSTag_seqS2'{b2 = true,
- i2 = 22},
- seqS3 = #'SeqSTag_seqS3'{b3 = true,
- i3 = 33}}),
- ?line {ok,{'SeqSTag',{'SeqSTag_seqS1',true,11},
- {'SeqSTag_seqS2',true,22},
- {'SeqSTag_seqS3',true,33}}} =
- asn1_wrapper:decode('SeqTypeRefSeq','SeqSTag',lists:flatten(Bytes31)),
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqTypeRefSeq','SeqTRseq',
- #'SeqTRseq'{'seqSeq' = #'SeqSeq'{seqOs = "A1",
- seqInt = 2},
- 'seqSeqI' = #'SeqSeq'{seqOs = "A2",
- seqInt = 2},
- 'seqSeqE' = #'SeqSeq'{seqOs = "A3",
- seqInt = 2},
- 'seqSeq-I' = #'SeqSeqImp'{seqOs = "A4",
- seqInt = 2},
- 'seqSeqI-I' = #'SeqSeqImp'{seqOs = "A5",
- seqInt = 2},
- 'seqSeqE-I' = #'SeqSeqImp'{seqOs = "A6",
- seqInt = 2},
- 'seqSeq-E' = #'SeqSeqExp'{seqOs = "A7",
- seqInt = 2},
- 'seqSeqI-E' = #'SeqSeqExp'{seqOs = "A8",
- seqInt = 2},
- 'seqSeqE-E' = #'SeqSeqExp'{seqOs = "A9",
- seqInt = 2}}),
- ?line {ok,{'SeqTRseq',{'SeqSeq',2,"A1"},
- {'SeqSeq',2,"A2"},
- {'SeqSeq',2,"A3"},
- {'SeqSeqImp',2,"A4"},
- {'SeqSeqImp',2,"A5"},
- {'SeqSeqImp',2,"A6"},
- {'SeqSeqExp',2,"A7"},
- {'SeqSeqExp',2,"A8"},
- {'SeqSeqExp',2,"A9"}}} =
- asn1_wrapper:decode('SeqTypeRefSeq','SeqTRseq',lists:flatten(Bytes41)),
-
+ roundtrip('Seq1',
+ #'Seq1'{bool1=true,int1=15,
+ seq1=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('Seq2',
+ #'Seq2'{seq2=#'SeqIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('Seq3',
+ #'Seq3'{bool3=true,seq3=#'SeqIn'{boolIn=true,intIn=66},int3=15}),
+ roundtrip('Seq4',
+ #'Seq4'{seq41=#'SeqIn'{boolIn=true,intIn=66},
+ seq42=#'SeqIn'{boolIn=true,intIn=66},
+ seq43=#'SeqIn'{boolIn=true,intIn=66}}),
+ roundtrip('SeqS1',
+ #'SeqS1'{boolS1=true,intS1=15,
+ seqS1=#'SeqS1_seqS1'{boolIn=true,intIn=66}}),
+ roundtrip('SeqS2',
+ #'SeqS2'{seqS2=#'SeqS2_seqS2'{boolIn=true,intIn=66},
+ boolS2=true,intS2=15}),
+ roundtrip('SeqS3',
+ #'SeqS3'{boolS3=true,seqS3=#'SeqS3_seqS3'{boolIn=true,intIn=66},
+ intS3=15}),
+ roundtrip('SeqSTag',
+ #'SeqSTag'{seqS1=#'SeqSTag_seqS1'{b1=true,i1=11},
+ seqS2=#'SeqSTag_seqS2'{b2=true,i2=22},
+ seqS3=#'SeqSTag_seqS3'{b3=true,i3=33}}),
+ roundtrip('SeqTRseq',
+ #'SeqTRseq'{seqSeq=#'SeqSeq'{seqInt=2,seqOs = <<"A1">>},
+ seqSeqI=#'SeqSeq'{seqInt=2,seqOs = <<"A2">>},
+ seqSeqE=#'SeqSeq'{seqInt=2,seqOs = <<"A3">>},
+ 'seqSeq-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A4">>},
+ 'seqSeqI-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A5">>},
+ 'seqSeqE-I'=#'SeqSeqImp'{seqInt=2,seqOs = <<"A6">>},
+ 'seqSeq-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A7">>},
+ 'seqSeqI-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A8">>},
+ 'seqSeqE-E'=#'SeqSeqExp'{seqInt=2,seqOs = <<"A9">>}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTypeRefSeq', T, V).
diff --git a/lib/asn1/test/testSeqTypeRefSet.erl b/lib/asn1/test/testSeqTypeRefSet.erl
index c06a0e7a2b..d73423284b 100644
--- a/lib/asn1/test/testSeqTypeRefSet.erl
+++ b/lib/asn1/test/testSeqTypeRefSet.erl
@@ -31,36 +31,17 @@
main(_Rules) ->
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SeqTypeRefSet','SeqTRset',
- #'SeqTRset'{'seqSet' = #'SeqSet'{setOs = "A1",
- setInt = 2},
- 'seqSetI' = #'SeqSet'{setOs = "A2",
- setInt = 2},
- 'seqSetE' = #'SeqSet'{setOs = "A3",
- setInt = 2},
- 'seqSet-I' = #'SeqSetImp'{setOs = "A4",
- setInt = 2},
- 'seqSetI-I' = #'SeqSetImp'{setOs = "A5",
- setInt = 2},
- 'seqSetE-I' = #'SeqSetImp'{setOs = "A6",
- setInt = 2},
- 'seqSet-E' = #'SeqSetExp'{setOs = "A7",
- setInt = 2},
- 'seqSetI-E' = #'SeqSetExp'{setOs = "A8",
- setInt = 2},
- 'seqSetE-E' = #'SeqSetExp'{setOs = "A9",
- setInt = 2}}),
- ?line {ok,{'SeqTRset',{'SeqSet',2,"A1"},
- {'SeqSet',2,"A2"},
- {'SeqSet',2,"A3"},
- {'SeqSetImp',2,"A4"},
- {'SeqSetImp',2,"A5"},
- {'SeqSetImp',2,"A6"},
- {'SeqSetExp',2,"A7"},
- {'SeqSetExp',2,"A8"},
- {'SeqSetExp',2,"A9"}}} =
- asn1_wrapper:decode('SeqTypeRefSet','SeqTRset',lists:flatten(Bytes41)),
-
+ roundtrip('SeqTRset',
+ #'SeqTRset'{seqSet=#'SeqSet'{setInt=2,setOs = <<"A1">>},
+ seqSetI=#'SeqSet'{setInt=2,setOs = <<"A2">>},
+ seqSetE=#'SeqSet'{setInt=2,setOs = <<"A3">>},
+ 'seqSet-I'=#'SeqSetImp'{setInt=2,setOs = <<"A4">>},
+ 'seqSetI-I'=#'SeqSetImp'{setInt=2,setOs = <<"A5">>},
+ 'seqSetE-I'=#'SeqSetImp'{setInt=2,setOs = <<"A6">>},
+ 'seqSet-E'=#'SeqSetExp'{setInt=2,setOs = <<"A7">>},
+ 'seqSetI-E'=#'SeqSetExp'{setInt=2,setOs = <<"A8">>},
+ 'seqSetE-E'=#'SeqSetExp'{setInt=2,setOs = <<"A9">>}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTypeRefSet', T, V).
diff --git a/lib/asn1/test/testSetDefault.erl b/lib/asn1/test/testSetDefault.erl
index 8aa205e0f0..055dc6cecf 100644
--- a/lib/asn1/test/testSetDefault.erl
+++ b/lib/asn1/test/testSetDefault.erl
@@ -26,58 +26,34 @@
-record('SetDef1',{bool1 = asn1_DEFAULT, int1, set1 = asn1_DEFAULT}).
-record('SetDef2',{set2 = asn1_DEFAULT, bool2, int2}).
-record('SetDef3',{bool3 = asn1_DEFAULT, set3 = asn1_DEFAULT, int3 = asn1_DEFAULT}).
--record('SetIn',{boolIn, intIn}).
+-record('SetIn', {boolIn = asn1_NOVALUE, intIn = 12}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetDefault','SetDef1',#'SetDef1'{bool1 = true,
- int1 = 15,
- set1 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetDef1',true,15,{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetDefault','SetDef1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} = asn1_wrapper:encode('SetDefault','SetDef1',#'SetDef1'{int1 = 15}),
- ?line {ok,{'SetDef1',true,15,{'SetIn',asn1_NOVALUE,12}}} =
- asn1_wrapper:decode('SetDefault','SetDef1',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetDefault','SetDef2',#'SetDef2'{bool2 = true,
- int2 = 15,
- set2 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetDef2',{'SetIn',true,66},true,15}} =
- asn1_wrapper:decode('SetDefault','SetDef2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} = asn1_wrapper:encode('SetDefault','SetDef2',#'SetDef2'{bool2 = true,
- int2 = 15}),
- ?line {ok,{'SetDef2',{'SetIn',asn1_NOVALUE,12},true,15}} =
- asn1_wrapper:decode('SetDefault','SetDef2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetDefault','SetDef3',#'SetDef3'{bool3 = true,
- int3 = 15,
- set3 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetDef3',true,{'SetIn',true,66},15}} =
- asn1_wrapper:decode('SetDefault','SetDef3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} = asn1_wrapper:encode('SetDefault','SetDef3',#'SetDef3'{int3 = 15}),
- ?line {ok,{'SetDef3',true,{'SetIn',asn1_NOVALUE,12},15}} =
- asn1_wrapper:decode('SetDefault','SetDef3',lists:flatten(Bytes32)),
-
-
-
-
+ roundtrip('SetDef1',
+ #'SetDef1'{bool1=true,int1=15,
+ set1=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetDef1',
+ #'SetDef1'{bool1=asn1_DEFAULT,int1=15,set1=asn1_DEFAULT},
+ #'SetDef1'{bool1=true,int1=15,set1=#'SetIn'{}}),
-
-
+ roundtrip('SetDef2',
+ #'SetDef2'{set2=#'SetIn'{boolIn=true,intIn=66},
+ bool2=true,int2=15}),
+ roundtrip('SetDef2',
+ #'SetDef2'{set2=asn1_DEFAULT,bool2=true,int2=15},
+ #'SetDef2'{set2=#'SetIn'{},bool2=true,int2=15}),
+
+ roundtrip('SetDef3',
+ #'SetDef3'{bool3=true,set3=#'SetIn'{boolIn=true,intIn=66},
+ int3=15}),
+ roundtrip('SetDef3',
+ #'SetDef3'{bool3=asn1_DEFAULT,set3=asn1_DEFAULT,int3=15},
+ #'SetDef3'{bool3=true,set3=#'SetIn'{},int3=15}),
ok.
+
+roundtrip(Type, Value) ->
+ roundtrip(Type, Value, Value).
+
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('SetDefault', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testSetExtension.erl b/lib/asn1/test/testSetExtension.erl
index c7fb3b42c4..4e2463326b 100644
--- a/lib/asn1/test/testSetExtension.erl
+++ b/lib/asn1/test/testSetExtension.erl
@@ -18,10 +18,7 @@
%%
%%
-module(testSetExtension).
-
-
-include("External.hrl").
--export([compile/3]).
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -31,76 +28,20 @@
-record('SetExt3',{bool, int}).
-record('SetExt4',{bool, int}).
-
-compile(Config,Rules,Options) ->
-
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "SetExtension",
- [Rules,{outdir,OutDir}]++Options).
-
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetExtension','SetExt1',#'SetExt1'{}),
- ?line {ok,{'SetExt1'}} =
- asn1_wrapper:decode('SetExtension','SetExt1',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetExtension','SetExt2',#'SetExt2'{bool = true,int = 99}),
- ?line {ok,{'SetExt2',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt2',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetExtension','SetExt2',#'SetExt2'{int = 99,bool = true}),
- ?line {ok,{'SetExt2',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt2',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetExtension','SetExt3',#'SetExt3'{bool = true,int = 99}),
- ?line {ok,{'SetExt3',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt3',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetExtension','SetExt3',#'SetExt3'{int = 99,bool = true}),
- ?line {ok,{'SetExt3',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt3',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetExtension','SetExt4',#'SetExt4'{bool = true,int = 99}),
- ?line {ok,{'SetExt4',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt4',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SetExtension','SetExt4',#'SetExt4'{int = 99,bool = true}),
- ?line {ok,{'SetExt4',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt4',lists:flatten(Bytes42)),
-
-
- %% Test of extension , needs to be improved and extended
-
- ?line {ok,BytesX11} =
- asn1_wrapper:encode('SetExtension','SetExt1',#'SetExt1'{}),
- ?line {ok,{'SetExt1'}} =
- asn1_wrapper:decode('SetExtension','SetExt1',lists:flatten(BytesX11)),
-
- ?line {ok,BytesX21} =
- asn1_wrapper:encode('SetExtension','SetExt2',#'SetExt2'{bool = true,int = 99}),
- ?line {ok,{'SetExt2',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt2',lists:flatten(BytesX21)),
-
- ?line {ok,BytesX22} =
- asn1_wrapper:encode('SetExtension','SetExt2',#'SetExt2'{int = 99,bool = true}),
- ?line {ok,{'SetExt2',true,99}} =
- asn1_wrapper:decode('SetExtension','SetExt2',lists:flatten(BytesX22)),
-
-
-
-
-
+ roundtrip('SetExt1', #'SetExt1'{}),
+ roundtrip('SetExt2', #'SetExt2'{bool=true,int=99}),
+ roundtrip('SetExt2', #'SetExt2'{bool=true,int=99}),
+ roundtrip('SetExt3', #'SetExt3'{bool=true,int=99}),
+ roundtrip('SetExt3', #'SetExt3'{bool=true,int=99}),
+ roundtrip('SetExt4', #'SetExt4'{bool=true,int=99}),
+ roundtrip('SetExt4', #'SetExt4'{bool=true,int=99}),
+ roundtrip('SetExt1', #'SetExt1'{}),
+ roundtrip('SetExt2', #'SetExt2'{bool=true,int=99}),
+ roundtrip('SetExt2', #'SetExt2'{bool=true,int=99}),
ok.
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetExtension', T, V).
+
diff --git a/lib/asn1/test/testSetExternal.erl b/lib/asn1/test/testSetExternal.erl
index 30cddcacfb..626adc5822 100644
--- a/lib/asn1/test/testSetExternal.erl
+++ b/lib/asn1/test/testSetExternal.erl
@@ -18,111 +18,36 @@
%%
%%
-module(testSetExternal).
-
--include("External.hrl").
-export([main/1]).
+-include("External.hrl").
-include_lib("test_server/include/test_server.hrl").
-
-record('SetXSeq1',{seq, bool, int}).
-record('SetXSeq2',{bool, seq, int}).
-record('SetXSeq3',{bool, int, seq}).
-%-record('NT',{os, bool}).
-%-record('Imp',{os, bool}).
-%-record('Exp',{os, bool}).
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetExternal','XNTNT',#'XSetNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XNTNT',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetExternal','XImpNT',#'XSetNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XImpNT',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetExternal','XExpNT',#'XSetNT'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetNT',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XExpNT',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetExternal','XNTImp',#'XSetImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XNTImp',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetExternal','XImpImp',#'XSetImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XImpImp',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetExternal','XExpImp',#'XSetImp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetImp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XExpImp',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetExternal','XNTExp',#'XSetExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XNTExp',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetExternal','XImpExp',#'XSetExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XImpExp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SetExternal','XExpExp',#'XSetExp'{bool = true, os = "kalle"}),
- ?line {ok,{'XSetExp',[107,97,108,108,101],true}} =
- asn1_wrapper:decode('SetExternal','XExpExp',lists:flatten(Bytes33)),
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetExternal','SetXSeq1',
- #'SetXSeq1'{bool = true,
- int = 66,
- seq = #'XSeq1'{bool1 = true,
- int1 = 77,
- seq1 = #'XSeqIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SetXSeq1',{'XSeq1',true,77,{'XSeqIn',false,88}},true,66}} =
- asn1_wrapper:decode('SetExternal','SetXSeq1',lists:flatten(Bytes41)),
-
-
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SetExternal','SetXSeq2',
- #'SetXSeq2'{bool = true,
- int = 66,
- seq = #'XSeq1'{bool1 = true,
- int1 = 77,
- seq1 = #'XSeqIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SetXSeq2',true,{'XSeq1',true,77,{'XSeqIn',false,88}},66}} =
- asn1_wrapper:decode('SetExternal','SetXSeq2',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SetExternal','SetXSeq3',
- #'SetXSeq3'{bool = true,
- int = 66,
- seq = #'XSeq1'{bool1 = true,
- int1 = 77,
- seq1 = #'XSeqIn'{boolIn = false,
- intIn = 88}}}),
- ?line {ok,{'SetXSeq3',true,66,{'XSeq1',true,77,{'XSeqIn',false,88}}}} =
- asn1_wrapper:decode('SetExternal','SetXSeq3',lists:flatten(Bytes43)),
-
-
-
-
+ roundtrip('XNTNT', #'XSetNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpNT', #'XSetNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpNT', #'XSetNT'{os = <<"kalle">>,bool=true}),
+ roundtrip('XNTImp', #'XSetImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpImp', #'XSetImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpImp', #'XSetImp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XNTExp', #'XSetExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XImpExp', #'XSetExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('XExpExp', #'XSetExp'{os = <<"kalle">>,bool=true}),
+ roundtrip('SetXSeq1', #'SetXSeq1'{seq=#'XSeq1'{bool1=true,int1=77,
+ seq1=#'XSeqIn'{boolIn=false,intIn=88}},
+ bool=true,int=66}),
+ roundtrip('SetXSeq2', #'SetXSeq2'{bool=true,
+ seq=#'XSeq1'{bool1=true,int1=77,
+ seq1=#'XSeqIn'{boolIn=false,intIn=88}},
+ int=66}),
+ roundtrip('SetXSeq3', #'SetXSeq3'{bool=true,int=66,
+ seq=#'XSeq1'{bool1=true,int1=77,
+ seq1=#'XSeqIn'{boolIn=false,intIn=88}}}),
ok.
-
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetExternal', T, V).
diff --git a/lib/asn1/test/testSetIndefinite.erl b/lib/asn1/test/testSetIndefinite.erl
deleted file mode 100644
index 73006da62b..0000000000
--- a/lib/asn1/test/testSetIndefinite.erl
+++ /dev/null
@@ -1,41 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-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(testSetIndefinite).
-
--export([main/1]).
-
--include_lib("test_server/include/test_server.hrl").
-
-
-main(per) -> ok;
-main(ber) ->
-
- %% normal encoding
- B = [49,20,1,1,255,49,9,1,1,255,2,4,251,35,238,194,2,4,251,55,236,161],
- %% indefinite length encoding
- Bi = [49,22,1,1,255,49,128,1,1,255,2,4,251,35,238,194,0,0,2,4,251,55,236,161],
- %% the value which is encoded
- V = {'SetS3',true,{'SetS3_setS3',true,-81531198},-80221023},
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SetS3',B),
- ?line {ok,V} = asn1_wrapper:decode('SeqSetIndefinite','SetS3',Bi),
- ok.
-
-
-
diff --git a/lib/asn1/test/testSetOf.erl b/lib/asn1/test/testSetOf.erl
index 08723fb468..0f82a14625 100644
--- a/lib/asn1/test/testSetOf.erl
+++ b/lib/asn1/test/testSetOf.erl
@@ -28,198 +28,108 @@
-record('Set3',{bool3, set3 = asn1_DEFAULT, int3}).
-record('Set4',{set41 = asn1_DEFAULT, set42 = asn1_DEFAULT, set43 = asn1_DEFAULT}).
-record('SetIn',{boolIn, intIn}).
-%-record('SetCho',{bool1, int1, set1 = asn1_DEFAULT}).
-%-record('SetChoInline',{bool1, int1, set1 = asn1_DEFAULT}).
-%-record('SetChoOfInline_SETOF',{bool1, int1, set1 = asn1_DEFAULT}).
-record('SetEmp',{set1}).
-record('Empty',{}).
main(_Rules) ->
+ roundtrip('Set1',
+ #'Set1'{bool1=true,int1=17,set1=asn1_DEFAULT},
+ #'Set1'{bool1=true,int1=17,set1=[]}),
+ roundtrip('Set1',
+ #'Set1'{bool1=true,int1=17,
+ set1=[#'SetIn'{boolIn=true,intIn=25}]}),
+ roundtrip('Set1', #'Set1'{bool1=true,int1=17,
+ set1=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}]}),
+
+ roundtrip('Set2',
+ #'Set2'{set2=asn1_DEFAULT,bool2=true,int2=17},
+ #'Set2'{set2=[],bool2=true,int2=17}),
+ roundtrip('Set2',
+ #'Set2'{set2=[#'SetIn'{boolIn=true,intIn=25}],
+ bool2=true,int2=17}),
+ roundtrip('Set2',
+ #'Set2'{set2=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ bool2=true,int2=17}),
+
+ roundtrip('Set3',
+ #'Set3'{bool3=true,set3=asn1_DEFAULT,int3=17},
+ #'Set3'{bool3=true,set3=[],int3=17}),
+ roundtrip('Set3',
+ #'Set3'{bool3=true,set3=[#'SetIn'{boolIn=true,intIn=25}],
+ int3=17}),
+ roundtrip('Set3',
+ #'Set3'{bool3=true,
+ set3=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ int3=17}),
+
+ roundtrip('Set4',
+ #'Set4'{set41=asn1_DEFAULT,set42=asn1_DEFAULT,
+ set43=asn1_DEFAULT},
+ #'Set4'{set41=[],set42=[],set43=[]}),
+ roundtrip('Set4',
+ #'Set4'{set41=[#'SetIn'{boolIn=true,intIn=25}],
+ set42=asn1_DEFAULT,set43=asn1_DEFAULT},
+ #'Set4'{set41=[#'SetIn'{boolIn=true,intIn=25}],
+ set42=[],set43=[]}),
+ roundtrip('Set4',
+ #'Set4'{set41=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ set42=asn1_DEFAULT,set43=asn1_DEFAULT},
+ #'Set4'{set41=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ set42=[],set43=[]}),
+ roundtrip('Set4',
+ #'Set4'{set41=asn1_DEFAULT,
+ set42=[#'SetIn'{boolIn=true,intIn=25}],
+ set43=asn1_DEFAULT},
+ #'Set4'{set41=[],
+ set42=[#'SetIn'{boolIn=true,intIn=25}],
+ set43=[]}),
+ roundtrip('Set4',
+ #'Set4'{set41=asn1_DEFAULT,
+ set42=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ set43=asn1_DEFAULT},
+ #'Set4'{set41=[],
+ set42=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}],
+ set43=[]}),
+ roundtrip('Set4',
+ #'Set4'{set41=asn1_DEFAULT,set42=asn1_DEFAULT,
+ set43=[#'SetIn'{boolIn=true,intIn=25}]},
+ #'Set4'{set41=[],set42=[],
+ set43=[#'SetIn'{boolIn=true,intIn=25}]}),
+ roundtrip('Set4',
+ #'Set4'{set41=asn1_DEFAULT,set42=asn1_DEFAULT,
+ set43=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}]},
+ #'Set4'{set41=[],set42=[],
+ set43=[#'SetIn'{boolIn=true,intIn=25},
+ #'SetIn'{boolIn=false,intIn=125},
+ #'SetIn'{boolIn=false,intIn=225}]}),
+
+ roundtrip('SetOs', [<<"First">>,<<"Second">>,<<"Third">>]),
+ roundtrip('SetOsImp', [<<"First">>,<<"Second">>,<<"Third">>]),
+ roundtrip('SetOsExp', [<<"First">>,<<"Second">>,<<"Third">>]),
+ roundtrip('SetEmp', #'SetEmp'{set1=[#'Empty'{}]}),
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetOf','Set1',#'Set1'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'Set1',true,17,[]}} =
- asn1_wrapper:decode('SetOf','Set1',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetOf','Set1',#'Set1'{bool1 = true,
- int1 = 17,
- set1 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set1',true,17,[{'SetIn',true,25}]}} =
- asn1_wrapper:decode('SetOf','Set1',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetOf','Set1',#'Set1'{bool1 = true,
- int1 = 17,
- set1 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set1',true,17,[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}]}} =
- asn1_wrapper:decode('SetOf','Set1',lists:flatten(Bytes13)),
-
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetOf','Set2',#'Set2'{bool2 = true,
- int2 = 17}),
-
- ?line {ok,{'Set2',[],true,17}} =
- asn1_wrapper:decode('SetOf','Set2',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetOf','Set2',#'Set2'{bool2 = true,
- int2 = 17,
- set2 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set2',[{'SetIn',true,25}],true,17}} =
- asn1_wrapper:decode('SetOf','Set2',lists:flatten(Bytes22)),
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetOf','Set2',#'Set2'{bool2 = true,
- int2 = 17,
- set2 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set2',[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}],true,17}} =
- asn1_wrapper:decode('SetOf','Set2',lists:flatten(Bytes23)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetOf','Set3',#'Set3'{bool3 = true,
- int3 = 17}),
- ?line {ok,{'Set3',true,[],17}} =
- asn1_wrapper:decode('SetOf','Set3',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetOf','Set3',#'Set3'{bool3 = true,
- int3 = 17,
- set3 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set3',true,[{'SetIn',true,25}],17}} =
- asn1_wrapper:decode('SetOf','Set3',lists:flatten(Bytes32)),
-
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SetOf','Set3',#'Set3'{bool3 = true,
- int3 = 17,
- set3 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set3',true,[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}],17}} =
- asn1_wrapper:decode('SetOf','Set3',lists:flatten(Bytes33)),
-
-
-
-
-
-
-
- ?line {ok,Bytes41} = asn1_wrapper:encode('SetOf','Set4',#'Set4'{}),
- ?line {ok,{'Set4',[],[],[]}} = asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes41)),
-
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set41 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set4',[{'SetIn',true,25}],[],[]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes42)),
-
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set41 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set4',[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}],[],[]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes43)),
-
-
- ?line {ok,Bytes44} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set42 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set4',[],[{'SetIn',true,25}],[]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes44)),
-
-
- ?line {ok,Bytes45} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set42 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set4',[],[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}],[]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes45)),
-
-
- ?line {ok,Bytes46} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set43 = [#'SetIn'{boolIn = true,
- intIn = 25}]}),
- ?line {ok,{'Set4',[],[],[{'SetIn',true,25}]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes46)),
-
-
- ?line {ok,Bytes47} =
- asn1_wrapper:encode('SetOf','Set4',#'Set4'{set43 = [#'SetIn'{boolIn = true,
- intIn = 25},
- #'SetIn'{boolIn = false,
- intIn = 125},
- #'SetIn'{boolIn = false,
- intIn = 225}]}),
- ?line {ok,{'Set4',[],[],[{'SetIn',true,25},{'SetIn',false,125},{'SetIn',false,225}]}} =
- asn1_wrapper:decode('SetOf','Set4',lists:flatten(Bytes47)),
-
-
-
-
- ?line {ok,Bytes51} = asn1_wrapper:encode('SetOf','SetOs',["First","Second","Third"]),
- ?line {ok,["First","Second","Third"]} =
- asn1_wrapper:decode('SetOf','SetOs',lists:flatten(Bytes51)),
-
- ?line {ok,Bytes52} = asn1_wrapper:encode('SetOf','SetOsImp',["First","Second","Third"]),
- ?line {ok,["First","Second","Third"]} =
- asn1_wrapper:decode('SetOf','SetOsImp',lists:flatten(Bytes52)),
-
- ?line {ok,Bytes53} = asn1_wrapper:encode('SetOf','SetOsExp',["First","Second","Third"]),
- ?line {ok,["First","Second","Third"]} =
- asn1_wrapper:decode('SetOf','SetOsExp',lists:flatten(Bytes53)),
-
-
-
-
-
-
-
- ?line {ok,Bytes71} = asn1_wrapper:encode('SetOf','SetEmp',#'SetEmp'{set1 = [#'Empty'{}]}),
- ?line {ok,{'SetEmp',[{'Empty'}]}} = asn1_wrapper:decode('SetOf','SetEmp',lists:flatten(Bytes71)),
-
ok.
+roundtrip(T, V) ->
+ roundtrip(T, V, V).
+
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('SetOf', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testSetOfCho.erl b/lib/asn1/test/testSetOfCho.erl
index c89bf9596e..09c075e468 100644
--- a/lib/asn1/test/testSetOfCho.erl
+++ b/lib/asn1/test/testSetOfCho.erl
@@ -30,120 +30,46 @@
-record('SetOfChoEmbDef_SETOF',{bool1, int1, set1 = asn1_DEFAULT}).
-record('SetOfChoEmbOpt_SETOF',{bool1, int1, set1 = asn1_NOVALUE}).
+main(_Rules) ->
+ roundtrip('SetChoDef',
+ #'SetChoDef'{bool1=true,int1=17,set1=asn1_DEFAULT},
+ #'SetChoDef'{bool1=true,int1=17,set1=[]}),
+ roundtrip('SetChoDef',
+ #'SetChoDef'{bool1=true,int1=17,set1=[{boolIn,true},{intIn,25}]}),
+ roundtrip('SetChoOpt',
+ #'SetChoOpt'{bool1=true,int1=17,set1=asn1_NOVALUE}),
+ roundtrip('SetChoOpt',
+ #'SetChoOpt'{bool1=true,int1=17,set1=[{boolIn,true},{intIn,25}]}),
+ roundtrip('SetChoEmbDef',
+ #'SetChoEmbDef'{bool1=true,int1=17,set1=asn1_DEFAULT},
+ #'SetChoEmbDef'{bool1=true,int1=17,set1=[]}),
+ roundtrip('SetChoEmbDef',
+ #'SetChoEmbDef'{bool1=true,int1=17,
+ set1=[{boolIn,true},{intIn,25}]}),
+ roundtrip('SetChoEmbOpt',
+ #'SetChoEmbOpt'{bool1=true,int1=17,set1=asn1_NOVALUE}),
+ roundtrip('SetChoEmbOpt',
+ #'SetChoEmbOpt'{bool1=true,int1=17,
+ set1=[{boolIn,true},{intIn,25}]}),
+
+ roundtrip('SetOfChoEmbDef',
+ [#'SetOfChoEmbDef_SETOF'{bool1=true,int1=17,set1=asn1_DEFAULT}],
+ [#'SetOfChoEmbDef_SETOF'{bool1=true,int1=17,set1=[]}]),
+ roundtrip('SetOfChoEmbDef',
+ [#'SetOfChoEmbDef_SETOF'{bool1=true,int1=17,
+ set1=[{boolIn,true},{intIn,25}]}]),
+
+ roundtrip('SetOfChoEmbOpt',
+ [#'SetOfChoEmbOpt_SETOF'{bool1=true,int1=17,set1=asn1_NOVALUE}]),
+ roundtrip('SetOfChoEmbOpt',
+ [#'SetOfChoEmbOpt_SETOF'{bool1=true,int1=17,
+ set1=[{boolIn,true},{intIn,25}]}]),
-main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetOfCho','SetChoDef',#'SetChoDef'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SetChoDef',true,17,[]}} =
- asn1_wrapper:decode('SetOfCho','SetChoDef',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetOfCho','SetChoDef',#'SetChoDef'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SetChoDef',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SetOfCho','SetChoDef',lists:flatten(Bytes12)),
-
-
-
- ?line {ok,Bytes15} =
- asn1_wrapper:encode('SetOfCho','SetChoOpt',#'SetChoOpt'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SetChoOpt',true,17,asn1_NOVALUE}} =
- asn1_wrapper:decode('SetOfCho','SetChoOpt',lists:flatten(Bytes15)),
-
-
- ?line {ok,Bytes16} =
- asn1_wrapper:encode('SetOfCho','SetChoOpt',#'SetChoOpt'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SetChoOpt',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SetOfCho','SetChoOpt',lists:flatten(Bytes16)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetOfCho','SetChoEmbDef',#'SetChoEmbDef'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SetChoEmbDef',true,17,[]}} =
- asn1_wrapper:decode('SetOfCho','SetChoEmbDef',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetOfCho','SetChoEmbDef',#'SetChoEmbDef'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SetChoEmbDef',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SetOfCho','SetChoEmbDef',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes25} =
- asn1_wrapper:encode('SetOfCho','SetChoEmbOpt',#'SetChoEmbOpt'{bool1 = true,
- int1 = 17}),
- ?line {ok,{'SetChoEmbOpt',true,17,asn1_NOVALUE}} =
- asn1_wrapper:decode('SetOfCho','SetChoEmbOpt',lists:flatten(Bytes25)),
-
-
- ?line {ok,Bytes26} =
- asn1_wrapper:encode('SetOfCho','SetChoEmbOpt',#'SetChoEmbOpt'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}),
- ?line {ok,{'SetChoEmbOpt',true,17,[{boolIn,true},{intIn,25}]}} =
- asn1_wrapper:decode('SetOfCho','SetChoEmbOpt',lists:flatten(Bytes26)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetOfCho','SetOfChoEmbDef',[#'SetOfChoEmbDef_SETOF'{bool1 = true,
- int1 = 17}]),
- ?line {ok,[{'SetOfChoEmbDef_SETOF',true,17,[]}]} =
- asn1_wrapper:decode('SetOfCho','SetOfChoEmbDef',lists:flatten(Bytes31)),
-
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetOfCho','SetOfChoEmbDef',
- [#'SetOfChoEmbDef_SETOF'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}]),
- ?line {ok,[{'SetOfChoEmbDef_SETOF',true,17,[{boolIn,true},{intIn,25}]}]} =
- asn1_wrapper:decode('SetOfCho','SetOfChoEmbDef',lists:flatten(Bytes32)),
-
-
-
- ?line {ok,Bytes35} =
- asn1_wrapper:encode('SetOfCho','SetOfChoEmbOpt',[#'SetOfChoEmbOpt_SETOF'{bool1 = true,
- int1 = 17}]),
- ?line {ok,[{'SetOfChoEmbOpt_SETOF',true,17,asn1_NOVALUE}]} =
- asn1_wrapper:decode('SetOfCho','SetOfChoEmbOpt',lists:flatten(Bytes35)),
-
-
- ?line {ok,Bytes36} =
- asn1_wrapper:encode('SetOfCho','SetOfChoEmbOpt',
- [#'SetOfChoEmbOpt_SETOF'{bool1 = true,
- int1 = 17,
- set1 = [{boolIn,true},
- {intIn,25}]}]),
- ?line {ok,[{'SetOfChoEmbOpt_SETOF',true,17,[{boolIn,true},{intIn,25}]}]} =
- asn1_wrapper:decode('SetOfCho','SetOfChoEmbOpt',lists:flatten(Bytes36)),
-
-
-
-
ok.
+roundtrip(T, V) ->
+ roundtrip(T, V, V).
+roundtrip(Type, Value, ExpectedValue) ->
+ asn1_test_lib:roundtrip('SetOfCho', Type, Value, ExpectedValue).
diff --git a/lib/asn1/test/testSetOfExternal.erl b/lib/asn1/test/testSetOfExternal.erl
index 6b280a2595..cc5fe10710 100644
--- a/lib/asn1/test/testSetOfExternal.erl
+++ b/lib/asn1/test/testSetOfExternal.erl
@@ -18,8 +18,6 @@
%%
%%
-module(testSetOfExternal).
-
-
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -29,133 +27,44 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetOfExternal','NTNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','NTNT',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetOfExternal','ImpNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ImpNT',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetOfExternal','ExpNT',[#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ExpNT',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetOfExternal','NTImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','NTImp',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetOfExternal','ImpImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ImpImp',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetOfExternal','ExpImp',[#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ExpImp',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetOfExternal','NTExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','NTExp',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetOfExternal','ImpExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ImpExp',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SetOfExternal','ExpExp',[#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','ExpExp',lists:flatten(Bytes33)),
-
-
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetOfExternal','XNTNT',[#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XNTNT',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SetOfExternal','XImpNT',[#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XImpNT',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SetOfExternal','XExpNT',[#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XExpNT',lists:flatten(Bytes43)),
-
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SetOfExternal','XNTImp',[#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XNTImp',lists:flatten(Bytes51)),
-
- ?line {ok,Bytes52} =
- asn1_wrapper:encode('SetOfExternal','XImpImp',[#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XImpImp',lists:flatten(Bytes52)),
-
- ?line {ok,Bytes53} =
- asn1_wrapper:encode('SetOfExternal','XExpImp',[#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XExpImp',lists:flatten(Bytes53)),
-
-
-
- ?line {ok,Bytes61} =
- asn1_wrapper:encode('SetOfExternal','XNTExp',[#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XNTExp',lists:flatten(Bytes61)),
-
- ?line {ok,Bytes62} =
- asn1_wrapper:encode('SetOfExternal','XImpExp',[#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XImpExp',lists:flatten(Bytes62)),
-
- ?line {ok,Bytes63} =
- asn1_wrapper:encode('SetOfExternal','XExpExp',[#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]),
- ?line {ok,[{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]} =
- asn1_wrapper:decode('SetOfExternal','XExpExp',lists:flatten(Bytes63)),
-
-
-
-
+ roundtrip('NTNT', [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpNT', [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpNT', [#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('NTImp', [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpImp', [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpImp', [#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('NTExp', [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ImpExp', [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('ExpExp', [#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTNT', [#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpNT', [#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpNT', [#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTImp', [#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpImp', [#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpImp', [#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XNTExp', [#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XImpExp', [#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]),
+ roundtrip('XExpExp', [#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetOfExternal', T, V).
diff --git a/lib/asn1/test/testSetOfTag.erl b/lib/asn1/test/testSetOfTag.erl
index 2c7a2f5473..0d656f05a6 100644
--- a/lib/asn1/test/testSetOfTag.erl
+++ b/lib/asn1/test/testSetOfTag.erl
@@ -18,14 +18,11 @@
%%
%%
-module(testSetOfTag).
-
-
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
-include("External.hrl").
-
-record('SetTagNt',{nt}).
-record('SetTagNtI',{imp}).
-record('SetTagNtE',{exp}).
@@ -44,148 +41,44 @@
-record('Imp',{os, bool}).
-record('Exp',{os, bool}).
-
-
main(_Rules) ->
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetOfTag','SetTagNt',
- #'SetTagNt'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagNt',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagNt',lists:flatten(Bytes11)),
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetOfTag','SetTagNtI',
- #'SetTagNtI'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagNtI',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagNtI',lists:flatten(Bytes12)),
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetOfTag','SetTagNtE',
- #'SetTagNtE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagNtE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagNtE',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetOfTag','SetTagI',
- #'SetTagI'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagI',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagI',lists:flatten(Bytes21)),
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetOfTag','SetTagII',
- #'SetTagII'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagII',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagII',lists:flatten(Bytes22)),
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetOfTag','SetTagIE',
- #'SetTagIE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagIE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagIE',lists:flatten(Bytes23)),
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetOfTag','SetTagE',
- #'SetTagE'{nt = [#'NT'{bool = true, os = "kalle"},
- #'NT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagE',
- [{'NT',[107,97,108,108,101],true},{'NT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagE',lists:flatten(Bytes31)),
-
- ?line {ok,Bytes32} =
- asn1_wrapper:encode('SetOfTag','SetTagEI',
- #'SetTagEI'{imp = [#'Imp'{bool = true, os = "kalle"},
- #'Imp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagEI',
- [{'Imp',[107,97,108,108,101],true},{'Imp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagEI',lists:flatten(Bytes32)),
-
- ?line {ok,Bytes33} =
- asn1_wrapper:encode('SetOfTag','SetTagEE',
- #'SetTagEE'{exp = [#'Exp'{bool = true, os = "kalle"},
- #'Exp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagEE',
- [{'Exp',[107,97,108,108,101],true},{'Exp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagEE',lists:flatten(Bytes33)),
-
-
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetOfTag','SetTagXNt',
- #'SetTagXNt'{xnt = [#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagXNt',
- [{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagXNt',lists:flatten(Bytes41)),
-
- ?line {ok,Bytes42} =
- asn1_wrapper:encode('SetOfTag','SetTagXI',
- #'SetTagXI'{ximp = [#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagXI',
- [{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagXI',lists:flatten(Bytes42)),
-
- ?line {ok,Bytes43} =
- asn1_wrapper:encode('SetOfTag','SetTagXE',
- #'SetTagXE'{xexp = [#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagXE',
- [{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagXE',lists:flatten(Bytes43)),
-
-
-
-
-
- ?line {ok,Bytes51} =
- asn1_wrapper:encode('SetOfTag','SetTagImpX',
- #'SetTagImpX'{xnt = [#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}],
- ximp = [#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}],
- xexp = [#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagImpX',
- [{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}],
- [{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}],
- [{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagImpX',lists:flatten(Bytes51)),
-
-
-
- ?line {ok,Bytes52} =
- asn1_wrapper:encode('SetOfTag','SetTagExpX',
- #'SetTagExpX'{xnt = [#'XSetNT'{bool = true, os = "kalle"},
- #'XSetNT'{bool = true, os = "kalle"}],
- ximp = [#'XSetImp'{bool = true, os = "kalle"},
- #'XSetImp'{bool = true, os = "kalle"}],
- xexp = [#'XSetExp'{bool = true, os = "kalle"},
- #'XSetExp'{bool = true, os = "kalle"}]}),
- ?line {ok,{'SetTagExpX',
- [{'XSetNT',[107,97,108,108,101],true},{'XSetNT',[107,97,108,108,101],true}],
- [{'XSetImp',[107,97,108,108,101],true},{'XSetImp',[107,97,108,108,101],true}],
- [{'XSetExp',[107,97,108,108,101],true},{'XSetExp',[107,97,108,108,101],true}]}} =
- asn1_wrapper:decode('SetOfTag','SetTagExpX',lists:flatten(Bytes52)),
-
+ roundtrip('SetTagNt', #'SetTagNt'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagNtI', #'SetTagNtI'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagNtE', #'SetTagNtE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagI', #'SetTagI'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagII', #'SetTagII'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagIE', #'SetTagIE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagE', #'SetTagE'{nt=[#'NT'{os = <<"kalle">>,bool=true},
+ #'NT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagEI', #'SetTagEI'{imp=[#'Imp'{os = <<"kalle">>,bool=true},
+ #'Imp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagEE', #'SetTagEE'{exp=[#'Exp'{os = <<"kalle">>,bool=true},
+ #'Exp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagXNt', #'SetTagXNt'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagXI', #'SetTagXI'{ximp=[#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagXE', #'SetTagXE'{xexp=[#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagImpX', #'SetTagImpX'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}],
+ ximp=[#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}],
+ xexp=[#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]}),
+ roundtrip('SetTagExpX', #'SetTagExpX'{xnt=[#'XSetNT'{os = <<"kalle">>,bool=true},
+ #'XSetNT'{os = <<"kalle">>,bool=true}],
+ ximp=[#'XSetImp'{os = <<"kalle">>,bool=true},
+ #'XSetImp'{os = <<"kalle">>,bool=true}],
+ xexp=[#'XSetExp'{os = <<"kalle">>,bool=true},
+ #'XSetExp'{os = <<"kalle">>,bool=true}]}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetOfTag', T, V).
diff --git a/lib/asn1/test/testSetOptional.erl b/lib/asn1/test/testSetOptional.erl
index bb43ff0a96..eb095fd480 100644
--- a/lib/asn1/test/testSetOptional.erl
+++ b/lib/asn1/test/testSetOptional.erl
@@ -93,6 +93,4 @@ ticket_7533(_) ->
ok.
roundtrip(Type, Value) ->
- {ok,Encoded} = 'SetOptional':encode(Type, Value),
- {ok,Value} = 'SetOptional':decode(Type, Encoded),
- ok.
+ asn1_test_lib:roundtrip('SetOptional', Type, Value).
diff --git a/lib/asn1/test/testSetPrim.erl b/lib/asn1/test/testSetPrim.erl
index 3234b65135..f417f343a7 100644
--- a/lib/asn1/test/testSetPrim.erl
+++ b/lib/asn1/test/testSetPrim.erl
@@ -27,59 +27,17 @@
-record('Empty',{}).
main(_Rules) ->
-
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetPrim','Set',#'Set'{bool = true,
- boolCon = true,
- boolPri = true,
- boolApp = true,
- boolExpCon = true,
- boolExpPri = true,
- boolExpApp = true}),
- ?line {ok,{'Set',true,true,true,true,true,true,true}} =
- asn1_wrapper:decode('SetPrim','Set',lists:flatten(Bytes11)),
-
-
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetPrim','Set',#'Set'{bool = false,
- boolCon = false,
- boolPri = false,
- boolApp = false,
- boolExpCon = false,
- boolExpPri = false,
- boolExpApp = false}),
- ?line {ok,{'Set',false,false,false,false,false,false,false}} =
- asn1_wrapper:decode('SetPrim','Set',lists:flatten(Bytes12)),
-
-
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetPrim','Set',#'Set'{bool = false,
- boolCon = true,
- boolPri = false,
- boolApp = true,
- boolExpCon = false,
- boolExpPri = true,
- boolExpApp = false}),
- ?line {ok,{'Set',false,true,false,true,false,true,false}} =
- asn1_wrapper:decode('SetPrim','Set',lists:flatten(Bytes13)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetPrim','Empty',#'Empty'{}),
- ?line {ok,{'Empty'}} =
- asn1_wrapper:decode('SetPrim','Empty',lists:flatten(Bytes21)),
-
-
-
+ roundtrip('Set',
+ #'Set'{bool=true,boolCon=true,boolPri=true,boolApp=true,
+ boolExpCon=true,boolExpPri=true,boolExpApp=true}),
+ roundtrip('Set',
+ #'Set'{bool=false,boolCon=false,boolPri=false,boolApp=false,
+ boolExpCon=false,boolExpPri=false,boolExpApp=false}),
+ roundtrip('Set',
+ #'Set'{bool=false,boolCon=true,boolPri=false,boolApp=true,
+ boolExpCon=false,boolExpPri=true,boolExpApp=false}),
+ roundtrip('Empty', #'Empty'{}),
ok.
-
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetPrim', T, V).
diff --git a/lib/asn1/test/testSetTag.erl b/lib/asn1/test/testSetTag.erl
index 8b9364d603..fa1d84f50d 100644
--- a/lib/asn1/test/testSetTag.erl
+++ b/lib/asn1/test/testSetTag.erl
@@ -18,7 +18,6 @@
%%
%%
-module(testSetTag).
-
-export([main/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,69 +34,25 @@
-record('Exp',{os, bool}).
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetTag','SetTag',#'SetTag'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTag',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTag',lists:flatten(Bytes11)),
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetTag','SetTagImp',#'SetTagImp'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTagImp',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTagImp',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetTag','SetTagExp',#'SetTagExp'{nt = #'NT'{bool = true, os = "kalle"},
- imp = #'Imp'{bool = true, os = "kalle"},
- exp = #'Exp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTagExp',{'NT',"kalle",true},{'Imp',"kalle",true},{'Exp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTagExp',lists:flatten(Bytes13)),
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetTag','SetTagX',
- #'SetTagX'{xnt = #'XSetNT'{bool = true, os = "kalle"},
- ximp = #'XSetImp'{bool = true, os = "kalle"},
- xexp = #'XSetExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTagX',{'XSetNT',"kalle",true},
- {'XSetImp',"kalle",true},
- {'XSetExp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTagX',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetTag','SetTagImpX',
- #'SetTagImpX'{xnt = #'XSetNT'{bool = true, os = "kalle"},
- ximp = #'XSetImp'{bool = true, os = "kalle"},
- xexp = #'XSetExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTagImpX',{'XSetNT',"kalle",true},
- {'XSetImp',"kalle",true},
- {'XSetExp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTagImpX',lists:flatten(Bytes22)),
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetTag','SetTagExpX',
- #'SetTagExpX'{xnt = #'XSetNT'{bool = true, os = "kalle"},
- ximp = #'XSetImp'{bool = true, os = "kalle"},
- xexp = #'XSetExp'{bool = true, os = "kalle"}}),
- ?line {ok,{'SetTagExpX',{'XSetNT',"kalle",true},
- {'XSetImp',"kalle",true},
- {'XSetExp',"kalle",true}}} =
- asn1_wrapper:decode('SetTag','SetTagExpX',lists:flatten(Bytes23)),
-
-
-
-
-
+ roundtrip('SetTag', #'SetTag'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SetTagImp', #'SetTagImp'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SetTagExp', #'SetTagExp'{nt=#'NT'{os = <<"kalle">>,bool=true},
+ imp=#'Imp'{os = <<"kalle">>,bool=true},
+ exp=#'Exp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SetTagX', #'SetTagX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSetImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SetTagImpX', #'SetTagImpX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSetImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}),
+ roundtrip('SetTagExpX', #'SetTagExpX'{xnt=#'XSetNT'{os = <<"kalle">>,bool=true},
+ ximp=#'XSetImp'{os = <<"kalle">>,bool=true},
+ xexp=#'XSetExp'{os = <<"kalle">>,bool=true}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetTag', T, V).
diff --git a/lib/asn1/test/testSetTypeRefCho.erl b/lib/asn1/test/testSetTypeRefCho.erl
index a0989926c7..97bbd557e0 100644
--- a/lib/asn1/test/testSetTypeRefCho.erl
+++ b/lib/asn1/test/testSetTypeRefCho.erl
@@ -28,17 +28,12 @@
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetTypeRefCho','SetTRcho',
- #'SetTRcho'{'setCho' = {choOs,"A string 1"},
- 'setChoE' = {choOs,"A string 3"},
- 'setCho-E' = {choOs,"A string 7"},
- 'setChoE-E' = {choOs,"A string 9"}}),
- ?line {ok,{'SetTRcho',{choOs,"A string 1"},{choOs,"A string 3"},{choOs,"A string 7"},{choOs,"A string 9"}}} =
- asn1_wrapper:decode('SetTypeRefCho','SetTRcho',lists:flatten(Bytes11)),
-
-
-
+ roundtrip('SetTRcho',
+ #'SetTRcho'{'setCho' = {choOs,<<"A string 1">>},
+ 'setChoE' = {choOs,<<"A string 3">>},
+ 'setCho-E' = {choOs,<<"A string 7">>},
+ 'setChoE-E' = {choOs,<<"A string 9">>}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetTypeRefCho', T, V).
diff --git a/lib/asn1/test/testSetTypeRefPrim.erl b/lib/asn1/test/testSetTypeRefPrim.erl
index 9c7fbd803e..d441fb789d 100644
--- a/lib/asn1/test/testSetTypeRefPrim.erl
+++ b/lib/asn1/test/testSetTypeRefPrim.erl
@@ -27,21 +27,17 @@
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetTypeRefPrim','SetTR',#'SetTR'{'octStr' = "A string 1",
- 'octStrI' = "A string 2",
- 'octStrE' = "A string 3",
- 'octStr-I' = "A string 4",
- 'octStrI-I' = "A string 5",
- 'octStrE-I' = "A string 6",
- 'octStr-E' = "A string 7",
- 'octStrI-E' = "A string 8",
- 'octStrE-E' = "A string 9"}),
- ?line {ok,{'SetTR',"A string 1","A string 2","A string 3","A string 4","A string 5","A string 6","A string 7","A string 8","A string 9"}} =
- asn1_wrapper:decode('SetTypeRefPrim','SetTR',lists:flatten(Bytes11)),
-
-
-
+ roundtrip('SetTR',
+ #'SetTR'{'octStr' = <<"A string 1">>,
+ 'octStrI' = <<"A string 2">>,
+ 'octStrE' = <<"A string 3">>,
+ 'octStr-I' = <<"A string 4">>,
+ 'octStrI-I' = <<"A string 5">>,
+ 'octStrE-I' = <<"A string 6">>,
+ 'octStr-E' = <<"A string 7">>,
+ 'octStrI-E' = <<"A string 8">>,
+ 'octStrE-E' = <<"A string 9">>}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetTypeRefPrim', T, V).
diff --git a/lib/asn1/test/testSetTypeRefSeq.erl b/lib/asn1/test/testSetTypeRefSeq.erl
index a3ef4b188d..a2b5f5745e 100644
--- a/lib/asn1/test/testSetTypeRefSeq.erl
+++ b/lib/asn1/test/testSetTypeRefSeq.erl
@@ -28,39 +28,27 @@
-record('SetSeqImp',{seqInt, seqOs}).
-record('SetSeqExp',{seqInt, seqOs}).
-
-
main(_Rules) ->
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetTypeRefSeq','SetTRseq',
- #'SetTRseq'{'setSeq' = #'SetSeq'{seqOs = "A1",
+ roundtrip('SetTRseq',
+ #'SetTRseq'{'setSeq' = #'SetSeq'{seqOs = <<"A1">>,
seqInt = 2},
- 'setSeqI' = #'SetSeq'{seqOs = "A2",
+ 'setSeqI' = #'SetSeq'{seqOs = <<"A2">>,
seqInt = 2},
- 'setSeqE' = #'SetSeq'{seqOs = "A3",
+ 'setSeqE' = #'SetSeq'{seqOs = <<"A3">>,
seqInt = 2},
- 'setSeq-I' = #'SetSeqImp'{seqOs = "A4",
+ 'setSeq-I' = #'SetSeqImp'{seqOs = <<"A4">>,
seqInt = 2},
- 'setSeqI-I' = #'SetSeqImp'{seqOs = "A5",
+ 'setSeqI-I' = #'SetSeqImp'{seqOs = <<"A5">>,
seqInt = 2},
- 'setSeqE-I' = #'SetSeqImp'{seqOs = "A6",
+ 'setSeqE-I' = #'SetSeqImp'{seqOs = <<"A6">>,
seqInt = 2},
- 'setSeq-E' = #'SetSeqExp'{seqOs = "A7",
+ 'setSeq-E' = #'SetSeqExp'{seqOs = <<"A7">>,
seqInt = 2},
- 'setSeqI-E' = #'SetSeqExp'{seqOs = "A8",
+ 'setSeqI-E' = #'SetSeqExp'{seqOs = <<"A8">>,
seqInt = 2},
- 'setSeqE-E' = #'SetSeqExp'{seqOs = "A9",
+ 'setSeqE-E' = #'SetSeqExp'{seqOs = <<"A9">>,
seqInt = 2}}),
- ?line {ok,{'SetTRseq',{'SetSeq',2,"A1"},
- {'SetSeq',2,"A2"},
- {'SetSeq',2,"A3"},
- {'SetSeqImp',2,"A4"},
- {'SetSeqImp',2,"A5"},
- {'SetSeqImp',2,"A6"},
- {'SetSeqExp',2,"A7"},
- {'SetSeqExp',2,"A8"},
- {'SetSeqExp',2,"A9"}}} =
- asn1_wrapper:decode('SetTypeRefSeq','SetTRseq',lists:flatten(Bytes41)),
-
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetTypeRefSeq', T, V).
diff --git a/lib/asn1/test/testSetTypeRefSet.erl b/lib/asn1/test/testSetTypeRefSet.erl
index ce77316ef8..80a6be58c9 100644
--- a/lib/asn1/test/testSetTypeRefSet.erl
+++ b/lib/asn1/test/testSetTypeRefSet.erl
@@ -46,131 +46,42 @@
main(_Rules) ->
-
-
- ?line {ok,Bytes11} =
- asn1_wrapper:encode('SetTypeRefSet','Set1',#'Set1'{bool1 = true,
- int1 = 15,
- set1 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'Set1',true,15,{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetTypeRefSet','Set1',lists:flatten(Bytes11)),
-
-
-
- ?line {ok,Bytes12} =
- asn1_wrapper:encode('SetTypeRefSet','Set2',#'Set2'{set2 = #'SetIn'{boolIn = true,
- intIn = 66},
- bool2 = true,
- int2 = 15}),
- ?line {ok,{'Set2',{'SetIn',true,66},true,15}} =
- asn1_wrapper:decode('SetTypeRefSet','Set2',lists:flatten(Bytes12)),
-
-
- ?line {ok,Bytes13} =
- asn1_wrapper:encode('SetTypeRefSet','Set3',#'Set3'{bool3 = true,
- set3 = #'SetIn'{boolIn = true,
- intIn = 66},
- int3 = 15}),
- ?line {ok,{'Set3',true,{'SetIn',true,66},15}} =
- asn1_wrapper:decode('SetTypeRefSet','Set3',lists:flatten(Bytes13)),
-
-
-
- ?line {ok,Bytes14} =
- asn1_wrapper:encode('SetTypeRefSet','Set4',#'Set4'{set41 = #'SetIn'{boolIn = true,
- intIn = 66},
- set42 = #'SetIn'{boolIn = true,
- intIn = 66},
- set43 = #'SetIn'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'Set4',{'SetIn',true,66},{'SetIn',true,66},{'SetIn',true,66}}} =
- asn1_wrapper:decode('SetTypeRefSet','Set4',lists:flatten(Bytes14)),
-
-
-
-
-
-
-
-
- ?line {ok,Bytes21} =
- asn1_wrapper:encode('SetTypeRefSet','SetS1',#'SetS1'{boolS1 = true,
- intS1 = 15,
- setS1 = #'SetS1_setS1'{boolIn = true,
- intIn = 66}}),
- ?line {ok,{'SetS1',true,15,{'SetS1_setS1',true,66}}} =
- asn1_wrapper:decode('SetTypeRefSet','SetS1',lists:flatten(Bytes21)),
-
-
- ?line {ok,Bytes22} =
- asn1_wrapper:encode('SetTypeRefSet','SetS2',#'SetS2'{setS2 = #'SetS2_setS2'{boolIn = true,
- intIn = 66},
- boolS2 = true,
- intS2 = 15}),
- ?line {ok,{'SetS2',{'SetS2_setS2',true,66},true,15}} =
- asn1_wrapper:decode('SetTypeRefSet','SetS2',lists:flatten(Bytes22)),
-
-
-
- ?line {ok,Bytes23} =
- asn1_wrapper:encode('SetTypeRefSet','SetS3',#'SetS3'{boolS3 = true,
- setS3 = #'SetS3_setS3'{boolIn = true,
- intIn = 66},
- intS3 = 15}),
- ?line {ok,{'SetS3',true,{'SetS3_setS3',true,66},15}} =
- asn1_wrapper:decode('SetTypeRefSet','SetS3',lists:flatten(Bytes23)),
-
-
-
-
-
-
- ?line {ok,Bytes31} =
- asn1_wrapper:encode('SetTypeRefSet','SetSTag',#'SetSTag'{setS1 = #'SetSTag_setS1'{b1 = true,
- i1 = 11},
- setS2 = #'SetSTag_setS2'{b2 = true,
- i2 = 22},
- setS3 = #'SetSTag_setS3'{b3 = true,
- i3 = 33}}),
- ?line {ok,{'SetSTag',{'SetSTag_setS1',true,11},
- {'SetSTag_setS2',true,22},
- {'SetSTag_setS3',true,33}}} =
- asn1_wrapper:decode('SetTypeRefSet','SetSTag',lists:flatten(Bytes31)),
-
-
-
-
-
- ?line {ok,Bytes41} =
- asn1_wrapper:encode('SetTypeRefSet','SetTRset',
- #'SetTRset'{'setSet' = #'SetSet'{setOs = "A1",
- setInt = 2},
- 'setSetI' = #'SetSet'{setOs = "A2",
- setInt = 2},
- 'setSetE' = #'SetSet'{setOs = "A3",
- setInt = 2},
- 'setSet-I' = #'SetSetImp'{setOs = "A4",
- setInt = 2},
- 'setSetI-I' = #'SetSetImp'{setOs = "A5",
- setInt = 2},
- 'setSetE-I' = #'SetSetImp'{setOs = "A6",
- setInt = 2},
- 'setSet-E' = #'SetSetExp'{setOs = "A7",
- setInt = 2},
- 'setSetI-E' = #'SetSetExp'{setOs = "A8",
- setInt = 2},
- 'setSetE-E' = #'SetSetExp'{setOs = "A9",
- setInt = 2}}),
- ?line {ok,{'SetTRset',{'SetSet',2,"A1"},
- {'SetSet',2,"A2"},
- {'SetSet',2,"A3"},
- {'SetSetImp',2,"A4"},
- {'SetSetImp',2,"A5"},
- {'SetSetImp',2,"A6"},
- {'SetSetExp',2,"A7"},
- {'SetSetExp',2,"A8"},
- {'SetSetExp',2,"A9"}}} =
- asn1_wrapper:decode('SetTypeRefSet','SetTRset',lists:flatten(Bytes41)),
+ roundtrip('Set1',
+ #'Set1'{bool1=true,int1=15,set1=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('Set2',
+ #'Set2'{set2=#'SetIn'{boolIn=true,intIn=66},bool2=true,int2=15}),
+ roundtrip('Set3',
+ #'Set3'{bool3=true,set3=#'SetIn'{boolIn=true,intIn=66},int3=15}),
+ roundtrip('Set4',
+ #'Set4'{set41=#'SetIn'{boolIn=true,intIn=66},
+ set42=#'SetIn'{boolIn=true,intIn=66},
+ set43=#'SetIn'{boolIn=true,intIn=66}}),
+ roundtrip('SetS1',
+ #'SetS1'{boolS1=true,intS1=15,
+ setS1=#'SetS1_setS1'{boolIn=true,intIn=66}}),
+ roundtrip('SetS2',
+ #'SetS2'{setS2=#'SetS2_setS2'{boolIn=true,intIn=66},
+ boolS2=true,intS2=15}),
+ roundtrip('SetS3',
+ #'SetS3'{boolS3=true,
+ setS3=#'SetS3_setS3'{boolIn=true,intIn=66},
+ intS3=15}),
+ roundtrip('SetSTag',
+ #'SetSTag'{setS1=#'SetSTag_setS1'{b1=true,i1=11},
+ setS2=#'SetSTag_setS2'{b2=true,i2=22},
+ setS3=#'SetSTag_setS3'{b3=true,i3=33}}),
+ roundtrip('SetTRset',
+ #'SetTRset'{setSet=#'SetSet'{setInt=2,setOs = <<"A1">>},
+ setSetI=#'SetSet'{setInt=2,setOs = <<"A2">>},
+ setSetE=#'SetSet'{setInt=2,setOs = <<"A3">>},
+ 'setSet-I'=#'SetSetImp'{setInt=2,setOs = <<"A4">>},
+ 'setSetI-I'=#'SetSetImp'{setInt=2,setOs = <<"A5">>},
+ 'setSetE-I'=#'SetSetImp'{setInt=2,setOs = <<"A6">>},
+ 'setSet-E'=#'SetSetExp'{setInt=2,setOs = <<"A7">>},
+ 'setSetI-E'=#'SetSetExp'{setInt=2,setOs = <<"A8">>},
+ 'setSetE-E'=#'SetSetExp'{setInt=2,setOs = <<"A9">>}}),
ok.
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SetTypeRefSet', T, V).
diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl
index aba13c94de..17511dc2b7 100644
--- a/lib/asn1/test/testTCAP.erl
+++ b/lib/asn1/test/testTCAP.erl
@@ -40,25 +40,26 @@ compile_asn1config(Config, Options) ->
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)),
+ {ok,_Res} = 'TCAPMessages-simple':decode('MessageType',
+ val_OTP_4798(Erule)),
+
%% testing OTP-4799, absent optional open type
- ?line {ok,_Res2} = asn1_wrapper:decode('TCAPMessages-simple','MessageType',val_OTP_4799(Erule)),
+ {ok,_Res2} = 'TCAPMessages-simple':decode('MessageType',
+ val_OTP_4799(Erule)),
+
%% testing vance shipley's problems. Parameterized object sets.
?line Val3 = 'TCAPPackage_msg':val('PackageType',unidirectional),
- ?line {ok,Bytes3} = asn1_wrapper:encode('TCAPPackage','PackageType',Val3),
- ?line {ok,Res3} = asn1_wrapper:decode('TCAPPackage','PackageType',Bytes3),
+ Res3 = enc_dec('PackageType', Val3),
?line ok = 'TCAPPackage_msg':check_result('PackageType',unidirectional,Res3),
%% ?line io:format("Res3:~n~p~n~n",[Res3]),
?line Val4 = 'TCAPPackage_msg':val('PackageType',abort),
- ?line {ok,Bytes4} = asn1_wrapper:encode('TCAPPackage','PackageType',Val4),
- ?line {ok,Res4} = asn1_wrapper:decode('TCAPPackage','PackageType',Bytes4),
+ Res4 = enc_dec('PackageType', Val4),
?line ok = 'TCAPPackage_msg':check_result('PackageType',abort,Res4),
%% ?line io:format("Res4:~n~p~n~n",[Res4]),
?line Val5 = 'TCAPPackage_msg':val('PackageType',response),
- ?line {ok,Bytes5} = asn1_wrapper:encode('TCAPPackage','PackageType',Val5),
- ?line {ok,Res5} = asn1_wrapper:decode('TCAPPackage','PackageType',Bytes5),
+ Res5 = enc_dec('PackageType', Val5),
?line ok = 'TCAPPackage_msg':check_result('PackageType',response,Res5).
%% ?line io:format("Res5:~n~p~n~n",[Res5]).
@@ -73,21 +74,26 @@ val_OTP_4799(_) ->
<<100,16,73,4,41,182,36,0,108,8,163,6,2,1,29,2,1,27>>.
test_asn1config() ->
- ?line Val = 'TCAPPackage_msg':val('PackageType',queryWithPerm),
- ?line {ok,B} = asn1_wrapper:encode('TCAPPackage','PackageType',Val),
- ?line {ok,ExMsg}='TCAPPackage':decode_PackageType(list_to_binary(B)),
- ?line {_,{_,_,_,{Key,ExVal}}}=ExMsg,
- ?line {ok,_Parts}='TCAPPackage':decode_part(Key,ExVal),
+ Val = 'TCAPPackage_msg':val('PackageType', queryWithPerm),
+ {ok,B} = 'TCAPPackage':encode('PackageType', Val),
+ {ok,ExMsg}='TCAPPackage':decode_PackageType(B),
+ {_,{_,_,_,{Key,ExVal}}} = ExMsg,
+ {ok,_Parts} = 'TCAPPackage':decode_part(Key, ExVal),
- ?line Val2 = 'TCAPPackage_msg':val('TransactionPDU'),
- ?line {ok,B2} = 'TCAPPackage':encode('TransactionPDU',Val2),
- {ok,ExMsg2}='TCAPPackage':decode_TransactionPDU(B2),
- ?line {_,_,_,{Key2,ExVal2}}=ExMsg2,
- ?line {ok,_Parts2}='TCAPPackage':decode_part(Key2,ExVal2),
+ Val2 = 'TCAPPackage_msg':val('TransactionPDU'),
+ {ok,B2} = 'TCAPPackage':encode('TransactionPDU', Val2),
+ {ok,ExMsg2} = 'TCAPPackage':decode_TransactionPDU(B2),
+ {_,_,_,{Key2,ExVal2}} = ExMsg2,
+ {ok,_Parts2} = 'TCAPPackage':decode_part(Key2, ExVal2),
- ?line Val3 = 'TCAPPackage_msg':val('PackageType',response),
- ?line {ok,B3} = asn1_wrapper:encode('TCAPPackage','PackageType',Val3),
- ?line {ok,ExMsg3}='TCAPPackage':decode_PackageType(list_to_binary(B3)),
- ?line {_,{_,_,_,{Key3,ExVal3}}}=ExMsg3,
- ?line {ok,_Parts3}='TCAPPackage':decode_part(Key3,ExVal3).
+ Val3 = 'TCAPPackage_msg':val('PackageType', response),
+ {ok,B3} = 'TCAPPackage':encode('PackageType', Val3),
+ {ok,ExMsg3} = 'TCAPPackage':decode_PackageType(B3),
+ {_,{_,_,_,{Key3,ExVal3}}} = ExMsg3,
+ {ok,_Parts3}='TCAPPackage':decode_part(Key3, ExVal3).
+enc_dec(T, V0) ->
+ M = 'TCAPPackage',
+ {ok,Enc} = M:encode(T, V0),
+ {ok,V} = M:decode(T, Enc),
+ V.
diff --git a/lib/asn1/test/testTcapsystem.erl b/lib/asn1/test/testTcapsystem.erl
index 4979a385b2..fcc9e084e0 100644
--- a/lib/asn1/test/testTcapsystem.erl
+++ b/lib/asn1/test/testTcapsystem.erl
@@ -21,44 +21,42 @@
-export([compile/2]).
--include_lib("test_server/include/test_server.hrl").
-
compile(Config, Options) ->
- [asn1_test_lib:compile(filename:join([tcapsystem, M]), Config, Options)
- || M <- ["DialoguePDUs.asn",
- "MAP-ApplicationContexts.asn",
- "MAP-BS-Code.asn",
- "MAP-CallHandlingOperations.asn",
- "MAP-CH-DataTypes.asn",
- "MAP-CommonDataTypes.asn",
- "MAP-DialogueInformation.asn",
- "MAP-ER-DataTypes.asn",
- "MAP-Errors.asn",
- "MAP-ExtensionDataTypes.asn",
- "MAP-GR-DataTypes.asn",
- "MAP-Group-Call-Operations.asn",
- "MAP-LCS-DataTypes.asn",
- "MAP-LocationServiceOperations.asn",
- "MAP-MobileServiceOperations.asn",
- "MAP-MS-DataTypes.asn",
- "MAP-OM-DataTypes.asn",
- "MAP-OperationAndMaintenanceOperations.asn",
- "MAP-Protocol.asn",
- "MAP-SecureTransportOperations.asn",
- "MAP-ShortMessageServiceOperations.asn",
- "MAP-SM-DataTypes.asn",
- "MAP-SS-Code.asn",
- "MAP-SS-DataTypes.asn",
- "MAP-ST-DataTypes.asn",
- "MAP-SupplementaryServiceOperations.asn",
- "MAP-TS-Code.asn",
- "MobileDomainDefinitions.asn",
- "Remote-Operations-Generic-ROS-PDUs.asn",
- "Remote-Operations-Information-Objects.asn",
- "Remote-Operations-Useful-Definitions.asn",
- "TCAP-Examples.asn",
- "TCAPMessages.asn",
- "TCAP-Tools.asn",
- "TC-Notation-Extensions.asn",
- "UnidialoguePDUs.asn"]],
- ok.
+ Fs = [filename:join("tcapsystem", M) ||
+ M <- ["DialoguePDUs.asn",
+ "MAP-ApplicationContexts.asn",
+ "MAP-BS-Code.asn",
+ "MAP-CallHandlingOperations.asn",
+ "MAP-CH-DataTypes.asn",
+ "MAP-CommonDataTypes.asn",
+ "MAP-DialogueInformation.asn",
+ "MAP-ER-DataTypes.asn",
+ "MAP-Errors.asn",
+ "MAP-ExtensionDataTypes.asn",
+ "MAP-GR-DataTypes.asn",
+ "MAP-Group-Call-Operations.asn",
+ "MAP-LCS-DataTypes.asn",
+ "MAP-LocationServiceOperations.asn",
+ "MAP-MobileServiceOperations.asn",
+ "MAP-MS-DataTypes.asn",
+ "MAP-OM-DataTypes.asn",
+ "MAP-OperationAndMaintenanceOperations.asn",
+ "MAP-Protocol.asn",
+ "MAP-SecureTransportOperations.asn",
+ "MAP-ShortMessageServiceOperations.asn",
+ "MAP-SM-DataTypes.asn",
+ "MAP-SS-Code.asn",
+ "MAP-SS-DataTypes.asn",
+ "MAP-ST-DataTypes.asn",
+ "MAP-SupplementaryServiceOperations.asn",
+ "MAP-TS-Code.asn",
+ "MobileDomainDefinitions.asn",
+ "Remote-Operations-Generic-ROS-PDUs.asn",
+ "Remote-Operations-Information-Objects.asn",
+ "Remote-Operations-Useful-Definitions.asn",
+ "TCAP-Examples.asn",
+ "TCAPMessages.asn",
+ "TCAP-Tools.asn",
+ "TC-Notation-Extensions.asn",
+ "UnidialoguePDUs.asn"]],
+ asn1_test_lib:compile_all(Fs, Config, Options).
diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl
index cd7ceb5630..89bc2b463d 100644
--- a/lib/asn1/test/testTimer.erl
+++ b/lib/asn1/test/testTimer.erl
@@ -18,166 +18,141 @@
%%
%%
-module(testTimer).
-
--compile(export_all).
-%%-export([Function/Arity, ...]).
+-export([go/0]).
-include_lib("test_server/include/test_server.hrl").
-define(times, 5000).
val() ->
- _Value = {'H323-UserInformation',{'H323-UU-PDU',
- {callProceeding,
- {'CallProceeding-UUIE',
- {0,8,222},
- {'EndpointType',
- {'NonStandardParameter',
- {object,{0,9,237}},
- "O"},
- {'VendorIdentifier',
- {'H221NonStandard',62,63,16282},
- "OC",
- "OC"},
- {'GatekeeperInfo',
- {'NonStandardParameter',
- {object,{0,10,260}},
- "O"}},
- {'GatewayInfo',
- [{h320,
- {'H320Caps',
- {'NonStandardParameter',
- {object,{0,11,282}},
- "O"},
- [{'DataRate',
- {'NonStandardParameter',
- {object,
- {0,11,295}},
- "O"},
- 1290470518,
- 78}],
- [{'SupportedPrefix',
- {'NonStandardParameter',
- {object,
- {0,12,312}},
- "O"},
- {'h323-ID',"BM"}}]}}],
- {'NonStandardParameter',
- {object,{0,13,326}},
- "O"}},
- {'McuInfo',
- {'NonStandardParameter',
- {object,{1,13,340,340}},
- "OC"}},
- {'TerminalInfo',
- {'NonStandardParameter',
- {object,{1,14,353,354}},
- "OC"}},
- true,
- true},
- {ipxAddress,
- {'TransportAddress_ipxAddress',
- "OCTET ",
- "OCTE",
- "OC"}},
- {'CallIdentifier',"OCTET STRINGOCTE"},
- {noSecurity,'NULL'},
- [{'ClearToken',
- 1667517741,
- "BM",
- {'DHset',[1],[1],[1]},
- "OCTET STR",
- -26430296,
- {'TypedCertificate',
- {1,16,405,406},
- "OC"},
- "BMP",
- {'NonStandardParameter',
- {1,16,414,415},
- "OC"}},
- {'ClearToken',
- 1817656756,
- "BMP",
- {'DHset',[1],[1],[1]},
- "OCTET STRI",
- -16356110,
- {'TypedCertificate',
- {1,17,442,443},
- "OC"},
- "BMP",
- {'NonStandardParameter',
- {1,18,452,452},
- "OC"}}],
- [{cryptoGKPwdEncr,
- {'CryptoH323Token_cryptoGKPwdEncr',
- {1,18,467,467},
- {'Params',-7477016,"OCTET ST"},
- "OC"}},
- {cryptoGKPwdEncr,
- {'CryptoH323Token_cryptoGKPwdEncr',
- {1,19,486,486},
- {'Params',-2404513,"OCTET ST"},
- []}}],
- []}},
- {'NonStandardParameter',{object,{0,3,84}},[]},
- [],
- true,
- [],
- []},
- {'H323-UserInformation_user-data',24,"O"}}.
+ {'H323-UserInformation',{'H323-UU-PDU',
+ {callProceeding,
+ {'CallProceeding-UUIE',
+ {0,8,222},
+ {'EndpointType',
+ {'NonStandardParameter',
+ {object,{0,9,237}},
+ <<"O">>},
+ {'VendorIdentifier',
+ {'H221NonStandard',62,63,16282},
+ <<"OC">>,
+ <<"OC">>},
+ {'GatekeeperInfo',
+ {'NonStandardParameter',
+ {object,{0,10,260}},
+ <<"O">>}},
+ {'GatewayInfo',
+ [{h320,
+ {'H320Caps',
+ {'NonStandardParameter',
+ {object,{0,11,282}},
+ <<"O">>},
+ [{'DataRate',
+ {'NonStandardParameter',
+ {object,
+ {0,11,295}},
+ <<"O">>},
+ 1290470518,
+ 78}],
+ [{'SupportedPrefix',
+ {'NonStandardParameter',
+ {object,
+ {0,12,312}},
+ <<"O">>},
+ {'h323-ID',"BM"}}]}}],
+ {'NonStandardParameter',
+ {object,{0,13,326}},
+ <<"O">>}},
+ {'McuInfo',
+ {'NonStandardParameter',
+ {object,{1,13,340,340}},
+ <<"OC">>}},
+ {'TerminalInfo',
+ {'NonStandardParameter',
+ {object,{1,14,353,354}},
+ <<"OC">>}},
+ true,
+ true},
+ {ipxAddress,
+ {'TransportAddress_ipxAddress',
+ <<"OCTET ">>,
+ <<"OCTE">>,
+ <<"OC">>}},
+ {'CallIdentifier',<<"OCTET STRINGOCTE">>},
+ {noSecurity,'NULL'},
+ [{'ClearToken',
+ 1667517741,
+ "BM",
+ {'DHset',<<1:1>>,<<1:1>>,<<1:1>>},
+ <<"OCTET STR">>,
+ -26430296,
+ {'TypedCertificate',
+ {1,16,405,406},
+ <<"OC">>},
+ "BMP",
+ {'NonStandardParameter',
+ {1,16,414,415},
+ <<"OC">>}},
+ {'ClearToken',
+ 1817656756,
+ "BMP",
+ {'DHset',<<1:1>>,<<1:1>>,<<1:1>>},
+ <<"OCTET STRI">>,
+ -16356110,
+ {'TypedCertificate',
+ {1,17,442,443},
+ <<"OC">>},
+ "BMP",
+ {'NonStandardParameter',
+ {1,18,452,452},
+ <<"OC">>}}],
+ [{cryptoGKPwdEncr,
+ {'CryptoH323Token_cryptoGKPwdEncr',
+ {1,18,467,467},
+ {'Params',-7477016,<<"OCTET ST">>},
+ <<"OC">>}},
+ {cryptoGKPwdEncr,
+ {'CryptoH323Token_cryptoGKPwdEncr',
+ {1,19,486,486},
+ {'Params',-2404513,<<"OCTET ST">>},
+ <<>>}}],
+ []}},
+ {'NonStandardParameter',{object,{0,3,84}},<<>>},
+ [],
+ true,
+ [],
+ []},
+ {'H323-UserInformation_user-data',24,<<"O">>}}.
-go(Config,Enc) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
+go() ->
Module = 'H323-MESSAGES',
Type = 'H323-UserInformation',
Value = val(),
- {ok,Bytes} = asn1rt:encode(Module,Type,Value),
-
- CompileOptions = compile_options(),
-
- ?line {ValWr, done} = timer:tc(?MODULE, encode, [?times, Module, Type, Value]),
- ?line io:format("ASN1 encode ~p: ~p micro~n", [CompileOptions, ValWr / ?times]),
+ Bytes = Module:encode(Type, Value),
+ Value = Module:decode(Type, Bytes),
- ?line done = decode(2,Module,Type,Bytes,Enc),
+ {ValWr,done} = timer:tc(fun() -> encode(?times, Module, Type, Value) end),
+ io:format("ASN.1 encoding: ~p micro~n", [ValWr / ?times]),
- ?line {ValRead, done} = timer:tc(?MODULE, decode, [?times, Module,
- Type, Bytes,Enc]),
- ?line io:format("ASN1 decode ~p: ~p micro~n", [CompileOptions, ValRead /?times]),
+ done = decode(2, Module, Type, Bytes),
+ {ValRead,done} = timer:tc(fun() -> decode(?times, Module, Type, Bytes) end),
+ io:format("ASN.1 decoding: ~p micro~n", [ValRead /?times]),
- ?line Comment = "encode: "++integer_to_list(round(ValWr/?times))++
- " micro, decode: "++integer_to_list(round(ValRead /?times))++
- " micro. " ++ CompileOptions,
+ Comment = "encode: "++integer_to_list(round(ValWr/?times)) ++
+ " micro, decode: "++integer_to_list(round(ValRead /?times)) ++
+ " micro. [" ++ atom_to_list(Module:encoding_rule()) ++ "]",
{comment,Comment}.
encode(0, _Module,_Type,_Value) ->
done;
encode(N, Module,Type,Value) ->
- ?line {ok,B} = asn1rt:encode(Module,Type,Value),
- _B2 = if
- is_list(B) -> list_to_binary(B);
- true -> B
- end,
- encode(N-1, Module,Type,Value).
+ Module:encode(Type, Value),
+ encode(N-1, Module, Type, Value).
-decode(0, _Module,_Type,_Value,_Erule) ->
+decode(0, _Module, _Type, _Value) ->
done;
-decode(N, Module,Type,Value,Erule) ->
- {ok,_B} = asn1rt:decode(Module,Type,Value),
- decode(N-1, Module,Type,Value,Erule).
-
-compile_options() ->
- {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.
-
+decode(N, Module, Type, Value) ->
+ Module:decode(Type, Value),
+ decode(N-1, Module, Type, Value).
diff --git a/lib/asn1/test/testTypeValueNotation.erl b/lib/asn1/test/testTypeValueNotation.erl
index 61d69edd0e..2b5f3f74c1 100644
--- a/lib/asn1/test/testTypeValueNotation.erl
+++ b/lib/asn1/test/testTypeValueNotation.erl
@@ -24,13 +24,15 @@
-record('Seq', {octstr, int, bool, enum, bitstr, null, oid, vstr}).
main(_Rule, _Option) ->
- Value1 = #'Seq'{octstr = [1, 2, 3, 4],
- int = 12,
- bool = true,
- enum = a,
- bitstr = <<2#1010:4>>,
- null = 'NULL',
- oid = {1, 2, 55},
- vstr = "Hello World"},
- {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1),
- {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes).
+ Value = #'Seq'{octstr = <<1,2,3,4>>,
+ int = 12,
+ bool = true,
+ enum = a,
+ bitstr = <<2#1010:4>>,
+ null = 'NULL',
+ oid = {1, 2, 55},
+ vstr = "Hello World"},
+ roundtrip('Seq', Value).
+
+roundtrip(T, V) ->
+ asn1_test_lib:roundtrip('SeqTypeRefPrim', T, V).
diff --git a/lib/asn1/test/testWSParamClass.erl b/lib/asn1/test/testWSParamClass.erl
index ae67ca8b81..66ba56a6d8 100644
--- a/lib/asn1/test/testWSParamClass.erl
+++ b/lib/asn1/test/testWSParamClass.erl
@@ -11,7 +11,4 @@ main(_) ->
ok.
roundtrip(Data) ->
- IF = 'InformationFramework',
- {ok,Enc} = asn1_wrapper:encode(IF, 'Attribute', Data),
- {ok,Data} = IF:decode('Attribute', Enc),
- ok.
+ asn1_test_lib:roundtrip('InformationFramework', 'Attribute', Data).
diff --git a/lib/asn1/test/testX420.erl b/lib/asn1/test/testX420.erl
index 70bdb0640d..4ddc55dc16 100644
--- a/lib/asn1/test/testX420.erl
+++ b/lib/asn1/test/testX420.erl
@@ -27,21 +27,11 @@
compile(Erule, Options, Config) ->
- Specs = specs(),
- 99 = length(Specs),
- ok = compile_loop(Erule,Specs,Options,Config).
-
-compile_loop(_Erule, [], _Options, _Config) ->
- ok;
-compile_loop(Erule, [Spec|Specs], Options, Config)
- when Erule =:= ber; Erule =:= per ->
+ Specs0 = specs(),
+ 99 = length(Specs0),
CaseDir = ?config(case_dir, Config),
- asn1_test_lib:compile(filename:join([x420, Spec]), Config,
- [Erule, {i, CaseDir} | Options]),
- compile_loop(Erule, Specs, Options, Config);
-compile_loop(_Erule, _Specs, _Options, _Config) ->
- ok.
-
+ Specs = [filename:join(x420, Spec) || Spec <- Specs0],
+ asn1_test_lib:compile_all(Specs, Config, [Erule,{i,CaseDir}|Options]).
specs() ->
["ACSE-1", "AuthenticationFramework", "BasicAccessControl",
@@ -93,9 +83,9 @@ specs() ->
ticket7759(_Erule,_Config) ->
Encoded = encoded_msg(),
io:format("Testing ticket7759 ...~n",[]),
- ?line {ok, ContentInfo} = asn1_wrapper:decode('PKCS7','ContentInfo',Encoded),
- ?line {'ContentInfo',_Id,PKCS7_content} = ContentInfo,
- ?line {ok,_} = asn1_wrapper:decode('PKCS7','SignedData',PKCS7_content),
+ {ok, ContentInfo} = 'PKCS7':decode('ContentInfo',Encoded),
+ {'ContentInfo',_Id,PKCS7_content} = ContentInfo,
+ {ok,_} = 'PKCS7':decode('SignedData',PKCS7_content),
ok.
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 179299c78d..7f358e863c 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -123,7 +123,7 @@ verbose(Config) when is_list(Config) ->
?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]),
?line test_server:capture_stop(),
?line [Line0|_] = test_server:capture_get(),
- ?line true = lists:prefix("Erlang ASN.1 version", Line0),
+ ?line true = lists:prefix("Erlang ASN.1 compiler", Line0),
%% Test non-verbose compile
?line test_server:capture_start(),
diff --git a/lib/asn1/test/test_driver_load.erl b/lib/asn1/test/test_driver_load.erl
deleted file mode 100644
index e0e6602046..0000000000
--- a/lib/asn1/test/test_driver_load.erl
+++ /dev/null
@@ -1,45 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-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_driver_load).
-
--export([test/1,encode/0]).
-
--include_lib("test_server/include/test_server.hrl").
-
-
-test(0) ->
- ok;
-test(N) ->
- spawn(?MODULE,encode,[]),
- test(N-1).
-
-encode() ->
- ?line Msg = msg(),
- ?line {ok,_}=asn1_wrapper:encode('P-Record','PersonnelRecord',Msg),
- ok.
-
-msg() ->
- {'PersonnelRecord',{'Name',"John","P","Smith"},
- "Director",
- 51,
- "19710917",
- {'Name',"Mary","T","Smith"},
- [{'ChildInformation',{'Name',"Ralph","T","Smith"},"19571111"},{'ChildInformation',{'Name',"Susan","B","Jones"},"19590717"}]}.
-
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index a525fd6ae1..0df72a1831 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -26,8 +26,9 @@ test(Config) ->
DataDir = ?config(data_dir,Config),
Der = read_pem(filename:join([DataDir,modified_x420,"p7_signed_data.pem"])),
- {ok,{_,_,SignedData}} = asn1_wrapper:decode('PKCS7', 'ContentInfo', Der),
- {ok,_} = asn1_wrapper:decode('PKCS7', 'SignedData', SignedData).
+ {ok,{_,_,SignedData}} = 'PKCS7':decode( 'ContentInfo', Der),
+ {ok,_} = 'PKCS7':decode('SignedData', SignedData),
+ ok.
read_pem(File) ->
{ok,Bin} = file:read_file(File),
diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl
index 8ede06938d..4a8a4cd74c 100644
--- a/lib/asn1/test/test_partial_incomplete_decode.erl
+++ b/lib/asn1/test/test_partial_incomplete_decode.erl
@@ -25,84 +25,57 @@
test(Config) ->
FMsg = msg('F'),
- ?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq','F',Bytes),
- ?line {ok,IncFMsg} =
- 'PartialDecSeq':decode_F_fb_incomplete(list_to_binary(Bytes)),
- ?line decode_parts('F',IncFMsg),
+ Bytes1 = roundtrip('PartialDecSeq', 'F', FMsg),
+ {ok,IncFMsg} = 'PartialDecSeq':decode_F_fb_incomplete(Bytes1),
+ decode_parts('F', IncFMsg),
+ {ok,IncF2Msg} = 'PartialDecSeq':decode_F_fb_exclusive2(Bytes1),
+ decode_parts('F2', IncF2Msg),
DMsg = msg('D'),
- ?line {ok,Bytes2} = asn1_wrapper:encode('PartialDecSeq','D',DMsg),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq','D',Bytes2),
- ?line {ok,IncDMsg} =
- 'PartialDecSeq':decode_D_incomplete(list_to_binary(Bytes2)),
- ?line decode_parts('D',IncDMsg),
-
- ?line {ok,IncF2Msg} =
- 'PartialDecSeq':decode_F_fb_exclusive2(list_to_binary(Bytes)),
- ?line decode_parts('F2',IncF2Msg),
+ Bytes2 = roundtrip('PartialDecSeq', 'D', DMsg),
+ {ok,IncDMsg} = 'PartialDecSeq':decode_D_incomplete(Bytes2),
+ decode_parts('D', IncDMsg),
F3Msg = msg('F3'),
- ?line {ok,BytesF3} = asn1_wrapper:encode('PartialDecSeq','F',F3Msg),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq','F',BytesF3),
- ?line {ok,IncF3Msg} =
- 'PartialDecSeq':decode_F_fb_exclusive3(list_to_binary(BytesF3)),
- ?line decode_parts('F3',IncF3Msg),
-
-
- AMsg =msg('A'),
- ?line {ok,Bytes3} = asn1_wrapper:encode('PartialDecSeq2','A',AMsg),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq2','A',Bytes3),
- ?line {ok,IncFMsg3} =
- 'PartialDecSeq2':decode_A_c_b_incomplete(list_to_binary(Bytes3)),
- ?line decode_parts('A',IncFMsg3),
+ BytesF3 = roundtrip('PartialDecSeq', 'F', F3Msg),
+ {ok,IncF3Msg} = 'PartialDecSeq':decode_F_fb_exclusive3(BytesF3),
+ decode_parts('F3', IncF3Msg),
+
+ AMsg = msg('A'),
+ Bytes3 = roundtrip('PartialDecSeq2', 'A', AMsg),
+ {ok,IncFMsg3} = 'PartialDecSeq2':decode_A_c_b_incomplete(Bytes3),
+ decode_parts('A', IncFMsg3),
MyHTTPMsg = msg('GetRequest'),
- ?line {ok,Bytes4} = asn1_wrapper:encode('PartialDecMyHTTP',
- 'GetRequest',MyHTTPMsg),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecMyHTTP','GetRequest',
- Bytes4),
- ?line {ok,IncFMsg4} =
- 'PartialDecMyHTTP':decode_GetRequest_incomplete(list_to_binary(Bytes4)),
- ?line decode_parts('GetRequest',IncFMsg4),
+ Bytes4 = roundtrip('PartialDecMyHTTP', 'GetRequest', MyHTTPMsg),
+ {ok,IncFMsg4} = 'PartialDecMyHTTP':decode_GetRequest_incomplete(Bytes4),
+ decode_parts('GetRequest', IncFMsg4),
MsgS1_1 = msg('S1_1'),
- ?line {ok,Bytes5} = asn1_wrapper:encode('PartialDecSeq3','S1',MsgS1_1),
- ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq3','S1',Bytes5),
- ?line {ok,IncFMsg5} =
- 'PartialDecSeq3':decode_S1_incomplete(list_to_binary(Bytes5)),
- ?line decode_parts('S1_1',IncFMsg5),
+ Bytes5 = roundtrip('PartialDecSeq3', 'S1', MsgS1_1),
+ {ok,IncFMsg5} = 'PartialDecSeq3':decode_S1_incomplete(Bytes5),
+ decode_parts('S1_1', IncFMsg5),
MsgS1_2 = msg('S1_2'),
- ?line {ok,Bytes6} = asn1_wrapper:encode('PartialDecSeq3','S1',MsgS1_2),
- ?line {ok,IncFMsg6} =
- 'PartialDecSeq3':decode_S1_incomplete(list_to_binary(Bytes6)),
- ?line ok = decode_parts('S1_2',IncFMsg6),
+ Bytes6 = roundtrip('PartialDecSeq3', 'S1', MsgS1_2),
+ {ok,IncFMsg6} = 'PartialDecSeq3':decode_S1_incomplete(Bytes6),
+ decode_parts('S1_2', IncFMsg6),
%% test of MEDIA-GATEWAY-CONTROL
test_megaco(Config),
ok.
test_megaco(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- Mod='MEDIA-GATEWAY-CONTROL',
- ?line {ok,FilenameList} = file:list_dir(filename:join([DataDir,
- megacomessages])),
- %% remove any junk files that may be in the megacomessage directory
- Pred = fun(X) ->
- case lists:reverse(X) of
- [$l,$a,$v,$.|_R] ->true;
- _ -> false
- end
- end,
- MegacoMsgFilenameList = lists:filter(Pred,FilenameList),
- Fun = fun(F) ->
- M = read_msg(filename:join([DataDir,megacomessages,F])),
- ?line {ok,B} = asn1_wrapper:encode(Mod,element(1,M),M),
- ?line exclusive_decode(list_to_binary(B),F)
- end,
- ?line lists:foreach(Fun,MegacoMsgFilenameList),
- ok.
+ DataDir = ?config(data_dir, Config),
+ Files = filelib:wildcard(filename:join([DataDir,megacomessages,"*.val"])),
+ Mod = 'MEDIA-GATEWAY-CONTROL',
+ lists:foreach(fun(File) ->
+ {ok,Bin} = file:read_file(File),
+ V = binary_to_term(Bin),
+ T = element(1, V),
+ Enc = roundtrip(Mod, T, V),
+ exclusive_decode(Enc, File)
+ end, Files).
exclusive_decode(Bin,F) ->
Mod='MEDIA-GATEWAY-CONTROL',
@@ -113,15 +86,6 @@ exclusive_decode(Bin,F) ->
?line {ok,_} = Mod:decode_part(MsgMBodyKey,MsgMBody),
ok.
-
-read_msg(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- binary_to_term(Bin);
- _ ->
- io:format("couldn't read file ~p~n",[File])
- end.
-
decode_parts('F',PartDecMsg) ->
?line {fb,{'E',35,{NameE_b,ListBinE_b},false,{NameE_d,BinE_d}}} = PartDecMsg,
?line {ok,[{'D',3,true}|_]} = 'PartialDecSeq':decode_part(NameE_b,ListBinE_b),
@@ -200,7 +164,10 @@ msg('A') ->
{'A',12,{c,{'S',true,false}},{b,{'A_c_b',false,false}}};
msg('GetRequest') ->
- {'GetRequest',true,false,{'AcceptTypes',[1,1,1,1],["hell","othe","reho","peyo","uare","fine"]},"IamfineThankYOu"};
+ {'GetRequest',true,false,
+ {'AcceptTypes',[html,'plain-text',gif,jpeg],
+ ["hell","othe","reho","peyo","uare","fine"]},
+ "IamfineThankYOu"};
msg('S1_1') ->
{'S1',14,msg('S2'),msg('C1_a'),msg('SO1')};
@@ -213,10 +180,13 @@ msg('C1_a') ->
msg('C1_b') ->
{b,{'C1_b',11,true,msg('S4')}};
msg('S3') ->
- {'S3',10,"PrintableString","OCTETSTRING",[1,1,1,1]};
+ {'S3',10,"PrintableString","OCTETSTRING",[one,two,three,four]};
msg('S4') ->
{'S4',msg('Name'),"MSc"};
msg('SO1') ->
[msg('Name'),msg('Name'),msg('Name')];
msg('Name') ->
{'Name',"Hans","HCA","Andersen"}.
+
+roundtrip(M, T, V) ->
+ asn1_test_lib:roundtrip_enc(M, T, V).
diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl
index ebe1296cf3..f42f24e0e3 100644
--- a/lib/asn1/test/test_selective_decode.erl
+++ b/lib/asn1/test/test_selective_decode.erl
@@ -18,39 +18,39 @@
%%
%%
-module(test_selective_decode).
-
-export([test/0]).
-include_lib("test_server/include/test_server.hrl").
-
test() ->
FMsg = msg('F'),
- ?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg),
- ?line {ok,3} =
- 'PartialDecSeq':selected_decode_F1(list_to_binary(Bytes)),
- ?line {ok,[{'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}]} = 'PartialDecSeq':selected_decode_F2(list_to_binary(Bytes)),
- ?line {ok,{'D',3,true}} = 'PartialDecSeq':selected_decode_F3(list_to_binary(Bytes)),
-
- ?line {ok,17} = 'PartialDecSeq':selected_decode_F4(list_to_binary(Bytes)),
+ Bytes = roundtrip('PartialDecSeq', 'F', FMsg),
+ {ok,3} = 'PartialDecSeq':selected_decode_F1(Bytes),
+ {ok,[{'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}]} =
+ 'PartialDecSeq':selected_decode_F2(Bytes),
+ {ok,{'D',3,true}} = 'PartialDecSeq':selected_decode_F3(Bytes),
+ {ok,17} = 'PartialDecSeq':selected_decode_F4(Bytes),
EMsg = msg('E'),
- ?line {ok,Bytes2} = asn1_wrapper:encode('PartialDecSeq','E',EMsg),
- ?line {ok,14} = 'PartialDecSeq':selected_decode_E1(list_to_binary(Bytes2)),
+ Bytes2 = roundtrip('PartialDecSeq', 'E', EMsg),
+ {ok,14} = 'PartialDecSeq':selected_decode_E1(Bytes2),
+
MGCMsg = msg('M-G-C'),
- ?line {ok,Bytes3} = asn1_wrapper:encode('MEDIA-GATEWAY-CONTROL',
- 'MegacoMessage',MGCMsg),
- ?line {ok,1} = 'MEDIA-GATEWAY-CONTROL':decode_MegacoMessage_selective(list_to_binary(Bytes3)),
+ Bytes3 = roundtrip('MEDIA-GATEWAY-CONTROL', 'MegacoMessage', MGCMsg),
+ {ok,1} = 'MEDIA-GATEWAY-CONTROL':decode_MegacoMessage_selective(Bytes3),
PRecMsg = {'PersonnelRecord',{'Name',"Sven","S","Svensson"},
"manager",123,"20000202",{'Name',"Inga","K","Svensson"},
asn1_DEFAULT},
- ?line {ok,Bytes4} = asn1_wrapper:encode('P-Record','PersonnelRecord',
- PRecMsg),
- ?line {ok,_} = 'P-Record':sel_dec(list_to_binary(Bytes4)),
- ok.
-
+ PRecMsgDec = {'PersonnelRecord',{'Name',"Sven","S","Svensson"},
+ "manager",123,"20000202",{'Name',"Inga","K","Svensson"},
+ []},
+ Bytes4 = roundtrip('P-Record', 'PersonnelRecord', PRecMsg, PRecMsgDec),
+ {ok,_} = 'P-Record':sel_dec(Bytes4),
+ ok.
msg('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}}]}}};
@@ -60,3 +60,10 @@ msg('E') ->
msg('M-G-C') ->
{'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]]}]}]}}}]}]}}}]}}}.
+
+
+roundtrip(M, T, V) ->
+ asn1_test_lib:roundtrip_enc(M, T, V).
+
+roundtrip(M, T, V, E) ->
+ asn1_test_lib:roundtrip_enc(M, T, V, E).
diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl
index 7dfab1f25a..0f52ae4cd2 100644
--- a/lib/asn1/test/test_special_decode_performance.erl
+++ b/lib/asn1/test/test_special_decode_performance.erl
@@ -19,7 +19,7 @@
%%
-module(test_special_decode_performance).
--export([go/1,loop2/4,loop1/5]).
+-export([go/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -49,7 +49,7 @@ go1(_,_,[],_,_,AccTime) ->
%% go1 for common decode
go1(common,Mod,_,Bin,N,_) ->
?line TT=get_top_type(Mod),
- ?line {Time,Result}=timer:tc(?MODULE,loop1,[Mod,decode,TT,Bin,N]),
+ {Time,Result} = timer:tc(fun() -> loop1(Mod, decode, TT, Bin, N) end),
case Result of
{ok,_R1} ->
io:format("common Decode ~p:decode, ~p times on time ~p~n",
@@ -59,7 +59,7 @@ go1(common,Mod,_,Bin,N,_) ->
end,
Time;
go1(Dec,Mod,[F|Fs],Bin,N,AccTime) ->
- ?line {Time,Result}=timer:tc(?MODULE,loop2,[Mod,F,Bin,N]),
+ {Time,Result}=timer:tc(fun() -> loop2(Mod, F, Bin, N) end),
case Result of
{ok,_R1} ->
io:format("~p Decode ~p:~p, ~p times on time ~p~n",[Dec,Mod,F,N,Time]);
diff --git a/lib/asn1/test/test_undecoded_rest.erl b/lib/asn1/test/test_undecoded_rest.erl
index 36fd26ed59..91e614d38a 100644
--- a/lib/asn1/test/test_undecoded_rest.erl
+++ b/lib/asn1/test/test_undecoded_rest.erl
@@ -26,28 +26,42 @@
%% testing OTP-5104
-test(Opt, Config) ->
- {ok, Msg} = asn1ct:value('P-Record', 'PersonnelRecord',
- [{i, ?config(case_dir, Config)}]),
- {ok, Bytes} = asn1_wrapper:encode('P-Record', 'PersonnelRecord', Msg),
- Bytes2 = if is_list(Bytes) ->
- Bytes ++ [55, 55, 55];
- is_binary(Bytes) ->
- iolist_to_binary([Bytes, <<55, 55, 55>>])
- end,
- case Opt of
- undec_rest ->
- {ok, Msg, R} = asn1_wrapper:decode('P-Record', 'PersonnelRecord',
- Bytes2),
+test(Opts, Config) ->
+ {ok,Msg} = asn1ct:value('P-Record', 'PersonnelRecord',
+ [{i,?config(case_dir, Config)}]),
+ Bytes0 = encode(Opts, 'PersonnelRecord', Msg),
+ Bytes1 = iolist_to_binary([Bytes0, <<55,55,55>>]),
+ case proplists:get_bool(undec_rest, Opts) of
+ true ->
+ {Msg,R} = decode(Opts, 'PersonnelRecord', Bytes1),
case R of
- <<55, 55, 55>> -> ok;
- [55, 55, 55] -> ok;
+ <<55,55,55>> ->
+ ok;
BStr when is_bitstring(BStr) ->
PadLen = (8 - (bit_size(BStr) rem 8)) rem 8,
- <<0, 55, 55, 55>> = <<0:PadLen, BStr/bitstring>>
+ <<0,55,55,55>> = <<0:PadLen, BStr/bitstring>>
end;
- _ ->
- {ok, Msg} = asn1_wrapper:decode('P-Record', 'PersonnelRecord',
- Bytes2)
+ false ->
+ Msg = decode(Opts, 'PersonnelRecord', Bytes1)
end,
ok.
+
+encode(Opts, T, V) ->
+ M = 'P-Record',
+ case proplists:get_bool(no_ok_wrapper, Opts) of
+ false ->
+ {ok,Enc} = M:encode(T, V),
+ Enc;
+ true ->
+ Enc = M:encode(T, V),
+ true = is_binary(Enc),
+ Enc
+ end.
+
+decode(Opts, T, E) ->
+ M = 'P-Record',
+ case {proplists:get_bool(no_ok_wrapper, Opts),M:decode(T, E)} of
+ {false,{ok,Val}} -> Val;
+ {false,{ok,Val,Rest}} -> {Val,Rest};
+ {true,Result} -> Result
+ end.
diff --git a/lib/asn1/test/test_x691.erl b/lib/asn1/test/test_x691.erl
index dcfa211d80..9b141e2389 100644
--- a/lib/asn1/test/test_x691.erl
+++ b/lib/asn1/test/test_x691.erl
@@ -18,50 +18,25 @@
%%
%%
-module(test_x691).
-
--export([cases/2]).
+-export([cases/1]).
-include_lib("test_server/include/test_server.hrl").
-cases(Erule,Variant) ->
- MsgA1 = a1(),
- ?line {ok,B1} = asn1_wrapper:encode('P-RecordA1','PersonnelRecord',MsgA1),
- ?line {ok,MsgA1} = asn1_wrapper:decode('P-RecordA1','PersonnelRecord',B1),
- io:format("compare_format(~p,B1) ->~p~nencval(a1,~p,binary) ->~p~n",
- [Erule,
- compare_format(Erule,B1),
- Variant,
- encval(a1,Variant,binary)]),
- ?line true = (compare_format(Erule,B1) == encval(a1,Variant,binary)),
-
- MsgA2 = a2(),
- ?line {ok,B2} = asn1_wrapper:encode('P-RecordA2','PersonnelRecord',MsgA2),
- ?line {ok,MsgA2} = asn1_wrapper:decode('P-RecordA2','PersonnelRecord',B2),
- io:format("compare_format(~p,B2) ->~p~nencval(a2,~p,binary) ->~p~n",
- [Erule,
- compare_format(Erule,B2),
- Variant,
- encval(a2,Variant,binary)]),
- ?line true = (compare_format(Erule,B2) == encval(a2,Variant,binary)),
-
- MsgA3 = a3(),
- ?line {ok,B3} = asn1_wrapper:encode('P-RecordA3','PersonnelRecord',MsgA3),
- ?line {ok,MsgA3} = asn1_wrapper:decode('P-RecordA3','PersonnelRecord',B3),
- io:format("compare_format(~p,B3) ->~p~nencval(a3,~p,binary) ->~p~n",
- [Erule,
- compare_format(Erule,B3),
- Variant,
- encval(a3,Variant,binary)]),
- ?line true = (compare_format(Erule,B3) == encval(a3,Variant,binary)).
-
-compare_format(Erule,Val) when is_list(Val) ->
- compare_format(Erule,list_to_binary(Val));
-%% compare_format(per,Val) ->
-%% binary_to_list(Val);
-compare_format(_,Val) ->
- Val.
-
-a1() ->
+cases(Erule) ->
+ _ = [begin
+ Mod = module(Name),
+ Msg = msg(Name),
+ Hex = encval(Name, Erule),
+ Enc = asn1_test_lib:hex_to_bin(Hex),
+ Enc = asn1_test_lib:roundtrip_enc(Mod, 'PersonnelRecord', Msg)
+ end || Name <- [a1,a2,a3]],
+ ok.
+
+module(a1) -> 'P-RecordA1';
+module(a2) -> 'P-RecordA2';
+module(a3) -> 'P-RecordA3'.
+
+msg(a1) ->
{'PersonnelRecord',
{'Name',"John", "P", "Smith"},
"Director",
@@ -73,12 +48,10 @@ a1() ->
"19571111"},
{'ChildInformation',
{'Name', "Susan", "B", "Jones"},
- "19590717"}]}.
-
-a2() ->
- a1().
-
-a3() ->
+ "19590717"}]};
+msg(a2) ->
+ msg(a1);
+msg(a3) ->
{'PersonnelRecord',
{'Name',"John", "P", "Smith"},
"Director",
@@ -94,119 +67,15 @@ a3() ->
"19590717",
female}]}.
-encval(An,Variant,Encoding) when Encoding == hex; Encoding == binary ->
- Msg = encval(An,Variant),
- encoding(Encoding,Msg).
-
-encval(a1,aligned) ->
+encval(a1, per) ->
"80044A6F 686E0150 05536D69 74680133 08446972 6563746F 72083139 37313039 3137044D 61727901 5405536D 69746802 0552616C 70680154 05536D69 74680831 39353731 31313105 53757361 6E014205 4A6F6E65 73083139 35393037 3137";
-encval(a1,unaligned) ->
+encval(a1, uper) ->
"824ADFA3 700D005A 7B74F4D0 02661113 4F2CB8FA 6FE410C5 CB762C1C B16E0937 0F2F2035 0169EDD3 D340102D 2C3B3868 01A80B4F 6E9E9A02 18B96ADD 8B162C41 69F5E787 700C2059 5BF765E6 10C5CB57 2C1BB16E";
-encval(a2,aligned) ->
+encval(a2, per) ->
"864A6F68 6E501053 6D697468 01330844 69726563 746F7219 7109170C 4D617279 5410536D 69746802 1052616C 70685410 536D6974 68195711 11105375 73616E42 104A6F6E 65731959 0717";
-encval(a2,unaligned) ->
+encval(a2, uper) ->
"865D51D2 888A5125 F1809984 44D3CB2E 3E9BF90C B8848B86 7396E8A8 8A5125F1 81089B93 D71AA229 4497C632 AE222222 985CE521 885D54C1 70CAC838 B8";
-encval(a3,aligned) ->
+encval(a3, per) ->
"40C04A6F 686E5008 536D6974 68000033 08446972 6563746F 72001971 0917034D 61727954 08536D69 74680100 52616C70 68540853 6D697468 00195711 11820053 7573616E 42084A6F 6E657300 19590717 010140";
-encval(a3,unaligned) ->
+encval(a3, uper) ->
"40CBAA3A 5108A512 5F180330 889A7965 C7D37F20 CB8848B8 19CE5BA2 A114A24B E3011372 7AE35422 94497C61 95711118 22985CE5 21842EAA 60B832B2 0E2E0202 80".
-
-encoding(binary,Msg) ->
- list_to_binary(bin(Msg));
-encoding(hex,Msg) ->
- hex(Msg).
-
-bin(Msg) ->
- HexList = hex(Msg),
- Fun = fun([H1,H2|Rest],F) -> [(H1 bsl 4) + H2|F(Rest,F)];([],_) -> [] end,
- Fun(HexList,Fun).
-
-hex(Msg) ->
- [to_hex(X)||X <- Msg,X /= $ ].
-
-to_hex(I) when I >= $0, I =< $9 ->
- I-48;
-to_hex(C) when C >= $A,C =< $F ->
- C - 55.
-
-%% ex('EUTRA','BCCH-DL-SCH-Message',1) ->
-%% {'BCCH-DL-SCH-Message',
-%% {c1,
-%% {systemInformation1,
-%% {'SystemInformationBlockType1',
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation',
-%% [{'SystemInformationBlockType1_cellAccessRelatedInformation_SOF',
-%% {'PLMN-Identity'},
-%% true},
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation_SOF',
-%% {'PLMN-Identity'},
-%% false},
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation_SOF',
-%% {'PLMN-Identity'},
-%% true}],
-%% {'TrackingAreaCode'},
-%% {'CellIdentity'},
-%% false,
-%% true,
-%% true,
-%% true},
-%% {'SystemInformationBlockType1_cellSelectionInfo',
-%% -50},
-%% 24,
-%% [{'SystemInformationBlockType1_schedulinInformation_SOF',
-%% {'SystemInformationBlockType1_schedulinInformation_SOF_si-MessageType'},
-%% ms320,
-%% {'SystemInformationBlockType1_schedulinInformation_SOF_sib-MappingInfo'}
-%% }],
-%% 0
-%% }
-%% }
-%% }
-%% }.
-
-%% eutra1(msg) ->
-%% {'BCCH-BCH-Message',{'MasterInformationBlock',[0,1,0,1],[1,0,1,0],{'PHICH-Configuration',short,ffs},[1,0,1,0,0,0,0,0]}};
-%% eutra1(result) ->
-%% <<90,80,0>>.
-
-%% eutra2(msg) ->
-%% {'BCCH-DL-SCH-Message',
-%% {c1,
-%% {systemInformation1,
-%% {'SystemInformationBlockType1',
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation',
-%% [{'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},true},
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},false},
-%% {'SystemInformationBlockType1_cellAccessRelatedInformation_plmn-IdentityList_SEQOF',{'PLMN-Identity'},true}],
-%% {'TrackingAreaCode'},
-%% {'CellIdentity'},
-%% false,
-%% true,
-%% true,
-%% true
-%% },
-%% {'SystemInformationBlockType1_cellSelectionInfo',-50},
-%% 24,
-%% [{'SystemInformationBlockType1_schedulinInformation_SEQOF',
-%% {'SystemInformationBlockType1_schedulinInformation_SEQOF_si-MessageType'},
-%% ms320,
-%% {'SystemInformationBlockType1_schedulinInformation_SEQOF_sib-MappingInfo'}}],
-%% 0
-%% }
-%% }
-%% }
-%% };
-%% eutra2(result) ->
-%% %% 55 5C A5 E0
-%% <<85,92,165,224>>.
-
-
-
-%% compare([H|T1],[H|T2],Acc) ->
-%% compare(T1,T2,[H|Acc]);
-%% compare([],[],_Acc) ->
-%% ok;
-%% compare(L1,L2,Acc) ->
-%% {miss_match,L1,L2,lists:reverse(Acc)}.
-
-
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index b75de179dc..d1c364c34a 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 = 2.0.2
+ASN1_VSN = 3.0.4