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

Merge pull request #144 from v0-e/jer-decoder

JER decoder
parents 23e6769e 47c81e8b
......@@ -53,6 +53,7 @@
#include <RELATIVE-OID_rfill.c>
#include <asn_codecs_prim.c>
#include <asn_codecs_prim_ber.c>
#include <asn_codecs_prim_jer.c>
#include <asn_codecs_prim_xer.c>
#include <asn1p_integer.c>
#include <asn_internal.c>
......@@ -824,6 +825,26 @@ xer_decode_general(const asn_codec_ctx_t *opt_codec_ctx, asn_struct_ctx_t *ctx,
return rv;
}
asn_dec_rval_t
jer_decode_general(const asn_codec_ctx_t *opt_codec_ctx, asn_struct_ctx_t *ctx,
void *struct_key, const char *json_key, const void *buf_ptr,
size_t size,
int (*otd)(void *struct_key, const void *chunk_buf,
size_t chunk_size),
ssize_t (*br)(void *struct_key, const void *chunk_buf,
size_t chunk_size, int have_more)) {
asn_dec_rval_t rv = {0, 0};
(void)opt_codec_ctx;
(void)ctx;
(void)struct_key;
(void)json_key;
(void)buf_ptr;
(void)size;
(void)otd;
(void)br;
return rv;
}
size_t
xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
(void)chunk_buf;
......@@ -831,6 +852,13 @@ xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
return 0;
}
size_t
jer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
(void)chunk_buf;
(void)chunk_size;
return 0;
}
int
OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *a,
const void *b) {
......
......@@ -33,9 +33,11 @@ asn_TYPE_operation_t asn_OP_ANY = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
ANY_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
......
......@@ -43,6 +43,7 @@ xer_type_encoder_f ANY_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f ANY_decode_jer;
jer_type_encoder_f ANY_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -39,9 +39,11 @@ asn_TYPE_operation_t asn_OP_BIT_STRING = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
BIT_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
BIT_STRING_decode_oer,
......
......@@ -45,6 +45,7 @@ xer_type_encoder_f BIT_STRING_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define BIT_STRING_decode_jer OCTET_STRING_decode_jer_binary
jer_type_encoder_f BIT_STRING_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -47,9 +47,11 @@ asn_TYPE_operation_t asn_OP_BMPString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
BMPString_decode_jer, /* Convert to UTF-8 */
BMPString_encode_jer, /* Convert to UTF-8 */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -42,6 +42,7 @@ xer_type_encoder_f BMPString_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f BMPString_decode_jer;
jer_type_encoder_f BMPString_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -7,6 +7,71 @@
#include <BMPString.h>
#include <UTF8String.h>
asn_dec_rval_t
BMPString_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) {
asn_dec_rval_t rc;
rc = OCTET_STRING_decode_jer_utf8(opt_codec_ctx, td, sptr, opt_mname,
buf_ptr, size);
if(rc.code == RC_OK) {
/*
* Now we have a whole string in UTF-8 format.
* Convert it into UCS-2.
*/
uint32_t *wcs;
size_t wcs_len;
UTF8String_t *st;
assert(*sptr);
st = (UTF8String_t *)*sptr;
assert(st->buf);
wcs_len = UTF8String_to_wcs(st, 0, 0);
wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
rc.code = RC_FAIL;
rc.consumed = 0;
return rc;
} else {
wcs[wcs_len] = 0; /* nul-terminate */
}
if(1) {
/* Swap byte order and trim encoding to 2 bytes */
uint32_t *wc = wcs;
uint32_t *wc_end = wcs + wcs_len;
uint16_t *dstwc = (uint16_t *)wcs;
for(; wc < wc_end; wc++, dstwc++) {
uint32_t wch = *wc;
if(wch > 0xffff) {
FREEMEM(wcs);
rc.code = RC_FAIL;
rc.consumed = 0;
return rc;
}
*((uint8_t *)dstwc + 0) = wch >> 8;
*((uint8_t *)dstwc + 1) = wch;
}
dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
if(!dstwc) {
FREEMEM(wcs);
rc.code = RC_FAIL;
rc.consumed = 0;
return rc;
} else {
dstwc[wcs_len] = 0; /* nul-terminate */
wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
}
}
FREEMEM(st->buf);
st->buf = (uint8_t *)wcs;
st->size = 2 * wcs_len;
}
return rc;
}
asn_enc_rval_t
BMPString_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
......
......@@ -34,9 +34,11 @@ asn_TYPE_operation_t asn_OP_BOOLEAN = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
BOOLEAN_decode_jer,
BOOLEAN_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
BOOLEAN_decode_oer,
......
......@@ -42,6 +42,7 @@ xer_type_encoder_f BOOLEAN_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f BOOLEAN_decode_jer;
jer_type_encoder_f BOOLEAN_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -8,6 +8,39 @@
#include <BOOLEAN.h>
#include <errno.h>
/*
* Decode the chunk of JSON text encoding INTEGER.
*/
static enum jer_pbd_rval
BOOLEAN__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
const char *p = (const char *)chunk_buf;
(void)td;
if(p[0] == 't' /* 'true' */) {
*st = 1;
return JPBD_BODY_CONSUMED;
} else if (p[0] == 'f' /* 'false' */) {
*st = 0;
return JPBD_BODY_CONSUMED;
} else {
return JPBD_BROKEN_ENCODING;
}
}
asn_dec_rval_t
BOOLEAN_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) {
return jer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
BOOLEAN__jer_body_decode);
}
asn_enc_rval_t
BOOLEAN_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum jer_encoder_flags_e flags,
......
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_ENUMERATED = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
INTEGER_decode_jer,
INTEGER_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
ENUMERATED_decode_oer,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_ENUMERATED;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define ENUMERATED_decode_jer INTEGER_decode_jer
#define ENUMERATED_encode_jer INTEGER_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_GeneralString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_GeneralString;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define GeneralString_decode_jer OCTET_STRING_decode_jer_hex
#define GeneralString_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -197,9 +197,11 @@ asn_TYPE_operation_t asn_OP_GeneralizedTime = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
GeneralizedTime_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ xer_type_encoder_f GeneralizedTime_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define GeneralizedTime_decode_jer OCTET_STRING_decode_jer_utf8
jer_type_encoder_f GeneralizedTime_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -35,6 +35,7 @@ asn_TYPE_operation_t asn_OP_GraphicString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer, /* Can't expect it to be ASCII/UTF8 */
#else
0,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_GraphicString;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define GraphicString_decode_jer OCTET_STRING_decode_jer
#define GraphicString_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -42,9 +42,11 @@ asn_TYPE_operation_t asn_OP_IA5String = {
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -40,6 +40,7 @@ asn_constr_check_f IA5String_constraint;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define IA5String_decode_jer OCTET_STRING_decode_jer_utf8
#define IA5String_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -37,9 +37,11 @@ asn_TYPE_operation_t asn_OP_INTEGER = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
INTEGER_decode_jer,
INTEGER_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
INTEGER_decode_oer, /* OER decoder */
......
......@@ -61,6 +61,7 @@ xer_type_encoder_f INTEGER_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f INTEGER_decode_jer;
jer_type_encoder_f INTEGER_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
This diff is collapsed.
......@@ -42,9 +42,11 @@ asn_TYPE_operation_t asn_OP_ISO646String = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -38,6 +38,7 @@ extern asn_TYPE_operation_t asn_OP_ISO646String;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define ISO646String_decode_jer OCTET_STRING_decode_jer_utf8
#define ISO646String_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -102,8 +102,10 @@ libasn1cskeletons_la_SOURCES = \
uper_support.c uper_support.h \
xer_decoder.c xer_decoder.h \
xer_encoder.c xer_encoder.h \
jer_decoder.c jer_decoder.h \
jer_encoder.c jer_encoder.h \
xer_support.c xer_support.h \
jer_support.c jer_support.h \
ANY_aper.c \
ANY_ber.c \
ANY_uper.c \
......@@ -181,6 +183,7 @@ libasn1cskeletons_la_SOURCES = \
OPEN_TYPE_ber.c \
OPEN_TYPE_uper.c \
OPEN_TYPE_xer.c \
OPEN_TYPE_jer.c \
REAL_aper.c \
REAL_oer.c \
REAL_print.c \
......@@ -203,6 +206,7 @@ libasn1cskeletons_la_SOURCES = \
UniversalString_jer.c \
asn_codecs_prim_ber.c \
asn_codecs_prim_xer.c \
asn_codecs_prim_jer.c \
constr_CHOICE_aper.c \
constr_CHOICE_ber.c \
constr_CHOICE_print.c \
......
......@@ -34,9 +34,11 @@ asn_TYPE_operation_t asn_OP_NULL = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
NULL_decode_jer,
NULL_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NULL_decode_oer,
......
......@@ -41,6 +41,7 @@ xer_type_encoder_f NULL_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f NULL_decode_jer;
jer_type_encoder_f NULL_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -24,3 +24,29 @@ NULL_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
er.encoded = 0;
ASN__ENCODED_OK(er);
}
static enum jer_pbd_rval
NULL__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
(void)td;
(void)sptr;
(void)chunk_buf; /* Going to be empty according to the rules below. */
/*
* There must be no content in self-terminating <NULL/> tag.
*/
if(chunk_size)
return JPBD_BROKEN_ENCODING;
else
return JPBD_BODY_CONSUMED;
}
asn_dec_rval_t
NULL_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) {
return jer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(NULL_t), opt_mname, buf_ptr, size,
NULL__jer_body_decode);
}
......@@ -41,9 +41,11 @@ asn_TYPE_operation_t asn_OP_NativeEnumerated = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
NativeInteger_decode_jer,
NativeEnumerated_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NativeEnumerated_decode_oer,
......
......@@ -42,6 +42,7 @@ xer_type_encoder_f NativeEnumerated_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define NativeEnumerated_decode_jer NativeInteger_decode_jer
jer_type_encoder_f NativeEnumerated_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -42,9 +42,11 @@ asn_TYPE_operation_t asn_OP_NativeInteger = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
NativeInteger_decode_jer,
NativeInteger_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NativeInteger_decode_oer, /* OER decoder */
......
......@@ -43,6 +43,7 @@ xer_type_encoder_f NativeInteger_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f NativeInteger_decode_jer;
jer_type_encoder_f NativeInteger_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -6,6 +6,51 @@
#include <asn_internal.h>
#include <NativeInteger.h>
/*
* Decode the chunk of JSON 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,
......
......@@ -61,9 +61,11 @@ asn_TYPE_operation_t asn_OP_NativeReal = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
NativeReal_decode_jer,
NativeReal_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NativeReal_decode_oer,
......
......@@ -51,6 +51,7 @@ xer_type_encoder_f NativeReal_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f NativeReal_decode_jer;
jer_type_encoder_f NativeReal_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -7,6 +7,33 @@
#include <NativeReal.h>
#include <REAL.h>
/*
* Decode the chunk of JSON text encoding REAL.
*/
asn_dec_rval_t
NativeReal_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) {
asn_dec_rval_t rval;
REAL_t st = { 0, 0 };
REAL_t *stp = &st;
rval = REAL_decode_jer(opt_codec_ctx, td, (void **)&stp, opt_mname,
buf_ptr, size);
if(rval.code == RC_OK) {
double d;
if(asn_REAL2double(&st, &d) || NativeReal__set(td, sptr, d) < 0) {
rval.code = RC_FAIL;
rval.consumed = 0;
}
} else {
/* Convert all errors into RC_FAIL */
rval.consumed = 0;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &st);
return rval;
}
asn_enc_rval_t
NativeReal_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum jer_encoder_flags_e flags,
......
......@@ -62,9 +62,11 @@ asn_TYPE_operation_t asn_OP_NumericString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ asn_constr_check_f NumericString_constraint;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define NumericString_decode_jer OCTET_STRING_decode_jer_utf8
#define NumericString_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -39,9 +39,11 @@ asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OBJECT_IDENTIFIER_decode_jer,
OBJECT_IDENTIFIER_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OBJECT_IDENTIFIER_decode_oer,
......
......@@ -46,6 +46,7 @@ xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f OBJECT_IDENTIFIER_decode_jer;
jer_type_encoder_f OBJECT_IDENTIFIER_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -6,6 +6,58 @@
#include <asn_internal.h>
#include <OBJECT_IDENTIFIER.h>
static enum jer_pbd_rval
OBJECT_IDENTIFIER__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;
const char *chunk_end = (const char *)chunk_buf + chunk_size;
const char *endptr;
asn_oid_arc_t s_arcs[10];
asn_oid_arc_t *arcs = s_arcs;
ssize_t num_arcs;
ssize_t ret;
(void)td;
num_arcs = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
if(num_arcs < 0) {
/* Expecting more than zero arcs */
return JPBD_BROKEN_ENCODING;
} else if(num_arcs == 0) {
return JPBD_NOT_BODY_IGNORE;
}
(void)chunk_end;
assert(endptr == chunk_end);
if((size_t)num_arcs > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(asn_oid_arc_t));
if(!arcs) return JPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
arcs, num_arcs, &endptr);
if(ret != num_arcs)
return JPBD_SYSTEM_FAILURE; /* assert?.. */
}
/*
* Convert arcs into BER representation.
*/
ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, num_arcs);
if(arcs != s_arcs) FREEMEM(arcs);
return ret ? JPBD_SYSTEM_FAILURE : JPBD_BODY_CONSUMED;
}
asn_dec_rval_t
OBJECT_IDENTIFIER_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) {
return jer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname,
buf_ptr, size, OBJECT_IDENTIFIER__jer_body_decode);
}
asn_enc_rval_t
OBJECT_IDENTIFIER_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
......
......@@ -41,9 +41,11 @@ asn_TYPE_operation_t asn_OP_OCTET_STRING = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -46,6 +46,8 @@ xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f OCTET_STRING_decode_jer_hex; /* Hexadecimal */
jer_type_decoder_f OCTET_STRING_decode_jer_utf8; /* ASCII/UTF-8 */
jer_type_encoder_f OCTET_STRING_encode_jer;
jer_type_encoder_f OCTET_STRING_encode_jer_utf8;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
This diff is collapsed.
......@@ -29,9 +29,11 @@ asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OPEN_TYPE_decode_jer,
OPEN_TYPE_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OPEN_TYPE_decode_oer,
......
......@@ -59,6 +59,13 @@ asn_dec_rval_t OPEN_TYPE_xer_get(
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_jer_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
const void *ptr, size_t size);
#define OPEN_TYPE_decode_jer NULL
#define OPEN_TYPE_encode_jer CHOICE_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
/*
* 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 <OPEN_TYPE.h>
#include <constr_CHOICE.h>
asn_dec_rval_t
OPEN_TYPE_jer_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
size_t consumed_myself = 0;
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
int jer_context = 0;
ssize_t ch_size;
pjer_chunk_type_e ch_type;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
assert(elm->flags == ATF_OPEN_TYPE);
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
!= 0) {
ASN__DECODE_FAILED;
}
}
/*
* Confirm wrapper.
*/
for(;;) {
ch_size = jer_next_token(&jer_context, ptr, size, &ch_type);
if(ch_size < 0) {
ASN__DECODE_FAILED;
} else {
switch(ch_type) {
case PJER_WMORE:
ASN__DECODE_STARVED;
case PJER_TEXT:
ADVANCE(ch_size);
continue;
default:
break;
}
break;
}
}
/*
* Wrapper value confirmed.
*/
switch(jer_check_sym(ptr, ch_size, elm->name)) {
case JCK_KEY:
ADVANCE(ch_size);
break;
case JCK_BROKEN:
default:
ASN__DECODE_FAILED;
}
/* Skip colon */
ch_size = jer_next_token(&jer_context, ptr, size, &ch_type);
if(ch_size < 0 || ch_type != PJER_DLM) {
ASN__DECODE_FAILED;
} else {
ADVANCE(ch_size);
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
rv = selected.type_descriptor->op->jer_decoder(
opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
ADVANCE(rv.consumed);
rv.consumed = 0;
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
break;
} else {
rv.code = RC_FAIL;
}
/* Fall through */
case RC_FAIL:
/* Point to a best position where failure occurred */
rv.consumed = consumed_myself;
/* Fall through */
case RC_WMORE:
/* Wrt. rv.consumed==0:
* In case a genuine RC_WMORE, the whole Open Type decoding
* will have to be restarted.
*/
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
return rv;
}
/*
* Finalize wrapper.
*/
for(;;) {
ch_size = jer_next_token(&jer_context, ptr, size, &ch_type);
if(ch_size < 0) {
ASN__DECODE_FAILED;
} else {
switch(ch_type) {
case PJER_WMORE:
ASN__DECODE_STARVED;
case PJER_TEXT:
ADVANCE(ch_size);
continue;
default:
break;
}
break;
}
}
/*
* Wrapper value confirmed.
*/
switch(jer_check_sym(ptr, ch_size, NULL)) {
case JCK_KEY:
case JCK_OEND:
ADVANCE(ch_size);
break;
case JCK_BROKEN:
default:
ASN__DECODE_FAILED;
}
rv.consumed += consumed_myself;
return rv;
}
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_ObjectDescriptor = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
......
......@@ -35,6 +35,7 @@ extern asn_TYPE_operation_t asn_OP_ObjectDescriptor;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define ObjectDescriptor_decode_jer OCTET_STRING_decode_jer_utf8
#define ObjectDescriptor_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -72,9 +72,11 @@ asn_TYPE_operation_t asn_OP_PrintableString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ asn_constr_check_f PrintableString_constraint;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define PrintableString_decode_jer OCTET_STRING_decode_jer_utf8
#define PrintableString_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -77,8 +77,10 @@ asn_TYPE_operation_t asn_OP_REAL = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
REAL_decode_jer,
REAL_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
......
......@@ -68,6 +68,7 @@ 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) */
......
......@@ -24,3 +24,81 @@ REAL_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
ASN__ENCODED_OK(er);
}
/*
* Decode the chunk of XML text encoding REAL.
*/
static enum jer_pbd_rval
REAL__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
REAL_t *st = (REAL_t *)sptr;
double value;
const char *jerdata = (const char *)chunk_buf;
char *endptr = 0;
char *b;
(void)td;
if(!chunk_size) return JPBD_BROKEN_ENCODING;
/*
* Decode an XMLSpecialRealValue: <MINUS-INFINITY>, etc.
*/
if(jerdata[0] == 0x3c /* '<' */) {
size_t i;
for(i = 0; i < sizeof(specialRealValue) / sizeof(specialRealValue[0]); i++) {
struct specialRealValue_s *srv = &specialRealValue[i];
double dv;
if(srv->length != chunk_size
|| memcmp(srv->string, chunk_buf, chunk_size))
continue;
/*
* It could've been done using
* (double)srv->dv / real_zero,
* but it summons fp exception on some platforms.
*/
switch(srv->dv) {
case -1: dv = - INFINITY; break;
case 0: dv = NAN; break;
case 1: dv = INFINITY; break;
default: return JPBD_SYSTEM_FAILURE;
}
if(asn_double2REAL(st, dv))
return JPBD_SYSTEM_FAILURE;
return JPBD_BODY_CONSUMED;
}
ASN_DEBUG("Unknown XMLSpecialRealValue");
return JPBD_BROKEN_ENCODING;
}
/*
* Copy chunk into the nul-terminated string, and run strtod.
*/
b = (char *)MALLOC(chunk_size + 1);
if(!b) return JPBD_SYSTEM_FAILURE;
memcpy(b, chunk_buf, chunk_size);
b[chunk_size] = 0; /* nul-terminate */
value = strtod(b, &endptr);
FREEMEM(b);
if(endptr == b) return JPBD_BROKEN_ENCODING;
if(asn_double2REAL(st, value))
return JPBD_SYSTEM_FAILURE;
return JPBD_BODY_CONSUMED;
}
asn_dec_rval_t
REAL_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) {
return jer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(REAL_t), opt_mname,
buf_ptr, size, REAL__jer_body_decode);
}
......@@ -37,9 +37,11 @@ asn_TYPE_operation_t asn_OP_RELATIVE_OID = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
RELATIVE_OID_decode_jer,
RELATIVE_OID_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
RELATIVE_OID_decode_oer,
......
......@@ -42,6 +42,7 @@ xer_type_encoder_f RELATIVE_OID_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f RELATIVE_OID_decode_jer;
jer_type_encoder_f RELATIVE_OID_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -6,6 +6,59 @@
#include <asn_internal.h>
#include <RELATIVE-OID.h>
static enum jer_pbd_rval
RELATIVE_OID__jer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
const char *chunk_end = (const char *)chunk_buf + chunk_size;
const char *endptr;
asn_oid_arc_t s_arcs[6];
asn_oid_arc_t *arcs = s_arcs;
ssize_t num_arcs;
int ret;
(void)td;
num_arcs = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
if(num_arcs < 0) {
/* Expecting at least one arc arcs */
return JPBD_BROKEN_ENCODING;
} else if(num_arcs == 0) {
return JPBD_NOT_BODY_IGNORE;
}
assert(endptr == chunk_end);
if((size_t)num_arcs > sizeof(s_arcs) / sizeof(s_arcs[0])) {
arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(arcs[0]));
if(!arcs) return JPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
arcs, num_arcs, &endptr);
if(ret != num_arcs) {
return JPBD_SYSTEM_FAILURE; /* assert?.. */
}
}
/*
* Convert arcs into BER representation.
*/
ret = RELATIVE_OID_set_arcs(st, arcs, num_arcs);
if(arcs != s_arcs) FREEMEM(arcs);
return ret ? JPBD_SYSTEM_FAILURE : JPBD_BODY_CONSUMED;
}
asn_dec_rval_t
RELATIVE_OID_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) {
return jer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(RELATIVE_OID_t), opt_mname,
buf_ptr, size, RELATIVE_OID__jer_body_decode);
}
asn_enc_rval_t
RELATIVE_OID_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum jer_encoder_flags_e flags,
......
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_T61String = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_T61String;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define T61String_decode_jer OCTET_STRING_decode_jer_hex
#define T61String_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_TeletexString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_TeletexString;
#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) */
......
......@@ -53,9 +53,11 @@ asn_TYPE_operation_t asn_OP_UTCTime = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
UTCTime_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ xer_type_encoder_f UTCTime_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define UTCTime_decode_jer OCTET_STRING_decode_jer_utf8
jer_type_encoder_f UTCTime_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -36,9 +36,11 @@ asn_TYPE_operation_t asn_OP_UTF8String = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ asn_constr_check_f UTF8String_constraint;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define UTF8String_decode_jer OCTET_STRING_decode_jer_utf8
#define UTF8String_encode_jer OCTET_STRING_encode_jer_utf8
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -47,9 +47,11 @@ asn_TYPE_operation_t asn_OP_UniversalString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
UniversalString_decode_jer, /* Convert from UTF-8 */
UniversalString_encode_jer, /* Convert into UTF-8 */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -38,6 +38,7 @@ 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) */
......
......@@ -7,6 +7,64 @@
#include <UniversalString.h>
#include <UTF8String.h>
asn_dec_rval_t
UniversalString_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) {
asn_dec_rval_t rc;
rc = OCTET_STRING_decode_jer_utf8(opt_codec_ctx, td, sptr, opt_mname,
buf_ptr, size);
if(rc.code == RC_OK) {
/*
* Now we have a whole string in UTF-8 format.
* Convert it into UCS-4.
*/
uint32_t *wcs;
size_t wcs_len;
UTF8String_t *st;
#ifndef WORDS_BIGENDIAN
int little_endian = 1;
#endif
assert(*sptr);
st = (UTF8String_t *)*sptr;
assert(st->buf);
wcs_len = UTF8String_to_wcs(st, 0, 0);
wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
rc.code = RC_FAIL;
rc.consumed = 0;
return rc;
} else {
wcs[wcs_len] = 0; /* nul-terminate */
}
#ifndef WORDS_BIGENDIAN
if(*(char *)&little_endian) {
/* Swap byte order in encoding */
uint32_t *wc = wcs;
uint32_t *wc_end = wcs + wcs_len;
for(; wc < wc_end; wc++) {
/* *wc = htonl(*wc); */
uint32_t wch = *wc;
*((uint8_t *)wc + 0) = wch >> 24;
*((uint8_t *)wc + 1) = wch >> 16;
*((uint8_t *)wc + 2) = wch >> 8;
*((uint8_t *)wc + 3) = wch;
}
}
#endif /* WORDS_BIGENDIAN */
FREEMEM(st->buf);
st->buf = (uint8_t *)wcs;
st->size = 4 * wcs_len;
}
return rc;
}
asn_enc_rval_t
UniversalString_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum jer_encoder_flags_e flags,
......
......@@ -35,9 +35,11 @@ asn_TYPE_operation_t asn_OP_VideotexString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_hex,
OCTET_STRING_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ extern asn_TYPE_operation_t asn_OP_VideotexString;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define VideotexString_decode_jer OCTET_STRING_decode_jer_hex
#define VideotexString_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -42,9 +42,11 @@ asn_TYPE_operation_t asn_OP_VisibleString = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
OCTET_STRING_decode_jer_utf8,
OCTET_STRING_encode_jer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
......
......@@ -37,6 +37,7 @@ asn_constr_check_f VisibleString_constraint;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define VisibleString_decode_jer OCTET_STRING_decode_jer_hex
#define VisibleString_encode_jer OCTET_STRING_encode_jer
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -533,6 +533,14 @@ asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
errno = ENOENT;
ASN__DECODE_FAILED;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
case ATS_JER:
#if !defined(ASN_DISABLE_JER_SUPPORT)
return jer_decode(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT;
ASN__DECODE_FAILED;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
}
}
......@@ -49,6 +49,32 @@ asn_dec_rval_t xer_decode_primitive(
xer_primitive_body_decoder_f *prim_body_decoder);
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
/*
* A callback specification for the jer_decode_primitive() function below.
*/
enum jer_pbd_rval {
JPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */
JPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */
JPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */
JPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */
JPBD_BODY_CONSUMED /* Body is recognized and consumed */
};
typedef enum jer_pbd_rval(jer_primitive_body_decoder_f)(
const asn_TYPE_descriptor_t *td, void *struct_ptr, const void *chunk_buf,
size_t chunk_size);
/*
* Specific function to decode simple primitive types.
* Also see jer_decode_general() in jer_decoder.h
*/
asn_dec_rval_t jer_decode_primitive(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
size_t struct_size, const char *opt_mname, const void *buf_ptr, size_t size,
jer_primitive_body_decoder_f *prim_body_decoder);
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#ifdef __cplusplus
}
#endif
......
/*
* 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 <asn_codecs_prim.h>
/*
* Local internal type passed around as an argument.
*/
struct jdp_arg_s {
const asn_TYPE_descriptor_t *type_descriptor;
void *struct_key;
jer_primitive_body_decoder_f *prim_body_decoder;
int decoded_something;
int want_more;
};
/*
* Since some kinds of primitive values can be encoded using value-specific
* tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
* be supplied with such tags to parse them as needed.
*/
static int
jer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
struct jdp_arg_s *arg = (struct jdp_arg_s *)key;
enum jer_pbd_rval bret;
/*
* The chunk_buf is guaranteed to start at '<'.
*/
assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
/*
* Decoding was performed once already. Prohibit doing it again.
*/
if(arg->decoded_something)
return -1;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf,
chunk_size);
switch(bret) {
case JPBD_SYSTEM_FAILURE:
case JPBD_DECODER_LIMIT:
case JPBD_BROKEN_ENCODING:
break;
case JPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case JPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return 0;
}
return -1;
}
static ssize_t
jer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
struct jdp_arg_s *arg = (struct jdp_arg_s *)key;
enum jer_pbd_rval bret;
size_t lead_wsp_size;
if(arg->decoded_something) {
if(jer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
/*
* Example:
* "<INTEGER>123<!--/--> </INTEGER>"
* ^- chunk_buf position.
*/
return chunk_size;
}
/*
* Decoding was done once already. Prohibit doing it again.
*/
return -1;
}
if(!have_more) {
/*
* If we've received something like "1", we can't really
* tell whether it is really `1` or `123`, until we know
* that there is no more data coming.
* The have_more argument will be set to 1 once something
* like this is available to the caller of this callback:
* "1<tag_start..."
*/
arg->want_more = 1;
return -1;
}
lead_wsp_size = jer_whitespace_span(chunk_buf, chunk_size);
chunk_buf = (chunk_buf == NULL)? NULL : ((const char *)chunk_buf + lead_wsp_size);
chunk_size -= lead_wsp_size;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf,
chunk_size);
switch(bret) {
case JPBD_SYSTEM_FAILURE:
case JPBD_DECODER_LIMIT:
case JPBD_BROKEN_ENCODING:
break;
case JPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case JPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return lead_wsp_size + chunk_size;
}
return -1;
}
asn_dec_rval_t
jer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
size_t struct_size, const char *opt_mname,
const void *buf_ptr, size_t size,
jer_primitive_body_decoder_f *prim_body_decoder) {
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
asn_struct_ctx_t s_ctx;
struct jdp_arg_s s_arg;
asn_dec_rval_t rc;
/*
* Create the structure if does not exist.
*/
if(!*sptr) {
*sptr = CALLOC(1, struct_size);
if(!*sptr) ASN__DECODE_FAILED;
}
memset(&s_ctx, 0, sizeof(s_ctx));
s_arg.type_descriptor = td;
s_arg.struct_key = *sptr;
s_arg.prim_body_decoder = prim_body_decoder;
s_arg.decoded_something = 0;
s_arg.want_more = 0;
rc = jer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
xml_tag, buf_ptr, size,
jer_decode__unexpected_tag,
jer_decode__primitive_body);
switch(rc.code) {
case RC_OK:
if(!s_arg.decoded_something) {
char ch;
ASN_DEBUG("Primitive body is not recognized, "
"supplying empty one");
/*
* Decoding opportunity has come and gone.
* Where's the result?
* Try to feed with empty body, see if it eats it.
*/
if(prim_body_decoder(s_arg.type_descriptor,
s_arg.struct_key, &ch, 0)
!= JPBD_BODY_CONSUMED) {
/*
* This decoder does not like empty stuff.
*/
ASN__DECODE_FAILED;
}
}
break;
case RC_WMORE:
/*
* Redo the whole thing later.
* We don't have a context to save intermediate parsing state.
*/
rc.consumed = 0;
break;
case RC_FAIL:
rc.consumed = 0;
if(s_arg.want_more)
rc.code = RC_WMORE;
else
ASN__DECODE_FAILED;
break;
}
return rc;
}
......@@ -28,9 +28,11 @@ asn_TYPE_operation_t asn_OP_CHOICE = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
CHOICE_decode_jer,
CHOICE_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
CHOICE_decode_oer,
......
......@@ -60,6 +60,7 @@ xer_type_encoder_f CHOICE_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f CHOICE_decode_jer;
jer_type_encoder_f CHOICE_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -26,6 +26,282 @@
consumed_myself += num; \
} while(0)
#undef JER_SAVE_STATE
#define JER_SAVE_STATE \
do { \
buf_ptr0 = buf_ptr; \
size0 = size; \
consumed_myself0 = consumed_myself; \
context0 = ctx->context; \
} while(0)
#undef JER_RESTORE_STATE
#define JER_RESTORE_STATE \
do { \
buf_ptr = buf_ptr0; \
size = size0; \
consumed_myself = consumed_myself0; \
ctx->context = context0; \
} while(0)
/*
* Decode the JER (JSON) data.
*/
asn_dec_rval_t
CHOICE_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **struct_ptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
const char *json_key = opt_mname ? opt_mname : td->xml_tag;
/*
* Parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval; /* Return value of a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
size_t edx; /* Element index */
int skip_outer = 0; /* Skip outer layer */
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
if(ctx->phase == 0 && !*json_key) {
/* Skip the outer key checking phase */
ctx->phase = 1;
skip_outer = 1;
}
const void* buf_ptr0 = buf_ptr;
size_t size0 = size;
ssize_t consumed_myself0 = consumed_myself; /* Consumed bytes from ptr */
int context0 = ctx->context;
/*
* Phases of JER/JSON processing:
* Phase 0: Check that the opening key matches our expectations.
* Phase 1: Processing body and reacting on closing key.
* Phase 2: Processing inner type.
* Phase 3: Only waiting for closing key.
* Phase 4: Skipping unknown extensions.
* Phase 5: PHASED OUT
*/
for(edx = ctx->step; ctx->phase <= 4;) {
pjer_chunk_type_e ch_type; /* JER chunk type */
ssize_t ch_size; /* Chunk size */
jer_check_sym_e scv; /* Tag check value */
asn_TYPE_member_t *elm;
/*
* Go inside the member.
*/
if(ctx->phase == 2) {
asn_dec_rval_t tmprval;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
unsigned old_present;
elm = &td->elements[edx];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st
+ elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Start/Continue decoding the inner member */
tmprval = elm->type->op->jer_decoder(opt_codec_ctx,
elm->type, memb_ptr2,
elm->name,
buf_ptr, size);
JER_ADVANCE(tmprval.consumed);
ASN_DEBUG("JER/CHOICE: itdf: [%s] code=%d",
elm->type->name, tmprval.code);
old_present = _fetch_present_idx(st,
specs->pres_offset,
specs->pres_size);
assert(old_present == 0 || old_present == edx + 1);
/* Record what we've got */
_set_present_idx(st,
specs->pres_offset,
specs->pres_size, edx + 1);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
ctx->phase = 3;
/* Fall through */
}
/* No need to wait for closing key; special mode. */
if(ctx->phase == 3 && !*json_key) {
ctx->phase = 5; /* Phase out */
RETURN(RC_OK);
}
/*
* Get the next part of the XML stream.
*/
ch_size = jer_next_token(&ctx->context, buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PJER_WMORE:
RETURN(RC_WMORE);
case PJER_TEXT: /* Ignore free-standing text */
JER_ADVANCE(ch_size); /* Skip silently */
continue;
case PJER_DLM:
case PJER_VALUE:
case PJER_KEY:
break; /* Check the rest down there */
}
}
scv = jer_check_sym(buf_ptr, ch_size, ctx->phase == 0 ? json_key : NULL);
ASN_DEBUG("JER/CHOICE checked [%c%c%c%c] vs [%s], scv=%d",
ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
json_key, scv);
/* Skip the extensions section */
if(ctx->phase == 4) {
ASN_DEBUG("skip_unknown(%d, %ld)",
scv, (long)ctx->left);
switch(jer_skip_unknown(scv, &ctx->left)) {
case -1:
ctx->phase = 5;
RETURN(RC_FAIL);
case 1:
ctx->phase = 3;
/* Fall through */
case 0:
JER_ADVANCE(ch_size);
continue;
case 2:
ctx->phase = 3;
break;
}
}
switch(scv) {
case JCK_OEND:
if(ctx->phase != 3)
break;
JER_ADVANCE(ch_size);
ctx->phase = 5; /* Phase out */
RETURN(RC_OK);
case JCK_KEY:
case JCK_COMMA:
if(ctx->phase == 0) {
JER_ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case JCK_UNKNOWN:
case JCK_OSTART:
if(ctx->phase != 1)
break; /* Really unexpected */
if (!skip_outer) {
JER_ADVANCE(ch_size); /* Skip silently */
// Save state
JER_SAVE_STATE; /* We have to look inside the object to see which
* key (choice) is present */
ctx->context = 0;
ch_size = jer_next_token(&ctx->context, buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
}
if (ch_type != PJER_KEY) {
JER_ADVANCE(ch_size); /* Skip silently */
ch_size = jer_next_token(&ctx->context, buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
}
}
}
/*
* Search which inner member corresponds to this key.
*/
for(edx = 0; edx < td->elements_count; edx++) {
elm = &td->elements[edx];
scv = jer_check_sym(buf_ptr,ch_size,elm->name);
switch(scv) {
case JCK_KEY:
/*
* Process this member.
*/
ctx->step = edx;
ctx->phase = 2;
break;
case JCK_UNKNOWN:
continue;
default:
edx = td->elements_count;
break; /* Phase out */
}
break;
}
if (!skip_outer) {
JER_RESTORE_STATE;
}
if(edx != td->elements_count)
continue;
/* It is expected extension */
if(specs->ext_start != -1) {
ASN_DEBUG("Got anticipated extension");
ctx->left = 1;
ctx->phase = 4; /* Skip ...'s */
JER_ADVANCE(ch_size);
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected JSON key [%c%c%c%c] in CHOICE [%s]"
" (ph=%d, key=%s)",
ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
td->name, ctx->phase, json_key);
break;
}
ctx->phase = 5; /* Phase out, just in case */
RETURN(RC_FAIL);
}
asn_enc_rval_t
CHOICE_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,
......
......@@ -29,9 +29,11 @@ asn_TYPE_operation_t asn_OP_SEQUENCE = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
SEQUENCE_decode_jer,
SEQUENCE_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
SEQUENCE_decode_oer,
......
......@@ -65,6 +65,7 @@ xer_type_encoder_f SEQUENCE_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f SEQUENCE_decode_jer;
jer_type_encoder_f SEQUENCE_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -30,9 +30,11 @@ asn_TYPE_operation_t asn_OP_SEQUENCE_OF = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
SEQUENCE_OF_decode_jer,
SEQUENCE_OF_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
SEQUENCE_OF_decode_oer, /* Same as SET OF decoder. */
......
......@@ -37,6 +37,7 @@ xer_type_encoder_f SEQUENCE_OF_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#define SEQUENCE_OF_decode_jer SET_OF_decode_jer
jer_type_encoder_f SEQUENCE_OF_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
This diff is collapsed.
......@@ -29,8 +29,10 @@ asn_TYPE_operation_t asn_OP_SET = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
SET_decode_jer,
SET_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
......
......@@ -66,6 +66,7 @@ xer_type_encoder_f SET_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f SET_decode_jer;
jer_type_encoder_f SET_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -29,9 +29,11 @@ asn_TYPE_operation_t asn_OP_SET_OF = {
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
SET_OF_decode_jer,
SET_OF_encode_jer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
SET_OF_decode_oer,
......
......@@ -47,6 +47,7 @@ xer_type_encoder_f SET_OF_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
jer_type_decoder_f SET_OF_decode_jer;
jer_type_encoder_f SET_OF_encode_jer;
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......
......@@ -6,6 +6,192 @@
#include <asn_internal.h>
#include <constr_SET_OF.h>
/*
* Return a standardized complex structure.
*/
#undef RETURN
#define RETURN(_code) \
do { \
rval.code = _code; \
rval.consumed = consumed_myself; \
return rval; \
} while(0)
#undef JER_ADVANCE
#define JER_ADVANCE(num_bytes) \
do { \
size_t num = num_bytes; \
buf_ptr = ((const char *)buf_ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
/*
* Decode the JER (JSON) data.
*/
asn_dec_rval_t
SET_OF_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **struct_ptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
const asn_TYPE_member_t *element = td->elements;
const char *elm_tag;
const char *json_key = opt_mname ? opt_mname : td->xml_tag;
/*
* ... and parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval = {RC_OK, 0}; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/* Which tag is expected for the downstream */
if(specs->as_XMLValueList) {
elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
} else {
elm_tag = (*element->name)
? element->name : element->type->xml_tag;
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Phases of JER/JSON processing:
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
*/
for(; ctx->phase <= 2;) {
pjer_chunk_type_e ch_type; /* JER chunk type */
ssize_t ch_size; /* Chunk size */
jer_check_sym_e scv; /* Tag check value */
/*
* Go inside the inner member of a set.
*/
if(ctx->phase == 2) {
asn_dec_rval_t tmprval = {RC_OK, 0};
/* Invoke the inner type decoder, m.b. multiple times */
ASN_DEBUG("JER/SET OF element [%s]", elm_tag);
tmprval = element->type->op->jer_decoder(opt_codec_ctx,
element->type,
&ctx->ptr, elm_tag,
buf_ptr, size);
if(tmprval.code == RC_OK) {
asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
if(ASN_SET_ADD(list, ctx->ptr) != 0)
RETURN(RC_FAIL);
ctx->ptr = 0;
JER_ADVANCE(tmprval.consumed);
} else {
JER_ADVANCE(tmprval.consumed);
RETURN(tmprval.code);
}
JER_ADVANCE(jer_whitespace_span(buf_ptr, size));
if(((const char*)buf_ptr)[0] != ']') {
ch_size = jer_next_token(&ctx->context, buf_ptr, size,
&ch_type);
JER_ADVANCE(ch_size);
}
ctx->phase = 1; /* Back to body processing */
ASN_DEBUG("JER/SET OF phase => %d", ctx->phase);
/* Fall through */
}
/*
* Get the next part of the XML stream.
*/
ch_size = jer_next_token(&ctx->context,
buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PJER_WMORE:
RETURN(RC_WMORE);
case PJER_TEXT: /* Got XML comment */
JER_ADVANCE(ch_size); /* Skip silently */
continue;
case PJER_DLM:
case PJER_VALUE:
case PJER_KEY:
break; /* Check the rest down there */
}
}
scv = jer_check_sym(buf_ptr, ch_size, ctx->phase == 0 ? json_key : NULL);
ASN_DEBUG("JER/SET OF: scv = %d, ph=%d t=%s",
scv, ctx->phase, json_key);
switch(scv) {
case JCK_ASTART:
continue;
case JCK_AEND:
if(ctx->phase == 0) break;
ctx->phase = 0;
if(ctx->phase == 0) {
/* No more things to decode */
JER_ADVANCE(ch_size);
ctx->phase = 3; /* Phase out */
RETURN(RC_OK);
}
case JCK_OEND:
/* Fall through */
case JCK_KEY:
case JCK_COMMA:
if(ctx->phase == 0) {
JER_ADVANCE(ch_size);
if (scv == JCK_KEY) {
ch_size = jer_next_token(&ctx->context, buf_ptr, size,
&ch_type);
JER_ADVANCE(ch_size);
}
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case JCK_UNKNOWN:
case JCK_OSTART:
ASN_DEBUG("JER/SET OF: scv=%d, ph=%d", scv, ctx->phase);
if(ctx->phase == 1) {
/*
* Process a single possible member.
*/
ctx->phase = 2;
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected JSON key in SET OF");
break;
}
ctx->phase = 3; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
typedef struct jer_tmp_enc_s {
void *buffer;
size_t offset;
......@@ -101,11 +287,6 @@ SET_OF_encode_jer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
size_t len = strlen(name);
ASN__CALLBACK3("<", 1, name, len, "/>", 2);
}
/* if(mname) { */
/* ASN__CALLBACK3("</", 2, mname, mlen, ">", 1); */
/* } */
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
......
......@@ -6,6 +6,298 @@
#include <asn_internal.h>
#include <constr_SET.h>
/*
* Return a standardized complex structure.
*/
#undef RETURN
#define RETURN(_code) \
do { \
rval.code = _code; \
rval.consumed = consumed_myself; \
return rval; \
} while(0)
/*
* Check whether we are inside the extensions group.
*/
#define IN_EXTENSION_GROUP(specs, memb_idx) \
((specs)->first_extension >= 0 \
&& (unsigned)(specs)->first_extension <= (memb_idx))
#undef JER_ADVANCE
#define JER_ADVANCE(num_bytes) \
do { \
size_t num = (num_bytes); \
ptr = ((const char *)ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
#define JER_SAVE_STATE \
do { \
ptr0 = ptr; \
size0 = size; \
consumed_myself0 = consumed_myself; \
context0 = ctx->context;\
} while(0)
#define JER_RESTORE_STATE \
do { \
ptr = ptr0; \
size = size0; \
consumed_myself = consumed_myself0; \
ctx->context = context0; \
} while(0)
/*
* Decode the JER (JSON) data.
*/
asn_dec_rval_t
SET_decode_jer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **struct_ptr,
const char *opt_mname, const void *ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
const asn_SET_specifics_t *specs
= (const asn_SET_specifics_t *)td->specifics;
asn_TYPE_member_t *elements = td->elements;
const char *json_key = opt_mname ? opt_mname : td->xml_tag;
/*
* ... and parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
ssize_t edx = -1; /* Element index */
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
asn_dec_rval_t tmprval = {0};
/* Restore vars */
const void* ptr0 = ptr;
size_t size0 = size;
ssize_t consumed_myself0 = consumed_myself; /* Consumed bytes from ptr */
int context0 = ctx->context;
/*
* Phases of JER/JSON processing:
* Phase 0: Check that the key matches our expectations.
* Phase 1: Processing body and reacting on closing key.
* Phase 2: Processing inner type.
* Phase 3: Skipping unknown extensions.
* Phase 4: PHASED OUT
*/
for(edx = ctx->step; ctx->phase <= 3;) {
pjer_chunk_type_e ch_type; /* JER chunk type */
ssize_t ch_size; /* Chunk size */
jer_check_sym_e scv; /* Tag check value */
asn_TYPE_member_t *elm;
/*
* Go inside the inner member of a sequence.
*/
if(ctx->phase == 2) {
void *memb_ptr_dontuse; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
elm = &td->elements[edx];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr_dontuse = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr_dontuse; /* Only use of memb_ptr_dontuse */
}
if(elm->flags & ATF_OPEN_TYPE) {
//tmprval = OPEN_TYPE_xer_get(opt_codec_ctx, td, st, elm, ptr, size);
} else {
/* Invoke the inner type decoder, m.b. multiple times */
tmprval = elm->type->op->jer_decoder(opt_codec_ctx,
elm->type, memb_ptr2, elm->name,
ptr, size);
}
JER_ADVANCE(tmprval.consumed);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
ctx->phase = 1; /* Back to body processing */
ctx->step = ++edx;
ASN_DEBUG("JER/SEQUENCE phase => %d, step => %d",
ctx->phase, ctx->step);
/* Fall through */
}
/*
* Get the next part of the JSON stream.
*/
ch_size = jer_next_token(&ctx->context, ptr, size,
&ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PJER_WMORE:
RETURN(RC_WMORE);
case PJER_TEXT: /* Ignore free-standing text */
JER_ADVANCE(ch_size); /* Skip silently */
continue;
case PJER_DLM:
case PJER_VALUE: /* Ignore free-standing text */
case PJER_KEY:
break; /* Check the rest down there */
}
}
scv = jer_check_sym(ptr, ch_size, ctx->phase == 0 ? json_key : NULL);
ASN_DEBUG("JER/SEQUENCE: scv = %d, ph=%d [%s]",
scv, ctx->phase, json_key);
/* Skip the extensions section */
if(ctx->phase == 3) {
switch(jer_skip_unknown(scv, &ctx->left)) {
case -1:
ctx->phase = 4;
RETURN(RC_FAIL);
case 0:
JER_ADVANCE(ch_size);
continue;
case 1:
JER_ADVANCE(ch_size);
ctx->phase = 1;
continue;
case 2:
ctx->phase = 1;
break;
}
}
switch(scv) {
case JCK_OEND:
if(ctx->phase == 0) break;
ctx->phase = 0;
/* Fall through */
case JCK_KEY:
case JCK_COMMA:
if(ctx->phase == 0) {
JER_ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case JCK_UNKNOWN:
case JCK_OSTART:
ASN_DEBUG("JER/SEQUENCE: scv=%d, ph=%d, edx=%" ASN_PRI_SIZE "",
scv, ctx->phase, edx);
if(ctx->phase != 1) {
break; /* Really unexpected */
}
if (td->elements_count == 0) {
JER_ADVANCE(ch_size);
continue;
}
if(edx < td->elements_count) {
JER_ADVANCE(ch_size);
/*
* We have to check which member is next.
*/
JER_SAVE_STATE;
ctx->context = 0;
ch_size = jer_next_token(&ctx->context, ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
}
if(ch_type != PJER_KEY) {
JER_ADVANCE(ch_size); /* Skip silently */
ch_size = jer_next_token(&ctx->context, ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
}
}
size_t n;
size_t edx_end = edx + elements[edx].optional + 1;
if(edx_end > td->elements_count) {
edx_end = td->elements_count;
}
for(n = edx; n < edx_end; n++) {
elm = &td->elements[n];
scv = jer_check_sym(ptr, ch_size, elm->name);
switch (scv) {
case JCK_KEY:
ctx->step = edx = n;
ctx->phase = 2;
break;
case JCK_UNKNOWN:
continue;
default:
n = edx_end;
break; /* Phase out */
}
break;
}
JER_RESTORE_STATE;
if(n != edx_end)
continue;
} else {
ASN_DEBUG("Out of defined members: %" ASN_PRI_SIZE "/%u",
edx, td->elements_count);
}
/* It is expected extension */
if(specs->extensible) {
ASN_DEBUG("Got anticipated extension");
ctx->left = 1;
ctx->phase = 3; /* Skip ...'s */
JER_ADVANCE(ch_size);
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected XML key in SEQUENCE [%c%c%c%c%c%c]",
size>0?((const char *)ptr)[0]:'.',
size>1?((const char *)ptr)[1]:'.',
size>2?((const char *)ptr)[2]:'.',
size>3?((const char *)ptr)[3]:'.',
size>4?((const char *)ptr)[4]:'.',
size>5?((const char *)ptr)[5]:'.');
break;
}
ctx->phase = 4; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
asn_enc_rval_t
SET_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,
......
......@@ -51,8 +51,10 @@ typedef void (xer_type_encoder_f)(void);
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_JER_SUPPORT)
#include <jer_decoder.h> /* Decoder of JER (JSON, text) */
#include <jer_encoder.h> /* Encoder into JER (JSON, text) */
#else
typedef void (jer_type_decoder_f)(void);
typedef void (jer_type_encoder_f)(void);
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
......@@ -177,6 +179,7 @@ typedef struct asn_TYPE_operation_s {
der_type_encoder_f *der_encoder; /* Canonical DER encoder */
xer_type_decoder_f *xer_decoder; /* Generic XER decoder */
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
jer_type_decoder_f *jer_decoder; /* Generic JER encoder */
jer_type_encoder_f *jer_encoder; /* Generic JER encoder */
oer_type_decoder_f *oer_decoder; /* Generic OER decoder */
oer_type_encoder_f *oer_encoder; /* Canonical OER encoder */
......
......@@ -243,8 +243,12 @@ constr_SET_OF.h constr_SET_OF_rfill.c
constr_SET.h constr_SET_rfill.c
CODEC-JER: # THIS IS A SPECIAL SECTION
jer_support.h
jer_decoder.h
jer_encoder.h
jer_encoder.h jer_encoder.c
jer_support.h jer_support.c # JSON parsing
jer_decoder.h jer_decoder.c # JER decoding support
jer_encoder.h jer_encoder.c # JER encoding support
ANY.h ANY_jer.c
BIT_STRING.h BIT_STRING_jer.c
BMPString.h BMPString_jer.c
......@@ -257,10 +261,12 @@ NativeInteger.h NativeInteger_jer.c
NativeReal.h NativeReal_jer.c
OBJECT_IDENTIFIER.h OBJECT_IDENTIFIER_jer.c
OCTET_STRING.h OCTET_STRING_jer.c
OPEN_TYPE.h OPEN_TYPE_jer.c
REAL.h REAL_jer.c
RELATIVE-OID.h RELATIVE-OID_jer.c
UTCTime.h UTCTime_jer.c
UniversalString.h UniversalString_jer.c
asn_codecs_prim.h asn_codecs_prim_jer.c
constr_CHOICE.h constr_CHOICE_jer.c
constr_SEQUENCE_OF.h constr_SEQUENCE_OF_jer.c
constr_SEQUENCE.h constr_SEQUENCE_jer.c
......
/*
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_application.h>
#include <asn_internal.h>
#include <jer_support.h> /* JER/JSON parsing support */
/*
* Decode the jer encoding of a given type.
*/
asn_dec_rval_t
jer_decode(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **struct_ptr,
const void *buffer, size_t size) {
asn_codec_ctx_t s_codec_ctx;
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}
/*
* Invoke type-specific decoder.
*/
return td->op->jer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);
}
struct jer__cb_arg {
pjson_chunk_type_e chunk_type;
size_t chunk_size;
const void *chunk_buf;
int callback_not_invoked;
};
static int
jer__token_cb(pjson_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
struct jer__cb_arg *arg = (struct jer__cb_arg *)key;
arg->chunk_type = type;
arg->chunk_size = _chunk_size;
arg->chunk_buf = _chunk_data;
arg->callback_not_invoked = 0;
return -1; /* Terminate the JSON parsing */
}
/*
* Fetch the next token from the JER/JSON stream.
*/
ssize_t
jer_next_token(int *stateContext, const void *buffer, size_t size, pjer_chunk_type_e *ch_type) {
struct jer__cb_arg arg;
int new_stateContext = *stateContext;
ssize_t ret;
arg.callback_not_invoked = 1;
ret = pjson_parse(&new_stateContext, buffer, size, jer__token_cb, &arg);
if(ret < 0) return -1;
if(arg.callback_not_invoked) {
assert(ret == 0); /* No data was consumed */
*ch_type = PJER_WMORE;
return 0; /* Try again with more data */
} else {
assert(arg.chunk_size);
assert(arg.chunk_buf == buffer);
}
/*
* Translate the JSON chunk types into more convenient ones.
*/
switch(arg.chunk_type) {
case PJSON_TEXT:
*ch_type = PJER_TEXT;
break;
case PJSON_KEY:
*ch_type = PJER_WMORE;
break;
case PJSON_DLM:
*ch_type = PJER_DLM;
break;
case PJSON_KEY_END:
*ch_type = PJER_KEY;
break;
case PJSON_VALUE_END:
*ch_type = PJER_VALUE;
break;
default:
return 0; /* Want more */
}
*stateContext = new_stateContext;
return arg.chunk_size;
}
#define LCBRAC 0x7b /* '{' */
#define RCBRAC 0x7d /* '}' */
#define CQUOTE 0x22 /* '"' */
#define CCOMMA 0x2c /* ',' */
#define LSBRAC 0x5b /* '[' */
#define RSBRAC 0x5d /* ']' */
jer_check_sym_e
jer_check_sym(const void *buf_ptr, int size, const char *need_key) {
const char *buf = (const char *)buf_ptr;
const char *end;
if(!need_key) { /* expected data end */
switch(buf[size-1]) {
case LCBRAC:
return JCK_OSTART;
case RCBRAC:
return JCK_OEND;
case LSBRAC:
return JCK_ASTART;
case RSBRAC:
return JCK_AEND;
case CCOMMA:
return JCK_COMMA;
default:
return JCK_UNKNOWN;
}
}
if(size < 2 ||
(buf[0] != CQUOTE || buf[size-1] != CQUOTE)) {
if(size >= 2)
ASN_DEBUG("Broken JSON key: \"%c...%c\"",
buf[0], buf[size - 1]);
return JCK_BROKEN;
}
buf++; /* advance past first quote */
size -= 2; /* strip quotes */
/*
* Determine the key name.
*/
for(end = buf + size; buf < end; buf++, need_key++) {
int b = *buf, n = *need_key;
if(b != n) {
if(n == 0) {
switch(b) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
/* "abc def": accept whitespace */
return JCK_KEY;
}
}
return JCK_UNKNOWN;
}
if(b == 0)
return JCK_BROKEN; /* Embedded 0 in buf?! */
}
if(*need_key)
return JCK_UNKNOWN;
return JCK_KEY;
}
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = (num_bytes); \
buf_ptr = ((const char *)buf_ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
#undef RETURN
#define RETURN(_code) do { \
rval.code = _code; \
rval.consumed = consumed_myself; \
if(rval.code != RC_OK) \
ASN_DEBUG("Failed with %d", rval.code); \
return rval; \
} while(0)
#define JER_GOT_BODY(chunk_buf, chunk_size, size) do { \
ssize_t converted_size = body_receiver \
(struct_key, chunk_buf, chunk_size, \
(size_t)chunk_size < size); \
if(converted_size == -1) RETURN(RC_FAIL); \
if(converted_size == 0 \
&& size == (size_t)chunk_size) \
RETURN(RC_WMORE); \
chunk_size = converted_size; \
} while(0)
#define JER_GOT_EMPTY() do { \
if(body_receiver(struct_key, 0, 0, size > 0) == -1) \
RETURN(RC_FAIL); \
} while(0)
/*
* Generalized function for decoding the primitive values.
*/
asn_dec_rval_t
jer_decode_general(const asn_codec_ctx_t *opt_codec_ctx,
asn_struct_ctx_t *ctx, /* Type decoder context */
void *struct_key,
const char *json_key, /* Expected JSON key */
const void *buf_ptr, size_t size,
int (*opt_unexpected_key_decoder)
(void *struct_key, const void *chunk_buf, size_t chunk_size),
ssize_t (*body_receiver)
(void *struct_key, const void *chunk_buf, size_t chunk_size,
int have_more)
) {
asn_dec_rval_t rval;
ssize_t consumed_myself = 0;
(void)opt_codec_ctx;
/*
* Phases of jer/JSON processing:
* Phase 0: Check that the opening key matches our expectations.
* Phase 1: Processing body and reacting on closing key.
*/
if(ctx->phase > 1) RETURN(RC_FAIL);
for(;;) {
pjer_chunk_type_e ch_type; /* jer chunk type */
ssize_t ch_size; /* Chunk size */
jer_check_sym_e scv; /* Symbol check value */
/*
* Get the next part of the JSON stream.
*/
ch_size = jer_next_token(&ctx->context, buf_ptr, size,
&ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PJER_WMORE:
RETURN(RC_WMORE);
case PJER_TEXT:
ADVANCE(ch_size);
continue;
case PJER_VALUE:
JER_GOT_BODY(buf_ptr, ch_size, size);
ADVANCE(ch_size);
ADVANCE(jer_whitespace_span(buf_ptr, size)); /* skip whitespace */
ch_size = 1;
case PJER_KEY:
case PJER_DLM:
break; /* Check the rest down there */
}
}
scv = jer_check_sym(buf_ptr, ch_size, ch_type == PJER_KEY ? json_key : NULL);
/*
* Phase 0:
* Expecting the opening key
* for the type being processed.
* Phase 1:
* Waiting for the closing JSON token.
*/
switch(scv) {
case JCK_KEY:
if(ctx->phase) break;
ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
case JCK_OEND:
case JCK_AEND:
case JCK_COMMA:
ctx->phase = 2; /* Phase out */
RETURN(RC_OK);
default:
break; /* Unexpected token */
}
ASN_DEBUG("Unexpected JSON key (expected \"%s\")", json_key);
break; /* Dark and mysterious things have just happened */
}
RETURN(RC_FAIL);
}
size_t
jer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
const char *p = (const char *)chunk_buf;
const char *pend = (p == NULL)? NULL : p + chunk_size;
for(; p < pend; p++) {
switch(*p) {
/* X.693, #8.1.4
* HORISONTAL TAB (9)
* LINE FEED (10)
* CARRIAGE RETURN (13)
* SPACE (32)
*/
case 0x09: case 0x0a: case 0x0d: case 0x20:
continue;
default:
break;
}
break;
}
return (p - (const char *)chunk_buf);
}
/*
* This is a vastly simplified, non-validating JSON tree skipper. [TODO]
*/
int
jer_skip_unknown(jer_check_sym_e scv, ber_tlv_len_t *depth) {
assert(*depth > 0);
switch(scv) {
case JCK_KEY:
++(*depth);
return 0;
case JCK_COMMA:
case JCK_OEND:
case JCK_UNKNOWN:
if(--(*depth) == 0)
return (scv == JCK_OEND) ? 2 : 1;
return 0;
default:
return -1;
}
}
/*-
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _JER_DECODER_H_
#define _JER_DECODER_H_
#include <asn_application.h>
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* The JER decoder of any ASN.1 type. May be invoked by the application.
* Decodes CANONICAL-JER and BASIC-JER.
*/
asn_dec_rval_t jer_decode(
const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *type_descriptor,
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
/*
* Type of the type-specific JER decoder function.
*/
typedef asn_dec_rval_t(jer_type_decoder_f)(
const asn_codec_ctx_t *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *type_descriptor, void **struct_ptr,
const char *opt_mname, /* Member name */
const void *buf_ptr, size_t size);
/*******************************
* INTERNALLY USEFUL FUNCTIONS *
*******************************/
/*
* Generalized function for decoding the primitive values.
* Used by more specialized functions, such as OCTET_STRING_decode_jer_utf8
* and others. This function should not be used by applications, as its API
* is subject to changes.
*/
asn_dec_rval_t jer_decode_general(
const asn_codec_ctx_t *opt_codec_ctx,
asn_struct_ctx_t *ctx, /* Type decoder context */
void *struct_key, /* Treated as opaque pointer */
const char *json_key, /* Expected XML tag name */
const void *buf_ptr, size_t size,
int (*opt_unexpected_tag_decoder)(void *struct_key, const void *chunk_buf,
size_t chunk_size),
ssize_t (*body_receiver)(void *struct_key, const void *chunk_buf,
size_t chunk_size, int have_more));
/*
* Fetch the next JER (JSON) token from the stream.
* The function returns the number of bytes occupied by the chunk type,
* returned in the _ch_type. The _ch_type is only set (and valid) when
* the return value is >= 0.
*/
typedef enum pjer_chunk_type {
PJER_WMORE, /* Chunk type is not clear, more data expected. */
PJER_TEXT, /* General data */
PJER_KEY, /* Complete JSON key */
PJER_VALUE, /* Complete JSON value */
PJER_DLM /* JSON delimiter */
} pjer_chunk_type_e;
ssize_t jer_next_token(int *stateContext,
const void *buffer, size_t size, pjer_chunk_type_e *_ch_type);
/*
* This function checks the buffer for the current token or
* against the key name expected to occur.
*/
typedef enum jer_check_sym {
JCK_BROKEN, /* Something is broken */
JCK_UNKNOWN, /* Key or delimiter is unknown */
JCK_KEY, /* Key is OK */
JCK_COMMA, /* Delimiter is ',' */
JCK_OSTART, /* Delimiter is '{' */
JCK_OEND, /* Delimiter is '}' */
JCK_ASTART, /* Delimiter is '[' */
JCK_AEND /* Delimiter is ']' */
} jer_check_sym_e;
jer_check_sym_e jer_check_sym(const void *buf_ptr, int size,
const char *need_key);
/*
* Get the number of bytes consisting entirely of JER whitespace characters.
* RETURN VALUES:
* >=0: Number of whitespace characters in the string.
*/
size_t jer_whitespace_span(const void *chunk_buf, size_t chunk_size);
/*
* Skip the series of anticipated extensions.
*/
int jer_skip_unknown(jer_check_sym_e scv, ber_tlv_len_t *depth);
#ifdef __cplusplus
}
#endif
#endif /* _JER_DECODER_H_ */
/*
* Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
* Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_system.h>
#include <jer_support.h>
/* Parser states */
typedef enum {
ST_TEXT,
ST_KEY,
ST_KEY_BODY,
ST_COLON,
ST_VALUE,
ST_VALUE_BODY,
ST_ARRAY_VALUE,
ST_ARRAY_VALUE_BODY,
ST_END
} pstate_e;
static const int _charclass[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, /* 01234567 89
*/
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* ABCDEFG HIJKLMNO */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, /* PQRSTUVW XYZ */
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* abcdefg hijklmno */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0 /* pqrstuvw xyz */
};
#define WHITESPACE(c) (_charclass[(unsigned char)(c)] == 1)
#define ALNUM(c) (_charclass[(unsigned char)(c)] >= 2)
#define ALPHA(c) (_charclass[(unsigned char)(c)] == 3)
/* Aliases for characters, ASCII/UTF-8 */
#define CCOLON 0x3a /* ':' */
#define LCBRAC 0x7b /* '{' */
#define RCBRAC 0x7d /* '}' */
#define CQUOTE 0x22 /* '"' */
#define LSBRAC 0x5b /* '[' */
#define RSBRAC 0x5d /* ']' */
#define CCOMMA 0x2c /* ',' */
/* Invoke token callback */
#define TOKEN_CB_CALL(type, _ns, _current_too, _final) \
do { \
int _ret; \
pstate_e ns = _ns; \
ssize_t _sz = (p - chunk_start) + _current_too; \
if(!_sz) { \
/* Shortcut */ \
state = _ns; \
break; \
} \
_ret = cb(type, chunk_start, _sz, key); \
if(_ret < _sz) { \
if(_current_too && _ret == -1) state = ns; \
goto finish; \
} \
chunk_start = p + _current_too; \
state = ns; \
} while(0)
#define TOKEN_CB(_type, _ns, _current_too) \
TOKEN_CB_CALL(_type, _ns, _current_too, 0)
#define PJSON_KEY_FINAL_CHUNK_TYPE PJSON_KEY_END
#define PJSON_VALUE_FINAL_CHUNK_TYPE PJSON_VALUE_END
#define TOKEN_CB_FINAL(_type, _ns, _current_too) \
TOKEN_CB_CALL(_type##_FINAL_CHUNK_TYPE, _ns, _current_too, 1)
/*
* Parser itself
*/
ssize_t
pjson_parse(int *stateContext, const void *jsonbuf, size_t size,
pjson_callback_f *cb, void *key) {
pstate_e state = (pstate_e)*stateContext;
const char *chunk_start = (const char *)jsonbuf;
const char *p = chunk_start;
const char *end = p + size;
int include = 0;
for(; p < end; p++) {
int C = *(const unsigned char *)p;
switch(state) {
case ST_TEXT:
/*
* Initial state: we're in the middle of some text,
* or just have started.
*/
switch(C) {
case LCBRAC:
/* We're now in an object */
state = ST_KEY;
break;
case CQUOTE:
TOKEN_CB(PJSON_TEXT, ST_KEY_BODY, 0);
break;
case RSBRAC:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, include);
break;
case RCBRAC:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, include);
break;
case CCOMMA:
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, 0);
break;
default:
break;
}
break;
case ST_KEY: /* Looking for key */
switch(C) {
case RCBRAC: /* Empty object { } */
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, 1);
break;
case CQUOTE: /* Key start */
TOKEN_CB(PJSON_TEXT, ST_KEY_BODY, 0);
break;
default:
break;
}
break;
case ST_KEY_BODY: /* Inside key */
switch(C) {
case CQUOTE: /* Key end */
TOKEN_CB_FINAL(PJSON_KEY, ST_COLON, 1);
break;
default:
break;
}
break;
case ST_COLON: /* Looking for colon */
switch(C) {
case CCOLON:
state = ST_VALUE;
break;
default:
break;
}
break;
case ST_VALUE: /* Looking for value */
if (WHITESPACE(C)) {
break;
} else {
switch(C) {
case LCBRAC:
TOKEN_CB(PJSON_DLM, ST_VALUE, 1);
break;
case CCOMMA:
TOKEN_CB(PJSON_DLM, ST_VALUE, 1);
break;
case LSBRAC:
TOKEN_CB(PJSON_DLM, ST_ARRAY_VALUE, 1);
break;
case RCBRAC:
TOKEN_CB(PJSON_DLM, ST_END, 1);
break;
case RSBRAC:
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, 1);
break;
default:
TOKEN_CB(PJSON_TEXT, ST_VALUE_BODY, 0);
break;
}
}
break;
case ST_VALUE_BODY: /* Inside value */
switch(C) {
case RCBRAC:
TOKEN_CB_FINAL(PJSON_VALUE, ST_END, 0);
break;
case CCOMMA:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_VALUE, include);
break;
default:
break;
}
break;
case ST_ARRAY_VALUE: /* Looking for array value */
if (WHITESPACE(C)) {
break;
} else {
switch(C) {
case LCBRAC:
TOKEN_CB(PJSON_DLM, ST_ARRAY_VALUE, 1);
break;
case CCOMMA:
TOKEN_CB(PJSON_DLM, ST_ARRAY_VALUE, 1);
break;
case LSBRAC:
TOKEN_CB(PJSON_DLM, ST_ARRAY_VALUE, 1);
break;
case RSBRAC:
TOKEN_CB(PJSON_DLM, ST_END, 1);
break;
default:
TOKEN_CB(PJSON_TEXT, ST_ARRAY_VALUE_BODY, 0);
break;
}
}
break;
case ST_ARRAY_VALUE_BODY: /* Inside array value */
switch(C) {
case RCBRAC:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_ARRAY_VALUE, include);
break;
case RSBRAC:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_ARRAY_VALUE, include);
break;
case CCOMMA:
include = !(p - chunk_start);
TOKEN_CB_FINAL(PJSON_VALUE, ST_ARRAY_VALUE, include);
break;
default:
break;
}
break;
case ST_END: /* End */
switch (C) {
case RCBRAC:
TOKEN_CB_FINAL(PJSON_VALUE, ST_TEXT, 1);
break;
default:
break;
}
break;
} /* switch(*ptr) */
} /* for() */
/*
* Flush the partially processed chunk, state permitting.
*/
if(p - chunk_start) {
switch (state) {
case ST_TEXT:
TOKEN_CB(PJSON_TEXT, state, 0);
break;
default:
break;
}
}
finish:
*stateContext = (int)state;
return chunk_start - (const char *)jsonbuf;
}
/*
* Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _JER_SUPPORT_H_
#define _JER_SUPPORT_H_
#include <asn_system.h> /* Platform-specific types */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Types of data transferred to the application.
*/
typedef enum {
PJSON_TEXT,
PJSON_KEY,
PJSON_VALUE,
PJSON_DLM,
/*
* The following chunk types are reported if the chunk
* terminates the specified JSON element.
*/
PJSON_KEY_END, /* Key ended */
PJSON_VALUE_END /* Value ended */
} pjson_chunk_type_e;
/*
* Callback function that is called by the parser when parsed data is
* available. The _opaque is the pointer to a field containing opaque user
* data specified in pxml_create() call. The chunk type is _type and the text
* data is the piece of buffer identified by _bufid (as supplied to
* pxml_feed() call) starting at offset _offset and of _size bytes size.
* The chunk is NOT '\0'-terminated.
*/
typedef int (pjson_callback_f)(pjson_chunk_type_e _type,
const void *_chunk_data, size_t _chunk_size, void *_key);
/*
* Parse the given buffer as it were a chunk of XML data.
* Invoke the specified callback each time the meaningful data is found.
* This function returns number of bytes consumed from the buffer.
* It will always be lesser than or equal to the specified _size.
* The next invocation of this function must account the difference.
*/
ssize_t pjson_parse(int *_stateContext, const void *_buf, size_t _size,
pjson_callback_f *cb, void *_key);
#ifdef __cplusplus
}
#endif
#endif /* _JER_SUPPORT_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