blob: ad6f28c9aa3b3461b97b6ff243b51d849f91f708 [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 Walkin41ba1f22004-09-14 12:46:35 +000016
17/*
18 * NativeReal basic type description.
19 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070020static const ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
Lev Walkin41ba1f22004-09-14 12:46:35 +000021 (ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
22};
Lev Walkin5e033762004-09-29 13:26:15 +000023asn_TYPE_descriptor_t asn_DEF_NativeReal = {
Lev Walkin41ba1f22004-09-14 12:46:35 +000024 "REAL", /* The ASN.1 type is still REAL */
Lev Walkindc06f6b2004-10-20 15:50:55 +000025 "REAL",
Lev Walkina9cc46e2004-09-22 16:06:28 +000026 NativeReal_free,
27 NativeReal_print,
Lev Walkin41ba1f22004-09-14 12:46:35 +000028 asn_generic_no_constraint,
29 NativeReal_decode_ber,
30 NativeReal_encode_der,
Lev Walkin8471cec2004-10-21 14:02:19 +000031 NativeReal_decode_xer,
Lev Walkina9cc46e2004-09-22 16:06:28 +000032 NativeReal_encode_xer,
Lev Walkin725883b2006-10-09 12:07:58 +000033 NativeReal_decode_uper,
34 NativeReal_encode_uper,
Lev Walkin41ba1f22004-09-14 12:46:35 +000035 0, /* Use generic outmost tag fetcher */
Lev Walkin5e033762004-09-29 13:26:15 +000036 asn_DEF_NativeReal_tags,
37 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
38 asn_DEF_NativeReal_tags, /* Same as above */
39 sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
Lev Walkin59b176e2005-11-26 11:25:14 +000040 0, /* No PER visible constraints */
Lev Walkin41ba1f22004-09-14 12:46:35 +000041 0, 0, /* No members */
42 0 /* No specifics */
43};
44
45/*
46 * Decode REAL type.
47 */
Lev Walkindc06f6b2004-10-20 15:50:55 +000048asn_dec_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +000049NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
50 asn_TYPE_descriptor_t *td,
Lev Walkin8c3b8542005-03-10 18:52:02 +000051 void **dbl_ptr, const void *buf_ptr, size_t size, int tag_mode) {
Lev Walkin41ba1f22004-09-14 12:46:35 +000052 double *Dbl = (double *)*dbl_ptr;
Lev Walkindc06f6b2004-10-20 15:50:55 +000053 asn_dec_rval_t rval;
Lev Walkin41ba1f22004-09-14 12:46:35 +000054 ber_tlv_len_t length;
55
56 /*
57 * If the structure is not there, allocate it.
58 */
59 if(Dbl == NULL) {
Lev Walkinc17d90f2005-01-17 14:32:45 +000060 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
61 Dbl = (double *)*dbl_ptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +000062 if(Dbl == NULL) {
63 rval.code = RC_FAIL;
64 rval.consumed = 0;
65 return rval;
66 }
67 }
68
69 ASN_DEBUG("Decoding %s as REAL (tm=%d)",
70 td->name, tag_mode);
71
72 /*
73 * Check tags.
74 */
Lev Walkin5e033762004-09-29 13:26:15 +000075 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
76 tag_mode, 0, &length, 0);
Lev Walkin41ba1f22004-09-14 12:46:35 +000077 if(rval.code != RC_OK)
78 return rval;
79
80 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
81
82 /*
83 * Make sure we have this length.
84 */
Lev Walkin8c3b8542005-03-10 18:52:02 +000085 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
Lev Walkin41ba1f22004-09-14 12:46:35 +000086 size -= rval.consumed;
87 if(length > (ber_tlv_len_t)size) {
88 rval.code = RC_WMORE;
89 rval.consumed = 0;
90 return rval;
91 }
92
93 /*
94 * ASN.1 encoded REAL: buf_ptr, length
95 * Fill the Dbl, at the same time checking for overflow.
96 * If overflow occured, return with RC_FAIL.
97 */
98 {
99 REAL_t tmp;
Lev Walkin7e033b52005-07-02 08:19:17 +0000100 union {
101 const void *constbuf;
102 void *nonconstbuf;
103 } unconst_buf;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000104 double d;
Lev Walkin7e033b52005-07-02 08:19:17 +0000105
106 unconst_buf.constbuf = buf_ptr;
107 tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000108 tmp.size = length;
109
Lev Walkin0959ffb2011-06-25 15:48:52 -0700110 if(length < (ber_tlv_len_t)size) {
111 int ret;
112 uint8_t saved_byte = tmp.buf[tmp.size];
113 tmp.buf[tmp.size] = '\0';
114 ret = asn_REAL2double(&tmp, &d);
115 tmp.buf[tmp.size] = saved_byte;
116 if(ret) {
117 rval.code = RC_FAIL;
118 rval.consumed = 0;
119 return rval;
120 }
121 } else if(length < 48 /* Enough for longish %f value. */) {
122 tmp.buf = alloca(length + 1);
123 tmp.size = length;
124 memcpy(tmp.buf, buf_ptr, length);
125 tmp.buf[tmp.size] = '\0';
126 if(asn_REAL2double(&tmp, &d)) {
127 rval.code = RC_FAIL;
128 rval.consumed = 0;
129 return rval;
130 }
131 } else {
132 /* This should probably never happen: impractically long value */
133 tmp.buf = CALLOC(1, length + 1);
134 tmp.size = length;
135 if(tmp.buf) memcpy(tmp.buf, buf_ptr, length);
136 if(!tmp.buf || asn_REAL2double(&tmp, &d)) {
137 FREEMEM(tmp.buf);
138 rval.code = RC_FAIL;
139 rval.consumed = 0;
140 return rval;
141 }
142 FREEMEM(tmp.buf);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000143 }
144
145 *Dbl = d;
146 }
147
148 rval.code = RC_OK;
149 rval.consumed += length;
150
Lev Walkin1e3ccbb2004-10-26 10:56:10 +0000151 ASN_DEBUG("Took %ld/%ld bytes to encode %s (%f)",
Lev Walkin41ba1f22004-09-14 12:46:35 +0000152 (long)rval.consumed, (long)length, td->name, *Dbl);
153
154 return rval;
155}
156
157/*
158 * Encode the NativeReal using the standard REAL type DER encoder.
159 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000160asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000161NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000162 int tag_mode, ber_tlv_tag_t tag,
163 asn_app_consume_bytes_f *cb, void *app_key) {
164 double Dbl = *(const double *)ptr;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000165 asn_enc_rval_t erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000166 REAL_t tmp;
167
Lev Walkina8bbbda2005-02-06 04:29:03 +0000168 /* Prepare a temporary clean structure */
169 memset(&tmp, 0, sizeof(tmp));
170
Lev Walkin5e033762004-09-29 13:26:15 +0000171 if(asn_double2REAL(&tmp, Dbl)) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000172 erval.encoded = -1;
173 erval.failed_type = td;
174 erval.structure_ptr = ptr;
175 return erval;
176 }
177
Lev Walkin8e8078a2004-09-26 13:10:40 +0000178 /* Encode a fake REAL */
179 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000180 if(erval.encoded == -1) {
181 assert(erval.structure_ptr == &tmp);
182 erval.structure_ptr = ptr;
183 }
Lev Walkina8bbbda2005-02-06 04:29:03 +0000184
185 /* Free possibly allocated members of the temporary structure */
Lev Walkinadcb5862006-03-17 02:11:12 +0000186 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkina8bbbda2005-02-06 04:29:03 +0000187
Lev Walkin41ba1f22004-09-14 12:46:35 +0000188 return erval;
189}
190
Lev Walkin725883b2006-10-09 12:07:58 +0000191/*
192 * Decode REAL type using PER.
193 */
194asn_dec_rval_t
195NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
196 asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
197 void **dbl_ptr, asn_per_data_t *pd) {
198 double *Dbl = (double *)*dbl_ptr;
199 asn_dec_rval_t rval;
200 REAL_t tmp;
201 void *ptmp = &tmp;
202 int ret;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000203
Lev Walkin725883b2006-10-09 12:07:58 +0000204 (void)constraints;
205
206 /*
207 * If the structure is not there, allocate it.
208 */
209 if(Dbl == NULL) {
210 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
211 Dbl = (double *)*dbl_ptr;
212 if(Dbl == NULL)
Lev Walkin7c1dc052016-03-14 03:08:15 -0700213 ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000214 }
215
216 memset(&tmp, 0, sizeof(tmp));
217 rval = OCTET_STRING_decode_uper(opt_codec_ctx, td, NULL,
218 &ptmp, pd);
219 if(rval.code != RC_OK) {
220 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
221 return rval;
222 }
223
224 ret = asn_REAL2double(&tmp, Dbl);
225 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700226 if(ret) ASN__DECODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000227
228 return rval;
229}
230
231/*
232 * Encode the NativeReal using the OCTET STRING PER encoder.
233 */
234asn_enc_rval_t
235NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
236 asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
237 double Dbl = *(const double *)sptr;
238 asn_enc_rval_t erval;
239 REAL_t tmp;
240
241 (void)constraints;
242
243 /* Prepare a temporary clean structure */
244 memset(&tmp, 0, sizeof(tmp));
245
246 if(asn_double2REAL(&tmp, Dbl))
Lev Walkin7c1dc052016-03-14 03:08:15 -0700247 ASN__ENCODE_FAILED;
Lev Walkin725883b2006-10-09 12:07:58 +0000248
249 /* Encode a DER REAL */
250 erval = OCTET_STRING_encode_uper(td, NULL, &tmp, po);
251 if(erval.encoded == -1)
252 erval.structure_ptr = sptr;
253
254 /* Free possibly allocated members of the temporary structure */
255 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
256
257 return erval;
258}
Lev Walkin8471cec2004-10-21 14:02:19 +0000259
260/*
261 * Decode the chunk of XML text encoding REAL.
262 */
263asn_dec_rval_t
264NativeReal_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
265 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000266 const void *buf_ptr, size_t size) {
Lev Walkin8471cec2004-10-21 14:02:19 +0000267 asn_dec_rval_t rval;
268 REAL_t *st = 0;
Lev Walkin1eded352006-07-13 11:19:01 +0000269 REAL_t **stp = &st;
Lev Walkin8471cec2004-10-21 14:02:19 +0000270 double *Dbl = (double *)*sptr;
271
272 if(!Dbl) {
Lev Walkinc17d90f2005-01-17 14:32:45 +0000273 *sptr = CALLOC(1, sizeof(double));
274 Dbl = (double *)*sptr;
Lev Walkin8471cec2004-10-21 14:02:19 +0000275 if(!Dbl) {
276 rval.code = RC_FAIL;
277 rval.consumed = 0;
278 return rval;
279 }
280 }
281
Lev Walkin1eded352006-07-13 11:19:01 +0000282 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname,
Lev Walkin8471cec2004-10-21 14:02:19 +0000283 buf_ptr, size);
284 if(rval.code == RC_OK) {
285 if(asn_REAL2double(st, Dbl)) {
286 rval.code = RC_FAIL;
287 rval.consumed = 0;
288 }
289 } else {
290 rval.consumed = 0;
291 }
Lev Walkinadcb5862006-03-17 02:11:12 +0000292 ASN_STRUCT_FREE(asn_DEF_REAL, st);
Lev Walkin8471cec2004-10-21 14:02:19 +0000293 return rval;
294}
295
Lev Walkina9cc46e2004-09-22 16:06:28 +0000296asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000297NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000298 int ilevel, enum xer_encoder_flags_e flags,
299 asn_app_consume_bytes_f *cb, void *app_key) {
300 const double *Dbl = (const double *)sptr;
301 asn_enc_rval_t er;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000302
303 (void)ilevel;
304
Lev Walkin7c1dc052016-03-14 03:08:15 -0700305 if(!Dbl) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000306
Lev Walkin8e8078a2004-09-26 13:10:40 +0000307 er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700308 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000309
Lev Walkin7c1dc052016-03-14 03:08:15 -0700310 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000311}
312
Lev Walkin41ba1f22004-09-14 12:46:35 +0000313/*
314 * REAL specific human-readable output.
315 */
316int
Lev Walkin5e033762004-09-29 13:26:15 +0000317NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000318 asn_app_consume_bytes_f *cb, void *app_key) {
319 const double *Dbl = (const double *)sptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000320
321 (void)td; /* Unused argument */
322 (void)ilevel; /* Unused argument */
323
Lev Walkin8e8078a2004-09-26 13:10:40 +0000324 if(!Dbl) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000325
326 return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000327}
328
329void
Lev Walkin5e033762004-09-29 13:26:15 +0000330NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000331
332 if(!td || !ptr)
333 return;
334
335 ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
336 td->name, contents_only, ptr);
337
338 if(!contents_only) {
339 FREEMEM(ptr);
340 }
341}
342