2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <constr_SET_OF.h>
9 typedef struct jer_tmp_enc_s {
16 SET_OF_encode_jer_callback(const void *buffer, size_t size, void *key) {
17 jer_tmp_enc_t *t = (jer_tmp_enc_t *)key;
18 if(t->offset + size >= t->size) {
19 size_t newsize = (t->size << 2) + size;
20 void *p = REALLOC(t->buffer, newsize);
25 memcpy((char *)t->buffer + t->offset, buffer, size);
31 SET_OF_jer_order(const void *aptr, const void *bptr) {
32 const jer_tmp_enc_t *a = (const jer_tmp_enc_t *)aptr;
33 const jer_tmp_enc_t *b = (const jer_tmp_enc_t *)bptr;
34 size_t minlen = a->offset;
36 if(b->offset < minlen) minlen = b->offset;
37 /* Well-formed UTF-8 has this nice lexicographical property... */
38 ret = memcmp(a->buffer, b->buffer, minlen);
39 if(ret != 0) return ret;
40 if(a->offset == b->offset)
42 if(a->offset == minlen)
48 SET_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
49 enum jer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
51 asn_enc_rval_t er = {0,0,0};
52 const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
53 const asn_TYPE_member_t *elm = td->elements;
54 const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
55 const char *mname = specs->as_XMLValueList
56 ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
57 size_t mlen = mname ? strlen(mname) : 0;
59 jer_tmp_enc_t *encs = 0;
60 size_t encs_count = 0;
61 void *original_app_key = app_key;
62 asn_app_consume_bytes_f *original_cb = cb;
65 if(!sptr) ASN__ENCODE_FAILED;
68 encs = (jer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
69 if(!encs) ASN__ENCODE_FAILED;
70 cb = SET_OF_encode_jer_callback;
75 for(i = 0; i < list->count; i++) {
76 asn_enc_rval_t tmper = {0,0,0};
78 void *memb_ptr = list->array[i];
79 if(!memb_ptr) continue;
82 memset(&encs[encs_count], 0, sizeof(encs[0]));
83 app_key = &encs[encs_count];
88 if(!xcan) ASN__TEXT_INDENT(1, ilevel);
89 ASN__CALLBACK3("\"", 1, mname, mlen, "\": ", 3);
92 if(!xcan && specs->as_XMLValueList == 1)
93 ASN__TEXT_INDENT(1, ilevel + 1);
94 tmper = elm->type->op->jer_encoder(elm->type, memb_ptr,
95 ilevel + (specs->as_XMLValueList != 2),
97 if(tmper.encoded == -1) return tmper;
98 er.encoded += tmper.encoded;
99 if(tmper.encoded == 0 && specs->as_XMLValueList) {
100 const char *name = elm->type->xml_tag;
101 size_t len = strlen(name);
102 ASN__CALLBACK3("<", 1, name, len, "/>", 2);
106 /* ASN__CALLBACK3("</", 2, mname, mlen, ">", 1); */
111 if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
114 jer_tmp_enc_t *enc = encs;
115 jer_tmp_enc_t *end = encs + encs_count;
116 ssize_t control_size = 0;
120 app_key = original_app_key;
121 qsort(encs, encs_count, sizeof(encs[0]), SET_OF_jer_order);
123 for(; enc < end; enc++) {
124 ASN__CALLBACK(enc->buffer, enc->offset);
125 FREEMEM(enc->buffer);
127 control_size += enc->offset;
129 assert(control_size == er.encoded);
138 for(n = 0; n < encs_count; n++) {
139 FREEMEM(encs[n].buffer);