blob: a1ff91e18004a53a1e0a0a57001a5d7ccd33a11a [file] [log] [blame]
Harald Welte92c45f32010-06-12 18:59:38 +02001/*-
Harald Welteec0e2172010-07-20 00:03:44 +02002 * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
Harald Welte92c45f32010-06-12 18:59:38 +02003 * Redistribution and modifications are permitted subject to BSD license.
4 */
5/*
6 * Read the NativeReal.h for the explanation wrt. differences between
7 * 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 */
12#include <asn_internal.h>
13#include <NativeReal.h>
14#include <REAL.h>
Harald Welteec0e2172010-07-20 00:03:44 +020015#include <OCTET_STRING.h>
Harald Welte92c45f32010-06-12 18:59:38 +020016
17/*
18 * NativeReal basic type description.
19 */
20static ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
21 (ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
22};
23asn_TYPE_descriptor_t asn_DEF_NativeReal = {
24 "REAL", /* The ASN.1 type is still REAL */
25 "REAL",
26 NativeReal_free,
27 NativeReal_print,
28 asn_generic_no_constraint,
29 NativeReal_decode_ber,
30 NativeReal_encode_der,
31 NativeReal_decode_xer,
32 NativeReal_encode_xer,
Harald Welteec0e2172010-07-20 00:03:44 +020033 NativeReal_decode_uper,
34 NativeReal_encode_uper,
Harald Welte92c45f32010-06-12 18:59:38 +020035 0, /* Use generic outmost tag fetcher */
36 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]),
40 0, /* No PER visible constraints */
41 0, 0, /* No members */
42 0 /* No specifics */
43};
44
45/*
46 * Decode REAL type.
47 */
48asn_dec_rval_t
49NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
50 asn_TYPE_descriptor_t *td,
51 void **dbl_ptr, const void *buf_ptr, size_t size, int tag_mode) {
52 double *Dbl = (double *)*dbl_ptr;
53 asn_dec_rval_t rval;
54 ber_tlv_len_t length;
55
56 /*
57 * If the structure is not there, allocate it.
58 */
59 if(Dbl == NULL) {
60 *dbl_ptr = CALLOC(1, sizeof(*Dbl));
61 Dbl = (double *)*dbl_ptr;
62 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 */
75 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
76 tag_mode, 0, &length, 0);
77 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 */
85 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
86 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;
100 union {
101 const void *constbuf;
102 void *nonconstbuf;
103 } unconst_buf;
104 double d;
105
106 unconst_buf.constbuf = buf_ptr;
107 tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
108 tmp.size = length;
109
110 if(asn_REAL2double(&tmp, &d)) {
111 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
122 ASN_DEBUG("Took %ld/%ld bytes to encode %s (%f)",
123 (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 */
131asn_enc_rval_t
132NativeReal_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
133 int tag_mode, ber_tlv_tag_t tag,
134 asn_app_consume_bytes_f *cb, void *app_key) {
135 double Dbl = *(const double *)ptr;
136 asn_enc_rval_t erval;
137 REAL_t tmp;
138
139 /* Prepare a temporary clean structure */
140 memset(&tmp, 0, sizeof(tmp));
141
142 if(asn_double2REAL(&tmp, Dbl)) {
143 erval.encoded = -1;
144 erval.failed_type = td;
145 erval.structure_ptr = ptr;
146 return erval;
147 }
148
149 /* Encode a fake REAL */
150 erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
151 if(erval.encoded == -1) {
152 assert(erval.structure_ptr == &tmp);
153 erval.structure_ptr = ptr;
154 }
155
156 /* Free possibly allocated members of the temporary structure */
157 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
158
159 return erval;
160}
161
Harald Welteec0e2172010-07-20 00:03:44 +0200162/*
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;
Harald Welte92c45f32010-06-12 18:59:38 +0200174
Harald Welteec0e2172010-07-20 00:03:44 +0200175 (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}
Harald Welte92c45f32010-06-12 18:59:38 +0200230
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,
237 const void *buf_ptr, size_t size) {
238 asn_dec_rval_t rval;
239 REAL_t *st = 0;
240 REAL_t **stp = &st;
241 double *Dbl = (double *)*sptr;
242
243 if(!Dbl) {
244 *sptr = CALLOC(1, sizeof(double));
245 Dbl = (double *)*sptr;
246 if(!Dbl) {
247 rval.code = RC_FAIL;
248 rval.consumed = 0;
249 return rval;
250 }
251 }
252
253 rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname,
254 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 }
263 ASN_STRUCT_FREE(asn_DEF_REAL, st);
264 return rval;
265}
266
267asn_enc_rval_t
268NativeReal_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
269 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;
273
274 (void)ilevel;
275
276 if(!Dbl) _ASN_ENCODE_FAILED;
277
278 er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key);
279 if(er.encoded < 0) _ASN_ENCODE_FAILED;
280
281 _ASN_ENCODED_OK(er);
282}
283
284/*
285 * REAL specific human-readable output.
286 */
287int
288NativeReal_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
289 asn_app_consume_bytes_f *cb, void *app_key) {
290 const double *Dbl = (const double *)sptr;
291
292 (void)td; /* Unused argument */
293 (void)ilevel; /* Unused argument */
294
295 if(!Dbl) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
296
297 return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
298}
299
300void
301NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
302
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