mirror of https://gerrit.osmocom.org/asn1c
add OER binary32 and binary64 IEEE-754 formats for native REAL type
This commit is contained in:
parent
cb5e1c7c87
commit
afcc891c86
|
@ -1872,6 +1872,14 @@ emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
|
|||
|
||||
if(range->incompatible || range->not_OER_visible) {
|
||||
OUT("{ 0, 0 }");
|
||||
} else if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
|
||||
if(range->narrowing == NARROW_FLOAT32) {
|
||||
OUT("{ sizeof(float), 0 }");
|
||||
} else if(range->narrowing == NARROW_FLOAT64) {
|
||||
OUT("{ sizeof(double), 0 }");
|
||||
} else {
|
||||
OUT("{ 0, 0 }");
|
||||
}
|
||||
} else if(range->left.type == ARE_VALUE && range->left.value >= 0
|
||||
&& range->right.type == ARE_MAX) {
|
||||
OUT("{ 0, 1 }");
|
||||
|
|
|
@ -78,40 +78,12 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
|
|||
0 /* No specifics */
|
||||
};
|
||||
|
||||
static double
|
||||
NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t float_size = specs ? specs->float_size : sizeof(double);
|
||||
if(float_size == sizeof(float)) {
|
||||
return *(const float *)ptr;
|
||||
} else {
|
||||
return *(const double *)ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t /* Returns -1 or float size. */
|
||||
NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t float_size = specs ? specs->float_size : sizeof(double);
|
||||
void *native;
|
||||
|
||||
if(!(native = *sptr)) {
|
||||
native = (*sptr = CALLOC(1, float_size));
|
||||
if(!native) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(float_size == sizeof(float)) {
|
||||
*(float *)native = d;
|
||||
} else {
|
||||
*(double *)native = d;
|
||||
}
|
||||
|
||||
return float_size;
|
||||
}
|
||||
static double NativeReal__get_double(const asn_TYPE_descriptor_t *td,
|
||||
const void *ptr);
|
||||
static ssize_t NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
double d);
|
||||
static void NativeReal__network_swap(size_t float_size, const void *srcp,
|
||||
uint8_t *dst);
|
||||
|
||||
/*
|
||||
* Decode REAL type.
|
||||
|
@ -302,30 +274,61 @@ asn_enc_rval_t
|
|||
NativeReal_encode_oer(asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
asn_enc_rval_t er = { 0, 0, 0 };
|
||||
ssize_t len_len;
|
||||
REAL_t tmp;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints && constraints->value.width != 0) {
|
||||
/* X.696 IEEE 754 binary32 and binary64 encoding */
|
||||
uint8_t scratch[sizeof(double)];
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t wire_size = constraints->value.width;
|
||||
|
||||
(void)td;
|
||||
(void)constraints; /* Constraints are unused in OER */
|
||||
if(specs ? (wire_size == specs->float_size)
|
||||
: (wire_size == sizeof(double))) {
|
||||
/*
|
||||
* Our representation matches the wire, modulo endianness.
|
||||
* That was the whole point of compact encoding!
|
||||
*/
|
||||
} else {
|
||||
assert(wire_size == sizeof(double)
|
||||
|| specs && specs->float_size == wire_size);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(asn_double2REAL(&tmp, d)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/* Encode a fake REAL */
|
||||
len_len = oer_serialize_length(tmp.size, cb, app_key);
|
||||
if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODE_FAILED;
|
||||
/*
|
||||
* The X.696 standard doesn't specify endianness, neither is IEEE 754.
|
||||
* So we assume the network format is big endian.
|
||||
*/
|
||||
NativeReal__network_swap(wire_size, sptr, scratch);
|
||||
if(cb(scratch, wire_size, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
er.encoded = wire_size;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
} else {
|
||||
er.encoded = len_len + tmp.size;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODED_OK(er);
|
||||
double d = NativeReal__get_double(td, sptr);
|
||||
ssize_t len_len;
|
||||
REAL_t tmp;
|
||||
|
||||
/* Prepare a temporary clean structure */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(asn_double2REAL(&tmp, d)) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/* Encode a fake REAL */
|
||||
len_len = oer_serialize_length(tmp.size, cb, app_key);
|
||||
if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
er.encoded = len_len + tmp.size;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +343,38 @@ NativeReal_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
|||
size_t real_body_len;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints; /* Constraints are unused in OER */
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints && constraints->value.width != 0) {
|
||||
/* X.696 IEEE 754 binary32 and binary64 encoding */
|
||||
uint8_t scratch[sizeof(double)];
|
||||
size_t wire_size = constraints->value.width;
|
||||
|
||||
if(size < wire_size)
|
||||
ASN__DECODE_STARVED;
|
||||
|
||||
/*
|
||||
* The X.696 standard doesn't specify endianness, neither is IEEE 754.
|
||||
* So we assume the network format is big endian.
|
||||
*/
|
||||
NativeReal__network_swap(wire_size, ptr, scratch);
|
||||
|
||||
switch(wire_size) {
|
||||
case sizeof(double):
|
||||
if(NativeReal__set(td, sptr, *(const double *)scratch) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
break;
|
||||
case sizeof(float):
|
||||
if(NativeReal__set(td, sptr, *(const float *)scratch) < 0)
|
||||
ASN__DECODE_FAILED;
|
||||
break;
|
||||
default:
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ok.consumed = wire_size;
|
||||
return ok;
|
||||
}
|
||||
|
||||
len_len = oer_fetch_length(ptr, size, &real_body_len);
|
||||
if(len_len < 0) ASN__DECODE_FAILED;
|
||||
|
@ -541,3 +575,99 @@ NativeReal_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
|||
result_ok.length = float_set_size;
|
||||
return result_ok;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local helper functions.
|
||||
*/
|
||||
|
||||
static double
|
||||
NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t float_size = specs ? specs->float_size : sizeof(double);
|
||||
if(float_size == sizeof(float)) {
|
||||
return *(const float *)ptr;
|
||||
} else {
|
||||
return *(const double *)ptr;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t /* Returns -1 or float size. */
|
||||
NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
|
||||
const asn_NativeReal_specifics_t *specs =
|
||||
(const asn_NativeReal_specifics_t *)td->specifics;
|
||||
size_t float_size = specs ? specs->float_size : sizeof(double);
|
||||
void *native;
|
||||
|
||||
if(!(native = *sptr)) {
|
||||
native = (*sptr = CALLOC(1, float_size));
|
||||
if(!native) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(float_size == sizeof(float)) {
|
||||
*(float *)native = d;
|
||||
} else {
|
||||
*(double *)native = d;
|
||||
}
|
||||
|
||||
return float_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap bytes from/to network, if local is little-endian.
|
||||
* Unused endianness sections are likely removed at compile phase.
|
||||
*/
|
||||
static void
|
||||
NativeReal__network_swap(size_t float_size, const void *srcp, uint8_t *dst) {
|
||||
const uint8_t *src = srcp;
|
||||
double test = -0.0;
|
||||
int float_big_endian = *(const char *)&test != 0;
|
||||
/* In lieu of static_assert(sizeof(double) == 8) */
|
||||
static const char sizeof_double_is_8_a[sizeof(double)-7] CC_NOTUSED;
|
||||
static const char sizeof_double_is_8_b[9-sizeof(double)] CC_NOTUSED;
|
||||
/* In lieu of static_assert(sizeof(sizeof) == 4) */
|
||||
static const char sizeof_float_is_4_a[sizeof(float)-3] CC_NOTUSED;
|
||||
static const char sizeof_float_is_4_b[5-sizeof(float)] CC_NOTUSED;
|
||||
|
||||
switch(float_size) {
|
||||
case sizeof(double):
|
||||
assert(sizeof(double) == 8);
|
||||
if(float_big_endian) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
dst[4] = src[4];
|
||||
dst[5] = src[5];
|
||||
dst[6] = src[6];
|
||||
dst[7] = src[7];
|
||||
} else {
|
||||
dst[0] = src[7];
|
||||
dst[1] = src[6];
|
||||
dst[2] = src[5];
|
||||
dst[3] = src[4];
|
||||
dst[4] = src[3];
|
||||
dst[5] = src[2];
|
||||
dst[6] = src[1];
|
||||
dst[7] = src[0];
|
||||
}
|
||||
return;
|
||||
case sizeof(float):
|
||||
assert(sizeof(float) == 4);
|
||||
if(float_big_endian) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
} else {
|
||||
dst[0] = src[3];
|
||||
dst[1] = src[2];
|
||||
dst[2] = src[1];
|
||||
dst[3] = src[0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct asn_NativeReal_specifics_s {
|
||||
unsigned float_size; /* 4 for 'float', 8 for 'double'. */
|
||||
unsigned float_size; /* sizeof(float) or sizeof(double) */
|
||||
} asn_NativeReal_specifics_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeReal;
|
||||
|
|
|
@ -179,7 +179,7 @@ Indirect_IEEE_binary32_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [Indirect-IEEE-binary32] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_Indirect_IEEE_binary32_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [Indirect-IEEE-binary32] >>> ***/
|
||||
|
@ -257,7 +257,7 @@ IEEE_binary32_w_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary32-w] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary32_w_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary32-w] >>> ***/
|
||||
|
@ -335,7 +335,7 @@ IEEE_binary32_0w_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary32-0w] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary32_0w_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary32-0w] >>> ***/
|
||||
|
@ -413,7 +413,7 @@ IEEE_binary32_w0_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary32-w0] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary32_w0_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary32-w0] >>> ***/
|
||||
|
@ -490,7 +490,7 @@ IEEE_binary64_w_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary64-w] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary64_w_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(double), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary64-w] >>> ***/
|
||||
|
@ -564,7 +564,7 @@ IEEE_binary64_0w_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary64-0w] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary64_0w_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(double), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary64-0w] >>> ***/
|
||||
|
@ -638,7 +638,7 @@ IEEE_binary64_w0_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [IEEE-binary64-w0] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_IEEE_binary64_w0_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(double), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [IEEE-binary64-w0] >>> ***/
|
||||
|
@ -794,16 +794,16 @@ ieee_binary32_w0_5_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
|||
/*** <<< CTDEFS [Test] >>> ***/
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_indirect_ieee_binary32_constr_2 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
static asn_oer_constraints_t asn_OER_type_ieee_binary32_w_constr_3 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
static asn_oer_constraints_t asn_OER_type_ieee_binary32_0w_constr_4 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
static asn_oer_constraints_t asn_OER_type_ieee_binary32_w0_constr_5 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
{ sizeof(float), 0 },
|
||||
-1};
|
||||
|
||||
/*** <<< STAT-DEFS [Test] >>> ***/
|
||||
|
|
Loading…
Reference in New Issue