blob: 68167835d5e5772eacca3fc85011241c53b952ed [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 Walkin41ba1f22004-09-14 12:46:35 +000093/*
94 * Decode REAL type.
95 */
Lev Walkindc06f6b2004-10-20 15:50:55 +000096asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -070097NativeReal_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkinb5450702017-10-04 02:52:57 -070098 asn_TYPE_descriptor_t *td, void **sptr,
Lev Walkinab1d1e12017-10-03 18:43:12 -070099 const void *buf_ptr, size_t size, int tag_mode) {
Lev Walkinb5450702017-10-04 02:52:57 -0700100 const asn_NativeReal_specifics_t *specs =
101 (const asn_NativeReal_specifics_t *)td->specifics;
102 size_t float_size = specs ? specs->float_size : sizeof(double);
103 void *native = *sptr;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700104 asn_dec_rval_t rval;
105 ber_tlv_len_t length;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000106
Lev Walkinab1d1e12017-10-03 18:43:12 -0700107 /*
108 * If the structure is not there, allocate it.
109 */
Lev Walkinb5450702017-10-04 02:52:57 -0700110 if(!native) {
111 native = (*sptr = CALLOC(1, float_size));
112 if(!native) ASN__DECODE_FAILED;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700113 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000114
Lev Walkinab1d1e12017-10-03 18:43:12 -0700115 ASN_DEBUG("Decoding %s as REAL (tm=%d)", td->name, tag_mode);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000116
Lev Walkinab1d1e12017-10-03 18:43:12 -0700117 /*
118 * Check tags.
119 */
120 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
121 &length, 0);
122 if(rval.code != RC_OK) return rval;
Lev Walkin4ca41492017-10-03 20:29:54 -0700123 assert(length >= 0); /* Ensured by ber_check_tags */
Lev Walkin41ba1f22004-09-14 12:46:35 +0000124
Lev Walkinab1d1e12017-10-03 18:43:12 -0700125 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000126
Lev Walkinab1d1e12017-10-03 18:43:12 -0700127 /*
128 * Make sure we have this length.
129 */
130 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
131 size -= rval.consumed;
132 if(length > (ber_tlv_len_t)size) {
133 rval.code = RC_WMORE;
134 rval.consumed = 0;
135 return rval;
136 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000137
Lev Walkinab1d1e12017-10-03 18:43:12 -0700138 /*
139 * ASN.1 encoded REAL: buf_ptr, length
140 * Fill the Dbl, at the same time checking for overflow.
141 * If overflow occured, return with RC_FAIL.
142 */
143 {
144 uint8_t scratch[24]; /* Longer than %.16f in decimal */
145 REAL_t tmp;
146 double d;
147 int ret;
Lev Walkin7e033b52005-07-02 08:19:17 +0000148
Lev Walkin4ca41492017-10-03 20:29:54 -0700149 if((size_t)length < sizeof(scratch)) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700150 tmp.buf = scratch;
151 tmp.size = length;
152 } else {
153 /* This rarely happens: impractically long value */
154 tmp.buf = CALLOC(1, length + 1);
155 tmp.size = length;
156 if(!tmp.buf) {
157 rval.code = RC_FAIL;
158 rval.consumed = 0;
159 return rval;
160 }
161 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000162
Lev Walkinab1d1e12017-10-03 18:43:12 -0700163 memcpy(tmp.buf, buf_ptr, length);
164 tmp.buf[length] = '\0';
Lev Walkin41ba1f22004-09-14 12:46:35 +0000165
Lev Walkinab1d1e12017-10-03 18:43:12 -0700166 ret = asn_REAL2double(&tmp, &d);
167 if(tmp.buf != scratch) FREEMEM(tmp.buf);
168 if(ret) {
169 rval.code = RC_FAIL;
170 rval.consumed = 0;
171 return rval;
172 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000173
Lev Walkinb5450702017-10-04 02:52:57 -0700174 if(float_size == sizeof(float)) {
175 *(float *)native = d;
176 } else {
177 *(double *)native = d;
178 }
Lev Walkinab1d1e12017-10-03 18:43:12 -0700179 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000180
Lev Walkinab1d1e12017-10-03 18:43:12 -0700181 rval.code = RC_OK;
182 rval.consumed += length;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000183
Lev Walkinb5450702017-10-04 02:52:57 -0700184 ASN_DEBUG("Took %ld/%ld bytes to encode %s", (long)rval.consumed,
185 (long)length, td->name);
Lev Walkinab1d1e12017-10-03 18:43:12 -0700186
187 return rval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000188}
189
190/*
191 * Encode the NativeReal using the standard REAL type DER encoder.
192 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000193asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000194NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000195 int tag_mode, ber_tlv_tag_t tag,
196 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinb5450702017-10-04 02:52:57 -0700197 double d = NativeReal__get_double(td, ptr);
198 asn_enc_rval_t erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000199 REAL_t tmp;
200
Lev Walkina8bbbda2005-02-06 04:29:03 +0000201 /* Prepare a temporary clean structure */
202 memset(&tmp, 0, sizeof(tmp));
203
Lev Walkinb5450702017-10-04 02:52:57 -0700204 if(asn_double2REAL(&tmp, d)) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000205 erval.encoded = -1;
206 erval.failed_type = td;
207 erval.structure_ptr = ptr;
208 return erval;
209 }
210
Lev Walkin8e8078a2004-09-26 13:10:40 +0000211 /* Encode a fake REAL */
212 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000213 if(erval.encoded == -1) {
214 assert(erval.structure_ptr == &tmp);
215 erval.structure_ptr = ptr;
216 }
Lev Walkina8bbbda2005-02-06 04:29:03 +0000217
218 /* Free possibly allocated members of the temporary structure */
Lev Walkinadcb5862006-03-17 02:11:12 +0000219 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkina8bbbda2005-02-06 04:29:03 +0000220
Lev Walkin41ba1f22004-09-14 12:46:35 +0000221 return erval;
222}
223
Lev Walkin41d972b2017-08-23 23:30:59 -0700224#ifndef ASN_DISABLE_PER_SUPPORT
225
Lev Walkin725883b2006-10-09 12:07:58 +0000226/*
227 * Decode REAL type using PER.
228 */
229asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700230NativeReal_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin494fb702017-08-07 20:07:00 -0700231 asn_TYPE_descriptor_t *td,
Lev Walkinb5450702017-10-04 02:52:57 -0700232 const asn_per_constraints_t *constraints, void **sptr,
Lev Walkin494fb702017-08-07 20:07:00 -0700233 asn_per_data_t *pd) {
Lev Walkinb5450702017-10-04 02:52:57 -0700234 const asn_NativeReal_specifics_t *specs =
235 (const asn_NativeReal_specifics_t *)td->specifics;
236 size_t float_size = specs ? specs->float_size : sizeof(double);
237 void *native = (void *)*sptr;
238 double d;
Lev Walkin725883b2006-10-09 12:07:58 +0000239 asn_dec_rval_t rval;
240 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
246 /*
247 * If the structure is not there, allocate it.
248 */
Lev Walkinb5450702017-10-04 02:52:57 -0700249 if(!native) {
250 native = (*sptr = CALLOC(1, float_size));
251 if(!native) ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000252 }
253
254 memset(&tmp, 0, sizeof(tmp));
Lev Walkinb5450702017-10-04 02:52:57 -0700255 rval = OCTET_STRING_decode_uper(opt_codec_ctx, &asn_DEF_REAL,
256 NULL, &ptmp, pd);
257 if(rval.code != RC_OK) {
Lev Walkin725883b2006-10-09 12:07:58 +0000258 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
259 return rval;
260 }
261
Lev Walkinb5450702017-10-04 02:52:57 -0700262 ret = asn_REAL2double(&tmp, &d);
Lev Walkin725883b2006-10-09 12:07:58 +0000263 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700264 if(ret) ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000265
Lev Walkinb5450702017-10-04 02:52:57 -0700266 if(float_size == sizeof(float)) {
267 *(float *)native = d;
268 } else {
269 *(double *)native = d;
270 }
271
Lev Walkin725883b2006-10-09 12:07:58 +0000272 return rval;
273}
274
275/*
276 * Encode the NativeReal using the OCTET STRING PER encoder.
277 */
278asn_enc_rval_t
279NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700280 const asn_per_constraints_t *constraints, void *sptr,
281 asn_per_outp_t *po) {
Lev Walkinb5450702017-10-04 02:52:57 -0700282 double d = NativeReal__get_double(td, sptr);
Lev Walkin725883b2006-10-09 12:07:58 +0000283 asn_enc_rval_t erval;
284 REAL_t tmp;
285
286 (void)constraints;
287
288 /* Prepare a temporary clean structure */
289 memset(&tmp, 0, sizeof(tmp));
290
Lev Walkinb5450702017-10-04 02:52:57 -0700291 if(asn_double2REAL(&tmp, d))
Lev Walkin7c1dc052016-03-14 03:08:15 -0700292 ASN__ENCODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000293
294 /* Encode a DER REAL */
Lev Walkinb5450702017-10-04 02:52:57 -0700295 erval = OCTET_STRING_encode_uper(&asn_DEF_REAL, NULL, &tmp, po);
296 if(erval.encoded == -1)
Lev Walkin725883b2006-10-09 12:07:58 +0000297 erval.structure_ptr = sptr;
298
299 /* Free possibly allocated members of the temporary structure */
300 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
301
302 return erval;
303}
Lev Walkin8471cec2004-10-21 14:02:19 +0000304
Lev Walkin41d972b2017-08-23 23:30:59 -0700305#endif /* ASN_DISABLE_PER_SUPPORT */
306
Lev Walkinab1d1e12017-10-03 18:43:12 -0700307#ifndef ASN_DISABLE_OER_SUPPORT
308
309/*
310 * Encode as Canonical OER.
311 */
312asn_enc_rval_t
313NativeReal_encode_oer(asn_TYPE_descriptor_t *td,
314 const asn_oer_constraints_t *constraints, void *sptr,
315 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinb5450702017-10-04 02:52:57 -0700316 double d = NativeReal__get_double(td, sptr);
Lev Walkinab1d1e12017-10-03 18:43:12 -0700317 asn_enc_rval_t er = { 0, 0, 0 };
318 ssize_t len_len;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700319 REAL_t tmp;
320
321 /* Prepare a temporary clean structure */
322 memset(&tmp, 0, sizeof(tmp));
323
324 (void)td;
325 (void)constraints; /* Constraints are unused in OER */
326
Lev Walkinb5450702017-10-04 02:52:57 -0700327 if(asn_double2REAL(&tmp, d)) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700328 ASN__ENCODE_FAILED;
329 }
330
331 /* Encode a fake REAL */
332 len_len = oer_serialize_length(tmp.size, cb, app_key);
333 if(len_len < 0 || cb(tmp.buf, tmp.size, app_key) < 0) {
334 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
335 ASN__ENCODE_FAILED;
336 } else {
337 er.encoded = len_len + tmp.size;
338 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
339 ASN__ENCODED_OK(er);
340 }
341}
342
343asn_dec_rval_t
344NativeReal_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
345 asn_TYPE_descriptor_t *td,
346 const asn_oer_constraints_t *constraints, void **sptr,
347 const void *ptr, size_t size) {
Lev Walkinb5450702017-10-04 02:52:57 -0700348 const asn_NativeReal_specifics_t *specs =
349 (const asn_NativeReal_specifics_t *)td->specifics;
350 size_t float_size = specs ? specs->float_size : sizeof(double);
Lev Walkinab1d1e12017-10-03 18:43:12 -0700351 asn_dec_rval_t ok = {RC_OK, 0};
Lev Walkinab1d1e12017-10-03 18:43:12 -0700352 double d;
Lev Walkinb5450702017-10-04 02:52:57 -0700353 void *native;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700354 ssize_t len_len;
355 size_t real_body_len;
356
357 (void)opt_codec_ctx;
358 (void)td;
359 (void)constraints; /* Constraints are unused in OER */
360
361 len_len = oer_fetch_length(ptr, size, &real_body_len);
362 if(len_len < 0) ASN__DECODE_FAILED;
363 if(len_len == 0) ASN__DECODE_STARVED;
364
365 ptr = (const char *)ptr + len_len;
366 size -= len_len;
367
368 if(real_body_len > size) ASN__DECODE_STARVED;
369
370 {
371 uint8_t scratch[24]; /* Longer than %.16f in decimal */
372 REAL_t tmp;
373 int ret;
374
375 if(real_body_len < sizeof(scratch)) {
376 tmp.buf = scratch;
377 tmp.size = real_body_len;
378 } else {
379 /* This rarely happens: impractically long value */
380 tmp.buf = CALLOC(1, real_body_len + 1);
381 tmp.size = real_body_len;
382 if(!tmp.buf) {
383 ASN__DECODE_FAILED;
384 }
385 }
386
387 memcpy(tmp.buf, ptr, real_body_len);
388 tmp.buf[real_body_len] = '\0';
389
390 ret = asn_REAL2double(&tmp, &d);
391 if(tmp.buf != scratch) FREEMEM(tmp.buf);
392 if(ret) {
393 ASN_DEBUG("REAL decoded in %zu bytes, but can't convert t double",
394 real_body_len);
395 ASN__DECODE_FAILED;
396 }
397 }
398
Lev Walkinb5450702017-10-04 02:52:57 -0700399 if(!(native = *sptr)) {
400 native = (*sptr = CALLOC(1, float_size));
401 if(!native) ASN__DECODE_FAILED;
Lev Walkinab1d1e12017-10-03 18:43:12 -0700402 }
403
Lev Walkinb5450702017-10-04 02:52:57 -0700404 if(float_size == sizeof(float)) {
405 *(float *)native = d;
406 } else {
407 *(double *)native = d;
408 }
Lev Walkinab1d1e12017-10-03 18:43:12 -0700409 ok.consumed = len_len + real_body_len;
410 return ok;
411}
412
413#endif /* ASN_DISABLE_OER_SUPPORT */
414
Lev Walkin8471cec2004-10-21 14:02:19 +0000415/*
416 * Decode the chunk of XML text encoding REAL.
417 */
418asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700419NativeReal_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin8471cec2004-10-21 14:02:19 +0000420 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000421 const void *buf_ptr, size_t size) {
Lev Walkinb5450702017-10-04 02:52:57 -0700422 const asn_NativeReal_specifics_t *specs =
423 (const asn_NativeReal_specifics_t *)td->specifics;
424 size_t float_size = specs ? specs->float_size : sizeof(double);
Lev Walkin8471cec2004-10-21 14:02:19 +0000425 asn_dec_rval_t rval;
Lev Walkinb5450702017-10-04 02:52:57 -0700426 REAL_t st = { 0, 0 };
427 REAL_t *stp = &st;
428 void *native = *sptr;
Lev Walkin8471cec2004-10-21 14:02:19 +0000429
Lev Walkinb5450702017-10-04 02:52:57 -0700430 if(!native) {
431 native = (*sptr = CALLOC(1, float_size));
432 if(!native) ASN__DECODE_FAILED;
433 }
Lev Walkin8471cec2004-10-21 14:02:19 +0000434
Lev Walkinb5450702017-10-04 02:52:57 -0700435 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)&stp, opt_mname,
Lev Walkin8471cec2004-10-21 14:02:19 +0000436 buf_ptr, size);
437 if(rval.code == RC_OK) {
Lev Walkinb5450702017-10-04 02:52:57 -0700438 double d;
439 if(asn_REAL2double(&st, &d)) {
Lev Walkin8471cec2004-10-21 14:02:19 +0000440 rval.code = RC_FAIL;
441 rval.consumed = 0;
Lev Walkinb5450702017-10-04 02:52:57 -0700442 } else {
443 if(float_size == sizeof(float)) {
444 *(float *)native = d;
445 } else {
446 *(double *)native = d;
447 }
448 }
Lev Walkin8471cec2004-10-21 14:02:19 +0000449 } else {
450 rval.consumed = 0;
451 }
Lev Walkinb5450702017-10-04 02:52:57 -0700452 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &st);
Lev Walkin8471cec2004-10-21 14:02:19 +0000453 return rval;
454}
455
Lev Walkina9cc46e2004-09-22 16:06:28 +0000456asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000457NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000458 int ilevel, enum xer_encoder_flags_e flags,
459 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinb5450702017-10-04 02:52:57 -0700460 double d = NativeReal__get_double(td, sptr);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000461 asn_enc_rval_t er;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000462
463 (void)ilevel;
464
Lev Walkinb5450702017-10-04 02:52:57 -0700465 er.encoded = REAL__dump(d, flags & XER_F_CANONICAL, cb, app_key);
466 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000467
Lev Walkin7c1dc052016-03-14 03:08:15 -0700468 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000469}
470
Lev Walkin41ba1f22004-09-14 12:46:35 +0000471/*
472 * REAL specific human-readable output.
473 */
474int
Lev Walkin5e033762004-09-29 13:26:15 +0000475NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000476 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000477
Lev Walkin41ba1f22004-09-14 12:46:35 +0000478 (void)ilevel; /* Unused argument */
479
Lev Walkinb5450702017-10-04 02:52:57 -0700480 if(sptr) {
481 double d = NativeReal__get_double(td, sptr);
482 return (REAL__dump(d, 0, cb, app_key) < 0) ? -1 : 0;
483 } else {
484 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
485 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000486}
487
Lev Walkincd2f48e2017-08-10 02:14:59 -0700488int
489NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
490 const void *bptr) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700491
Lev Walkinb5450702017-10-04 02:52:57 -0700492 if(aptr && bptr) {
493 double a = NativeReal__get_double(td, aptr);
494 double b = NativeReal__get_double(td, bptr);
495
Lev Walkincd2f48e2017-08-10 02:14:59 -0700496 /* NaN sorted above everything else */
Lev Walkinb5450702017-10-04 02:52:57 -0700497 if(asn_isnan(a)) {
498 if(asn_isnan(b)) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700499 return 0;
500 } else {
501 return -1;
502 }
Lev Walkinb5450702017-10-04 02:52:57 -0700503 } else if(asn_isnan(b)) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700504 return 1;
505 }
506 /* Value comparison. */
Lev Walkinb5450702017-10-04 02:52:57 -0700507 if(a < b) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700508 return -1;
Lev Walkinb5450702017-10-04 02:52:57 -0700509 } else if(a > b) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700510 return 1;
511 } else {
512 return 0;
513 }
Lev Walkinb5450702017-10-04 02:52:57 -0700514 } else if(!aptr) {
Lev Walkincd2f48e2017-08-10 02:14:59 -0700515 return -1;
516 } else {
517 return 1;
518 }
519}
520
Lev Walkin41ba1f22004-09-14 12:46:35 +0000521void
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700522NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr,
523 enum asn_struct_free_method method) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700524 if(!td || !ptr)
Lev Walkin41ba1f22004-09-14 12:46:35 +0000525 return;
526
527 ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700528 td->name, method, ptr);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000529
Lev Walkin8d99d7b2017-08-25 01:06:00 -0700530 switch(method) {
531 case ASFM_FREE_EVERYTHING:
532 FREEMEM(ptr);
533 break;
534 case ASFM_FREE_UNDERLYING:
535 break;
536 case ASFM_FREE_UNDERLYING_AND_RESET:
537 memset(ptr, 0, sizeof(double));
538 break;
539 }
Lev Walkin41ba1f22004-09-14 12:46:35 +0000540}
541
Lev Walkina5972be2017-09-29 23:15:58 -0700542
543asn_random_fill_result_t
544NativeReal_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
545 const asn_encoding_constraints_t *constraints,
546 size_t max_length) {
Lev Walkinab1d1e12017-10-03 18:43:12 -0700547 asn_random_fill_result_t result_ok = {ARFILL_OK, sizeof(double)};
Lev Walkina5972be2017-09-29 23:15:58 -0700548 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
549 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
Lev Walkinab1d1e12017-10-03 18:43:12 -0700550 static const double values[] = {
551 0, -0.0, -1, 1, -M_E, M_E, -3.14, 3.14, -M_PI, M_PI, -255, 255,
552 /* 2^51 */
553 -2251799813685248.0, 2251799813685248.0,
554 /* 2^52 */
555 -4503599627370496.0, 4503599627370496.0,
556 /* 2^100 */
557 -1267650600228229401496703205376.0, 1267650600228229401496703205376.0,
Lev Walkin4ca41492017-10-03 20:29:54 -0700558#if __STDC_VERSION__ >= 199901L
Jon Ringle35c3f0d2017-10-04 21:54:39 -0400559 -FLT_MAX, FLT_MAX,
Lev Walkin4ca41492017-10-03 20:29:54 -0700560#endif
561 INFINITY, -INFINITY, NAN};
Lev Walkina5972be2017-09-29 23:15:58 -0700562 double *st;
563 double d;
564
565 (void)td;
566 (void)constraints;
567
568 if(max_length == 0) return result_skipped;
569
570 d = values[asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1)];
571
572 if(*sptr) {
573 st = *sptr;
574 } else {
575 st = (double *)(*sptr = CALLOC(1, sizeof(double)));
576 if(!st) {
577 return result_failed;
578 }
579 }
580
581 *st = d;
582
Lev Walkina5972be2017-09-29 23:15:58 -0700583 return result_ok;
584}