--- /dev/null
+/*-\r
+ * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.\r
+ * All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+#include <asn_internal.h>\r
+#include <constr_SEQUENCE_OF.h>\r
+#include <asn_SEQUENCE_OF.h>\r
+\r
+/*\r
+ * The DER encoder of the SEQUENCE OF type.\r
+ */\r
+asn_enc_rval_t\r
+SEQUENCE_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *ptr,\r
+ int tag_mode, ber_tlv_tag_t tag,\r
+ asn_app_consume_bytes_f *cb, void *app_key) {\r
+ asn_TYPE_member_t *elm = td->elements;\r
+ const asn_anonymous_sequence_ *list = _A_CSEQUENCE_FROM_VOID(ptr);\r
+ size_t computed_size = 0;\r
+ ssize_t encoding_size = 0;\r
+ asn_enc_rval_t erval = {0,0,0};\r
+ int edx;\r
+\r
+ ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);\r
+\r
+ /*\r
+ * Gather the length of the underlying members sequence.\r
+ */\r
+ for(edx = 0; edx < list->count; edx++) {\r
+ void *memb_ptr = list->array[edx];\r
+ if(!memb_ptr) continue;\r
+ erval = elm->type->op->der_encoder(elm->type, memb_ptr,\r
+ 0, elm->tag,\r
+ 0, 0);\r
+ if(erval.encoded == -1)\r
+ return erval;\r
+ computed_size += erval.encoded;\r
+ }\r
+\r
+ /*\r
+ * Encode the TLV for the sequence itself.\r
+ */\r
+ encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,\r
+ cb, app_key);\r
+ if(encoding_size == -1) {\r
+ erval.encoded = -1;\r
+ erval.failed_type = td;\r
+ erval.structure_ptr = ptr;\r
+ return erval;\r
+ }\r
+\r
+ computed_size += encoding_size;\r
+ if(!cb) {\r
+ erval.encoded = computed_size;\r
+ ASN__ENCODED_OK(erval);\r
+ }\r
+\r
+ ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);\r
+\r
+ /*\r
+ * Encode all members.\r
+ */\r
+ for(edx = 0; edx < list->count; edx++) {\r
+ void *memb_ptr = list->array[edx];\r
+ if(!memb_ptr) continue;\r
+ erval = elm->type->op->der_encoder(elm->type, memb_ptr,\r
+ 0, elm->tag,\r
+ cb, app_key);\r
+ if(erval.encoded == -1)\r
+ return erval;\r
+ encoding_size += erval.encoded;\r
+ }\r
+\r
+ if(computed_size != (size_t)encoding_size) {\r
+ /*\r
+ * Encoded size is not equal to the computed size.\r
+ */\r
+ erval.encoded = -1;\r
+ erval.failed_type = td;\r
+ erval.structure_ptr = ptr;\r
+ } else {\r
+ erval.encoded = computed_size;\r
+ erval.structure_ptr = 0;\r
+ erval.failed_type = 0;\r
+ }\r
+\r
+ return erval;\r
+}\r
+\r
+asn_enc_rval_t\r
+SEQUENCE_OF_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,\r
+ int ilevel, enum xer_encoder_flags_e flags,\r
+ asn_app_consume_bytes_f *cb, void *app_key) {\r
+ asn_enc_rval_t er = {0,0,0};\r
+ const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;\r
+ const asn_TYPE_member_t *elm = td->elements;\r
+ const asn_anonymous_sequence_ *list = _A_CSEQUENCE_FROM_VOID(sptr);\r
+ const char *mname = specs->as_XMLValueList\r
+ ? 0\r
+ : ((*elm->name) ? elm->name : elm->type->xml_tag);\r
+ size_t mlen = mname ? strlen(mname) : 0;\r
+ int xcan = (flags & XER_F_CANONICAL);\r
+ int i;\r
+\r
+ if(!sptr) ASN__ENCODE_FAILED;\r
+\r
+ er.encoded = 0;\r
+\r
+ for(i = 0; i < list->count; i++) {\r
+ asn_enc_rval_t tmper = {0,0,0};\r
+ void *memb_ptr = list->array[i];\r
+ if(!memb_ptr) continue;\r
+\r
+ if(mname) {\r
+ if(!xcan) ASN__TEXT_INDENT(1, ilevel);\r
+ ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);\r
+ }\r
+\r
+ tmper = elm->type->op->xer_encoder(elm->type, memb_ptr, ilevel + 1,\r
+ flags, cb, app_key);\r
+ if(tmper.encoded == -1) return tmper;\r
+ er.encoded += tmper.encoded;\r
+ if(tmper.encoded == 0 && specs->as_XMLValueList) {\r
+ const char *name = elm->type->xml_tag;\r
+ size_t len = strlen(name);\r
+ if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);\r
+ ASN__CALLBACK3("<", 1, name, len, "/>", 2);\r
+ }\r
+\r
+ if(mname) {\r
+ ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);\r
+ }\r
+ }\r
+\r
+ if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);\r
+\r
+ ASN__ENCODED_OK(er);\r
+cb_failed:\r
+ ASN__ENCODE_FAILED;\r
+}\r
+\r
+#ifndef ASN_DISABLE_PER_SUPPORT\r
+\r
+asn_enc_rval_t\r
+SEQUENCE_OF_encode_uper(const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ const void *sptr, asn_per_outp_t *po) {\r
+ const asn_anonymous_sequence_ *list;\r
+ const asn_per_constraint_t *ct;\r
+ asn_enc_rval_t er = {0,0,0};\r
+ const asn_TYPE_member_t *elm = td->elements;\r
+ size_t encoded_edx;\r
+\r
+ if(!sptr) ASN__ENCODE_FAILED;\r
+ list = _A_CSEQUENCE_FROM_VOID(sptr);\r
+\r
+ er.encoded = 0;\r
+\r
+ ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);\r
+\r
+ if(constraints) ct = &constraints->size;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->size;\r
+ else ct = 0;\r
+\r
+ /* If extensible constraint, check if size is in root */\r
+ if(ct) {\r
+ int not_in_root =\r
+ (list->count < ct->lower_bound || list->count > ct->upper_bound);\r
+ ASN_DEBUG("lb %ld ub %ld %s", ct->lower_bound, ct->upper_bound,\r
+ ct->flags & APC_EXTENSIBLE ? "ext" : "fix");\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ /* Declare whether size is in extension root */\r
+ if(per_put_few_bits(po, not_in_root, 1)) ASN__ENCODE_FAILED;\r
+ if(not_in_root) ct = 0;\r
+ } else if(not_in_root && ct->effective_bits >= 0) {\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ }\r
+\r
+ if(ct && ct->effective_bits >= 0) {\r
+ /* X.691, #19.5: No length determinant */\r
+ if(per_put_few_bits(po, list->count - ct->lower_bound,\r
+ ct->effective_bits))\r
+ ASN__ENCODE_FAILED;\r
+ } else if(list->count == 0) {\r
+ /* When the list is empty add only the length determinant\r
+ * X.691, #20.6 and #11.9.4.1\r
+ */\r
+ if (uper_put_length(po, 0, 0)) {\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+ ASN__ENCODED_OK(er);\r
+ }\r
+\r
+ for(encoded_edx = 0; (ssize_t)encoded_edx < list->count;) {\r
+ ssize_t may_encode;\r
+ size_t edx;\r
+ int need_eom = 0;\r
+\r
+ if(ct && ct->effective_bits >= 0) {\r
+ may_encode = list->count;\r
+ } else {\r
+ may_encode =\r
+ uper_put_length(po, list->count - encoded_edx, &need_eom);\r
+ if(may_encode < 0) ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ for(edx = encoded_edx; edx < encoded_edx + may_encode; edx++) {\r
+ void *memb_ptr = list->array[edx];\r
+ if(!memb_ptr) ASN__ENCODE_FAILED;\r
+ er = elm->type->op->uper_encoder(\r
+ elm->type, elm->encoding_constraints.per_constraints, memb_ptr,\r
+ po);\r
+ if(er.encoded == -1) ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ if(need_eom && uper_put_length(po, 0, 0))\r
+ ASN__ENCODE_FAILED; /* End of Message length */\r
+\r
+ encoded_edx += may_encode;\r
+ }\r
+\r
+ ASN__ENCODED_OK(er);\r
+}\r
+\r
+asn_enc_rval_t\r
+SEQUENCE_OF_encode_aper(const asn_TYPE_descriptor_t *td,\r
+ const asn_per_constraints_t *constraints,\r
+ const void *sptr, asn_per_outp_t *po) {\r
+ const asn_anonymous_sequence_ *list;\r
+ const asn_per_constraint_t *ct;\r
+ asn_enc_rval_t er = {0,0,0};\r
+ asn_TYPE_member_t *elm = td->elements;\r
+ int seq;\r
+\r
+ if(!sptr) ASN__ENCODE_FAILED;\r
+ list = _A_CSEQUENCE_FROM_VOID(sptr);\r
+\r
+ er.encoded = 0;\r
+\r
+ ASN_DEBUG("Encoding %s as SEQUENCE OF size (%d) using ALIGNED PER", td->name, list->count);\r
+\r
+ if(constraints) ct = &constraints->size;\r
+ else if(td->encoding_constraints.per_constraints)\r
+ ct = &td->encoding_constraints.per_constraints->size;\r
+ else ct = 0;\r
+\r
+ /* If extensible constraint, check if size is in root */\r
+ if(ct) {\r
+ int not_in_root = (list->count < ct->lower_bound\r
+ || list->count > ct->upper_bound);\r
+ ASN_DEBUG("lb %ld ub %ld %s",\r
+ ct->lower_bound, ct->upper_bound,\r
+ ct->flags & APC_EXTENSIBLE ? "ext" : "fix");\r
+ if(ct->flags & APC_EXTENSIBLE) {\r
+ /* Declare whether size is in extension root */\r
+ if(per_put_few_bits(po, not_in_root, 1))\r
+ ASN__ENCODE_FAILED;\r
+ if(not_in_root) ct = 0;\r
+ } else if(not_in_root && ct->effective_bits >= 0)\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ if(ct && ct->effective_bits >= 0) {\r
+ /* X.691, #19.5: No length determinant */\r
+/* if(per_put_few_bits(po, list->count - ct->lower_bound,\r
+ ct->effective_bits))\r
+ ASN__ENCODE_FAILED;\r
+*/\r
+ if (aper_put_length(po, ct->upper_bound - ct->lower_bound + 1, list->count - ct->lower_bound) < 0)\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ for(seq = -1; seq < list->count;) {\r
+ ssize_t mayEncode;\r
+ if(seq < 0) seq = 0;\r
+ if(ct && ct->effective_bits >= 0) {\r
+ mayEncode = list->count;\r
+ } else {\r
+ mayEncode = aper_put_length(po, -1, list->count - seq);\r
+ if(mayEncode < 0) ASN__ENCODE_FAILED;\r
+ }\r
+\r
+ while(mayEncode--) {\r
+ void *memb_ptr = list->array[seq++];\r
+ if(!memb_ptr) ASN__ENCODE_FAILED;\r
+ er = elm->type->op->aper_encoder(elm->type,\r
+ elm->encoding_constraints.per_constraints, memb_ptr, po);\r
+ if(er.encoded == -1)\r
+ ASN__ENCODE_FAILED;\r
+ }\r
+ }\r
+\r
+ ASN__ENCODED_OK(er);\r
+}\r
+#endif /* ASN_DISABLE_PER_SUPPORT */\r
+\r
+int\r
+SEQUENCE_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,\r
+ const void *bptr) {\r
+ const asn_anonymous_sequence_ *a = _A_CSEQUENCE_FROM_VOID(aptr);\r
+ const asn_anonymous_sequence_ *b = _A_CSEQUENCE_FROM_VOID(bptr);\r
+ ssize_t idx;\r
+\r
+ if(a && b) {\r
+ ssize_t common_length = (a->count < b->count ? a->count : b->count);\r
+ for(idx = 0; idx < common_length; idx++) {\r
+ int ret = td->elements->type->op->compare_struct(\r
+ td->elements->type, a->array[idx], b->array[idx]);\r
+ if(ret) return ret;\r
+ }\r
+\r
+ if(idx < b->count) /* more elements in b */\r
+ return -1; /* a is shorter, so put it first */\r
+ if(idx < a->count) return 1;\r
+\r
+ } else if(!a) {\r
+ return -1;\r
+ } else if(!b) {\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+asn_TYPE_operation_t asn_OP_SEQUENCE_OF = {\r
+ SEQUENCE_OF_free,\r
+ SEQUENCE_OF_print,\r
+ SEQUENCE_OF_compare,\r
+ SEQUENCE_OF_decode_ber,\r
+ SEQUENCE_OF_encode_der,\r
+ SEQUENCE_OF_decode_xer,\r
+ SEQUENCE_OF_encode_xer,\r
+#ifdef ASN_DISABLE_OER_SUPPORT\r
+ 0,\r
+ 0,\r
+#else\r
+ SEQUENCE_OF_decode_oer, /* Same as SET OF decoder. */\r
+ SEQUENCE_OF_encode_oer, /* Same as SET OF encoder */\r
+#endif /* ASN_DISABLE_OER_SUPPORT */\r
+#ifdef ASN_DISABLE_PER_SUPPORT\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+#else\r
+ SEQUENCE_OF_decode_uper, /* Same as SET OF decoder */\r
+ SEQUENCE_OF_encode_uper,\r
+ SEQUENCE_OF_decode_aper,\r
+ SEQUENCE_OF_encode_aper,\r
+#endif /* ASN_DISABLE_PER_SUPPORT */\r
+ SEQUENCE_OF_random_fill,\r
+ 0 /* Use generic outmost tag fetcher */\r
+};\r
+\r