aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons/constr_SET_OF.c
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-10-03 09:12:07 +0000
committerLev Walkin <vlm@lionet.info>2004-10-03 09:12:07 +0000
commitd519380089e6cdcf2a94bf71b363cf92fe5d5099 (patch)
treea3767a691d9f6fde33f6705ca557a857defd953d /skeletons/constr_SET_OF.c
parentff1333afb1ee1b3db32abec0b16ad52e4812a0c7 (diff)
Support for canonical CANONICAL-XER ordering
Diffstat (limited to 'skeletons/constr_SET_OF.c')
-rw-r--r--skeletons/constr_SET_OF.c94
1 files changed, 92 insertions, 2 deletions
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;
}