Commit 45daecbb authored by Senthil Prabakaran's avatar Senthil Prabakaran Committed by Mouse

Add JER Support

parent 0101252e
......@@ -83,6 +83,8 @@ asn1c__save_asn_config(arg_t *arg, const char *destdir,
safe_fprintf(mkf, "#define ASN_DISABLE_PRINT_SUPPORT 1\n");
if(!(arg->flags & A1C_GEN_RFILL))
safe_fprintf(mkf, "#define ASN_DISABLE_RFILL_SUPPORT 1\n");
if(!(arg->flags & A1C_GEN_JER))
safe_fprintf(mkf, "#define ASN_DISABLE_JER_SUPPORT 1\n");
fclose(mkf);
safe_fprintf(stderr, "Generated %s%s\n", destdir, cfgfile_name);
......@@ -189,7 +191,8 @@ asn1c__save_library_makefile(arg_t *arg, const asn1c_dep_chainset *deps,
(arg->flags & A1C_GEN_UPER) ? "" : "-DASN_DISABLE_UPER_SUPPORT ",
(arg->flags & A1C_GEN_APER) ? "" : "-DASN_DISABLE_APER_SUPPORT ",
(arg->flags & A1C_GEN_PRINT) ? "" : "-DASN_DISABLE_PRINT_SUPPORT ",
(arg->flags & A1C_GEN_RFILL) ? "" : "-DASN_DISABLE_RFILL_SUPPORT ");
(arg->flags & A1C_GEN_RFILL) ? "" : "-DASN_DISABLE_RFILL_SUPPORT ",
(arg->flags & A1C_GEN_JER) ? "" : "-DASN_DISABLE_JER_SUPPORT ");
safe_fprintf(
mkf,
......@@ -238,6 +241,7 @@ asn1c__save_example_mk_makefile(arg_t *arg, const asn1c_dep_chainset *deps,
(arg->flags & A1C_GEN_APER) ? "": "-DASN_DISABLE_APER_SUPPORT ",
(arg->flags & A1C_GEN_PRINT) ? "": "-DASN_DISABLE_PRINT_SUPPORT ",
(arg->flags & A1C_GEN_RFILL) ? "": "-DASN_DISABLE_RFILL_SUPPORT ",
(arg->flags & A1C_GEN_JER) ? "": "-DASN_DISABLE_JER_SUPPORT ",
need_to_generate_pdu_collection(arg) ? "-DASN_PDU_COLLECTION " : "");
if(dlist) {
......@@ -321,6 +325,7 @@ asn1c__save_example_am_makefile(arg_t *arg, const asn1c_dep_chainset *deps, cons
(arg->flags & A1C_GEN_APER) ? "": "-DASN_DISABLE_APER_SUPPORT ",
(arg->flags & A1C_GEN_PRINT) ? "": "-DASN_DISABLE_PRINT_SUPPORT ",
(arg->flags & A1C_GEN_RFILL) ? "": "-DASN_DISABLE_RFILL_SUPPORT ",
(arg->flags & A1C_GEN_JER) ? "": "-DASN_DISABLE_JER_SUPPORT ",
need_to_generate_pdu_collection(arg) ? "-DASN_PDU_COLLECTION " : "", destdir);
if(dlist) {
......
......@@ -123,6 +123,12 @@ enum asn1c_flags {
* Generate Aligned Packed Encoding Rules support code
*/
A1C_GEN_APER = 0x8000000,
/*
* -gen-JER / -no-gen-JER
* Generate JSON Encoding Rules support code
*/
A1C_GEN_JER = 0x10000000,
};
/*
......
......@@ -102,6 +102,7 @@ libasn1cskeletons_la_SOURCES = \
uper_support.c uper_support.h \
xer_decoder.c xer_decoder.h \
xer_encoder.c xer_encoder.h \
jer_encoder.c jer_encoder.h \
xer_support.c xer_support.h \
ANY_aper.c \
ANY_ber.c \
......
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NativeInteger.h>
/*
* Decode the chunk of XML text encoding INTEGER.
*/
asn_dec_rval_t
NativeInteger_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr,
size_t size) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
INTEGER_t st;
void *st_ptr = (void *)&st;
long *native = (long *)*sptr;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&st, 0, sizeof(st));
rval = INTEGER_decode_jer(opt_codec_ctx, td, &st_ptr,
opt_mname, buf_ptr, size);
if(rval.code == RC_OK) {
long l;
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&st, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
} else {
*native = l;
}
} else {
/*
* Cannot restart from the middle;
* there is no place to save state in the native type.
* Request a continuation from the very beginning.
*/
rval.consumed = 0;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
return rval;
}
asn_enc_rval_t
NativeInteger_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, void *app_key) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit int */
asn_enc_rval_t er = {0,0,0};
const long *native = (const long *)sptr;
(void)ilevel;
(void)flags;
if(!native) ASN__ENCODE_FAILED;
er.encoded = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|| cb(scratch, er.encoded, app_key) < 0)
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
......@@ -67,6 +67,11 @@ xer_type_decoder_f REAL_decode_xer;
xer_type_encoder_f REAL_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f REAL_decode_jer;
jer_type_encoder_f REAL_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f REAL_decode_oer;
oer_type_encoder_f REAL_encode_oer;
......
......@@ -36,6 +36,11 @@ extern asn_TYPE_operation_t asn_OP_TeletexString;
#define TeletexString_encode_xer OCTET_STRING_encode_xer
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define TeletexString_decode_jer OCTET_STRING_decode_jer_hex
#define TeletexString_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define TeletexString_decode_uper OCTET_STRING_decode_uper
#define TeletexString_encode_uper OCTET_STRING_encode_uper
......
......@@ -37,6 +37,11 @@ xer_type_decoder_f UniversalString_decode_xer;
xer_type_encoder_f UniversalString_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f UniversalString_decode_jer;
jer_type_encoder_f UniversalString_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define UniversalString_decode_uper OCTET_STRING_decode_uper
#define UniversalString_encode_uper OCTET_STRING_encode_uper
......
/*-
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <stdio.h>
#include <errno.h>
/*
* The JER encoder of any type. May be invoked by the application.
*/
asn_enc_rval_t
jer_encode(const asn_TYPE_descriptor_t *td, const void *sptr,
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;
const char *mname;
size_t mlen;
int xcan = (jer_flags & JER_F_CANONICAL) ? 1 : 2;
if(!td || !sptr) goto cb_failed;
mname = td->xml_tag;
mlen = strlen(mname);
ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
tmper = td->op->jer_encoder(td, sptr, 1, jer_flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
er.encoded += tmper.encoded;
ASN__CALLBACK3("</", 2, mname, mlen, ">\n", xcan);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
/*
* This is a helper function for jer_fprint, which directs all incoming data
* into the provided file descriptor.
*/
static int
jer__print2fp(const void *buffer, size_t size, void *app_key) {
FILE *stream = (FILE *)app_key;
if(fwrite(buffer, 1, size, stream) != size)
return -1;
return 0;
}
int
jer_fprint(FILE *stream, const asn_TYPE_descriptor_t *td, const void *sptr) {
asn_enc_rval_t er = {0,0,0};
if(!stream) stream = stdout;
if(!td || !sptr)
return -1;
er = jer_encode(td, sptr, JER_F_BASIC, jer__print2fp, stream);
if(er.encoded == -1)
return -1;
return fflush(stream);
}
struct jer_buffer {
char *buffer;
size_t buffer_size;
size_t allocated_size;
};
static int
jer__buffer_append(const void *buffer, size_t size, void *app_key) {
struct jer_buffer *xb = app_key;
while(xb->buffer_size + size + 1 > xb->allocated_size) {
size_t new_size = 2 * (xb->allocated_size ? xb->allocated_size : 64);
char *new_buf = MALLOC(new_size);
if(!new_buf) return -1;
if (xb->buffer) {
memcpy(new_buf, xb->buffer, xb->buffer_size);
}
FREEMEM(xb->buffer);
xb->buffer = new_buf;
xb->allocated_size = new_size;
}
memcpy(xb->buffer + xb->buffer_size, buffer, size);
xb->buffer_size += size;
xb->buffer[xb->buffer_size] = '\0';
return 0;
}
enum jer_equivalence_e
jer_equivalent(const struct asn_TYPE_descriptor_s *td, const void *struct1,
const void *struct2, FILE *opt_debug_stream) {
struct jer_buffer xb1 = {0, 0, 0};
struct jer_buffer xb2 = {0, 0, 0};
asn_enc_rval_t e1, e2;
asn_dec_rval_t rval;
void *sptr = NULL;
if(!td || !struct1 || !struct2) {
if(opt_debug_stream) {
if(!td) fprintf(opt_debug_stream, "Type descriptor missing\n");
if(!struct1) fprintf(opt_debug_stream, "Structure 1 missing\n");
if(!struct2) fprintf(opt_debug_stream, "Structure 2 missing\n");
}
return XEQ_FAILURE;
}
e1 = jer_encode(td, struct1, JER_F_BASIC, jer__buffer_append, &xb1);
if(e1.encoded == -1) {
if(opt_debug_stream) {
fprintf(stderr, "JER Encoding of %s failed\n", td->name);
}
FREEMEM(xb1.buffer);
return XEQ_ENCODE1_FAILED;
}
e2 = jer_encode(td, struct2, JER_F_BASIC, jer__buffer_append, &xb2);
if(e2.encoded == -1) {
if(opt_debug_stream) {
fprintf(stderr, "JER Encoding of %s failed\n", td->name);
}
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_ENCODE1_FAILED;
}
if(xb1.buffer_size != xb2.buffer_size
|| memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) {
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"Structures JER-encoded into different byte streams:\n=== "
"Structure 1 ===\n%s\n=== Structure 2 ===\n%s\n",
xb1.buffer, xb2.buffer);
}
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_DIFFERENT;
} else {
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"Both structures encoded into the same JER byte stream "
"of size %" ASN_PRI_SIZE ":\n%s",
xb1.buffer_size, xb1.buffer);
}
}
rval = jer_decode(NULL, td, (void **)&sptr, xb1.buffer,
xb1.buffer_size);
switch(rval.code) {
case RC_OK:
break;
case RC_WMORE:
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"Structure %s JER decode unexpectedly requires "
"more data:\n%s\n",
td->name, xb1.buffer);
}
/* Fall through */
case RC_FAIL:
default:
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"Structure %s JER decoding resulted in failure.\n",
td->name);
}
ASN_STRUCT_FREE(*td, sptr);
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_DECODE_FAILED;
}
if(rval.consumed != xb1.buffer_size
&& ((rval.consumed > xb1.buffer_size)
|| jer_whitespace_span(xb1.buffer + rval.consumed,
xb1.buffer_size - rval.consumed)
!= (xb1.buffer_size - rval.consumed))) {
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"Round-trip decode of %s required less bytes (%" ASN_PRI_SIZE ") than "
"encoded (%" ASN_PRI_SIZE ")\n",
td->name, rval.consumed, xb1.buffer_size);
}
ASN_STRUCT_FREE(*td, sptr);
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_ROUND_TRIP_FAILED;
}
/*
* Reuse xb2 to encode newly decoded structure.
*/
FREEMEM(xb2.buffer);
memset(&xb2, 0, sizeof(xb2));
e2 = jer_encode(td, sptr, JER_F_BASIC, jer__buffer_append, &xb2);
if(e2.encoded == -1) {
if(opt_debug_stream) {
fprintf(stderr, "JER Encoding of round-trip decode of %s failed\n",
td->name);
}
ASN_STRUCT_FREE(*td, sptr);
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_ROUND_TRIP_FAILED;
}
ASN_STRUCT_FREE(*td, sptr);
sptr = 0;
if(xb1.buffer_size != xb2.buffer_size
|| memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) {
if(opt_debug_stream) {
fprintf(opt_debug_stream,
"JER Encoding of round-trip decode of %s resulted in "
"different byte stream:\n"
"=== Original ===\n%s\n"
"=== Round-tripped ===\n%s\n",
xb1.buffer, xb2.buffer, td->name);
}
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_ROUND_TRIP_FAILED;
}
FREEMEM(xb1.buffer);
FREEMEM(xb2.buffer);
return XEQ_SUCCESS;
}
/*-
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _JER_ENCODER_H_
#define _JER_ENCODER_H_
#include <asn_application.h>
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/* Flags used by the jer_encode() and (*jer_type_encoder_f), defined below */
enum jer_encoder_flags_e {
/* Mode of encoding */
JER_F_BASIC = 0x01, /* BASIC-JER (pretty-printing) */
JER_F_CANONICAL = 0x02 /* Canonical JER (strict rules) */
};
/*
* The JER encoder of any type. May be invoked by the application.
* Produces CANONICAL-JER and BASIC-JER depending on the (jer_flags).
*/
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 */
);
/*
* The variant of the above function which dumps the BASIC-JER (JER_F_BASIC)
* output into the chosen file pointer.
* RETURN VALUES:
* 0: The structure is printed.
* -1: Problem printing the structure.
* WARNING: No sensible errno value is returned.
*/
int jer_fprint(FILE *stream, const struct asn_TYPE_descriptor_s *td,
const void *struct_ptr);
/*
* A helper function that uses JER encoding/decoding to verify that:
* - Both structures encode into the same BASIC JER.
* - Both resulting JER byte streams can be decoded back.
* - Both decoded structures encode into the same BASIC JER (round-trip).
* All of this verifies equivalence between structures and a round-trip.
* ARGUMENTS:
* (opt_debug_stream) - If specified, prints ongoing details.
*/
enum jer_equivalence_e {
JEQ_SUCCESS, /* The only completely positive return value */
JEQ_FAILURE, /* General failure */
JEQ_ENCODE1_FAILED, /* First structure JER encoding failed */
JEQ_ENCODE2_FAILED, /* Second structure JER encoding failed */
JEQ_DIFFERENT, /* Structures encoded into different JER */
JEQ_DECODE_FAILED, /* Decode of the JER data failed */
JEQ_ROUND_TRIP_FAILED /* Bad round-trip */
};
enum jer_equivalence_e jer_equivalent(
const struct asn_TYPE_descriptor_s *type_descriptor, const void *struct1,
const void *struct2, FILE *opt_debug_stream);
/*
* Type of the generic JER encoder.
*/
typedef asn_enc_rval_t(jer_type_encoder_f)(
const struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr, /* Structure to be encoded */
int ilevel, /* Level of indentation */
enum jer_encoder_flags_e jer_flags,
asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */
void *app_key /* Arbitrary callback argument */
);
#ifdef __cplusplus
}
#endif
#endif /* _JER_ENCODER_H_ */
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