]> git.stg.codes - stg.git/blob - libs/smux/NativeEnumerated.c
Add subscriptions (to replace notifiers).
[stg.git] / libs / smux / NativeEnumerated.c
1 /*-
2  * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 /*
6  * Read the NativeInteger.h for the explanation wrt. differences between
7  * INTEGER and NativeInteger.
8  * Basically, both are decoders and encoders of ASN.1 INTEGER 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 <NativeEnumerated.h>
14
15 /*
16  * NativeEnumerated basic type description.
17  */
18 static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
19         (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
20 };
21 asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
22         "ENUMERATED",                   /* The ASN.1 type is still ENUMERATED */
23         "ENUMERATED",
24         NativeInteger_free,
25         NativeInteger_print,
26         asn_generic_no_constraint,
27         NativeInteger_decode_ber,
28         NativeInteger_encode_der,
29         NativeInteger_decode_xer,
30         NativeEnumerated_encode_xer,
31         NativeEnumerated_decode_uper,
32         NativeEnumerated_encode_uper,
33         0, /* Use generic outmost tag fetcher */
34         asn_DEF_NativeEnumerated_tags,
35         sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
36         asn_DEF_NativeEnumerated_tags,  /* Same as above */
37         sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
38         0,      /* No PER visible constraints */
39         0, 0,   /* No members */
40         0       /* No specifics */
41 };
42
43 asn_enc_rval_t
44 NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
45         int ilevel, enum xer_encoder_flags_e flags,
46                 asn_app_consume_bytes_f *cb, void *app_key) {
47         asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
48         asn_enc_rval_t er;
49         const long *native = (const long *)sptr;
50         const asn_INTEGER_enum_map_t *el;
51
52         (void)ilevel;
53         (void)flags;
54
55         if(!native) ASN__ENCODE_FAILED;
56
57         el = INTEGER_map_value2enum(specs, *native);
58         if(el) {
59                 size_t srcsize = el->enum_len + 5;
60                 char *src = (char *)alloca(srcsize);
61
62                 er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
63                 assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
64                 if(cb(src, er.encoded, app_key) < 0) ASN__ENCODE_FAILED;
65                 ASN__ENCODED_OK(er);
66         } else {
67                 ASN_DEBUG("ASN.1 forbids dealing with "
68                         "unknown value of ENUMERATED type");
69                 ASN__ENCODE_FAILED;
70         }
71 }
72
73 asn_dec_rval_t
74 NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
75         asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
76         void **sptr, asn_per_data_t *pd) {
77         asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
78         asn_dec_rval_t rval = { RC_OK, 0 };
79         long *native = (long *)*sptr;
80         asn_per_constraint_t *ct;
81         long value;
82
83         (void)opt_codec_ctx;
84
85         if(constraints) ct = &constraints->value;
86         else if(td->per_constraints) ct = &td->per_constraints->value;
87         else ASN__DECODE_FAILED;        /* Mandatory! */
88         if(!specs) ASN__DECODE_FAILED;
89
90         if(!native) {
91                 native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
92                 if(!native) ASN__DECODE_FAILED;
93         }
94
95         ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
96
97         if(ct->flags & APC_EXTENSIBLE) {
98                 int inext = per_get_few_bits(pd, 1);
99                 if(inext < 0) ASN__DECODE_STARVED;
100                 if(inext) ct = 0;
101         }
102
103         if(ct && ct->range_bits >= 0) {
104                 value = per_get_few_bits(pd, ct->range_bits);
105                 if(value < 0) ASN__DECODE_STARVED;
106                 if(value >= (specs->extension
107                         ? specs->extension - 1 : specs->map_count))
108                         ASN__DECODE_FAILED;
109         } else {
110                 if(!specs->extension)
111                         ASN__DECODE_FAILED;
112                 /*
113                  * X.691, #10.6: normally small non-negative whole number;
114                  */
115                 value = uper_get_nsnnwn(pd);
116                 if(value < 0) ASN__DECODE_STARVED;
117                 value += specs->extension - 1;
118                 if(value >= specs->map_count)
119                         ASN__DECODE_FAILED;
120         }
121
122         *native = specs->value2enum[value].nat_value;
123         ASN_DEBUG("Decoded %s = %ld", td->name, *native);
124
125         return rval;
126 }
127
128 static int
129 NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
130         const asn_INTEGER_enum_map_t *a = ap;
131         const asn_INTEGER_enum_map_t *b = bp;
132         if(a->nat_value == b->nat_value)
133                 return 0;
134         if(a->nat_value < b->nat_value)
135                 return -1;
136         return 1;
137 }
138
139 asn_enc_rval_t
140 NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
141         asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
142         asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
143         asn_enc_rval_t er;
144         long native, value;
145         asn_per_constraint_t *ct;
146         int inext = 0;
147         asn_INTEGER_enum_map_t key;
148         const asn_INTEGER_enum_map_t *kf;
149
150         if(!sptr) ASN__ENCODE_FAILED;
151         if(!specs) ASN__ENCODE_FAILED;
152
153         if(constraints) ct = &constraints->value;
154         else if(td->per_constraints) ct = &td->per_constraints->value;
155         else ASN__ENCODE_FAILED;        /* Mandatory! */
156
157         ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
158
159         er.encoded = 0;
160
161         native = *(long *)sptr;
162         if(native < 0) ASN__ENCODE_FAILED;
163
164         key.nat_value = native;
165         kf = bsearch(&key, specs->value2enum, specs->map_count,
166                 sizeof(key), NativeEnumerated__compar_value2enum);
167         if(!kf) {
168                 ASN_DEBUG("No element corresponds to %ld", native);
169                 ASN__ENCODE_FAILED;
170         }
171         value = kf - specs->value2enum;
172
173         if(ct->range_bits >= 0) {
174                 int cmpWith = specs->extension
175                                 ? specs->extension - 1 : specs->map_count;
176                 if(value >= cmpWith)
177                         inext = 1;
178         }
179         if(ct->flags & APC_EXTENSIBLE) {
180                 if(per_put_few_bits(po, inext, 1))
181                         ASN__ENCODE_FAILED;
182                 if(inext) ct = 0;
183         } else if(inext) {
184                 ASN__ENCODE_FAILED;
185         }
186
187         if(ct && ct->range_bits >= 0) {
188                 if(per_put_few_bits(po, value, ct->range_bits))
189                         ASN__ENCODE_FAILED;
190                 ASN__ENCODED_OK(er);
191         }
192
193         if(!specs->extension)
194                 ASN__ENCODE_FAILED;
195
196         /*
197          * X.691, #10.6: normally small non-negative whole number;
198          */
199         ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
200                 value, specs->extension, inext,
201                 value - (inext ? (specs->extension - 1) : 0));
202         if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
203                 ASN__ENCODE_FAILED;
204
205         ASN__ENCODED_OK(er);
206 }
207