blob: 419e7d1253379b8dfbf99a52e43efd43fc26bc17 [file] [log] [blame]
Lev Walkin41ba1f22004-09-14 12:46:35 +00001/*-
Lev Walkinab1d1e12017-10-03 18:43:12 -07002 * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
Lev Walkin41ba1f22004-09-14 12:46:35 +00003 * Redistribution and modifications are permitted subject to BSD license.
4 */
5/*
Lev Walkin41635d32006-03-18 05:06:57 +00006 * Read the NativeReal.h for the explanation wrt. differences between
Lev Walkin41ba1f22004-09-14 12:46:35 +00007 * REAL and NativeReal.
8 * Basically, both are decoders and encoders of ASN.1 REAL type, but this
9 * implementation deals with the standard (machine-specific) representation
10 * of them instead of using the platform-independent buffer.
11 */
Lev Walkina9cc46e2004-09-22 16:06:28 +000012#include <asn_internal.h>
Lev Walkin41ba1f22004-09-14 12:46:35 +000013#include <NativeReal.h>
Lev Walkin41ba1f22004-09-14 12:46:35 +000014#include <REAL.h>
Lev Walkin725883b2006-10-09 12:07:58 +000015#include <OCTET_STRING.h>
Lev Walkincd2f48e2017-08-10 02:14:59 -070016#include <math.h>
Jon Ringle35c3f0d2017-10-04 21:54:39 -040017#include <float.h>
Lev Walkin41ba1f22004-09-14 12:46:35 +000018
Lev Walkineff98a52017-09-13 22:24:35 +000019#if defined(__clang__)
20/*
21 * isnan() is defined using generic selections and won't compile in
22 * strict C89 mode because of too fancy system's standard library.
23 * However, prior to C11 the math had a perfectly working isnan()
24 * in the math library.
25 * Disable generic selection warning so we can test C89 mode with newer libc.
26 */
27#pragma clang diagnostic push
28#pragma clang diagnostic ignored "-Wc11-extensions"
29static int asn_isnan(double d) {
30 return isnan(d);
31}
32#pragma clang diagnostic pop
33#else
34#define asn_isnan(v) isnan(v)
35#endif /* generic selections */
36
Lev Walkin41ba1f22004-09-14 12:46:35 +000037/*
38 * NativeReal basic type description.
39 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070040static const ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
Lev Walkin41ba1f22004-09-14 12:46:35 +000041 (ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
42};
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080043asn_TYPE_operation_t asn_OP_NativeReal = {
Lev Walkina9cc46e2004-09-22 16:06:28 +000044 NativeReal_free,
45 NativeReal_print,
Lev Walkincd2f48e2017-08-10 02:14:59 -070046 NativeReal_compare,
Lev Walkin41ba1f22004-09-14 12:46:35 +000047 NativeReal_decode_ber,
48 NativeReal_encode_der,
Lev Walkin8471cec2004-10-21 14:02:19 +000049 NativeReal_decode_xer,
Lev Walkina9cc46e2004-09-22 16:06:28 +000050 NativeReal_encode_xer,
Lev Walkincc159472017-07-06 08:26:36 -070051#ifdef ASN_DISABLE_OER_SUPPORT
52 0,
53 0,
54#else
Lev Walkinab1d1e12017-10-03 18:43:12 -070055 NativeReal_decode_oer,
56 NativeReal_encode_oer,
Lev Walkincc159472017-07-06 08:26:36 -070057#endif /* ASN_DISABLE_OER_SUPPORT */
Lev Walkinb33425f2017-07-14 14:59:52 +040058#ifdef ASN_DISABLE_PER_SUPPORT
59 0,
60 0,
61#else
62 NativeReal_decode_uper,
63 NativeReal_encode_uper,
64#endif /* ASN_DISABLE_PER_SUPPORT */
Lev Walkina5972be2017-09-29 23:15:58 -070065 NativeReal_random_fill,
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080066 0 /* Use generic outmost tag fetcher */
67};
68asn_TYPE_descriptor_t asn_DEF_NativeReal = {
69 "REAL", /* The ASN.1 type is still REAL */
70 "REAL",
71 &asn_OP_NativeReal,
Lev Walkin5e033762004-09-29 13:26:15 +000072 asn_DEF_NativeReal_tags,
73 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
74 asn_DEF_NativeReal_tags, /* Same as above */
75 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
Lev Walkina5972be2017-09-29 23:15:58 -070076 { 0, 0, asn_generic_no_constraint },
Lev Walkin41ba1f22004-09-14 12:46:35 +000077 0, 0, /* No members */
78 0 /* No specifics */
79};
80
Lev Walkinb5450702017-10-04 02:52:57 -070081static double
82NativeReal__get_double(const asn_TYPE_descriptor_t *td, const void *ptr) {
83 const asn_NativeReal_specifics_t *specs =
84 (const asn_NativeReal_specifics_t *)td->specifics;
85 size_t float_size = specs ? specs->float_size : sizeof(double);
86 if(float_size == sizeof(float)) {
87 return *(const float *)ptr;
88 } else {
89 return *(const double *)ptr;
90 }
91}
92
Lev Walkincb5e1c72017-10-04 22:23:08 -070093static ssize_t /* Returns -1 or float size. */
94NativeReal__set(const asn_TYPE_descriptor_t *td, void **sptr, double d) {
95 const asn_NativeReal_specifics_t *specs =
96 (const asn_NativeReal_specifics_t *)td->specifics;
97 size_t float_size = specs ? specs->float_size : sizeof(double);
98 void *native;
99
100 if(!(native = *sptr)) {
101 native = (*sptr = CALLOC(1, float_size));
102 if(!native) {
103 return -1;
104 }
105 }
106
107 if(float_size == sizeof(float)) {
108 *(float *)native = d;
109 } else {
110 *(double *)native = d;
111 }
112
113 return float_size;
114}
115
Lev Walkin41ba1f22004-09-14 12:46:35 +0000116/*
117 * Decode REAL type.
118 */
Lev Walkindc06f6b2004-10-20 15:50:55 +0000119asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700120NativeReal_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkinb5450702017-10-04 02:52:57 -0700121 asn_TYPE_descriptor_t *td, void **sptr,
Lev Walkinab1d1e12017-10-03 18:43:12 -0700122 const void *buf_ptr, size_t size, int tag_mode) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700123 asn_dec_rval_t rval;
124 ber_tlv_len_t length;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000125
Lev Walkinab1d1e12017-10-03 18:43:12 -0700126 ASN_DEBUG("Decoding %s as REAL (tm=%d)", td->name, tag_mode);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000127
Lev Walkinab1d1e12017-10-03 18:43:12 -0700128 /*
129 * Check tags.
130 */
131 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
132 &length, 0);
133 if(rval.code != RC_OK) return rval;
Lev Walkin4ca41492017-10-03 20:29:54 -0700134 assert(length >= 0); /* Ensured by ber_check_tags */
Lev Walkin41ba1f22004-09-14 12:46:35 +0000135
Lev Walkinab1d1e12017-10-03 18:43:12 -0700136 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000137
Lev Walkinab1d1e12017-10-03 18:43:12 -0700138 /*
139 * Make sure we have this length.
140 */
141 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
142 size -= rval.consumed;
143 if(length > (ber_tlv_len_t)size) {
144 rval.code = RC_WMORE;
145 rval.consumed = 0;
146 return rval;
147 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000148
Lev Walkinab1d1e12017-10-03 18:43:12 -0700149 /*
150 * ASN.1 encoded REAL: buf_ptr, length
151 * Fill the Dbl, at the same time checking for overflow.
152 * If overflow occured, return with RC_FAIL.
153 */
154 {
155 uint8_t scratch[24]; /* Longer than %.16f in decimal */
156 REAL_t tmp;
157 double d;
158 int ret;
Lev Walkin7e033b52005-07-02 08:19:17 +0000159
Lev Walkin4ca41492017-10-03 20:29:54 -0700160 if((size_t)length < sizeof(scratch)) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700161 tmp.buf = scratch;
162 tmp.size = length;
163 } else {
164 /* This rarely happens: impractically long value */
165 tmp.buf = CALLOC(1, length + 1);
166 tmp.size = length;
167 if(!tmp.buf) {
168 rval.code = RC_FAIL;
169 rval.consumed = 0;
170 return rval;
171 }
172 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000173
Lev Walkinab1d1e12017-10-03 18:43:12 -0700174 memcpy(tmp.buf, buf_ptr, length);
175 tmp.buf[length] = '\0';
Lev Walkin41ba1f22004-09-14 12:46:35 +0000176
Lev Walkinab1d1e12017-10-03 18:43:12 -0700177 ret = asn_REAL2double(&tmp, &d);
178 if(tmp.buf != scratch) FREEMEM(tmp.buf);
179 if(ret) {
180 rval.code = RC_FAIL;
181 rval.consumed = 0;
182 return rval;
183 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000184
Lev Walkincb5e1c72017-10-04 22:23:08 -0700185 if(NativeReal__set(td, sptr, d) < 0)
186 ASN__DECODE_FAILED;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700187 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000188
Lev Walkinab1d1e12017-10-03 18:43:12 -0700189 rval.code = RC_OK;
190 rval.consumed += length;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000191
Lev Walkinb5450702017-10-04 02:52:57 -0700192 ASN_DEBUG("Took %ld/%ld bytes to encode %s", (long)rval.consumed,
193 (long)length, td->name);
Lev Walkinab1d1e12017-10-03 18:43:12 -0700194
195 return rval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000196}
197
198/*
199 * Encode the NativeReal using the standard REAL type DER encoder.
200 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000201asn_enc_rval_t
Lev Walkincb5e1c72017-10-04 22:23:08 -0700202NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000203 int tag_mode, ber_tlv_tag_t tag,
204 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkincb5e1c72017-10-04 22:23:08 -0700205 double d = NativeReal__get_double(td, sptr);
Lev Walkinb5450702017-10-04 02:52:57 -0700206 asn_enc_rval_t erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000207 REAL_t tmp;
208
Lev Walkina8bbbda2005-02-06 04:29:03 +0000209 /* Prepare a temporary clean structure */
210 memset(&tmp, 0, sizeof(tmp));
211
Lev Walkincb5e1c72017-10-04 22:23:08 -0700212 if(asn_double2REAL(&tmp, d))
213 ASN__ENCODE_FAILED;
214
215 /* Encode a fake REAL */
216 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
217 if(erval.encoded == -1) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000218 assert(erval.structure_ptr == &tmp);
Lev Walkincb5e1c72017-10-04 22:23:08 -0700219 erval.structure_ptr = sptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000220 }
Lev Walkina8bbbda2005-02-06 04:29:03 +0000221
222 /* Free possibly allocated members of the temporary structure */
Lev Walkincb5e1c72017-10-04 22:23:08 -0700223 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkina8bbbda2005-02-06 04:29:03 +0000224
Lev Walkincb5e1c72017-10-04 22:23:08 -0700225 return erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000226}
227
Lev Walkin41d972b2017-08-23 23:30:59 -0700228#ifndef ASN_DISABLE_PER_SUPPORT
229
Lev Walkin725883b2006-10-09 12:07:58 +0000230/*
231 * Decode REAL type using PER.
232 */
233asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700234NativeReal_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin494fb702017-08-07 20:07:00 -0700235 asn_TYPE_descriptor_t *td,
Lev Walkinb5450702017-10-04 02:52:57 -0700236 const asn_per_constraints_t *constraints, void **sptr,
Lev Walkin494fb702017-08-07 20:07:00 -0700237 asn_per_data_t *pd) {
Lev Walkin725883b2006-10-09 12:07:58 +0000238 asn_dec_rval_t rval;
Lev Walkincb5e1c72017-10-04 22:23:08 -0700239 double d;
Lev Walkin725883b2006-10-09 12:07:58 +0000240 REAL_t tmp;
241 void *ptmp = &tmp;
242 int ret;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000243
Lev Walkin725883b2006-10-09 12:07:58 +0000244 (void)constraints;
245
Lev Walkin725883b2006-10-09 12:07:58 +0000246 memset(&tmp, 0, sizeof(tmp));
Lev Walkinb5450702017-10-04 02:52:57 -0700247 rval = OCTET_STRING_decode_uper(opt_codec_ctx, &asn_DEF_REAL,
248 NULL, &ptmp, pd);
249 if(rval.code != RC_OK) {
Lev Walkin725883b2006-10-09 12:07:58 +0000250 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
251 return rval;
252 }
253
Lev Walkinb5450702017-10-04 02:52:57 -0700254 ret = asn_REAL2double(&tmp, &d);
Lev Walkin725883b2006-10-09 12:07:58 +0000255 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700256 if(ret) ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000257
Lev Walkincb5e1c72017-10-04 22:23:08 -0700258 if(NativeReal__set(td, sptr, d) < 0 )
259 ASN__DECODE_FAILED;
Lev Walkinb5450702017-10-04 02:52:57 -0700260
Lev Walkin725883b2006-10-09 12:07:58 +0000261 return rval;
262}
263
264/*
265 * Encode the NativeReal using the OCTET STRING PER encoder.
266 */
267asn_enc_rval_t
268NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700269 const asn_per_constraints_t *constraints, void *sptr,
270 asn_per_outp_t *po) {
Lev Walkinb5450702017-10-04 02:52:57 -0700271 double d = NativeReal__get_double(td, sptr);
Lev Walkin725883b2006-10-09 12:07:58 +0000272 asn_enc_rval_t erval;
273 REAL_t tmp;
274
275 (void)constraints;
276
277 /* Prepare a temporary clean structure */
278 memset(&tmp, 0, sizeof(tmp));
279
Lev Walkinb5450702017-10-04 02:52:57 -0700280 if(asn_double2REAL(&tmp, d))
Lev Walkin7c1dc052016-03-14 03:08:15 -0700281 ASN__ENCODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000282
283 /* Encode a DER REAL */
Lev Walkinb5450702017-10-04 02:52:57 -0700284 erval = OCTET_STRING_encode_uper(&asn_DEF_REAL, NULL, &tmp, po);
285 if(erval.encoded == -1)
Lev Walkin725883b2006-10-09 12:07:58 +0000286 erval.structure_ptr = sptr;
287
288 /* Free possibly allocated members of the temporary structure */
289 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
290
291 return erval;
292}
Lev Walkin8471cec2004-10-21 14:02:19 +0000293
Lev Walkin41d972b2017-08-23 23:30:59 -0700294#endif /* ASN_DISABLE_PER_SUPPORT */
295
Lev Walkinab1d1e12017-10-03 18:43:12 -0700296#ifndef ASN_DISABLE_OER_SUPPORT
297
298/*
299 * Encode as Canonical OER.
300 */
301asn_enc_rval_t
302NativeReal_encode_oer(asn_TYPE_descriptor_t *td,
303 const asn_oer_constraints_t *constraints, void *sptr,
304 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinb5450702017-10-04 02:52:57 -0700305 double d = NativeReal__get_double(td, sptr);
Lev Walkinab1d1e12017-10-03 18:43:12 -0700306 asn_enc_rval_t er = { 0, 0, 0 };
307 ssize_t len_len;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700308 REAL_t tmp;
309
310 /* Prepare a temporary clean structure */
311 memset(&tmp, 0, sizeof(tmp));
312
313 (void)td;
314 (void)constraints; /* Constraints are unused in OER */
315
Lev Walkinb5450702017-10-04 02:52:57 -0700316 if(asn_double2REAL(&tmp, d)) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700317 ASN__ENCODE_FAILED;
318 }
319
320 /* Encode a fake REAL */
321 len_len = oer_serialize_length(tmp.size, cb, app_key);
322 if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
323 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
324 ASN__ENCODE_FAILED;
325 } else {
326 er.encoded = len_len + tmp.size;
327 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
328 ASN__ENCODED_OK(er);
329 }
330}
331
332asn_dec_rval_t
333NativeReal_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
334 asn_TYPE_descriptor_t *td,
335 const asn_oer_constraints_t *constraints, void **sptr,
336 const void *ptr, size_t size) {
337 asn_dec_rval_t ok = {RC_OK, 0};
Lev Walkinab1d1e12017-10-03 18:43:12 -0700338 double d;
339 ssize_t len_len;
340 size_t real_body_len;
341
342 (void)opt_codec_ctx;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700343 (void)constraints; /* Constraints are unused in OER */
344
345 len_len = oer_fetch_length(ptr, size, &real_body_len);
346 if(len_len < 0) ASN__DECODE_FAILED;
347 if(len_len == 0) ASN__DECODE_STARVED;
348
349 ptr = (const char *)ptr + len_len;
350 size -= len_len;
351
352 if(real_body_len > size) ASN__DECODE_STARVED;
353
354 {
355 uint8_t scratch[24]; /* Longer than %.16f in decimal */
356 REAL_t tmp;
357 int ret;
358
359 if(real_body_len < sizeof(scratch)) {
360 tmp.buf = scratch;
361 tmp.size = real_body_len;
362 } else {
363 /* This rarely happens: impractically long value */
364 tmp.buf = CALLOC(1, real_body_len + 1);
365 tmp.size = real_body_len;
366 if(!tmp.buf) {
367 ASN__DECODE_FAILED;
368 }
369 }
370
371 memcpy(tmp.buf, ptr, real_body_len);
372 tmp.buf[real_body_len] = '\0';
373
374 ret = asn_REAL2double(&tmp, &d);
375 if(tmp.buf != scratch) FREEMEM(tmp.buf);
376 if(ret) {
377 ASN_DEBUG("REAL decoded in %zu bytes, but can't convert t double",
378 real_body_len);
379 ASN__DECODE_FAILED;
380 }
381 }
382
Lev Walkincb5e1c72017-10-04 22:23:08 -0700383 if(NativeReal__set(td, sptr, d) < 0)
384 ASN__DECODE_FAILED;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700385
Lev Walkinab1d1e12017-10-03 18:43:12 -0700386 ok.consumed = len_len + real_body_len;
387 return ok;
388}
389
390#endif /* ASN_DISABLE_OER_SUPPORT */
391
Lev Walkin8471cec2004-10-21 14:02:19 +0000392/*
393 * Decode the chunk of XML text encoding REAL.
394 */
395asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700396NativeReal_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin8471cec2004-10-21 14:02:19 +0000397 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000398 const void *buf_ptr, size_t size) {
Lev Walkin8471cec2004-10-21 14:02:19 +0000399 asn_dec_rval_t rval;
Lev Walkinb5450702017-10-04 02:52:57 -0700400 REAL_t st = { 0, 0 };
401 REAL_t *stp = &st;
Lev Walkin8471cec2004-10-21 14:02:19 +0000402
Lev Walkinb5450702017-10-04 02:52:57 -0700403 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)&stp, opt_mname,
Lev Walkin8471cec2004-10-21 14:02:19 +0000404 buf_ptr, size);
405 if(rval.code == RC_OK) {
Lev Walkinb5450702017-10-04 02:52:57 -0700406 double d;
Lev Walkincb5e1c72017-10-04 22:23:08 -0700407 if(asn_REAL2double(&st, &d) || NativeReal__set(td, sptr, d) < 0) {
408 rval.code = RC_FAIL;
409 rval.consumed = 0;
Lev Walkinb5450702017-10-04 02:52:57 -0700410 }
Lev Walkin8471cec2004-10-21 14:02:19 +0000411 } else {
Lev Walkincb5e1c72017-10-04 22:23:08 -0700412 /* Convert all errors into RC_FAIL */
413 rval.consumed = 0;
Lev Walkin8471cec2004-10-21 14:02:19 +0000414 }
Lev Walkinb5450702017-10-04 02:52:57 -0700415 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &st);
Lev Walkin8471cec2004-10-21 14:02:19 +0000416 return rval;
417}
418
Lev Walkina9cc46e2004-09-22 16:06:28 +0000419asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000420NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000421 int ilevel, enum xer_encoder_flags_e flags,
422 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinb5450702017-10-04 02:52:57 -0700423 double d = NativeReal__get_double(td, sptr);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000424 asn_enc_rval_t er;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000425
426 (void)ilevel;
427
Lev Walkinb5450702017-10-04 02:52:57 -0700428 er.encoded = REAL__dump(d, flags & XER_F_CANONICAL, cb, app_key);
429 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000430
Lev Walkin7c1dc052016-03-14 03:08:15 -0700431 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000432}
433
Lev Walkin41ba1f22004-09-14 12:46:35 +0000434/*
435 * REAL specific human-readable output.
436 */
437int
Lev Walkin5e033762004-09-29 13:26:15 +0000438NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000439 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000440
Lev Walkin41ba1f22004-09-14 12:46:35 +0000441 (void)ilevel; /* Unused argument */
442
Lev Walkinb5450702017-10-04 02:52:57 -0700443 if(sptr) {
444 double d = NativeReal__get_double(td, sptr);
445 return (REAL__dump(d, 0, cb, app_key) < 0) ? -1 : 0;
446 } else {
447 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
448 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000449}
450
Lev Walkincd2f48e2017-08-10 02:14:59 -0700451int
452NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
453 const void *bptr) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700454
Lev Walkinb5450702017-10-04 02:52:57 -0700455 if(aptr && bptr) {
456 double a = NativeReal__get_double(td, aptr);
457 double b = NativeReal__get_double(td, bptr);
458
Lev Walkincd2f48e2017-08-10 02:14:59 -0700459 /* NaN sorted above everything else */
Lev Walkinb5450702017-10-04 02:52:57 -0700460 if(asn_isnan(a)) {
461 if(asn_isnan(b)) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700462 return 0;
463 } else {
464 return -1;
465 }
Lev Walkinb5450702017-10-04 02:52:57 -0700466 } else if(asn_isnan(b)) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700467 return 1;
468 }
469 /* Value comparison. */
Lev Walkinb5450702017-10-04 02:52:57 -0700470 if(a < b) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700471 return -1;
Lev Walkinb5450702017-10-04 02:52:57 -0700472 } else if(a > b) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700473 return 1;
474 } else {
475 return 0;
476 }
Lev Walkinb5450702017-10-04 02:52:57 -0700477 } else if(!aptr) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700478 return -1;
479 } else {
480 return 1;
481 }
482}
483
Lev Walkin41ba1f22004-09-14 12:46:35 +0000484void
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700485NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr,
486 enum asn_struct_free_method method) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700487 if(!td || !ptr)
Lev Walkin41ba1f22004-09-14 12:46:35 +0000488 return;
489
490 ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700491 td->name, method, ptr);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000492
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700493 switch(method) {
494 case ASFM_FREE_EVERYTHING:
495 FREEMEM(ptr);
496 break;
497 case ASFM_FREE_UNDERLYING:
498 break;
Lev Walkincb5e1c72017-10-04 22:23:08 -0700499 case ASFM_FREE_UNDERLYING_AND_RESET: {
500 const asn_NativeReal_specifics_t *specs;
501 size_t float_size;
502 specs = (const asn_NativeReal_specifics_t *)td->specifics;
503 float_size = specs ? specs->float_size : sizeof(double);
504 memset(ptr, 0, float_size);
505 } break;
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700506 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000507}
508
Lev Walkina5972be2017-09-29 23:15:58 -0700509
510asn_random_fill_result_t
511NativeReal_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
512 const asn_encoding_constraints_t *constraints,
513 size_t max_length) {
Lev Walkincb5e1c72017-10-04 22:23:08 -0700514 asn_random_fill_result_t result_ok = {ARFILL_OK, 0};
Lev Walkina5972be2017-09-29 23:15:58 -0700515 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
516 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
Lev Walkinab1d1e12017-10-03 18:43:12 -0700517 static const double values[] = {
518 0, -0.0, -1, 1, -M_E, M_E, -3.14, 3.14, -M_PI, M_PI, -255, 255,
519 /* 2^51 */
520 -2251799813685248.0, 2251799813685248.0,
521 /* 2^52 */
522 -4503599627370496.0, 4503599627370496.0,
523 /* 2^100 */
524 -1267650600228229401496703205376.0, 1267650600228229401496703205376.0,
Lev Walkin4ca41492017-10-03 20:29:54 -0700525#if __STDC_VERSION__ >= 199901L
Jon Ringle35c3f0d2017-10-04 21:54:39 -0400526 -FLT_MAX, FLT_MAX,
Lev Walkin4ca41492017-10-03 20:29:54 -0700527#endif
528 INFINITY, -INFINITY, NAN};
Lev Walkincb5e1c72017-10-04 22:23:08 -0700529 ssize_t float_set_size;
Lev Walkina5972be2017-09-29 23:15:58 -0700530 double d;
531
Lev Walkina5972be2017-09-29 23:15:58 -0700532 (void)constraints;
533
534 if(max_length == 0) return result_skipped;
535
536 d = values[asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1)];
537
Lev Walkincb5e1c72017-10-04 22:23:08 -0700538 float_set_size = NativeReal__set(td, sptr, d);
539 if(float_set_size < 0) return result_failed;
Lev Walkina5972be2017-09-29 23:15:58 -0700540
Lev Walkincb5e1c72017-10-04 22:23:08 -0700541 result_ok.length = float_set_size;
Lev Walkina5972be2017-09-29 23:15:58 -0700542 return result_ok;
543}