diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c index d9f93c3b2fc89b7d964e010731fe601f9dc7f054..a64c2ff48f2abac4fb89be7ac72127481459c4f8 100644 --- a/skeletons/constr_SET.c +++ b/skeletons/constr_SET.c @@ -435,11 +435,11 @@ SET_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ asn_enc_rval_t SET_encode_der(asn_TYPE_descriptor_t *td, - void *ptr, int tag_mode, ber_tlv_tag_t tag, + void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics; size_t computed_size = 0; - asn_enc_rval_t my_erval; + asn_enc_rval_t er; int t2m_build_own = (specs->tag2el_count != td->elements_count); asn_TYPE_tag2member_t *t2m; int t2m_count; @@ -451,12 +451,7 @@ SET_encode_der(asn_TYPE_descriptor_t *td, */ if(t2m_build_own) { (void *)t2m = alloca(td->elements_count * sizeof(t2m[0])); - if(!t2m) { /* There are such platforms */ - my_erval.encoded = -1; - my_erval.failed_type = td; - my_erval.structure_ptr = ptr; - return my_erval; - } + if(!t2m) _ASN_ENCODE_FAILED; /* There are such platforms */ t2m_count = 0; } else { /* @@ -472,14 +467,14 @@ SET_encode_der(asn_TYPE_descriptor_t *td, */ for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm = &td->elements[edx]; - asn_enc_rval_t erval; + asn_enc_rval_t tmper; void *memb_ptr; /* * Compute the length of the encoding of this member. */ if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)ptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) { if(t2m_build_own) { t2m[t2m_count].el_no = edx; @@ -489,14 +484,14 @@ SET_encode_der(asn_TYPE_descriptor_t *td, continue; } } else { - memb_ptr = (void *)((char *)ptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } - erval = elm->type->der_encoder(elm->type, memb_ptr, + tmper = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, 0, 0); - if(erval.encoded == -1) - return erval; - computed_size += erval.encoded; + if(tmper.encoded == -1) + return tmper; + computed_size += tmper.encoded; /* * Remember the outmost tag of this member. @@ -533,72 +528,74 @@ SET_encode_der(asn_TYPE_descriptor_t *td, * Encode the TLV for the sequence itself. */ ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); - if(ret == -1) { - my_erval.encoded = -1; - my_erval.failed_type = td; - my_erval.structure_ptr = ptr; - return my_erval; - } - my_erval.encoded = computed_size + ret; + if(ret == -1) _ASN_ENCODE_FAILED; + er.encoded = computed_size + ret; - if(!cb) return my_erval; + if(!cb) return er; /* * Encode all members. */ for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm; - asn_enc_rval_t erval; + asn_enc_rval_t tmper; void *memb_ptr; /* Encode according to the tag order */ elm = &td->elements[t2m[edx].el_no]; if(elm->flags & ATF_POINTER) { - memb_ptr = *(void **)((char *)ptr + elm->memb_offset); + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); if(!memb_ptr) continue; } else { - memb_ptr = (void *)((char *)ptr + elm->memb_offset); + memb_ptr = (void *)((char *)sptr + elm->memb_offset); } - erval = elm->type->der_encoder(elm->type, memb_ptr, + tmper = elm->type->der_encoder(elm->type, memb_ptr, elm->tag_mode, elm->tag, cb, app_key); - if(erval.encoded == -1) - return erval; - computed_size -= erval.encoded; + if(tmper.encoded == -1) + return tmper; + computed_size -= tmper.encoded; } if(computed_size != 0) { /* * Encoded size is not equal to the computed size. */ - my_erval.encoded = -1; - my_erval.failed_type = td; - my_erval.structure_ptr = ptr; + _ASN_ENCODE_FAILED; } - return my_erval; + return er; } asn_enc_rval_t SET_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb, void *app_key) { + asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics; asn_enc_rval_t er; int xcan = (flags & XER_F_CANONICAL); + asn_TYPE_tag2member_t *t2m = specs->tag2el_cxer; + int t2m_count = specs->tag2el_cxer_count; int edx; if(!sptr) _ASN_ENCODE_FAILED; + assert(t2m_count == td->elements_count); + er.encoded = 0; - for(edx = 0; edx < td->elements_count; edx++) { + for(edx = 0; edx < t2m_count; edx++) { asn_enc_rval_t tmper; - asn_TYPE_member_t *elm = &td->elements[edx]; + asn_TYPE_member_t *elm; void *memb_ptr; - const char *mname = elm->name; - unsigned int mlen = strlen(elm->name); + const char *mname; + unsigned int mlen; + + elm = &td->elements[t2m[edx].el_no]; + mname = elm->name; + mlen = strlen(elm->name); if(elm->flags & ATF_POINTER) { memb_ptr = *(void **)((char *)sptr + elm->memb_offset); @@ -624,6 +621,8 @@ SET_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); return er; +cb_failed: + _ASN_ENCODE_FAILED; } int diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h index 8f9b265cb46beb7f9c76c9d32cda6421757dadeb..41d6a7fb9fc2cc46e4b4fb01bcfb1c05d64dca72 100644 --- a/skeletons/constr_SET.h +++ b/skeletons/constr_SET.h @@ -18,10 +18,19 @@ typedef struct asn_SET_specifics_s { /* * Tags to members mapping table (sorted). + * Sometimes suitable for DER encoding (untagged CHOICE is present); + * if so, tag2el_count will be greater than td->elements_count. */ asn_TYPE_tag2member_t *tag2el; int tag2el_count; + /* + * Tags to members mapping table, second edition. + * Suitable for CANONICAL-XER encoding. + */ + asn_TYPE_tag2member_t *tag2el_cxer; + int tag2el_cxer_count; + /* * Extensions-related stuff. */ diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index 00c4cb3dd256a672559ab18410bad0bd12939b06..c298cc297173a3acc646f08d54353f53a0926a81 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -5,6 +5,7 @@ #include <asn_internal.h> #include <constr_SET_OF.h> #include <asn_SET_OF.h> +#include <assert.h> /* * Number of bytes left for this structure. @@ -449,6 +450,43 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, return erval; } +typedef struct xer_tmp_enc_s { + void *buffer; + size_t offset; + size_t size; +} xer_tmp_enc_t; +static int +SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { + xer_tmp_enc_t *t = (xer_tmp_enc_t *)key; + if(t->offset + size >= t->size) { + size_t newsize = (t->size << 2) + size; + void *p = REALLOC(t->buffer, newsize); + if(!p) return -1; + t->buffer = p; + t->size = newsize; + } + memcpy((char *)t->buffer + t->offset, buffer, size); + t->offset += size; + return 0; +} +static int +SET_OF_xer_order(const void *aptr, const void *bptr) { + const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr; + const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr; + size_t minlen = a->offset; + int ret; + if(b->offset < minlen) minlen = b->offset; + /* Well-formed UTF-8 has this nice lexicographical property... */ + ret = memcmp(a->buffer, b->buffer, minlen); + if(ret != 0) return ret; + if(a->offset == b->offset) + return 0; + if(a->offset == minlen) + return -1; + return 1; +} + + asn_enc_rval_t SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, enum xer_encoder_flags_e flags, @@ -461,19 +499,36 @@ SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, ? 0 : ((*element->name) ? element->name : element->type->name); size_t mlen = mname ? strlen(mname) : 0; int xcan = (flags & XER_F_CANONICAL); + xer_tmp_enc_t *encs = 0; + size_t encs_count = 0; + void *original_app_key = app_key; + asn_app_consume_bytes_f *original_cb = cb; int i; if(!sptr) _ASN_ENCODE_FAILED; + (void *)list = sptr; + + if(xcan) { + encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); + if(!encs) _ASN_ENCODE_FAILED; + cb = SET_OF_encode_xer_callback; + } + er.encoded = 0; - (void *)list = sptr; for(i = 0; i < list->count; i++) { asn_enc_rval_t tmper; void *memb_ptr = list->array[i]; if(!memb_ptr) continue; + if(encs) { + memset(&encs[encs_count], 0, sizeof(encs[0])); + app_key = &encs[encs_count]; + encs_count++; + } + if(mname) { if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); @@ -481,7 +536,11 @@ SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, tmper = element->type->xer_encoder(element->type, memb_ptr, ilevel + 1, flags, cb, app_key); - if(tmper.encoded == -1) return tmper; + if(tmper.encoded == -1) { + td = tmper.failed_type; + sptr = tmper.structure_ptr; + goto cb_failed; + } if(mname) { _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1); @@ -493,6 +552,37 @@ SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + if(encs) { + xer_tmp_enc_t *enc = encs; + xer_tmp_enc_t *end = encs + encs_count; + ssize_t control_size = 0; + + cb = original_cb; + app_key = original_app_key; + qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); + + for(; enc < end; enc++) { + _ASN_CALLBACK(enc->buffer, enc->offset); + FREEMEM(enc->buffer); + enc->buffer = 0; + control_size += enc->offset; + } + assert(control_size == er.encoded); + } + + goto cleanup; +cb_failed: + er.encoded = -1; + er.failed_type = td; + er.structure_ptr = sptr; +cleanup: + if(encs) { + while(encs_count-- > 0) { + if(encs[encs_count].buffer) + FREEMEM(encs[encs_count].buffer); + } + free(encs); + } return er; }