aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons
diff options
context:
space:
mode:
Diffstat (limited to 'skeletons')
-rw-r--r--skeletons/constr_SET.c75
-rw-r--r--skeletons/constr_SET.h9
-rw-r--r--skeletons/constr_SET_OF.c94
3 files changed, 138 insertions, 40 deletions
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index d9f93c3b..a64c2ff4 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 8f9b265c..41d6a7fb 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -18,11 +18,20 @@ 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.
*/
int extensible; /* Whether SET is extensible */
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index 00c4cb3d..c298cc29 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;
}