2
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
4
* Redistribution and modifications are permitted subject to BSD license.
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.
13
#include <asn_internal.h>
14
#include <NativeInteger.h>
17
* NativeInteger basic type description.
19
static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
20
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
22
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
23
"INTEGER", /* The ASN.1 type is still INTEGER */
27
asn_generic_no_constraint,
28
NativeInteger_decode_ber,
29
NativeInteger_encode_der,
30
NativeInteger_decode_xer,
31
NativeInteger_encode_xer,
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 */
45
* Decode INTEGER type.
48
NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
49
asn_TYPE_descriptor_t *td,
50
void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
51
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
52
long *native = (long *)*nint_ptr;
57
* If the structure is not there, allocate it.
60
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
68
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
74
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
75
tag_mode, 0, &length, 0);
76
if(rval.code != RC_OK)
79
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
82
* Make sure we have this length.
84
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
85
size -= rval.consumed;
86
if(length > (ber_tlv_len_t)size) {
93
* ASN.1 encoded INTEGER: buf_ptr, length
94
* Fill the native, at the same time checking for overflow.
95
* If overflow occured, return with RC_FAIL.
100
const void *constbuf;
105
unconst_buf.constbuf = buf_ptr;
106
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
109
if((specs&&specs->field_unsigned)
110
? asn_INTEGER2ulong(&tmp, &l)
111
: asn_INTEGER2long(&tmp, &l)) {
121
rval.consumed += length;
123
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
124
(long)rval.consumed, (long)length, td->name, (long)*native);
130
* Encode the NativeInteger using the standard INTEGER type DER encoder.
133
NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
134
int tag_mode, ber_tlv_tag_t tag,
135
asn_app_consume_bytes_f *cb, void *app_key) {
136
unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */
137
asn_enc_rval_t erval;
140
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
142
tmp.buf = (uint8_t *)&native;
143
tmp.size = sizeof(native);
145
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
146
uint8_t buf[sizeof(native)];
149
/* Prepare a fake INTEGER */
150
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
151
*p = (uint8_t)native;
154
tmp.size = sizeof(buf);
155
#endif /* WORDS_BIGENDIAN */
157
/* Encode fake INTEGER */
158
erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
159
if(erval.encoded == -1) {
160
assert(erval.structure_ptr == &tmp);
161
erval.structure_ptr = ptr;
167
* Decode the chunk of XML text encoding INTEGER.
170
NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
171
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
172
const void *buf_ptr, size_t size) {
173
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
176
void *st_ptr = (void *)&st;
177
long *native = (long *)*sptr;
180
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
181
if(!native) _ASN_DECODE_FAILED;
184
memset(&st, 0, sizeof(st));
185
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
186
opt_mname, buf_ptr, size);
187
if(rval.code == RC_OK) {
189
if((specs&&specs->field_unsigned)
190
? asn_INTEGER2ulong(&st, &l)
191
: asn_INTEGER2long(&st, &l)) {
199
* Cannot restart from the middle;
200
* there is no place to save state in the native type.
201
* Request a continuation from the very beginning.
205
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
211
NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
212
int ilevel, enum xer_encoder_flags_e flags,
213
asn_app_consume_bytes_f *cb, void *app_key) {
214
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
215
char scratch[32]; /* Enough for 64-bit int */
217
const long *native = (const long *)sptr;
222
if(!native) _ASN_ENCODE_FAILED;
224
er.encoded = snprintf(scratch, sizeof(scratch),
225
(specs && specs->field_unsigned)
226
? "%lu" : "%ld", *native);
227
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
228
|| cb(scratch, er.encoded, app_key) < 0)
235
NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
236
asn_TYPE_descriptor_t *td,
237
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
239
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
241
long *native = (long *)*sptr;
243
void *tmpintptr = &tmpint;
246
ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
249
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
250
if(!native) _ASN_DECODE_FAILED;
253
memset(&tmpint, 0, sizeof tmpint);
254
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
256
if(rval.code == RC_OK) {
257
if((specs&&specs->field_unsigned)
258
? asn_INTEGER2ulong(&tmpint, native)
259
: asn_INTEGER2long(&tmpint, native))
262
ASN_DEBUG("NativeInteger %s got value %ld",
265
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
271
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
272
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
273
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
278
if(!sptr) _ASN_ENCODE_FAILED;
280
native = *(long *)sptr;
282
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
284
memset(&tmpint, 0, sizeof(tmpint));
285
if((specs&&specs->field_unsigned)
286
? asn_ulong2INTEGER(&tmpint, native)
287
: asn_long2INTEGER(&tmpint, native))
289
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
290
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
295
* INTEGER specific human-readable output.
298
NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
299
asn_app_consume_bytes_f *cb, void *app_key) {
300
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
301
const long *native = (const long *)sptr;
302
char scratch[32]; /* Enough for 64-bit int */
305
(void)td; /* Unused argument */
306
(void)ilevel; /* Unused argument */
309
ret = snprintf(scratch, sizeof(scratch),
310
(specs && specs->field_unsigned)
311
? "%lu" : "%ld", *native);
312
assert(ret > 0 && (size_t)ret < sizeof(scratch));
313
return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
315
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
320
NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
325
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
326
td->name, contents_only, ptr);