blob: f305d8bd4d0e408a64a6610b2761f70d7264b0cb [file] [log] [blame]
Lev Walkin41ba1f22004-09-14 12:46:35 +00001/*-
Lev Walkin725883b2006-10-09 12:07:58 +00002 * Copyright (c) 2004, 2006 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>
Lev Walkin41ba1f22004-09-14 12:46:35 +000017
18/*
19 * NativeReal basic type description.
20 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070021static const ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
Lev Walkin41ba1f22004-09-14 12:46:35 +000022 (ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
23};
Lev Walkin5e033762004-09-29 13:26:15 +000024asn_TYPE_descriptor_t asn_DEF_NativeReal = {
Lev Walkin41ba1f22004-09-14 12:46:35 +000025 "REAL", /* The ASN.1 type is still REAL */
Lev Walkindc06f6b2004-10-20 15:50:55 +000026 "REAL",
Lev Walkina9cc46e2004-09-22 16:06:28 +000027 NativeReal_free,
28 NativeReal_print,
Lev Walkincd2f48e2017-08-10 02:14:59 -070029 NativeReal_compare,
Lev Walkin41ba1f22004-09-14 12:46:35 +000030 asn_generic_no_constraint,
31 NativeReal_decode_ber,
32 NativeReal_encode_der,
Lev Walkin8471cec2004-10-21 14:02:19 +000033 NativeReal_decode_xer,
Lev Walkina9cc46e2004-09-22 16:06:28 +000034 NativeReal_encode_xer,
Lev Walkincc159472017-07-06 08:26:36 -070035#ifdef ASN_DISABLE_OER_SUPPORT
36 0,
37 0,
38#else
39 0,
40 0,
41#endif /* ASN_DISABLE_OER_SUPPORT */
Lev Walkinb33425f2017-07-14 14:59:52 +040042#ifdef ASN_DISABLE_PER_SUPPORT
43 0,
44 0,
45#else
46 NativeReal_decode_uper,
47 NativeReal_encode_uper,
48#endif /* ASN_DISABLE_PER_SUPPORT */
Lev Walkin41ba1f22004-09-14 12:46:35 +000049 0, /* Use generic outmost tag fetcher */
Lev Walkin5e033762004-09-29 13:26:15 +000050 asn_DEF_NativeReal_tags,
51 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
52 asn_DEF_NativeReal_tags, /* Same as above */
53 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
Lev Walkin76780762017-07-07 10:07:30 -070054 0, /* No OER visible constraints */
Lev Walkin59b176e2005-11-26 11:25:14 +000055 0, /* No PER visible constraints */
Lev Walkin41ba1f22004-09-14 12:46:35 +000056 0, 0, /* No members */
57 0 /* No specifics */
58};
59
60/*
61 * Decode REAL type.
62 */
Lev Walkindc06f6b2004-10-20 15:50:55 +000063asn_dec_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +000064NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
65 asn_TYPE_descriptor_t *td,
Lev Walkin8c3b8542005-03-10 18:52:02 +000066 void **dbl_ptr, const void *buf_ptr, size_t size, int tag_mode) {
Lev Walkin41ba1f22004-09-14 12:46:35 +000067 double *Dbl = (double *)*dbl_ptr;
Lev Walkindc06f6b2004-10-20 15:50:55 +000068 asn_dec_rval_t rval;
Lev Walkin41ba1f22004-09-14 12:46:35 +000069 ber_tlv_len_t length;
70
71 /*
72 * If the structure is not there, allocate it.
73 */
74 if(Dbl == NULL) {
Lev Walkinc17d90f2005-01-17 14:32:45 +000075 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
76 Dbl = (double *)*dbl_ptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +000077 if(Dbl == NULL) {
78 rval.code = RC_FAIL;
79 rval.consumed = 0;
80 return rval;
81 }
82 }
83
84 ASN_DEBUG("Decoding %s as REAL (tm=%d)",
85 td->name, tag_mode);
86
87 /*
88 * Check tags.
89 */
Lev Walkin5e033762004-09-29 13:26:15 +000090 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
91 tag_mode, 0, &length, 0);
Lev Walkin41ba1f22004-09-14 12:46:35 +000092 if(rval.code != RC_OK)
93 return rval;
94
95 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
96
97 /*
98 * Make sure we have this length.
99 */
Lev Walkin8c3b8542005-03-10 18:52:02 +0000100 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000101 size -= rval.consumed;
102 if(length > (ber_tlv_len_t)size) {
103 rval.code = RC_WMORE;
104 rval.consumed = 0;
105 return rval;
106 }
107
108 /*
109 * ASN.1 encoded REAL: buf_ptr, length
110 * Fill the Dbl, at the same time checking for overflow.
111 * If overflow occured, return with RC_FAIL.
112 */
113 {
114 REAL_t tmp;
Lev Walkin7e033b52005-07-02 08:19:17 +0000115 union {
116 const void *constbuf;
117 void *nonconstbuf;
118 } unconst_buf;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000119 double d;
Lev Walkin7e033b52005-07-02 08:19:17 +0000120
121 unconst_buf.constbuf = buf_ptr;
122 tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000123 tmp.size = length;
124
Lev Walkin0959ffb2011-06-25 15:48:52 -0700125 if(length < (ber_tlv_len_t)size) {
126 int ret;
127 uint8_t saved_byte = tmp.buf[tmp.size];
128 tmp.buf[tmp.size] = '\0';
129 ret = asn_REAL2double(&tmp, &d);
130 tmp.buf[tmp.size] = saved_byte;
131 if(ret) {
132 rval.code = RC_FAIL;
133 rval.consumed = 0;
134 return rval;
135 }
136 } else if(length < 48 /* Enough for longish %f value. */) {
137 tmp.buf = alloca(length + 1);
138 tmp.size = length;
139 memcpy(tmp.buf, buf_ptr, length);
140 tmp.buf[tmp.size] = '\0';
141 if(asn_REAL2double(&tmp, &d)) {
142 rval.code = RC_FAIL;
143 rval.consumed = 0;
144 return rval;
145 }
146 } else {
147 /* This should probably never happen: impractically long value */
148 tmp.buf = CALLOC(1, length + 1);
149 tmp.size = length;
150 if(tmp.buf) memcpy(tmp.buf, buf_ptr, length);
151 if(!tmp.buf || asn_REAL2double(&tmp, &d)) {
152 FREEMEM(tmp.buf);
153 rval.code = RC_FAIL;
154 rval.consumed = 0;
155 return rval;
156 }
157 FREEMEM(tmp.buf);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000158 }
159
160 *Dbl = d;
161 }
162
163 rval.code = RC_OK;
164 rval.consumed += length;
165
Lev Walkin1e3ccbb2004-10-26 10:56:10 +0000166 ASN_DEBUG("Took %ld/%ld bytes to encode %s (%f)",
Lev Walkin41ba1f22004-09-14 12:46:35 +0000167 (long)rval.consumed, (long)length, td->name, *Dbl);
168
169 return rval;
170}
171
172/*
173 * Encode the NativeReal using the standard REAL type DER encoder.
174 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000175asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000176NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000177 int tag_mode, ber_tlv_tag_t tag,
178 asn_app_consume_bytes_f *cb, void *app_key) {
179 double Dbl = *(const double *)ptr;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000180 asn_enc_rval_t erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000181 REAL_t tmp;
182
Lev Walkina8bbbda2005-02-06 04:29:03 +0000183 /* Prepare a temporary clean structure */
184 memset(&tmp, 0, sizeof(tmp));
185
Lev Walkin5e033762004-09-29 13:26:15 +0000186 if(asn_double2REAL(&tmp, Dbl)) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000187 erval.encoded = -1;
188 erval.failed_type = td;
189 erval.structure_ptr = ptr;
190 return erval;
191 }
192
Lev Walkin8e8078a2004-09-26 13:10:40 +0000193 /* Encode a fake REAL */
194 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000195 if(erval.encoded == -1) {
196 assert(erval.structure_ptr == &tmp);
197 erval.structure_ptr = ptr;
198 }
Lev Walkina8bbbda2005-02-06 04:29:03 +0000199
200 /* Free possibly allocated members of the temporary structure */
Lev Walkinadcb5862006-03-17 02:11:12 +0000201 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkina8bbbda2005-02-06 04:29:03 +0000202
Lev Walkin41ba1f22004-09-14 12:46:35 +0000203 return erval;
204}
205
Lev Walkin725883b2006-10-09 12:07:58 +0000206/*
207 * Decode REAL type using PER.
208 */
209asn_dec_rval_t
210NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin494fb702017-08-07 20:07:00 -0700211 asn_TYPE_descriptor_t *td,
212 const asn_per_constraints_t *constraints, void **dbl_ptr,
213 asn_per_data_t *pd) {
214 double *Dbl = (double *)*dbl_ptr;
Lev Walkin725883b2006-10-09 12:07:58 +0000215 asn_dec_rval_t rval;
216 REAL_t tmp;
217 void *ptmp = &tmp;
218 int ret;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000219
Lev Walkin725883b2006-10-09 12:07:58 +0000220 (void)constraints;
221
222 /*
223 * If the structure is not there, allocate it.
224 */
225 if(Dbl == NULL) {
226 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
227 Dbl = (double *)*dbl_ptr;
228 if(Dbl == NULL)
Lev Walkin7c1dc052016-03-14 03:08:15 -0700229 ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000230 }
231
232 memset(&tmp, 0, sizeof(tmp));
233 rval = OCTET_STRING_decode_uper(opt_codec_ctx, td, NULL,
234 &ptmp, pd);
235 if(rval.code != RC_OK) {
236 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
237 return rval;
238 }
239
240 ret = asn_REAL2double(&tmp, Dbl);
241 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700242 if(ret) ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000243
244 return rval;
245}
246
247/*
248 * Encode the NativeReal using the OCTET STRING PER encoder.
249 */
250asn_enc_rval_t
251NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700252 const asn_per_constraints_t *constraints, void *sptr,
253 asn_per_outp_t *po) {
254 double Dbl = *(const double *)sptr;
Lev Walkin725883b2006-10-09 12:07:58 +0000255 asn_enc_rval_t erval;
256 REAL_t tmp;
257
258 (void)constraints;
259
260 /* Prepare a temporary clean structure */
261 memset(&tmp, 0, sizeof(tmp));
262
263 if(asn_double2REAL(&tmp, Dbl))
Lev Walkin7c1dc052016-03-14 03:08:15 -0700264 ASN__ENCODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000265
266 /* Encode a DER REAL */
267 erval = OCTET_STRING_encode_uper(td, NULL, &tmp, po);
268 if(erval.encoded == -1)
269 erval.structure_ptr = sptr;
270
271 /* Free possibly allocated members of the temporary structure */
272 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
273
274 return erval;
275}
Lev Walkin8471cec2004-10-21 14:02:19 +0000276
277/*
278 * Decode the chunk of XML text encoding REAL.
279 */
280asn_dec_rval_t
281NativeReal_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
282 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000283 const void *buf_ptr, size_t size) {
Lev Walkin8471cec2004-10-21 14:02:19 +0000284 asn_dec_rval_t rval;
285 REAL_t *st = 0;
Lev Walkin1eded352006-07-13 11:19:01 +0000286 REAL_t **stp = &st;
Lev Walkin8471cec2004-10-21 14:02:19 +0000287 double *Dbl = (double *)*sptr;
288
289 if(!Dbl) {
Lev Walkinc17d90f2005-01-17 14:32:45 +0000290 *sptr = CALLOC(1, sizeof(double));
291 Dbl = (double *)*sptr;
Lev Walkin8471cec2004-10-21 14:02:19 +0000292 if(!Dbl) {
293 rval.code = RC_FAIL;
294 rval.consumed = 0;
295 return rval;
296 }
297 }
298
Lev Walkin1eded352006-07-13 11:19:01 +0000299 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname,
Lev Walkin8471cec2004-10-21 14:02:19 +0000300 buf_ptr, size);
301 if(rval.code == RC_OK) {
302 if(asn_REAL2double(st, Dbl)) {
303 rval.code = RC_FAIL;
304 rval.consumed = 0;
305 }
306 } else {
307 rval.consumed = 0;
308 }
Lev Walkinadcb5862006-03-17 02:11:12 +0000309 ASN_STRUCT_FREE(asn_DEF_REAL, st);
Lev Walkin8471cec2004-10-21 14:02:19 +0000310 return rval;
311}
312
Lev Walkina9cc46e2004-09-22 16:06:28 +0000313asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000314NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000315 int ilevel, enum xer_encoder_flags_e flags,
316 asn_app_consume_bytes_f *cb, void *app_key) {
317 const double *Dbl = (const double *)sptr;
318 asn_enc_rval_t er;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000319
320 (void)ilevel;
321
Lev Walkin7c1dc052016-03-14 03:08:15 -0700322 if(!Dbl) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000323
Lev Walkin8e8078a2004-09-26 13:10:40 +0000324 er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700325 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000326
Lev Walkin7c1dc052016-03-14 03:08:15 -0700327 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000328}
329
Lev Walkin41ba1f22004-09-14 12:46:35 +0000330/*
331 * REAL specific human-readable output.
332 */
333int
Lev Walkin5e033762004-09-29 13:26:15 +0000334NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000335 asn_app_consume_bytes_f *cb, void *app_key) {
336 const double *Dbl = (const double *)sptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000337
338 (void)td; /* Unused argument */
339 (void)ilevel; /* Unused argument */
340
Lev Walkin8e8078a2004-09-26 13:10:40 +0000341 if(!Dbl) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000342
343 return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000344}
345
Lev Walkincd2f48e2017-08-10 02:14:59 -0700346int
347NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
348 const void *bptr) {
349 const double *a = aptr;
350 const double *b = bptr;
351 (void)td;
352
353 if(a && b) {
354 /* NaN sorted above everything else */
355 if(isnan(*a)) {
356 if(isnan(*b)) {
357 return 0;
358 } else {
359 return -1;
360 }
361 } else if(isnan(*b)) {
362 return 1;
363 }
364 /* Value comparison. */
365 if(*a < *b) {
366 return -1;
367 } else if(*a > *b) {
368 return 1;
369 } else {
370 return 0;
371 }
372 } else if(!a) {
373 return -1;
374 } else {
375 return 1;
376 }
377}
378
Lev Walkin41ba1f22004-09-14 12:46:35 +0000379void
Lev Walkinf6853ce2017-08-11 00:50:27 -0700380NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
381 if(!td || !ptr)
Lev Walkin41ba1f22004-09-14 12:46:35 +0000382 return;
383
384 ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
385 td->name, contents_only, ptr);
386
387 if(!contents_only) {
388 FREEMEM(ptr);
389 }
390}
391