aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2006-08-18 01:34:18 +0000
committerLev Walkin <vlm@lionet.info>2006-08-18 01:34:18 +0000
commit523de9eba2d6963b2e0620bc93a3edc50e038c67 (patch)
tree14ca9b70265a116636cc10677d92af9a0f630e01
parent1dc85299236b3264bc9eb6d7f2177153ffe0ce55 (diff)
per support
-rw-r--r--skeletons/ANY.c2
-rw-r--r--skeletons/BIT_STRING.c1
-rw-r--r--skeletons/BMPString.c2
-rw-r--r--skeletons/BOOLEAN.c16
-rw-r--r--skeletons/BOOLEAN.h1
-rw-r--r--skeletons/ENUMERATED.c17
-rw-r--r--skeletons/ENUMERATED.h1
-rw-r--r--skeletons/GeneralString.c2
-rw-r--r--skeletons/GeneralizedTime.c2
-rw-r--r--skeletons/GraphicString.c2
-rw-r--r--skeletons/IA5String.c2
-rw-r--r--skeletons/INTEGER.c75
-rw-r--r--skeletons/INTEGER.h1
-rw-r--r--skeletons/ISO646String.c2
-rw-r--r--skeletons/NULL.c15
-rw-r--r--skeletons/NULL.h1
-rw-r--r--skeletons/NativeEnumerated.c83
-rw-r--r--skeletons/NativeEnumerated.h4
-rw-r--r--skeletons/NativeInteger.c25
-rw-r--r--skeletons/NativeInteger.h1
-rw-r--r--skeletons/NativeReal.c2
-rw-r--r--skeletons/NumericString.c2
-rw-r--r--skeletons/OBJECT_IDENTIFIER.c25
-rw-r--r--skeletons/OCTET_STRING.c98
-rw-r--r--skeletons/OCTET_STRING.h1
-rw-r--r--skeletons/ObjectDescriptor.c2
-rw-r--r--skeletons/PrintableString.c2
-rw-r--r--skeletons/REAL.c2
-rw-r--r--skeletons/RELATIVE-OID.c2
-rw-r--r--skeletons/T61String.c2
-rw-r--r--skeletons/TeletexString.c2
-rw-r--r--skeletons/UTCTime.c2
-rw-r--r--skeletons/UTF8String.c2
-rw-r--r--skeletons/UniversalString.c2
-rw-r--r--skeletons/VideotexString.c2
-rw-r--r--skeletons/VisibleString.c2
-rw-r--r--skeletons/constr_CHOICE.c82
-rw-r--r--skeletons/constr_CHOICE.h1
-rw-r--r--skeletons/constr_SEQUENCE.c98
-rw-r--r--skeletons/constr_SEQUENCE.h1
-rw-r--r--skeletons/constr_SEQUENCE_OF.c69
-rw-r--r--skeletons/constr_SEQUENCE_OF.h1
-rw-r--r--skeletons/constr_SET_OF.h1
-rw-r--r--skeletons/constr_TYPE.h6
-rw-r--r--skeletons/der_encoder.c7
-rw-r--r--skeletons/der_encoder.h2
-rw-r--r--skeletons/file-dependencies1
-rw-r--r--skeletons/per_encoder.c89
-rw-r--r--skeletons/per_encoder.h49
-rw-r--r--skeletons/per_support.c162
-rw-r--r--skeletons/per_support.h32
-rw-r--r--skeletons/tests/check-PER.c100
52 files changed, 1043 insertions, 63 deletions
diff --git a/skeletons/ANY.c b/skeletons/ANY.c
index a96aac0b..612238b6 100644
--- a/skeletons/ANY.c
+++ b/skeletons/ANY.c
@@ -21,7 +21,7 @@ asn_TYPE_descriptor_t asn_DEF_ANY = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
0, /* No PER visible constraints */
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 7434a2e1..6469d4fd 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -28,6 +28,7 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
OCTET_STRING_decode_xer_binary,
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
+ OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index 10fd05e0..1bfb174f 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
OCTET_STRING_encode_der,
BMPString_decode_xer, /* Convert from UTF-8 */
BMPString_encode_xer, /* Convert to UTF-8 */
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 84e57858..bb4697c2 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -23,6 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
BOOLEAN_decode_xer,
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
+ BOOLEAN_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
@@ -266,3 +267,18 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+
+asn_enc_rval_t
+BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ asn_enc_rval_t er;
+
+ (void)constraints;
+
+ if(!st) _ASN_ENCODE_FAILED;
+
+ per_put_few_bits(po, *st ? 1 : 0, 1);
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/BOOLEAN.h b/skeletons/BOOLEAN.h
index 1cf19803..217d0f16 100644
--- a/skeletons/BOOLEAN.h
+++ b/skeletons/BOOLEAN.h
@@ -27,6 +27,7 @@ der_type_encoder_f BOOLEAN_encode_der;
xer_type_decoder_f BOOLEAN_decode_xer;
xer_type_encoder_f BOOLEAN_encode_xer;
per_type_decoder_f BOOLEAN_decode_uper;
+per_type_encoder_f BOOLEAN_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index 6a8b9c67..90761a2d 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
@@ -24,6 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
INTEGER_decode_xer, /* This is temporary! */
INTEGER_encode_xer,
ENUMERATED_decode_uper, /* Unaligned PER decoder */
+ ENUMERATED_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_ENUMERATED_tags,
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
@@ -54,3 +56,16 @@ ENUMERATED_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td
rval.code = RC_FAIL;
return rval;
}
+
+asn_enc_rval_t
+ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ ENUMERATED_t *st = (ENUMERATED_t *)sptr;
+ long value;
+
+ if(asn_INTEGER2long(st, &value))
+ _ASN_ENCODE_FAILED;
+
+ return NativeEnumerated_encode_uper(td, constraints, &value, po);
+}
+
diff --git a/skeletons/ENUMERATED.h b/skeletons/ENUMERATED.h
index e65a15af..542dcae9 100644
--- a/skeletons/ENUMERATED.h
+++ b/skeletons/ENUMERATED.h
@@ -16,6 +16,7 @@ typedef INTEGER_t ENUMERATED_t; /* Implemented via INTEGER */
extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
per_type_decoder_f ENUMERATED_decode_uper;
+per_type_encoder_f ENUMERATED_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index c1a8823e..55bb6643 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralString_tags,
sizeof(asn_DEF_GeneralString_tags)
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 6236d2af..6d7855ee 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -152,7 +152,7 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
GeneralizedTime_encode_der,
OCTET_STRING_decode_xer_utf8,
GeneralizedTime_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index 0c3ad47c..135cd733 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_GraphicString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags)
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index abc9ff38..5c000b03 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index c43ac638..e9f61ac0 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -25,6 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = {
INTEGER_decode_xer,
INTEGER_encode_xer,
INTEGER_decode_uper, /* Unaligned PER decoder */
+ INTEGER_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_INTEGER_tags,
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
@@ -530,6 +531,78 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rval;
}
+asn_enc_rval_t
+INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_enc_rval_t er;
+ INTEGER_t *st = (INTEGER_t *)sptr;
+ const uint8_t *buf;
+ const uint8_t *end;
+ asn_per_constraint_t *ct;
+ long value = 0;
+
+ if(!st || st->size == 0) _ASN_ENCODE_FAILED;
+
+ if(!constraints) constraints = td->per_constraints;
+ ct = constraints ? &constraints->value : 0;
+
+ er.encoded = 0;
+
+ if(ct) {
+ int inext = 0;
+ if(asn_INTEGER2long(st, &value))
+ _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(value < ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(value < ct->lower_bound
+ || value > ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
+ value, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ if(inext) ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
+
+ /* X.691, #12.2.2 */
+ if(ct && ct->range_bits >= 0) {
+ /* #10.5.6 */
+ ASN_DEBUG("Encoding integer with range %d bits",
+ ct->range_bits);
+ if(per_put_few_bits(po, value - ct->lower_bound,
+ ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(ct && ct->lower_bound) {
+ ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
+ /* TODO: adjust lower bound */
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(buf = st->buf, end = st->buf + st->size; buf < end;) {
+ ssize_t mayEncode = uper_put_length(po, end - buf);
+ if(mayEncode < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_many_bits(po, buf, 8 * mayEncode))
+ _ASN_ENCODE_FAILED;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
int
asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
uint8_t *b, *end;
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 410fbe90..62832b12 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -38,6 +38,7 @@ der_type_encoder_f INTEGER_encode_der;
xer_type_decoder_f INTEGER_decode_xer;
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
+per_type_encoder_f INTEGER_encode_uper;
/***********************************
* Some handy conversion routines. *
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 829af328..d164aa7b 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 504be954..6d3316f1 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -24,6 +24,7 @@ asn_TYPE_descriptor_t asn_DEF_NULL = {
NULL_decode_xer,
NULL_encode_xer,
NULL_decode_uper, /* Unaligned PER decoder */
+ NULL_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NULL_tags,
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
@@ -130,3 +131,17 @@ NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rv.consumed = 0;
return rv;
}
+
+asn_enc_rval_t
+NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void *sptr, asn_per_outp_t *po) {
+ asn_enc_rval_t er;
+
+ (void)td;
+ (void)constraints;
+ (void)sptr;
+ (void)po;
+
+ er.encoded = 0;
+ _ASN_ENCODED_OK(er);
+}
diff --git a/skeletons/NULL.h b/skeletons/NULL.h
index 7126e1df..131e7759 100644
--- a/skeletons/NULL.h
+++ b/skeletons/NULL.h
@@ -24,6 +24,7 @@ der_type_encoder_f NULL_encode_der;
xer_type_decoder_f NULL_decode_xer;
xer_type_encoder_f NULL_encode_xer;
per_type_decoder_f NULL_decode_uper;
+per_type_encoder_f NULL_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 937accd1..fa16eb07 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -29,6 +29,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
NativeInteger_decode_xer,
NativeEnumerated_encode_xer,
NativeEnumerated_decode_uper,
+ NativeEnumerated_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
@@ -70,8 +71,9 @@ NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
}
asn_dec_rval_t
-NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
- asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
@@ -123,3 +125,80 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor
return rval;
}
+static int
+NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
+ const asn_INTEGER_enum_map_t *a = ap;
+ const asn_INTEGER_enum_map_t *b = bp;
+ if(a->nat_value == b->nat_value)
+ return 0;
+ if(a->nat_value < b->nat_value)
+ return -1;
+ return 1;
+}
+
+asn_enc_rval_t
+NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ long native, value;
+ asn_per_constraint_t *ct;
+ int inext = 0;
+ asn_INTEGER_enum_map_t key;
+ asn_INTEGER_enum_map_t *kf;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ if(!specs) _ASN_ENCODE_FAILED;
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else _ASN_ENCODE_FAILED; /* Mandatory! */
+
+ ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
+
+ er.encoded = 0;
+
+ native = *(long *)sptr;
+ if(native < 0) _ASN_ENCODE_FAILED;
+
+ key.nat_value = native;
+ kf = bsearch(&key, specs->value2enum, specs->map_count,
+ sizeof(key), NativeEnumerated__compar_value2enum);
+ if(!kf) {
+ ASN_DEBUG("No element corresponds to %ld", native);
+ _ASN_ENCODE_FAILED;
+ }
+ value = kf - specs->value2enum;
+
+ if(ct->range_bits >= 0) {
+ int cmpWith = specs->extension
+ ? specs->extension - 1 : specs->map_count;
+ if(value >= cmpWith)
+ inext = 1;
+ }
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 0))
+ _ASN_ENCODE_FAILED;
+ ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(!specs->extension)
+ _ASN_ENCODE_FAILED;
+
+ /*
+ * X.691, #10.6: normally small non-negative whole number;
+ */
+ if(uper_put_nsnnwn(po, value - (specs->extension - 1)))
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
+
diff --git a/skeletons/NativeEnumerated.h b/skeletons/NativeEnumerated.h
index 5792beed..c59bb1ba 100644
--- a/skeletons/NativeEnumerated.h
+++ b/skeletons/NativeEnumerated.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
@@ -22,6 +23,7 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer;
per_type_decoder_f NativeEnumerated_decode_uper;
+per_type_encoder_f NativeEnumerated_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index 3d1d6b47..34599f61 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
@@ -29,6 +30,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
NativeInteger_decode_xer,
NativeInteger_encode_xer,
NativeInteger_decode_uper, /* Unaligned PER decoder */
+ NativeInteger_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
@@ -253,6 +255,27 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
+asn_enc_rval_t
+NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_enc_rval_t er;
+ long native;
+ INTEGER_t tmpint;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ native = *(long *)sptr;
+
+ ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
+
+ memset(&tmpint, 0, sizeof(tmpint));
+ if(asn_long2INTEGER(&tmpint, native))
+ _ASN_ENCODE_FAILED;
+ er = INTEGER_encode_uper(td, constraints, &tmpint, po);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+ return er;
+}
+
/*
* INTEGER specific human-readable output.
*/
diff --git a/skeletons/NativeInteger.h b/skeletons/NativeInteger.h
index e2ce22e9..4e63a835 100644
--- a/skeletons/NativeInteger.h
+++ b/skeletons/NativeInteger.h
@@ -28,6 +28,7 @@ der_type_encoder_f NativeInteger_encode_der;
xer_type_decoder_f NativeInteger_decode_xer;
xer_type_encoder_f NativeInteger_encode_xer;
per_type_decoder_f NativeInteger_decode_uper;
+per_type_encoder_f NativeInteger_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 1683f901..2b8ec166 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -29,7 +29,7 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
NativeReal_encode_der,
NativeReal_decode_xer,
NativeReal_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeReal_tags,
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index f980dcdc..cef64ea6 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index 53d5353e..b1666dc6 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
der_encode_primitive,
OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
@@ -425,6 +425,7 @@ OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned i
* The following conditions must hold:
* assert(arcval);
* assert(arcval_size > 0);
+ * assert(arcval_size <= 16);
* assert(arcbuf);
*/
#ifdef WORDS_BIGENDIAN
@@ -437,12 +438,7 @@ OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned i
unsigned int cache;
uint8_t *bp = arcbuf;
int bits;
-#ifdef __GNUC__
- uint8_t buffer[arcval_size];
-#else
- uint8_t *buffer = alloca(arcval_size);
- if(!buffer) { errno = ENOMEM; return -1; }
-#endif
+ uint8_t buffer[16];
if(isLittleEndian && !prepared_order) {
const uint8_t *a = (const unsigned char *)arcval + arcval_size - 1;
@@ -502,7 +498,9 @@ OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned
unsigned size;
unsigned i;
- if(!oid || !arcs || arc_type_size < 1 || arc_slots < 2) {
+ if(!oid || !arcs || arc_type_size < 1
+ || arc_type_size > 16
+ || arc_slots < 2) {
errno = EINVAL;
return -1;
}
@@ -586,17 +584,8 @@ OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned
*/
{
uint8_t *tp;
-#ifdef __GNUC__
- uint8_t first_value[1 + arc_type_size]; /* of two arcs */
- uint8_t *fv = first_value;
-#else
- uint8_t *first_value = alloca(1 + arc_type_size);
+ uint8_t first_value[1 + 16]; /* of two arcs */
uint8_t *fv = first_value;
- if(!first_value) {
- errno = ENOMEM;
- return -1;
- }
-#endif
/*
* Simulate first_value = arc0 * 40 + arc1;
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index c5a4ed34..f2dd1c60 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -33,6 +33,7 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
+ OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_OCTET_STRING_tags,
sizeof(asn_DEF_OCTET_STRING_tags)
@@ -1297,6 +1298,103 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
+asn_enc_rval_t
+OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+ asn_OCTET_STRING_specifics_t *specs = td->specifics
+ ? (asn_OCTET_STRING_specifics_t *)td->specifics
+ : &asn_DEF_OCTET_STRING_specs;
+ asn_per_constraint_t *ct = constraints ? &constraints->size
+ : (td->per_constraints
+ ? &td->per_constraints->size
+ : &asn_DEF_OCTET_STRING_constraint);
+ const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+ int unit_bits = (specs->subvariant != 1) * 7 + 1;
+ asn_enc_rval_t er;
+ int ct_extensible = ct->flags & APC_EXTENSIBLE;
+ int inext = 0; /* Lies not within extension root */
+ int sizeinunits = st->size;
+ const uint8_t *buf;
+ int ret;
+
+ if(!st || !st->buf)
+ _ASN_ENCODE_FAILED;
+
+ if(unit_bits == 1) {
+ ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
+ sizeinunits, st->bits_unused);
+ sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07);
+ }
+
+ ASN_DEBUG("Encoding %s into %d units",
+ td->name, sizeinunits);
+
+ /* Figure out wheter size lies within PER visible consrtaint */
+
+ if(ct->effective_bits >= 0) {
+ if(sizeinunits < ct->lower_bound
+ || sizeinunits > ct->upper_bound) {
+ if(ct_extensible) {
+ ct = &asn_DEF_OCTET_STRING_constraint;
+ inext = 1;
+ } else
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ inext = 0;
+ }
+
+ if(ct_extensible) {
+ /* Declare whether length is [not] within extension root */
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /* X.691, #16.5: zero-length encoding */
+ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+ if(ct->effective_bits >= 0) {
+ ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
+ st->size, sizeinunits - ct->lower_bound,
+ ct->effective_bits);
+ ret = per_put_few_bits(po, sizeinunits - ct->lower_bound,
+ ct->effective_bits);
+ if(ret) _ASN_ENCODE_FAILED;
+ ret = per_put_many_bits(po, st->buf, sizeinunits);
+ if(ret) _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ ASN_DEBUG("Encoding %d bytes", st->size);
+
+ if(sizeinunits == 0) {
+ if(uper_put_length(po, 0))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ buf = st->buf;
+ while(sizeinunits) {
+ ssize_t maySave = uper_put_length(po, sizeinunits);
+ if(maySave < 0) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits);
+
+ ret = per_put_many_bits(po, buf, maySave);
+ if(ret) _ASN_ENCODE_FAILED;
+
+ if(unit_bits == 1)
+ buf += maySave >> 3;
+ else
+ buf += maySave;
+ sizeinunits -= maySave;
+ assert(!(maySave & 0x07) || !sizeinunits);
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
int
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
diff --git a/skeletons/OCTET_STRING.h b/skeletons/OCTET_STRING.h
index e85d05c3..5150161a 100644
--- a/skeletons/OCTET_STRING.h
+++ b/skeletons/OCTET_STRING.h
@@ -31,6 +31,7 @@ xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
+per_type_encoder_f OCTET_STRING_encode_uper;
/******************************
* Handy conversion routines. *
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index 37f51e8c..44cb5f66 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags)
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 5533253f..f5880832 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 689b05ec..dfaedf7d 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -42,7 +42,7 @@ asn_TYPE_descriptor_t asn_DEF_REAL = {
der_encode_primitive,
REAL_decode_xer,
REAL_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_REAL_tags,
sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 74511b7b..01814342 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -25,7 +25,7 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
der_encode_primitive,
RELATIVE_OID_decode_xer,
RELATIVE_OID_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_RELATIVE_OID_tags,
sizeof(asn_DEF_RELATIVE_OID_tags)
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index 4157a6b2..25d887ae 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_T61String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_T61String_tags,
sizeof(asn_DEF_T61String_tags)
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index 11f57033..b96cb3bb 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_TeletexString_tags,
sizeof(asn_DEF_TeletexString_tags)
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 5d7ba84e..3793a0e6 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -28,7 +28,7 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_utf8,
UTCTime_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 85f2ccd8..3cd574d5 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 0fab915f..a39e5699 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -23,7 +23,7 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
OCTET_STRING_encode_der,
UniversalString_decode_xer, /* Convert from UTF-8 */
UniversalString_encode_xer, /* Convert into UTF-8 */
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index c51c31aa..5f5f33d6 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_VideotexString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_VideotexString_tags,
sizeof(asn_DEF_VideotexString_tags)
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 7c705013..8796582d 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -22,7 +22,7 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
- 0,
+ 0, 0,
0, /* Use generic outmost tag fetcher */
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 84a3b4e3..224e56a9 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -363,6 +363,8 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
size_t computed_size = 0;
int present;
+ if(!sptr) _ASN_ENCODE_FAILED;
+
ASN_DEBUG("%s %s as CHOICE",
cb?"Encoding":"Estimating", td->name);
@@ -892,6 +894,82 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+asn_enc_rval_t
+CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ asn_per_constraint_t *ct;
+ void *memb_ptr;
+ int present;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %s as CHOICE", td->name);
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ present = _fetch_present_idx(sptr,
+ specs->pres_offset, specs->pres_size);
+
+ /*
+ * If the structure was not initialized properly, it cannot be encoded:
+ * can't deduce what to encode in the choice type.
+ */
+ if(present <= 0 || present > td->elements_count)
+ _ASN_ENCODE_FAILED;
+ else
+ present--;
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ present = specs->canonical_order[present];
+
+ ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
+ if(ct && ct->range_bits >= 0) {
+ if(present < ct->lower_bound
+ || present > ct->upper_bound) {
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 1, 1))
+ _ASN_ENCODE_FAILED;
+ } else {
+ _ASN_ENCODE_FAILED;
+ }
+ ct = 0;
+ }
+ }
+ if(ct && ct->flags & APC_EXTENSIBLE)
+ if(per_put_few_bits(po, 0, 1))
+ _ASN_ENCODE_FAILED;
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, present, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ } else {
+ if(specs->ext_start == -1)
+ _ASN_ENCODE_FAILED;
+ if(uper_put_nsnnwn(po, present - specs->ext_start))
+ _ASN_ENCODE_FAILED;
+ ASN_DEBUG("NOT IMPLEMENTED YET");
+ _ASN_ENCODE_FAILED;
+ }
+
+ elm = &td->elements[present];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ } else {
+ memb_ptr = (char *)sptr + elm->memb_offset;
+ }
+
+ return elm->type->uper_encoder(elm->type, elm->per_constraints,
+ memb_ptr, po);
+}
+
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index 6276d7e4..83404e6d 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -47,6 +47,7 @@ der_type_encoder_f CHOICE_encode_der;
xer_type_decoder_f CHOICE_decode_xer;
xer_type_encoder_f CHOICE_encode_xer;
per_type_decoder_f CHOICE_decode_uper;
+per_type_encoder_f CHOICE_encode_uper;
asn_outmost_tag_f CHOICE_outmost_tag;
#ifdef __cplusplus
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index d38afb5a..5b240070 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -1097,7 +1097,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* This element is not present */
if(elm->default_value) {
/* Fill-in DEFAULT */
- if(elm->default_value(memb_ptr2)) {
+ if(elm->default_value(1, memb_ptr2)) {
FREEMEM(opres);
_ASN_DECODE_FAILED;
}
@@ -1137,14 +1137,15 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
- memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ memb_ptr2 = (void **)((char *)st
+ + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Set default value */
- if(elm->default_value(memb_ptr2)) {
+ if(elm->default_value(1, memb_ptr2)) {
FREEMEM(opres);
_ASN_DECODE_FAILED;
}
@@ -1157,3 +1158,92 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+asn_enc_rval_t
+SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_SEQUENCE_specifics_t *specs
+ = (asn_SEQUENCE_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ int edx;
+ int i;
+
+ (void)constraints;
+
+ if(!sptr)
+ _ASN_ENCODE_FAILED;
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
+ if(specs->ext_before >= 0)
+ _ASN_ENCODE_FAILED; /* We don't encode extensions yet */
+
+ /* Encode a presence bitmap */
+ for(i = 0; i < specs->roms_count; i++) {
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ edx = specs->oms[i];
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ int present;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ present = 1;
+ }
+
+ /* Eliminate default values */
+ if(present && elm->default_value
+ && elm->default_value(0, memb_ptr2) == 1)
+ present = 0;
+
+ ASN_DEBUG("Element %s %s %s->%s is %s",
+ elm->flags & ATF_POINTER ? "ptr" : "inline",
+ elm->default_value ? "def" : "wtv",
+ td->name, elm->name, present ? "present" : "absent");
+ if(per_put_few_bits(po, present, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /*
+ * Get the sequence ROOT elements.
+ */
+ for(edx = 0; edx < ((specs->ext_before < 0)
+ ? td->elements_count : specs->ext_before + 1); edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ if(!*memb_ptr2) {
+ ASN_DEBUG("Element %s %d not present",
+ elm->name, edx);
+ if(elm->optional)
+ continue;
+ /* Mandatory element is missing */
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ /* Eliminate default values */
+ if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
+ continue;
+
+ er = elm->type->uper_encoder(elm->type, elm->per_constraints,
+ *memb_ptr2, po);
+ if(er.encoded == -1)
+ return er;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index b4ee47f9..5f589d5c 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -51,6 +51,7 @@ der_type_encoder_f SEQUENCE_encode_der;
xer_type_decoder_f SEQUENCE_decode_xer;
xer_type_encoder_f SEQUENCE_encode_xer;
per_type_decoder_f SEQUENCE_decode_uper;
+per_type_encoder_f SEQUENCE_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c
index 3ddd5a39..aa101176 100644
--- a/skeletons/constr_SEQUENCE_OF.c
+++ b/skeletons/constr_SEQUENCE_OF.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
@@ -139,3 +140,69 @@ cb_failed:
_ASN_ENCODE_FAILED;
}
+asn_enc_rval_t
+SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_anonymous_sequence_ *list;
+ asn_per_constraint_t *ct;
+ asn_enc_rval_t er;
+ asn_TYPE_member_t *elm = td->elements;
+ int seq;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ list = _A_SEQUENCE_FROM_VOID(sptr);
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
+
+ if(constraints) ct = &constraints->size;
+ else if(td->per_constraints) ct = &td->per_constraints->size;
+ else ct = 0;
+
+ /* If extensible constraint, check if size is in root */
+ if(ct) {
+ int not_in_root = (list->count < ct->lower_bound
+ || list->count > ct->upper_bound);
+ ASN_DEBUG("lb %ld ub %ld %s",
+ ct->lower_bound, ct->upper_bound,
+ ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
+ if(ct->flags & APC_EXTENSIBLE) {
+ /* Declare whether size is in extension root */
+ if(per_put_few_bits(po, not_in_root, 1))
+ _ASN_ENCODE_FAILED;
+ if(not_in_root) ct = 0;
+ } else if(not_in_root && ct->effective_bits >= 0)
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->effective_bits >= 0) {
+ /* X.691, #19.5: No length determinant */
+ if(per_put_few_bits(po, list->count - ct->lower_bound,
+ ct->effective_bits))
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(seq = -1; seq < list->count;) {
+ ssize_t mayEncode;
+ if(seq < 0) seq = 0;
+ if(ct && ct->effective_bits >= 0) {
+ mayEncode = list->count;
+ } else {
+ mayEncode = uper_put_length(po, list->count - seq);
+ if(mayEncode < 0) _ASN_ENCODE_FAILED;
+ }
+
+ while(mayEncode--) {
+ void *memb_ptr = list->array[seq++];
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ er = elm->type->uper_encoder(elm->type,
+ elm->per_constraints, memb_ptr, po);
+ if(er.encoded == -1)
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
diff --git a/skeletons/constr_SEQUENCE_OF.h b/skeletons/constr_SEQUENCE_OF.h
index 32078cb3..e2272f32 100644
--- a/skeletons/constr_SEQUENCE_OF.h
+++ b/skeletons/constr_SEQUENCE_OF.h
@@ -24,6 +24,7 @@ extern "C" {
#define SEQUENCE_OF_decode_uper SET_OF_decode_uper
der_type_encoder_f SEQUENCE_OF_encode_der;
xer_type_encoder_f SEQUENCE_OF_encode_xer;
+per_type_encoder_f SEQUENCE_OF_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index 14209316..bcd09662 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -33,6 +33,7 @@ der_type_encoder_f SET_OF_encode_der;
xer_type_decoder_f SET_OF_decode_xer;
xer_type_encoder_f SET_OF_encode_xer;
per_type_decoder_f SET_OF_decode_uper;
+per_type_encoder_f SET_OF_encode_uper;
#ifdef __cplusplus
}
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index 70e78828..95507c80 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -40,6 +40,7 @@ typedef struct asn_struct_ctx_s {
#include <xer_decoder.h> /* Decoder of XER (XML, text) */
#include <xer_encoder.h> /* Encoder into XER (XML, text) */
#include <per_decoder.h> /* Packet Encoding Rules decoder */
+#include <per_encoder.h> /* Packet Encoding Rules encoder */
#include <constraints.h> /* Subtype constraints support */
/*
@@ -97,6 +98,7 @@ typedef struct asn_TYPE_descriptor_s {
xer_type_decoder_f *xer_decoder; /* Generic XER decoder */
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */
+ per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */
/***********************************************************************
* Internally useful members. Not to be used by applications directly. *
@@ -144,7 +146,7 @@ typedef struct asn_TYPE_member_s {
asn_TYPE_descriptor_t *type; /* Member type descriptor */
asn_constr_check_f *memb_constraints; /* Constraints validator */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
- int (*default_value)(void **sptr); /* DEFAULT <value> */
+ int (*default_value)(int setval, void **sptr); /* DEFAULT <value> */
char *name; /* ASN.1 identifier of the element */
} asn_TYPE_member_t;
diff --git a/skeletons/der_encoder.c b/skeletons/der_encoder.c
index 68dd24e6..6c859e1b 100644
--- a/skeletons/der_encoder.c
+++ b/skeletons/der_encoder.c
@@ -52,20 +52,19 @@ static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
*/
asn_enc_rval_t
der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
- void *buffer, size_t *buffer_size) {
+ void *buffer, size_t buffer_size) {
enc_to_buf_arg arg;
asn_enc_rval_t ec;
arg.buffer = buffer;
- arg.left = *buffer_size;
+ arg.left = buffer_size;
ec = type_descriptor->der_encoder(type_descriptor,
struct_ptr, /* Pointer to the destination structure */
0, 0, encode_to_buffer_cb, &arg);
if(ec.encoded != -1) {
- assert(ec.encoded == (ssize_t)(*buffer_size - arg.left));
+ assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
/* Return the encoded contents size */
- *buffer_size = ec.encoded;
}
return ec;
}
diff --git a/skeletons/der_encoder.h b/skeletons/der_encoder.h
index 9e7867da..4e2fb06c 100644
--- a/skeletons/der_encoder.h
+++ b/skeletons/der_encoder.h
@@ -27,7 +27,7 @@ asn_enc_rval_t der_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
- size_t *buffer_size /* Initial buffer size (max) */
+ size_t buffer_size /* Initial buffer size (maximum) */
);
/*
diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies
index ca43363c..972eea47 100644
--- a/skeletons/file-dependencies
+++ b/skeletons/file-dependencies
@@ -60,6 +60,7 @@ xer_decoder.h xer_decoder.c # XER decoding support
xer_encoder.h xer_encoder.c # XER encoding support
per_support.h per_support.c # PER parsing
per_decoder.h per_decoder.c # PER decoding support
+per_encoder.h per_encoder.c # PER encoding support
#asn-decoder-template.c # Template for quick decoder creation
CODEC-PER: # THIS IS A SPECIAL SECTION
diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c
new file mode 100644
index 00000000..6ba28e53
--- /dev/null
+++ b/skeletons/per_encoder.c
@@ -0,0 +1,89 @@
+#include <asn_application.h>
+#include <asn_internal.h>
+#include <per_encoder.h>
+
+/* Flush partially filled buffer */
+static int _uper_encode_flush_outp(asn_per_outp_t *po);
+
+asn_enc_rval_t
+uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_per_outp_t po;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->uper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 8 * sizeof(po.tmpspace);
+ po.outper = cb;
+ po.op_key = app_key;
+
+ er = td->uper_encoder(td, 0, sptr, &po);
+ if(er.encoded != -1 && _uper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+
+ return er;
+}
+
+/*
+ * Argument type and callback necessary for uper_encode_to_buffer().
+ */
+typedef struct enc_to_buf_arg {
+ void *buffer;
+ size_t left;
+} enc_to_buf_arg;
+static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
+ enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
+
+ if(arg->left < size)
+ return -1; /* Data exceeds the available buffer size */
+
+ memcpy(arg->buffer, buffer, size);
+ arg->buffer = ((char *)arg->buffer) + size;
+ arg->left -= size;
+
+ return 0;
+}
+
+asn_enc_rval_t
+uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
+ enc_to_buf_arg key;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->uper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ key.buffer = buffer;
+ key.left = buffer_size;
+
+ ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
+
+ er = uper_encode(td, sptr, encode_to_buffer_cb, &key);
+ if(er.encoded != -1)
+ er.encoded = buffer_size - key.left;
+ return er;
+}
+
+static int
+_uper_encode_flush_outp(asn_per_outp_t *po) {
+ uint8_t *buf;
+
+ if(po->nboff == 0 && po->buffer == po->tmpspace)
+ return 0;
+
+ buf = po->buffer + (po->nboff >> 3);
+ /* Make sure we account for the last, partially filled */
+ if(po->nboff & 0x07) {
+ buf[0] &= 0xff << (8 - (po->nboff & 0x07));
+ buf++;
+ }
+
+ return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
+}
diff --git a/skeletons/per_encoder.h b/skeletons/per_encoder.h
new file mode 100644
index 00000000..9ac130b7
--- /dev/null
+++ b/skeletons/per_encoder.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _PER_ENCODER_H_
+#define _PER_ENCODER_H_
+
+#include <asn_application.h>
+#include <per_support.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s; /* Forward declaration */
+
+/*
+ * Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
+ */
+asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
+ void *struct_ptr, /* Structure to be encoded */
+ asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */
+ void *app_key /* Arbitrary callback argument */
+);
+
+/* A variant of uper_encode() which encodes data into the existing buffer */
+asn_enc_rval_t uper_encode_to_buffer(
+ struct asn_TYPE_descriptor_s *type_descriptor,
+ void *struct_ptr, /* Structure to be encoded */
+ void *buffer, /* Pre-allocated buffer */
+ size_t buffer_size /* Initial buffer size (max) */
+);
+
+
+/*
+ * Type of the generic PER encoder function.
+ */
+typedef asn_enc_rval_t (per_type_encoder_f)(
+ struct asn_TYPE_descriptor_s *type_descriptor,
+ asn_per_constraints_t *constraints,
+ void *struct_ptr,
+ asn_per_outp_t *per_output
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PER_ENCODER_H_ */
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index 63b39d08..0eb381c8 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2005, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_system.h>
@@ -80,7 +80,7 @@ per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
} else {
value = per_get_few_bits(pd, nbits);
if(value < 0) return -1;
- if(nbits & 7) { /* implies alright */
+ if(nbits & 7) { /* implies left alignment */
value <<= 8 - (nbits & 7),
nbits += 8 - (nbits & 7);
if(nbits > 24)
@@ -150,3 +150,161 @@ uper_get_nsnnwn(asn_per_data_t *pd) {
return value;
}
+
+/*
+ * Put the normally small non-negative whole number.
+ * X.691, #10.6
+ */
+int
+uper_put_nsnnwn(asn_per_outp_t *po, int n) {
+ int bytes;
+
+ if(n <= 63) {
+ if(n < 0) return -1;
+ return per_put_few_bits(po, n, 7);
+ }
+ if(n < 256)
+ bytes = 1;
+ else if(n < 65536)
+ bytes = 2;
+ else if(n < 256 * 65536)
+ bytes = 3;
+ else
+ return -1; /* This is not a "normally small" value */
+ if(per_put_few_bits(po, bytes, 8))
+ return -1;
+
+ return per_put_few_bits(po, n, 8 * bytes);
+}
+
+
+/*
+ * Put a small number of bits (<= 31).
+ */
+int
+per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
+ size_t off; /* Next after last bit offset */
+ size_t omsk; /* Existing last byte meaningful bits mask */
+ uint8_t *buf;
+
+ if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
+
+ /*
+ * Normalize position indicator.
+ */
+ if(po->nboff >= 8) {
+ po->buffer += (po->nboff >> 3);
+ po->nbits -= (po->nboff & ~0x07);
+ po->nboff &= 0x07;
+ }
+
+ /*
+ * Flush whole-bytes output, if necessary.
+ */
+ if(po->nboff + obits > po->nbits) {
+ int complete_bytes = (po->buffer - po->tmpspace);
+ if(po->outper(po->buffer, complete_bytes, po->op_key) < 0)
+ return -1;
+ if(po->nboff)
+ po->tmpspace[0] = po->buffer[0];
+ po->buffer = po->tmpspace;
+ po->nbits = 8 * sizeof(po->tmpspace);
+ }
+
+ /*
+ * Now, due to sizeof(tmpspace), we are guaranteed large enough space.
+ */
+ buf = po->buffer;
+ omsk = ~((1 << (8 - po->nboff)) - 1);
+ off = (po->nboff += obits);
+
+ /* Clear data of debris before meaningful bits */
+ bits &= (((uint32_t)1 << obits) - 1);
+
+ ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits,
+ po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
+
+ if(off <= 8) /* Completely within 1 byte */
+ bits <<= (8 - off),
+ buf[0] = (buf[0] & omsk) | bits;
+ else if(off <= 16)
+ bits <<= (16 - off),
+ buf[0] = (buf[0] & omsk) | (bits >> 8),
+ buf[1] = bits;
+ else if(off <= 24)
+ bits <<= (24 - off),
+ buf[0] = (buf[0] & omsk) | (bits >> 16),
+ buf[1] = bits >> 8,
+ buf[2] = bits;
+ else if(off <= 31)
+ bits <<= (32 - off),
+ buf[0] = (buf[0] & omsk) | (bits >> 24),
+ buf[1] = bits >> 16,
+ buf[2] = bits >> 8,
+ buf[3] = bits;
+ else {
+ ASN_DEBUG("->[PER out split %d]", obits);
+ per_put_few_bits(po, bits >> 8, 24);
+ per_put_few_bits(po, bits, obits - 24);
+ ASN_DEBUG("<-[PER out split %d]", obits);
+ }
+
+ ASN_DEBUG("[PER out %u/%x => %02x buf+%d]",
+ bits, bits, buf[0], po->buffer - po->tmpspace);
+
+ return 0;
+}
+
+
+/*
+ * Output a large number of bits.
+ */
+int
+per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
+
+ while(nbits) {
+ uint32_t value;
+
+ if(nbits >= 24) {
+ value = (src[0] << 16) | (src[1] << 8) | src[2];
+ src += 3;
+ nbits -= 24;
+ if(per_put_few_bits(po, value, 24))
+ return -1;
+ } else {
+ value = src[0];
+ if(nbits > 8)
+ value = (value << 8) | src[1];
+ if(nbits > 16)
+ value = (value << 8) | src[2];
+ if(nbits & 0x07)
+ value >>= (8 - (nbits & 0x07));
+ if(per_put_few_bits(po, value, nbits))
+ return -1;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Put the length "n" (or part of it) into the stream.
+ */
+ssize_t
+uper_put_length(asn_per_outp_t *po, size_t length) {
+
+ if(length <= 127) /* #10.9.3.6 */
+ return per_put_few_bits(po, length, 8)
+ ? -1 : (ssize_t)length;
+ else if(length < 16384) /* #10.9.3.7 */
+ return per_put_few_bits(po, length|0x8000, 16)
+ ? -1 : (ssize_t)length;
+
+ length >>= 14;
+ if(length > 4) length = 4;
+
+ return per_put_few_bits(po, 0xC0 | length, 8)
+ ? -1 : (ssize_t)(length << 14);
+}
+
diff --git a/skeletons/per_support.h b/skeletons/per_support.h
index 44f0bb40..747abe27 100644
--- a/skeletons/per_support.h
+++ b/skeletons/per_support.h
@@ -12,7 +12,7 @@ extern "C" {
#endif
/*
- * This structure describes a position inside a PER bit stream.
+ * This structure describes a position inside an incoming PER bit stream.
*/
typedef struct asn_per_data_s {
const uint8_t *buffer; /* Pointer to the octet stream */
@@ -21,12 +21,27 @@ typedef struct asn_per_data_s {
} asn_per_data_t;
/*
+ * This structure supports forming PER output.
+ */
+typedef struct asn_per_outp_s {
+ uint8_t *buffer; /* Pointer into the (tmpspace) */
+ size_t nboff; /* Bit offset to the meaningful bit */
+ size_t nbits; /* Number of bits left in (tmpspace) */
+ uint8_t tmpspace[32]; /* Preliminary storage to hold data */
+ int (*outper)(const void *data, size_t size, void *op_key);
+ void *op_key;
+} asn_per_outp_t;
+
+/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
* extracted due to EOD or other conditions.
*/
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
+/* Output a small number of bits (<= 31) */
+int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
+
/*
* Extract a large number of bits from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
@@ -35,6 +50,9 @@ int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align,
int get_nbits);
+/* Output a large number of bits */
+int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
+
/*
* Get the length "n" from the Unaligned PER stream.
*/
@@ -43,10 +61,22 @@ ssize_t uper_get_length(asn_per_data_t *pd,
int *repeat);
/*
+ * Put the length "n" to the Unaligned PER stream.
+ * This function returns the number of units which may be flushed
+ * in the next units saving iteration.
+ */
+ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
+
+/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
+/*
+ * Put the normally small non-negative whole number.
+ */
+int uper_put_nsnnwn(asn_per_outp_t *po, int n);
+
#ifdef __cplusplus
}
#endif
diff --git a/skeletons/tests/check-PER.c b/skeletons/tests/check-PER.c
index 5fcb1aee..6d355e83 100644
--- a/skeletons/tests/check-PER.c
+++ b/skeletons/tests/check-PER.c
@@ -1,8 +1,8 @@
#include <per_support.c>
#include <assert.h>
-int
-main() {
+static void
+check_per_decoding() {
uint8_t buf[] = { 0xB7, 0x19, 0x2F, 0xEE, 0xAD };
uint8_t tmpbuf[10];
int32_t z;
@@ -119,6 +119,102 @@ main() {
assert(tmpbuf[2] == buf[2]);
assert(tmpbuf[3] == buf[3]);
assert(tmpbuf[4] == buf[4]);
+}
+
+static int Ignore(const void *data, size_t size, void *op_key) {
+ return 0;
+}
+static void
+check_per_encoding() {
+ asn_per_outp_t po;
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 0;
+ po.outper = Ignore;
+ po.op_key = 0;
+ po.tmpspace[0] = 0xff;
+ int ret;
+
+ ret = per_put_few_bits(&po, 0, 0);
+ assert(ret == 0);
+ assert(po.nboff == 0);
+ assert(po.buffer == po.tmpspace);
+ assert(po.tmpspace[0] == 0xff);
+
+ ret = per_put_few_bits(&po, 0, 1);
+ assert(ret == 0);
+ assert(po.nboff == 1);
+ assert(po.nbits == 8 * sizeof(po.tmpspace));
+ assert(po.buffer == po.tmpspace);
+ assert(po.tmpspace[0] == 0x00);
+
+ ret = per_put_few_bits(&po, 1, 1);
+ assert(ret == 0);
+ assert(po.nboff == 2);
+ assert(po.nbits == 8 * sizeof(po.tmpspace));
+ assert(po.buffer == po.tmpspace);
+ assert(po.tmpspace[0] == 0x40);
+
+ ret = per_put_few_bits(&po, 1, 1);
+ assert(ret == 0);
+ assert(po.nboff == 3);
+ assert(po.nbits == 8 * sizeof(po.tmpspace));
+ assert(po.buffer == po.tmpspace);
+ assert(po.tmpspace[0] == 0x60);
+
+ ret = per_put_few_bits(&po, 15, 5);
+ assert(ret == 0);
+ assert(po.nboff == 8);
+ assert(po.nbits == 8 * sizeof(po.tmpspace));
+ assert(po.buffer == po.tmpspace);
+ assert(po.tmpspace[0] == 0x6F);
+
+ ret = per_put_few_bits(&po, 0xf0ff, 16);
+ assert(ret == 0);
+ assert(po.nboff == 16);
+ assert(po.nbits == 8 * sizeof(po.tmpspace) - 8);
+ assert(po.buffer == po.tmpspace + 1);
+ assert(po.tmpspace[0] == 0x6F);
+ assert(po.tmpspace[1] == 0xf0);
+ assert(po.tmpspace[2] == 0xff);
+
+ po.nboff--;
+
+ ret = per_put_few_bits(&po, 2, 1);
+ assert(ret == 0);
+ assert(po.nboff == 8);
+ assert(po.nbits == 8 * sizeof(po.tmpspace) - 16);
+ assert(po.buffer == po.tmpspace + 2);
+ assert(po.tmpspace[0] == 0x6F);
+ assert(po.tmpspace[1] == 0xf0);
+ assert(po.tmpspace[2] == 0xfe);
+
+ ret = per_put_few_bits(&po, 2, 32);
+ assert(ret == -1);
+
+ ret = per_put_few_bits(&po, 2, -1);
+ assert(ret == -1);
+
+ ret = per_put_few_bits(&po, -1, 31);
+ assert(ret == 0);
+ assert(po.nboff == 31);
+ assert(po.nbits == 8 * sizeof(po.tmpspace) - 24);
+ assert(po.buffer == po.tmpspace + 3);
+ assert(po.tmpspace[0] == 0x6F);
+ assert(po.tmpspace[1] == 0xf0);
+ assert(po.tmpspace[2] == 0xfe);
+ assert(po.tmpspace[3] == 0xff);
+ assert(po.tmpspace[4] == 0xff);
+ assert(po.tmpspace[5] == 0xff);
+ assert(po.tmpspace[6] == 0xfe);
+
+
+}
+
+int
+main() {
+ check_per_decoding();
+ check_per_encoding();
return 0;
}