/src/libiec61850/src/mms/iso_mms/asn1c/NativeInteger.c
Line | Count | Source |
1 | | /*- |
2 | | * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>. |
3 | | * All rights reserved. |
4 | | * Redistribution and modifications are permitted subject to BSD license. |
5 | | */ |
6 | | /* |
7 | | * Read the NativeInteger.h for the explanation wrt. differences between |
8 | | * INTEGER and NativeInteger. |
9 | | * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this |
10 | | * implementation deals with the standard (machine-specific) representation |
11 | | * of them instead of using the platform-independent buffer. |
12 | | */ |
13 | | #include <asn_internal.h> |
14 | | #include <NativeInteger.h> |
15 | | |
16 | | /* |
17 | | * NativeInteger basic type description. |
18 | | */ |
19 | | static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { |
20 | | (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) |
21 | | }; |
22 | | asn_TYPE_descriptor_t asn_DEF_NativeInteger = { |
23 | | "INTEGER", /* The ASN.1 type is still INTEGER */ |
24 | | "INTEGER", |
25 | | NativeInteger_free, |
26 | | NULL, |
27 | | asn_generic_no_constraint, |
28 | | NativeInteger_decode_ber, |
29 | | NativeInteger_encode_der, |
30 | | NULL, |
31 | | NULL, |
32 | | NativeInteger_decode_uper, /* Unaligned PER decoder */ |
33 | | NativeInteger_encode_uper, /* Unaligned PER encoder */ |
34 | | 0, /* Use generic outmost tag fetcher */ |
35 | | asn_DEF_NativeInteger_tags, |
36 | | sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), |
37 | | asn_DEF_NativeInteger_tags, /* Same as above */ |
38 | | sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), |
39 | | 0, /* No PER visible constraints */ |
40 | | 0, 0, /* No members */ |
41 | | 0 /* No specifics */ |
42 | | }; |
43 | | |
44 | | /* |
45 | | * Decode INTEGER type. |
46 | | */ |
47 | | asn_dec_rval_t |
48 | | NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx, |
49 | | asn_TYPE_descriptor_t *td, |
50 | 0 | void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) { |
51 | 0 | long *native = (long *)*nint_ptr; |
52 | 0 | asn_dec_rval_t rval; |
53 | 0 | ber_tlv_len_t length; |
54 | | |
55 | | /* |
56 | | * If the structure is not there, allocate it. |
57 | | */ |
58 | 0 | if(native == NULL) { |
59 | 0 | native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native))); |
60 | 0 | if(native == NULL) { |
61 | 0 | rval.code = RC_FAIL; |
62 | 0 | rval.consumed = 0; |
63 | 0 | return rval; |
64 | 0 | } |
65 | 0 | } |
66 | | |
67 | 0 | ASN_DEBUG("Decoding %s as INTEGER (tm=%d)", |
68 | 0 | td->name, tag_mode); |
69 | | |
70 | | /* |
71 | | * Check tags. |
72 | | */ |
73 | 0 | rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, |
74 | 0 | tag_mode, 0, &length, 0); |
75 | 0 | if(rval.code != RC_OK) |
76 | 0 | return rval; |
77 | | |
78 | 0 | ASN_DEBUG("%s length is %d bytes", td->name, (int)length); |
79 | | |
80 | | /* |
81 | | * Make sure we have this length. |
82 | | */ |
83 | 0 | buf_ptr = ((const char *)buf_ptr) + rval.consumed; |
84 | 0 | size -= rval.consumed; |
85 | 0 | if(length > (ber_tlv_len_t)size) { |
86 | 0 | rval.code = RC_WMORE; |
87 | 0 | rval.consumed = 0; |
88 | 0 | return rval; |
89 | 0 | } |
90 | | |
91 | | /* |
92 | | * ASN.1 encoded INTEGER: buf_ptr, length |
93 | | * Fill the native, at the same time checking for overflow. |
94 | | * If overflow occured, return with RC_FAIL. |
95 | | */ |
96 | 0 | { |
97 | 0 | INTEGER_t tmp; |
98 | 0 | union { |
99 | 0 | const void *constbuf; |
100 | 0 | void *nonconstbuf; |
101 | 0 | } unconst_buf; |
102 | 0 | long l; |
103 | |
|
104 | 0 | unconst_buf.constbuf = buf_ptr; |
105 | 0 | tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; |
106 | 0 | tmp.size = length; |
107 | |
|
108 | 0 | if(asn_INTEGER2long(&tmp, &l)) { |
109 | 0 | rval.code = RC_FAIL; |
110 | 0 | rval.consumed = 0; |
111 | 0 | return rval; |
112 | 0 | } |
113 | | |
114 | 0 | *native = l; |
115 | 0 | } |
116 | | |
117 | 0 | rval.code = RC_OK; |
118 | 0 | rval.consumed += length; |
119 | |
|
120 | 0 | ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)", |
121 | 0 | (long)rval.consumed, (long)length, td->name, (long)*native); |
122 | |
|
123 | 0 | return rval; |
124 | 0 | } |
125 | | |
126 | | /* |
127 | | * Encode the NativeInteger using the standard INTEGER type DER encoder. |
128 | | */ |
129 | | asn_enc_rval_t |
130 | | NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, |
131 | | int tag_mode, ber_tlv_tag_t tag, |
132 | 0 | asn_app_consume_bytes_f *cb, void *app_key) { |
133 | 0 | unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */ |
134 | 0 | asn_enc_rval_t erval; |
135 | 0 | INTEGER_t tmp; |
136 | |
|
137 | | #ifdef WORDS_BIGENDIAN /* Opportunistic optimization */ |
138 | | |
139 | | tmp.buf = (uint8_t *)&native; |
140 | | tmp.size = sizeof(native); |
141 | | |
142 | | #else /* Works even if WORDS_BIGENDIAN is not set where should've been */ |
143 | 0 | uint8_t buf[sizeof(native)]; |
144 | 0 | uint8_t *p; |
145 | | |
146 | | /* Prepare a fake INTEGER */ |
147 | 0 | for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) |
148 | 0 | *p = native; |
149 | |
|
150 | 0 | tmp.buf = buf; |
151 | 0 | tmp.size = sizeof(buf); |
152 | 0 | #endif /* WORDS_BIGENDIAN */ |
153 | | |
154 | | /* Encode fake INTEGER */ |
155 | 0 | erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key); |
156 | 0 | if(erval.encoded == -1) { |
157 | 0 | assert(erval.structure_ptr == &tmp); |
158 | 0 | erval.structure_ptr = ptr; |
159 | 0 | } |
160 | 0 | return erval; |
161 | 0 | } |
162 | | |
163 | | |
164 | | asn_dec_rval_t |
165 | | NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, |
166 | | asn_TYPE_descriptor_t *td, |
167 | 0 | asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { |
168 | |
|
169 | 0 | asn_dec_rval_t rval; |
170 | 0 | long *native = (long *)*sptr; |
171 | 0 | INTEGER_t tmpint; |
172 | 0 | void *tmpintptr = &tmpint; |
173 | |
|
174 | 0 | (void)opt_codec_ctx; |
175 | 0 | ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name); |
176 | |
|
177 | 0 | if(!native) { |
178 | 0 | native = (long *)(*sptr = CALLOC(1, sizeof(*native))); |
179 | 0 | if(!native) _ASN_DECODE_FAILED; |
180 | 0 | } |
181 | | |
182 | 0 | memset(&tmpint, 0, sizeof tmpint); |
183 | 0 | rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, |
184 | 0 | &tmpintptr, pd); |
185 | 0 | if(rval.code == RC_OK) { |
186 | 0 | if(asn_INTEGER2long(&tmpint, native)) |
187 | 0 | rval.code = RC_FAIL; |
188 | 0 | else |
189 | 0 | ASN_DEBUG("NativeInteger %s got value %ld", |
190 | 0 | td->name, *native); |
191 | 0 | } |
192 | 0 | ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); |
193 | |
|
194 | 0 | return rval; |
195 | 0 | } |
196 | | |
197 | | asn_enc_rval_t |
198 | | NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, |
199 | 0 | asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { |
200 | 0 | asn_enc_rval_t er; |
201 | 0 | long native; |
202 | 0 | INTEGER_t tmpint; |
203 | |
|
204 | 0 | if(!sptr) _ASN_ENCODE_FAILED; |
205 | | |
206 | 0 | native = *(long *)sptr; |
207 | |
|
208 | 0 | ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); |
209 | |
|
210 | 0 | memset(&tmpint, 0, sizeof(tmpint)); |
211 | 0 | if(asn_long2INTEGER(&tmpint, native)) |
212 | 0 | _ASN_ENCODE_FAILED; |
213 | 0 | er = INTEGER_encode_uper(td, constraints, &tmpint, po); |
214 | 0 | ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); |
215 | 0 | return er; |
216 | 0 | } |
217 | | |
218 | | void |
219 | 0 | NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { |
220 | |
|
221 | 0 | if(!td || !ptr) |
222 | 0 | return; |
223 | | |
224 | 0 | ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", |
225 | 0 | td->name, contents_only, ptr); |
226 | |
|
227 | 0 | if(!contents_only) { |
228 | 0 | FREEMEM(ptr); |
229 | 0 | } |
230 | 0 | } |
231 | | |