Unverified Commit e4ea3fbc authored by Mouse's avatar Mouse Committed by GitHub

Merge pull request #160 from v0-e/jer-minified

jer: Minified JSON option
parents f4d3232d 9c507a90
......@@ -229,6 +229,9 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
#if !defined(ASN_DISABLE_XER_SUPPORT)
enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
enum jer_encoder_flags_e jer_flags = JER_F;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
(void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
......@@ -432,9 +435,15 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
case ATS_JER_MINIFIED:
/* Currently JER_F and JER_F_MINIFIED have opposite purposes
* so we just flip the flag. */
jer_flags &= ~JER_F;
jer_flags |= JER_F_MINIFIED;
/* Fall through. */
case ATS_JER:
if(td->op->jer_encoder) {
er = jer_encode(td, sptr, callback, callback_key);
er = jer_encode(td, sptr, jer_flags, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->jer_encoder) {
errno = EBADF; /* Structure has incorrect form. */
......@@ -535,6 +544,7 @@ asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
case ATS_JER:
case ATS_JER_MINIFIED:
#if !defined(ASN_DISABLE_JER_SUPPORT)
return jer_decode(opt_codec_ctx, td, sptr, buffer, size);
#else
......
......@@ -61,7 +61,13 @@ enum asn_transfer_syntax {
*/
ATS_BASIC_XER,
ATS_CANONICAL_XER,
/*
* X.697:
* JER: JSON Encoding Rules.
* MINIFIED produces a whitespace-free JSON.
*/
ATS_JER,
ATS_JER_MINIFIED,
};
/*
......
......@@ -270,7 +270,7 @@ CHOICE_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
(const asn_CHOICE_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
unsigned present = 0;
int xcan = 0;
int jmin = (flags & JER_F_MINIFIED);
if(!sptr)
ASN__ENCODE_FAILED;
......@@ -300,15 +300,19 @@ CHOICE_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
er.encoded = 0;
ASN__CALLBACK("{",1);
if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);
ASN__CALLBACK3("\"", 1, mname, mlen, "\": ", 3);
if(!jmin) {
ASN__TEXT_INDENT(1, ilevel + 1);
ASN__CALLBACK3("\"", 1, mname, mlen, "\": ", 3);
} else {
ASN__CALLBACK3("\"", 1, mname, mlen, "\":", 2);
}
tmper = elm->type->op->jer_encoder(elm->type, memb_ptr,
ilevel + 1, flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
er.encoded += tmper.encoded;
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
if(!jmin) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK("}", 1);
}
......
......@@ -15,7 +15,7 @@ SEQUENCE_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
const asn_TYPE_member_t *elm = td->elements;
const asn_anonymous_sequence_ *list = _A_CSEQUENCE_FROM_VOID(sptr);
int xcan = 0;
int jmin = (flags & JER_F_MINIFIED);
int i;
if(!sptr) ASN__ENCODE_FAILED;
......@@ -28,7 +28,7 @@ SEQUENCE_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
void *memb_ptr = list->array[i];
if(!memb_ptr) continue;
if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);
if(!jmin) ASN__TEXT_INDENT(1, ilevel + 1);
tmper = elm->type->op->jer_encoder(elm->type, memb_ptr, ilevel + 1,
flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
......@@ -36,7 +36,7 @@ SEQUENCE_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
if(tmper.encoded == 0 && specs->as_XMLValueList) {
const char *name = elm->type->xml_tag;
size_t len = strlen(name);
if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);
if(!jmin) ASN__TEXT_INDENT(1, ilevel + 1);
ASN__CALLBACK3("\"", 1, name, len, "\"", 1);
}
......@@ -45,7 +45,7 @@ SEQUENCE_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
}
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
if(!jmin) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK("]", 1);
ASN__ENCODED_OK(er);
......
......@@ -298,7 +298,7 @@ asn_enc_rval_t SEQUENCE_encode_jer(const asn_TYPE_descriptor_t *td, const void *
int ilevel, enum jer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er = {0,0,0};
int xcan = 0;
int jmin = (flags & JER_F_MINIFIED);
asn_TYPE_descriptor_t *tmp_def_val_td = 0;
void *tmp_def_val = 0;
size_t edx;
......@@ -344,8 +344,12 @@ asn_enc_rval_t SEQUENCE_encode_jer(const asn_TYPE_descriptor_t *td, const void *
bAddComma = 0;
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel+1);
ASN__CALLBACK3("\"", 1, mname, mlen, "\": ", 3);
if(!jmin) {
ASN__TEXT_INDENT(1, ilevel + 1);
ASN__CALLBACK3("\"", 1, mname, mlen, "\": ", 3);
} else {
ASN__CALLBACK3("\"", 1, mname, mlen, "\":", 2);
}
/* Print the member itself */
tmper = elm->type->op->jer_encoder(elm->type, memb_ptr, ilevel + 1,
......@@ -360,7 +364,7 @@ asn_enc_rval_t SEQUENCE_encode_jer(const asn_TYPE_descriptor_t *td, const void *
bAddComma = 1;
}
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
if(!jmin) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK("}", 1);
......
......@@ -180,44 +180,6 @@ SET_OF_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
RETURN(RC_FAIL);
}
typedef struct jer_tmp_enc_s {
void *buffer;
size_t offset;
size_t size;
} jer_tmp_enc_t;
static int
SET_OF_encode_jer_callback(const void *buffer, size_t size, void *key) {
jer_tmp_enc_t *t = (jer_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_jer_order(const void *aptr, const void *bptr) {
const jer_tmp_enc_t *a = (const jer_tmp_enc_t *)aptr;
const jer_tmp_enc_t *b = (const jer_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_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
enum jer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
......@@ -226,21 +188,11 @@ SET_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
const asn_TYPE_member_t *elm = td->elements;
const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
int xcan = 0;
jer_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 jmin = (flags & JER_F_MINIFIED);
int i;
if(!sptr) ASN__ENCODE_FAILED;
if(xcan) {
encs = (jer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
if(!encs) ASN__ENCODE_FAILED;
cb = SET_OF_encode_jer_callback;
}
er.encoded = 0;
ASN__CALLBACK("[", 1);
......@@ -250,13 +202,7 @@ SET_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
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++;
}
ASN__TEXT_INDENT(1, ilevel + 1);
if(!jmin) ASN__TEXT_INDENT(1, ilevel + 1);
tmper = elm->type->op->jer_encoder(elm->type, memb_ptr,
ilevel + (specs->as_XMLValueList != 2),
flags, cb, app_key);
......@@ -272,38 +218,12 @@ SET_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
if(!jmin) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK("]", 1);
if(encs) {
jer_tmp_enc_t *enc = encs;
jer_tmp_enc_t *end = encs + encs_count;
ssize_t control_size = 0;
er.encoded = 0;
cb = original_cb;
app_key = original_app_key;
qsort(encs, encs_count, sizeof(encs[0]), SET_OF_jer_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:
ASN__ENCODE_FAILED;
cleanup:
if(encs) {
size_t n;
for(n = 0; n < encs_count; n++) {
FREEMEM(encs[n].buffer);
}
FREEMEM(encs);
}
ASN__ENCODED_OK(er);
}
......@@ -11,15 +11,14 @@
*/
asn_enc_rval_t
jer_encode(const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_consume_bytes_f *cb,
enum jer_encoder_flags_e jer_flags, asn_app_consume_bytes_f *cb,
void *app_key) {
asn_enc_rval_t er = {0, 0, 0};
asn_enc_rval_t tmper;
if(!td || !sptr) goto cb_failed;
int xFail = 1; /* TODO JER flags */
tmper = td->op->jer_encoder(td, sptr, 0, xFail, cb, app_key);
tmper = td->op->jer_encoder(td, sptr, 0, jer_flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
er.encoded += tmper.encoded;
......@@ -50,7 +49,7 @@ jer_fprint(FILE *stream, const asn_TYPE_descriptor_t *td, const void *sptr) {
if(!td || !sptr)
return -1;
er = jer_encode(td, sptr, jer__print2fp, stream);
er = jer_encode(td, sptr, JER_F, jer__print2fp, stream);
if(er.encoded == -1)
return -1;
......
......@@ -13,15 +13,13 @@ extern "C" {
struct asn_TYPE_descriptor_s; /* Forward declaration */
/* Flags used by the jer_encode() and (*jer_type_encoder_f), defined below
*
* This isn't actually used, it might be used in the future to support
* both normal JSON and prettified JSON output or removed.
* It came from XER
/*
* Flags used by the jer_encode() and (*jer_type_encoder_f), defined below
*/
enum jer_encoder_flags_e {
/* Mode of encoding */
JER_F = 0x01, /* JER (pretty-printing) */
JER_F = 0x01, /* JER (pretty-printing) */
JER_F_MINIFIED = 0x02, /* JER (minified) */
};
/*
......@@ -30,6 +28,7 @@ enum jer_encoder_flags_e {
*/
asn_enc_rval_t jer_encode(const struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr, /* Structure to be encoded */
enum jer_encoder_flags_e jer_flags,
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key /* Arbitrary callback argument */
);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment