blob: a1ff91e18004a53a1e0a0a57001a5d7ccd33a11a [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 */
Lev Walkin5e033762004-09-29 13:26:15 +000020static 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 Walkin5e033762004-09-29 13:26:15 +0000110 if(asn_REAL2double(&tmp, &d)) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000111 rval.code = RC_FAIL;
112 rval.consumed = 0;
113 return rval;
114 }
115
116 *Dbl = d;
117 }
118
119 rval.code = RC_OK;
120 rval.consumed += length;
121
Lev Walkin1e3ccbb2004-10-26 10:56:10 +0000122 ASN_DEBUG("Took %ld/%ld bytes to encode %s (%f)",
Lev Walkin41ba1f22004-09-14 12:46:35 +0000123 (long)rval.consumed, (long)length, td->name, *Dbl);
124
125 return rval;
126}
127
128/*
129 * Encode the NativeReal using the standard REAL type DER encoder.
130 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000131asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000132NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000133 int tag_mode, ber_tlv_tag_t tag,
134 asn_app_consume_bytes_f *cb, void *app_key) {
135 double Dbl = *(const double *)ptr;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000136 asn_enc_rval_t erval;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000137 REAL_t tmp;
138
Lev Walkina8bbbda2005-02-06 04:29:03 +0000139 /* Prepare a temporary clean structure */
140 memset(&tmp, 0, sizeof(tmp));
141
Lev Walkin5e033762004-09-29 13:26:15 +0000142 if(asn_double2REAL(&tmp, Dbl)) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000143 erval.encoded = -1;
144 erval.failed_type = td;
145 erval.structure_ptr = ptr;
146 return erval;
147 }
148
Lev Walkin8e8078a2004-09-26 13:10:40 +0000149 /* Encode a fake REAL */
150 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
Lev Walkin41ba1f22004-09-14 12:46:35 +0000151 if(erval.encoded == -1) {
152 assert(erval.structure_ptr == &tmp);
153 erval.structure_ptr = ptr;
154 }
Lev Walkina8bbbda2005-02-06 04:29:03 +0000155
156 /* Free possibly allocated members of the temporary structure */
Lev Walkinadcb5862006-03-17 02:11:12 +0000157 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
Lev Walkina8bbbda2005-02-06 04:29:03 +0000158
Lev Walkin41ba1f22004-09-14 12:46:35 +0000159 return erval;
160}
161
Lev Walkin725883b2006-10-09 12:07:58 +0000162/*
163 * Decode REAL type using PER.
164 */
165asn_dec_rval_t
166NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
167 asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
168 void **dbl_ptr, asn_per_data_t *pd) {
169 double *Dbl = (double *)*dbl_ptr;
170 asn_dec_rval_t rval;
171 REAL_t tmp;
172 void *ptmp = &tmp;
173 int ret;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000174
Lev Walkin725883b2006-10-09 12:07:58 +0000175 (void)constraints;
176
177 /*
178 * If the structure is not there, allocate it.
179 */
180 if(Dbl == NULL) {
181 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
182 Dbl = (double *)*dbl_ptr;
183 if(Dbl == NULL)
184 _ASN_DECODE_FAILED;
185 }
186
187 memset(&tmp, 0, sizeof(tmp));
188 rval = OCTET_STRING_decode_uper(opt_codec_ctx, td, NULL,
189 &ptmp, pd);
190 if(rval.code != RC_OK) {
191 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
192 return rval;
193 }
194
195 ret = asn_REAL2double(&tmp, Dbl);
196 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
197 if(ret) _ASN_DECODE_FAILED;
198
199 return rval;
200}
201
202/*
203 * Encode the NativeReal using the OCTET STRING PER encoder.
204 */
205asn_enc_rval_t
206NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
207 asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
208 double Dbl = *(const double *)sptr;
209 asn_enc_rval_t erval;
210 REAL_t tmp;
211
212 (void)constraints;
213
214 /* Prepare a temporary clean structure */
215 memset(&tmp, 0, sizeof(tmp));
216
217 if(asn_double2REAL(&tmp, Dbl))
218 _ASN_ENCODE_FAILED;
219
220 /* Encode a DER REAL */
221 erval = OCTET_STRING_encode_uper(td, NULL, &tmp, po);
222 if(erval.encoded == -1)
223 erval.structure_ptr = sptr;
224
225 /* Free possibly allocated members of the temporary structure */
226 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
227
228 return erval;
229}
Lev Walkin8471cec2004-10-21 14:02:19 +0000230
231/*
232 * Decode the chunk of XML text encoding REAL.
233 */
234asn_dec_rval_t
235NativeReal_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
236 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000237 const void *buf_ptr, size_t size) {
Lev Walkin8471cec2004-10-21 14:02:19 +0000238 asn_dec_rval_t rval;
239 REAL_t *st = 0;
Lev Walkin1eded352006-07-13 11:19:01 +0000240 REAL_t **stp = &st;
Lev Walkin8471cec2004-10-21 14:02:19 +0000241 double *Dbl = (double *)*sptr;
242
243 if(!Dbl) {
Lev Walkinc17d90f2005-01-17 14:32:45 +0000244 *sptr = CALLOC(1, sizeof(double));
245 Dbl = (double *)*sptr;
Lev Walkin8471cec2004-10-21 14:02:19 +0000246 if(!Dbl) {
247 rval.code = RC_FAIL;
248 rval.consumed = 0;
249 return rval;
250 }
251 }
252
Lev Walkin1eded352006-07-13 11:19:01 +0000253 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname,
Lev Walkin8471cec2004-10-21 14:02:19 +0000254 buf_ptr, size);
255 if(rval.code == RC_OK) {
256 if(asn_REAL2double(st, Dbl)) {
257 rval.code = RC_FAIL;
258 rval.consumed = 0;
259 }
260 } else {
261 rval.consumed = 0;
262 }
Lev Walkinadcb5862006-03-17 02:11:12 +0000263 ASN_STRUCT_FREE(asn_DEF_REAL, st);
Lev Walkin8471cec2004-10-21 14:02:19 +0000264 return rval;
265}
266
Lev Walkina9cc46e2004-09-22 16:06:28 +0000267asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000268NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000269 int ilevel, enum xer_encoder_flags_e flags,
270 asn_app_consume_bytes_f *cb, void *app_key) {
271 const double *Dbl = (const double *)sptr;
272 asn_enc_rval_t er;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000273
274 (void)ilevel;
275
276 if(!Dbl) _ASN_ENCODE_FAILED;
277
Lev Walkin8e8078a2004-09-26 13:10:40 +0000278 er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000279 if(er.encoded < 0) _ASN_ENCODE_FAILED;
280
Lev Walkin59b176e2005-11-26 11:25:14 +0000281 _ASN_ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000282}
283
Lev Walkin41ba1f22004-09-14 12:46:35 +0000284/*
285 * REAL specific human-readable output.
286 */
287int
Lev Walkin5e033762004-09-29 13:26:15 +0000288NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkin41ba1f22004-09-14 12:46:35 +0000289 asn_app_consume_bytes_f *cb, void *app_key) {
290 const double *Dbl = (const double *)sptr;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000291
292 (void)td; /* Unused argument */
293 (void)ilevel; /* Unused argument */
294
Lev Walkin8e8078a2004-09-26 13:10:40 +0000295 if(!Dbl) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000296
297 return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
Lev Walkin41ba1f22004-09-14 12:46:35 +0000298}
299
300void
Lev Walkin5e033762004-09-29 13:26:15 +0000301NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
Lev Walkin41ba1f22004-09-14 12:46:35 +0000302
303 if(!td || !ptr)
304 return;
305
306 ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
307 td->name, contents_only, ptr);
308
309 if(!contents_only) {
310 FREEMEM(ptr);
311 }
312}
313