Support for canonical CANONICAL-XER ordering

This commit is contained in:
Lev Walkin 2004-10-03 09:12:07 +00:00
parent ff1333afb1
commit d519380089
3 changed files with 138 additions and 40 deletions

View File

@ -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

View File

@ -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.
*/

View File

@ -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;
}