Upstreaming version 0.10.7

Change-Id: Ica4c824e3e053be68d2b0ab3d6d467638632f5e1
Signed-off-by: kalnagy <kalman.nagy@nokia.com>
diff --git a/e2ap/lib/constr_CHOICE.c b/e2ap/lib/constr_CHOICE.c
index 613e6ea..86dcbb0 100644
--- a/e2ap/lib/constr_CHOICE.c
+++ b/e2ap/lib/constr_CHOICE.c
@@ -1017,6 +1017,7 @@
 	const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
 	asn_dec_rval_t rv;
 	const asn_per_constraint_t *ct;
+	const asn_per_constraint_t *ext_ct = NULL;
 	asn_TYPE_member_t *elm;	/* CHOICE's element */
 	void *memb_ptr;
 	void **memb_ptr2;
@@ -1042,9 +1043,13 @@
 	if(ct && ct->flags & APC_EXTENSIBLE) {
 		value = per_get_few_bits(pd, 1);
 		if(value < 0) ASN__DECODE_STARVED;
-		if(value) ct = 0;	/* Not restricted */
+		if(value) {
+		  ext_ct = ct;
+		  ct = 0;	/* Not restricted */
+		}
 	}
 
+
 	if(ct && ct->range_bits >= 0) {
 		value = per_get_few_bits(pd, ct->range_bits);
 		if(value < 0) ASN__DECODE_STARVED;
@@ -1055,7 +1060,7 @@
 	} else {
 		if(specs->ext_start == -1)
 			ASN__DECODE_FAILED;
-		value = uper_get_nsnnwn(pd);
+		value = aper_get_nsnnwn(pd, ext_ct->range_bits);
 		if(value < 0) ASN__DECODE_STARVED;
 		value += specs->ext_start;
 		if((unsigned)value >= td->elements_count)
@@ -1083,7 +1088,7 @@
 		rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type,
 		                                 elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 	} else {
-		rv = uper_open_type_get(opt_codec_ctx, elm->type,
+		rv = aper_open_type_get(opt_codec_ctx, elm->type,
 		                        elm->encoding_constraints.per_constraints, memb_ptr2, pd);
 	}
 
@@ -1099,10 +1104,12 @@
                    const void *sptr, asn_per_outp_t *po) {
 	const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
 	const asn_TYPE_member_t *elm; /* CHOICE's element */
-	const asn_per_constraint_t *ct;
+	const asn_per_constraint_t *ct = NULL;
+	const asn_per_constraint_t *ext_ct = NULL;
 	const void *memb_ptr;
-	int present;
-
+	unsigned present;
+	int present_enc;
+	
 	if(!sptr) ASN__ENCODE_FAILED;
 
 	ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
@@ -1110,7 +1117,7 @@
 	if(constraints) ct = &constraints->value;
 	else if(td->encoding_constraints.per_constraints)
 		ct = &td->encoding_constraints.per_constraints->value;
-	else ct = 0;
+	else ct = NULL;
 
 	present = _fetch_present_idx(sptr,
 	                             specs->pres_offset, specs->pres_size);
@@ -1126,25 +1133,38 @@
 
 	/* Adjust if canonical order is different from natural order */
 	if(specs->to_canonical_order)
-		present = specs->to_canonical_order[present];
-
+		present_enc = specs->to_canonical_order[present];
+	else
+	        present_enc = 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->range_bits >= 0)) {
+	  // Value is not within the range of the primary values ?
+	  if(present < ct->lower_bound || present > ct->upper_bound) {
+	    if(ct->flags & APC_EXTENSIBLE) {
+	      ASN_DEBUG("CHOICE member %d (enc %d) is an extension (%ld..%ld)",
+			present, present_enc, ct->lower_bound, ct->upper_bound);
+	      // X691/23.5 Extension marker = 1 
+	      if(per_put_few_bits(po, 1, 1)) {
+		ASN__ENCODE_FAILED;
+	      }
+	    } else {
+	      ASN__ENCODE_FAILED;
+	    }
+	    // no more need of constraint.
+	    ext_ct = ct;
+	    ct = NULL;
+	  }
 	}
-	if(ct && ct->flags & APC_EXTENSIBLE) {
-		if(per_put_few_bits(po, 0, 1))
-			ASN__ENCODE_FAILED;
+	
+	if(ct && (ct->flags & APC_EXTENSIBLE)) {
+	  ASN_DEBUG("CHOICE member %d (enc %d) is not an extension (%ld..%ld)",
+		    present, present, ct->lower_bound, ct->upper_bound);
+	  // X691.23.5 Extension marker = 0
+	  if(per_put_few_bits(po, 0, 1)) {
+	    ASN__ENCODE_FAILED;
+	  }
 	}
 
 	elm = &td->elements[present];
@@ -1156,8 +1176,10 @@
 		memb_ptr = (const char *)sptr + elm->memb_offset;
 	}
 
-	if(ct && ct->range_bits >= 0) {
-		if(per_put_few_bits(po, present, ct->range_bits))
+	if(ct && (ct->range_bits >= 0)) {
+	        // By construction (ct != 0), the alternative value is a non extended one.
+	        // X691/23.7 X691/23.6 alternative value encoded as a range_bits bits value.
+		if(per_put_few_bits(po, present_enc, ct->range_bits))
 			ASN__ENCODE_FAILED;
 
 		return elm->type->op->aper_encoder(elm->type, elm->encoding_constraints.per_constraints,
@@ -1166,10 +1188,10 @@
 		asn_enc_rval_t rval = {0,0,0};
 		if(specs->ext_start == -1)
 			ASN__ENCODE_FAILED;
-		if (ct) {
-		  if(aper_put_nsnnwn(po, ct->range_bits, present - specs->ext_start))
+		// X691/23.8 normally encoded as a small non negative whole number
+		
+		if(ext_ct && aper_put_nsnnwn(po, ext_ct->range_bits, present_enc - specs->ext_start))
 			ASN__ENCODE_FAILED;
-		}
 		if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
 		                      memb_ptr, po))
 			ASN__ENCODE_FAILED;