asn1c/skeletons/NativeInteger.c

333 lines
8.6 KiB
C
Raw Normal View History

2004-06-03 03:38:44 +00:00
/*-
2006-08-18 01:34:18 +00:00
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
2004-06-03 03:38:44 +00:00
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
2006-03-18 05:06:57 +00:00
* Read the NativeInteger.h for the explanation wrt. differences between
2004-06-03 03:38:44 +00:00
* INTEGER and NativeInteger.
* Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
* implementation deals with the standard (machine-specific) representation
* of them instead of using the platform-independent buffer.
*/
2004-09-22 16:06:28 +00:00
#include <asn_internal.h>
2004-06-03 03:38:44 +00:00
#include <NativeInteger.h>
/*
* NativeInteger basic type description.
*/
static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
2004-06-03 03:38:44 +00:00
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
2004-09-29 13:26:15 +00:00
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
2004-06-03 03:38:44 +00:00
"INTEGER", /* The ASN.1 type is still INTEGER */
2004-10-20 15:50:55 +00:00
"INTEGER",
2004-09-22 16:06:28 +00:00
NativeInteger_free,
NativeInteger_print,
2004-06-03 03:38:44 +00:00
asn_generic_no_constraint,
NativeInteger_decode_ber,
NativeInteger_encode_der,
2004-10-21 14:13:48 +00:00
NativeInteger_decode_xer,
2004-09-22 16:06:28 +00:00
NativeInteger_encode_xer,
2005-11-26 11:25:14 +00:00
NativeInteger_decode_uper, /* Unaligned PER decoder */
2006-08-18 01:34:18 +00:00
NativeInteger_encode_uper, /* Unaligned PER encoder */
2004-06-03 03:38:44 +00:00
0, /* Use generic outmost tag fetcher */
2004-09-29 13:26:15 +00:00
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
asn_DEF_NativeInteger_tags, /* Same as above */
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
2005-11-26 11:25:14 +00:00
0, /* No PER visible constraints */
2004-08-20 13:23:42 +00:00
0, 0, /* No members */
2004-06-05 08:17:50 +00:00
0 /* No specifics */
2004-06-03 03:38:44 +00:00
};
/*
* Decode INTEGER type.
*/
2004-10-20 15:50:55 +00:00
asn_dec_rval_t
2004-09-29 13:26:15 +00:00
NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
2005-03-10 18:52:02 +00:00
void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2005-02-25 12:10:27 +00:00
long *native = (long *)*nint_ptr;
2004-10-20 15:50:55 +00:00
asn_dec_rval_t rval;
2004-06-03 03:38:44 +00:00
ber_tlv_len_t length;
/*
* If the structure is not there, allocate it.
*/
2005-02-25 12:10:27 +00:00
if(native == NULL) {
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
if(native == NULL) {
2004-06-03 03:38:44 +00:00
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
}
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
td->name, tag_mode);
/*
* Check tags.
*/
2004-09-29 13:26:15 +00:00
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
2004-06-03 03:38:44 +00:00
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
/*
* Make sure we have this length.
*/
2005-03-10 18:52:02 +00:00
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
2004-06-03 03:38:44 +00:00
size -= rval.consumed;
2004-06-05 08:17:50 +00:00
if(length > (ber_tlv_len_t)size) {
2004-06-03 03:38:44 +00:00
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
/*
* ASN.1 encoded INTEGER: buf_ptr, length
2005-02-25 12:10:27 +00:00
* Fill the native, at the same time checking for overflow.
2004-06-03 03:38:44 +00:00
* If overflow occured, return with RC_FAIL.
*/
{
INTEGER_t tmp;
union {
const void *constbuf;
void *nonconstbuf;
} unconst_buf;
2004-06-03 03:38:44 +00:00
long l;
unconst_buf.constbuf = buf_ptr;
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
2004-06-03 03:38:44 +00:00
tmp.size = length;
if((specs&&specs->field_unsigned)
2010-10-24 23:56:30 +00:00
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&tmp, &l)) {
2004-06-03 03:38:44 +00:00
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
2005-02-25 12:10:27 +00:00
*native = l;
2004-06-03 03:38:44 +00:00
}
rval.code = RC_OK;
rval.consumed += length;
2005-02-25 12:10:27 +00:00
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
(long)rval.consumed, (long)length, td->name, (long)*native);
2004-06-03 03:38:44 +00:00
return rval;
}
/*
* Encode the NativeInteger using the standard INTEGER type DER encoder.
*/
2004-09-22 16:06:28 +00:00
asn_enc_rval_t
2004-09-29 13:26:15 +00:00
NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
2004-06-03 03:38:44 +00:00
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
2005-02-25 12:10:27 +00:00
unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */
2004-09-22 16:06:28 +00:00
asn_enc_rval_t erval;
2004-06-03 03:38:44 +00:00
INTEGER_t tmp;
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
2005-02-25 12:10:27 +00:00
tmp.buf = (uint8_t *)&native;
tmp.size = sizeof(native);
2004-06-03 03:38:44 +00:00
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
2005-02-25 12:10:27 +00:00
uint8_t buf[sizeof(native)];
2004-06-03 03:38:44 +00:00
uint8_t *p;
2004-10-27 13:24:51 +00:00
/* Prepare a fake INTEGER */
2005-02-25 12:10:27 +00:00
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
2007-11-13 23:53:13 +00:00
*p = (uint8_t)native;
2004-06-03 03:38:44 +00:00
tmp.buf = buf;
tmp.size = sizeof(buf);
#endif /* WORDS_BIGENDIAN */
/* Encode fake INTEGER */
erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
if(erval.encoded == -1) {
assert(erval.structure_ptr == &tmp);
erval.structure_ptr = ptr;
}
return erval;
}
2004-10-21 14:13:48 +00:00
/*
* Decode the chunk of XML text encoding INTEGER.
*/
asn_dec_rval_t
NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
2005-03-10 18:52:02 +00:00
const void *buf_ptr, size_t size) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2004-10-21 14:13:48 +00:00
asn_dec_rval_t rval;
2005-11-26 11:25:14 +00:00
INTEGER_t st;
2005-01-27 17:54:57 +00:00
void *st_ptr = (void *)&st;
2005-02-25 12:10:27 +00:00
long *native = (long *)*sptr;
2004-10-21 14:13:48 +00:00
2005-02-25 12:10:27 +00:00
if(!native) {
2005-11-26 11:25:14 +00:00
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
2016-03-14 10:08:15 +00:00
if(!native) ASN__DECODE_FAILED;
2004-10-21 14:13:48 +00:00
}
2005-11-26 11:25:14 +00:00
memset(&st, 0, sizeof(st));
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
2005-01-27 17:54:57 +00:00
opt_mname, buf_ptr, size);
2004-10-21 14:13:48 +00:00
if(rval.code == RC_OK) {
long l;
if((specs&&specs->field_unsigned)
2010-10-24 23:56:30 +00:00
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&st, &l)) {
2004-10-21 14:13:48 +00:00
rval.code = RC_FAIL;
rval.consumed = 0;
} else {
2005-02-25 12:10:27 +00:00
*native = l;
2004-10-21 14:13:48 +00:00
}
} else {
2005-02-25 12:10:27 +00:00
/*
* Cannot restart from the middle;
* there is no place to save state in the native type.
* Request a continuation from the very beginning.
*/
2004-10-21 14:13:48 +00:00
rval.consumed = 0;
}
2006-03-17 02:11:12 +00:00
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
2004-10-21 14:13:48 +00:00
return rval;
}
2004-09-22 16:06:28 +00:00
asn_enc_rval_t
2004-09-29 13:26:15 +00:00
NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
2004-09-22 16:06:28 +00:00
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2004-09-22 16:06:28 +00:00
char scratch[32]; /* Enough for 64-bit int */
asn_enc_rval_t er;
2005-02-25 12:10:27 +00:00
const long *native = (const long *)sptr;
2004-09-22 16:06:28 +00:00
(void)ilevel;
(void)flags;
2016-03-14 10:08:15 +00:00
if(!native) ASN__ENCODE_FAILED;
2004-09-22 16:06:28 +00:00
er.encoded = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
2004-09-22 16:06:28 +00:00
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|| cb(scratch, er.encoded, app_key) < 0)
2016-03-14 10:08:15 +00:00
ASN__ENCODE_FAILED;
2004-09-22 16:06:28 +00:00
2016-03-14 10:08:15 +00:00
ASN__ENCODED_OK(er);
2005-11-26 11:25:14 +00:00
}
asn_dec_rval_t
NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2005-11-26 11:25:14 +00:00
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
void *tmpintptr = &tmpint;
(void)opt_codec_ctx;
ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
2016-03-14 10:08:15 +00:00
if(!native) ASN__DECODE_FAILED;
2005-11-26 11:25:14 +00:00
}
memset(&tmpint, 0, sizeof tmpint);
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
2005-11-27 12:40:43 +00:00
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
2010-10-24 23:56:30 +00:00
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
2005-11-26 11:25:14 +00:00
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
td->name, *native);
2005-11-27 12:40:43 +00:00
}
2006-03-17 02:11:12 +00:00
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
2005-11-26 11:25:14 +00:00
return rval;
2004-09-22 16:06:28 +00:00
}
2006-08-18 01:34:18 +00:00
asn_enc_rval_t
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2006-08-18 01:34:18 +00:00
asn_enc_rval_t er;
long native;
INTEGER_t tmpint;
2016-03-14 10:08:15 +00:00
if(!sptr) ASN__ENCODE_FAILED;
2006-08-18 01:34:18 +00:00
native = *(long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if((specs&&specs->field_unsigned)
? asn_ulong2INTEGER(&tmpint, native)
: asn_long2INTEGER(&tmpint, native))
2016-03-14 10:08:15 +00:00
ASN__ENCODE_FAILED;
2006-08-18 01:34:18 +00:00
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}
2004-06-03 03:38:44 +00:00
/*
* INTEGER specific human-readable output.
*/
int
2004-09-29 13:26:15 +00:00
NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
2004-06-03 03:38:44 +00:00
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
2005-02-25 12:10:27 +00:00
const long *native = (const long *)sptr;
2004-07-19 17:30:25 +00:00
char scratch[32]; /* Enough for 64-bit int */
2004-06-03 03:38:44 +00:00
int ret;
2004-06-05 08:17:50 +00:00
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
2005-02-25 12:10:27 +00:00
if(native) {
ret = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
2005-02-25 12:10:27 +00:00
assert(ret > 0 && (size_t)ret < sizeof(scratch));
return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
2004-06-03 03:38:44 +00:00
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
2004-06-03 03:38:44 +00:00
}
}
void
2004-09-29 13:26:15 +00:00
NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
2004-06-03 03:38:44 +00:00
if(!td || !ptr)
return;
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
td->name, contents_only, ptr);
if(!contents_only) {
FREEMEM(ptr);
}
}