blob: 25831e2b6250c84e46d198ecb14be63b886e7e3c [file] [log] [blame]
Peter Szilagyifbc56f92019-07-23 19:29:46 +00001/*-
2 * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <asn_internal.h>
6#include <asn_codecs_prim.h>
7#include <BOOLEAN.h>
8
9/*
10 * BOOLEAN basic type description.
11 */
12static const ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
13 (ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
14};
15asn_TYPE_operation_t asn_OP_BOOLEAN = {
16 BOOLEAN_free,
17 BOOLEAN_print,
18 BOOLEAN_compare,
19 BOOLEAN_decode_ber,
20 BOOLEAN_encode_der,
21 BOOLEAN_decode_xer,
22 BOOLEAN_encode_xer,
23#ifdef ASN_DISABLE_OER_SUPPORT
24 0,
25 0,
26#else
27 BOOLEAN_decode_oer,
28 BOOLEAN_encode_oer,
29#endif /* ASN_DISABLE_OER_SUPPORT */
30#ifdef ASN_DISABLE_PER_SUPPORT
31 0,
32 0,
33 0,
34 0,
35#else
36 BOOLEAN_decode_uper, /* Unaligned PER decoder */
37 BOOLEAN_encode_uper, /* Unaligned PER encoder */
38 BOOLEAN_decode_aper, /* Aligned PER decoder */
39 BOOLEAN_encode_aper, /* Aligned PER encoder */
40#endif /* ASN_DISABLE_PER_SUPPORT */
41 BOOLEAN_random_fill,
42 0 /* Use generic outmost tag fetcher */
43};
44asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
45 "BOOLEAN",
46 "BOOLEAN",
47 &asn_OP_BOOLEAN,
48 asn_DEF_BOOLEAN_tags,
49 sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
50 asn_DEF_BOOLEAN_tags, /* Same as above */
51 sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
52 { 0, 0, asn_generic_no_constraint },
53 0, 0, /* No members */
54 0 /* No specifics */
55};
56
57/*
58 * Decode BOOLEAN type.
59 */
60asn_dec_rval_t
61BOOLEAN_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
62 const asn_TYPE_descriptor_t *td, void **bool_value,
63 const void *buf_ptr, size_t size, int tag_mode) {
64 BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
65 asn_dec_rval_t rval;
66 ber_tlv_len_t length;
67 ber_tlv_len_t lidx;
68
69 if(st == NULL) {
70 st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
71 if(st == NULL) {
72 rval.code = RC_FAIL;
73 rval.consumed = 0;
74 return rval;
75 }
76 }
77
78 ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
79 td->name, tag_mode);
80
81 /*
82 * Check tags.
83 */
84 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
85 tag_mode, 0, &length, 0);
86 if(rval.code != RC_OK)
87 return rval;
88
89 ASN_DEBUG("Boolean length is %d bytes", (int)length);
90
91 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
92 size -= rval.consumed;
93 if(length > (ber_tlv_len_t)size) {
94 rval.code = RC_WMORE;
95 rval.consumed = 0;
96 return rval;
97 }
98
99 /*
100 * Compute boolean value.
101 */
102 for(*st = 0, lidx = 0;
103 (lidx < length) && *st == 0; lidx++) {
104 /*
105 * Very simple approach: read bytes until the end or
106 * value is already TRUE.
107 * BOOLEAN is not supposed to contain meaningful data anyway.
108 */
109 *st |= ((const uint8_t *)buf_ptr)[lidx];
110 }
111
112 rval.code = RC_OK;
113 rval.consumed += length;
114
115 ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
116 (long)rval.consumed, (long)length,
117 td->name, *st);
118
119 return rval;
120}
121
122asn_enc_rval_t
123BOOLEAN_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
124 int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
125 void *app_key) {
126 asn_enc_rval_t erval = {0,0,0};
127 const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
128
129 erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
130 if(erval.encoded == -1) {
131 erval.failed_type = td;
132 erval.structure_ptr = sptr;
133 return erval;
134 }
135
136 if(cb) {
137 uint8_t bool_value;
138
139 bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
140
141 if(cb(&bool_value, 1, app_key) < 0) {
142 erval.encoded = -1;
143 erval.failed_type = td;
144 erval.structure_ptr = sptr;
145 return erval;
146 }
147 }
148
149 erval.encoded += 1;
150
151 ASN__ENCODED_OK(erval);
152}
153
154
155/*
156 * Decode the chunk of XML text encoding INTEGER.
157 */
158static enum xer_pbd_rval
159BOOLEAN__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
160 const void *chunk_buf, size_t chunk_size) {
161 BOOLEAN_t *st = (BOOLEAN_t *)sptr;
162 const char *p = (const char *)chunk_buf;
163
164 (void)td;
165
166 if(chunk_size && p[0] == 0x3c /* '<' */) {
167 switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
168 case XCT_BOTH:
169 /* "<false/>" */
170 *st = 0;
171 break;
172 case XCT_UNKNOWN_BO:
173 if(xer_check_tag(chunk_buf, chunk_size, "true")
174 != XCT_BOTH)
175 return XPBD_BROKEN_ENCODING;
176 /* "<true/>" */
177 *st = 1; /* Or 0xff as in DER?.. */
178 break;
179 default:
180 return XPBD_BROKEN_ENCODING;
181 }
182 return XPBD_BODY_CONSUMED;
183 } else {
184 return XPBD_BROKEN_ENCODING;
185 }
186}
187
188
189asn_dec_rval_t
190BOOLEAN_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
191 const asn_TYPE_descriptor_t *td, void **sptr,
192 const char *opt_mname, const void *buf_ptr, size_t size) {
193 return xer_decode_primitive(opt_codec_ctx, td,
194 sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
195 BOOLEAN__xer_body_decode);
196}
197
198asn_enc_rval_t
199BOOLEAN_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
200 int ilevel, enum xer_encoder_flags_e flags,
201 asn_app_consume_bytes_f *cb, void *app_key) {
202 const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
203 asn_enc_rval_t er = {0, 0, 0};
204
205 (void)ilevel;
206 (void)flags;
207
208 if(!st) ASN__ENCODE_FAILED;
209
210 if(*st) {
211 ASN__CALLBACK("<true/>", 7);
212 } else {
213 ASN__CALLBACK("<false/>", 8);
214 }
215
216 ASN__ENCODED_OK(er);
217cb_failed:
218 ASN__ENCODE_FAILED;
219}
220
221int
222BOOLEAN_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
223 asn_app_consume_bytes_f *cb, void *app_key) {
224 const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
225 const char *buf;
226 size_t buflen;
227
228 (void)td; /* Unused argument */
229 (void)ilevel; /* Unused argument */
230
231 if(st) {
232 if(*st) {
233 buf = "TRUE";
234 buflen = 4;
235 } else {
236 buf = "FALSE";
237 buflen = 5;
238 }
239 } else {
240 buf = "<absent>";
241 buflen = 8;
242 }
243
244 return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
245}
246
247void
248BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr,
249 enum asn_struct_free_method method) {
250 if(td && ptr) {
251 switch(method) {
252 case ASFM_FREE_EVERYTHING:
253 FREEMEM(ptr);
254 break;
255 case ASFM_FREE_UNDERLYING:
256 break;
257 case ASFM_FREE_UNDERLYING_AND_RESET:
258 memset(ptr, 0, sizeof(BOOLEAN_t));
259 break;
260 }
261 }
262}
263
264#ifndef ASN_DISABLE_PER_SUPPORT
265
266asn_dec_rval_t
267BOOLEAN_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
268 const asn_TYPE_descriptor_t *td,
269 const asn_per_constraints_t *constraints, void **sptr,
270 asn_per_data_t *pd) {
271 asn_dec_rval_t rv;
272 BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
273
274 (void)opt_codec_ctx;
275 (void)td;
276 (void)constraints;
277
278 if(!st) {
279 st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
280 if(!st) ASN__DECODE_FAILED;
281 }
282
283 /*
284 * Extract a single bit
285 */
286 switch(per_get_few_bits(pd, 1)) {
287 case 1: *st = 1; break;
288 case 0: *st = 0; break;
289 case -1: default: ASN__DECODE_STARVED;
290 }
291
292 ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
293
294 rv.code = RC_OK;
295 rv.consumed = 1;
296 return rv;
297}
298
299
300asn_enc_rval_t
301BOOLEAN_encode_uper(const asn_TYPE_descriptor_t *td,
302 const asn_per_constraints_t *constraints, const void *sptr,
303 asn_per_outp_t *po) {
304 const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
305 asn_enc_rval_t er = { 0, 0, 0 };
306
307 (void)constraints;
308
309 if(!st) ASN__ENCODE_FAILED;
310
311 if(per_put_few_bits(po, *st ? 1 : 0, 1))
312 ASN__ENCODE_FAILED;
313
314 ASN__ENCODED_OK(er);
315}
316
317asn_dec_rval_t
318BOOLEAN_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td,
319 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
320 asn_dec_rval_t rv;
321 BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
322
323 (void)opt_codec_ctx;
324 (void)constraints;
325 (void)td;
326
327 if(!st) {
328 st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
329 if(!st) ASN__DECODE_FAILED;
330 }
331
332 /*
333 * Extract a single bit
334 */
335 switch(per_get_few_bits(pd, 1)) {
336 case 1:
337 *st = 1;
338 break;
339 case 0:
340 *st = 0;
341 break;
342 case -1:
343 default:
344 ASN__DECODE_STARVED;
345 }
346
347 ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
348
349 rv.code = RC_OK;
350 rv.consumed = 1;
351 return rv;
352}
353
354asn_enc_rval_t
355BOOLEAN_encode_aper(const asn_TYPE_descriptor_t *td,
356 const asn_per_constraints_t *constraints,
357 const void *sptr, asn_per_outp_t *po) {
358 const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
359 asn_enc_rval_t er = { 0, 0, 0 };
360
361 (void)constraints;
362
363 if(!st) ASN__ENCODE_FAILED;
364
365 if(per_put_few_bits(po, *st ? 1 : 0, 1))
366 ASN__ENCODE_FAILED;
367
368 ASN__ENCODED_OK(er);
369}
370
371#endif /* ASN_DISABLE_PER_SUPPORT */
372
373#ifndef ASN_DISABLE_OER_SUPPORT
374
375/*
376 * Encode as Canonical OER.
377 */
378asn_enc_rval_t
379BOOLEAN_encode_oer(const asn_TYPE_descriptor_t *td,
380 const asn_oer_constraints_t *constraints, const void *sptr,
381 asn_app_consume_bytes_f *cb, void *app_key) {
382 asn_enc_rval_t er = { 1, 0, 0 };
383 const BOOLEAN_t *st = sptr;
384 uint8_t bool_value = *st ? 0xff : 0; /* 0xff mandated by OER */
385
386 (void)td;
387 (void)constraints; /* Constraints are unused in OER */
388
389 if(cb(&bool_value, 1, app_key) < 0) {
390 ASN__ENCODE_FAILED;
391 } else {
392 ASN__ENCODED_OK(er);
393 }
394}
395
396asn_dec_rval_t
397BOOLEAN_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
398 const asn_TYPE_descriptor_t *td,
399 const asn_oer_constraints_t *constraints, void **sptr,
400 const void *ptr, size_t size) {
401 asn_dec_rval_t ok = {RC_OK, 1};
402 BOOLEAN_t *st;
403
404 (void)opt_codec_ctx;
405 (void)td;
406 (void)constraints; /* Constraints are unused in OER */
407
408 if(size < 1) {
409 ASN__DECODE_STARVED;
410 }
411
412 if(!(st = *sptr)) {
413 st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
414 if(!st) ASN__DECODE_FAILED;
415 }
416
417 *st = *(const uint8_t *)ptr;
418
419 return ok;
420}
421
422
423
424#endif
425
426int
427BOOLEAN_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
428 const void *bptr) {
429 const BOOLEAN_t *a = aptr;
430 const BOOLEAN_t *b = bptr;
431
432 (void)td;
433
434 if(a && b) {
435 if(!*a == !*b) { /* TRUE can be encoded by any non-zero byte. */
436 return 0;
437 } else if(!*a) {
438 return -1;
439 } else {
440 return 1;
441 }
442 } else if(!a) {
443 return -1;
444 } else {
445 return 1;
446 }
447}
448
449asn_random_fill_result_t
450BOOLEAN_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
451 const asn_encoding_constraints_t *constraints,
452 size_t max_length) {
453 asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
454 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
455 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
456 BOOLEAN_t *st = *sptr;
457
458 if(max_length == 0) return result_skipped;
459
460 if(st == NULL) {
461 st = (BOOLEAN_t *)(*sptr = CALLOC(1, sizeof(*st)));
462 if(st == NULL) {
463 return result_failed;
464 }
465 }
466
467 if(!constraints || !constraints->per_constraints)
468 constraints = &td->encoding_constraints;
469 if(constraints->per_constraints) {
470 const asn_per_constraint_t *pc = &constraints->per_constraints->value;
471 if(pc->flags & APC_CONSTRAINED) {
472 *st = asn_random_between(pc->lower_bound, pc->upper_bound);
473 return result_ok;
474 }
475 }
476
477 /* Simulate booleans that are sloppily set and biased. */
478 switch(asn_random_between(0, 7)) {
479 case 0:
480 case 1:
481 case 2:
482 *st = 0; break;
483 case 3: *st = -1; break;
484 case 4: *st = 1; break;
485 case 5: *st = INT_MIN; break;
486 case 6: *st = INT_MAX; break;
487 default:
488 *st = asn_random_between(INT_MIN, INT_MAX);
489 break;
490 }
491 return result_ok;
492}